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 : : /* Struct TxDesc in kernel r8169 */
40 : : struct rtl_tx_desc {
41 : : u32 opts1;
42 : : u32 opts2;
43 : : u64 addr;
44 : : u32 reserved0;
45 : : u32 reserved1;
46 : : u32 reserved2;
47 : : u32 reserved3;
48 : : };
49 : :
50 : : /* Struct RxDesc in kernel r8169 */
51 : : struct rtl_rx_desc {
52 : : u32 opts1;
53 : : u32 opts2;
54 : : u64 addr;
55 : : };
56 : :
57 : : /* Structure associated with each descriptor of the TX ring of a TX queue. */
58 : : struct rtl_tx_entry {
59 : : struct rte_mbuf *mbuf;
60 : : };
61 : :
62 : : /* Structure associated with each descriptor of the RX ring of a RX queue. */
63 : : struct rtl_rx_entry {
64 : : struct rte_mbuf *mbuf;
65 : : };
66 : :
67 : : /* Structure associated with each TX queue. */
68 : : struct rtl_tx_queue {
69 : : struct rtl_tx_desc *hw_ring;
70 : : struct rtl_tx_entry *sw_ring;
71 : : struct rtl_hw *hw;
72 : : uint64_t hw_ring_phys_addr;
73 : : uint16_t nb_tx_desc;
74 : : RTE_ATOMIC(uint32_t) tx_tail;
75 : : uint16_t tx_head;
76 : : uint16_t queue_id;
77 : : uint16_t port_id;
78 : : uint16_t tx_free_thresh;
79 : : uint16_t tx_free;
80 : : };
81 : :
82 : : /* Structure associated with each RX queue. */
83 : : struct rtl_rx_queue {
84 : : struct rte_mempool *mb_pool;
85 : : struct rtl_rx_desc *hw_ring;
86 : : struct rtl_rx_entry *sw_ring;
87 : : struct rte_mbuf *pkt_first_seg; /* First segment of current packet. */
88 : : struct rte_mbuf *pkt_last_seg; /* Last segment of current packet. */
89 : : struct rtl_hw *hw;
90 : : uint64_t hw_ring_phys_addr;
91 : : uint64_t offloads;
92 : : uint16_t nb_rx_desc;
93 : : uint16_t rx_tail;
94 : : uint16_t nb_rx_hold;
95 : : uint16_t queue_id;
96 : : uint16_t port_id;
97 : : uint16_t rx_free_thresh;
98 : : };
99 : :
100 : : enum _DescStatusBit {
101 : : DescOwn = (1 << 31), /* Descriptor is owned by NIC. */
102 : : RingEnd = (1 << 30), /* End of descriptor ring */
103 : : FirstFrag = (1 << 29), /* First segment of a packet */
104 : : LastFrag = (1 << 28), /* Final segment of a packet */
105 : :
106 : : DescOwn_V3 = DescOwn, /* Descriptor is owned by NIC. */
107 : : RingEnd_V3 = RingEnd, /* End of descriptor ring */
108 : : FirstFrag_V3 = (1 << 25), /* First segment of a packet */
109 : : LastFrag_V3 = (1 << 24), /* 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 : : /*@@@@@@ offset 4 of RX descriptor => bits for RTL8169 only end @@@@@@*/
180 : : };
181 : :
182 : : #define GTTCPHO_SHIFT 18
183 : : #define GTTCPHO_MAX 0x70U
184 : : #define GTPKTSIZE_MAX 0x3ffffU
185 : : #define TCPHO_SHIFT 18
186 : : #define TCPHO_MAX 0x3ffU
187 : : #define LSOPKTSIZE_MAX 0xffffU
188 : : #define MSS_MAX 0x07ffu /* MSS value */
189 : :
190 : : /* ---------------------------------RX---------------------------------- */
191 : :
192 : : static void
193 : 0 : rtl_rx_queue_release_mbufs(struct rtl_rx_queue *rxq)
194 : : {
195 : : int i;
196 : :
197 : 0 : PMD_INIT_FUNC_TRACE();
198 : :
199 [ # # ]: 0 : if (rxq != NULL) {
200 [ # # ]: 0 : if (rxq->sw_ring != NULL) {
201 [ # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc; i++) {
202 [ # # ]: 0 : if (rxq->sw_ring[i].mbuf != NULL) {
203 : : rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf);
204 : 0 : rxq->sw_ring[i].mbuf = NULL;
205 : : }
206 : : }
207 : : }
208 : : }
209 : 0 : }
210 : :
211 : : void
212 : 0 : rtl_rx_queue_release(struct rte_eth_dev *dev, uint16_t rx_queue_id)
213 : : {
214 : 0 : struct rtl_rx_queue *rxq = dev->data->rx_queues[rx_queue_id];
215 : :
216 : 0 : PMD_INIT_FUNC_TRACE();
217 : :
218 [ # # ]: 0 : if (rxq != NULL) {
219 : 0 : rtl_rx_queue_release_mbufs(rxq);
220 : 0 : rte_free(rxq->sw_ring);
221 : 0 : rte_free(rxq);
222 : : }
223 : 0 : }
224 : :
225 : : void
226 : 0 : rtl_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
227 : : struct rte_eth_rxq_info *qinfo)
228 : : {
229 : : struct rtl_rx_queue *rxq;
230 : :
231 : 0 : rxq = dev->data->rx_queues[queue_id];
232 : :
233 : 0 : qinfo->mp = rxq->mb_pool;
234 : 0 : qinfo->scattered_rx = dev->data->scattered_rx;
235 : 0 : qinfo->nb_desc = rxq->nb_rx_desc;
236 : :
237 : 0 : qinfo->conf.rx_free_thresh = rxq->rx_free_thresh;
238 : 0 : qinfo->conf.offloads = rxq->offloads;
239 : 0 : }
240 : :
241 : : static void
242 : : rtl_reset_rx_queue(struct rtl_rx_queue *rxq)
243 : : {
244 : : static const struct rtl_rx_desc zero_rxd = {0};
245 : : int i;
246 : :
247 [ # # # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc; i++)
248 : 0 : rxq->hw_ring[i] = zero_rxd;
249 : :
250 : 0 : rxq->hw_ring[rxq->nb_rx_desc - 1].opts1 = rte_cpu_to_le_32(RingEnd);
251 : 0 : rxq->rx_tail = 0;
252 : 0 : rxq->pkt_first_seg = NULL;
253 : 0 : rxq->pkt_last_seg = NULL;
254 : : }
255 : :
256 : : uint64_t
257 : 0 : rtl_get_rx_port_offloads(void)
258 : : {
259 : : uint64_t offloads;
260 : :
261 : : offloads = RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
262 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
263 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
264 : : RTE_ETH_RX_OFFLOAD_SCATTER |
265 : : RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
266 : :
267 : 0 : return offloads;
268 : : }
269 : :
270 : : int
271 : 0 : rtl_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
272 : : uint16_t nb_rx_desc, unsigned int socket_id,
273 : : const struct rte_eth_rxconf *rx_conf,
274 : : struct rte_mempool *mb_pool)
275 : : {
276 : : struct rtl_rx_queue *rxq;
277 : : const struct rte_memzone *mz;
278 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
279 : 0 : struct rtl_hw *hw = &adapter->hw;
280 : : uint32_t size;
281 : :
282 : 0 : PMD_INIT_FUNC_TRACE();
283 : :
284 : : /*
285 : : * If this queue existed already, free the associated memory. The
286 : : * queue cannot be reused in case we need to allocate memory on
287 : : * different socket than was previously used.
288 : : */
289 [ # # ]: 0 : if (dev->data->rx_queues[queue_idx] != NULL) {
290 : 0 : rtl_rx_queue_release(dev, queue_idx);
291 : 0 : dev->data->rx_queues[queue_idx] = NULL;
292 : : }
293 : :
294 : : /* First allocate the rx queue data structure */
295 : 0 : rxq = rte_zmalloc_socket("r8169 RX queue", sizeof(struct rtl_rx_queue),
296 : : RTE_CACHE_LINE_SIZE, socket_id);
297 : :
298 [ # # ]: 0 : if (rxq == NULL) {
299 : 0 : PMD_INIT_LOG(ERR, "Cannot allocate Rx queue structure");
300 : 0 : return -ENOMEM;
301 : : }
302 : :
303 : : /* Setup queue */
304 : 0 : rxq->mb_pool = mb_pool;
305 : 0 : rxq->nb_rx_desc = nb_rx_desc;
306 : 0 : rxq->port_id = dev->data->port_id;
307 : 0 : rxq->queue_id = queue_idx;
308 : 0 : rxq->rx_free_thresh = rx_conf->rx_free_thresh;
309 : :
310 : : /* Allocate memory for the software ring */
311 : 0 : rxq->sw_ring = rte_calloc("r8169 sw rx ring", nb_rx_desc,
312 : : sizeof(struct rtl_rx_entry), RTE_CACHE_LINE_SIZE);
313 : :
314 [ # # ]: 0 : if (rxq->sw_ring == NULL) {
315 : 0 : PMD_INIT_LOG(ERR,
316 : : "Port %d: Cannot allocate software ring for queue %d",
317 : : rxq->port_id, rxq->queue_id);
318 : 0 : rte_free(rxq);
319 : 0 : return -ENOMEM;
320 : : }
321 : :
322 : : /*
323 : : * Allocate RX ring hardware descriptors. A memzone large enough to
324 : : * handle the maximum ring size is allocated in order to allow for
325 : : * resizing in later calls to the queue setup function.
326 : : */
327 : 0 : size = sizeof(struct rtl_rx_desc) * (nb_rx_desc + 1);
328 : 0 : mz = rte_eth_dma_zone_reserve(dev, "rx_ring", queue_idx, size,
329 : : RTL_RING_ALIGN, socket_id);
330 [ # # ]: 0 : if (mz == NULL) {
331 : 0 : PMD_INIT_LOG(ERR,
332 : : "Port %d: Cannot allocate software ring for queue %d",
333 : : rxq->port_id, rxq->queue_id);
334 : 0 : rtl_rx_queue_release(dev, rxq->queue_id);
335 : 0 : return -ENOMEM;
336 : : }
337 : :
338 : 0 : rxq->hw = hw;
339 : 0 : rxq->hw_ring = mz->addr;
340 : 0 : rxq->hw_ring_phys_addr = mz->iova;
341 : 0 : rxq->offloads = rx_conf->offloads | dev->data->dev_conf.rxmode.offloads;
342 : :
343 : : rtl_reset_rx_queue(rxq);
344 : :
345 : 0 : dev->data->rx_queues[queue_idx] = rxq;
346 : :
347 : 0 : return 0;
348 : : }
349 : :
350 : : static int
351 : 0 : rtl_alloc_rx_queue_mbufs(struct rtl_rx_queue *rxq)
352 : : {
353 : 0 : struct rtl_rx_entry *rxe = rxq->sw_ring;
354 : 0 : struct rtl_hw *hw = rxq->hw;
355 : : struct rtl_rx_desc *rxd;
356 : : int i;
357 : : uint64_t dma_addr;
358 : :
359 : 0 : rxd = &rxq->hw_ring[0];
360 : :
361 : : /* Initialize software ring entries */
362 [ # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc; i++) {
363 : 0 : struct rte_mbuf *mbuf = rte_mbuf_raw_alloc(rxq->mb_pool);
364 : :
365 [ # # ]: 0 : if (mbuf == NULL) {
366 : 0 : PMD_INIT_LOG(ERR, "RX mbuf alloc failed queue_id=%hu",
367 : : rxq->queue_id);
368 : 0 : return -ENOMEM;
369 : : }
370 : :
371 : : dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(mbuf));
372 : :
373 : 0 : rxd = &rxq->hw_ring[i];
374 : 0 : rxd->addr = dma_addr;
375 : 0 : rxd->opts2 = 0;
376 : : rte_wmb();
377 : 0 : rxd->opts1 = rte_cpu_to_le_32(DescOwn | hw->rx_buf_sz);
378 : 0 : rxe[i].mbuf = mbuf;
379 : : }
380 : :
381 : : /* Mark as last desc */
382 : 0 : rxd->opts1 |= rte_cpu_to_le_32(RingEnd);
383 : :
384 : 0 : return 0;
385 : : }
386 : :
387 : : static int
388 : 0 : rtl_hw_set_features(struct rtl_hw *hw, uint64_t offloads)
389 : : {
390 : : u16 cp_cmd;
391 : : u32 rx_config;
392 : :
393 : 0 : rx_config = RTL_R32(hw, RxConfig);
394 [ # # ]: 0 : if (offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
395 : 0 : rx_config |= (EnableInnerVlan | EnableOuterVlan);
396 : : else
397 : 0 : rx_config &= ~(EnableInnerVlan | EnableOuterVlan);
398 : :
399 : 0 : RTL_W32(hw, RxConfig, rx_config);
400 : :
401 : 0 : cp_cmd = RTL_R16(hw, CPlusCmd);
402 : :
403 [ # # ]: 0 : if (offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM)
404 : 0 : cp_cmd |= RxChkSum;
405 : : else
406 : 0 : cp_cmd &= ~RxChkSum;
407 : :
408 : 0 : RTL_W16(hw, CPlusCmd, cp_cmd);
409 : :
410 : 0 : return 0;
411 : : }
412 : :
413 : : static void
414 : : rtl_hw_set_rx_packet_filter(struct rtl_hw *hw)
415 : : {
416 : : int rx_mode;
417 : :
418 : 0 : hw->hw_ops.hw_init_rxcfg(hw);
419 : :
420 : : rx_mode = AcceptBroadcast | AcceptMyPhys;
421 : 0 : RTL_W32(hw, RxConfig, rx_mode | (RTL_R32(hw, RxConfig)));
422 : : }
423 : :
424 : : int
425 : 0 : rtl_rx_init(struct rte_eth_dev *dev)
426 : : {
427 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
428 : 0 : struct rtl_hw *hw = &adapter->hw;
429 : : struct rtl_rx_queue *rxq;
430 : : int ret;
431 : : u32 max_rx_pkt_size;
432 : :
433 : 0 : rxq = dev->data->rx_queues[0];
434 : :
435 [ # # ]: 0 : if (rxq->mb_pool == NULL) {
436 : 0 : PMD_INIT_LOG(ERR, "r8169 rx queue pool not setup!");
437 : 0 : return -ENOMEM;
438 : : }
439 : :
440 : 0 : RTL_W32(hw, RxDescAddrLow, ((u64)rxq->hw_ring_phys_addr & DMA_BIT_MASK(32)));
441 : 0 : RTL_W32(hw, RxDescAddrHigh, ((u64)rxq->hw_ring_phys_addr >> 32));
442 : :
443 : 0 : dev->rx_pkt_burst = rtl_recv_pkts;
444 [ # # ]: 0 : hw->rx_buf_sz = rte_pktmbuf_data_room_size(rxq->mb_pool) - RTE_PKTMBUF_HEADROOM;
445 : :
446 : 0 : max_rx_pkt_size = dev->data->mtu + RTL_ETH_OVERHEAD;
447 : :
448 [ # # # # ]: 0 : if (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_SCATTER ||
449 : : max_rx_pkt_size > hw->rx_buf_sz) {
450 [ # # ]: 0 : if (!dev->data->scattered_rx)
451 : 0 : PMD_INIT_LOG(DEBUG, "forcing scatter mode");
452 : 0 : dev->rx_pkt_burst = rtl_recv_scattered_pkts;
453 : 0 : dev->data->scattered_rx = 1;
454 : : }
455 : :
456 : 0 : RTL_W16(hw, RxMaxSize, max_rx_pkt_size);
457 : :
458 : 0 : ret = rtl_alloc_rx_queue_mbufs(rxq);
459 [ # # ]: 0 : if (ret) {
460 : 0 : PMD_INIT_LOG(ERR, "r8169 rx mbuf alloc failed!");
461 : 0 : return ret;
462 : : }
463 : :
464 : 0 : rtl_enable_cfg9346_write(hw);
465 : :
466 : : /* RX accept type and csum vlan offload */
467 : 0 : rtl_hw_set_features(hw, rxq->offloads);
468 : :
469 : 0 : rtl_disable_rxdvgate(hw);
470 : :
471 : : /* Set Rx packet filter */
472 : : rtl_hw_set_rx_packet_filter(hw);
473 : :
474 : 0 : rtl_disable_cfg9346_write(hw);
475 : :
476 : 0 : RTL_W8(hw, ChipCmd, RTL_R8(hw, ChipCmd) | CmdRxEnb);
477 : :
478 : 0 : dev->data->rx_queue_state[0] = RTE_ETH_QUEUE_STATE_STARTED;
479 : :
480 : 0 : return 0;
481 : : }
482 : :
483 : : static inline void
484 : : rtl_mark_to_asic(struct rtl_rx_desc *rxd, u32 size)
485 : : {
486 : 0 : u32 eor = rte_le_to_cpu_32(rxd->opts1) & RingEnd;
487 : :
488 : 0 : rxd->opts1 = rte_cpu_to_le_32(DescOwn | eor | size);
489 : : }
490 : :
491 : : static inline uint64_t
492 : : rtl_rx_desc_error_to_pkt_flags(struct rtl_rx_queue *rxq, uint32_t opts1,
493 : : uint32_t opts2)
494 : : {
495 : : uint64_t pkt_flags = 0;
496 : :
497 [ # # # # ]: 0 : if (!(rxq->offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM))
498 : 0 : goto exit;
499 : :
500 : : /* RX csum offload for RTL8169*/
501 [ # # # # : 0 : if (((opts2 & RxV4F) && !(opts1 & RxIPF)) || (opts2 & RxV6F)) {
# # # # #
# # # ]
502 : : pkt_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
503 [ # # # # ]: 0 : if (((opts1 & RxTCPT) && !(opts1 & RxTCPF)) ||
504 [ # # # # ]: 0 : ((opts1 & RxUDPT) && !(opts1 & RxUDPF)))
505 : : pkt_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
506 : : }
507 : :
508 : 0 : exit:
509 : : return pkt_flags;
510 : : }
511 : :
512 : : /* PMD receive function */
513 : : uint16_t
514 : 0 : rtl_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
515 : : {
516 : : struct rtl_rx_queue *rxq = (struct rtl_rx_queue *)rx_queue;
517 : 0 : struct rte_eth_dev *dev = &rte_eth_devices[rxq->port_id];
518 : 0 : struct rtl_hw *hw = rxq->hw;
519 : : struct rtl_rx_desc *rxd;
520 : : struct rtl_rx_desc *hw_ring;
521 : : struct rtl_rx_entry *rxe;
522 : 0 : struct rtl_rx_entry *sw_ring = rxq->sw_ring;
523 : : struct rte_mbuf *new_mb;
524 : : struct rte_mbuf *rmb;
525 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
526 : : struct rtl_sw_stats *stats = &adapter->sw_stats;
527 : : uint16_t nb_rx = 0;
528 : : uint16_t nb_hold = 0;
529 : 0 : uint16_t tail = rxq->rx_tail;
530 : 0 : const uint16_t nb_rx_desc = rxq->nb_rx_desc;
531 : : uint32_t opts1;
532 : : uint32_t opts2;
533 : : uint16_t pkt_len = 0;
534 : : uint64_t dma_addr;
535 : :
536 : 0 : hw_ring = rxq->hw_ring;
537 : :
538 : : RTE_ASSERT(RTL_R8(hw, ChipCmd) & CmdRxEnb);
539 : :
540 [ # # ]: 0 : while (nb_rx < nb_pkts) {
541 : 0 : rxd = &hw_ring[tail];
542 : :
543 : 0 : opts1 = rte_le_to_cpu_32(rxd->opts1);
544 [ # # ]: 0 : if (opts1 & DescOwn)
545 : : break;
546 : :
547 : : /*
548 : : * This barrier is needed to keep us from reading
549 : : * any other fields out of the Rx descriptor until
550 : : * we know the status of DescOwn.
551 : : */
552 : : rte_rmb();
553 : :
554 [ # # ]: 0 : if (unlikely(opts1 & RxRES)) {
555 : 0 : stats->rx_errors++;
556 : 0 : rtl_mark_to_asic(rxd, hw->rx_buf_sz);
557 : 0 : nb_hold++;
558 : 0 : tail = (tail + 1) % nb_rx_desc;
559 : : } else {
560 : 0 : opts2 = rte_le_to_cpu_32(rxd->opts2);
561 : :
562 : 0 : new_mb = rte_mbuf_raw_alloc(rxq->mb_pool);
563 [ # # ]: 0 : if (new_mb == NULL) {
564 : : PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u "
565 : : "queue_id=%u",
566 : : (uint32_t)rxq->port_id, (uint32_t)rxq->queue_id);
567 : 0 : dev->data->rx_mbuf_alloc_failed++;
568 : 0 : break;
569 : : }
570 : :
571 : 0 : nb_hold++;
572 : 0 : rxe = &sw_ring[tail];
573 : :
574 : 0 : rmb = rxe->mbuf;
575 : :
576 : 0 : tail = (tail + 1) % nb_rx_desc;
577 : :
578 : : /* Prefetch next mbufs */
579 : 0 : rte_prefetch0(sw_ring[tail].mbuf);
580 : :
581 : : /*
582 : : * When next RX descriptor is on a cache-line boundary,
583 : : * prefetch the next 4 RX descriptors and the next 8 pointers
584 : : * to mbufs.
585 : : */
586 [ # # ]: 0 : if ((tail & 0x3) == 0) {
587 : : rte_prefetch0(&sw_ring[tail]);
588 : 0 : rte_prefetch0(&hw_ring[tail]);
589 : : }
590 : :
591 : : /* Refill the RX desc */
592 : 0 : rxe->mbuf = new_mb;
593 : : dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(new_mb));
594 : :
595 : : /* Setup RX descriptor */
596 : 0 : rxd->addr = dma_addr;
597 : 0 : rxd->opts2 = 0;
598 : : rte_wmb();
599 : 0 : rtl_mark_to_asic(rxd, hw->rx_buf_sz);
600 : :
601 : 0 : pkt_len = opts1 & 0x00003fff;
602 : 0 : pkt_len -= RTE_ETHER_CRC_LEN;
603 : :
604 : 0 : rmb->data_off = RTE_PKTMBUF_HEADROOM;
605 : 0 : rte_prefetch1((char *)rmb->buf_addr + rmb->data_off);
606 : 0 : rmb->nb_segs = 1;
607 : 0 : rmb->next = NULL;
608 : 0 : rmb->pkt_len = pkt_len;
609 : 0 : rmb->data_len = pkt_len;
610 : 0 : rmb->port = rxq->port_id;
611 : :
612 [ # # ]: 0 : if (opts2 & RxVlanTag)
613 [ # # ]: 0 : rmb->vlan_tci = rte_bswap16(opts2 & 0xffff);
614 : :
615 : 0 : rmb->ol_flags = rtl_rx_desc_error_to_pkt_flags(rxq, opts1, opts2);
616 : :
617 : : /*
618 : : * Store the mbuf address into the next entry of the array
619 : : * of returned packets.
620 : : */
621 : 0 : rx_pkts[nb_rx++] = rmb;
622 : :
623 : 0 : stats->rx_bytes += pkt_len;
624 : 0 : stats->rx_packets++;
625 : : }
626 : : }
627 : :
628 : 0 : rxq->rx_tail = tail;
629 : :
630 : 0 : nb_hold = (uint16_t)(nb_hold + rxq->nb_rx_hold);
631 [ # # ]: 0 : if (nb_hold > rxq->rx_free_thresh) {
632 : : rte_wmb();
633 : :
634 : : /* Clear RDU */
635 : 0 : RTL_W32(hw, ISR0_8125, (RxOK | RxErr | RxDescUnavail));
636 : :
637 : : nb_hold = 0;
638 : : }
639 : :
640 : 0 : rxq->nb_rx_hold = nb_hold;
641 : :
642 : 0 : return nb_rx;
643 : : }
644 : :
645 : : /* PMD receive function for scattered pkts */
646 : : uint16_t
647 : 0 : rtl_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
648 : : uint16_t nb_pkts)
649 : : {
650 : : struct rtl_rx_queue *rxq = (struct rtl_rx_queue *)rx_queue;
651 : 0 : struct rte_eth_dev *dev = &rte_eth_devices[rxq->port_id];
652 : 0 : struct rtl_hw *hw = rxq->hw;
653 : : struct rtl_rx_desc *rxd;
654 : : struct rtl_rx_desc *hw_ring;
655 : : struct rtl_rx_entry *rxe;
656 : 0 : struct rtl_rx_entry *sw_ring = rxq->sw_ring;
657 : : struct rte_mbuf *first_seg;
658 : : struct rte_mbuf *last_seg;
659 : : struct rte_mbuf *new_mb;
660 : : struct rte_mbuf *rmb;
661 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
662 : : struct rtl_sw_stats *stats = &adapter->sw_stats;
663 : : uint16_t nb_rx = 0;
664 : : uint16_t nb_hold = 0;
665 : : uint16_t data_len = 0;
666 : 0 : uint16_t tail = rxq->rx_tail;
667 : 0 : const uint16_t nb_rx_desc = rxq->nb_rx_desc;
668 : : uint32_t opts1;
669 : : uint32_t opts2;
670 : : uint64_t dma_addr;
671 : :
672 : 0 : hw_ring = rxq->hw_ring;
673 : :
674 : : /*
675 : : * Retrieve RX context of current packet, if any.
676 : : */
677 : 0 : first_seg = rxq->pkt_first_seg;
678 : 0 : last_seg = rxq->pkt_last_seg;
679 : :
680 : : RTE_ASSERT(RTL_R8(hw, ChipCmd) & CmdRxEnb);
681 : :
682 [ # # ]: 0 : while (nb_rx < nb_pkts) {
683 : 0 : next_desc:
684 : 0 : rxd = &hw_ring[tail];
685 : :
686 : 0 : opts1 = rte_le_to_cpu_32(rxd->opts1);
687 [ # # ]: 0 : if (opts1 & DescOwn)
688 : : break;
689 : :
690 : : /*
691 : : * This barrier is needed to keep us from reading
692 : : * any other fields out of the Rx descriptor until
693 : : * we know the status of DescOwn
694 : : */
695 : : rte_rmb();
696 : :
697 [ # # ]: 0 : if (unlikely(opts1 & RxRES)) {
698 : 0 : stats->rx_errors++;
699 : 0 : rtl_mark_to_asic(rxd, hw->rx_buf_sz);
700 : 0 : nb_hold++;
701 : 0 : tail = (tail + 1) % nb_rx_desc;
702 : : } else {
703 : 0 : opts2 = rte_le_to_cpu_32(rxd->opts2);
704 : :
705 : 0 : new_mb = rte_mbuf_raw_alloc(rxq->mb_pool);
706 [ # # ]: 0 : if (new_mb == NULL) {
707 : : PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u "
708 : : "queue_id=%u",
709 : : (uint32_t)rxq->port_id, (uint32_t)rxq->queue_id);
710 : 0 : dev->data->rx_mbuf_alloc_failed++;
711 : 0 : break;
712 : : }
713 : :
714 : 0 : nb_hold++;
715 : 0 : rxe = &sw_ring[tail];
716 : :
717 : 0 : rmb = rxe->mbuf;
718 : :
719 : : /* Prefetch next mbufs */
720 : 0 : tail = (tail + 1) % nb_rx_desc;
721 : 0 : rte_prefetch0(sw_ring[tail].mbuf);
722 : :
723 : : /*
724 : : * When next RX descriptor is on a cache-line boundary,
725 : : * prefetch the next 4 RX descriptors and the next 8 pointers
726 : : * to mbufs.
727 : : */
728 [ # # ]: 0 : if ((tail & 0x3) == 0) {
729 : : rte_prefetch0(&sw_ring[tail]);
730 : 0 : rte_prefetch0(&hw_ring[tail]);
731 : : }
732 : :
733 : : /* Refill the RX desc */
734 : 0 : rxe->mbuf = new_mb;
735 : : dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(new_mb));
736 : :
737 : : /* Setup RX descriptor */
738 : 0 : rxd->addr = dma_addr;
739 : 0 : rxd->opts2 = 0;
740 : : rte_wmb();
741 : 0 : rtl_mark_to_asic(rxd, hw->rx_buf_sz);
742 : :
743 : 0 : data_len = opts1 & 0x00003fff;
744 : 0 : rmb->data_len = data_len;
745 : 0 : rmb->data_off = RTE_PKTMBUF_HEADROOM;
746 : :
747 : : /*
748 : : * If this is the first buffer of the received packet,
749 : : * set the pointer to the first mbuf of the packet and
750 : : * initialize its context.
751 : : * Otherwise, update the total length and the number of segments
752 : : * of the current scattered packet, and update the pointer to
753 : : * the last mbuf of the current packet.
754 : : */
755 [ # # ]: 0 : if (first_seg == NULL) {
756 : : first_seg = rmb;
757 : 0 : first_seg->pkt_len = data_len;
758 : 0 : first_seg->nb_segs = 1;
759 : : } else {
760 : 0 : first_seg->pkt_len += data_len;
761 : 0 : first_seg->nb_segs++;
762 : 0 : last_seg->next = rmb;
763 : : }
764 : :
765 : : /*
766 : : * If this is not the last buffer of the received packet,
767 : : * update the pointer to the last mbuf of the current scattered
768 : : * packet and continue to parse the RX ring.
769 : : */
770 [ # # ]: 0 : if (!(opts1 & LastFrag)) {
771 : : last_seg = rmb;
772 : 0 : goto next_desc;
773 : : }
774 : :
775 : : /*
776 : : * This is the last buffer of the received packet.
777 : : */
778 : 0 : rmb->next = NULL;
779 : :
780 : 0 : first_seg->pkt_len -= RTE_ETHER_CRC_LEN;
781 [ # # ]: 0 : if (data_len <= RTE_ETHER_CRC_LEN) {
782 : : rte_pktmbuf_free_seg(rmb);
783 : 0 : first_seg->nb_segs--;
784 : 0 : last_seg->data_len = last_seg->data_len -
785 : : (RTE_ETHER_CRC_LEN - data_len);
786 : 0 : last_seg->next = NULL;
787 : : } else {
788 : 0 : rmb->data_len = data_len - RTE_ETHER_CRC_LEN;
789 : : }
790 : :
791 : 0 : first_seg->port = rxq->port_id;
792 : :
793 [ # # ]: 0 : if (opts2 & RxVlanTag)
794 [ # # ]: 0 : first_seg->vlan_tci = rte_bswap16(opts2 & 0xffff);
795 : :
796 : 0 : first_seg->ol_flags = rtl_rx_desc_error_to_pkt_flags(rxq, opts1, opts2);
797 : :
798 : 0 : rte_prefetch1((char *)first_seg->buf_addr + first_seg->data_off);
799 : :
800 : : /*
801 : : * Store the mbuf address into the next entry of the array
802 : : * of returned packets.
803 : : */
804 : 0 : rx_pkts[nb_rx++] = first_seg;
805 : :
806 : 0 : stats->rx_bytes += first_seg->pkt_len;
807 : 0 : stats->rx_packets++;
808 : :
809 : : /*
810 : : * Setup receipt context for a new packet.
811 : : */
812 : : first_seg = NULL;
813 : : }
814 : : }
815 : :
816 : : /*
817 : : * Record index of the next RX descriptor to probe.
818 : : */
819 : 0 : rxq->rx_tail = tail;
820 : :
821 : : /*
822 : : * Save receive context.
823 : : */
824 : 0 : rxq->pkt_first_seg = first_seg;
825 : 0 : rxq->pkt_last_seg = last_seg;
826 : :
827 : 0 : nb_hold = (uint16_t)(nb_hold + rxq->nb_rx_hold);
828 [ # # ]: 0 : if (nb_hold > rxq->rx_free_thresh) {
829 : : rte_wmb();
830 : :
831 : : /* Clear RDU */
832 : 0 : RTL_W32(hw, ISR0_8125, (RxOK | RxErr | RxDescUnavail));
833 : :
834 : : nb_hold = 0;
835 : : }
836 : :
837 : 0 : rxq->nb_rx_hold = nb_hold;
838 : :
839 : 0 : return nb_rx;
840 : : }
841 : :
842 : : /* ---------------------------------TX---------------------------------- */
843 : : static void
844 : 0 : rtl_tx_queue_release_mbufs(struct rtl_tx_queue *txq)
845 : : {
846 : : int i;
847 : :
848 : 0 : PMD_INIT_FUNC_TRACE();
849 : :
850 [ # # ]: 0 : if (txq != NULL) {
851 [ # # ]: 0 : if (txq->sw_ring != NULL) {
852 [ # # ]: 0 : for (i = 0; i < txq->nb_tx_desc; i++) {
853 [ # # ]: 0 : if (txq->sw_ring[i].mbuf != NULL) {
854 : : rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf);
855 : 0 : txq->sw_ring[i].mbuf = NULL;
856 : : }
857 : : }
858 : : }
859 : : }
860 : 0 : }
861 : :
862 : : void
863 : 0 : rtl_tx_queue_release(struct rte_eth_dev *dev, uint16_t tx_queue_id)
864 : : {
865 : 0 : struct rtl_tx_queue *txq = dev->data->tx_queues[tx_queue_id];
866 : :
867 : 0 : PMD_INIT_FUNC_TRACE();
868 : :
869 [ # # ]: 0 : if (txq != NULL) {
870 : 0 : rtl_tx_queue_release_mbufs(txq);
871 : 0 : rte_free(txq->sw_ring);
872 : 0 : rte_free(txq);
873 : : }
874 : 0 : }
875 : :
876 : : void
877 : 0 : rtl_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
878 : : struct rte_eth_txq_info *qinfo)
879 : : {
880 : : struct rtl_tx_queue *txq;
881 : :
882 : 0 : txq = dev->data->tx_queues[queue_id];
883 : :
884 : 0 : qinfo->nb_desc = txq->nb_tx_desc;
885 : 0 : }
886 : :
887 : : static void
888 : : rtl_reset_tx_queue(struct rtl_tx_queue *txq)
889 : : {
890 : : static const struct rtl_tx_desc zero_txd = {0};
891 : : int i;
892 : :
893 [ # # # # ]: 0 : for (i = 0; i < txq->nb_tx_desc; i++)
894 : 0 : txq->hw_ring[i] = zero_txd;
895 : :
896 : 0 : txq->hw_ring[txq->nb_tx_desc - 1].opts1 = rte_cpu_to_le_32(RingEnd);
897 : :
898 : 0 : txq->tx_tail = 0;
899 : 0 : txq->tx_head = 0;
900 : 0 : txq->tx_free = txq->nb_tx_desc - 1;
901 : : }
902 : :
903 : : uint64_t
904 : 0 : rtl_get_tx_port_offloads(void)
905 : : {
906 : : uint64_t tx_offload_capa;
907 : :
908 : : tx_offload_capa = RTE_ETH_TX_OFFLOAD_VLAN_INSERT |
909 : : RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
910 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
911 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
912 : : RTE_ETH_TX_OFFLOAD_TCP_TSO |
913 : : RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
914 : :
915 : 0 : return tx_offload_capa;
916 : : }
917 : :
918 : : int
919 : 0 : rtl_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
920 : : uint16_t nb_tx_desc, unsigned int socket_id,
921 : : const struct rte_eth_txconf *tx_conf)
922 : : {
923 : : struct rtl_tx_queue *txq;
924 : : const struct rte_memzone *mz;
925 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
926 : 0 : struct rtl_hw *hw = &adapter->hw;
927 : : u32 size;
928 : :
929 : 0 : PMD_INIT_FUNC_TRACE();
930 : :
931 : : /*
932 : : * If this queue existed already, free the associated memory. The
933 : : * queue cannot be reused in case we need to allocate memory on
934 : : * different socket than was previously used.
935 : : */
936 [ # # ]: 0 : if (dev->data->tx_queues[queue_idx] != NULL) {
937 : 0 : rtl_tx_queue_release(dev, queue_idx);
938 : 0 : dev->data->tx_queues[queue_idx] = NULL;
939 : : }
940 : :
941 : 0 : txq = rte_zmalloc_socket("r8169 TX queue", sizeof(struct rtl_tx_queue),
942 : : RTE_CACHE_LINE_SIZE, socket_id);
943 : :
944 [ # # ]: 0 : if (txq == NULL) {
945 : 0 : PMD_INIT_LOG(ERR, "Cannot allocate Tx queue structure");
946 : 0 : return -ENOMEM;
947 : : }
948 : :
949 : : /* Setup queue */
950 : 0 : txq->nb_tx_desc = nb_tx_desc;
951 : 0 : txq->port_id = dev->data->port_id;
952 : 0 : txq->queue_id = queue_idx;
953 : 0 : txq->tx_free_thresh = tx_conf->tx_free_thresh;
954 : :
955 : : /* Allocate memory for the software ring */
956 : 0 : txq->sw_ring = rte_calloc("r8169 sw tx ring", nb_tx_desc,
957 : : sizeof(struct rtl_tx_entry), RTE_CACHE_LINE_SIZE);
958 : :
959 [ # # ]: 0 : if (txq->sw_ring == NULL) {
960 : 0 : PMD_INIT_LOG(ERR,
961 : : "Port %d: Cannot allocate software ring for queue %d",
962 : : txq->port_id, txq->queue_id);
963 : 0 : rte_free(txq);
964 : 0 : return -ENOMEM;
965 : : }
966 : :
967 : : /*
968 : : * Allocate TX ring hardware descriptors. A memzone large enough to
969 : : * handle the maximum ring size is allocated in order to allow for
970 : : * resizing in later calls to the queue setup function.
971 : : */
972 : 0 : size = sizeof(struct rtl_tx_desc) * (nb_tx_desc + 1);
973 : 0 : mz = rte_eth_dma_zone_reserve(dev, "tx_ring", queue_idx, size,
974 : : RTL_RING_ALIGN, socket_id);
975 [ # # ]: 0 : if (mz == NULL) {
976 : 0 : PMD_INIT_LOG(ERR,
977 : : "Port %d: Cannot allocate hardware ring for queue %d",
978 : : txq->port_id, txq->queue_id);
979 : 0 : rtl_tx_queue_release(dev, txq->queue_id);
980 : 0 : return -ENOMEM;
981 : : }
982 : :
983 : 0 : txq->hw = hw;
984 : 0 : txq->hw_ring = mz->addr;
985 : 0 : txq->hw_ring_phys_addr = mz->iova;
986 : :
987 : : rtl_reset_tx_queue(txq);
988 : :
989 : : /* EnableTxNoClose */
990 : 0 : hw->NextHwDesCloPtr0 = 0;
991 : 0 : hw->BeginHwDesCloPtr0 = 0;
992 : :
993 : 0 : dev->data->tx_queues[queue_idx] = txq;
994 : :
995 : 0 : return 0;
996 : : }
997 : :
998 : : int
999 : 0 : rtl_tx_init(struct rte_eth_dev *dev)
1000 : : {
1001 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
1002 : 0 : struct rtl_hw *hw = &adapter->hw;
1003 : : struct rtl_tx_queue *txq;
1004 : :
1005 : 0 : txq = dev->data->tx_queues[0];
1006 : :
1007 : 0 : RTL_W32(hw, TxDescStartAddrLow,
1008 : : ((u64)txq->hw_ring_phys_addr & DMA_BIT_MASK(32)));
1009 : 0 : RTL_W32(hw, TxDescStartAddrHigh, ((u64)txq->hw_ring_phys_addr >> 32));
1010 : :
1011 : 0 : rtl_enable_cfg9346_write(hw);
1012 : :
1013 : : /* Set TDFNR: TX Desc Fetch NumbeR */
1014 [ # # ]: 0 : switch (hw->mcfg) {
1015 : 0 : case CFG_METHOD_48 ... CFG_METHOD_57:
1016 : : case CFG_METHOD_69 ... CFG_METHOD_71:
1017 : 0 : RTL_W8(hw, TDFNR, 0x10);
1018 : : break;
1019 : : }
1020 : :
1021 : 0 : rtl_disable_cfg9346_write(hw);
1022 : :
1023 : 0 : RTL_W8(hw, ChipCmd, RTL_R8(hw, ChipCmd) | CmdTxEnb);
1024 : :
1025 : 0 : dev->data->tx_queue_state[0] = RTE_ETH_QUEUE_STATE_STARTED;
1026 : :
1027 : 0 : return 0;
1028 : : }
1029 : :
1030 : : static inline uint32_t
1031 : : rtl_tx_vlan_tag(struct rte_mbuf *tx_pkt, uint64_t ol_flags)
1032 : : {
1033 : 0 : return (ol_flags & RTE_MBUF_F_TX_VLAN) ?
1034 [ # # ]: 0 : (TxVlanTag | rte_bswap16(tx_pkt->vlan_tci)) :
1035 : : 0;
1036 : : }
1037 : :
1038 : : static inline int
1039 : 0 : rtl_tso_setup(struct rte_mbuf *tx_pkt, uint64_t ol_flags, u32 *opts)
1040 : : {
1041 : : uint32_t mss;
1042 : : uint64_t l4_offset;
1043 : :
1044 : : /* Check if TCP segmentation required for this packet */
1045 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) {
1046 : 0 : mss = tx_pkt->tso_segsz;
1047 : 0 : l4_offset = tx_pkt->l2_len + tx_pkt->l3_len;
1048 [ # # ]: 0 : if (l4_offset <= GTTCPHO_MAX) {
1049 : : /* Implies IP cksum in IPv4 */
1050 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
1051 : 0 : opts[0] |= GiantSendv4;
1052 : : else
1053 : 0 : opts[0] |= GiantSendv6;
1054 : :
1055 : 0 : opts[0] |= l4_offset << GTTCPHO_SHIFT;
1056 : 0 : opts[1] |= RTE_MIN(mss, MSS_MAX) << 18;
1057 : :
1058 : 0 : return 1;
1059 : : }
1060 : : }
1061 : :
1062 : : return 0;
1063 : : }
1064 : :
1065 : : static inline void
1066 : 0 : rtl_setup_csum_offload(struct rte_mbuf *tx_pkt, uint64_t ol_flags,
1067 : : uint32_t *opts)
1068 : : {
1069 : : uint32_t csum_cmd = 0;
1070 : : uint64_t l4_offset;
1071 : :
1072 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
1073 : : csum_cmd |= TxIPCS_C;
1074 : :
1075 [ # # # ]: 0 : switch (ol_flags & RTE_MBUF_F_TX_L4_MASK) {
1076 : 0 : case RTE_MBUF_F_TX_UDP_CKSUM:
1077 : 0 : csum_cmd |= TxUDPCS_C;
1078 : 0 : break;
1079 : 0 : case RTE_MBUF_F_TX_TCP_CKSUM:
1080 : 0 : csum_cmd |= TxTCPCS_C;
1081 : 0 : break;
1082 : : }
1083 : :
1084 [ # # ]: 0 : if (csum_cmd != 0) {
1085 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_TX_IPV6) {
1086 : 0 : l4_offset = tx_pkt->l2_len + tx_pkt->l3_len;
1087 : 0 : csum_cmd |= TxIPV6F_C;
1088 : 0 : csum_cmd |= l4_offset << TCPHO_SHIFT;
1089 : : } else {
1090 : 0 : csum_cmd |= TxIPCS_C;
1091 : : }
1092 : 0 : opts[1] |= csum_cmd;
1093 : : }
1094 : 0 : }
1095 : :
1096 : : static uint32_t
1097 : 0 : rtl8125_get_patch_pad_len(struct rte_mbuf *tx_pkt)
1098 : : {
1099 : : uint16_t dest_port;
1100 : : uint32_t pad_len = 0;
1101 : : int udp_hdr_len = sizeof(struct rte_udp_hdr);
1102 : : int trans_data_len, l4_offset;
1103 : : struct rte_udp_hdr *udp_hdr;
1104 : :
1105 [ # # # # ]: 0 : if (!(tx_pkt->l4_len && tx_pkt->data_len < 175))
1106 : 0 : goto no_padding;
1107 : :
1108 : 0 : l4_offset = tx_pkt->l2_len + tx_pkt->l3_len;
1109 : 0 : trans_data_len = tx_pkt->data_len - l4_offset;
1110 : :
1111 [ # # ]: 0 : if (trans_data_len > 3 && trans_data_len < MIN_PATCH_LENGTH) {
1112 : 0 : udp_hdr = rte_pktmbuf_mtod_offset(tx_pkt, struct rte_udp_hdr *, l4_offset);
1113 [ # # ]: 0 : dest_port = ntohs(udp_hdr->dst_port);
1114 [ # # ]: 0 : if (dest_port == 0x13f || dest_port == 0x140) {
1115 : 0 : pad_len = MIN_PATCH_LENGTH - trans_data_len;
1116 : 0 : goto out;
1117 : : }
1118 : : }
1119 : :
1120 [ # # ]: 0 : if (trans_data_len < udp_hdr_len)
1121 : 0 : pad_len = udp_hdr_len - trans_data_len;
1122 : :
1123 : 0 : out:
1124 [ # # ]: 0 : if ((tx_pkt->data_len + pad_len) < ETH_ZLEN)
1125 : 0 : pad_len = ETH_ZLEN - tx_pkt->data_len;
1126 : :
1127 : : return pad_len;
1128 : :
1129 : : no_padding:
1130 : :
1131 : 0 : return 0;
1132 : : }
1133 : :
1134 : : static void
1135 : 0 : rtl8125_ptp_patch(struct rte_mbuf *tx_pkt)
1136 : : {
1137 : : uint32_t pad_len;
1138 : : char *padding;
1139 : :
1140 [ # # ]: 0 : if (tx_pkt->packet_type & RTE_PTYPE_L4_UDP) {
1141 : 0 : pad_len = rtl8125_get_patch_pad_len(tx_pkt);
1142 [ # # ]: 0 : if (pad_len > 0) {
1143 : 0 : padding = rte_pktmbuf_append(tx_pkt, pad_len);
1144 [ # # ]: 0 : if (unlikely(padding == NULL))
1145 : 0 : PMD_DRV_LOG(ERR, "Not enough mbuf trailing space.");
1146 : 0 : memset(padding, 0, pad_len);
1147 : : }
1148 : : }
1149 : 0 : }
1150 : :
1151 : : static inline void
1152 : 0 : rtl_xmit_pkt(struct rtl_hw *hw, struct rtl_tx_queue *txq,
1153 : : struct rte_mbuf *tx_pkt)
1154 : : {
1155 : : struct rte_mbuf *m_seg;
1156 : 0 : struct rte_eth_dev *dev = &rte_eth_devices[txq->port_id];
1157 : 0 : struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
1158 : : struct rtl_sw_stats *stats = &adapter->sw_stats;
1159 : : struct rtl_tx_desc *txd;
1160 : : struct rtl_tx_entry *txe = NULL;
1161 : : uint16_t desc_count = 0;
1162 : 0 : const uint16_t nb_tx_desc = txq->nb_tx_desc;
1163 : : uint16_t tail;
1164 : : u32 len;
1165 : : u32 opts[2] = {0};
1166 : : u32 opts1;
1167 : : u32 opts2;
1168 : : int large_send;
1169 : : uint64_t buf_dma_addr;
1170 : : uint64_t ol_flags;
1171 : : uint64_t tx_ol_flags;
1172 : :
1173 : : /* Like cur_tx */
1174 : 0 : tail = (uint16_t)(txq->tx_tail % nb_tx_desc);
1175 : :
1176 : : /* If hardware offload required */
1177 : 0 : ol_flags = tx_pkt->ol_flags;
1178 : 0 : tx_ol_flags = ol_flags & RTL_TX_OFFLOAD_MASK;
1179 : :
1180 [ # # ]: 0 : opts[0] = DescOwn;
1181 : 0 : opts[1] = rtl_tx_vlan_tag(tx_pkt, tx_ol_flags);
1182 : :
1183 : 0 : large_send = rtl_tso_setup(tx_pkt, tx_ol_flags, opts);
1184 : :
1185 : : /* No TSO */
1186 [ # # ]: 0 : if (large_send == 0) {
1187 : 0 : rtl_setup_csum_offload(tx_pkt, tx_ol_flags, opts);
1188 : :
1189 [ # # ]: 0 : switch (hw->mcfg) {
1190 : 0 : case CFG_METHOD_48 ... CFG_METHOD_53:
1191 : 0 : rtl8125_ptp_patch(tx_pkt);
1192 : 0 : break;
1193 : : }
1194 : : }
1195 : :
1196 [ # # ]: 0 : for (m_seg = tx_pkt; m_seg; m_seg = m_seg->next) {
1197 : 0 : opts1 = opts[0];
1198 : 0 : opts2 = opts[1];
1199 : :
1200 : 0 : len = m_seg->data_len;
1201 : :
1202 [ # # ]: 0 : if (len == 0)
1203 : : break;
1204 : :
1205 [ # # ]: 0 : txd = &txq->hw_ring[tail];
1206 : :
1207 : : buf_dma_addr = rte_mbuf_data_iova(m_seg);
1208 : 0 : txd->addr = rte_cpu_to_le_64(buf_dma_addr);
1209 : :
1210 : 0 : opts1 |= len;
1211 [ # # ]: 0 : if (m_seg == tx_pkt)
1212 : 0 : opts1 |= FirstFrag;
1213 [ # # ]: 0 : if (!m_seg->next)
1214 : 0 : opts1 |= LastFrag;
1215 [ # # ]: 0 : if (tail == nb_tx_desc - 1)
1216 : 0 : opts1 |= RingEnd;
1217 : :
1218 : : /* Store mbuf for freeing later */
1219 : 0 : txe = &txq->sw_ring[tail];
1220 : :
1221 [ # # ]: 0 : if (txe->mbuf)
1222 : : rte_pktmbuf_free_seg(txe->mbuf);
1223 : :
1224 : 0 : txe->mbuf = m_seg;
1225 : :
1226 : 0 : txd->opts2 = rte_cpu_to_le_32(opts2);
1227 : : rte_wmb();
1228 : 0 : txd->opts1 = rte_cpu_to_le_32(opts1);
1229 : :
1230 : 0 : tail = (tail + 1) % nb_tx_desc;
1231 : :
1232 : 0 : desc_count++;
1233 : :
1234 : 0 : stats->tx_bytes += len;
1235 : : }
1236 : :
1237 : 0 : txq->tx_tail += desc_count;
1238 : 0 : txq->tx_free -= desc_count;
1239 : :
1240 : 0 : stats->tx_packets++;
1241 : 0 : }
1242 : :
1243 : : static inline u32
1244 : : rtl_fast_mod_mask(const u32 input, const u32 mask)
1245 : : {
1246 : 0 : return input > mask ? input & mask : input;
1247 : : }
1248 : :
1249 : : static u32
1250 : : rtl_get_hw_clo_ptr(struct rtl_hw *hw)
1251 : : {
1252 [ # # # # : 0 : switch (hw->HwSuppTxNoCloseVer) {
# # ]
1253 : 0 : case 3:
1254 : 0 : return RTL_R16(hw, hw->hw_clo_ptr_reg);
1255 : 0 : case 4:
1256 : : case 5:
1257 : : case 6:
1258 : 0 : return RTL_R32(hw, hw->hw_clo_ptr_reg);
1259 : : default:
1260 : : return 0;
1261 : : }
1262 : : }
1263 : :
1264 : : static u32
1265 : : rtl_get_opts1(struct rtl_tx_desc *txd)
1266 : : {
1267 : 0 : rte_smp_rmb();
1268 : :
1269 : 0 : return rte_le_to_cpu_32(txd->opts1);
1270 : : }
1271 : :
1272 : : static void
1273 : 0 : rtl_tx_clean(struct rtl_hw *hw, struct rtl_tx_queue *txq)
1274 : : {
1275 : 0 : struct rtl_tx_entry *sw_ring = txq->sw_ring;
1276 : : struct rtl_tx_entry *txe;
1277 : : struct rtl_tx_desc *txd;
1278 : 0 : const uint8_t enable_tx_no_close = hw->EnableTxNoClose;
1279 : 0 : const uint16_t nb_tx_desc = txq->nb_tx_desc;
1280 : 0 : uint16_t head = txq->tx_head;
1281 : : uint16_t desc_freed = 0;
1282 : : uint32_t tx_left;
1283 : : uint32_t tx_desc_closed, next_hw_desc_clo_ptr0;
1284 : :
1285 : : if (txq == NULL)
1286 : : return;
1287 : :
1288 [ # # ]: 0 : if (enable_tx_no_close) {
1289 : : next_hw_desc_clo_ptr0 = rtl_get_hw_clo_ptr(hw);
1290 : 0 : hw->NextHwDesCloPtr0 = next_hw_desc_clo_ptr0;
1291 : 0 : tx_desc_closed = rtl_fast_mod_mask(next_hw_desc_clo_ptr0 -
1292 [ # # ]: 0 : hw->BeginHwDesCloPtr0, hw->MaxTxDescPtrMask);
1293 : 0 : tx_left = RTE_MIN(((rte_atomic_load_explicit(&txq->tx_tail,
1294 : : rte_memory_order_relaxed) % nb_tx_desc) - head),
1295 : : tx_desc_closed);
1296 : 0 : hw->BeginHwDesCloPtr0 += tx_left;
1297 : : } else {
1298 : 0 : tx_left = (rte_atomic_load_explicit(&txq->tx_tail,
1299 : 0 : rte_memory_order_relaxed) % nb_tx_desc) - head;
1300 : : }
1301 : :
1302 [ # # ]: 0 : while (tx_left > 0) {
1303 : 0 : txd = &txq->hw_ring[head];
1304 : :
1305 [ # # # # ]: 0 : if (!enable_tx_no_close && (rtl_get_opts1(txd) & DescOwn))
1306 : : break;
1307 : :
1308 : 0 : txe = &sw_ring[head];
1309 [ # # ]: 0 : if (txe->mbuf) {
1310 : : rte_pktmbuf_free_seg(txe->mbuf);
1311 : 0 : txe->mbuf = NULL;
1312 : : }
1313 : :
1314 : 0 : head = (head + 1) % nb_tx_desc;
1315 : 0 : desc_freed++;
1316 : 0 : tx_left--;
1317 : : }
1318 : 0 : txq->tx_free += desc_freed;
1319 : 0 : txq->tx_head = head;
1320 : : }
1321 : :
1322 : : int
1323 : 0 : rtl_tx_done_cleanup(void *tx_queue, uint32_t free_cnt)
1324 : : {
1325 : : struct rtl_tx_queue *txq = tx_queue;
1326 : 0 : struct rtl_hw *hw = txq->hw;
1327 : 0 : struct rtl_tx_entry *sw_ring = txq->sw_ring;
1328 : : struct rtl_tx_entry *txe;
1329 : : struct rtl_tx_desc *txd;
1330 : 0 : const uint8_t enable_tx_no_close = hw->EnableTxNoClose;
1331 : 0 : const uint16_t nb_tx_desc = txq->nb_tx_desc;
1332 : 0 : uint16_t head = txq->tx_head;
1333 : : uint16_t desc_freed = 0;
1334 : : uint32_t tx_left;
1335 : : uint32_t count = 0;
1336 : : uint32_t status;
1337 : : uint32_t tx_desc_closed, next_hw_desc_clo_ptr0;
1338 : :
1339 : : if (txq == NULL)
1340 : : return -ENODEV;
1341 : :
1342 [ # # ]: 0 : if (enable_tx_no_close) {
1343 : : next_hw_desc_clo_ptr0 = rtl_get_hw_clo_ptr(hw);
1344 : 0 : hw->NextHwDesCloPtr0 = next_hw_desc_clo_ptr0;
1345 : 0 : tx_desc_closed = rtl_fast_mod_mask(next_hw_desc_clo_ptr0 -
1346 [ # # ]: 0 : hw->BeginHwDesCloPtr0, hw->MaxTxDescPtrMask);
1347 : 0 : tx_left = RTE_MIN(((rte_atomic_load_explicit(&txq->tx_tail,
1348 : : rte_memory_order_relaxed) % nb_tx_desc) - head),
1349 : : tx_desc_closed);
1350 : 0 : hw->BeginHwDesCloPtr0 += tx_left;
1351 : : } else {
1352 : 0 : tx_left = (rte_atomic_load_explicit(&txq->tx_tail,
1353 : 0 : rte_memory_order_relaxed) % nb_tx_desc) - head;
1354 : : }
1355 : :
1356 [ # # ]: 0 : while (tx_left > 0) {
1357 : 0 : txd = &txq->hw_ring[head];
1358 : :
1359 : : status = rtl_get_opts1(txd);
1360 : :
1361 [ # # ]: 0 : if (!enable_tx_no_close && (status & DescOwn))
1362 : : break;
1363 : :
1364 : 0 : txe = &sw_ring[head];
1365 [ # # ]: 0 : if (txe->mbuf) {
1366 : : rte_pktmbuf_free_seg(txe->mbuf);
1367 : 0 : txe->mbuf = NULL;
1368 : : }
1369 : :
1370 : 0 : head = (head + 1) % nb_tx_desc;
1371 : :
1372 : 0 : desc_freed++;
1373 : 0 : tx_left--;
1374 : :
1375 [ # # ]: 0 : if (status & LastFrag) {
1376 : 0 : count++;
1377 [ # # ]: 0 : if (count == free_cnt)
1378 : : break;
1379 : : }
1380 : : }
1381 : :
1382 : 0 : txq->tx_free += desc_freed;
1383 : 0 : txq->tx_head = head;
1384 : :
1385 : 0 : return count;
1386 : : }
1387 : :
1388 : : static void
1389 : : rtl_doorbell(struct rtl_hw *hw, struct rtl_tx_queue *txq)
1390 : : {
1391 [ # # ]: 0 : if (hw->EnableTxNoClose)
1392 [ # # ]: 0 : if (hw->HwSuppTxNoCloseVer > 3)
1393 : 0 : RTL_W32(hw, hw->sw_tail_ptr_reg, txq->tx_tail);
1394 : : else
1395 : 0 : RTL_W16(hw, hw->sw_tail_ptr_reg, txq->tx_tail);
1396 : : else
1397 : 0 : RTL_W16(hw, TPPOLL_8125, BIT_0);
1398 : : }
1399 : :
1400 : : /* PMD transmit function */
1401 : : uint16_t
1402 : 0 : rtl_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
1403 : : {
1404 : : struct rtl_tx_queue *txq = tx_queue;
1405 : 0 : struct rtl_hw *hw = txq->hw;
1406 : : struct rte_mbuf *tx_pkt;
1407 : : uint16_t nb_tx;
1408 : :
1409 : : RTE_ASSERT(RTL_R8(hw, ChipCmd) & CmdTxEnb);
1410 : :
1411 : : PMD_TX_LOG(DEBUG,
1412 : : "port %d txq %d pkts: %d tx_free=%d tx_tail=%d tx_head=%d",
1413 : : txq->port_id, txq->queue_id, nb_pkts, txq->tx_free,
1414 : : txq->tx_tail, txq->tx_head);
1415 : :
1416 [ # # ]: 0 : for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
1417 : 0 : tx_pkt = *tx_pkts++;
1418 : :
1419 [ # # ]: 0 : if (txq->tx_free < tx_pkt->nb_segs)
1420 : : break;
1421 : :
1422 : : /* Check mbuf is valid */
1423 [ # # # # : 0 : if (tx_pkt->nb_segs == 0 || tx_pkt->pkt_len == 0 ||
# # ]
1424 [ # # ]: 0 : (tx_pkt->nb_segs > 1 && tx_pkt->next == NULL))
1425 : : break;
1426 : :
1427 : 0 : rtl_xmit_pkt(hw, txq, tx_pkt);
1428 : : }
1429 : :
1430 : : rte_wmb();
1431 : :
1432 [ # # ]: 0 : if (nb_tx > 0)
1433 : : rtl_doorbell(hw, txq);
1434 : :
1435 : : PMD_TX_LOG(DEBUG, "%s %d transmitted", __func__, nb_tx);
1436 : :
1437 : 0 : rtl_tx_clean(hw, txq);
1438 : :
1439 : 0 : return nb_tx;
1440 : : }
1441 : :
1442 : : int
1443 : 0 : rtl_stop_queues(struct rte_eth_dev *dev)
1444 : : {
1445 : : struct rtl_tx_queue *txq;
1446 : : struct rtl_rx_queue *rxq;
1447 : :
1448 : 0 : PMD_INIT_FUNC_TRACE();
1449 : :
1450 : 0 : txq = dev->data->tx_queues[0];
1451 : :
1452 : 0 : rtl_tx_queue_release_mbufs(txq);
1453 : : rtl_reset_tx_queue(txq);
1454 : 0 : dev->data->tx_queue_state[0] = RTE_ETH_QUEUE_STATE_STOPPED;
1455 : :
1456 : 0 : rxq = dev->data->rx_queues[0];
1457 : :
1458 : 0 : rtl_rx_queue_release_mbufs(rxq);
1459 : : rtl_reset_rx_queue(rxq);
1460 : 0 : dev->data->rx_queue_state[0] = RTE_ETH_QUEUE_STATE_STOPPED;
1461 : :
1462 : 0 : return 0;
1463 : : }
1464 : :
1465 : : void
1466 : 0 : rtl_free_queues(struct rte_eth_dev *dev)
1467 : : {
1468 : 0 : PMD_INIT_FUNC_TRACE();
1469 : :
1470 : 0 : rte_eth_dma_zone_free(dev, "rx_ring", 0);
1471 : 0 : rtl_rx_queue_release(dev, 0);
1472 : 0 : dev->data->rx_queues[0] = 0;
1473 : 0 : dev->data->nb_rx_queues = 0;
1474 : :
1475 : 0 : rte_eth_dma_zone_free(dev, "tx_ring", 0);
1476 : 0 : rtl_tx_queue_release(dev, 0);
1477 : 0 : dev->data->tx_queues[0] = 0;
1478 : 0 : dev->data->nb_tx_queues = 0;
1479 : 0 : }
|