get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/81931/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 81931,
    "url": "https://patches.dpdk.org/api/patches/81931/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1603443599-7356-6-git-send-email-tianfei.zhang@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1603443599-7356-6-git-send-email-tianfei.zhang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1603443599-7356-6-git-send-email-tianfei.zhang@intel.com",
    "date": "2020-10-23T08:59:59",
    "name": "[v3,5/5] raw/ifpga/base: enhance driver reliablity in multi-process",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "6893a87176d25085365fed76601831f40e36dba0",
    "submitter": {
        "id": 987,
        "url": "https://patches.dpdk.org/api/people/987/?format=api",
        "name": "Zhang, Tianfei",
        "email": "tianfei.zhang@intel.com"
    },
    "delegate": {
        "id": 1540,
        "url": "https://patches.dpdk.org/api/users/1540/?format=api",
        "username": "qzhan15",
        "first_name": "Qi",
        "last_name": "Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1603443599-7356-6-git-send-email-tianfei.zhang@intel.com/mbox/",
    "series": [
        {
            "id": 13263,
            "url": "https://patches.dpdk.org/api/series/13263/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=13263",
            "date": "2020-10-23T08:59:55",
            "name": "raw/ifpga/base: An improvement for multi-process",
            "version": 3,
            "mbox": "https://patches.dpdk.org/series/13263/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/81931/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/81931/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id D8BA9A04DE;\n\tFri, 23 Oct 2020 12:01:50 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id D369FA950;\n\tFri, 23 Oct 2020 12:00:14 +0200 (CEST)",
            "from mga06.intel.com (mga06.intel.com [134.134.136.31])\n by dpdk.org (Postfix) with ESMTP id C7553A93A\n for <dev@dpdk.org>; Fri, 23 Oct 2020 12:00:06 +0200 (CEST)",
            "from fmsmga003.fm.intel.com ([10.253.24.29])\n by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 23 Oct 2020 03:00:06 -0700",
            "from unknown (HELO sh_lab5_1.sh.intel.com) ([10.238.175.190])\n by FMSMGA003.fm.intel.com with ESMTP; 23 Oct 2020 03:00:04 -0700"
        ],
        "IronPort-SDR": [
            "\n SHPt0XuVwzm6Mr7IIXgtuJZw42+ewAHIc30FKPv8ET2u/XRSbkcp2F+K+dV33cZeO9ykBLTVqN\n BcPJ3rLbSVQg==",
            "\n PjWoLDH0PT8S6UiOUazlvj9Wx4r/b4pDbMWj0XR8gUBun/7yJ3iVKJ3C5wnbTzEynxQJfC02kv\n ossk0awON28Q=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9782\"; a=\"229288226\"",
            "E=Sophos;i=\"5.77,407,1596524400\"; d=\"scan'208\";a=\"229288226\"",
            "E=Sophos;i=\"5.77,407,1596524400\"; d=\"scan'208\";a=\"359556600\""
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "From": "Tianfei zhang <tianfei.zhang@intel.com>",
        "To": "dev@dpdk.org ,\n\trosen.xu@intel.com,\n\tqi.z.zhang@intel.com",
        "Cc": "Wei Huang <wei.huang@intel.com>,\n\tTianfei zhang <tianfei.zhang@intel.com>",
        "Date": "Fri, 23 Oct 2020 04:59:59 -0400",
        "Message-Id": "<1603443599-7356-6-git-send-email-tianfei.zhang@intel.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1603443599-7356-1-git-send-email-tianfei.zhang@intel.com>",
        "References": "<1600846213-18093-1-git-send-email-tianfei.zhang@intel.com>\n <1603443599-7356-1-git-send-email-tianfei.zhang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v3 5/5] raw/ifpga/base: enhance driver reliablity\n\tin multi-process",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Wei Huang <wei.huang@intel.com>\n\nCurrent hardware protection is based on pthread mutex which\nwork just for situation of multi-thread in one process. In\nmulti-process environment, hardware state machine would be\ncorrupted by concurrent access, that means original pthread\nmutex mechanism need be enhanced.\n\nThe major modifications in this patch are list below:\n1. Create a mutex for adapter in shared memory named\n\"mutex.IFPGA:domain:bus:dev.func\" when device is probed.\n2. Create a shared memory named \"IFPGA:domain:bus:dev.func\"\nduring opae adapter is initializing. There is a reference\ncount in shared memory. Shared memory will be destroyed\nonce reference count turned to zero.\n3. Two mutexs are created in shared memory and initialized\nwith flag PTHREAD_PROCESS_SHARED. One for SPI and the\nother for I2C. They will be passed to SPI and I2C driver\nsubsequently.\n4. DTB data in flash will be cached in shared memory. Then\nMAX10 driver can read DTB from shared memory instead of\nflash. This avoid confliction of concurrent flash access\nbetween hardware and software.\n\nSigned-off-by: Wei Huang <wei.huang@intel.com>\nSigned-off-by: Tianfei zhang <tianfei.zhang@intel.com>\n---\n drivers/raw/ifpga/base/ifpga_fme.c            |  52 +++-\n drivers/raw/ifpga/base/meson.build            |  12 +\n drivers/raw/ifpga/base/opae_hw_api.c          | 250 ++++++++++++++++++\n drivers/raw/ifpga/base/opae_hw_api.h          |  27 +-\n drivers/raw/ifpga/base/opae_i2c.c             |   9 +-\n drivers/raw/ifpga/base/opae_i2c.h             |   1 +\n drivers/raw/ifpga/base/opae_intel_max10.c     | 152 ++++++-----\n drivers/raw/ifpga/base/opae_spi.c             |   4 +\n drivers/raw/ifpga/base/opae_spi.h             |   5 +\n drivers/raw/ifpga/base/opae_spi_transaction.c |  15 +-\n 10 files changed, 456 insertions(+), 71 deletions(-)",
    "diff": "diff --git a/drivers/raw/ifpga/base/ifpga_fme.c b/drivers/raw/ifpga/base/ifpga_fme.c\nindex 9057087b5..540bb1110 100644\n--- a/drivers/raw/ifpga/base/ifpga_fme.c\n+++ b/drivers/raw/ifpga/base/ifpga_fme.c\n@@ -919,6 +919,25 @@ static int spi_self_checking(struct intel_max10_device *dev)\n \treturn 0;\n }\n \n+static void init_spi_share_data(struct ifpga_fme_hw *fme,\n+\t\t\t\tstruct altera_spi_device *spi)\n+{\n+\tstruct ifpga_hw *hw = (struct ifpga_hw *)fme->parent;\n+\topae_share_data *sd = NULL;\n+\n+\tif (hw && hw->adapter && hw->adapter->shm.ptr) {\n+\t\tdev_info(NULL, \"transfer share data to spi\\n\");\n+\t\tsd = (opae_share_data *)hw->adapter->shm.ptr;\n+\t\tspi->mutex = &sd->spi_mutex;\n+\t\tspi->dtb_sz_ptr = &sd->dtb_size;\n+\t\tspi->dtb = sd->dtb;\n+\t} else {\n+\t\tspi->mutex = NULL;\n+\t\tspi->dtb_sz_ptr = NULL;\n+\t\tspi->dtb = NULL;\n+\t}\n+}\n+\n static int fme_spi_init(struct ifpga_feature *feature)\n {\n \tstruct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;\n@@ -935,6 +954,7 @@ static int fme_spi_init(struct ifpga_feature *feature)\n \tspi_master = altera_spi_alloc(feature->addr, TYPE_SPI);\n \tif (!spi_master)\n \t\treturn -ENODEV;\n+\tinit_spi_share_data(fme, spi_master);\n \n \taltera_spi_init(spi_master);\n \n@@ -945,7 +965,6 @@ static int fme_spi_init(struct ifpga_feature *feature)\n \t\tgoto spi_fail;\n \t}\n \n-\n \tfme->max10_dev = max10;\n \n \t/* SPI self test */\n@@ -1084,11 +1103,15 @@ static int fme_nios_spi_init(struct ifpga_feature *feature)\n \tspi_master = altera_spi_alloc(feature->addr, TYPE_NIOS_SPI);\n \tif (!spi_master)\n \t\treturn -ENODEV;\n+\tinit_spi_share_data(fme, spi_master);\n \n \t/**\n \t * 1. wait A10 NIOS initial finished and\n \t * release the SPI master to Host\n \t */\n+\tif (spi_master->mutex)\n+\t\tpthread_mutex_lock(spi_master->mutex);\n+\n \tret = nios_spi_wait_init_done(spi_master);\n \tif (ret != 0) {\n \t\tdev_err(fme, \"FME NIOS_SPI init fail\\n\");\n@@ -1101,6 +1124,9 @@ static int fme_nios_spi_init(struct ifpga_feature *feature)\n \tif (nios_spi_check_error(spi_master))\n \t\tdev_info(fme, \"NIOS_SPI INIT done, but found some error\\n\");\n \n+\tif (spi_master->mutex)\n+\t\tpthread_mutex_unlock(spi_master->mutex);\n+\n \t/* 3. init the spi master*/\n \taltera_spi_init(spi_master);\n \n@@ -1112,11 +1138,12 @@ static int fme_nios_spi_init(struct ifpga_feature *feature)\n \t\tgoto release_dev;\n \t}\n \n+\tfme->max10_dev = max10;\n+\n \tmax10->bus = hw->pci_data->bus;\n \n \tfme_get_board_interface(fme);\n \n-\tfme->max10_dev = max10;\n \tmgr->sensor_list = &max10->opae_sensor_list;\n \n \t/* SPI self test */\n@@ -1178,6 +1205,25 @@ static int i2c_mac_rom_test(struct altera_i2c_dev *dev)\n \treturn 0;\n }\n \n+static void init_i2c_mutex(struct ifpga_fme_hw *fme)\n+{\n+\tstruct ifpga_hw *hw = (struct ifpga_hw *)fme->parent;\n+\tstruct altera_i2c_dev *i2c_dev;\n+\topae_share_data *sd = NULL;\n+\n+\tif (fme->i2c_master) {\n+\t\ti2c_dev = (struct altera_i2c_dev *)fme->i2c_master;\n+\t\tif (hw && hw->adapter && hw->adapter->shm.ptr) {\n+\t\t\tdev_info(NULL, \"use multi-process mutex in i2c\\n\");\n+\t\t\tsd = (opae_share_data *)hw->adapter->shm.ptr;\n+\t\t\ti2c_dev->mutex = &sd->i2c_mutex;\n+\t\t} else {\n+\t\t\tdev_info(NULL, \"use multi-thread mutex in i2c\\n\");\n+\t\t\ti2c_dev->mutex = &i2c_dev->lock;\n+\t\t}\n+\t}\n+}\n+\n static int fme_i2c_init(struct ifpga_feature *feature)\n {\n \tstruct feature_fme_i2c *i2c;\n@@ -1191,6 +1237,8 @@ static int fme_i2c_init(struct ifpga_feature *feature)\n \tif (!fme->i2c_master)\n \t\treturn -ENODEV;\n \n+\tinit_i2c_mutex(fme);\n+\n \t/* MAC ROM self test */\n \ti2c_mac_rom_test(fme->i2c_master);\n \ndiff --git a/drivers/raw/ifpga/base/meson.build b/drivers/raw/ifpga/base/meson.build\nindex b13e13e89..da2d6e33c 100644\n--- a/drivers/raw/ifpga/base/meson.build\n+++ b/drivers/raw/ifpga/base/meson.build\n@@ -23,6 +23,18 @@ sources = [\n \t'opae_eth_group.c',\n ]\n \n+rtdep = dependency('librt', required: false)\n+if not rtdep.found()\n+\trtdep = cc.find_library('librt', required: false)\n+endif\n+if not rtdep.found()\n+\tbuild = false\n+\treason = 'missing dependency, \"librt\"'\n+\tsubdir_done()\n+endif\n+\n+ext_deps += rtdep\n+\n base_lib = static_library('ifpga_rawdev_base', sources,\n \tdependencies: static_rte_eal,\n \tc_args: cflags)\ndiff --git a/drivers/raw/ifpga/base/opae_hw_api.c b/drivers/raw/ifpga/base/opae_hw_api.c\nindex c969dfed3..600afdea1 100644\n--- a/drivers/raw/ifpga/base/opae_hw_api.c\n+++ b/drivers/raw/ifpga/base/opae_hw_api.c\n@@ -2,6 +2,10 @@\n  * Copyright(c) 2010-2018 Intel Corporation\n  */\n \n+#include <sys/mman.h>\n+#include <sys/stat.h>\n+#include <fcntl.h>\n+#include <unistd.h>\n #include \"opae_hw_api.h\"\n #include \"opae_debug.h\"\n #include \"ifpga_api.h\"\n@@ -305,6 +309,244 @@ static struct opae_adapter_ops *match_ops(struct opae_adapter *adapter)\n \treturn NULL;\n }\n \n+static void opae_mutex_init(pthread_mutex_t *mutex)\n+{\n+\tpthread_mutexattr_t mattr;\n+\n+\tpthread_mutexattr_init(&mattr);\n+\tpthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);\n+\tpthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);\n+\tpthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST);\n+\tpthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT);\n+\tpthread_mutex_init(mutex, &mattr);\n+\tpthread_mutexattr_destroy(&mattr);\n+}\n+\n+static int opae_shm_open(char *shm_name, u32 size, int *new_shm)\n+{\n+\tint shm_id;\n+\tint ret;\n+\n+\tshm_id = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR, 0666);\n+\tif (shm_id == -1) {\n+\t\tif (errno == EEXIST) {\n+\t\t\tdev_info(NULL, \"shared memory %s already exist\\n\",\n+\t\t\t\t\tshm_name);\n+\t\t\tshm_id = shm_open(shm_name, O_RDWR, 0666);\n+\t\t} else {\n+\t\t\tdev_err(NULL, \"failed to create shared memory %s\\n\",\n+\t\t\t\t\tshm_name);\n+\t\t\treturn -1;\n+\t\t}\n+\t} else {\n+\t\t*new_shm = 1;\n+\t\tret = ftruncate(shm_id, size);\n+\t\tif (ret == -1) {\n+\t\t\tdev_err(NULL,\n+\t\t\t\t\t\"failed to set shared memory size to %u\\n\",\n+\t\t\t\t\tsize);\n+\t\t\tret = shm_unlink(shm_name);\n+\t\t\tif (ret == -1) {\n+\t\t\t\tdev_err(NULL,\n+\t\t\t\t\t\t\"failed to unlink shared memory %s\\n\",\n+\t\t\t\t\t\tshm_name);\n+\t\t\t}\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\treturn shm_id;\n+}\n+\n+static pthread_mutex_t *opae_adapter_mutex_open(struct opae_adapter *adapter)\n+{\n+\tchar shm_name[32];\n+\tvoid *ptr;\n+\tint shm_id;\n+\tint new_shm = 0;\n+\n+\tif (!adapter->data)\n+\t\treturn NULL;\n+\tadapter->lock = NULL;\n+\n+\tsnprintf(shm_name, sizeof(shm_name), \"/mutex.IFPGA:%s\", adapter->name);\n+\tshm_id = opae_shm_open(shm_name, sizeof(pthread_mutex_t), &new_shm);\n+\tif (shm_id == -1) {\n+\t\tdev_err(NULL, \"failed to open shared memory %s\\n\", shm_name);\n+\t} else {\n+\t\tdev_info(NULL, \"shared memory %s id is %d\\n\",\n+\t\t\t\tshm_name, shm_id);\n+\t\tptr = mmap(NULL, sizeof(pthread_mutex_t),\n+\t\t\t\tPROT_READ | PROT_WRITE, MAP_SHARED,\n+\t\t\t\tshm_id, 0);\n+\t\tadapter->lock = (pthread_mutex_t *)ptr;\n+\t\tif (ptr) {\n+\t\t\tdev_info(NULL,\n+\t\t\t\t\t\"shared memory %s address is %p\\n\",\n+\t\t\t\t\tshm_name, ptr);\n+\t\t\tif (new_shm)\n+\t\t\t\topae_mutex_init(adapter->lock);\n+\t\t} else {\n+\t\t\tdev_err(NULL, \"failed to map shared memory %s\\n\",\n+\t\t\t\t\tshm_name);\n+\t\t}\n+\t}\n+\n+\treturn adapter->lock;\n+}\n+\n+static void opae_adapter_mutex_close(struct opae_adapter *adapter)\n+{\n+\tchar shm_name[32];\n+\tint ret;\n+\n+\tif (!adapter->lock)\n+\t\treturn;\n+\n+\tsnprintf(shm_name, sizeof(shm_name), \"/mutex.IFPGA:%s\", adapter->name);\n+\n+\tret = munmap(adapter->lock, sizeof(pthread_mutex_t));\n+\tif (ret == -1)\n+\t\tdev_err(NULL, \"failed to unmap shared memory %s\\n\", shm_name);\n+\telse\n+\t\tadapter->lock = NULL;\n+}\n+\n+/**\n+ * opae_adapter_lock - lock this adapter\n+ * @adapter: adapter to lock.\n+ * @timeout: maximum time to wait for lock done\n+ *           -1  wait until the lock is available\n+ *           0   do not wait and return immediately\n+ *           t   positive time in second to wait\n+ *\n+ * Return: 0 on success, otherwise error code.\n+ */\n+int opae_adapter_lock(struct opae_adapter *adapter, int timeout)\n+{\n+\tstruct timespec t;\n+\tint ret = -EINVAL;\n+\n+\tif (adapter && adapter->lock) {\n+\t\tif (timeout < 0) {\n+\t\t\tret = pthread_mutex_lock(adapter->lock);\n+\t\t} else if (timeout == 0) {\n+\t\t\tret = pthread_mutex_trylock(adapter->lock);\n+\t\t} else {\n+\t\t\tclock_gettime(CLOCK_REALTIME, &t);\n+\t\t\tt.tv_sec += timeout;\n+\t\t\tret = pthread_mutex_timedlock(adapter->lock, &t);\n+\t\t}\n+\t}\n+\treturn ret;\n+}\n+\n+/**\n+ * opae_adapter_unlock - unlock this adapter\n+ * @adapter: adapter to unlock.\n+ *\n+ * Return: 0 on success, otherwise error code.\n+ */\n+int opae_adapter_unlock(struct opae_adapter *adapter)\n+{\n+\tint ret = -EINVAL;\n+\n+\tif (adapter && adapter->lock)\n+\t\tret = pthread_mutex_unlock(adapter->lock);\n+\n+\treturn ret;\n+}\n+\n+static void opae_adapter_shm_init(struct opae_adapter *adapter)\n+{\n+\topae_share_data *sd;\n+\n+\tif (!adapter->shm.ptr)\n+\t\treturn;\n+\n+\tsd = (opae_share_data *)adapter->shm.ptr;\n+\tdev_info(NULL, \"initialize shared memory\\n\");\n+\topae_mutex_init(&sd->spi_mutex);\n+\topae_mutex_init(&sd->i2c_mutex);\n+\tsd->ref_cnt = 0;\n+\tsd->dtb_size = SHM_BLK_SIZE;\n+}\n+\n+static void *opae_adapter_shm_alloc(struct opae_adapter *adapter)\n+{\n+\tchar shm_name[32];\n+\topae_share_data *sd;\n+\tu32 size = sizeof(opae_share_data);\n+\tint shm_id;\n+\tint new_shm = 0;\n+\n+\tif (!adapter->data)\n+\t\treturn NULL;\n+\n+\tsnprintf(shm_name, sizeof(shm_name), \"/IFPGA:%s\", adapter->name);\n+\tadapter->shm.ptr = NULL;\n+\n+\topae_adapter_lock(adapter, -1);\n+\tshm_id = opae_shm_open(shm_name, size, &new_shm);\n+\tif (shm_id == -1) {\n+\t\tdev_err(NULL, \"failed to open shared memory %s\\n\", shm_name);\n+\t} else {\n+\t\tdev_info(NULL, \"shared memory %s id is %d\\n\",\n+\t\t\t\tshm_name, shm_id);\n+\t\tadapter->shm.id = shm_id;\n+\t\tadapter->shm.size = size;\n+\t\tadapter->shm.ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,\n+\t\t\t\t\t\t\tMAP_SHARED, shm_id, 0);\n+\t\tif (adapter->shm.ptr) {\n+\t\t\tdev_info(NULL,\n+\t\t\t\t\t\"shared memory %s address is %p\\n\",\n+\t\t\t\t\tshm_name, adapter->shm.ptr);\n+\t\t\tif (new_shm)\n+\t\t\t\topae_adapter_shm_init(adapter);\n+\t\t\tsd = (opae_share_data *)adapter->shm.ptr;\n+\t\t\tsd->ref_cnt++;\n+\t\t} else {\n+\t\t\tdev_err(NULL, \"failed to map shared memory %s\\n\",\n+\t\t\t\t\tshm_name);\n+\t\t}\n+\t}\n+\topae_adapter_unlock(adapter);\n+\n+\treturn adapter->shm.ptr;\n+}\n+\n+static void opae_adapter_shm_free(struct opae_adapter *adapter)\n+{\n+\tchar shm_name[32];\n+\topae_share_data *sd;\n+\tu32 ref_cnt;\n+\tint ret;\n+\n+\tif (!adapter->shm.ptr)\n+\t\treturn;\n+\n+\tsd = (opae_share_data *)adapter->shm.ptr;\n+\tsnprintf(shm_name, sizeof(shm_name), \"/IFPGA:%s\", adapter->name);\n+\n+\topae_adapter_lock(adapter, -1);\n+\tref_cnt = --sd->ref_cnt;\n+\tret = munmap(adapter->shm.ptr, adapter->shm.size);\n+\tif (ret == -1)\n+\t\tdev_err(NULL, \"failed to unmap shared memory %s\\n\", shm_name);\n+\telse\n+\t\tadapter->shm.ptr = NULL;\n+\n+\tif (ref_cnt == 0) {\n+\t\tdev_info(NULL, \"unlink shared memory %s\\n\", shm_name);\n+\t\tret = shm_unlink(shm_name);\n+\t\tif (ret == -1) {\n+\t\t\tdev_err(NULL, \"failed to unlink shared memory %s\\n\",\n+\t\t\t\t\tshm_name);\n+\t\t}\n+\t}\n+\topae_adapter_unlock(adapter);\n+}\n+\n /**\n  * opae_adapter_init - init opae_adapter data structure\n  * @adapter: pointer of opae_adapter data structure\n@@ -324,6 +566,12 @@ int opae_adapter_init(struct opae_adapter *adapter,\n \tadapter->name = name;\n \tadapter->ops = match_ops(adapter);\n \n+\tif (!opae_adapter_mutex_open(adapter))\n+\t\treturn -ENOMEM;\n+\n+\tif (!opae_adapter_shm_alloc(adapter))\n+\t\treturn -ENOMEM;\n+\n \treturn 0;\n }\n \n@@ -359,6 +607,8 @@ void opae_adapter_destroy(struct opae_adapter *adapter)\n {\n \tif (adapter && adapter->ops && adapter->ops->destroy)\n \t\tadapter->ops->destroy(adapter);\n+\topae_adapter_shm_free(adapter);\n+\topae_adapter_mutex_close(adapter);\n }\n \n /**\ndiff --git a/drivers/raw/ifpga/base/opae_hw_api.h b/drivers/raw/ifpga/base/opae_hw_api.h\nindex cf8ff93a6..e99ee4564 100644\n--- a/drivers/raw/ifpga/base/opae_hw_api.h\n+++ b/drivers/raw/ifpga/base/opae_hw_api.h\n@@ -265,12 +265,36 @@ TAILQ_HEAD(opae_accelerator_list, opae_accelerator);\n #define opae_adapter_for_each_acc(adatper, acc) \\\n \tTAILQ_FOREACH(acc, &adapter->acc_list, node)\n \n+#define SHM_PREFIX     \"/IFPGA:\"\n+#define SHM_BLK_SIZE   0x2000\n+\n+typedef struct {\n+\tunion {\n+\t\tu8 byte[SHM_BLK_SIZE];\n+\t\tstruct {\n+\t\t\tpthread_mutex_t spi_mutex;\n+\t\t\tpthread_mutex_t i2c_mutex;\n+\t\t\tu32 ref_cnt;    /* reference count of shared memory */\n+\t\t\tu32 dtb_size;   /* actual length of DTB data in byte */\n+\t\t};\n+\t};\n+\tu8 dtb[SHM_BLK_SIZE];   /* DTB data */\n+} opae_share_data;\n+\n+typedef struct  {\n+\tint id;       /* shared memory id returned by shm_open */\n+\tu32 size;     /* size of shared memory in byte */\n+\tvoid *ptr;    /* start address of shared memory */\n+} opae_share_memory;\n+\n struct opae_adapter {\n \tconst char *name;\n \tstruct opae_manager *mgr;\n \tstruct opae_accelerator_list acc_list;\n \tstruct opae_adapter_ops *ops;\n \tvoid *data;\n+\tpthread_mutex_t *lock;   /* multi-process mutex for IFPGA */\n+\topae_share_memory shm;\n };\n \n /* OPAE Adapter APIs */\n@@ -280,7 +304,8 @@ void *opae_adapter_data_alloc(enum opae_adapter_type type);\n int opae_adapter_init(struct opae_adapter *adapter,\n \t\tconst char *name, void *data);\n #define opae_adapter_free(adapter) opae_free(adapter)\n-\n+int opae_adapter_lock(struct opae_adapter *adapter, int timeout);\n+int opae_adapter_unlock(struct opae_adapter *adapter);\n int opae_adapter_enumerate(struct opae_adapter *adapter);\n void opae_adapter_destroy(struct opae_adapter *adapter);\n static inline struct opae_manager *\ndiff --git a/drivers/raw/ifpga/base/opae_i2c.c b/drivers/raw/ifpga/base/opae_i2c.c\nindex 846d751f5..598eab574 100644\n--- a/drivers/raw/ifpga/base/opae_i2c.c\n+++ b/drivers/raw/ifpga/base/opae_i2c.c\n@@ -30,7 +30,7 @@ int i2c_read(struct altera_i2c_dev *dev, int flags, unsigned int slave_addr,\n \tint i = 0;\n \tint ret;\n \n-\tpthread_mutex_lock(&dev->lock);\n+\tpthread_mutex_lock(dev->mutex);\n \n \tif (flags & I2C_FLAG_ADDR16)\n \t\tmsgbuf[i++] = offset >> 8;\n@@ -60,7 +60,7 @@ int i2c_read(struct altera_i2c_dev *dev, int flags, unsigned int slave_addr,\n \tret = i2c_transfer(dev, msg, 2);\n \n exit:\n-\tpthread_mutex_unlock(&dev->lock);\n+\tpthread_mutex_unlock(dev->mutex);\n \treturn ret;\n }\n \n@@ -72,7 +72,7 @@ int i2c_write(struct altera_i2c_dev *dev, int flags, unsigned int slave_addr,\n \tint ret;\n \tint i = 0;\n \n-\tpthread_mutex_lock(&dev->lock);\n+\tpthread_mutex_lock(dev->mutex);\n \n \tif (!dev->xfer) {\n \t\tret = -ENODEV;\n@@ -100,7 +100,7 @@ int i2c_write(struct altera_i2c_dev *dev, int flags, unsigned int slave_addr,\n \n \topae_free(buf);\n exit:\n-\tpthread_mutex_unlock(&dev->lock);\n+\tpthread_mutex_unlock(dev->mutex);\n \treturn ret;\n }\n \n@@ -496,6 +496,7 @@ struct altera_i2c_dev *altera_i2c_probe(void *base)\n \n \tif (pthread_mutex_init(&dev->lock, NULL))\n \t\treturn NULL;\n+\tdev->mutex = &dev->lock;\n \n \taltera_i2c_hardware_init(dev);\n \ndiff --git a/drivers/raw/ifpga/base/opae_i2c.h b/drivers/raw/ifpga/base/opae_i2c.h\nindex 266e127b7..4f6b0b28b 100644\n--- a/drivers/raw/ifpga/base/opae_i2c.h\n+++ b/drivers/raw/ifpga/base/opae_i2c.h\n@@ -94,6 +94,7 @@ struct altera_i2c_dev {\n \tu8 *buf;\n \tint (*xfer)(struct altera_i2c_dev *dev, struct i2c_msg *msg, int num);\n \tpthread_mutex_t lock;\n+\tpthread_mutex_t *mutex;  /* multi-process mutex from adapter */\n };\n \n /**\ndiff --git a/drivers/raw/ifpga/base/opae_intel_max10.c b/drivers/raw/ifpga/base/opae_intel_max10.c\nindex 8e23ca18a..1a526ea54 100644\n--- a/drivers/raw/ifpga/base/opae_intel_max10.c\n+++ b/drivers/raw/ifpga/base/opae_intel_max10.c\n@@ -138,84 +138,116 @@ static int enable_nor_flash(struct intel_max10_device *dev, bool on)\n \n static int init_max10_device_table(struct intel_max10_device *max10)\n {\n+\tstruct altera_spi_device *spi = NULL;\n \tstruct max10_compatible_id *id;\n \tstruct fdt_header hdr;\n \tchar *fdt_root = NULL;\n-\n+\tu32 dtb_magic = 0;\n \tu32 dt_size, dt_addr, val;\n-\tint ret;\n-\n-\tret = max10_sys_read(max10, DT_AVAIL_REG, &val);\n-\tif (ret) {\n-\t\tdev_err(max10 \"cannot read DT_AVAIL_REG\\n\");\n-\t\treturn ret;\n-\t}\n+\tint ret = 0;\n \n-\tif (!(val & DT_AVAIL)) {\n-\t\tdev_err(max10 \"DT not available\\n\");\n+\tspi = (struct altera_spi_device *)max10->spi_master;\n+\tif (!spi) {\n+\t\tdev_err(max10, \"spi master is not set\\n\");\n \t\treturn -EINVAL;\n \t}\n+\tif (spi->dtb)\n+\t\tdtb_magic = *(u32 *)spi->dtb;\n+\n+\tif (dtb_magic != 0xEDFE0DD0) {\n+\t\tdev_info(max10, \"read DTB from NOR flash\\n\");\n+\t\tret = max10_sys_read(max10, DT_AVAIL_REG, &val);\n+\t\tif (ret) {\n+\t\t\tdev_err(max10 \"cannot read DT_AVAIL_REG\\n\");\n+\t\t\treturn ret;\n+\t\t}\n \n-\tret = max10_sys_read(max10, DT_BASE_ADDR_REG, &dt_addr);\n-\tif (ret) {\n-\t\tdev_info(max10 \"cannot get base addr of device table\\n\");\n-\t\treturn ret;\n-\t}\n-\n-\tret = enable_nor_flash(max10, true);\n-\tif (ret) {\n-\t\tdev_err(max10 \"fail to enable flash\\n\");\n-\t\treturn ret;\n-\t}\n+\t\tif (!(val & DT_AVAIL)) {\n+\t\t\tdev_err(max10 \"DT not available\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n \n-\tret = altera_nor_flash_read(max10, dt_addr, &hdr, sizeof(hdr));\n-\tif (ret) {\n-\t\tdev_err(max10 \"read fdt header fail\\n\");\n-\t\tgoto done;\n-\t}\n+\t\tret = max10_sys_read(max10, DT_BASE_ADDR_REG, &dt_addr);\n+\t\tif (ret) {\n+\t\t\tdev_info(max10 \"cannot get base addr of device table\\n\");\n+\t\t\treturn ret;\n+\t\t}\n \n-\tret = fdt_check_header(&hdr);\n-\tif (ret) {\n-\t\tdev_err(max10 \"check fdt header fail\\n\");\n-\t\tgoto done;\n-\t}\n+\t\tret = enable_nor_flash(max10, true);\n+\t\tif (ret) {\n+\t\t\tdev_err(max10 \"fail to enable flash\\n\");\n+\t\t\treturn ret;\n+\t\t}\n \n-\tdt_size = fdt_totalsize(&hdr);\n-\tif (dt_size > DFT_MAX_SIZE) {\n-\t\tdev_err(max10 \"invalid device table size\\n\");\n-\t\tret = -EINVAL;\n-\t\tgoto done;\n-\t}\n+\t\tret = altera_nor_flash_read(max10, dt_addr, &hdr, sizeof(hdr));\n+\t\tif (ret) {\n+\t\t\tdev_err(max10 \"read fdt header fail\\n\");\n+\t\t\tgoto disable_nor_flash;\n+\t\t}\n \n-\tfdt_root = opae_malloc(dt_size);\n-\tif (!fdt_root) {\n-\t\tret = -ENOMEM;\n-\t\tgoto done;\n-\t}\n+\t\tret = fdt_check_header(&hdr);\n+\t\tif (ret) {\n+\t\t\tdev_err(max10 \"check fdt header fail\\n\");\n+\t\t\tgoto disable_nor_flash;\n+\t\t}\n \n-\tret = altera_nor_flash_read(max10, dt_addr, fdt_root, dt_size);\n-\tif (ret) {\n-\t\tdev_err(max10 \"cannot read device table\\n\");\n-\t\tgoto done;\n-\t}\n+\t\tdt_size = fdt_totalsize(&hdr);\n+\t\tif (dt_size > DFT_MAX_SIZE) {\n+\t\t\tdev_err(max10 \"invalid device table size\\n\");\n+\t\t\tret = -EINVAL;\n+\t\t\tgoto disable_nor_flash;\n+\t\t}\n \n-\tid = max10_match_compatible(fdt_root);\n-\tif (!id) {\n-\t\tdev_err(max10 \"max10 compatible not found\\n\");\n-\t\tret = -ENODEV;\n-\t\tgoto done;\n-\t}\n+\t\tfdt_root = opae_malloc(dt_size);\n+\t\tif (!fdt_root) {\n+\t\t\tret = -ENOMEM;\n+\t\t\tgoto disable_nor_flash;\n+\t\t}\n \n-\tmax10->flags |= MAX10_FLAGS_DEVICE_TABLE;\n+\t\tret = altera_nor_flash_read(max10, dt_addr, fdt_root, dt_size);\n+\t\tif (ret) {\n+\t\t\topae_free(fdt_root);\n+\t\t\tfdt_root = NULL;\n+\t\t\tdev_err(max10 \"cannot read device table\\n\");\n+\t\t\tgoto disable_nor_flash;\n+\t\t}\n \n-\tmax10->id = id;\n-\tmax10->fdt_root = fdt_root;\n+\t\tif (spi->dtb) {\n+\t\t\tif (*spi->dtb_sz_ptr < dt_size) {\n+\t\t\t\tdev_warn(max10,\n+\t\t\t\t\t\t \"share memory for dtb is smaller than required %u\\n\",\n+\t\t\t\t\t\t dt_size);\n+\t\t\t} else {\n+\t\t\t\t*spi->dtb_sz_ptr = dt_size;\n+\t\t\t}\n+\t\t\t/* store dtb data into share memory  */\n+\t\t\tmemcpy(spi->dtb, fdt_root, *spi->dtb_sz_ptr);\n+\t\t}\n \n-done:\n-\tret = enable_nor_flash(max10, false);\n+disable_nor_flash:\n+\t\tenable_nor_flash(max10, false);\n+\t} else {\n+\t\tif (*spi->dtb_sz_ptr > 0) {\n+\t\t\tdev_info(max10, \"read DTB from shared memory\\n\");\n+\t\t\tfdt_root = opae_malloc(*spi->dtb_sz_ptr);\n+\t\t\tif (fdt_root)\n+\t\t\t\tmemcpy(fdt_root, spi->dtb, *spi->dtb_sz_ptr);\n+\t\t\telse\n+\t\t\t\tret = -ENOMEM;\n+\t\t}\n+\t}\n \n-\tif (ret && fdt_root)\n-\t\topae_free(fdt_root);\n+\tif (fdt_root) {\n+\t\tid = max10_match_compatible(fdt_root);\n+\t\tif (!id) {\n+\t\t\tdev_err(max10 \"max10 compatible not found\\n\");\n+\t\t\tret = -ENODEV;\n+\t\t} else {\n+\t\t\tmax10->flags |= MAX10_FLAGS_DEVICE_TABLE;\n+\t\t\tmax10->id = id;\n+\t\t\tmax10->fdt_root = fdt_root;\n+\t\t}\n+\t}\n \n \treturn ret;\n }\ndiff --git a/drivers/raw/ifpga/base/opae_spi.c b/drivers/raw/ifpga/base/opae_spi.c\nindex bfdc83e6c..9efeecb79 100644\n--- a/drivers/raw/ifpga/base/opae_spi.c\n+++ b/drivers/raw/ifpga/base/opae_spi.c\n@@ -285,11 +285,15 @@ void altera_spi_init(struct altera_spi_device *spi_dev)\n \t\t\tspi_dev->num_chipselect,\n \t\t\tspi_dev->spi_param.clock_phase);\n \n+\tif (spi_dev->mutex)\n+\t\tpthread_mutex_lock(spi_dev->mutex);\n \t/* clear */\n \tspi_reg_write(spi_dev, ALTERA_SPI_CONTROL, 0);\n \tspi_reg_write(spi_dev, ALTERA_SPI_STATUS, 0);\n \t/* flush rxdata */\n \tspi_flush_rx(spi_dev);\n+\tif (spi_dev->mutex)\n+\t\tpthread_mutex_unlock(spi_dev->mutex);\n }\n \n void altera_spi_release(struct altera_spi_device *dev)\ndiff --git a/drivers/raw/ifpga/base/opae_spi.h b/drivers/raw/ifpga/base/opae_spi.h\nindex 73a227673..af11656e4 100644\n--- a/drivers/raw/ifpga/base/opae_spi.h\n+++ b/drivers/raw/ifpga/base/opae_spi.h\n@@ -77,6 +77,10 @@ struct altera_spi_device {\n \tint (*reg_read)(struct altera_spi_device *dev, u32 reg, u32 *val);\n \tint (*reg_write)(struct altera_spi_device *dev, u32 reg,\n \t\t\tu32 value);\n+\t/* below are data to be shared in multiple process */\n+\tpthread_mutex_t *mutex;     /* to be passed to spi_transaction_dev */\n+\tunsigned int *dtb_sz_ptr;   /* to be used in init_max10_device_table */\n+\tunsigned char *dtb;         /* to be used in init_max10_device_table */\n };\n \n #define HEADER_LEN 8\n@@ -103,6 +107,7 @@ struct spi_transaction_dev {\n \tint chipselect;\n \tstruct spi_tran_buffer *buffer;\n \tpthread_mutex_t lock;\n+\tpthread_mutex_t *mutex;  /* multi-process mutex from adapter */\n };\n \n struct spi_tran_header {\ndiff --git a/drivers/raw/ifpga/base/opae_spi_transaction.c b/drivers/raw/ifpga/base/opae_spi_transaction.c\nindex d13d2fbc8..006cdb4c1 100644\n--- a/drivers/raw/ifpga/base/opae_spi_transaction.c\n+++ b/drivers/raw/ifpga/base/opae_spi_transaction.c\n@@ -434,11 +434,11 @@ int spi_transaction_read(struct spi_transaction_dev *dev, unsigned int addr,\n {\n \tint ret;\n \n-\tpthread_mutex_lock(&dev->lock);\n+\tpthread_mutex_lock(dev->mutex);\n \tret = do_transaction(dev, addr, size, data,\n \t\t\t(size > SPI_REG_BYTES) ?\n \t\t\tSPI_TRAN_SEQ_READ : SPI_TRAN_NON_SEQ_READ);\n-\tpthread_mutex_unlock(&dev->lock);\n+\tpthread_mutex_unlock(dev->mutex);\n \n \treturn ret;\n }\n@@ -448,11 +448,11 @@ int spi_transaction_write(struct spi_transaction_dev *dev, unsigned int addr,\n {\n \tint ret;\n \n-\tpthread_mutex_lock(&dev->lock);\n+\tpthread_mutex_lock(dev->mutex);\n \tret = do_transaction(dev, addr, size, data,\n \t\t\t(size > SPI_REG_BYTES) ?\n \t\t\tSPI_TRAN_SEQ_WRITE : SPI_TRAN_NON_SEQ_WRITE);\n-\tpthread_mutex_unlock(&dev->lock);\n+\tpthread_mutex_unlock(dev->mutex);\n \n \treturn ret;\n }\n@@ -479,6 +479,13 @@ struct spi_transaction_dev *spi_transaction_init(struct altera_spi_device *dev,\n \t\tdev_err(spi_tran_dev, \"fail to init mutex lock\\n\");\n \t\tgoto err;\n \t}\n+\tif (dev->mutex) {\n+\t\tdev_info(NULL, \"use multi-process mutex in spi\\n\");\n+\t\tspi_tran_dev->mutex = dev->mutex;\n+\t} else {\n+\t\tdev_info(NULL, \"use multi-thread mutex in spi\\n\");\n+\t\tspi_tran_dev->mutex = &spi_tran_dev->lock;\n+\t}\n \n \treturn spi_tran_dev;\n \n",
    "prefixes": [
        "v3",
        "5/5"
    ]
}