Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2025 Huawei Technologies Co., Ltd
3 : : */
4 : :
5 : : #include "base/hinic3_compat.h"
6 : : #include "base/hinic3_hwif.h"
7 : : #include "base/hinic3_hwdev.h"
8 : : #include "base/hinic3_wq.h"
9 : : #include "base/hinic3_nic_cfg.h"
10 : : #include "hinic3_nic_io.h"
11 : : #include "hinic3_ethdev.h"
12 : : #include "hinic3_rx.h"
13 : :
14 : : /**
15 : : * Get wqe from receive queue.
16 : : *
17 : : * @param[in] rxq
18 : : * Receive queue.
19 : : * @param[out] rq_wqe
20 : : * Receive queue wqe.
21 : : * @param[out] pi
22 : : * Current pi.
23 : : */
24 : : static inline void
25 : : hinic3_get_rq_wqe(struct hinic3_rxq *rxq, struct hinic3_rq_wqe **rq_wqe,
26 : : uint16_t *pi)
27 : : {
28 : 0 : *pi = MASKED_QUEUE_IDX(rxq, rxq->prod_idx);
29 : :
30 : : /* Get only one rxq wqe. */
31 : 0 : rxq->prod_idx++;
32 : 0 : rxq->delta--;
33 : :
34 : 0 : *rq_wqe = NIC_WQE_ADDR(rxq, *pi);
35 : : }
36 : :
37 : : /**
38 : : * Put wqe into receive queue.
39 : : *
40 : : * @param[in] rxq
41 : : * Receive queue.
42 : : * @param[in] wqe_cnt
43 : : * Wqebb counters.
44 : : */
45 : : static inline void
46 : : hinic3_put_rq_wqe(struct hinic3_rxq *rxq, uint16_t wqe_cnt)
47 : : {
48 : 0 : rxq->delta += wqe_cnt;
49 : 0 : rxq->prod_idx -= wqe_cnt;
50 : : }
51 : :
52 : : /**
53 : : * Get receive queue local pi.
54 : : *
55 : : * @param[in] rxq
56 : : * Receive queue.
57 : : * @return
58 : : * Receive queue local pi.
59 : : */
60 : : static inline uint16_t
61 : : hinic3_get_rq_local_pi(struct hinic3_rxq *rxq)
62 : : {
63 : 0 : return MASKED_QUEUE_IDX(rxq, rxq->prod_idx);
64 : : }
65 : :
66 : : uint16_t
67 : 0 : hinic3_rx_fill_wqe(struct hinic3_rxq *rxq)
68 : : {
69 : : struct hinic3_rq_wqe *rq_wqe = NULL;
70 : 0 : struct hinic3_nic_dev *nic_dev = rxq->nic_dev;
71 : : rte_iova_t cqe_dma;
72 : : uint16_t pi = 0;
73 : : uint16_t i;
74 : :
75 : 0 : cqe_dma = rxq->cqe_start_paddr;
76 [ # # ]: 0 : for (i = 0; i < rxq->q_depth; i++) {
77 : : hinic3_get_rq_wqe(rxq, &rq_wqe, &pi);
78 [ # # ]: 0 : if (!rq_wqe) {
79 : 0 : PMD_DRV_LOG(ERR,
80 : : "Get rq wqe failed, rxq id: %d, wqe id: %d",
81 : : rxq->q_id, i);
82 : 0 : break;
83 : : }
84 : :
85 [ # # ]: 0 : if (rxq->wqe_type == HINIC3_EXTEND_RQ_WQE) {
86 : : /* Unit of cqe length is 16B. */
87 : 0 : hinic3_set_sge(&rq_wqe->extend_wqe.cqe_sect.sge,
88 : : cqe_dma,
89 : : HINIC3_CQE_LEN >> HINIC3_CQE_SIZE_SHIFT);
90 : : /* Use fixed len. */
91 : 0 : rq_wqe->extend_wqe.buf_desc.sge.len = nic_dev->rx_buff_len;
92 : : } else {
93 : 0 : rq_wqe->normal_wqe.cqe_hi_addr = upper_32_bits(cqe_dma);
94 : 0 : rq_wqe->normal_wqe.cqe_lo_addr = lower_32_bits(cqe_dma);
95 : : }
96 : :
97 : 0 : cqe_dma += sizeof(struct hinic3_rq_cqe);
98 : :
99 : : hinic3_cpu_to_hw(rq_wqe, rxq->wqebb_size);
100 : : }
101 : :
102 : : hinic3_put_rq_wqe(rxq, i);
103 : :
104 : 0 : return i;
105 : : }
106 : :
107 : : static struct rte_mbuf *
108 : 0 : hinic3_rx_alloc_mbuf(struct hinic3_rxq *rxq, rte_iova_t *dma_addr)
109 : : {
110 : 0 : struct rte_mbuf *mbuf = NULL;
111 : :
112 [ # # ]: 0 : if (unlikely(rte_pktmbuf_alloc_bulk(rxq->mb_pool, &mbuf, 1) != 0))
113 : : return NULL;
114 : :
115 : 0 : *dma_addr = rte_mbuf_data_iova_default(mbuf);
116 : : #ifdef HINIC3_XSTAT_MBUF_USE
117 : : rxq->rxq_stats.rx_alloc_mbuf_bytes++;
118 : : #endif
119 : 0 : return mbuf;
120 : : }
121 : :
122 : : #ifdef HINIC3_XSTAT_RXBUF_INFO
123 : : static void
124 : : hinic3_rxq_buffer_done_count(struct hinic3_rxq *rxq)
125 : : {
126 : : uint16_t sw_ci, avail_pkts = 0, hit_done = 0, cqe_hole = 0;
127 : : RTE_ATOMIC(uint32_t)status;
128 : : volatile struct hinic3_rq_cqe *rx_cqe;
129 : :
130 : : for (sw_ci = 0; sw_ci < rxq->q_depth; sw_ci++) {
131 : : rx_cqe = &rxq->rx_cqe[sw_ci];
132 : :
133 : : /* Check current ci is done. */
134 : : status = rx_cqe->status;
135 : : if (!HINIC3_GET_RX_DONE(status)) {
136 : : if (hit_done) {
137 : : cqe_hole++;
138 : : hit_done = 0;
139 : : }
140 : : continue;
141 : : }
142 : :
143 : : avail_pkts++;
144 : : hit_done = 1;
145 : : }
146 : :
147 : : rxq->rxq_stats.rx_avail = avail_pkts;
148 : : rxq->rxq_stats.rx_hole = cqe_hole;
149 : : }
150 : :
151 : : void
152 : : hinic3_get_stats(struct hinic3_rxq *rxq)
153 : : {
154 : : rxq->rxq_stats.rx_mbuf = rxq->q_depth - hinic3_get_rq_free_wqebb(rxq);
155 : :
156 : : hinic3_rxq_buffer_done_count(rxq);
157 : : }
158 : : #endif
159 : :
160 : : uint16_t
161 : 0 : hinic3_rx_fill_buffers(struct hinic3_rxq *rxq)
162 : : {
163 : : struct hinic3_rq_wqe *rq_wqe = NULL;
164 : : struct hinic3_rx_info *rx_info = NULL;
165 : : struct rte_mbuf *mb = NULL;
166 : : rte_iova_t dma_addr;
167 : : uint16_t i, free_wqebbs;
168 : :
169 : 0 : free_wqebbs = rxq->delta - 1;
170 [ # # ]: 0 : for (i = 0; i < free_wqebbs; i++) {
171 : 0 : rx_info = &rxq->rx_info[rxq->next_to_update];
172 : :
173 : 0 : mb = hinic3_rx_alloc_mbuf(rxq, &dma_addr);
174 [ # # ]: 0 : if (!mb) {
175 : 0 : PMD_DRV_LOG(ERR, "Alloc mbuf failed");
176 : 0 : break;
177 : : }
178 : :
179 : 0 : rx_info->mbuf = mb;
180 : :
181 : 0 : rq_wqe = NIC_WQE_ADDR(rxq, rxq->next_to_update);
182 : :
183 : : /* Fill buffer address only. */
184 [ # # ]: 0 : if (rxq->wqe_type == HINIC3_EXTEND_RQ_WQE) {
185 : 0 : rq_wqe->extend_wqe.buf_desc.sge.hi_addr =
186 : 0 : hinic3_hw_be32(upper_32_bits(dma_addr));
187 : 0 : rq_wqe->extend_wqe.buf_desc.sge.lo_addr =
188 : 0 : hinic3_hw_be32(lower_32_bits(dma_addr));
189 : : } else {
190 : 0 : rq_wqe->normal_wqe.buf_hi_addr =
191 : 0 : hinic3_hw_be32(upper_32_bits(dma_addr));
192 : 0 : rq_wqe->normal_wqe.buf_lo_addr =
193 : 0 : hinic3_hw_be32(lower_32_bits(dma_addr));
194 : : }
195 : :
196 : 0 : rxq->next_to_update = (rxq->next_to_update + 1) & rxq->q_mask;
197 : : }
198 : :
199 [ # # ]: 0 : if (likely(i > 0)) {
200 : 0 : hinic3_write_db(rxq->db_addr, rxq->q_id, 0, RQ_CFLAG_DP,
201 : 0 : (rxq->next_to_update << rxq->wqe_type));
202 : : /* Init rxq contxet used, need to optimization. */
203 : 0 : rxq->prod_idx = rxq->next_to_update;
204 : 0 : rxq->delta -= i;
205 : : } else {
206 : 0 : PMD_DRV_LOG(ERR, "Alloc rx buffers failed, rxq_id: %d", rxq->q_id);
207 : : }
208 : :
209 : 0 : return i;
210 : : }
211 : :
212 : : void
213 : 0 : hinic3_free_rxq_mbufs(struct hinic3_rxq *rxq)
214 : : {
215 : : struct hinic3_rx_info *rx_info = NULL;
216 : 0 : int free_wqebbs = hinic3_get_rq_free_wqebb(rxq) + 1;
217 : : volatile struct hinic3_rq_cqe *rx_cqe = NULL;
218 : : uint16_t ci;
219 : :
220 [ # # ]: 0 : while (free_wqebbs++ < rxq->q_depth) {
221 : : ci = hinic3_get_rq_local_ci(rxq);
222 : :
223 : 0 : rx_cqe = &rxq->rx_cqe[ci];
224 : :
225 : : /* Clear done bit. */
226 : 0 : rx_cqe->status = 0;
227 : :
228 : 0 : rx_info = &rxq->rx_info[ci];
229 : 0 : rte_pktmbuf_free(rx_info->mbuf);
230 : 0 : rx_info->mbuf = NULL;
231 : :
232 : : hinic3_update_rq_local_ci(rxq, 1);
233 : : #ifdef HINIC3_XSTAT_MBUF_USE
234 : : rxq->rxq_stats.rx_free_mbuf_bytes++;
235 : : #endif
236 : : }
237 : 0 : }
238 : :
239 : : void
240 : 0 : hinic3_free_all_rxq_mbufs(struct hinic3_nic_dev *nic_dev)
241 : : {
242 : : uint16_t qid;
243 : :
244 [ # # ]: 0 : for (qid = 0; qid < nic_dev->num_rqs; qid++)
245 : 0 : hinic3_free_rxq_mbufs(nic_dev->rxqs[qid]);
246 : 0 : }
247 : :
248 : : static uint32_t
249 : : hinic3_rx_alloc_mbuf_bulk(struct hinic3_rxq *rxq, struct rte_mbuf **mbufs,
250 : : uint32_t exp_mbuf_cnt)
251 : : {
252 : : uint32_t avail_cnt;
253 : : int err;
254 : :
255 : 0 : err = rte_pktmbuf_alloc_bulk(rxq->mb_pool, mbufs, exp_mbuf_cnt);
256 [ # # ]: 0 : if (likely(err == 0)) {
257 : : avail_cnt = exp_mbuf_cnt;
258 : : } else {
259 : : avail_cnt = 0;
260 : 0 : rxq->rxq_stats.rx_nombuf += exp_mbuf_cnt;
261 : : }
262 : : #ifdef HINIC3_XSTAT_MBUF_USE
263 : : rxq->rxq_stats.rx_alloc_mbuf_bytes += avail_cnt;
264 : : #endif
265 : : return avail_cnt;
266 : : }
267 : :
268 : : static int
269 : 0 : hinic3_rearm_rxq_mbuf(struct hinic3_rxq *rxq)
270 : : {
271 : : struct hinic3_rq_wqe *rq_wqe = NULL;
272 : : struct rte_mbuf **rearm_mbufs;
273 : : uint32_t i, free_wqebbs, rearm_wqebbs, exp_wqebbs;
274 : : rte_iova_t dma_addr;
275 : : uint16_t pi;
276 [ # # ]: 0 : struct hinic3_nic_dev *nic_dev = rxq->nic_dev;
277 : :
278 : : /* Check free wqebb cnt fo rearm. */
279 : 0 : free_wqebbs = hinic3_get_rq_free_wqebb(rxq);
280 [ # # ]: 0 : if (unlikely(free_wqebbs < rxq->rx_free_thresh))
281 : : return -ENOMEM;
282 : :
283 : : /* Get rearm mbuf array. */
284 : : pi = hinic3_get_rq_local_pi(rxq);
285 : 0 : rearm_mbufs = (struct rte_mbuf **)(&rxq->rx_info[pi]);
286 : :
287 : : /* Check rxq free wqebbs turn around. */
288 : 0 : exp_wqebbs = rxq->q_depth - pi;
289 : : if (free_wqebbs < exp_wqebbs)
290 : : exp_wqebbs = free_wqebbs;
291 : :
292 : : /* Alloc mbuf in bulk. */
293 : : rearm_wqebbs = hinic3_rx_alloc_mbuf_bulk(rxq, rearm_mbufs, exp_wqebbs);
294 [ # # ]: 0 : if (unlikely(rearm_wqebbs == 0))
295 : : return -ENOMEM;
296 : :
297 : : /* Rearm rxq mbuf. */
298 : 0 : rq_wqe = NIC_WQE_ADDR(rxq, pi);
299 [ # # ]: 0 : for (i = 0; i < rearm_wqebbs; i++) {
300 [ # # ]: 0 : dma_addr = rte_mbuf_data_iova_default(rearm_mbufs[i]);
301 : :
302 : : /* Fill buffer address only. */
303 [ # # ]: 0 : if (rxq->wqe_type == HINIC3_EXTEND_RQ_WQE) {
304 : 0 : rq_wqe->extend_wqe.buf_desc.sge.hi_addr =
305 : 0 : hinic3_hw_be32(upper_32_bits(dma_addr));
306 : 0 : rq_wqe->extend_wqe.buf_desc.sge.lo_addr =
307 : 0 : hinic3_hw_be32(lower_32_bits(dma_addr));
308 : 0 : rq_wqe->extend_wqe.buf_desc.sge.len =
309 : 0 : nic_dev->rx_buff_len;
310 : : } else {
311 : 0 : rq_wqe->normal_wqe.buf_hi_addr =
312 : 0 : hinic3_hw_be32(upper_32_bits(dma_addr));
313 : 0 : rq_wqe->normal_wqe.buf_lo_addr =
314 : 0 : hinic3_hw_be32(lower_32_bits(dma_addr));
315 : : }
316 : :
317 : 0 : rq_wqe =
318 : 0 : (struct hinic3_rq_wqe *)((uint64_t)rq_wqe + rxq->wqebb_size);
319 : : }
320 : 0 : rxq->prod_idx += rearm_wqebbs;
321 : 0 : rxq->delta -= rearm_wqebbs;
322 : :
323 : 0 : hinic3_write_db(rxq->db_addr, rxq->q_id, 0, RQ_CFLAG_DP,
324 : 0 : ((pi + rearm_wqebbs) & rxq->q_mask) << rxq->wqe_type);
325 : 0 : return 0;
326 : : }
327 : :
328 : : static int
329 : 0 : hinic3_init_rss_key(struct hinic3_nic_dev *nic_dev,
330 : : struct rte_eth_rss_conf *rss_conf)
331 : : {
332 : 0 : uint8_t default_rss_key[HINIC3_RSS_KEY_SIZE] = {
333 : : 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
334 : : 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
335 : : 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
336 : : 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
337 : : 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa};
338 : 0 : uint8_t hashkey[HINIC3_RSS_KEY_SIZE] = {0};
339 : : int err;
340 : :
341 [ # # ]: 0 : if (rss_conf->rss_key == NULL ||
342 [ # # ]: 0 : rss_conf->rss_key_len > HINIC3_RSS_KEY_SIZE)
343 : : memcpy(hashkey, default_rss_key, HINIC3_RSS_KEY_SIZE);
344 : : else
345 : 0 : memcpy(hashkey, rss_conf->rss_key, rss_conf->rss_key_len);
346 : :
347 : 0 : err = hinic3_rss_set_hash_key(nic_dev->hwdev, hashkey, HINIC3_RSS_KEY_SIZE);
348 [ # # ]: 0 : if (err)
349 : : return err;
350 : :
351 : 0 : memcpy(nic_dev->rss_key, hashkey, HINIC3_RSS_KEY_SIZE);
352 : 0 : return 0;
353 : : }
354 : :
355 : : void
356 : 0 : hinic3_add_rq_to_rx_queue_list(struct hinic3_nic_dev *nic_dev, uint16_t queue_id)
357 : : {
358 : 0 : uint8_t rss_queue_count = nic_dev->num_rss;
359 : :
360 : : RTE_ASSERT(rss_queue_count <= (RTE_DIM(nic_dev->rx_queue_list) - 1));
361 : :
362 : 0 : nic_dev->rx_queue_list[rss_queue_count] = (uint8_t)queue_id;
363 : 0 : nic_dev->num_rss++;
364 : 0 : }
365 : :
366 : : void
367 : 0 : hinic3_init_rx_queue_list(struct hinic3_nic_dev *nic_dev)
368 : : {
369 : 0 : nic_dev->num_rss = 0;
370 : 0 : }
371 : :
372 : : static void
373 : 0 : hinic3_fill_indir_tbl(struct hinic3_nic_dev *nic_dev, uint32_t *indir_tbl)
374 : : {
375 : 0 : uint8_t rss_queue_count = nic_dev->num_rss;
376 : : int i = 0;
377 : : int j;
378 : :
379 [ # # ]: 0 : if (rss_queue_count == 0) {
380 : : /* Delete q_id from indir tbl. */
381 [ # # ]: 0 : for (i = 0; i < HINIC3_RSS_INDIR_SIZE; i++)
382 : : /* Invalid value in indir tbl. */
383 : 0 : indir_tbl[i] = 0xFFFF;
384 : : } else {
385 [ # # ]: 0 : while (i < HINIC3_RSS_INDIR_SIZE)
386 [ # # # # ]: 0 : for (j = 0; (j < rss_queue_count) &&
387 : 0 : (i < HINIC3_RSS_INDIR_SIZE); j++)
388 : 0 : indir_tbl[i++] = nic_dev->rx_queue_list[j];
389 : : }
390 : 0 : }
391 : :
392 : : int
393 : 0 : hinic3_refill_indir_rqid(struct hinic3_rxq *rxq)
394 : : {
395 : 0 : struct hinic3_nic_dev *nic_dev = rxq->nic_dev;
396 : : uint32_t *indir_tbl;
397 : : int err;
398 : :
399 : 0 : indir_tbl = rte_zmalloc(NULL, HINIC3_RSS_INDIR_SIZE * sizeof(uint32_t), 0);
400 [ # # ]: 0 : if (!indir_tbl) {
401 : 0 : PMD_DRV_LOG(ERR,
402 : : "Alloc indir_tbl mem failed, eth_dev:%s, queue_idx:%d",
403 : : nic_dev->dev_name, rxq->q_id);
404 : 0 : return -ENOMEM;
405 : : }
406 : :
407 : : /* Build indir tbl according to the number of rss queue. */
408 : 0 : hinic3_fill_indir_tbl(nic_dev, indir_tbl);
409 : :
410 : 0 : err = hinic3_rss_set_indir_tbl(nic_dev->hwdev, indir_tbl,
411 : : HINIC3_RSS_INDIR_SIZE);
412 [ # # ]: 0 : if (err) {
413 : 0 : PMD_DRV_LOG(ERR,
414 : : "Set indirect table failed, eth_dev:%s, queue_idx:%d",
415 : : nic_dev->dev_name, rxq->q_id);
416 : 0 : goto out;
417 : : }
418 : :
419 : 0 : out:
420 : 0 : rte_free(indir_tbl);
421 : 0 : return err;
422 : : }
423 : :
424 : : static int
425 : 0 : hinic3_init_rss_type(struct hinic3_nic_dev *nic_dev,
426 : : struct rte_eth_rss_conf *rss_conf)
427 : : {
428 : : struct hinic3_rss_type rss_type = {0};
429 : 0 : uint64_t rss_hf = rss_conf->rss_hf;
430 : : int err;
431 : :
432 : 0 : rss_type.ipv4 = (rss_hf & (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4)) ? 1 : 0;
433 : 0 : rss_type.tcp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) ? 1 : 0;
434 : 0 : rss_type.ipv6 = (rss_hf & (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6)) ? 1 : 0;
435 : 0 : rss_type.ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_EX) ? 1 : 0;
436 : 0 : rss_type.tcp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) ? 1 : 0;
437 : 0 : rss_type.tcp_ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_TCP_EX) ? 1 : 0;
438 : 0 : rss_type.udp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) ? 1 : 0;
439 : 0 : rss_type.udp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) ? 1 : 0;
440 : :
441 : 0 : err = hinic3_set_rss_type(nic_dev->hwdev, rss_type);
442 : 0 : return err;
443 : : }
444 : :
445 : : int
446 : 0 : hinic3_update_rss_config(struct rte_eth_dev *dev,
447 : : struct rte_eth_rss_conf *rss_conf)
448 : : {
449 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
450 : 0 : uint8_t prio_tc[HINIC3_DCB_UP_MAX] = {0};
451 : : uint8_t num_tc = 0;
452 : : int err;
453 : :
454 [ # # ]: 0 : if (rss_conf->rss_hf == 0) {
455 : 0 : rss_conf->rss_hf = HINIC3_RSS_OFFLOAD_ALL;
456 [ # # ]: 0 : } else if ((rss_conf->rss_hf & HINIC3_RSS_OFFLOAD_ALL) == 0) {
457 : 0 : PMD_DRV_LOG(ERR, "Doesn't support rss hash type: %" PRIu64,
458 : : rss_conf->rss_hf);
459 : 0 : return -EINVAL;
460 : : }
461 : :
462 : 0 : err = hinic3_rss_template_alloc(nic_dev->hwdev);
463 [ # # ]: 0 : if (err) {
464 : 0 : PMD_DRV_LOG(ERR, "Alloc rss template failed, err: %d", err);
465 : 0 : return err;
466 : : }
467 : :
468 : 0 : err = hinic3_init_rss_key(nic_dev, rss_conf);
469 [ # # ]: 0 : if (err) {
470 : 0 : PMD_DRV_LOG(ERR, "Init rss hash key failed, err: %d", err);
471 : 0 : goto init_rss_fail;
472 : : }
473 : :
474 : 0 : err = hinic3_init_rss_type(nic_dev, rss_conf);
475 [ # # ]: 0 : if (err) {
476 : 0 : PMD_DRV_LOG(ERR, "Init rss hash type failed, err: %d", err);
477 : 0 : goto init_rss_fail;
478 : : }
479 : :
480 : 0 : err = hinic3_rss_set_hash_engine(nic_dev->hwdev,
481 : : HINIC3_RSS_HASH_ENGINE_TYPE_TOEP);
482 [ # # ]: 0 : if (err) {
483 : 0 : PMD_DRV_LOG(ERR, "Init rss hash function failed, err: %d", err);
484 : 0 : goto init_rss_fail;
485 : : }
486 : :
487 : 0 : err = hinic3_rss_cfg(nic_dev->hwdev, HINIC3_RSS_ENABLE, num_tc,
488 : : prio_tc);
489 [ # # ]: 0 : if (err) {
490 : 0 : PMD_DRV_LOG(ERR, "Enable rss failed, err: %d", err);
491 : 0 : goto init_rss_fail;
492 : : }
493 : :
494 : 0 : nic_dev->rss_state = HINIC3_RSS_ENABLE;
495 : 0 : return 0;
496 : :
497 : 0 : init_rss_fail:
498 [ # # ]: 0 : if (hinic3_rss_template_free(nic_dev->hwdev))
499 : 0 : PMD_DRV_LOG(WARNING, "Free rss template failed");
500 : :
501 : : return err;
502 : : }
503 : :
504 : : /**
505 : : * Search given queue array to find position of given id.
506 : : * Return queue pos or queue_count if not found.
507 : : */
508 : : static uint8_t
509 : : hinic3_find_queue_pos_by_rq_id(uint8_t *queues, uint8_t queues_count, uint8_t queue_id)
510 : : {
511 : : uint8_t pos;
512 : :
513 [ # # ]: 0 : for (pos = 0; pos < queues_count; pos++) {
514 [ # # ]: 0 : if (queue_id == queues[pos])
515 : : break;
516 : : }
517 : :
518 : : return pos;
519 : : }
520 : :
521 : : void
522 : 0 : hinic3_remove_rq_from_rx_queue_list(struct hinic3_nic_dev *nic_dev,
523 : : uint16_t queue_id)
524 : : {
525 : : uint8_t queue_pos;
526 : 0 : uint8_t rss_queue_count = nic_dev->num_rss;
527 : :
528 : 0 : queue_pos = hinic3_find_queue_pos_by_rq_id(nic_dev->rx_queue_list,
529 : : rss_queue_count, queue_id);
530 : : /*
531 : : * If queue was not at the end of the list,
532 : : * shift started queues up queue array list.
533 : : */
534 [ # # ]: 0 : if (queue_pos < rss_queue_count) {
535 : 0 : rss_queue_count--;
536 : 0 : memmove(nic_dev->rx_queue_list + queue_pos,
537 : 0 : nic_dev->rx_queue_list + queue_pos + 1,
538 : 0 : (rss_queue_count - queue_pos) *
539 : : sizeof(nic_dev->rx_queue_list[0]));
540 : : }
541 : :
542 : : RTE_ASSERT(rss_queue_count < RTE_DIM(nic_dev->rx_queue_list));
543 : 0 : nic_dev->num_rss = rss_queue_count;
544 : 0 : }
545 : :
546 : : static void
547 : 0 : hinic3_rx_queue_release_mbufs(struct hinic3_rxq *rxq)
548 : : {
549 : : uint16_t sw_ci, ci_mask, free_wqebbs;
550 : : uint16_t rx_buf_len;
551 : : uint32_t vlan_len, pkt_len;
552 : : RTE_ATOMIC(uint32_t)status;
553 : : uint32_t pkt_left_len = 0;
554 : : uint32_t nr_released = 0;
555 : : struct hinic3_rx_info *rx_info;
556 : : volatile struct hinic3_rq_cqe *rx_cqe;
557 : :
558 : : sw_ci = hinic3_get_rq_local_ci(rxq);
559 : 0 : rx_info = &rxq->rx_info[sw_ci];
560 : 0 : rx_cqe = &rxq->rx_cqe[sw_ci];
561 : : free_wqebbs = hinic3_get_rq_free_wqebb(rxq) + 1;
562 : 0 : status = rx_cqe->status;
563 : : ci_mask = rxq->q_mask;
564 : :
565 [ # # ]: 0 : while (free_wqebbs < rxq->q_depth) {
566 : 0 : rx_buf_len = rxq->buf_len;
567 [ # # ]: 0 : if (pkt_left_len != 0) {
568 : : /* Flush continues jumbo rqe. */
569 : 0 : pkt_left_len = (pkt_left_len <= rx_buf_len)
570 [ # # ]: 0 : ? 0 : (pkt_left_len - rx_buf_len);
571 [ # # ]: 0 : } else if (HINIC3_GET_RX_FLUSH(status)) {
572 : : /* Flush one released rqe. */
573 : : pkt_left_len = 0;
574 [ # # ]: 0 : } else if (HINIC3_GET_RX_DONE(status)) {
575 : : /* Flush single packet or first jumbo rqe. */
576 : 0 : vlan_len = hinic3_hw_cpu32(rx_cqe->vlan_len);
577 : 0 : pkt_len = HINIC3_GET_RX_PKT_LEN(vlan_len);
578 : 0 : pkt_left_len = (pkt_len <= rx_buf_len)
579 [ # # ]: 0 : ? 0 : (pkt_len - rx_buf_len);
580 : : } else {
581 : : break;
582 : : }
583 : 0 : rte_pktmbuf_free(rx_info->mbuf);
584 : :
585 : 0 : rx_info->mbuf = NULL;
586 : 0 : rx_cqe->status = 0;
587 : 0 : nr_released++;
588 : 0 : free_wqebbs++;
589 : :
590 : : /* Update ci to next cqe. */
591 : 0 : sw_ci++;
592 : 0 : sw_ci &= ci_mask;
593 : 0 : rx_info = &rxq->rx_info[sw_ci];
594 : 0 : rx_cqe = &rxq->rx_cqe[sw_ci];
595 : 0 : status = rx_cqe->status;
596 : : }
597 : :
598 : 0 : hinic3_update_rq_local_ci(rxq, nr_released);
599 : 0 : }
600 : :
601 : : int
602 : 0 : hinic3_poll_rq_empty(struct hinic3_rxq *rxq)
603 : : {
604 : : uint64_t end;
605 : : int free_wqebb;
606 : : int err = -EFAULT;
607 : :
608 : 0 : end = msecs_to_cycles(HINIC3_FLUSH_QUEUE_TIMEOUT) + cycles;
609 : : do {
610 : 0 : free_wqebb = hinic3_get_rq_free_wqebb(rxq) + 1;
611 [ # # ]: 0 : if (free_wqebb == rxq->q_depth) {
612 : : err = 0;
613 : : break;
614 : : }
615 : 0 : hinic3_rx_queue_release_mbufs(rxq);
616 : 0 : rte_delay_us(1);
617 [ # # ]: 0 : } while (time_before(cycles, end));
618 : :
619 : 0 : return err;
620 : : }
621 : :
622 : : void
623 : 0 : hinic3_dump_cqe_status(struct hinic3_rxq *rxq, uint32_t *cqe_done_cnt,
624 : : uint32_t *cqe_hole_cnt, uint32_t *head_ci, uint32_t *head_done)
625 : : {
626 : : uint16_t sw_ci;
627 : : uint16_t avail_pkts = 0;
628 : : uint16_t hit_done = 0;
629 : : uint16_t cqe_hole = 0;
630 : : RTE_ATOMIC(uint32_t)status;
631 : : volatile struct hinic3_rq_cqe *rx_cqe;
632 : :
633 : : sw_ci = hinic3_get_rq_local_ci(rxq);
634 : 0 : rx_cqe = &rxq->rx_cqe[sw_ci];
635 : 0 : status = rx_cqe->status;
636 : 0 : *head_done = HINIC3_GET_RX_DONE(status);
637 : 0 : *head_ci = sw_ci;
638 : :
639 [ # # ]: 0 : for (sw_ci = 0; sw_ci < rxq->q_depth; sw_ci++) {
640 : 0 : rx_cqe = &rxq->rx_cqe[sw_ci];
641 : :
642 : : /* Check current ci is done. */
643 : 0 : status = rx_cqe->status;
644 [ # # ]: 0 : if (!HINIC3_GET_RX_DONE(status) ||
645 [ # # ]: 0 : !HINIC3_GET_RX_FLUSH(status)) {
646 [ # # ]: 0 : if (hit_done) {
647 : 0 : cqe_hole++;
648 : : hit_done = 0;
649 : : }
650 : :
651 : 0 : continue;
652 : : }
653 : :
654 : 0 : avail_pkts++;
655 : : hit_done = 1;
656 : : }
657 : :
658 : 0 : *cqe_done_cnt = avail_pkts;
659 : 0 : *cqe_hole_cnt = cqe_hole;
660 : 0 : }
661 : :
662 : : int
663 : 0 : hinic3_stop_rq(struct rte_eth_dev *eth_dev, struct hinic3_rxq *rxq)
664 : : {
665 : 0 : struct hinic3_nic_dev *nic_dev = rxq->nic_dev;
666 : 0 : uint32_t cqe_done_cnt = 0;
667 : 0 : uint32_t cqe_hole_cnt = 0;
668 : : uint32_t head_ci, head_done;
669 : : int err;
670 : :
671 : : /* Disable rxq intr. */
672 : 0 : hinic3_dev_rx_queue_intr_disable(eth_dev, rxq->q_id);
673 : :
674 : : /* Lock dev queue switch. */
675 : 0 : rte_spinlock_lock(&nic_dev->queue_list_lock);
676 : :
677 [ # # ]: 0 : if (nic_dev->num_rss == 1) {
678 : 0 : err = hinic3_set_vport_enable(nic_dev->hwdev, false);
679 [ # # ]: 0 : if (err) {
680 : 0 : PMD_DRV_LOG(ERR, "%s Disable vport failed, rc:%d",
681 : : nic_dev->dev_name, err);
682 : : }
683 : : }
684 : 0 : hinic3_remove_rq_from_rx_queue_list(nic_dev, rxq->q_id);
685 : :
686 : : /*
687 : : * If RSS is enable, remove q_id from rss indir table.
688 : : * If RSS is disable, no mbuf in rq, packet will be dropped.
689 : : */
690 [ # # ]: 0 : if (nic_dev->rss_state == HINIC3_RSS_ENABLE) {
691 : 0 : err = hinic3_refill_indir_rqid(rxq);
692 [ # # ]: 0 : if (err) {
693 : 0 : PMD_DRV_LOG(ERR,
694 : : "Clear rq in indirect table failed, eth_dev:%s, queue_idx:%d",
695 : : nic_dev->dev_name, rxq->q_id);
696 : 0 : hinic3_add_rq_to_rx_queue_list(nic_dev, rxq->q_id);
697 : 0 : goto set_indir_failed;
698 : : }
699 : : }
700 : :
701 : : /* Unlock dev queue list switch. */
702 : : rte_spinlock_unlock(&nic_dev->queue_list_lock);
703 : :
704 : : /* Send flush rxq cmd to device. */
705 : 0 : err = hinic3_set_rq_flush(nic_dev->hwdev, rxq->q_id);
706 [ # # ]: 0 : if (err) {
707 : 0 : PMD_DRV_LOG(ERR, "Flush rq failed, eth_dev:%s, queue_idx:%d",
708 : : nic_dev->dev_name, rxq->q_id);
709 : 0 : goto rq_flush_failed;
710 : : }
711 : :
712 : 0 : err = hinic3_poll_rq_empty(rxq);
713 [ # # ]: 0 : if (err) {
714 : 0 : hinic3_dump_cqe_status(rxq, &cqe_done_cnt, &cqe_hole_cnt,
715 : : &head_ci, &head_done);
716 : 0 : PMD_DRV_LOG(ERR, "Poll rq empty timeout");
717 : 0 : PMD_DRV_LOG(ERR,
718 : : "eth_dev:%s, queue_idx:%d, mbuf_left:%d, cqe_done:%d, cqe_hole:%d, cqe[%d].done=%d",
719 : : nic_dev->dev_name, rxq->q_id,
720 : : rxq->q_depth - hinic3_get_rq_free_wqebb(rxq),
721 : : cqe_done_cnt, cqe_hole_cnt, head_ci, head_done);
722 : 0 : goto poll_rq_failed;
723 : : }
724 : :
725 : : return 0;
726 : :
727 : : poll_rq_failed:
728 : 0 : rq_flush_failed:
729 : : rte_spinlock_lock(&nic_dev->queue_list_lock);
730 : 0 : set_indir_failed:
731 : 0 : hinic3_add_rq_to_rx_queue_list(nic_dev, rxq->q_id);
732 [ # # ]: 0 : if (nic_dev->rss_state == HINIC3_RSS_ENABLE)
733 : 0 : hinic3_refill_indir_rqid(rxq);
734 : : rte_spinlock_unlock(&nic_dev->queue_list_lock);
735 : 0 : hinic3_dev_rx_queue_intr_enable(eth_dev, rxq->q_id);
736 : 0 : return err;
737 : : }
738 : :
739 : : int
740 : 0 : hinic3_start_rq(struct rte_eth_dev *eth_dev, struct hinic3_rxq *rxq)
741 : : {
742 : 0 : struct hinic3_nic_dev *nic_dev = rxq->nic_dev;
743 : : int err = 0;
744 : :
745 : : /* Lock dev queue switch. */
746 : 0 : rte_spinlock_lock(&nic_dev->queue_list_lock);
747 : 0 : hinic3_add_rq_to_rx_queue_list(nic_dev, rxq->q_id);
748 : :
749 [ # # ]: 0 : if (nic_dev->rss_state == HINIC3_RSS_ENABLE) {
750 : 0 : err = hinic3_refill_indir_rqid(rxq);
751 [ # # ]: 0 : if (err) {
752 : 0 : PMD_DRV_LOG(ERR,
753 : : "Refill rq to indirect table failed, eth_dev:%s, queue_idx:%d err:%d",
754 : : nic_dev->dev_name, rxq->q_id, err);
755 : 0 : hinic3_remove_rq_from_rx_queue_list(nic_dev, rxq->q_id);
756 : : }
757 : : }
758 : 0 : hinic3_rearm_rxq_mbuf(rxq);
759 [ # # ]: 0 : if (rxq->nic_dev->num_rss == 1) {
760 : 0 : err = hinic3_set_vport_enable(nic_dev->hwdev, true);
761 [ # # ]: 0 : if (err)
762 : 0 : PMD_DRV_LOG(ERR, "%s enable vport failed, err:%d",
763 : : nic_dev->dev_name, err);
764 : : }
765 : :
766 : : /* Unlock dev queue list switch. */
767 : : rte_spinlock_unlock(&nic_dev->queue_list_lock);
768 : :
769 : 0 : hinic3_dev_rx_queue_intr_enable(eth_dev, rxq->q_id);
770 : :
771 : 0 : return err;
772 : : }
773 : :
774 : :
775 : : static inline uint64_t
776 : : hinic3_rx_vlan(uint32_t offload_type, uint32_t vlan_len, uint16_t *vlan_tci)
777 : : {
778 : : uint16_t vlan_tag;
779 : :
780 : 0 : vlan_tag = HINIC3_GET_RX_VLAN_TAG(vlan_len);
781 [ # # ]: 0 : if (!HINIC3_GET_RX_VLAN_OFFLOAD_EN(offload_type) || vlan_tag == 0) {
782 : 0 : *vlan_tci = 0;
783 : 0 : return 0;
784 : : }
785 : :
786 : 0 : *vlan_tci = vlan_tag;
787 : :
788 : 0 : return HINIC3_PKT_RX_VLAN | HINIC3_PKT_RX_VLAN_STRIPPED;
789 : : }
790 : :
791 : : static inline uint64_t
792 : 0 : hinic3_rx_csum(uint32_t status, struct hinic3_rxq *rxq)
793 : : {
794 : 0 : struct hinic3_nic_dev *nic_dev = rxq->nic_dev;
795 : : uint32_t csum_err;
796 : : uint64_t flags;
797 : :
798 [ # # ]: 0 : if (unlikely(!(nic_dev->rx_csum_en & HINIC3_DEFAULT_RX_CSUM_OFFLOAD)))
799 : : return HINIC3_PKT_RX_IP_CKSUM_UNKNOWN;
800 : :
801 : 0 : csum_err = HINIC3_GET_RX_CSUM_ERR(status);
802 [ # # ]: 0 : if (likely(csum_err == 0))
803 : : return (HINIC3_PKT_RX_IP_CKSUM_GOOD |
804 : : HINIC3_PKT_RX_L4_CKSUM_GOOD);
805 : :
806 : : /*
807 : : * If bypass bit is set, all other err status indications should be
808 : : * ignored.
809 : : */
810 [ # # ]: 0 : if (unlikely(csum_err & HINIC3_RX_CSUM_HW_CHECK_NONE))
811 : : return HINIC3_PKT_RX_IP_CKSUM_UNKNOWN;
812 : :
813 : : flags = 0;
814 : :
815 : : /* IP checksum error. */
816 [ # # ]: 0 : if (csum_err & HINIC3_RX_CSUM_IP_CSUM_ERR) {
817 : : flags |= HINIC3_PKT_RX_IP_CKSUM_BAD;
818 : 0 : rxq->rxq_stats.csum_errors++;
819 : : }
820 : :
821 : : /* L4 checksum error. */
822 : 0 : if ((csum_err & HINIC3_RX_CSUM_TCP_CSUM_ERR) ||
823 [ # # ]: 0 : (csum_err & HINIC3_RX_CSUM_UDP_CSUM_ERR) ||
824 : : (csum_err & HINIC3_RX_CSUM_SCTP_CRC_ERR)) {
825 : 0 : flags |= HINIC3_PKT_RX_L4_CKSUM_BAD;
826 : 0 : rxq->rxq_stats.csum_errors++;
827 : : }
828 : :
829 [ # # ]: 0 : if (unlikely(csum_err == HINIC3_RX_CSUM_IPSU_OTHER_ERR))
830 : 0 : rxq->rxq_stats.other_errors++;
831 : :
832 : : return flags;
833 : : }
834 : :
835 : : static inline uint64_t
836 : : hinic3_rx_rss_hash(uint32_t offload_type, uint32_t rss_hash_value, uint32_t *rss_hash)
837 : : {
838 : : uint32_t rss_type;
839 : :
840 : 0 : rss_type = HINIC3_GET_RSS_TYPES(offload_type);
841 : 0 : if (likely(rss_type != 0)) {
842 : 0 : *rss_hash = rss_hash_value;
843 : 0 : return HINIC3_PKT_RX_RSS_HASH;
844 : : }
845 : :
846 : : return 0;
847 : : }
848 : :
849 : : static void
850 : 0 : hinic3_recv_jumbo_pkt(struct hinic3_rxq *rxq, struct rte_mbuf *head_mbuf,
851 : : uint32_t remain_pkt_len)
852 : : {
853 : : struct rte_mbuf *cur_mbuf = NULL;
854 : : struct rte_mbuf *rxm = NULL;
855 : : struct hinic3_rx_info *rx_info = NULL;
856 : 0 : uint16_t sw_ci, rx_buf_len = rxq->buf_len;
857 : : uint32_t pkt_len;
858 : :
859 [ # # ]: 0 : while (remain_pkt_len > 0) {
860 : : sw_ci = hinic3_get_rq_local_ci(rxq);
861 [ # # ]: 0 : rx_info = &rxq->rx_info[sw_ci];
862 : :
863 : : hinic3_update_rq_local_ci(rxq, 1);
864 : :
865 : 0 : pkt_len = remain_pkt_len > rx_buf_len ? rx_buf_len
866 : 0 : : remain_pkt_len;
867 : 0 : remain_pkt_len -= pkt_len;
868 : :
869 : 0 : cur_mbuf = rx_info->mbuf;
870 : 0 : cur_mbuf->data_len = (uint16_t)pkt_len;
871 : 0 : cur_mbuf->next = NULL;
872 : :
873 : 0 : head_mbuf->pkt_len += cur_mbuf->data_len;
874 : 0 : head_mbuf->nb_segs++;
875 : : #ifdef HINIC3_XSTAT_MBUF_USE
876 : : rxq->rxq_stats.rx_free_mbuf_bytes++;
877 : : #endif
878 [ # # ]: 0 : if (!rxm)
879 : 0 : head_mbuf->next = cur_mbuf;
880 : : else
881 : 0 : rxm->next = cur_mbuf;
882 : :
883 : : rxm = cur_mbuf;
884 : : }
885 : 0 : }
886 : :
887 : : int
888 : 0 : hinic3_start_all_rqs(struct rte_eth_dev *eth_dev)
889 : : {
890 : : struct hinic3_nic_dev *nic_dev = NULL;
891 : : struct hinic3_rxq *rxq = NULL;
892 : : int err = 0;
893 : : int i;
894 : :
895 : 0 : nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
896 : :
897 [ # # ]: 0 : for (i = 0; i < nic_dev->num_rqs; i++) {
898 : 0 : rxq = eth_dev->data->rx_queues[i];
899 : 0 : hinic3_add_rq_to_rx_queue_list(nic_dev, rxq->q_id);
900 : 0 : err = hinic3_rearm_rxq_mbuf(rxq);
901 [ # # ]: 0 : if (err) {
902 : 0 : PMD_DRV_LOG(ERR,
903 : : "Fail to alloc mbuf for Rx queue %d, qid = %u, need_mbuf: %d",
904 : : i, rxq->q_id, rxq->q_depth);
905 : 0 : goto out;
906 : : }
907 : 0 : hinic3_dev_rx_queue_intr_enable(eth_dev, rxq->q_id);
908 [ # # ]: 0 : if (rxq->rx_deferred_start)
909 : 0 : continue;
910 : 0 : eth_dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
911 : : }
912 : :
913 [ # # ]: 0 : if (nic_dev->rss_state == HINIC3_RSS_ENABLE) {
914 : 0 : err = hinic3_refill_indir_rqid(rxq);
915 [ # # ]: 0 : if (err) {
916 : 0 : PMD_DRV_LOG(ERR,
917 : : "Refill rq to indirect table failed, eth_dev:%s, queue_idx:%d, err:%d",
918 : : rxq->nic_dev->dev_name, rxq->q_id, err);
919 : 0 : goto out;
920 : : }
921 : : }
922 : :
923 : : return 0;
924 : 0 : out:
925 [ # # ]: 0 : for (i = 0; i < nic_dev->num_rqs; i++) {
926 : 0 : rxq = eth_dev->data->rx_queues[i];
927 : 0 : hinic3_remove_rq_from_rx_queue_list(nic_dev, rxq->q_id);
928 : 0 : hinic3_free_rxq_mbufs(rxq);
929 : 0 : hinic3_dev_rx_queue_intr_disable(eth_dev, rxq->q_id);
930 : 0 : eth_dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
931 : : }
932 : : return err;
933 : : }
934 : :
935 : : #define HINIC3_RX_EMPTY_THRESHOLD 3
936 : : uint16_t
937 : 0 : hinic3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
938 : : {
939 : : struct hinic3_rxq *rxq = rx_queue;
940 : : struct hinic3_rx_info *rx_info = NULL;
941 : : volatile struct hinic3_rq_cqe *rx_cqe = NULL;
942 : : struct rte_mbuf *rxm = NULL;
943 : : uint16_t sw_ci, rx_buf_len, wqebb_cnt = 0, pkts = 0;
944 : : uint32_t status, pkt_len, vlan_len, offload_type, lro_num;
945 : : uint64_t rx_bytes = 0;
946 : : uint32_t hash_value;
947 : :
948 : : #ifdef HINIC3_XSTAT_PROF_RX
949 : : uint64_t t1 = rte_get_tsc_cycles();
950 : : uint64_t t2;
951 : : #endif
952 [ # # ]: 0 : if (((rte_get_timer_cycles() - rxq->rxq_stats.tsc) < rxq->wait_time_cycle) &&
953 [ # # ]: 0 : rxq->rxq_stats.empty >= HINIC3_RX_EMPTY_THRESHOLD)
954 : 0 : goto out;
955 : :
956 : : sw_ci = hinic3_get_rq_local_ci(rxq);
957 : 0 : rx_buf_len = rxq->buf_len;
958 : :
959 [ # # ]: 0 : while (pkts < nb_pkts) {
960 : 0 : rx_cqe = &rxq->rx_cqe[sw_ci];
961 : 0 : status = hinic3_hw_cpu32((uint32_t)(rte_atomic_load_explicit(&rx_cqe->status,
962 : : rte_memory_order_acquire)));
963 [ # # ]: 0 : if (!HINIC3_GET_RX_DONE(status)) {
964 : 0 : rxq->rxq_stats.empty++;
965 : 0 : break;
966 : : }
967 : :
968 : 0 : vlan_len = hinic3_hw_cpu32(rx_cqe->vlan_len);
969 : :
970 : 0 : pkt_len = HINIC3_GET_RX_PKT_LEN(vlan_len);
971 : :
972 : 0 : rx_info = &rxq->rx_info[sw_ci];
973 : 0 : rxm = rx_info->mbuf;
974 : :
975 : : /* 1. Next ci point and prefetch. */
976 : 0 : sw_ci++;
977 : 0 : sw_ci &= rxq->q_mask;
978 : :
979 : : /* 2. Prefetch next mbuf first 64B. */
980 : 0 : rte_prefetch0(rxq->rx_info[sw_ci].mbuf);
981 : :
982 : : /* 3. Jumbo frame process. */
983 [ # # ]: 0 : if (likely(pkt_len <= rx_buf_len)) {
984 : 0 : rxm->data_len = (uint16_t)pkt_len;
985 : 0 : rxm->pkt_len = pkt_len;
986 : 0 : wqebb_cnt++;
987 : : } else {
988 : 0 : rxm->data_len = rx_buf_len;
989 : 0 : rxm->pkt_len = rx_buf_len;
990 : :
991 : : /*
992 : : * If receive jumbo, updating ci will be done by
993 : : * hinic3_recv_jumbo_pkt function.
994 : : */
995 : 0 : hinic3_update_rq_local_ci(rxq, wqebb_cnt + 1);
996 : : wqebb_cnt = 0;
997 : 0 : hinic3_recv_jumbo_pkt(rxq, rxm, pkt_len - rx_buf_len);
998 : : sw_ci = hinic3_get_rq_local_ci(rxq);
999 : : }
1000 : :
1001 : 0 : rxm->data_off = RTE_PKTMBUF_HEADROOM;
1002 : 0 : rxm->port = rxq->port_id;
1003 : :
1004 : : /* 4. Rx checksum offload. */
1005 : 0 : rxm->ol_flags |= hinic3_rx_csum(status, rxq);
1006 : :
1007 : : /* 5. Vlan offload. */
1008 [ # # ]: 0 : offload_type = hinic3_hw_cpu32(rx_cqe->offload_type);
1009 : :
1010 : 0 : rxm->ol_flags |=
1011 : : hinic3_rx_vlan(offload_type, vlan_len, &rxm->vlan_tci);
1012 : :
1013 : : /* 6. RSS. */
1014 [ # # ]: 0 : hash_value = hinic3_hw_cpu32(rx_cqe->hash_val);
1015 : 0 : rxm->ol_flags |= hinic3_rx_rss_hash(offload_type, hash_value,
1016 : : &rxm->hash.rss);
1017 : : /* 8. LRO. */
1018 : 0 : lro_num = HINIC3_GET_RX_NUM_LRO(status);
1019 [ # # ]: 0 : if (unlikely(lro_num != 0)) {
1020 : 0 : rxm->ol_flags |= HINIC3_PKT_RX_LRO;
1021 : 0 : rxm->tso_segsz = pkt_len / lro_num;
1022 : : }
1023 : :
1024 : 0 : rx_cqe->status = 0;
1025 : :
1026 : 0 : rx_bytes += pkt_len;
1027 : 0 : rx_pkts[pkts++] = rxm;
1028 : : }
1029 : :
1030 [ # # ]: 0 : if (pkts) {
1031 : : /* 9. Update local ci. */
1032 : : hinic3_update_rq_local_ci(rxq, wqebb_cnt);
1033 : :
1034 : : /* Update packet stats. */
1035 : 0 : rxq->rxq_stats.packets += pkts;
1036 : 0 : rxq->rxq_stats.bytes += rx_bytes;
1037 : 0 : rxq->rxq_stats.empty = 0;
1038 : : #ifdef HINIC3_XSTAT_MBUF_USE
1039 : : rxq->rxq_stats.rx_free_mbuf_bytes += pkts;
1040 : : #endif
1041 : : }
1042 : 0 : rxq->rxq_stats.burst_pkts = pkts;
1043 : 0 : rxq->rxq_stats.tsc = rte_get_timer_cycles();
1044 : 0 : out:
1045 : : /* 10. Rearm mbuf to rxq. */
1046 : 0 : hinic3_rearm_rxq_mbuf(rxq);
1047 : :
1048 : : #ifdef HINIC3_XSTAT_PROF_RX
1049 : : /* Do profiling stats. */
1050 : : t2 = rte_get_tsc_cycles();
1051 : : rxq->rxq_stats.app_tsc = t1 - rxq->prof_rx_end_tsc;
1052 : : rxq->prof_rx_end_tsc = t2;
1053 : : rxq->rxq_stats.pmd_tsc = t2 - t1;
1054 : : #endif
1055 : :
1056 : 0 : return pkts;
1057 : : }
|