get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 110010,
    "url": "http://patches.dpdk.org/api/patches/110010/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20220421151900.703467-5-john.miller@atomicrules.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": "<20220421151900.703467-5-john.miller@atomicrules.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220421151900.703467-5-john.miller@atomicrules.com",
    "date": "2022-04-21T15:18:55",
    "name": "[05/10] baseband/ark: add ark baseband device",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "ce3e1452c3b0b28a22bec7dd3cc77eaa1f8ec2f4",
    "submitter": {
        "id": 719,
        "url": "http://patches.dpdk.org/api/people/719/?format=api",
        "name": "John Miller",
        "email": "john.miller@atomicrules.com"
    },
    "delegate": {
        "id": 6690,
        "url": "http://patches.dpdk.org/api/users/6690/?format=api",
        "username": "akhil",
        "first_name": "akhil",
        "last_name": "goyal",
        "email": "gakhil@marvell.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20220421151900.703467-5-john.miller@atomicrules.com/mbox/",
    "series": [
        {
            "id": 22596,
            "url": "http://patches.dpdk.org/api/series/22596/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=22596",
            "date": "2022-04-21T15:18:51",
            "name": "[01/10] doc/guides/bbdevs: add ark baseband device documentation",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/22596/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/110010/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/110010/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 40689A0093;\n\tThu, 21 Apr 2022 17:19:43 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id A011B427EC;\n\tThu, 21 Apr 2022 17:19:24 +0200 (CEST)",
            "from mail-pl1-f179.google.com (mail-pl1-f179.google.com\n [209.85.214.179])\n by mails.dpdk.org (Postfix) with ESMTP id 7C0FF427FE\n for <dev@dpdk.org>; Thu, 21 Apr 2022 17:19:22 +0200 (CEST)",
            "by mail-pl1-f179.google.com with SMTP id b7so5184638plh.2\n for <dev@dpdk.org>; Thu, 21 Apr 2022 08:19:22 -0700 (PDT)",
            "from john-All-Series.tds\n (h75-100-85-216.cntcnh.broadband.dynamic.tds.net. [75.100.85.216])\n by smtp.gmail.com with ESMTPSA id\n q5-20020a056a00084500b0050ace4a699dsm6463465pfk.95.2022.04.21.08.19.19\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 21 Apr 2022 08:19:20 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=atomicrules-com.20210112.gappssmtp.com; s=20210112;\n h=from:to:cc:subject:date:message-id:in-reply-to:references\n :mime-version:content-transfer-encoding;\n bh=py4SuoAVf+nvLpz0nTSkxikJUk20y4m0CYE5cArRewk=;\n b=0kbThIVbf+ZQOayTwKu05sALiA0NnAEuzjaDKP19A0GHL7TG7k0lO7hexVDtCGeBCL\n o41r2KTVZF+YzX/rObXZHAJuY4T04CvD7G3DzW827XLSOscOtwMuLgS1Ca06dpbjm6p0\n ZiCfoRUHhGjfZFDzvIhodnyDs04LDE0lFrGOM8WvLLoQkpUX0WccLRJ3Loy5gn4B0fgJ\n 0Th4eXgYVV0BTcB+YQN6vWHmdjgDtY7cgf2PF8cE1eu/OwFAZ2jgTScnkiSXD5eGyIb+\n M6yc4/sd2bVbhqhWzhESAs91FjMoQK6+2nqOgNIopIlA6qBf9Xby/LoJJfr4TomSZad0\n ImNA==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20210112;\n h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n :references:mime-version:content-transfer-encoding;\n bh=py4SuoAVf+nvLpz0nTSkxikJUk20y4m0CYE5cArRewk=;\n b=sI50duSrP+m9Aub29qcBv0twkvMX1b5mrSI1FswFHeWBWIQztzBlTvDbt+2PNmFOZq\n Gp3Nzw836kXl1YnWnVHljQcBPvDsoiGuAKfaRYkwYytlm6LlIwQCgttR3dPQSsUjWH9/\n sglFw00Fstz/gtKd8DQykZmpNFu2TbZFaxg4LtqhpGnenrf7rpwgXMakecOvx1EhMaCq\n PFey8dQzkuGyD3rAnLSQ0oXJhRtlHtKGk4kgdYvKT3jbxlVGUPeLNf7glyaz98W+tiy8\n 8gl2dW8uFICYlfvSxZ3gDCGuVP85Kt4etwHjZVD3GtuVtYG3hFS5jw67c731VkC2UPH5\n 9i8w==",
        "X-Gm-Message-State": "AOAM533VHpEn4Ei6oUYexUV5pGBL4qLoXNAElgYQrtfLeBYpr4KVK1fD\n oZS425CTDXSnII2qITeS6fBzOId71rZZRA==",
        "X-Google-Smtp-Source": "\n ABdhPJzhgQztCJAoqzKSNq0rc7gM3x4U48poK3cxmw12ThPhomE/j7df3kxHAB9f0gNZaGOqIxrn4g==",
        "X-Received": "by 2002:a17:902:9a0a:b0:158:a22a:5448 with SMTP id\n v10-20020a1709029a0a00b00158a22a5448mr26812697plp.20.1650554360878;\n Thu, 21 Apr 2022 08:19:20 -0700 (PDT)",
        "From": "John Miller <john.miller@atomicrules.com>",
        "To": "dev@dpdk.org",
        "Cc": "ferruh.yigit@xilinx.com, ed.czeck@atomicrules.com,\n John Miller <john.miller@atomicrules.com>",
        "Subject": "[PATCH 05/10] baseband/ark: add ark baseband device",
        "Date": "Thu, 21 Apr 2022 10:18:55 -0500",
        "Message-Id": "<20220421151900.703467-5-john.miller@atomicrules.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20220421151900.703467-1-john.miller@atomicrules.com>",
        "References": "<20220421151900.703467-1-john.miller@atomicrules.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "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"
    },
    "content": "Add new ark baseband device.\n\nSigned-off-by: John Miller <john.miller@atomicrules.com>\n---\n drivers/baseband/ark/ark_bbdev.c        | 1064 +++++++++++++++++++++++\n drivers/baseband/ark/ark_bbdev_common.c |  125 +++\n drivers/baseband/ark/ark_bbdev_common.h |   92 ++\n drivers/baseband/ark/ark_bbdev_custom.c |  201 +++++\n drivers/baseband/ark/ark_bbdev_custom.h |   30 +\n drivers/baseband/ark/meson.build        |   11 +\n drivers/baseband/ark/version.map        |    3 +\n 7 files changed, 1526 insertions(+)\n create mode 100644 drivers/baseband/ark/ark_bbdev.c\n create mode 100644 drivers/baseband/ark/ark_bbdev_common.c\n create mode 100644 drivers/baseband/ark/ark_bbdev_common.h\n create mode 100644 drivers/baseband/ark/ark_bbdev_custom.c\n create mode 100644 drivers/baseband/ark/ark_bbdev_custom.h\n create mode 100644 drivers/baseband/ark/meson.build\n create mode 100644 drivers/baseband/ark/version.map",
    "diff": "diff --git a/drivers/baseband/ark/ark_bbdev.c b/drivers/baseband/ark/ark_bbdev.c\nnew file mode 100644\nindex 0000000000..b23bbd44d1\n--- /dev/null\n+++ b/drivers/baseband/ark/ark_bbdev.c\n@@ -0,0 +1,1064 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2016-2021 Atomic Rules LLC\n+ */\n+\n+#include \"ark_common.h\"\n+#include \"ark_bbdev_common.h\"\n+#include \"ark_bbdev_custom.h\"\n+#include \"ark_ddm.h\"\n+#include \"ark_mpu.h\"\n+#include \"ark_rqp.h\"\n+#include \"ark_udm.h\"\n+\n+#include <rte_bbdev.h>\n+#include <rte_bbdev_pmd.h>\n+#include <rte_bus_pci.h>\n+#include <rte_common.h>\n+#include <rte_devargs.h>\n+#include <rte_malloc.h>\n+#include <rte_ring.h>\n+\n+#include <unistd.h>\n+\n+#define DRIVER_NAME baseband_ark\n+\n+RTE_LOG_REGISTER_DEFAULT(ark_bbdev_logtype, DEBUG);\n+\n+#define ARK_SYSCTRL_BASE  0x0\n+#define ARK_PKTGEN_BASE   0x10000\n+#define ARK_MPU_RX_BASE   0x20000\n+#define ARK_UDM_BASE      0x30000\n+#define ARK_MPU_TX_BASE   0x40000\n+#define ARK_DDM_BASE      0x60000\n+#define ARK_PKTDIR_BASE   0xa0000\n+#define ARK_PKTCHKR_BASE  0x90000\n+#define ARK_RCPACING_BASE 0xb0000\n+#define ARK_MPU_QOFFSET   0x00100\n+\n+#define BB_ARK_TX_Q_FACTOR 4\n+\n+/* TODO move to UDM, verify configuration */\n+#define ARK_RX_META_SIZE 32\n+#define ARK_RX_META_OFFSET (RTE_PKTMBUF_HEADROOM - ARK_RX_META_SIZE)\n+#define ARK_RX_MAX_NOCHAIN (RTE_MBUF_DEFAULT_DATAROOM)\n+\n+static_assert(sizeof(struct ark_rx_meta) == ARK_RX_META_SIZE, \"Unexpected struct size ark_rx_meta\");\n+static_assert(sizeof(union ark_tx_meta) == 8, \"Unexpected struct size ark_tx_meta\");\n+\n+static struct rte_pci_id pci_id_ark[] = {\n+\t{RTE_PCI_DEVICE(AR_VENDOR_ID, 0x1015)},\n+\t{RTE_PCI_DEVICE(AR_VENDOR_ID, 0x1016)},\n+\t{.device_id = 0},\n+};\n+\n+static const struct ark_dev_caps\n+ark_device_caps[] = {\n+\t\t     SET_DEV_CAPS(0x1015, true),\n+\t\t     SET_DEV_CAPS(0x1016, true),\n+\t\t     {.device_id = 0,}\n+};\n+\n+\n+/* Forward declarations */\n+static const struct rte_bbdev_ops ark_bbdev_pmd_ops;\n+\n+\n+/* queue */\n+struct ark_bbdev_queue {\n+\tstruct rte_ring *active_ops;  /* Ring for processed packets */\n+\n+\t/* RX components */\n+\t/* array of physical addresses of the mbuf data pointer */\n+\trte_iova_t *rx_paddress_q;\n+\tstruct ark_udm_t *udm;\n+\tstruct ark_mpu_t *rx_mpu;\n+\n+\t/* TX components */\n+\tunion ark_tx_meta *tx_meta_q;\n+\tstruct ark_mpu_t *tx_mpu;\n+\tstruct ark_ddm_t *ddm;\n+\n+\t/*  */\n+\tuint32_t tx_queue_mask;\n+\tuint32_t rx_queue_mask;\n+\n+\tint32_t rx_seed_index;\t\t/* step 1 set with empty mbuf */\n+\tint32_t rx_cons_index;\t\t/* step 3 consumed by driver */\n+\n+\t/* 3 indexes to the paired data rings. */\n+\tint32_t tx_prod_index;\t\t/* where to put the next one */\n+\tint32_t tx_free_index;\t\t/* local copy of tx_cons_index */\n+\n+\t/* separate cache line -- written by FPGA -- RX announce */\n+\tRTE_MARKER cacheline1 __rte_cache_min_aligned;\n+\tvolatile int32_t rx_prod_index; /* step 2 filled by FPGA */\n+\n+\t/* Separate cache line -- written by FPGA -- RX completion */\n+\tRTE_MARKER cacheline2 __rte_cache_min_aligned;\n+\tvolatile int32_t tx_cons_index; /* hw is done, can be freed */\n+} __rte_cache_aligned;\n+\n+static int\n+ark_bb_hw_q_setup(struct rte_bbdev *bbdev, uint16_t q_id, uint16_t queue_size)\n+{\n+\tstruct ark_bbdev_queue *q = bbdev->data->queues[q_id].queue_private;\n+\n+\trte_iova_t queue_base;\n+\trte_iova_t phys_addr_q_base;\n+\trte_iova_t phys_addr_prod_index;\n+\trte_iova_t phys_addr_cons_index;\n+\n+\tuint32_t write_interval_ns = 500; /* TODO this seems big */\n+\n+\tif (ark_mpu_verify(q->rx_mpu, sizeof(rte_iova_t))) {\n+\t\tARK_BBDEV_LOG(ERR, \"Illegal hw/sw configuration RX queue\");\n+\t\treturn -1;\n+\t}\n+\tARK_BBDEV_LOG(DEBUG, \"ark_bb_q setup %u:%u\",\n+\t\t      bbdev->data->dev_id, q_id);\n+\n+\t/* RX MPU */\n+\tphys_addr_q_base = rte_malloc_virt2iova(q->rx_paddress_q);\n+\t/* Force TX mode on MPU to match bbdev behavior */\n+\tark_mpu_configure(q->rx_mpu, phys_addr_q_base, queue_size, 1);\n+\tark_mpu_reset_stats(q->rx_mpu);\n+\tark_mpu_start(q->rx_mpu);\n+\n+\t/* UDM */\n+\tqueue_base = rte_malloc_virt2iova(q);\n+\tphys_addr_prod_index = queue_base +\n+\t\toffsetof(struct ark_bbdev_queue, rx_prod_index);\n+\tark_udm_write_addr(q->udm, phys_addr_prod_index);\n+\tark_udm_queue_enable(q->udm, 1);\n+\n+\t/* TX MPU */\n+\tphys_addr_q_base = rte_malloc_virt2iova(q->tx_meta_q);\n+\tark_mpu_configure(q->tx_mpu, phys_addr_q_base,\n+\t\t\t  BB_ARK_TX_Q_FACTOR * queue_size, 1);\n+\tark_mpu_start(q->tx_mpu);\n+\n+\t/* DDM */\n+\tphys_addr_cons_index = queue_base +\n+\t\toffsetof(struct ark_bbdev_queue, tx_cons_index);\n+\tark_ddm_setup(q->ddm, phys_addr_cons_index, write_interval_ns);\n+\n+\treturn 0;\n+}\n+\n+/* Setup a queue */\n+static int\n+ark_bb_q_setup(struct rte_bbdev *bbdev, uint16_t q_id,\n+\t       const struct rte_bbdev_queue_conf *queue_conf)\n+{\n+\tstruct ark_bbdev_queue *q;\n+\tstruct ark_bbdevice *ark_bb =  bbdev->data->dev_private;\n+\n+\tconst uint32_t queue_size = queue_conf->queue_size;\n+\tconst int socket_id = queue_conf->socket;\n+\tconst uint64_t pg_sz = sysconf(_SC_PAGESIZE);\n+\tchar ring_name[RTE_RING_NAMESIZE];\n+\n+\t/* Configuration checks */\n+\tif (!rte_is_power_of_2(queue_size)) {\n+\t\tARK_BBDEV_LOG(ERR,\n+\t\t\t      \"Configuration queue size\"\n+\t\t\t      \" must be power of two %u\",\n+\t\t\t      queue_size);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (RTE_PKTMBUF_HEADROOM < ARK_RX_META_SIZE) {\n+\t\tARK_BBDEV_LOG(ERR,\n+\t\t\t      \"Error: Ark bbdev requires head room > %d bytes (%s)\",\n+\t\t\t      ARK_RX_META_SIZE, __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* Allocate the queue data structure. */\n+\tq = rte_zmalloc_socket(RTE_STR(DRIVER_NAME), sizeof(*q),\n+\t\t\tRTE_CACHE_LINE_SIZE, queue_conf->socket);\n+\tif (q == NULL) {\n+\t\tARK_BBDEV_LOG(ERR, \"Failed to allocate queue memory\");\n+\t\treturn -ENOMEM;\n+\t}\n+\tbbdev->data->queues[q_id].queue_private = q;\n+\n+\t/* RING */\n+\tsnprintf(ring_name, RTE_RING_NAMESIZE, RTE_STR(DRIVER_NAME) \"%u:%u\",\n+\t\t bbdev->data->dev_id, q_id);\n+\tq->active_ops = rte_ring_create(ring_name,\n+\t\t\t\t\tqueue_size,\n+\t\t\t\t\tqueue_conf->socket,\n+\t\t\t\t\tRING_F_SP_ENQ | RING_F_SC_DEQ);\n+\tif (q->active_ops == NULL) {\n+\t\tARK_BBDEV_LOG(ERR, \"Failed to create ring\");\n+\t\tgoto free_all;\n+\t}\n+\n+\tq->rx_queue_mask = queue_size - 1;\n+\tq->tx_queue_mask = (BB_ARK_TX_Q_FACTOR * queue_size) - 1;\n+\n+\t/* Each mbuf requires 2 to 4 objects, factor by BB_ARK_TX_Q_FACTOR */\n+\tq->tx_meta_q =\n+\t\trte_zmalloc_socket(\"Ark_bb_txqueue meta\",\n+\t\t\t\t   queue_size * BB_ARK_TX_Q_FACTOR *\n+\t\t\t\t   sizeof(union ark_tx_meta),\n+\t\t\t\t   pg_sz,\n+\t\t\t\t   socket_id);\n+\n+\tif (q->tx_meta_q == 0) {\n+\t\tARK_BBDEV_LOG(ERR, \"Failed to allocate \"\n+\t\t\t      \"queue memory in %s\", __func__);\n+\t\tgoto free_all;\n+\t}\n+\n+\tq->ddm = RTE_PTR_ADD(ark_bb->ddm.v, q_id * ARK_DDM_QOFFSET);\n+\tq->tx_mpu = RTE_PTR_ADD(ark_bb->mputx.v, q_id * ARK_MPU_QOFFSET);\n+\n+\tq->rx_paddress_q =\n+\t\trte_zmalloc_socket(\"ark_bb_rx_paddress_q\",\n+\t\t\t\t   queue_size * sizeof(rte_iova_t),\n+\t\t\t\t   pg_sz,\n+\t\t\t\t   socket_id);\n+\n+\tif (q->rx_paddress_q == 0) {\n+\t\tARK_BBDEV_LOG(ERR,\n+\t\t\t      \"Failed to allocate queue memory in %s\",\n+\t\t\t      __func__);\n+\t\tgoto free_all;\n+\t}\n+\tq->udm = RTE_PTR_ADD(ark_bb->udm.v, q_id * ARK_UDM_QOFFSET);\n+\tq->rx_mpu = RTE_PTR_ADD(ark_bb->mpurx.v, q_id * ARK_MPU_QOFFSET);\n+\n+\t/* Structure have been configured, set the hardware */\n+\treturn ark_bb_hw_q_setup(bbdev, q_id, queue_size);\n+\n+free_all:\n+\trte_free(q->tx_meta_q);\n+\trte_free(q->rx_paddress_q);\n+\trte_free(q);\n+\treturn -EFAULT;\n+}\n+\n+/* Release queue */\n+static int\n+ark_bb_q_release(struct rte_bbdev *bbdev, uint16_t q_id)\n+{\n+\tstruct ark_bbdev_queue *q = bbdev->data->queues[q_id].queue_private;\n+\n+\t/* TODO Wait for ddm to send out all packets in flight,\n+\t * Is this only called after q stop?\n+\t */\n+\n+\tark_mpu_dump(q->rx_mpu, \"rx_MPU release\", q_id);\n+\tark_mpu_dump(q->tx_mpu, \"tx_MPU release\", q_id);\n+\n+\trte_ring_free(q->active_ops);\n+\trte_free(q->tx_meta_q);\n+\trte_free(q->rx_paddress_q);\n+\trte_free(q);\n+\tbbdev->data->queues[q_id].queue_private = NULL;\n+\n+\tARK_BBDEV_LOG(DEBUG, \"released device queue %u:%u\",\n+\t\t      bbdev->data->dev_id, q_id);\n+\treturn 0;\n+}\n+\n+static int\n+ark_bbdev_start(struct rte_bbdev *bbdev)\n+{\n+\tstruct ark_bbdevice *ark_bb = bbdev->data->dev_private;\n+\n+\tARK_BBDEV_LOG(DEBUG, \"Starting device %u\", bbdev->data->dev_id);\n+\tif (ark_bb->started)\n+\t\treturn 0;\n+\n+\t/* start UDM */\n+\tark_udm_start(ark_bb->udm.v);\n+\n+\t/* start DDM */\n+\tark_ddm_start(ark_bb->ddm.v);\n+\n+\tark_bb->started = 1;\n+\n+\tif (ark_bb->start_pg)\n+\t\tark_pktchkr_run(ark_bb->pc);\n+\n+\tif (ark_bb->start_pg) {\n+\t\tpthread_t thread;\n+\n+\t\t/* Delay packet generator start allow the hardware to be ready\n+\t\t * This is only used for sanity checking with internal generator\n+\t\t */\n+\t\tif (pthread_create(&thread, NULL,\n+\t\t\t\t   ark_pktgen_delay_start, ark_bb->pg)) {\n+\t\t\tARK_BBDEV_LOG(ERR, \"Could not create pktgen \"\n+\t\t\t\t    \"starter thread\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static void\n+ark_bbdev_stop(struct rte_bbdev *bbdev)\n+{\n+\tstruct ark_bbdevice *ark_bb = bbdev->data->dev_private;\n+\tstruct ark_mpu_t *mpu;\n+\tunsigned int i;\n+\tint status;\n+\n+\tARK_BBDEV_LOG(DEBUG, \"Stopping device %u\", bbdev->data->dev_id);\n+\n+\tif (!ark_bb->started)\n+\t\treturn;\n+\n+\t/* Stop the packet generator */\n+\tif (ark_bb->start_pg)\n+\t\tark_pktgen_pause(ark_bb->pg);\n+\n+\t/* Stop DDM */\n+\t/* Wait up to 0.1 second.  each stop is up to 1000 * 10 useconds */\n+\tfor (i = 0; i < 10; i++) {\n+\t\tstatus = ark_ddm_stop(ark_bb->ddm.v, 1);\n+\t\tif (status == 0)\n+\t\t\tbreak;\n+\t}\n+\tif (status || i != 0) {\n+\t\tARK_BBDEV_LOG(ERR, \"DDM stop anomaly. status:\"\n+\t\t\t      \" %d iter: %u. (%s)\",\n+\t\t\t      status,\n+\t\t\t      i,\n+\t\t\t      __func__);\n+\t\tark_ddm_dump(ark_bb->ddm.v, \"Stop anomaly\");\n+\n+\t\tmpu = ark_bb->mputx.v;\n+\t\tfor (i = 0; i < ark_bb->max_nb_queues; i++) {\n+\t\t\tark_mpu_dump(mpu, \"DDM failure dump\", i);\n+\t\t\tmpu = RTE_PTR_ADD(mpu, ARK_MPU_QOFFSET);\n+\t\t}\n+\t}\n+\tark_ddm_dump_stats(ark_bb->ddm.v, \"bbdev stop\");\n+\n+\t/* STOP RX Side */\n+\t/* Stop UDM  multiple tries attempted */\n+\tfor (i = 0; i < 10; i++) {\n+\t\tstatus = ark_udm_stop(ark_bb->udm.v, 1);\n+\t\tif (status == 0)\n+\t\t\tbreak;\n+\t}\n+\tif (status || i != 0) {\n+\t\tARK_BBDEV_LOG(WARNING, \"UDM stop anomaly. status %d iter: %u. (%s)\",\n+\t\t\t      status, i, __func__);\n+\t\tark_udm_dump(ark_bb->udm.v, \"Stop anomaly\");\n+\n+\t\tmpu = ark_bb->mpurx.v;\n+\t\tfor (i = 0; i < ark_bb->max_nb_queues; i++) {\n+\t\t\tark_mpu_dump(mpu, \"UDM Stop anomaly\", i);\n+\t\t\tmpu = RTE_PTR_ADD(mpu, ARK_MPU_QOFFSET);\n+\t\t}\n+\t}\n+\n+\tark_udm_dump_stats(ark_bb->udm.v, \"Post stop\");\n+\tark_udm_dump_perf(ark_bb->udm.v, \"Post stop\");\n+\n+\t/* Stop the packet checker if it is running */\n+\tif (ark_bb->start_pg) {\n+\t\tark_pktchkr_dump_stats(ark_bb->pc);\n+\t\tark_pktchkr_stop(ark_bb->pc);\n+\t}\n+}\n+\n+static int\n+ark_bb_q_start(struct rte_bbdev *bbdev, uint16_t q_id)\n+{\n+\tstruct ark_bbdev_queue *q = bbdev->data->queues[q_id].queue_private;\n+\tARK_BBDEV_LOG(DEBUG, \"ark_bb_q start %u:%u\", bbdev->data->dev_id, q_id);\n+\tark_mpu_start(q->tx_mpu);\n+\tark_mpu_start(q->rx_mpu);\n+\treturn 0;\n+}\n+static int\n+ark_bb_q_stop(struct rte_bbdev *bbdev, uint16_t q_id)\n+{\n+\tstruct ark_bbdev_queue *q = bbdev->data->queues[q_id].queue_private;\n+\tARK_BBDEV_LOG(DEBUG, \"ark_bb_q stop %u:%u\", bbdev->data->dev_id, q_id);\n+\tark_mpu_stop(q->tx_mpu);\n+\tark_mpu_stop(q->rx_mpu);\n+\treturn 0;\n+}\n+\n+/* ************************************************************************* */\n+/* Common function for all enqueue and dequeue ops */\n+static inline void\n+ark_bb_enqueue_desc_fill(struct ark_bbdev_queue *q,\n+\t\t\t struct rte_mbuf *mbuf,\n+\t\t\t uint16_t offset, /* Extra offset */\n+\t\t\t uint8_t  flags,\n+\t\t\t uint32_t *meta,\n+\t\t\t uint8_t  meta_cnt /* 0, 1 or 2 */\n+\t\t\t )\n+{\n+\tunion ark_tx_meta *tx_meta;\n+\tint32_t tx_idx;\n+\tuint8_t m;\n+\n+\t/* Header */\n+\ttx_idx = q->tx_prod_index & q->tx_queue_mask;\n+\ttx_meta = &q->tx_meta_q[tx_idx];\n+\ttx_meta->data_len = rte_pktmbuf_data_len(mbuf) - offset;\n+\ttx_meta->flags = flags;\n+\ttx_meta->meta_cnt = meta_cnt;\n+\ttx_meta->user1 = *meta++;\n+\tq->tx_prod_index++;\n+\n+\tfor (m = 0; m < meta_cnt; m++) {\n+\t\ttx_idx = q->tx_prod_index & q->tx_queue_mask;\n+\t\ttx_meta = &q->tx_meta_q[tx_idx];\n+\t\ttx_meta->usermeta0 = *meta++;\n+\t\ttx_meta->usermeta1 = *meta++;\n+\t\tq->tx_prod_index++;\n+\t}\n+\n+\ttx_idx = q->tx_prod_index & q->tx_queue_mask;\n+\ttx_meta = &q->tx_meta_q[tx_idx];\n+\ttx_meta->physaddr = rte_mbuf_data_iova(mbuf) + offset;\n+\tq->tx_prod_index++;\n+}\n+\n+static inline void\n+ark_bb_enqueue_segmented_pkt(struct ark_bbdev_queue *q,\n+\t\t\t     struct rte_mbuf *mbuf,\n+\t\t\t     uint16_t offset,\n+\t\t\t     uint32_t *meta, uint8_t meta_cnt)\n+{\n+\tstruct rte_mbuf *next;\n+\tuint8_t flags = ARK_DDM_SOP;\n+\n+\twhile (mbuf != NULL) {\n+\t\tnext = mbuf->next;\n+\t\tflags |= (next == NULL) ? ARK_DDM_EOP : 0;\n+\n+\t\tark_bb_enqueue_desc_fill(q, mbuf, offset, flags,\n+\t\t\t\t\t meta, meta_cnt);\n+\n+\t\tflags &= ~ARK_DDM_SOP;\t/* drop SOP flags */\n+\t\tmeta_cnt = 0;\n+\t\toffset = 0;\n+\n+\t\tmbuf = next;\n+\t}\n+}\n+\n+static inline int\n+ark_bb_enqueue_common(struct ark_bbdev_queue *q,\n+\t\t      struct rte_mbuf *m_in, struct rte_mbuf *m_out,\n+\t\t      uint16_t offset,\n+\t\t      uint32_t *meta, uint8_t meta_cnt)\n+{\n+\tint32_t free_queue_space;\n+\tint32_t rx_idx;\n+\n+\t/* TX side limit */\n+\tfree_queue_space = q->tx_queue_mask -\n+\t\t(q->tx_prod_index - q->tx_free_index);\n+\tif (unlikely(free_queue_space < (2 + (2 * m_in->nb_segs))))\n+\t\treturn 1;\n+\n+\t/* RX side limit */\n+\tfree_queue_space = q->rx_queue_mask -\n+\t\t(q->rx_seed_index - q->rx_cons_index);\n+\tif (unlikely(free_queue_space < m_out->nb_segs))\n+\t\treturn 1;\n+\n+\tif (unlikely(m_in->nb_segs > 1))\n+\t\tark_bb_enqueue_segmented_pkt(q, m_in, offset, meta, meta_cnt);\n+\telse\n+\t\tark_bb_enqueue_desc_fill(q, m_in, offset,\n+\t\t\t\t\t ARK_DDM_SOP | ARK_DDM_EOP,\n+\t\t\t\t\t meta, meta_cnt);\n+\n+\t/* We assume that the return mubf has exactly enough segments for\n+\t * return data, which is 2048 bytes per segment.\n+\t */\n+\tdo {\n+\t\trx_idx = q->rx_seed_index & q->rx_queue_mask;\n+\t\tq->rx_paddress_q[rx_idx] = m_out->buf_iova;\n+\t\tq->rx_seed_index++;\n+\t\tm_out = m_out->next;\n+\t} while (m_out);\n+\n+\treturn 0;\n+}\n+\n+static inline void\n+ark_bb_enqueue_finalize(struct rte_bbdev_queue_data *q_data,\n+\t\t\tstruct ark_bbdev_queue *q,\n+\t\t\tvoid **ops,\n+\t\t\tuint16_t nb_ops, uint16_t nb)\n+{\n+\t/* BBDEV global stats */\n+\t/* These are not really errors, not sure why bbdev counts these. */\n+\tq_data->queue_stats.enqueue_err_count += nb_ops - nb;\n+\tq_data->queue_stats.enqueued_count += nb;\n+\n+\t/* Notify HW that  */\n+\tif (unlikely(nb == 0))\n+\t\treturn;\n+\n+\tark_mpu_set_producer(q->tx_mpu, q->tx_prod_index);\n+\tark_mpu_set_producer(q->rx_mpu, q->rx_seed_index);\n+\n+\t/* Queue info for dequeue-side processing */\n+\trte_ring_enqueue_burst(q->active_ops,\n+\t\t\t       (void **)ops, nb, NULL);\n+}\n+\n+static int\n+ark_bb_dequeue_segmented(struct rte_mbuf *mbuf0,\n+\t\t\t int32_t *prx_cons_index,\n+\t\t\t uint16_t pkt_len\n+\t\t\t )\n+{\n+\tstruct rte_mbuf *mbuf;\n+\tuint16_t data_len;\n+\tuint16_t remaining;\n+\tuint16_t segments = 1;\n+\n+\tdata_len = RTE_MIN(pkt_len, RTE_MBUF_DEFAULT_DATAROOM);\n+\tremaining = pkt_len - data_len;\n+\n+\tmbuf = mbuf0;\n+\tmbuf0->data_len = data_len;\n+\twhile (remaining) {\n+\t\tsegments += 1;\n+\t\tmbuf = mbuf->next;\n+\t\tif (unlikely(mbuf == 0)) {\n+\t\t\tARK_BBDEV_LOG(CRIT, \"Expected chained mbuf with \"\n+\t\t\t\t      \"at least %d segments for dequeue \"\n+\t\t\t\t      \"of packet length %d\",\n+\t\t\t\t      segments, pkt_len);\n+\t\t\treturn 1;\n+\t\t}\n+\n+\t\tdata_len = RTE_MIN(remaining,\n+\t\t\t\t   RTE_MBUF_DEFAULT_DATAROOM);\n+\t\tremaining -= data_len;\n+\n+\t\tmbuf->data_len = data_len;\n+\t\t*prx_cons_index += 1;\n+\t}\n+\n+\tif (mbuf->next != 0) {\n+\t\tARK_BBDEV_LOG(CRIT, \"Expected chained mbuf with \"\n+\t\t\t      \"at exactly %d segments for dequeue \"\n+\t\t\t      \"of packet length %d. Found %d \"\n+\t\t\t      \"segments\",\n+\t\t\t      segments, pkt_len, mbuf0->nb_segs);\n+\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n+\n+/* ************************************************************************* */\n+/* LDPC Decode ops */\n+static int16_t\n+ark_bb_enqueue_ldpc_dec_one_op(struct ark_bbdev_queue *q,\n+\t\t\t       struct rte_bbdev_dec_op *this_op)\n+{\n+\tstruct rte_bbdev_op_ldpc_dec *ldpc_dec_op = &this_op->ldpc_dec;\n+\tstruct rte_mbuf *m_in = ldpc_dec_op->input.data;\n+\tstruct rte_mbuf *m_out = ldpc_dec_op->hard_output.data;\n+\tuint16_t offset = ldpc_dec_op->input.offset;\n+\tuint32_t meta[5] = {0};\n+\tuint8_t meta_cnt = 0;\n+\n+\t/* User's meta move from bbdev op to Arkville HW */\n+\tif (ark_bb_user_enqueue_ldpc_dec(this_op, meta, &meta_cnt)) {\n+\t\tARK_BBDEV_LOG(ERR, \"%s failed\", __func__);\n+\t\treturn 1;\n+\t}\n+\n+\treturn ark_bb_enqueue_common(q, m_in, m_out, offset, meta, meta_cnt);\n+}\n+\n+/* Enqueue LDPC Decode -- burst */\n+static uint16_t\n+ark_bb_enqueue_ldpc_dec_ops(struct rte_bbdev_queue_data *q_data,\n+\t\t\t    struct rte_bbdev_dec_op **ops, uint16_t nb_ops)\n+{\n+\tstruct ark_bbdev_queue *q = q_data->queue_private;\n+\tunsigned int max_enq;\n+\tuint16_t nb;\n+\n+\tmax_enq = rte_ring_free_count(q->active_ops);\n+\tmax_enq = RTE_MIN(max_enq, nb_ops);\n+\tfor (nb = 0; nb < max_enq; nb++) {\n+\t\tif (ark_bb_enqueue_ldpc_dec_one_op(q, ops[nb]))\n+\t\t\tbreak;\n+\t}\n+\n+\tark_bb_enqueue_finalize(q_data, q, (void **)ops, nb_ops, nb);\n+\treturn nb;\n+}\n+\n+/* ************************************************************************* */\n+/* Dequeue LDPC Decode -- burst */\n+static uint16_t\n+ark_bb_dequeue_ldpc_dec_ops(struct rte_bbdev_queue_data *q_data,\n+\t\t\t    struct rte_bbdev_dec_op **ops, uint16_t nb_ops)\n+{\n+\tstruct ark_bbdev_queue *q = q_data->queue_private;\n+\tstruct rte_mbuf *mbuf;\n+\tstruct rte_bbdev_dec_op *this_op;\n+\tstruct ark_rx_meta *meta;\n+\tuint32_t *usermeta;\n+\n+\tuint16_t nb = 0;\n+\tint32_t prod_index = q->rx_prod_index;\n+\tint32_t cons_index = q->rx_cons_index;\n+\n+\tq->tx_free_index = q->tx_cons_index;\n+\n+\twhile ((prod_index - cons_index) > 0) {\n+\t\tif (rte_ring_dequeue(q->active_ops, (void **)&this_op)) {\n+\t\t\tARK_BBDEV_LOG(ERR, \"%s data ready but no op!\",\n+\t\t\t\t      __func__);\n+\t\t\tq_data->queue_stats.dequeue_err_count += 1;\n+\t\t\tbreak;\n+\t\t}\n+\t\tops[nb] = this_op;\n+\n+\t\tmbuf = this_op->ldpc_dec.hard_output.data;\n+\n+\t\t/* META DATA embedded in headroom */\n+\t\tmeta = RTE_PTR_ADD(mbuf->buf_addr, ARK_RX_META_OFFSET);\n+\n+\t\tmbuf->pkt_len = meta->pkt_len;\n+\t\tmbuf->data_len = meta->pkt_len;\n+\n+\t\tif (unlikely(meta->pkt_len > ARK_RX_MAX_NOCHAIN)) {\n+\t\t\tif (ark_bb_dequeue_segmented(mbuf, &cons_index,\n+\t\t\t\t\t\t     meta->pkt_len))\n+\t\t\t\tq_data->queue_stats.dequeue_err_count += 1;\n+\t\t} else if (mbuf->next != 0) {\n+\t\t\tARK_BBDEV_LOG(CRIT, \"Expected mbuf with \"\n+\t\t\t\t      \"at exactly 1 segments for dequeue \"\n+\t\t\t\t      \"of packet length %d. Found %d \"\n+\t\t\t\t      \"segments\",\n+\t\t\t\t      meta->pkt_len, mbuf->nb_segs);\n+\t\t\tq_data->queue_stats.dequeue_err_count += 1;\n+\t\t}\n+\n+\t\tusermeta = meta->user_meta;\n+\t\t/* User's meta move from Arkville HW to bbdev OP */\n+\t\tark_bb_user_dequeue_ldpc_dec(this_op, usermeta);\n+\t\tnb++;\n+\t\tcons_index++;\n+\t\tif (nb >= nb_ops)\n+\t\t\tbreak;\n+\t}\n+\n+\tq->rx_cons_index = cons_index;\n+\n+\t/* BBdev stats */\n+\tq_data->queue_stats.dequeued_count += nb;\n+\n+\treturn nb;\n+}\n+\n+/**************************************************************************/\n+/* Enqueue LDPC Encode */\n+static int16_t\n+ark_bb_enqueue_ldpc_enc_one_op(struct ark_bbdev_queue *q,\n+\t\t\t       struct rte_bbdev_enc_op *this_op)\n+{\n+\tstruct rte_bbdev_op_ldpc_enc *ldpc_enc_op = &this_op->ldpc_enc;\n+\tstruct rte_mbuf *m_in = ldpc_enc_op->input.data;\n+\tstruct rte_mbuf *m_out = ldpc_enc_op->output.data;\n+\tuint16_t offset = ldpc_enc_op->input.offset;\n+\tuint32_t meta[5] = {0};\n+\tuint8_t meta_cnt = 0;\n+\n+\t/* User's meta move from bbdev op to Arkville HW */\n+\tif (ark_bb_user_enqueue_ldpc_enc(this_op, meta, &meta_cnt)) {\n+\t\tARK_BBDEV_LOG(ERR, \"%s failed\", __func__);\n+\t\treturn 1;\n+\t}\n+\n+\treturn ark_bb_enqueue_common(q, m_in, m_out, offset, meta, meta_cnt);\n+}\n+\n+/* Enqueue LDPC Encode -- burst */\n+static uint16_t\n+ark_bb_enqueue_ldpc_enc_ops(struct rte_bbdev_queue_data *q_data,\n+\t\t\t    struct rte_bbdev_enc_op **ops, uint16_t nb_ops)\n+{\n+\tstruct ark_bbdev_queue *q = q_data->queue_private;\n+\tunsigned int max_enq;\n+\tuint16_t nb;\n+\n+\tmax_enq = rte_ring_free_count(q->active_ops);\n+\tmax_enq = RTE_MIN(max_enq, nb_ops);\n+\tfor (nb = 0; nb < max_enq; nb++) {\n+\t\tif (ark_bb_enqueue_ldpc_enc_one_op(q, ops[nb]))\n+\t\t\tbreak;\n+\t}\n+\n+\tark_bb_enqueue_finalize(q_data, q, (void **)ops, nb_ops, nb);\n+\treturn nb;\n+}\n+\n+/* Dequeue LDPC Encode -- burst */\n+static uint16_t\n+ark_bb_dequeue_ldpc_enc_ops(struct rte_bbdev_queue_data *q_data,\n+\t\t\t    struct rte_bbdev_enc_op **ops, uint16_t nb_ops)\n+{\n+\tstruct ark_bbdev_queue *q = q_data->queue_private;\n+\tstruct rte_mbuf *mbuf;\n+\tstruct rte_bbdev_enc_op *this_op;\n+\tstruct ark_rx_meta *meta;\n+\tuint32_t *usermeta;\n+\n+\tuint16_t nb = 0;\n+\tint32_t prod_index = q->rx_prod_index;\n+\tint32_t cons_index = q->rx_cons_index;\n+\n+\tq->tx_free_index = q->tx_cons_index;\n+\n+\twhile ((prod_index - cons_index) > 0) {\n+\t\tif (rte_ring_dequeue(q->active_ops, (void **)&this_op)) {\n+\t\t\tARK_BBDEV_LOG(ERR, \"%s data ready but no op!\",\n+\t\t\t\t      __func__);\n+\t\t\tq_data->queue_stats.dequeue_err_count += 1;\n+\t\t\tbreak;\n+\t\t}\n+\t\tops[nb] = this_op;\n+\n+\t\tmbuf = this_op->ldpc_enc.output.data;\n+\n+\t\t/* META DATA embedded in headroom */\n+\t\tmeta = RTE_PTR_ADD(mbuf->buf_addr, ARK_RX_META_OFFSET);\n+\n+\t\tmbuf->pkt_len = meta->pkt_len;\n+\t\tmbuf->data_len = meta->pkt_len;\n+\t\tusermeta = meta->user_meta;\n+\n+\t\tif (unlikely(meta->pkt_len > ARK_RX_MAX_NOCHAIN)) {\n+\t\t\tif (ark_bb_dequeue_segmented(mbuf, &cons_index,\n+\t\t\t\t\t\t     meta->pkt_len))\n+\t\t\t\tq_data->queue_stats.dequeue_err_count += 1;\n+\t\t} else if (mbuf->next != 0) {\n+\t\t\tARK_BBDEV_LOG(CRIT, \"Expected mbuf with \"\n+\t\t\t\t      \"at exactly 1 segments for dequeue \"\n+\t\t\t\t      \"of packet length %d. Found %d \"\n+\t\t\t\t      \"segments\",\n+\t\t\t\t      meta->pkt_len, mbuf->nb_segs);\n+\t\t\tq_data->queue_stats.dequeue_err_count += 1;\n+\t\t}\n+\n+\t\t/* User's meta move from Arkville HW to bbdev OP */\n+\t\tark_bb_user_dequeue_ldpc_enc(this_op, usermeta);\n+\t\tnb++;\n+\t\tcons_index++;\n+\t\tif (nb >= nb_ops)\n+\t\t\tbreak;\n+\t}\n+\n+\tq->rx_cons_index = cons_index;\n+\n+\t/* BBdev stats */\n+\tq_data->queue_stats.dequeued_count += nb;\n+\n+\treturn nb;\n+}\n+\n+/**************************************************************************/\n+/*\n+ *Initial device hardware configuration when device is opened\n+ * setup the DDM, and UDM; called once per PCIE device\n+ */\n+static int\n+ark_bb_config_device(struct ark_bbdevice *ark_bb)\n+{\n+\tuint16_t num_q, i;\n+\tstruct ark_mpu_t *mpu;\n+\n+\t/*\n+\t * Make sure that the packet director, generator and checker are in a\n+\t * known state\n+\t */\n+\tark_bb->start_pg = 0;\n+\tark_bb->pg = ark_pktgen_init(ark_bb->pktgen.v, 0, 1);\n+\tif (ark_bb->pg == NULL)\n+\t\treturn -1;\n+\tark_pktgen_reset(ark_bb->pg);\n+\tark_bb->pc = ark_pktchkr_init(ark_bb->pktchkr.v, 0, 1);\n+\tif (ark_bb->pc == NULL)\n+\t\treturn -1;\n+\tark_pktchkr_stop(ark_bb->pc);\n+\tark_bb->pd = ark_pktdir_init(ark_bb->pktdir.v);\n+\tif (ark_bb->pd == NULL)\n+\t\treturn -1;\n+\n+\t/* Verify HW */\n+\tif (ark_udm_verify(ark_bb->udm.v))\n+\t\treturn -1;\n+\tif (ark_ddm_verify(ark_bb->ddm.v))\n+\t\treturn -1;\n+\n+\t/* UDM */\n+\tif (ark_udm_reset(ark_bb->udm.v)) {\n+\t\tARK_BBDEV_LOG(ERR, \"Unable to stop and reset UDM\");\n+\t\treturn -1;\n+\t}\n+\t/* Keep in reset until the MPU are cleared */\n+\n+\t/* MPU reset */\n+\tmpu = ark_bb->mpurx.v;\n+\tnum_q = ark_api_num_queues(mpu);\n+\tark_bb->max_nb_queues = num_q;\n+\n+\tfor (i = 0; i < num_q; i++) {\n+\t\tark_mpu_reset(mpu);\n+\t\tmpu = RTE_PTR_ADD(mpu, ARK_MPU_QOFFSET);\n+\t}\n+\n+\t/* Only 1 queue supported in the udm */\n+\tark_udm_stop(ark_bb->udm.v, 0);\n+\tark_udm_configure(ark_bb->udm.v,\n+\t\t\t  RTE_PKTMBUF_HEADROOM,\n+\t\t\t  bbdev->data->queues[q_id]->dataroom,\n+\t\t\t  ARK_RX_WRITE_TIME_NS);\n+\n+\n+\tark_udm_stats_reset(ark_bb->udm.v);\n+\tark_udm_stop(ark_bb->udm.v, 0);\n+\n+\t/* TX -- DDM */\n+\tif (ark_ddm_stop(ark_bb->ddm.v, 1))\n+\t\tARK_BBDEV_LOG(ERR, \"Unable to stop DDM\");\n+\n+\tmpu = ark_bb->mputx.v;\n+\tnum_q = ark_api_num_queues(mpu);\n+\tfor (i = 0; i < num_q; i++) {\n+\t\tark_mpu_reset(mpu);\n+\t\tmpu = RTE_PTR_ADD(mpu, ARK_MPU_QOFFSET);\n+\t}\n+\n+\tark_ddm_reset(ark_bb->ddm.v);\n+\tark_ddm_stats_reset(ark_bb->ddm.v);\n+\n+\tark_ddm_stop(ark_bb->ddm.v, 0);\n+\tif (ark_bb->rqpacing)\n+\t\tark_rqp_stats_reset(ark_bb->rqpacing);\n+\n+\tARK_BBDEV_LOG(INFO, \"packet director set to 0x%x\", ark_bb->pkt_dir_v);\n+\tark_pktdir_setup(ark_bb->pd, ark_bb->pkt_dir_v);\n+\n+\tif (ark_bb->pkt_gen_args[0]) {\n+\t\tARK_BBDEV_LOG(INFO, \"Setting up the packet generator\");\n+\t\tark_pktgen_parse(ark_bb->pkt_gen_args);\n+\t\tark_pktgen_reset(ark_bb->pg);\n+\t\tark_pktgen_setup(ark_bb->pg);\n+\t\tark_bb->start_pg = 1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+ark_bbdev_init(struct rte_bbdev *bbdev, struct rte_pci_driver *pci_drv)\n+{\n+\tstruct ark_bbdevice *ark_bb = bbdev->data->dev_private;\n+\tstruct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(bbdev->device);\n+\tbool rqpacing = false;\n+\tint p;\n+\n+\tRTE_SET_USED(pci_drv);\n+\n+\tark_bb->bar0 = (uint8_t *)pci_dev->mem_resource[0].addr;\n+\tark_bb->a_bar = (uint8_t *)pci_dev->mem_resource[2].addr;\n+\n+\tark_bb->sysctrl.v  = (void *)&ark_bb->bar0[ARK_SYSCTRL_BASE];\n+\tark_bb->mpurx.v  = (void *)&ark_bb->bar0[ARK_MPU_RX_BASE];\n+\tark_bb->udm.v  = (void *)&ark_bb->bar0[ARK_UDM_BASE];\n+\tark_bb->mputx.v  = (void *)&ark_bb->bar0[ARK_MPU_TX_BASE];\n+\tark_bb->ddm.v  = (void *)&ark_bb->bar0[ARK_DDM_BASE];\n+\tark_bb->pktdir.v  = (void *)&ark_bb->bar0[ARK_PKTDIR_BASE];\n+\tark_bb->pktgen.v  = (void *)&ark_bb->bar0[ARK_PKTGEN_BASE];\n+\tark_bb->pktchkr.v  = (void *)&ark_bb->bar0[ARK_PKTCHKR_BASE];\n+\n+\tp = 0;\n+\twhile (ark_device_caps[p].device_id != 0) {\n+\t\tif (pci_dev->id.device_id == ark_device_caps[p].device_id) {\n+\t\t\trqpacing = ark_device_caps[p].caps.rqpacing;\n+\t\t\tbreak;\n+\t\t}\n+\t\tp++;\n+\t}\n+\n+\tif (rqpacing)\n+\t\tark_bb->rqpacing =\n+\t\t\t(struct ark_rqpace_t *)(ark_bb->bar0 + ARK_RCPACING_BASE);\n+\telse\n+\t\tark_bb->rqpacing = NULL;\n+\n+\tark_bb->started = 0;\n+\n+\tARK_BBDEV_LOG(INFO, \"Sys Ctrl Const = 0x%x  HW Commit_ID: %08x\",\n+\t\t      ark_bb->sysctrl.t32[4],\n+\t\t      rte_be_to_cpu_32(ark_bb->sysctrl.t32[0x20 / 4]));\n+\tARK_BBDEV_LOG(INFO, \"Arkville HW Commit_ID: %08x\",\n+\t\t    rte_be_to_cpu_32(ark_bb->sysctrl.t32[0x20 / 4]));\n+\n+\t/* If HW sanity test fails, return an error */\n+\tif (ark_bb->sysctrl.t32[4] != 0xcafef00d) {\n+\t\tARK_BBDEV_LOG(ERR,\n+\t\t\t      \"HW Sanity test has failed, expected constant\"\n+\t\t\t      \" 0x%x, read 0x%x (%s)\",\n+\t\t\t      0xcafef00d,\n+\t\t\t      ark_bb->sysctrl.t32[4], __func__);\n+\t\treturn -1;\n+\t}\n+\n+\treturn ark_bb_config_device(ark_bb);\n+}\n+\n+static int\n+ark_bbdev_uninit(struct rte_bbdev *bbdev)\n+{\n+\tstruct ark_bbdevice *ark_bb = bbdev->data->dev_private;\n+\n+\tif (rte_eal_process_type() != RTE_PROC_PRIMARY)\n+\t\treturn 0;\n+\n+\tark_pktgen_uninit(ark_bb->pg);\n+\tark_pktchkr_uninit(ark_bb->pc);\n+\n+\treturn 0;\n+}\n+\n+static int\n+ark_bbdev_probe(struct rte_pci_driver *pci_drv,\n+\t\tstruct rte_pci_device *pci_dev)\n+{\n+\tstruct rte_bbdev *bbdev = NULL;\n+\tchar dev_name[RTE_BBDEV_NAME_MAX_LEN];\n+\tstruct ark_bbdevice *ark_bb;\n+\n+\tif (pci_dev == NULL)\n+\t\treturn -EINVAL;\n+\n+\trte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));\n+\n+\t/* Allocate memory to be used privately by drivers */\n+\tbbdev = rte_bbdev_allocate(pci_dev->device.name);\n+\tif (bbdev == NULL)\n+\t\treturn -ENODEV;\n+\n+\t/* allocate device private memory */\n+\tbbdev->data->dev_private = rte_zmalloc_socket(dev_name,\n+\t\t\tsizeof(struct ark_bbdevice),\n+\t\t\tRTE_CACHE_LINE_SIZE,\n+\t\t\tpci_dev->device.numa_node);\n+\n+\tif (bbdev->data->dev_private == NULL) {\n+\t\tARK_BBDEV_LOG(CRIT,\n+\t\t\t\t\"Allocate of %zu bytes for device \\\"%s\\\" failed\",\n+\t\t\t\tsizeof(struct ark_bbdevice), dev_name);\n+\t\t\t\trte_bbdev_release(bbdev);\n+\t\t\treturn -ENOMEM;\n+\t}\n+\tark_bb = bbdev->data->dev_private;\n+\t/* Initialize ark_bb */\n+\tark_bb->pkt_dir_v = 0x00110110;\n+\n+\t/* Fill HW specific part of device structure */\n+\tbbdev->device = &pci_dev->device;\n+\tbbdev->intr_handle = NULL;\n+\tbbdev->data->socket_id = pci_dev->device.numa_node;\n+\tbbdev->dev_ops = &ark_bbdev_pmd_ops;\n+\tif (pci_dev->device.devargs)\n+\t\tparse_ark_bbdev_params(pci_dev->device.devargs->args, ark_bb);\n+\n+\n+\t/* Device specific initialization */\n+\tif (ark_bbdev_init(bbdev, pci_drv))\n+\t\treturn -EIO;\n+\tif (ark_bbdev_start(bbdev))\n+\t\treturn -EIO;\n+\n+\t/* Core operations LDPC encode amd decode */\n+\tbbdev->enqueue_ldpc_enc_ops = ark_bb_enqueue_ldpc_enc_ops;\n+\tbbdev->dequeue_ldpc_enc_ops = ark_bb_dequeue_ldpc_enc_ops;\n+\tbbdev->enqueue_ldpc_dec_ops = ark_bb_enqueue_ldpc_dec_ops;\n+\tbbdev->dequeue_ldpc_dec_ops = ark_bb_dequeue_ldpc_dec_ops;\n+\n+\tARK_BBDEV_LOG(DEBUG, \"bbdev id = %u [%s]\",\n+\t\t      bbdev->data->dev_id, dev_name);\n+\n+\treturn 0;\n+}\n+\n+/* Uninitialize device */\n+static int\n+ark_bbdev_remove(struct rte_pci_device *pci_dev)\n+{\n+\tstruct rte_bbdev *bbdev;\n+\tint ret;\n+\n+\tif (pci_dev == NULL)\n+\t\treturn -EINVAL;\n+\n+\t/* Find device */\n+\tbbdev = rte_bbdev_get_named_dev(pci_dev->device.name);\n+\tif (bbdev == NULL) {\n+\t\tARK_BBDEV_LOG(CRIT,\n+\t\t\t\t\"Couldn't find HW dev \\\"%s\\\" to Uninitialize it\",\n+\t\t\t\tpci_dev->device.name);\n+\t\treturn -ENODEV;\n+\t}\n+\n+\t/* Arkville device close */\n+\tark_bbdev_uninit(bbdev);\n+\trte_free(bbdev->data->dev_private);\n+\n+\t/* Close device */\n+\tret = rte_bbdev_close(bbdev->data->dev_id);\n+\tif (ret < 0)\n+\t\tARK_BBDEV_LOG(ERR,\n+\t\t\t\t\"Device %i failed to close during remove: %i\",\n+\t\t\t\tbbdev->data->dev_id, ret);\n+\n+\treturn rte_bbdev_release(bbdev);\n+}\n+\n+/* Operation for the PMD */\n+static const struct rte_bbdev_ops ark_bbdev_pmd_ops = {\n+\t.info_get = ark_bbdev_info_get,\n+\t.start = ark_bbdev_start,\n+\t.stop = ark_bbdev_stop,\n+\t.queue_setup = ark_bb_q_setup,\n+\t.queue_release = ark_bb_q_release,\n+\t.queue_start = ark_bb_q_start,\n+\t.queue_stop = ark_bb_q_stop,\n+};\n+\n+\n+\n+static struct rte_pci_driver ark_bbdev_pmd_drv = {\n+\t.probe = ark_bbdev_probe,\n+\t.remove = ark_bbdev_remove,\n+\t.id_table = pci_id_ark,\n+\t.drv_flags = RTE_PCI_DRV_NEED_MAPPING\n+};\n+\n+RTE_PMD_REGISTER_PCI(DRIVER_NAME, ark_bbdev_pmd_drv);\n+RTE_PMD_REGISTER_PCI_TABLE(DRIVER_NAME, pci_id_ark);\n+RTE_PMD_REGISTER_PARAM_STRING(DRIVER_NAME,\n+\t\t\t      ARK_BBDEV_PKTGEN_ARG \"=<filename> \"\n+\t\t\t      ARK_BBDEV_PKTCHKR_ARG \"=<filename> \"\n+\t\t\t      ARK_BBDEV_PKTDIR_ARG \"=<bitmap>\"\n+\t\t\t      );\ndiff --git a/drivers/baseband/ark/ark_bbdev_common.c b/drivers/baseband/ark/ark_bbdev_common.c\nnew file mode 100644\nindex 0000000000..6ef0f43654\n--- /dev/null\n+++ b/drivers/baseband/ark/ark_bbdev_common.c\n@@ -0,0 +1,125 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2016-2021 Atomic Rules LLC\n+ */\n+\n+#include <string.h>\n+\n+#include <rte_kvargs.h>\n+#include <rte_log.h>\n+\n+#include \"ark_bbdev_common.h\"\n+\n+static const char * const ark_bbdev_valid_params[] = {\n+\tARK_BBDEV_PKTDIR_ARG,\n+\tARK_BBDEV_PKTGEN_ARG,\n+\tARK_BBDEV_PKTCHKR_ARG,\n+\tNULL\n+};\n+\n+/* Parse 16-bit integer from string argument */\n+static inline int\n+parse_u16_arg(const char *key, const char *value, void *extra_args)\n+{\n+\tuint16_t *u16 = extra_args;\n+\tunsigned int long result;\n+\n+\tif ((value == NULL) || (extra_args == NULL))\n+\t\treturn -EINVAL;\n+\terrno = 0;\n+\tresult = strtoul(value, NULL, 0);\n+\tif ((result >= (1 << 16)) || (errno != 0)) {\n+\t\tARK_BBDEV_LOG(ERR, \"Invalid value %\" PRIu64 \" for %s\", result, key);\n+\t\treturn -ERANGE;\n+\t}\n+\t*u16 = (uint16_t)result;\n+\treturn 0;\n+}\n+\n+static inline int\n+process_pktdir_arg(const char *key, const char *value,\n+\t\t   void *extra_args)\n+{\n+\tuint32_t *u32 = extra_args;\n+\tARK_BBDEV_LOG(DEBUG, \"key = %s, value = %s\", key, value);\n+\n+\t*u32 = strtol(value, NULL, 0);\n+\tARK_BBDEV_LOG(DEBUG, \"pkt_dir_v = 0x%x\", *u32);\n+\treturn 0;\n+}\n+\n+static inline int\n+process_file_args(const char *key, const char *value, void *extra_args)\n+{\n+\tchar *args = (char *)extra_args;\n+\tARK_BBDEV_LOG(DEBUG, \"key = %s, value = %s\", key, value);\n+\n+\t/* Open the configuration file */\n+\tFILE *file = fopen(value, \"r\");\n+\tchar line[ARK_MAX_ARG_LEN];\n+\tint  size = 0;\n+\tint first = 1;\n+\n+\tif (file == NULL) {\n+\t\tARK_BBDEV_LOG(ERR, \"Unable to open config file %s\",\n+\t\t\t      value);\n+\t\treturn -1;\n+\t}\n+\n+\twhile (fgets(line, sizeof(line), file)) {\n+\t\tsize += strlen(line);\n+\t\tif (size >= ARK_MAX_ARG_LEN) {\n+\t\t\tARK_BBDEV_LOG(ERR, \"Unable to parse file %s args, \"\n+\t\t\t\t      \"parameter list is too long\", value);\n+\t\t\tfclose(file);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tif (first) {\n+\t\t\tstrncpy(args, line, ARK_MAX_ARG_LEN);\n+\t\t\tfirst = 0;\n+\t\t} else {\n+\t\t\tstrncat(args, line, ARK_MAX_ARG_LEN);\n+\t\t}\n+\t}\n+\tARK_BBDEV_LOG(DEBUG, \"file = %s\", args);\n+\tfclose(file);\n+\treturn 0;\n+}\n+\n+\n+/* Parse parameters used to create device */\n+int\n+parse_ark_bbdev_params(const char *input_args,\n+\t\t       struct ark_bbdevice *ark_bb)\n+{\n+\tstruct rte_kvargs *kvlist = NULL;\n+\tint ret = 0;\n+\n+\tif (ark_bb == NULL)\n+\t\treturn -EINVAL;\n+\tif (input_args == NULL)\n+\t\treturn ret;\n+\n+\tkvlist = rte_kvargs_parse(input_args, ark_bbdev_valid_params);\n+\tif (kvlist == NULL)\n+\t\treturn -EFAULT;\n+\n+\tret = rte_kvargs_process(kvlist, ARK_BBDEV_PKTDIR_ARG,\n+\t\t\t\t  &process_pktdir_arg, &ark_bb->pkt_dir_v);\n+\tif (ret < 0)\n+\t\tgoto exit;\n+\n+\tret = rte_kvargs_process(kvlist, ARK_BBDEV_PKTGEN_ARG,\n+\t\t\t\t &process_file_args, &ark_bb->pkt_gen_args);\n+\tif (ret < 0)\n+\t\tgoto exit;\n+\n+\tret = rte_kvargs_process(kvlist, ARK_BBDEV_PKTCHKR_ARG,\n+\t\t\t\t &process_file_args, &ark_bb->pkt_chkr_args);\n+\tif (ret < 0)\n+\t\tgoto exit;\n+\n+ exit:\n+\tif (kvlist)\n+\t\trte_kvargs_free(kvlist);\n+\treturn ret;\n+}\ndiff --git a/drivers/baseband/ark/ark_bbdev_common.h b/drivers/baseband/ark/ark_bbdev_common.h\nnew file mode 100644\nindex 0000000000..670e7e86d6\n--- /dev/null\n+++ b/drivers/baseband/ark/ark_bbdev_common.h\n@@ -0,0 +1,92 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2016-2021 Atomic Rules LLC\n+ */\n+\n+#ifndef _ARK_BBDEV_COMMON_H_\n+#define _ARK_BBDEV_COMMON_H_\n+\n+#include \"ark_pktchkr.h\"\n+#include \"ark_pktdir.h\"\n+#include \"ark_pktgen.h\"\n+\n+#define ARK_MAX_ARG_LEN 256\n+\n+/* Acceptable params for ark BBDEV devices */\n+/*\n+ * The packet generator is a functional block used to generate packet\n+ * patterns for testing.  It is not intended for nominal use.\n+ */\n+#define ARK_BBDEV_PKTGEN_ARG \"Pkt_gen\"\n+\n+/*\n+ * The packet checker is a functional block used to verify packet\n+ * patterns for testing.  It is not intended for nominal use.\n+ */\n+#define ARK_BBDEV_PKTCHKR_ARG \"Pkt_chkr\"\n+\n+/*\n+ * The packet director is used to select the internal ingress and\n+ * egress packets paths during testing.  It is not intended for\n+ * nominal use.\n+ */\n+#define ARK_BBDEV_PKTDIR_ARG \"Pkt_dir\"\n+\n+\n+#define def_ptr(type, name) \\\n+\tunion type {\t\t   \\\n+\t\tuint64_t *t64;\t   \\\n+\t\tuint32_t *t32;\t   \\\n+\t\tuint16_t *t16;\t   \\\n+\t\tuint8_t  *t8;\t   \\\n+\t\tvoid     *v;\t   \\\n+\t} name\n+\n+/*\n+ * Structure to store private data for each PF/VF instance.\n+ */\n+struct ark_bbdevice {\n+\t/* Our Bar 0 */\n+\tuint8_t *bar0;\n+\n+\t/* Application Bar needed for extensions */\n+\tuint8_t *a_bar;\n+\n+\t/* Arkville hardware block offsets */\n+\tdef_ptr(sys_ctrl, sysctrl);\n+\tdef_ptr(pkt_gen, pktgen);\n+\tdef_ptr(mpu_rx, mpurx);\n+\tdef_ptr(UDM, udm);\n+\tdef_ptr(mpu_tx, mputx);\n+\tdef_ptr(DDM, ddm);\n+\tdef_ptr(pkt_dir, pktdir);\n+\tdef_ptr(pkt_chkr, pktchkr);\n+\tstruct ark_rqpace_t *rqpacing;\n+\n+\t/* Pointers to packet generator and checker */\n+\tint start_pg;\n+\tark_pkt_gen_t pg;\n+\tark_pkt_chkr_t pc;\n+\tark_pkt_dir_t pd;\n+\n+\t/* Packet generator/checker args */\n+\tchar pkt_gen_args[ARK_MAX_ARG_LEN];\n+\tchar pkt_chkr_args[ARK_MAX_ARG_LEN];\n+\tuint32_t pkt_dir_v;\n+\n+\tint started;\n+\tunsigned int max_nb_queues;  /**< Max number of queues */\n+\n+};\n+\n+\n+/* Log message for PMD */\n+extern int ark_bbdev_logtype;\n+\n+/* Helper macro for logging */\n+#define ARK_BBDEV_LOG(level, fmt, ...) \\\n+\trte_log(RTE_LOG_ ## level, ark_bbdev_logtype, \\\n+\t\t\"ARK_BBD: \" fmt \"\\n\", ##__VA_ARGS__)\n+\n+int parse_ark_bbdev_params(const char *argv, struct ark_bbdevice *dev);\n+\n+#endif\ndiff --git a/drivers/baseband/ark/ark_bbdev_custom.c b/drivers/baseband/ark/ark_bbdev_custom.c\nnew file mode 100644\nindex 0000000000..6b1553abe1\n--- /dev/null\n+++ b/drivers/baseband/ark/ark_bbdev_custom.c\n@@ -0,0 +1,201 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2016-2021 Atomic Rules LLC\n+ */\n+\n+#include <rte_bbdev.h>\n+#include <rte_bbdev_pmd.h>\n+\n+#include <rte_mbuf.h>\n+#include <rte_hexdump.h>\t/* For debug */\n+\n+\n+#include \"ark_bbdev_common.h\"\n+#include \"ark_bbdev_custom.h\"\n+\n+/* It is expected that functions in this file will be modified based on\n+ * specifics of the FPGA hardware beyond the core Arkville\n+ * components.\n+ */\n+\n+/* bytyes must be range of 0 to 20 */\n+static inline\n+uint8_t ark_bb_cvt_bytes_meta_cnt(size_t bytes)\n+{\n+\treturn (bytes + 3) / 8;\n+}\n+\n+void\n+ark_bbdev_info_get(struct rte_bbdev *dev,\n+\t\t   struct rte_bbdev_driver_info *dev_info)\n+{\n+\tstruct ark_bbdevice *ark_bb =  dev->data->dev_private;\n+\n+\tstatic const struct rte_bbdev_op_cap bbdev_capabilities[] = {\n+\t\t{\n+\t\t\t.type = RTE_BBDEV_OP_LDPC_DEC,\n+\t\t\t.cap.ldpc_dec = {\n+\t\t\t\t.capability_flags =\n+\t\t\t\t\tRTE_BBDEV_LDPC_CRC_24B_ATTACH |\n+\t\t\t\t\tRTE_BBDEV_LDPC_RATE_MATCH,\n+\t\t\t\t.num_buffers_src =\n+\t\t\t\t\tRTE_BBDEV_LDPC_MAX_CODE_BLOCKS,\n+\t\t\t\t.num_buffers_hard_out =\n+\t\t\t\t\tRTE_BBDEV_LDPC_MAX_CODE_BLOCKS\n+\t\t\t}\n+\t\t},\n+\t\t{\n+\t\t\t.type = RTE_BBDEV_OP_LDPC_ENC,\n+\t\t\t.cap.ldpc_enc = {\n+\t\t\t\t.capability_flags =\n+\t\t\t\t\tRTE_BBDEV_LDPC_CRC_24B_ATTACH |\n+\t\t\t\t\tRTE_BBDEV_LDPC_RATE_MATCH,\n+\t\t\t\t.num_buffers_src =\n+\t\t\t\t\tRTE_BBDEV_LDPC_MAX_CODE_BLOCKS,\n+\t\t\t\t.num_buffers_dst =\n+\t\t\t\t\tRTE_BBDEV_LDPC_MAX_CODE_BLOCKS\n+\t\t\t}\n+\t\t},\n+\t\tRTE_BBDEV_END_OF_CAPABILITIES_LIST(),\n+\t};\n+\n+\tstatic struct rte_bbdev_queue_conf default_queue_conf = {\n+\t\t.queue_size = RTE_BBDEV_QUEUE_SIZE_LIMIT,\n+\t};\n+\n+\tdefault_queue_conf.socket = dev->data->socket_id;\n+\n+\tdev_info->driver_name = RTE_STR(DRIVER_NAME);\n+\tdev_info->max_num_queues = ark_bb->max_nb_queues;\n+\tdev_info->queue_size_lim = RTE_BBDEV_QUEUE_SIZE_LIMIT;\n+\tdev_info->hardware_accelerated = true;\n+\tdev_info->max_dl_queue_priority = 0;\n+\tdev_info->max_ul_queue_priority = 0;\n+\tdev_info->default_queue_conf = default_queue_conf;\n+\tdev_info->capabilities = bbdev_capabilities;\n+\tdev_info->cpu_flag_reqs = NULL;\n+\tdev_info->min_alignment = 4;\n+\n+}\n+\n+/* Structure defining layout of the ldpc command struct */\n+struct ark_bb_ldpc_enc_meta {\n+\tuint16_t header;\n+\tuint8_t rv_index:2,\n+\t\tbasegraph:1,\n+\t\tcode_block_mode:1,\n+\t\trfu_71_68:4;\n+\n+\tuint8_t q_m;\n+\tuint32_t e_ea;\n+\tuint32_t eb;\n+\tuint8_t c;\n+\tuint8_t cab;\n+\tuint16_t n_cb;\n+\tuint16_t pad;\n+\tuint16_t trailer;\n+} __rte_packed;\n+\n+/* The size must be less then 20 Bytes */\n+static_assert(sizeof(struct ark_bb_ldpc_enc_meta) <= 20, \"struct size\");\n+\n+/* Custom operation on equeue ldpc operation  */\n+/* Do these function need queue number? */\n+/* Maximum of 20 bytes */\n+int\n+ark_bb_user_enqueue_ldpc_enc(struct rte_bbdev_enc_op *enc_op,\n+\t\t\t  uint32_t *meta, uint8_t *meta_cnt)\n+{\n+\tstruct rte_bbdev_op_ldpc_enc *ldpc_enc_op = &enc_op->ldpc_enc;\n+\tstruct ark_bb_ldpc_enc_meta *src = (struct ark_bb_ldpc_enc_meta *)meta;\n+\n+\tsrc->header = 0x4321;\t/* For testings */\n+\tsrc->trailer = 0xFEDC;\n+\n+\tsrc->rv_index = ldpc_enc_op->rv_index;\n+\tsrc->basegraph = ldpc_enc_op->basegraph;\n+\tsrc->code_block_mode = ldpc_enc_op->code_block_mode;\n+\n+\tsrc->q_m = ldpc_enc_op->q_m;\n+\tsrc->e_ea = 0xABCD;\n+\tsrc->eb = ldpc_enc_op->tb_params.eb;\n+\tsrc->c = ldpc_enc_op->tb_params.c;\n+\tsrc->cab = ldpc_enc_op->tb_params.cab;\n+\n+\tsrc->n_cb = 0;\n+\n+\tmeta[0] = 0x11111110;\n+\tmeta[1] = 0x22222220;\n+\tmeta[2] = 0x33333330;\n+\tmeta[3] = 0x44444440;\n+\tmeta[4] = 0x55555550;\n+\n+\t*meta_cnt = ark_bb_cvt_bytes_meta_cnt(\n+\t\t\tsizeof(struct ark_bb_ldpc_enc_meta));\n+\treturn 0;\n+}\n+\n+/* Custom operation on dequeue ldpc operation  */\n+int\n+ark_bb_user_dequeue_ldpc_enc(struct rte_bbdev_enc_op *enc_op,\n+\t\t\t     const uint32_t *usermeta)\n+{\n+\tstatic int dump;\t/* = 0 */\n+\t/* Just compare with what was sent? */\n+\tuint32_t meta_in[5] = {0};\n+\tuint8_t  meta_cnt;\n+\n+\tark_bb_user_enqueue_ldpc_enc(enc_op, meta_in, &meta_cnt);\n+\tif (memcmp(usermeta, meta_in, 3 + (meta_cnt * 8))) {\n+\t\tfprintf(stderr,\n+\t\t\t\"------------------------------------------\\n\");\n+\t\trte_hexdump(stdout, \"meta difference for lpdc_enc IN\",\n+\t\t\t    meta_in, 20);\n+\t\trte_hexdump(stdout, \"meta difference for lpdc_enc OUT\",\n+\t\t\t    usermeta, 20);\n+\t} else if (dump) {\n+\t\trte_hexdump(stdout, \"DUMP lpdc_enc IN\", usermeta, 20);\n+\t\tdump--;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+\n+/* Turbo op call backs for user meta data */\n+int ark_bb_user_enqueue_ldpc_dec(struct rte_bbdev_dec_op *enc_op,\n+\t\t\t\t uint32_t *meta, uint8_t *meta_cnt)\n+{\n+\tRTE_SET_USED(enc_op);\n+\tmeta[0] = 0xF1111110;\n+\tmeta[1] = 0xF2222220;\n+\tmeta[2] = 0xF3333330;\n+\tmeta[3] = 0xF4444440;\n+\tmeta[4] = 0xF5555550;\n+\n+\t*meta_cnt = ark_bb_cvt_bytes_meta_cnt(20);\n+\treturn 0;\n+}\n+\n+int ark_bb_user_dequeue_ldpc_dec(struct rte_bbdev_dec_op *enc_op,\n+\t\t\t\t const uint32_t *usermeta)\n+{\n+\tRTE_SET_USED(enc_op);\n+\tstatic int dump;\t/* = 0 */\n+\t/* Just compare with what was sent? */\n+\tuint32_t meta_in[5] = {0};\n+\tuint8_t  meta_cnt;\n+\n+\tark_bb_user_enqueue_ldpc_dec(enc_op, meta_in, &meta_cnt);\n+\tif (memcmp(usermeta, meta_in, 3 + (meta_cnt * 8))) {\n+\t\tfprintf(stderr,\n+\t\t\t\"------------------------------------------\\n\");\n+\t\trte_hexdump(stdout, \"meta difference for lpdc_enc IN\",\n+\t\t\t    meta_in, 20);\n+\t\trte_hexdump(stdout, \"meta difference for lpdc_enc OUT\",\n+\t\t\t    usermeta, 20);\n+\t} else if (dump) {\n+\t\trte_hexdump(stdout, \"DUMP lpdc_enc IN\", usermeta, 20);\n+\t\tdump--;\n+\t}\n+\treturn 0;\n+}\ndiff --git a/drivers/baseband/ark/ark_bbdev_custom.h b/drivers/baseband/ark/ark_bbdev_custom.h\nnew file mode 100644\nindex 0000000000..32a2ef6bb6\n--- /dev/null\n+++ b/drivers/baseband/ark/ark_bbdev_custom.h\n@@ -0,0 +1,30 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2016-2021 Atomic Rules LLC\n+ */\n+\n+#ifndef _ARK_BBDEV_CUSTOM_H_\n+#define _ARK_BBDEV_CUSTOM_H_\n+\n+#include <stdint.h>\n+\n+/* Forward declarations */\n+struct rte_bbdev;\n+struct rte_bbdev_driver_info;\n+struct rte_bbdev_enc_op;\n+struct rte_bbdev_dec_op;\n+struct rte_mbuf;\n+\n+void ark_bbdev_info_get(struct rte_bbdev *dev,\n+\t\t\tstruct rte_bbdev_driver_info *dev_info);\n+\n+int ark_bb_user_enqueue_ldpc_dec(struct rte_bbdev_dec_op *enc_op,\n+\t\t\t\t uint32_t *meta, uint8_t *meta_cnt);\n+int ark_bb_user_dequeue_ldpc_dec(struct rte_bbdev_dec_op *enc_op,\n+\t\t\t\t const uint32_t *usermeta);\n+\n+int ark_bb_user_enqueue_ldpc_enc(struct rte_bbdev_enc_op *enc_op,\n+\t\t\t\t uint32_t *meta, uint8_t *meta_cnt);\n+int ark_bb_user_dequeue_ldpc_enc(struct rte_bbdev_enc_op *enc_op,\n+\t\t\t\t const uint32_t *usermeta);\n+\n+#endif\ndiff --git a/drivers/baseband/ark/meson.build b/drivers/baseband/ark/meson.build\nnew file mode 100644\nindex 0000000000..b876f05c6e\n--- /dev/null\n+++ b/drivers/baseband/ark/meson.build\n@@ -0,0 +1,11 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2018 Luca Boccassi <bluca@debian.org>\n+\n+deps += ['common_ark', 'bbdev', 'bus_pci', 'pci', 'ring']\n+sources = files(\n+\t'ark_bbdev.c',\n+\t'ark_bbdev_common.c',\n+\t'ark_bbdev_custom.c'\n+\t)\n+\n+includes += include_directories('../../common/ark')\ndiff --git a/drivers/baseband/ark/version.map b/drivers/baseband/ark/version.map\nnew file mode 100644\nindex 0000000000..4a76d1d52d\n--- /dev/null\n+++ b/drivers/baseband/ark/version.map\n@@ -0,0 +1,3 @@\n+DPDK_21 {\n+\tlocal: *;\n+};\n",
    "prefixes": [
        "05/10"
    ]
}