get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 96609,
    "url": "http://patchwork.dpdk.org/api/patches/96609/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/1627990189-36531-5-git-send-email-fengchengwen@huawei.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.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": "<1627990189-36531-5-git-send-email-fengchengwen@huawei.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1627990189-36531-5-git-send-email-fengchengwen@huawei.com",
    "date": "2021-08-03T11:29:47",
    "name": "[v13,4/6] dmadev: introduce DMA device library implementation",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "d4da669f11df4e3d4a97a7f50c61bf14f5c859d4",
    "submitter": {
        "id": 2146,
        "url": "http://patchwork.dpdk.org/api/people/2146/?format=api",
        "name": "fengchengwen",
        "email": "fengchengwen@huawei.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patchwork.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/1627990189-36531-5-git-send-email-fengchengwen@huawei.com/mbox/",
    "series": [
        {
            "id": 18161,
            "url": "http://patchwork.dpdk.org/api/series/18161/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=18161",
            "date": "2021-08-03T11:29:47",
            "name": "support dmadev",
            "version": 13,
            "mbox": "http://patchwork.dpdk.org/series/18161/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/96609/comments/",
    "check": "warning",
    "checks": "http://patchwork.dpdk.org/api/patches/96609/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 53F91A0A0C;\n\tTue,  3 Aug 2021 13:33:58 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id B620B411D7;\n\tTue,  3 Aug 2021 13:33:41 +0200 (CEST)",
            "from szxga08-in.huawei.com (szxga08-in.huawei.com [45.249.212.255])\n by mails.dpdk.org (Postfix) with ESMTP id 2C133411C1\n for <dev@dpdk.org>; Tue,  3 Aug 2021 13:33:37 +0200 (CEST)",
            "from dggemv704-chm.china.huawei.com (unknown [172.30.72.56])\n by szxga08-in.huawei.com (SkyGuard) with ESMTP id 4GfCRt6Q9Fz1CRD1;\n Tue,  3 Aug 2021 19:33:30 +0800 (CST)",
            "from dggpeml500024.china.huawei.com (7.185.36.10) by\n dggemv704-chm.china.huawei.com (10.3.19.47) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id\n 15.1.2176.2; Tue, 3 Aug 2021 19:33:34 +0800",
            "from localhost.localdomain (10.67.165.24) by\n dggpeml500024.china.huawei.com (7.185.36.10) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id\n 15.1.2176.2; Tue, 3 Aug 2021 19:33:34 +0800"
        ],
        "From": "Chengwen Feng <fengchengwen@huawei.com>",
        "To": "<thomas@monjalon.net>, <ferruh.yigit@intel.com>,\n <bruce.richardson@intel.com>, <jerinj@marvell.com>, <jerinjacobk@gmail.com>,\n <andrew.rybchenko@oktetlabs.ru>",
        "CC": "<dev@dpdk.org>, <mb@smartsharesystems.com>, <nipun.gupta@nxp.com>,\n <hemant.agrawal@nxp.com>, <maxime.coquelin@redhat.com>,\n <honnappa.nagarahalli@arm.com>, <david.marchand@redhat.com>,\n <sburla@marvell.com>, <pkapoor@marvell.com>, <konstantin.ananyev@intel.com>",
        "Date": "Tue, 3 Aug 2021 19:29:47 +0800",
        "Message-ID": "<1627990189-36531-5-git-send-email-fengchengwen@huawei.com>",
        "X-Mailer": "git-send-email 2.8.1",
        "In-Reply-To": "<1627990189-36531-1-git-send-email-fengchengwen@huawei.com>",
        "References": "<1625231891-2963-1-git-send-email-fengchengwen@huawei.com>\n <1627990189-36531-1-git-send-email-fengchengwen@huawei.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"UTF-8\"",
        "Content-Transfer-Encoding": "8bit",
        "X-Originating-IP": "[10.67.165.24]",
        "X-ClientProxiedBy": "dggems702-chm.china.huawei.com (10.3.19.179) To\n dggpeml500024.china.huawei.com (7.185.36.10)",
        "X-CFilter-Loop": "Reflected",
        "Subject": "[dpdk-dev] [PATCH v13 4/6] dmadev: introduce DMA device library\n implementation",
        "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": "This patch introduce DMA device library implementation which includes\nconfiguration and I/O with the DMA devices.\n\nSigned-off-by: Chengwen Feng <fengchengwen@huawei.com>\nAcked-by: Bruce Richardson <bruce.richardson@intel.com>\nAcked-by: Morten Brørup <mb@smartsharesystems.com>\n---\n config/rte_config.h          |   3 +\n lib/dmadev/meson.build       |   1 +\n lib/dmadev/rte_dmadev.c      | 563 +++++++++++++++++++++++++++++++++++++++++++\n lib/dmadev/rte_dmadev.h      | 118 ++++++++-\n lib/dmadev/rte_dmadev_core.h |   2 +\n lib/dmadev/version.map       |   1 +\n 6 files changed, 676 insertions(+), 12 deletions(-)\n create mode 100644 lib/dmadev/rte_dmadev.c",
    "diff": "diff --git a/config/rte_config.h b/config/rte_config.h\nindex 590903c..331a431 100644\n--- a/config/rte_config.h\n+++ b/config/rte_config.h\n@@ -81,6 +81,9 @@\n /* rawdev defines */\n #define RTE_RAWDEV_MAX_DEVS 64\n \n+/* dmadev defines */\n+#define RTE_DMADEV_MAX_DEVS 64\n+\n /* ip_fragmentation defines */\n #define RTE_LIBRTE_IP_FRAG_MAX_FRAG 4\n #undef RTE_LIBRTE_IP_FRAG_TBL_STAT\ndiff --git a/lib/dmadev/meson.build b/lib/dmadev/meson.build\nindex 833baf7..d2fc85e 100644\n--- a/lib/dmadev/meson.build\n+++ b/lib/dmadev/meson.build\n@@ -1,6 +1,7 @@\n # SPDX-License-Identifier: BSD-3-Clause\n # Copyright(c) 2021 HiSilicon Limited.\n \n+sources = files('rte_dmadev.c')\n headers = files('rte_dmadev.h')\n indirect_headers += files('rte_dmadev_core.h')\n driver_sdk_headers += files('rte_dmadev_pmd.h')\ndiff --git a/lib/dmadev/rte_dmadev.c b/lib/dmadev/rte_dmadev.c\nnew file mode 100644\nindex 0000000..b4f5498\n--- /dev/null\n+++ b/lib/dmadev/rte_dmadev.c\n@@ -0,0 +1,563 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2021 HiSilicon Limited.\n+ * Copyright(c) 2021 Intel Corporation.\n+ */\n+\n+#include <ctype.h>\n+#include <inttypes.h>\n+#include <stdint.h>\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <string.h>\n+\n+#include <rte_debug.h>\n+#include <rte_dev.h>\n+#include <rte_eal.h>\n+#include <rte_errno.h>\n+#include <rte_lcore.h>\n+#include <rte_log.h>\n+#include <rte_memory.h>\n+#include <rte_memzone.h>\n+#include <rte_malloc.h>\n+#include <rte_string_fns.h>\n+\n+#include \"rte_dmadev.h\"\n+#include \"rte_dmadev_pmd.h\"\n+\n+struct rte_dmadev rte_dmadevices[RTE_DMADEV_MAX_DEVS];\n+\n+static const char *mz_rte_dmadev_data = \"rte_dmadev_data\";\n+/* Shared memory between primary and secondary processes. */\n+static struct {\n+\tstruct rte_dmadev_data data[RTE_DMADEV_MAX_DEVS];\n+} *dmadev_shared_data;\n+\n+RTE_LOG_REGISTER_DEFAULT(rte_dmadev_logtype, INFO);\n+#define RTE_DMADEV_LOG(level, ...) \\\n+\trte_log(RTE_LOG_ ## level, rte_dmadev_logtype, \"\" __VA_ARGS__)\n+\n+/* Macros to check for valid device id */\n+#define RTE_DMADEV_VALID_DEV_ID_OR_ERR_RET(dev_id, retval) do { \\\n+\tif (!rte_dmadev_is_valid_dev(dev_id)) { \\\n+\t\tRTE_DMADEV_LOG(ERR, \"Invalid dev_id=%u\\n\", dev_id); \\\n+\t\treturn retval; \\\n+\t} \\\n+} while (0)\n+\n+static int\n+dmadev_check_name(const char *name)\n+{\n+\tsize_t name_len;\n+\n+\tif (name == NULL) {\n+\t\tRTE_DMADEV_LOG(ERR, \"Name can't be NULL\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tname_len = strnlen(name, RTE_DMADEV_NAME_MAX_LEN);\n+\tif (name_len == 0) {\n+\t\tRTE_DMADEV_LOG(ERR, \"Zero length DMA device name\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\tif (name_len >= RTE_DMADEV_NAME_MAX_LEN) {\n+\t\tRTE_DMADEV_LOG(ERR, \"DMA device name is too long\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static uint16_t\n+dmadev_find_free_dev(void)\n+{\n+\tuint16_t i;\n+\n+\tfor (i = 0; i < RTE_DMADEV_MAX_DEVS; i++) {\n+\t\tif (dmadev_shared_data->data[i].dev_name[0] == '\\0')\n+\t\t\treturn i;\n+\t}\n+\n+\treturn RTE_DMADEV_MAX_DEVS;\n+}\n+\n+static struct rte_dmadev*\n+dmadev_find(const char *name)\n+{\n+\tuint16_t i;\n+\n+\tfor (i = 0; i < RTE_DMADEV_MAX_DEVS; i++) {\n+\t\tif ((rte_dmadevices[i].state == RTE_DMADEV_ATTACHED) &&\n+\t\t    (!strcmp(name, rte_dmadevices[i].data->dev_name)))\n+\t\t\treturn &rte_dmadevices[i];\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+static int\n+dmadev_shared_data_prepare(void)\n+{\n+\tconst struct rte_memzone *mz;\n+\n+\tif (dmadev_shared_data == NULL) {\n+\t\tif (rte_eal_process_type() == RTE_PROC_PRIMARY) {\n+\t\t\t/* Allocate port data and ownership shared memory. */\n+\t\t\tmz = rte_memzone_reserve(mz_rte_dmadev_data,\n+\t\t\t\t\t sizeof(*dmadev_shared_data),\n+\t\t\t\t\t rte_socket_id(), 0);\n+\t\t} else\n+\t\t\tmz = rte_memzone_lookup(mz_rte_dmadev_data);\n+\t\tif (mz == NULL)\n+\t\t\treturn -ENOMEM;\n+\n+\t\tdmadev_shared_data = mz->addr;\n+\t\tif (rte_eal_process_type() == RTE_PROC_PRIMARY)\n+\t\t\tmemset(dmadev_shared_data->data, 0,\n+\t\t\t       sizeof(dmadev_shared_data->data));\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static struct rte_dmadev *\n+dmadev_allocate(const char *name)\n+{\n+\tstruct rte_dmadev *dev;\n+\tuint16_t dev_id;\n+\n+\tdev = dmadev_find(name);\n+\tif (dev != NULL) {\n+\t\tRTE_DMADEV_LOG(ERR, \"DMA device already allocated\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\tif (dmadev_shared_data_prepare() != 0) {\n+\t\tRTE_DMADEV_LOG(ERR, \"Cannot allocate DMA shared data\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\tdev_id = dmadev_find_free_dev();\n+\tif (dev_id == RTE_DMADEV_MAX_DEVS) {\n+\t\tRTE_DMADEV_LOG(ERR, \"Reached maximum number of DMA devices\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\tdev = &rte_dmadevices[dev_id];\n+\tdev->data = &dmadev_shared_data->data[dev_id];\n+\tdev->data->dev_id = dev_id;\n+\trte_strscpy(dev->data->dev_name, name, sizeof(dev->data->dev_name));\n+\n+\treturn dev;\n+}\n+\n+static struct rte_dmadev *\n+dmadev_attach_secondary(const char *name)\n+{\n+\tstruct rte_dmadev *dev;\n+\tuint16_t i;\n+\n+\tif (dmadev_shared_data_prepare() != 0) {\n+\t\tRTE_DMADEV_LOG(ERR, \"Cannot allocate DMA shared data\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\tfor (i = 0; i < RTE_DMADEV_MAX_DEVS; i++) {\n+\t\tif (!strcmp(dmadev_shared_data->data[i].dev_name, name))\n+\t\t\tbreak;\n+\t}\n+\tif (i == RTE_DMADEV_MAX_DEVS) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %s is not driven by the primary process\\n\",\n+\t\t\tname);\n+\t\treturn NULL;\n+\t}\n+\n+\tdev = &rte_dmadevices[i];\n+\tdev->data = &dmadev_shared_data->data[i];\n+\tdev->dev_private = dev->data->dev_private;\n+\n+\treturn dev;\n+}\n+\n+struct rte_dmadev *\n+rte_dmadev_pmd_allocate(const char *name)\n+{\n+\tstruct rte_dmadev *dev;\n+\n+\tif (dmadev_check_name(name) != 0)\n+\t\treturn NULL;\n+\n+\tif (rte_eal_process_type() == RTE_PROC_PRIMARY)\n+\t\tdev = dmadev_allocate(name);\n+\telse\n+\t\tdev = dmadev_attach_secondary(name);\n+\n+\tif (dev == NULL)\n+\t\treturn NULL;\n+\tdev->state = RTE_DMADEV_ATTACHED;\n+\n+\treturn dev;\n+}\n+\n+int\n+rte_dmadev_pmd_release(struct rte_dmadev *dev)\n+{\n+\tvoid *dev_private_tmp;\n+\n+\tif (dev == NULL)\n+\t\treturn -EINVAL;\n+\n+\tif (dev->state == RTE_DMADEV_UNUSED)\n+\t\treturn 0;\n+\n+\tif (rte_eal_process_type() == RTE_PROC_PRIMARY)\n+\t\tmemset(dev->data, 0, sizeof(struct rte_dmadev_data));\n+\n+\tdev_private_tmp = dev->dev_private;\n+\tmemset(dev, 0, sizeof(struct rte_dmadev));\n+\tif (rte_eal_process_type() == RTE_PROC_PRIMARY)\n+\t\tdev->dev_private = dev_private_tmp;\n+\tdev->state = RTE_DMADEV_UNUSED;\n+\n+\treturn 0;\n+}\n+\n+struct rte_dmadev *\n+rte_dmadev_get_device_by_name(const char *name)\n+{\n+\tif (dmadev_check_name(name) != 0)\n+\t\treturn NULL;\n+\treturn dmadev_find(name);\n+}\n+\n+int\n+rte_dmadev_get_dev_id(const char *name)\n+{\n+\tstruct rte_dmadev *dev = rte_dmadev_get_device_by_name(name);\n+\tif (dev != NULL)\n+\t\treturn dev->data->dev_id;\n+\treturn -EINVAL;\n+}\n+\n+bool\n+rte_dmadev_is_valid_dev(uint16_t dev_id)\n+{\n+\treturn (dev_id < RTE_DMADEV_MAX_DEVS) &&\n+\t\trte_dmadevices[dev_id].state == RTE_DMADEV_ATTACHED;\n+}\n+\n+uint16_t\n+rte_dmadev_count(void)\n+{\n+\tuint16_t count = 0;\n+\tuint16_t i;\n+\n+\tfor (i = 0; i < RTE_DMADEV_MAX_DEVS; i++) {\n+\t\tif (rte_dmadevices[i].state == RTE_DMADEV_ATTACHED)\n+\t\t\tcount++;\n+\t}\n+\n+\treturn count;\n+}\n+\n+int\n+rte_dmadev_info_get(uint16_t dev_id, struct rte_dmadev_info *dev_info)\n+{\n+\tconst struct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\tint ret;\n+\n+\tRTE_DMADEV_VALID_DEV_ID_OR_ERR_RET(dev_id, -EINVAL);\n+\tif (dev_info == NULL)\n+\t\treturn -EINVAL;\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_info_get, -ENOTSUP);\n+\tmemset(dev_info, 0, sizeof(struct rte_dmadev_info));\n+\tret = (*dev->dev_ops->dev_info_get)(dev, dev_info,\n+\t\t\t\t\t    sizeof(struct rte_dmadev_info));\n+\tif (ret != 0)\n+\t\treturn ret;\n+\n+\tdev_info->device = dev->device;\n+\tdev_info->nb_vchans = dev->data->dev_conf.max_vchans;\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_dmadev_configure(uint16_t dev_id, const struct rte_dmadev_conf *dev_conf)\n+{\n+\tstruct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\tstruct rte_dmadev_info info;\n+\tint ret;\n+\n+\tRTE_DMADEV_VALID_DEV_ID_OR_ERR_RET(dev_id, -EINVAL);\n+\tif (dev_conf == NULL)\n+\t\treturn -EINVAL;\n+\n+\tif (dev->data->dev_started != 0) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u must be stopped to allow configuration\\n\",\n+\t\t\tdev_id);\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tret = rte_dmadev_info_get(dev_id, &info);\n+\tif (ret != 0) {\n+\t\tRTE_DMADEV_LOG(ERR, \"Device %u get device info fail\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (dev_conf->max_vchans == 0) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u configure zero vchans\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (dev_conf->max_vchans > info.max_vchans) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u configure too many vchans\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (dev_conf->enable_silent &&\n+\t    !(info.dev_capa & RTE_DMADEV_CAPA_SILENT)) {\n+\t\tRTE_DMADEV_LOG(ERR, \"Device %u don't support silent\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_configure, -ENOTSUP);\n+\tret = (*dev->dev_ops->dev_configure)(dev, dev_conf);\n+\tif (ret == 0)\n+\t\tmemcpy(&dev->data->dev_conf, dev_conf, sizeof(*dev_conf));\n+\n+\treturn ret;\n+}\n+\n+int\n+rte_dmadev_start(uint16_t dev_id)\n+{\n+\tstruct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\tint ret;\n+\n+\tRTE_DMADEV_VALID_DEV_ID_OR_ERR_RET(dev_id, -EINVAL);\n+\n+\tif (dev->data->dev_started != 0) {\n+\t\tRTE_DMADEV_LOG(WARNING, \"Device %u already started\\n\", dev_id);\n+\t\treturn 0;\n+\t}\n+\n+\tif (dev->dev_ops->dev_start == NULL)\n+\t\tgoto mark_started;\n+\n+\tret = (*dev->dev_ops->dev_start)(dev);\n+\tif (ret != 0)\n+\t\treturn ret;\n+\n+mark_started:\n+\tdev->data->dev_started = 1;\n+\treturn 0;\n+}\n+\n+int\n+rte_dmadev_stop(uint16_t dev_id)\n+{\n+\tstruct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\tint ret;\n+\n+\tRTE_DMADEV_VALID_DEV_ID_OR_ERR_RET(dev_id, -EINVAL);\n+\n+\tif (dev->data->dev_started == 0) {\n+\t\tRTE_DMADEV_LOG(WARNING, \"Device %u already stopped\\n\", dev_id);\n+\t\treturn 0;\n+\t}\n+\n+\tif (dev->dev_ops->dev_stop == NULL)\n+\t\tgoto mark_stopped;\n+\n+\tret = (*dev->dev_ops->dev_stop)(dev);\n+\tif (ret != 0)\n+\t\treturn ret;\n+\n+mark_stopped:\n+\tdev->data->dev_started = 0;\n+\treturn 0;\n+}\n+\n+int\n+rte_dmadev_close(uint16_t dev_id)\n+{\n+\tstruct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\n+\tRTE_DMADEV_VALID_DEV_ID_OR_ERR_RET(dev_id, -EINVAL);\n+\n+\t/* Device must be stopped before it can be closed */\n+\tif (dev->data->dev_started == 1) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u must be stopped before closing\\n\", dev_id);\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_close, -ENOTSUP);\n+\treturn (*dev->dev_ops->dev_close)(dev);\n+}\n+\n+int\n+rte_dmadev_vchan_setup(uint16_t dev_id,\n+\t\t       const struct rte_dmadev_vchan_conf *conf)\n+{\n+\tstruct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\tstruct rte_dmadev_info info;\n+\tbool src_is_dev, dst_is_dev;\n+\tint ret;\n+\n+\tRTE_DMADEV_VALID_DEV_ID_OR_ERR_RET(dev_id, -EINVAL);\n+\tif (conf == NULL)\n+\t\treturn -EINVAL;\n+\n+\tif (dev->data->dev_started != 0) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u must be stopped to allow configuration\\n\",\n+\t\t\tdev_id);\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tret = rte_dmadev_info_get(dev_id, &info);\n+\tif (ret != 0) {\n+\t\tRTE_DMADEV_LOG(ERR, \"Device %u get device info fail\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (conf->direction != RTE_DMA_DIR_MEM_TO_MEM &&\n+\t    conf->direction != RTE_DMA_DIR_MEM_TO_DEV &&\n+\t    conf->direction != RTE_DMA_DIR_DEV_TO_MEM &&\n+\t    conf->direction != RTE_DMA_DIR_DEV_TO_DEV) {\n+\t\tRTE_DMADEV_LOG(ERR, \"Device %u direction invalid!\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (conf->direction == RTE_DMA_DIR_MEM_TO_MEM &&\n+\t    !(info.dev_capa & RTE_DMADEV_CAPA_MEM_TO_MEM)) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u don't support mem2mem transfer\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (conf->direction == RTE_DMA_DIR_MEM_TO_DEV &&\n+\t    !(info.dev_capa & RTE_DMADEV_CAPA_MEM_TO_DEV)) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u don't support mem2dev transfer\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (conf->direction == RTE_DMA_DIR_DEV_TO_MEM &&\n+\t    !(info.dev_capa & RTE_DMADEV_CAPA_DEV_TO_MEM)) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u don't support dev2mem transfer\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (conf->direction == RTE_DMA_DIR_DEV_TO_DEV &&\n+\t    !(info.dev_capa & RTE_DMADEV_CAPA_DEV_TO_DEV)) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u don't support dev2dev transfer\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (conf->nb_desc < info.min_desc || conf->nb_desc > info.max_desc) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u number of descriptors invalid\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\tsrc_is_dev = conf->direction == RTE_DMA_DIR_DEV_TO_MEM ||\n+\t\t     conf->direction == RTE_DMA_DIR_DEV_TO_DEV;\n+\tif ((conf->src_port.port_type == RTE_DMADEV_PORT_NONE && src_is_dev) ||\n+\t    (conf->src_port.port_type != RTE_DMADEV_PORT_NONE && !src_is_dev)) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u source port type invalid\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\tdst_is_dev = conf->direction == RTE_DMA_DIR_MEM_TO_DEV ||\n+\t\t     conf->direction == RTE_DMA_DIR_DEV_TO_DEV;\n+\tif ((conf->dst_port.port_type == RTE_DMADEV_PORT_NONE && dst_is_dev) ||\n+\t    (conf->dst_port.port_type != RTE_DMADEV_PORT_NONE && !dst_is_dev)) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u destination port type invalid\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vchan_setup, -ENOTSUP);\n+\treturn (*dev->dev_ops->vchan_setup)(dev, conf);\n+}\n+\n+int\n+rte_dmadev_stats_get(uint16_t dev_id, uint16_t vchan,\n+\t\t     struct rte_dmadev_stats *stats)\n+{\n+\tconst struct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\n+\tRTE_DMADEV_VALID_DEV_ID_OR_ERR_RET(dev_id, -EINVAL);\n+\tif (stats == NULL)\n+\t\treturn -EINVAL;\n+\tif (vchan >= dev->data->dev_conf.max_vchans &&\n+\t    vchan != RTE_DMADEV_ALL_VCHAN) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u vchan %u out of range\\n\", dev_id, vchan);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_get, -ENOTSUP);\n+\tmemset(stats, 0, sizeof(struct rte_dmadev_stats));\n+\treturn (*dev->dev_ops->stats_get)(dev, vchan, stats,\n+\t\t\t\t\t  sizeof(struct rte_dmadev_stats));\n+}\n+\n+int\n+rte_dmadev_stats_reset(uint16_t dev_id, uint16_t vchan)\n+{\n+\tstruct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\n+\tRTE_DMADEV_VALID_DEV_ID_OR_ERR_RET(dev_id, -EINVAL);\n+\tif (vchan >= dev->data->dev_conf.max_vchans &&\n+\t    vchan != RTE_DMADEV_ALL_VCHAN) {\n+\t\tRTE_DMADEV_LOG(ERR,\n+\t\t\t\"Device %u vchan %u out of range\\n\", dev_id, vchan);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_reset, -ENOTSUP);\n+\treturn (*dev->dev_ops->stats_reset)(dev, vchan);\n+}\n+\n+int\n+rte_dmadev_dump(uint16_t dev_id, FILE *f)\n+{\n+\tconst struct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\tstruct rte_dmadev_info info;\n+\tint ret;\n+\n+\tRTE_DMADEV_VALID_DEV_ID_OR_ERR_RET(dev_id, -EINVAL);\n+\tif (f == NULL)\n+\t\treturn -EINVAL;\n+\n+\tret = rte_dmadev_info_get(dev_id, &info);\n+\tif (ret != 0) {\n+\t\tRTE_DMADEV_LOG(ERR, \"Device %u get device info fail\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfprintf(f, \"DMA Dev %u, '%s' [%s]\\n\",\n+\t\tdev->data->dev_id,\n+\t\tdev->data->dev_name,\n+\t\tdev->data->dev_started ? \"started\" : \"stopped\");\n+\tfprintf(f, \"  dev_capa: 0x%\" PRIx64 \"\\n\", info.dev_capa);\n+\tfprintf(f, \"  max_vchans_supported: %u\\n\", info.max_vchans);\n+\tfprintf(f, \"  max_vchans_configured: %u\\n\", info.nb_vchans);\n+\tfprintf(f, \"  silent_mode: %s\\n\",\n+\t\tdev->data->dev_conf.enable_silent ? \"on\" : \"off\");\n+\n+\tif (dev->dev_ops->dev_dump != NULL)\n+\t\treturn (*dev->dev_ops->dev_dump)(dev, f);\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_dmadev_selftest(uint16_t dev_id)\n+{\n+\tstruct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\n+\tRTE_DMADEV_VALID_DEV_ID_OR_ERR_RET(dev_id, -EINVAL);\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_selftest, -ENOTSUP);\n+\treturn (*dev->dev_ops->dev_selftest)(dev_id);\n+}\ndiff --git a/lib/dmadev/rte_dmadev.h b/lib/dmadev/rte_dmadev.h\nindex 439ad95..a6fbce6 100644\n--- a/lib/dmadev/rte_dmadev.h\n+++ b/lib/dmadev/rte_dmadev.h\n@@ -799,9 +799,21 @@ struct rte_dmadev_sge {\n  *   - <0: Error code returned by the driver copy function.\n  */\n __rte_experimental\n-int\n+static inline int\n rte_dmadev_copy(uint16_t dev_id, uint16_t vchan, rte_iova_t src, rte_iova_t dst,\n-\t\tuint32_t length, uint64_t flags);\n+\t\tuint32_t length, uint64_t flags)\n+{\n+\tstruct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\n+#ifdef RTE_DMADEV_DEBUG\n+\tif (!rte_dmadev_is_valid_dev(dev_id) ||\n+\t    vchan >= dev->data->dev_conf.max_vchans || length == 0)\n+\t\treturn -EINVAL;\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->copy, -ENOTSUP);\n+#endif\n+\n+\treturn (*dev->copy)(dev, vchan, src, dst, length, flags);\n+}\n \n /**\n  * @warning\n@@ -836,10 +848,23 @@ rte_dmadev_copy(uint16_t dev_id, uint16_t vchan, rte_iova_t src, rte_iova_t dst,\n  *   - <0: Error code returned by the driver copy scatter-gather list function.\n  */\n __rte_experimental\n-int\n+static inline int\n rte_dmadev_copy_sg(uint16_t dev_id, uint16_t vchan, struct rte_dmadev_sge *src,\n \t\t   struct rte_dmadev_sge *dst, uint16_t nb_src, uint16_t nb_dst,\n-\t\t   uint64_t flags);\n+\t\t   uint64_t flags)\n+{\n+\tstruct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\n+#ifdef RTE_DMADEV_DEBUG\n+\tif (!rte_dmadev_is_valid_dev(dev_id) ||\n+\t    vchan >= dev->data->dev_conf.max_vchans ||\n+\t    src == NULL || dst == NULL || nb_src == 0 || nb_dst == 0)\n+\t\treturn -EINVAL;\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->copy_sg, -ENOTSUP);\n+#endif\n+\n+\treturn (*dev->copy_sg)(dev, vchan, src, dst, nb_src, nb_dst, flags);\n+}\n \n /**\n  * @warning\n@@ -870,9 +895,21 @@ rte_dmadev_copy_sg(uint16_t dev_id, uint16_t vchan, struct rte_dmadev_sge *src,\n  *   - <0: Error code returned by the driver fill function.\n  */\n __rte_experimental\n-int\n+static inline int\n rte_dmadev_fill(uint16_t dev_id, uint16_t vchan, uint64_t pattern,\n-\t\trte_iova_t dst, uint32_t length, uint64_t flags);\n+\t\trte_iova_t dst, uint32_t length, uint64_t flags)\n+{\n+\tstruct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\n+#ifdef RTE_DMADEV_DEBUG\n+\tif (!rte_dmadev_is_valid_dev(dev_id) ||\n+\t    vchan >= dev->data->dev_conf.max_vchans || length == 0)\n+\t\treturn -EINVAL;\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->fill, -ENOTSUP);\n+#endif\n+\n+\treturn (*dev->fill)(dev, vchan, pattern, dst, length, flags);\n+}\n \n /**\n  * @warning\n@@ -893,8 +930,20 @@ rte_dmadev_fill(uint16_t dev_id, uint16_t vchan, uint64_t pattern,\n  *   - <0: Failure to trigger hardware.\n  */\n __rte_experimental\n-int\n-rte_dmadev_submit(uint16_t dev_id, uint16_t vchan);\n+static inline int\n+rte_dmadev_submit(uint16_t dev_id, uint16_t vchan)\n+{\n+\tstruct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\n+#ifdef RTE_DMADEV_DEBUG\n+\tif (!rte_dmadev_is_valid_dev(dev_id) ||\n+\t    vchan >= dev->data->dev_conf.max_vchans)\n+\t\treturn -EINVAL;\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->submit, -ENOTSUP);\n+#endif\n+\n+\treturn (*dev->submit)(dev, vchan);\n+}\n \n /**\n  * @warning\n@@ -920,9 +969,37 @@ rte_dmadev_submit(uint16_t dev_id, uint16_t vchan);\n  *   must be less than or equal to the value of nb_cpls.\n  */\n __rte_experimental\n-uint16_t\n+static inline uint16_t\n rte_dmadev_completed(uint16_t dev_id, uint16_t vchan, const uint16_t nb_cpls,\n-\t\t     uint16_t *last_idx, bool *has_error);\n+\t\t     uint16_t *last_idx, bool *has_error)\n+{\n+\tstruct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\tuint16_t idx;\n+\tbool err;\n+\n+#ifdef RTE_DMADEV_DEBUG\n+\tif (!rte_dmadev_is_valid_dev(dev_id) ||\n+\t    vchan >= dev->data->dev_conf.max_vchans || nb_cpls == 0)\n+\t\treturn 0;\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->completed, 0);\n+#endif\n+\n+\t/* Ensure the pointer values are non-null to simplify drivers.\n+\t * In most cases these should be compile time evaluated, since this is\n+\t * an inline function.\n+\t * - If NULL is explicitly passed as parameter, then compiler knows the\n+\t *   value is NULL\n+\t * - If address of local variable is passed as parameter, then compiler\n+\t *   can know it's non-NULL.\n+\t */\n+\tif (last_idx == NULL)\n+\t\tlast_idx = &idx;\n+\tif (has_error == NULL)\n+\t\thas_error = &err;\n+\n+\t*has_error = false;\n+\treturn (*dev->completed)(dev, vchan, nb_cpls, last_idx, has_error);\n+}\n \n /**\n  * @warning\n@@ -952,10 +1029,27 @@ rte_dmadev_completed(uint16_t dev_id, uint16_t vchan, const uint16_t nb_cpls,\n  *   status array are also set.\n  */\n __rte_experimental\n-uint16_t\n+static inline uint16_t\n rte_dmadev_completed_status(uint16_t dev_id, uint16_t vchan,\n \t\t\t    const uint16_t nb_cpls, uint16_t *last_idx,\n-\t\t\t    enum rte_dma_status_code *status);\n+\t\t\t    enum rte_dma_status_code *status)\n+{\n+\tstruct rte_dmadev *dev = &rte_dmadevices[dev_id];\n+\tuint16_t idx;\n+\n+#ifdef RTE_DMADEV_DEBUG\n+\tif (!rte_dmadev_is_valid_dev(dev_id) ||\n+\t    vchan >= dev->data->dev_conf.max_vchans ||\n+\t    nb_cpls == 0 || status == NULL)\n+\t\treturn 0;\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->completed_status, 0);\n+#endif\n+\n+\tif (last_idx == NULL)\n+\t\tlast_idx = &idx;\n+\n+\treturn (*dev->completed_status)(dev, vchan, nb_cpls, last_idx, status);\n+}\n \n #ifdef __cplusplus\n }\ndiff --git a/lib/dmadev/rte_dmadev_core.h b/lib/dmadev/rte_dmadev_core.h\nindex 599ab15..9272725 100644\n--- a/lib/dmadev/rte_dmadev_core.h\n+++ b/lib/dmadev/rte_dmadev_core.h\n@@ -177,4 +177,6 @@ struct rte_dmadev {\n \tuint64_t reserved[2]; /**< Reserved for future fields. */\n } __rte_cache_aligned;\n \n+extern struct rte_dmadev rte_dmadevices[];\n+\n #endif /* _RTE_DMADEV_CORE_H_ */\ndiff --git a/lib/dmadev/version.map b/lib/dmadev/version.map\nindex 408b93c..86c5e75 100644\n--- a/lib/dmadev/version.map\n+++ b/lib/dmadev/version.map\n@@ -27,6 +27,7 @@ EXPERIMENTAL {\n INTERNAL {\n         global:\n \n+\trte_dmadevices;\n \trte_dmadev_get_device_by_name;\n \trte_dmadev_pmd_allocate;\n \trte_dmadev_pmd_release;\n",
    "prefixes": [
        "v13",
        "4/6"
    ]
}