get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 52144,
    "url": "http://patches.dpdk.org/api/patches/52144/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20190403071844.21126-3-tiwei.bie@intel.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": "<20190403071844.21126-3-tiwei.bie@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20190403071844.21126-3-tiwei.bie@intel.com",
    "date": "2019-04-03T07:18:43",
    "name": "[RFC,2/3] bus/mdev: add mdev bus support",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "d7b7490d0e1db768d7b51587aedeb6e57dc5888f",
    "submitter": {
        "id": 617,
        "url": "http://patches.dpdk.org/api/people/617/?format=api",
        "name": "Tiwei Bie",
        "email": "tiwei.bie@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20190403071844.21126-3-tiwei.bie@intel.com/mbox/",
    "series": [
        {
            "id": 4075,
            "url": "http://patches.dpdk.org/api/series/4075/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=4075",
            "date": "2019-04-03T07:18:41",
            "name": "Add mdev (Mediated device) support in DPDK",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/4075/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/52144/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/52144/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 07FE05F11;\n\tWed,  3 Apr 2019 09:19:34 +0200 (CEST)",
            "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n\tby dpdk.org (Postfix) with ESMTP id 69FFC5B1C\n\tfor <dev@dpdk.org>; Wed,  3 Apr 2019 09:19:27 +0200 (CEST)",
            "from orsmga007.jf.intel.com ([10.7.209.58])\n\tby orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t03 Apr 2019 00:19:26 -0700",
            "from dpdk-tbie.sh.intel.com ([10.67.104.173])\n\tby orsmga007.jf.intel.com with ESMTP; 03 Apr 2019 00:19:25 -0700"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.60,303,1549958400\"; d=\"scan'208\";a=\"128206258\"",
        "From": "Tiwei Bie <tiwei.bie@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "cunming.liang@intel.com, bruce.richardson@intel.com,\n\talejandro.lucero@netronome.com",
        "Date": "Wed,  3 Apr 2019 15:18:43 +0800",
        "Message-Id": "<20190403071844.21126-3-tiwei.bie@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20190403071844.21126-1-tiwei.bie@intel.com>",
        "References": "<20190403071844.21126-1-tiwei.bie@intel.com>",
        "Subject": "[dpdk-dev] [RFC 2/3] bus/mdev: add mdev bus support",
        "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": "This patch adds the mdev (Mediated device) bus support in DPDK.\nThis bus driver will scan all the mdev devices in the system,\nand do the probe based on device API (mdev_type/device_api).\n\nSigned-off-by: Cunming Liang <cunming.liang@intel.com>\nSigned-off-by: Tiwei Bie <tiwei.bie@intel.com>\n---\n config/common_base                        |   5 +\n config/common_linux                       |   1 +\n drivers/bus/Makefile                      |   1 +\n drivers/bus/mdev/Makefile                 |  41 +++\n drivers/bus/mdev/linux/Makefile           |   6 +\n drivers/bus/mdev/linux/mdev.c             | 117 ++++++++\n drivers/bus/mdev/mdev.c                   | 310 ++++++++++++++++++++++\n drivers/bus/mdev/meson.build              |  15 ++\n drivers/bus/mdev/private.h                |  90 +++++++\n drivers/bus/mdev/rte_bus_mdev.h           | 141 ++++++++++\n drivers/bus/mdev/rte_bus_mdev_version.map |  12 +\n drivers/bus/meson.build                   |   2 +-\n mk/rte.app.mk                             |   1 +\n 13 files changed, 741 insertions(+), 1 deletion(-)\n create mode 100644 drivers/bus/mdev/Makefile\n create mode 100644 drivers/bus/mdev/linux/Makefile\n create mode 100644 drivers/bus/mdev/linux/mdev.c\n create mode 100644 drivers/bus/mdev/mdev.c\n create mode 100644 drivers/bus/mdev/meson.build\n create mode 100644 drivers/bus/mdev/private.h\n create mode 100644 drivers/bus/mdev/rte_bus_mdev.h\n create mode 100644 drivers/bus/mdev/rte_bus_mdev_version.map",
    "diff": "diff --git a/config/common_base b/config/common_base\nindex 6292bc4af..d29e9a089 100644\n--- a/config/common_base\n+++ b/config/common_base\n@@ -168,6 +168,11 @@ CONFIG_RTE_LIBRTE_COMMON_DPAAX=n\n #\n CONFIG_RTE_LIBRTE_IFPGA_BUS=y\n \n+#\n+# Compile the mdev bus\n+#\n+CONFIG_RTE_LIBRTE_MDEV_BUS=n\n+\n #\n # Compile PCI bus driver\n #\ndiff --git a/config/common_linux b/config/common_linux\nindex 75334273d..7de9624c0 100644\n--- a/config/common_linux\n+++ b/config/common_linux\n@@ -25,6 +25,7 @@ CONFIG_RTE_LIBRTE_AVP_PMD=y\n CONFIG_RTE_LIBRTE_VDEV_NETVSC_PMD=y\n CONFIG_RTE_LIBRTE_NFP_PMD=y\n CONFIG_RTE_LIBRTE_POWER=y\n+CONFIG_RTE_LIBRTE_MDEV_BUS=y\n CONFIG_RTE_VIRTIO_USER=y\n CONFIG_RTE_PROC_INFO=y\n \ndiff --git a/drivers/bus/Makefile b/drivers/bus/Makefile\nindex cea3b55e6..b2144ee63 100644\n--- a/drivers/bus/Makefile\n+++ b/drivers/bus/Makefile\n@@ -8,6 +8,7 @@ ifeq ($(CONFIG_RTE_EAL_VFIO),y)\n DIRS-$(CONFIG_RTE_LIBRTE_FSLMC_BUS) += fslmc\n endif\n DIRS-$(CONFIG_RTE_LIBRTE_IFPGA_BUS) += ifpga\n+DIRS-$(CONFIG_RTE_LIBRTE_MDEV_BUS) += mdev\n DIRS-$(CONFIG_RTE_LIBRTE_PCI_BUS) += pci\n DIRS-$(CONFIG_RTE_LIBRTE_VDEV_BUS) += vdev\n DIRS-$(CONFIG_RTE_LIBRTE_VMBUS) += vmbus\ndiff --git a/drivers/bus/mdev/Makefile b/drivers/bus/mdev/Makefile\nnew file mode 100644\nindex 000000000..b2faee395\n--- /dev/null\n+++ b/drivers/bus/mdev/Makefile\n@@ -0,0 +1,41 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2019 Intel Corporation\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+#\n+# library name\n+#\n+LIB = librte_bus_mdev.a\n+\n+CFLAGS += -O3\n+CFLAGS += $(WERROR_FLAGS)\n+CFLAGS += -DALLOW_EXPERIMENTAL_API\n+CFLAGS += -I$(SRCDIR)\n+\n+# versioning export map\n+EXPORT_MAP := rte_bus_mdev_version.map\n+\n+# library version\n+LIBABIVER := 1\n+\n+ifneq ($(CONFIG_RTE_EXEC_ENV_LINUX),)\n+SYSTEM := linux\n+endif\n+ifneq ($(CONFIG_RTE_EXEC_ENV_FREEBSD),)\n+$(error \"Mdev bus not implemented for BSD yet\")\n+endif\n+\n+CFLAGS += -I$(RTE_SDK)/drivers/bus/mdev/$(SYSTEM)\n+CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common\n+CFLAGS += -I$(RTE_SDK)/lib/librte_eal/$(SYSTEM)/eal\n+\n+LDLIBS += -lrte_eal\n+\n+include $(RTE_SDK)/drivers/bus/mdev/$(SYSTEM)/Makefile\n+SRCS-$(CONFIG_RTE_LIBRTE_MDEV_BUS) := $(addprefix $(SYSTEM)/,$(SRCS))\n+SRCS-$(CONFIG_RTE_LIBRTE_MDEV_BUS) += mdev.c\n+\n+SYMLINK-$(CONFIG_RTE_LIBRTE_MDEV_BUS)-include += rte_bus_mdev.h\n+\n+include $(RTE_SDK)/mk/rte.lib.mk\ndiff --git a/drivers/bus/mdev/linux/Makefile b/drivers/bus/mdev/linux/Makefile\nnew file mode 100644\nindex 000000000..a777ad3d4\n--- /dev/null\n+++ b/drivers/bus/mdev/linux/Makefile\n@@ -0,0 +1,6 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2019 Intel Corporation\n+\n+SRCS += mdev.c\n+\n+CFLAGS += -D_GNU_SOURCE\ndiff --git a/drivers/bus/mdev/linux/mdev.c b/drivers/bus/mdev/linux/mdev.c\nnew file mode 100644\nindex 000000000..ecfe0eba6\n--- /dev/null\n+++ b/drivers/bus/mdev/linux/mdev.c\n@@ -0,0 +1,117 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Intel Corporation\n+ */\n+\n+#include <string.h>\n+#include <dirent.h>\n+\n+#include <rte_log.h>\n+#include <rte_bus_mdev.h>\n+\n+#include \"eal_filesystem.h\"\n+\n+#include \"private.h\"\n+\n+static int\n+mdev_scan_one(const char *dirname, const rte_uuid_t addr)\n+{\n+\tstruct rte_mdev_device *mdev;\n+\tchar device_api[PATH_MAX];\n+\tchar filename[PATH_MAX];\n+\tchar *ptr;\n+\n+\tmdev = malloc(sizeof(*mdev));\n+\tif (mdev == NULL)\n+\t\treturn -1;\n+\n+\tmemset(mdev, 0, sizeof(*mdev));\n+\tmdev->device.bus = &rte_mdev_bus.bus;\n+\trte_uuid_copy(mdev->addr, addr);\n+\n+\t/* get device_api */\n+\tsnprintf(filename, sizeof(filename), \"%s/mdev_type/device_api\",\n+\t\t dirname);\n+\tif (rte_eal_parse_sysfs_str(filename, device_api,\n+\t\t\t\t    sizeof(device_api)) < 0) {\n+\t\tfree(mdev);\n+\t\treturn -1;\n+\t}\n+\n+\tptr = strchr(device_api, '\\n');\n+\tif (ptr != NULL)\n+\t\t*ptr = '\\0';\n+\n+\tmdev_name_set(mdev);\n+\n+\tif (strcmp(device_api, \"vfio-pci\") == 0) {\n+\t\t/* device api */\n+\t\tmdev->dev_api = RTE_MDEV_DEV_API_VFIO_PCI;\n+\n+\t\tif (TAILQ_EMPTY(&rte_mdev_bus.device_list))\n+\t\t\trte_mdev_add_device(mdev);\n+\t\telse {\n+\t\t\tstruct rte_mdev_device *dev;\n+\t\t\tint ret;\n+\n+\t\t\tTAILQ_FOREACH(dev, &rte_mdev_bus.device_list, next) {\n+\t\t\t\tret = rte_uuid_compare(mdev->addr, dev->addr);\n+\t\t\t\tif (ret > 0)\n+\t\t\t\t\tcontinue;\n+\n+\t\t\t\tif (ret < 0)\n+\t\t\t\t\trte_mdev_insert_device(dev, mdev);\n+\t\t\t\telse /* already registered */\n+\t\t\t\t\tfree(mdev);\n+\n+\t\t\t\treturn 0;\n+\t\t\t}\n+\n+\t\t\trte_mdev_add_device(mdev);\n+\t\t}\n+\t} else {\n+\t\tRTE_LOG(DEBUG, EAL, \"%s(): mdev device_api %s is not supported\\n\",\n+\t\t\t__func__, device_api);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Scan the content of the mdev bus, and the devices in the devices\n+ * list\n+ */\n+int\n+rte_mdev_scan(void)\n+{\n+\tstruct dirent *e;\n+\tDIR *dir;\n+\tchar dirname[PATH_MAX];\n+\trte_uuid_t addr;\n+\n+\tdir = opendir(rte_mdev_get_sysfs_path());\n+\tif (dir == NULL) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): opendir failed: %s\\n\",\n+\t\t\t__func__, strerror(errno));\n+\t\treturn -1;\n+\t}\n+\n+\twhile ((e = readdir(dir)) != NULL) {\n+\t\tif (e->d_name[0] == '.')\n+\t\t\tcontinue;\n+\n+\t\tif (rte_uuid_parse(e->d_name, addr) != 0)\n+\t\t\tcontinue;\n+\n+\t\tsnprintf(dirname, sizeof(dirname), \"%s/%s\",\n+\t\t\t rte_mdev_get_sysfs_path(), e->d_name);\n+\n+\t\tif (mdev_scan_one(dirname, addr) < 0)\n+\t\t\tgoto error;\n+\t}\n+\tclosedir(dir);\n+\treturn 0;\n+\n+error:\n+\tclosedir(dir);\n+\treturn -1;\n+}\ndiff --git a/drivers/bus/mdev/mdev.c b/drivers/bus/mdev/mdev.c\nnew file mode 100644\nindex 000000000..2f9209cca\n--- /dev/null\n+++ b/drivers/bus/mdev/mdev.c\n@@ -0,0 +1,310 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Intel Corporation\n+ */\n+\n+#include <string.h>\n+#include <inttypes.h>\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <sys/queue.h>\n+#include <sys/mman.h>\n+\n+#include <rte_errno.h>\n+#include <rte_interrupts.h>\n+#include <rte_log.h>\n+#include <rte_per_lcore.h>\n+#include <rte_memory.h>\n+#include <rte_eal.h>\n+#include <rte_common.h>\n+#include <rte_devargs.h>\n+#include <rte_uuid.h>\n+#include <rte_bus_mdev.h>\n+\n+#include \"private.h\"\n+\n+#define SYSFS_MDEV_DEVICES \"/sys/bus/mdev/devices\"\n+\n+const char *rte_mdev_get_sysfs_path(void)\n+{\n+\tconst char *path = NULL;\n+\n+\tpath = getenv(\"SYSFS_MDEV_DEVICES\");\n+\tif (path == NULL)\n+\t\treturn SYSFS_MDEV_DEVICES;\n+\n+\treturn path;\n+}\n+\n+static void\n+rte_mdev_device_name(const rte_uuid_t addr, char *output, size_t size)\n+{\n+\tRTE_VERIFY(size >= RTE_UUID_STRLEN);\n+\trte_uuid_unparse(addr, output, size);\n+}\n+\n+static struct rte_devargs *\n+mdev_devargs_lookup(struct rte_mdev_device *dev)\n+{\n+\tstruct rte_devargs *devargs;\n+\trte_uuid_t addr;\n+\n+\tRTE_EAL_DEVARGS_FOREACH(\"mdev\", devargs) {\n+\t\tdevargs->bus->parse(devargs->name, addr);\n+\t\tif (!rte_uuid_compare(dev->addr, addr))\n+\t\t\treturn devargs;\n+\t}\n+\treturn NULL;\n+}\n+\n+void\n+mdev_name_set(struct rte_mdev_device *dev)\n+{\n+\tstruct rte_devargs *devargs;\n+\n+\t/* Each device has its internal, canonical name set. */\n+\trte_mdev_device_name(dev->addr, dev->name, sizeof(dev->name));\n+\tdevargs = mdev_devargs_lookup(dev);\n+\tdev->device.devargs = devargs;\n+\t/* In blacklist mode, if the device is not blacklisted, no\n+\t * rte_devargs exists for it.\n+\t */\n+\tif (devargs != NULL)\n+\t\t/* If an rte_devargs exists, the generic rte_device uses the\n+\t\t * given name as its name.\n+\t\t */\n+\t\tdev->device.name = dev->device.devargs->name;\n+\telse\n+\t\t/* Otherwise, it uses the internal, canonical form. */\n+\t\tdev->device.name = dev->name;\n+}\n+\n+void\n+rte_mdev_register(struct rte_mdev_driver *driver)\n+{\n+\tTAILQ_INSERT_TAIL(&rte_mdev_bus.driver_list, driver, next);\n+\tdriver->bus = &rte_mdev_bus;\n+}\n+\n+void\n+rte_mdev_unregister(struct rte_mdev_driver *driver)\n+{\n+\tTAILQ_REMOVE(&rte_mdev_bus.driver_list, driver, next);\n+\tdriver->bus = NULL;\n+}\n+\n+void\n+rte_mdev_add_device(struct rte_mdev_device *mdev)\n+{\n+\tTAILQ_INSERT_TAIL(&rte_mdev_bus.device_list, mdev, next);\n+}\n+\n+void\n+rte_mdev_insert_device(struct rte_mdev_device *exist_mdev,\n+\t\t       struct rte_mdev_device *new_mdev)\n+{\n+\tTAILQ_INSERT_BEFORE(exist_mdev, new_mdev, next);\n+}\n+\n+void\n+rte_mdev_remove_device(struct rte_mdev_device *mdev)\n+{\n+\tTAILQ_REMOVE(&rte_mdev_bus.device_list, mdev, next);\n+}\n+\n+static struct rte_device *\n+mdev_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,\n+\t\t const void *data)\n+{\n+\tconst struct rte_mdev_device *pstart;\n+\tstruct rte_mdev_device *pdev;\n+\n+\tif (start != NULL) {\n+\t\tpstart = RTE_DEV_TO_MDEV_CONST(start);\n+\t\tpdev = TAILQ_NEXT(pstart, next);\n+\t} else {\n+\t\tpdev = TAILQ_FIRST(&rte_mdev_bus.device_list);\n+\t}\n+\twhile (pdev != NULL) {\n+\t\tif (cmp(&pdev->device, data) == 0)\n+\t\t\treturn &pdev->device;\n+\t\tpdev = TAILQ_NEXT(pdev, next);\n+\t}\n+\treturn NULL;\n+}\n+\n+int\n+rte_mdev_match(const struct rte_mdev_driver *mdev_drv,\n+\t       const struct rte_mdev_device *mdev_dev)\n+{\n+\tif (mdev_drv->dev_api == mdev_dev->dev_api)\n+\t\treturn 1;\n+\n+\treturn 0;\n+}\n+\n+static int\n+rte_mdev_probe_one_driver(struct rte_mdev_driver *dr,\n+\t\t\t  struct rte_mdev_device *dev)\n+{\n+\tint ret;\n+\n+\tif (dr == NULL || dev == NULL)\n+\t\treturn -EINVAL;\n+\n+\t/* no initialization when blacklisted, return without error */\n+\tif (dev->device.devargs != NULL &&\n+\t    dev->device.devargs->policy == RTE_DEV_BLACKLISTED) {\n+\t\tRTE_LOG(INFO, EAL, \"Device is blacklisted, not initializing\\n\");\n+\t\treturn 1;\n+\t}\n+\n+\t/* The device is not blacklisted; Check if driver supports it */\n+\tif (!rte_mdev_match(dr, dev)) {\n+\t\t/* Match of device and driver failed */\n+\t\treturn 1;\n+\t}\n+\n+\t/* reference driver structure */\n+\tdev->driver = dr;\n+\n+\t/* call the driver probe() function */\n+\tret = dr->probe(dr, dev);\n+\tif (ret != 0)\n+\t\tdev->driver = NULL;\n+\n+\treturn ret;\n+}\n+\n+static int\n+mdev_probe_all_drivers(struct rte_mdev_device *dev)\n+{\n+\tstruct rte_mdev_driver *dr = NULL;\n+\tint rc = 0;\n+\n+\tif (dev == NULL)\n+\t\treturn -1;\n+\n+\t/* Check if a driver is already loaded */\n+\tif (dev->driver != NULL)\n+\t\treturn 0;\n+\n+\tFOREACH_DRIVER_ON_MDEV_BUS(dr) {\n+\t\trc = rte_mdev_probe_one_driver(dr, dev);\n+\t\tif (rc < 0)\n+\t\t\t/* negative value is an error */\n+\t\t\treturn -1;\n+\t\tif (rc > 0)\n+\t\t\t/* positive value means driver doesn't support it */\n+\t\t\tcontinue;\n+\t\treturn 0;\n+\t}\n+\treturn 1;\n+}\n+\n+int\n+rte_mdev_probe(void)\n+{\n+\tstruct rte_mdev_device *mdev = NULL;\n+\tsize_t probed = 0, failed = 0;\n+\tstruct rte_devargs *devargs;\n+\tint probe_all = 0;\n+\tint ret = 0;\n+\n+\tif (rte_mdev_bus.bus.conf.scan_mode != RTE_BUS_SCAN_WHITELIST)\n+\t\tprobe_all = 1;\n+\n+\tFOREACH_DEVICE_ON_MDEV_BUS(mdev) {\n+\t\tprobed++;\n+\n+\t\tdevargs = mdev->device.devargs;\n+\t\t/* probe all or only whitelisted devices */\n+\t\tif (probe_all)\n+\t\t\tret = mdev_probe_all_drivers(mdev);\n+\t\telse if (devargs != NULL &&\n+\t\t\tdevargs->policy == RTE_DEV_WHITELISTED)\n+\t\t\tret = mdev_probe_all_drivers(mdev);\n+\t\tif (ret < 0) {\n+\t\t\tchar name[RTE_UUID_STRLEN];\n+\t\t\trte_uuid_unparse(mdev->addr, name, sizeof(name));\n+\t\t\tRTE_LOG(ERR, EAL, \"Requested device %s cannot be used\\n\",\n+\t\t\t\tname);\n+\t\t\trte_errno = errno;\n+\t\t\tfailed++;\n+\t\t\tret = 0;\n+\t\t}\n+\t}\n+\n+\treturn (probed && probed == failed) ? -1 : 0;\n+}\n+\n+static int\n+mdev_plug(struct rte_device *dev)\n+{\n+\treturn mdev_probe_all_drivers(RTE_DEV_TO_MDEV(dev));\n+}\n+\n+static int\n+rte_mdev_detach_dev(struct rte_mdev_device *dev)\n+{\n+\tstruct rte_mdev_driver *dr;\n+\tint ret = 0;\n+\n+\tif (dev == NULL)\n+\t\treturn -EINVAL;\n+\n+\tdr = dev->driver;\n+\n+\tif (dr->remove) {\n+\t\tret = dr->remove(dev);\n+\t\tif (ret != 0)\n+\t\t\treturn ret;\n+\t}\n+\n+\t/* clear driver structure */\n+\tdev->driver = NULL;\n+\n+\treturn 0;\n+}\n+\n+static int\n+mdev_unplug(struct rte_device *dev)\n+{\n+\tstruct rte_mdev_device *pmdev;\n+\tint ret;\n+\n+\tpmdev = RTE_DEV_TO_MDEV(dev);\n+\tret = rte_mdev_detach_dev(pmdev);\n+\tif (ret == 0) {\n+\t\trte_mdev_remove_device(pmdev);\n+\t\tfree(pmdev);\n+\t}\n+\treturn ret;\n+}\n+\n+static int\n+mdev_parse(const char *name, void *addr)\n+{\n+\trte_uuid_t uuid;\n+\tint parse;\n+\n+\tparse = (rte_uuid_parse(name, uuid) == 0);\n+\tif (parse && addr != NULL)\n+\t\trte_uuid_copy(addr, uuid);\n+\treturn parse == false;\n+}\n+\n+struct rte_mdev_bus rte_mdev_bus = {\n+\t.bus = {\n+\t\t.scan = rte_mdev_scan,\n+\t\t.probe = rte_mdev_probe,\n+\t\t.find_device = mdev_find_device,\n+\t\t.plug = mdev_plug,\n+\t\t.unplug = mdev_unplug,\n+\t\t.parse = mdev_parse,\n+\t},\n+\t.device_list = TAILQ_HEAD_INITIALIZER(rte_mdev_bus.device_list),\n+\t.driver_list = TAILQ_HEAD_INITIALIZER(rte_mdev_bus.driver_list),\n+};\n+\n+RTE_REGISTER_BUS(mdev, rte_mdev_bus.bus);\ndiff --git a/drivers/bus/mdev/meson.build b/drivers/bus/mdev/meson.build\nnew file mode 100644\nindex 000000000..33c701cb9\n--- /dev/null\n+++ b/drivers/bus/mdev/meson.build\n@@ -0,0 +1,15 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2019 Intel Corporation\n+\n+version = 1\n+allow_experimental_apis = true\n+install_headers('rte_bus_mdev.h')\n+sources = files('mdev.c')\n+\n+if host_machine.system() == 'linux'\n+\tsources += files('linux/mdev.c')\n+\tincludes += include_directories('linux')\n+\tcflags += ['-D_GNU_SOURCE']\n+else\n+\tbuild = false\n+endif\ndiff --git a/drivers/bus/mdev/private.h b/drivers/bus/mdev/private.h\nnew file mode 100644\nindex 000000000..81cfe3045\n--- /dev/null\n+++ b/drivers/bus/mdev/private.h\n@@ -0,0 +1,90 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Intel Corporation\n+ */\n+\n+#ifndef _MDEV_PRIVATE_H_\n+#define _MDEV_PRIVATE_H_\n+\n+#include <stdbool.h>\n+#include <stdio.h>\n+#include <rte_bus_mdev.h>\n+\n+struct rte_mdev_driver;\n+struct rte_mdev_device;\n+\n+extern struct rte_mdev_bus rte_mdev_bus;\n+\n+/**\n+ * Probe the mdev bus.\n+ *\n+ * @return\n+ *   - 0 on success.\n+ *   - !0 on error.\n+ */\n+int rte_mdev_probe(void);\n+\n+/**\n+ * Scan the content of the mdev bus, and the devices in the devices\n+ * list.\n+ *\n+ * @return\n+ *  0 on success, negative on error\n+ */\n+int rte_mdev_scan(void);\n+\n+/**\n+ * Set the name of a mdev device.\n+ */\n+void mdev_name_set(struct rte_mdev_device *dev);\n+\n+/**\n+ * Add a mdev device to the mdev bus (append to mdev device list). This function\n+ * also updates the bus references of the mdev device (and the generic device\n+ * object embedded within.\n+ *\n+ * @param mdev\n+ *\tmdev device to add\n+ * @return void\n+ */\n+void rte_mdev_add_device(struct rte_mdev_device *mdev);\n+\n+/**\n+ * Insert a mdev device in the mdev bus at a particular location in the device\n+ * list. It also updates the mdev bus reference of the new devices to be\n+ * inserted.\n+ *\n+ * @param exist_mdev\n+ *\texisting mdev device in mdev bus\n+ * @param new_mdev\n+ *\tmdev device to be added before exist_mdev\n+ * @return void\n+ */\n+void rte_mdev_insert_device(struct rte_mdev_device *exist_mdev,\n+\t\t\t    struct rte_mdev_device *new_mdev);\n+\n+/**\n+ * Remove a mdev device from the mdev bus. This sets to NULL the bus references\n+ * in the mdev device object as well as the generic device object.\n+ *\n+ * @param mdev_device\n+ *\tmdev device to be removed from mdev bus\n+ * @return void\n+ */\n+void rte_mdev_remove_device(struct rte_mdev_device *mdev_device);\n+\n+/**\n+ * Match the mdev driver and device using mdev device_api.\n+ *\n+ * @param mdev_drv\n+ *      mdev driver from which device_api would be extracted\n+ * @param mdev_dev\n+ *      mdev device to match against the driver\n+ * @return\n+ *      1 for successful match\n+ *      0 for unsuccessful match\n+ */\n+int\n+rte_mdev_match(const struct rte_mdev_driver *mdev_drv,\n+\t       const struct rte_mdev_device *mdev_dev);\n+\n+#endif /* _MDEV_PRIVATE_H_ */\ndiff --git a/drivers/bus/mdev/rte_bus_mdev.h b/drivers/bus/mdev/rte_bus_mdev.h\nnew file mode 100644\nindex 000000000..913521ace\n--- /dev/null\n+++ b/drivers/bus/mdev/rte_bus_mdev.h\n@@ -0,0 +1,141 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Intel Corporation\n+ */\n+\n+#ifndef _RTE_BUS_MDEV_H_\n+#define _RTE_BUS_MDEV_H_\n+\n+/**\n+ * @file\n+ *\n+ * RTE Mdev Bus Interface\n+ */\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <limits.h>\n+#include <errno.h>\n+#include <sys/queue.h>\n+#include <stdint.h>\n+#include <inttypes.h>\n+\n+#include <rte_debug.h>\n+#include <rte_interrupts.h>\n+#include <rte_dev.h>\n+#include <rte_uuid.h>\n+#include <rte_bus.h>\n+\n+struct rte_devargs;\n+\n+enum rte_mdev_device_api {\n+\tRTE_MDEV_DEV_API_VFIO_PCI = 0,\n+\tRTE_MDEV_DEV_API_MAX,\n+};\n+\n+struct rte_mdev_bus;\n+struct rte_mdev_driver;\n+struct rte_mdev_device;\n+\n+/** Pathname of mdev devices directory. */\n+const char * __rte_experimental rte_mdev_get_sysfs_path(void);\n+\n+/**\n+ * Register a mdev driver.\n+ *\n+ * @param driver\n+ *   A pointer to a rte_mdev_driver structure describing the driver\n+ *   to be registered.\n+ */\n+void __rte_experimental rte_mdev_register(struct rte_mdev_driver *driver);\n+\n+#define RTE_MDEV_REGISTER_DRIVER(nm, mdev_drv) \\\n+RTE_INIT(mdevinitfn_ ##nm) \\\n+{ \\\n+\t(mdev_drv).driver.name = RTE_STR(nm); \\\n+\trte_mdev_register(&mdev_drv); \\\n+} \\\n+RTE_PMD_EXPORT_NAME(nm, __COUNTER__)\n+\n+/**\n+ * Unregister a mdev driver.\n+ *\n+ * @param driver\n+ *   A pointer to a rte_mdev_driver structure describing the driver\n+ *   to be unregistered.\n+ */\n+void __rte_experimental rte_mdev_unregister(struct rte_mdev_driver *driver);\n+\n+/**\n+ * Initialisation function for the driver called during mdev probing.\n+ */\n+typedef int (mdev_probe_t)(struct rte_mdev_driver *, struct rte_mdev_device *);\n+\n+/**\n+ * Uninitialisation function for the driver called during hotplugging.\n+ */\n+typedef int (mdev_remove_t)(struct rte_mdev_device *);\n+\n+/**\n+ * A structure describing a mdev driver.\n+ */\n+struct rte_mdev_driver {\n+\tTAILQ_ENTRY(rte_mdev_driver) next; /**< Next in list. */\n+\tstruct rte_driver driver;          /**< Inherit core driver. */\n+\tstruct rte_mdev_bus *bus;          /**< Mdev bus reference. */\n+\tmdev_probe_t *probe;               /**< Device probe function. */\n+\tmdev_remove_t *remove;             /**< Device remove function. */\n+\tenum rte_mdev_device_api dev_api;  /**< Device API. */\n+};\n+\n+/**\n+ * A structure describing a mdev device.\n+ */\n+struct rte_mdev_device {\n+\tTAILQ_ENTRY(rte_mdev_device) next; /**< Next mdev device. */\n+\tstruct rte_device device;\t   /**< Inherit core device. */\n+\tenum rte_mdev_device_api dev_api;  /**< Device API. */\n+\tstruct rte_mdev_driver *driver;    /**< Associated driver. */\n+\trte_uuid_t addr;                   /**< Location. */\n+\tchar name[RTE_UUID_STRLEN];        /**< Location (ASCII). */\n+\tvoid *private;                     /**< Driver-specific data. */\n+};\n+\n+/**\n+ * @internal\n+ * Helper macro for drivers that need to convert to struct rte_mdev_device.\n+ */\n+#define RTE_DEV_TO_MDEV(ptr) container_of(ptr, struct rte_mdev_device, device)\n+\n+#define RTE_DEV_TO_MDEV_CONST(ptr) \\\n+\tcontainer_of(ptr, const struct rte_mdev_device, device)\n+\n+/** List of mdev devices */\n+TAILQ_HEAD(rte_mdev_device_list, rte_mdev_device);\n+/** List of mdev drivers */\n+TAILQ_HEAD(rte_mdev_driver_list, rte_mdev_driver);\n+\n+/**\n+ * Structure describing the mdev bus\n+ */\n+struct rte_mdev_bus {\n+\tstruct rte_bus bus;                /**< Inherit the generic class */\n+\tstruct rte_mdev_device_list device_list;  /**< List of mdev devices */\n+\tstruct rte_mdev_driver_list driver_list;  /**< List of mdev drivers */\n+};\n+\n+/* Mdev Bus iterators */\n+#define FOREACH_DEVICE_ON_MDEV_BUS(p)\t\\\n+\t\tTAILQ_FOREACH(p, &(rte_mdev_bus.device_list), next)\n+\n+#define FOREACH_DRIVER_ON_MDEV_BUS(p)\t\\\n+\t\tTAILQ_FOREACH(p, &(rte_mdev_bus.driver_list), next)\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* _RTE_BUS_MDEV_H_ */\ndiff --git a/drivers/bus/mdev/rte_bus_mdev_version.map b/drivers/bus/mdev/rte_bus_mdev_version.map\nnew file mode 100644\nindex 000000000..7f73bf96b\n--- /dev/null\n+++ b/drivers/bus/mdev/rte_bus_mdev_version.map\n@@ -0,0 +1,12 @@\n+DPDK_19.05 {\n+\n+\tlocal: *;\n+};\n+\n+EXPERIMENTAL {\n+\tglobal:\n+\n+\trte_mdev_get_sysfs_path;\n+\trte_mdev_register;\n+\trte_mdev_unregister;\n+};\ndiff --git a/drivers/bus/meson.build b/drivers/bus/meson.build\nindex 80de2d91d..f0ab19a03 100644\n--- a/drivers/bus/meson.build\n+++ b/drivers/bus/meson.build\n@@ -1,7 +1,7 @@\n # SPDX-License-Identifier: BSD-3-Clause\n # Copyright(c) 2017 Intel Corporation\n \n-drivers = ['dpaa', 'fslmc', 'ifpga', 'pci', 'vdev', 'vmbus']\n+drivers = ['dpaa', 'fslmc', 'ifpga', 'mdev', 'pci', 'vdev', 'vmbus']\n std_deps = ['eal']\n config_flag_fmt = 'RTE_LIBRTE_@0@_BUS'\n driver_name_fmt = 'rte_bus_@0@'\ndiff --git a/mk/rte.app.mk b/mk/rte.app.mk\nindex 262132fc6..f8abe8237 100644\n--- a/mk/rte.app.mk\n+++ b/mk/rte.app.mk\n@@ -123,6 +123,7 @@ ifeq ($(CONFIG_RTE_LIBRTE_FSLMC_BUS),y)\n _LDLIBS-$(CONFIG_RTE_LIBRTE_COMMON_DPAAX)   += -lrte_common_dpaax\n endif\n \n+_LDLIBS-$(CONFIG_RTE_LIBRTE_MDEV_BUS)       += -lrte_bus_mdev\n _LDLIBS-$(CONFIG_RTE_LIBRTE_PCI_BUS)        += -lrte_bus_pci\n _LDLIBS-$(CONFIG_RTE_LIBRTE_VDEV_BUS)       += -lrte_bus_vdev\n _LDLIBS-$(CONFIG_RTE_LIBRTE_DPAA_BUS)       += -lrte_bus_dpaa\n",
    "prefixes": [
        "RFC",
        "2/3"
    ]
}