get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 74698,
    "url": "https://patches.dpdk.org/api/patches/74698/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20200723200910.376581-9-parav@mellanox.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": "<20200723200910.376581-9-parav@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200723200910.376581-9-parav@mellanox.com",
    "date": "2020-07-23T20:09:08",
    "name": "[v8,08/10] common/mlx5: introduce layer to support multiple class drivers",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "d760dbe612f70bf277508c0e5fde5019b4eb26ec",
    "submitter": {
        "id": 1780,
        "url": "https://patches.dpdk.org/api/people/1780/?format=api",
        "name": "Parav Pandit",
        "email": "parav@mellanox.com"
    },
    "delegate": {
        "id": 3268,
        "url": "https://patches.dpdk.org/api/users/3268/?format=api",
        "username": "rasland",
        "first_name": "Raslan",
        "last_name": "Darawsheh",
        "email": "rasland@nvidia.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20200723200910.376581-9-parav@mellanox.com/mbox/",
    "series": [
        {
            "id": 11259,
            "url": "https://patches.dpdk.org/api/series/11259/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=11259",
            "date": "2020-07-23T20:09:00",
            "name": "Improve mlx5 PMD driver framework for multiple classes",
            "version": 8,
            "mbox": "https://patches.dpdk.org/series/11259/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/74698/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/74698/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 9EDEBA0518;\n\tThu, 23 Jul 2020 22:10:56 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 143061C0B2;\n\tThu, 23 Jul 2020 22:09:51 +0200 (CEST)",
            "from EUR01-HE1-obe.outbound.protection.outlook.com\n (mail-eopbgr130089.outbound.protection.outlook.com [40.107.13.89])\n by dpdk.org (Postfix) with ESMTP id 8AD001C000\n for <dev@dpdk.org>; Thu, 23 Jul 2020 22:09:46 +0200 (CEST)",
            "from DB7PR05MB4876.eurprd05.prod.outlook.com (2603:10a6:10:1d::32)\n by DB7PR05MB5558.eurprd05.prod.outlook.com (2603:10a6:10:5c::21) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3216.20; Thu, 23 Jul\n 2020 20:09:44 +0000",
            "from DB7PR05MB4876.eurprd05.prod.outlook.com\n ([fe80::8cb3:93cb:c3ef:4293]) by DB7PR05MB4876.eurprd05.prod.outlook.com\n ([fe80::8cb3:93cb:c3ef:4293%5]) with mapi id 15.20.3216.022; Thu, 23 Jul 2020\n 20:09:44 +0000",
            "from sw-mtx-036.mtx.labs.mlnx (208.176.44.194) by\n DM6PR03CA0009.namprd03.prod.outlook.com (2603:10b6:5:40::22) 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; Thu, 23 Jul 2020 20:09:42 +0000"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=e0foKv1tuk18lbOlphG20Dwy69M9GYH4IQX5Owmk+tjOeI1LWsOqzrEgCTlIsWRxNiPe9Wg3mRIKjeGT7BW/6yperW/9fLPSGoxo9rD9wOejJRm2RwQVSjI2ddCCqwnrb/G0azel3zmz5iBlVsbEJ+V4bt3izXl6T1GRLL/2/MSEMkvUk3Mahlxua8FQU/yLvZhRmOaueCmtr0QWWf4NbbFXN0oOCs52O6rQJqaB7HJJt3nZKruhon5wafZzuYiuYc6B7ErSxwzzp2Sk/mB+QrndEqW8SDQFUoZ3CdE8MkuiehjPfPsXDndVh6ZmWnaSqIPnWT+xOQOeywTvRi5OCg==",
        "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=o8hauFXDFJda5hDlL67i08cuhrtGnJzOo/C1D6NGCAM=;\n b=k46ScDetdxZSTj0YFEGP/PpK5XpcLg+KOE9efDhyRd4Nx8Sz1glh6WFgrVQ2//hsCVXKMvdkH4WWkFwn5eE5juGOEAu6XSAAJzqO5t0j1sAQHSgEDtnPsKm6ZrhfRaK+vTOu8q1PN4qK+cB/buofUHUb/UeFz62rRNVeBU1iYcK6aUsiLjcm7+gwSGN9jhwHJS4eRqVtURZs+FOs9feHVuq6Wls5+0TB0DY2ztaaFKaSYswgZnWxqfpyk8eyXdkkOZDanyJt9+OacvteZxeFG4roI/4ZMxQpHgda9jeU++MULyLBOZhGqjKfiCQ6QgFiCjNfIp3QPSz2mDfAEX758g==",
        "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=o8hauFXDFJda5hDlL67i08cuhrtGnJzOo/C1D6NGCAM=;\n b=k2VPnXC2BDuWeaPg2AxL1uMvGGuiOOxOixNThUmOFzR5JUtXB7uNs3y6AWJ7o4u/Z92S3HfrXA1YglqsQTsVKhFUK0jv3qzKSJi7WT7V5rl45to6tEho3LZEZfWxBt+oIGsopDv8Q3OGNrqh5X1hsMr9I4LUxkhJaWzVEKb2Yiw=",
        "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": "Thu, 23 Jul 2020 23:09:08 +0300",
        "Message-Id": "<20200723200910.376581-9-parav@mellanox.com>",
        "X-Mailer": [
            "git-send-email 2.26.2",
            "git-send-email 2.26.2"
        ],
        "In-Reply-To": "<20200723200910.376581-1-parav@mellanox.com>",
        "References": "<20200610171728.89-2-parav@mellanox.com>\n <20200723200910.376581-1-parav@mellanox.com>",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-ClientProxiedBy": "DM6PR03CA0009.namprd03.prod.outlook.com\n (2603:10b6:5:40::22) To DB7PR05MB4876.eurprd05.prod.outlook.com\n (2603:10a6:10:1d::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": "83b894f3-5acd-4d21-6829-08d82f4456ea",
        "X-MS-TrafficTypeDiagnostic": "DB7PR05MB5558:",
        "X-LD-Processed": "a652971c-7d2e-4d9b-a6a4-d149256f461b,ExtFwd,ExtAddr",
        "X-MS-Exchange-Transport-Forked": "True",
        "X-Microsoft-Antispam-PRVS": "\n <DB7PR05MB55581E8E572EADEF933E2818D1760@DB7PR05MB5558.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 5NMAY7aJ1eTEu9tsHgZqnG5a3vQnXuuthSHHLc2xvzy5Q+z/oHtKRYjBHm+JEpeKN2GkkLhNbd6xNQlXWqIZJTHNOCy9Abxzjp6AmoJ18sDxoWl6yM5g2JmZ4LW0vTLQRCxmouhIuHeXV+LXmT9VcnRC+NfA2qJovtOJ4ivHzfWm9uvRNdhOWbCqg5aP/Dv/TCxxtTGPaFsmbvukYCq0PJ6plPoTizDIoirRIF8RNXfmO8iIg2J0ZTeSSYOpDLfJovT+3MnpkTsQIfPkyfkLJiAPcoKIn1BGS3WMEW28+mPzeXRJNIcM/CtuKBeVam5K",
        "X-Forefront-Antispam-Report": "CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;\n IPV:NLI; SFV:NSPM; H:DB7PR05MB4876.eurprd05.prod.outlook.com; PTR:; CAT:NONE;\n SFTY:;\n SFS:(4636009)(376002)(346002)(366004)(396003)(136003)(39860400002)(6506007)(8676002)(8936002)(26005)(52116002)(2906002)(4326008)(478600001)(66946007)(66476007)(66556008)(83380400001)(36756003)(5660300002)(2616005)(6486002)(86362001)(956004)(1076003)(6512007)(6666004)(107886003)(186003)(16526019)(316002)(30864003);\n DIR:OUT; SFP:1101;",
        "X-MS-Exchange-AntiSpam-MessageData": "\n lHuCh5nkQNzQsUzW7PGAveHP+JNU1lpcRp3NQiCEDD1n8pNqE//i972Wib1zVecUoaKl7R9E8VCQQjuNxQsBjBRm7TenSkznfFZzKBrmIjvFqbQNIIqw8UB5KunZUB18D8Vhh9cEqz/9ckgEyvTmANj3UacYiNmj36smdOXlsbSY05LVHJjURSYiBEnvt+39iBMaGLB80lgHWXvxwRowMsYTg7O8wKs19xeRiFVH+NwPSOpLWZVR+9YiPNfWuymd2ka8lauuwa1D2ZQbLAE8/WeIj7iZsKGmCD9IMd4Z3Dgyov941D9mga8FBNif5aGASmENXbpEfE2GoM4ucHFLHjFQa3LMbZl/q8EogALJKvXN0qq1/MO4MhPrlN3M85eb16MCMzkvd6piAuf/e037E7ARidmq1mSBriEX4LiSdGQbKoDUzhzdu+p0pk+eJ5TgeMxu0z3cuG808ZSBhgjUZxGU1Zyh1ixGSqpfKBvJkFWMxkrEm4sHYQvMuWQC7JlS",
        "X-OriginatorOrg": "Mellanox.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 83b894f3-5acd-4d21-6829-08d82f4456ea",
        "X-MS-Exchange-CrossTenant-AuthSource": "DB7PR05MB4876.eurprd05.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Internal",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "23 Jul 2020 20:09:44.2895 (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 ZAsFdhWQY8Avcn4it1yMzIAdd0awJl4ExGrilM/eTAAtgtC0znJ+wPrOZqzlmPRNkD1AaENTA61hEl2jNgZMJQ==",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "DB7PR05MB5558",
        "Subject": "[dpdk-dev] [PATCH v8 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": "From: Thomas Monjalon <thomas@monjalon.net>\n\nAdd 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---\n drivers/Makefile                              |  10 +-\n drivers/common/Makefile                       |   4 -\n drivers/common/meson.build                    |   2 +-\n drivers/common/mlx5/Makefile                  |   1 +\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, 638 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..eaabb8c10 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\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..b42f7469f\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+      struct rte_pci_device *pci_dev;\n+      TAILQ_ENTRY(mlx5_pci_device) next;\n+      uint32_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": [
        "v8",
        "08/10"
    ]
}