get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 74773,
    "url": "http://patches.dpdk.org/api/patches/74773/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200724142403.6132-9-parav@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": "<20200724142403.6132-9-parav@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200724142403.6132-9-parav@mellanox.com",
    "date": "2020-07-24T14:24:01",
    "name": "[v9,08/10] common/mlx5: introduce layer to support multiple class drivers",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "af5e8416fed0aa75c7eb599235eb067a56266ae6",
    "submitter": {
        "id": 1780,
        "url": "http://patches.dpdk.org/api/people/1780/?format=api",
        "name": "Parav Pandit",
        "email": "parav@mellanox.com"
    },
    "delegate": {
        "id": 3268,
        "url": "http://patches.dpdk.org/api/users/3268/?format=api",
        "username": "rasland",
        "first_name": "Raslan",
        "last_name": "Darawsheh",
        "email": "rasland@nvidia.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20200724142403.6132-9-parav@mellanox.com/mbox/",
    "series": [
        {
            "id": 11290,
            "url": "http://patches.dpdk.org/api/series/11290/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=11290",
            "date": "2020-07-24T14:23:54",
            "name": "Improve mlx5 PMD driver framework for multiple classes",
            "version": 9,
            "mbox": "http://patches.dpdk.org/series/11290/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/74773/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/74773/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 13D61A0526;\n\tFri, 24 Jul 2020 16:25:52 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id E1C321C0CD;\n\tFri, 24 Jul 2020 16:24:45 +0200 (CEST)",
            "from EUR02-VE1-obe.outbound.protection.outlook.com\n (mail-eopbgr20069.outbound.protection.outlook.com [40.107.2.69])\n by dpdk.org (Postfix) with ESMTP id CF96F1C07E\n for <dev@dpdk.org>; Fri, 24 Jul 2020 16:24:41 +0200 (CEST)",
            "from AM0PR05MB4866.eurprd05.prod.outlook.com (2603:10a6:208:c0::32)\n by AM4PR05MB3203.eurprd05.prod.outlook.com (2603:10a6:205:6::28) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3216.20; Fri, 24 Jul\n 2020 14:24:40 +0000",
            "from AM0PR05MB4866.eurprd05.prod.outlook.com\n ([fe80::eccf:72b3:bacb:f09d]) by AM0PR05MB4866.eurprd05.prod.outlook.com\n ([fe80::eccf:72b3:bacb:f09d%5]) with mapi id 15.20.3216.024; Fri, 24 Jul 2020\n 14:24:40 +0000",
            "from sw-mtx-036.mtx.labs.mlnx (208.176.44.194) by\n DM6PR02CA0136.namprd02.prod.outlook.com (2603:10b6:5:1b4::38) with Microsoft\n SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.20.3216.21 via Frontend Transport; Fri, 24 Jul 2020 14:24:38 +0000"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=DmIbftGwm4AxkQgUgKqu8YkBpPPAdC+obg0ZcQ0yf1OFKH5lLD7EToxAQre3jXV1zEBVca22U8xJaGHF0+Zwmow9PizBuotl7smwOxUAlTBpx7YVRqdgOKwbT1+Cay0a2vU6UXq9jL/Ah1Ek6NeRBN3re4O7Fr8N96O72c0tMd1yx4CgCdAsLomMhGGkxRKS2AHadwL4XivFDpvVKQhGr/T7720GHQ+Cno4sxZdIFeAOiWfU0VuK0yYDPp3frb/QesRv6T/RVPELOED3CWzKTrqCdZOSNKjUbrAm8GuYQLmMlCWvSEW0nXTPJSU/9YpeVIFkujQKHhI3A5M954kqgQ==",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector9901;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=u8i3FQhLAH2WYVLri2cj/ZsgmQbUoYpDBRhSrFK/wmk=;\n b=TfwLkyIHIwoDbA2LmwAyeGKNRU1x2TUqGwmwbX5sdN61FTD1226Ylm7iXGdo60ezK1FrB67Z9FuCQFnVXlDskgG/6+11Uj6X2MbWsLj6guOgyuZvu1iy8GnaBcsqm1BsF4ZJtwBwjOmhJjDgZzepOdWwUoLKW8Ed1XztCg5oiSwlBasDYTvtGP68qcTjI8335KFgkFFz1WeakWK5XH2oeKIBtm13RiVIr/PiXM9ZCydYOebAOHj4Lwb+1JVEdpTOpx6zvLhorgOvLNU7fI6mAvxfn9zRnvVkZtCbz39UEPQ9RTiUKtFtV4fyLz35Ct+6y4cxSvzbphT6CvngIEM+bw==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass\n smtp.mailfrom=mellanox.com; dmarc=pass action=none header.from=mellanox.com;\n dkim=pass header.d=mellanox.com; arc=none",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=Mellanox.com;\n s=selector1;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=u8i3FQhLAH2WYVLri2cj/ZsgmQbUoYpDBRhSrFK/wmk=;\n b=cgKFoRtkec/CgUjrunMtoAey5j88AJgGfHHW7/8oE1Ai9qB7ScP9KRxcWthy+tUukP1EgFXIDf3eJHkwxPV2mR+NecOKSvF6AicNgNafpknVLT1S2o4f9NO6VBKHPETOUEGTlC45JO8KGUg79d+wPRrn3TU6xXiXT5UjhNemkQo=",
        "Authentication-Results": "dpdk.org; dkim=none (message not signed)\n header.d=none;dpdk.org; dmarc=none action=none header.from=mellanox.com;",
        "From": "Parav Pandit <parav@mellanox.com>",
        "To": "dev@dpdk.org, grive@u256.net, ferruh.yigit@intel.com, thomas@monjalon.net",
        "Cc": "rasland@mellanox.com, orika@mellanox.com, matan@mellanox.com,\n joyce.kong@arm.com, Parav Pandit <parav@mellanox.com>",
        "Date": "Fri, 24 Jul 2020 17:24:01 +0300",
        "Message-Id": "<20200724142403.6132-9-parav@mellanox.com>",
        "X-Mailer": [
            "git-send-email 2.26.2",
            "git-send-email 2.26.2"
        ],
        "In-Reply-To": "<20200724142403.6132-1-parav@mellanox.com>",
        "References": "<20200610171728.89-2-parav@mellanox.com>\n <20200724142403.6132-1-parav@mellanox.com>",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-ClientProxiedBy": "DM6PR02CA0136.namprd02.prod.outlook.com\n (2603:10b6:5:1b4::38) To AM0PR05MB4866.eurprd05.prod.outlook.com\n (2603:10a6:208:c0::32)",
        "MIME-Version": "1.0",
        "X-MS-Exchange-MessageSentRepresentingType": "1",
        "X-Originating-IP": "[208.176.44.194]",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-Office365-Filtering-HT": "Tenant",
        "X-MS-Office365-Filtering-Correlation-Id": "09ffa660-5519-4fea-2d79-08d82fdd4cea",
        "X-MS-TrafficTypeDiagnostic": "AM4PR05MB3203:",
        "X-LD-Processed": "a652971c-7d2e-4d9b-a6a4-d149256f461b,ExtFwd,ExtAddr",
        "X-MS-Exchange-Transport-Forked": "True",
        "X-Microsoft-Antispam-PRVS": "\n <AM4PR05MB32030217F5ECAA8D406DD355D1770@AM4PR05MB3203.eurprd05.prod.outlook.com>",
        "X-MS-Oob-TLC-OOBClassifiers": "OLM:1051;",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n 25gBvpjwS03jt7ifV3hvtI/WARV7hAggvmsYtyXxMCCho8J7nqXRCBnr6EgoPXBOIeA+LoSJ0/CLl/cto9bq2jWbaAOTsbMwNNI1+ka+hlLx7LIghPZK9rrNe2mYAG0USFfkUaZty7uhDcgBeMggKMtmnNUgEoxOySSMvaCvQ89OIpjKRd8jjDC8q5puFbbdlog+Zl/f+/nIlG6XyF26m/jeQKh3+DTWGIIEmYTTPLa0g569WP41OAmNEDOZKkRwo82yQXZNTiXDl4OIOA/rxjgk56WRElA8mREjvzGFn8vKtDq0NIeiVp9s8GZDZwOI",
        "X-Forefront-Antispam-Report": "CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;\n IPV:NLI; SFV:NSPM; H:AM0PR05MB4866.eurprd05.prod.outlook.com; PTR:; CAT:NONE;\n SFTY:;\n SFS:(4636009)(376002)(346002)(136003)(366004)(396003)(39860400002)(5660300002)(86362001)(2616005)(956004)(6512007)(2906002)(66946007)(66476007)(66556008)(316002)(6506007)(4326008)(16526019)(186003)(26005)(107886003)(8936002)(478600001)(8676002)(6666004)(30864003)(52116002)(6486002)(83380400001)(1076003)(36756003);\n DIR:OUT; SFP:1101;",
        "X-MS-Exchange-AntiSpam-MessageData": "\n XJMWULhgjcbgUS+KkzMVJ52mFgoUsFm3wjlPhZU0BIIJrtueOQ9Fn3Smtcxq5LwOD4VSTif6DAZmUHVmLVDpCwhRfomi9qdqrO28UlSHzQ6aKKD8rnIaca1EJvcSWTZvS0I017QJXyLbBqns4znPX1mwE1uwaU6hZmLoKkcmf1XSMIqwHNBHPrWBKMnuDXbODZUr0f8qq/oxSyXXtH+OzIeU1nCMYZZ6NKmzDvTCV4MvWWHADVOcVCxk+PzowkaOiSECZAmwK62W4r5u+VL8/1DSK3japw6n9kLYlc9AqBDlh/IdbVnKTycFaZergtfD3G5i/9aJ85YZR+2cFZa40E0jpZs1ryOFgna49S2jVU/+OwNny3glHq4sfi4TTqaiDpKFvB8GrfoXuwvBogBJbwBxIkiYZW3f+083xxPNzi+WdSpAZ2eXalx4HbzDZttGUydyFRfowL3yZ1DtFa3nZRwFpdTdSGrZmQqeo3GPrkiUXTLDvqzqNooRnoJuZg8d",
        "X-OriginatorOrg": "Mellanox.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 09ffa660-5519-4fea-2d79-08d82fdd4cea",
        "X-MS-Exchange-CrossTenant-AuthSource": "AM0PR05MB4866.eurprd05.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Internal",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "24 Jul 2020 14:24:40.1036 (UTC)",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "Hosted",
        "X-MS-Exchange-CrossTenant-Id": "a652971c-7d2e-4d9b-a6a4-d149256f461b",
        "X-MS-Exchange-CrossTenant-MailboxType": "HOSTED",
        "X-MS-Exchange-CrossTenant-UserPrincipalName": "\n EuuL50BcCXZMOjdiEv390pLccL/0ZtoplvSOoPC0LKK3U/c2bFspM9KW1IBrm5edlSBddnkQe9ARVhBRpZpnbg==",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "AM4PR05MB3203",
        "Subject": "[dpdk-dev] [PATCH v9 08/10] common/mlx5: introduce layer to support\n\tmultiple class drivers",
        "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": "Add generic mlx5 PCI PMD layer as part of existing common_mlx5\nmodule. This enables multiple classes (net, regex, vdpa) PMDs\nto be supported at same time.\n\nSigned-off-by: Parav Pandit <parav@mellanox.com>\nAcked-by: Matan Azrad <matan@mellanox.com>\n---\nChangelog:\nv8->v9:\n - Added missing LDFLAG for pci bus\n - Fixed white spaces at start of the line\n---\n drivers/Makefile                              |  10 +-\n drivers/common/Makefile                       |   4 -\n drivers/common/meson.build                    |   2 +-\n drivers/common/mlx5/Makefile                  |   2 +\n drivers/common/mlx5/meson.build               |   9 +-\n drivers/common/mlx5/mlx5_common.c             |   2 +\n drivers/common/mlx5/mlx5_common_pci.c         | 541 ++++++++++++++++++\n drivers/common/mlx5/mlx5_common_pci.h         |  77 +++\n .../common/mlx5/rte_common_mlx5_version.map   |   2 +\n drivers/meson.build                           |   1 +\n 10 files changed, 639 insertions(+), 11 deletions(-)\n create mode 100644 drivers/common/mlx5/mlx5_common_pci.c\n create mode 100644 drivers/common/mlx5/mlx5_common_pci.h",
    "diff": "diff --git a/drivers/Makefile b/drivers/Makefile\nindex 1551272ef..7f06162dc 100644\n--- a/drivers/Makefile\n+++ b/drivers/Makefile\n@@ -8,8 +8,12 @@ DIRS-y += bus\n DEPDIRS-bus := common\n DIRS-y += mempool\n DEPDIRS-mempool := common bus\n+ifeq ($(findstring y,$(CONFIG_RTE_LIBRTE_MLX5_PMD)$(CONFIG_RTE_LIBRTE_MLX5_VDPA_PMD)$(CONFIG_RTE_LIBRTE_MLX5_REGEX_PMD)),y)\n+DIRS-y += common/mlx5\n+DEPDIRS-common/mlx5 := bus\n+endif\n DIRS-y += net\n-DEPDIRS-net := common bus mempool\n+DEPDIRS-net := common bus mempool common/mlx5\n DIRS-$(CONFIG_RTE_LIBRTE_BBDEV) += baseband\n DEPDIRS-baseband := common bus mempool\n DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += crypto\n@@ -19,9 +23,9 @@ DEPDIRS-common/qat := bus mempool\n DIRS-$(CONFIG_RTE_LIBRTE_COMPRESSDEV) += compress\n DEPDIRS-compress := bus mempool\n DIRS-$(CONFIG_RTE_LIBRTE_REGEXDEV) += regex\n-DEPDIRS-regex := common bus\n+DEPDIRS-regex := common bus common/mlx5\n DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += vdpa\n-DEPDIRS-vdpa := common bus mempool\n+DEPDIRS-vdpa := common bus mempool common/mlx5\n DIRS-$(CONFIG_RTE_LIBRTE_EVENTDEV) += event\n DEPDIRS-event := common bus mempool net crypto\n DIRS-$(CONFIG_RTE_LIBRTE_RAWDEV) += raw\ndiff --git a/drivers/common/Makefile b/drivers/common/Makefile\nindex cbc71077c..cfb6b4dc8 100644\n--- a/drivers/common/Makefile\n+++ b/drivers/common/Makefile\n@@ -36,8 +36,4 @@ ifneq (,$(findstring y,$(IAVF-y)))\n DIRS-y += iavf\n endif\n \n-ifeq ($(findstring y,$(CONFIG_RTE_LIBRTE_MLX5_PMD)$(CONFIG_RTE_LIBRTE_MLX5_VDPA_PMD)$(CONFIG_RTE_LIBRTE_MLX5_REGEX_PMD)),y)\n-DIRS-y += mlx5\n-endif\n-\n include $(RTE_SDK)/mk/rte.subdir.mk\ndiff --git a/drivers/common/meson.build b/drivers/common/meson.build\nindex 5db7e29b1..9ed4c04ba 100644\n--- a/drivers/common/meson.build\n+++ b/drivers/common/meson.build\n@@ -6,6 +6,6 @@ if is_windows\n endif\n \n std_deps = ['eal']\n-drivers = ['cpt', 'dpaax', 'iavf', 'mlx5', 'mvep', 'octeontx', 'octeontx2', 'qat']\n+drivers = ['cpt', 'dpaax', 'iavf', 'mvep', 'octeontx', 'octeontx2', 'qat']\n config_flag_fmt = 'RTE_LIBRTE_@0@_COMMON'\n driver_name_fmt = 'rte_common_@0@'\ndiff --git a/drivers/common/mlx5/Makefile b/drivers/common/mlx5/Makefile\nindex 6b89a6c85..4edd54104 100644\n--- a/drivers/common/mlx5/Makefile\n+++ b/drivers/common/mlx5/Makefile\n@@ -22,6 +22,7 @@ SRCS-y += linux/mlx5_common_verbs.c\n SRCS-y += mlx5_common_mp.c\n SRCS-y += mlx5_common_mr.c\n SRCS-y += mlx5_malloc.c\n+SRCS-y += mlx5_common_pci.c\n ifeq ($(CONFIG_RTE_IBVERBS_LINK_DLOPEN),y)\n INSTALL-y-lib += $(LIB_GLUE)\n endif\n@@ -51,6 +52,7 @@ LDLIBS += -libverbs -lmlx5\n endif\n \n LDLIBS += -lrte_eal -lrte_pci -lrte_kvargs -lrte_net\n+LDLIBS += -lrte_bus_pci\n \n # A few warnings cannot be avoided in external headers.\n CFLAGS += -Wno-error=cast-qual -UPEDANTIC\ndiff --git a/drivers/common/mlx5/meson.build b/drivers/common/mlx5/meson.build\nindex 70e2c1c32..8e5608703 100644\n--- a/drivers/common/mlx5/meson.build\n+++ b/drivers/common/mlx5/meson.build\n@@ -1,19 +1,22 @@\n # SPDX-License-Identifier: BSD-3-Clause\n # Copyright 2019 Mellanox Technologies, Ltd\n \n-if not (is_linux or is_windows)\n+if not is_linux\n \tbuild = false\n-\treason = 'only supported on Linux and Windows'\n+\treason = 'only supported on Linux'\n \tsubdir_done()\n endif\n \n-deps += ['hash', 'pci', 'net', 'eal', 'kvargs']\n+config_flag_fmt = 'RTE_LIBRTE_@0@_COMMON'\n+driver_name_fmt = 'rte_common_@0@'\n+deps += ['hash', 'pci', 'bus_pci', 'net', 'eal', 'kvargs']\n sources += files(\n \t'mlx5_devx_cmds.c',\n \t'mlx5_common.c',\n \t'mlx5_common_mp.c',\n \t'mlx5_common_mr.c',\n \t'mlx5_malloc.c',\n+\t'mlx5_common_pci.c',\n )\n \n cflags_options = [\ndiff --git a/drivers/common/mlx5/mlx5_common.c b/drivers/common/mlx5/mlx5_common.c\nindex 2b336bb2d..fd818ef24 100644\n--- a/drivers/common/mlx5/mlx5_common.c\n+++ b/drivers/common/mlx5/mlx5_common.c\n@@ -14,6 +14,7 @@\n #include \"mlx5_common_os.h\"\n #include \"mlx5_common_utils.h\"\n #include \"mlx5_malloc.h\"\n+#include \"mlx5_common_pci.h\"\n \n int mlx5_common_logtype;\n \n@@ -100,6 +101,7 @@ mlx5_common_init(void)\n \t\treturn;\n \n \tmlx5_glue_constructor();\n+\tmlx5_common_pci_init();\n \tmlx5_common_initialized = true;\n }\n \ndiff --git a/drivers/common/mlx5/mlx5_common_pci.c b/drivers/common/mlx5/mlx5_common_pci.c\nnew file mode 100644\nindex 000000000..adb3f707d\n--- /dev/null\n+++ b/drivers/common/mlx5/mlx5_common_pci.c\n@@ -0,0 +1,541 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright 2020 Mellanox Technologies Ltd\n+ */\n+\n+#include <stdlib.h>\n+#include <rte_malloc.h>\n+#include \"mlx5_common_utils.h\"\n+#include \"mlx5_common_pci.h\"\n+\n+struct mlx5_pci_device {\n+\tstruct rte_pci_device *pci_dev;\n+\tTAILQ_ENTRY(mlx5_pci_device) next;\n+\tuint32_t classes_loaded;\n+};\n+\n+/* Head of list of drivers. */\n+static TAILQ_HEAD(mlx5_pci_bus_drv_head, mlx5_pci_driver) drv_list =\n+\t\t\t\tTAILQ_HEAD_INITIALIZER(drv_list);\n+\n+/* Head of mlx5 pci devices. */\n+static TAILQ_HEAD(mlx5_pci_devices_head, mlx5_pci_device) devices_list =\n+\t\t\t\tTAILQ_HEAD_INITIALIZER(devices_list);\n+\n+static const struct {\n+\tconst char *name;\n+\tunsigned int driver_class;\n+} mlx5_classes[] = {\n+\t{ .name = \"vdpa\", .driver_class = MLX5_CLASS_VDPA },\n+\t{ .name = \"net\", .driver_class = MLX5_CLASS_NET },\n+\t{ .name = \"regex\", .driver_class = MLX5_CLASS_REGEX },\n+};\n+\n+static const unsigned int mlx5_class_combinations[] = {\n+\tMLX5_CLASS_NET,\n+\tMLX5_CLASS_VDPA,\n+\tMLX5_CLASS_REGEX,\n+\t/* New class combination should be added here.\n+\t * For example a new multi class device combination\n+\t * can be MLX5_CLASS_FOO | MLX5_CLASS_BAR.\n+\t */\n+};\n+\n+static int\n+class_name_to_value(const char *class_name)\n+{\n+\tunsigned int i;\n+\n+\tfor (i = 0; i < RTE_DIM(mlx5_classes); i++) {\n+\t\tif (strcmp(class_name, mlx5_classes[i].name) == 0)\n+\t\t\treturn mlx5_classes[i].driver_class;\n+\t}\n+\treturn -EINVAL;\n+}\n+\n+static struct mlx5_pci_driver *\n+driver_get(uint32_t class)\n+{\n+\tstruct mlx5_pci_driver *driver;\n+\n+\tTAILQ_FOREACH(driver, &drv_list, next) {\n+\t\tif (driver->driver_class == class)\n+\t\t\treturn driver;\n+\t}\n+\treturn NULL;\n+}\n+\n+static int\n+bus_cmdline_options_handler(__rte_unused const char *key,\n+\t\t\t    const char *class_names, void *opaque)\n+{\n+\tint *ret = opaque;\n+\tchar *nstr_org;\n+\tint class_val;\n+\tchar *found;\n+\tchar *nstr;\n+\n+\t*ret = 0;\n+\tnstr = strdup(class_names);\n+\tif (!nstr) {\n+\t\t*ret = -ENOMEM;\n+\t\treturn *ret;\n+\t}\n+\tnstr_org = nstr;\n+\twhile (nstr) {\n+\t\t/* Extract each individual class name. Multiple\n+\t\t * class key,value is supplied as class=net:vdpa:foo:bar.\n+\t\t */\n+\t\tfound = strsep(&nstr, \":\");\n+\t\tif (!found)\n+\t\t\tcontinue;\n+\t\t/* Check if its a valid class. */\n+\t\tclass_val = class_name_to_value(found);\n+\t\tif (class_val < 0) {\n+\t\t\t*ret = -EINVAL;\n+\t\t\tgoto err;\n+\t\t}\n+\t\t*ret |= class_val;\n+\t}\n+err:\n+\tfree(nstr_org);\n+\tif (*ret < 0)\n+\t\tDRV_LOG(ERR, \"Invalid mlx5 class options %s.\"\n+\t\t\t\" Maybe typo in device class argument setting?\",\n+\t\t\tclass_names);\n+\treturn *ret;\n+}\n+\n+static int\n+parse_class_options(const struct rte_devargs *devargs)\n+{\n+\tconst char *key = MLX5_CLASS_ARG_NAME;\n+\tstruct rte_kvargs *kvlist;\n+\tint ret = 0;\n+\n+\tif (devargs == NULL)\n+\t\treturn 0;\n+\tkvlist = rte_kvargs_parse(devargs->args, NULL);\n+\tif (kvlist == NULL)\n+\t\treturn 0;\n+\tif (rte_kvargs_count(kvlist, key))\n+\t\trte_kvargs_process(kvlist, key, bus_cmdline_options_handler,\n+\t\t\t\t   &ret);\n+\trte_kvargs_free(kvlist);\n+\treturn ret;\n+}\n+\n+static bool\n+mlx5_bus_match(const struct mlx5_pci_driver *drv,\n+\t       const struct rte_pci_device *pci_dev)\n+{\n+\tconst struct rte_pci_id *id_table;\n+\n+\tfor (id_table = drv->pci_driver.id_table; id_table->vendor_id != 0;\n+\t     id_table++) {\n+\t\t/* Check if device's ids match the class driver's ids. */\n+\t\tif (id_table->vendor_id != pci_dev->id.vendor_id &&\n+\t\t    id_table->vendor_id != PCI_ANY_ID)\n+\t\t\tcontinue;\n+\t\tif (id_table->device_id != pci_dev->id.device_id &&\n+\t\t    id_table->device_id != PCI_ANY_ID)\n+\t\t\tcontinue;\n+\t\tif (id_table->subsystem_vendor_id !=\n+\t\t    pci_dev->id.subsystem_vendor_id &&\n+\t\t    id_table->subsystem_vendor_id != PCI_ANY_ID)\n+\t\t\tcontinue;\n+\t\tif (id_table->subsystem_device_id !=\n+\t\t    pci_dev->id.subsystem_device_id &&\n+\t\t    id_table->subsystem_device_id != PCI_ANY_ID)\n+\t\t\tcontinue;\n+\t\tif (id_table->class_id != pci_dev->id.class_id &&\n+\t\t    id_table->class_id != RTE_CLASS_ANY_ID)\n+\t\t\tcontinue;\n+\t\treturn true;\n+\t}\n+\treturn false;\n+}\n+\n+static int\n+is_valid_class_combination(uint32_t user_classes)\n+{\n+\tunsigned int i;\n+\n+\t/* Verify if user specified valid supported combination. */\n+\tfor (i = 0; i < RTE_DIM(mlx5_class_combinations); i++) {\n+\t\tif (mlx5_class_combinations[i] == user_classes)\n+\t\t\treturn 0;\n+\t}\n+\t/* Not found any valid class combination. */\n+\treturn -EINVAL;\n+}\n+\n+static struct mlx5_pci_device *\n+pci_to_mlx5_device(const struct rte_pci_device *pci_dev)\n+{\n+\tstruct mlx5_pci_device *dev;\n+\n+\tTAILQ_FOREACH(dev, &devices_list, next) {\n+\t\tif (dev->pci_dev == pci_dev)\n+\t\t\treturn dev;\n+\t}\n+\treturn NULL;\n+}\n+\n+static bool\n+device_class_enabled(const struct mlx5_pci_device *device, uint32_t class)\n+{\n+\treturn (device->classes_loaded & class) ? true : false;\n+}\n+\n+static void\n+dev_release(struct mlx5_pci_device *dev)\n+{\n+\tTAILQ_REMOVE(&devices_list, dev, next);\n+\trte_free(dev);\n+}\n+\n+static int\n+drivers_remove(struct mlx5_pci_device *dev, uint32_t enabled_classes)\n+{\n+\tstruct mlx5_pci_driver *driver;\n+\tint local_ret = -ENODEV;\n+\tunsigned int i = 0;\n+\tint ret = 0;\n+\n+\tenabled_classes &= dev->classes_loaded;\n+\twhile (enabled_classes) {\n+\t\tdriver = driver_get(RTE_BIT64(i));\n+\t\tif (driver) {\n+\t\t\tlocal_ret = driver->pci_driver.remove(dev->pci_dev);\n+\t\t\tif (!local_ret)\n+\t\t\t\tdev->classes_loaded &= ~RTE_BIT64(i);\n+\t\t\telse if (ret == 0)\n+\t\t\t\tret = local_ret;\n+\t\t}\n+\t\tenabled_classes &= ~RTE_BIT64(i);\n+\t\ti++;\n+\t}\n+\tif (local_ret)\n+\t\tret = local_ret;\n+\treturn ret;\n+}\n+\n+static int\n+drivers_probe(struct mlx5_pci_device *dev, struct rte_pci_driver *pci_drv,\n+\t      struct rte_pci_device *pci_dev, uint32_t user_classes)\n+{\n+\tstruct mlx5_pci_driver *driver;\n+\tuint32_t enabled_classes = 0;\n+\tbool already_loaded;\n+\tint ret;\n+\n+\tTAILQ_FOREACH(driver, &drv_list, next) {\n+\t\tif ((driver->driver_class & user_classes) == 0)\n+\t\t\tcontinue;\n+\t\tif (!mlx5_bus_match(driver, pci_dev))\n+\t\t\tcontinue;\n+\t\talready_loaded = dev->classes_loaded & driver->driver_class;\n+\t\tif (already_loaded &&\n+\t\t    !(driver->pci_driver.drv_flags & RTE_PCI_DRV_PROBE_AGAIN)) {\n+\t\t\tDRV_LOG(ERR, \"Device %s is already probed\\n\",\n+\t\t\t\tpci_dev->device.name);\n+\t\t\tret = -EEXIST;\n+\t\t\tgoto probe_err;\n+\t\t}\n+\t\tret = driver->pci_driver.probe(pci_drv, pci_dev);\n+\t\tif (ret < 0) {\n+\t\t\tDRV_LOG(ERR, \"Failed to load driver = %s.\\n\",\n+\t\t\t\tdriver->pci_driver.driver.name);\n+\t\t\tgoto probe_err;\n+\t\t}\n+\t\tenabled_classes |= driver->driver_class;\n+\t}\n+\tdev->classes_loaded |= enabled_classes;\n+\treturn 0;\n+probe_err:\n+\t/* Only unload drivers which are enabled which were enabled\n+\t * in this probe instance.\n+\t */\n+\tdrivers_remove(dev, enabled_classes);\n+\treturn ret;\n+}\n+\n+/**\n+ * DPDK callback to register to probe multiple drivers for a PCI device.\n+ *\n+ * @param[in] pci_drv\n+ *   PCI driver structure.\n+ * @param[in] dev\n+ *   PCI device information.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+mlx5_common_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,\n+\t\t      struct rte_pci_device *pci_dev)\n+{\n+\tstruct mlx5_pci_device *dev;\n+\tuint32_t user_classes = 0;\n+\tbool new_device = false;\n+\tint ret;\n+\n+\tret = parse_class_options(pci_dev->device.devargs);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\tuser_classes = ret;\n+\tif (user_classes) {\n+\t\t/* Validate combination here. */\n+\t\tret = is_valid_class_combination(user_classes);\n+\t\tif (ret) {\n+\t\t\tDRV_LOG(ERR, \"Unsupported mlx5 classes supplied.\");\n+\t\t\treturn ret;\n+\t\t}\n+\t} else {\n+\t\t/* Default to net class. */\n+\t\tuser_classes = MLX5_CLASS_NET;\n+\t}\n+\tdev = pci_to_mlx5_device(pci_dev);\n+\tif (!dev) {\n+\t\tdev = rte_zmalloc(\"mlx5_pci_device\", sizeof(*dev), 0);\n+\t\tif (!dev)\n+\t\t\treturn -ENOMEM;\n+\t\tdev->pci_dev = pci_dev;\n+\t\tTAILQ_INSERT_HEAD(&devices_list, dev, next);\n+\t\tnew_device = true;\n+\t}\n+\tret = drivers_probe(dev, pci_drv, pci_dev, user_classes);\n+\tif (ret)\n+\t\tgoto class_err;\n+\treturn 0;\n+class_err:\n+\tif (new_device)\n+\t\tdev_release(dev);\n+\treturn ret;\n+}\n+\n+/**\n+ * DPDK callback to remove one or more drivers for a PCI device.\n+ *\n+ * This function removes all drivers probed for a given PCI device.\n+ *\n+ * @param[in] pci_dev\n+ *   Pointer to the PCI device.\n+ *\n+ * @return\n+ *   0 on success, the function cannot fail.\n+ */\n+static int\n+mlx5_common_pci_remove(struct rte_pci_device *pci_dev)\n+{\n+\tstruct mlx5_pci_device *dev;\n+\tint ret;\n+\n+\tdev = pci_to_mlx5_device(pci_dev);\n+\tif (!dev)\n+\t\treturn -ENODEV;\n+\t/* Matching device found, cleanup and unload drivers. */\n+\tret = drivers_remove(dev, dev->classes_loaded);\n+\tif (!ret)\n+\t\tdev_release(dev);\n+\treturn ret;\n+}\n+\n+static int\n+mlx5_common_pci_dma_map(struct rte_pci_device *pci_dev, void *addr,\n+\t\t\tuint64_t iova, size_t len)\n+{\n+\tstruct mlx5_pci_driver *driver = NULL;\n+\tstruct mlx5_pci_driver *temp;\n+\tstruct mlx5_pci_device *dev;\n+\tint ret = -EINVAL;\n+\n+\tdev = pci_to_mlx5_device(pci_dev);\n+\tif (!dev)\n+\t\treturn -ENODEV;\n+\tTAILQ_FOREACH(driver, &drv_list, next) {\n+\t\tif (device_class_enabled(dev, driver->driver_class) &&\n+\t\t    driver->pci_driver.dma_map) {\n+\t\t\tret = driver->pci_driver.dma_map(pci_dev, addr,\n+\t\t\t\t\t\t\t iova, len);\n+\t\t\tif (ret)\n+\t\t\t\tgoto map_err;\n+\t\t}\n+\t}\n+\treturn ret;\n+map_err:\n+\tTAILQ_FOREACH(temp, &drv_list, next) {\n+\t\tif (temp == driver)\n+\t\t\tbreak;\n+\t\tif (device_class_enabled(dev, temp->driver_class) &&\n+\t\t    temp->pci_driver.dma_map && temp->pci_driver.dma_unmap)\n+\t\t\ttemp->pci_driver.dma_unmap(pci_dev, addr, iova, len);\n+\t}\n+\treturn ret;\n+}\n+\n+static int\n+mlx5_common_pci_dma_unmap(struct rte_pci_device *pci_dev, void *addr,\n+\t\t\t  uint64_t iova, size_t len)\n+{\n+\tstruct mlx5_pci_driver *driver;\n+\tstruct mlx5_pci_device *dev;\n+\tint local_ret = -EINVAL;\n+\tint ret;\n+\n+\tdev = pci_to_mlx5_device(pci_dev);\n+\tif (!dev)\n+\t\treturn -ENODEV;\n+\tret = 0;\n+\t/* There is no unmap error recovery in current implementation. */\n+\tTAILQ_FOREACH_REVERSE(driver, &drv_list, mlx5_pci_bus_drv_head, next) {\n+\t\tif (device_class_enabled(dev, driver->driver_class) &&\n+\t\t    driver->pci_driver.dma_unmap) {\n+\t\t\tlocal_ret = driver->pci_driver.dma_unmap(pci_dev, addr,\n+\t\t\t\t\t\t\t\t iova, len);\n+\t\t\tif (local_ret && (ret == 0))\n+\t\t\t\tret = local_ret;\n+\t\t}\n+\t}\n+\tif (local_ret)\n+\t\tret = local_ret;\n+\treturn ret;\n+}\n+\n+/* PCI ID table is build dynamically based on registered mlx5 drivers. */\n+static struct rte_pci_id *mlx5_pci_id_table;\n+\n+static struct rte_pci_driver mlx5_pci_driver = {\n+\t.driver = {\n+\t\t.name = \"mlx5_pci\",\n+\t},\n+\t.probe = mlx5_common_pci_probe,\n+\t.remove = mlx5_common_pci_remove,\n+\t.dma_map = mlx5_common_pci_dma_map,\n+\t.dma_unmap = mlx5_common_pci_dma_unmap,\n+};\n+\n+static int\n+pci_id_table_size_get(const struct rte_pci_id *id_table)\n+{\n+\tint table_size = 0;\n+\n+\tfor (; id_table->vendor_id != 0; id_table++)\n+\t\ttable_size++;\n+\treturn table_size;\n+}\n+\n+static bool\n+pci_id_exists(const struct rte_pci_id *id, const struct rte_pci_id *table,\n+\t      int next_idx)\n+{\n+\tint current_size = next_idx - 1;\n+\tint i;\n+\n+\tfor (i = 0; i < current_size; i++) {\n+\t\tif (id->device_id == table[i].device_id &&\n+\t\t    id->vendor_id == table[i].vendor_id &&\n+\t\t    id->subsystem_vendor_id == table[i].subsystem_vendor_id &&\n+\t\t    id->subsystem_device_id == table[i].subsystem_device_id)\n+\t\t\treturn true;\n+\t}\n+\treturn false;\n+}\n+\n+static void\n+pci_id_insert(struct rte_pci_id *new_table, int *next_idx,\n+\t      const struct rte_pci_id *id_table)\n+{\n+\t/* Traverse the id_table, check if entry exists in new_table;\n+\t * Add non duplicate entries to new table.\n+\t */\n+\tfor (; id_table->vendor_id != 0; id_table++) {\n+\t\tif (!pci_id_exists(id_table, new_table, *next_idx)) {\n+\t\t\t/* New entry; add to the table. */\n+\t\t\tnew_table[*next_idx] = *id_table;\n+\t\t\t(*next_idx)++;\n+\t\t}\n+\t}\n+}\n+\n+static int\n+pci_ids_table_update(const struct rte_pci_id *driver_id_table)\n+{\n+\tconst struct rte_pci_id *id_iter;\n+\tstruct rte_pci_id *updated_table;\n+\tstruct rte_pci_id *old_table;\n+\tint num_ids = 0;\n+\tint i = 0;\n+\n+\told_table = mlx5_pci_id_table;\n+\tif (old_table)\n+\t\tnum_ids = pci_id_table_size_get(old_table);\n+\tnum_ids += pci_id_table_size_get(driver_id_table);\n+\t/* Increase size by one for the termination entry of vendor_id = 0. */\n+\tnum_ids += 1;\n+\tupdated_table = calloc(num_ids, sizeof(*updated_table));\n+\tif (!updated_table)\n+\t\treturn -ENOMEM;\n+\tif (TAILQ_EMPTY(&drv_list)) {\n+\t\t/* Copy the first driver's ID table. */\n+\t\tfor (id_iter = driver_id_table; id_iter->vendor_id != 0;\n+\t\t     id_iter++, i++)\n+\t\t\tupdated_table[i] = *id_iter;\n+\t} else {\n+\t\t/* First copy existing table entries. */\n+\t\tfor (id_iter = old_table; id_iter->vendor_id != 0;\n+\t\t     id_iter++, i++)\n+\t\t\tupdated_table[i] = *id_iter;\n+\t\t/* New id to be added at the end of current ID table. */\n+\t\tpci_id_insert(updated_table, &i, driver_id_table);\n+\t}\n+\t/* Terminate table with empty entry. */\n+\tupdated_table[i].vendor_id = 0;\n+\tmlx5_pci_driver.id_table = updated_table;\n+\tmlx5_pci_id_table = updated_table;\n+\tif (old_table)\n+\t\tfree(old_table);\n+\treturn 0;\n+}\n+\n+void\n+mlx5_pci_driver_register(struct mlx5_pci_driver *driver)\n+{\n+\tint ret;\n+\n+\tret = pci_ids_table_update(driver->pci_driver.id_table);\n+\tif (ret)\n+\t\treturn;\n+\tmlx5_pci_driver.drv_flags |= driver->pci_driver.drv_flags;\n+\tTAILQ_INSERT_TAIL(&drv_list, driver, next);\n+}\n+\n+void mlx5_common_pci_init(void)\n+{\n+\tconst struct rte_pci_id empty_table[] = {\n+\t\t{\n+\t\t\t.vendor_id = 0\n+\t\t},\n+\t};\n+\n+\t/* All mlx5 PMDs constructor runs at same priority. So any of the PMD\n+\t * including this one can register the PCI table first. If any other\n+\t * PMD(s) have registered the PCI ID table, No need to register an empty\n+\t * default one.\n+\t */\n+\tif (mlx5_pci_id_table == NULL && pci_ids_table_update(empty_table))\n+\t\t\treturn;\n+\trte_pci_register(&mlx5_pci_driver);\n+}\n+\n+RTE_FINI(mlx5_common_pci_finish)\n+{\n+\tif (mlx5_pci_id_table != NULL) {\n+\t\t/* Constructor doesn't register with PCI bus if it failed\n+\t\t * to build the table.\n+\t\t */\n+\t\trte_pci_unregister(&mlx5_pci_driver);\n+\t\tfree(mlx5_pci_id_table);\n+\t}\n+}\n+RTE_PMD_EXPORT_NAME(mlx5_common_pci, __COUNTER__);\ndiff --git a/drivers/common/mlx5/mlx5_common_pci.h b/drivers/common/mlx5/mlx5_common_pci.h\nnew file mode 100644\nindex 000000000..41b73e17a\n--- /dev/null\n+++ b/drivers/common/mlx5/mlx5_common_pci.h\n@@ -0,0 +1,77 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright 2020 Mellanox Technologies, Ltd\n+ */\n+\n+#ifndef _MLX5_COMMON_PCI_H_\n+#define _MLX5_COMMON_PCI_H_\n+\n+/**\n+ * @file\n+ *\n+ * RTE Mellanox PCI Driver Interface\n+ * Mellanox ConnectX PCI device supports multiple class (net/vdpa/regex)\n+ * devices. This layer enables creating such multiple class of devices on a\n+ * single PCI device by allowing to bind multiple class specific device\n+ * driver to attach to mlx5_pci driver.\n+ *\n+ * -----------    ------------    -------------\n+ * |   mlx5  |    |   mlx5   |    |   mlx5    |\n+ * | net pmd |    | vdpa pmd |    | regex pmd |\n+ * -----------    ------------    -------------\n+ *      \\              |                 /\n+ *       \\             |                /\n+ *        \\       --------------       /\n+ *         \\______|   mlx5     |_____ /\n+ *                | pci common |\n+ *                --------------\n+ *                     |\n+ *                 -----------\n+ *                 |   mlx5  |\n+ *                 | pci dev |\n+ *                 -----------\n+ *\n+ * - mlx5 pci driver binds to mlx5 PCI devices defined by PCI\n+ *   ID table of all related mlx5 PCI devices.\n+ * - mlx5 class driver such as net, vdpa, regex PMD defines its\n+ *   specific PCI ID table and mlx5 bus driver probes matching\n+ *   class drivers.\n+ * - mlx5 pci bus driver is cental place that validates supported\n+ *   class combinations.\n+ */\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif /* __cplusplus */\n+\n+#include <rte_pci.h>\n+#include <rte_bus_pci.h>\n+\n+#include <mlx5_common.h>\n+\n+void mlx5_common_pci_init(void);\n+\n+/**\n+ * A structure describing a mlx5 pci driver.\n+ */\n+struct mlx5_pci_driver {\n+\tstruct rte_pci_driver pci_driver;\t/**< Inherit core pci driver. */\n+\tuint32_t driver_class;\t/**< Class of this driver, enum mlx5_class */\n+\tTAILQ_ENTRY(mlx5_pci_driver) next;\n+};\n+\n+/**\n+ * Register a mlx5_pci device driver.\n+ *\n+ * @param driver\n+ *   A pointer to a mlx5_pci_driver structure describing the driver\n+ *   to be registered.\n+ */\n+__rte_internal\n+void\n+mlx5_pci_driver_register(struct mlx5_pci_driver *driver);\n+\n+#ifdef __cplusplus\n+}\n+#endif /* __cplusplus */\n+\n+#endif /* _MLX5_COMMON_PCI_H_ */\ndiff --git a/drivers/common/mlx5/rte_common_mlx5_version.map b/drivers/common/mlx5/rte_common_mlx5_version.map\nindex 65f25252a..73cf72548 100644\n--- a/drivers/common/mlx5/rte_common_mlx5_version.map\n+++ b/drivers/common/mlx5/rte_common_mlx5_version.map\n@@ -91,5 +91,7 @@ INTERNAL {\n \tmlx5_malloc;\n \tmlx5_realloc;\n \tmlx5_free;\n+\n+\tmlx5_pci_driver_register;\n };\n \ndiff --git a/drivers/meson.build b/drivers/meson.build\nindex e6d0409aa..95df7ef1d 100644\n--- a/drivers/meson.build\n+++ b/drivers/meson.build\n@@ -5,6 +5,7 @@\n subdirs = [\n \t'common',\n \t'bus',\n+\t'common/mlx5', # depends on bus.\n \t'mempool', # depends on common and bus.\n \t'net',     # depends on common, bus, mempool\n \t'raw',     # depends on common, bus and net.\n",
    "prefixes": [
        "v9",
        "08/10"
    ]
}