Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
3 : : */
4 : :
5 : : #include <rte_common.h>
6 : : #include <rte_net.h>
7 : : #include <rte_vect.h>
8 : : #include <rte_malloc.h>
9 : : #include <rte_memzone.h>
10 : : #include <ethdev_driver.h>
11 : : #include "sxe2_osal.h"
12 : : #include "sxe2_txrx_common.h"
13 : : #include "sxe2_txrx_vec_common.h"
14 : : #include "sxe2_txrx_poll.h"
15 : : #include "sxe2_txrx.h"
16 : : #include "sxe2_txrx_vec.h"
17 : : #include "sxe2_queue.h"
18 : : #include "sxe2_ethdev.h"
19 : : #include "sxe2_common_log.h"
20 : :
21 : : static __rte_always_inline int32_t
22 : 0 : sxe2_tx_bufs_free(struct sxe2_tx_queue *txq)
23 : : {
24 : 0 : struct sxe2_tx_buffer *buffer;
25 : 0 : struct rte_mbuf *mbuf;
26 : 0 : struct rte_mbuf *mbuf_free_arr[SXE2_TX_FREE_BUFFER_SIZE_MAX];
27 : 0 : int32_t ret;
28 : 0 : uint32_t i;
29 : 0 : uint16_t rs_thresh;
30 : 0 : uint16_t free_num;
31 : 0 : if ((txq->desc_ring[txq->next_dd].wb.dd &
32 : : rte_cpu_to_le_64(SXE2_TX_DESC_DTYPE_MASK)) !=
33 : : rte_cpu_to_le_64(SXE2_TX_DESC_DTYPE_DESC_DONE)) {
34 : 0 : ret = 0;
35 : 0 : goto l_end;
36 : : }
37 : 0 : rs_thresh = txq->rs_thresh;
38 : 0 : buffer = &txq->buffer_ring[txq->next_dd - rs_thresh + 1];
39 [ # # # # ]: 0 : if (txq->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) {
40 [ # # # # ]: 0 : if (likely(rs_thresh <= SXE2_TX_FREE_BUFFER_SIZE_MAX)) {
41 : 0 : mbuf = buffer[0].mbuf;
42 : 0 : mbuf_free_arr[0] = mbuf;
43 : 0 : free_num = 1;
44 [ # # # # ]: 0 : for (i = 1; i < rs_thresh; ++i) {
45 : 0 : mbuf = buffer[i].mbuf;
46 [ # # # # ]: 0 : if (likely(mbuf->pool == mbuf_free_arr[0]->pool)) {
47 : 0 : mbuf_free_arr[free_num] = mbuf;
48 : 0 : free_num++;
49 : : } else {
50 [ # # # # ]: 0 : rte_mempool_put_bulk(mbuf_free_arr[0]->pool,
51 : : (void *)mbuf_free_arr, free_num);
52 : 0 : mbuf_free_arr[0] = mbuf;
53 : 0 : free_num = 1;
54 : : }
55 : : }
56 [ # # # # ]: 0 : rte_mempool_put_bulk(mbuf_free_arr[0]->pool,
57 : : (void *)mbuf_free_arr, free_num);
58 : : } else {
59 [ # # # # ]: 0 : for (i = 0; i < rs_thresh; ++i, ++buffer) {
60 [ # # # # ]: 0 : rte_mempool_put(buffer->mbuf->pool, buffer->mbuf);
61 : 0 : buffer->mbuf = NULL;
62 : : }
63 : : }
64 : : } else {
65 [ # # # # ]: 0 : for (i = 0; i < rs_thresh; ++i, ++buffer) {
66 : 0 : mbuf = rte_pktmbuf_prefree_seg(buffer[i].mbuf);
67 : 0 : if (mbuf != NULL)
68 [ # # # # ]: 0 : rte_mempool_put(mbuf->pool, mbuf);
69 : 0 : buffer->mbuf = NULL;
70 : : }
71 : : }
72 : 0 : txq->desc_free_num += rs_thresh;
73 : 0 : txq->next_dd += rs_thresh;
74 [ # # # # ]: 0 : if (txq->next_dd >= txq->ring_depth)
75 : 0 : txq->next_dd = rs_thresh - 1;
76 : : ret = rs_thresh;
77 : 0 : l_end:
78 : 0 : return ret;
79 : : }
80 : :
81 : 0 : static inline int32_t sxe2_tx_cleanup(struct sxe2_tx_queue *txq)
82 : : {
83 : 0 : int32_t ret = 0;
84 : 0 : volatile union sxe2_tx_data_desc *desc_ring = txq->desc_ring;
85 : 0 : struct sxe2_tx_buffer *buffer_ring = txq->buffer_ring;
86 : 0 : uint16_t ring_depth = txq->ring_depth;
87 : 0 : uint16_t next_clean = txq->next_clean;
88 : 0 : uint16_t clean_last;
89 : 0 : uint16_t clean_num;
90 : :
91 : 0 : clean_last = next_clean + txq->rs_thresh;
92 [ # # ]: 0 : if (clean_last >= ring_depth)
93 : 0 : clean_last = clean_last - ring_depth;
94 : :
95 : 0 : clean_last = buffer_ring[clean_last].last_id;
96 : 0 : if (rte_cpu_to_le_64(SXE2_TX_DESC_DTYPE_DESC_DONE) !=
97 [ # # ]: 0 : (txq->desc_ring[clean_last].wb.dd & rte_cpu_to_le_64(SXE2_TX_DESC_DTYPE_MASK))) {
98 : 0 : PMD_LOG_DEBUG(TX, "desc[%u] is not done.port_id=%u queue_id=%u val=0x%" PRIx64,
99 : : clean_last, txq->port_id,
100 : : txq->queue_id, txq->desc_ring[clean_last].wb.dd);
101 : 0 : ret = -1;
102 : 0 : goto l_end;
103 : : }
104 : :
105 [ # # ]: 0 : if (clean_last > next_clean)
106 : 0 : clean_num = clean_last - next_clean;
107 : : else
108 : 0 : clean_num = ring_depth - next_clean + clean_last;
109 : :
110 : 0 : desc_ring[clean_last].wb.dd = 0;
111 : :
112 : 0 : txq->next_clean = clean_last;
113 : 0 : txq->desc_free_num += clean_num;
114 : :
115 : 0 : ret = 0;
116 : :
117 : 0 : l_end:
118 : 0 : return ret;
119 : : }
120 : :
121 : 0 : static int32_t sxe2_tx_done_cleanup_simple(struct sxe2_tx_queue *txq, uint32_t free_cnt)
122 : : {
123 : 0 : uint32_t free_cnt_align;
124 : 0 : uint32_t free_cnt_once;
125 : 0 : uint32_t i;
126 : :
127 [ # # # # ]: 0 : if (free_cnt == 0 || free_cnt > txq->ring_depth)
128 : 0 : free_cnt = txq->ring_depth;
129 : :
130 : 0 : free_cnt_align = free_cnt - (free_cnt % txq->rs_thresh);
131 [ # # ]: 0 : for (i = 0; i < free_cnt_align; i += free_cnt_once) {
132 [ # # ]: 0 : if ((txq->ring_depth - txq->desc_free_num) < txq->rs_thresh)
133 : : break;
134 : :
135 [ # # ]: 0 : free_cnt_once = sxe2_tx_bufs_free(txq);
136 [ # # ]: 0 : if (free_cnt_once == 0)
137 : : break;
138 : : }
139 : :
140 : 0 : return i;
141 : : }
142 : :
143 : 0 : static int32_t sxe2_tx_done_cleanup_normal(struct sxe2_tx_queue *txq, uint32_t free_cnt)
144 : : {
145 : 0 : struct sxe2_tx_buffer *buffer_ring = txq->buffer_ring;
146 : 0 : int32_t ret;
147 : 0 : uint16_t clean_last_idx, clean_idx;
148 : 0 : uint16_t clean_last, clean_once;
149 : 0 : uint16_t pkt_cnt, i;
150 : :
151 [ # # # # ]: 0 : if (txq->desc_free_num == 0 && sxe2_tx_cleanup(txq) != 0) {
152 : 0 : ret = 0;
153 : 0 : goto l_end;
154 : : }
155 : :
156 [ # # ]: 0 : if (free_cnt == 0)
157 : 0 : free_cnt = txq->ring_depth;
158 : :
159 : 0 : clean_last_idx = txq->next_use;
160 : 0 : clean_idx = buffer_ring[clean_last_idx].next_id;
161 : 0 : clean_once = txq->desc_free_num;
162 : 0 : clean_last = txq->desc_free_num;
163 : :
164 [ # # ]: 0 : for (pkt_cnt = 0; pkt_cnt < free_cnt;) {
165 : 0 : for (i = 0; ((i < clean_once) &&
166 [ # # # # : 0 : (pkt_cnt < free_cnt) &&
# # ]
167 : 0 : clean_idx != clean_last_idx); ++i) {
168 [ # # ]: 0 : if (buffer_ring[clean_idx].mbuf != NULL) {
169 : 0 : rte_pktmbuf_free_seg(buffer_ring[clean_idx].mbuf);
170 : 0 : buffer_ring[clean_idx].mbuf = NULL;
171 [ # # ]: 0 : if (buffer_ring[clean_idx].last_id == clean_idx)
172 : 0 : pkt_cnt++;
173 : : }
174 : 0 : clean_idx = buffer_ring[clean_idx].next_id;
175 : : }
176 : :
177 [ # # # # ]: 0 : if ((txq->rs_thresh > (txq->ring_depth - txq->desc_free_num)) ||
178 : : clean_idx == clean_last_idx)
179 : : break;
180 : :
181 [ # # ]: 0 : if (pkt_cnt < free_cnt) {
182 [ # # ]: 0 : if (sxe2_tx_cleanup(txq) != 0)
183 : : break;
184 : :
185 : 0 : clean_once = txq->desc_free_num - clean_last;
186 : 0 : clean_last = txq->desc_free_num;
187 : : }
188 : : }
189 : :
190 : 0 : ret = pkt_cnt;
191 : 0 : l_end:
192 : 0 : return ret;
193 : : }
194 : :
195 : 0 : int32_t sxe2_tx_done_cleanup(void *tx_queue, uint32_t free_cnt)
196 : : {
197 : 0 : struct sxe2_tx_queue *txq = (struct sxe2_tx_queue *)tx_queue;
198 : 0 : struct sxe2_adapter *adapter;
199 : 0 : int32_t ret;
200 : :
201 [ # # ]: 0 : if (txq == NULL) {
202 : 0 : ret = 0;
203 : 0 : goto l_end;
204 : : }
205 : :
206 : 0 : adapter = txq->vsi->adapter;
207 [ # # ]: 0 : if (adapter->q_ctxt.tx_mode_flags & SXE2_TX_MODE_VEC_SET_MASK)
208 : : ret = -ENOTSUP;
209 [ # # ]: 0 : else if (adapter->q_ctxt.tx_mode_flags & SXE2_TX_MODE_SIMPLE_BATCH)
210 : 0 : ret = sxe2_tx_done_cleanup_simple(txq, free_cnt);
211 : : else
212 : 0 : ret = sxe2_tx_done_cleanup_normal(txq, free_cnt);
213 : :
214 : 0 : PMD_LOG_DEBUG(TX, "TX cleanup done desc queue_id=%u free_cnt=%d.",
215 : : txq->queue_id, ret);
216 : :
217 : 0 : l_end:
218 : 0 : return ret;
219 : : }
220 : :
221 : : static __rte_always_inline uint32_t
222 : : sxe2_tx_pkt_data_desc_count(struct rte_mbuf *tx_pkt)
223 : : {
224 : : struct rte_mbuf *m_seg = tx_pkt;
225 : : uint32_t count = 0;
226 : :
227 [ # # ]: 0 : while (m_seg != NULL) {
228 : 0 : count += SXE2_DIV_ROUND_UP(m_seg->data_len,
229 : : SXE2_TX_MAX_DATA_NUM_PER_DESC);
230 : 0 : m_seg = m_seg->next;
231 : : }
232 : :
233 : 0 : return count;
234 : : }
235 : :
236 : : static __rte_always_inline void
237 : 0 : sxe2_tx_desc_checksum_fill(uint64_t offloads, uint32_t *desc_cmd, uint32_t *desc_offset,
238 : : union sxe2_tx_offload_info ol_info)
239 : : {
240 : 0 : if (offloads & RTE_MBUF_F_TX_IP_CKSUM) {
241 : 0 : *desc_cmd |= SXE2_TX_DATA_DESC_CMD_IIPT_IPV4_CSUM;
242 : 0 : *desc_offset |= SXE2_TX_DATA_DESC_IPLEN_VAL(ol_info.l3_len);
243 [ # # ]: 0 : } else if (offloads & RTE_MBUF_F_TX_IPV4) {
244 : 0 : *desc_cmd |= SXE2_TX_DATA_DESC_CMD_IIPT_IPV4;
245 : 0 : *desc_offset |= SXE2_TX_DATA_DESC_IPLEN_VAL(ol_info.l3_len);
246 [ # # ]: 0 : } else if (offloads & RTE_MBUF_F_TX_IPV6) {
247 : 0 : *desc_cmd |= SXE2_TX_DATA_DESC_CMD_IIPT_IPV6;
248 : 0 : *desc_offset |= SXE2_TX_DATA_DESC_IPLEN_VAL(ol_info.l3_len);
249 : : }
250 : :
251 [ # # ]: 0 : if (offloads & RTE_MBUF_F_TX_TCP_SEG) {
252 : 0 : *desc_cmd |= SXE2_TX_DATA_DESC_CMD_L4T_EOFT_TCP;
253 : 0 : *desc_offset |= SXE2_TX_DATA_DESC_L4LEN_VAL(ol_info.l4_len);
254 : 0 : goto l_end;
255 : : }
256 : :
257 [ # # ]: 0 : if (offloads & RTE_MBUF_F_TX_UDP_SEG) {
258 : 0 : *desc_cmd |= SXE2_TX_DATA_DESC_CMD_L4T_EOFT_UDP;
259 : 0 : *desc_offset |= SXE2_TX_DATA_DESC_L4LEN_VAL(ol_info.l4_len);
260 : 0 : goto l_end;
261 : : }
262 : :
263 [ # # # # ]: 0 : switch (offloads & RTE_MBUF_F_TX_L4_MASK) {
264 : 0 : case RTE_MBUF_F_TX_TCP_CKSUM:
265 : 0 : *desc_cmd |= SXE2_TX_DATA_DESC_CMD_L4T_EOFT_TCP;
266 : 0 : *desc_offset |= SXE2_TX_DATA_DESC_L4LEN_VAL(ol_info.l4_len);
267 : 0 : break;
268 : 0 : case RTE_MBUF_F_TX_SCTP_CKSUM:
269 : 0 : *desc_cmd |= SXE2_TX_DATA_DESC_CMD_L4T_EOFT_SCTP;
270 : 0 : *desc_offset |= SXE2_TX_DATA_DESC_L4LEN_VAL(ol_info.l4_len);
271 : 0 : break;
272 : 0 : case RTE_MBUF_F_TX_UDP_CKSUM:
273 : 0 : *desc_cmd |= SXE2_TX_DATA_DESC_CMD_L4T_EOFT_UDP;
274 : 0 : *desc_offset |= SXE2_TX_DATA_DESC_L4LEN_VAL(ol_info.l4_len);
275 : 0 : break;
276 : : default:
277 : :
278 : : break;
279 : : }
280 : :
281 : 0 : l_end:
282 : 0 : return;
283 : : }
284 : :
285 : : static __rte_always_inline uint64_t
286 : 0 : sxe2_tx_data_desc_build_cobt(uint32_t cmd, uint32_t offset, uint16_t buf_size, uint16_t l2tag)
287 : : {
288 : 0 : return rte_cpu_to_le_64(SXE2_TX_DESC_DTYPE_DATA |
289 : : (((uint64_t)cmd) << SXE2_TX_DATA_DESC_CMD_SHIFT) |
290 : : (((uint64_t)offset) << SXE2_TX_DATA_DESC_OFFSET_SHIFT) |
291 : : (((uint64_t)buf_size) << SXE2_TX_DATA_DESC_BUF_SZ_SHIFT) |
292 : : (((uint64_t)l2tag) << SXE2_TX_DATA_DESC_L2TAG1_SHIFT));
293 : : }
294 : :
295 : 0 : uint16_t sxe2_tx_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
296 : : {
297 : 0 : struct sxe2_tx_queue *txq = tx_queue;
298 : 0 : struct sxe2_tx_buffer *buffer_ring;
299 : 0 : struct sxe2_tx_buffer *buffer;
300 : 0 : struct sxe2_tx_buffer *next_buffer;
301 : 0 : struct rte_mbuf *tx_pkt;
302 : 0 : struct rte_mbuf *m_seg;
303 : 0 : volatile union sxe2_tx_data_desc *desc_ring;
304 : 0 : volatile union sxe2_tx_data_desc *desc;
305 : 0 : volatile struct sxe2_tx_context_desc *ctxt_desc;
306 : 0 : union sxe2_tx_offload_info ol_info;
307 : 0 : struct sxe2_vsi *vsi = txq->vsi;
308 : 0 : rte_iova_t buf_dma_addr;
309 : 0 : uint64_t offloads;
310 : 0 : uint64_t desc_type_cmd_tso_mss;
311 : 0 : uint32_t desc_cmd;
312 : 0 : uint32_t desc_offset;
313 : 0 : uint32_t desc_tag;
314 : 0 : uint32_t desc_tunneling_params;
315 : 0 : uint16_t ipsec_offset;
316 : 0 : uint16_t ctxt_desc_num;
317 : 0 : uint32_t desc_sum_num;
318 : 0 : uint16_t tx_num;
319 : 0 : uint16_t seg_len;
320 : 0 : uint16_t next_use;
321 : 0 : uint16_t last_use;
322 : 0 : uint16_t desc_l2tag2;
323 : :
324 : 0 : buffer_ring = txq->buffer_ring;
325 : 0 : desc_ring = txq->desc_ring;
326 : 0 : next_use = txq->next_use;
327 : 0 : buffer = &buffer_ring[next_use];
328 : :
329 [ # # ]: 0 : if (txq->desc_free_num < txq->free_thresh)
330 : 0 : (void)sxe2_tx_cleanup(txq);
331 : :
332 [ # # ]: 0 : for (tx_num = 0; tx_num < nb_pkts; tx_num++) {
333 : 0 : tx_pkt = *tx_pkts++;
334 : 0 : desc_cmd = 0;
335 : 0 : desc_offset = 0;
336 : 0 : desc_tag = 0;
337 : 0 : desc_tunneling_params = 0;
338 : 0 : ipsec_offset = 0;
339 : 0 : offloads = tx_pkt->ol_flags;
340 : 0 : ol_info.l2_len = tx_pkt->l2_len;
341 : 0 : ol_info.l3_len = tx_pkt->l3_len;
342 : 0 : ol_info.l4_len = tx_pkt->l4_len;
343 : 0 : ol_info.tso_segsz = tx_pkt->tso_segsz;
344 : 0 : ol_info.outer_l2_len = tx_pkt->outer_l2_len;
345 : 0 : ol_info.outer_l3_len = tx_pkt->outer_l3_len;
346 : :
347 : 0 : ctxt_desc_num = (offloads &
348 : 0 : SXE2_TX_OFFLOAD_CTXT_NEEDCK_MASK) ? 1 : 0;
349 [ # # ]: 0 : if (unlikely(vsi->vsi_type == SXE2_VSI_T_DPDK_ESW))
350 : 0 : ctxt_desc_num = 1;
351 : :
352 [ # # ]: 0 : if (offloads & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG))
353 : 0 : desc_sum_num = sxe2_tx_pkt_data_desc_count(tx_pkt) + ctxt_desc_num;
354 : : else
355 : 0 : desc_sum_num = tx_pkt->nb_segs + ctxt_desc_num;
356 : :
357 : 0 : last_use = next_use + desc_sum_num - 1;
358 [ # # ]: 0 : if (last_use >= txq->ring_depth)
359 : 0 : last_use = last_use - txq->ring_depth;
360 : :
361 [ # # ]: 0 : if (desc_sum_num > txq->desc_free_num) {
362 [ # # ]: 0 : if (unlikely(sxe2_tx_cleanup(txq) != 0))
363 : 0 : goto l_cleanup_exit;
364 : :
365 [ # # ]: 0 : if (unlikely(desc_sum_num > txq->rs_thresh)) {
366 [ # # ]: 0 : while (desc_sum_num > txq->desc_free_num) {
367 [ # # ]: 0 : if (unlikely(sxe2_tx_cleanup(txq) != 0))
368 : 0 : goto l_cleanup_exit;
369 : : }
370 : : }
371 : : }
372 : :
373 : 0 : desc_offset |= SXE2_TX_DATA_DESC_MACLEN_VAL(ol_info.l2_len);
374 : :
375 [ # # ]: 0 : if (offloads & SXE2_TX_OFFLOAD_CKSUM_MASK) {
376 [ # # ]: 0 : sxe2_tx_desc_checksum_fill(offloads, &desc_cmd,
377 : : &desc_offset, ol_info);
378 : : }
379 : :
380 [ # # ]: 0 : if (offloads & (RTE_MBUF_F_TX_VLAN | RTE_MBUF_F_TX_QINQ)) {
381 : 0 : desc_cmd |= SXE2_TX_DATA_DESC_CMD_IL2TAG1;
382 : 0 : desc_tag = tx_pkt->vlan_tci;
383 : : }
384 : :
385 [ # # ]: 0 : if (ctxt_desc_num) {
386 : 0 : ctxt_desc = (volatile struct sxe2_tx_context_desc *)
387 : 0 : &desc_ring[next_use];
388 : 0 : desc_l2tag2 = 0;
389 : 0 : desc_type_cmd_tso_mss = SXE2_TX_DESC_DTYPE_CTXT;
390 : :
391 : 0 : next_buffer = &buffer_ring[buffer->next_id];
392 [ # # ]: 0 : RTE_MBUF_PREFETCH_TO_FREE(next_buffer->mbuf);
393 : :
394 [ # # ]: 0 : if (buffer->mbuf) {
395 [ # # ]: 0 : rte_pktmbuf_free_seg(buffer->mbuf);
396 : 0 : buffer->mbuf = NULL;
397 : : }
398 : :
399 [ # # ]: 0 : if (offloads & RTE_MBUF_F_TX_QINQ) {
400 : 0 : desc_l2tag2 = tx_pkt->vlan_tci_outer;
401 : 0 : desc_type_cmd_tso_mss |= SXE2_TX_CTXT_DESC_CMD_IL2TAG2_MASK;
402 : : }
403 : :
404 : 0 : ctxt_desc->tunneling_params =
405 : : rte_cpu_to_le_32(desc_tunneling_params);
406 : 0 : ctxt_desc->l2tag2 = rte_cpu_to_le_16(desc_l2tag2);
407 : 0 : ctxt_desc->type_cmd_tso_mss = rte_cpu_to_le_64(desc_type_cmd_tso_mss);
408 : 0 : ctxt_desc->ipsec_offset = rte_cpu_to_le_16(ipsec_offset);
409 : :
410 : 0 : buffer->last_id = last_use;
411 : 0 : next_use = buffer->next_id;
412 : 0 : buffer = next_buffer;
413 : : }
414 : :
415 : : m_seg = tx_pkt;
416 : :
417 : 0 : do {
418 : 0 : desc = &desc_ring[next_use];
419 : 0 : next_buffer = &buffer_ring[buffer->next_id];
420 [ # # ]: 0 : RTE_MBUF_PREFETCH_TO_FREE(next_buffer->mbuf);
421 [ # # ]: 0 : if (buffer->mbuf) {
422 [ # # ]: 0 : rte_pktmbuf_free_seg(buffer->mbuf);
423 : 0 : buffer->mbuf = NULL;
424 : : }
425 : :
426 : 0 : buffer->mbuf = m_seg;
427 : 0 : seg_len = m_seg->data_len;
428 : 0 : buf_dma_addr = rte_mbuf_data_iova(m_seg);
429 : 0 : while ((offloads & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG)) &&
430 [ # # ]: 0 : unlikely(seg_len > SXE2_TX_MAX_DATA_NUM_PER_DESC)) {
431 : 0 : desc->read.buf_addr = rte_cpu_to_le_64(buf_dma_addr);
432 : 0 : desc->read.type_cmd_off_bsz_l2t =
433 : 0 : sxe2_tx_data_desc_build_cobt(desc_cmd, desc_offset,
434 : : SXE2_TX_MAX_DATA_NUM_PER_DESC,
435 : : desc_tag);
436 : 0 : buf_dma_addr += SXE2_TX_MAX_DATA_NUM_PER_DESC;
437 : 0 : seg_len -= SXE2_TX_MAX_DATA_NUM_PER_DESC;
438 : 0 : buffer->last_id = last_use;
439 : 0 : next_use = buffer->next_id;
440 : 0 : buffer = next_buffer;
441 : 0 : desc = &desc_ring[next_use];
442 : 0 : next_buffer = &buffer_ring[buffer->next_id];
443 [ # # # # ]: 0 : RTE_MBUF_PREFETCH_TO_FREE(next_buffer->mbuf);
444 : : }
445 : :
446 : 0 : desc->read.buf_addr = rte_cpu_to_le_64(buf_dma_addr);
447 : 0 : desc->read.type_cmd_off_bsz_l2t =
448 : 0 : sxe2_tx_data_desc_build_cobt(desc_cmd,
449 : : desc_offset, seg_len, desc_tag);
450 : :
451 : 0 : buffer->last_id = last_use;
452 : 0 : next_use = buffer->next_id;
453 : 0 : buffer = next_buffer;
454 : :
455 : 0 : m_seg = m_seg->next;
456 [ # # ]: 0 : } while (m_seg);
457 : :
458 : 0 : desc_cmd |= SXE2_TX_DATA_DESC_CMD_EOP;
459 : 0 : txq->desc_used_num += desc_sum_num;
460 : 0 : txq->desc_free_num -= desc_sum_num;
461 : :
462 [ # # ]: 0 : if (txq->desc_used_num >= txq->rs_thresh) {
463 : 0 : PMD_LOG_DEBUG(TX, "Tx pkts set RS bit."
464 : : "last_use=%u port_id=%u, queue_id=%u",
465 : : last_use, txq->port_id, txq->queue_id);
466 : 0 : desc_cmd |= SXE2_TX_DATA_DESC_CMD_RS;
467 : 0 : txq->desc_used_num = 0;
468 : : }
469 : :
470 : 0 : desc->read.type_cmd_off_bsz_l2t |=
471 : 0 : rte_cpu_to_le_64(((uint64_t)desc_cmd) << SXE2_TX_DATA_DESC_CMD_SHIFT);
472 : : }
473 : 0 : goto l_end_of_tx;
474 : :
475 : 0 : l_cleanup_exit:
476 [ # # ]: 0 : if (tx_num == 0)
477 : : return 0;
478 : 0 : l_end_of_tx:
479 : 0 : SXE2_PCI_REG_WRITE_WC(txq->tdt_reg_addr, next_use);
480 : 0 : PMD_LOG_DEBUG(TX, "port_id=%u queue_id=%u next_use=%u send_pkts=%u",
481 : : txq->port_id, txq->queue_id, next_use, tx_num);
482 : :
483 : 0 : txq->next_use = next_use;
484 : 0 : return tx_num;
485 : : }
486 : :
487 : : static __rte_always_inline void
488 : 0 : sxe2_tx_data_desc_fill(volatile union sxe2_tx_data_desc *desc,
489 : : struct rte_mbuf **tx_pkts)
490 : : {
491 : 0 : rte_iova_t buf_dma_addr;
492 : 0 : uint32_t desc_offset;
493 : 0 : buf_dma_addr = rte_mbuf_data_iova(*tx_pkts);
494 : 0 : desc->read.buf_addr = rte_cpu_to_le_64(buf_dma_addr);
495 : 0 : desc_offset = SXE2_TX_DATA_DESC_MACLEN_VAL((*tx_pkts)->l2_len);
496 : 0 : desc->read.type_cmd_off_bsz_l2t =
497 : 0 : sxe2_tx_data_desc_build_cobt(SXE2_TX_DATA_DESC_CMD_EOP,
498 : 0 : desc_offset, (*tx_pkts)->data_len, 0);
499 : : }
500 : : static __rte_always_inline void
501 : 0 : sxe2_tx_data_desc_fill_batch(volatile union sxe2_tx_data_desc *desc,
502 : : struct rte_mbuf **tx_pkts)
503 : : {
504 : 0 : rte_iova_t buf_dma_addr;
505 : 0 : uint32_t i;
506 : 0 : uint32_t desc_offset;
507 [ # # ]: 0 : for (i = 0; i < SXE2_TX_FILL_PER_LOOP; ++i, ++desc, ++tx_pkts) {
508 : 0 : buf_dma_addr = rte_mbuf_data_iova(*tx_pkts);
509 : 0 : desc->read.buf_addr = rte_cpu_to_le_64(buf_dma_addr);
510 : 0 : desc_offset = SXE2_TX_DATA_DESC_MACLEN_VAL((*tx_pkts)->l2_len);
511 : 0 : desc->read.type_cmd_off_bsz_l2t =
512 : 0 : sxe2_tx_data_desc_build_cobt(SXE2_TX_DATA_DESC_CMD_EOP,
513 : : desc_offset,
514 : 0 : (*tx_pkts)->data_len,
515 : : 0);
516 : : }
517 : : }
518 : :
519 : 0 : static inline void sxe2_tx_ring_fill(struct sxe2_tx_queue *txq,
520 : : struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
521 : : {
522 : 0 : struct sxe2_tx_buffer *buffer = &txq->buffer_ring[txq->next_use];
523 : 0 : volatile union sxe2_tx_data_desc *desc = &txq->desc_ring[txq->next_use];
524 : 0 : uint32_t i, j;
525 : 0 : uint32_t mainpart;
526 : 0 : uint32_t leftover;
527 : 0 : mainpart = nb_pkts & ((uint32_t)~SXE2_TX_FILL_PER_LOOP_MASK);
528 : 0 : leftover = nb_pkts & ((uint32_t)SXE2_TX_FILL_PER_LOOP_MASK);
529 [ # # ]: 0 : for (i = 0; i < mainpart; i += SXE2_TX_FILL_PER_LOOP) {
530 [ # # ]: 0 : for (j = 0; j < SXE2_TX_FILL_PER_LOOP; ++j)
531 : 0 : (buffer + i + j)->mbuf = *(tx_pkts + i + j);
532 : 0 : sxe2_tx_data_desc_fill_batch(desc + i, tx_pkts + i);
533 : : }
534 [ # # ]: 0 : if (unlikely(leftover > 0)) {
535 [ # # ]: 0 : for (i = 0; i < leftover; ++i) {
536 : 0 : (buffer + mainpart + i)->mbuf = *(tx_pkts + mainpart + i);
537 : 0 : sxe2_tx_data_desc_fill(desc + mainpart + i,
538 : : tx_pkts + mainpart + i);
539 : : }
540 : : }
541 : 0 : }
542 : :
543 : 0 : static inline uint16_t sxe2_tx_pkts_batch(void *tx_queue,
544 : : struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
545 : : {
546 : 0 : struct sxe2_tx_queue *txq = (struct sxe2_tx_queue *)tx_queue;
547 : 0 : volatile union sxe2_tx_data_desc *desc_ring = txq->desc_ring;
548 : 0 : uint16_t res_num = 0;
549 [ # # ]: 0 : if (txq->desc_free_num < txq->free_thresh)
550 [ # # ]: 0 : (void)sxe2_tx_bufs_free(txq);
551 : 0 : nb_pkts = RTE_MIN(txq->desc_free_num, nb_pkts);
552 [ # # ]: 0 : if (unlikely(nb_pkts == 0)) {
553 : 0 : PMD_LOG_DEBUG(TX, "Tx batch: may not enough free desc, "
554 : : "free_desc=%u, need_tx_pkts=%u",
555 : : txq->desc_free_num, nb_pkts);
556 : 0 : goto l_end;
557 : : }
558 : 0 : txq->desc_free_num -= nb_pkts;
559 [ # # ]: 0 : if ((txq->next_use + nb_pkts) > txq->ring_depth) {
560 : 0 : res_num = txq->ring_depth - txq->next_use;
561 : 0 : sxe2_tx_ring_fill(txq, tx_pkts, res_num);
562 : 0 : desc_ring[txq->next_rs].read.type_cmd_off_bsz_l2t |=
563 : : rte_cpu_to_le_64(SXE2_TX_DATA_DESC_CMD_RS_MASK);
564 : 0 : txq->next_rs = txq->rs_thresh - 1;
565 : 0 : txq->next_use = 0;
566 : : }
567 : 0 : sxe2_tx_ring_fill(txq, tx_pkts + res_num, nb_pkts - res_num);
568 : 0 : txq->next_use = txq->next_use + (nb_pkts - res_num);
569 [ # # ]: 0 : if (txq->next_use > txq->next_rs) {
570 : 0 : desc_ring[txq->next_rs].read.type_cmd_off_bsz_l2t |=
571 : : rte_cpu_to_le_64(SXE2_TX_DATA_DESC_CMD_RS_MASK);
572 : 0 : txq->next_rs += txq->rs_thresh;
573 [ # # ]: 0 : if (txq->next_rs >= txq->ring_depth)
574 : 0 : txq->next_rs = txq->rs_thresh - 1;
575 : : }
576 [ # # ]: 0 : if (txq->next_use >= txq->ring_depth)
577 : 0 : txq->next_use = 0;
578 : 0 : PMD_LOG_DEBUG(TX, "port_id=%u queue_id=%u next_use=%u send_pkts=%u",
579 : : txq->port_id, txq->queue_id, txq->next_use, nb_pkts);
580 : 0 : SXE2_PCI_REG_WRITE_WC(txq->tdt_reg_addr, txq->next_use);
581 : 0 : l_end:
582 : 0 : return nb_pkts;
583 : : }
584 : :
585 : 0 : uint16_t sxe2_tx_pkts_simple(void *tx_queue,
586 : : struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
587 : : {
588 : 0 : uint16_t tx_done_num;
589 : 0 : uint16_t tx_once_num;
590 : 0 : uint16_t tx_need_num;
591 [ # # ]: 0 : if (likely(nb_pkts <= SXE2_TX_PKTS_BURST_BATCH_NUM)) {
592 : 0 : tx_done_num = sxe2_tx_pkts_batch(tx_queue,
593 : : tx_pkts, nb_pkts);
594 : 0 : goto l_end;
595 : : }
596 : : tx_done_num = 0;
597 [ # # ]: 0 : while (nb_pkts) {
598 : 0 : tx_need_num = RTE_MIN(nb_pkts, SXE2_TX_PKTS_BURST_BATCH_NUM);
599 : 0 : tx_once_num = sxe2_tx_pkts_batch(tx_queue,
600 : 0 : &tx_pkts[tx_done_num],
601 : : tx_need_num);
602 : 0 : nb_pkts -= tx_once_num;
603 : 0 : tx_done_num += tx_once_num;
604 [ # # ]: 0 : if (tx_once_num < tx_need_num)
605 : : break;
606 : : }
607 : 0 : l_end:
608 : 0 : return tx_done_num;
609 : : }
610 : :
611 : : static inline void
612 : 0 : sxe2_update_rx_tail(struct sxe2_rx_queue *rxq, uint16_t hold_num, uint16_t rx_id)
613 : : {
614 : 0 : hold_num += rxq->hold_num;
615 : :
616 [ # # ]: 0 : if (hold_num > rxq->rx_free_thresh) {
617 [ # # ]: 0 : rx_id = (uint16_t)((rx_id == 0) ? (rxq->ring_depth - 1) : (rx_id - 1));
618 : 0 : SXE2_PCI_REG_WRITE_WC(rxq->rdt_reg_addr, rx_id);
619 : : hold_num = 0;
620 : : }
621 : 0 : rxq->hold_num = hold_num;
622 : 0 : }
623 : :
624 : : static inline uint64_t
625 : 0 : sxe2_rx_desc_error_para(__rte_unused struct sxe2_rx_queue *rxq,
626 : : union sxe2_rx_desc *desc)
627 : : {
628 : 0 : uint64_t flags = 0;
629 : 0 : uint64_t desc_qw1 = rte_le_to_cpu_64(desc->wb.status_err_ptype_len);
630 : :
631 [ # # ]: 0 : if (unlikely(0 == (desc_qw1 & SXE2_RX_DESC_STATUS_L3L4_P_MASK)))
632 : 0 : goto l_end;
633 : :
634 [ # # ]: 0 : if (likely(0 == (desc->wb.rxdid_src & SXE2_RX_DESC_EUDPE_MASK)))
635 : : flags = RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD;
636 : : else
637 : 0 : flags = RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD;
638 : :
639 [ # # ]: 0 : if (likely(0 == (desc_qw1 & SXE2_RX_DESC_QW1_ERRORS_MASK))) {
640 : 0 : flags |= (RTE_MBUF_F_RX_IP_CKSUM_GOOD |
641 : : RTE_MBUF_F_RX_L4_CKSUM_GOOD |
642 : : RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD);
643 : 0 : goto l_end;
644 : : }
645 : :
646 [ # # ]: 0 : if (likely(0 == (desc_qw1 & SXE2_RX_DESC_ERROR_CSUM_IPE_MASK)))
647 : 0 : flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
648 : : else
649 : 0 : flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
650 : :
651 [ # # ]: 0 : if (likely(0 == (desc_qw1 & SXE2_RX_DESC_ERROR_CSUM_L4_MASK)))
652 : 0 : flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
653 : : else
654 : 0 : flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
655 : :
656 [ # # ]: 0 : if (unlikely(0 != (desc_qw1 & SXE2_RX_DESC_ERROR_CSUM_EIP_MASK)))
657 : 0 : flags |= RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD;
658 : :
659 : 0 : l_end:
660 : 0 : return flags;
661 : : }
662 : :
663 : : static __rte_always_inline void
664 : 0 : sxe2_rx_mbuf_common_fields_fill(struct sxe2_rx_queue *rxq, struct rte_mbuf *mbuf,
665 : : union sxe2_rx_desc *rxd)
666 : : {
667 : 0 : uint32_t *ptype_tbl = rxq->vsi->adapter->ptype_tbl;
668 : 0 : uint64_t qword1;
669 : 0 : uint64_t pkt_flags;
670 : 0 : qword1 = rte_le_to_cpu_64(rxd->wb.status_err_ptype_len);
671 : :
672 : 0 : mbuf->ol_flags = 0;
673 : 0 : mbuf->packet_type = ptype_tbl[SXE2_RX_DESC_PTYPE_VAL_GET(qword1)];
674 : :
675 : 0 : pkt_flags = sxe2_rx_desc_error_para(rxq, rxd);
676 : :
677 : 0 : mbuf->ol_flags |= pkt_flags;
678 : : }
679 : :
680 : : static __rte_always_inline void
681 : 0 : sxe2_rx_sw_stats_update(struct sxe2_rx_queue *rxq, struct rte_mbuf *mbuf,
682 : : union sxe2_rx_desc *rxd)
683 : : {
684 : 0 : uint64_t qword1 = rte_le_to_cpu_64(rxd->wb.status_err_ptype_len);
685 : 0 : rte_atomic_fetch_add_explicit(&rxq->sw_stats.pkts, 1,
686 : : rte_memory_order_relaxed);
687 : 0 : rte_atomic_fetch_add_explicit(&rxq->sw_stats.bytes,
688 : : mbuf->pkt_len + RTE_ETHER_CRC_LEN,
689 : : rte_memory_order_relaxed);
690 : 0 : switch (SXE2_RX_DESC_STATUS_UMBCAST_VAL_GET(qword1)) {
691 : 0 : case SXE2_RX_DESC_STATUS_UNICAST:
692 : 0 : rte_atomic_fetch_add_explicit(&rxq->sw_stats.unicast_pkts, 1,
693 : : rte_memory_order_relaxed);
694 : 0 : break;
695 : 0 : case SXE2_RX_DESC_STATUS_MULTICAST:
696 : 0 : rte_atomic_fetch_add_explicit(&rxq->sw_stats.multicast_pkts, 1,
697 : : rte_memory_order_relaxed);
698 : 0 : break;
699 : 0 : case SXE2_RX_DESC_STATUS_BROADCAST:
700 : 0 : rte_atomic_fetch_add_explicit(&rxq->sw_stats.broadcast_pkts, 1,
701 : : rte_memory_order_relaxed);
702 : 0 : break;
703 : : default:
704 : : break;
705 : : }
706 : : }
707 : :
708 : 0 : uint16_t sxe2_rx_pkts_scattered(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
709 : : {
710 : 0 : struct sxe2_rx_queue *rxq = (struct sxe2_rx_queue *)rx_queue;
711 : 0 : volatile union sxe2_rx_desc *desc_ring;
712 : 0 : volatile union sxe2_rx_desc *desc;
713 : 0 : union sxe2_rx_desc desc_tmp;
714 : 0 : struct rte_mbuf **buffer_ring;
715 : 0 : struct rte_mbuf **cur_buffer;
716 : 0 : struct rte_mbuf *cur_mbuf;
717 : 0 : struct rte_mbuf *new_mbuf;
718 : 0 : struct rte_mbuf *first_seg;
719 : 0 : struct rte_mbuf *last_seg;
720 : 0 : uint64_t qword1;
721 : 0 : uint16_t done_num;
722 : 0 : uint16_t hold_num;
723 : 0 : uint16_t cur_idx;
724 : 0 : uint16_t pkt_len;
725 : :
726 : 0 : desc_ring = rxq->desc_ring;
727 : 0 : buffer_ring = rxq->buffer_ring;
728 : 0 : cur_idx = rxq->processing_idx;
729 : 0 : first_seg = rxq->pkt_first_seg;
730 : 0 : last_seg = rxq->pkt_last_seg;
731 : 0 : done_num = 0;
732 : 0 : hold_num = 0;
733 [ # # ]: 0 : while (done_num < nb_pkts) {
734 : 0 : desc = &desc_ring[cur_idx];
735 : 0 : qword1 = rte_le_to_cpu_64(desc->wb.status_err_ptype_len);
736 [ # # ]: 0 : if (0 == (SXE2_RX_DESC_STATUS_DD_MASK & qword1))
737 : : break;
738 : :
739 : 0 : new_mbuf = rte_mbuf_raw_alloc(rxq->mb_pool);
740 [ # # ]: 0 : if (unlikely(new_mbuf == NULL)) {
741 : 0 : rxq->vsi->adapter->dev_info.dev_data->rx_mbuf_alloc_failed++;
742 : 0 : PMD_LOG_INFO(RX, "Rx new_mbuf alloc failed port_id:%u "
743 : : "queue_id:%u", rxq->port_id, rxq->queue_id);
744 : 0 : break;
745 : : }
746 : :
747 : 0 : hold_num++;
748 : 0 : desc_tmp = *desc;
749 : 0 : cur_buffer = &buffer_ring[cur_idx];
750 : 0 : cur_idx++;
751 [ # # ]: 0 : if (unlikely(cur_idx == rxq->ring_depth))
752 : 0 : cur_idx = 0;
753 : :
754 : 0 : rte_prefetch0(buffer_ring[cur_idx]);
755 : :
756 [ # # ]: 0 : if (0 == (cur_idx & 0x3)) {
757 : 0 : rte_prefetch0(&desc_ring[cur_idx]);
758 : 0 : rte_prefetch0(&buffer_ring[cur_idx]);
759 : : }
760 : :
761 : 0 : cur_mbuf = *cur_buffer;
762 : :
763 : 0 : *cur_buffer = new_mbuf;
764 : :
765 : 0 : desc->read.hdr_addr = 0;
766 [ # # ]: 0 : desc->read.pkt_addr =
767 : 0 : rte_cpu_to_le_64(rte_mbuf_data_iova_default(new_mbuf));
768 : :
769 : 0 : pkt_len = SXE2_RX_DESC_PKT_LEN_VAL_GET(qword1);
770 : 0 : cur_mbuf->data_len = pkt_len;
771 : 0 : cur_mbuf->data_off = RTE_PKTMBUF_HEADROOM;
772 : :
773 [ # # ]: 0 : if (first_seg == NULL) {
774 : 0 : first_seg = cur_mbuf;
775 : 0 : first_seg->nb_segs = 1;
776 : 0 : first_seg->pkt_len = pkt_len;
777 : : } else {
778 : 0 : first_seg->pkt_len += pkt_len;
779 : 0 : first_seg->nb_segs++;
780 : 0 : last_seg->next = cur_mbuf;
781 : : }
782 : :
783 [ # # ]: 0 : if (0 == (qword1 & SXE2_RX_DESC_STATUS_EOP_MASK)) {
784 : 0 : last_seg = cur_mbuf;
785 : 0 : continue;
786 : : }
787 : :
788 [ # # ]: 0 : if (unlikely(qword1 & SXE2_RX_DESC_ERROR_RXE_MASK) ||
789 [ # # ]: 0 : unlikely(qword1 & SXE2_RX_DESC_ERROR_OVERSIZE_MASK)) {
790 : 0 : rte_atomic_fetch_add_explicit(&rxq->sw_stats.drop_pkts, 1,
791 : : rte_memory_order_relaxed);
792 : 0 : rte_atomic_fetch_add_explicit(&rxq->sw_stats.drop_bytes,
793 : : first_seg->pkt_len - rxq->crc_len + RTE_ETHER_CRC_LEN,
794 : : rte_memory_order_relaxed);
795 : 0 : rte_pktmbuf_free(first_seg);
796 : 0 : first_seg = NULL;
797 : 0 : continue;
798 : : }
799 : :
800 : 0 : cur_mbuf->next = NULL;
801 [ # # ]: 0 : if (unlikely(rxq->crc_len > 0)) {
802 : 0 : first_seg->pkt_len -= RTE_ETHER_CRC_LEN;
803 : :
804 [ # # ]: 0 : if (pkt_len <= RTE_ETHER_CRC_LEN) {
805 [ # # ]: 0 : rte_pktmbuf_free_seg(cur_mbuf);
806 : 0 : first_seg->nb_segs--;
807 : 0 : last_seg->data_len = last_seg->data_len + pkt_len -
808 : : RTE_ETHER_CRC_LEN;
809 : 0 : last_seg->next = NULL;
810 : : } else {
811 : 0 : cur_mbuf->data_len = pkt_len - RTE_ETHER_CRC_LEN;
812 : : }
813 : :
814 [ # # ]: 0 : } else if (pkt_len == 0) {
815 [ # # ]: 0 : rte_pktmbuf_free_seg(cur_mbuf);
816 : 0 : first_seg->nb_segs--;
817 : 0 : last_seg->next = NULL;
818 : : }
819 : :
820 : 0 : rte_prefetch0(RTE_PTR_ADD(first_seg->buf_addr, first_seg->data_off));
821 : 0 : first_seg->port = rxq->port_id;
822 : :
823 : 0 : sxe2_rx_mbuf_common_fields_fill(rxq, first_seg, &desc_tmp);
824 : :
825 [ # # ]: 0 : if (rxq->vsi->adapter->devargs.sw_stats_en)
826 [ # # # # ]: 0 : sxe2_rx_sw_stats_update(rxq, first_seg, &desc_tmp);
827 : :
828 : 0 : rte_prefetch0(RTE_PTR_ADD(first_seg->buf_addr, first_seg->data_off));
829 : :
830 : 0 : rx_pkts[done_num] = first_seg;
831 : 0 : done_num++;
832 : :
833 : 0 : first_seg = NULL;
834 : : }
835 : :
836 : 0 : rxq->processing_idx = cur_idx;
837 : 0 : rxq->pkt_first_seg = first_seg;
838 : 0 : rxq->pkt_last_seg = last_seg;
839 : :
840 : 0 : sxe2_update_rx_tail(rxq, hold_num, cur_idx);
841 : :
842 : 0 : return done_num;
843 : : }
844 : :
845 : 0 : uint16_t sxe2_rx_pkts_scattered_split(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
846 : : {
847 : 0 : struct sxe2_rx_queue *rxq = (struct sxe2_rx_queue *)rx_queue;
848 : 0 : volatile union sxe2_rx_desc *desc_ring;
849 : 0 : volatile union sxe2_rx_desc *desc;
850 : 0 : union sxe2_rx_desc desc_tmp;
851 : 0 : struct rte_mbuf **buffer_ring;
852 : 0 : struct rte_mbuf **cur_buffer;
853 : 0 : struct rte_mbuf *cur_mbuf;
854 : 0 : struct rte_mbuf *cur_mbuf_pay;
855 : 0 : struct rte_mbuf *new_mbuf;
856 : 0 : struct rte_mbuf *new_mbuf_pay = NULL;
857 : 0 : struct rte_mbuf *first_seg;
858 : 0 : struct rte_mbuf *last_seg;
859 : 0 : uint64_t qword1;
860 : 0 : uint16_t done_num;
861 : 0 : uint16_t hold_num;
862 : 0 : uint16_t cur_idx;
863 : 0 : uint16_t pkt_len;
864 : 0 : uint16_t hdr_len;
865 : :
866 : 0 : desc_ring = rxq->desc_ring;
867 : 0 : buffer_ring = rxq->buffer_ring;
868 : 0 : cur_idx = rxq->processing_idx;
869 : 0 : first_seg = rxq->pkt_first_seg;
870 : 0 : last_seg = rxq->pkt_last_seg;
871 : 0 : done_num = 0;
872 : 0 : hold_num = 0;
873 : 0 : new_mbuf = NULL;
874 : :
875 [ # # ]: 0 : while (done_num < nb_pkts) {
876 : 0 : desc = &desc_ring[cur_idx];
877 : 0 : qword1 = rte_le_to_cpu_64(desc->wb.status_err_ptype_len);
878 : :
879 [ # # ]: 0 : if (0 == (SXE2_RX_DESC_STATUS_DD_MASK & qword1))
880 : : break;
881 : :
882 [ # # # # ]: 0 : if ((rxq->offloads & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT) == 0 ||
883 : : first_seg == NULL) {
884 : 0 : new_mbuf = rte_mbuf_raw_alloc(rxq->mb_pool);
885 [ # # ]: 0 : if (unlikely(new_mbuf == NULL)) {
886 : 0 : rxq->vsi->adapter->dev_info.dev_data->rx_mbuf_alloc_failed++;
887 : 0 : break;
888 : : }
889 : : }
890 : :
891 [ # # ]: 0 : if (rxq->offloads & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT) {
892 : 0 : new_mbuf_pay = rte_mbuf_raw_alloc(rxq->rx_seg[1].mp);
893 [ # # ]: 0 : if (unlikely(new_mbuf_pay == NULL)) {
894 : 0 : rxq->vsi->adapter->dev_info.dev_data->rx_mbuf_alloc_failed++;
895 [ # # ]: 0 : if (new_mbuf != NULL)
896 : 0 : rte_pktmbuf_free(new_mbuf);
897 : 0 : new_mbuf = NULL;
898 : : break;
899 : : }
900 : : }
901 : :
902 : 0 : hold_num++;
903 : 0 : desc_tmp = *desc;
904 : 0 : cur_buffer = &buffer_ring[cur_idx];
905 : 0 : cur_idx++;
906 [ # # ]: 0 : if (unlikely(cur_idx == rxq->ring_depth))
907 : 0 : cur_idx = 0;
908 : 0 : rte_prefetch0(buffer_ring[cur_idx]);
909 [ # # ]: 0 : if (0 == (cur_idx & 0x3)) {
910 : 0 : rte_prefetch0(&desc_ring[cur_idx]);
911 : 0 : rte_prefetch0(&buffer_ring[cur_idx]);
912 : : }
913 : 0 : cur_mbuf = *cur_buffer;
914 [ # # ]: 0 : if (0 == (rxq->offloads & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT)) {
915 : 0 : *cur_buffer = new_mbuf;
916 : 0 : desc->read.hdr_addr = 0;
917 : 0 : desc->read.pkt_addr =
918 : 0 : rte_cpu_to_le_64(rte_mbuf_data_iova_default(new_mbuf));
919 : : } else {
920 [ # # ]: 0 : if (first_seg == NULL) {
921 : 0 : *cur_buffer = new_mbuf;
922 : 0 : new_mbuf->next = new_mbuf_pay;
923 : 0 : new_mbuf->data_off = RTE_PKTMBUF_HEADROOM;
924 : 0 : new_mbuf_pay->next = NULL;
925 : 0 : new_mbuf_pay->data_off = RTE_PKTMBUF_HEADROOM;
926 : 0 : desc->read.hdr_addr =
927 : 0 : rte_cpu_to_le_64(rte_mbuf_data_iova_default(new_mbuf));
928 : 0 : desc->read.pkt_addr =
929 : 0 : rte_cpu_to_le_64(rte_mbuf_data_iova_default(new_mbuf_pay));
930 : : } else {
931 : 0 : cur_mbuf_pay = cur_mbuf->next;
932 : 0 : new_mbuf_pay->next = NULL;
933 : 0 : new_mbuf_pay->data_off = RTE_PKTMBUF_HEADROOM;
934 : 0 : cur_mbuf->next = new_mbuf_pay;
935 : 0 : desc->read.hdr_addr =
936 : 0 : rte_cpu_to_le_64(rte_mbuf_data_iova_default(cur_mbuf));
937 : 0 : desc->read.pkt_addr =
938 : 0 : rte_cpu_to_le_64(rte_mbuf_data_iova_default(new_mbuf_pay));
939 : 0 : cur_mbuf = cur_mbuf_pay;
940 : : }
941 : : }
942 : 0 : new_mbuf = NULL;
943 [ # # ]: 0 : if (0 == (rxq->offloads & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT)) {
944 : 0 : pkt_len = SXE2_RX_DESC_PKT_LEN_VAL_GET(qword1);
945 : 0 : cur_mbuf->data_len = pkt_len;
946 : 0 : cur_mbuf->data_off = RTE_PKTMBUF_HEADROOM;
947 [ # # ]: 0 : if (first_seg == NULL) {
948 : 0 : first_seg = cur_mbuf;
949 : 0 : first_seg->nb_segs = 1;
950 : 0 : first_seg->pkt_len = pkt_len;
951 : : } else {
952 : 0 : first_seg->pkt_len += pkt_len;
953 : 0 : first_seg->nb_segs++;
954 : 0 : last_seg->next = cur_mbuf;
955 : : }
956 : : } else {
957 [ # # ]: 0 : if (first_seg == NULL) {
958 : 0 : cur_mbuf->nb_segs = 2;
959 : 0 : cur_mbuf->next->next = NULL;
960 : 0 : pkt_len = SXE2_RX_DESC_PKT_LEN_VAL_GET(qword1);
961 : 0 : hdr_len = SXE2_RX_DESC_HDR_LEN_VAL_GET(qword1);
962 : 0 : cur_mbuf->data_len = hdr_len;
963 : 0 : cur_mbuf->pkt_len = hdr_len + pkt_len;
964 : 0 : cur_mbuf->next->data_len = pkt_len;
965 : 0 : first_seg = cur_mbuf;
966 : 0 : cur_mbuf = cur_mbuf->next;
967 : 0 : last_seg = cur_mbuf;
968 : : } else {
969 : 0 : cur_mbuf->nb_segs = 1;
970 : 0 : cur_mbuf->next = NULL;
971 : 0 : pkt_len = SXE2_RX_DESC_PKT_LEN_VAL_GET(qword1);
972 : 0 : cur_mbuf->data_len = pkt_len;
973 : :
974 : 0 : first_seg->pkt_len += pkt_len;
975 : 0 : first_seg->nb_segs++;
976 : 0 : last_seg->next = cur_mbuf;
977 : : }
978 : : }
979 : :
980 : : #ifdef RTE_ETHDEV_DEBUG_RX
981 : :
982 : : rte_pktmbuf_dump(stdout, first_seg, rte_pktmbuf_pkt_len(first_seg));
983 : : #endif
984 : :
985 [ # # ]: 0 : if (0 == (rte_le_to_cpu_64(desc_tmp.wb.status_err_ptype_len) &
986 : : SXE2_RX_DESC_STATUS_EOP_MASK)) {
987 : 0 : last_seg = cur_mbuf;
988 : 0 : continue;
989 : : }
990 : :
991 [ # # ]: 0 : if (unlikely(qword1 & SXE2_RX_DESC_ERROR_RXE_MASK) ||
992 [ # # ]: 0 : unlikely(qword1 & SXE2_RX_DESC_ERROR_OVERSIZE_MASK)) {
993 : 0 : rte_atomic_fetch_add_explicit(&rxq->sw_stats.drop_pkts, 1,
994 : : rte_memory_order_relaxed);
995 : 0 : rte_atomic_fetch_add_explicit(&rxq->sw_stats.drop_bytes,
996 : : first_seg->pkt_len - rxq->crc_len + RTE_ETHER_CRC_LEN,
997 : : rte_memory_order_relaxed);
998 : 0 : rte_pktmbuf_free(first_seg);
999 : 0 : first_seg = NULL;
1000 : 0 : continue;
1001 : : }
1002 : :
1003 : 0 : cur_mbuf->next = NULL;
1004 [ # # ]: 0 : if (unlikely(rxq->crc_len > 0)) {
1005 : 0 : first_seg->pkt_len -= RTE_ETHER_CRC_LEN;
1006 [ # # ]: 0 : if (pkt_len <= RTE_ETHER_CRC_LEN) {
1007 [ # # ]: 0 : rte_pktmbuf_free_seg(cur_mbuf);
1008 : 0 : cur_mbuf = NULL;
1009 : 0 : first_seg->nb_segs--;
1010 : 0 : last_seg->data_len = last_seg->data_len +
1011 : 0 : pkt_len - RTE_ETHER_CRC_LEN;
1012 : 0 : last_seg->next = NULL;
1013 : : } else {
1014 : 0 : cur_mbuf->data_len = pkt_len - RTE_ETHER_CRC_LEN;
1015 : : }
1016 [ # # ]: 0 : } else if (pkt_len == 0) {
1017 [ # # ]: 0 : rte_pktmbuf_free_seg(cur_mbuf);
1018 : 0 : cur_mbuf = NULL;
1019 : 0 : first_seg->nb_segs--;
1020 : 0 : last_seg->next = NULL;
1021 : : }
1022 : :
1023 : 0 : first_seg->port = rxq->port_id;
1024 : 0 : sxe2_rx_mbuf_common_fields_fill(rxq, first_seg, &desc_tmp);
1025 : :
1026 [ # # ]: 0 : if (rxq->vsi->adapter->devargs.sw_stats_en)
1027 [ # # # # ]: 0 : sxe2_rx_sw_stats_update(rxq, first_seg, &desc_tmp);
1028 : :
1029 : 0 : rte_prefetch0(RTE_PTR_ADD(first_seg->buf_addr, first_seg->data_off));
1030 : :
1031 : 0 : rx_pkts[done_num] = first_seg;
1032 : 0 : done_num++;
1033 : :
1034 : 0 : first_seg = NULL;
1035 : : }
1036 : :
1037 : 0 : rxq->processing_idx = cur_idx;
1038 : 0 : rxq->pkt_first_seg = first_seg;
1039 : 0 : rxq->pkt_last_seg = last_seg;
1040 : :
1041 : 0 : sxe2_update_rx_tail(rxq, hold_num, cur_idx);
1042 : :
1043 : 0 : return done_num;
1044 : : }
|