get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 42735,
    "url": "http://patches.dpdk.org/api/patches/42735/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20180710155743.14448-8-adrien.mazarguil@6wind.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": "<20180710155743.14448-8-adrien.mazarguil@6wind.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20180710155743.14448-8-adrien.mazarguil@6wind.com",
    "date": "2018-07-10T16:04:54",
    "name": "[v5,07/10] net/mlx5: probe all port representors",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "528cadf90f772529d3d4a2b2dbd24170d7ed0614",
    "submitter": {
        "id": 165,
        "url": "http://patches.dpdk.org/api/people/165/?format=api",
        "name": "Adrien Mazarguil",
        "email": "adrien.mazarguil@6wind.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/20180710155743.14448-8-adrien.mazarguil@6wind.com/mbox/",
    "series": [
        {
            "id": 501,
            "url": "http://patches.dpdk.org/api/series/501/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=501",
            "date": "2018-07-10T16:04:39",
            "name": "net/mlx5: add port representor support",
            "version": 5,
            "mbox": "http://patches.dpdk.org/series/501/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/42735/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/42735/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 825711B462;\n\tTue, 10 Jul 2018 18:05:16 +0200 (CEST)",
            "from mail-wr1-f65.google.com (mail-wr1-f65.google.com\n\t[209.85.221.65]) by dpdk.org (Postfix) with ESMTP id 542611B452\n\tfor <dev@dpdk.org>; Tue, 10 Jul 2018 18:05:11 +0200 (CEST)",
            "by mail-wr1-f65.google.com with SMTP id s11-v6so15192024wra.13\n\tfor <dev@dpdk.org>; Tue, 10 Jul 2018 09:05:11 -0700 (PDT)",
            "from 6wind.com (host.78.145.23.62.rev.coltfrance.com.\n\t[62.23.145.78]) by smtp.gmail.com with ESMTPSA id\n\tq140-v6sm24473980wmb.35.2018.07.10.09.05.10\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tTue, 10 Jul 2018 09:05:10 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=6wind-com.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:in-reply-to;\n\tbh=VhC3Y2HO4ZXiMa/bUy+RgaIjhKfcca8X0XmZin+OFTQ=;\n\tb=GaTekbmCBrbDNbVP+nmcisYo/Ry/KOEpzSgjrp6d6kKY3+RvGzUxB4Y+iDmiLo+WtF\n\tdVqfTOmo3xXUEg9W2PvuDyZfNI9bTu0m0st8bfBASn66Mc9dCL8f3iL/3VSB50JjOIPO\n\ty9YbyaGvHwN6jcUjb70o5csLqfgp+Zf/6NGB9FCF8yribLNMDs6y6du7sjh1I93sO7rL\n\tpa394rGSeTGEBMAmX7pblKr6etOrgsXizvsrq9vggyUkiYjRJEXKB9EnZxey4tWw5eWf\n\t8nYPrSyJt1Oz+0A++qeZhaZnyakRCMDo44VbrP3dNs43s+z1c6QtC8xl8kGd9e77zYMt\n\tezPQ==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:in-reply-to;\n\tbh=VhC3Y2HO4ZXiMa/bUy+RgaIjhKfcca8X0XmZin+OFTQ=;\n\tb=fgG1TwtsN9H15Dg2tsvAA4t4/aoFiLhSCkGCjOo0vbX5siJfrv3cuUIJ948PMCTNE9\n\tkcNdKsJ7NFuT/GDXwI8QjwghKLjBrVrprTqJTpthdZ2HXO/ItcImKRTLBWzKE9Ihmlv3\n\tJSSp7vIig4gL7Xh9CmxIEZ9VS5DQl9jpXol0rT9jDXzBOCzrDFHdTd7xUsrA09cbCwFK\n\tVRPaPaixNmkGzxXilRr5uqKmpc6b1ivTS/5N1U2trLsAne0W1TkEKEtIWwK1Bw5TNXui\n\t5zkb2gr0A24kQwFf4qjyjoAgoekVSlq38g71GCquPyJbBDBRAN37RG4T3H77Xdt1ZcXZ\n\trbSQ==",
        "X-Gm-Message-State": "APt69E39ZOmBg+IdghwUKzHgM1SUk7XL2nv/obs7Pq5DvUwvHvMutuo9\n\tiqi+zdAiAV9bqtrTYX2YXCu7cQ==",
        "X-Google-Smtp-Source": "AAOMgpeuVPChlPLjcQf0YtRgZyi6pacBQIX62Cx/fFp6jjBC1t+rpS87ZqYghncXaI17nMF6+A+aAA==",
        "X-Received": "by 2002:adf:b05c:: with SMTP id\n\tg28-v6mr17664983wra.128.1531238710844; \n\tTue, 10 Jul 2018 09:05:10 -0700 (PDT)",
        "Date": "Tue, 10 Jul 2018 18:04:54 +0200",
        "From": "Adrien Mazarguil <adrien.mazarguil@6wind.com>",
        "To": "Shahaf Shuler <shahafs@mellanox.com>",
        "Cc": "dev@dpdk.org, Nelio Laranjeiro <nelio.laranjeiro@6wind.com>,\n\tXueming Li <xuemingl@mellanox.com>",
        "Message-ID": "<20180710155743.14448-8-adrien.mazarguil@6wind.com>",
        "References": "<20180705083934.5535-1-adrien.mazarguil@6wind.com>\n\t<20180710155743.14448-1-adrien.mazarguil@6wind.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=us-ascii",
        "Content-Disposition": "inline",
        "In-Reply-To": "<20180710155743.14448-1-adrien.mazarguil@6wind.com>",
        "X-Mailer": "git-send-email 2.11.0",
        "Subject": "[dpdk-dev] [PATCH v5 07/10] net/mlx5: probe all port representors",
        "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": "Probe existing port representors in addition to their master device and\nassociate them automatically.\n\nTo avoid collision between Ethernet devices, they are named as follows:\n\n- \"{DBDF}\" for master/switch devices.\n- \"{DBDF}_representor_{rep}\" with \"rep\" starting from 0 for port\n  representors.\n\n(Patch based on prior work from Yuanhan Liu)\n\nSigned-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>\nSigned-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>\nReviewed-by: Xueming Li <xuemingl@mellanox.com>\nCc: Xueming Li <xuemingl@mellanox.com>\nCc: Shahaf Shuler <shahafs@mellanox.com>\n--\nv4 changes:\n\n- Fixed domain ID release once the last port using it is closed. Closed\n  devices are not necessarily detached, their presence is not a good\n  indicator. Code was modified to check if they still use their domain IDs\n  before deciding to release it.\n\nv3 changes:\n\n- Nelio introduced mlx5_dev_to_port_id() to prevent the master device from\n  releasing a domain ID while representors are still bound. It is now\n  released by the last device closed.\n- Reverted to original naming convention as requested by Xueming and\n  Shahaf; \"net_\" prefix and \"_0\" suffix were dropped.\n- mlx5_dev_spawn() (previously mlx5_dev_spawn_one()) now decides on its own\n  whether underlying device is a representor.\n- Devices can now be probed in any order and not necessarily all at once;\n  representors can exist without a master device.\n- mlx5_pci_probe() iterates on the list of devices directly instead of\n  relying on an intermediate function (previously mlx5_dev_spawn()).\n- mlx5_get_ifname() was rewritten to rely on mlx5_nl_ifindex() when faced\n  with a representor.\n- Since it is not necessarily present, master device is now dynamically\n  retrieved in mlx5_dev_infos_get().\n\nv2 changes:\n\n- Added representor information to dev_infos_get(). DPDK port ID of master\n  device is now stored in the private structure to retrieve it\n  conveniently.\n- Master device is assigned dummy representor ID value -1 to better\n  distinguish from the the first actual representor reported by\n  dev_infos_get() as those are indexed from 0.\n- Added RTE_ETH_DEV_REPRESENTOR device flag.\n---\n drivers/net/mlx5/mlx5.c        | 134 ++++++++++++++++++++++++++++--------\n drivers/net/mlx5/mlx5.h        |  12 +++-\n drivers/net/mlx5/mlx5_ethdev.c | 133 +++++++++++++++++++++++++++++++----\n drivers/net/mlx5/mlx5_mac.c    |   2 +-\n drivers/net/mlx5/mlx5_stats.c  |   6 +-\n 5 files changed, 238 insertions(+), 49 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex d06ba9886..c02afbb82 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -307,7 +307,27 @@ mlx5_dev_close(struct rte_eth_dev *dev)\n \tif (ret)\n \t\tDRV_LOG(WARNING, \"port %u some flows still remain\",\n \t\t\tdev->data->port_id);\n+\tif (priv->domain_id != RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) {\n+\t\tunsigned int c = 0;\n+\t\tunsigned int i = mlx5_dev_to_port_id(dev->device, NULL, 0);\n+\t\tuint16_t port_id[i];\n+\n+\t\ti = RTE_MIN(mlx5_dev_to_port_id(dev->device, port_id, i), i);\n+\t\twhile (i--) {\n+\t\t\tstruct priv *opriv =\n+\t\t\t\trte_eth_devices[port_id[i]].data->dev_private;\n+\n+\t\t\tif (!opriv ||\n+\t\t\t    opriv->domain_id != priv->domain_id ||\n+\t\t\t    &rte_eth_devices[port_id[i]] == dev)\n+\t\t\t\tcontinue;\n+\t\t\t++c;\n+\t\t}\n+\t\tif (!c)\n+\t\t\tclaim_zero(rte_eth_switch_domain_free(priv->domain_id));\n+\t}\n \tmemset(priv, 0, sizeof(*priv));\n+\tpriv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;\n }\n \n const struct eth_dev_ops mlx5_dev_ops = {\n@@ -647,6 +667,8 @@ mlx5_uar_init_secondary(struct rte_eth_dev *dev)\n  *   Verbs device.\n  * @param vf\n  *   If nonzero, enable VF-specific features.\n+ * @param[in] switch_info\n+ *   Switch properties of Ethernet device.\n  *\n  * @return\n  *   A valid Ethernet device object on success, NULL otherwise and rte_errno\n@@ -655,7 +677,8 @@ mlx5_uar_init_secondary(struct rte_eth_dev *dev)\n static struct rte_eth_dev *\n mlx5_dev_spawn(struct rte_device *dpdk_dev,\n \t       struct ibv_device *ibv_dev,\n-\t       int vf)\n+\t       int vf,\n+\t       const struct mlx5_switch_info *switch_info)\n {\n \tstruct ibv_context *ctx;\n \tstruct ibv_device_attr_ex attr;\n@@ -697,6 +720,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n #endif\n \tstruct ether_addr mac;\n \tchar name[RTE_ETH_NAME_MAX_LEN];\n+\tint own_domain_id = 0;\n+\tunsigned int i;\n \n \t/* Prepare shared data between primary and secondary process. */\n \tmlx5_prepare_shared_data();\n@@ -805,7 +830,12 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n \t\tDEBUG(\"ibv_query_device_ex() failed\");\n \t\tgoto error;\n \t}\n-\trte_strlcpy(name, dpdk_dev->name, sizeof(name));\n+\tif (!switch_info->representor)\n+\t\trte_strlcpy(name, dpdk_dev->name, sizeof(name));\n+\telse\n+\t\tsnprintf(name, sizeof(name), \"%s_representor_%u\",\n+\t\t\t dpdk_dev->name, switch_info->port_name);\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@@ -874,6 +904,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\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@@ -883,6 +915,41 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n \tpriv->nl_socket_rdma = mlx5_nl_init(0, NETLINK_RDMA);\n \tpriv->nl_socket_route =\tmlx5_nl_init(RTMGRP_LINK, NETLINK_ROUTE);\n \tpriv->nl_sn = 0;\n+\tpriv->representor = !!switch_info->representor;\n+\tpriv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;\n+\tpriv->representor_id =\n+\t\tswitch_info->representor ? switch_info->port_name : -1;\n+\t/*\n+\t * Look for sibling devices in order to reuse their switch domain\n+\t * if any, otherwise allocate one.\n+\t */\n+\ti = mlx5_dev_to_port_id(dpdk_dev, NULL, 0);\n+\tif (i > 0) {\n+\t\tuint16_t port_id[i];\n+\n+\t\ti = RTE_MIN(mlx5_dev_to_port_id(dpdk_dev, port_id, i), i);\n+\t\twhile (i--) {\n+\t\t\tconst struct priv *opriv =\n+\t\t\t\trte_eth_devices[port_id[i]].data->dev_private;\n+\n+\t\t\tif (!opriv ||\n+\t\t\t    opriv->domain_id ==\n+\t\t\t    RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID)\n+\t\t\t\tcontinue;\n+\t\t\tpriv->domain_id = opriv->domain_id;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tif (priv->domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) {\n+\t\terr = rte_eth_switch_domain_alloc(&priv->domain_id);\n+\t\tif (err) {\n+\t\t\terr = rte_errno;\n+\t\t\tDRV_LOG(ERR, \"unable to allocate switch domain: %s\",\n+\t\t\t\tstrerror(rte_errno));\n+\t\t\tgoto error;\n+\t\t}\n+\t\town_domain_id = 1;\n+\t}\n \terr = mlx5_args(&config, dpdk_dev->devargs);\n \tif (err) {\n \t\terr = rte_errno;\n@@ -966,6 +1033,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n \t\terr = ENOMEM;\n \t\tgoto error;\n \t}\n+\tif (priv->representor)\n+\t\teth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;\n \teth_dev->data->dev_private = priv;\n \tpriv->dev_data = eth_dev->data;\n \teth_dev->data->mac_addrs = priv->mac;\n@@ -1084,6 +1153,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n \t\t\tclose(priv->nl_socket_route);\n \t\tif (priv->nl_socket_rdma >= 0)\n \t\t\tclose(priv->nl_socket_rdma);\n+\t\tif (own_domain_id)\n+\t\t\tclaim_zero(rte_eth_switch_domain_free(priv->domain_id));\n \t\trte_free(priv);\n \t}\n \tif (pd)\n@@ -1100,7 +1171,7 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n /**\n  * DPDK callback to register a PCI device.\n  *\n- * This function spawns an Ethernet device out of a given PCI device.\n+ * This function spawns Ethernet devices out of a given PCI device.\n  *\n  * @param[in] pci_drv\n  *   PCI driver structure (mlx5_driver).\n@@ -1115,7 +1186,6 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,\n \t       struct rte_pci_device *pci_dev)\n {\n \tstruct ibv_device **ibv_list;\n-\tstruct rte_eth_dev *eth_dev = NULL;\n \tunsigned int n = 0;\n \tint vf;\n \tint ret;\n@@ -1150,9 +1220,11 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,\n \n \tunsigned int ifindex[n];\n \tstruct mlx5_switch_info info[n];\n+\tstruct rte_eth_dev *eth_list[n];\n \tint nl_route = n ? mlx5_nl_init(0, NETLINK_ROUTE) : -1;\n \tint nl_rdma = n ? mlx5_nl_init(0, NETLINK_RDMA) : -1;\n \tunsigned int i;\n+\tunsigned int u;\n \n \t/*\n \t * The existence of several matching entries (n > 1) means port\n@@ -1187,28 +1259,14 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,\n \t\tclose(nl_rdma);\n \tif (nl_route >= 0)\n \t\tclose(nl_route);\n-\t/* Look for master device. */\n-\tfor (i = 0; i != n; ++i) {\n-\t\tif (!info[i].master)\n-\t\t\tcontinue;\n-\t\t/* Make it the first entry. */\n-\t\tif (i == 0)\n-\t\t\tbreak;\n-\t\tibv_match[n] = ibv_match[0];\n-\t\tibv_match[0] = ibv_match[i];\n-\t\tibv_match[n] = NULL;\n-\t\tbreak;\n-\t}\n-\tif (n && i == n) {\n-\t\tif (n == 1 && !info[0].representor) {\n+\t/* Count unidentified devices. */\n+\tfor (u = 0, i = 0; i != n; ++i)\n+\t\tif (!info[i].master && !info[i].representor)\n+\t\t\t++u;\n+\tif (u) {\n+\t\tif (n == 1 && u == 1) {\n \t\t\t/* Case #2. */\n \t\t\tDRV_LOG(INFO, \"no switch support detected\");\n-\t\t} else if (n == 1) {\n-\t\t\t/* Case #3. */\n-\t\t\tDRV_LOG(ERR,\n-\t\t\t\t\"device looks like a port representor, this is\"\n-\t\t\t\t\" not supported yet\");\n-\t\t\tn = 0;\n \t\t} else {\n \t\t\t/* Case #3. */\n \t\t\tDRV_LOG(ERR,\n@@ -1227,8 +1285,19 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,\n \tdefault:\n \t\tvf = 0;\n \t}\n-\tif (n)\n-\t\teth_dev = mlx5_dev_spawn(&pci_dev->device, ibv_match[0], vf);\n+\tfor (i = 0; i != n; ++i) {\n+\t\tuint32_t restore;\n+\n+\t\teth_list[i] = mlx5_dev_spawn(&pci_dev->device, ibv_match[i],\n+\t\t\t\t\t     vf, &info[i]);\n+\t\tif (!eth_list[i])\n+\t\t\tbreak;\n+\t\trestore = eth_list[i]->data->dev_flags;\n+\t\trte_eth_copy_pci_info(eth_list[i], pci_dev);\n+\t\t/* Restore non-PCI flags cleared by the above call. */\n+\t\teth_list[i]->data->dev_flags |= restore;\n+\t\trte_eth_dev_probing_finish(eth_list[i]);\n+\t}\n \tmlx5_glue->free_device_list(ibv_list);\n \tif (!n) {\n \t\tDRV_LOG(WARNING,\n@@ -1238,7 +1307,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,\n \t\t\tpci_dev->addr.devid, pci_dev->addr.function);\n \t\trte_errno = ENOENT;\n \t\tret = -rte_errno;\n-\t} else if (!eth_dev) {\n+\t} else if (i != n) {\n \t\tDRV_LOG(ERR,\n \t\t\t\"probe of PCI device \" PCI_PRI_FMT \" aborted after\"\n \t\t\t\" encountering an error: %s\",\n@@ -1246,9 +1315,16 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,\n \t\t\tpci_dev->addr.devid, pci_dev->addr.function,\n \t\t\tstrerror(rte_errno));\n \t\tret = -rte_errno;\n+\t\t/* Roll back. */\n+\t\twhile (i--) {\n+\t\t\tmlx5_dev_close(eth_list[i]);\n+\t\t\tif (rte_eal_process_type() == RTE_PROC_PRIMARY)\n+\t\t\t\trte_free(eth_list[i]->data->dev_private);\n+\t\t\tclaim_zero(rte_eth_dev_release_port(eth_list[i]));\n+\t\t}\n+\t\t/* Restore original error. */\n+\t\trte_errno = -ret;\n \t} else {\n-\t\trte_eth_copy_pci_info(eth_dev, pci_dev);\n-\t\trte_eth_dev_probing_finish(eth_dev);\n \t\tret = 0;\n \t}\n \treturn ret;\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 704046270..cc01310e0 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -159,6 +159,7 @@ struct priv {\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+\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 ether_addr mac[MLX5_MAX_MAC_ADDRESSES]; /* MAC addresses. */\n \tBITFIELD_DECLARE(mac_own, uint64_t, MLX5_MAX_MAC_ADDRESSES);\n@@ -168,6 +169,9 @@ struct priv {\n \t/* Device properties. */\n \tuint16_t mtu; /* Configured MTU. */\n \tunsigned int isolated:1; /* Whether isolated mode is enabled. */\n+\tunsigned int representor:1; /* Device is a port representor. */\n+\tuint16_t domain_id; /* Switch domain identifier. */\n+\tint32_t representor_id; /* Port representor identifier. */\n \t/* RX/TX queues. */\n \tunsigned int rxqs_n; /* RX queues array size. */\n \tunsigned int txqs_n; /* TX queues array size. */\n@@ -217,9 +221,12 @@ int mlx5_getenv_int(const char *);\n \n /* mlx5_ethdev.c */\n \n+int mlx5_get_master_ifname(const struct rte_eth_dev *dev,\n+\t\t\t   char (*ifname)[IF_NAMESIZE]);\n int mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE]);\n int mlx5_ifindex(const struct rte_eth_dev *dev);\n-int mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr);\n+int mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr,\n+\t       int master);\n int mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu);\n int mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep,\n \t\t   unsigned int flags);\n@@ -244,6 +251,9 @@ int mlx5_set_link_up(struct rte_eth_dev *dev);\n int mlx5_is_removed(struct rte_eth_dev *dev);\n eth_tx_burst_t mlx5_select_tx_function(struct rte_eth_dev *dev);\n eth_rx_burst_t mlx5_select_rx_function(struct rte_eth_dev *dev);\n+unsigned int mlx5_dev_to_port_id(const struct rte_device *dev,\n+\t\t\t\t uint16_t *port_list,\n+\t\t\t\t unsigned int port_list_n);\n \n /* mlx5_mac.c */\n \ndiff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c\nindex 819f5baad..05f66f7b6 100644\n--- a/drivers/net/mlx5/mlx5_ethdev.c\n+++ b/drivers/net/mlx5/mlx5_ethdev.c\n@@ -27,6 +27,7 @@\n #include <time.h>\n \n #include <rte_atomic.h>\n+#include <rte_common.h>\n #include <rte_ethdev_driver.h>\n #include <rte_bus_pci.h>\n #include <rte_mbuf.h>\n@@ -93,7 +94,7 @@ struct ethtool_link_settings {\n #endif\n \n /**\n- * Get interface name from private structure.\n+ * Get master interface name from private structure.\n  *\n  * @param[in] dev\n  *   Pointer to Ethernet device.\n@@ -104,7 +105,8 @@ struct ethtool_link_settings {\n  *   0 on success, a negative errno value otherwise and rte_errno is set.\n  */\n int\n-mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE])\n+mlx5_get_master_ifname(const struct rte_eth_dev *dev,\n+\t\t       char (*ifname)[IF_NAMESIZE])\n {\n \tstruct priv *priv = dev->data->dev_private;\n \tDIR *dir;\n@@ -179,6 +181,39 @@ mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE])\n }\n \n /**\n+ * Get interface name from private structure.\n+ *\n+ * This is a port representor-aware version of mlx5_get_master_ifname().\n+ *\n+ * @param[in] dev\n+ *   Pointer to Ethernet device.\n+ * @param[out] ifname\n+ *   Interface name output buffer.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+int\n+mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE])\n+{\n+\tstruct priv *priv = dev->data->dev_private;\n+\tunsigned int ifindex =\n+\t\tpriv->nl_socket_rdma >= 0 ?\n+\t\tmlx5_nl_ifindex(priv->nl_socket_rdma, priv->ibdev_name) : 0;\n+\n+\tif (!ifindex) {\n+\t\tif (!priv->representor)\n+\t\t\treturn mlx5_get_master_ifname(dev, ifname);\n+\t\trte_errno = ENXIO;\n+\t\treturn -rte_errno;\n+\t}\n+\tif (if_indextoname(ifindex, &(*ifname)[0]))\n+\t\treturn 0;\n+\trte_errno = errno;\n+\treturn -rte_errno;\n+}\n+\n+/**\n  * Get the interface index from device name.\n  *\n  * @param[in] dev\n@@ -214,12 +249,16 @@ mlx5_ifindex(const struct rte_eth_dev *dev)\n  *   Request number to pass to ioctl().\n  * @param[out] ifr\n  *   Interface request structure output buffer.\n+ * @param master\n+ *   When device is a port representor, perform request on master device\n+ *   instead.\n  *\n  * @return\n  *   0 on success, a negative errno value otherwise and rte_errno is set.\n  */\n int\n-mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr)\n+mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr,\n+\t   int master)\n {\n \tint sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);\n \tint ret = 0;\n@@ -228,7 +267,10 @@ mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr)\n \t\trte_errno = errno;\n \t\treturn -rte_errno;\n \t}\n-\tret = mlx5_get_ifname(dev, &ifr->ifr_name);\n+\tif (master)\n+\t\tret = mlx5_get_master_ifname(dev, &ifr->ifr_name);\n+\telse\n+\t\tret = mlx5_get_ifname(dev, &ifr->ifr_name);\n \tif (ret)\n \t\tgoto error;\n \tret = ioctl(sock, req, ifr);\n@@ -258,7 +300,7 @@ int\n mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu)\n {\n \tstruct ifreq request;\n-\tint ret = mlx5_ifreq(dev, SIOCGIFMTU, &request);\n+\tint ret = mlx5_ifreq(dev, SIOCGIFMTU, &request, 0);\n \n \tif (ret)\n \t\treturn ret;\n@@ -282,7 +324,7 @@ mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)\n {\n \tstruct ifreq request = { .ifr_mtu = mtu, };\n \n-\treturn mlx5_ifreq(dev, SIOCSIFMTU, &request);\n+\treturn mlx5_ifreq(dev, SIOCSIFMTU, &request, 0);\n }\n \n /**\n@@ -302,13 +344,13 @@ int\n mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags)\n {\n \tstruct ifreq request;\n-\tint ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request);\n+\tint ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request, 0);\n \n \tif (ret)\n \t\treturn ret;\n \trequest.ifr_flags &= keep;\n \trequest.ifr_flags |= flags & ~keep;\n-\treturn mlx5_ifreq(dev, SIOCSIFFLAGS, &request);\n+\treturn mlx5_ifreq(dev, SIOCSIFFLAGS, &request, 0);\n }\n \n /**\n@@ -477,6 +519,30 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)\n \tinfo->speed_capa = priv->link_speed_capa;\n \tinfo->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK;\n \tmlx5_set_default_params(dev, info);\n+\tinfo->switch_info.name = dev->data->name;\n+\tinfo->switch_info.domain_id = priv->domain_id;\n+\tinfo->switch_info.port_id = priv->representor_id;\n+\tif (priv->representor) {\n+\t\tunsigned int i = mlx5_dev_to_port_id(dev->device, NULL, 0);\n+\t\tuint16_t port_id[i];\n+\n+\t\ti = RTE_MIN(mlx5_dev_to_port_id(dev->device, port_id, i), i);\n+\t\twhile (i--) {\n+\t\t\tstruct priv *opriv =\n+\t\t\t\trte_eth_devices[port_id[i]].data->dev_private;\n+\n+\t\t\tif (!opriv ||\n+\t\t\t    opriv->representor ||\n+\t\t\t    opriv->domain_id != priv->domain_id)\n+\t\t\t\tcontinue;\n+\t\t\t/*\n+\t\t\t * Override switch name with that of the master\n+\t\t\t * device.\n+\t\t\t */\n+\t\t\tinfo->switch_info.name = opriv->dev_data->name;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n }\n \n /**\n@@ -540,7 +606,7 @@ mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,\n \tint link_speed = 0;\n \tint ret;\n \n-\tret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);\n+\tret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr, 1);\n \tif (ret) {\n \t\tDRV_LOG(WARNING, \"port %u ioctl(SIOCGIFFLAGS) failed: %s\",\n \t\t\tdev->data->port_id, strerror(rte_errno));\n@@ -550,7 +616,7 @@ mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,\n \tdev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&\n \t\t\t\t(ifr.ifr_flags & IFF_RUNNING));\n \tifr.ifr_data = (void *)&edata;\n-\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);\n+\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);\n \tif (ret) {\n \t\tDRV_LOG(WARNING,\n \t\t\t\"port %u ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s\",\n@@ -611,7 +677,7 @@ mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,\n \tuint64_t sc;\n \tint ret;\n \n-\tret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);\n+\tret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr, 1);\n \tif (ret) {\n \t\tDRV_LOG(WARNING, \"port %u ioctl(SIOCGIFFLAGS) failed: %s\",\n \t\t\tdev->data->port_id, strerror(rte_errno));\n@@ -621,7 +687,7 @@ mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,\n \tdev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&\n \t\t\t\t(ifr.ifr_flags & IFF_RUNNING));\n \tifr.ifr_data = (void *)&gcmd;\n-\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);\n+\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);\n \tif (ret) {\n \t\tDRV_LOG(DEBUG,\n \t\t\t\"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)\"\n@@ -638,7 +704,7 @@ mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,\n \n \t*ecmd = gcmd;\n \tifr.ifr_data = (void *)ecmd;\n-\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);\n+\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);\n \tif (ret) {\n \t\tDRV_LOG(DEBUG,\n \t\t\t\"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)\"\n@@ -801,7 +867,7 @@ mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)\n \tint ret;\n \n \tifr.ifr_data = (void *)&ethpause;\n-\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);\n+\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);\n \tif (ret) {\n \t\tDRV_LOG(WARNING,\n \t\t\t\"port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:\"\n@@ -854,7 +920,7 @@ mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)\n \t\tethpause.tx_pause = 1;\n \telse\n \t\tethpause.tx_pause = 0;\n-\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);\n+\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 0);\n \tif (ret) {\n \t\tDRV_LOG(WARNING,\n \t\t\t\"port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)\"\n@@ -1193,3 +1259,40 @@ mlx5_is_removed(struct rte_eth_dev *dev)\n \t\treturn 1;\n \treturn 0;\n }\n+\n+/**\n+ * Get port ID list of mlx5 instances sharing a common device.\n+ *\n+ * @param[in] dev\n+ *   Device to look for.\n+ * @param[out] port_list\n+ *   Result buffer for collected port IDs.\n+ * @param port_list_n\n+ *   Maximum number of entries in result buffer. If 0, @p port_list can be\n+ *   NULL.\n+ *\n+ * @return\n+ *   Number of matching instances regardless of the @p port_list_n\n+ *   parameter, 0 if none were found.\n+ */\n+unsigned int\n+mlx5_dev_to_port_id(const struct rte_device *dev, uint16_t *port_list,\n+\t\t    unsigned int port_list_n)\n+{\n+\tuint16_t id;\n+\tunsigned int n = 0;\n+\n+\tRTE_ETH_FOREACH_DEV(id) {\n+\t\tstruct rte_eth_dev *ldev = &rte_eth_devices[id];\n+\n+\t\tif (!ldev->device ||\n+\t\t    !ldev->device->driver ||\n+\t\t    strcmp(ldev->device->driver->name, MLX5_DRIVER_NAME) ||\n+\t\t    ldev->device != dev)\n+\t\t\tcontinue;\n+\t\tif (n < port_list_n)\n+\t\t\tport_list[n] = id;\n+\t\tn++;\n+\t}\n+\treturn n;\n+}\ndiff --git a/drivers/net/mlx5/mlx5_mac.c b/drivers/net/mlx5/mlx5_mac.c\nindex 672a47619..12ee37f55 100644\n--- a/drivers/net/mlx5/mlx5_mac.c\n+++ b/drivers/net/mlx5/mlx5_mac.c\n@@ -49,7 +49,7 @@ mlx5_get_mac(struct rte_eth_dev *dev, uint8_t (*mac)[ETHER_ADDR_LEN])\n \tstruct ifreq request;\n \tint ret;\n \n-\tret = mlx5_ifreq(dev, SIOCGIFHWADDR, &request);\n+\tret = mlx5_ifreq(dev, SIOCGIFHWADDR, &request, 0);\n \tif (ret)\n \t\treturn ret;\n \tmemcpy(mac, request.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);\ndiff --git a/drivers/net/mlx5/mlx5_stats.c b/drivers/net/mlx5/mlx5_stats.c\nindex 875dd1027..91f3d474a 100644\n--- a/drivers/net/mlx5/mlx5_stats.c\n+++ b/drivers/net/mlx5/mlx5_stats.c\n@@ -146,7 +146,7 @@ mlx5_read_dev_counters(struct rte_eth_dev *dev, uint64_t *stats)\n \tet_stats->cmd = ETHTOOL_GSTATS;\n \tet_stats->n_stats = xstats_ctrl->stats_n;\n \tifr.ifr_data = (caddr_t)et_stats;\n-\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);\n+\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);\n \tif (ret) {\n \t\tDRV_LOG(WARNING,\n \t\t\t\"port %u unable to read statistic values from device\",\n@@ -194,7 +194,7 @@ mlx5_ethtool_get_stats_n(struct rte_eth_dev *dev) {\n \n \tdrvinfo.cmd = ETHTOOL_GDRVINFO;\n \tifr.ifr_data = (caddr_t)&drvinfo;\n-\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);\n+\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);\n \tif (ret) {\n \t\tDRV_LOG(WARNING, \"port %u unable to query number of statistics\",\n \t\t\tdev->data->port_id);\n@@ -244,7 +244,7 @@ mlx5_xstats_init(struct rte_eth_dev *dev)\n \tstrings->string_set = ETH_SS_STATS;\n \tstrings->len = dev_stats_n;\n \tifr.ifr_data = (caddr_t)strings;\n-\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);\n+\tret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);\n \tif (ret) {\n \t\tDRV_LOG(WARNING, \"port %u unable to get statistic names\",\n \t\t\tdev->data->port_id);\n",
    "prefixes": [
        "v5",
        "07/10"
    ]
}