get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 51739,
    "url": "http://patches.dpdk.org/api/patches/51739/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1553614522-12151-6-git-send-email-viacheslavo@mellanox.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<1553614522-12151-6-git-send-email-viacheslavo@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1553614522-12151-6-git-send-email-viacheslavo@mellanox.com",
    "date": "2019-03-26T15:35:14",
    "name": "[v3,05/13] net/mlx5: add IB shared context alloc/free functions",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "53e76eb7296e3f0f30d5e3426ed8f98bb01aa255",
    "submitter": {
        "id": 1102,
        "url": "http://patches.dpdk.org/api/people/1102/?format=api",
        "name": "Slava Ovsiienko",
        "email": "viacheslavo@mellanox.com"
    },
    "delegate": {
        "id": 6624,
        "url": "http://patches.dpdk.org/api/users/6624/?format=api",
        "username": "shahafs",
        "first_name": "Shahaf",
        "last_name": "Shuler",
        "email": "shahafs@mellanox.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1553614522-12151-6-git-send-email-viacheslavo@mellanox.com/mbox/",
    "series": [
        {
            "id": 3928,
            "url": "http://patches.dpdk.org/api/series/3928/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=3928",
            "date": "2019-03-26T15:35:11",
            "name": "net/mlx5: add support for multiport IB devices",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/3928/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/51739/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/51739/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 83E6B1B39A;\n\tTue, 26 Mar 2019 16:36:40 +0100 (CET)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n\tby dpdk.org (Postfix) with ESMTP id 67BAE1B130\n\tfor <dev@dpdk.org>; Tue, 26 Mar 2019 16:36:05 +0100 (CET)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n\tviacheslavo@mellanox.com)\n\twith ESMTPS (AES256-SHA encrypted); 26 Mar 2019 17:36:02 +0200",
            "from pegasus12.mtr.labs.mlnx. (pegasus12.mtr.labs.mlnx\n\t[10.210.17.40])\n\tby labmailer.mlnx (8.13.8/8.13.8) with ESMTP id x2QFa1wS019637;\n\tTue, 26 Mar 2019 17:36:02 +0200"
        ],
        "From": "Viacheslav Ovsiienko <viacheslavo@mellanox.com>",
        "To": "dev@dpdk.org",
        "Cc": "shahafs@mellanox.com",
        "Date": "Tue, 26 Mar 2019 15:35:14 +0000",
        "Message-Id": "<1553614522-12151-6-git-send-email-viacheslavo@mellanox.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1553614522-12151-1-git-send-email-viacheslavo@mellanox.com>",
        "References": "<1553533414-9911-1-git-send-email-viacheslavo@mellanox.com>\n\t<1553614522-12151-1-git-send-email-viacheslavo@mellanox.com>",
        "Subject": "[dpdk-dev] [PATCH v3 05/13] net/mlx5: add IB shared context\n\talloc/free functions",
        "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\t<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\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "The Mellanox NICs support SR-IOV and have E-Switch feature.\nWhen SR-IOV is set up in switchdev mode and E-Switch is enabled\nwe have so called VF representors in the system. All representors\nbelonging to the same E-Switch are created on the basis of the\nsingle PCI function and with current implementation each representor\nhas its own dedicated Infiniband device and operates within its\nown Infiniband context. It is proposed to provide representors\nas ports of the single Infiniband device and operate on the\nshared Infiniband context saving various resources. This patch\nintroduces appropriate structures.\n\nAlso the functions to allocate and free shared IB context for\nmultiport are added. The IB device context, Protection Domain,\ndevice attributes, Infiniband names are going to be relocated\nto the shared structure from the device private one.\nmlx5_dev_spawn() is updated to support shared context.\n\nSigned-off-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>\n---\n drivers/net/mlx5/mlx5.c | 302 +++++++++++++++++++++++++++++++++---------------\n drivers/net/mlx5/mlx5.h |  32 +++++\n 2 files changed, 239 insertions(+), 95 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex 9e3a98f..dd70e53 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -140,6 +140,145 @@ struct mlx5_dev_spawn_data {\n \tstruct rte_eth_dev *eth_dev; /**< Associated Ethernet device. */\n };\n \n+static LIST_HEAD(, mlx5_ibv_shared) mlx5_ibv_list = LIST_HEAD_INITIALIZER();\n+static pthread_mutex_t mlx5_ibv_list_mutex = PTHREAD_MUTEX_INITIALIZER;\n+\n+/**\n+ * Allocate shared IB device context. If there is multiport device the\n+ * master and representors will share this context, if there is single\n+ * port dedicated IB device, the context will be used by only given\n+ * port due to unification.\n+ *\n+ * Routine first searches the context for the spesified IB device name,\n+ * if found the shared context assumed and reference counter is incremented.\n+ * If no context found the new one is created and initialized with specified\n+ * IB device context and parameters.\n+ *\n+ * @param[in] spawn\n+ *   Pointer to the IB device attributes (name, port, etc).\n+ *\n+ * @return\n+ *   Pointer to mlx5_ibv_shared object on success,\n+ *   otherwise NULL and rte_errno is set.\n+ */\n+static struct mlx5_ibv_shared *\n+mlx5_alloc_shared_ibctx(const struct mlx5_dev_spawn_data *spawn)\n+{\n+\tstruct mlx5_ibv_shared *sh;\n+\tint err = 0;\n+\n+\tassert(spawn);\n+\t/* Secondary process should not create the shared context. */\n+\tassert(rte_eal_process_type() == RTE_PROC_PRIMARY);\n+\tpthread_mutex_lock(&mlx5_ibv_list_mutex);\n+\t/* Search for IB context by device name. */\n+\tLIST_FOREACH(sh, &mlx5_ibv_list, next) {\n+\t\tif (!strcmp(sh->ibdev_name, spawn->ibv_dev->name)) {\n+\t\t\tsh->refcnt++;\n+\t\t\tgoto exit;\n+\t\t}\n+\t}\n+\t/* No device found, we have to create new sharted context. */\n+\tassert(spawn->max_port);\n+\tsh = rte_zmalloc(\"ethdev shared ib context\",\n+\t\t\t sizeof(struct mlx5_ibv_shared) +\n+\t\t\t spawn->max_port *\n+\t\t\t sizeof(struct mlx5_ibv_shared_port),\n+\t\t\t RTE_CACHE_LINE_SIZE);\n+\tif (!sh) {\n+\t\tDRV_LOG(ERR, \"shared context allocation failure\");\n+\t\trte_errno  = ENOMEM;\n+\t\tgoto exit;\n+\t}\n+\t/* Try to open IB device with DV first, then usual Verbs. */\n+\terrno = 0;\n+\tsh->ctx = mlx5_glue->dv_open_device(spawn->ibv_dev);\n+\tif (sh->ctx) {\n+\t\tsh->devx = 1;\n+\t\tDRV_LOG(DEBUG, \"DevX is supported\");\n+\t} else {\n+\t\tsh->ctx = mlx5_glue->open_device(spawn->ibv_dev);\n+\t\tif (!sh->ctx) {\n+\t\t\terr = errno ? errno : ENODEV;\n+\t\t\tgoto error;\n+\t\t}\n+\t\tDRV_LOG(DEBUG, \"DevX is NOT supported\");\n+\t}\n+\terr = mlx5_glue->query_device_ex(sh->ctx, NULL, &sh->device_attr);\n+\tif (err) {\n+\t\tDRV_LOG(DEBUG, \"ibv_query_device_ex() failed\");\n+\t\tgoto error;\n+\t}\n+\tsh->refcnt = 1;\n+\tsh->max_port = spawn->max_port;\n+\tstrncpy(sh->ibdev_name, sh->ctx->device->name,\n+\t\tsizeof(sh->ibdev_name));\n+\tstrncpy(sh->ibdev_path, sh->ctx->device->ibdev_path,\n+\t\tsizeof(sh->ibdev_path));\n+\tsh->pd = mlx5_glue->alloc_pd(sh->ctx);\n+\tif (sh->pd == NULL) {\n+\t\tDRV_LOG(ERR, \"PD allocation failure\");\n+\t\terr = ENOMEM;\n+\t\tgoto error;\n+\t}\n+\tLIST_INSERT_HEAD(&mlx5_ibv_list, sh, next);\n+exit:\n+\tpthread_mutex_unlock(&mlx5_ibv_list_mutex);\n+\treturn sh;\n+error:\n+\tpthread_mutex_unlock(&mlx5_ibv_list_mutex);\n+\tassert(sh);\n+\tif (sh->pd)\n+\t\tclaim_zero(mlx5_glue->dealloc_pd(sh->pd));\n+\tif (sh->ctx)\n+\t\tclaim_zero(mlx5_glue->close_device(sh->ctx));\n+\trte_free(sh);\n+\tassert(err > 0);\n+\trte_errno = err;\n+\treturn NULL;\n+}\n+\n+/**\n+ * Free shared IB device context. Decrement counter and if zero free\n+ * all allocated resources and close handles.\n+ *\n+ * @param[in] sh\n+ *   Pointer to mlx5_ibv_shared object to free\n+ */\n+static void\n+mlx5_free_shared_ibctx(struct mlx5_ibv_shared *sh)\n+{\n+\tpthread_mutex_lock(&mlx5_ibv_list_mutex);\n+#ifndef NDEBUG\n+\t/* Check the object presence in the list. */\n+\tstruct mlx5_ibv_shared *lctx;\n+\n+\tLIST_FOREACH(lctx, &mlx5_ibv_list, next)\n+\t\tif (lctx == sh)\n+\t\t\tbreak;\n+\tassert(lctx);\n+\tif (lctx != sh) {\n+\t\tDRV_LOG(ERR, \"Freeing non-existing shared IB context\");\n+\t\tgoto exit;\n+\t}\n+#endif\n+\tassert(sh);\n+\tassert(sh->refcnt);\n+\t/* Secondary process should not free the shared context. */\n+\tassert(rte_eal_process_type() == RTE_PROC_PRIMARY);\n+\tif (--sh->refcnt)\n+\t\tgoto exit;\n+\tLIST_REMOVE(sh, next);\n+\tif (sh->pd)\n+\t\tclaim_zero(mlx5_glue->dealloc_pd(sh->pd));\n+\tif (sh->ctx)\n+\t\tclaim_zero(mlx5_glue->close_device(sh->ctx));\n+\trte_free(sh);\n+exit:\n+\tpthread_mutex_unlock(&mlx5_ibv_list_mutex);\n+}\n+\n+\n /**\n  * Prepare shared data between primary and secondary process.\n  */\n@@ -289,12 +428,10 @@ struct mlx5_dev_spawn_data {\n \t}\n \tmlx5_mprq_free_mp(dev);\n \tmlx5_mr_release(dev);\n-\tif (priv->pd != NULL) {\n-\t\tassert(priv->ctx != NULL);\n-\t\tclaim_zero(mlx5_glue->dealloc_pd(priv->pd));\n-\t\tclaim_zero(mlx5_glue->close_device(priv->ctx));\n-\t} else\n-\t\tassert(priv->ctx == NULL);\n+\tassert(priv->sh);\n+\tif (priv->sh)\n+\t\tmlx5_free_shared_ibctx(priv->sh);\n+\tpriv->sh = NULL;\n \tif (priv->rss_conf.rss_key != NULL)\n \t\trte_free(priv->rss_conf.rss_key);\n \tif (priv->reta_idx != NULL)\n@@ -744,11 +881,8 @@ struct mlx5_dev_spawn_data {\n \t       struct mlx5_dev_config config)\n {\n \tconst struct mlx5_switch_info *switch_info = &spawn->info;\n-\tstruct ibv_device *ibv_dev = spawn->ibv_dev;\n-\tstruct ibv_context *ctx = NULL;\n-\tstruct ibv_device_attr_ex attr;\n+\tstruct mlx5_ibv_shared *sh;\n \tstruct ibv_port_attr port_attr;\n-\tstruct ibv_pd *pd = NULL;\n \tstruct mlx5dv_context dv_attr = { .comp_mask = 0 };\n \tstruct rte_eth_dev *eth_dev = NULL;\n \tstruct mlx5_priv *priv = NULL;\n@@ -807,18 +941,47 @@ struct mlx5_dev_spawn_data {\n \t}\n \t/* Prepare shared data between primary and secondary process. */\n \tmlx5_prepare_shared_data();\n-\terrno = 0;\n-\tctx = mlx5_glue->dv_open_device(ibv_dev);\n-\tif (ctx) {\n-\t\tconfig.devx = 1;\n-\t\tDRV_LOG(DEBUG, \"DEVX is supported\");\n-\t} else {\n-\t\tctx = mlx5_glue->open_device(ibv_dev);\n-\t\tif (!ctx) {\n-\t\t\trte_errno = errno ? errno : ENODEV;\n-\t\t\treturn NULL;\n+\tDRV_LOG(DEBUG, \"naming Ethernet device \\\"%s\\\"\", name);\n+\tif (rte_eal_process_type() == RTE_PROC_SECONDARY) {\n+\t\teth_dev = rte_eth_dev_attach_secondary(name);\n+\t\tif (eth_dev == NULL) {\n+\t\t\tDRV_LOG(ERR, \"can not attach rte ethdev\");\n+\t\t\trte_errno = ENOMEM;\n+\t\t\terr = rte_errno;\n+\t\t\tgoto error;\n+\t\t}\n+\t\teth_dev->device = dpdk_dev;\n+\t\teth_dev->dev_ops = &mlx5_dev_sec_ops;\n+\t\terr = mlx5_uar_init_secondary(eth_dev);\n+\t\tif (err) {\n+\t\t\terr = rte_errno;\n+\t\t\tgoto error;\n \t\t}\n+\t\t/* Receive command fd from primary process */\n+\t\terr = mlx5_socket_connect(eth_dev);\n+\t\tif (err < 0) {\n+\t\t\terr = rte_errno;\n+\t\t\tgoto error;\n+\t\t}\n+\t\t/* Remap UAR for Tx queues. */\n+\t\terr = mlx5_tx_uar_remap(eth_dev, err);\n+\t\tif (err) {\n+\t\t\terr = rte_errno;\n+\t\t\tgoto error;\n+\t\t}\n+\t\t/*\n+\t\t * Ethdev pointer is still required as input since\n+\t\t * the primary device is not accessible from the\n+\t\t * secondary process.\n+\t\t */\n+\t\teth_dev->rx_pkt_burst = mlx5_select_rx_function(eth_dev);\n+\t\teth_dev->tx_pkt_burst = mlx5_select_tx_function(eth_dev);\n+\t\treturn eth_dev;\n \t}\n+\tsh = mlx5_alloc_shared_ibctx(spawn);\n+\tif (!sh)\n+\t\treturn NULL;\n+\tconfig.devx = sh->devx;\n #ifdef HAVE_IBV_MLX5_MOD_SWP\n \tdv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_SWP;\n #endif\n@@ -832,7 +995,7 @@ struct mlx5_dev_spawn_data {\n #ifdef HAVE_IBV_DEVICE_STRIDING_RQ_SUPPORT\n \tdv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_STRIDING_RQ;\n #endif\n-\tmlx5_glue->dv_query_device(ctx, &dv_attr);\n+\tmlx5_glue->dv_query_device(sh->ctx, &dv_attr);\n \tif (dv_attr.flags & MLX5DV_CONTEXT_FLAGS_MPW_ALLOWED) {\n \t\tif (dv_attr.flags & MLX5DV_CONTEXT_FLAGS_ENHANCED_MPW) {\n \t\t\tDRV_LOG(DEBUG, \"enhanced MPW is supported\");\n@@ -917,51 +1080,8 @@ struct mlx5_dev_spawn_data {\n \t\t\" old OFED/rdma-core version or firmware configuration\");\n #endif\n \tconfig.mpls_en = mpls_en;\n-\terr = mlx5_glue->query_device_ex(ctx, NULL, &attr);\n-\tif (err) {\n-\t\tDEBUG(\"ibv_query_device_ex() failed\");\n-\t\tgoto error;\n-\t}\n-\tDRV_LOG(DEBUG, \"naming Ethernet device \\\"%s\\\"\", name);\n-\tif (rte_eal_process_type() == RTE_PROC_SECONDARY) {\n-\t\teth_dev = rte_eth_dev_attach_secondary(name);\n-\t\tif (eth_dev == NULL) {\n-\t\t\tDRV_LOG(ERR, \"can not attach rte ethdev\");\n-\t\t\trte_errno = ENOMEM;\n-\t\t\terr = rte_errno;\n-\t\t\tgoto error;\n-\t\t}\n-\t\teth_dev->device = dpdk_dev;\n-\t\teth_dev->dev_ops = &mlx5_dev_sec_ops;\n-\t\terr = mlx5_uar_init_secondary(eth_dev);\n-\t\tif (err) {\n-\t\t\terr = rte_errno;\n-\t\t\tgoto error;\n-\t\t}\n-\t\t/* Receive command fd from primary process */\n-\t\terr = mlx5_socket_connect(eth_dev);\n-\t\tif (err < 0) {\n-\t\t\terr = rte_errno;\n-\t\t\tgoto error;\n-\t\t}\n-\t\t/* Remap UAR for Tx queues. */\n-\t\terr = mlx5_tx_uar_remap(eth_dev, err);\n-\t\tif (err) {\n-\t\t\terr = rte_errno;\n-\t\t\tgoto error;\n-\t\t}\n-\t\t/*\n-\t\t * Ethdev pointer is still required as input since\n-\t\t * the primary device is not accessible from the\n-\t\t * secondary process.\n-\t\t */\n-\t\teth_dev->rx_pkt_burst = mlx5_select_rx_function(eth_dev);\n-\t\teth_dev->tx_pkt_burst = mlx5_select_tx_function(eth_dev);\n-\t\tclaim_zero(mlx5_glue->close_device(ctx));\n-\t\treturn eth_dev;\n-\t}\n \t/* Check port status. */\n-\terr = mlx5_glue->query_port(ctx, spawn->ibv_port, &port_attr);\n+\terr = mlx5_glue->query_port(sh->ctx, spawn->ibv_port, &port_attr);\n \tif (err) {\n \t\tDRV_LOG(ERR, \"port query failed: %s\", strerror(err));\n \t\tgoto error;\n@@ -975,13 +1095,7 @@ struct mlx5_dev_spawn_data {\n \t\tDRV_LOG(DEBUG, \"port is not active: \\\"%s\\\" (%d)\",\n \t\t\tmlx5_glue->port_state_str(port_attr.state),\n \t\t\tport_attr.state);\n-\t/* Allocate protection domain. */\n-\tpd = mlx5_glue->alloc_pd(ctx);\n-\tif (pd == NULL) {\n-\t\tDRV_LOG(ERR, \"PD allocation failure\");\n-\t\terr = ENOMEM;\n-\t\tgoto error;\n-\t}\n+\t/* Allocate private eth device data. */\n \tpriv = rte_zmalloc(\"ethdev private structure\",\n \t\t\t   sizeof(*priv),\n \t\t\t   RTE_CACHE_LINE_SIZE);\n@@ -990,13 +1104,11 @@ struct mlx5_dev_spawn_data {\n \t\terr = ENOMEM;\n \t\tgoto error;\n \t}\n-\tpriv->ctx = ctx;\n-\tstrncpy(priv->ibdev_name, priv->ctx->device->name,\n-\t\tsizeof(priv->ibdev_name));\n-\tstrncpy(priv->ibdev_path, priv->ctx->device->ibdev_path,\n-\t\tsizeof(priv->ibdev_path));\n-\tpriv->device_attr = attr;\n-\tpriv->pd = pd;\n+\tpriv->sh = sh;\n+\tpriv->ctx = sh->ctx;\n+\tpriv->ibv_port = spawn->ibv_port;\n+\tpriv->device_attr = sh->device_attr;\n+\tpriv->pd = sh->pd;\n \tpriv->mtu = ETHER_MTU;\n #ifndef RTE_ARCH_64\n \t/* Initialize UAR access locks for 32bit implementations. */\n@@ -1065,7 +1177,8 @@ struct mlx5_dev_spawn_data {\n \t\t\tstrerror(rte_errno));\n \t\tgoto error;\n \t}\n-\tconfig.hw_csum = !!(attr.device_cap_flags_ex & IBV_DEVICE_RAW_IP_CSUM);\n+\tconfig.hw_csum = !!(sh->device_attr.device_cap_flags_ex &\n+\t\t\t    IBV_DEVICE_RAW_IP_CSUM);\n \tDRV_LOG(DEBUG, \"checksum offloading is %ssupported\",\n \t\t(config.hw_csum ? \"\" : \"not \"));\n #if !defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) && \\\n@@ -1079,7 +1192,7 @@ struct mlx5_dev_spawn_data {\n \t}\n #endif\n \tconfig.ind_table_max_size =\n-\t\tattr.rss_caps.max_rwq_indirection_table_size;\n+\t\tsh->device_attr.rss_caps.max_rwq_indirection_table_size;\n \t/*\n \t * Remove this check once DPDK supports larger/variable\n \t * indirection tables.\n@@ -1088,18 +1201,18 @@ struct mlx5_dev_spawn_data {\n \t\tconfig.ind_table_max_size = ETH_RSS_RETA_SIZE_512;\n \tDRV_LOG(DEBUG, \"maximum Rx indirection table size is %u\",\n \t\tconfig.ind_table_max_size);\n-\tconfig.hw_vlan_strip = !!(attr.raw_packet_caps &\n+\tconfig.hw_vlan_strip = !!(sh->device_attr.raw_packet_caps &\n \t\t\t\t  IBV_RAW_PACKET_CAP_CVLAN_STRIPPING);\n \tDRV_LOG(DEBUG, \"VLAN stripping is %ssupported\",\n \t\t(config.hw_vlan_strip ? \"\" : \"not \"));\n-\tconfig.hw_fcs_strip = !!(attr.raw_packet_caps &\n+\tconfig.hw_fcs_strip = !!(sh->device_attr.raw_packet_caps &\n \t\t\t\t IBV_RAW_PACKET_CAP_SCATTER_FCS);\n \tDRV_LOG(DEBUG, \"FCS stripping configuration is %ssupported\",\n \t\t(config.hw_fcs_strip ? \"\" : \"not \"));\n #if defined(HAVE_IBV_WQ_FLAG_RX_END_PADDING)\n-\thw_padding = !!attr.rx_pad_end_addr_align;\n+\thw_padding = !!sh->device_attr.rx_pad_end_addr_align;\n #elif defined(HAVE_IBV_WQ_FLAGS_PCI_WRITE_END_PADDING)\n-\thw_padding = !!(attr.device_cap_flags_ex &\n+\thw_padding = !!(sh->device_attr.device_cap_flags_ex &\n \t\t\tIBV_DEVICE_PCI_WRITE_END_PADDING);\n #endif\n \tif (config.hw_padding && !hw_padding) {\n@@ -1108,11 +1221,11 @@ struct mlx5_dev_spawn_data {\n \t} else if (config.hw_padding) {\n \t\tDRV_LOG(DEBUG, \"Rx end alignment padding is enabled\");\n \t}\n-\tconfig.tso = (attr.tso_caps.max_tso > 0 &&\n-\t\t      (attr.tso_caps.supported_qpts &\n+\tconfig.tso = (sh->device_attr.tso_caps.max_tso > 0 &&\n+\t\t      (sh->device_attr.tso_caps.supported_qpts &\n \t\t       (1 << IBV_QPT_RAW_PACKET)));\n \tif (config.tso)\n-\t\tconfig.tso_max_payload_sz = attr.tso_caps.max_tso;\n+\t\tconfig.tso_max_payload_sz = sh->device_attr.tso_caps.max_tso;\n \t/*\n \t * MPW is disabled by default, while the Enhanced MPW is enabled\n \t * by default.\n@@ -1246,7 +1359,7 @@ struct mlx5_dev_spawn_data {\n \t\t}\n \t}\n #ifdef HAVE_MLX5DV_DR\n-\t\tns = mlx5dv_dr_create_ns(ctx,\n+\t\tns = mlx5dv_dr_create_ns(sh->ctx,\n \t\t\t\t\t MLX5DV_DR_NS_DOMAIN_INGRESS_BYPASS);\n \t\tif (ns == NULL) {\n \t\t\tDRV_LOG(ERR, \"mlx5dv_dr_create_ns failed\");\n@@ -1254,7 +1367,7 @@ struct mlx5_dev_spawn_data {\n \t\t\tgoto error;\n \t\t}\n \t\tpriv->rx_ns = ns;\n-\t\tns = mlx5dv_dr_create_ns(ctx,\n+\t\tns = mlx5dv_dr_create_ns(sh->ctx,\n \t\t\t\t\t MLX5DV_DR_NS_DOMAIN_EGRESS_BYPASS);\n \t\tif (ns == NULL) {\n \t\t\tDRV_LOG(ERR, \"mlx5dv_dr_create_ns failed\");\n@@ -1271,7 +1384,8 @@ struct mlx5_dev_spawn_data {\n \t\t.free = &mlx5_free_verbs_buf,\n \t\t.data = priv,\n \t};\n-\tmlx5_glue->dv_set_context_attr(ctx, MLX5DV_CTX_ATTR_BUF_ALLOCATORS,\n+\tmlx5_glue->dv_set_context_attr(sh->ctx,\n+\t\t\t\t       MLX5DV_CTX_ATTR_BUF_ALLOCATORS,\n \t\t\t\t       (void *)((uintptr_t)&alctr));\n \t/* Bring Ethernet device up. */\n \tDRV_LOG(DEBUG, \"port %u forcing Ethernet interface up\",\n@@ -1325,15 +1439,13 @@ struct mlx5_dev_spawn_data {\n \t\tif (eth_dev != NULL)\n \t\t\teth_dev->data->dev_private = NULL;\n \t}\n-\tif (pd)\n-\t\tclaim_zero(mlx5_glue->dealloc_pd(pd));\n \tif (eth_dev != NULL) {\n \t\t/* mac_addrs must not be freed alone because part of dev_private */\n \t\teth_dev->data->mac_addrs = NULL;\n \t\trte_eth_dev_release_port(eth_dev);\n \t}\n-\tif (ctx)\n-\t\tclaim_zero(mlx5_glue->close_device(ctx));\n+\tif (sh)\n+\t\tmlx5_free_shared_ibctx(sh);\n \tassert(err > 0);\n \trte_errno = err;\n \treturn NULL;\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 309232b..f612577 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -196,10 +196,42 @@ struct mlx5_flow_tbl_resource {\n #define MLX5_MAX_TABLES 1024\n #define MLX5_GROUP_FACTOR 1\n \n+/* Per port data of shared IB device. */\n+struct mlx5_ibv_shared_port {\n+\tuint32_t ih_port_id;\n+\t/*\n+\t * Interrupt handler port_id. Used by shared interrupt\n+\t * handler to find the corresponding rte_eth device\n+\t * by IB port index. If value is equal or greater\n+\t * RTE_MAX_ETHPORTS it means there is no subhandler\n+\t * installed for specified IB port index.\n+\t */\n+};\n+\n+/*\n+ * Shared Infiniband device context for Master/Representors\n+ * which belong to same IB device with multiple IB ports.\n+ **/\n+struct mlx5_ibv_shared {\n+\tLIST_ENTRY(mlx5_ibv_shared) next;\n+\tuint32_t refcnt;\n+\tuint32_t devx:1; /* Opened with DV. */\n+\tuint32_t max_port; /* Maximal IB device port index. */\n+\tstruct ibv_context *ctx; /* Verbs/DV context. */\n+\tstruct ibv_pd *pd; /* Protection Domain. */\n+\tchar ibdev_name[IBV_SYSFS_NAME_MAX]; /* IB device name. */\n+\tchar ibdev_path[IBV_SYSFS_PATH_MAX]; /* IB device path for secondary */\n+\tstruct ibv_device_attr_ex device_attr; /* Device properties. */\n+\tstruct rte_intr_handle intr_handle; /* Interrupt handler for device. */\n+\tstruct mlx5_ibv_shared_port port[]; /* per device port data array. */\n+};\n+\n struct mlx5_priv {\n \tLIST_ENTRY(mlx5_priv) mem_event_cb;\n \t/**< Called by memory event callback. */\n \tstruct rte_eth_dev_data *dev_data;  /* Pointer to device data. */\n+\tstruct mlx5_ibv_shared *sh; /* Shared IB device context. */\n+\tuint32_t ibv_port; /* IB device port number. */\n \tstruct ibv_context *ctx; /* Verbs context. */\n \tstruct ibv_device_attr_ex device_attr; /* Device properties. */\n \tstruct ibv_pd *pd; /* Protection Domain. */\n",
    "prefixes": [
        "v3",
        "05/13"
    ]
}