From: Ziyang Xuan <xuanziyang2@huawei.com>
To: <dev@dpdk.org>
Cc: <ferruh.yigit@intel.com>, <cloud.wangxiaoyun@huawei.com>,
<zhouguoyang@huawei.com>, <shahar.belkar@huawei.com>,
<luoxianjun@huawei.com>, Ziyang Xuan <xuanziyang2@huawei.com>
Subject: [dpdk-dev] [PATCH v5 09/15] net/hinic/base: add context and work queue support
Date: Thu, 20 Jun 2019 00:05:39 +0800 [thread overview]
Message-ID: <58113c06486f2fa347e7921beb45f97eef74db66.1560958308.git.xuanziyang2@huawei.com> (raw)
In-Reply-To: <cover.1560958308.git.xuanziyang2@huawei.com>
Work queue is used for cmdq and tx/rx buff description.
Nic business needs to configure cmdq context and txq/rxq
context. This patch adds data structures and function codes
for work queue and context.
Signed-off-by: Ziyang Xuan <xuanziyang2@huawei.com>
---
drivers/net/hinic/base/hinic_pmd_nicio.c | 894 +++++++++++++++++++++++
drivers/net/hinic/base/hinic_pmd_nicio.h | 265 +++++++
drivers/net/hinic/base/hinic_pmd_wq.c | 179 +++++
drivers/net/hinic/base/hinic_pmd_wq.h | 137 ++++
4 files changed, 1475 insertions(+)
create mode 100644 drivers/net/hinic/base/hinic_pmd_nicio.c
create mode 100644 drivers/net/hinic/base/hinic_pmd_nicio.h
create mode 100644 drivers/net/hinic/base/hinic_pmd_wq.c
create mode 100644 drivers/net/hinic/base/hinic_pmd_wq.h
diff --git a/drivers/net/hinic/base/hinic_pmd_nicio.c b/drivers/net/hinic/base/hinic_pmd_nicio.c
new file mode 100644
index 000000000..248211f90
--- /dev/null
+++ b/drivers/net/hinic/base/hinic_pmd_nicio.c
@@ -0,0 +1,894 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ */
+#include<rte_bus_pci.h>
+
+#include "hinic_compat.h"
+#include "hinic_pmd_hwdev.h"
+#include "hinic_pmd_hwif.h"
+#include "hinic_pmd_wq.h"
+#include "hinic_pmd_mgmt.h"
+#include "hinic_pmd_cmdq.h"
+#include "hinic_pmd_cfg.h"
+#include "hinic_pmd_niccfg.h"
+#include "hinic_pmd_nicio.h"
+
+#define WQ_PREFETCH_MAX 6
+#define WQ_PREFETCH_MIN 1
+#define WQ_PREFETCH_THRESHOLD 256
+
+#define DEFAULT_RX_BUF_SIZE ((u16)0xB)
+
+enum {
+ RECYCLE_MODE_NIC = 0x0,
+ RECYCLE_MODE_DPDK = 0x1,
+};
+
+/* Queue buffer related define */
+enum hinic_rx_buf_size {
+ HINIC_RX_BUF_SIZE_32B = 0x20,
+ HINIC_RX_BUF_SIZE_64B = 0x40,
+ HINIC_RX_BUF_SIZE_96B = 0x60,
+ HINIC_RX_BUF_SIZE_128B = 0x80,
+ HINIC_RX_BUF_SIZE_192B = 0xC0,
+ HINIC_RX_BUF_SIZE_256B = 0x100,
+ HINIC_RX_BUF_SIZE_384B = 0x180,
+ HINIC_RX_BUF_SIZE_512B = 0x200,
+ HINIC_RX_BUF_SIZE_768B = 0x300,
+ HINIC_RX_BUF_SIZE_1K = 0x400,
+ HINIC_RX_BUF_SIZE_1_5K = 0x600,
+ HINIC_RX_BUF_SIZE_2K = 0x800,
+ HINIC_RX_BUF_SIZE_3K = 0xC00,
+ HINIC_RX_BUF_SIZE_4K = 0x1000,
+ HINIC_RX_BUF_SIZE_8K = 0x2000,
+ HINIC_RX_BUF_SIZE_16K = 0x4000,
+};
+
+const u32 hinic_hw_rx_buf_size[] = {
+ HINIC_RX_BUF_SIZE_32B,
+ HINIC_RX_BUF_SIZE_64B,
+ HINIC_RX_BUF_SIZE_96B,
+ HINIC_RX_BUF_SIZE_128B,
+ HINIC_RX_BUF_SIZE_192B,
+ HINIC_RX_BUF_SIZE_256B,
+ HINIC_RX_BUF_SIZE_384B,
+ HINIC_RX_BUF_SIZE_512B,
+ HINIC_RX_BUF_SIZE_768B,
+ HINIC_RX_BUF_SIZE_1K,
+ HINIC_RX_BUF_SIZE_1_5K,
+ HINIC_RX_BUF_SIZE_2K,
+ HINIC_RX_BUF_SIZE_3K,
+ HINIC_RX_BUF_SIZE_4K,
+ HINIC_RX_BUF_SIZE_8K,
+ HINIC_RX_BUF_SIZE_16K,
+};
+
+struct hinic_qp_ctxt_header {
+ u16 num_queues;
+ u16 queue_type;
+ u32 addr_offset;
+};
+
+struct hinic_sq_ctxt {
+ u32 ceq_attr;
+
+ u32 ci_owner;
+
+ u32 wq_pfn_hi;
+ u32 wq_pfn_lo;
+
+ u32 pref_cache;
+ u32 pref_owner;
+ u32 pref_wq_pfn_hi_ci;
+ u32 pref_wq_pfn_lo;
+
+ u32 rsvd8;
+ u32 rsvd9;
+
+ u32 wq_block_pfn_hi;
+ u32 wq_block_pfn_lo;
+};
+
+struct hinic_rq_ctxt {
+ u32 ceq_attr;
+
+ u32 pi_intr_attr;
+
+ u32 wq_pfn_hi_ci;
+ u32 wq_pfn_lo;
+
+ u32 pref_cache;
+ u32 pref_owner;
+
+ u32 pref_wq_pfn_hi_ci;
+ u32 pref_wq_pfn_lo;
+
+ u32 pi_paddr_hi;
+ u32 pi_paddr_lo;
+
+ u32 wq_block_pfn_hi;
+ u32 wq_block_pfn_lo;
+};
+
+struct hinic_sq_ctxt_block {
+ struct hinic_qp_ctxt_header cmdq_hdr;
+ struct hinic_sq_ctxt sq_ctxt[HINIC_Q_CTXT_MAX];
+};
+
+struct hinic_rq_ctxt_block {
+ struct hinic_qp_ctxt_header cmdq_hdr;
+ struct hinic_rq_ctxt rq_ctxt[HINIC_Q_CTXT_MAX];
+};
+
+struct hinic_clean_queue_ctxt {
+ struct hinic_qp_ctxt_header cmdq_hdr;
+ u32 ctxt_size;
+};
+
+
+static void
+hinic_qp_prepare_cmdq_header(struct hinic_qp_ctxt_header *qp_ctxt_hdr,
+ enum hinic_qp_ctxt_type ctxt_type,
+ u16 num_queues, u16 max_queues, u16 q_id)
+{
+ qp_ctxt_hdr->queue_type = ctxt_type;
+ qp_ctxt_hdr->num_queues = num_queues;
+
+ if (ctxt_type == HINIC_QP_CTXT_TYPE_SQ)
+ qp_ctxt_hdr->addr_offset =
+ SQ_CTXT_OFFSET(max_queues, max_queues, q_id);
+ else
+ qp_ctxt_hdr->addr_offset =
+ RQ_CTXT_OFFSET(max_queues, max_queues, q_id);
+
+ qp_ctxt_hdr->addr_offset = SIZE_16BYTES(qp_ctxt_hdr->addr_offset);
+
+ hinic_cpu_to_be32(qp_ctxt_hdr, sizeof(*qp_ctxt_hdr));
+}
+
+static void hinic_sq_prepare_ctxt(struct hinic_sq *sq, u16 global_qpn,
+ struct hinic_sq_ctxt *sq_ctxt)
+{
+ struct hinic_wq *wq = sq->wq;
+ u64 wq_page_addr;
+ u64 wq_page_pfn, wq_block_pfn;
+ u32 wq_page_pfn_hi, wq_page_pfn_lo;
+ u32 wq_block_pfn_hi, wq_block_pfn_lo;
+ u16 pi_start, ci_start;
+
+ ci_start = (u16)(wq->cons_idx);
+ pi_start = (u16)(wq->prod_idx);
+
+ /* read the first page from the HW table */
+ wq_page_addr = wq->queue_buf_paddr;
+
+ wq_page_pfn = WQ_PAGE_PFN(wq_page_addr);
+ wq_page_pfn_hi = upper_32_bits(wq_page_pfn);
+ wq_page_pfn_lo = lower_32_bits(wq_page_pfn);
+
+ wq_block_pfn = WQ_BLOCK_PFN(wq_page_addr);
+ wq_block_pfn_hi = upper_32_bits(wq_block_pfn);
+ wq_block_pfn_lo = lower_32_bits(wq_block_pfn);
+
+ /* must config as ceq disabled */
+ sq_ctxt->ceq_attr = SQ_CTXT_CEQ_ATTR_SET(global_qpn, GLOBAL_SQ_ID) |
+ SQ_CTXT_CEQ_ATTR_SET(0, ARM) |
+ SQ_CTXT_CEQ_ATTR_SET(0, CEQ_ID) |
+ SQ_CTXT_CEQ_ATTR_SET(0, EN);
+
+ sq_ctxt->ci_owner = SQ_CTXT_CI_SET(ci_start, IDX) |
+ SQ_CTXT_CI_SET(1, OWNER);
+
+ sq_ctxt->wq_pfn_hi =
+ SQ_CTXT_WQ_PAGE_SET(wq_page_pfn_hi, HI_PFN) |
+ SQ_CTXT_WQ_PAGE_SET(pi_start, PI);
+
+ sq_ctxt->wq_pfn_lo = wq_page_pfn_lo;
+
+ sq_ctxt->pref_cache =
+ SQ_CTXT_PREF_SET(WQ_PREFETCH_MIN, CACHE_MIN) |
+ SQ_CTXT_PREF_SET(WQ_PREFETCH_MAX, CACHE_MAX) |
+ SQ_CTXT_PREF_SET(WQ_PREFETCH_THRESHOLD, CACHE_THRESHOLD);
+
+ sq_ctxt->pref_owner = 1;
+
+ sq_ctxt->pref_wq_pfn_hi_ci =
+ SQ_CTXT_PREF_SET(ci_start, CI) |
+ SQ_CTXT_PREF_SET(wq_page_pfn_hi, WQ_PFN_HI);
+
+ sq_ctxt->pref_wq_pfn_lo = wq_page_pfn_lo;
+
+ sq_ctxt->wq_block_pfn_hi =
+ SQ_CTXT_WQ_BLOCK_SET(wq_block_pfn_hi, PFN_HI);
+
+ sq_ctxt->wq_block_pfn_lo = wq_block_pfn_lo;
+
+ hinic_cpu_to_be32(sq_ctxt, sizeof(*sq_ctxt));
+}
+
+static void hinic_rq_prepare_ctxt(struct hinic_rq *rq,
+ struct hinic_rq_ctxt *rq_ctxt)
+{
+ struct hinic_wq *wq = rq->wq;
+ u64 wq_page_addr;
+ u64 wq_page_pfn, wq_block_pfn;
+ u32 wq_page_pfn_hi, wq_page_pfn_lo;
+ u32 wq_block_pfn_hi, wq_block_pfn_lo;
+ u16 pi_start, ci_start;
+
+ ci_start = (u16)(wq->cons_idx);
+ pi_start = (u16)(wq->prod_idx);
+
+ /* read the first page from the HW table */
+ wq_page_addr = wq->queue_buf_paddr;
+
+ wq_page_pfn = WQ_PAGE_PFN(wq_page_addr);
+ wq_page_pfn_hi = upper_32_bits(wq_page_pfn);
+ wq_page_pfn_lo = lower_32_bits(wq_page_pfn);
+
+ wq_block_pfn = WQ_BLOCK_PFN(wq_page_addr);
+ wq_block_pfn_hi = upper_32_bits(wq_block_pfn);
+ wq_block_pfn_lo = lower_32_bits(wq_block_pfn);
+
+ /* must config as ceq enable but do not generate ceq */
+ rq_ctxt->ceq_attr = RQ_CTXT_CEQ_ATTR_SET(1, EN) |
+ RQ_CTXT_CEQ_ATTR_SET(1, OWNER);
+
+ rq_ctxt->pi_intr_attr = RQ_CTXT_PI_SET(pi_start, IDX) |
+ RQ_CTXT_PI_SET(rq->msix_entry_idx, INTR) |
+ RQ_CTXT_PI_SET(0, CEQ_ARM);
+
+ rq_ctxt->wq_pfn_hi_ci = RQ_CTXT_WQ_PAGE_SET(wq_page_pfn_hi, HI_PFN) |
+ RQ_CTXT_WQ_PAGE_SET(ci_start, CI);
+
+ rq_ctxt->wq_pfn_lo = wq_page_pfn_lo;
+
+ rq_ctxt->pref_cache =
+ RQ_CTXT_PREF_SET(WQ_PREFETCH_MIN, CACHE_MIN) |
+ RQ_CTXT_PREF_SET(WQ_PREFETCH_MAX, CACHE_MAX) |
+ RQ_CTXT_PREF_SET(WQ_PREFETCH_THRESHOLD, CACHE_THRESHOLD);
+
+ rq_ctxt->pref_owner = 1;
+
+ rq_ctxt->pref_wq_pfn_hi_ci =
+ RQ_CTXT_PREF_SET(wq_page_pfn_hi, WQ_PFN_HI) |
+ RQ_CTXT_PREF_SET(ci_start, CI);
+
+ rq_ctxt->pref_wq_pfn_lo = wq_page_pfn_lo;
+
+ rq_ctxt->pi_paddr_hi = upper_32_bits(rq->pi_dma_addr);
+ rq_ctxt->pi_paddr_lo = lower_32_bits(rq->pi_dma_addr);
+
+ rq_ctxt->wq_block_pfn_hi =
+ RQ_CTXT_WQ_BLOCK_SET(wq_block_pfn_hi, PFN_HI);
+
+ rq_ctxt->wq_block_pfn_lo = wq_block_pfn_lo;
+
+ hinic_cpu_to_be32(rq_ctxt, sizeof(*rq_ctxt));
+}
+
+static int init_sq_ctxts(struct hinic_nic_io *nic_io)
+{
+ struct hinic_hwdev *hwdev = nic_io->hwdev;
+ struct hinic_sq_ctxt_block *sq_ctxt_block;
+ struct hinic_sq_ctxt *sq_ctxt;
+ struct hinic_cmd_buf *cmd_buf;
+ struct hinic_qp *qp;
+ u64 out_param = EIO;
+ u16 q_id, curr_id, global_qpn, max_ctxts, i;
+ int err = 0;
+
+ cmd_buf = hinic_alloc_cmd_buf(hwdev);
+ if (!cmd_buf) {
+ PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
+ return -ENOMEM;
+ }
+
+ q_id = 0;
+ /* sq and rq number may not equal */
+ while (q_id < nic_io->num_sqs) {
+ sq_ctxt_block = cmd_buf->buf;
+ sq_ctxt = sq_ctxt_block->sq_ctxt;
+
+ max_ctxts = (nic_io->num_sqs - q_id) > HINIC_Q_CTXT_MAX ?
+ HINIC_Q_CTXT_MAX : (nic_io->num_sqs - q_id);
+
+ hinic_qp_prepare_cmdq_header(&sq_ctxt_block->cmdq_hdr,
+ HINIC_QP_CTXT_TYPE_SQ, max_ctxts,
+ nic_io->max_qps, q_id);
+
+ for (i = 0; i < max_ctxts; i++) {
+ curr_id = q_id + i;
+ qp = &nic_io->qps[curr_id];
+ global_qpn = nic_io->global_qpn + curr_id;
+
+ hinic_sq_prepare_ctxt(&qp->sq, global_qpn, &sq_ctxt[i]);
+ }
+
+ cmd_buf->size = SQ_CTXT_SIZE(max_ctxts);
+
+ err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
+ HINIC_MOD_L2NIC,
+ HINIC_UCODE_CMD_MDY_QUEUE_CONTEXT,
+ cmd_buf, &out_param, 0);
+ if (err || out_param != 0) {
+ PMD_DRV_LOG(ERR, "Failed to set SQ ctxts, err:%d", err);
+ err = -EFAULT;
+ break;
+ }
+
+ q_id += max_ctxts;
+ }
+
+ hinic_free_cmd_buf(hwdev, cmd_buf);
+
+ return err;
+}
+
+static int init_rq_ctxts(struct hinic_nic_io *nic_io)
+{
+ struct hinic_hwdev *hwdev = nic_io->hwdev;
+ struct hinic_rq_ctxt_block *rq_ctxt_block;
+ struct hinic_rq_ctxt *rq_ctxt;
+ struct hinic_cmd_buf *cmd_buf;
+ struct hinic_qp *qp;
+ u64 out_param = 0;
+ u16 q_id, curr_id, max_ctxts, i;
+ int err = 0;
+
+ cmd_buf = hinic_alloc_cmd_buf(hwdev);
+ if (!cmd_buf) {
+ PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
+ return -ENOMEM;
+ }
+
+ q_id = 0;
+ /* sq and rq number may not equal */
+ while (q_id < nic_io->num_rqs) {
+ rq_ctxt_block = cmd_buf->buf;
+ rq_ctxt = rq_ctxt_block->rq_ctxt;
+
+ max_ctxts = (nic_io->num_rqs - q_id) > HINIC_Q_CTXT_MAX ?
+ HINIC_Q_CTXT_MAX : (nic_io->num_rqs - q_id);
+
+ hinic_qp_prepare_cmdq_header(&rq_ctxt_block->cmdq_hdr,
+ HINIC_QP_CTXT_TYPE_RQ, max_ctxts,
+ nic_io->max_qps, q_id);
+
+ for (i = 0; i < max_ctxts; i++) {
+ curr_id = q_id + i;
+ qp = &nic_io->qps[curr_id];
+
+ hinic_rq_prepare_ctxt(&qp->rq, &rq_ctxt[i]);
+ }
+
+ cmd_buf->size = RQ_CTXT_SIZE(max_ctxts);
+
+ err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
+ HINIC_MOD_L2NIC,
+ HINIC_UCODE_CMD_MDY_QUEUE_CONTEXT,
+ cmd_buf, &out_param, 0);
+
+ if ((err) || out_param != 0) {
+ PMD_DRV_LOG(ERR, "Failed to set RQ ctxts");
+ err = -EFAULT;
+ break;
+ }
+
+ q_id += max_ctxts;
+ }
+
+ hinic_free_cmd_buf(hwdev, cmd_buf);
+
+ return err;
+}
+
+static int init_qp_ctxts(struct hinic_nic_io *nic_io)
+{
+ return (init_sq_ctxts(nic_io) || init_rq_ctxts(nic_io));
+}
+
+static int clean_queue_offload_ctxt(struct hinic_nic_io *nic_io,
+ enum hinic_qp_ctxt_type ctxt_type)
+{
+ struct hinic_hwdev *hwdev = nic_io->hwdev;
+ struct hinic_clean_queue_ctxt *ctxt_block;
+ struct hinic_cmd_buf *cmd_buf;
+ u64 out_param = 0;
+ int err;
+
+ cmd_buf = hinic_alloc_cmd_buf(hwdev);
+ if (!cmd_buf) {
+ PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
+ return -ENOMEM;
+ }
+
+ ctxt_block = cmd_buf->buf;
+ ctxt_block->cmdq_hdr.num_queues = nic_io->max_qps;
+ ctxt_block->cmdq_hdr.queue_type = ctxt_type;
+ ctxt_block->cmdq_hdr.addr_offset = 0;
+
+ /* TSO/LRO ctxt size: 0x0:0B; 0x1:160B; 0x2:200B; 0x3:240B */
+ ctxt_block->ctxt_size = 0x3;
+
+ hinic_cpu_to_be32(ctxt_block, sizeof(*ctxt_block));
+
+ cmd_buf->size = sizeof(*ctxt_block);
+
+ err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
+ HINIC_MOD_L2NIC,
+ HINIC_UCODE_CMD_CLEAN_QUEUE_CONTEXT,
+ cmd_buf, &out_param, 0);
+
+ if ((err) || (out_param)) {
+ PMD_DRV_LOG(ERR, "Failed to clean queue offload ctxts");
+ err = -EFAULT;
+ }
+
+ hinic_free_cmd_buf(hwdev, cmd_buf);
+
+ return err;
+}
+
+static int clean_qp_offload_ctxt(struct hinic_nic_io *nic_io)
+{
+ /* clean LRO/TSO context space */
+ return (clean_queue_offload_ctxt(nic_io, HINIC_QP_CTXT_TYPE_SQ) ||
+ clean_queue_offload_ctxt(nic_io, HINIC_QP_CTXT_TYPE_RQ));
+}
+
+/**
+ * get_hw_rx_buf_size - translate rx_buf_size into hw_rx_buf_size
+ * @rx_buf_sz: receive buffer size
+ * @return
+ * hw rx buffer size
+ **/
+static u16 get_hw_rx_buf_size(u32 rx_buf_sz)
+{
+ u16 num_hw_types = sizeof(hinic_hw_rx_buf_size)
+ / sizeof(hinic_hw_rx_buf_size[0]);
+ u16 i;
+
+ for (i = 0; i < num_hw_types; i++) {
+ if (hinic_hw_rx_buf_size[i] == rx_buf_sz)
+ return i;
+ }
+
+ PMD_DRV_LOG(ERR, "Hw can't support rx buf size of %u", rx_buf_sz);
+
+ return DEFAULT_RX_BUF_SIZE; /* default 2K */
+}
+
+/**
+ * hinic_set_root_ctxt - init root context in NIC
+ * @hwdev: the hardware interface of a nic device
+ * @rq_depth: the depth of receive queue
+ * @sq_depth: the depth of transmit queue
+ * @rx_buf_sz: receive buffer size from app
+ * Return: 0 on success, negative error value otherwise.
+ **/
+static int
+hinic_set_root_ctxt(void *hwdev, u16 rq_depth, u16 sq_depth, int rx_buf_sz)
+{
+ struct hinic_root_ctxt root_ctxt;
+
+ memset(&root_ctxt, 0, sizeof(root_ctxt));
+ root_ctxt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+ root_ctxt.func_idx = hinic_global_func_id(hwdev);
+ root_ctxt.ppf_idx = hinic_ppf_idx(hwdev);
+ root_ctxt.set_cmdq_depth = 0;
+ root_ctxt.cmdq_depth = 0;
+ root_ctxt.lro_en = 1;
+ root_ctxt.rq_depth = (u16)ilog2(rq_depth);
+ root_ctxt.rx_buf_sz = get_hw_rx_buf_size(rx_buf_sz);
+ root_ctxt.sq_depth = (u16)ilog2(sq_depth);
+
+ return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+ HINIC_MGMT_CMD_VAT_SET,
+ &root_ctxt, sizeof(root_ctxt),
+ NULL, NULL, 0);
+}
+
+/**
+ * hinic_clean_root_ctxt - clean root context table in NIC
+ * @hwdev: the hardware interface of a nic device
+ * @return
+ * 0 on success,
+ * negative error value otherwise.
+ **/
+static int hinic_clean_root_ctxt(void *hwdev)
+{
+ struct hinic_root_ctxt root_ctxt;
+
+ memset(&root_ctxt, 0, sizeof(root_ctxt));
+ root_ctxt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+ root_ctxt.func_idx = hinic_global_func_id(hwdev);
+ root_ctxt.ppf_idx = hinic_ppf_idx(hwdev);
+ root_ctxt.set_cmdq_depth = 0;
+ root_ctxt.cmdq_depth = 0;
+ root_ctxt.lro_en = 0;
+ root_ctxt.rq_depth = 0;
+ root_ctxt.rx_buf_sz = 0;
+ root_ctxt.sq_depth = 0;
+
+ return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+ HINIC_MGMT_CMD_VAT_SET,
+ &root_ctxt, sizeof(root_ctxt),
+ NULL, NULL, 0);
+}
+
+/* init qps ctxt and set sq ci attr and arm all sq and set vat page_size */
+int hinic_init_qp_ctxts(struct hinic_hwdev *hwdev)
+{
+ struct hinic_nic_io *nic_io = hwdev->nic_io;
+ struct hinic_sq_attr sq_attr;
+ u16 q_id;
+ int err, rx_buf_sz;
+
+ /* set vat page size to max queue depth page_size */
+ err = hinic_set_pagesize(hwdev, HINIC_PAGE_SIZE_DPDK);
+ if (err != HINIC_OK) {
+ PMD_DRV_LOG(ERR, "Set vat page size: %d failed, rc: %d",
+ HINIC_PAGE_SIZE_DPDK, err);
+ return err;
+ }
+
+ err = init_qp_ctxts(nic_io);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Init QP ctxts failed, rc: %d", err);
+ return err;
+ }
+
+ /* clean LRO/TSO context space */
+ err = clean_qp_offload_ctxt(nic_io);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Clean qp offload ctxts failed, rc: %d",
+ err);
+ return err;
+ }
+
+ rx_buf_sz = nic_io->rq_buf_size;
+
+ /* update rx buf size to function table */
+ err = hinic_set_rx_vhd_mode(hwdev, 0, rx_buf_sz);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Set rx vhd mode failed, rc: %d",
+ err);
+ return err;
+ }
+
+ err = hinic_set_root_ctxt(hwdev, nic_io->rq_depth,
+ nic_io->sq_depth, rx_buf_sz);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Set root context failed, rc: %d",
+ err);
+ return err;
+ }
+
+ for (q_id = 0; q_id < nic_io->num_sqs; q_id++) {
+ sq_attr.ci_dma_base =
+ HINIC_CI_PADDR(nic_io->ci_dma_base, q_id) >> 2;
+ /* performance: sq ci update threshold as 8 */
+ sq_attr.pending_limit = 1;
+ sq_attr.coalescing_time = 1;
+ sq_attr.intr_en = 0;
+ sq_attr.l2nic_sqn = q_id;
+ sq_attr.dma_attr_off = 0;
+ err = hinic_set_ci_table(hwdev, q_id, &sq_attr);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Set ci table failed, rc: %d",
+ err);
+ goto set_cons_idx_table_err;
+ }
+ }
+
+ return 0;
+
+set_cons_idx_table_err:
+ (void)hinic_clean_root_ctxt(hwdev);
+ return err;
+}
+
+void hinic_free_qp_ctxts(struct hinic_hwdev *hwdev)
+{
+ int err;
+
+ err = hinic_clean_root_ctxt(hwdev);
+ if (err)
+ PMD_DRV_LOG(ERR, "Failed to clean root ctxt");
+}
+
+static int hinic_init_nic_hwdev(struct hinic_hwdev *hwdev)
+{
+ struct hinic_nic_io *nic_io = hwdev->nic_io;
+ u16 global_qpn, rx_buf_sz;
+ int err;
+
+ err = hinic_get_base_qpn(hwdev, &global_qpn);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Failed to get base qpn");
+ goto err_init_nic_hwdev;
+ }
+
+ nic_io->global_qpn = global_qpn;
+ rx_buf_sz = HINIC_IS_VF(hwdev) ? RX_BUF_LEN_1_5K : RX_BUF_LEN_16K;
+ err = hinic_init_function_table(hwdev, rx_buf_sz);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Failed to init function table");
+ goto err_init_nic_hwdev;
+ }
+
+ err = hinic_set_fast_recycle_mode(hwdev, RECYCLE_MODE_DPDK);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Failed to set fast recycle mode");
+ goto err_init_nic_hwdev;
+ }
+
+ return 0;
+
+err_init_nic_hwdev:
+ return err;
+}
+
+static void hinic_free_nic_hwdev(struct hinic_hwdev *hwdev)
+{
+ hwdev->nic_io = NULL;
+}
+
+int hinic_rx_tx_flush(struct hinic_hwdev *hwdev)
+{
+ return hinic_func_rx_tx_flush(hwdev);
+}
+
+int hinic_get_sq_free_wqebbs(struct hinic_hwdev *hwdev, u16 q_id)
+{
+ struct hinic_nic_io *nic_io = hwdev->nic_io;
+ struct hinic_wq *wq = &nic_io->sq_wq[q_id];
+
+ return (wq->delta) - 1;
+}
+
+int hinic_get_rq_free_wqebbs(struct hinic_hwdev *hwdev, u16 q_id)
+{
+ struct hinic_nic_io *nic_io = hwdev->nic_io;
+ struct hinic_wq *wq = &nic_io->rq_wq[q_id];
+
+ return (wq->delta) - 1;
+}
+
+u16 hinic_get_sq_local_ci(struct hinic_hwdev *hwdev, u16 q_id)
+{
+ struct hinic_nic_io *nic_io = hwdev->nic_io;
+ struct hinic_wq *wq = &nic_io->sq_wq[q_id];
+
+ return (wq->cons_idx) & wq->mask;
+}
+
+void hinic_return_sq_wqe(struct hinic_hwdev *hwdev, u16 q_id,
+ int num_wqebbs, u16 owner)
+{
+ struct hinic_nic_io *nic_io = hwdev->nic_io;
+ struct hinic_sq *sq = &nic_io->qps[q_id].sq;
+
+ if (owner != sq->owner)
+ sq->owner = owner;
+
+ sq->wq->delta += num_wqebbs;
+ sq->wq->prod_idx -= num_wqebbs;
+}
+
+void hinic_update_sq_local_ci(struct hinic_hwdev *hwdev,
+ u16 q_id, int wqebb_cnt)
+{
+ struct hinic_nic_io *nic_io = hwdev->nic_io;
+ struct hinic_sq *sq = &nic_io->qps[q_id].sq;
+
+ hinic_put_wqe(sq->wq, wqebb_cnt);
+}
+
+void *hinic_get_rq_wqe(struct hinic_hwdev *hwdev, u16 q_id, u16 *pi)
+{
+ struct hinic_nic_io *nic_io = hwdev->nic_io;
+ struct hinic_rq *rq = &nic_io->qps[q_id].rq;
+
+ return hinic_get_wqe(rq->wq, 1, pi);
+}
+
+void hinic_return_rq_wqe(struct hinic_hwdev *hwdev, u16 q_id, int num_wqebbs)
+{
+ struct hinic_nic_io *nic_io = hwdev->nic_io;
+ struct hinic_rq *rq = &nic_io->qps[q_id].rq;
+
+ rq->wq->delta += num_wqebbs;
+ rq->wq->prod_idx -= num_wqebbs;
+}
+
+u16 hinic_get_rq_local_ci(struct hinic_hwdev *hwdev, u16 q_id)
+{
+ struct hinic_nic_io *nic_io = hwdev->nic_io;
+ struct hinic_wq *wq = &nic_io->rq_wq[q_id];
+
+ return (wq->cons_idx) & wq->mask;
+}
+
+void hinic_update_rq_local_ci(struct hinic_hwdev *hwdev, u16 q_id, int wqe_cnt)
+{
+ struct hinic_nic_io *nic_io = hwdev->nic_io;
+ struct hinic_rq *rq = &nic_io->qps[q_id].rq;
+
+ hinic_put_wqe(rq->wq, wqe_cnt);
+}
+
+static int hinic_alloc_nicio(struct hinic_hwdev *hwdev)
+{
+ int err;
+ u16 max_qps, num_qp;
+ struct hinic_nic_io *nic_io = hwdev->nic_io;
+
+ max_qps = hinic_func_max_qnum(hwdev);
+ if ((max_qps & (max_qps - 1))) {
+ PMD_DRV_LOG(ERR, "wrong number of max_qps: %d",
+ max_qps);
+ return -EINVAL;
+ }
+
+ nic_io->max_qps = max_qps;
+ nic_io->num_qps = max_qps;
+ num_qp = max_qps;
+
+ nic_io->qps = kzalloc_aligned(num_qp * sizeof(*nic_io->qps),
+ GFP_KERNEL);
+ if (!nic_io->qps) {
+ PMD_DRV_LOG(ERR, "Failed to allocate qps");
+ err = -ENOMEM;
+ goto alloc_qps_err;
+ }
+
+ nic_io->ci_vaddr_base =
+ dma_zalloc_coherent(hwdev,
+ CI_TABLE_SIZE(num_qp, HINIC_PAGE_SIZE),
+ &nic_io->ci_dma_base, GFP_KERNEL);
+ if (!nic_io->ci_vaddr_base) {
+ PMD_DRV_LOG(ERR, "Failed to allocate ci area");
+ err = -ENOMEM;
+ goto ci_base_err;
+ }
+
+ nic_io->sq_wq = kzalloc_aligned(num_qp * sizeof(*nic_io->sq_wq),
+ GFP_KERNEL);
+ if (!nic_io->sq_wq) {
+ PMD_DRV_LOG(ERR, "Failed to allocate sq wq array");
+ err = -ENOMEM;
+ goto sq_wq_err;
+ }
+
+ nic_io->rq_wq = kzalloc_aligned(num_qp * sizeof(*nic_io->rq_wq),
+ GFP_KERNEL);
+ if (!nic_io->rq_wq) {
+ PMD_DRV_LOG(ERR, "Failed to allocate rq wq array");
+ err = -ENOMEM;
+ goto rq_wq_err;
+ }
+
+ return HINIC_OK;
+
+rq_wq_err:
+ kfree(nic_io->sq_wq);
+
+sq_wq_err:
+ dma_free_coherent(hwdev, CI_TABLE_SIZE(num_qp, HINIC_PAGE_SIZE),
+ nic_io->ci_vaddr_base, nic_io->ci_dma_base);
+
+ci_base_err:
+ kfree(nic_io->qps);
+
+alloc_qps_err:
+ return err;
+}
+
+static void hinic_free_nicio(struct hinic_hwdev *hwdev)
+{
+ struct hinic_nic_io *nic_io = hwdev->nic_io;
+
+ /* nic_io->rq_wq */
+ kfree(nic_io->rq_wq);
+
+ /* nic_io->sq_wq */
+ kfree(nic_io->sq_wq);
+
+ /* nic_io->ci_vaddr_base */
+ dma_free_coherent(hwdev,
+ CI_TABLE_SIZE(nic_io->max_qps, HINIC_PAGE_SIZE),
+ nic_io->ci_vaddr_base, nic_io->ci_dma_base);
+
+ /* nic_io->qps */
+ kfree(nic_io->qps);
+}
+
+/* alloc nic hwdev and init function table */
+int hinic_init_nicio(struct hinic_hwdev *hwdev)
+{
+ int rc;
+
+ hwdev->nic_io = rte_zmalloc("hinic_nicio", sizeof(*hwdev->nic_io),
+ RTE_CACHE_LINE_SIZE);
+ if (!hwdev->nic_io) {
+ PMD_DRV_LOG(ERR, "Allocate nic_io failed, dev_name: %s",
+ hwdev->pcidev_hdl->name);
+ return -ENOMEM;
+ }
+ hwdev->nic_io->hwdev = hwdev;
+
+ /* alloc root working queue set */
+ rc = hinic_alloc_nicio(hwdev);
+ if (rc) {
+ PMD_DRV_LOG(ERR, "Allocate nic_io failed, dev_name: %s",
+ hwdev->pcidev_hdl->name);
+ goto allc_nicio_fail;
+ }
+
+ rc = hinic_init_nic_hwdev(hwdev);
+ if (rc) {
+ PMD_DRV_LOG(ERR, "Initialize hwdev failed, dev_name: %s",
+ hwdev->pcidev_hdl->name);
+ goto init_nic_hwdev_fail;
+ }
+
+ return 0;
+
+init_nic_hwdev_fail:
+ hinic_free_nicio(hwdev);
+
+allc_nicio_fail:
+ rte_free(hwdev->nic_io);
+ return rc;
+}
+
+void hinic_deinit_nicio(struct hinic_hwdev *hwdev)
+{
+ hinic_free_nicio(hwdev);
+
+ hinic_free_nic_hwdev(hwdev);
+
+ rte_free(hwdev->nic_io);
+ hwdev->nic_io = NULL;
+}
+
+/**
+ * hinic_convert_rx_buf_size - convert rx buffer size to hw size
+ * @rx_buf_sz: receive buffer size of mbuf
+ * @match_sz: receive buffer size of hardware
+ * @return
+ * 0 on success,
+ * negative error value otherwise.
+ **/
+int hinic_convert_rx_buf_size(u32 rx_buf_sz, u32 *match_sz)
+{
+ u32 i, num_hw_types, best_match_sz;
+
+ if (unlikely(!match_sz || rx_buf_sz < HINIC_RX_BUF_SIZE_32B))
+ return -EINVAL;
+
+ if (rx_buf_sz >= HINIC_RX_BUF_SIZE_16K) {
+ best_match_sz = HINIC_RX_BUF_SIZE_16K;
+ goto size_matched;
+ }
+
+ num_hw_types = sizeof(hinic_hw_rx_buf_size) /
+ sizeof(hinic_hw_rx_buf_size[0]);
+ best_match_sz = hinic_hw_rx_buf_size[0];
+ for (i = 0; i < num_hw_types; i++) {
+ if (rx_buf_sz == hinic_hw_rx_buf_size[i]) {
+ best_match_sz = hinic_hw_rx_buf_size[i];
+ break;
+ } else if (rx_buf_sz < hinic_hw_rx_buf_size[i]) {
+ break;
+ }
+ best_match_sz = hinic_hw_rx_buf_size[i];
+ }
+
+size_matched:
+ *match_sz = best_match_sz;
+
+ return 0;
+}
diff --git a/drivers/net/hinic/base/hinic_pmd_nicio.h b/drivers/net/hinic/base/hinic_pmd_nicio.h
new file mode 100644
index 000000000..487e44064
--- /dev/null
+++ b/drivers/net/hinic/base/hinic_pmd_nicio.h
@@ -0,0 +1,265 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ */
+
+#ifndef _HINIC_PMD_NICIO_H_
+#define _HINIC_PMD_NICIO_H_
+
+#define RX_BUF_LEN_16K 16384
+#define RX_BUF_LEN_1_5K 1536
+
+#define HINIC_Q_CTXT_MAX 42
+
+/* performance: ci addr RTE_CACHE_SIZE(64B) alignment */
+#define HINIC_CI_Q_ADDR_SIZE 64
+
+#define CI_TABLE_SIZE(num_qps, pg_sz) \
+ (ALIGN((num_qps) * HINIC_CI_Q_ADDR_SIZE, pg_sz))
+
+#define HINIC_CI_VADDR(base_addr, q_id) \
+ ((u8 *)(base_addr) + (q_id) * HINIC_CI_Q_ADDR_SIZE)
+
+#define HINIC_CI_PADDR(base_paddr, q_id) \
+ ((base_paddr) + (q_id) * HINIC_CI_Q_ADDR_SIZE)
+
+#define Q_CTXT_SIZE 48
+#define TSO_LRO_CTXT_SIZE 240
+
+#define SQ_CTXT_OFFSET(max_sqs, max_rqs, q_id) \
+ (((max_rqs) + (max_sqs)) * TSO_LRO_CTXT_SIZE + \
+ (q_id) * Q_CTXT_SIZE)
+
+#define RQ_CTXT_OFFSET(max_sqs, max_rqs, q_id) \
+ (((max_rqs) + (max_sqs)) * TSO_LRO_CTXT_SIZE + \
+ (max_sqs) * Q_CTXT_SIZE + (q_id) * Q_CTXT_SIZE)
+
+#define SQ_CTXT_SIZE(num_sqs) \
+ ((u16)(sizeof(struct hinic_qp_ctxt_header) + \
+ (num_sqs) * sizeof(struct hinic_sq_ctxt)))
+
+#define RQ_CTXT_SIZE(num_rqs) \
+ ((u16)(sizeof(struct hinic_qp_ctxt_header) + \
+ (num_rqs) * sizeof(struct hinic_rq_ctxt)))
+
+#define SQ_CTXT_CEQ_ATTR_CEQ_ID_SHIFT 8
+#define SQ_CTXT_CEQ_ATTR_GLOBAL_SQ_ID_SHIFT 13
+#define SQ_CTXT_CEQ_ATTR_EN_SHIFT 23
+#define SQ_CTXT_CEQ_ATTR_ARM_SHIFT 31
+
+#define SQ_CTXT_CEQ_ATTR_CEQ_ID_MASK 0x1FU
+#define SQ_CTXT_CEQ_ATTR_GLOBAL_SQ_ID_MASK 0x3FFU
+#define SQ_CTXT_CEQ_ATTR_EN_MASK 0x1U
+#define SQ_CTXT_CEQ_ATTR_ARM_MASK 0x1U
+
+#define SQ_CTXT_CEQ_ATTR_SET(val, member) \
+ (((val) & SQ_CTXT_CEQ_ATTR_##member##_MASK) << \
+ SQ_CTXT_CEQ_ATTR_##member##_SHIFT)
+
+#define SQ_CTXT_CI_IDX_SHIFT 11
+#define SQ_CTXT_CI_OWNER_SHIFT 23
+
+#define SQ_CTXT_CI_IDX_MASK 0xFFFU
+#define SQ_CTXT_CI_OWNER_MASK 0x1U
+
+#define SQ_CTXT_CI_SET(val, member) \
+ (((val) & SQ_CTXT_CI_##member##_MASK) << SQ_CTXT_CI_##member##_SHIFT)
+
+#define SQ_CTXT_WQ_PAGE_HI_PFN_SHIFT 0
+#define SQ_CTXT_WQ_PAGE_PI_SHIFT 20
+
+#define SQ_CTXT_WQ_PAGE_HI_PFN_MASK 0xFFFFFU
+#define SQ_CTXT_WQ_PAGE_PI_MASK 0xFFFU
+
+#define SQ_CTXT_WQ_PAGE_SET(val, member) \
+ (((val) & SQ_CTXT_WQ_PAGE_##member##_MASK) << \
+ SQ_CTXT_WQ_PAGE_##member##_SHIFT)
+
+#define SQ_CTXT_PREF_CACHE_THRESHOLD_SHIFT 0
+#define SQ_CTXT_PREF_CACHE_MAX_SHIFT 14
+#define SQ_CTXT_PREF_CACHE_MIN_SHIFT 25
+
+#define SQ_CTXT_PREF_CACHE_THRESHOLD_MASK 0x3FFFU
+#define SQ_CTXT_PREF_CACHE_MAX_MASK 0x7FFU
+#define SQ_CTXT_PREF_CACHE_MIN_MASK 0x7FU
+
+#define SQ_CTXT_PREF_WQ_PFN_HI_SHIFT 0
+#define SQ_CTXT_PREF_CI_SHIFT 20
+
+#define SQ_CTXT_PREF_WQ_PFN_HI_MASK 0xFFFFFU
+#define SQ_CTXT_PREF_CI_MASK 0xFFFU
+
+#define SQ_CTXT_PREF_SET(val, member) \
+ (((val) & SQ_CTXT_PREF_##member##_MASK) << \
+ SQ_CTXT_PREF_##member##_SHIFT)
+
+#define SQ_CTXT_WQ_BLOCK_PFN_HI_SHIFT 0
+
+#define SQ_CTXT_WQ_BLOCK_PFN_HI_MASK 0x7FFFFFU
+
+#define SQ_CTXT_WQ_BLOCK_SET(val, member) \
+ (((val) & SQ_CTXT_WQ_BLOCK_##member##_MASK) << \
+ SQ_CTXT_WQ_BLOCK_##member##_SHIFT)
+
+#define RQ_CTXT_CEQ_ATTR_EN_SHIFT 0
+#define RQ_CTXT_CEQ_ATTR_OWNER_SHIFT 1
+
+#define RQ_CTXT_CEQ_ATTR_EN_MASK 0x1U
+#define RQ_CTXT_CEQ_ATTR_OWNER_MASK 0x1U
+
+#define RQ_CTXT_CEQ_ATTR_SET(val, member) \
+ (((val) & RQ_CTXT_CEQ_ATTR_##member##_MASK) << \
+ RQ_CTXT_CEQ_ATTR_##member##_SHIFT)
+
+#define RQ_CTXT_PI_IDX_SHIFT 0
+#define RQ_CTXT_PI_INTR_SHIFT 22
+#define RQ_CTXT_PI_CEQ_ARM_SHIFT 31
+
+#define RQ_CTXT_PI_IDX_MASK 0xFFFU
+#define RQ_CTXT_PI_INTR_MASK 0x3FFU
+#define RQ_CTXT_PI_CEQ_ARM_MASK 0x1U
+
+#define RQ_CTXT_PI_SET(val, member) \
+ (((val) & RQ_CTXT_PI_##member##_MASK) << RQ_CTXT_PI_##member##_SHIFT)
+
+#define RQ_CTXT_WQ_PAGE_HI_PFN_SHIFT 0
+#define RQ_CTXT_WQ_PAGE_CI_SHIFT 20
+
+#define RQ_CTXT_WQ_PAGE_HI_PFN_MASK 0xFFFFFU
+#define RQ_CTXT_WQ_PAGE_CI_MASK 0xFFFU
+
+#define RQ_CTXT_WQ_PAGE_SET(val, member) \
+ (((val) & RQ_CTXT_WQ_PAGE_##member##_MASK) << \
+ RQ_CTXT_WQ_PAGE_##member##_SHIFT)
+
+#define RQ_CTXT_PREF_CACHE_THRESHOLD_SHIFT 0
+#define RQ_CTXT_PREF_CACHE_MAX_SHIFT 14
+#define RQ_CTXT_PREF_CACHE_MIN_SHIFT 25
+
+#define RQ_CTXT_PREF_CACHE_THRESHOLD_MASK 0x3FFFU
+#define RQ_CTXT_PREF_CACHE_MAX_MASK 0x7FFU
+#define RQ_CTXT_PREF_CACHE_MIN_MASK 0x7FU
+
+#define RQ_CTXT_PREF_WQ_PFN_HI_SHIFT 0
+#define RQ_CTXT_PREF_CI_SHIFT 20
+
+#define RQ_CTXT_PREF_WQ_PFN_HI_MASK 0xFFFFFU
+#define RQ_CTXT_PREF_CI_MASK 0xFFFU
+
+#define RQ_CTXT_PREF_SET(val, member) \
+ (((val) & RQ_CTXT_PREF_##member##_MASK) << \
+ RQ_CTXT_PREF_##member##_SHIFT)
+
+#define RQ_CTXT_WQ_BLOCK_PFN_HI_SHIFT 0
+
+#define RQ_CTXT_WQ_BLOCK_PFN_HI_MASK 0x7FFFFFU
+
+#define RQ_CTXT_WQ_BLOCK_SET(val, member) \
+ (((val) & RQ_CTXT_WQ_BLOCK_##member##_MASK) << \
+ RQ_CTXT_WQ_BLOCK_##member##_SHIFT)
+
+#define SIZE_16BYTES(size) (ALIGN((size), 16) >> 4)
+
+enum hinic_qp_ctxt_type {
+ HINIC_QP_CTXT_TYPE_SQ,
+ HINIC_QP_CTXT_TYPE_RQ,
+};
+
+struct hinic_sq {
+ struct hinic_wq *wq;
+ volatile u16 *cons_idx_addr;
+ void __iomem *db_addr;
+
+ u16 q_id;
+ u16 owner;
+ u16 sq_depth;
+};
+
+struct hinic_rq {
+ struct hinic_wq *wq;
+ volatile u16 *pi_virt_addr;
+ dma_addr_t pi_dma_addr;
+
+ u16 irq_id;
+ u16 msix_entry_idx;
+ u16 q_id;
+ u16 rq_depth;
+};
+
+struct hinic_qp {
+ struct hinic_sq sq;
+ struct hinic_rq rq;
+};
+
+struct hinic_event {
+ void (*tx_ack)(void *handle, u16 q_id);
+ /* status: 0 - link down; 1 - link up */
+ void (*link_change)(void *handle, int status);
+};
+
+struct hinic_nic_io {
+ struct hinic_hwdev *hwdev;
+
+ u16 global_qpn;
+
+ struct hinic_wq *sq_wq;
+ struct hinic_wq *rq_wq;
+
+ u16 max_qps;
+ u16 num_qps;
+
+ u16 num_sqs;
+ u16 num_rqs;
+
+ u16 sq_depth;
+ u16 rq_depth;
+
+ u16 rq_buf_size;
+ u16 vhd_mode;
+
+ struct hinic_qp *qps;
+ /* sq ci mem base addr of the function*/
+ void *ci_vaddr_base;
+ dma_addr_t ci_dma_base;
+
+ struct hinic_event event;
+ void *event_handle;
+};
+
+struct hinic_sq_db {
+ u32 db_info;
+};
+
+
+int hinic_init_qp_ctxts(struct hinic_hwdev *hwdev);
+
+void hinic_free_qp_ctxts(struct hinic_hwdev *hwdev);
+
+int hinic_rx_tx_flush(struct hinic_hwdev *hwdev);
+
+int hinic_get_sq_free_wqebbs(struct hinic_hwdev *hwdev, u16 q_id);
+
+u16 hinic_get_sq_local_ci(struct hinic_hwdev *hwdev, u16 q_id);
+
+void hinic_update_sq_local_ci(struct hinic_hwdev *hwdev, u16 q_id,
+ int wqebb_cnt);
+
+void hinic_return_sq_wqe(struct hinic_hwdev *hwdev, u16 q_id,
+ int num_wqebbs, u16 owner);
+
+int hinic_get_rq_free_wqebbs(struct hinic_hwdev *hwdev, u16 q_id);
+
+void *hinic_get_rq_wqe(struct hinic_hwdev *hwdev, u16 q_id, u16 *pi);
+
+void hinic_return_rq_wqe(struct hinic_hwdev *hwdev, u16 q_id, int num_wqebbs);
+
+u16 hinic_get_rq_local_ci(struct hinic_hwdev *hwdev, u16 q_id);
+
+void hinic_update_rq_local_ci(struct hinic_hwdev *hwdev, u16 q_id, int wqe_cnt);
+
+int hinic_init_nicio(struct hinic_hwdev *hwdev);
+
+void hinic_deinit_nicio(struct hinic_hwdev *hwdev);
+
+int hinic_convert_rx_buf_size(u32 rx_buf_sz, u32 *match_sz);
+
+#endif /* _HINIC_PMD_NICIO_H_ */
diff --git a/drivers/net/hinic/base/hinic_pmd_wq.c b/drivers/net/hinic/base/hinic_pmd_wq.c
new file mode 100644
index 000000000..04c81f9bc
--- /dev/null
+++ b/drivers/net/hinic/base/hinic_pmd_wq.c
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ */
+
+#include "hinic_compat.h"
+#include "hinic_pmd_hwdev.h"
+#include "hinic_pmd_wq.h"
+
+static void free_wq_pages(struct hinic_hwdev *hwdev, struct hinic_wq *wq)
+{
+ dma_free_coherent(hwdev, wq->wq_buf_size, (void *)wq->queue_buf_vaddr,
+ (dma_addr_t)wq->queue_buf_paddr);
+
+ wq->queue_buf_paddr = 0;
+ wq->queue_buf_vaddr = 0;
+}
+
+static int alloc_wq_pages(struct hinic_hwdev *hwdev, struct hinic_wq *wq)
+{
+ dma_addr_t dma_addr = 0;
+
+ wq->queue_buf_vaddr = (u64)(u64 *)
+ dma_zalloc_coherent_aligned256k(hwdev, wq->wq_buf_size,
+ &dma_addr, GFP_KERNEL);
+ if (!wq->queue_buf_vaddr) {
+ PMD_DRV_LOG(ERR, "Failed to allocate wq page");
+ return -ENOMEM;
+ }
+
+ if (!ADDR_256K_ALIGNED(dma_addr)) {
+ PMD_DRV_LOG(ERR, "Wqe pages is not 256k aligned!");
+ dma_free_coherent(hwdev, wq->wq_buf_size,
+ (void *)wq->queue_buf_vaddr,
+ dma_addr);
+ return -ENOMEM;
+ }
+ wq->queue_buf_paddr = dma_addr;
+
+ return 0;
+}
+
+int hinic_wq_allocate(struct hinic_hwdev *hwdev, struct hinic_wq *wq,
+ u32 wqebb_shift, u16 q_depth)
+{
+ int err;
+
+ if (q_depth & (q_depth - 1)) {
+ PMD_DRV_LOG(ERR, "WQ q_depth isn't power of 2");
+ return -EINVAL;
+ }
+
+ wq->wqebb_size = 1 << wqebb_shift;
+ wq->wqebb_shift = wqebb_shift;
+ wq->wq_buf_size = ((u32)q_depth) << wqebb_shift;
+ wq->q_depth = q_depth;
+
+ if (wq->wq_buf_size > (HINIC_PAGE_SIZE << HINIC_PAGE_SIZE_DPDK)) {
+ PMD_DRV_LOG(ERR, "Invalid q_depth %u which one page_size can not hold",
+ q_depth);
+ return -EINVAL;
+ }
+
+ err = alloc_wq_pages(hwdev, wq);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Failed to allocate wq pages");
+ return err;
+ }
+
+ wq->cons_idx = 0;
+ wq->prod_idx = 0;
+ wq->delta = q_depth;
+ wq->mask = q_depth - 1;
+
+ return 0;
+}
+
+void hinic_wq_free(struct hinic_hwdev *hwdev, struct hinic_wq *wq)
+{
+ free_wq_pages(hwdev, wq);
+}
+
+void hinic_put_wqe(struct hinic_wq *wq, int num_wqebbs)
+{
+ wq->cons_idx += num_wqebbs;
+ wq->delta += num_wqebbs;
+}
+
+void *hinic_read_wqe(struct hinic_wq *wq, int num_wqebbs, u16 *cons_idx)
+{
+ u16 curr_cons_idx;
+
+ if ((wq->delta + num_wqebbs) > wq->q_depth)
+ return NULL;
+
+ curr_cons_idx = (u16)(wq->cons_idx);
+
+ curr_cons_idx = MASKED_WQE_IDX(wq, curr_cons_idx);
+
+ *cons_idx = curr_cons_idx;
+
+ return WQ_WQE_ADDR(wq, (u32)(*cons_idx));
+}
+
+int hinic_cmdq_alloc(struct hinic_wq *wq, struct hinic_hwdev *hwdev,
+ int cmdq_blocks, u32 wq_buf_size, u32 wqebb_shift,
+ u16 q_depth)
+{
+ int i, j, err = -ENOMEM;
+
+ /* validate q_depth is power of 2 & wqebb_size is not 0 */
+ for (i = 0; i < cmdq_blocks; i++) {
+ wq[i].wqebb_size = 1 << wqebb_shift;
+ wq[i].wqebb_shift = wqebb_shift;
+ wq[i].wq_buf_size = wq_buf_size;
+ wq[i].q_depth = q_depth;
+
+ err = alloc_wq_pages(hwdev, &wq[i]);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Failed to alloc CMDQ blocks");
+ goto cmdq_block_err;
+ }
+
+ wq[i].cons_idx = 0;
+ wq[i].prod_idx = 0;
+ wq[i].delta = q_depth;
+
+ wq[i].mask = q_depth - 1;
+ }
+
+ return 0;
+
+cmdq_block_err:
+ for (j = 0; j < i; j++)
+ free_wq_pages(hwdev, &wq[j]);
+
+ return err;
+}
+
+void hinic_cmdq_free(struct hinic_hwdev *hwdev, struct hinic_wq *wq,
+ int cmdq_blocks)
+{
+ int i;
+
+ for (i = 0; i < cmdq_blocks; i++)
+ free_wq_pages(hwdev, &wq[i]);
+}
+
+void hinic_wq_wqe_pg_clear(struct hinic_wq *wq)
+{
+ wq->cons_idx = 0;
+ wq->prod_idx = 0;
+
+ memset((void *)wq->queue_buf_vaddr, 0, wq->wq_buf_size);
+}
+
+void *hinic_get_wqe(struct hinic_wq *wq, int num_wqebbs, u16 *prod_idx)
+{
+ u16 curr_prod_idx;
+
+ wq->delta -= num_wqebbs;
+ curr_prod_idx = wq->prod_idx;
+ wq->prod_idx += num_wqebbs;
+ *prod_idx = MASKED_WQE_IDX(wq, curr_prod_idx);
+
+ return WQ_WQE_ADDR(wq, (u32)(*prod_idx));
+}
+
+/**
+ * hinic_set_sge - set dma area in scatter gather entry
+ * @sge: scatter gather entry
+ * @addr: dma address
+ * @len: length of relevant data in the dma address
+ **/
+void hinic_set_sge(struct hinic_sge *sge, dma_addr_t addr, u32 len)
+{
+ sge->hi_addr = upper_32_bits(addr);
+ sge->lo_addr = lower_32_bits(addr);
+ sge->len = len;
+}
diff --git a/drivers/net/hinic/base/hinic_pmd_wq.h b/drivers/net/hinic/base/hinic_pmd_wq.h
new file mode 100644
index 000000000..53ecc225c
--- /dev/null
+++ b/drivers/net/hinic/base/hinic_pmd_wq.h
@@ -0,0 +1,137 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ */
+
+#ifndef _HINIC_PMD_WQ_H_
+#define _HINIC_PMD_WQ_H_
+
+#define WQS_BLOCKS_PER_PAGE 4
+
+#define WQ_SIZE(wq) (u32)((u64)(wq)->q_depth * (wq)->wqebb_size)
+
+#define WQE_PAGE_NUM(wq, idx) (((idx) >> ((wq)->wqebbs_per_page_shift)) & \
+ ((wq)->num_q_pages - 1))
+
+#define WQE_PAGE_OFF(wq, idx) ((u64)((wq)->wqebb_size) * \
+ ((idx) & ((wq)->num_wqebbs_per_page - 1)))
+
+#define WQ_PAGE_ADDR_SIZE sizeof(u64)
+#define WQ_PAGE_ADDR_SIZE_SHIFT 3
+#define WQ_PAGE_ADDR(wq, idx) \
+ (u8 *)(*(u64 *)((u64)((wq)->shadow_block_vaddr) + \
+ (WQE_PAGE_NUM(wq, idx) << WQ_PAGE_ADDR_SIZE_SHIFT)))
+
+#define WQ_BLOCK_SIZE 4096UL
+#define WQS_PAGE_SIZE (WQS_BLOCKS_PER_PAGE * WQ_BLOCK_SIZE)
+#define WQ_MAX_PAGES (WQ_BLOCK_SIZE >> WQ_PAGE_ADDR_SIZE_SHIFT)
+
+#define CMDQ_BLOCKS_PER_PAGE 8
+#define CMDQ_BLOCK_SIZE 512UL
+#define CMDQ_PAGE_SIZE ALIGN((CMDQ_BLOCKS_PER_PAGE * \
+ CMDQ_BLOCK_SIZE), PAGE_SIZE)
+
+#define ADDR_4K_ALIGNED(addr) (0 == ((addr) & 0xfff))
+#define ADDR_256K_ALIGNED(addr) (0 == ((addr) & 0x3ffff))
+
+#define WQ_BASE_VADDR(wqs, wq) \
+ (u64 *)(((u64)((wqs)->page_vaddr[(wq)->page_idx])) \
+ + (wq)->block_idx * WQ_BLOCK_SIZE)
+
+#define WQ_BASE_PADDR(wqs, wq) (((wqs)->page_paddr[(wq)->page_idx]) \
+ + (u64)(wq)->block_idx * WQ_BLOCK_SIZE)
+
+#define WQ_BASE_ADDR(wqs, wq) \
+ (u64 *)(((u64)((wqs)->shadow_page_vaddr[(wq)->page_idx])) \
+ + (wq)->block_idx * WQ_BLOCK_SIZE)
+
+#define CMDQ_BASE_VADDR(cmdq_pages, wq) \
+ (u64 *)(((u64)((cmdq_pages)->cmdq_page_vaddr)) \
+ + (wq)->block_idx * CMDQ_BLOCK_SIZE)
+
+#define CMDQ_BASE_PADDR(cmdq_pages, wq) \
+ (((u64)((cmdq_pages)->cmdq_page_paddr)) \
+ + (u64)(wq)->block_idx * CMDQ_BLOCK_SIZE)
+
+#define CMDQ_BASE_ADDR(cmdq_pages, wq) \
+ (u64 *)(((u64)((cmdq_pages)->cmdq_shadow_page_vaddr)) \
+ + (wq)->block_idx * CMDQ_BLOCK_SIZE)
+
+#define MASKED_WQE_IDX(wq, idx) ((idx) & (wq)->mask)
+
+#define WQE_SHADOW_PAGE(wq, wqe) \
+ (u16)(((unsigned long)(wqe) - (unsigned long)(wq)->shadow_wqe) \
+ / (wq)->max_wqe_size)
+
+#define WQE_IN_RANGE(wqe, start, end) \
+ (((unsigned long)(wqe) >= (unsigned long)(start)) && \
+ ((unsigned long)(wqe) < (unsigned long)(end)))
+
+#define WQ_NUM_PAGES(num_wqs) \
+ (ALIGN((u32)num_wqs, WQS_BLOCKS_PER_PAGE) / WQS_BLOCKS_PER_PAGE)
+
+#define WQ_WQE_ADDR(wq, idx) ((void *)((u64)((wq)->queue_buf_vaddr) + \
+ ((idx) << (wq)->wqebb_shift)))
+
+#define WQ_PAGE_PFN_SHIFT 12
+#define WQ_BLOCK_PFN_SHIFT 9
+
+#define WQ_PAGE_PFN(page_addr) ((page_addr) >> WQ_PAGE_PFN_SHIFT)
+#define WQ_BLOCK_PFN(page_addr) ((page_addr) >> WQ_BLOCK_PFN_SHIFT)
+
+
+#define HINIC_SQ_WQEBB_SIZE 64
+#define HINIC_RQ_WQE_SIZE 32
+#define HINIC_SQ_WQEBB_SHIFT 6
+#define HINIC_RQ_WQEBB_SHIFT 5
+
+struct hinic_sge {
+ u32 hi_addr;
+ u32 lo_addr;
+ u32 len;
+};
+
+/* Working Queue */
+struct hinic_wq {
+ /* The addresses are 64 bit in the HW */
+ u64 queue_buf_vaddr;
+
+ u16 q_depth;
+ u16 mask;
+ u32 delta;
+
+ u32 cons_idx;
+ u32 prod_idx;
+
+ u64 queue_buf_paddr;
+
+ u32 wqebb_size;
+ u32 wqebb_shift;
+
+ u32 wq_buf_size;
+
+ u32 rsvd[5];
+};
+
+void hinic_wq_wqe_pg_clear(struct hinic_wq *wq);
+
+int hinic_cmdq_alloc(struct hinic_wq *wq, struct hinic_hwdev *hwdev,
+ int cmdq_blocks, u32 wq_buf_size, u32 wqebb_shift,
+ u16 q_depth);
+
+void hinic_cmdq_free(struct hinic_hwdev *hwdev, struct hinic_wq *wq,
+ int cmdq_blocks);
+
+int hinic_wq_allocate(struct hinic_hwdev *hwdev, struct hinic_wq *wq,
+ u32 wqebb_shift, u16 q_depth);
+
+void hinic_wq_free(struct hinic_hwdev *hwdev, struct hinic_wq *wq);
+
+void *hinic_get_wqe(struct hinic_wq *wq, int num_wqebbs, u16 *prod_idx);
+
+void hinic_put_wqe(struct hinic_wq *wq, int num_wqebbs);
+
+void *hinic_read_wqe(struct hinic_wq *wq, int num_wqebbs, u16 *cons_idx);
+
+void hinic_set_sge(struct hinic_sge *sge, dma_addr_t addr, u32 len);
+
+#endif /* _HINIC_PMD_WQ_H_ */
--
2.18.0
next prev parent reply other threads:[~2019-06-19 16:16 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-19 15:45 [dpdk-dev] [PATCH v5 00/15] A new net PMD - hinic Ziyang Xuan
2019-06-19 15:46 ` [dpdk-dev] [PATCH v5 01/15] net/hinic/base: add HW registers definition Ziyang Xuan
2019-06-19 15:50 ` [dpdk-dev] [PATCH v5 02/15] net/hinic/base: add HW interfaces of bar operation Ziyang Xuan
2019-06-19 15:47 ` Ziyang Xuan
2019-06-19 15:54 ` [dpdk-dev] [PATCH v5 03/15] net/hinic/base: add api command channel code Ziyang Xuan
2019-06-19 15:55 ` [dpdk-dev] [PATCH v5 04/15] net/hinic/base: add support for cmdq mechanism Ziyang Xuan
2019-06-19 15:56 ` [dpdk-dev] [PATCH v5 05/15] net/hinic/base: add eq mechanism function code Ziyang Xuan
2019-06-19 15:57 ` [dpdk-dev] [PATCH v5 06/15] net/hinic/base: add mgmt module " Ziyang Xuan
2019-06-19 16:02 ` [dpdk-dev] [PATCH v5 07/15] net/hinic/base: add code about hardware operation Ziyang Xuan
2019-06-19 15:58 ` Ziyang Xuan
2019-06-19 16:04 ` [dpdk-dev] [PATCH v5 08/15] net/hinic/base: add nic business configurations Ziyang Xuan
2019-06-19 16:05 ` Ziyang Xuan [this message]
2019-06-19 16:08 ` [dpdk-dev] [PATCH v5 10/15] net/hinic: add various headers Ziyang Xuan
2019-06-26 11:54 ` Ferruh Yigit
2019-06-19 16:09 ` [dpdk-dev] [PATCH v5 11/15] net/hinic: add hinic PMD build and doc files Ziyang Xuan
2019-06-19 16:13 ` Ziyang Xuan
2019-06-26 11:55 ` Ferruh Yigit
2019-06-19 16:16 ` [dpdk-dev] [PATCH v5 12/15] net/hinic: add device initailization Ziyang Xuan
2019-06-19 16:14 ` Ziyang Xuan
2019-06-19 16:30 ` Ziyang Xuan
2019-06-19 16:18 ` [dpdk-dev] [PATCH v5 13/15] net/hinic: add start stop close queue ops Ziyang Xuan
2019-06-19 16:32 ` Ziyang Xuan
2019-06-19 16:20 ` [dpdk-dev] [PATCH v5 14/15] net/hinic: add tx/rx package burst Ziyang Xuan
2019-06-19 16:25 ` Ziyang Xuan
2019-06-26 11:54 ` Ferruh Yigit
2019-06-26 15:58 ` [dpdk-dev] 答复: " Xuanziyang (William, Chip Application Design Logic and Hardware Development Dept IT_Products & Solutions)
2019-06-26 16:05 ` Ferruh Yigit
2019-06-19 16:23 ` [dpdk-dev] [PATCH v5 15/15] net/hinic: add rss stats promisc ops Ziyang Xuan
2019-06-26 11:56 ` [dpdk-dev] [PATCH v5 00/15] A new net PMD - hinic Ferruh Yigit
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=58113c06486f2fa347e7921beb45f97eef74db66.1560958308.git.xuanziyang2@huawei.com \
--to=xuanziyang2@huawei.com \
--cc=cloud.wangxiaoyun@huawei.com \
--cc=dev@dpdk.org \
--cc=ferruh.yigit@intel.com \
--cc=luoxianjun@huawei.com \
--cc=shahar.belkar@huawei.com \
--cc=zhouguoyang@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).