164727024SZiyang Xuan /* SPDX-License-Identifier: BSD-3-Clause
264727024SZiyang Xuan * Copyright(c) 2017 Huawei Technologies Co., Ltd
364727024SZiyang Xuan */
464727024SZiyang Xuan
564727024SZiyang Xuan #include <rte_ether.h>
664727024SZiyang Xuan #include <rte_mbuf.h>
736f98ed2SDavid Marchand #ifdef RTE_ARCH_ARM64
8076221c8SZiyang Xuan #include <arm_neon.h>
9076221c8SZiyang Xuan #endif
1064727024SZiyang Xuan
1164727024SZiyang Xuan #include "base/hinic_compat.h"
1264727024SZiyang Xuan #include "base/hinic_pmd_hwdev.h"
1364727024SZiyang Xuan #include "base/hinic_pmd_wq.h"
1464727024SZiyang Xuan #include "base/hinic_pmd_niccfg.h"
1564727024SZiyang Xuan #include "base/hinic_pmd_nicio.h"
1664727024SZiyang Xuan #include "hinic_pmd_ethdev.h"
1764727024SZiyang Xuan #include "hinic_pmd_rx.h"
1864727024SZiyang Xuan
192c473729SZiyang Xuan /* rxq wq operations */
202c473729SZiyang Xuan #define HINIC_GET_RQ_WQE_MASK(rxq) \
212c473729SZiyang Xuan ((rxq)->wq->mask)
222c473729SZiyang Xuan
232c473729SZiyang Xuan #define HINIC_GET_RQ_LOCAL_CI(rxq) \
242c473729SZiyang Xuan (((rxq)->wq->cons_idx) & HINIC_GET_RQ_WQE_MASK(rxq))
252c473729SZiyang Xuan
262c473729SZiyang Xuan #define HINIC_GET_RQ_LOCAL_PI(rxq) \
272c473729SZiyang Xuan (((rxq)->wq->prod_idx) & HINIC_GET_RQ_WQE_MASK(rxq))
282c473729SZiyang Xuan
292c473729SZiyang Xuan #define HINIC_UPDATE_RQ_LOCAL_CI(rxq, wqebb_cnt) \
302c473729SZiyang Xuan do { \
312c473729SZiyang Xuan (rxq)->wq->cons_idx += (wqebb_cnt); \
322c473729SZiyang Xuan (rxq)->wq->delta += (wqebb_cnt); \
332c473729SZiyang Xuan } while (0)
342c473729SZiyang Xuan
352c473729SZiyang Xuan #define HINIC_UPDATE_RQ_HW_PI(rxq, pi) \
362c473729SZiyang Xuan (*((rxq)->pi_virt_addr) = \
372c473729SZiyang Xuan cpu_to_be16((pi) & HINIC_GET_RQ_WQE_MASK(rxq)))
382c473729SZiyang Xuan
392c473729SZiyang Xuan #define HINIC_GET_RQ_FREE_WQEBBS(rxq) ((rxq)->wq->delta - 1)
402c473729SZiyang Xuan
41076221c8SZiyang Xuan /* rxq cqe done and status bit */
42076221c8SZiyang Xuan #define HINIC_GET_RX_DONE_BE(status) \
43076221c8SZiyang Xuan ((status) & 0x80U)
44076221c8SZiyang Xuan
452c473729SZiyang Xuan #define HINIC_RX_CSUM_OFFLOAD_EN 0xFFF
462c473729SZiyang Xuan
47076221c8SZiyang Xuan #define RQ_CQE_SGE_VLAN_SHIFT 0
48076221c8SZiyang Xuan #define RQ_CQE_SGE_LEN_SHIFT 16
49076221c8SZiyang Xuan
50076221c8SZiyang Xuan #define RQ_CQE_SGE_VLAN_MASK 0xFFFFU
51076221c8SZiyang Xuan #define RQ_CQE_SGE_LEN_MASK 0xFFFFU
52076221c8SZiyang Xuan
53076221c8SZiyang Xuan #define RQ_CQE_SGE_GET(val, member) \
54076221c8SZiyang Xuan (((val) >> RQ_CQE_SGE_##member##_SHIFT) & RQ_CQE_SGE_##member##_MASK)
55076221c8SZiyang Xuan
56076221c8SZiyang Xuan #define HINIC_GET_RX_VLAN_TAG(vlan_len) \
57076221c8SZiyang Xuan RQ_CQE_SGE_GET(vlan_len, VLAN)
58076221c8SZiyang Xuan
59076221c8SZiyang Xuan #define HINIC_GET_RX_PKT_LEN(vlan_len) \
60076221c8SZiyang Xuan RQ_CQE_SGE_GET(vlan_len, LEN)
61076221c8SZiyang Xuan
62076221c8SZiyang Xuan #define RQ_CQE_STATUS_CSUM_ERR_SHIFT 0
63076221c8SZiyang Xuan #define RQ_CQE_STATUS_NUM_LRO_SHIFT 16
64076221c8SZiyang Xuan #define RQ_CQE_STATUS_LRO_PUSH_SHIFT 25
65076221c8SZiyang Xuan #define RQ_CQE_STATUS_LRO_ENTER_SHIFT 26
66076221c8SZiyang Xuan #define RQ_CQE_STATUS_LRO_INTR_SHIFT 27
67076221c8SZiyang Xuan
68076221c8SZiyang Xuan #define RQ_CQE_STATUS_BP_EN_SHIFT 30
69076221c8SZiyang Xuan #define RQ_CQE_STATUS_RXDONE_SHIFT 31
70076221c8SZiyang Xuan #define RQ_CQE_STATUS_FLUSH_SHIFT 28
71076221c8SZiyang Xuan
72076221c8SZiyang Xuan #define RQ_CQE_STATUS_CSUM_ERR_MASK 0xFFFFU
73076221c8SZiyang Xuan #define RQ_CQE_STATUS_NUM_LRO_MASK 0xFFU
74076221c8SZiyang Xuan #define RQ_CQE_STATUS_LRO_PUSH_MASK 0X1U
75076221c8SZiyang Xuan #define RQ_CQE_STATUS_LRO_ENTER_MASK 0X1U
76076221c8SZiyang Xuan #define RQ_CQE_STATUS_LRO_INTR_MASK 0X1U
77076221c8SZiyang Xuan #define RQ_CQE_STATUS_BP_EN_MASK 0X1U
78076221c8SZiyang Xuan #define RQ_CQE_STATUS_RXDONE_MASK 0x1U
79076221c8SZiyang Xuan #define RQ_CQE_STATUS_FLUSH_MASK 0x1U
80076221c8SZiyang Xuan
81076221c8SZiyang Xuan #define RQ_CQE_STATUS_GET(val, member) \
82076221c8SZiyang Xuan (((val) >> RQ_CQE_STATUS_##member##_SHIFT) & \
83076221c8SZiyang Xuan RQ_CQE_STATUS_##member##_MASK)
84076221c8SZiyang Xuan
85076221c8SZiyang Xuan #define RQ_CQE_STATUS_CLEAR(val, member) \
86076221c8SZiyang Xuan ((val) & (~(RQ_CQE_STATUS_##member##_MASK << \
87076221c8SZiyang Xuan RQ_CQE_STATUS_##member##_SHIFT)))
88076221c8SZiyang Xuan
89076221c8SZiyang Xuan #define HINIC_GET_RX_CSUM_ERR(status) \
90076221c8SZiyang Xuan RQ_CQE_STATUS_GET(status, CSUM_ERR)
91076221c8SZiyang Xuan
92076221c8SZiyang Xuan #define HINIC_GET_RX_DONE(status) \
93076221c8SZiyang Xuan RQ_CQE_STATUS_GET(status, RXDONE)
94076221c8SZiyang Xuan
95076221c8SZiyang Xuan #define HINIC_GET_RX_FLUSH(status) \
96076221c8SZiyang Xuan RQ_CQE_STATUS_GET(status, FLUSH)
97076221c8SZiyang Xuan
98076221c8SZiyang Xuan #define HINIC_GET_RX_BP_EN(status) \
99076221c8SZiyang Xuan RQ_CQE_STATUS_GET(status, BP_EN)
100076221c8SZiyang Xuan
101076221c8SZiyang Xuan #define HINIC_GET_RX_NUM_LRO(status) \
102076221c8SZiyang Xuan RQ_CQE_STATUS_GET(status, NUM_LRO)
103076221c8SZiyang Xuan
1042c473729SZiyang Xuan /* RQ_CTRL */
1052c473729SZiyang Xuan #define RQ_CTRL_BUFDESC_SECT_LEN_SHIFT 0
1062c473729SZiyang Xuan #define RQ_CTRL_COMPLETE_FORMAT_SHIFT 15
1072c473729SZiyang Xuan #define RQ_CTRL_COMPLETE_LEN_SHIFT 27
1082c473729SZiyang Xuan #define RQ_CTRL_LEN_SHIFT 29
1092c473729SZiyang Xuan
1102c473729SZiyang Xuan #define RQ_CTRL_BUFDESC_SECT_LEN_MASK 0xFFU
1112c473729SZiyang Xuan #define RQ_CTRL_COMPLETE_FORMAT_MASK 0x1U
1122c473729SZiyang Xuan #define RQ_CTRL_COMPLETE_LEN_MASK 0x3U
1132c473729SZiyang Xuan #define RQ_CTRL_LEN_MASK 0x3U
1142c473729SZiyang Xuan
1152c473729SZiyang Xuan #define RQ_CTRL_SET(val, member) \
1162c473729SZiyang Xuan (((val) & RQ_CTRL_##member##_MASK) << RQ_CTRL_##member##_SHIFT)
1172c473729SZiyang Xuan
1182c473729SZiyang Xuan #define RQ_CTRL_GET(val, member) \
1192c473729SZiyang Xuan (((val) >> RQ_CTRL_##member##_SHIFT) & RQ_CTRL_##member##_MASK)
1202c473729SZiyang Xuan
1212c473729SZiyang Xuan #define RQ_CTRL_CLEAR(val, member) \
1222c473729SZiyang Xuan ((val) & (~(RQ_CTRL_##member##_MASK << RQ_CTRL_##member##_SHIFT)))
1232c473729SZiyang Xuan
124076221c8SZiyang Xuan #define RQ_CQE_PKT_NUM_SHIFT 1
125076221c8SZiyang Xuan #define RQ_CQE_PKT_FIRST_LEN_SHIFT 19
126076221c8SZiyang Xuan #define RQ_CQE_PKT_LAST_LEN_SHIFT 6
127076221c8SZiyang Xuan #define RQ_CQE_SUPER_CQE_EN_SHIFT 0
128076221c8SZiyang Xuan
129076221c8SZiyang Xuan #define RQ_CQE_PKT_FIRST_LEN_MASK 0x1FFFU
130076221c8SZiyang Xuan #define RQ_CQE_PKT_LAST_LEN_MASK 0x1FFFU
131076221c8SZiyang Xuan #define RQ_CQE_PKT_NUM_MASK 0x1FU
132076221c8SZiyang Xuan #define RQ_CQE_SUPER_CQE_EN_MASK 0x1
133076221c8SZiyang Xuan
134076221c8SZiyang Xuan #define RQ_CQE_PKT_NUM_GET(val, member) \
135076221c8SZiyang Xuan (((val) >> RQ_CQE_PKT_##member##_SHIFT) & RQ_CQE_PKT_##member##_MASK)
136076221c8SZiyang Xuan
137076221c8SZiyang Xuan #define HINIC_GET_RQ_CQE_PKT_NUM(pkt_info) RQ_CQE_PKT_NUM_GET(pkt_info, NUM)
138076221c8SZiyang Xuan
139076221c8SZiyang Xuan #define RQ_CQE_SUPER_CQE_EN_GET(val, member) \
140076221c8SZiyang Xuan (((val) >> RQ_CQE_##member##_SHIFT) & RQ_CQE_##member##_MASK)
141076221c8SZiyang Xuan
142076221c8SZiyang Xuan #define HINIC_GET_SUPER_CQE_EN(pkt_info) \
143076221c8SZiyang Xuan RQ_CQE_SUPER_CQE_EN_GET(pkt_info, SUPER_CQE_EN)
144076221c8SZiyang Xuan
145076221c8SZiyang Xuan #define RQ_CQE_OFFOLAD_TYPE_VLAN_EN_SHIFT 21
146076221c8SZiyang Xuan #define RQ_CQE_OFFOLAD_TYPE_VLAN_EN_MASK 0x1U
147076221c8SZiyang Xuan
148076221c8SZiyang Xuan #define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_SHIFT 0
149076221c8SZiyang Xuan #define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_MASK 0xFFFU
150076221c8SZiyang Xuan
151076221c8SZiyang Xuan #define RQ_CQE_OFFOLAD_TYPE_PKT_UMBCAST_SHIFT 19
152076221c8SZiyang Xuan #define RQ_CQE_OFFOLAD_TYPE_PKT_UMBCAST_MASK 0x3U
153076221c8SZiyang Xuan
154076221c8SZiyang Xuan #define RQ_CQE_OFFOLAD_TYPE_RSS_TYPE_SHIFT 24
155076221c8SZiyang Xuan #define RQ_CQE_OFFOLAD_TYPE_RSS_TYPE_MASK 0xFFU
156076221c8SZiyang Xuan
157076221c8SZiyang Xuan #define RQ_CQE_OFFOLAD_TYPE_GET(val, member) (((val) >> \
158076221c8SZiyang Xuan RQ_CQE_OFFOLAD_TYPE_##member##_SHIFT) & \
159076221c8SZiyang Xuan RQ_CQE_OFFOLAD_TYPE_##member##_MASK)
160076221c8SZiyang Xuan
161076221c8SZiyang Xuan #define HINIC_GET_RX_VLAN_OFFLOAD_EN(offload_type) \
162076221c8SZiyang Xuan RQ_CQE_OFFOLAD_TYPE_GET(offload_type, VLAN_EN)
163076221c8SZiyang Xuan
164076221c8SZiyang Xuan #define HINIC_GET_RSS_TYPES(offload_type) \
165076221c8SZiyang Xuan RQ_CQE_OFFOLAD_TYPE_GET(offload_type, RSS_TYPE)
166076221c8SZiyang Xuan
167076221c8SZiyang Xuan #define HINIC_GET_RX_PKT_TYPE(offload_type) \
168076221c8SZiyang Xuan RQ_CQE_OFFOLAD_TYPE_GET(offload_type, PKT_TYPE)
169076221c8SZiyang Xuan
170076221c8SZiyang Xuan #define HINIC_GET_RX_PKT_UMBCAST(offload_type) \
171076221c8SZiyang Xuan RQ_CQE_OFFOLAD_TYPE_GET(offload_type, PKT_UMBCAST)
172076221c8SZiyang Xuan
173076221c8SZiyang Xuan #define RQ_CQE_STATUS_CSUM_BYPASS_VAL 0x80U
174076221c8SZiyang Xuan #define RQ_CQE_STATUS_CSUM_ERR_IP_MASK 0x39U
175076221c8SZiyang Xuan #define RQ_CQE_STATUS_CSUM_ERR_L4_MASK 0x46U
176076221c8SZiyang Xuan #define RQ_CQE_STATUS_CSUM_ERR_OTHER 0x100U
177076221c8SZiyang Xuan
178076221c8SZiyang Xuan #define HINIC_CSUM_ERR_BYPASSED(csum_err) \
179076221c8SZiyang Xuan ((csum_err) == RQ_CQE_STATUS_CSUM_BYPASS_VAL)
180076221c8SZiyang Xuan
181076221c8SZiyang Xuan #define HINIC_CSUM_ERR_IP(csum_err) \
182076221c8SZiyang Xuan ((csum_err) & RQ_CQE_STATUS_CSUM_ERR_IP_MASK)
183076221c8SZiyang Xuan
184076221c8SZiyang Xuan #define HINIC_CSUM_ERR_L4(csum_err) \
185076221c8SZiyang Xuan ((csum_err) & RQ_CQE_STATUS_CSUM_ERR_L4_MASK)
186076221c8SZiyang Xuan
187076221c8SZiyang Xuan #define HINIC_CSUM_ERR_OTHER(csum_err) \
188076221c8SZiyang Xuan ((csum_err) == RQ_CQE_STATUS_CSUM_ERR_OTHER)
189076221c8SZiyang Xuan
1902c473729SZiyang Xuan
hinic_get_func_rx_buf_size(struct hinic_nic_dev * nic_dev)1912c473729SZiyang Xuan void hinic_get_func_rx_buf_size(struct hinic_nic_dev *nic_dev)
1922c473729SZiyang Xuan {
1932c473729SZiyang Xuan struct hinic_rxq *rxq;
1942c473729SZiyang Xuan u16 q_id;
1952c473729SZiyang Xuan u16 buf_size = 0;
1962c473729SZiyang Xuan
1972c473729SZiyang Xuan for (q_id = 0; q_id < nic_dev->num_rq; q_id++) {
1982c473729SZiyang Xuan rxq = nic_dev->rxqs[q_id];
1992c473729SZiyang Xuan
2002c473729SZiyang Xuan if (rxq == NULL)
2012c473729SZiyang Xuan continue;
2022c473729SZiyang Xuan
2032c473729SZiyang Xuan if (q_id == 0)
2042c473729SZiyang Xuan buf_size = rxq->buf_len;
2052c473729SZiyang Xuan
2062c473729SZiyang Xuan buf_size = buf_size > rxq->buf_len ? rxq->buf_len : buf_size;
2072c473729SZiyang Xuan }
2082c473729SZiyang Xuan
2092c473729SZiyang Xuan nic_dev->hwdev->nic_io->rq_buf_size = buf_size;
2102c473729SZiyang Xuan }
2112c473729SZiyang Xuan
hinic_create_rq(struct hinic_hwdev * hwdev,u16 q_id,u16 rq_depth,unsigned int socket_id)2121b7b9f17SXiaoyun Wang int hinic_create_rq(struct hinic_hwdev *hwdev, u16 q_id,
2131b7b9f17SXiaoyun Wang u16 rq_depth, unsigned int socket_id)
2142c473729SZiyang Xuan {
2152c473729SZiyang Xuan int err;
2162c473729SZiyang Xuan struct hinic_nic_io *nic_io = hwdev->nic_io;
2172c473729SZiyang Xuan struct hinic_qp *qp = &nic_io->qps[q_id];
2182c473729SZiyang Xuan struct hinic_rq *rq = &qp->rq;
2192c473729SZiyang Xuan
2202c473729SZiyang Xuan /* in case of hardware still generate interrupt, do not use msix 0 */
2212c473729SZiyang Xuan rq->msix_entry_idx = 1;
2222c473729SZiyang Xuan rq->q_id = q_id;
2232c473729SZiyang Xuan rq->rq_depth = rq_depth;
2242c473729SZiyang Xuan nic_io->rq_depth = rq_depth;
2252c473729SZiyang Xuan
2262c473729SZiyang Xuan err = hinic_wq_allocate(hwdev, &nic_io->rq_wq[q_id],
2271b7b9f17SXiaoyun Wang HINIC_RQ_WQEBB_SHIFT, nic_io->rq_depth, socket_id);
2282c473729SZiyang Xuan if (err) {
2292c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to allocate WQ for RQ");
2302c473729SZiyang Xuan return err;
2312c473729SZiyang Xuan }
2322c473729SZiyang Xuan rq->wq = &nic_io->rq_wq[q_id];
2332c473729SZiyang Xuan
2341b7b9f17SXiaoyun Wang rq->pi_virt_addr = (volatile u16 *)dma_zalloc_coherent(hwdev,
2351b7b9f17SXiaoyun Wang HINIC_PAGE_SIZE, &rq->pi_dma_addr, socket_id);
2362c473729SZiyang Xuan if (!rq->pi_virt_addr) {
2372c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to allocate rq pi virt addr");
2382c473729SZiyang Xuan err = -ENOMEM;
2392c473729SZiyang Xuan goto rq_pi_alloc_err;
2402c473729SZiyang Xuan }
2412c473729SZiyang Xuan
2422c473729SZiyang Xuan return HINIC_OK;
2432c473729SZiyang Xuan
2442c473729SZiyang Xuan rq_pi_alloc_err:
2452c473729SZiyang Xuan hinic_wq_free(hwdev, &nic_io->rq_wq[q_id]);
2462c473729SZiyang Xuan
2472c473729SZiyang Xuan return err;
2482c473729SZiyang Xuan }
24964727024SZiyang Xuan
hinic_destroy_rq(struct hinic_hwdev * hwdev,u16 q_id)25064727024SZiyang Xuan void hinic_destroy_rq(struct hinic_hwdev *hwdev, u16 q_id)
25164727024SZiyang Xuan {
25264727024SZiyang Xuan struct hinic_nic_io *nic_io = hwdev->nic_io;
25364727024SZiyang Xuan struct hinic_qp *qp = &nic_io->qps[q_id];
25464727024SZiyang Xuan struct hinic_rq *rq = &qp->rq;
25564727024SZiyang Xuan
25664727024SZiyang Xuan if (qp->rq.wq == NULL)
25764727024SZiyang Xuan return;
25864727024SZiyang Xuan
25964727024SZiyang Xuan dma_free_coherent_volatile(hwdev, HINIC_PAGE_SIZE,
26064727024SZiyang Xuan (volatile void *)rq->pi_virt_addr,
26164727024SZiyang Xuan rq->pi_dma_addr);
26264727024SZiyang Xuan hinic_wq_free(nic_io->hwdev, qp->rq.wq);
26364727024SZiyang Xuan qp->rq.wq = NULL;
26464727024SZiyang Xuan }
26564727024SZiyang Xuan
2662c473729SZiyang Xuan static void
hinic_prepare_rq_wqe(void * wqe,__rte_unused u16 pi,dma_addr_t buf_addr,dma_addr_t cqe_dma)2672c473729SZiyang Xuan hinic_prepare_rq_wqe(void *wqe, __rte_unused u16 pi, dma_addr_t buf_addr,
2682c473729SZiyang Xuan dma_addr_t cqe_dma)
2692c473729SZiyang Xuan {
2702c473729SZiyang Xuan struct hinic_rq_wqe *rq_wqe = wqe;
2712c473729SZiyang Xuan struct hinic_rq_ctrl *ctrl = &rq_wqe->ctrl;
2722c473729SZiyang Xuan struct hinic_rq_cqe_sect *cqe_sect = &rq_wqe->cqe_sect;
2732c473729SZiyang Xuan struct hinic_rq_bufdesc *buf_desc = &rq_wqe->buf_desc;
2742c473729SZiyang Xuan u32 rq_ceq_len = sizeof(struct hinic_rq_cqe);
2752c473729SZiyang Xuan
2762c473729SZiyang Xuan ctrl->ctrl_fmt =
2772c473729SZiyang Xuan RQ_CTRL_SET(SIZE_8BYTES(sizeof(*ctrl)), LEN) |
2782c473729SZiyang Xuan RQ_CTRL_SET(SIZE_8BYTES(sizeof(*cqe_sect)), COMPLETE_LEN) |
2792c473729SZiyang Xuan RQ_CTRL_SET(SIZE_8BYTES(sizeof(*buf_desc)), BUFDESC_SECT_LEN) |
2802c473729SZiyang Xuan RQ_CTRL_SET(RQ_COMPLETE_SGE, COMPLETE_FORMAT);
2812c473729SZiyang Xuan
2822c473729SZiyang Xuan hinic_set_sge(&cqe_sect->sge, cqe_dma, rq_ceq_len);
2832c473729SZiyang Xuan
2842c473729SZiyang Xuan buf_desc->addr_high = upper_32_bits(buf_addr);
2852c473729SZiyang Xuan buf_desc->addr_low = lower_32_bits(buf_addr);
2862c473729SZiyang Xuan }
2872c473729SZiyang Xuan
hinic_rxq_get_stats(struct hinic_rxq * rxq,struct hinic_rxq_stats * stats)288076221c8SZiyang Xuan void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats)
289076221c8SZiyang Xuan {
290076221c8SZiyang Xuan if (!rxq || !stats)
291076221c8SZiyang Xuan return;
292076221c8SZiyang Xuan
293076221c8SZiyang Xuan memcpy(stats, &rxq->rxq_stats, sizeof(rxq->rxq_stats));
294076221c8SZiyang Xuan }
295076221c8SZiyang Xuan
hinic_rxq_stats_reset(struct hinic_rxq * rxq)296076221c8SZiyang Xuan void hinic_rxq_stats_reset(struct hinic_rxq *rxq)
297076221c8SZiyang Xuan {
298076221c8SZiyang Xuan struct hinic_rxq_stats *rxq_stats;
299076221c8SZiyang Xuan
300076221c8SZiyang Xuan if (rxq == NULL)
301076221c8SZiyang Xuan return;
302076221c8SZiyang Xuan
303076221c8SZiyang Xuan rxq_stats = &rxq->rxq_stats;
304076221c8SZiyang Xuan memset(rxq_stats, 0, sizeof(*rxq_stats));
305076221c8SZiyang Xuan }
306076221c8SZiyang Xuan
hinic_rx_alloc_cqe(struct hinic_rxq * rxq,unsigned int socket_id)3071b7b9f17SXiaoyun Wang static int hinic_rx_alloc_cqe(struct hinic_rxq *rxq, unsigned int socket_id)
3082c473729SZiyang Xuan {
3092c473729SZiyang Xuan size_t cqe_mem_size;
3102c473729SZiyang Xuan
3112c473729SZiyang Xuan cqe_mem_size = sizeof(struct hinic_rq_cqe) * rxq->q_depth;
3121b7b9f17SXiaoyun Wang rxq->cqe_start_vaddr = dma_zalloc_coherent(rxq->nic_dev->hwdev,
3131b7b9f17SXiaoyun Wang cqe_mem_size, &rxq->cqe_start_paddr, socket_id);
3142c473729SZiyang Xuan if (!rxq->cqe_start_vaddr) {
3152c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate cqe dma memory failed");
3162c473729SZiyang Xuan return -ENOMEM;
3172c473729SZiyang Xuan }
3182c473729SZiyang Xuan
3192c473729SZiyang Xuan rxq->rx_cqe = (struct hinic_rq_cqe *)rxq->cqe_start_vaddr;
3202c473729SZiyang Xuan
3212c473729SZiyang Xuan return HINIC_OK;
3222c473729SZiyang Xuan }
3232c473729SZiyang Xuan
hinic_rx_free_cqe(struct hinic_rxq * rxq)32464727024SZiyang Xuan static void hinic_rx_free_cqe(struct hinic_rxq *rxq)
32564727024SZiyang Xuan {
32664727024SZiyang Xuan size_t cqe_mem_size;
32764727024SZiyang Xuan
32864727024SZiyang Xuan cqe_mem_size = sizeof(struct hinic_rq_cqe) * rxq->q_depth;
32964727024SZiyang Xuan dma_free_coherent(rxq->nic_dev->hwdev, cqe_mem_size,
33064727024SZiyang Xuan rxq->cqe_start_vaddr, rxq->cqe_start_paddr);
33164727024SZiyang Xuan rxq->cqe_start_vaddr = NULL;
33264727024SZiyang Xuan }
33364727024SZiyang Xuan
hinic_rx_fill_wqe(struct hinic_rxq * rxq)3342c473729SZiyang Xuan static int hinic_rx_fill_wqe(struct hinic_rxq *rxq)
3352c473729SZiyang Xuan {
3362c473729SZiyang Xuan struct hinic_nic_dev *nic_dev = rxq->nic_dev;
3372c473729SZiyang Xuan struct hinic_rq_wqe *rq_wqe;
3382c473729SZiyang Xuan dma_addr_t buf_dma_addr, cqe_dma_addr;
3392c473729SZiyang Xuan u16 pi = 0;
3402c473729SZiyang Xuan int i;
3412c473729SZiyang Xuan
3422c473729SZiyang Xuan buf_dma_addr = 0;
3432c473729SZiyang Xuan cqe_dma_addr = rxq->cqe_start_paddr;
3442c473729SZiyang Xuan for (i = 0; i < rxq->q_depth; i++) {
3452c473729SZiyang Xuan rq_wqe = hinic_get_rq_wqe(nic_dev->hwdev, rxq->q_id, &pi);
3462c473729SZiyang Xuan if (!rq_wqe) {
3472c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Get rq wqe failed");
3482c473729SZiyang Xuan break;
3492c473729SZiyang Xuan }
3502c473729SZiyang Xuan
3512c473729SZiyang Xuan hinic_prepare_rq_wqe(rq_wqe, pi, buf_dma_addr, cqe_dma_addr);
3522c473729SZiyang Xuan cqe_dma_addr += sizeof(struct hinic_rq_cqe);
3532c473729SZiyang Xuan
3542c473729SZiyang Xuan hinic_cpu_to_be32(rq_wqe, sizeof(struct hinic_rq_wqe));
3552c473729SZiyang Xuan }
3562c473729SZiyang Xuan
3572c473729SZiyang Xuan hinic_return_rq_wqe(nic_dev->hwdev, rxq->q_id, i);
3582c473729SZiyang Xuan
3592c473729SZiyang Xuan return i;
3602c473729SZiyang Xuan }
3612c473729SZiyang Xuan
3622c473729SZiyang Xuan /* alloc cqe and prepare rqe */
hinic_setup_rx_resources(struct hinic_rxq * rxq)3632c473729SZiyang Xuan int hinic_setup_rx_resources(struct hinic_rxq *rxq)
3642c473729SZiyang Xuan {
3652c473729SZiyang Xuan u64 rx_info_sz;
3662c473729SZiyang Xuan int err, pkts;
3672c473729SZiyang Xuan
3682c473729SZiyang Xuan rx_info_sz = rxq->q_depth * sizeof(*rxq->rx_info);
3691b7b9f17SXiaoyun Wang rxq->rx_info = rte_zmalloc_socket("rx_info", rx_info_sz,
3701b7b9f17SXiaoyun Wang RTE_CACHE_LINE_SIZE, rxq->socket_id);
3712c473729SZiyang Xuan if (!rxq->rx_info)
3722c473729SZiyang Xuan return -ENOMEM;
3732c473729SZiyang Xuan
3741b7b9f17SXiaoyun Wang err = hinic_rx_alloc_cqe(rxq, rxq->socket_id);
3752c473729SZiyang Xuan if (err) {
3762c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate rx cqe failed");
3772c473729SZiyang Xuan goto rx_cqe_err;
3782c473729SZiyang Xuan }
3792c473729SZiyang Xuan
3802c473729SZiyang Xuan pkts = hinic_rx_fill_wqe(rxq);
3812c473729SZiyang Xuan if (pkts != rxq->q_depth) {
3822c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Fill rx wqe failed");
3832c473729SZiyang Xuan err = -ENOMEM;
3842c473729SZiyang Xuan goto rx_fill_err;
3852c473729SZiyang Xuan }
3862c473729SZiyang Xuan
3872c473729SZiyang Xuan return 0;
3882c473729SZiyang Xuan
3892c473729SZiyang Xuan rx_fill_err:
3902c473729SZiyang Xuan hinic_rx_free_cqe(rxq);
3912c473729SZiyang Xuan
3922c473729SZiyang Xuan rx_cqe_err:
3931b7b9f17SXiaoyun Wang rte_free(rxq->rx_info);
3942c473729SZiyang Xuan rxq->rx_info = NULL;
3952c473729SZiyang Xuan
3962c473729SZiyang Xuan return err;
3972c473729SZiyang Xuan }
3982c473729SZiyang Xuan
hinic_free_rx_resources(struct hinic_rxq * rxq)39964727024SZiyang Xuan void hinic_free_rx_resources(struct hinic_rxq *rxq)
40064727024SZiyang Xuan {
40164727024SZiyang Xuan if (rxq->rx_info == NULL)
40264727024SZiyang Xuan return;
40364727024SZiyang Xuan
40464727024SZiyang Xuan hinic_rx_free_cqe(rxq);
4051b7b9f17SXiaoyun Wang rte_free(rxq->rx_info);
40664727024SZiyang Xuan rxq->rx_info = NULL;
40764727024SZiyang Xuan }
40864727024SZiyang Xuan
hinic_free_all_rx_resources(struct rte_eth_dev * eth_dev)40964727024SZiyang Xuan void hinic_free_all_rx_resources(struct rte_eth_dev *eth_dev)
41064727024SZiyang Xuan {
41164727024SZiyang Xuan u16 q_id;
41264727024SZiyang Xuan struct hinic_nic_dev *nic_dev =
41364727024SZiyang Xuan HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
41464727024SZiyang Xuan
41564727024SZiyang Xuan for (q_id = 0; q_id < nic_dev->num_rq; q_id++) {
416a2177d2eSXiaoyun Wang if (eth_dev->data->rx_queues != NULL)
41764727024SZiyang Xuan eth_dev->data->rx_queues[q_id] = NULL;
41864727024SZiyang Xuan
41964727024SZiyang Xuan if (nic_dev->rxqs[q_id] == NULL)
42064727024SZiyang Xuan continue;
42164727024SZiyang Xuan
422c3ba1f0fSXiaoyun Wang hinic_free_all_rx_mbufs(nic_dev->rxqs[q_id]);
42364727024SZiyang Xuan hinic_free_rx_resources(nic_dev->rxqs[q_id]);
42464727024SZiyang Xuan kfree(nic_dev->rxqs[q_id]);
42564727024SZiyang Xuan nic_dev->rxqs[q_id] = NULL;
42664727024SZiyang Xuan }
42764727024SZiyang Xuan }
42864727024SZiyang Xuan
hinic_free_all_rx_mbuf(struct rte_eth_dev * eth_dev)4292c473729SZiyang Xuan void hinic_free_all_rx_mbuf(struct rte_eth_dev *eth_dev)
4302c473729SZiyang Xuan {
4312c473729SZiyang Xuan struct hinic_nic_dev *nic_dev =
4322c473729SZiyang Xuan HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
4332c473729SZiyang Xuan u16 q_id;
4342c473729SZiyang Xuan
4352c473729SZiyang Xuan for (q_id = 0; q_id < nic_dev->num_rq; q_id++)
436c3ba1f0fSXiaoyun Wang hinic_free_all_rx_mbufs(nic_dev->rxqs[q_id]);
4372c473729SZiyang Xuan }
4382c473729SZiyang Xuan
hinic_recv_jumbo_pkt(struct hinic_rxq * rxq,struct rte_mbuf * head_mbuf,u32 remain_pkt_len)439076221c8SZiyang Xuan static void hinic_recv_jumbo_pkt(struct hinic_rxq *rxq,
440c3ba1f0fSXiaoyun Wang struct rte_mbuf *head_mbuf,
441076221c8SZiyang Xuan u32 remain_pkt_len)
442076221c8SZiyang Xuan {
443076221c8SZiyang Xuan struct hinic_nic_dev *nic_dev = rxq->nic_dev;
444076221c8SZiyang Xuan struct rte_mbuf *cur_mbuf, *rxm = NULL;
445076221c8SZiyang Xuan struct hinic_rx_info *rx_info;
446076221c8SZiyang Xuan u16 sw_ci, rx_buf_len = rxq->buf_len;
447076221c8SZiyang Xuan u32 pkt_len;
448076221c8SZiyang Xuan
449076221c8SZiyang Xuan while (remain_pkt_len > 0) {
450076221c8SZiyang Xuan sw_ci = hinic_get_rq_local_ci(nic_dev->hwdev, rxq->q_id);
451076221c8SZiyang Xuan rx_info = &rxq->rx_info[sw_ci];
452076221c8SZiyang Xuan
453076221c8SZiyang Xuan hinic_update_rq_local_ci(nic_dev->hwdev, rxq->q_id, 1);
454076221c8SZiyang Xuan
455076221c8SZiyang Xuan pkt_len = remain_pkt_len > rx_buf_len ?
456076221c8SZiyang Xuan rx_buf_len : remain_pkt_len;
457076221c8SZiyang Xuan remain_pkt_len -= pkt_len;
458076221c8SZiyang Xuan
459076221c8SZiyang Xuan cur_mbuf = rx_info->mbuf;
460076221c8SZiyang Xuan cur_mbuf->data_len = (u16)pkt_len;
461076221c8SZiyang Xuan cur_mbuf->next = NULL;
462076221c8SZiyang Xuan
463c3ba1f0fSXiaoyun Wang head_mbuf->pkt_len += cur_mbuf->data_len;
464c3ba1f0fSXiaoyun Wang head_mbuf->nb_segs++;
465076221c8SZiyang Xuan
466076221c8SZiyang Xuan if (!rxm)
467c3ba1f0fSXiaoyun Wang head_mbuf->next = cur_mbuf;
468076221c8SZiyang Xuan else
469076221c8SZiyang Xuan rxm->next = cur_mbuf;
470076221c8SZiyang Xuan
471076221c8SZiyang Xuan rxm = cur_mbuf;
472076221c8SZiyang Xuan }
473076221c8SZiyang Xuan }
474076221c8SZiyang Xuan
hinic_rss_deinit(struct hinic_nic_dev * nic_dev)4752c473729SZiyang Xuan static void hinic_rss_deinit(struct hinic_nic_dev *nic_dev)
4762c473729SZiyang Xuan {
4772c473729SZiyang Xuan u8 prio_tc[HINIC_DCB_UP_MAX] = {0};
4782c473729SZiyang Xuan (void)hinic_rss_cfg(nic_dev->hwdev, 0,
4792c473729SZiyang Xuan nic_dev->rss_tmpl_idx, 0, prio_tc);
4802c473729SZiyang Xuan }
4812c473729SZiyang Xuan
hinic_rss_key_init(struct hinic_nic_dev * nic_dev,struct rte_eth_rss_conf * rss_conf)4822c473729SZiyang Xuan static int hinic_rss_key_init(struct hinic_nic_dev *nic_dev,
4832c473729SZiyang Xuan struct rte_eth_rss_conf *rss_conf)
4842c473729SZiyang Xuan {
4852c473729SZiyang Xuan u8 default_rss_key[HINIC_RSS_KEY_SIZE] = {
4862c473729SZiyang Xuan 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
4872c473729SZiyang Xuan 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
4882c473729SZiyang Xuan 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
4892c473729SZiyang Xuan 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
4902c473729SZiyang Xuan 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa};
4912c473729SZiyang Xuan u8 hashkey[HINIC_RSS_KEY_SIZE] = {0};
4922c473729SZiyang Xuan u8 tmpl_idx = nic_dev->rss_tmpl_idx;
4932c473729SZiyang Xuan
4942c473729SZiyang Xuan if (rss_conf->rss_key == NULL)
4952c473729SZiyang Xuan memcpy(hashkey, default_rss_key, HINIC_RSS_KEY_SIZE);
4962c473729SZiyang Xuan else
4972c473729SZiyang Xuan memcpy(hashkey, rss_conf->rss_key, rss_conf->rss_key_len);
4982c473729SZiyang Xuan
4992c473729SZiyang Xuan return hinic_rss_set_template_tbl(nic_dev->hwdev, tmpl_idx, hashkey);
5002c473729SZiyang Xuan }
5012c473729SZiyang Xuan
hinic_fill_rss_type(struct nic_rss_type * rss_type,struct rte_eth_rss_conf * rss_conf)5022c473729SZiyang Xuan static void hinic_fill_rss_type(struct nic_rss_type *rss_type,
5032c473729SZiyang Xuan struct rte_eth_rss_conf *rss_conf)
5042c473729SZiyang Xuan {
5052c473729SZiyang Xuan u64 rss_hf = rss_conf->rss_hf;
5062c473729SZiyang Xuan
507295968d1SFerruh Yigit rss_type->ipv4 = (rss_hf & (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4)) ? 1 : 0;
508295968d1SFerruh Yigit rss_type->tcp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) ? 1 : 0;
509295968d1SFerruh Yigit rss_type->ipv6 = (rss_hf & (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6)) ? 1 : 0;
510295968d1SFerruh Yigit rss_type->ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_EX) ? 1 : 0;
511295968d1SFerruh Yigit rss_type->tcp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) ? 1 : 0;
512295968d1SFerruh Yigit rss_type->tcp_ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_TCP_EX) ? 1 : 0;
513295968d1SFerruh Yigit rss_type->udp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) ? 1 : 0;
514295968d1SFerruh Yigit rss_type->udp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) ? 1 : 0;
5152c473729SZiyang Xuan }
5162c473729SZiyang Xuan
hinic_fillout_indir_tbl(struct hinic_nic_dev * nic_dev,u32 * indir)5172c473729SZiyang Xuan static void hinic_fillout_indir_tbl(struct hinic_nic_dev *nic_dev, u32 *indir)
5182c473729SZiyang Xuan {
5192c473729SZiyang Xuan u8 rss_queue_count = nic_dev->num_rss;
5202c473729SZiyang Xuan int i = 0, j;
5212c473729SZiyang Xuan
5222c473729SZiyang Xuan if (rss_queue_count == 0) {
5232c473729SZiyang Xuan /* delete q_id from indir tbl */
5242c473729SZiyang Xuan for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
5252c473729SZiyang Xuan indir[i] = 0xFF; /* Invalid value in indir tbl */
5262c473729SZiyang Xuan } else {
5272c473729SZiyang Xuan while (i < HINIC_RSS_INDIR_SIZE)
5282c473729SZiyang Xuan for (j = 0; (j < rss_queue_count) &&
5292c473729SZiyang Xuan (i < HINIC_RSS_INDIR_SIZE); j++)
5302c473729SZiyang Xuan indir[i++] = nic_dev->rx_queue_list[j];
5312c473729SZiyang Xuan }
5322c473729SZiyang Xuan }
5332c473729SZiyang Xuan
hinic_rss_init(struct hinic_nic_dev * nic_dev,__rte_unused u8 * rq2iq_map,struct rte_eth_rss_conf * rss_conf)5342c473729SZiyang Xuan static int hinic_rss_init(struct hinic_nic_dev *nic_dev,
535f2fc83b4SThomas Monjalon __rte_unused u8 *rq2iq_map,
5362c473729SZiyang Xuan struct rte_eth_rss_conf *rss_conf)
5372c473729SZiyang Xuan {
5382c473729SZiyang Xuan u32 indir_tbl[HINIC_RSS_INDIR_SIZE] = {0};
5392c473729SZiyang Xuan struct nic_rss_type rss_type = {0};
5402c473729SZiyang Xuan u8 prio_tc[HINIC_DCB_UP_MAX] = {0};
5412c473729SZiyang Xuan u8 tmpl_idx = 0xFF, num_tc = 0;
5422c473729SZiyang Xuan int err;
5432c473729SZiyang Xuan
5442c473729SZiyang Xuan tmpl_idx = nic_dev->rss_tmpl_idx;
5452c473729SZiyang Xuan
5462c473729SZiyang Xuan err = hinic_rss_key_init(nic_dev, rss_conf);
5472c473729SZiyang Xuan if (err)
5482c473729SZiyang Xuan return err;
5492c473729SZiyang Xuan
5502c473729SZiyang Xuan if (!nic_dev->rss_indir_flag) {
5512c473729SZiyang Xuan hinic_fillout_indir_tbl(nic_dev, indir_tbl);
5522c473729SZiyang Xuan err = hinic_rss_set_indir_tbl(nic_dev->hwdev, tmpl_idx,
5532c473729SZiyang Xuan indir_tbl);
5542c473729SZiyang Xuan if (err)
5552c473729SZiyang Xuan return err;
5562c473729SZiyang Xuan }
5572c473729SZiyang Xuan
5582c473729SZiyang Xuan hinic_fill_rss_type(&rss_type, rss_conf);
5592c473729SZiyang Xuan err = hinic_set_rss_type(nic_dev->hwdev, tmpl_idx, rss_type);
5602c473729SZiyang Xuan if (err)
5612c473729SZiyang Xuan return err;
5622c473729SZiyang Xuan
5632c473729SZiyang Xuan err = hinic_rss_set_hash_engine(nic_dev->hwdev, tmpl_idx,
5642c473729SZiyang Xuan HINIC_RSS_HASH_ENGINE_TYPE_TOEP);
5652c473729SZiyang Xuan if (err)
5662c473729SZiyang Xuan return err;
5672c473729SZiyang Xuan
5682c473729SZiyang Xuan return hinic_rss_cfg(nic_dev->hwdev, 1, tmpl_idx, num_tc, prio_tc);
5692c473729SZiyang Xuan }
5702c473729SZiyang Xuan
57164727024SZiyang Xuan static void
hinic_add_rq_to_rx_queue_list(struct hinic_nic_dev * nic_dev,u16 queue_id)57264727024SZiyang Xuan hinic_add_rq_to_rx_queue_list(struct hinic_nic_dev *nic_dev, u16 queue_id)
57364727024SZiyang Xuan {
57464727024SZiyang Xuan u8 rss_queue_count = nic_dev->num_rss;
57564727024SZiyang Xuan
57664727024SZiyang Xuan RTE_ASSERT(rss_queue_count <= (RTE_DIM(nic_dev->rx_queue_list) - 1));
57764727024SZiyang Xuan
57864727024SZiyang Xuan nic_dev->rx_queue_list[rss_queue_count] = queue_id;
57964727024SZiyang Xuan nic_dev->num_rss++;
58064727024SZiyang Xuan }
58164727024SZiyang Xuan
58264727024SZiyang Xuan /**
58364727024SZiyang Xuan * hinic_setup_num_qps - determine num_qps from rss_tmpl_id
58464727024SZiyang Xuan * @nic_dev: pointer to the private ethernet device
58564727024SZiyang Xuan * Return: 0 on Success, error code otherwise.
58664727024SZiyang Xuan **/
hinic_setup_num_qps(struct hinic_nic_dev * nic_dev)58764727024SZiyang Xuan static int hinic_setup_num_qps(struct hinic_nic_dev *nic_dev)
58864727024SZiyang Xuan {
58964727024SZiyang Xuan int err, i;
59064727024SZiyang Xuan
591295968d1SFerruh Yigit if (!(nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG)) {
592295968d1SFerruh Yigit nic_dev->flags &= ~RTE_ETH_MQ_RX_RSS_FLAG;
59364727024SZiyang Xuan nic_dev->num_rss = 0;
59464727024SZiyang Xuan if (nic_dev->num_rq > 1) {
59564727024SZiyang Xuan /* get rss template id */
59664727024SZiyang Xuan err = hinic_rss_template_alloc(nic_dev->hwdev,
59764727024SZiyang Xuan &nic_dev->rss_tmpl_idx);
59864727024SZiyang Xuan if (err) {
59964727024SZiyang Xuan PMD_DRV_LOG(WARNING, "Alloc rss template failed");
60064727024SZiyang Xuan return err;
60164727024SZiyang Xuan }
602295968d1SFerruh Yigit nic_dev->flags |= RTE_ETH_MQ_RX_RSS_FLAG;
60364727024SZiyang Xuan for (i = 0; i < nic_dev->num_rq; i++)
60464727024SZiyang Xuan hinic_add_rq_to_rx_queue_list(nic_dev, i);
60564727024SZiyang Xuan }
60664727024SZiyang Xuan }
60764727024SZiyang Xuan
60864727024SZiyang Xuan return 0;
60964727024SZiyang Xuan }
61064727024SZiyang Xuan
hinic_destroy_num_qps(struct hinic_nic_dev * nic_dev)61164727024SZiyang Xuan static void hinic_destroy_num_qps(struct hinic_nic_dev *nic_dev)
61264727024SZiyang Xuan {
613295968d1SFerruh Yigit if (nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG) {
61464727024SZiyang Xuan if (hinic_rss_template_free(nic_dev->hwdev,
61564727024SZiyang Xuan nic_dev->rss_tmpl_idx))
61664727024SZiyang Xuan PMD_DRV_LOG(WARNING, "Free rss template failed");
61764727024SZiyang Xuan
618295968d1SFerruh Yigit nic_dev->flags &= ~RTE_ETH_MQ_RX_RSS_FLAG;
61964727024SZiyang Xuan }
62064727024SZiyang Xuan }
62164727024SZiyang Xuan
hinic_config_mq_rx_rss(struct hinic_nic_dev * nic_dev,bool on)62264727024SZiyang Xuan static int hinic_config_mq_rx_rss(struct hinic_nic_dev *nic_dev, bool on)
62364727024SZiyang Xuan {
62464727024SZiyang Xuan int ret = 0;
62564727024SZiyang Xuan
62664727024SZiyang Xuan if (on) {
62764727024SZiyang Xuan ret = hinic_setup_num_qps(nic_dev);
62864727024SZiyang Xuan if (ret)
62964727024SZiyang Xuan PMD_DRV_LOG(ERR, "Setup num_qps failed");
63064727024SZiyang Xuan } else {
63164727024SZiyang Xuan hinic_destroy_num_qps(nic_dev);
63264727024SZiyang Xuan }
63364727024SZiyang Xuan
63464727024SZiyang Xuan return ret;
63564727024SZiyang Xuan }
63664727024SZiyang Xuan
hinic_config_mq_mode(struct rte_eth_dev * dev,bool on)63764727024SZiyang Xuan int hinic_config_mq_mode(struct rte_eth_dev *dev, bool on)
63864727024SZiyang Xuan {
63964727024SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
64064727024SZiyang Xuan struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
64164727024SZiyang Xuan int ret = 0;
64264727024SZiyang Xuan
64364727024SZiyang Xuan switch (dev_conf->rxmode.mq_mode) {
644295968d1SFerruh Yigit case RTE_ETH_MQ_RX_RSS:
64564727024SZiyang Xuan ret = hinic_config_mq_rx_rss(nic_dev, on);
64664727024SZiyang Xuan break;
64764727024SZiyang Xuan default:
64864727024SZiyang Xuan break;
64964727024SZiyang Xuan }
65064727024SZiyang Xuan
65164727024SZiyang Xuan return ret;
65264727024SZiyang Xuan }
65364727024SZiyang Xuan
hinic_rx_configure(struct rte_eth_dev * dev)6542c473729SZiyang Xuan int hinic_rx_configure(struct rte_eth_dev *dev)
6552c473729SZiyang Xuan {
6562c473729SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
6572c473729SZiyang Xuan struct rte_eth_rss_conf rss_conf =
6582c473729SZiyang Xuan dev->data->dev_conf.rx_adv_conf.rss_conf;
6592c473729SZiyang Xuan int err;
6609d02f40dSXiaoyun Wang bool lro_en;
6619d02f40dSXiaoyun Wang int max_lro_size;
6629d02f40dSXiaoyun Wang int lro_wqe_num;
6639d02f40dSXiaoyun Wang int buf_size;
6642c473729SZiyang Xuan
665295968d1SFerruh Yigit if (nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG) {
6662c473729SZiyang Xuan if (rss_conf.rss_hf == 0) {
6672c473729SZiyang Xuan rss_conf.rss_hf = HINIC_RSS_OFFLOAD_ALL;
6682c473729SZiyang Xuan } else if ((rss_conf.rss_hf & HINIC_RSS_OFFLOAD_ALL) == 0) {
6692c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Do not support rss offload all");
6702c473729SZiyang Xuan goto rss_config_err;
6712c473729SZiyang Xuan }
6722c473729SZiyang Xuan
6732c473729SZiyang Xuan err = hinic_rss_init(nic_dev, NULL, &rss_conf);
6742c473729SZiyang Xuan if (err) {
6752c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Init rss failed");
6762c473729SZiyang Xuan goto rss_config_err;
6772c473729SZiyang Xuan }
6782c473729SZiyang Xuan }
6792c473729SZiyang Xuan
6802c473729SZiyang Xuan /* Enable both L3/L4 rx checksum offload */
681295968d1SFerruh Yigit if (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM)
682c3ba1f0fSXiaoyun Wang nic_dev->rx_csum_en = HINIC_RX_CSUM_OFFLOAD_EN;
6832c473729SZiyang Xuan
684c3ba1f0fSXiaoyun Wang err = hinic_set_rx_csum_offload(nic_dev->hwdev,
685c3ba1f0fSXiaoyun Wang HINIC_RX_CSUM_OFFLOAD_EN);
6862c473729SZiyang Xuan if (err)
6872c473729SZiyang Xuan goto rx_csum_ofl_err;
6882c473729SZiyang Xuan
6899d02f40dSXiaoyun Wang /* config lro */
690295968d1SFerruh Yigit lro_en = dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO ?
6919d02f40dSXiaoyun Wang true : false;
6929d02f40dSXiaoyun Wang max_lro_size = dev->data->dev_conf.rxmode.max_lro_pkt_size;
6939d02f40dSXiaoyun Wang buf_size = nic_dev->hwdev->nic_io->rq_buf_size;
6949d02f40dSXiaoyun Wang lro_wqe_num = max_lro_size / buf_size ? (max_lro_size / buf_size) : 1;
6959d02f40dSXiaoyun Wang
6969d02f40dSXiaoyun Wang err = hinic_set_rx_lro(nic_dev->hwdev, lro_en, lro_en, lro_wqe_num);
6979d02f40dSXiaoyun Wang if (err) {
6989d02f40dSXiaoyun Wang PMD_DRV_LOG(ERR, "%s %s lro failed, err: %d, max_lro_size: %d",
6999d02f40dSXiaoyun Wang dev->data->name, lro_en ? "Enable" : "Disable",
7009d02f40dSXiaoyun Wang err, max_lro_size);
7019d02f40dSXiaoyun Wang goto set_rx_lro_err;
7029d02f40dSXiaoyun Wang }
7039d02f40dSXiaoyun Wang
7042c473729SZiyang Xuan return 0;
7052c473729SZiyang Xuan
7069d02f40dSXiaoyun Wang set_rx_lro_err:
7072c473729SZiyang Xuan rx_csum_ofl_err:
7082c473729SZiyang Xuan rss_config_err:
7099d02f40dSXiaoyun Wang
7102c473729SZiyang Xuan hinic_destroy_num_qps(nic_dev);
7112c473729SZiyang Xuan
7122c473729SZiyang Xuan return HINIC_ERROR;
7132c473729SZiyang Xuan }
7142c473729SZiyang Xuan
hinic_rx_remove_lro(struct hinic_nic_dev * nic_dev)7159d02f40dSXiaoyun Wang static void hinic_rx_remove_lro(struct hinic_nic_dev *nic_dev)
7169d02f40dSXiaoyun Wang {
7179d02f40dSXiaoyun Wang int err;
7189d02f40dSXiaoyun Wang
7199d02f40dSXiaoyun Wang err = hinic_set_rx_lro(nic_dev->hwdev, false, false, 0);
7209d02f40dSXiaoyun Wang if (err)
7219d02f40dSXiaoyun Wang PMD_DRV_LOG(ERR, "%s disable LRO failed",
7229d02f40dSXiaoyun Wang nic_dev->proc_dev_name);
7239d02f40dSXiaoyun Wang }
7249d02f40dSXiaoyun Wang
hinic_rx_remove_configure(struct rte_eth_dev * dev)7252c473729SZiyang Xuan void hinic_rx_remove_configure(struct rte_eth_dev *dev)
7262c473729SZiyang Xuan {
7272c473729SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
7282c473729SZiyang Xuan
729295968d1SFerruh Yigit if (nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG) {
7302c473729SZiyang Xuan hinic_rss_deinit(nic_dev);
7312c473729SZiyang Xuan hinic_destroy_num_qps(nic_dev);
7322c473729SZiyang Xuan }
7339d02f40dSXiaoyun Wang
7349d02f40dSXiaoyun Wang hinic_rx_remove_lro(nic_dev);
7352c473729SZiyang Xuan }
7362c473729SZiyang Xuan
hinic_free_all_rx_mbufs(struct hinic_rxq * rxq)737c3ba1f0fSXiaoyun Wang void hinic_free_all_rx_mbufs(struct hinic_rxq *rxq)
73864727024SZiyang Xuan {
73964727024SZiyang Xuan struct hinic_nic_dev *nic_dev = rxq->nic_dev;
74064727024SZiyang Xuan struct hinic_rx_info *rx_info;
74164727024SZiyang Xuan int free_wqebbs =
74264727024SZiyang Xuan hinic_get_rq_free_wqebbs(nic_dev->hwdev, rxq->q_id) + 1;
74364727024SZiyang Xuan volatile struct hinic_rq_cqe *rx_cqe;
74464727024SZiyang Xuan u16 ci;
74564727024SZiyang Xuan
74664727024SZiyang Xuan while (free_wqebbs++ < rxq->q_depth) {
74764727024SZiyang Xuan ci = hinic_get_rq_local_ci(nic_dev->hwdev, rxq->q_id);
74864727024SZiyang Xuan
74964727024SZiyang Xuan rx_cqe = &rxq->rx_cqe[ci];
75064727024SZiyang Xuan
75164727024SZiyang Xuan /* clear done bit */
75264727024SZiyang Xuan rx_cqe->status = 0;
75364727024SZiyang Xuan
75464727024SZiyang Xuan rx_info = &rxq->rx_info[ci];
75564727024SZiyang Xuan rte_pktmbuf_free(rx_info->mbuf);
75664727024SZiyang Xuan rx_info->mbuf = NULL;
75764727024SZiyang Xuan
75864727024SZiyang Xuan hinic_update_rq_local_ci(nic_dev->hwdev, rxq->q_id, 1);
75964727024SZiyang Xuan }
76064727024SZiyang Xuan }
7612c473729SZiyang Xuan
hinic_rq_cqe_be_to_cpu32(void * dst_le32,volatile void * src_be32)762076221c8SZiyang Xuan static inline void hinic_rq_cqe_be_to_cpu32(void *dst_le32,
763076221c8SZiyang Xuan volatile void *src_be32)
764076221c8SZiyang Xuan {
76536f98ed2SDavid Marchand #if defined(RTE_ARCH_X86_64)
766076221c8SZiyang Xuan volatile __m128i *wqe_be = (volatile __m128i *)src_be32;
767076221c8SZiyang Xuan __m128i *wqe_le = (__m128i *)dst_le32;
768076221c8SZiyang Xuan __m128i shuf_mask = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10,
769076221c8SZiyang Xuan 11, 4, 5, 6, 7, 0, 1, 2, 3);
770076221c8SZiyang Xuan
771076221c8SZiyang Xuan /* l2nic just use first 128 bits */
772076221c8SZiyang Xuan wqe_le[0] = _mm_shuffle_epi8(wqe_be[0], shuf_mask);
77336f98ed2SDavid Marchand #elif defined(RTE_ARCH_ARM64)
774076221c8SZiyang Xuan volatile uint8x16_t *wqe_be = (volatile uint8x16_t *)src_be32;
775076221c8SZiyang Xuan uint8x16_t *wqe_le = (uint8x16_t *)dst_le32;
776076221c8SZiyang Xuan const uint8x16_t shuf_mask = {3, 2, 1, 0, 7, 6, 5, 4, 11, 10,
777076221c8SZiyang Xuan 9, 8, 15, 14, 13, 12};
778076221c8SZiyang Xuan
779076221c8SZiyang Xuan /* l2nic just use first 128 bits */
780076221c8SZiyang Xuan wqe_le[0] = vqtbl1q_u8(wqe_be[0], shuf_mask);
781076221c8SZiyang Xuan #else
782076221c8SZiyang Xuan u32 i;
783076221c8SZiyang Xuan volatile u32 *wqe_be = (volatile u32 *)src_be32;
784076221c8SZiyang Xuan u32 *wqe_le = (u32 *)dst_le32;
785076221c8SZiyang Xuan
786076221c8SZiyang Xuan #define HINIC_L2NIC_RQ_CQE_USED 4 /* 4Bytes unit */
787076221c8SZiyang Xuan
788076221c8SZiyang Xuan for (i = 0; i < HINIC_L2NIC_RQ_CQE_USED; i++) {
789076221c8SZiyang Xuan *wqe_le = rte_be_to_cpu_32(*wqe_be);
790076221c8SZiyang Xuan wqe_be++;
791076221c8SZiyang Xuan wqe_le++;
792076221c8SZiyang Xuan }
793076221c8SZiyang Xuan #endif
794076221c8SZiyang Xuan }
795076221c8SZiyang Xuan
hinic_rx_rss_hash(uint32_t offload_type,uint32_t cqe_hass_val,uint32_t * rss_hash)796076221c8SZiyang Xuan static inline uint64_t hinic_rx_rss_hash(uint32_t offload_type,
797076221c8SZiyang Xuan uint32_t cqe_hass_val,
798076221c8SZiyang Xuan uint32_t *rss_hash)
799076221c8SZiyang Xuan {
800076221c8SZiyang Xuan uint32_t rss_type;
801076221c8SZiyang Xuan
802076221c8SZiyang Xuan rss_type = HINIC_GET_RSS_TYPES(offload_type);
803076221c8SZiyang Xuan if (likely(rss_type != 0)) {
804076221c8SZiyang Xuan *rss_hash = cqe_hass_val;
805daa02b5cSOlivier Matz return RTE_MBUF_F_RX_RSS_HASH;
806076221c8SZiyang Xuan }
807076221c8SZiyang Xuan
808076221c8SZiyang Xuan return 0;
809076221c8SZiyang Xuan }
810076221c8SZiyang Xuan
hinic_rx_csum(uint32_t status,struct hinic_rxq * rxq)811076221c8SZiyang Xuan static inline uint64_t hinic_rx_csum(uint32_t status, struct hinic_rxq *rxq)
812076221c8SZiyang Xuan {
813076221c8SZiyang Xuan uint32_t checksum_err;
814076221c8SZiyang Xuan uint64_t flags;
815c3ba1f0fSXiaoyun Wang struct hinic_nic_dev *nic_dev = rxq->nic_dev;
816c3ba1f0fSXiaoyun Wang
817c3ba1f0fSXiaoyun Wang if (unlikely(!(nic_dev->rx_csum_en & HINIC_RX_CSUM_OFFLOAD_EN)))
818daa02b5cSOlivier Matz return RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN;
819076221c8SZiyang Xuan
820076221c8SZiyang Xuan /* most case checksum is ok */
821076221c8SZiyang Xuan checksum_err = HINIC_GET_RX_CSUM_ERR(status);
822076221c8SZiyang Xuan if (likely(checksum_err == 0))
823daa02b5cSOlivier Matz return (RTE_MBUF_F_RX_IP_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD);
824076221c8SZiyang Xuan
825076221c8SZiyang Xuan /* If BYPASS bit set, all other status indications should be ignored */
826076221c8SZiyang Xuan if (unlikely(HINIC_CSUM_ERR_BYPASSED(checksum_err)))
827daa02b5cSOlivier Matz return RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN;
828076221c8SZiyang Xuan
829076221c8SZiyang Xuan flags = 0;
830076221c8SZiyang Xuan
831076221c8SZiyang Xuan /* IP checksum error */
832076221c8SZiyang Xuan if (HINIC_CSUM_ERR_IP(checksum_err))
833daa02b5cSOlivier Matz flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
834076221c8SZiyang Xuan else
835daa02b5cSOlivier Matz flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
836076221c8SZiyang Xuan
837076221c8SZiyang Xuan /* L4 checksum error */
838076221c8SZiyang Xuan if (HINIC_CSUM_ERR_L4(checksum_err))
839daa02b5cSOlivier Matz flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
840076221c8SZiyang Xuan else
841daa02b5cSOlivier Matz flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
842076221c8SZiyang Xuan
843076221c8SZiyang Xuan if (unlikely(HINIC_CSUM_ERR_OTHER(checksum_err)))
844daa02b5cSOlivier Matz flags = RTE_MBUF_F_RX_L4_CKSUM_NONE;
845076221c8SZiyang Xuan
846076221c8SZiyang Xuan rxq->rxq_stats.errors++;
847076221c8SZiyang Xuan
848076221c8SZiyang Xuan return flags;
849076221c8SZiyang Xuan }
850076221c8SZiyang Xuan
hinic_rx_vlan(uint32_t offload_type,uint32_t vlan_len,uint16_t * vlan_tci)851076221c8SZiyang Xuan static inline uint64_t hinic_rx_vlan(uint32_t offload_type, uint32_t vlan_len,
852076221c8SZiyang Xuan uint16_t *vlan_tci)
853076221c8SZiyang Xuan {
854076221c8SZiyang Xuan uint16_t vlan_tag;
855076221c8SZiyang Xuan
856076221c8SZiyang Xuan vlan_tag = HINIC_GET_RX_VLAN_TAG(vlan_len);
857076221c8SZiyang Xuan if (!HINIC_GET_RX_VLAN_OFFLOAD_EN(offload_type) || 0 == vlan_tag) {
858076221c8SZiyang Xuan *vlan_tci = 0;
859076221c8SZiyang Xuan return 0;
860076221c8SZiyang Xuan }
861076221c8SZiyang Xuan
862076221c8SZiyang Xuan *vlan_tci = vlan_tag;
863076221c8SZiyang Xuan
864daa02b5cSOlivier Matz return RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
865076221c8SZiyang Xuan }
866076221c8SZiyang Xuan
hinic_rx_alloc_mbuf_bulk(struct hinic_rxq * rxq,struct rte_mbuf ** mbufs,u32 exp_mbuf_cnt)867076221c8SZiyang Xuan static inline u32 hinic_rx_alloc_mbuf_bulk(struct hinic_rxq *rxq,
868076221c8SZiyang Xuan struct rte_mbuf **mbufs,
869076221c8SZiyang Xuan u32 exp_mbuf_cnt)
870076221c8SZiyang Xuan {
871076221c8SZiyang Xuan int rc;
872076221c8SZiyang Xuan u32 avail_cnt;
873076221c8SZiyang Xuan
874076221c8SZiyang Xuan rc = rte_pktmbuf_alloc_bulk(rxq->mb_pool, mbufs, exp_mbuf_cnt);
875076221c8SZiyang Xuan if (likely(rc == HINIC_OK)) {
876076221c8SZiyang Xuan avail_cnt = exp_mbuf_cnt;
877076221c8SZiyang Xuan } else {
878076221c8SZiyang Xuan avail_cnt = 0;
879076221c8SZiyang Xuan rxq->rxq_stats.rx_nombuf += exp_mbuf_cnt;
880076221c8SZiyang Xuan }
881076221c8SZiyang Xuan
882076221c8SZiyang Xuan return avail_cnt;
883076221c8SZiyang Xuan }
884076221c8SZiyang Xuan
hinic_rx_alloc_mbuf(struct hinic_rxq * rxq,dma_addr_t * dma_addr)8852c473729SZiyang Xuan static struct rte_mbuf *hinic_rx_alloc_mbuf(struct hinic_rxq *rxq,
8862c473729SZiyang Xuan dma_addr_t *dma_addr)
8872c473729SZiyang Xuan {
888abd41e3dSXiaoyun Wang struct rte_mbuf *mbuf = NULL;
889abd41e3dSXiaoyun Wang int rc;
8902c473729SZiyang Xuan
891abd41e3dSXiaoyun Wang rc = rte_pktmbuf_alloc_bulk(rxq->mb_pool, &mbuf, 1);
892abd41e3dSXiaoyun Wang if (unlikely(rc != HINIC_OK))
8932c473729SZiyang Xuan return NULL;
8942c473729SZiyang Xuan
8952c473729SZiyang Xuan *dma_addr = rte_mbuf_data_iova_default(mbuf);
8962c473729SZiyang Xuan
8972c473729SZiyang Xuan return mbuf;
8982c473729SZiyang Xuan }
8992c473729SZiyang Xuan
hinic_rearm_rxq_mbuf(struct hinic_rxq * rxq)900076221c8SZiyang Xuan static inline void hinic_rearm_rxq_mbuf(struct hinic_rxq *rxq)
901076221c8SZiyang Xuan {
902076221c8SZiyang Xuan u16 pi;
903076221c8SZiyang Xuan u32 i, free_wqebbs, rearm_wqebbs, exp_wqebbs;
904076221c8SZiyang Xuan dma_addr_t dma_addr;
905076221c8SZiyang Xuan struct hinic_rq_wqe *rq_wqe;
906076221c8SZiyang Xuan struct rte_mbuf **rearm_mbufs;
907076221c8SZiyang Xuan
908076221c8SZiyang Xuan /* check free wqebb fo rearm */
909076221c8SZiyang Xuan free_wqebbs = HINIC_GET_RQ_FREE_WQEBBS(rxq);
910076221c8SZiyang Xuan if (unlikely(free_wqebbs < rxq->rx_free_thresh))
911076221c8SZiyang Xuan return;
912076221c8SZiyang Xuan
913076221c8SZiyang Xuan /* get rearm mbuf array */
914076221c8SZiyang Xuan pi = HINIC_GET_RQ_LOCAL_PI(rxq);
915076221c8SZiyang Xuan rearm_mbufs = (struct rte_mbuf **)(&rxq->rx_info[pi]);
916076221c8SZiyang Xuan
917076221c8SZiyang Xuan /* check rxq free wqebbs turn around */
918076221c8SZiyang Xuan exp_wqebbs = rxq->q_depth - pi;
919076221c8SZiyang Xuan if (free_wqebbs < exp_wqebbs)
920076221c8SZiyang Xuan exp_wqebbs = free_wqebbs;
921076221c8SZiyang Xuan
922076221c8SZiyang Xuan /* alloc mbuf in bulk */
923076221c8SZiyang Xuan rearm_wqebbs = hinic_rx_alloc_mbuf_bulk(rxq, rearm_mbufs, exp_wqebbs);
924076221c8SZiyang Xuan if (unlikely(rearm_wqebbs == 0))
925076221c8SZiyang Xuan return;
926076221c8SZiyang Xuan
927076221c8SZiyang Xuan /* rearm rx mbuf */
928076221c8SZiyang Xuan rq_wqe = WQ_WQE_ADDR(rxq->wq, (u32)pi);
929076221c8SZiyang Xuan for (i = 0; i < rearm_wqebbs; i++) {
930076221c8SZiyang Xuan dma_addr = rte_mbuf_data_iova_default(rearm_mbufs[i]);
931076221c8SZiyang Xuan rq_wqe->buf_desc.addr_high =
932076221c8SZiyang Xuan cpu_to_be32(upper_32_bits(dma_addr));
933076221c8SZiyang Xuan rq_wqe->buf_desc.addr_low =
934076221c8SZiyang Xuan cpu_to_be32(lower_32_bits(dma_addr));
935076221c8SZiyang Xuan rq_wqe++;
936076221c8SZiyang Xuan }
937076221c8SZiyang Xuan rxq->wq->prod_idx += rearm_wqebbs;
938076221c8SZiyang Xuan rxq->wq->delta -= rearm_wqebbs;
939076221c8SZiyang Xuan
940076221c8SZiyang Xuan /* update rq hw_pi */
941076221c8SZiyang Xuan rte_wmb();
942076221c8SZiyang Xuan HINIC_UPDATE_RQ_HW_PI(rxq, pi + rearm_wqebbs);
943076221c8SZiyang Xuan }
944076221c8SZiyang Xuan
hinic_rx_alloc_pkts(struct hinic_rxq * rxq)9452c473729SZiyang Xuan void hinic_rx_alloc_pkts(struct hinic_rxq *rxq)
9462c473729SZiyang Xuan {
9472c473729SZiyang Xuan struct hinic_nic_dev *nic_dev = rxq->nic_dev;
9482c473729SZiyang Xuan struct hinic_rq_wqe *rq_wqe;
9492c473729SZiyang Xuan struct hinic_rx_info *rx_info;
9502c473729SZiyang Xuan struct rte_mbuf *mb;
9512c473729SZiyang Xuan dma_addr_t dma_addr;
9522c473729SZiyang Xuan u16 pi = 0;
9532c473729SZiyang Xuan int i, free_wqebbs;
9542c473729SZiyang Xuan
9552c473729SZiyang Xuan free_wqebbs = HINIC_GET_RQ_FREE_WQEBBS(rxq);
9562c473729SZiyang Xuan for (i = 0; i < free_wqebbs; i++) {
9572c473729SZiyang Xuan mb = hinic_rx_alloc_mbuf(rxq, &dma_addr);
9582c473729SZiyang Xuan if (unlikely(!mb)) {
9592c473729SZiyang Xuan rxq->rxq_stats.rx_nombuf++;
9602c473729SZiyang Xuan break;
9612c473729SZiyang Xuan }
9622c473729SZiyang Xuan
9632c473729SZiyang Xuan rq_wqe = hinic_get_rq_wqe(nic_dev->hwdev, rxq->q_id, &pi);
9642c473729SZiyang Xuan if (unlikely(!rq_wqe)) {
9652c473729SZiyang Xuan rte_pktmbuf_free(mb);
9662c473729SZiyang Xuan break;
9672c473729SZiyang Xuan }
9682c473729SZiyang Xuan
9692c473729SZiyang Xuan /* fill buffer address only */
9702c473729SZiyang Xuan rq_wqe->buf_desc.addr_high =
9712c473729SZiyang Xuan cpu_to_be32(upper_32_bits(dma_addr));
9722c473729SZiyang Xuan rq_wqe->buf_desc.addr_low =
9732c473729SZiyang Xuan cpu_to_be32(lower_32_bits(dma_addr));
9742c473729SZiyang Xuan
9752c473729SZiyang Xuan rx_info = &rxq->rx_info[pi];
9762c473729SZiyang Xuan rx_info->mbuf = mb;
9772c473729SZiyang Xuan }
9782c473729SZiyang Xuan
9792c473729SZiyang Xuan if (likely(i > 0)) {
9802c473729SZiyang Xuan rte_wmb();
9812c473729SZiyang Xuan HINIC_UPDATE_RQ_HW_PI(rxq, pi + 1);
9822c473729SZiyang Xuan }
9832c473729SZiyang Xuan }
984076221c8SZiyang Xuan
hinic_recv_pkts(void * rx_queue,struct rte_mbuf ** rx_pkts,u16 nb_pkts)985076221c8SZiyang Xuan u16 hinic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, u16 nb_pkts)
986076221c8SZiyang Xuan {
987076221c8SZiyang Xuan struct rte_mbuf *rxm;
988076221c8SZiyang Xuan struct hinic_rxq *rxq = rx_queue;
989076221c8SZiyang Xuan struct hinic_rx_info *rx_info;
990076221c8SZiyang Xuan volatile struct hinic_rq_cqe *rx_cqe;
991076221c8SZiyang Xuan u16 rx_buf_len, pkts = 0;
992076221c8SZiyang Xuan u16 sw_ci, ci_mask, wqebb_cnt = 0;
9939d02f40dSXiaoyun Wang u32 pkt_len, status, vlan_len, lro_num;
994076221c8SZiyang Xuan u64 rx_bytes = 0;
995076221c8SZiyang Xuan struct hinic_rq_cqe cqe;
996076221c8SZiyang Xuan u32 offload_type, rss_hash;
997076221c8SZiyang Xuan
998076221c8SZiyang Xuan rx_buf_len = rxq->buf_len;
999076221c8SZiyang Xuan
1000076221c8SZiyang Xuan /* 1. get polling start ci */
1001076221c8SZiyang Xuan ci_mask = HINIC_GET_RQ_WQE_MASK(rxq);
1002076221c8SZiyang Xuan sw_ci = HINIC_GET_RQ_LOCAL_CI(rxq);
1003076221c8SZiyang Xuan
1004076221c8SZiyang Xuan while (pkts < nb_pkts) {
1005076221c8SZiyang Xuan /* 2. current ci is done */
1006076221c8SZiyang Xuan rx_cqe = &rxq->rx_cqe[sw_ci];
1007*e12a0166STyler Retzlaff status = rte_atomic_load_explicit(&rx_cqe->status, rte_memory_order_acquire);
1008076221c8SZiyang Xuan if (!HINIC_GET_RX_DONE_BE(status))
1009076221c8SZiyang Xuan break;
1010076221c8SZiyang Xuan
1011076221c8SZiyang Xuan /* convert cqe and get packet length */
1012076221c8SZiyang Xuan hinic_rq_cqe_be_to_cpu32(&cqe, (volatile void *)rx_cqe);
1013076221c8SZiyang Xuan vlan_len = cqe.vlan_len;
1014076221c8SZiyang Xuan
1015076221c8SZiyang Xuan rx_info = &rxq->rx_info[sw_ci];
1016076221c8SZiyang Xuan rxm = rx_info->mbuf;
1017076221c8SZiyang Xuan
1018076221c8SZiyang Xuan /* 3. next ci point and prefetch */
1019076221c8SZiyang Xuan sw_ci++;
1020076221c8SZiyang Xuan sw_ci &= ci_mask;
1021076221c8SZiyang Xuan
1022076221c8SZiyang Xuan /* prefetch next mbuf first 64B */
1023076221c8SZiyang Xuan rte_prefetch0(rxq->rx_info[sw_ci].mbuf);
1024076221c8SZiyang Xuan
1025076221c8SZiyang Xuan /* 4. jumbo frame process */
1026076221c8SZiyang Xuan pkt_len = HINIC_GET_RX_PKT_LEN(vlan_len);
1027076221c8SZiyang Xuan if (likely(pkt_len <= rx_buf_len)) {
1028076221c8SZiyang Xuan rxm->data_len = pkt_len;
1029076221c8SZiyang Xuan rxm->pkt_len = pkt_len;
1030076221c8SZiyang Xuan wqebb_cnt++;
1031076221c8SZiyang Xuan } else {
1032076221c8SZiyang Xuan rxm->data_len = rx_buf_len;
1033076221c8SZiyang Xuan rxm->pkt_len = rx_buf_len;
1034076221c8SZiyang Xuan
1035c3ba1f0fSXiaoyun Wang /* if receive jumbo, updating ci will be done by
1036c3ba1f0fSXiaoyun Wang * hinic_recv_jumbo_pkt function.
1037076221c8SZiyang Xuan */
1038076221c8SZiyang Xuan HINIC_UPDATE_RQ_LOCAL_CI(rxq, wqebb_cnt + 1);
1039076221c8SZiyang Xuan wqebb_cnt = 0;
1040076221c8SZiyang Xuan hinic_recv_jumbo_pkt(rxq, rxm, pkt_len - rx_buf_len);
1041076221c8SZiyang Xuan sw_ci = HINIC_GET_RQ_LOCAL_CI(rxq);
1042076221c8SZiyang Xuan }
1043076221c8SZiyang Xuan
1044076221c8SZiyang Xuan /* 5. vlan/checksum/rss/pkt_type/gro offload */
1045076221c8SZiyang Xuan rxm->data_off = RTE_PKTMBUF_HEADROOM;
1046076221c8SZiyang Xuan rxm->port = rxq->port_id;
1047076221c8SZiyang Xuan offload_type = cqe.offload_type;
1048076221c8SZiyang Xuan
1049076221c8SZiyang Xuan /* vlan offload */
1050076221c8SZiyang Xuan rxm->ol_flags |= hinic_rx_vlan(offload_type, vlan_len,
1051076221c8SZiyang Xuan &rxm->vlan_tci);
1052076221c8SZiyang Xuan
1053076221c8SZiyang Xuan /* checksum offload */
1054076221c8SZiyang Xuan rxm->ol_flags |= hinic_rx_csum(cqe.status, rxq);
1055076221c8SZiyang Xuan
1056076221c8SZiyang Xuan /* rss hash offload */
1057076221c8SZiyang Xuan rss_hash = cqe.rss_hash;
1058076221c8SZiyang Xuan rxm->ol_flags |= hinic_rx_rss_hash(offload_type, rss_hash,
1059076221c8SZiyang Xuan &rxm->hash.rss);
1060076221c8SZiyang Xuan
10619d02f40dSXiaoyun Wang /* lro offload */
10629d02f40dSXiaoyun Wang lro_num = HINIC_GET_RX_NUM_LRO(cqe.status);
10639d02f40dSXiaoyun Wang if (unlikely(lro_num != 0)) {
1064daa02b5cSOlivier Matz rxm->ol_flags |= RTE_MBUF_F_RX_LRO;
10659d02f40dSXiaoyun Wang rxm->tso_segsz = pkt_len / lro_num;
10669d02f40dSXiaoyun Wang }
10679d02f40dSXiaoyun Wang
1068076221c8SZiyang Xuan /* 6. clear done bit */
1069076221c8SZiyang Xuan rx_cqe->status = 0;
1070076221c8SZiyang Xuan
1071076221c8SZiyang Xuan rx_bytes += pkt_len;
1072076221c8SZiyang Xuan rx_pkts[pkts++] = rxm;
1073076221c8SZiyang Xuan }
1074076221c8SZiyang Xuan
1075076221c8SZiyang Xuan if (pkts) {
1076076221c8SZiyang Xuan /* 7. update ci */
1077076221c8SZiyang Xuan HINIC_UPDATE_RQ_LOCAL_CI(rxq, wqebb_cnt);
1078076221c8SZiyang Xuan
1079076221c8SZiyang Xuan /* do packet stats */
1080076221c8SZiyang Xuan rxq->rxq_stats.packets += pkts;
1081076221c8SZiyang Xuan rxq->rxq_stats.bytes += rx_bytes;
1082076221c8SZiyang Xuan }
1083076221c8SZiyang Xuan rxq->rxq_stats.burst_pkts = pkts;
1084076221c8SZiyang Xuan
1085076221c8SZiyang Xuan /* 8. rearm mbuf to rxq */
1086076221c8SZiyang Xuan hinic_rearm_rxq_mbuf(rxq);
1087076221c8SZiyang Xuan
1088076221c8SZiyang Xuan return pkts;
1089076221c8SZiyang Xuan }
1090