Hi John, 

> From: John Miller <john.mil...@atomicrules.com> 
> Sent: Monday, October 31, 2022 10:34 AM
> To: Chautru, Nicolas <nicolas.chau...@intel.com>
> Cc: dev@dpdk.org; ed.cz...@atomicrules.com; Shepard Siegel 
> <shepard.sie...@atomicrules.com>; Maxime Coquelin <maxime.coque...@redhat.com>
> Subject: Re: [PATCH 10/14] baseband/ark: introduce ark baseband driver
> 
> Hi Nicolas,
> 
> 
> 
> On Oct 26, 2022, at 7:11 PM, Chautru, Nicolas 
> <mailto:nicolas.chau...@intel.com> wrote:
> 
> Hi John,
> 
> General comment. I was a bit lost in the split in the commits 10 to 14. 
> First I would have expected it to build from the first commit. I don't 
> believe it makes sense to add 13 and 14 after the fact. 
> 
> I first introduced this patch set in 22.07 but we had to defer due other 
> company priorities.  I had 10 to 14 in the same commit but you asked me to 
> split it into smaller commits.  Perhaps I misunderstood what you were asking. 
>  I will put 10 thru 14 back into the same commit.
> 

This is about splitting these logically not artificially, see examples from 
other PMDs contributions with incremental commits but still not based on 
splitting away doc/build. 


> 
> Between 10 and 11 there were a bit of confusion as well to me.
> Like ark_bbdev_info_get is being first referred in 10 but then the 
> implementation is in 11.
> The ldpc decoding functions are also split between 10 and 11. As a 
> consequence the commit 10 is a hard to review in one chunk arguably. 
> 
> This will be addressed when I put them all in the same commit.
> 

That is not the intent see above. 

