From: Xin Wang <wangxin...@h-partners.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: Xin Wang <wangxin...@h-partners.com> Reviewed-by: Feifei Wang <wangfeife...@huawei.com> Reviewed-by: Yi Chen <chenyi...@huawei.com> --- drivers/net/hinic3/base/hinic3_wq.c | 148 ++++++++++++++++++++++++++++ drivers/net/hinic3/base/hinic3_wq.h | 109 ++++++++++++++++++++ 2 files changed, 257 insertions(+) create mode 100644 drivers/net/hinic3/base/hinic3_wq.c create mode 100644 drivers/net/hinic3/base/hinic3_wq.h diff --git a/drivers/net/hinic3/base/hinic3_wq.c b/drivers/net/hinic3/base/hinic3_wq.c new file mode 100644 index 0000000000..9bccb10c9a --- /dev/null +++ b/drivers/net/hinic3/base/hinic3_wq.c @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2025 Huawei Technologies Co., Ltd + */ +#include <rte_bus_pci.h> +#include <rte_errno.h> +#include <rte_ether.h> +#include <rte_malloc.h> +#include <rte_mbuf.h> +#include <rte_mempool.h> +#include <rte_pci.h> + +#include "hinic3_compat.h" +#include "hinic3_hwdev.h" +#include "hinic3_wq.h" + +static void +free_wq_pages(struct hinic3_wq *wq) +{ + hinic3_memzone_free(wq->wq_mz); + + wq->queue_buf_paddr = 0; + wq->queue_buf_vaddr = 0; +} + +static int +alloc_wq_pages(struct hinic3_hwdev *hwdev, struct hinic3_wq *wq, int qid) +{ + const struct rte_memzone *wq_mz; + + wq_mz = hinic3_dma_zone_reserve(hwdev->eth_dev, "hinic3_wq_mz", + (uint16_t)qid, wq->wq_buf_size, + RTE_PGSIZE_256K, SOCKET_ID_ANY); + if (!wq_mz) { + PMD_DRV_LOG(ERR, "Allocate wq[%d] rq_mz failed", qid); + return -ENOMEM; + } + + memset(wq_mz->addr, 0, wq->wq_buf_size); + wq->wq_mz = wq_mz; + wq->queue_buf_paddr = wq_mz->iova; + wq->queue_buf_vaddr = (u64)(u64 *)wq_mz->addr; + + return 0; +} + +void +hinic3_put_wqe(struct hinic3_wq *wq, int num_wqebbs) +{ + wq->cons_idx += num_wqebbs; + rte_atomic_fetch_add_explicit(&wq->delta, num_wqebbs, + rte_memory_order_seq_cst); +} + +void * +hinic3_read_wqe(struct hinic3_wq *wq, int num_wqebbs, u16 *cons_idx) +{ + u16 curr_cons_idx; + + if ((rte_atomic_load_explicit(&wq->delta, rte_memory_order_seq_cst) + + 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 +hinic3_cmdq_alloc(struct hinic3_wq *wq, void *dev, int cmdq_blocks, + u32 wq_buf_size, u32 wqebb_shift, u16 q_depth) +{ + struct hinic3_hwdev *hwdev = (struct hinic3_hwdev *)dev; + int i, j; + int err; + + /* Validate q_depth is power of 2 & wqebb_size is not 0. */ + for (i = 0; i < cmdq_blocks; i++) { + wq[i].wqebb_size = 1U << 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], 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; + rte_atomic_store_explicit(&wq[i].delta, q_depth, + rte_memory_order_seq_cst); + + wq[i].mask = q_depth - 1; + } + + return 0; + +cmdq_block_err: + for (j = 0; j < i; j++) + free_wq_pages(&wq[j]); + + return err; +} + +void +hinic3_cmdq_free(struct hinic3_wq *wq, int cmdq_blocks) +{ + int i; + + for (i = 0; i < cmdq_blocks; i++) + free_wq_pages(&wq[i]); +} + +void +hinic3_wq_wqe_pg_clear(struct hinic3_wq *wq) +{ + wq->cons_idx = 0; + wq->prod_idx = 0; + + memset((void *)wq->queue_buf_vaddr, 0, wq->wq_buf_size); +} + +void * +hinic3_get_wqe(struct hinic3_wq *wq, int num_wqebbs, u16 *prod_idx) +{ + u16 curr_prod_idx; + + rte_atomic_fetch_sub_explicit(&wq->delta, num_wqebbs, + rte_memory_order_seq_cst); + curr_prod_idx = (u16)(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)); +} + +void +hinic3_set_sge(struct hinic3_sge *sge, uint64_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/hinic3/base/hinic3_wq.h b/drivers/net/hinic3/base/hinic3_wq.h new file mode 100644 index 0000000000..84d54c2aeb --- /dev/null +++ b/drivers/net/hinic3/base/hinic3_wq.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2025 Huawei Technologies Co., Ltd + */ + +#ifndef _HINIC3_WQ_H_ +#define _HINIC3_WQ_H_ + +/* Use 0-level CLA, page size must be: SQ 16B(wqe) * 64k(max_q_depth). */ +#define HINIC3_DEFAULT_WQ_PAGE_SIZE 0x100000 +#define HINIC3_HW_WQ_PAGE_SIZE 0x1000 + +#define MASKED_WQE_IDX(wq, idx) ((idx) & (wq)->mask) + +#define WQ_WQE_ADDR(wq, idx) \ + ({ \ + typeof(wq) __wq = (wq); \ + (void *)((u64)(__wq->queue_buf_vaddr) + ((idx) << __wq->wqebb_shift)); \ + }) + +struct hinic3_sge { + u32 hi_addr; + u32 lo_addr; + u32 len; +}; + +struct hinic3_wq { + /* The addresses are 64 bit in the HW. */ + u64 queue_buf_vaddr; + + u16 q_depth; + u16 mask; + RTE_ATOMIC(int32_t)delta; + + u32 cons_idx; + u32 prod_idx; + + u64 queue_buf_paddr; + + u32 wqebb_size; + u32 wqebb_shift; + + u32 wq_buf_size; + + const struct rte_memzone *wq_mz; + + u32 rsvd[5]; +}; + +void hinic3_put_wqe(struct hinic3_wq *wq, int num_wqebbs); + +/** + * Read a WQE and update CI. + * + * @param[in] wq + * The work queue structure. + * @param[in] num_wqebbs + * The number of work queue elements to read. + * @param[out] cons_idx + * The updated consumer index. + * + * @return + * The address of WQE, or NULL if not enough elements are available. + */ +void *hinic3_read_wqe(struct hinic3_wq *wq, int num_wqebbs, u16 *cons_idx); + +/** + * Allocate command queue blocks and initialize related parameters. + * + * @param[in] wq + * The cmdq->wq structure. + * @param[in] dev + * The device context for the hardware. + * @param[in] cmdq_blocks + * The number of command queue blocks to allocate. + * @param[in] wq_buf_size + * The size of each work queue buffer. + * @param[in] wqebb_shift + * The shift value for determining the work queue element size. + * @param[in] q_depth + * The depth of each command queue. + * + * @return + * 0 on success, non-zero on failure. + */ +int hinic3_cmdq_alloc(struct hinic3_wq *wq, void *dev, int cmdq_blocks, + u32 wq_buf_size, u32 wqebb_shift, u16 q_depth); + +void hinic3_cmdq_free(struct hinic3_wq *wq, int cmdq_blocks); + +void hinic3_wq_wqe_pg_clear(struct hinic3_wq *wq); + +/** + * Get WQE and update PI. + * + * @param[in] wq + * The cmdq->wq structure. + * @param[in] num_wqebbs + * The number of work queue elements to allocate. + * @param[out] prod_idx + * The updated producer index, masked according to the queue size. + * + * @return + * The address of the work queue element. + */ +void *hinic3_get_wqe(struct hinic3_wq *wq, int num_wqebbs, u16 *prod_idx); + +void hinic3_set_sge(struct hinic3_sge *sge, uint64_t addr, u32 len); + +#endif /* _HINIC3_WQ_H_ */ -- 2.47.0.windows.2