Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2017 Huawei Technologies Co., Ltd
3 : : */
4 : :
5 : : #include <rte_ether.h>
6 : : #include <rte_mbuf.h>
7 : : #ifdef RTE_ARCH_ARM64
8 : : #include <arm_neon.h>
9 : : #endif
10 : :
11 : : #include "base/hinic_compat.h"
12 : : #include "base/hinic_pmd_hwdev.h"
13 : : #include "base/hinic_pmd_wq.h"
14 : : #include "base/hinic_pmd_niccfg.h"
15 : : #include "base/hinic_pmd_nicio.h"
16 : : #include "hinic_pmd_ethdev.h"
17 : : #include "hinic_pmd_rx.h"
18 : :
19 : : /* rxq wq operations */
20 : : #define HINIC_GET_RQ_WQE_MASK(rxq) \
21 : : ((rxq)->wq->mask)
22 : :
23 : : #define HINIC_GET_RQ_LOCAL_CI(rxq) \
24 : : (((rxq)->wq->cons_idx) & HINIC_GET_RQ_WQE_MASK(rxq))
25 : :
26 : : #define HINIC_GET_RQ_LOCAL_PI(rxq) \
27 : : (((rxq)->wq->prod_idx) & HINIC_GET_RQ_WQE_MASK(rxq))
28 : :
29 : : #define HINIC_UPDATE_RQ_LOCAL_CI(rxq, wqebb_cnt) \
30 : : do { \
31 : : (rxq)->wq->cons_idx += (wqebb_cnt); \
32 : : (rxq)->wq->delta += (wqebb_cnt); \
33 : : } while (0)
34 : :
35 : : #define HINIC_UPDATE_RQ_HW_PI(rxq, pi) \
36 : : (*((rxq)->pi_virt_addr) = \
37 : : cpu_to_be16((pi) & HINIC_GET_RQ_WQE_MASK(rxq)))
38 : :
39 : : #define HINIC_GET_RQ_FREE_WQEBBS(rxq) ((rxq)->wq->delta - 1)
40 : :
41 : : /* rxq cqe done and status bit */
42 : : #define HINIC_GET_RX_DONE_BE(status) \
43 : : ((status) & 0x80U)
44 : :
45 : : #define HINIC_RX_CSUM_OFFLOAD_EN 0xFFF
46 : :
47 : : #define RQ_CQE_SGE_VLAN_SHIFT 0
48 : : #define RQ_CQE_SGE_LEN_SHIFT 16
49 : :
50 : : #define RQ_CQE_SGE_VLAN_MASK 0xFFFFU
51 : : #define RQ_CQE_SGE_LEN_MASK 0xFFFFU
52 : :
53 : : #define RQ_CQE_SGE_GET(val, member) \
54 : : (((val) >> RQ_CQE_SGE_##member##_SHIFT) & RQ_CQE_SGE_##member##_MASK)
55 : :
56 : : #define HINIC_GET_RX_VLAN_TAG(vlan_len) \
57 : : RQ_CQE_SGE_GET(vlan_len, VLAN)
58 : :
59 : : #define HINIC_GET_RX_PKT_LEN(vlan_len) \
60 : : RQ_CQE_SGE_GET(vlan_len, LEN)
61 : :
62 : : #define RQ_CQE_STATUS_CSUM_ERR_SHIFT 0
63 : : #define RQ_CQE_STATUS_NUM_LRO_SHIFT 16
64 : : #define RQ_CQE_STATUS_LRO_PUSH_SHIFT 25
65 : : #define RQ_CQE_STATUS_LRO_ENTER_SHIFT 26
66 : : #define RQ_CQE_STATUS_LRO_INTR_SHIFT 27
67 : :
68 : : #define RQ_CQE_STATUS_BP_EN_SHIFT 30
69 : : #define RQ_CQE_STATUS_RXDONE_SHIFT 31
70 : : #define RQ_CQE_STATUS_FLUSH_SHIFT 28
71 : :
72 : : #define RQ_CQE_STATUS_CSUM_ERR_MASK 0xFFFFU
73 : : #define RQ_CQE_STATUS_NUM_LRO_MASK 0xFFU
74 : : #define RQ_CQE_STATUS_LRO_PUSH_MASK 0X1U
75 : : #define RQ_CQE_STATUS_LRO_ENTER_MASK 0X1U
76 : : #define RQ_CQE_STATUS_LRO_INTR_MASK 0X1U
77 : : #define RQ_CQE_STATUS_BP_EN_MASK 0X1U
78 : : #define RQ_CQE_STATUS_RXDONE_MASK 0x1U
79 : : #define RQ_CQE_STATUS_FLUSH_MASK 0x1U
80 : :
81 : : #define RQ_CQE_STATUS_GET(val, member) \
82 : : (((val) >> RQ_CQE_STATUS_##member##_SHIFT) & \
83 : : RQ_CQE_STATUS_##member##_MASK)
84 : :
85 : : #define RQ_CQE_STATUS_CLEAR(val, member) \
86 : : ((val) & (~(RQ_CQE_STATUS_##member##_MASK << \
87 : : RQ_CQE_STATUS_##member##_SHIFT)))
88 : :
89 : : #define HINIC_GET_RX_CSUM_ERR(status) \
90 : : RQ_CQE_STATUS_GET(status, CSUM_ERR)
91 : :
92 : : #define HINIC_GET_RX_DONE(status) \
93 : : RQ_CQE_STATUS_GET(status, RXDONE)
94 : :
95 : : #define HINIC_GET_RX_FLUSH(status) \
96 : : RQ_CQE_STATUS_GET(status, FLUSH)
97 : :
98 : : #define HINIC_GET_RX_BP_EN(status) \
99 : : RQ_CQE_STATUS_GET(status, BP_EN)
100 : :
101 : : #define HINIC_GET_RX_NUM_LRO(status) \
102 : : RQ_CQE_STATUS_GET(status, NUM_LRO)
103 : :
104 : : /* RQ_CTRL */
105 : : #define RQ_CTRL_BUFDESC_SECT_LEN_SHIFT 0
106 : : #define RQ_CTRL_COMPLETE_FORMAT_SHIFT 15
107 : : #define RQ_CTRL_COMPLETE_LEN_SHIFT 27
108 : : #define RQ_CTRL_LEN_SHIFT 29
109 : :
110 : : #define RQ_CTRL_BUFDESC_SECT_LEN_MASK 0xFFU
111 : : #define RQ_CTRL_COMPLETE_FORMAT_MASK 0x1U
112 : : #define RQ_CTRL_COMPLETE_LEN_MASK 0x3U
113 : : #define RQ_CTRL_LEN_MASK 0x3U
114 : :
115 : : #define RQ_CTRL_SET(val, member) \
116 : : (((val) & RQ_CTRL_##member##_MASK) << RQ_CTRL_##member##_SHIFT)
117 : :
118 : : #define RQ_CTRL_GET(val, member) \
119 : : (((val) >> RQ_CTRL_##member##_SHIFT) & RQ_CTRL_##member##_MASK)
120 : :
121 : : #define RQ_CTRL_CLEAR(val, member) \
122 : : ((val) & (~(RQ_CTRL_##member##_MASK << RQ_CTRL_##member##_SHIFT)))
123 : :
124 : : #define RQ_CQE_PKT_NUM_SHIFT 1
125 : : #define RQ_CQE_PKT_FIRST_LEN_SHIFT 19
126 : : #define RQ_CQE_PKT_LAST_LEN_SHIFT 6
127 : : #define RQ_CQE_SUPER_CQE_EN_SHIFT 0
128 : :
129 : : #define RQ_CQE_PKT_FIRST_LEN_MASK 0x1FFFU
130 : : #define RQ_CQE_PKT_LAST_LEN_MASK 0x1FFFU
131 : : #define RQ_CQE_PKT_NUM_MASK 0x1FU
132 : : #define RQ_CQE_SUPER_CQE_EN_MASK 0x1
133 : :
134 : : #define RQ_CQE_PKT_NUM_GET(val, member) \
135 : : (((val) >> RQ_CQE_PKT_##member##_SHIFT) & RQ_CQE_PKT_##member##_MASK)
136 : :
137 : : #define HINIC_GET_RQ_CQE_PKT_NUM(pkt_info) RQ_CQE_PKT_NUM_GET(pkt_info, NUM)
138 : :
139 : : #define RQ_CQE_SUPER_CQE_EN_GET(val, member) \
140 : : (((val) >> RQ_CQE_##member##_SHIFT) & RQ_CQE_##member##_MASK)
141 : :
142 : : #define HINIC_GET_SUPER_CQE_EN(pkt_info) \
143 : : RQ_CQE_SUPER_CQE_EN_GET(pkt_info, SUPER_CQE_EN)
144 : :
145 : : #define RQ_CQE_OFFOLAD_TYPE_VLAN_EN_SHIFT 21
146 : : #define RQ_CQE_OFFOLAD_TYPE_VLAN_EN_MASK 0x1U
147 : :
148 : : #define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_SHIFT 0
149 : : #define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_MASK 0xFFFU
150 : :
151 : : #define RQ_CQE_OFFOLAD_TYPE_PKT_UMBCAST_SHIFT 19
152 : : #define RQ_CQE_OFFOLAD_TYPE_PKT_UMBCAST_MASK 0x3U
153 : :
154 : : #define RQ_CQE_OFFOLAD_TYPE_RSS_TYPE_SHIFT 24
155 : : #define RQ_CQE_OFFOLAD_TYPE_RSS_TYPE_MASK 0xFFU
156 : :
157 : : #define RQ_CQE_OFFOLAD_TYPE_GET(val, member) (((val) >> \
158 : : RQ_CQE_OFFOLAD_TYPE_##member##_SHIFT) & \
159 : : RQ_CQE_OFFOLAD_TYPE_##member##_MASK)
160 : :
161 : : #define HINIC_GET_RX_VLAN_OFFLOAD_EN(offload_type) \
162 : : RQ_CQE_OFFOLAD_TYPE_GET(offload_type, VLAN_EN)
163 : :
164 : : #define HINIC_GET_RSS_TYPES(offload_type) \
165 : : RQ_CQE_OFFOLAD_TYPE_GET(offload_type, RSS_TYPE)
166 : :
167 : : #define HINIC_GET_RX_PKT_TYPE(offload_type) \
168 : : RQ_CQE_OFFOLAD_TYPE_GET(offload_type, PKT_TYPE)
169 : :
170 : : #define HINIC_GET_RX_PKT_UMBCAST(offload_type) \
171 : : RQ_CQE_OFFOLAD_TYPE_GET(offload_type, PKT_UMBCAST)
172 : :
173 : : #define RQ_CQE_STATUS_CSUM_BYPASS_VAL 0x80U
174 : : #define RQ_CQE_STATUS_CSUM_ERR_IP_MASK 0x39U
175 : : #define RQ_CQE_STATUS_CSUM_ERR_L4_MASK 0x46U
176 : : #define RQ_CQE_STATUS_CSUM_ERR_OTHER 0x100U
177 : :
178 : : #define HINIC_CSUM_ERR_BYPASSED(csum_err) \
179 : : ((csum_err) == RQ_CQE_STATUS_CSUM_BYPASS_VAL)
180 : :
181 : : #define HINIC_CSUM_ERR_IP(csum_err) \
182 : : ((csum_err) & RQ_CQE_STATUS_CSUM_ERR_IP_MASK)
183 : :
184 : : #define HINIC_CSUM_ERR_L4(csum_err) \
185 : : ((csum_err) & RQ_CQE_STATUS_CSUM_ERR_L4_MASK)
186 : :
187 : : #define HINIC_CSUM_ERR_OTHER(csum_err) \
188 : : ((csum_err) == RQ_CQE_STATUS_CSUM_ERR_OTHER)
189 : :
190 : :
191 : 0 : void hinic_get_func_rx_buf_size(struct hinic_nic_dev *nic_dev)
192 : : {
193 : : struct hinic_rxq *rxq;
194 : : u16 q_id;
195 : : u16 buf_size = 0;
196 : :
197 [ # # ]: 0 : for (q_id = 0; q_id < nic_dev->num_rq; q_id++) {
198 : 0 : rxq = nic_dev->rxqs[q_id];
199 : :
200 [ # # ]: 0 : if (rxq == NULL)
201 : 0 : continue;
202 : :
203 [ # # ]: 0 : if (q_id == 0)
204 : 0 : buf_size = rxq->buf_len;
205 : :
206 : 0 : buf_size = buf_size > rxq->buf_len ? rxq->buf_len : buf_size;
207 : : }
208 : :
209 : 0 : nic_dev->hwdev->nic_io->rq_buf_size = buf_size;
210 : 0 : }
211 : :
212 : 0 : int hinic_create_rq(struct hinic_hwdev *hwdev, u16 q_id,
213 : : u16 rq_depth, unsigned int socket_id)
214 : : {
215 : : int err;
216 : 0 : struct hinic_nic_io *nic_io = hwdev->nic_io;
217 : 0 : struct hinic_qp *qp = &nic_io->qps[q_id];
218 : : struct hinic_rq *rq = &qp->rq;
219 : :
220 : : /* in case of hardware still generate interrupt, do not use msix 0 */
221 : 0 : rq->msix_entry_idx = 1;
222 : 0 : rq->q_id = q_id;
223 : 0 : rq->rq_depth = rq_depth;
224 : 0 : nic_io->rq_depth = rq_depth;
225 : :
226 : 0 : err = hinic_wq_allocate(hwdev, &nic_io->rq_wq[q_id],
227 : : HINIC_RQ_WQEBB_SHIFT, nic_io->rq_depth, socket_id);
228 [ # # ]: 0 : if (err) {
229 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate WQ for RQ");
230 : 0 : return err;
231 : : }
232 : 0 : rq->wq = &nic_io->rq_wq[q_id];
233 : :
234 : 0 : rq->pi_virt_addr = (volatile u16 *)dma_zalloc_coherent(hwdev,
235 : : HINIC_PAGE_SIZE, &rq->pi_dma_addr, socket_id);
236 [ # # ]: 0 : if (!rq->pi_virt_addr) {
237 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate rq pi virt addr");
238 : : err = -ENOMEM;
239 : 0 : goto rq_pi_alloc_err;
240 : : }
241 : :
242 : : return HINIC_OK;
243 : :
244 : : rq_pi_alloc_err:
245 : 0 : hinic_wq_free(hwdev, &nic_io->rq_wq[q_id]);
246 : :
247 : 0 : return err;
248 : : }
249 : :
250 : 0 : void hinic_destroy_rq(struct hinic_hwdev *hwdev, u16 q_id)
251 : : {
252 : 0 : struct hinic_nic_io *nic_io = hwdev->nic_io;
253 : 0 : struct hinic_qp *qp = &nic_io->qps[q_id];
254 : : struct hinic_rq *rq = &qp->rq;
255 : :
256 [ # # ]: 0 : if (qp->rq.wq == NULL)
257 : : return;
258 : :
259 : 0 : dma_free_coherent_volatile(hwdev, HINIC_PAGE_SIZE,
260 : 0 : (volatile void *)rq->pi_virt_addr,
261 : : rq->pi_dma_addr);
262 : 0 : hinic_wq_free(nic_io->hwdev, qp->rq.wq);
263 : 0 : qp->rq.wq = NULL;
264 : : }
265 : :
266 : : static void
267 : : hinic_prepare_rq_wqe(void *wqe, __rte_unused u16 pi, dma_addr_t buf_addr,
268 : : dma_addr_t cqe_dma)
269 : : {
270 : : struct hinic_rq_wqe *rq_wqe = wqe;
271 : : struct hinic_rq_ctrl *ctrl = &rq_wqe->ctrl;
272 : : struct hinic_rq_cqe_sect *cqe_sect = &rq_wqe->cqe_sect;
273 : : struct hinic_rq_bufdesc *buf_desc = &rq_wqe->buf_desc;
274 : : u32 rq_ceq_len = sizeof(struct hinic_rq_cqe);
275 : :
276 : 0 : ctrl->ctrl_fmt =
277 : : RQ_CTRL_SET(SIZE_8BYTES(sizeof(*ctrl)), LEN) |
278 : : RQ_CTRL_SET(SIZE_8BYTES(sizeof(*cqe_sect)), COMPLETE_LEN) |
279 : : RQ_CTRL_SET(SIZE_8BYTES(sizeof(*buf_desc)), BUFDESC_SECT_LEN) |
280 : : RQ_CTRL_SET(RQ_COMPLETE_SGE, COMPLETE_FORMAT);
281 : :
282 : 0 : hinic_set_sge(&cqe_sect->sge, cqe_dma, rq_ceq_len);
283 : :
284 : 0 : buf_desc->addr_high = upper_32_bits(buf_addr);
285 : 0 : buf_desc->addr_low = lower_32_bits(buf_addr);
286 : : }
287 : :
288 : 0 : void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats)
289 : : {
290 [ # # ]: 0 : if (!rxq || !stats)
291 : : return;
292 : :
293 : 0 : memcpy(stats, &rxq->rxq_stats, sizeof(rxq->rxq_stats));
294 : : }
295 : :
296 : 0 : void hinic_rxq_stats_reset(struct hinic_rxq *rxq)
297 : : {
298 : : struct hinic_rxq_stats *rxq_stats;
299 : :
300 [ # # ]: 0 : if (rxq == NULL)
301 : : return;
302 : :
303 : 0 : rxq_stats = &rxq->rxq_stats;
304 : : memset(rxq_stats, 0, sizeof(*rxq_stats));
305 : : }
306 : :
307 : 0 : static int hinic_rx_alloc_cqe(struct hinic_rxq *rxq, unsigned int socket_id)
308 : : {
309 : : size_t cqe_mem_size;
310 : :
311 : 0 : cqe_mem_size = sizeof(struct hinic_rq_cqe) * rxq->q_depth;
312 : 0 : rxq->cqe_start_vaddr = dma_zalloc_coherent(rxq->nic_dev->hwdev,
313 : : cqe_mem_size, &rxq->cqe_start_paddr, socket_id);
314 [ # # ]: 0 : if (!rxq->cqe_start_vaddr) {
315 : 0 : PMD_DRV_LOG(ERR, "Allocate cqe dma memory failed");
316 : 0 : return -ENOMEM;
317 : : }
318 : :
319 : 0 : rxq->rx_cqe = (struct hinic_rq_cqe *)rxq->cqe_start_vaddr;
320 : :
321 : 0 : return HINIC_OK;
322 : : }
323 : :
324 : 0 : static void hinic_rx_free_cqe(struct hinic_rxq *rxq)
325 : : {
326 : : size_t cqe_mem_size;
327 : :
328 : 0 : cqe_mem_size = sizeof(struct hinic_rq_cqe) * rxq->q_depth;
329 : 0 : dma_free_coherent(rxq->nic_dev->hwdev, cqe_mem_size,
330 : : rxq->cqe_start_vaddr, rxq->cqe_start_paddr);
331 : 0 : rxq->cqe_start_vaddr = NULL;
332 : 0 : }
333 : :
334 : 0 : static int hinic_rx_fill_wqe(struct hinic_rxq *rxq)
335 : : {
336 : 0 : struct hinic_nic_dev *nic_dev = rxq->nic_dev;
337 : : struct hinic_rq_wqe *rq_wqe;
338 : : dma_addr_t buf_dma_addr, cqe_dma_addr;
339 : 0 : u16 pi = 0;
340 : : int i;
341 : :
342 : : buf_dma_addr = 0;
343 : 0 : cqe_dma_addr = rxq->cqe_start_paddr;
344 [ # # ]: 0 : for (i = 0; i < rxq->q_depth; i++) {
345 : 0 : rq_wqe = hinic_get_rq_wqe(nic_dev->hwdev, rxq->q_id, &pi);
346 [ # # ]: 0 : if (!rq_wqe) {
347 : 0 : PMD_DRV_LOG(ERR, "Get rq wqe failed");
348 : 0 : break;
349 : : }
350 : :
351 : : hinic_prepare_rq_wqe(rq_wqe, pi, buf_dma_addr, cqe_dma_addr);
352 : 0 : cqe_dma_addr += sizeof(struct hinic_rq_cqe);
353 : :
354 : 0 : hinic_cpu_to_be32(rq_wqe, sizeof(struct hinic_rq_wqe));
355 : : }
356 : :
357 : 0 : hinic_return_rq_wqe(nic_dev->hwdev, rxq->q_id, i);
358 : :
359 : 0 : return i;
360 : : }
361 : :
362 : : /* alloc cqe and prepare rqe */
363 : 0 : int hinic_setup_rx_resources(struct hinic_rxq *rxq)
364 : : {
365 : : u64 rx_info_sz;
366 : : int err, pkts;
367 : :
368 : 0 : rx_info_sz = rxq->q_depth * sizeof(*rxq->rx_info);
369 : 0 : rxq->rx_info = rte_zmalloc_socket("rx_info", rx_info_sz,
370 : 0 : RTE_CACHE_LINE_SIZE, rxq->socket_id);
371 [ # # ]: 0 : if (!rxq->rx_info)
372 : : return -ENOMEM;
373 : :
374 : 0 : err = hinic_rx_alloc_cqe(rxq, rxq->socket_id);
375 [ # # ]: 0 : if (err) {
376 : 0 : PMD_DRV_LOG(ERR, "Allocate rx cqe failed");
377 : 0 : goto rx_cqe_err;
378 : : }
379 : :
380 : 0 : pkts = hinic_rx_fill_wqe(rxq);
381 [ # # ]: 0 : if (pkts != rxq->q_depth) {
382 : 0 : PMD_DRV_LOG(ERR, "Fill rx wqe failed");
383 : : err = -ENOMEM;
384 : 0 : goto rx_fill_err;
385 : : }
386 : :
387 : : return 0;
388 : :
389 : : rx_fill_err:
390 : 0 : hinic_rx_free_cqe(rxq);
391 : :
392 : 0 : rx_cqe_err:
393 : 0 : rte_free(rxq->rx_info);
394 : 0 : rxq->rx_info = NULL;
395 : :
396 : 0 : return err;
397 : : }
398 : :
399 : 0 : void hinic_free_rx_resources(struct hinic_rxq *rxq)
400 : : {
401 [ # # ]: 0 : if (rxq->rx_info == NULL)
402 : : return;
403 : :
404 : 0 : hinic_rx_free_cqe(rxq);
405 : 0 : rte_free(rxq->rx_info);
406 : 0 : rxq->rx_info = NULL;
407 : : }
408 : :
409 : 0 : void hinic_free_all_rx_resources(struct rte_eth_dev *eth_dev)
410 : : {
411 : : u16 q_id;
412 : 0 : struct hinic_nic_dev *nic_dev =
413 : 0 : HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
414 : :
415 [ # # ]: 0 : for (q_id = 0; q_id < nic_dev->num_rq; q_id++) {
416 [ # # ]: 0 : if (eth_dev->data->rx_queues != NULL)
417 : 0 : eth_dev->data->rx_queues[q_id] = NULL;
418 : :
419 [ # # ]: 0 : if (nic_dev->rxqs[q_id] == NULL)
420 : 0 : continue;
421 : :
422 : 0 : hinic_free_all_rx_mbufs(nic_dev->rxqs[q_id]);
423 : 0 : hinic_free_rx_resources(nic_dev->rxqs[q_id]);
424 : 0 : kfree(nic_dev->rxqs[q_id]);
425 : 0 : nic_dev->rxqs[q_id] = NULL;
426 : : }
427 : 0 : }
428 : :
429 : 0 : void hinic_free_all_rx_mbuf(struct rte_eth_dev *eth_dev)
430 : : {
431 : 0 : struct hinic_nic_dev *nic_dev =
432 : 0 : HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
433 : : u16 q_id;
434 : :
435 [ # # ]: 0 : for (q_id = 0; q_id < nic_dev->num_rq; q_id++)
436 : 0 : hinic_free_all_rx_mbufs(nic_dev->rxqs[q_id]);
437 : 0 : }
438 : :
439 : 0 : static void hinic_recv_jumbo_pkt(struct hinic_rxq *rxq,
440 : : struct rte_mbuf *head_mbuf,
441 : : u32 remain_pkt_len)
442 : : {
443 : 0 : struct hinic_nic_dev *nic_dev = rxq->nic_dev;
444 : : struct rte_mbuf *cur_mbuf, *rxm = NULL;
445 : : struct hinic_rx_info *rx_info;
446 : 0 : u16 sw_ci, rx_buf_len = rxq->buf_len;
447 : : u32 pkt_len;
448 : :
449 [ # # ]: 0 : while (remain_pkt_len > 0) {
450 : 0 : sw_ci = hinic_get_rq_local_ci(nic_dev->hwdev, rxq->q_id);
451 : 0 : rx_info = &rxq->rx_info[sw_ci];
452 : :
453 : 0 : hinic_update_rq_local_ci(nic_dev->hwdev, rxq->q_id, 1);
454 : :
455 : 0 : pkt_len = remain_pkt_len > rx_buf_len ?
456 : 0 : rx_buf_len : remain_pkt_len;
457 : 0 : remain_pkt_len -= pkt_len;
458 : :
459 : 0 : cur_mbuf = rx_info->mbuf;
460 : 0 : cur_mbuf->data_len = (u16)pkt_len;
461 : 0 : cur_mbuf->next = NULL;
462 : :
463 : 0 : head_mbuf->pkt_len += cur_mbuf->data_len;
464 : 0 : head_mbuf->nb_segs++;
465 : :
466 [ # # ]: 0 : if (!rxm)
467 : 0 : head_mbuf->next = cur_mbuf;
468 : : else
469 : 0 : rxm->next = cur_mbuf;
470 : :
471 : : rxm = cur_mbuf;
472 : : }
473 : 0 : }
474 : :
475 : : static void hinic_rss_deinit(struct hinic_nic_dev *nic_dev)
476 : : {
477 : 0 : u8 prio_tc[HINIC_DCB_UP_MAX] = {0};
478 : 0 : (void)hinic_rss_cfg(nic_dev->hwdev, 0,
479 : 0 : nic_dev->rss_tmpl_idx, 0, prio_tc);
480 : : }
481 : :
482 : 0 : static int hinic_rss_key_init(struct hinic_nic_dev *nic_dev,
483 : : struct rte_eth_rss_conf *rss_conf)
484 : : {
485 : 0 : u8 default_rss_key[HINIC_RSS_KEY_SIZE] = {
486 : : 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
487 : : 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
488 : : 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
489 : : 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
490 : : 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa};
491 : 0 : u8 hashkey[HINIC_RSS_KEY_SIZE] = {0};
492 : 0 : u8 tmpl_idx = nic_dev->rss_tmpl_idx;
493 : :
494 [ # # ]: 0 : if (rss_conf->rss_key == NULL)
495 : : memcpy(hashkey, default_rss_key, HINIC_RSS_KEY_SIZE);
496 : : else
497 : 0 : memcpy(hashkey, rss_conf->rss_key, rss_conf->rss_key_len);
498 : :
499 : 0 : return hinic_rss_set_template_tbl(nic_dev->hwdev, tmpl_idx, hashkey);
500 : : }
501 : :
502 : 0 : static void hinic_fill_rss_type(struct nic_rss_type *rss_type,
503 : : struct rte_eth_rss_conf *rss_conf)
504 : : {
505 : 0 : u64 rss_hf = rss_conf->rss_hf;
506 : :
507 : 0 : rss_type->ipv4 = (rss_hf & (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4)) ? 1 : 0;
508 : 0 : rss_type->tcp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) ? 1 : 0;
509 : 0 : rss_type->ipv6 = (rss_hf & (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6)) ? 1 : 0;
510 : 0 : rss_type->ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_EX) ? 1 : 0;
511 : 0 : rss_type->tcp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) ? 1 : 0;
512 : 0 : rss_type->tcp_ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_TCP_EX) ? 1 : 0;
513 : 0 : rss_type->udp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) ? 1 : 0;
514 : 0 : rss_type->udp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) ? 1 : 0;
515 : 0 : }
516 : :
517 : 0 : static void hinic_fillout_indir_tbl(struct hinic_nic_dev *nic_dev, u32 *indir)
518 : : {
519 : 0 : u8 rss_queue_count = nic_dev->num_rss;
520 : : int i = 0, j;
521 : :
522 [ # # ]: 0 : if (rss_queue_count == 0) {
523 : : /* delete q_id from indir tbl */
524 [ # # ]: 0 : for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
525 : 0 : indir[i] = 0xFF; /* Invalid value in indir tbl */
526 : : } else {
527 [ # # ]: 0 : while (i < HINIC_RSS_INDIR_SIZE)
528 [ # # # # ]: 0 : for (j = 0; (j < rss_queue_count) &&
529 : 0 : (i < HINIC_RSS_INDIR_SIZE); j++)
530 : 0 : indir[i++] = nic_dev->rx_queue_list[j];
531 : : }
532 : 0 : }
533 : :
534 : 0 : static int hinic_rss_init(struct hinic_nic_dev *nic_dev,
535 : : __rte_unused u8 *rq2iq_map,
536 : : struct rte_eth_rss_conf *rss_conf)
537 : : {
538 : 0 : u32 indir_tbl[HINIC_RSS_INDIR_SIZE] = {0};
539 : 0 : struct nic_rss_type rss_type = {0};
540 : 0 : u8 prio_tc[HINIC_DCB_UP_MAX] = {0};
541 : : u8 tmpl_idx = 0xFF, num_tc = 0;
542 : : int err;
543 : :
544 : 0 : tmpl_idx = nic_dev->rss_tmpl_idx;
545 : :
546 : 0 : err = hinic_rss_key_init(nic_dev, rss_conf);
547 [ # # ]: 0 : if (err)
548 : : return err;
549 : :
550 [ # # ]: 0 : if (!nic_dev->rss_indir_flag) {
551 : 0 : hinic_fillout_indir_tbl(nic_dev, indir_tbl);
552 : 0 : err = hinic_rss_set_indir_tbl(nic_dev->hwdev, tmpl_idx,
553 : : indir_tbl);
554 [ # # ]: 0 : if (err)
555 : : return err;
556 : : }
557 : :
558 : 0 : hinic_fill_rss_type(&rss_type, rss_conf);
559 : 0 : err = hinic_set_rss_type(nic_dev->hwdev, tmpl_idx, rss_type);
560 [ # # ]: 0 : if (err)
561 : : return err;
562 : :
563 : 0 : err = hinic_rss_set_hash_engine(nic_dev->hwdev, tmpl_idx,
564 : : HINIC_RSS_HASH_ENGINE_TYPE_TOEP);
565 [ # # ]: 0 : if (err)
566 : : return err;
567 : :
568 : 0 : return hinic_rss_cfg(nic_dev->hwdev, 1, tmpl_idx, num_tc, prio_tc);
569 : : }
570 : :
571 : : static void
572 : : hinic_add_rq_to_rx_queue_list(struct hinic_nic_dev *nic_dev, u16 queue_id)
573 : : {
574 : 0 : u8 rss_queue_count = nic_dev->num_rss;
575 : :
576 : : RTE_ASSERT(rss_queue_count <= (RTE_DIM(nic_dev->rx_queue_list) - 1));
577 : :
578 : 0 : nic_dev->rx_queue_list[rss_queue_count] = queue_id;
579 : 0 : nic_dev->num_rss++;
580 : : }
581 : :
582 : : /**
583 : : * hinic_setup_num_qps - determine num_qps from rss_tmpl_id
584 : : * @nic_dev: pointer to the private ethernet device
585 : : * Return: 0 on Success, error code otherwise.
586 : : **/
587 : 0 : static int hinic_setup_num_qps(struct hinic_nic_dev *nic_dev)
588 : : {
589 : : int err, i;
590 : :
591 [ # # ]: 0 : if (!(nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG)) {
592 : 0 : nic_dev->flags &= ~RTE_ETH_MQ_RX_RSS_FLAG;
593 : 0 : nic_dev->num_rss = 0;
594 [ # # ]: 0 : if (nic_dev->num_rq > 1) {
595 : : /* get rss template id */
596 : 0 : err = hinic_rss_template_alloc(nic_dev->hwdev,
597 : : &nic_dev->rss_tmpl_idx);
598 [ # # ]: 0 : if (err) {
599 : 0 : PMD_DRV_LOG(WARNING, "Alloc rss template failed");
600 : 0 : return err;
601 : : }
602 : 0 : nic_dev->flags |= RTE_ETH_MQ_RX_RSS_FLAG;
603 [ # # ]: 0 : for (i = 0; i < nic_dev->num_rq; i++)
604 : : hinic_add_rq_to_rx_queue_list(nic_dev, i);
605 : : }
606 : : }
607 : :
608 : : return 0;
609 : : }
610 : :
611 : 0 : static void hinic_destroy_num_qps(struct hinic_nic_dev *nic_dev)
612 : : {
613 [ # # ]: 0 : if (nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG) {
614 [ # # ]: 0 : if (hinic_rss_template_free(nic_dev->hwdev,
615 : 0 : nic_dev->rss_tmpl_idx))
616 : 0 : PMD_DRV_LOG(WARNING, "Free rss template failed");
617 : :
618 : 0 : nic_dev->flags &= ~RTE_ETH_MQ_RX_RSS_FLAG;
619 : : }
620 : 0 : }
621 : :
622 : 0 : static int hinic_config_mq_rx_rss(struct hinic_nic_dev *nic_dev, bool on)
623 : : {
624 : : int ret = 0;
625 : :
626 [ # # ]: 0 : if (on) {
627 : 0 : ret = hinic_setup_num_qps(nic_dev);
628 [ # # ]: 0 : if (ret)
629 : 0 : PMD_DRV_LOG(ERR, "Setup num_qps failed");
630 : : } else {
631 : 0 : hinic_destroy_num_qps(nic_dev);
632 : : }
633 : :
634 : 0 : return ret;
635 : : }
636 : :
637 : 0 : int hinic_config_mq_mode(struct rte_eth_dev *dev, bool on)
638 : : {
639 : 0 : struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
640 : : struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
641 : : int ret = 0;
642 : :
643 [ # # ]: 0 : switch (dev_conf->rxmode.mq_mode) {
644 : 0 : case RTE_ETH_MQ_RX_RSS:
645 : 0 : ret = hinic_config_mq_rx_rss(nic_dev, on);
646 : 0 : break;
647 : : default:
648 : : break;
649 : : }
650 : :
651 : 0 : return ret;
652 : : }
653 : :
654 : 0 : int hinic_rx_configure(struct rte_eth_dev *dev)
655 : : {
656 : 0 : struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
657 : 0 : struct rte_eth_rss_conf rss_conf =
658 : : dev->data->dev_conf.rx_adv_conf.rss_conf;
659 : : int err;
660 : : bool lro_en;
661 : : int max_lro_size;
662 : : int lro_wqe_num;
663 : : int buf_size;
664 : :
665 [ # # ]: 0 : if (nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG) {
666 [ # # ]: 0 : if (rss_conf.rss_hf == 0) {
667 : 0 : rss_conf.rss_hf = HINIC_RSS_OFFLOAD_ALL;
668 [ # # ]: 0 : } else if ((rss_conf.rss_hf & HINIC_RSS_OFFLOAD_ALL) == 0) {
669 : 0 : PMD_DRV_LOG(ERR, "Do not support rss offload all");
670 : 0 : goto rss_config_err;
671 : : }
672 : :
673 : 0 : err = hinic_rss_init(nic_dev, NULL, &rss_conf);
674 [ # # ]: 0 : if (err) {
675 : 0 : PMD_DRV_LOG(ERR, "Init rss failed");
676 : 0 : goto rss_config_err;
677 : : }
678 : : }
679 : :
680 : : /* Enable both L3/L4 rx checksum offload */
681 [ # # ]: 0 : if (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM)
682 : 0 : nic_dev->rx_csum_en = HINIC_RX_CSUM_OFFLOAD_EN;
683 : :
684 : 0 : err = hinic_set_rx_csum_offload(nic_dev->hwdev,
685 : : HINIC_RX_CSUM_OFFLOAD_EN);
686 [ # # ]: 0 : if (err)
687 : 0 : goto rx_csum_ofl_err;
688 : :
689 : : /* config lro */
690 : 0 : lro_en = dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO ?
691 : 0 : true : false;
692 : 0 : max_lro_size = dev->data->dev_conf.rxmode.max_lro_pkt_size;
693 : 0 : buf_size = nic_dev->hwdev->nic_io->rq_buf_size;
694 [ # # ]: 0 : lro_wqe_num = max_lro_size / buf_size ? (max_lro_size / buf_size) : 1;
695 : :
696 : 0 : err = hinic_set_rx_lro(nic_dev->hwdev, lro_en, lro_en, lro_wqe_num);
697 [ # # ]: 0 : if (err) {
698 [ # # ]: 0 : PMD_DRV_LOG(ERR, "%s %s lro failed, err: %d, max_lro_size: %d",
699 : : dev->data->name, lro_en ? "Enable" : "Disable",
700 : : err, max_lro_size);
701 : 0 : goto set_rx_lro_err;
702 : : }
703 : :
704 : : return 0;
705 : :
706 : : set_rx_lro_err:
707 : 0 : rx_csum_ofl_err:
708 : 0 : rss_config_err:
709 : :
710 : 0 : hinic_destroy_num_qps(nic_dev);
711 : :
712 : 0 : return HINIC_ERROR;
713 : : }
714 : :
715 : 0 : static void hinic_rx_remove_lro(struct hinic_nic_dev *nic_dev)
716 : : {
717 : : int err;
718 : :
719 : 0 : err = hinic_set_rx_lro(nic_dev->hwdev, false, false, 0);
720 [ # # ]: 0 : if (err)
721 : 0 : PMD_DRV_LOG(ERR, "%s disable LRO failed",
722 : : nic_dev->proc_dev_name);
723 : 0 : }
724 : :
725 : 0 : void hinic_rx_remove_configure(struct rte_eth_dev *dev)
726 : : {
727 : 0 : struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
728 : :
729 [ # # ]: 0 : if (nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG) {
730 : : hinic_rss_deinit(nic_dev);
731 : 0 : hinic_destroy_num_qps(nic_dev);
732 : : }
733 : :
734 : 0 : hinic_rx_remove_lro(nic_dev);
735 : 0 : }
736 : :
737 : 0 : void hinic_free_all_rx_mbufs(struct hinic_rxq *rxq)
738 : : {
739 : 0 : struct hinic_nic_dev *nic_dev = rxq->nic_dev;
740 : : struct hinic_rx_info *rx_info;
741 : 0 : int free_wqebbs =
742 : 0 : hinic_get_rq_free_wqebbs(nic_dev->hwdev, rxq->q_id) + 1;
743 : : volatile struct hinic_rq_cqe *rx_cqe;
744 : : u16 ci;
745 : :
746 [ # # ]: 0 : while (free_wqebbs++ < rxq->q_depth) {
747 : 0 : ci = hinic_get_rq_local_ci(nic_dev->hwdev, rxq->q_id);
748 : :
749 : 0 : rx_cqe = &rxq->rx_cqe[ci];
750 : :
751 : : /* clear done bit */
752 : 0 : rx_cqe->status = 0;
753 : :
754 : 0 : rx_info = &rxq->rx_info[ci];
755 : 0 : rte_pktmbuf_free(rx_info->mbuf);
756 : 0 : rx_info->mbuf = NULL;
757 : :
758 : 0 : hinic_update_rq_local_ci(nic_dev->hwdev, rxq->q_id, 1);
759 : : }
760 : 0 : }
761 : :
762 : : static inline void hinic_rq_cqe_be_to_cpu32(void *dst_le32,
763 : : volatile void *src_be32)
764 : : {
765 : : #if defined(RTE_ARCH_X86_64)
766 : : volatile __m128i *wqe_be = (volatile __m128i *)src_be32;
767 : : __m128i *wqe_le = (__m128i *)dst_le32;
768 : : __m128i shuf_mask = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10,
769 : : 11, 4, 5, 6, 7, 0, 1, 2, 3);
770 : :
771 : : /* l2nic just use first 128 bits */
772 : 0 : wqe_le[0] = _mm_shuffle_epi8(wqe_be[0], shuf_mask);
773 : : #elif defined(RTE_ARCH_ARM64)
774 : : volatile uint8x16_t *wqe_be = (volatile uint8x16_t *)src_be32;
775 : : uint8x16_t *wqe_le = (uint8x16_t *)dst_le32;
776 : : const uint8x16_t shuf_mask = {3, 2, 1, 0, 7, 6, 5, 4, 11, 10,
777 : : 9, 8, 15, 14, 13, 12};
778 : :
779 : : /* l2nic just use first 128 bits */
780 : : wqe_le[0] = vqtbl1q_u8(wqe_be[0], shuf_mask);
781 : : #else
782 : : u32 i;
783 : : volatile u32 *wqe_be = (volatile u32 *)src_be32;
784 : : u32 *wqe_le = (u32 *)dst_le32;
785 : :
786 : : #define HINIC_L2NIC_RQ_CQE_USED 4 /* 4Bytes unit */
787 : :
788 : : for (i = 0; i < HINIC_L2NIC_RQ_CQE_USED; i++) {
789 : : *wqe_le = rte_be_to_cpu_32(*wqe_be);
790 : : wqe_be++;
791 : : wqe_le++;
792 : : }
793 : : #endif
794 : : }
795 : :
796 : : static inline uint64_t hinic_rx_rss_hash(uint32_t offload_type,
797 : : uint32_t cqe_hass_val,
798 : : uint32_t *rss_hash)
799 : : {
800 : : uint32_t rss_type;
801 : :
802 : 0 : rss_type = HINIC_GET_RSS_TYPES(offload_type);
803 : 0 : if (likely(rss_type != 0)) {
804 : 0 : *rss_hash = cqe_hass_val;
805 : 0 : return RTE_MBUF_F_RX_RSS_HASH;
806 : : }
807 : :
808 : : return 0;
809 : : }
810 : :
811 : 0 : static inline uint64_t hinic_rx_csum(uint32_t status, struct hinic_rxq *rxq)
812 : : {
813 : : uint32_t checksum_err;
814 : : uint64_t flags;
815 : 0 : struct hinic_nic_dev *nic_dev = rxq->nic_dev;
816 : :
817 [ # # ]: 0 : if (unlikely(!(nic_dev->rx_csum_en & HINIC_RX_CSUM_OFFLOAD_EN)))
818 : : return RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN;
819 : :
820 : : /* most case checksum is ok */
821 : 0 : checksum_err = HINIC_GET_RX_CSUM_ERR(status);
822 [ # # ]: 0 : if (likely(checksum_err == 0))
823 : : return (RTE_MBUF_F_RX_IP_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD);
824 : :
825 : : /* If BYPASS bit set, all other status indications should be ignored */
826 [ # # ]: 0 : if (unlikely(HINIC_CSUM_ERR_BYPASSED(checksum_err)))
827 : : return RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN;
828 : :
829 : : flags = 0;
830 : :
831 : : /* IP checksum error */
832 [ # # ]: 0 : if (HINIC_CSUM_ERR_IP(checksum_err))
833 : : flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
834 : : else
835 : : flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
836 : :
837 : : /* L4 checksum error */
838 [ # # ]: 0 : if (HINIC_CSUM_ERR_L4(checksum_err))
839 : 0 : flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
840 : : else
841 : 0 : flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
842 : :
843 [ # # ]: 0 : if (unlikely(HINIC_CSUM_ERR_OTHER(checksum_err)))
844 : : flags = RTE_MBUF_F_RX_L4_CKSUM_NONE;
845 : :
846 : 0 : rxq->rxq_stats.errors++;
847 : :
848 : 0 : return flags;
849 : : }
850 : :
851 : : static inline uint64_t hinic_rx_vlan(uint32_t offload_type, uint32_t vlan_len,
852 : : uint16_t *vlan_tci)
853 : : {
854 : : uint16_t vlan_tag;
855 : :
856 : 0 : vlan_tag = HINIC_GET_RX_VLAN_TAG(vlan_len);
857 [ # # ]: 0 : if (!HINIC_GET_RX_VLAN_OFFLOAD_EN(offload_type) || 0 == vlan_tag) {
858 : 0 : *vlan_tci = 0;
859 : 0 : return 0;
860 : : }
861 : :
862 : 0 : *vlan_tci = vlan_tag;
863 : :
864 : 0 : return RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
865 : : }
866 : :
867 : : static inline u32 hinic_rx_alloc_mbuf_bulk(struct hinic_rxq *rxq,
868 : : struct rte_mbuf **mbufs,
869 : : u32 exp_mbuf_cnt)
870 : : {
871 : : int rc;
872 : : u32 avail_cnt;
873 : :
874 : 0 : rc = rte_pktmbuf_alloc_bulk(rxq->mb_pool, mbufs, exp_mbuf_cnt);
875 [ # # ]: 0 : if (likely(rc == HINIC_OK)) {
876 : : avail_cnt = exp_mbuf_cnt;
877 : : } else {
878 : : avail_cnt = 0;
879 : 0 : rxq->rxq_stats.rx_nombuf += exp_mbuf_cnt;
880 : : }
881 : :
882 : : return avail_cnt;
883 : : }
884 : :
885 : 0 : static struct rte_mbuf *hinic_rx_alloc_mbuf(struct hinic_rxq *rxq,
886 : : dma_addr_t *dma_addr)
887 : : {
888 : 0 : struct rte_mbuf *mbuf = NULL;
889 : : int rc;
890 : :
891 : 0 : rc = rte_pktmbuf_alloc_bulk(rxq->mb_pool, &mbuf, 1);
892 [ # # ]: 0 : if (unlikely(rc != HINIC_OK))
893 : : return NULL;
894 : :
895 : 0 : *dma_addr = rte_mbuf_data_iova_default(mbuf);
896 : :
897 : 0 : return mbuf;
898 : : }
899 : :
900 : 0 : static inline void hinic_rearm_rxq_mbuf(struct hinic_rxq *rxq)
901 : : {
902 : : u16 pi;
903 : : u32 i, free_wqebbs, rearm_wqebbs, exp_wqebbs;
904 : : dma_addr_t dma_addr;
905 : : struct hinic_rq_wqe *rq_wqe;
906 : : struct rte_mbuf **rearm_mbufs;
907 : :
908 : : /* check free wqebb fo rearm */
909 : 0 : free_wqebbs = HINIC_GET_RQ_FREE_WQEBBS(rxq);
910 [ # # ]: 0 : if (unlikely(free_wqebbs < rxq->rx_free_thresh))
911 : : return;
912 : :
913 : : /* get rearm mbuf array */
914 : 0 : pi = HINIC_GET_RQ_LOCAL_PI(rxq);
915 : 0 : rearm_mbufs = (struct rte_mbuf **)(&rxq->rx_info[pi]);
916 : :
917 : : /* check rxq free wqebbs turn around */
918 : 0 : exp_wqebbs = rxq->q_depth - pi;
919 : : if (free_wqebbs < exp_wqebbs)
920 : : exp_wqebbs = free_wqebbs;
921 : :
922 : : /* alloc mbuf in bulk */
923 : : rearm_wqebbs = hinic_rx_alloc_mbuf_bulk(rxq, rearm_mbufs, exp_wqebbs);
924 [ # # ]: 0 : if (unlikely(rearm_wqebbs == 0))
925 : : return;
926 : :
927 : : /* rearm rx mbuf */
928 : 0 : rq_wqe = WQ_WQE_ADDR(rxq->wq, (u32)pi);
929 [ # # ]: 0 : for (i = 0; i < rearm_wqebbs; i++) {
930 [ # # ]: 0 : dma_addr = rte_mbuf_data_iova_default(rearm_mbufs[i]);
931 : 0 : rq_wqe->buf_desc.addr_high =
932 [ # # ]: 0 : cpu_to_be32(upper_32_bits(dma_addr));
933 : 0 : rq_wqe->buf_desc.addr_low =
934 [ # # ]: 0 : cpu_to_be32(lower_32_bits(dma_addr));
935 : 0 : rq_wqe++;
936 : : }
937 : 0 : rxq->wq->prod_idx += rearm_wqebbs;
938 : 0 : rxq->wq->delta -= rearm_wqebbs;
939 : :
940 : : /* update rq hw_pi */
941 : : rte_wmb();
942 [ # # ]: 0 : HINIC_UPDATE_RQ_HW_PI(rxq, pi + rearm_wqebbs);
943 : : }
944 : :
945 : 0 : void hinic_rx_alloc_pkts(struct hinic_rxq *rxq)
946 : : {
947 : 0 : struct hinic_nic_dev *nic_dev = rxq->nic_dev;
948 : : struct hinic_rq_wqe *rq_wqe;
949 : : struct hinic_rx_info *rx_info;
950 : : struct rte_mbuf *mb;
951 : : dma_addr_t dma_addr;
952 : 0 : u16 pi = 0;
953 : : int i, free_wqebbs;
954 : :
955 : 0 : free_wqebbs = HINIC_GET_RQ_FREE_WQEBBS(rxq);
956 [ # # ]: 0 : for (i = 0; i < free_wqebbs; i++) {
957 : 0 : mb = hinic_rx_alloc_mbuf(rxq, &dma_addr);
958 [ # # ]: 0 : if (unlikely(!mb)) {
959 : 0 : rxq->rxq_stats.rx_nombuf++;
960 : 0 : break;
961 : : }
962 : :
963 : 0 : rq_wqe = hinic_get_rq_wqe(nic_dev->hwdev, rxq->q_id, &pi);
964 [ # # ]: 0 : if (unlikely(!rq_wqe)) {
965 : 0 : rte_pktmbuf_free(mb);
966 : 0 : break;
967 : : }
968 : :
969 : : /* fill buffer address only */
970 : 0 : rq_wqe->buf_desc.addr_high =
971 [ # # ]: 0 : cpu_to_be32(upper_32_bits(dma_addr));
972 : 0 : rq_wqe->buf_desc.addr_low =
973 [ # # ]: 0 : cpu_to_be32(lower_32_bits(dma_addr));
974 : :
975 : 0 : rx_info = &rxq->rx_info[pi];
976 : 0 : rx_info->mbuf = mb;
977 : : }
978 : :
979 [ # # ]: 0 : if (likely(i > 0)) {
980 : : rte_wmb();
981 [ # # ]: 0 : HINIC_UPDATE_RQ_HW_PI(rxq, pi + 1);
982 : : }
983 : 0 : }
984 : :
985 : 0 : u16 hinic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, u16 nb_pkts)
986 : : {
987 : : struct rte_mbuf *rxm;
988 : : struct hinic_rxq *rxq = rx_queue;
989 : : struct hinic_rx_info *rx_info;
990 : : volatile struct hinic_rq_cqe *rx_cqe;
991 : : u16 rx_buf_len, pkts = 0;
992 : : u16 sw_ci, ci_mask, wqebb_cnt = 0;
993 : : u32 pkt_len, status, vlan_len, lro_num;
994 : : u64 rx_bytes = 0;
995 : : struct hinic_rq_cqe cqe;
996 : : u32 offload_type, rss_hash;
997 : :
998 : 0 : rx_buf_len = rxq->buf_len;
999 : :
1000 : : /* 1. get polling start ci */
1001 : 0 : ci_mask = HINIC_GET_RQ_WQE_MASK(rxq);
1002 : 0 : sw_ci = HINIC_GET_RQ_LOCAL_CI(rxq);
1003 : :
1004 [ # # ]: 0 : while (pkts < nb_pkts) {
1005 : : /* 2. current ci is done */
1006 : 0 : rx_cqe = &rxq->rx_cqe[sw_ci];
1007 : 0 : status = rte_atomic_load_explicit(&rx_cqe->status, rte_memory_order_acquire);
1008 [ # # ]: 0 : if (!HINIC_GET_RX_DONE_BE(status))
1009 : : break;
1010 : :
1011 : : /* convert cqe and get packet length */
1012 : : hinic_rq_cqe_be_to_cpu32(&cqe, (volatile void *)rx_cqe);
1013 : : vlan_len = cqe.vlan_len;
1014 : :
1015 : 0 : rx_info = &rxq->rx_info[sw_ci];
1016 : 0 : rxm = rx_info->mbuf;
1017 : :
1018 : : /* 3. next ci point and prefetch */
1019 : 0 : sw_ci++;
1020 : 0 : sw_ci &= ci_mask;
1021 : :
1022 : : /* prefetch next mbuf first 64B */
1023 : 0 : rte_prefetch0(rxq->rx_info[sw_ci].mbuf);
1024 : :
1025 : : /* 4. jumbo frame process */
1026 : 0 : pkt_len = HINIC_GET_RX_PKT_LEN(vlan_len);
1027 [ # # ]: 0 : if (likely(pkt_len <= rx_buf_len)) {
1028 : 0 : rxm->data_len = pkt_len;
1029 : 0 : rxm->pkt_len = pkt_len;
1030 : 0 : wqebb_cnt++;
1031 : : } else {
1032 : 0 : rxm->data_len = rx_buf_len;
1033 : 0 : rxm->pkt_len = rx_buf_len;
1034 : :
1035 : : /* if receive jumbo, updating ci will be done by
1036 : : * hinic_recv_jumbo_pkt function.
1037 : : */
1038 : 0 : HINIC_UPDATE_RQ_LOCAL_CI(rxq, wqebb_cnt + 1);
1039 : : wqebb_cnt = 0;
1040 : 0 : hinic_recv_jumbo_pkt(rxq, rxm, pkt_len - rx_buf_len);
1041 : 0 : sw_ci = HINIC_GET_RQ_LOCAL_CI(rxq);
1042 : : }
1043 : :
1044 : : /* 5. vlan/checksum/rss/pkt_type/gro offload */
1045 : 0 : rxm->data_off = RTE_PKTMBUF_HEADROOM;
1046 [ # # ]: 0 : rxm->port = rxq->port_id;
1047 : : offload_type = cqe.offload_type;
1048 : :
1049 : : /* vlan offload */
1050 : 0 : rxm->ol_flags |= hinic_rx_vlan(offload_type, vlan_len,
1051 : : &rxm->vlan_tci);
1052 : :
1053 : : /* checksum offload */
1054 [ # # ]: 0 : rxm->ol_flags |= hinic_rx_csum(cqe.status, rxq);
1055 : :
1056 : : /* rss hash offload */
1057 : : rss_hash = cqe.rss_hash;
1058 : 0 : rxm->ol_flags |= hinic_rx_rss_hash(offload_type, rss_hash,
1059 : : &rxm->hash.rss);
1060 : :
1061 : : /* lro offload */
1062 : 0 : lro_num = HINIC_GET_RX_NUM_LRO(cqe.status);
1063 [ # # ]: 0 : if (unlikely(lro_num != 0)) {
1064 : 0 : rxm->ol_flags |= RTE_MBUF_F_RX_LRO;
1065 : 0 : rxm->tso_segsz = pkt_len / lro_num;
1066 : : }
1067 : :
1068 : : /* 6. clear done bit */
1069 : 0 : rx_cqe->status = 0;
1070 : :
1071 : 0 : rx_bytes += pkt_len;
1072 : 0 : rx_pkts[pkts++] = rxm;
1073 : : }
1074 : :
1075 [ # # ]: 0 : if (pkts) {
1076 : : /* 7. update ci */
1077 : 0 : HINIC_UPDATE_RQ_LOCAL_CI(rxq, wqebb_cnt);
1078 : :
1079 : : /* do packet stats */
1080 : 0 : rxq->rxq_stats.packets += pkts;
1081 : 0 : rxq->rxq_stats.bytes += rx_bytes;
1082 : : }
1083 : 0 : rxq->rxq_stats.burst_pkts = pkts;
1084 : :
1085 : : /* 8. rearm mbuf to rxq */
1086 : 0 : hinic_rearm_rxq_mbuf(rxq);
1087 : :
1088 : 0 : return pkts;
1089 : : }
|