> 
> 
> I would suggest to consider a split of commits that may be more logical and 
> incremental. For instance what was done recently for the acc driver just as 
> an imperfect example. 
> This way it would also provide more digestible chunks of code to be reviewed 
> incrementally. 
> 
> I would be nice to have some doc with the first commit matching the code. 
> Notably as I had the impression the implementation doesn't fully match your 
> cover letter (I will add some more comments on this for 11), but unclear to 
> me whether this is intentional or not.
> 
> 
> We will address the doc to make sure it is accurate.
> 
> 
> We will address your other comments in a separate response.
> 
> Thank you
> -John
> 
> 
> 
> Thanks
> Nic
> 
> 
> 
> -----Original Message-----
> From: John Miller <mailto:john.mil...@atomicrules.com>
> Sent: Wednesday, October 26, 2022 12:46 PM
> To: Chautru, Nicolas <mailto:nicolas.chau...@intel.com>
> Cc: mailto:dev@dpdk.org; mailto:ed.cz...@atomicrules.com; Shepard Siegel
> <mailto:shepard.sie...@atomicrules.com>; John Miller
> <mailto:john.mil...@atomicrules.com>
> Subject: [PATCH 10/14] baseband/ark: introduce ark baseband driver
> 
> This patch introduces the Arkville baseband device driver.
> 
> Signed-off-by: John Miller <mailto:john.mil...@atomicrules.com>
> ---
> drivers/baseband/ark/ark_bbdev.c | 1127
> ++++++++++++++++++++++++++++++  drivers/baseband/ark/ark_bbext.h |  163
> +++++
> 2 files changed, 1290 insertions(+)
> create mode 100644 drivers/baseband/ark/ark_bbdev.c  create mode 100644
> drivers/baseband/ark/ark_bbext.h
> 
> diff --git a/drivers/baseband/ark/ark_bbdev.c
> b/drivers/baseband/ark/ark_bbdev.c
> new file mode 100644
> index 0000000000..8736d170d1
> --- /dev/null
> +++ b/drivers/baseband/ark/ark_bbdev.c
> @@ -0,0 +1,1127 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2016-2021 Atomic Rules LLC  */
> +
> +#include <sys/stat.h>
> +#include <dlfcn.h>
> +#include <unistd.h>
> +
> +#include <rte_common.h>
> +#include <rte_pci.h>
> +#include <bus_pci_driver.h>
> +#include <rte_bbdev.h>
> +#include <rte_bbdev_pmd.h>
> +#include <rte_bus_pci.h>
> +#include <rte_devargs.h>
> +#include <rte_malloc.h>
> +#include <rte_ring.h>
> +
> +#include "ark_common.h"
> +#include "ark_bbdev_common.h"
> +#include "ark_bbdev_custom.h"
> +#include "ark_ddm.h"
> +#include "ark_mpu.h"
> +#include "ark_rqp.h"
> +#include "ark_udm.h"
> +#include "ark_bbext.h"
> +
> +#define DRIVER_NAME baseband_ark
> +
> +#define ARK_SYSCTRL_BASE  0x0
> +#define ARK_PKTGEN_BASE   0x10000
> +#define ARK_MPU_RX_BASE   0x20000
> +#define ARK_UDM_BASE      0x30000
> +#define ARK_MPU_TX_BASE   0x40000
> +#define ARK_DDM_BASE      0x60000
> +#define ARK_PKTDIR_BASE   0xa0000
> +#define ARK_PKTCHKR_BASE  0x90000
> +#define ARK_RCPACING_BASE 0xb0000
> +#define ARK_MPU_QOFFSET   0x00100
> +
> +#define BB_ARK_TX_Q_FACTOR 4
> +
> +#define ARK_RX_META_SIZE 32
> +#define ARK_RX_META_OFFSET (RTE_PKTMBUF_HEADROOM -
> ARK_RX_META_SIZE)
> +#define ARK_RX_MAX_NOCHAIN (RTE_MBUF_DEFAULT_DATAROOM)
> +
> +static_assert(sizeof(struct ark_rx_meta) == ARK_RX_META_SIZE,
> +"Unexpected struct size ark_rx_meta"); static_assert(sizeof(union
> +ark_tx_meta) == 8, "Unexpected struct size ark_tx_meta");
> +
> +static struct rte_pci_id pci_id_ark[] = {
> +     {RTE_PCI_DEVICE(AR_VENDOR_ID, 0x1015)},
> +     {RTE_PCI_DEVICE(AR_VENDOR_ID, 0x1016)},
> +     {.device_id = 0},
> +};
> +
> +static const struct ark_dev_caps
> +ark_device_caps[] = {
> +                  SET_DEV_CAPS(0x1015, true, false),
> +                  SET_DEV_CAPS(0x1016, true, false),
> +                  {.device_id = 0,}
> +};
> +
> +
> +/* Forward declarations */
> +static const struct rte_bbdev_ops ark_bbdev_pmd_ops;
> +
> +static int
> +check_for_ext(struct ark_bbdevice *ark) {
> +     /* Get the env */
> +     const char *dllpath = getenv("ARK_BBEXT_PATH");
> +
> +     if (dllpath == NULL) {
> +             ARK_BBDEV_LOG(DEBUG, "EXT NO dll path specified\n");
> +             return 0;
> +     }
> +     ARK_BBDEV_LOG(NOTICE, "EXT found dll path at %s\n", dllpath);
> +
> +     /* Open and load the .so */
> +     ark->d_handle = dlopen(dllpath, RTLD_LOCAL | RTLD_LAZY);
> +     if (ark->d_handle == NULL) {
> +             ARK_BBDEV_LOG(ERR, "Could not load user extension %s\n",
> +                         dllpath);
> +             return -1;
> +     }
> +     ARK_BBDEV_LOG(DEBUG, "SUCCESS: loaded user extension %s\n",
> +                         dllpath);
> +
> +     /* Get the entry points */
> +     ark->user_ext.dev_init =
> +             (void *(*)(struct rte_bbdev *, void *))
> +             dlsym(ark->d_handle, "rte_pmd_ark_bbdev_init");
> +
> +     ark->user_ext.dev_uninit =
> +             (int (*)(struct rte_bbdev *, void *))
> +             dlsym(ark->d_handle, "rte_pmd_ark_dev_uninit");
> +     ark->user_ext.dev_start =
> +             (int (*)(struct rte_bbdev *, void *))
> +             dlsym(ark->d_handle, "rte_pmd_ark_bbdev_start");
> +     ark->user_ext.dev_stop =
> +             (int (*)(struct rte_bbdev *, void *))
> +             dlsym(ark->d_handle, "rte_pmd_ark_bbdev_stop");
> +     ark->user_ext.dequeue_ldpc_dec  =
> +             (int (*)(struct rte_bbdev *,
> +                      struct rte_bbdev_dec_op *,
> +                      uint32_t *,
> +                      void *))
> +             dlsym(ark->d_handle,
> "rte_pmd_ark_bbdev_dequeue_ldpc_dec");
> +     ark->user_ext.enqueue_ldpc_dec  =
> +             (int (*)(struct rte_bbdev *,
> +                      struct rte_bbdev_dec_op *,
> +                      uint32_t *,
> +                      uint8_t *,
> +                      void *))
> +             dlsym(ark->d_handle,
> "rte_pmd_ark_bbdev_enqueue_ldpc_dec");
> +     ark->user_ext.dequeue_ldpc_enc  =
> +             (int (*)(struct rte_bbdev *,
> +                      struct rte_bbdev_enc_op *,
> +                      uint32_t *,
> +                      void *))
> +             dlsym(ark->d_handle,
> "rte_pmd_ark_bbdev_dequeue_ldpc_enc");
> +     ark->user_ext.enqueue_ldpc_enc  =
> +             (int (*)(struct rte_bbdev *,
> +                      struct rte_bbdev_enc_op *,
> +                      uint32_t *,
> +                      uint8_t *,
> +                      void *))
> +             dlsym(ark->d_handle,
> "rte_pmd_ark_bbdev_enqueue_ldpc_enc");
> +
> +     return 0;
> +}
> +
> +
> +/* queue */
> +struct ark_bbdev_queue {
> +     struct ark_bbdevice *ark_bbdev;
> +
> +     struct rte_ring *active_ops;  /* Ring for processed packets */
> +
> +     /* RX components */
> +     /* array of physical addresses of the mbuf data pointer */
> +     rte_iova_t *rx_paddress_q;
> +     struct ark_udm_t *udm;
> +     struct ark_mpu_t *rx_mpu;
> +
> +     /* TX components */
> +     union ark_tx_meta *tx_meta_q;
> +     struct ark_mpu_t *tx_mpu;
> +     struct ark_ddm_t *ddm;
> +
> +     /*  */
> +     uint32_t tx_queue_mask;
> +     uint32_t rx_queue_mask;
> +
> +     int32_t rx_seed_index;          /* step 1 set with empty mbuf */
> +     int32_t rx_cons_index;          /* step 3 consumed by driver */
> +
> +     /* 3 indexes to the paired data rings. */
> +     int32_t tx_prod_index;          /* where to put the next one */
> +     int32_t tx_free_index;          /* local copy of tx_cons_index */
> +
> +     /* separate cache line -- written by FPGA -- RX announce */
> +     RTE_MARKER cacheline1 __rte_cache_min_aligned;
> +     volatile int32_t rx_prod_index; /* step 2 filled by FPGA */
> +
> +     /* Separate cache line -- written by FPGA -- RX completion */
> +     RTE_MARKER cacheline2 __rte_cache_min_aligned;
> +     volatile int32_t tx_cons_index; /* hw is done, can be freed */ }
> +__rte_cache_aligned;
> +
> +
> +static int
> +ark_bb_hw_q_setup(struct rte_bbdev *bbdev, uint16_t q_id, uint16_t
> +queue_size) {
> +     struct ark_bbdev_queue *q = bbdev->data-
> 
> queues[q_id].queue_private;
> +
> +     rte_iova_t queue_base;
> +     rte_iova_t phys_addr_q_base;
> +     rte_iova_t phys_addr_prod_index;
> +     rte_iova_t phys_addr_cons_index;
> +
> +     if (ark_mpu_verify(q->rx_mpu, sizeof(rte_iova_t))) {
> +             ARK_BBDEV_LOG(ERR, "Illegal hw/sw configuration RX
> queue");
> +             return -1;
> +     }
> +     ARK_BBDEV_LOG(DEBUG, "ark_bb_q setup %u:%u",
> +                   bbdev->data->dev_id, q_id);
> +
> +     /* RX MPU */
> +     phys_addr_q_base = rte_malloc_virt2iova(q->rx_paddress_q);
> +     /* Force TX mode on MPU to match bbdev behavior */
> +     ark_mpu_configure(q->rx_mpu, phys_addr_q_base, queue_size, 1);
> +     ark_mpu_start(q->rx_mpu);
> +
> +     /* UDM */
> +     queue_base = rte_malloc_virt2iova(q);
> +     phys_addr_prod_index = queue_base +
> +             offsetof(struct ark_bbdev_queue, rx_prod_index);
> +     ark_udm_write_addr(q->udm, phys_addr_prod_index);
> +     ark_udm_queue_enable(q->udm, 1);
> +
> +     /* TX MPU */
> +     phys_addr_q_base = rte_malloc_virt2iova(q->tx_meta_q);
> +     ark_mpu_configure(q->tx_mpu, phys_addr_q_base,
> +                       BB_ARK_TX_Q_FACTOR * queue_size, 1);
> +     ark_mpu_start(q->tx_mpu);
> +
> +     /* DDM */
> +     phys_addr_cons_index = queue_base +
> +             offsetof(struct ark_bbdev_queue, tx_cons_index);
> +     ark_ddm_queue_setup(q->ddm, phys_addr_cons_index);
> +     ark_ddm_queue_reset_stats(q->ddm);
> +
> +     return 0;
> +}
> +
> +
> +
> +/* Setup a queue */
> +static int
> +ark_bb_q_setup(struct rte_bbdev *bbdev, uint16_t q_id,
> +            const struct rte_bbdev_queue_conf *queue_conf) {
> +     struct ark_bbdev_queue *q;
> +     struct ark_bbdevice *ark_bb =  bbdev->data->dev_private;
> +
> +     const uint32_t queue_size = queue_conf->queue_size;
> +     const int socket_id = queue_conf->socket;
> +     const uint64_t pg_sz = sysconf(_SC_PAGESIZE);
> +     char ring_name[RTE_RING_NAMESIZE];
> +
> +     /* Configuration checks */
> +     if (!rte_is_power_of_2(queue_size)) {
> +             ARK_BBDEV_LOG(ERR,
> +                           "Configuration queue size"
> +                           " must be power of two %u",
> +                           queue_size);
> +             return -EINVAL;
> +     }
> +
> +     if (RTE_PKTMBUF_HEADROOM < ARK_RX_META_SIZE) {
> +             ARK_BBDEV_LOG(ERR,
> +                           "Error: Ark bbdev requires head room > %d bytes
> (%s)",
> +                           ARK_RX_META_SIZE, __func__);
> +             return -EINVAL;
> +     }
> +
> +     /* Allocate the queue data structure. */
> +     q = rte_zmalloc_socket(RTE_STR(DRIVER_NAME), sizeof(*q),
> +                     RTE_CACHE_LINE_SIZE, queue_conf->socket);
> +     if (q == NULL) {
> +             ARK_BBDEV_LOG(ERR, "Failed to allocate queue memory");
> +             return -ENOMEM;
> +     }
> +     bbdev->data->queues[q_id].queue_private = q;
> +     q->ark_bbdev = ark_bb;
> +
> +     /* RING */
> +     snprintf(ring_name, RTE_RING_NAMESIZE, RTE_STR(DRIVER_NAME)
> "%u:%u",
> +              bbdev->data->dev_id, q_id);
> +     q->active_ops = rte_ring_create(ring_name,
> +                                     queue_size,
> +                                     queue_conf->socket,
> +                                     RING_F_SP_ENQ | RING_F_SC_DEQ);
> +     if (q->active_ops == NULL) {
> +             ARK_BBDEV_LOG(ERR, "Failed to create ring");
> +             goto free_all;
> +     }
> +
> +     q->rx_queue_mask = queue_size - 1;
> +     q->tx_queue_mask = (BB_ARK_TX_Q_FACTOR * queue_size) - 1;
> +
> +     /* Each mbuf requires 2 to 4 objects, factor by BB_ARK_TX_Q_FACTOR
> */
> +     q->tx_meta_q =
> +             rte_zmalloc_socket("Ark_bb_txqueue meta",
> +                                queue_size * BB_ARK_TX_Q_FACTOR *
> +                                sizeof(union ark_tx_meta),
> +                                pg_sz,
> +                                socket_id);
> +
> +     if (q->tx_meta_q == 0) {
> +             ARK_BBDEV_LOG(ERR, "Failed to allocate "
> +                           "queue memory in %s", __func__);
> +             goto free_all;
> +     }
> +
> +     q->ddm = RTE_PTR_ADD(ark_bb->ddm.v, q_id * ARK_DDM_QOFFSET);
> +     q->tx_mpu = RTE_PTR_ADD(ark_bb->mputx.v, q_id *
> ARK_MPU_QOFFSET);
> +
> +     q->rx_paddress_q =
> +             rte_zmalloc_socket("ark_bb_rx_paddress_q",
> +                                queue_size * sizeof(rte_iova_t),
> +                                pg_sz,
> +                                socket_id);
> +
> +     if (q->rx_paddress_q == 0) {
> +             ARK_BBDEV_LOG(ERR,
> +                           "Failed to allocate queue memory in %s",
> +                           __func__);
> +             goto free_all;
> +     }
> +     q->udm = RTE_PTR_ADD(ark_bb->udm.v, q_id * ARK_UDM_QOFFSET);
> +     q->rx_mpu = RTE_PTR_ADD(ark_bb->mpurx.v, q_id *
> ARK_MPU_QOFFSET);
> +
> +     /* Structure have been configured, set the hardware */
> +     return ark_bb_hw_q_setup(bbdev, q_id, queue_size);
> +
> +free_all:
> +     rte_free(q->tx_meta_q);
> +     rte_free(q->rx_paddress_q);
> +     rte_free(q);
> +     return -EFAULT;
> +}
> +
> +
> +/* Release queue */
> +static int
> +ark_bb_q_release(struct rte_bbdev *bbdev, uint16_t q_id) {
> +     struct ark_bbdev_queue *q = bbdev->data-
> 
> queues[q_id].queue_private;
> +
> +     ark_mpu_dump(q->rx_mpu, "rx_MPU release", q_id);
> +     ark_mpu_dump(q->tx_mpu, "tx_MPU release", q_id);
> +
> +     rte_ring_free(q->active_ops);
> +     rte_free(q->tx_meta_q);
> +     rte_free(q->rx_paddress_q);
> +     rte_free(q);
> +     bbdev->data->queues[q_id].queue_private = NULL;
> +
> +     ARK_BBDEV_LOG(DEBUG, "released device queue %u:%u",
> +                   bbdev->data->dev_id, q_id);
> +     return 0;
> +}
> +
> +static int
> +ark_bbdev_start(struct rte_bbdev *bbdev) {
> +     struct ark_bbdevice *ark_bb = bbdev->data->dev_private;
> +
> +     ARK_BBDEV_LOG(DEBUG, "Starting device %u", bbdev->data-
> 
> dev_id);
> +     if (ark_bb->started)
> +             return 0;
> +
> +     /* User start hook */
> +     if (ark_bb->user_ext.dev_start)
> +             ark_bb->user_ext.dev_start(bbdev,
> +                                        ark_bb->user_data);
> +
> +     ark_bb->started = 1;
> +
> +     if (ark_bb->start_pg)
> +             ark_pktchkr_run(ark_bb->pc);
> +
> +     if (ark_bb->start_pg) {
> +             pthread_t thread;
> +
> +             /* Delay packet generator start allow the hardware to be
> ready
> +              * This is only used for sanity checking with internal generator
> +              */
> +             if (pthread_create(&thread, NULL,
> +                                ark_pktgen_delay_start, ark_bb->pg)) {
> +                     ARK_BBDEV_LOG(ERR, "Could not create pktgen "
> +                                 "starter thread");
> +                     return -1;
> +             }
> +     }
> +
> +     return 0;
> +}
> +
> +
> +static void
> +ark_bbdev_stop(struct rte_bbdev *bbdev) {
> +     struct ark_bbdevice *ark_bb = bbdev->data->dev_private;
> +
> +     ARK_BBDEV_LOG(DEBUG, "Stopping device %u", bbdev->data-
> 
> dev_id);
> +
> +     if (!ark_bb->started)
> +             return;
> +
> +     /* Stop the packet generator */
> +     if (ark_bb->start_pg)
> +             ark_pktgen_pause(ark_bb->pg);
> +
> +     /* STOP RX Side */
> +     ark_udm_dump_stats(ark_bb->udm.v, "Post stop");
> +
> +     /* Stop the packet checker if it is running */
> +     if (ark_bb->start_pg) {
> +             ark_pktchkr_dump_stats(ark_bb->pc);
> +             ark_pktchkr_stop(ark_bb->pc);
> +     }
> +
> +     /* User stop hook */
> +     if (ark_bb->user_ext.dev_stop)
> +             ark_bb->user_ext.dev_stop(bbdev,
> +                                       ark_bb->user_data);
> +
> +}
> +
> +
> +static int
> +ark_bb_q_start(struct rte_bbdev *bbdev, uint16_t q_id) {
> +     struct ark_bbdev_queue *q = bbdev->data-
> 
> queues[q_id].queue_private;
> +     ARK_BBDEV_LOG(DEBUG, "ark_bb_q start %u:%u", bbdev->data-
> 
> dev_id, q_id);
> +     ark_ddm_queue_enable(q->ddm, 1);
> +     ark_udm_queue_enable(q->udm, 1);
> +     ark_mpu_start(q->tx_mpu);
> +     ark_mpu_start(q->rx_mpu);
> +     return 0;
> +}
> +static int
> +ark_bb_q_stop(struct rte_bbdev *bbdev, uint16_t q_id) {
> +     struct ark_bbdev_queue *q = bbdev->data-
> 
> queues[q_id].queue_private;
> +     int cnt = 0;
> +
> +     ARK_BBDEV_LOG(DEBUG, "ark_bb_q stop %u:%u", bbdev->data-
> 
> dev_id,
> +q_id);
> +
> +     while (q->tx_cons_index != q->tx_prod_index) {
> +             usleep(100);
> +             if (cnt++ > 10000) {
> +                     fprintf(stderr, "XXXX %s(%u, %u %u) %d Failured\n",
> __func__, q_id,
> +                             q->tx_cons_index, q->tx_prod_index,
> +                             (int32_t) (q->tx_prod_index - q-
> 
> tx_cons_index));
> +                     return -1;
> +             }
> +     }
> +
> +     ark_mpu_stop(q->tx_mpu);
> +     ark_mpu_stop(q->rx_mpu);
> +     ark_udm_queue_enable(q->udm, 0);
> +     ark_ddm_queue_enable(q->ddm, 0);
> +     return 0;
> +}
> +
> +
> +
> +
> +/*
> +***************************************************************
> ********
> +** */
> +/* Common function for all enqueue and dequeue ops */ static inline
> +void ark_bb_enqueue_desc_fill(struct ark_bbdev_queue *q,
> +                      struct rte_mbuf *mbuf,
> +                      uint16_t offset, /* Extra offset */
> +                      uint8_t  flags,
> +                      uint32_t *meta,
> +                      uint8_t  meta_cnt /* 0, 1 or 2 */
> +                      )
> +{
> +     union ark_tx_meta *tx_meta;
> +     int32_t tx_idx;
> +     uint8_t m;
> +
> +     /* Header */
> +     tx_idx = q->tx_prod_index & q->tx_queue_mask;
> +     tx_meta = &q->tx_meta_q[tx_idx];
> +     tx_meta->data_len = rte_pktmbuf_data_len(mbuf) - offset;
> +     tx_meta->flags = flags;
> +     tx_meta->meta_cnt = meta_cnt;
> +     tx_meta->user1 = *meta++;
> +     q->tx_prod_index++;
> +
> +     for (m = 0; m < meta_cnt; m++) {
> +             tx_idx = q->tx_prod_index & q->tx_queue_mask;
> +             tx_meta = &q->tx_meta_q[tx_idx];
> +             tx_meta->usermeta0 = *meta++;
> +             tx_meta->usermeta1 = *meta++;
> +             q->tx_prod_index++;
> +     }
> +
> +     tx_idx = q->tx_prod_index & q->tx_queue_mask;
> +     tx_meta = &q->tx_meta_q[tx_idx];
> +     tx_meta->physaddr = rte_mbuf_data_iova(mbuf) + offset;
> +     q->tx_prod_index++;
> +}
> +
> +static inline void
> +ark_bb_enqueue_segmented_pkt(struct ark_bbdev_queue *q,
> +                          struct rte_mbuf *mbuf,
> +                          uint16_t offset,
> +                          uint32_t *meta, uint8_t meta_cnt) {
> +     struct rte_mbuf *next;
> +     uint8_t flags = ARK_DDM_SOP;
> +
> +     while (mbuf != NULL) {
> +             next = mbuf->next;
> +             flags |= (next == NULL) ? ARK_DDM_EOP : 0;
> +
> +             ark_bb_enqueue_desc_fill(q, mbuf, offset, flags,
> +                                      meta, meta_cnt);
> +
> +             flags &= ~ARK_DDM_SOP;  /* drop SOP flags */
> +             meta_cnt = 0;
> +             offset = 0;
> +
> +             mbuf = next;
> +     }
> +}
> +
> +static inline int
> +ark_bb_enqueue_common(struct ark_bbdev_queue *q,
> +                   struct rte_mbuf *m_in, struct rte_mbuf *m_out,
> +                   uint16_t offset,
> +                   uint32_t *meta, uint8_t meta_cnt) {
> +     int32_t free_queue_space;
> +     int32_t rx_idx;
> +
> +     /* TX side limit */
> +     free_queue_space = q->tx_queue_mask -
> +             (q->tx_prod_index - q->tx_free_index);
> +     if (unlikely(free_queue_space < (2 + (2 * m_in->nb_segs))))
> +             return 1;
> +
> +     /* RX side limit */
> +     free_queue_space = q->rx_queue_mask -
> +             (q->rx_seed_index - q->rx_cons_index);
> +     if (unlikely(free_queue_space < m_out->nb_segs))
> +             return 1;
> +
> +     if (unlikely(m_in->nb_segs > 1))
> +             ark_bb_enqueue_segmented_pkt(q, m_in, offset, meta,
> meta_cnt);
> +     else
> +             ark_bb_enqueue_desc_fill(q, m_in, offset,
> +                                      ARK_DDM_SOP | ARK_DDM_EOP,
> +                                      meta, meta_cnt);
> +
> +     /* We assume that the return mubf has exactly enough segments for
> +      * return data, which is 2048 bytes per segment.
> +      */
> +     do {
> +             rx_idx = q->rx_seed_index & q->rx_queue_mask;
> +             q->rx_paddress_q[rx_idx] = m_out->buf_iova;
> +             q->rx_seed_index++;
> +             m_out = m_out->next;
> +     } while (m_out);
> +
> +     return 0;
> +}
> +
> +static inline void
> +ark_bb_enqueue_finalize(struct rte_bbdev_queue_data *q_data,
> +                     struct ark_bbdev_queue *q,
> +                     void **ops,
> +                     uint16_t nb_ops, uint16_t nb)
> +{
> +     /* BBDEV global stats */
> +     /* These are not really errors, not sure why bbdev counts these. */
> +     q_data->queue_stats.enqueue_err_count += nb_ops - nb;
> +     q_data->queue_stats.enqueued_count += nb;
> +
> +     /* Notify HW that  */
> +     if (unlikely(nb == 0))
> +             return;
> +
> +     ark_mpu_set_producer(q->tx_mpu, q->tx_prod_index);
> +     ark_mpu_set_producer(q->rx_mpu, q->rx_seed_index);
> +
> +     /* Queue info for dequeue-side processing */
> +     rte_ring_enqueue_burst(q->active_ops,
> +                            (void **)ops, nb, NULL);
> +}
> +
> +static int
> +ark_bb_dequeue_segmented(struct rte_mbuf *mbuf0,
> +                      int32_t *prx_cons_index,
> +                      uint16_t pkt_len
> +                      )
> +{
> +     struct rte_mbuf *mbuf;
> +     uint16_t data_len;
> +     uint16_t remaining;
> +     uint16_t segments = 1;
> +
> +     data_len = RTE_MIN(pkt_len, RTE_MBUF_DEFAULT_DATAROOM);
> +     remaining = pkt_len - data_len;
> +
> +     mbuf = mbuf0;
> +     mbuf0->data_len = data_len;
> +     while (remaining) {
> +             segments += 1;
> +             mbuf = mbuf->next;
> +             if (unlikely(mbuf == 0)) {
> +                     ARK_BBDEV_LOG(CRIT, "Expected chained mbuf with
> "
> +                                   "at least %d segments for dequeue "
> +                                   "of packet length %d",
> +                                   segments, pkt_len);
> +                     return 1;
> +             }
> +
> +             data_len = RTE_MIN(remaining,
> +                                RTE_MBUF_DEFAULT_DATAROOM);
> +             remaining -= data_len;
> +
> +             mbuf->data_len = data_len;
> +             *prx_cons_index += 1;
> +     }
> +
> +     if (mbuf->next != 0) {
> +             ARK_BBDEV_LOG(CRIT, "Expected chained mbuf with "
> +                           "at exactly %d segments for dequeue "
> +                           "of packet length %d. Found %d "
> +                           "segments",
> +                           segments, pkt_len, mbuf0->nb_segs);
> +             return 1;
> +     }
> +     return 0;
> +}
> +
> +/*
> +***************************************************************
> ********
> +** */
> +/* LDPC Decode ops */
> +static int16_t
> +ark_bb_enqueue_ldpc_dec_one_op(struct ark_bbdev_queue *q,
> +                            struct rte_bbdev_dec_op *this_op) {
> +     struct rte_bbdev_op_ldpc_dec *ldpc_dec_op = &this_op->ldpc_dec;
> +     struct rte_mbuf *m_in = ldpc_dec_op->input.data;
> +     struct rte_mbuf *m_out = ldpc_dec_op->hard_output.data;
> +     uint16_t offset = ldpc_dec_op->input.offset;
> +     uint32_t meta[5] = {0};
> +     uint8_t meta_cnt = 0;
> +
> +     if (q->ark_bbdev->user_ext.enqueue_ldpc_dec) {
> +             if (q->ark_bbdev->user_ext.enqueue_ldpc_dec(q->ark_bbdev-
> 
> bbdev,
> +                                                         this_op,
> +                                                         meta,
> +                                                         &meta_cnt,
> +                                                         q->ark_bbdev-
> 
> user_data)) {
> +                     ARK_BBDEV_LOG(ERR, "%s failed", __func__);
> +                     return 1;
> +             }
> +     }
> +
> +     return ark_bb_enqueue_common(q, m_in, m_out, offset, meta,
> meta_cnt);
> +}
> +
> +/* Enqueue LDPC Decode -- burst */
> +static uint16_t
> +ark_bb_enqueue_ldpc_dec_ops(struct rte_bbdev_queue_data *q_data,
> +                         struct rte_bbdev_dec_op **ops, uint16_t nb_ops) {
> +     struct ark_bbdev_queue *q = q_data->queue_private;
> +     unsigned int max_enq;
> +     uint16_t nb;
> +
> +     max_enq = rte_ring_free_count(q->active_ops);
> +     max_enq = RTE_MIN(max_enq, nb_ops);
> +     for (nb = 0; nb < max_enq; nb++) {
> +             if (ark_bb_enqueue_ldpc_dec_one_op(q, ops[nb]))
> +                     break;
> +     }
> +
> +     ark_bb_enqueue_finalize(q_data, q, (void **)ops, nb_ops, nb);
> +     return nb;
> +}
> +
> +
> +/*
> +***************************************************************
> ********
> +** */
> +/* Dequeue LDPC Decode -- burst */
> +static uint16_t
> +ark_bb_dequeue_ldpc_dec_ops(struct rte_bbdev_queue_data *q_data,
> +                         struct rte_bbdev_dec_op **ops, uint16_t nb_ops) {
> +     struct ark_bbdev_queue *q = q_data->queue_private;
> +     struct rte_mbuf *mbuf;
> +     struct rte_bbdev_dec_op *this_op;
> +     struct ark_rx_meta *meta;
> +     uint32_t *usermeta;
> +
> +     uint16_t nb = 0;
> +     int32_t prod_index = q->rx_prod_index;
> +     int32_t cons_index = q->rx_cons_index;
> +
> +     q->tx_free_index = q->tx_cons_index;
> +
> +     while ((prod_index - cons_index) > 0) {
> +             if (rte_ring_dequeue(q->active_ops, (void **)&this_op)) {
> +                     ARK_BBDEV_LOG(ERR, "%s data ready but no op!",
> +                                   __func__);
> +                     q_data->queue_stats.dequeue_err_count += 1;
> +                     break;
> +             }
> +             ops[nb] = this_op;
> +
> +             mbuf = this_op->ldpc_dec.hard_output.data;
> +
> +             /* META DATA embedded in headroom */
> +             meta = RTE_PTR_ADD(mbuf->buf_addr,
> ARK_RX_META_OFFSET);
> +
> +             mbuf->pkt_len = meta->pkt_len;
> +             mbuf->data_len = meta->pkt_len;
> +
> +             if (unlikely(meta->pkt_len > ARK_RX_MAX_NOCHAIN)) {
> +                     if (ark_bb_dequeue_segmented(mbuf, &cons_index,
> +                                                  meta->pkt_len))
> +                             q_data->queue_stats.dequeue_err_count +=
> 1;
> +             } else if (mbuf->next != 0) {
> +                     ARK_BBDEV_LOG(CRIT, "Expected mbuf with "
> +                                   "at exactly 1 segments for dequeue "
> +                                   "of packet length %d. Found %d "
> +                                   "segments",
> +                                   meta->pkt_len, mbuf->nb_segs);
> +                     q_data->queue_stats.dequeue_err_count += 1;
> +             }
> +
> +             usermeta = meta->user_meta;
> +
> +             /* User's meta move from Arkville HW to bbdev OP */
> +             if (q->ark_bbdev->user_ext.dequeue_ldpc_dec) {
> +                     if (q->ark_bbdev->user_ext.dequeue_ldpc_dec(q-
> 
> ark_bbdev->bbdev,
> +                                                                 this_op,
> +                                                                 usermeta,
> +                                                                 q-
> 
> ark_bbdev->user_data)) {
> +                             ARK_BBDEV_LOG(ERR, "%s failed", __func__);
> +                             return 1;
> +                     }
> +             }
> +
> +             nb++;
> +             cons_index++;
> +             if (nb >= nb_ops)
> +                     break;
> +     }
> +
> +     q->rx_cons_index = cons_index;
> +
> +     /* BBdev stats */
> +     q_data->queue_stats.dequeued_count += nb;
> +
> +     return nb;
> +}
> +
> +/**************************************************************
> ********
> +****/
> +/* Enqueue LDPC Encode */
> +static int16_t
> +ark_bb_enqueue_ldpc_enc_one_op(struct ark_bbdev_queue *q,
> +                            struct rte_bbdev_enc_op *this_op) {
> +     struct rte_bbdev_op_ldpc_enc *ldpc_enc_op = &this_op->ldpc_enc;
> +     struct rte_mbuf *m_in = ldpc_enc_op->input.data;
> +     struct rte_mbuf *m_out = ldpc_enc_op->output.data;
> +     uint16_t offset = ldpc_enc_op->input.offset;
> +     uint32_t meta[5] = {0};
> +     uint8_t meta_cnt = 0;
> +
> +     /* User's meta move from bbdev op to Arkville HW */
> +     if (q->ark_bbdev->user_ext.enqueue_ldpc_enc) {
> +             if (q->ark_bbdev->user_ext.enqueue_ldpc_enc(q->ark_bbdev-
> 
> bbdev,
> +                                                         this_op,
> +                                                         meta,
> +                                                         &meta_cnt,
> +                                                         q->ark_bbdev-
> 
> user_data)) {
> +                     ARK_BBDEV_LOG(ERR, "%s failed", __func__);
> +                     return 1;
> +             }
> +     }
> +
> +     return ark_bb_enqueue_common(q, m_in, m_out, offset, meta,
> meta_cnt);
> +}
> +
> +/* Enqueue LDPC Encode -- burst */
> +static uint16_t
> +ark_bb_enqueue_ldpc_enc_ops(struct rte_bbdev_queue_data *q_data,
> +                         struct rte_bbdev_enc_op **ops, uint16_t nb_ops) {
> +     struct ark_bbdev_queue *q = q_data->queue_private;
> +     unsigned int max_enq;
> +     uint16_t nb;
> +
> +     max_enq = rte_ring_free_count(q->active_ops);
> +     max_enq = RTE_MIN(max_enq, nb_ops);
> +     for (nb = 0; nb < max_enq; nb++) {
> +             if (ark_bb_enqueue_ldpc_enc_one_op(q, ops[nb]))
> +                     break;
> +     }
> +
> +     ark_bb_enqueue_finalize(q_data, q, (void **)ops, nb_ops, nb);
> +     return nb;
> +}
> +
> +/* Dequeue LDPC Encode -- burst */
> +static uint16_t
> +ark_bb_dequeue_ldpc_enc_ops(struct rte_bbdev_queue_data *q_data,
> +                         struct rte_bbdev_enc_op **ops, uint16_t nb_ops) {
> +     struct ark_bbdev_queue *q = q_data->queue_private;
> +     struct rte_mbuf *mbuf;
> +     struct rte_bbdev_enc_op *this_op;
> +     struct ark_rx_meta *meta;
> +     uint32_t *usermeta;
> +
> +     uint16_t nb = 0;
> +     int32_t prod_index = q->rx_prod_index;
> +     int32_t cons_index = q->rx_cons_index;
> +
> +     q->tx_free_index = q->tx_cons_index;
> +
> +     while ((prod_index - cons_index) > 0) {
> +             if (rte_ring_dequeue(q->active_ops, (void **)&this_op)) {
> +                     ARK_BBDEV_LOG(ERR, "%s data ready but no op!",
> +                                   __func__);
> +                     q_data->queue_stats.dequeue_err_count += 1;
> +                     break;
> +             }
> +             ops[nb] = this_op;
> +
> +             mbuf = this_op->ldpc_enc.output.data;
> +
> +             /* META DATA embedded in headroom */
> +             meta = RTE_PTR_ADD(mbuf->buf_addr,
> ARK_RX_META_OFFSET);
> +
> +             mbuf->pkt_len = meta->pkt_len;
> +             mbuf->data_len = meta->pkt_len;
> +             usermeta = meta->user_meta;
> +
> +             if (unlikely(meta->pkt_len > ARK_RX_MAX_NOCHAIN)) {
> +                     if (ark_bb_dequeue_segmented(mbuf, &cons_index,
> +                                                  meta->pkt_len))
> +                             q_data->queue_stats.dequeue_err_count +=
> 1;
> +             } else if (mbuf->next != 0) {
> +                     ARK_BBDEV_LOG(CRIT, "Expected mbuf with "
> +                                   "at exactly 1 segments for dequeue "
> +                                   "of packet length %d. Found %d "
> +                                   "segments",
> +                                   meta->pkt_len, mbuf->nb_segs);
> +                     q_data->queue_stats.dequeue_err_count += 1;
> +             }
> +
> +             /* User's meta move from Arkville HW to bbdev OP */
> +             if (q->ark_bbdev->user_ext.dequeue_ldpc_enc) {
> +                     if (q->ark_bbdev->user_ext.dequeue_ldpc_enc(q-
> 
> ark_bbdev->bbdev,
> +                                                                 this_op,
> +                                                                 usermeta,
> +                                                                 q-
> 
> ark_bbdev->user_data)) {
> +                             ARK_BBDEV_LOG(ERR, "%s failed", __func__);
> +                             return 1;
> +                     }
> +             }
> +
> +             nb++;
> +             cons_index++;
> +             if (nb >= nb_ops)
> +                     break;
> +     }
> +
> +     q->rx_cons_index = cons_index;
> +
> +     /* BBdev stats */
> +     q_data->queue_stats.dequeued_count += nb;
> +
> +     return nb;
> +}
> +
> +
> +/**************************************************************
> ********
> +****/
> +/*
> + *Initial device hardware configuration when device is opened
> + * setup the DDM, and UDM; called once per PCIE device  */ static int
> +ark_bb_config_device(struct ark_bbdevice *ark_bb) {
> +     uint16_t num_q, i;
> +     struct ark_mpu_t *mpu;
> +
> +     /*
> +      * Make sure that the packet director, generator and checker are in a
> +      * known state
> +      */
> +     ark_bb->start_pg = 0;
> +     ark_bb->pg = ark_pktgen_init(ark_bb->pktgen.v, 0, 1);
> +     if (ark_bb->pg == NULL)
> +             return -1;
> +     ark_pktgen_reset(ark_bb->pg);
> +     ark_bb->pc = ark_pktchkr_init(ark_bb->pktchkr.v, 0, 1);
> +     if (ark_bb->pc == NULL)
> +             return -1;
> +     ark_pktchkr_stop(ark_bb->pc);
> +     ark_bb->pd = ark_pktdir_init(ark_bb->pktdir.v);
> +     if (ark_bb->pd == NULL)
> +             return -1;
> +
> +     /* Verify HW */
> +     if (ark_udm_verify(ark_bb->udm.v))
> +             return -1;
> +     if (ark_ddm_verify(ark_bb->ddm.v))
> +             return -1;
> +
> +     /* MPU reset */
> +     mpu = ark_bb->mpurx.v;
> +     num_q = ark_api_num_queues(mpu);
> +     ark_bb->max_nb_queues = num_q;
> +
> +     for (i = 0; i < num_q; i++) {
> +             ark_mpu_reset(mpu);
> +             mpu = RTE_PTR_ADD(mpu, ARK_MPU_QOFFSET);
> +     }
> +
> +     ark_udm_configure(ark_bb->udm.v,
> +                       RTE_PKTMBUF_HEADROOM,
> +                       RTE_MBUF_DEFAULT_DATAROOM);
> +
> +     mpu = ark_bb->mputx.v;
> +     num_q = ark_api_num_queues(mpu);
> +     for (i = 0; i < num_q; i++) {
> +             ark_mpu_reset(mpu);
> +             mpu = RTE_PTR_ADD(mpu, ARK_MPU_QOFFSET);
> +     }
> +
> +     ark_rqp_stats_reset(ark_bb->rqpacing);
> +
> +     ARK_BBDEV_LOG(INFO, "packet director set to 0x%x", ark_bb-
> 
> pkt_dir_v);
> +     ark_pktdir_setup(ark_bb->pd, ark_bb->pkt_dir_v);
> +
> +     if (ark_bb->pkt_gen_args[0]) {
> +             ARK_BBDEV_LOG(INFO, "Setting up the packet generator");
> +             ark_pktgen_parse(ark_bb->pkt_gen_args);
> +             ark_pktgen_reset(ark_bb->pg);
> +             ark_pktgen_setup(ark_bb->pg);
> +             ark_bb->start_pg = 1;
> +     }
> +
> +     return 0;
> +}
> +
> +static int
> +ark_bbdev_init(struct rte_bbdev *bbdev, struct rte_pci_driver *pci_drv)
> +{
> +     struct ark_bbdevice *ark_bb = bbdev->data->dev_private;
> +     struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(bbdev->device);
> +     bool rqpacing = false;
> +     int p;
> +     ark_bb->bbdev = bbdev;
> +
> +     RTE_SET_USED(pci_drv);
> +
> +     ark_bb->bar0 = (uint8_t *)pci_dev->mem_resource[0].addr;
> +     ark_bb->a_bar = (uint8_t *)pci_dev->mem_resource[2].addr;
> +
> +     ark_bb->sysctrl.v  = (void *)&ark_bb->bar0[ARK_SYSCTRL_BASE];
> +     ark_bb->mpurx.v  = (void *)&ark_bb->bar0[ARK_MPU_RX_BASE];
> +     ark_bb->udm.v  = (void *)&ark_bb->bar0[ARK_UDM_BASE];
> +     ark_bb->mputx.v  = (void *)&ark_bb->bar0[ARK_MPU_TX_BASE];
> +     ark_bb->ddm.v  = (void *)&ark_bb->bar0[ARK_DDM_BASE];
> +     ark_bb->pktdir.v  = (void *)&ark_bb->bar0[ARK_PKTDIR_BASE];
> +     ark_bb->pktgen.v  = (void *)&ark_bb->bar0[ARK_PKTGEN_BASE];
> +     ark_bb->pktchkr.v  = (void *)&ark_bb->bar0[ARK_PKTCHKR_BASE];
> +
> +     p = 0;
> +     while (ark_device_caps[p].device_id != 0) {
> +             if (pci_dev->id.device_id == ark_device_caps[p].device_id) {
> +                     rqpacing = ark_device_caps[p].caps.rqpacing;
> +                     break;
> +             }
> +             p++;
> +     }
> +
> +     if (rqpacing)
> +             ark_bb->rqpacing =
> +                     (struct ark_rqpace_t *)(ark_bb->bar0 +
> ARK_RCPACING_BASE);
> +     else
> +             ark_bb->rqpacing = NULL;
> +
> +     /* Check to see if there is an extension that we need to load */
> +     if (check_for_ext(ark_bb))
> +             return -1;
> +
> +     ark_bb->started = 0;
> +
> +     ARK_BBDEV_LOG(INFO, "Sys Ctrl Const = 0x%x  HW Commit_ID: %08x",
> +                   ark_bb->sysctrl.t32[4],
> +                   rte_be_to_cpu_32(ark_bb->sysctrl.t32[0x20 / 4]));
> +     ARK_BBDEV_LOG(INFO, "Arkville HW Commit_ID: %08x",
> +                 rte_be_to_cpu_32(ark_bb->sysctrl.t32[0x20 / 4]));
> +
> +     /* If HW sanity test fails, return an error */
> +     if (ark_bb->sysctrl.t32[4] != 0xcafef00d) {
> +             ARK_BBDEV_LOG(ERR,
> +                           "HW Sanity test has failed, expected constant"
> +                           " 0x%x, read 0x%x (%s)",
> +                           0xcafef00d,
> +                           ark_bb->sysctrl.t32[4], __func__);
> +             return -1;
> +     }
> +
> +     return ark_bb_config_device(ark_bb);
> +}
> +
> +static int
> +ark_bbdev_uninit(struct rte_bbdev *bbdev) {
> +     struct ark_bbdevice *ark_bb = bbdev->data->dev_private;
> +
> +     if (rte_eal_process_type() != RTE_PROC_PRIMARY)
> +             return 0;
> +
> +     ark_pktgen_uninit(ark_bb->pg);
> +     ark_pktchkr_uninit(ark_bb->pc);
> +
> +     return 0;
> +}
> +
> +static int
> +ark_bbdev_probe(struct rte_pci_driver *pci_drv,
> +             struct rte_pci_device *pci_dev)
> +{
> +     struct rte_bbdev *bbdev = NULL;
> +     char dev_name[RTE_BBDEV_NAME_MAX_LEN];
> +     struct ark_bbdevice *ark_bb;
> +
> +     if (pci_dev == NULL)
> +             return -EINVAL;
> +
> +     rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));
> +
> +     /* Allocate memory to be used privately by drivers */
> +     bbdev = rte_bbdev_allocate(pci_dev->device.name);
> +     if (bbdev == NULL)
> +             return -ENODEV;
> +
> +     /* allocate device private memory */
> +     bbdev->data->dev_private = rte_zmalloc_socket(dev_name,
> +                     sizeof(struct ark_bbdevice),
> +                     RTE_CACHE_LINE_SIZE,
> +                     pci_dev->device.numa_node);
> +
> +     if (bbdev->data->dev_private == NULL) {
> +             ARK_BBDEV_LOG(CRIT,
> +                             "Allocate of %zu bytes for device \"%s\"
> failed",
> +                             sizeof(struct ark_bbdevice), dev_name);
> +                             rte_bbdev_release(bbdev);
> +                     return -ENOMEM;
> +     }
> +     ark_bb = bbdev->data->dev_private;
> +     /* Initialize ark_bb */
> +     ark_bb->pkt_dir_v = 0x00110110;
> 
> There a few magic number that you may to define separately
> 
> 
> +
> +     /* Fill HW specific part of device structure */
> +     bbdev->device = &pci_dev->device;
> +     bbdev->intr_handle = NULL;
> +     bbdev->data->socket_id = pci_dev->device.numa_node;
> +     bbdev->dev_ops = &ark_bbdev_pmd_ops;
> +     if (pci_dev->device.devargs)
> +             parse_ark_bbdev_params(pci_dev->device.devargs->args,
> ark_bb);
> +
> +
> +     /* Device specific initialization */
> +     if (ark_bbdev_init(bbdev, pci_drv))
> +             return -EIO;
> +     if (ark_bbdev_start(bbdev))
> +             return -EIO;
> +
> +     /* Core operations LDPC encode amd decode */
> +     bbdev->enqueue_ldpc_enc_ops = ark_bb_enqueue_ldpc_enc_ops;
> +     bbdev->dequeue_ldpc_enc_ops = ark_bb_dequeue_ldpc_enc_ops;
> +     bbdev->enqueue_ldpc_dec_ops = ark_bb_enqueue_ldpc_dec_ops;
> +     bbdev->dequeue_ldpc_dec_ops = ark_bb_dequeue_ldpc_dec_ops;
> +
> +     ARK_BBDEV_LOG(DEBUG, "bbdev id = %u [%s]",
> +                   bbdev->data->dev_id, dev_name);
> +
> +     return 0;
> +}
> +
> +/* Uninitialize device */
> +static int
> +ark_bbdev_remove(struct rte_pci_device *pci_dev) {
> +     struct rte_bbdev *bbdev;
> +     int ret;
> +
> +     if (pci_dev == NULL)
> +             return -EINVAL;
> +
> +     /* Find device */
> +     bbdev = rte_bbdev_get_named_dev(pci_dev->device.name);
> +     if (bbdev == NULL) {
> +             ARK_BBDEV_LOG(CRIT,
> +                             "Couldn't find HW dev \"%s\" to Uninitialize
> it",
> +                             pci_dev->device.name);
> +             return -ENODEV;
> +     }
> +
> +     /* Arkville device close */
> +     ark_bbdev_uninit(bbdev);
> +     rte_free(bbdev->data->dev_private);
> +
> +     /* Close device */
> +     ret = rte_bbdev_close(bbdev->data->dev_id);
> +     if (ret < 0)
> +             ARK_BBDEV_LOG(ERR,
> +                             "Device %i failed to close during remove: %i",
> +                             bbdev->data->dev_id, ret);
> +
> +     return rte_bbdev_release(bbdev);
> +}
> +
> +/* Operation for the PMD */
> +static const struct rte_bbdev_ops ark_bbdev_pmd_ops = {
> +     .info_get = ark_bbdev_info_get,
> 
> This is the one mentioned above. This is actually defined in your future 
> commit.
> You could start with info_get, then queue, then processing for instance. 
> 
> 
> +     .start = ark_bbdev_start,
> +     .stop = ark_bbdev_stop,
> +     .queue_setup = ark_bb_q_setup,
> +     .queue_release = ark_bb_q_release,
> +     .queue_start = ark_bb_q_start,
> +     .queue_stop = ark_bb_q_stop,
> +};
> +
> +static struct rte_pci_driver ark_bbdev_pmd_drv = {
> +     .probe = ark_bbdev_probe,
> +     .remove = ark_bbdev_remove,
> +     .id_table = pci_id_ark,
> +     .drv_flags = RTE_PCI_DRV_NEED_MAPPING
> +};
> +
> +RTE_PMD_REGISTER_PCI(DRIVER_NAME, ark_bbdev_pmd_drv);
> +RTE_PMD_REGISTER_PCI_TABLE(DRIVER_NAME, pci_id_ark);
> +RTE_PMD_REGISTER_PARAM_STRING(DRIVER_NAME,
> +                           ARK_BBDEV_PKTGEN_ARG "=<filename> "
> +                           ARK_BBDEV_PKTCHKR_ARG "=<filename> "
> +                           ARK_BBDEV_PKTDIR_ARG "=<bitmap>"
> +                           );
> diff --git a/drivers/baseband/ark/ark_bbext.h
> b/drivers/baseband/ark/ark_bbext.h
> new file mode 100644
> index 0000000000..2e9cc4ccf3
> --- /dev/null
> +++ b/drivers/baseband/ark/ark_bbext.h
> @@ -0,0 +1,163 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright (c) 2015-2018 Atomic Rules LLC  */
> +
> +#ifndef _ARK_BBEXT_H_
> +#define _ARK_BBEXT_H_
> +
> +#include <rte_bbdev.h>
> +#include <rte_bbdev_pmd.h>
> +
> +/* The following section lists function prototypes for Arkville's
> + * baseband dynamic PMD extension. User's who create an extension
> + * must include this file and define the necessary and desired
> + * functions. Only 1 function is required for an extension,
> + * rte_pmd_ark_bbdev_init(); all other functions prototypes in this
> + * section are optional.
> + * See documentation for compiling and use of extensions.
> + */
> +
> +/**
> + * Extension prototype, required implementation if extensions are used.
> + * Called during device probe to initialize the user structure
> + * passed to other extension functions.  This is called once for each
> + * port of the device.
> + *
> + * @param dev
> + *   current device.
> + * @param a_bar
> + *   access to PCIe device bar (application bar) and hence access to
> + *   user's portion of FPGA.
> + * @return user_data
> + *   which will be passed to other extension functions.
> + */
> +void *rte_pmd_ark_bbdev_init(struct rte_bbdev *dev, void *a_bar);
> +
> +/**
> + * Extension prototype, optional implementation.
> + * Called during device uninit.
> + *
> + * @param dev
> + *   current device.
> + * @param user_data
> + *   user argument from dev_init() call.
> + */
> +int rte_pmd_ark_bbdev_uninit(struct rte_bbdev *dev, void *user_data);
> +
> +/**
> + * Extension prototype, optional implementation.
> + * Called during rte_bbdev_start().
> + *
> + * @param dev
> + *   current device.
> + * @param user_data
> + *   user argument from dev_init() call.
> + * @return (0) if successful.
> + */
> +int rte_pmd_ark_bbdev_start(struct rte_bbdev *dev, void *user_data);
> +
> +/**
> + * Extension prototype, optional implementation.
> + * Called during  rte_bbdev_stop().
> + *
> + * @param dev
> + *   current device.
> + * @param user_data
> + *   user argument from dev_init() call.
> + * @return (0) if successful.
> + */
> +int rte_pmd_ark_bbdev_stop(struct rte_bbdev *dev, void *user_data);
> +
> +/**
> + * Extension prototype, optional implementation.
> + * Called during rte_bbdev_dequeue_ldpc_dec_ops
> + *
> + * @param dev
> + *   current device.
> + * @param user_data
> + *   user argument from dev_init() call.
> + * @return (0) if successful.
> + */
> +int rte_pmd_ark_bbdev_dequeue_ldpc_dec(struct rte_bbdev *dev,
> +                               struct rte_bbdev_dec_op *this_op,
> +                               uint32_t *usermeta,
> +                               void *user_data);
> +
> +/**
> + * Extension prototype, optional implementation.
> + * Called during rte_bbdev_dequeue_ldpc_enc_ops
> + *
> + * @param dev
> + *   current device.
> + * @param user_data
> + *   user argument from dev_init() call.
> + * @return (0) if successful.
> + */
> +int rte_pmd_ark_bbdev_dequeue_ldpc_enc(struct rte_bbdev *dev,
> +                               struct rte_bbdev_enc_op *this_op,
> +                               uint32_t *usermeta,
> +                               void *user_data);
> +
> +/**
> + * Extension prototype, optional implementation.
> + * Called during rte_bbdev_enqueue_ldpc_dec_ops
> + *
> + * @param dev
> + *   current device.
> + * @param user_data
> + *   user argument from dev_init() call.
> + * @return (0) if successful.
> + */
> +int rte_pmd_ark_bbdev_enqueue_ldpc_dec(struct rte_bbdev *dev,
> +                                     struct rte_bbdev_dec_op *this_op,
> +                                     uint32_t *usermeta,
> +                                     uint8_t *meta_cnt,
> +                                     void *user_data);
> +
> +/**
> + * Extension prototype, optional implementation.
> + * Called during rte_bbdev_enqueue_ldpc_enc_ops
> + *
> + * @param dev
> + *   current device.
> + * @param user_data
> + *   user argument from dev_init() call.
> + * @return (0) if successful.
> + */
> +int rte_pmd_ark_bbdev_enqueue_ldpc_enc(struct rte_bbdev *dev,
> +                                     struct rte_bbdev_enc_op *this_op,
> +                                     uint32_t *usermeta,
> +                                     uint8_t *meta_cnt,
> +                                     void *user_data);
> +
> +
> +struct arkbb_user_ext {
> +     void *(*dev_init)(struct rte_bbdev *dev, void *abar);
> +     int (*dev_uninit)(struct rte_bbdev *dev, void *udata);
> +     int (*dev_start)(struct rte_bbdev *dev, void *udata);
> +     int (*dev_stop)(struct rte_bbdev *dev, void *udata);
> +     int (*dequeue_ldpc_dec)(struct rte_bbdev *dev,
> +                              struct rte_bbdev_dec_op *op,
> +                              uint32_t *v,
> +                              void *udata);
> +     int (*dequeue_ldpc_enc)(struct rte_bbdev *dev,
> +                              struct rte_bbdev_enc_op *op,
> +                              uint32_t *v,
> +                              void *udata);
> +     int (*enqueue_ldpc_dec)(struct rte_bbdev *dev,
> +                              struct rte_bbdev_dec_op *op,
> +                              uint32_t *v,
> +                              uint8_t *v1,
> +                              void *udata);
> +     int (*enqueue_ldpc_enc)(struct rte_bbdev *dev,
> +                              struct rte_bbdev_enc_op *op,
> +                              uint32_t *v,
> +                              uint8_t *v1,
> +                              void *udata);
> +};
> +
> +
> +
> +
> +
> +#endif
> --
> 2.25.1
>

Reply via email to