Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2018-2024 NXP
3 : : */
4 : :
5 : : #include <stdbool.h>
6 : : #include <stdint.h>
7 : : #include <unistd.h>
8 : :
9 : : #include "rte_ethdev.h"
10 : : #include "rte_malloc.h"
11 : : #include "rte_memzone.h"
12 : :
13 : : #include "base/enetc_hw.h"
14 : : #include "base/enetc4_hw.h"
15 : : #include "enetc.h"
16 : : #include "enetc_logs.h"
17 : :
18 : : #define ENETC_CACHE_LINE_RXBDS (RTE_CACHE_LINE_SIZE / \
19 : : sizeof(union enetc_rx_bd))
20 : : #define ENETC_RXBD_BUNDLE 16 /* Number of buffers to allocate at once */
21 : :
22 : : static int
23 : 0 : enetc_clean_tx_ring(struct enetc_bdr *tx_ring)
24 : : {
25 : : int tx_frm_cnt = 0;
26 : : struct enetc_swbd *tx_swbd, *tx_swbd_base;
27 : : int i, hwci, bd_count;
28 : : struct rte_mbuf *m[ENETC_RXBD_BUNDLE];
29 : :
30 : : /* we don't need barriers here, we just want a relatively current value
31 : : * from HW.
32 : : */
33 : 0 : hwci = (int)(rte_read32_relaxed(tx_ring->tcisr) &
34 : : ENETC_TBCISR_IDX_MASK);
35 : :
36 : 0 : tx_swbd_base = tx_ring->q_swbd;
37 : 0 : bd_count = tx_ring->bd_count;
38 : 0 : i = tx_ring->next_to_clean;
39 : 0 : tx_swbd = &tx_swbd_base[i];
40 : :
41 : : /* we're only reading the CI index once here, which means HW may update
42 : : * it while we're doing clean-up. We could read the register in a loop
43 : : * but for now I assume it's OK to leave a few Tx frames for next call.
44 : : * The issue with reading the register in a loop is that we're stalling
45 : : * here trying to catch up with HW which keeps sending traffic as long
46 : : * as it has traffic to send, so in effect we could be waiting here for
47 : : * the Tx ring to be drained by HW, instead of us doing Rx in that
48 : : * meantime.
49 : : */
50 [ # # ]: 0 : while (i != hwci) {
51 : : /* It seems calling rte_pktmbuf_free is wasting a lot of cycles,
52 : : * make a list and call _free when it's done.
53 : : */
54 [ # # ]: 0 : if (tx_frm_cnt == ENETC_RXBD_BUNDLE) {
55 : 0 : rte_pktmbuf_free_bulk(m, tx_frm_cnt);
56 : : tx_frm_cnt = 0;
57 : : }
58 : :
59 : 0 : m[tx_frm_cnt] = tx_swbd->buffer_addr;
60 : 0 : tx_swbd->buffer_addr = NULL;
61 : :
62 : 0 : i++;
63 : 0 : tx_swbd++;
64 [ # # ]: 0 : if (unlikely(i == bd_count)) {
65 : : i = 0;
66 : : tx_swbd = tx_swbd_base;
67 : : }
68 : :
69 : 0 : tx_frm_cnt++;
70 : : }
71 : :
72 [ # # ]: 0 : if (tx_frm_cnt)
73 : 0 : rte_pktmbuf_free_bulk(m, tx_frm_cnt);
74 : :
75 : 0 : tx_ring->next_to_clean = i;
76 : :
77 : 0 : return 0;
78 : : }
79 : :
80 : : uint16_t
81 : 0 : enetc_xmit_pkts(void *tx_queue,
82 : : struct rte_mbuf **tx_pkts,
83 : : uint16_t nb_pkts)
84 : : {
85 : : struct enetc_swbd *tx_swbd;
86 : : int i, start, bds_to_use;
87 : : struct enetc_tx_bd *txbd;
88 : : struct enetc_bdr *tx_ring = (struct enetc_bdr *)tx_queue;
89 : :
90 [ # # ]: 0 : i = tx_ring->next_to_use;
91 : :
92 : : bds_to_use = enetc_bd_unused(tx_ring);
93 [ # # ]: 0 : if (bds_to_use < nb_pkts)
94 : 0 : nb_pkts = bds_to_use;
95 : :
96 : : start = 0;
97 [ # # ]: 0 : while (nb_pkts--) {
98 : 0 : tx_ring->q_swbd[i].buffer_addr = tx_pkts[start];
99 : :
100 : 0 : txbd = ENETC_TXBD(*tx_ring, i);
101 : : tx_swbd = &tx_ring->q_swbd[i];
102 : 0 : txbd->frm_len = tx_pkts[start]->pkt_len;
103 : 0 : txbd->buf_len = txbd->frm_len;
104 : 0 : txbd->flags = rte_cpu_to_le_16(ENETC_TXBD_FLAGS_F);
105 : 0 : txbd->addr = (uint64_t)(uintptr_t)
106 : 0 : rte_cpu_to_le_64((size_t)tx_swbd->buffer_addr->buf_iova +
107 : : tx_swbd->buffer_addr->data_off);
108 : 0 : i++;
109 : 0 : start++;
110 [ # # ]: 0 : if (unlikely(i == tx_ring->bd_count))
111 : : i = 0;
112 : : }
113 : :
114 : : /* we're only cleaning up the Tx ring here, on the assumption that
115 : : * software is slower than hardware and hardware completed sending
116 : : * older frames out by now.
117 : : * We're also cleaning up the ring before kicking off Tx for the new
118 : : * batch to minimize chances of contention on the Tx ring
119 : : */
120 : 0 : enetc_clean_tx_ring(tx_ring);
121 : :
122 : 0 : tx_ring->next_to_use = i;
123 : 0 : enetc_wr_reg(tx_ring->tcir, i);
124 : 0 : return start;
125 : : }
126 : :
127 : : static void
128 : 0 : enetc4_tx_offload_checksum(struct rte_mbuf *mbuf, struct enetc_tx_bd *txbd)
129 : : {
130 [ # # ]: 0 : if ((mbuf->ol_flags & (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_IPV4))
131 : : == ENETC4_MBUF_F_TX_IP_IPV4) {
132 : 0 : txbd->l3t = ENETC4_TXBD_L3T;
133 : 0 : txbd->ipcs = ENETC4_TXBD_IPCS;
134 : 0 : txbd->l3_start = mbuf->l2_len;
135 : 0 : txbd->l3_hdr_size = mbuf->l3_len / 4;
136 : 0 : txbd->flags |= rte_cpu_to_le_16(ENETC4_TXBD_FLAGS_L_TX_CKSUM);
137 [ # # ]: 0 : if ((mbuf->ol_flags & RTE_MBUF_F_TX_UDP_CKSUM) == RTE_MBUF_F_TX_UDP_CKSUM) {
138 : 0 : txbd->l4t = rte_cpu_to_le_16(ENETC4_TXBD_L4T_UDP);
139 : 0 : txbd->flags |= rte_cpu_to_le_16(ENETC4_TXBD_FLAGS_L4CS);
140 [ # # ]: 0 : } else if ((mbuf->ol_flags & RTE_MBUF_F_TX_TCP_CKSUM) == RTE_MBUF_F_TX_TCP_CKSUM) {
141 : 0 : txbd->l4t = rte_cpu_to_le_16(ENETC4_TXBD_L4T_TCP);
142 : 0 : txbd->flags |= rte_cpu_to_le_16(ENETC4_TXBD_FLAGS_L4CS);
143 : : }
144 : : }
145 : 0 : }
146 : :
147 : : uint16_t
148 : 0 : enetc_xmit_pkts_nc(void *tx_queue,
149 : : struct rte_mbuf **tx_pkts,
150 : : uint16_t nb_pkts)
151 : : {
152 : : struct enetc_swbd *tx_swbd;
153 : : int i, start, bds_to_use;
154 : : struct enetc_tx_bd *txbd;
155 : : struct enetc_bdr *tx_ring = (struct enetc_bdr *)tx_queue;
156 : : unsigned int buflen, j;
157 : : uint8_t *data;
158 : :
159 [ # # ]: 0 : i = tx_ring->next_to_use;
160 : :
161 : : bds_to_use = enetc_bd_unused(tx_ring);
162 [ # # ]: 0 : if (bds_to_use < nb_pkts)
163 : 0 : nb_pkts = bds_to_use;
164 : :
165 : : start = 0;
166 [ # # ]: 0 : while (nb_pkts--) {
167 : 0 : tx_ring->q_swbd[i].buffer_addr = tx_pkts[start];
168 : :
169 : 0 : buflen = rte_pktmbuf_pkt_len(tx_ring->q_swbd[i].buffer_addr);
170 : 0 : data = rte_pktmbuf_mtod(tx_ring->q_swbd[i].buffer_addr, void *);
171 [ # # ]: 0 : for (j = 0; j <= buflen; j += RTE_CACHE_LINE_SIZE)
172 : : dcbf(data + j);
173 : :
174 : 0 : txbd = ENETC_TXBD(*tx_ring, i);
175 : 0 : txbd->flags = rte_cpu_to_le_16(ENETC4_TXBD_FLAGS_F);
176 [ # # ]: 0 : if (tx_ring->q_swbd[i].buffer_addr->ol_flags & ENETC4_TX_CKSUM_OFFLOAD_MASK)
177 : 0 : enetc4_tx_offload_checksum(tx_ring->q_swbd[i].buffer_addr, txbd);
178 : :
179 : : tx_swbd = &tx_ring->q_swbd[i];
180 : 0 : txbd->frm_len = buflen;
181 : 0 : txbd->buf_len = txbd->frm_len;
182 : 0 : txbd->addr = (uint64_t)(uintptr_t)
183 : 0 : rte_cpu_to_le_64((size_t)tx_swbd->buffer_addr->buf_iova +
184 : : tx_swbd->buffer_addr->data_off);
185 : 0 : i++;
186 : 0 : start++;
187 [ # # ]: 0 : if (unlikely(i == tx_ring->bd_count))
188 : : i = 0;
189 : : }
190 : :
191 : : /* we're only cleaning up the Tx ring here, on the assumption that
192 : : * software is slower than hardware and hardware completed sending
193 : : * older frames out by now.
194 : : * We're also cleaning up the ring before kicking off Tx for the new
195 : : * batch to minimize chances of contention on the Tx ring
196 : : */
197 : 0 : enetc_clean_tx_ring(tx_ring);
198 : :
199 : 0 : tx_ring->next_to_use = i;
200 : 0 : enetc_wr_reg(tx_ring->tcir, i);
201 : 0 : return start;
202 : : }
203 : :
204 : : int
205 : 0 : enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt)
206 : : {
207 : : struct enetc_swbd *rx_swbd;
208 : : union enetc_rx_bd *rxbd;
209 : : int i, j, k = ENETC_RXBD_BUNDLE;
210 : : struct rte_mbuf *m[ENETC_RXBD_BUNDLE];
211 : : struct rte_mempool *mb_pool;
212 : :
213 : 0 : i = rx_ring->next_to_use;
214 : 0 : mb_pool = rx_ring->mb_pool;
215 : 0 : rx_swbd = &rx_ring->q_swbd[i];
216 : 0 : rxbd = ENETC_RXBD(*rx_ring, i);
217 [ # # ]: 0 : for (j = 0; j < buff_cnt; j++) {
218 : : /* bulk alloc for the next up to 8 BDs */
219 [ # # ]: 0 : if (k == ENETC_RXBD_BUNDLE) {
220 : : k = 0;
221 : 0 : int m_cnt = RTE_MIN(buff_cnt - j, ENETC_RXBD_BUNDLE);
222 : :
223 [ # # ]: 0 : if (rte_pktmbuf_alloc_bulk(mb_pool, m, m_cnt))
224 : : return -1;
225 : : }
226 : :
227 : 0 : rx_swbd->buffer_addr = m[k];
228 : 0 : rxbd->w.addr = (uint64_t)(uintptr_t)
229 : 0 : rx_swbd->buffer_addr->buf_iova +
230 : 0 : rx_swbd->buffer_addr->data_off;
231 : : /* clear 'R" as well */
232 : 0 : rxbd->r.lstatus = 0;
233 : 0 : rx_swbd++;
234 : 0 : rxbd++;
235 : 0 : i++;
236 : 0 : k++;
237 [ # # ]: 0 : if (unlikely(i == rx_ring->bd_count)) {
238 : : i = 0;
239 : 0 : rxbd = ENETC_RXBD(*rx_ring, i);
240 : 0 : rx_swbd = &rx_ring->q_swbd[i];
241 : : }
242 : : }
243 : :
244 [ # # ]: 0 : if (likely(j)) {
245 : 0 : rx_ring->next_to_alloc = i;
246 : 0 : rx_ring->next_to_use = i;
247 : 0 : enetc_wr_reg(rx_ring->rcir, i);
248 : : }
249 : :
250 : : return j;
251 : : }
252 : :
253 : 0 : static inline void enetc_slow_parsing(struct rte_mbuf *m,
254 : : uint64_t parse_results)
255 : : {
256 : 0 : m->ol_flags &= ~(RTE_MBUF_F_RX_IP_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD);
257 : :
258 [ # # # # : 0 : switch (parse_results) {
# # # # #
# # ]
259 : 0 : case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV4:
260 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
261 : : RTE_PTYPE_L3_IPV4;
262 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
263 : 0 : return;
264 : 0 : case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV6:
265 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
266 : : RTE_PTYPE_L3_IPV6;
267 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
268 : 0 : return;
269 : 0 : case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV4_TCP:
270 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
271 : : RTE_PTYPE_L3_IPV4 |
272 : : RTE_PTYPE_L4_TCP;
273 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD |
274 : : RTE_MBUF_F_RX_L4_CKSUM_BAD;
275 : 0 : return;
276 : 0 : case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV6_TCP:
277 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
278 : : RTE_PTYPE_L3_IPV6 |
279 : : RTE_PTYPE_L4_TCP;
280 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD |
281 : : RTE_MBUF_F_RX_L4_CKSUM_BAD;
282 : 0 : return;
283 : 0 : case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV4_UDP:
284 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
285 : : RTE_PTYPE_L3_IPV4 |
286 : : RTE_PTYPE_L4_UDP;
287 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD |
288 : : RTE_MBUF_F_RX_L4_CKSUM_BAD;
289 : 0 : return;
290 : 0 : case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV6_UDP:
291 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
292 : : RTE_PTYPE_L3_IPV6 |
293 : : RTE_PTYPE_L4_UDP;
294 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD |
295 : : RTE_MBUF_F_RX_L4_CKSUM_BAD;
296 : 0 : return;
297 : 0 : case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV4_SCTP:
298 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
299 : : RTE_PTYPE_L3_IPV4 |
300 : : RTE_PTYPE_L4_SCTP;
301 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD |
302 : : RTE_MBUF_F_RX_L4_CKSUM_BAD;
303 : 0 : return;
304 : 0 : case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV6_SCTP:
305 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
306 : : RTE_PTYPE_L3_IPV6 |
307 : : RTE_PTYPE_L4_SCTP;
308 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD |
309 : : RTE_MBUF_F_RX_L4_CKSUM_BAD;
310 : 0 : return;
311 : 0 : case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV4_ICMP:
312 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
313 : : RTE_PTYPE_L3_IPV4 |
314 : : RTE_PTYPE_L4_ICMP;
315 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD |
316 : : RTE_MBUF_F_RX_L4_CKSUM_BAD;
317 : 0 : return;
318 : 0 : case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV6_ICMP:
319 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
320 : : RTE_PTYPE_L3_IPV6 |
321 : : RTE_PTYPE_L4_ICMP;
322 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD |
323 : : RTE_MBUF_F_RX_L4_CKSUM_BAD;
324 : 0 : return;
325 : : /* More switch cases can be added */
326 : 0 : default:
327 : 0 : m->packet_type = RTE_PTYPE_UNKNOWN;
328 : : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN |
329 : : RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN;
330 : : }
331 : : }
332 : :
333 : :
334 : : static inline void __rte_hot
335 : 0 : enetc_dev_rx_parse(struct rte_mbuf *m, uint16_t parse_results)
336 : : {
337 : : ENETC_PMD_DP_DEBUG("parse summary = 0x%x ", parse_results);
338 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD;
339 : :
340 [ # # # # : 0 : switch (parse_results) {
# # # # #
# # # #
# ]
341 : 0 : case ENETC_PKT_TYPE_ETHER:
342 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER;
343 : 0 : return;
344 : 0 : case ENETC_PKT_TYPE_IPV4:
345 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
346 : : RTE_PTYPE_L3_IPV4;
347 : 0 : return;
348 : 0 : case ENETC_PKT_TYPE_IPV6:
349 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
350 : : RTE_PTYPE_L3_IPV6;
351 : 0 : return;
352 : 0 : case ENETC_PKT_TYPE_IPV4_TCP:
353 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
354 : : RTE_PTYPE_L3_IPV4 |
355 : : RTE_PTYPE_L4_TCP;
356 : 0 : return;
357 : 0 : case ENETC_PKT_TYPE_IPV6_TCP:
358 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
359 : : RTE_PTYPE_L3_IPV6 |
360 : : RTE_PTYPE_L4_TCP;
361 : 0 : return;
362 : 0 : case ENETC_PKT_TYPE_IPV4_UDP:
363 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
364 : : RTE_PTYPE_L3_IPV4 |
365 : : RTE_PTYPE_L4_UDP;
366 : 0 : return;
367 : 0 : case ENETC_PKT_TYPE_IPV6_UDP:
368 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
369 : : RTE_PTYPE_L3_IPV6 |
370 : : RTE_PTYPE_L4_UDP;
371 : 0 : return;
372 : 0 : case ENETC_PKT_TYPE_IPV4_SCTP:
373 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
374 : : RTE_PTYPE_L3_IPV4 |
375 : : RTE_PTYPE_L4_SCTP;
376 : 0 : return;
377 : 0 : case ENETC_PKT_TYPE_IPV6_SCTP:
378 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
379 : : RTE_PTYPE_L3_IPV6 |
380 : : RTE_PTYPE_L4_SCTP;
381 : 0 : return;
382 : 0 : case ENETC_PKT_TYPE_IPV4_ICMP:
383 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
384 : : RTE_PTYPE_L3_IPV4 |
385 : : RTE_PTYPE_L4_ICMP;
386 : 0 : return;
387 : 0 : case ENETC_PKT_TYPE_IPV6_ICMP:
388 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
389 : : RTE_PTYPE_L3_IPV6 |
390 : : RTE_PTYPE_L4_ICMP;
391 : 0 : return;
392 : 0 : case ENETC_PKT_TYPE_IPV4_FRAG:
393 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
394 : : RTE_PTYPE_L3_IPV4 |
395 : : RTE_PTYPE_L4_FRAG;
396 : 0 : return;
397 : 0 : case ENETC_PKT_TYPE_IPV6_FRAG:
398 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
399 : : RTE_PTYPE_L3_IPV6 |
400 : : RTE_PTYPE_L4_FRAG;
401 : 0 : return;
402 : : /* More switch cases can be added */
403 : 0 : default:
404 : 0 : enetc_slow_parsing(m, parse_results);
405 : : }
406 : :
407 : : }
408 : :
409 : : static int
410 : 0 : enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
411 : : struct rte_mbuf **rx_pkts,
412 : : int work_limit)
413 : : {
414 : : int rx_frm_cnt = 0;
415 : : int cleaned_cnt, i, bd_count;
416 : : struct enetc_swbd *rx_swbd;
417 : : union enetc_rx_bd *rxbd;
418 : : uint32_t bd_status;
419 : :
420 : : /* next descriptor to process */
421 : 0 : i = rx_ring->next_to_clean;
422 : : /* next descriptor to process */
423 : 0 : rxbd = ENETC_RXBD(*rx_ring, i);
424 : : rte_prefetch0(rxbd);
425 : 0 : bd_count = rx_ring->bd_count;
426 : : /* LS1028A does not have platform cache so any software access following
427 : : * a hardware write will go directly to DDR. Latency of such a read is
428 : : * in excess of 100 core cycles, so try to prefetch more in advance to
429 : : * mitigate this.
430 : : * How much is worth prefetching really depends on traffic conditions.
431 : : * With congested Rx this could go up to 4 cache lines or so. But if
432 : : * software keeps up with hardware and follows behind Rx PI by a cache
433 : : * line or less then it's harmful in terms of performance to cache more.
434 : : * We would only prefetch BDs that have yet to be written by ENETC,
435 : : * which will have to be evicted again anyway.
436 : : */
437 : 0 : rte_prefetch0(ENETC_RXBD(*rx_ring,
438 : : (i + ENETC_CACHE_LINE_RXBDS) % bd_count));
439 : 0 : rte_prefetch0(ENETC_RXBD(*rx_ring,
440 : : (i + ENETC_CACHE_LINE_RXBDS * 2) % bd_count));
441 : :
442 : : cleaned_cnt = enetc_bd_unused(rx_ring);
443 : 0 : rx_swbd = &rx_ring->q_swbd[i];
444 : :
445 [ # # ]: 0 : while (likely(rx_frm_cnt < work_limit)) {
446 : 0 : bd_status = rte_le_to_cpu_32(rxbd->r.lstatus);
447 [ # # ]: 0 : if (!bd_status)
448 : : break;
449 : :
450 : 0 : rx_swbd->buffer_addr->pkt_len = rxbd->r.buf_len -
451 : 0 : rx_ring->crc_len;
452 : 0 : rx_swbd->buffer_addr->data_len = rxbd->r.buf_len -
453 : 0 : rx_ring->crc_len;
454 : 0 : rx_swbd->buffer_addr->hash.rss = rxbd->r.rss_hash;
455 : 0 : rx_swbd->buffer_addr->ol_flags = 0;
456 : 0 : enetc_dev_rx_parse(rx_swbd->buffer_addr,
457 : 0 : rxbd->r.parse_summary);
458 : :
459 : 0 : rx_pkts[rx_frm_cnt] = rx_swbd->buffer_addr;
460 : 0 : cleaned_cnt++;
461 : 0 : rx_swbd++;
462 : 0 : i++;
463 [ # # ]: 0 : if (unlikely(i == rx_ring->bd_count)) {
464 : : i = 0;
465 : : rx_swbd = &rx_ring->q_swbd[i];
466 : : }
467 : 0 : rxbd = ENETC_RXBD(*rx_ring, i);
468 : 0 : rte_prefetch0(ENETC_RXBD(*rx_ring,
469 : : (i + ENETC_CACHE_LINE_RXBDS) %
470 : : bd_count));
471 : 0 : rte_prefetch0(ENETC_RXBD(*rx_ring,
472 : : (i + ENETC_CACHE_LINE_RXBDS * 2) %
473 : : bd_count));
474 : :
475 : 0 : rx_frm_cnt++;
476 : : }
477 : :
478 : 0 : rx_ring->next_to_clean = i;
479 : 0 : enetc_refill_rx_ring(rx_ring, cleaned_cnt);
480 : :
481 : 0 : return rx_frm_cnt;
482 : : }
483 : :
484 : : static int
485 : 0 : enetc_clean_rx_ring_nc(struct enetc_bdr *rx_ring,
486 : : struct rte_mbuf **rx_pkts,
487 : : int work_limit)
488 : : {
489 : : int rx_frm_cnt = 0;
490 : : int cleaned_cnt, i;
491 : : struct enetc_swbd *rx_swbd;
492 : : union enetc_rx_bd *rxbd, rxbd_temp;
493 : : uint32_t bd_status;
494 : : uint8_t *data;
495 : : uint32_t j;
496 : :
497 : : /* next descriptor to process */
498 : 0 : i = rx_ring->next_to_clean;
499 : : /* next descriptor to process */
500 [ # # ]: 0 : rxbd = ENETC_RXBD(*rx_ring, i);
501 : :
502 : : cleaned_cnt = enetc_bd_unused(rx_ring);
503 : 0 : rx_swbd = &rx_ring->q_swbd[i];
504 : :
505 [ # # ]: 0 : while (likely(rx_frm_cnt < work_limit)) {
506 : 0 : rxbd_temp = *rxbd;
507 : 0 : bd_status = rte_le_to_cpu_32(rxbd_temp.r.lstatus);
508 [ # # ]: 0 : if (!bd_status)
509 : : break;
510 [ # # ]: 0 : if (rxbd_temp.r.error)
511 : 0 : rx_ring->ierrors++;
512 : :
513 : 0 : rx_swbd->buffer_addr->pkt_len = rxbd_temp.r.buf_len -
514 : 0 : rx_ring->crc_len;
515 : 0 : rx_swbd->buffer_addr->data_len = rx_swbd->buffer_addr->pkt_len;
516 : 0 : rx_swbd->buffer_addr->hash.rss = rxbd_temp.r.rss_hash;
517 : 0 : enetc_dev_rx_parse(rx_swbd->buffer_addr,
518 : : rxbd_temp.r.parse_summary);
519 : :
520 : : data = rte_pktmbuf_mtod(rx_swbd->buffer_addr, void *);
521 [ # # ]: 0 : for (j = 0; j <= rx_swbd->buffer_addr->pkt_len; j += RTE_CACHE_LINE_SIZE)
522 : : dccivac(data + j);
523 : :
524 : 0 : rx_pkts[rx_frm_cnt] = rx_swbd->buffer_addr;
525 : 0 : cleaned_cnt++;
526 : 0 : rx_swbd++;
527 : 0 : i++;
528 [ # # ]: 0 : if (unlikely(i == rx_ring->bd_count)) {
529 : : i = 0;
530 : : rx_swbd = &rx_ring->q_swbd[i];
531 : : }
532 : 0 : rxbd = ENETC_RXBD(*rx_ring, i);
533 : 0 : rx_frm_cnt++;
534 : : }
535 : :
536 : 0 : rx_ring->next_to_clean = i;
537 : 0 : enetc_refill_rx_ring(rx_ring, cleaned_cnt);
538 : :
539 : 0 : return rx_frm_cnt;
540 : : }
541 : :
542 : : uint16_t
543 : 0 : enetc_recv_pkts_nc(void *rxq, struct rte_mbuf **rx_pkts,
544 : : uint16_t nb_pkts)
545 : : {
546 : : struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq;
547 : :
548 : 0 : return enetc_clean_rx_ring_nc(rx_ring, rx_pkts, nb_pkts);
549 : : }
550 : :
551 : : uint16_t
552 : 0 : enetc_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts,
553 : : uint16_t nb_pkts)
554 : : {
555 : : struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq;
556 : :
557 : 0 : return enetc_clean_rx_ring(rx_ring, rx_pkts, nb_pkts);
558 : : }
|