get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 68718,
    "url": "http://patches.dpdk.org/api/patches/68718/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1587098436-7493-5-git-send-email-nicolas.chautru@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1587098436-7493-5-git-send-email-nicolas.chautru@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1587098436-7493-5-git-send-email-nicolas.chautru@intel.com",
    "date": "2020-04-17T04:40:29",
    "name": "[v3,04/11] baseband/fpga_5gnr_fec: add queue configuration",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "75801244581e98cd815a5ee70efb6b732091423f",
    "submitter": {
        "id": 1314,
        "url": "http://patches.dpdk.org/api/people/1314/?format=api",
        "name": "Chautru, Nicolas",
        "email": "nicolas.chautru@intel.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/1587098436-7493-5-git-send-email-nicolas.chautru@intel.com/mbox/",
    "series": [
        {
            "id": 9446,
            "url": "http://patches.dpdk.org/api/series/9446/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=9446",
            "date": "2020-04-17T04:40:25",
            "name": "drivers/baseband: PMD for FPGA 5GNR FEC",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/9446/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/68718/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/68718/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 dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 31A13A0588;\n\tFri, 17 Apr 2020 06:42:15 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 815651DE4B;\n\tFri, 17 Apr 2020 06:41:44 +0200 (CEST)",
            "from mga17.intel.com (mga17.intel.com [192.55.52.151])\n by dpdk.org (Postfix) with ESMTP id B12AE1DE26\n for <dev@dpdk.org>; Fri, 17 Apr 2020 06:41:38 +0200 (CEST)",
            "from orsmga002.jf.intel.com ([10.7.209.21])\n by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 16 Apr 2020 21:41:38 -0700",
            "from skx-5gnr-sc12-4.sc.intel.com ([172.25.69.210])\n by orsmga002.jf.intel.com with ESMTP; 16 Apr 2020 21:41:37 -0700"
        ],
        "IronPort-SDR": [
            "\n 0xv9Eg0JiGbot2kHOGlanakN2jlXrXP7x4TQ9kPeJ/dPiurgRmDbuY6BfvfozvB+v3PtVzt3L4\n hxgFnq1Xg2+A==",
            "\n S6tjv5jLWf0pp5p+JCPj/hwP7iwkW6ny2B2Y7m0LcuF4DIpiK+Sq0+HvuAFXjfjIbPzIFFfQdP\n y4nbZMHWPNbQ=="
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.72,393,1580803200\"; d=\"scan'208\";a=\"272304049\"",
        "From": "Nicolas Chautru <nicolas.chautru@intel.com>",
        "To": "dev@dpdk.org,\n\takhil.goyal@nxp.com",
        "Cc": "bruce.richardson@intel.com,\n\tNicolas Chautru <nicolas.chautru@intel.com>",
        "Date": "Thu, 16 Apr 2020 21:40:29 -0700",
        "Message-Id": "<1587098436-7493-5-git-send-email-nicolas.chautru@intel.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1587098436-7493-1-git-send-email-nicolas.chautru@intel.com>",
        "References": "<1587098436-7493-1-git-send-email-nicolas.chautru@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v3 04/11] baseband/fpga_5gnr_fec: add queue\n\tconfiguration",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Adding function to create and configure queues for\nthe device. Still no capability.\n\nSigned-off-by: Nicolas Chautru <nicolas.chautru@intel.com>\n---\n drivers/baseband/fpga_5gnr_fec/fpga_5gnr_fec.h     | 110 +++++++\n drivers/baseband/fpga_5gnr_fec/rte_fpga_5gnr_fec.c | 365 ++++++++++++++++++++-\n 2 files changed, 474 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/drivers/baseband/fpga_5gnr_fec/fpga_5gnr_fec.h b/drivers/baseband/fpga_5gnr_fec/fpga_5gnr_fec.h\nindex 167d440..acfa3ad 100644\n--- a/drivers/baseband/fpga_5gnr_fec/fpga_5gnr_fec.h\n+++ b/drivers/baseband/fpga_5gnr_fec/fpga_5gnr_fec.h\n@@ -223,10 +223,120 @@ struct __attribute__((__packed__)) fpga_ring_ctrl_reg {\n struct fpga_5gnr_fec_device {\n \t/** Base address of MMIO registers (BAR0) */\n \tvoid *mmio_base;\n+\t/** Base address of memory for sw rings */\n+\tvoid *sw_rings;\n+\t/** Physical address of sw_rings */\n+\trte_iova_t sw_rings_phys;\n+\t/** Number of bytes available for each queue in device. */\n+\tuint32_t sw_ring_size;\n+\t/** Max number of entries available for each queue in device */\n+\tuint32_t sw_ring_max_depth;\n+\t/** Base address of response tail pointer buffer */\n+\tuint32_t *tail_ptrs;\n+\t/** Physical address of tail pointers */\n+\trte_iova_t tail_ptr_phys;\n+\t/** Queues flush completion flag */\n+\tuint64_t *flush_queue_status;\n+\t/* Bitmap capturing which Queues are bound to the PF/VF */\n+\tuint64_t q_bound_bit_map;\n+\t/* Bitmap capturing which Queues have already been assigned */\n+\tuint64_t q_assigned_bit_map;\n \t/** True if this is a PF FPGA FEC device */\n \tbool pf_device;\n };\n \n+/* Structure associated with each queue. */\n+struct __rte_cache_aligned fpga_queue {\n+\tstruct fpga_ring_ctrl_reg ring_ctrl_reg;  /* Ring Control Register */\n+\tunion fpga_dma_desc *ring_addr;  /* Virtual address of software ring */\n+\tuint64_t *ring_head_addr;  /* Virtual address of completion_head */\n+\tuint64_t shadow_completion_head; /* Shadow completion head value */\n+\tuint16_t head_free_desc;  /* Ring head */\n+\tuint16_t tail;  /* Ring tail */\n+\t/* Mask used to wrap enqueued descriptors on the sw ring */\n+\tuint32_t sw_ring_wrap_mask;\n+\tuint32_t irq_enable;  /* Enable ops dequeue interrupts if set to 1 */\n+\tuint8_t q_idx;  /* Queue index */\n+\tstruct fpga_5gnr_fec_device *d;\n+\t/* MMIO register of shadow_tail used to enqueue descriptors */\n+\tvoid *shadow_tail_addr;\n+};\n+\n+/* Write to 16 bit MMIO register address */\n+static inline void\n+mmio_write_16(void *addr, uint16_t value)\n+{\n+\t*((volatile uint16_t *)(addr)) = rte_cpu_to_le_16(value);\n+}\n+\n+/* Write to 32 bit MMIO register address */\n+static inline void\n+mmio_write_32(void *addr, uint32_t value)\n+{\n+\t*((volatile uint32_t *)(addr)) = rte_cpu_to_le_32(value);\n+}\n+\n+/* Write to 64 bit MMIO register address */\n+static inline void\n+mmio_write_64(void *addr, uint64_t value)\n+{\n+\t*((volatile uint64_t *)(addr)) = rte_cpu_to_le_64(value);\n+}\n+\n+/* Write a 8 bit register of a FPGA 5GNR FEC device */\n+static inline void\n+fpga_reg_write_8(void *mmio_base, uint32_t offset, uint8_t payload)\n+{\n+\tvoid *reg_addr = RTE_PTR_ADD(mmio_base, offset);\n+\t*((volatile uint8_t *)(reg_addr)) = payload;\n+}\n+\n+/* Write a 16 bit register of a FPGA 5GNR FEC device */\n+static inline void\n+fpga_reg_write_16(void *mmio_base, uint32_t offset, uint16_t payload)\n+{\n+\tvoid *reg_addr = RTE_PTR_ADD(mmio_base, offset);\n+\tmmio_write_16(reg_addr, payload);\n+}\n+\n+/* Write a 32 bit register of a FPGA 5GNR FEC device */\n+static inline void\n+fpga_reg_write_32(void *mmio_base, uint32_t offset, uint32_t payload)\n+{\n+\tvoid *reg_addr = RTE_PTR_ADD(mmio_base, offset);\n+\tmmio_write_32(reg_addr, payload);\n+}\n+\n+/* Write a 64 bit register of a FPGA 5GNR FEC device */\n+static inline void\n+fpga_reg_write_64(void *mmio_base, uint32_t offset, uint64_t payload)\n+{\n+\tvoid *reg_addr = RTE_PTR_ADD(mmio_base, offset);\n+\tmmio_write_64(reg_addr, payload);\n+}\n+\n+/* Write a ring control register of a FPGA 5GNR FEC device */\n+static inline void\n+fpga_ring_reg_write(void *mmio_base, uint32_t offset,\n+\t\tstruct fpga_ring_ctrl_reg payload)\n+{\n+\tfpga_reg_write_64(mmio_base, offset, payload.ring_base_addr);\n+\tfpga_reg_write_64(mmio_base, offset + FPGA_5GNR_FEC_RING_HEAD_ADDR,\n+\t\t\tpayload.ring_head_addr);\n+\tfpga_reg_write_16(mmio_base, offset + FPGA_5GNR_FEC_RING_SIZE,\n+\t\t\tpayload.ring_size);\n+\tfpga_reg_write_16(mmio_base, offset + FPGA_5GNR_FEC_RING_HEAD_POINT,\n+\t\t\tpayload.head_point);\n+\tfpga_reg_write_8(mmio_base, offset + FPGA_5GNR_FEC_RING_FLUSH_QUEUE_EN,\n+\t\t\tpayload.flush_queue_en);\n+\tfpga_reg_write_16(mmio_base, offset + FPGA_5GNR_FEC_RING_SHADOW_TAIL,\n+\t\t\tpayload.shadow_tail);\n+\tfpga_reg_write_8(mmio_base, offset + FPGA_5GNR_FEC_RING_MISC,\n+\t\t\tpayload.misc);\n+\tfpga_reg_write_8(mmio_base, offset + FPGA_5GNR_FEC_RING_ENABLE,\n+\t\t\tpayload.enable);\n+}\n+\n /* Read a register of FPGA 5GNR FEC device */\n static inline uint32_t\n fpga_reg_read_32(void *mmio_base, uint32_t offset)\ndiff --git a/drivers/baseband/fpga_5gnr_fec/rte_fpga_5gnr_fec.c b/drivers/baseband/fpga_5gnr_fec/rte_fpga_5gnr_fec.c\nindex b3f2d0e..ec74860 100644\n--- a/drivers/baseband/fpga_5gnr_fec/rte_fpga_5gnr_fec.c\n+++ b/drivers/baseband/fpga_5gnr_fec/rte_fpga_5gnr_fec.c\n@@ -23,8 +23,113 @@\n static int fpga_5gnr_fec_logtype;\n \n static int\n-fpga_dev_close(struct rte_bbdev *dev __rte_unused)\n+fpga_setup_queues(struct rte_bbdev *dev, uint16_t num_queues, int socket_id)\n {\n+\t/* Number of queues bound to a PF/VF */\n+\tuint32_t hw_q_num = 0;\n+\tuint32_t ring_size, payload, address, q_id, offset;\n+\trte_iova_t phys_addr;\n+\tstruct fpga_ring_ctrl_reg ring_reg;\n+\tstruct fpga_5gnr_fec_device *fpga_dev = dev->data->dev_private;\n+\n+\taddress = FPGA_5GNR_FEC_QUEUE_PF_VF_MAP_DONE;\n+\tif (!(fpga_reg_read_32(fpga_dev->mmio_base, address) & 0x1)) {\n+\t\trte_bbdev_log(ERR,\n+\t\t\t\t\"Queue-PF/VF mapping is not set! Was PF configured for device (%s) ?\",\n+\t\t\t\tdev->data->name);\n+\t\treturn -EPERM;\n+\t}\n+\n+\t/* Clear queue registers structure */\n+\tmemset(&ring_reg, 0, sizeof(struct fpga_ring_ctrl_reg));\n+\n+\t/* Scan queue map.\n+\t * If a queue is valid and mapped to a calling PF/VF the read value is\n+\t * replaced with a queue ID and if it's not then\n+\t * FPGA_INVALID_HW_QUEUE_ID is returned.\n+\t */\n+\tfor (q_id = 0; q_id < FPGA_TOTAL_NUM_QUEUES; ++q_id) {\n+\t\tuint32_t hw_q_id = fpga_reg_read_32(fpga_dev->mmio_base,\n+\t\t\t\tFPGA_5GNR_FEC_QUEUE_MAP + (q_id << 2));\n+\n+\t\trte_bbdev_log_debug(\"%s: queue ID: %u, registry queue ID: %u\",\n+\t\t\t\tdev->device->name, q_id, hw_q_id);\n+\n+\t\tif (hw_q_id != FPGA_INVALID_HW_QUEUE_ID) {\n+\t\t\tfpga_dev->q_bound_bit_map |= (1ULL << q_id);\n+\t\t\t/* Clear queue register of found queue */\n+\t\t\toffset = FPGA_5GNR_FEC_RING_CTRL_REGS +\n+\t\t\t\t(sizeof(struct fpga_ring_ctrl_reg) * q_id);\n+\t\t\tfpga_ring_reg_write(fpga_dev->mmio_base,\n+\t\t\t\t\toffset, ring_reg);\n+\t\t\t++hw_q_num;\n+\t\t}\n+\t}\n+\tif (hw_q_num == 0) {\n+\t\trte_bbdev_log(ERR,\n+\t\t\t\"No HW queues assigned to this device. Probably this is a VF configured for PF mode. Check device configuration!\");\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tif (num_queues > hw_q_num) {\n+\t\trte_bbdev_log(ERR,\n+\t\t\t\"Not enough queues for device %s! Requested: %u, available: %u\",\n+\t\t\tdev->device->name, num_queues, hw_q_num);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tring_size = FPGA_RING_MAX_SIZE * sizeof(struct fpga_dma_dec_desc);\n+\n+\t/* Enforce 32 byte alignment */\n+\tRTE_BUILD_BUG_ON((RTE_CACHE_LINE_SIZE % 32) != 0);\n+\n+\t/* Allocate memory for SW descriptor rings */\n+\tfpga_dev->sw_rings = rte_zmalloc_socket(dev->device->driver->name,\n+\t\t\tnum_queues * ring_size, RTE_CACHE_LINE_SIZE,\n+\t\t\tsocket_id);\n+\tif (fpga_dev->sw_rings == NULL) {\n+\t\trte_bbdev_log(ERR,\n+\t\t\t\t\"Failed to allocate memory for %s:%u sw_rings\",\n+\t\t\t\tdev->device->driver->name, dev->data->dev_id);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tfpga_dev->sw_rings_phys = rte_malloc_virt2iova(fpga_dev->sw_rings);\n+\tfpga_dev->sw_ring_size = ring_size;\n+\tfpga_dev->sw_ring_max_depth = FPGA_RING_MAX_SIZE;\n+\n+\t/* Allocate memory for ring flush status */\n+\tfpga_dev->flush_queue_status = rte_zmalloc_socket(NULL,\n+\t\t\tsizeof(uint64_t), RTE_CACHE_LINE_SIZE, socket_id);\n+\tif (fpga_dev->flush_queue_status == NULL) {\n+\t\trte_bbdev_log(ERR,\n+\t\t\t\t\"Failed to allocate memory for %s:%u flush_queue_status\",\n+\t\t\t\tdev->device->driver->name, dev->data->dev_id);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\t/* Set the flush status address registers */\n+\tphys_addr = rte_malloc_virt2iova(fpga_dev->flush_queue_status);\n+\n+\taddress = FPGA_5GNR_FEC_VFQ_FLUSH_STATUS_LW;\n+\tpayload = (uint32_t)(phys_addr);\n+\tfpga_reg_write_32(fpga_dev->mmio_base, address, payload);\n+\n+\taddress = FPGA_5GNR_FEC_VFQ_FLUSH_STATUS_HI;\n+\tpayload = (uint32_t)(phys_addr >> 32);\n+\tfpga_reg_write_32(fpga_dev->mmio_base, address, payload);\n+\n+\treturn 0;\n+}\n+\n+static int\n+fpga_dev_close(struct rte_bbdev *dev)\n+{\n+\tstruct fpga_5gnr_fec_device *fpga_dev = dev->data->dev_private;\n+\n+\trte_free(fpga_dev->sw_rings);\n+\trte_free(fpga_dev->flush_queue_status);\n+\n \treturn 0;\n }\n \n@@ -80,9 +185,267 @@\n \t}\n }\n \n+/**\n+ * Find index of queue bound to current PF/VF which is unassigned. Return -1\n+ * when there is no available queue\n+ */\n+static inline int\n+fpga_find_free_queue_idx(struct rte_bbdev *dev,\n+\t\tconst struct rte_bbdev_queue_conf *conf)\n+{\n+\tstruct fpga_5gnr_fec_device *d = dev->data->dev_private;\n+\tuint64_t q_idx;\n+\tuint8_t i = 0;\n+\tuint8_t range = FPGA_TOTAL_NUM_QUEUES >> 1;\n+\n+\tif (conf->op_type == RTE_BBDEV_OP_LDPC_ENC) {\n+\t\ti = FPGA_NUM_DL_QUEUES;\n+\t\trange = FPGA_TOTAL_NUM_QUEUES;\n+\t}\n+\n+\tfor (; i < range; ++i) {\n+\t\tq_idx = 1ULL << i;\n+\t\t/* Check if index of queue is bound to current PF/VF */\n+\t\tif (d->q_bound_bit_map & q_idx)\n+\t\t\t/* Check if found queue was not already assigned */\n+\t\t\tif (!(d->q_assigned_bit_map & q_idx)) {\n+\t\t\t\td->q_assigned_bit_map |= q_idx;\n+\t\t\t\treturn i;\n+\t\t\t}\n+\t}\n+\n+\trte_bbdev_log(INFO, \"Failed to find free queue on %s\", dev->data->name);\n+\n+\treturn -1;\n+}\n+\n+static int\n+fpga_queue_setup(struct rte_bbdev *dev, uint16_t queue_id,\n+\t\tconst struct rte_bbdev_queue_conf *conf)\n+{\n+\tuint32_t address, ring_offset;\n+\tstruct fpga_5gnr_fec_device *d = dev->data->dev_private;\n+\tstruct fpga_queue *q;\n+\tint8_t q_idx;\n+\n+\t/* Check if there is a free queue to assign */\n+\tq_idx = fpga_find_free_queue_idx(dev, conf);\n+\tif (q_idx == -1)\n+\t\treturn -1;\n+\n+\t/* Allocate the queue data structure. */\n+\tq = rte_zmalloc_socket(dev->device->driver->name, sizeof(*q),\n+\t\t\tRTE_CACHE_LINE_SIZE, conf->socket);\n+\tif (q == NULL) {\n+\t\t/* Mark queue as un-assigned */\n+\t\td->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q_idx));\n+\t\trte_bbdev_log(ERR, \"Failed to allocate queue memory\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tq->d = d;\n+\tq->q_idx = q_idx;\n+\n+\t/* Set ring_base_addr */\n+\tq->ring_addr = RTE_PTR_ADD(d->sw_rings, (d->sw_ring_size * queue_id));\n+\tq->ring_ctrl_reg.ring_base_addr = d->sw_rings_phys +\n+\t\t\t(d->sw_ring_size * queue_id);\n+\n+\t/* Allocate memory for Completion Head variable*/\n+\tq->ring_head_addr = rte_zmalloc_socket(dev->device->driver->name,\n+\t\t\tsizeof(uint64_t), RTE_CACHE_LINE_SIZE, conf->socket);\n+\tif (q->ring_head_addr == NULL) {\n+\t\t/* Mark queue as un-assigned */\n+\t\td->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q_idx));\n+\t\trte_free(q);\n+\t\trte_bbdev_log(ERR,\n+\t\t\t\t\"Failed to allocate memory for %s:%u completion_head\",\n+\t\t\t\tdev->device->driver->name, dev->data->dev_id);\n+\t\treturn -ENOMEM;\n+\t}\n+\t/* Set ring_head_addr */\n+\tq->ring_ctrl_reg.ring_head_addr =\n+\t\t\trte_malloc_virt2iova(q->ring_head_addr);\n+\n+\t/* Clear shadow_completion_head */\n+\tq->shadow_completion_head = 0;\n+\n+\t/* Set ring_size */\n+\tif (conf->queue_size > FPGA_RING_MAX_SIZE) {\n+\t\t/* Mark queue as un-assigned */\n+\t\td->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q_idx));\n+\t\trte_free(q->ring_head_addr);\n+\t\trte_free(q);\n+\t\trte_bbdev_log(ERR,\n+\t\t\t\t\"Size of queue is too big %d (MAX: %d ) for %s:%u\",\n+\t\t\t\tconf->queue_size, FPGA_RING_MAX_SIZE,\n+\t\t\t\tdev->device->driver->name, dev->data->dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\tq->ring_ctrl_reg.ring_size = conf->queue_size;\n+\n+\t/* Set Miscellaneous FPGA register*/\n+\t/* Max iteration number for TTI mitigation - todo */\n+\tq->ring_ctrl_reg.max_ul_dec = 0;\n+\t/* Enable max iteration number for TTI - todo */\n+\tq->ring_ctrl_reg.max_ul_dec_en = 0;\n+\n+\t/* Enable the ring */\n+\tq->ring_ctrl_reg.enable = 1;\n+\n+\t/* Set FPGA head_point and tail registers */\n+\tq->ring_ctrl_reg.head_point = q->tail = 0;\n+\n+\t/* Set FPGA shadow_tail register */\n+\tq->ring_ctrl_reg.shadow_tail = q->tail;\n+\n+\t/* Calculates the ring offset for found queue */\n+\tring_offset = FPGA_5GNR_FEC_RING_CTRL_REGS +\n+\t\t\t(sizeof(struct fpga_ring_ctrl_reg) * q_idx);\n+\n+\t/* Set FPGA Ring Control Registers */\n+\tfpga_ring_reg_write(d->mmio_base, ring_offset, q->ring_ctrl_reg);\n+\n+\t/* Store MMIO register of shadow_tail */\n+\taddress = ring_offset + FPGA_5GNR_FEC_RING_SHADOW_TAIL;\n+\tq->shadow_tail_addr = RTE_PTR_ADD(d->mmio_base, address);\n+\n+\tq->head_free_desc = q->tail;\n+\n+\t/* Set wrap mask */\n+\tq->sw_ring_wrap_mask = conf->queue_size - 1;\n+\n+\trte_bbdev_log_debug(\"Setup dev%u q%u: queue_idx=%u\",\n+\t\t\tdev->data->dev_id, queue_id, q->q_idx);\n+\n+\tdev->data->queues[queue_id].queue_private = q;\n+\n+\trte_bbdev_log_debug(\"BBDEV queue[%d] set up for FPGA queue[%d]\",\n+\t\t\tqueue_id, q_idx);\n+\n+\treturn 0;\n+}\n+\n+static int\n+fpga_queue_release(struct rte_bbdev *dev, uint16_t queue_id)\n+{\n+\tstruct fpga_5gnr_fec_device *d = dev->data->dev_private;\n+\tstruct fpga_queue *q = dev->data->queues[queue_id].queue_private;\n+\tstruct fpga_ring_ctrl_reg ring_reg;\n+\tuint32_t offset;\n+\n+\trte_bbdev_log_debug(\"FPGA Queue[%d] released\", queue_id);\n+\n+\tif (q != NULL) {\n+\t\tmemset(&ring_reg, 0, sizeof(struct fpga_ring_ctrl_reg));\n+\t\toffset = FPGA_5GNR_FEC_RING_CTRL_REGS +\n+\t\t\t(sizeof(struct fpga_ring_ctrl_reg) * q->q_idx);\n+\t\t/* Disable queue */\n+\t\tfpga_reg_write_8(d->mmio_base,\n+\t\t\t\toffset + FPGA_5GNR_FEC_RING_ENABLE, 0x00);\n+\t\t/* Clear queue registers */\n+\t\tfpga_ring_reg_write(d->mmio_base, offset, ring_reg);\n+\n+\t\t/* Mark the Queue as un-assigned */\n+\t\td->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q->q_idx));\n+\t\trte_free(q->ring_head_addr);\n+\t\trte_free(q);\n+\t\tdev->data->queues[queue_id].queue_private = NULL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/* Function starts a device queue. */\n+static int\n+fpga_queue_start(struct rte_bbdev *dev, uint16_t queue_id)\n+{\n+\tstruct fpga_5gnr_fec_device *d = dev->data->dev_private;\n+#ifdef RTE_LIBRTE_BBDEV_DEBUG\n+\tif (d == NULL) {\n+\t\trte_bbdev_log(ERR, \"Invalid device pointer\");\n+\t\treturn -1;\n+\t}\n+#endif\n+\tstruct fpga_queue *q = dev->data->queues[queue_id].queue_private;\n+\tuint32_t offset = FPGA_5GNR_FEC_RING_CTRL_REGS +\n+\t\t\t(sizeof(struct fpga_ring_ctrl_reg) * q->q_idx);\n+\tuint8_t enable = 0x01;\n+\tuint16_t zero = 0x0000;\n+\n+\t/* Clear queue head and tail variables */\n+\tq->tail = q->head_free_desc = 0;\n+\n+\t/* Clear FPGA head_point and tail registers */\n+\tfpga_reg_write_16(d->mmio_base, offset + FPGA_5GNR_FEC_RING_HEAD_POINT,\n+\t\t\tzero);\n+\tfpga_reg_write_16(d->mmio_base, offset + FPGA_5GNR_FEC_RING_SHADOW_TAIL,\n+\t\t\tzero);\n+\n+\t/* Enable queue */\n+\tfpga_reg_write_8(d->mmio_base, offset + FPGA_5GNR_FEC_RING_ENABLE,\n+\t\t\tenable);\n+\n+\trte_bbdev_log_debug(\"FPGA Queue[%d] started\", queue_id);\n+\treturn 0;\n+}\n+\n+/* Function stops a device queue. */\n+static int\n+fpga_queue_stop(struct rte_bbdev *dev, uint16_t queue_id)\n+{\n+\tstruct fpga_5gnr_fec_device *d = dev->data->dev_private;\n+#ifdef RTE_LIBRTE_BBDEV_DEBUG\n+\tif (d == NULL) {\n+\t\trte_bbdev_log(ERR, \"Invalid device pointer\");\n+\t\treturn -1;\n+\t}\n+#endif\n+\tstruct fpga_queue *q = dev->data->queues[queue_id].queue_private;\n+\tuint32_t offset = FPGA_5GNR_FEC_RING_CTRL_REGS +\n+\t\t\t(sizeof(struct fpga_ring_ctrl_reg) * q->q_idx);\n+\tuint8_t payload = 0x01;\n+\tuint8_t counter = 0;\n+\tuint8_t timeout = FPGA_QUEUE_FLUSH_TIMEOUT_US /\n+\t\t\tFPGA_TIMEOUT_CHECK_INTERVAL;\n+\n+\t/* Set flush_queue_en bit to trigger queue flushing */\n+\tfpga_reg_write_8(d->mmio_base,\n+\t\t\toffset + FPGA_5GNR_FEC_RING_FLUSH_QUEUE_EN, payload);\n+\n+\t/** Check if queue flush is completed.\n+\t * FPGA will update the completion flag after queue flushing is\n+\t * completed. If completion flag is not updated within 1ms it is\n+\t * considered as a failure.\n+\t */\n+\twhile (!(*((volatile uint8_t *)d->flush_queue_status + q->q_idx)\n+\t\t\t& payload)) {\n+\t\tif (counter > timeout) {\n+\t\t\trte_bbdev_log(ERR, \"FPGA Queue Flush failed for queue %d\",\n+\t\t\t\t\tqueue_id);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tusleep(FPGA_TIMEOUT_CHECK_INTERVAL);\n+\t\tcounter++;\n+\t}\n+\n+\t/* Disable queue */\n+\tpayload = 0x00;\n+\tfpga_reg_write_8(d->mmio_base, offset + FPGA_5GNR_FEC_RING_ENABLE,\n+\t\t\tpayload);\n+\n+\trte_bbdev_log_debug(\"FPGA Queue[%d] stopped\", queue_id);\n+\treturn 0;\n+}\n+\n static const struct rte_bbdev_ops fpga_ops = {\n+\t.setup_queues = fpga_setup_queues,\n \t.close = fpga_dev_close,\n \t.info_get = fpga_dev_info_get,\n+\t.queue_setup = fpga_queue_setup,\n+\t.queue_stop = fpga_queue_stop,\n+\t.queue_start = fpga_queue_start,\n+\t.queue_release = fpga_queue_release,\n };\n \n /* Initialization Function */\n",
    "prefixes": [
        "v3",
        "04/11"
    ]
}