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