Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2024 Realtek Corporation. All rights reserved
3 : : */
4 : :
5 : : #include <stdio.h>
6 : : #include <errno.h>
7 : : #include <stdint.h>
8 : :
9 : : #include <rte_eal.h>
10 : :
11 : : #include <rte_common.h>
12 : : #include <rte_interrupts.h>
13 : : #include <rte_byteorder.h>
14 : : #include <rte_debug.h>
15 : : #include <rte_pci.h>
16 : : #include <bus_pci_driver.h>
17 : : #include <rte_ether.h>
18 : : #include <ethdev_driver.h>
19 : : #include <ethdev_pci.h>
20 : : #include <rte_memory.h>
21 : : #include <rte_malloc.h>
22 : : #include <dev_driver.h>
23 : :
24 : : #include "r8169_ethdev.h"
25 : : #include "r8169_hw.h"
26 : : #include "r8169_logs.h"
27 : :
28 : : /* Bit mask to indicate what bits required for building TX context */
29 : : #define RTL_TX_OFFLOAD_MASK (RTE_MBUF_F_TX_IPV6 | \
30 : : RTE_MBUF_F_TX_IPV4 | \
31 : : RTE_MBUF_F_TX_VLAN | \
32 : : RTE_MBUF_F_TX_IP_CKSUM | \
33 : : RTE_MBUF_F_TX_L4_MASK | \
34 : : RTE_MBUF_F_TX_TCP_SEG)
35 : :
36 : : #define MIN_PATCH_LENGTH 47
37 : : #define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
38 : :
39 : : #define QUEUE_NUM_LIMIT 128
40 : :
41 : : /* Struct TxDesc in kernel r8169 */
42 : : struct rtl_tx_desc {
43 : : RTE_ATOMIC(u32) opts1;
44 : : u32 opts2;
45 : : u64 addr;
46 : : };
47 : :
48 : : /* Structure associated with each descriptor of the TX ring of a TX queue. */
49 : : struct rtl_tx_entry {
50 : : struct rte_mbuf *mbuf;
51 : : };
52 : :
53 : : /* Structure associated with each descriptor of the RX ring of a RX queue. */
54 : : struct rtl_rx_entry {
55 : : struct rte_mbuf *mbuf;
56 : : };
57 : :
58 : : /* Structure associated with each TX queue. */
59 : : struct rtl_tx_queue {
60 : : struct rtl_tx_desc *hw_ring;
61 : : struct rtl_tx_entry *sw_ring;
62 : : struct rtl_hw *hw;
63 : : uint64_t hw_ring_phys_addr;
64 : : uint16_t nb_tx_desc;
65 : : RTE_ATOMIC(uint32_t) tx_tail;
66 : : uint16_t tx_head;
67 : : uint16_t queue_id;
68 : : uint16_t port_id;
69 : : uint16_t tx_free_thresh;
70 : : uint16_t tx_free;
71 : : uint16_t hw_clo_ptr_reg;
72 : : uint16_t sw_tail_ptr_reg;
73 : : uint32_t NextHwDesCloPtr;
74 : : uint32_t BeginHwDesCloPtr;
75 : : };
76 : :
77 : : /* Structure associated with each RX queue. */
78 : : struct rtl_rx_queue {
79 : : struct rte_mempool *mb_pool;
80 : : struct rtl_rx_desc *hw_ring;
81 : : struct rtl_rx_entry *sw_ring;
82 : : struct rte_mbuf *pkt_first_seg; /* First segment of current packet. */
83 : : struct rte_mbuf *pkt_last_seg; /* Last segment of current packet. */
84 : : struct rtl_hw *hw;
85 : : uint64_t hw_ring_phys_addr;
86 : : uint64_t offloads;
87 : : uint16_t nb_rx_desc;
88 : : uint16_t rx_tail;
89 : : uint16_t nb_rx_hold;
90 : : uint16_t queue_id;
91 : : uint16_t port_id;
92 : : uint16_t rx_free_thresh;
93 : : };
94 : :
95 : : enum _DescStatusBit {
96 : : DescOwn = (1 << 31), /* Descriptor is owned by NIC. */
97 : : RingEnd = (1 << 30), /* End of descriptor ring */
98 : : FirstFrag = (1 << 29), /* First segment of a packet */
99 : : LastFrag = (1 << 28), /* Final segment of a packet */
100 : :
101 : : DescOwn_V3 = DescOwn, /* Descriptor is owned by NIC. */
102 : : RingEnd_V3 = RingEnd, /* End of descriptor ring */
103 : : FirstFrag_V3 = (1 << 25), /* First segment of a packet */
104 : : LastFrag_V3 = (1 << 24), /* Final segment of a packet */
105 : :
106 : : DescOwn_V4 = DescOwn, /* Descriptor is owned by NIC */
107 : : RingEnd_V4 = RingEnd, /* End of descriptor ring */
108 : : FirstFrag_V4 = FirstFrag, /* First segment of a packet */
109 : : LastFrag_V4 = LastFrag, /* Final segment of a packet */
110 : :
111 : : /* TX private */
112 : : /*------ offset 0 of TX descriptor ------*/
113 : : LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */
114 : : GiantSendv4 = (1 << 26), /* TCP Giant Send Offload V4 (GSOv4) */
115 : : GiantSendv6 = (1 << 25), /* TCP Giant Send Offload V6 (GSOv6) */
116 : : LargeSend_DP = (1 << 16), /* TCP Large Send Offload (TSO) */
117 : : MSSShift = 16, /* MSS value position */
118 : : MSSMask = 0x7FFU, /* MSS value 11 bits */
119 : : TxIPCS = (1 << 18), /* Calculate IP checksum */
120 : : TxUDPCS = (1 << 17), /* Calculate UDP/IP checksum */
121 : : TxTCPCS = (1 << 16), /* Calculate TCP/IP checksum */
122 : : TxVlanTag = (1 << 17), /* Add VLAN tag */
123 : :
124 : : /*@@@@@@ offset 4 of TX descriptor => bits for RTL8169 only begin @@@@@@*/
125 : : TxUDPCS_C = (1 << 31), /* Calculate UDP/IP checksum */
126 : : TxTCPCS_C = (1 << 30), /* Calculate TCP/IP checksum */
127 : : TxIPCS_C = (1 << 29), /* Calculate IP checksum */
128 : : TxIPV6F_C = (1 << 28), /* Indicate it is an IPv6 packet */
129 : : /*@@@@@@ offset 4 of tx descriptor => bits for RTL8169 only end @@@@@@*/
130 : :
131 : : /* RX private */
132 : : /* ------ offset 0 of RX descriptor ------ */
133 : : PID1 = (1 << 18), /* Protocol ID bit 1/2 */
134 : : PID0 = (1 << 17), /* Protocol ID bit 2/2 */
135 : :
136 : : #define RxProtoUDP PID1
137 : : #define RxProtoTCP PID0
138 : : #define RxProtoIP (PID1 | PID0)
139 : : #define RxProtoMask RxProtoIP
140 : :
141 : : RxIPF = (1 << 16), /* IP checksum failed */
142 : : RxUDPF = (1 << 15), /* UDP/IP checksum failed */
143 : : RxTCPF = (1 << 14), /* TCP/IP checksum failed */
144 : : RxVlanTag = (1 << 16), /* VLAN tag available */
145 : :
146 : : /*@@@@@@ offset 0 of RX descriptor => bits for RTL8169 only begin @@@@@@*/
147 : : RxUDPT = (1 << 18),
148 : : RxTCPT = (1 << 17),
149 : : /*@@@@@@ offset 0 of RX descriptor => bits for RTL8169 only end @@@@@@*/
150 : :
151 : : /*@@@@@@ offset 4 of RX descriptor => bits for RTL8169 only begin @@@@@@*/
152 : : RxV6F = (1 << 31),
153 : : RxV4F = (1 << 30),
154 : : /*@@@@@@ offset 4 of RX descriptor => bits for RTL8169 only end @@@@@@*/
155 : :
156 : : PID1_v3 = (1 << 29), /* Protocol ID bit 1/2 */
157 : : PID0_v3 = (1 << 28), /* Protocol ID bit 2/2 */
158 : :
159 : : #define RxProtoUDP_v3 PID1_v3
160 : : #define RxProtoTCP_v3 PID0_v3
161 : : #define RxProtoIP_v3 (PID1_v3 | PID0_v3)
162 : : #define RxProtoMask_v3 RxProtoIP_v3
163 : :
164 : : RxIPF_v3 = (1 << 26), /* IP checksum failed */
165 : : RxUDPF_v3 = (1 << 25), /* UDP/IP checksum failed */
166 : : RxTCPF_v3 = (1 << 24), /* TCP/IP checksum failed */
167 : : RxSCTPF_v3 = (1 << 23), /* TCP/IP checksum failed */
168 : : RxVlanTag_v3 = (RxVlanTag), /* VLAN tag available */
169 : :
170 : : /*@@@@@@ offset 0 of RX descriptor => bits for RTL8169 only begin @@@@@@*/
171 : : RxUDPT_v3 = (1 << 29),
172 : : RxTCPT_v3 = (1 << 28),
173 : : RxSCTP_v3 = (1 << 27),
174 : : /*@@@@@@ offset 0 of RX descriptor => bits for RTL8169 only end @@@@@@*/
175 : :
176 : : /*@@@@@@ offset 4 of RX descriptor => bits for RTL8169 only begin @@@@@@*/
177 : : RxV6F_v3 = RxV6F,
178 : : RxV4F_v3 = RxV4F,
179 : :
180 : : /*@@@@@@ offset 4 of RX descriptor => bits for RTL8169 only end @@@@@@*/
181 : : RxIPF_v4 = (1 << 17), /* IP checksum failed */
182 : : RxUDPF_v4 = (1 << 16), /* UDP/IP checksum failed */
183 : : RxTCPF_v4 = (1 << 15), /* TCP/IP checksum failed */
184 : : RxSCTPF_v4 = (1 << 19), /* SCTP checksum failed */
185 : : RxVlanTag_v4 = RxVlanTag, /* VLAN tag available */
186 : :
187 : : /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/
188 : : RxUDPT_v4 = (1 << 19),
189 : : RxTCPT_v4 = (1 << 18),
190 : : RxSCTP_v4 = (1 << 19),
191 : : /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only end @@@@@@*/
192 : :
193 : : /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only begin @@@@@@*/
194 : : RxV6F_v4 = RxV6F,
195 : : RxV4F_v4 = RxV4F,
196 : : /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/
197 : : };
198 : :
199 : : #define GTTCPHO_SHIFT 18
200 : : #define GTTCPHO_MAX 0x70U
201 : : #define GTPKTSIZE_MAX 0x3ffffU
202 : : #define TCPHO_SHIFT 18
203 : : #define TCPHO_MAX 0x3ffU
204 : : #define LSOPKTSIZE_MAX 0xffffU
205 : : #define MSS_MAX 0x07ffu /* MSS value */
206 : :
207 : : typedef void (*rtl_clear_rdu_func)(struct rtl_hw *, uint16_t);
208 : : static rtl_clear_rdu_func rtl_clear_rdu;
209 : :
210 : : /* ---------------------------------RX---------------------------------- */
211 : :
212 : : static void
213 : 0 : rtl_rx_queue_release_mbufs(struct rtl_rx_queue *rxq)
214 : : {
215 : : int i;
216 : :
217 : 0 : PMD_INIT_FUNC_TRACE();
218 : :
219 [ # # ]: 0 : if (rxq != NULL) {
220 [ # # ]: 0 : if (rxq->sw_ring != NULL) {
221 [ # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc; i++) {
222 [ # # ]: 0 : if (rxq->sw_ring[i].mbuf != NULL) {
223 : : rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf);
224 : 0 : rxq->sw_ring[i].mbuf = NULL;
225 : : }
226 : : }
227 : : }
228 : : }
229 : 0 : }
230 : :
231 : : void
232 : 0 : rtl_rx_queue_release(struct rte_eth_dev *dev, uint16_t rx_queue_id)
233 : : {
234 : 0 : struct rtl_rx_queue *rxq = dev->data->rx_queues[rx_queue_id];
235 : :
236 : 0 : PMD_INIT_FUNC_TRACE();
237 : :
238 [ # # ]: 0 : if (rxq != NULL) {
239 : 0 : rtl_rx_queue_release_mbufs(rxq);
240 : 0 : rte_free(rxq->sw_ring);
241 : 0 : rte_free(rxq);
242 : : }
243 : 0 : }
244 : :
245 : : void
246 : 0 : rtl_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
247 : : struct rte_eth_rxq_info *qinfo)
248 : : {
249 : : struct rtl_rx_queue *rxq;
250 : :
251 : 0 : rxq = dev->data->rx_queues[queue_id];
252 : :
253 : 0 : qinfo->mp = rxq->mb_pool;
254 : 0 : qinfo->scattered_rx = dev->data->scattered_rx;
255 : 0 : qinfo->nb_desc = rxq->nb_rx_desc;
256 : :
257 : 0 : qinfo->conf.rx_free_thresh = rxq->rx_free_thresh;
258 : 0 : qinfo->conf.offloads = rxq->offloads;
259 : 0 : }
260 : :
261 : : static void
262 : : rtl_mark_as_last_descriptor_v1(struct rtl_rx_desc *desc)
263 : : {
264 : 0 : desc->opts1 |= rte_cpu_to_le_32(RingEnd);
265 : 0 : }
266 : :
267 : : static void
268 : : rtl_mark_as_last_descriptor_v3(struct rtl_rx_descv3 *descv3)
269 : : {
270 : 0 : descv3->RxDescNormalDDWord4.opts1 |= rte_cpu_to_le_32(RingEnd);
271 : 0 : }
272 : :
273 : : static void
274 : : rtl_mark_as_last_descriptor_v4(struct rtl_rx_descv4 *descv4)
275 : : {
276 : 0 : descv4->RxDescNormalDDWord2.opts1 |= rte_cpu_to_le_32(RingEnd);
277 : 0 : }
278 : :
279 : : static void
280 : : rtl_mark_as_last_descriptor(struct rtl_hw *hw, struct rtl_rx_desc *desc)
281 : : {
282 [ # # # # : 0 : switch (hw->HwSuppRxDescType) {
# # ]
283 : : case RX_DESC_RING_TYPE_3:
284 : : rtl_mark_as_last_descriptor_v3((struct rtl_rx_descv3 *)desc);
285 : : break;
286 : : case RX_DESC_RING_TYPE_4:
287 : : rtl_mark_as_last_descriptor_v4((struct rtl_rx_descv4 *)desc);
288 : : break;
289 : : default:
290 : : rtl_mark_as_last_descriptor_v1(desc);
291 : : break;
292 : : }
293 : : }
294 : :
295 : : static void
296 : 0 : rtl_reset_rx_queue(struct rtl_rx_queue *rxq)
297 : : {
298 : 0 : struct rtl_hw *hw = rxq->hw;
299 : : int i;
300 : :
301 [ # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc; i++)
302 : 0 : memset(rxq->hw_ring, 0, hw->RxDescLength * rxq->nb_rx_desc);
303 : :
304 : 0 : rtl_mark_as_last_descriptor(hw, rtl_get_rxdesc(hw, rxq->hw_ring,
305 [ # # # # : 0 : rxq->nb_rx_desc - 1));
# # ]
306 : :
307 : 0 : rxq->rx_tail = 0;
308 : 0 : rxq->pkt_first_seg = NULL;
309 : 0 : rxq->pkt_last_seg = NULL;
310 : 0 : }
311 : :
312 : : uint64_t
313 : 0 : rtl_get_rx_port_offloads(struct rtl_hw *hw)
314 : : {
315 : : uint64_t offloads;
316 : :
317 : : offloads = RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
318 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
319 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
320 : : RTE_ETH_RX_OFFLOAD_SCATTER |
321 : : RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
322 : :
323 [ # # ]: 0 : if (hw->EnableRss)
324 : : offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
325 : :
326 : 0 : return offloads;
327 : : }
328 : :
329 : : int
330 : 0 : rtl_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
331 : : uint16_t nb_rx_desc, unsigned int socket_id,
332 : : const struct rte_eth_rxconf *rx_conf,
333 : : struct rte_mempool *mb_pool)
334 : : {
335 : : struct rtl_rx_queue *rxq;
336 : : const struct rte_memzone *mz;
337 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
338 : 0 : struct rtl_hw *hw = &adapter->hw;
339 : : uint32_t size;
340 : :
341 : 0 : PMD_INIT_FUNC_TRACE();
342 : :
343 : : /*
344 : : * If this queue existed already, free the associated memory. The
345 : : * queue cannot be reused in case we need to allocate memory on
346 : : * different socket than was previously used.
347 : : */
348 [ # # ]: 0 : if (dev->data->rx_queues[queue_idx] != NULL) {
349 : 0 : rtl_rx_queue_release(dev, queue_idx);
350 : 0 : dev->data->rx_queues[queue_idx] = NULL;
351 : : }
352 : :
353 : : /* First allocate the rx queue data structure */
354 : 0 : rxq = rte_zmalloc_socket("r8169 RX queue", sizeof(struct rtl_rx_queue),
355 : : RTE_CACHE_LINE_SIZE, socket_id);
356 : :
357 [ # # ]: 0 : if (rxq == NULL) {
358 : 0 : PMD_INIT_LOG(ERR, "Cannot allocate Rx queue structure");
359 : 0 : return -ENOMEM;
360 : : }
361 : :
362 : : /* Setup queue */
363 : 0 : rxq->mb_pool = mb_pool;
364 : 0 : rxq->nb_rx_desc = nb_rx_desc;
365 : 0 : rxq->port_id = dev->data->port_id;
366 : 0 : rxq->queue_id = queue_idx;
367 : 0 : rxq->rx_free_thresh = rx_conf->rx_free_thresh;
368 : :
369 : : /* Allocate memory for the software ring */
370 : 0 : rxq->sw_ring = rte_calloc("r8169 sw rx ring", nb_rx_desc,
371 : : sizeof(struct rtl_rx_entry), RTE_CACHE_LINE_SIZE);
372 : :
373 [ # # ]: 0 : if (rxq->sw_ring == NULL) {
374 : 0 : PMD_INIT_LOG(ERR,
375 : : "Port %d: Cannot allocate software ring for queue %d",
376 : : rxq->port_id, rxq->queue_id);
377 : 0 : rte_free(rxq);
378 : 0 : return -ENOMEM;
379 : : }
380 : :
381 : : /*
382 : : * Allocate RX ring hardware descriptors. A memzone large enough to
383 : : * handle the maximum ring size is allocated in order to allow for
384 : : * resizing in later calls to the queue setup function.
385 : : */
386 : 0 : size = hw->RxDescLength * (nb_rx_desc + 1);
387 : 0 : mz = rte_eth_dma_zone_reserve(dev, "rx_ring", queue_idx, size,
388 : : RTL_RING_ALIGN, socket_id);
389 [ # # ]: 0 : if (mz == NULL) {
390 : 0 : PMD_INIT_LOG(ERR,
391 : : "Port %d: Cannot allocate software ring for queue %d",
392 : : rxq->port_id, rxq->queue_id);
393 : 0 : rtl_rx_queue_release(dev, rxq->queue_id);
394 : 0 : return -ENOMEM;
395 : : }
396 : :
397 : 0 : rxq->hw = hw;
398 : 0 : rxq->hw_ring = mz->addr;
399 : 0 : rxq->hw_ring_phys_addr = mz->iova;
400 : 0 : rxq->offloads = rx_conf->offloads | dev->data->dev_conf.rxmode.offloads;
401 : :
402 : 0 : rtl_reset_rx_queue(rxq);
403 : :
404 : 0 : dev->data->rx_queues[queue_idx] = rxq;
405 : :
406 : 0 : return 0;
407 : : }
408 : :
409 : : static inline void
410 : : rtl_set_desc_dma_addr(struct rtl_hw *hw, struct rtl_rx_desc *desc,
411 : : uint64_t dma_addr)
412 : : {
413 [ # # # # : 0 : switch (hw->HwSuppRxDescType) {
# # # #
# ]
414 : 0 : case RX_DESC_RING_TYPE_3:
415 : 0 : ((struct rtl_rx_descv3 *)desc)->addr = dma_addr;
416 : 0 : break;
417 : 0 : case RX_DESC_RING_TYPE_4:
418 : 0 : ((struct rtl_rx_descv4 *)desc)->addr = dma_addr;
419 : 0 : break;
420 : 0 : default:
421 : 0 : desc->addr = dma_addr;
422 : 0 : break;
423 : : }
424 : : }
425 : :
426 : : static inline void
427 : : rtl_mark_to_asic_v1(struct rtl_rx_desc *desc, u32 rx_buf_sz)
428 : : {
429 : 0 : u32 eor = rte_le_to_cpu_32(desc->opts1) & RingEnd;
430 : :
431 : 0 : desc->opts2 = 0;
432 : : rte_wmb();
433 : 0 : desc->opts1 = rte_cpu_to_le_32(DescOwn | eor | rx_buf_sz);
434 : 0 : }
435 : :
436 : : static inline void
437 : : rtl_mark_to_asic_v3(struct rtl_rx_descv3 *descv3, u32 rx_buf_sz)
438 : : {
439 : 0 : u32 eor = rte_le_to_cpu_32(descv3->RxDescNormalDDWord4.opts1) & RingEnd;
440 : :
441 : 0 : descv3->RxDescNormalDDWord4.opts2 = 0;
442 : : rte_wmb();
443 : 0 : descv3->RxDescNormalDDWord4.opts1 = rte_cpu_to_le_32(DescOwn | eor |
444 : : rx_buf_sz);
445 : 0 : }
446 : :
447 : : static inline void
448 : : rtl_mark_to_asic_v4(struct rtl_rx_descv4 *descv4, u32 rx_buf_sz)
449 : : {
450 : 0 : u32 eor = rte_le_to_cpu_32(descv4->RxDescNormalDDWord2.opts1) & RingEnd;
451 : :
452 : 0 : descv4->RxDescNormalDDWord2.opts2 = 0;
453 : : rte_wmb();
454 : 0 : descv4->RxDescNormalDDWord2.opts1 = rte_cpu_to_le_32(DescOwn | eor |
455 : : rx_buf_sz);
456 : 0 : }
457 : :
458 : : static inline void
459 : 0 : rtl_mark_to_asic(struct rtl_hw *hw, struct rtl_rx_desc *desc)
460 : : {
461 [ # # # ]: 0 : switch (hw->HwSuppRxDescType) {
462 : 0 : case RX_DESC_RING_TYPE_3:
463 : 0 : rtl_mark_to_asic_v3((struct rtl_rx_descv3 *)desc, hw->rx_buf_sz);
464 : : break;
465 : 0 : case RX_DESC_RING_TYPE_4:
466 : 0 : rtl_mark_to_asic_v4((struct rtl_rx_descv4 *)desc, hw->rx_buf_sz);
467 : : break;
468 : 0 : default:
469 : 0 : rtl_mark_to_asic_v1(desc, hw->rx_buf_sz);
470 : : break;
471 : : }
472 : 0 : }
473 : :
474 : : static inline void
475 : : rtl_map_to_asic(struct rtl_hw *hw, struct rtl_rx_desc *desc, uint64_t dma_addr)
476 : : {
477 : : rtl_set_desc_dma_addr(hw, desc, dma_addr);
478 : 0 : rtl_mark_to_asic(hw, desc);
479 : : }
480 : :
481 : : static int
482 : 0 : rtl_alloc_rx_queue_mbufs(struct rtl_rx_queue *rxq)
483 : : {
484 : 0 : struct rtl_rx_entry *rxe = rxq->sw_ring;
485 : 0 : struct rtl_hw *hw = rxq->hw;
486 : : int i;
487 : : uint64_t dma_addr;
488 : :
489 : : /* Initialize software ring entries */
490 [ # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc; i++) {
491 : 0 : struct rte_mbuf *mbuf = rte_mbuf_raw_alloc(rxq->mb_pool);
492 : :
493 [ # # ]: 0 : if (mbuf == NULL) {
494 : 0 : PMD_INIT_LOG(ERR, "RX mbuf alloc failed queue_id=%hu",
495 : : rxq->queue_id);
496 : 0 : return -ENOMEM;
497 : : }
498 : :
499 : : dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(mbuf));
500 : :
501 [ # # # ]: 0 : rtl_map_to_asic(hw, rtl_get_rxdesc(hw, rxq->hw_ring, i),
502 : : dma_addr);
503 : 0 : rxe[i].mbuf = mbuf;
504 : : }
505 : :
506 [ # # # ]: 0 : rtl_mark_as_last_descriptor(hw, rtl_get_rxdesc(hw, rxq->hw_ring, i));
507 : :
508 : : return 0;
509 : : }
510 : :
511 : : static void
512 : 0 : rtl8125_hw_set_features(struct rtl_hw *hw, uint64_t offloads)
513 : : {
514 : : u16 cp_cmd;
515 : : u32 rx_config;
516 : :
517 : 0 : rx_config = RTL_R32(hw, RxConfig);
518 [ # # ]: 0 : if (offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
519 : 0 : rx_config |= (EnableInnerVlan | EnableOuterVlan);
520 : : else
521 : 0 : rx_config &= ~(EnableInnerVlan | EnableOuterVlan);
522 : :
523 : 0 : RTL_W32(hw, RxConfig, rx_config);
524 : :
525 : 0 : cp_cmd = RTL_R16(hw, CPlusCmd);
526 : :
527 [ # # ]: 0 : if (offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM)
528 : 0 : cp_cmd |= RxChkSum;
529 : : else
530 : 0 : cp_cmd &= ~RxChkSum;
531 : :
532 : 0 : RTL_W16(hw, CPlusCmd, cp_cmd);
533 : 0 : }
534 : :
535 : : static void
536 : : rtl8168_hw_set_features(struct rtl_hw *hw, uint64_t offloads)
537 : : {
538 : : u16 cp_cmd;
539 : :
540 : 0 : cp_cmd = RTL_R16(hw, CPlusCmd);
541 : :
542 [ # # ]: 0 : if (offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM)
543 : 0 : cp_cmd |= RxChkSum;
544 : : else
545 : 0 : cp_cmd &= ~RxChkSum;
546 : :
547 [ # # ]: 0 : if (offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
548 : 0 : cp_cmd |= RxVlan;
549 : : else
550 : 0 : cp_cmd &= ~RxVlan;
551 : :
552 : 0 : RTL_W16(hw, CPlusCmd, cp_cmd);
553 : 0 : }
554 : :
555 : : static void
556 : 0 : rtl_hw_set_features(struct rtl_hw *hw, uint64_t offloads)
557 : : {
558 [ # # ]: 0 : if (rtl_is_8125(hw))
559 : 0 : rtl8125_hw_set_features(hw, offloads);
560 : : else
561 : : rtl8168_hw_set_features(hw, offloads);
562 : 0 : }
563 : :
564 : : static void
565 : : rtl_hw_set_rx_packet_filter(struct rtl_hw *hw)
566 : : {
567 : : int rx_mode;
568 : :
569 : 0 : hw->hw_ops.hw_init_rxcfg(hw);
570 : :
571 : : rx_mode = AcceptBroadcast | AcceptMyPhys;
572 : 0 : RTL_W32(hw, RxConfig, rx_mode | (RTL_R32(hw, RxConfig)));
573 : : }
574 : :
575 : : static void
576 : 0 : rtl8125_clear_rdu(struct rtl_hw *hw, uint16_t queue_id)
577 : : {
578 [ # # ]: 0 : if (queue_id == 0)
579 : 0 : RTL_W32(hw, ISR0_8125, (RxOK | RxErr | RxDescUnavail));
580 : : else
581 : 0 : RTL_W8(hw, ISR1_8125 + (queue_id - 1) * 4, (BIT_0 | BIT_1));
582 : 0 : }
583 : :
584 : : static void
585 : 0 : rtl8168_clear_rdu(struct rtl_hw *hw, uint16_t queue_id __rte_unused)
586 : : {
587 : 0 : RTL_W16(hw, IntrStatus, (RxOK | RxErr | RxDescUnavail));
588 : 0 : }
589 : :
590 : : static void
591 : 0 : rtl_init_rss(struct rtl_hw *hw, u16 nb_rx_queues)
592 : : {
593 : : u64 rand;
594 : : int i;
595 : :
596 [ # # ]: 0 : for (i = 0; i < RTL_MAX_INDIRECTION_TABLE_ENTRIES; i++)
597 : 0 : hw->rss_indir_tbl[i] = i & (nb_rx_queues - 1);
598 : :
599 [ # # ]: 0 : for (i = 0; i < RTL_RSS_KEY_SIZE; i += sizeof(u64)) {
600 : 0 : rand = rte_rand();
601 : 0 : memcpy(&hw->rss_key[i], &rand, sizeof(u64));
602 : : }
603 : 0 : }
604 : :
605 : : static void
606 [ # # ]: 0 : rtl8125_set_rx_q_num(struct rtl_hw *hw, unsigned int num_rx_queues)
607 : : {
608 : : u16 q_ctrl;
609 : : u16 rx_q_num;
610 : :
611 : 0 : rx_q_num = (u16)rte_log2_u32(num_rx_queues);
612 : : rx_q_num &= (BIT_0 | BIT_1 | BIT_2);
613 : 0 : rx_q_num <<= 2;
614 : 0 : q_ctrl = RTL_R16(hw, Q_NUM_CTRL_8125);
615 : 0 : q_ctrl &= ~(BIT_2 | BIT_3 | BIT_4);
616 : 0 : q_ctrl |= rx_q_num;
617 : 0 : RTL_W16(hw, Q_NUM_CTRL_8125, q_ctrl);
618 : 0 : }
619 : :
620 : : int
621 : 0 : rtl_rx_init(struct rte_eth_dev *dev)
622 : : {
623 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
624 : 0 : struct rtl_hw *hw = &adapter->hw;
625 : : struct rtl_rx_queue *rxq;
626 : : int ret, i;
627 : : u32 csi_tmp, max_rx_pkt_size;
628 : 0 : u16 nb_rx_queues = dev->data->nb_rx_queues;
629 : : u16 desc_start_addr_lo[QUEUE_NUM_LIMIT];
630 : :
631 : 0 : desc_start_addr_lo[0] = RxDescAddrLow;
632 [ # # ]: 0 : for (i = 1; i < nb_rx_queues; i++)
633 : 0 : desc_start_addr_lo[i] = (u16)(RDSAR_Q1_LOW_8125 + (i - 1) * 8);
634 : :
635 : 0 : rxq = dev->data->rx_queues[0];
636 [ # # ]: 0 : for (i = 0; i < nb_rx_queues; i++) {
637 : 0 : rxq = dev->data->rx_queues[i];
638 : :
639 [ # # ]: 0 : if (!rxq->mb_pool) {
640 : 0 : PMD_INIT_LOG(ERR, "r8169 rx queue pool not setup!");
641 : 0 : return -ENOMEM;
642 : : }
643 : :
644 : 0 : hw->rx_buf_sz = rte_pktmbuf_data_room_size(rxq->mb_pool) -
645 : : RTE_PKTMBUF_HEADROOM;
646 : :
647 : 0 : RTL_W32(hw, desc_start_addr_lo[i],
648 : : (u64)rxq->hw_ring_phys_addr & DMA_BIT_MASK(32));
649 : 0 : RTL_W32(hw, desc_start_addr_lo[i] + 4,
650 : : (u64)rxq->hw_ring_phys_addr >> 32);
651 : :
652 : 0 : ret = rtl_alloc_rx_queue_mbufs(rxq);
653 [ # # ]: 0 : if (ret) {
654 : 0 : PMD_INIT_LOG(ERR, "r8169 rx mbuf alloc failed!");
655 : 0 : return ret;
656 : : }
657 : :
658 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
659 : : }
660 : :
661 : 0 : max_rx_pkt_size = dev->data->mtu + RTL_ETH_OVERHEAD;
662 : 0 : RTL_W16(hw, RxMaxSize, max_rx_pkt_size);
663 : :
664 : 0 : dev->rx_pkt_burst = rtl_recv_pkts;
665 [ # # ]: 0 : if (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_SCATTER ||
666 [ # # ]: 0 : max_rx_pkt_size > hw->rx_buf_sz) {
667 [ # # ]: 0 : if (!dev->data->scattered_rx)
668 : 0 : PMD_INIT_LOG(DEBUG, "forcing scatter mode");
669 : 0 : dev->rx_pkt_burst = rtl_recv_scattered_pkts;
670 : 0 : dev->data->scattered_rx = 1;
671 : : }
672 : :
673 : 0 : rtl_enable_cfg9346_write(hw);
674 : :
675 [ # # ]: 0 : if (!rtl_is_8125(hw)) {
676 : : /* RX ftr mcu enable */
677 : 0 : csi_tmp = rtl_eri_read(hw, 0xDC, 1, ERIAR_ExGMAC);
678 : 0 : csi_tmp &= ~BIT_0;
679 : 0 : rtl_eri_write(hw, 0xDC, 1, csi_tmp, ERIAR_ExGMAC);
680 : 0 : csi_tmp |= BIT_0;
681 : 0 : rtl_eri_write(hw, 0xDC, 1, csi_tmp, ERIAR_ExGMAC);
682 : :
683 : : /* RSS disable */
684 : 0 : rtl_eri_write(hw, 0xC0, 2, 0x0000, ERIAR_ExGMAC); /* queue num = 1 */
685 : 0 : rtl_eri_write(hw, 0xB8, 4, 0x00000000, ERIAR_ExGMAC);
686 : : }
687 : :
688 : : /* RX accept type and csum vlan offload */
689 : 0 : rtl_hw_set_features(hw, rxq->offloads);
690 : :
691 : 0 : rtl_disable_rxdvgate(hw);
692 : :
693 : : /* Set Rx packet filter */
694 : : rtl_hw_set_rx_packet_filter(hw);
695 : :
696 : 0 : rtl_disable_cfg9346_write(hw);
697 : :
698 [ # # ]: 0 : if (rtl_is_8125(hw))
699 : 0 : rtl_clear_rdu = rtl8125_clear_rdu;
700 : : else
701 : 0 : rtl_clear_rdu = rtl8168_clear_rdu;
702 : :
703 : : /* RSS_control_0 */
704 [ # # ]: 0 : if (hw->EnableRss) {
705 : 0 : rtl_init_rss(hw, nb_rx_queues);
706 : 0 : rtl8125_config_rss(hw, nb_rx_queues);
707 : : } else {
708 : 0 : RTL_W32(hw, RSS_CTRL_8125, 0x00);
709 : : }
710 : :
711 : : /* VMQ_control */
712 : 0 : rtl8125_set_rx_q_num(hw, nb_rx_queues);
713 : :
714 : 0 : RTL_W8(hw, ChipCmd, RTL_R8(hw, ChipCmd) | CmdRxEnb);
715 : :
716 : 0 : return 0;
717 : : }
718 : :
719 : : static inline bool
720 : 0 : rtl_rx_ip_csum(struct rtl_hw *hw, uint32_t opts1, uint32_t opts2)
721 : : {
722 [ # # # ]: 0 : switch (hw->HwSuppRxDescType) {
723 : 0 : case RX_DESC_RING_TYPE_3:
724 [ # # # # ]: 0 : return (((opts2 & RxV4F_v3) && !(opts2 & RxIPF_v3)) ||
725 : : (opts2 & RxV6F_v3));
726 : 0 : case RX_DESC_RING_TYPE_4:
727 [ # # # # : 0 : return (((opts2 & RxV4F_v4) && !(opts1 & RxIPF_v4)) ||
# # ]
728 : : (opts2 & RxV6F_v4));
729 : 0 : default:
730 [ # # # # : 0 : return (((opts2 & RxV4F) && !(opts1 & RxIPF)) ||
# # ]
731 : : (opts2 & RxV6F));
732 : : }
733 : : }
734 : :
735 : : static inline bool
736 : 0 : rtl_rx_l4_csum(struct rtl_hw *hw, uint32_t opts1, uint32_t opts2)
737 : : {
738 [ # # # ]: 0 : switch (hw->HwSuppRxDescType) {
739 : 0 : case RX_DESC_RING_TYPE_3:
740 [ # # ]: 0 : return (((opts2 & RxTCPT_v3) && !(opts2 & RxTCPF_v3)) ||
741 [ # # ]: 0 : ((opts2 & RxUDPT_v3) && !(opts2 & RxUDPF_v3)));
742 : 0 : case RX_DESC_RING_TYPE_4:
743 [ # # ]: 0 : return (((opts1 & RxTCPT_v4) && !(opts1 & RxTCPF_v4)) ||
744 [ # # ]: 0 : ((opts1 & RxUDPT_v4) && !(opts1 & RxUDPF_v4)));
745 : 0 : default:
746 [ # # ]: 0 : return (((opts1 & RxTCPT) && !(opts1 & RxTCPF)) ||
747 [ # # ]: 0 : ((opts1 & RxUDPT) && !(opts1 & RxUDPF)));
748 : : }
749 : : }
750 : :
751 : : static inline uint64_t
752 : 0 : rtl_rx_desc_error_to_pkt_flags(struct rtl_rx_queue *rxq, uint32_t opts1,
753 : : uint32_t opts2)
754 : : {
755 : : uint64_t pkt_flags = 0;
756 : 0 : struct rtl_hw *hw = rxq->hw;
757 : :
758 [ # # ]: 0 : if (!(rxq->offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM))
759 : 0 : goto exit;
760 : :
761 : : /* RX csum offload for RTL8169*/
762 [ # # ]: 0 : if (rtl_rx_ip_csum(hw, opts1, opts2)) {
763 : : pkt_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
764 [ # # ]: 0 : if (rtl_rx_l4_csum(hw, opts1, opts2))
765 : : pkt_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
766 : : }
767 : :
768 : 0 : exit:
769 : 0 : return pkt_flags;
770 : : }
771 : :
772 : : static u32
773 : : rtl_rx_desc_opts1(struct rtl_hw *hw, struct rtl_rx_desc *desc)
774 : : {
775 : : uint32_t opts1;
776 : :
777 [ # # # # : 0 : switch (hw->HwSuppRxDescType) {
# # ]
778 : 0 : case RX_DESC_RING_TYPE_3:
779 : 0 : opts1 = ((struct rtl_rx_descv3 *)desc)->RxDescNormalDDWord4.opts1;
780 : 0 : break;
781 : 0 : case RX_DESC_RING_TYPE_4:
782 : 0 : opts1 = ((struct rtl_rx_descv4 *)desc)->RxDescNormalDDWord2.opts1;
783 : 0 : break;
784 : 0 : default:
785 : 0 : opts1 = desc->opts1;
786 : 0 : break;
787 : : }
788 : :
789 : : return rte_le_to_cpu_32(opts1);
790 : : }
791 : :
792 : : static u32
793 : : rtl_rx_desc_opts2(struct rtl_hw *hw, struct rtl_rx_desc *desc)
794 : : {
795 : : uint32_t opts2;
796 : :
797 [ # # # # : 0 : switch (hw->HwSuppRxDescType) {
# # ]
798 : 0 : case RX_DESC_RING_TYPE_3:
799 : 0 : opts2 = ((struct rtl_rx_descv3 *)desc)->RxDescNormalDDWord4.opts2;
800 : 0 : break;
801 : 0 : case RX_DESC_RING_TYPE_4:
802 : 0 : opts2 = ((struct rtl_rx_descv4 *)desc)->RxDescNormalDDWord2.opts2;
803 : 0 : break;
804 : 0 : default:
805 : 0 : opts2 = desc->opts2;
806 : 0 : break;
807 : : }
808 : :
809 : : return rte_le_to_cpu_32(opts2);
810 : : }
811 : :
812 : : static u32
813 : : rtl_get_rx_desc_hash(struct rtl_hw *hw, struct rtl_rx_desc *desc)
814 : : {
815 : : u32 rss = 0;
816 : :
817 [ # # # # : 0 : switch (hw->HwSuppRxDescType) {
# # ]
818 : 0 : case RX_DESC_RING_TYPE_3:
819 : 0 : rss = ((struct rtl_rx_descv3 *)desc)->RxDescNormalDDWord2.RSSResult;
820 : 0 : break;
821 : 0 : case RX_DESC_RING_TYPE_4:
822 : 0 : rss = ((struct rtl_rx_descv4 *)desc)->RxDescNormalDDWord1.RSSResult;
823 : 0 : break;
824 : : }
825 : :
826 : : return rte_le_to_cpu_32(rss);
827 : : }
828 : :
829 : : static inline int
830 : : rtl_check_rx_desc_error(struct rtl_hw *hw, uint32_t opts1)
831 : : {
832 [ # # # # : 0 : switch (hw->HwSuppRxDescType) {
# # ]
833 : 0 : case RX_DESC_RING_TYPE_3:
834 : 0 : return (opts1 & RxRES_V3);
835 : 0 : case RX_DESC_RING_TYPE_4:
836 : 0 : return (opts1 & RxRES_V4);
837 : 0 : default:
838 : 0 : return (opts1 & RxRES);
839 : : }
840 : : }
841 : :
842 : : /* PMD receive function */
843 : : uint16_t
844 : 0 : rtl_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
845 : : {
846 : : struct rtl_rx_queue *rxq = (struct rtl_rx_queue *)rx_queue;
847 : 0 : struct rte_eth_dev *dev = &rte_eth_devices[rxq->port_id];
848 : 0 : struct rtl_hw *hw = rxq->hw;
849 : : struct rtl_rx_desc *rxd;
850 : : struct rtl_rx_entry *rxe;
851 : 0 : struct rtl_rx_entry *sw_ring = rxq->sw_ring;
852 : : struct rte_mbuf *new_mb;
853 : : struct rte_mbuf *rmb;
854 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
855 : : struct rtl_sw_stats *stats = &adapter->sw_stats;
856 : : uint16_t nb_rx = 0;
857 : : uint16_t nb_hold = 0;
858 : 0 : uint16_t tail = rxq->rx_tail;
859 : : uint16_t pkt_len = 0;
860 : 0 : const uint16_t nb_rx_desc = rxq->nb_rx_desc;
861 : : uint32_t opts1;
862 : : uint32_t opts2;
863 : : uint64_t dma_addr;
864 : :
865 : : RTE_ASSERT(RTL_R8(hw, ChipCmd) & CmdRxEnb);
866 : :
867 [ # # ]: 0 : while (nb_rx < nb_pkts) {
868 [ # # # ]: 0 : rxd = rtl_get_rxdesc(hw, rxq->hw_ring, tail);
869 : :
870 : : opts1 = rtl_rx_desc_opts1(hw, rxd);
871 [ # # ]: 0 : if (opts1 & DescOwn)
872 : : break;
873 : :
874 : : /*
875 : : * This barrier is needed to keep us from reading
876 : : * any other fields out of the Rx descriptor until
877 : : * we know the status of DescOwn.
878 : : */
879 : : rte_rmb();
880 : :
881 [ # # ]: 0 : if (unlikely(rtl_check_rx_desc_error(hw, opts1))) {
882 : 0 : stats->rx_errors++;
883 : 0 : rtl_mark_to_asic(hw, rxd);
884 : 0 : nb_hold++;
885 : 0 : tail = (tail + 1) % nb_rx_desc;
886 : 0 : continue;
887 : : }
888 : :
889 : : opts2 = rtl_rx_desc_opts2(hw, rxd);
890 : :
891 : 0 : new_mb = rte_mbuf_raw_alloc(rxq->mb_pool);
892 [ # # ]: 0 : if (!new_mb) {
893 : : PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u "
894 : : "queue_id=%u",
895 : : (u32)rxq->port_id, (u32)rxq->queue_id);
896 : 0 : dev->data->rx_mbuf_alloc_failed++;
897 : 0 : break;
898 : : }
899 : :
900 : 0 : nb_hold++;
901 : 0 : rxe = &sw_ring[tail];
902 : :
903 : 0 : rmb = rxe->mbuf;
904 : :
905 : : /* Prefetch next mbufs */
906 : 0 : tail = (tail + 1) % nb_rx_desc;
907 : 0 : rte_prefetch0(sw_ring[tail].mbuf);
908 : :
909 : : /*
910 : : * When next RX descriptor is on a cache-line boundary,
911 : : * prefetch the next 4 RX descriptors and the next 8 pointers
912 : : * to mbufs.
913 : : */
914 [ # # ]: 0 : if ((tail & 0x3) == 0) {
915 : : rte_prefetch0(&sw_ring[tail]);
916 : 0 : rte_prefetch0(rtl_get_rxdesc(hw, rxq->hw_ring, tail));
917 : : }
918 : :
919 : : /* Refill the RX desc */
920 [ # # # ]: 0 : rxe->mbuf = new_mb;
921 : : dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(new_mb));
922 : :
923 : : /* Setup RX descriptor */
924 : : rtl_map_to_asic(hw, rxd, dma_addr);
925 : :
926 : 0 : pkt_len = opts1 & 0x00003fff;
927 : 0 : pkt_len -= RTE_ETHER_CRC_LEN;
928 : :
929 : 0 : rmb->data_off = RTE_PKTMBUF_HEADROOM;
930 : 0 : rte_prefetch1((char *)rmb->buf_addr + rmb->data_off);
931 : 0 : rmb->nb_segs = 1;
932 : 0 : rmb->next = NULL;
933 : 0 : rmb->pkt_len = pkt_len;
934 : 0 : rmb->data_len = pkt_len;
935 : 0 : rmb->port = rxq->port_id;
936 : :
937 [ # # ]: 0 : if (hw->EnableRss)
938 : 0 : rmb->hash.rss = rtl_get_rx_desc_hash(hw, rxd);
939 : :
940 [ # # ]: 0 : if (opts2 & RxVlanTag)
941 [ # # ]: 0 : rmb->vlan_tci = rte_bswap16(opts2 & 0xffff);
942 : :
943 : 0 : rmb->ol_flags = rtl_rx_desc_error_to_pkt_flags(rxq, opts1, opts2);
944 : :
945 : : /*
946 : : * Store the mbuf address into the next entry of the array
947 : : * of returned packets.
948 : : */
949 : 0 : rx_pkts[nb_rx++] = rmb;
950 : :
951 : 0 : stats->rx_bytes += pkt_len;
952 : 0 : stats->rx_packets++;
953 : : }
954 : :
955 : 0 : rxq->rx_tail = tail;
956 : :
957 : 0 : nb_hold = (uint16_t)(nb_hold + rxq->nb_rx_hold);
958 [ # # ]: 0 : if (nb_hold > rxq->rx_free_thresh) {
959 : : rte_wmb();
960 : :
961 : : /* Clear RDU */
962 : 0 : rtl_clear_rdu(hw, rxq->queue_id);
963 : :
964 : : nb_hold = 0;
965 : : }
966 : :
967 : 0 : rxq->nb_rx_hold = nb_hold;
968 : :
969 : 0 : return nb_rx;
970 : : }
971 : :
972 : : static inline int
973 : : rtl_is_non_eop(struct rtl_hw *hw, u32 opts1)
974 : : {
975 [ # # # ]: 0 : switch (hw->HwSuppRxDescType) {
976 : 0 : case RX_DESC_RING_TYPE_3:
977 : 0 : return !(opts1 & LastFrag_V3);
978 : 0 : case RX_DESC_RING_TYPE_4:
979 : 0 : return !(opts1 & LastFrag_V4);
980 : 0 : default:
981 : 0 : return !(opts1 & LastFrag);
982 : : }
983 : : }
984 : :
985 : : /* PMD receive function for scattered pkts */
986 : : uint16_t
987 : 0 : rtl_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
988 : : uint16_t nb_pkts)
989 : : {
990 : : struct rtl_rx_queue *rxq = (struct rtl_rx_queue *)rx_queue;
991 : 0 : struct rte_eth_dev *dev = &rte_eth_devices[rxq->port_id];
992 : 0 : struct rtl_hw *hw = rxq->hw;
993 : : struct rtl_rx_desc *rxd;
994 : : struct rtl_rx_entry *rxe;
995 : 0 : struct rtl_rx_entry *sw_ring = rxq->sw_ring;
996 : : struct rte_mbuf *first_seg;
997 : : struct rte_mbuf *last_seg;
998 : : struct rte_mbuf *new_mb;
999 : : struct rte_mbuf *rmb;
1000 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
1001 : : struct rtl_sw_stats *stats = &adapter->sw_stats;
1002 : : uint16_t nb_rx = 0;
1003 : : uint16_t nb_hold = 0;
1004 : : uint16_t data_len = 0;
1005 : 0 : uint16_t tail = rxq->rx_tail;
1006 : 0 : const uint16_t nb_rx_desc = rxq->nb_rx_desc;
1007 : : uint32_t opts1;
1008 : : uint32_t opts2;
1009 : : uint64_t dma_addr;
1010 : :
1011 : : /*
1012 : : * Retrieve RX context of current packet, if any.
1013 : : */
1014 : 0 : first_seg = rxq->pkt_first_seg;
1015 : 0 : last_seg = rxq->pkt_last_seg;
1016 : :
1017 : : RTE_ASSERT(RTL_R8(hw, ChipCmd) & CmdRxEnb);
1018 : :
1019 [ # # ]: 0 : while (nb_rx < nb_pkts) {
1020 : 0 : next_desc:
1021 [ # # # ]: 0 : rxd = rtl_get_rxdesc(hw, rxq->hw_ring, tail);
1022 : :
1023 : : opts1 = rtl_rx_desc_opts1(hw, rxd);
1024 [ # # ]: 0 : if (opts1 & DescOwn)
1025 : : break;
1026 : :
1027 : : /*
1028 : : * This barrier is needed to keep us from reading
1029 : : * any other fields out of the Rx descriptor until
1030 : : * we know the status of DescOwn.
1031 : : */
1032 : : rte_rmb();
1033 : :
1034 [ # # ]: 0 : if (unlikely(rtl_check_rx_desc_error(hw, opts1))) {
1035 : 0 : stats->rx_errors++;
1036 : 0 : rtl_mark_to_asic(hw, rxd);
1037 : 0 : nb_hold++;
1038 : 0 : tail = (tail + 1) % nb_rx_desc;
1039 : 0 : continue;
1040 : : }
1041 : :
1042 : : opts2 = rtl_rx_desc_opts2(hw, rxd);
1043 : :
1044 : 0 : new_mb = rte_mbuf_raw_alloc(rxq->mb_pool);
1045 [ # # ]: 0 : if (!new_mb) {
1046 : : PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u "
1047 : : "queue_id=%u",
1048 : : (u32)rxq->port_id, (u32)rxq->queue_id);
1049 : 0 : dev->data->rx_mbuf_alloc_failed++;
1050 : 0 : break;
1051 : : }
1052 : :
1053 : 0 : nb_hold++;
1054 : 0 : rxe = &sw_ring[tail];
1055 : :
1056 : 0 : rmb = rxe->mbuf;
1057 : :
1058 : : /* Prefetch next mbufs */
1059 : 0 : tail = (tail + 1) % nb_rx_desc;
1060 : 0 : rte_prefetch0(sw_ring[tail].mbuf);
1061 : :
1062 : : /*
1063 : : * When next RX descriptor is on a cache-line boundary,
1064 : : * prefetch the next 4 RX descriptors and the next 8 pointers
1065 : : * to mbufs.
1066 : : */
1067 [ # # ]: 0 : if ((tail & 0x3) == 0) {
1068 : : rte_prefetch0(&sw_ring[tail]);
1069 : 0 : rte_prefetch0(rtl_get_rxdesc(hw, rxq->hw_ring, tail));
1070 : : }
1071 : :
1072 : : /* Refill the RX desc */
1073 [ # # # ]: 0 : rxe->mbuf = new_mb;
1074 : : dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(new_mb));
1075 : :
1076 : : /* Setup RX descriptor */
1077 : : rtl_map_to_asic(hw, rxd, dma_addr);
1078 : :
1079 : 0 : data_len = opts1 & 0x00003fff;
1080 : 0 : rmb->data_len = data_len;
1081 : 0 : rmb->data_off = RTE_PKTMBUF_HEADROOM;
1082 : :
1083 : : /*
1084 : : * If this is the first buffer of the received packet,
1085 : : * set the pointer to the first mbuf of the packet and
1086 : : * initialize its context.
1087 : : * Otherwise, update the total length and the number of segments
1088 : : * of the current scattered packet, and update the pointer to
1089 : : * the last mbuf of the current packet.
1090 : : */
1091 [ # # ]: 0 : if (!first_seg) {
1092 : : first_seg = rmb;
1093 : 0 : first_seg->pkt_len = data_len;
1094 : 0 : first_seg->nb_segs = 1;
1095 : : } else {
1096 : 0 : first_seg->pkt_len += data_len;
1097 : 0 : first_seg->nb_segs++;
1098 : 0 : last_seg->next = rmb;
1099 : : }
1100 : :
1101 : : /*
1102 : : * If this is not the last buffer of the received packet,
1103 : : * update the pointer to the last mbuf of the current scattered
1104 : : * packet and continue to parse the RX ring.
1105 : : */
1106 [ # # ]: 0 : if (rtl_is_non_eop(hw, opts1)) {
1107 : : last_seg = rmb;
1108 : 0 : goto next_desc;
1109 : : }
1110 : :
1111 : : /*
1112 : : * This is the last buffer of the received packet.
1113 : : */
1114 : 0 : rmb->next = NULL;
1115 : :
1116 : 0 : first_seg->pkt_len -= RTE_ETHER_CRC_LEN;
1117 [ # # ]: 0 : if (data_len <= RTE_ETHER_CRC_LEN) {
1118 : : rte_pktmbuf_free_seg(rmb);
1119 : 0 : first_seg->nb_segs--;
1120 : 0 : last_seg->data_len = last_seg->data_len -
1121 : : (RTE_ETHER_CRC_LEN - data_len);
1122 : 0 : last_seg->next = NULL;
1123 : : } else {
1124 : 0 : rmb->data_len = data_len - RTE_ETHER_CRC_LEN;
1125 : : }
1126 : :
1127 : 0 : first_seg->port = rxq->port_id;
1128 [ # # ]: 0 : if (hw->EnableRss)
1129 : 0 : first_seg->hash.rss = rtl_get_rx_desc_hash(hw, rxd);
1130 : :
1131 [ # # ]: 0 : if (opts2 & RxVlanTag)
1132 [ # # ]: 0 : first_seg->vlan_tci = rte_bswap16(opts2 & 0xffff);
1133 : :
1134 : 0 : first_seg->ol_flags = rtl_rx_desc_error_to_pkt_flags(rxq, opts1, opts2);
1135 : :
1136 : 0 : rte_prefetch1((char *)first_seg->buf_addr + first_seg->data_off);
1137 : :
1138 : : /*
1139 : : * Store the mbuf address into the next entry of the array
1140 : : * of returned packets.
1141 : : */
1142 : 0 : rx_pkts[nb_rx++] = first_seg;
1143 : :
1144 : 0 : stats->rx_bytes += first_seg->pkt_len;
1145 : 0 : stats->rx_packets++;
1146 : :
1147 : : /*
1148 : : * Setup receipt context for a new packet.
1149 : : */
1150 : : first_seg = NULL;
1151 : : }
1152 : :
1153 : : /*
1154 : : * Record index of the next RX descriptor to probe.
1155 : : */
1156 : 0 : rxq->rx_tail = tail;
1157 : :
1158 : : /*
1159 : : * Save receive context.
1160 : : */
1161 : 0 : rxq->pkt_first_seg = first_seg;
1162 : 0 : rxq->pkt_last_seg = last_seg;
1163 : :
1164 : 0 : nb_hold = (uint16_t)(nb_hold + rxq->nb_rx_hold);
1165 [ # # ]: 0 : if (nb_hold > rxq->rx_free_thresh) {
1166 : : rte_wmb();
1167 : :
1168 : : /* Clear RDU */
1169 : 0 : rtl_clear_rdu(hw, rxq->queue_id);
1170 : :
1171 : : nb_hold = 0;
1172 : : }
1173 : :
1174 : 0 : rxq->nb_rx_hold = nb_hold;
1175 : :
1176 : 0 : return nb_rx;
1177 : : }
1178 : :
1179 : : /* ---------------------------------TX---------------------------------- */
1180 : : static void
1181 : 0 : rtl_tx_queue_release_mbufs(struct rtl_tx_queue *txq)
1182 : : {
1183 : : int i;
1184 : :
1185 : 0 : PMD_INIT_FUNC_TRACE();
1186 : :
1187 [ # # ]: 0 : if (txq != NULL) {
1188 [ # # ]: 0 : if (txq->sw_ring != NULL) {
1189 [ # # ]: 0 : for (i = 0; i < txq->nb_tx_desc; i++) {
1190 [ # # ]: 0 : if (txq->sw_ring[i].mbuf != NULL) {
1191 : : rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf);
1192 : 0 : txq->sw_ring[i].mbuf = NULL;
1193 : : }
1194 : : }
1195 : : }
1196 : : }
1197 : 0 : }
1198 : :
1199 : : void
1200 : 0 : rtl_tx_queue_release(struct rte_eth_dev *dev, uint16_t tx_queue_id)
1201 : : {
1202 : 0 : struct rtl_tx_queue *txq = dev->data->tx_queues[tx_queue_id];
1203 : :
1204 : 0 : PMD_INIT_FUNC_TRACE();
1205 : :
1206 [ # # ]: 0 : if (txq != NULL) {
1207 : 0 : rtl_tx_queue_release_mbufs(txq);
1208 : 0 : rte_free(txq->sw_ring);
1209 : 0 : rte_free(txq);
1210 : : }
1211 : 0 : }
1212 : :
1213 : : void
1214 : 0 : rtl_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
1215 : : struct rte_eth_txq_info *qinfo)
1216 : : {
1217 : : struct rtl_tx_queue *txq;
1218 : :
1219 : 0 : txq = dev->data->tx_queues[queue_id];
1220 : :
1221 : 0 : qinfo->nb_desc = txq->nb_tx_desc;
1222 : 0 : }
1223 : :
1224 : : static void
1225 : : rtl_reset_tx_queue(struct rtl_tx_queue *txq)
1226 : : {
1227 : : static const struct rtl_tx_desc zero_txd = {0};
1228 : : int i;
1229 : :
1230 [ # # # # ]: 0 : for (i = 0; i < txq->nb_tx_desc; i++)
1231 : 0 : txq->hw_ring[i] = zero_txd;
1232 : :
1233 : 0 : txq->hw_ring[txq->nb_tx_desc - 1].opts1 = rte_cpu_to_le_32(RingEnd);
1234 : :
1235 : 0 : txq->tx_tail = 0;
1236 : 0 : txq->tx_head = 0;
1237 : 0 : txq->tx_free = txq->nb_tx_desc - 1;
1238 : :
1239 : : /* EnableTxNoClose */
1240 : 0 : txq->NextHwDesCloPtr = 0;
1241 : 0 : txq->BeginHwDesCloPtr = 0;
1242 : : }
1243 : :
1244 : : uint64_t
1245 : 0 : rtl_get_tx_port_offloads(void)
1246 : : {
1247 : : uint64_t tx_offload_capa;
1248 : :
1249 : : tx_offload_capa = RTE_ETH_TX_OFFLOAD_VLAN_INSERT |
1250 : : RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
1251 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
1252 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
1253 : : RTE_ETH_TX_OFFLOAD_TCP_TSO |
1254 : : RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
1255 : :
1256 : 0 : return tx_offload_capa;
1257 : : }
1258 : :
1259 : : int
1260 : 0 : rtl_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
1261 : : uint16_t nb_tx_desc, unsigned int socket_id,
1262 : : const struct rte_eth_txconf *tx_conf)
1263 : : {
1264 : : struct rtl_tx_queue *txq;
1265 : : const struct rte_memzone *mz;
1266 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
1267 : 0 : struct rtl_hw *hw = &adapter->hw;
1268 : : u32 size;
1269 : :
1270 : 0 : PMD_INIT_FUNC_TRACE();
1271 : :
1272 : : /*
1273 : : * If this queue existed already, free the associated memory. The
1274 : : * queue cannot be reused in case we need to allocate memory on
1275 : : * different socket than was previously used.
1276 : : */
1277 [ # # ]: 0 : if (dev->data->tx_queues[queue_idx] != NULL) {
1278 : 0 : rtl_tx_queue_release(dev, queue_idx);
1279 : 0 : dev->data->tx_queues[queue_idx] = NULL;
1280 : : }
1281 : :
1282 : 0 : txq = rte_zmalloc_socket("r8169 TX queue", sizeof(struct rtl_tx_queue),
1283 : : RTE_CACHE_LINE_SIZE, socket_id);
1284 : :
1285 [ # # ]: 0 : if (!txq) {
1286 : 0 : PMD_INIT_LOG(ERR, "Cannot allocate Tx queue structure");
1287 : 0 : return -ENOMEM;
1288 : : }
1289 : :
1290 : : /* Setup queue */
1291 : 0 : txq->nb_tx_desc = nb_tx_desc;
1292 : 0 : txq->port_id = dev->data->port_id;
1293 : 0 : txq->queue_id = queue_idx;
1294 : 0 : txq->tx_free_thresh = tx_conf->tx_free_thresh;
1295 : :
1296 : : /* Allocate memory for the software ring */
1297 : 0 : txq->sw_ring = rte_calloc("r8169 sw tx ring", nb_tx_desc,
1298 : : sizeof(struct rtl_tx_entry), RTE_CACHE_LINE_SIZE);
1299 : :
1300 [ # # ]: 0 : if (txq->sw_ring == NULL) {
1301 : 0 : PMD_INIT_LOG(ERR,
1302 : : "Port %d: Cannot allocate software ring for queue %d",
1303 : : txq->port_id, txq->queue_id);
1304 : 0 : rte_free(txq);
1305 : 0 : return -ENOMEM;
1306 : : }
1307 : :
1308 : : /*
1309 : : * Allocate TX ring hardware descriptors. A memzone large enough to
1310 : : * handle the maximum ring size is allocated in order to allow for
1311 : : * resizing in later calls to the queue setup function.
1312 : : */
1313 : 0 : size = sizeof(struct rtl_tx_desc) * (nb_tx_desc + 1);
1314 : 0 : mz = rte_eth_dma_zone_reserve(dev, "tx_ring", queue_idx, size,
1315 : : RTL_RING_ALIGN, socket_id);
1316 [ # # ]: 0 : if (mz == NULL) {
1317 : 0 : PMD_INIT_LOG(ERR,
1318 : : "Port %d: Cannot allocate hardware ring for queue %d",
1319 : : txq->port_id, txq->queue_id);
1320 : 0 : rtl_tx_queue_release(dev, txq->queue_id);
1321 : 0 : return -ENOMEM;
1322 : : }
1323 : :
1324 : 0 : txq->hw = hw;
1325 : 0 : txq->hw_ring = mz->addr;
1326 : 0 : txq->hw_ring_phys_addr = mz->iova;
1327 : :
1328 : : rtl_reset_tx_queue(txq);
1329 : :
1330 : 0 : dev->data->tx_queues[queue_idx] = txq;
1331 : :
1332 : 0 : return 0;
1333 : : }
1334 : :
1335 : : static void
1336 : 0 : rtl8125_set_tx_tag_num(struct rtl_hw *hw)
1337 : : {
1338 : : u32 mac_ocp_data;
1339 : :
1340 : 0 : mac_ocp_data = rtl_mac_ocp_read(hw, 0xE614);
1341 : 0 : mac_ocp_data &= ~(BIT_10 | BIT_9 | BIT_8);
1342 [ # # # # ]: 0 : switch (hw->mcfg) {
1343 : 0 : case CFG_METHOD_50:
1344 : : case CFG_METHOD_51:
1345 : : case CFG_METHOD_53:
1346 : 0 : mac_ocp_data |= (2 << 8);
1347 : 0 : break;
1348 : 0 : case CFG_METHOD_69:
1349 : : case CFG_METHOD_70:
1350 : : case CFG_METHOD_71:
1351 [ # # ]: 0 : if (hw->EnableTxNoClose)
1352 : 0 : mac_ocp_data |= (4 << 8);
1353 : : else
1354 : 0 : mac_ocp_data |= (3 << 8);
1355 : : break;
1356 : 0 : case CFG_METHOD_91:
1357 : 0 : mac_ocp_data |= (15 << 8);
1358 : 0 : break;
1359 : 0 : default:
1360 : 0 : mac_ocp_data |= (3 << 8);
1361 : 0 : break;
1362 : : }
1363 : 0 : rtl_mac_ocp_write(hw, 0xE614, mac_ocp_data);
1364 : 0 : }
1365 : :
1366 : : /* Set MTPS: Max Tx Pkt Size */
1367 : : static void
1368 : : rtl8168_set_mtps(struct rtl_hw *hw)
1369 : : {
1370 [ # # ]: 0 : if (hw->mtu > RTE_ETHER_MTU)
1371 : 0 : RTL_W8(hw, MTPS, 0x27);
1372 : : else
1373 : 0 : RTL_W8(hw, MTPS, 0x3F);
1374 : : }
1375 : :
1376 : : static void
1377 : 0 : rtl8125_set_tx_q_num(struct rtl_hw *hw, unsigned int num_tx_queues)
1378 : : {
1379 : : u16 mac_ocp_data;
1380 : :
1381 : 0 : mac_ocp_data = rtl_mac_ocp_read(hw, 0xE63E);
1382 [ # # ]: 0 : mac_ocp_data &= ~(BIT_11 | BIT_10);
1383 : 0 : mac_ocp_data |= ((rte_log2_u32(num_tx_queues) & 0x03) << 10);
1384 : 0 : rtl_mac_ocp_write(hw, 0xE63E, mac_ocp_data);
1385 : 0 : }
1386 : :
1387 : : int
1388 : 0 : rtl_tx_init(struct rte_eth_dev *dev)
1389 : : {
1390 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
1391 : 0 : struct rtl_hw *hw = &adapter->hw;
1392 : : struct rtl_tx_queue *txq;
1393 : 0 : u16 nb_tx_queues = dev->data->nb_tx_queues;
1394 : : u16 desc_start_addr_lo[QUEUE_NUM_LIMIT];
1395 : : u16 hw_clo_ptr0_reg, sw_tail_ptr0_reg, reg_len;
1396 : : int i;
1397 : :
1398 : 0 : desc_start_addr_lo[0] = TxDescStartAddrLow;
1399 [ # # ]: 0 : for (i = 1; i < nb_tx_queues; i++)
1400 : 0 : desc_start_addr_lo[i] = (u16)(TNPDS_Q1_LOW_8125 + (i - 1) * 8);
1401 : :
1402 [ # # # ]: 0 : switch (hw->HwSuppTxNoCloseVer) {
1403 : : case 4:
1404 : : case 5:
1405 : : hw_clo_ptr0_reg = HW_CLO_PTR0_8126;
1406 : : sw_tail_ptr0_reg = SW_TAIL_PTR0_8126;
1407 : : reg_len = 4;
1408 : : break;
1409 : 0 : case 6:
1410 : : hw_clo_ptr0_reg = HW_CLO_PTR0_8125BP;
1411 : : sw_tail_ptr0_reg = SW_TAIL_PTR0_8125BP;
1412 : : reg_len = 8;
1413 : 0 : break;
1414 : 0 : default:
1415 : : hw_clo_ptr0_reg = HW_CLO_PTR0_8125;
1416 : : sw_tail_ptr0_reg = SW_TAIL_PTR0_8125;
1417 : : reg_len = 4;
1418 : 0 : break;
1419 : : }
1420 : :
1421 [ # # ]: 0 : for (i = 0; i < nb_tx_queues; i++) {
1422 : 0 : txq = dev->data->tx_queues[i];
1423 : :
1424 : 0 : RTL_W32(hw, desc_start_addr_lo[i],
1425 : : (u64)txq->hw_ring_phys_addr & DMA_BIT_MASK(32));
1426 : 0 : RTL_W32(hw, desc_start_addr_lo[i] + 4,
1427 : : (u64)txq->hw_ring_phys_addr >> 32);
1428 : :
1429 : 0 : txq->hw_clo_ptr_reg = (u16)(hw_clo_ptr0_reg + i * reg_len);
1430 : 0 : txq->sw_tail_ptr_reg = (u16)(sw_tail_ptr0_reg + i * reg_len);
1431 : :
1432 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
1433 : : }
1434 : :
1435 : 0 : rtl_enable_cfg9346_write(hw);
1436 : :
1437 [ # # ]: 0 : if (rtl_is_8125(hw)) {
1438 : 0 : rtl8125_set_tx_tag_num(hw);
1439 : :
1440 : 0 : RTL_W8(hw, TDFNR, 0x10);
1441 : : } else {
1442 : : rtl8168_set_mtps(hw);
1443 : :
1444 : 0 : RTL_W8(hw, TDFNR, 0x4);
1445 : : }
1446 : :
1447 : 0 : rtl_disable_cfg9346_write(hw);
1448 : :
1449 : 0 : rtl8125_set_tx_q_num(hw, nb_tx_queues);
1450 : :
1451 : 0 : RTL_W8(hw, ChipCmd, RTL_R8(hw, ChipCmd) | CmdTxEnb);
1452 : :
1453 : 0 : return 0;
1454 : : }
1455 : :
1456 : : static inline uint32_t
1457 : : rtl_tx_vlan_tag(struct rte_mbuf *tx_pkt, uint64_t ol_flags)
1458 : : {
1459 : 0 : return (ol_flags & RTE_MBUF_F_TX_VLAN) ?
1460 [ # # ]: 0 : (TxVlanTag | rte_bswap16(tx_pkt->vlan_tci)) :
1461 : : 0;
1462 : : }
1463 : :
1464 : : static inline int
1465 : 0 : rtl_tso_setup(struct rte_mbuf *tx_pkt, uint64_t ol_flags, u32 *opts)
1466 : : {
1467 : : uint32_t mss;
1468 : : uint64_t l4_offset;
1469 : :
1470 : : /* Check if TCP segmentation required for this packet */
1471 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) {
1472 : 0 : mss = tx_pkt->tso_segsz;
1473 : 0 : l4_offset = tx_pkt->l2_len + tx_pkt->l3_len;
1474 [ # # ]: 0 : if (l4_offset <= GTTCPHO_MAX) {
1475 : : /* Implies IP cksum in IPv4 */
1476 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
1477 : 0 : opts[0] |= GiantSendv4;
1478 : : else
1479 : 0 : opts[0] |= GiantSendv6;
1480 : :
1481 : 0 : opts[0] |= l4_offset << GTTCPHO_SHIFT;
1482 : 0 : opts[1] |= RTE_MIN(mss, MSS_MAX) << 18;
1483 : :
1484 : 0 : return 1;
1485 : : }
1486 : : }
1487 : :
1488 : : return 0;
1489 : : }
1490 : :
1491 : : static inline void
1492 : 0 : rtl_setup_csum_offload(struct rte_mbuf *tx_pkt, uint64_t ol_flags,
1493 : : uint32_t *opts)
1494 : : {
1495 : : uint32_t csum_cmd = 0;
1496 : : uint64_t l4_offset;
1497 : :
1498 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
1499 : : csum_cmd |= TxIPCS_C;
1500 : :
1501 [ # # # ]: 0 : switch (ol_flags & RTE_MBUF_F_TX_L4_MASK) {
1502 : 0 : case RTE_MBUF_F_TX_UDP_CKSUM:
1503 : 0 : csum_cmd |= TxUDPCS_C;
1504 : 0 : break;
1505 : 0 : case RTE_MBUF_F_TX_TCP_CKSUM:
1506 : 0 : csum_cmd |= TxTCPCS_C;
1507 : 0 : break;
1508 : : }
1509 : :
1510 [ # # ]: 0 : if (csum_cmd != 0) {
1511 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_TX_IPV6) {
1512 : 0 : l4_offset = tx_pkt->l2_len + tx_pkt->l3_len;
1513 : 0 : csum_cmd |= TxIPV6F_C;
1514 : 0 : csum_cmd |= l4_offset << TCPHO_SHIFT;
1515 : : } else {
1516 : 0 : csum_cmd |= TxIPCS_C;
1517 : : }
1518 : 0 : opts[1] |= csum_cmd;
1519 : : }
1520 : 0 : }
1521 : :
1522 : : static uint32_t
1523 : 0 : rtl8125_get_patch_pad_len(struct rte_mbuf *tx_pkt)
1524 : : {
1525 : : uint16_t dest_port;
1526 : : uint32_t pad_len = 0;
1527 : : int udp_hdr_len = sizeof(struct rte_udp_hdr);
1528 : : int trans_data_len, l4_offset;
1529 : : struct rte_udp_hdr *udp_hdr;
1530 : :
1531 [ # # # # ]: 0 : if (!(tx_pkt->l4_len && tx_pkt->data_len < 175))
1532 : 0 : goto no_padding;
1533 : :
1534 : 0 : l4_offset = tx_pkt->l2_len + tx_pkt->l3_len;
1535 : 0 : trans_data_len = tx_pkt->data_len - l4_offset;
1536 : :
1537 [ # # ]: 0 : if (trans_data_len > 3 && trans_data_len < MIN_PATCH_LENGTH) {
1538 : 0 : udp_hdr = rte_pktmbuf_mtod_offset(tx_pkt, struct rte_udp_hdr *, l4_offset);
1539 [ # # ]: 0 : dest_port = ntohs(udp_hdr->dst_port);
1540 [ # # ]: 0 : if (dest_port == 0x13f || dest_port == 0x140) {
1541 : 0 : pad_len = MIN_PATCH_LENGTH - trans_data_len;
1542 : 0 : goto out;
1543 : : }
1544 : : }
1545 : :
1546 [ # # ]: 0 : if (trans_data_len < udp_hdr_len)
1547 : 0 : pad_len = udp_hdr_len - trans_data_len;
1548 : :
1549 : 0 : out:
1550 [ # # ]: 0 : if ((tx_pkt->data_len + pad_len) < ETH_ZLEN)
1551 : 0 : pad_len = ETH_ZLEN - tx_pkt->data_len;
1552 : :
1553 : : return pad_len;
1554 : :
1555 : : no_padding:
1556 : :
1557 : 0 : return 0;
1558 : : }
1559 : :
1560 : : static void
1561 : 0 : rtl8125_ptp_patch(struct rte_mbuf *tx_pkt)
1562 : : {
1563 : : uint32_t pad_len;
1564 : : char *padding;
1565 : :
1566 [ # # ]: 0 : if (tx_pkt->packet_type & RTE_PTYPE_L4_UDP) {
1567 : 0 : pad_len = rtl8125_get_patch_pad_len(tx_pkt);
1568 [ # # ]: 0 : if (pad_len > 0) {
1569 : 0 : padding = rte_pktmbuf_append(tx_pkt, pad_len);
1570 [ # # ]: 0 : if (unlikely(padding == NULL))
1571 : 0 : PMD_DRV_LOG(ERR, "Not enough mbuf trailing space.");
1572 : 0 : memset(padding, 0, pad_len);
1573 : : }
1574 : : }
1575 : 0 : }
1576 : :
1577 : : static inline void
1578 : 0 : rtl_xmit_pkt(struct rtl_hw *hw, struct rtl_tx_queue *txq,
1579 : : struct rte_mbuf *tx_pkt)
1580 : : {
1581 : : struct rte_mbuf *m_seg;
1582 : 0 : struct rte_eth_dev *dev = &rte_eth_devices[txq->port_id];
1583 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
1584 : : struct rtl_sw_stats *stats = &adapter->sw_stats;
1585 : : struct rtl_tx_desc *txd;
1586 : : struct rtl_tx_entry *txe = NULL;
1587 : : uint16_t desc_count = 0;
1588 : 0 : const uint16_t nb_tx_desc = txq->nb_tx_desc;
1589 : : uint16_t tail;
1590 : : u32 len;
1591 : : u32 opts[2] = {0};
1592 : : u32 opts1;
1593 : : u32 opts2;
1594 : : int large_send;
1595 : : uint64_t buf_dma_addr;
1596 : : uint64_t ol_flags;
1597 : : uint64_t tx_ol_flags;
1598 : :
1599 : : /* Like cur_tx */
1600 : 0 : tail = (uint16_t)(txq->tx_tail % nb_tx_desc);
1601 : :
1602 : : /* If hardware offload required */
1603 : 0 : ol_flags = tx_pkt->ol_flags;
1604 : 0 : tx_ol_flags = ol_flags & RTL_TX_OFFLOAD_MASK;
1605 : :
1606 [ # # ]: 0 : opts[0] = DescOwn;
1607 : 0 : opts[1] = rtl_tx_vlan_tag(tx_pkt, tx_ol_flags);
1608 : :
1609 : 0 : large_send = rtl_tso_setup(tx_pkt, tx_ol_flags, opts);
1610 : :
1611 : : /* No TSO */
1612 [ # # ]: 0 : if (large_send == 0) {
1613 : 0 : rtl_setup_csum_offload(tx_pkt, tx_ol_flags, opts);
1614 : :
1615 [ # # ]: 0 : if (hw->mcfg >= CFG_METHOD_48 && hw->mcfg <= CFG_METHOD_53)
1616 : 0 : rtl8125_ptp_patch(tx_pkt);
1617 : : }
1618 : :
1619 [ # # ]: 0 : for (m_seg = tx_pkt; m_seg; m_seg = m_seg->next) {
1620 : 0 : opts1 = opts[0];
1621 : 0 : opts2 = opts[1];
1622 : :
1623 : 0 : len = m_seg->data_len;
1624 : :
1625 [ # # ]: 0 : if (len == 0)
1626 : : break;
1627 : :
1628 [ # # ]: 0 : txd = &txq->hw_ring[tail];
1629 : :
1630 : : buf_dma_addr = rte_mbuf_data_iova(m_seg);
1631 : 0 : txd->addr = rte_cpu_to_le_64(buf_dma_addr);
1632 : :
1633 : 0 : opts1 |= len;
1634 [ # # ]: 0 : if (m_seg == tx_pkt)
1635 : 0 : opts1 |= FirstFrag;
1636 [ # # ]: 0 : if (!m_seg->next)
1637 : 0 : opts1 |= LastFrag;
1638 [ # # ]: 0 : if (tail == nb_tx_desc - 1)
1639 : 0 : opts1 |= RingEnd;
1640 : :
1641 : : /* Store mbuf for freeing later */
1642 : 0 : txe = &txq->sw_ring[tail];
1643 : :
1644 [ # # ]: 0 : if (txe->mbuf)
1645 : : rte_pktmbuf_free_seg(txe->mbuf);
1646 : :
1647 : 0 : txe->mbuf = m_seg;
1648 : :
1649 : 0 : txd->opts2 = rte_cpu_to_le_32(opts2);
1650 : : rte_wmb();
1651 : 0 : txd->opts1 = rte_cpu_to_le_32(opts1);
1652 : :
1653 : 0 : tail = (tail + 1) % nb_tx_desc;
1654 : :
1655 : 0 : desc_count++;
1656 : :
1657 : 0 : stats->tx_bytes += len;
1658 : : }
1659 : :
1660 : 0 : txq->tx_tail += desc_count;
1661 : 0 : txq->tx_free -= desc_count;
1662 : :
1663 : 0 : stats->tx_packets++;
1664 : 0 : }
1665 : :
1666 : : static inline u32
1667 : : rtl_fast_mod_mask(const u32 input, const u32 mask)
1668 : : {
1669 : 0 : return input > mask ? input & mask : input;
1670 : : }
1671 : :
1672 : : static u32
1673 : : rtl_get_hw_clo_ptr(struct rtl_tx_queue *txq)
1674 : : {
1675 : 0 : struct rtl_hw *hw = txq->hw;
1676 : :
1677 [ # # # # : 0 : switch (hw->HwSuppTxNoCloseVer) {
# # ]
1678 : 0 : case 3:
1679 : 0 : return RTL_R16(hw, txq->hw_clo_ptr_reg);
1680 : 0 : case 4:
1681 : : case 5:
1682 : : case 6:
1683 : 0 : return RTL_R32(hw, txq->hw_clo_ptr_reg);
1684 : : default:
1685 : : return 0;
1686 : : }
1687 : : }
1688 : :
1689 : : static u32
1690 : : rtl_get_opts1(struct rtl_tx_desc *txd)
1691 : : {
1692 : 0 : u32 opts1 = rte_atomic_load_explicit(&txd->opts1, rte_memory_order_acquire);
1693 : :
1694 : : return rte_le_to_cpu_32(opts1);
1695 : : }
1696 : :
1697 : : static void
1698 : 0 : rtl8125_tx_clean(struct rtl_hw *hw, struct rtl_tx_queue *txq)
1699 : : {
1700 : 0 : struct rtl_tx_entry *sw_ring = txq->sw_ring;
1701 : : struct rtl_tx_entry *txe;
1702 : : struct rtl_tx_desc *txd;
1703 : 0 : const uint8_t enable_tx_no_close = hw->EnableTxNoClose;
1704 : 0 : const uint16_t nb_tx_desc = txq->nb_tx_desc;
1705 : 0 : uint16_t head = txq->tx_head;
1706 : : uint16_t desc_freed = 0;
1707 : : uint32_t tx_left;
1708 : : uint32_t tx_desc_closed;
1709 : :
1710 [ # # ]: 0 : if (enable_tx_no_close) {
1711 : 0 : txq->NextHwDesCloPtr = rtl_get_hw_clo_ptr(txq);
1712 : 0 : tx_desc_closed = rtl_fast_mod_mask(txq->NextHwDesCloPtr -
1713 [ # # ]: 0 : txq->BeginHwDesCloPtr,
1714 : : hw->MaxTxDescPtrMask);
1715 : 0 : tx_left = RTE_MIN(((rte_atomic_load_explicit(&txq->tx_tail,
1716 : : rte_memory_order_relaxed) % nb_tx_desc) - head),
1717 : : tx_desc_closed);
1718 : 0 : txq->BeginHwDesCloPtr += tx_left;
1719 : : } else {
1720 : 0 : tx_left = (rte_atomic_load_explicit(&txq->tx_tail,
1721 : 0 : rte_memory_order_relaxed) % nb_tx_desc) - head;
1722 : : }
1723 : :
1724 [ # # ]: 0 : while (tx_left > 0) {
1725 : 0 : txd = &txq->hw_ring[head];
1726 : :
1727 [ # # # # ]: 0 : if (!enable_tx_no_close && (rtl_get_opts1(txd) & DescOwn))
1728 : : break;
1729 : :
1730 : 0 : txe = &sw_ring[head];
1731 [ # # ]: 0 : if (txe->mbuf) {
1732 : : rte_pktmbuf_free_seg(txe->mbuf);
1733 : 0 : txe->mbuf = NULL;
1734 : : }
1735 : :
1736 : 0 : head = (head + 1) % nb_tx_desc;
1737 : 0 : desc_freed++;
1738 : 0 : tx_left--;
1739 : : }
1740 : 0 : txq->tx_free += desc_freed;
1741 : 0 : txq->tx_head = head;
1742 : 0 : }
1743 : :
1744 : : static void
1745 : 0 : rtl8168_tx_clean(struct rtl_hw *hw __rte_unused, struct rtl_tx_queue *txq)
1746 : : {
1747 : 0 : struct rtl_tx_entry *sw_ring = txq->sw_ring;
1748 : : struct rtl_tx_entry *txe;
1749 : : struct rtl_tx_desc *txd;
1750 : 0 : const uint16_t nb_tx_desc = txq->nb_tx_desc;
1751 : 0 : const int tx_tail = txq->tx_tail % nb_tx_desc;
1752 : 0 : int head = txq->tx_head;
1753 : : uint16_t desc_freed = 0;
1754 : :
1755 : : while (1) {
1756 : 0 : txd = &txq->hw_ring[head];
1757 : :
1758 [ # # ]: 0 : if (rtl_get_opts1(txd) & DescOwn)
1759 : : break;
1760 : :
1761 : 0 : txe = &sw_ring[head];
1762 [ # # ]: 0 : if (txe->mbuf) {
1763 : : rte_pktmbuf_free_seg(txe->mbuf);
1764 : 0 : txe->mbuf = NULL;
1765 : : }
1766 : :
1767 : 0 : head = (head + 1) % nb_tx_desc;
1768 : 0 : desc_freed++;
1769 : :
1770 [ # # ]: 0 : if (head == tx_tail)
1771 : : break;
1772 : : }
1773 : :
1774 : 0 : txq->tx_free += desc_freed;
1775 : 0 : txq->tx_head = head;
1776 : 0 : }
1777 : :
1778 : : static void
1779 : 0 : rtl_tx_clean(struct rtl_hw *hw, struct rtl_tx_queue *txq)
1780 : : {
1781 [ # # ]: 0 : if (rtl_is_8125(hw))
1782 : 0 : rtl8125_tx_clean(hw, txq);
1783 : : else
1784 : 0 : rtl8168_tx_clean(hw, txq);
1785 : 0 : }
1786 : :
1787 : : static int
1788 : 0 : rtl8125_tx_done_cleanup(void *tx_queue, uint32_t free_cnt)
1789 : : {
1790 : : struct rtl_tx_queue *txq = tx_queue;
1791 : : struct rtl_hw *hw;
1792 : : struct rtl_tx_entry *sw_ring;
1793 : : struct rtl_tx_entry *txe;
1794 : : struct rtl_tx_desc *txd;
1795 : : uint8_t enable_tx_no_close;
1796 : : uint16_t nb_tx_desc;
1797 : : uint16_t head;
1798 : : uint16_t desc_freed = 0;
1799 : : uint32_t tx_left;
1800 : : uint32_t count = 0;
1801 : : uint32_t status;
1802 : : uint32_t tx_desc_closed;
1803 : :
1804 [ # # ]: 0 : if (!txq)
1805 : : return -ENODEV;
1806 : :
1807 : 0 : hw = txq->hw;
1808 : 0 : enable_tx_no_close = hw->EnableTxNoClose;
1809 : 0 : sw_ring = txq->sw_ring;
1810 : 0 : nb_tx_desc = txq->nb_tx_desc;
1811 : 0 : head = txq->tx_head;
1812 : :
1813 [ # # ]: 0 : if (enable_tx_no_close) {
1814 : 0 : txq->NextHwDesCloPtr = rtl_get_hw_clo_ptr(txq);
1815 : 0 : tx_desc_closed = rtl_fast_mod_mask(txq->NextHwDesCloPtr -
1816 [ # # ]: 0 : txq->BeginHwDesCloPtr,
1817 : : hw->MaxTxDescPtrMask);
1818 : 0 : tx_left = RTE_MIN(((rte_atomic_load_explicit(&txq->tx_tail,
1819 : : rte_memory_order_relaxed) % nb_tx_desc) - head),
1820 : : tx_desc_closed);
1821 : 0 : txq->BeginHwDesCloPtr += tx_left;
1822 : : } else {
1823 : 0 : tx_left = (rte_atomic_load_explicit(&txq->tx_tail,
1824 : 0 : rte_memory_order_relaxed) % nb_tx_desc) - head;
1825 : : }
1826 : :
1827 [ # # ]: 0 : while (tx_left > 0) {
1828 : 0 : txd = &txq->hw_ring[head];
1829 : :
1830 : : status = rtl_get_opts1(txd);
1831 : :
1832 [ # # ]: 0 : if (!enable_tx_no_close && (status & DescOwn))
1833 : : break;
1834 : :
1835 : 0 : txe = &sw_ring[head];
1836 [ # # ]: 0 : if (txe->mbuf) {
1837 : : rte_pktmbuf_free_seg(txe->mbuf);
1838 : 0 : txe->mbuf = NULL;
1839 : : }
1840 : :
1841 : 0 : head = (head + 1) % nb_tx_desc;
1842 : :
1843 : 0 : desc_freed++;
1844 : 0 : tx_left--;
1845 : :
1846 [ # # ]: 0 : if (status & LastFrag) {
1847 : 0 : count++;
1848 [ # # ]: 0 : if (count == free_cnt)
1849 : : break;
1850 : : }
1851 : : }
1852 : :
1853 : 0 : txq->tx_free += desc_freed;
1854 : 0 : txq->tx_head = head;
1855 : :
1856 : 0 : return count;
1857 : : }
1858 : :
1859 : : static int
1860 : 0 : rtl8168_tx_done_cleanup(void *tx_queue, uint32_t free_cnt)
1861 : : {
1862 : : struct rtl_tx_queue *txq = tx_queue;
1863 : : struct rtl_tx_entry *sw_ring;
1864 : : struct rtl_tx_entry *txe;
1865 : : struct rtl_tx_desc *txd;
1866 : : uint16_t nb_tx_desc;
1867 : : uint16_t desc_freed = 0;
1868 : : uint32_t status;
1869 : : int tx_tail;
1870 : : int head;
1871 : : int count = 0;
1872 : :
1873 [ # # ]: 0 : if (!txq)
1874 : : return -ENODEV;
1875 : :
1876 : 0 : sw_ring = txq->sw_ring;
1877 : 0 : nb_tx_desc = txq->nb_tx_desc;
1878 : 0 : tx_tail = txq->tx_tail % nb_tx_desc;
1879 : 0 : head = txq->tx_head;
1880 : :
1881 : : while (1) {
1882 : 0 : txd = &txq->hw_ring[head];
1883 : :
1884 : : status = rtl_get_opts1(txd);
1885 : :
1886 [ # # ]: 0 : if (status & DescOwn)
1887 : : break;
1888 : :
1889 : 0 : txe = &sw_ring[head];
1890 [ # # ]: 0 : if (txe->mbuf) {
1891 : : rte_pktmbuf_free_seg(txe->mbuf);
1892 : 0 : txe->mbuf = NULL;
1893 : : }
1894 : :
1895 : 0 : head = (head + 1) % nb_tx_desc;
1896 : 0 : desc_freed++;
1897 : :
1898 [ # # ]: 0 : if (status & LastFrag) {
1899 : 0 : count++;
1900 [ # # ]: 0 : if ((uint32_t)count == free_cnt)
1901 : : break;
1902 : : }
1903 : :
1904 [ # # ]: 0 : if (head == tx_tail)
1905 : : break;
1906 : : }
1907 : :
1908 : 0 : txq->tx_free += desc_freed;
1909 : 0 : txq->tx_head = head;
1910 : :
1911 : 0 : return count;
1912 : : }
1913 : :
1914 : : int
1915 : 0 : rtl_tx_done_cleanup(void *tx_queue, uint32_t free_cnt)
1916 : : {
1917 : : struct rtl_tx_queue *txq = tx_queue;
1918 : 0 : struct rtl_hw *hw = txq->hw;
1919 : :
1920 [ # # ]: 0 : if (rtl_is_8125(hw))
1921 : 0 : return rtl8125_tx_done_cleanup(tx_queue, free_cnt);
1922 : : else
1923 : 0 : return rtl8168_tx_done_cleanup(tx_queue, free_cnt);
1924 : : }
1925 : :
1926 : : static void
1927 : : rtl8125_doorbell(struct rtl_hw *hw, struct rtl_tx_queue *txq)
1928 : : {
1929 [ # # ]: 0 : if (hw->EnableTxNoClose)
1930 [ # # ]: 0 : if (hw->HwSuppTxNoCloseVer > 3)
1931 : 0 : RTL_W32(hw, txq->sw_tail_ptr_reg, txq->tx_tail);
1932 : : else
1933 : 0 : RTL_W16(hw, txq->sw_tail_ptr_reg, txq->tx_tail);
1934 : : else
1935 : 0 : RTL_W16(hw, TPPOLL_8125, BIT_0);
1936 : : }
1937 : :
1938 : : static void
1939 : : rtl8168_doorbell(struct rtl_hw *hw)
1940 : : {
1941 : 0 : RTL_W8(hw, TxPoll, NPQ);
1942 : 0 : }
1943 : :
1944 : : static void
1945 : 0 : rtl_doorbell(struct rtl_hw *hw, struct rtl_tx_queue *txq)
1946 : : {
1947 [ # # ]: 0 : if (rtl_is_8125(hw))
1948 : : rtl8125_doorbell(hw, txq);
1949 : : else
1950 : : rtl8168_doorbell(hw);
1951 : 0 : }
1952 : :
1953 : : /* PMD transmit function */
1954 : : uint16_t
1955 : 0 : rtl_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
1956 : : {
1957 : : struct rtl_tx_queue *txq = tx_queue;
1958 : 0 : struct rtl_hw *hw = txq->hw;
1959 : : struct rte_mbuf *tx_pkt;
1960 : : uint16_t nb_tx;
1961 : :
1962 : : RTE_ASSERT(RTL_R8(hw, ChipCmd) & CmdTxEnb);
1963 : :
1964 : : PMD_TX_LOG(DEBUG,
1965 : : "port %d txq %d pkts: %d tx_free=%d tx_tail=%d tx_head=%d",
1966 : : txq->port_id, txq->queue_id, nb_pkts, txq->tx_free,
1967 : : txq->tx_tail, txq->tx_head);
1968 : :
1969 [ # # ]: 0 : for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
1970 : 0 : tx_pkt = *tx_pkts++;
1971 : :
1972 [ # # ]: 0 : if (txq->tx_free < tx_pkt->nb_segs)
1973 : : break;
1974 : :
1975 : : /* Check mbuf is valid */
1976 [ # # # # : 0 : if (tx_pkt->nb_segs == 0 || tx_pkt->pkt_len == 0 ||
# # ]
1977 [ # # ]: 0 : (tx_pkt->nb_segs > 1 && tx_pkt->next == NULL))
1978 : : break;
1979 : :
1980 : 0 : rtl_xmit_pkt(hw, txq, tx_pkt);
1981 : : }
1982 : :
1983 : : rte_wmb();
1984 : :
1985 [ # # ]: 0 : if (nb_tx > 0)
1986 : 0 : rtl_doorbell(hw, txq);
1987 : :
1988 : : PMD_TX_LOG(DEBUG, "%s %d transmitted", __func__, nb_tx);
1989 : :
1990 : 0 : rtl_tx_clean(hw, txq);
1991 : :
1992 : 0 : return nb_tx;
1993 : : }
1994 : :
1995 : : int
1996 : 0 : rtl_stop_queues(struct rte_eth_dev *dev)
1997 : : {
1998 : : struct rtl_tx_queue *txq;
1999 : : struct rtl_rx_queue *rxq;
2000 : : int i;
2001 : :
2002 : 0 : PMD_INIT_FUNC_TRACE();
2003 : :
2004 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
2005 : 0 : txq = dev->data->tx_queues[i];
2006 : :
2007 : 0 : rtl_tx_queue_release_mbufs(txq);
2008 : : rtl_reset_tx_queue(txq);
2009 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
2010 : : }
2011 : :
2012 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
2013 : 0 : rxq = dev->data->rx_queues[i];
2014 : :
2015 : 0 : rtl_rx_queue_release_mbufs(rxq);
2016 : 0 : rtl_reset_rx_queue(rxq);
2017 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
2018 : : }
2019 : 0 : return 0;
2020 : : }
2021 : :
2022 : : void
2023 : 0 : rtl_free_queues(struct rte_eth_dev *dev)
2024 : : {
2025 : : int i;
2026 : :
2027 : 0 : PMD_INIT_FUNC_TRACE();
2028 : :
2029 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
2030 : 0 : rte_eth_dma_zone_free(dev, "tx_ring", i);
2031 : 0 : rtl_tx_queue_release(dev, i);
2032 : 0 : dev->data->tx_queues[i] = 0;
2033 : : }
2034 : 0 : dev->data->nb_tx_queues = 0;
2035 : :
2036 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
2037 : 0 : rte_eth_dma_zone_free(dev, "rx_ring", i);
2038 : 0 : rtl_rx_queue_release(dev, i);
2039 : 0 : dev->data->rx_queues[i] = 0;
2040 : : }
2041 : 0 : dev->data->nb_rx_queues = 0;
2042 : 0 : }
|