get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 101382,
    "url": "https://patches.dpdk.org/api/patches/101382/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20211013163053.1033998-4-kevin.laatz@intel.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": "<20211013163053.1033998-4-kevin.laatz@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20211013163053.1033998-4-kevin.laatz@intel.com",
    "date": "2021-10-13T16:30:40",
    "name": "[v7,03/16] dma/idxd: add bus device probing",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "1c5ec7bd0fc23f2377dd41d094fd03d154744eed",
    "submitter": {
        "id": 921,
        "url": "https://patches.dpdk.org/api/people/921/?format=api",
        "name": "Kevin Laatz",
        "email": "kevin.laatz@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20211013163053.1033998-4-kevin.laatz@intel.com/mbox/",
    "series": [
        {
            "id": 19603,
            "url": "https://patches.dpdk.org/api/series/19603/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=19603",
            "date": "2021-10-13T16:30:37",
            "name": "add dmadev driver for idxd devices",
            "version": 7,
            "mbox": "https://patches.dpdk.org/series/19603/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/101382/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/101382/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 mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 67F7EA0C55;\n\tWed, 13 Oct 2021 18:31:27 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 51DCA41149;\n\tWed, 13 Oct 2021 18:31:10 +0200 (CEST)",
            "from mga05.intel.com (mga05.intel.com [192.55.52.43])\n by mails.dpdk.org (Postfix) with ESMTP id 4DAA241104\n for <dev@dpdk.org>; Wed, 13 Oct 2021 18:31:06 +0200 (CEST)",
            "from orsmga008.jf.intel.com ([10.7.209.65])\n by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 13 Oct 2021 09:31:05 -0700",
            "from silpixa00401122.ir.intel.com ([10.55.128.10])\n by orsmga008.jf.intel.com with ESMTP; 13 Oct 2021 09:31:04 -0700"
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6200,9189,10136\"; a=\"313670739\"",
            "E=Sophos;i=\"5.85,371,1624345200\"; d=\"scan'208\";a=\"313670739\"",
            "E=Sophos;i=\"5.85,371,1624345200\"; d=\"scan'208\";a=\"491541229\""
        ],
        "X-ExtLoop1": "1",
        "From": "Kevin Laatz <kevin.laatz@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "bruce.richardson@intel.com, fengchengwen@huawei.com, jerinj@marvell.com,\n conor.walsh@intel.com, Kevin Laatz <kevin.laatz@intel.com>",
        "Date": "Wed, 13 Oct 2021 16:30:40 +0000",
        "Message-Id": "<20211013163053.1033998-4-kevin.laatz@intel.com>",
        "X-Mailer": "git-send-email 2.30.2",
        "In-Reply-To": "<20211013163053.1033998-1-kevin.laatz@intel.com>",
        "References": "<20210827172048.558704-1-kevin.laatz@intel.com>\n <20211013163053.1033998-1-kevin.laatz@intel.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v7 03/16] dma/idxd: add bus device probing",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "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 the basic device probing for DSA devices bound to the IDXD kernel\ndriver. These devices can be configured via sysfs and made available to\nDPDK if they are found during bus scan. Relevant documentation is included.\n\nSigned-off-by: Bruce Richardson <bruce.richardson@intel.com>\nSigned-off-by: Kevin Laatz <kevin.laatz@intel.com>\nReviewed-by: Conor Walsh <conor.walsh@intel.com>\n---\n doc/guides/dmadevs/idxd.rst  |  64 +++++++\n drivers/dma/idxd/idxd_bus.c  | 351 +++++++++++++++++++++++++++++++++++\n drivers/dma/idxd/meson.build |   1 +\n 3 files changed, 416 insertions(+)\n create mode 100644 drivers/dma/idxd/idxd_bus.c",
    "diff": "diff --git a/doc/guides/dmadevs/idxd.rst b/doc/guides/dmadevs/idxd.rst\nindex 924700d17e..ce33e2857a 100644\n--- a/doc/guides/dmadevs/idxd.rst\n+++ b/doc/guides/dmadevs/idxd.rst\n@@ -32,6 +32,56 @@ target platform is x86-based. No additional compilation steps are necessary.\n Device Setup\n -------------\n \n+Intel\\ |reg| DSA devices can use the IDXD kernel driver or DPDK-supported drivers,\n+such as ``vfio-pci``. Both are supported by the IDXD PMD.\n+\n+Intel\\ |reg| DSA devices using IDXD kernel driver\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+To use an Intel\\ |reg| DSA device bound to the IDXD kernel driver, the device must first be configured.\n+The `accel-config <https://github.com/intel/idxd-config>`_ utility library can be used for configuration.\n+\n+.. note::\n+        The device configuration can also be done by directly interacting with the sysfs nodes.\n+        An example of how this may be done can be seen in the script ``dpdk_idxd_cfg.py``\n+        included in the driver source directory.\n+\n+There are some mandatory configuration steps before being able to use a device with an application.\n+The internal engines, which do the copies or other operations,\n+and the work-queues, which are used by applications to assign work to the device,\n+need to be assigned to groups, and the various other configuration options,\n+such as priority or queue depth, need to be set for each queue.\n+\n+To assign an engine to a group::\n+\n+        $ accel-config config-engine dsa0/engine0.0 --group-id=0\n+        $ accel-config config-engine dsa0/engine0.1 --group-id=1\n+\n+To assign work queues to groups for passing descriptors to the engines a similar accel-config command can be used.\n+However, the work queues also need to be configured depending on the use case.\n+Some configuration options include:\n+\n+* mode (Dedicated/Shared): Indicates whether a WQ may accept jobs from multiple queues simultaneously.\n+* priority: WQ priority between 1 and 15. Larger value means higher priority.\n+* wq-size: the size of the WQ. Sum of all WQ sizes must be less that the total-size defined by the device.\n+* type: WQ type (kernel/mdev/user). Determines how the device is presented.\n+* name: identifier given to the WQ.\n+\n+Example configuration for a work queue::\n+\n+        $ accel-config config-wq dsa0/wq0.0 --group-id=0 \\\n+           --mode=dedicated --priority=10 --wq-size=8 \\\n+           --type=user --name=dpdk_app1\n+\n+Once the devices have been configured, they need to be enabled::\n+\n+        $ accel-config enable-device dsa0\n+        $ accel-config enable-wq dsa0/wq0.0\n+\n+Check the device configuration::\n+\n+        $ accel-config list\n+\n Devices using VFIO/UIO drivers\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n \n@@ -56,3 +106,17 @@ If fewer workqueues are required, then the ``max_queues`` parameter may be passe\n the device driver on the EAL commandline, via the ``allowlist`` or ``-a`` flag e.g.::\n \n \t$ dpdk-test -a <b:d:f>,max_queues=4\n+\n+For devices bound to the IDXD kernel driver,\n+the DPDK IDXD driver will automatically perform a scan for available workqueues\n+to use. Any workqueues found listed in ``/dev/dsa`` on the system will be checked\n+in ``/sys``, and any which have ``dpdk_`` prefix in their name will be automatically\n+probed by the driver to make them available to the application.\n+Alternatively, to support use by multiple DPDK processes simultaneously,\n+the value used as the DPDK ``--file-prefix`` parameter may be used as a workqueue\n+name prefix, instead of ``dpdk_``, allowing each DPDK application instance to only\n+use a subset of configured queues.\n+\n+Once probed successfully, irrespective of kernel driver, the device will appear as a ``dmadev``,\n+that is a \"DMA device type\" inside DPDK, and can be accessed using APIs from the\n+``rte_dmadev`` library.\ndiff --git a/drivers/dma/idxd/idxd_bus.c b/drivers/dma/idxd/idxd_bus.c\nnew file mode 100644\nindex 0000000000..ef589af30e\n--- /dev/null\n+++ b/drivers/dma/idxd/idxd_bus.c\n@@ -0,0 +1,351 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2021 Intel Corporation\n+ */\n+\n+#include <dirent.h>\n+#include <fcntl.h>\n+#include <unistd.h>\n+#include <sys/mman.h>\n+#include <libgen.h>\n+\n+#include <rte_bus.h>\n+#include <rte_log.h>\n+#include <rte_dmadev_pmd.h>\n+#include <rte_string_fns.h>\n+\n+#include \"idxd_internal.h\"\n+\n+/* default value for DSA paths, but allow override in environment for testing */\n+#define DSA_DEV_PATH \"/dev/dsa\"\n+#define DSA_SYSFS_PATH \"/sys/bus/dsa/devices\"\n+\n+static unsigned int devcount;\n+\n+/** unique identifier for a DSA device/WQ instance */\n+struct dsa_wq_addr {\n+\tuint16_t device_id;\n+\tuint16_t wq_id;\n+};\n+\n+/** a DSA device instance */\n+struct rte_dsa_device {\n+\tstruct rte_device device;           /**< Inherit core device */\n+\tTAILQ_ENTRY(rte_dsa_device) next;   /**< next dev in list */\n+\n+\tchar wq_name[32];                   /**< the workqueue name/number e.g. wq0.1 */\n+\tstruct dsa_wq_addr addr;            /**< Identifies the specific WQ */\n+};\n+\n+/* forward prototypes */\n+struct dsa_bus;\n+static int dsa_scan(void);\n+static int dsa_probe(void);\n+static struct rte_device *dsa_find_device(const struct rte_device *start,\n+\t\trte_dev_cmp_t cmp,  const void *data);\n+static enum rte_iova_mode dsa_get_iommu_class(void);\n+static int dsa_addr_parse(const char *name, void *addr);\n+\n+/** List of devices */\n+TAILQ_HEAD(dsa_device_list, rte_dsa_device);\n+\n+/**\n+ * Structure describing the DSA bus\n+ */\n+struct dsa_bus {\n+\tstruct rte_bus bus;               /**< Inherit the generic class */\n+\tstruct rte_driver driver;         /**< Driver struct for devices to point to */\n+\tstruct dsa_device_list device_list;  /**< List of PCI devices */\n+};\n+\n+struct dsa_bus dsa_bus = {\n+\t.bus = {\n+\t\t.scan = dsa_scan,\n+\t\t.probe = dsa_probe,\n+\t\t.find_device = dsa_find_device,\n+\t\t.get_iommu_class = dsa_get_iommu_class,\n+\t\t.parse = dsa_addr_parse,\n+\t},\n+\t.driver = {\n+\t\t.name = \"dmadev_idxd\"\n+\t},\n+\t.device_list = TAILQ_HEAD_INITIALIZER(dsa_bus.device_list),\n+};\n+\n+static inline const char *\n+dsa_get_dev_path(void)\n+{\n+\tconst char *path = getenv(\"DSA_DEV_PATH\");\n+\treturn path ? path : DSA_DEV_PATH;\n+}\n+\n+static inline const char *\n+dsa_get_sysfs_path(void)\n+{\n+\tconst char *path = getenv(\"DSA_SYSFS_PATH\");\n+\treturn path ? path : DSA_SYSFS_PATH;\n+}\n+\n+static void *\n+idxd_bus_mmap_wq(struct rte_dsa_device *dev)\n+{\n+\tvoid *addr;\n+\tchar path[PATH_MAX];\n+\tint fd;\n+\n+\tsnprintf(path, sizeof(path), \"%s/%s\", dsa_get_dev_path(), dev->wq_name);\n+\tfd = open(path, O_RDWR);\n+\tif (fd < 0) {\n+\t\tIDXD_PMD_ERR(\"Failed to open device path: %s\", path);\n+\t\treturn NULL;\n+\t}\n+\n+\taddr = mmap(NULL, 0x1000, PROT_WRITE, MAP_SHARED, fd, 0);\n+\tclose(fd);\n+\tif (addr == MAP_FAILED) {\n+\t\tIDXD_PMD_ERR(\"Failed to mmap device %s\", path);\n+\t\treturn NULL;\n+\t}\n+\n+\treturn addr;\n+}\n+\n+static int\n+read_wq_string(struct rte_dsa_device *dev, const char *filename,\n+\t\tchar *value, size_t valuelen)\n+{\n+\tchar sysfs_node[PATH_MAX];\n+\tint len;\n+\tint fd;\n+\n+\tsnprintf(sysfs_node, sizeof(sysfs_node), \"%s/%s/%s\",\n+\t\t\tdsa_get_sysfs_path(), dev->wq_name, filename);\n+\tfd = open(sysfs_node, O_RDONLY);\n+\tif (fd < 0) {\n+\t\tIDXD_PMD_ERR(\"%s(): opening file '%s' failed: %s\",\n+\t\t\t\t__func__, sysfs_node, strerror(errno));\n+\t\treturn -1;\n+\t}\n+\n+\tlen = read(fd, value, valuelen - 1);\n+\tclose(fd);\n+\tif (len < 0) {\n+\t\tIDXD_PMD_ERR(\"%s(): error reading file '%s': %s\",\n+\t\t\t\t__func__, sysfs_node, strerror(errno));\n+\t\treturn -1;\n+\t}\n+\tvalue[len] = '\\0';\n+\treturn 0;\n+}\n+\n+static int\n+read_wq_int(struct rte_dsa_device *dev, const char *filename,\n+\t\tint *value)\n+{\n+\tchar sysfs_node[PATH_MAX];\n+\tFILE *f;\n+\tint ret = 0;\n+\n+\tsnprintf(sysfs_node, sizeof(sysfs_node), \"%s/%s/%s\",\n+\t\t\tdsa_get_sysfs_path(), dev->wq_name, filename);\n+\tf = fopen(sysfs_node, \"r\");\n+\tif (f == NULL) {\n+\t\tIDXD_PMD_ERR(\"%s(): opening file '%s' failed: %s\",\n+\t\t\t\t__func__, sysfs_node, strerror(errno));\n+\t\treturn -1;\n+\t}\n+\n+\tif (fscanf(f, \"%d\", value) != 1) {\n+\t\tIDXD_PMD_ERR(\"%s(): error reading file '%s': %s\",\n+\t\t\t\t__func__, sysfs_node, strerror(errno));\n+\t\tret = -1;\n+\t}\n+\n+\tfclose(f);\n+\treturn ret;\n+}\n+\n+static int\n+read_device_int(struct rte_dsa_device *dev, const char *filename,\n+\t\tint *value)\n+{\n+\tchar sysfs_node[PATH_MAX];\n+\tFILE *f;\n+\tint ret = 0;\n+\n+\tsnprintf(sysfs_node, sizeof(sysfs_node), \"%s/dsa%d/%s\",\n+\t\t\tdsa_get_sysfs_path(), dev->addr.device_id, filename);\n+\tf = fopen(sysfs_node, \"r\");\n+\tif (f == NULL) {\n+\t\tIDXD_PMD_ERR(\"%s(): opening file '%s' failed: %s\",\n+\t\t\t\t__func__, sysfs_node, strerror(errno));\n+\t\treturn -1;\n+\t}\n+\n+\tif (fscanf(f, \"%d\", value) != 1) {\n+\t\tIDXD_PMD_ERR(\"%s(): error reading file '%s': %s\",\n+\t\t\t\t__func__, sysfs_node, strerror(errno));\n+\t\tret = -1;\n+\t}\n+\n+\tfclose(f);\n+\treturn ret;\n+}\n+\n+static int\n+idxd_probe_dsa(struct rte_dsa_device *dev)\n+{\n+\tstruct idxd_dmadev idxd = {0};\n+\tint ret = 0;\n+\n+\tIDXD_PMD_INFO(\"Probing device %s on numa node %d\",\n+\t\t\tdev->wq_name, dev->device.numa_node);\n+\tif (read_wq_int(dev, \"size\", &ret) < 0)\n+\t\treturn -1;\n+\tidxd.max_batches = ret;\n+\tif (read_wq_int(dev, \"max_batch_size\", &ret) < 0)\n+\t\treturn -1;\n+\tidxd.max_batch_size = ret;\n+\tidxd.qid = dev->addr.wq_id;\n+\tidxd.sva_support = 1;\n+\n+\tidxd.portal = idxd_bus_mmap_wq(dev);\n+\tif (idxd.portal == NULL) {\n+\t\tIDXD_PMD_ERR(\"WQ mmap failed\");\n+\t\treturn -ENOENT;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+is_for_this_process_use(const char *name)\n+{\n+\tchar *runtime_dir = strdup(rte_eal_get_runtime_dir());\n+\tchar *prefix = basename(runtime_dir);\n+\tint prefixlen = strlen(prefix);\n+\tint retval = 0;\n+\n+\tif (strncmp(name, \"dpdk_\", 5) == 0)\n+\t\tretval = 1;\n+\tif (strncmp(name, prefix, prefixlen) == 0 && name[prefixlen] == '_')\n+\t\tretval = 1;\n+\n+\tfree(runtime_dir);\n+\treturn retval;\n+}\n+\n+static int\n+dsa_probe(void)\n+{\n+\tstruct rte_dsa_device *dev;\n+\n+\tTAILQ_FOREACH(dev, &dsa_bus.device_list, next) {\n+\t\tchar type[64], name[64];\n+\n+\t\tif (read_wq_string(dev, \"type\", type, sizeof(type)) < 0 ||\n+\t\t\t\tread_wq_string(dev, \"name\", name, sizeof(name)) < 0)\n+\t\t\tcontinue;\n+\n+\t\tif (strncmp(type, \"user\", 4) == 0 && is_for_this_process_use(name)) {\n+\t\t\tdev->device.driver = &dsa_bus.driver;\n+\t\t\tidxd_probe_dsa(dev);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tIDXD_PMD_DEBUG(\"WQ '%s', not allocated to DPDK\", dev->wq_name);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+dsa_scan(void)\n+{\n+\tconst char *path = dsa_get_dev_path();\n+\tstruct dirent *wq;\n+\tDIR *dev_dir;\n+\n+\tdev_dir = opendir(path);\n+\tif (dev_dir == NULL) {\n+\t\tif (errno == ENOENT)\n+\t\t\treturn 0; /* no bus, return without error */\n+\t\tIDXD_PMD_ERR(\"%s(): opendir '%s' failed: %s\",\n+\t\t\t\t__func__, path, strerror(errno));\n+\t\treturn -1;\n+\t}\n+\n+\twhile ((wq = readdir(dev_dir)) != NULL) {\n+\t\tstruct rte_dsa_device *dev;\n+\t\tint numa_node = -1;\n+\n+\t\tif (strncmp(wq->d_name, \"wq\", 2) != 0)\n+\t\t\tcontinue;\n+\t\tif (strnlen(wq->d_name, sizeof(dev->wq_name)) == sizeof(dev->wq_name)) {\n+\t\t\tIDXD_PMD_ERR(\"%s(): wq name too long: '%s', skipping\",\n+\t\t\t\t\t__func__, wq->d_name);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tIDXD_PMD_DEBUG(\"%s(): found %s/%s\", __func__, path, wq->d_name);\n+\n+\t\tdev = malloc(sizeof(*dev));\n+\t\tif (dsa_addr_parse(wq->d_name, &dev->addr) < 0) {\n+\t\t\tIDXD_PMD_ERR(\"Error parsing WQ name: %s\", wq->d_name);\n+\t\t\tfree(dev);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tdev->device.bus = &dsa_bus.bus;\n+\t\tstrlcpy(dev->wq_name, wq->d_name, sizeof(dev->wq_name));\n+\t\tTAILQ_INSERT_TAIL(&dsa_bus.device_list, dev, next);\n+\t\tdevcount++;\n+\n+\t\tread_device_int(dev, \"numa_node\", &numa_node);\n+\t\tdev->device.numa_node = numa_node;\n+\t\tdev->device.name = dev->wq_name;\n+\t}\n+\n+\tclosedir(dev_dir);\n+\treturn 0;\n+}\n+\n+static struct rte_device *\n+dsa_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,\n+\t\t\t const void *data)\n+{\n+\tstruct rte_dsa_device *dev = TAILQ_FIRST(&dsa_bus.device_list);\n+\n+\t/* the rte_device struct must be at start of dsa structure */\n+\tRTE_BUILD_BUG_ON(offsetof(struct rte_dsa_device, device) != 0);\n+\n+\tif (start != NULL) /* jump to start point if given */\n+\t\tdev = TAILQ_NEXT((const struct rte_dsa_device *)start, next);\n+\twhile (dev != NULL) {\n+\t\tif (cmp(&dev->device, data) == 0)\n+\t\t\treturn &dev->device;\n+\t\tdev = TAILQ_NEXT(dev, next);\n+\t}\n+\treturn NULL;\n+}\n+\n+static enum rte_iova_mode\n+dsa_get_iommu_class(void)\n+{\n+\t/* if there are no devices, report don't care, otherwise VA mode */\n+\treturn devcount > 0 ? RTE_IOVA_VA : RTE_IOVA_DC;\n+}\n+\n+static int\n+dsa_addr_parse(const char *name, void *addr)\n+{\n+\tstruct dsa_wq_addr *wq = addr;\n+\tunsigned int device_id, wq_id;\n+\n+\tif (sscanf(name, \"wq%u.%u\", &device_id, &wq_id) != 2) {\n+\t\tIDXD_PMD_DEBUG(\"Parsing WQ name failed: %s\", name);\n+\t\treturn -1;\n+\t}\n+\n+\twq->device_id = device_id;\n+\twq->wq_id = wq_id;\n+\treturn 0;\n+}\n+\n+RTE_REGISTER_BUS(dsa, dsa_bus.bus);\ndiff --git a/drivers/dma/idxd/meson.build b/drivers/dma/idxd/meson.build\nindex 4426a9f65c..45418077f4 100644\n--- a/drivers/dma/idxd/meson.build\n+++ b/drivers/dma/idxd/meson.build\n@@ -7,5 +7,6 @@ endif\n \n deps += ['bus_pci']\n sources = files(\n+        'idxd_bus.c',\n         'idxd_pci.c'\n )\n",
    "prefixes": [
        "v7",
        "03/16"
    ]
}