xref: /dpdk/drivers/net/hinic/hinic_pmd_rx.c (revision e12a0166c80f65e35408f4715b2f3a60763c3741)
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