Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 Advanced Micro Devices, Inc. All rights reserved.
3 : : * Copyright(c) 2018 Synopsys, Inc. All rights reserved.
4 : : */
5 : :
6 : : #include "axgbe_ethdev.h"
7 : : #include "axgbe_rxtx.h"
8 : : #include "axgbe_phy.h"
9 : :
10 : : #include <rte_time.h>
11 : : #include <rte_mempool.h>
12 : : #include <rte_mbuf.h>
13 : : #include <rte_vect.h>
14 : :
15 : : static void
16 : 0 : axgbe_rx_queue_release(struct axgbe_rx_queue *rx_queue)
17 : : {
18 : : uint16_t i;
19 : : struct rte_mbuf **sw_ring;
20 : :
21 [ # # ]: 0 : if (rx_queue) {
22 : 0 : sw_ring = rx_queue->sw_ring;
23 [ # # ]: 0 : if (sw_ring) {
24 [ # # ]: 0 : for (i = 0; i < rx_queue->nb_desc; i++) {
25 : 0 : rte_pktmbuf_free(sw_ring[i]);
26 : : }
27 : 0 : rte_free(sw_ring);
28 : : }
29 : 0 : rte_free(rx_queue);
30 : : }
31 : 0 : }
32 : :
33 : 0 : void axgbe_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t queue_idx)
34 : : {
35 : 0 : axgbe_rx_queue_release(dev->data->rx_queues[queue_idx]);
36 : 0 : }
37 : :
38 : 0 : int axgbe_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
39 : : uint16_t nb_desc, unsigned int socket_id,
40 : : const struct rte_eth_rxconf *rx_conf,
41 : : struct rte_mempool *mp)
42 : : {
43 : : PMD_INIT_FUNC_TRACE();
44 : : uint32_t size;
45 : : const struct rte_memzone *dma;
46 : : struct axgbe_rx_queue *rxq;
47 : 0 : uint32_t rx_desc = nb_desc;
48 [ # # ]: 0 : struct axgbe_port *pdata = dev->data->dev_private;
49 : :
50 : : /*
51 : : * validate Rx descriptors count
52 : : * should be power of 2 and less than h/w supported
53 : : */
54 : 0 : if ((!rte_is_power_of_2(rx_desc)) ||
55 [ # # ]: 0 : rx_desc > pdata->rx_desc_count)
56 : : return -EINVAL;
57 : : /* First allocate the rx queue data structure */
58 : 0 : rxq = rte_zmalloc_socket("ethdev RX queue",
59 : : sizeof(struct axgbe_rx_queue),
60 : : RTE_CACHE_LINE_SIZE, socket_id);
61 [ # # ]: 0 : if (!rxq) {
62 : 0 : PMD_INIT_LOG(ERR, "rte_zmalloc for rxq failed!");
63 : 0 : return -ENOMEM;
64 : : }
65 : :
66 : 0 : rxq->cur = 0;
67 : 0 : rxq->dirty = 0;
68 : 0 : rxq->pdata = pdata;
69 : 0 : rxq->mb_pool = mp;
70 : 0 : rxq->queue_id = queue_idx;
71 : 0 : rxq->port_id = dev->data->port_id;
72 : 0 : rxq->nb_desc = rx_desc;
73 : 0 : rxq->dma_regs = (void *)((uint8_t *)pdata->xgmac_regs + DMA_CH_BASE +
74 : 0 : (DMA_CH_INC * rxq->queue_id));
75 : 0 : rxq->dma_tail_reg = (volatile uint32_t *)((uint8_t *)rxq->dma_regs +
76 : : DMA_CH_RDTR_LO);
77 [ # # ]: 0 : if (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC)
78 : 0 : rxq->crc_len = RTE_ETHER_CRC_LEN;
79 : : else
80 : 0 : rxq->crc_len = 0;
81 : :
82 : : /* CRC strip in AXGBE supports per port not per queue */
83 : 0 : pdata->crc_strip_enable = (rxq->crc_len == 0) ? 1 : 0;
84 [ # # ]: 0 : rxq->free_thresh = rx_conf->rx_free_thresh ?
85 : : rx_conf->rx_free_thresh : AXGBE_RX_FREE_THRESH;
86 [ # # ]: 0 : if (rxq->free_thresh > rxq->nb_desc)
87 : 0 : rxq->free_thresh = rxq->nb_desc >> 3;
88 : :
89 : 0 : rxq->offloads = rx_conf->offloads | dev->data->dev_conf.rxmode.offloads;
90 : : /* Allocate RX ring hardware descriptors */
91 : 0 : size = rxq->nb_desc * sizeof(union axgbe_rx_desc);
92 : 0 : dma = rte_eth_dma_zone_reserve(dev, "rx_ring", queue_idx, size, 128,
93 : : socket_id);
94 [ # # ]: 0 : if (!dma) {
95 : 0 : PMD_DRV_LOG_LINE(ERR, "ring_dma_zone_reserve for rx_ring failed");
96 : 0 : axgbe_rx_queue_release(rxq);
97 : 0 : return -ENOMEM;
98 : : }
99 : 0 : rxq->ring_phys_addr = (uint64_t)dma->iova;
100 : 0 : rxq->desc = (volatile union axgbe_rx_desc *)dma->addr;
101 : : memset((void *)rxq->desc, 0, size);
102 : : /* Allocate software ring */
103 : 0 : size = rxq->nb_desc * sizeof(struct rte_mbuf *);
104 : 0 : rxq->sw_ring = rte_zmalloc_socket("sw_ring", size,
105 : : RTE_CACHE_LINE_SIZE,
106 : : socket_id);
107 [ # # ]: 0 : if (!rxq->sw_ring) {
108 : 0 : PMD_DRV_LOG_LINE(ERR, "rte_zmalloc for sw_ring failed");
109 : 0 : axgbe_rx_queue_release(rxq);
110 : 0 : return -ENOMEM;
111 : : }
112 : 0 : dev->data->rx_queues[queue_idx] = rxq;
113 [ # # ]: 0 : if (!pdata->rx_queues)
114 : 0 : pdata->rx_queues = dev->data->rx_queues;
115 : :
116 : : return 0;
117 : : }
118 : :
119 : 0 : static void axgbe_prepare_rx_stop(struct axgbe_port *pdata,
120 : : unsigned int queue)
121 : : {
122 : : unsigned int rx_status;
123 : : unsigned long rx_timeout;
124 : :
125 : : /* The Rx engine cannot be stopped if it is actively processing
126 : : * packets. Wait for the Rx queue to empty the Rx fifo. Don't
127 : : * wait forever though...
128 : : */
129 : 0 : rx_timeout = rte_get_timer_cycles() + (AXGBE_DMA_STOP_TIMEOUT *
130 : : rte_get_timer_hz());
131 : :
132 [ # # ]: 0 : while (time_before(rte_get_timer_cycles(), rx_timeout)) {
133 : 0 : rx_status = AXGMAC_MTL_IOREAD(pdata, queue, MTL_Q_RQDR);
134 [ # # ]: 0 : if ((AXGMAC_GET_BITS(rx_status, MTL_Q_RQDR, PRXQ) == 0) &&
135 [ # # ]: 0 : (AXGMAC_GET_BITS(rx_status, MTL_Q_RQDR, RXQSTS) == 0))
136 : : break;
137 : :
138 : 0 : rte_delay_us(900);
139 : : }
140 : :
141 [ # # ]: 0 : if (!time_before(rte_get_timer_cycles(), rx_timeout))
142 : 0 : PMD_DRV_LOG_LINE(ERR,
143 : : "timed out waiting for Rx queue %u to empty",
144 : : queue);
145 : 0 : }
146 : :
147 : 0 : void axgbe_dev_disable_rx(struct rte_eth_dev *dev)
148 : : {
149 : : struct axgbe_rx_queue *rxq;
150 : 0 : struct axgbe_port *pdata = dev->data->dev_private;
151 : : unsigned int i;
152 : :
153 : : /* Disable MAC Rx */
154 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RCR, DCRCC, 0);
155 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RCR, CST, 0);
156 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RCR, ACS, 0);
157 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RCR, RE, 0);
158 : :
159 : : /* Prepare for Rx DMA channel stop */
160 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
161 : : rxq = dev->data->rx_queues[i];
162 : 0 : axgbe_prepare_rx_stop(pdata, i);
163 : : }
164 : : /* Disable each Rx queue */
165 : 0 : AXGMAC_IOWRITE(pdata, MAC_RQC0R, 0);
166 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
167 : 0 : rxq = dev->data->rx_queues[i];
168 : : /* Disable Rx DMA channel */
169 : 0 : AXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RCR, SR, 0);
170 : : }
171 : 0 : }
172 : :
173 : 0 : void axgbe_dev_enable_rx(struct rte_eth_dev *dev)
174 : : {
175 : : struct axgbe_rx_queue *rxq;
176 : 0 : struct axgbe_port *pdata = dev->data->dev_private;
177 : : unsigned int i;
178 : : unsigned int reg_val = 0;
179 : :
180 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
181 : 0 : rxq = dev->data->rx_queues[i];
182 : : /* Enable Rx DMA channel */
183 : 0 : AXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RCR, SR, 1);
184 : : }
185 : :
186 : : reg_val = 0;
187 [ # # ]: 0 : for (i = 0; i < pdata->rx_q_count; i++)
188 : 0 : reg_val |= (0x02 << (i << 1));
189 : 0 : AXGMAC_IOWRITE(pdata, MAC_RQC0R, reg_val);
190 : :
191 : : /* Enable MAC Rx */
192 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RCR, DCRCC, 1);
193 : : /* Frame is forwarded after stripping CRC to application*/
194 [ # # ]: 0 : if (pdata->crc_strip_enable) {
195 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RCR, CST, 1);
196 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RCR, ACS, 1);
197 : : }
198 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RCR, RE, 1);
199 : 0 : }
200 : :
201 : : /* Rx function one to one refresh */
202 : : uint16_t
203 : 0 : axgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
204 : : uint16_t nb_pkts)
205 : : {
206 : : PMD_INIT_FUNC_TRACE();
207 : : uint16_t nb_rx = 0;
208 : : struct axgbe_rx_queue *rxq = rx_queue;
209 : : volatile union axgbe_rx_desc *desc;
210 : 0 : uint64_t old_dirty = rxq->dirty;
211 : : struct rte_mbuf *mbuf, *tmbuf;
212 : : unsigned int err, etlt;
213 : : uint32_t error_status;
214 : : uint16_t idx, pidx, pkt_len;
215 : :
216 : 0 : idx = AXGBE_GET_DESC_IDX(rxq, rxq->cur);
217 [ # # ]: 0 : while (nb_rx < nb_pkts) {
218 [ # # ]: 0 : if (unlikely(idx == rxq->nb_desc))
219 : : idx = 0;
220 : :
221 : 0 : desc = &rxq->desc[idx];
222 : :
223 [ # # ]: 0 : if (AXGMAC_GET_BITS_LE(desc->write.desc3, RX_NORMAL_DESC3, OWN))
224 : : break;
225 : 0 : tmbuf = rte_mbuf_raw_alloc(rxq->mb_pool);
226 [ # # ]: 0 : if (unlikely(!tmbuf)) {
227 : 0 : PMD_DRV_LOG_LINE(ERR, "RX mbuf alloc failed port_id = %u"
228 : : " queue_id = %u",
229 : : (unsigned int)rxq->port_id,
230 : : (unsigned int)rxq->queue_id);
231 : : rte_eth_devices[
232 : 0 : rxq->port_id].data->rx_mbuf_alloc_failed++;
233 : 0 : rxq->rx_mbuf_alloc_failed++;
234 : 0 : break;
235 : : }
236 : 0 : pidx = idx + 1;
237 [ # # ]: 0 : if (unlikely(pidx == rxq->nb_desc))
238 : : pidx = 0;
239 : :
240 : 0 : rte_prefetch0(rxq->sw_ring[pidx]);
241 [ # # ]: 0 : if ((pidx & 0x3) == 0) {
242 : 0 : rte_prefetch0(&rxq->desc[pidx]);
243 : : rte_prefetch0(&rxq->sw_ring[pidx]);
244 : : }
245 : :
246 : 0 : mbuf = rxq->sw_ring[idx];
247 : : /* Check for any errors and free mbuf*/
248 : 0 : err = AXGMAC_GET_BITS_LE(desc->write.desc3,
249 : : RX_NORMAL_DESC3, ES);
250 : : error_status = 0;
251 [ # # ]: 0 : if (unlikely(err)) {
252 : 0 : error_status = desc->write.desc3 & AXGBE_ERR_STATUS;
253 : 0 : if ((error_status != AXGBE_L3_CSUM_ERR) &&
254 [ # # ]: 0 : (error_status != AXGBE_L4_CSUM_ERR)) {
255 : 0 : rxq->errors++;
256 : 0 : rte_pktmbuf_free(mbuf);
257 : 0 : goto err_set;
258 : : }
259 : : }
260 [ # # ]: 0 : if (rxq->pdata->rx_csum_enable) {
261 : : mbuf->ol_flags = 0;
262 : : mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
263 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
264 [ # # ]: 0 : if (unlikely(error_status == AXGBE_L3_CSUM_ERR)) {
265 : : mbuf->ol_flags &= ~RTE_MBUF_F_RX_IP_CKSUM_GOOD;
266 : : mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
267 : 0 : mbuf->ol_flags &= ~RTE_MBUF_F_RX_L4_CKSUM_GOOD;
268 : : mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN;
269 : 0 : } else if (
270 [ # # ]: 0 : unlikely(error_status == AXGBE_L4_CSUM_ERR)) {
271 : : mbuf->ol_flags &= ~RTE_MBUF_F_RX_L4_CKSUM_GOOD;
272 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
273 : : }
274 : : }
275 : 0 : rte_prefetch1(rte_pktmbuf_mtod(mbuf, void *));
276 : : /* Get the RSS hash */
277 [ # # ]: 0 : if (AXGMAC_GET_BITS_LE(desc->write.desc3, RX_NORMAL_DESC3, RSV))
278 : 0 : mbuf->hash.rss = rte_le_to_cpu_32(desc->write.desc1);
279 : 0 : etlt = AXGMAC_GET_BITS_LE(desc->write.desc3,
280 : : RX_NORMAL_DESC3, ETLT);
281 [ # # ]: 0 : if (!err || !etlt) {
282 [ # # ]: 0 : if (etlt == RX_CVLAN_TAG_PRESENT) {
283 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN;
284 : 0 : mbuf->vlan_tci =
285 : 0 : AXGMAC_GET_BITS_LE(desc->write.desc0,
286 : : RX_NORMAL_DESC0, OVT);
287 [ # # ]: 0 : if (rxq->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
288 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN_STRIPPED;
289 : : else
290 : 0 : mbuf->ol_flags &= ~RTE_MBUF_F_RX_VLAN_STRIPPED;
291 : : } else {
292 : 0 : mbuf->ol_flags &=
293 : : ~(RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED);
294 : 0 : mbuf->vlan_tci = 0;
295 : : }
296 : : }
297 : : /* Indicate if a Context Descriptor is next */
298 [ # # ]: 0 : if (AXGMAC_GET_BITS_LE(desc->write.desc3, RX_NORMAL_DESC3, CDA))
299 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP
300 : : | RTE_MBUF_F_RX_IEEE1588_TMST;
301 : 0 : pkt_len = AXGMAC_GET_BITS_LE(desc->write.desc3, RX_NORMAL_DESC3,
302 : 0 : PL) - rxq->crc_len;
303 : : /* Mbuf populate */
304 : 0 : mbuf->next = NULL;
305 : 0 : mbuf->data_off = RTE_PKTMBUF_HEADROOM;
306 : 0 : mbuf->nb_segs = 1;
307 : 0 : mbuf->port = rxq->port_id;
308 : 0 : mbuf->pkt_len = pkt_len;
309 : 0 : mbuf->data_len = pkt_len;
310 : 0 : rxq->bytes += pkt_len;
311 : 0 : rx_pkts[nb_rx++] = mbuf;
312 : 0 : err_set:
313 : 0 : rxq->cur++;
314 : 0 : rxq->sw_ring[idx++] = tmbuf;
315 : 0 : desc->read.baddr =
316 : : rte_cpu_to_le_64(rte_mbuf_data_iova_default(tmbuf));
317 : 0 : memset((void *)(&desc->read.desc2), 0, 8);
318 : 0 : AXGMAC_SET_BITS_LE(desc->read.desc3, RX_NORMAL_DESC3, OWN, 1);
319 : 0 : rxq->dirty++;
320 : : }
321 : 0 : rxq->pkts += nb_rx;
322 [ # # ]: 0 : if (rxq->dirty != old_dirty) {
323 : : rte_wmb();
324 : 0 : idx = AXGBE_GET_DESC_IDX(rxq, rxq->dirty - 1);
325 : 0 : AXGMAC_DMA_IOWRITE(rxq, DMA_CH_RDTR_LO,
326 : : low32_value(rxq->ring_phys_addr +
327 : : (idx * sizeof(union axgbe_rx_desc))));
328 : : }
329 : :
330 : 0 : return nb_rx;
331 : : }
332 : :
333 : :
334 : 0 : uint16_t eth_axgbe_recv_scattered_pkts(void *rx_queue,
335 : : struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
336 : : {
337 : : PMD_INIT_FUNC_TRACE();
338 : : uint16_t nb_rx = 0;
339 : : struct axgbe_rx_queue *rxq = rx_queue;
340 : : volatile union axgbe_rx_desc *desc;
341 : :
342 : : struct rte_mbuf *first_seg = NULL;
343 : : struct rte_mbuf *mbuf, *tmbuf;
344 : : unsigned int err = 0, etlt;
345 : : uint32_t error_status = 0;
346 : : uint16_t idx, pidx, data_len = 0, pkt_len = 0;
347 : : bool eop = 0;
348 : :
349 : : idx = AXGBE_GET_DESC_IDX(rxq, rxq->cur);
350 : :
351 [ # # ]: 0 : while (nb_rx < nb_pkts) {
352 : 0 : next_desc:
353 : 0 : idx = AXGBE_GET_DESC_IDX(rxq, rxq->cur);
354 : :
355 : 0 : desc = &rxq->desc[idx];
356 : :
357 [ # # ]: 0 : if (AXGMAC_GET_BITS_LE(desc->write.desc3, RX_NORMAL_DESC3, OWN))
358 : : break;
359 : :
360 : 0 : tmbuf = rte_mbuf_raw_alloc(rxq->mb_pool);
361 [ # # ]: 0 : if (unlikely(!tmbuf)) {
362 : 0 : PMD_DRV_LOG_LINE(ERR, "RX mbuf alloc failed port_id = %u"
363 : : " queue_id = %u",
364 : : (unsigned int)rxq->port_id,
365 : : (unsigned int)rxq->queue_id);
366 : 0 : rte_eth_devices[rxq->port_id].data->rx_mbuf_alloc_failed++;
367 : 0 : break;
368 : : }
369 : :
370 : 0 : pidx = idx + 1;
371 [ # # ]: 0 : if (unlikely(pidx == rxq->nb_desc))
372 : : pidx = 0;
373 : :
374 : 0 : rte_prefetch0(rxq->sw_ring[pidx]);
375 [ # # ]: 0 : if ((pidx & 0x3) == 0) {
376 : 0 : rte_prefetch0(&rxq->desc[pidx]);
377 : : rte_prefetch0(&rxq->sw_ring[pidx]);
378 : : }
379 : :
380 : 0 : mbuf = rxq->sw_ring[idx];
381 : 0 : rte_prefetch1(rte_pktmbuf_mtod(mbuf, void *));
382 : :
383 [ # # ]: 0 : if (!AXGMAC_GET_BITS_LE(desc->write.desc3,
384 : : RX_NORMAL_DESC3, LD)) {
385 : : eop = 0;
386 : 0 : pkt_len = rxq->buf_size;
387 : : data_len = pkt_len;
388 : : } else {
389 : : eop = 1;
390 : 0 : pkt_len = AXGMAC_GET_BITS_LE(desc->write.desc3,
391 : 0 : RX_NORMAL_DESC3, PL) - rxq->crc_len;
392 : 0 : data_len = pkt_len % rxq->buf_size;
393 : : /* Check for any errors and free mbuf*/
394 : 0 : err = AXGMAC_GET_BITS_LE(desc->write.desc3,
395 : : RX_NORMAL_DESC3, ES);
396 : : error_status = 0;
397 [ # # ]: 0 : if (unlikely(err)) {
398 : 0 : error_status = desc->write.desc3 &
399 : : AXGBE_ERR_STATUS;
400 : 0 : if (error_status != AXGBE_L3_CSUM_ERR &&
401 [ # # ]: 0 : error_status != AXGBE_L4_CSUM_ERR) {
402 : 0 : rxq->errors++;
403 : 0 : rte_pktmbuf_free(mbuf);
404 : 0 : rte_pktmbuf_free(first_seg);
405 : : first_seg = NULL;
406 : : eop = 0;
407 : 0 : goto err_set;
408 : : }
409 : : }
410 : :
411 : : }
412 : : /* Mbuf populate */
413 : 0 : mbuf->data_off = RTE_PKTMBUF_HEADROOM;
414 : 0 : mbuf->data_len = data_len;
415 : 0 : mbuf->pkt_len = data_len;
416 : :
417 [ # # ]: 0 : if (rxq->saved_mbuf) {
418 : : first_seg = rxq->saved_mbuf;
419 : 0 : rxq->saved_mbuf = NULL;
420 : : }
421 : :
422 [ # # ]: 0 : if (first_seg != NULL) {
423 : : if (rte_pktmbuf_chain(first_seg, mbuf) != 0) {
424 : 0 : rte_pktmbuf_free(first_seg);
425 : : first_seg = NULL;
426 : 0 : rte_pktmbuf_free(mbuf);
427 : 0 : rxq->saved_mbuf = NULL;
428 : 0 : rxq->errors++;
429 : : eop = 0;
430 : 0 : break;
431 : : }
432 : : } else {
433 : : first_seg = mbuf;
434 : : }
435 : :
436 : : /* Get the RSS hash */
437 [ # # ]: 0 : if (AXGMAC_GET_BITS_LE(desc->write.desc3, RX_NORMAL_DESC3, RSV))
438 : 0 : first_seg->hash.rss =
439 : 0 : rte_le_to_cpu_32(desc->write.desc1);
440 : 0 : etlt = AXGMAC_GET_BITS_LE(desc->write.desc3,
441 : : RX_NORMAL_DESC3, ETLT);
442 [ # # ]: 0 : if (!err || !etlt) {
443 [ # # ]: 0 : if (etlt == RX_CVLAN_TAG_PRESENT) {
444 : 0 : first_seg->ol_flags |= RTE_MBUF_F_RX_VLAN;
445 : 0 : first_seg->vlan_tci =
446 : 0 : AXGMAC_GET_BITS_LE(desc->write.desc0,
447 : : RX_NORMAL_DESC0, OVT);
448 [ # # ]: 0 : if (rxq->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
449 : 0 : first_seg->ol_flags |=
450 : : RTE_MBUF_F_RX_VLAN_STRIPPED;
451 : : else
452 : 0 : first_seg->ol_flags &=
453 : : ~RTE_MBUF_F_RX_VLAN_STRIPPED;
454 : : } else {
455 : 0 : first_seg->ol_flags &=
456 : : ~(RTE_MBUF_F_RX_VLAN |
457 : : RTE_MBUF_F_RX_VLAN_STRIPPED);
458 : 0 : first_seg->vlan_tci = 0;
459 : : }
460 : : }
461 : :
462 : 0 : err_set:
463 : 0 : rxq->cur++;
464 [ # # ]: 0 : rxq->sw_ring[idx] = tmbuf;
465 : 0 : desc->read.baddr =
466 : : rte_cpu_to_le_64(rte_mbuf_data_iova_default(tmbuf));
467 [ # # ]: 0 : memset((void *)(&desc->read.desc2), 0, 8);
468 : 0 : AXGMAC_SET_BITS_LE(desc->read.desc3, RX_NORMAL_DESC3, OWN, 1);
469 : :
470 [ # # ]: 0 : if (!eop)
471 : 0 : goto next_desc;
472 : : eop = 0;
473 : :
474 : 0 : rxq->bytes += pkt_len;
475 : :
476 : 0 : first_seg->port = rxq->port_id;
477 [ # # ]: 0 : if (rxq->pdata->rx_csum_enable) {
478 : : first_seg->ol_flags = 0;
479 : : first_seg->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
480 : 0 : first_seg->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
481 [ # # ]: 0 : if (unlikely(error_status == AXGBE_L3_CSUM_ERR)) {
482 : : first_seg->ol_flags &=
483 : : ~RTE_MBUF_F_RX_IP_CKSUM_GOOD;
484 : : first_seg->ol_flags |=
485 : : RTE_MBUF_F_RX_IP_CKSUM_BAD;
486 : 0 : first_seg->ol_flags &=
487 : : ~RTE_MBUF_F_RX_L4_CKSUM_GOOD;
488 : : first_seg->ol_flags |=
489 : : RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN;
490 [ # # ]: 0 : } else if (unlikely(error_status
491 : : == AXGBE_L4_CSUM_ERR)) {
492 : : first_seg->ol_flags &=
493 : : ~RTE_MBUF_F_RX_L4_CKSUM_GOOD;
494 : 0 : first_seg->ol_flags |=
495 : : RTE_MBUF_F_RX_L4_CKSUM_BAD;
496 : : }
497 : : }
498 : :
499 : 0 : rx_pkts[nb_rx++] = first_seg;
500 : :
501 : : /* Setup receipt context for a new packet.*/
502 : : first_seg = NULL;
503 : : }
504 : :
505 : : /* Check if we need to save state before leaving */
506 [ # # ]: 0 : if (first_seg != NULL && eop == 0)
507 : 0 : rxq->saved_mbuf = first_seg;
508 : :
509 : : /* Save receive context.*/
510 : 0 : rxq->pkts += nb_rx;
511 : :
512 [ # # ]: 0 : if (rxq->dirty != rxq->cur) {
513 : : rte_wmb();
514 : 0 : idx = AXGBE_GET_DESC_IDX(rxq, rxq->cur - 1);
515 : 0 : AXGMAC_DMA_IOWRITE(rxq, DMA_CH_RDTR_LO,
516 : : low32_value(rxq->ring_phys_addr +
517 : : (idx * sizeof(union axgbe_rx_desc))));
518 : 0 : rxq->dirty = rxq->cur;
519 : : }
520 : 0 : return nb_rx;
521 : : }
522 : :
523 : : /* Tx Apis */
524 : 0 : static void axgbe_tx_queue_release(struct axgbe_tx_queue *tx_queue)
525 : : {
526 : : uint16_t i;
527 : : struct rte_mbuf **sw_ring;
528 : :
529 [ # # ]: 0 : if (tx_queue) {
530 : 0 : sw_ring = tx_queue->sw_ring;
531 [ # # ]: 0 : if (sw_ring) {
532 [ # # ]: 0 : for (i = 0; i < tx_queue->nb_desc; i++) {
533 : 0 : rte_pktmbuf_free(sw_ring[i]);
534 : : }
535 : 0 : rte_free(sw_ring);
536 : : }
537 : 0 : rte_free(tx_queue);
538 : : }
539 : 0 : }
540 : :
541 : 0 : void axgbe_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t queue_idx)
542 : : {
543 : 0 : axgbe_tx_queue_release(dev->data->tx_queues[queue_idx]);
544 : 0 : }
545 : :
546 : 0 : int axgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
547 : : uint16_t nb_desc, unsigned int socket_id,
548 : : const struct rte_eth_txconf *tx_conf)
549 : : {
550 : : PMD_INIT_FUNC_TRACE();
551 : : uint32_t tx_desc;
552 : : struct axgbe_port *pdata;
553 : : struct axgbe_tx_queue *txq;
554 : : unsigned int tsize;
555 : : const struct rte_memzone *tz;
556 : : uint64_t offloads;
557 : 0 : struct rte_eth_dev_data *dev_data = dev->data;
558 : :
559 : 0 : tx_desc = nb_desc;
560 [ # # ]: 0 : pdata = dev->data->dev_private;
561 : :
562 : : /*
563 : : * validate tx descriptors count
564 : : * should be power of 2 and less than h/w supported
565 : : */
566 : 0 : if ((!rte_is_power_of_2(tx_desc)) ||
567 [ # # # # ]: 0 : tx_desc > pdata->tx_desc_count ||
568 : : tx_desc < AXGBE_MIN_RING_DESC)
569 : : return -EINVAL;
570 : :
571 : : /* First allocate the tx queue data structure */
572 : 0 : txq = rte_zmalloc("ethdev TX queue", sizeof(struct axgbe_tx_queue),
573 : : RTE_CACHE_LINE_SIZE);
574 [ # # ]: 0 : if (!txq)
575 : : return -ENOMEM;
576 : 0 : txq->pdata = pdata;
577 : 0 : offloads = tx_conf->offloads |
578 : 0 : dev->data->dev_conf.txmode.offloads;
579 : 0 : txq->nb_desc = tx_desc;
580 [ # # ]: 0 : txq->free_thresh = tx_conf->tx_free_thresh ?
581 : : tx_conf->tx_free_thresh : AXGBE_TX_FREE_THRESH;
582 [ # # ]: 0 : if (txq->free_thresh > txq->nb_desc)
583 : 0 : txq->free_thresh = (txq->nb_desc >> 1);
584 : 0 : txq->free_batch_cnt = txq->free_thresh;
585 : :
586 : : /* In vector_tx path threshold should be multiple of queue_size*/
587 [ # # ]: 0 : if (txq->nb_desc % txq->free_thresh != 0)
588 : 0 : txq->vector_disable = 1;
589 : :
590 [ # # ]: 0 : if (offloads != 0)
591 : 0 : txq->vector_disable = 1;
592 : :
593 : : /* Allocate TX ring hardware descriptors */
594 : 0 : tsize = txq->nb_desc * sizeof(struct axgbe_tx_desc);
595 : 0 : tz = rte_eth_dma_zone_reserve(dev, "tx_ring", queue_idx,
596 : : tsize, AXGBE_DESC_ALIGN, socket_id);
597 [ # # ]: 0 : if (!tz) {
598 : 0 : axgbe_tx_queue_release(txq);
599 : 0 : return -ENOMEM;
600 : : }
601 : 0 : memset(tz->addr, 0, tsize);
602 : 0 : txq->ring_phys_addr = (uint64_t)tz->iova;
603 : 0 : txq->desc = tz->addr;
604 : 0 : txq->queue_id = queue_idx;
605 : 0 : txq->port_id = dev->data->port_id;
606 : 0 : txq->offloads = offloads;
607 : 0 : txq->dma_regs = (void *)((uint8_t *)pdata->xgmac_regs + DMA_CH_BASE +
608 : 0 : (DMA_CH_INC * txq->queue_id));
609 : 0 : txq->dma_tail_reg = (volatile uint32_t *)((uint8_t *)txq->dma_regs +
610 : : DMA_CH_TDTR_LO);
611 : 0 : txq->cur = 0;
612 : 0 : txq->dirty = 0;
613 : 0 : txq->nb_desc_free = txq->nb_desc;
614 : : /* Allocate software ring */
615 : 0 : tsize = txq->nb_desc * sizeof(struct rte_mbuf *);
616 : 0 : txq->sw_ring = rte_zmalloc("tx_sw_ring", tsize,
617 : : RTE_CACHE_LINE_SIZE);
618 [ # # ]: 0 : if (!txq->sw_ring) {
619 : 0 : axgbe_tx_queue_release(txq);
620 : 0 : return -ENOMEM;
621 : : }
622 : 0 : dev->data->tx_queues[queue_idx] = txq;
623 [ # # ]: 0 : if (!pdata->tx_queues)
624 : 0 : pdata->tx_queues = dev->data->tx_queues;
625 : :
626 [ # # ]: 0 : if ((dev_data->dev_conf.txmode.offloads &
627 : : RTE_ETH_TX_OFFLOAD_MULTI_SEGS))
628 : 0 : pdata->multi_segs_tx = true;
629 : :
630 [ # # ]: 0 : if ((dev_data->dev_conf.txmode.offloads &
631 : : RTE_ETH_TX_OFFLOAD_TCP_TSO))
632 : 0 : pdata->tso_tx = true;
633 : :
634 : : return 0;
635 : : }
636 : :
637 : 0 : int axgbe_dev_fw_version_get(struct rte_eth_dev *eth_dev,
638 : : char *fw_version, size_t fw_size)
639 : : {
640 : : struct axgbe_port *pdata;
641 : : struct axgbe_hw_features *hw_feat;
642 : : int ret;
643 : :
644 : 0 : pdata = (struct axgbe_port *)eth_dev->data->dev_private;
645 : : hw_feat = &pdata->hw_feat;
646 : :
647 : 0 : ret = snprintf(fw_version, fw_size, "%d.%d.%d",
648 : 0 : AXGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER),
649 : 0 : AXGMAC_GET_BITS(hw_feat->version, MAC_VR, DEVID),
650 [ # # ]: 0 : AXGMAC_GET_BITS(hw_feat->version, MAC_VR, SNPSVER));
651 [ # # ]: 0 : if (ret < 0)
652 : : return -EINVAL;
653 : :
654 : 0 : ret += 1; /* add the size of '\0' */
655 [ # # ]: 0 : if (fw_size < (size_t)ret)
656 : : return ret;
657 : : else
658 : 0 : return 0;
659 : : }
660 : :
661 : 0 : static void axgbe_txq_prepare_tx_stop(struct axgbe_port *pdata,
662 : : unsigned int queue)
663 : : {
664 : : unsigned int tx_status;
665 : : unsigned long tx_timeout;
666 : :
667 : : /* The Tx engine cannot be stopped if it is actively processing
668 : : * packets. Wait for the Tx queue to empty the Tx fifo. Don't
669 : : * wait forever though...
670 : : */
671 : 0 : tx_timeout = rte_get_timer_cycles() + (AXGBE_DMA_STOP_TIMEOUT *
672 : : rte_get_timer_hz());
673 [ # # ]: 0 : while (time_before(rte_get_timer_cycles(), tx_timeout)) {
674 : 0 : tx_status = AXGMAC_MTL_IOREAD(pdata, queue, MTL_Q_TQDR);
675 [ # # ]: 0 : if ((AXGMAC_GET_BITS(tx_status, MTL_Q_TQDR, TRCSTS) != 1) &&
676 [ # # ]: 0 : (AXGMAC_GET_BITS(tx_status, MTL_Q_TQDR, TXQSTS) == 0))
677 : : break;
678 : :
679 : 0 : rte_delay_us(900);
680 : : }
681 : :
682 [ # # ]: 0 : if (!time_before(rte_get_timer_cycles(), tx_timeout))
683 : 0 : PMD_DRV_LOG_LINE(ERR,
684 : : "timed out waiting for Tx queue %u to empty",
685 : : queue);
686 : 0 : }
687 : :
688 : 0 : static void axgbe_prepare_tx_stop(struct axgbe_port *pdata,
689 : : unsigned int queue)
690 : : {
691 : : unsigned int tx_dsr, tx_pos, tx_qidx;
692 : : unsigned int tx_status;
693 : : unsigned long tx_timeout;
694 : :
695 [ # # ]: 0 : if (AXGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) > 0x20)
696 : 0 : return axgbe_txq_prepare_tx_stop(pdata, queue);
697 : :
698 : : /* Calculate the status register to read and the position within */
699 [ # # ]: 0 : if (queue < DMA_DSRX_FIRST_QUEUE) {
700 : : tx_dsr = DMA_DSR0;
701 : 0 : tx_pos = (queue * DMA_DSR_Q_WIDTH) + DMA_DSR0_TPS_START;
702 : : } else {
703 : 0 : tx_qidx = queue - DMA_DSRX_FIRST_QUEUE;
704 : :
705 : 0 : tx_dsr = DMA_DSR1 + ((tx_qidx / DMA_DSRX_QPR) * DMA_DSRX_INC);
706 : 0 : tx_pos = ((tx_qidx % DMA_DSRX_QPR) * DMA_DSR_Q_WIDTH) +
707 : : DMA_DSRX_TPS_START;
708 : : }
709 : :
710 : : /* The Tx engine cannot be stopped if it is actively processing
711 : : * descriptors. Wait for the Tx engine to enter the stopped or
712 : : * suspended state. Don't wait forever though...
713 : : */
714 : 0 : tx_timeout = rte_get_timer_cycles() + (AXGBE_DMA_STOP_TIMEOUT *
715 : : rte_get_timer_hz());
716 [ # # ]: 0 : while (time_before(rte_get_timer_cycles(), tx_timeout)) {
717 : 0 : tx_status = AXGMAC_IOREAD(pdata, tx_dsr);
718 : 0 : tx_status = GET_BITS(tx_status, tx_pos, DMA_DSR_TPS_WIDTH);
719 : 0 : if ((tx_status == DMA_TPS_STOPPED) ||
720 [ # # ]: 0 : (tx_status == DMA_TPS_SUSPENDED))
721 : : break;
722 : :
723 : 0 : rte_delay_us(900);
724 : : }
725 : :
726 [ # # ]: 0 : if (!time_before(rte_get_timer_cycles(), tx_timeout))
727 : 0 : PMD_DRV_LOG_LINE(ERR,
728 : : "timed out waiting for Tx DMA channel %u to stop",
729 : : queue);
730 : : }
731 : :
732 : 0 : void axgbe_dev_disable_tx(struct rte_eth_dev *dev)
733 : : {
734 : : struct axgbe_tx_queue *txq;
735 : 0 : struct axgbe_port *pdata = dev->data->dev_private;
736 : : unsigned int i;
737 : :
738 : : /* Prepare for stopping DMA channel */
739 [ # # ]: 0 : for (i = 0; i < pdata->tx_q_count; i++) {
740 : : txq = dev->data->tx_queues[i];
741 : 0 : axgbe_prepare_tx_stop(pdata, i);
742 : : }
743 : : /* Disable MAC Tx */
744 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
745 : : /* Disable each Tx queue*/
746 [ # # ]: 0 : for (i = 0; i < pdata->tx_q_count; i++)
747 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TXQEN,
748 : : 0);
749 : : /* Disable each Tx DMA channel */
750 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
751 : 0 : txq = dev->data->tx_queues[i];
752 : 0 : AXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, ST, 0);
753 : : }
754 : 0 : }
755 : :
756 : 0 : void axgbe_dev_enable_tx(struct rte_eth_dev *dev)
757 : : {
758 : : struct axgbe_tx_queue *txq;
759 : 0 : struct axgbe_port *pdata = dev->data->dev_private;
760 : : unsigned int i;
761 : :
762 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
763 : 0 : txq = dev->data->tx_queues[i];
764 : : /* Enable Tx DMA channel */
765 : 0 : AXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, ST, 1);
766 : : }
767 : : /* Enable Tx queue*/
768 [ # # ]: 0 : for (i = 0; i < pdata->tx_q_count; i++)
769 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TXQEN,
770 : : MTL_Q_ENABLED);
771 : : /* Enable MAC Tx */
772 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 1);
773 : 0 : }
774 : :
775 : : /* Free Tx conformed mbufs segments */
776 : : static void
777 : 0 : axgbe_xmit_cleanup_seg(struct axgbe_tx_queue *txq)
778 : : {
779 : : volatile struct axgbe_tx_desc *desc;
780 : : uint16_t idx;
781 : :
782 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->dirty);
783 [ # # ]: 0 : while (txq->cur != txq->dirty) {
784 [ # # ]: 0 : if (unlikely(idx == txq->nb_desc))
785 : : idx = 0;
786 : 0 : desc = &txq->desc[idx];
787 : : /* Check for ownership */
788 [ # # ]: 0 : if (AXGMAC_GET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN))
789 : : return;
790 : 0 : memset((void *)&desc->desc2, 0, 8);
791 : : /* Free mbuf */
792 : 0 : rte_pktmbuf_free_seg(txq->sw_ring[idx]);
793 : 0 : txq->sw_ring[idx++] = NULL;
794 : 0 : txq->dirty++;
795 : : }
796 : : }
797 : :
798 : : /* Free Tx conformed mbufs */
799 : 0 : static void axgbe_xmit_cleanup(struct axgbe_tx_queue *txq)
800 : : {
801 : : volatile struct axgbe_tx_desc *desc;
802 : : uint16_t idx;
803 : :
804 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->dirty);
805 [ # # ]: 0 : while (txq->cur != txq->dirty) {
806 [ # # ]: 0 : if (unlikely(idx == txq->nb_desc))
807 : : idx = 0;
808 : 0 : desc = &txq->desc[idx];
809 : : /* Check for ownership */
810 [ # # ]: 0 : if (AXGMAC_GET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN))
811 : : return;
812 : 0 : memset((void *)&desc->desc2, 0, 8);
813 : : /* Free mbuf */
814 : 0 : rte_pktmbuf_free(txq->sw_ring[idx]);
815 : 0 : txq->sw_ring[idx++] = NULL;
816 : 0 : txq->dirty++;
817 : : }
818 : : }
819 : :
820 : : /* Tx Descriptor formation
821 : : * Considering each mbuf requires one desc
822 : : * mbuf is linear
823 : : */
824 : 0 : static int axgbe_xmit_hw(struct axgbe_tx_queue *txq,
825 : : struct rte_mbuf *mbuf)
826 : : {
827 : : volatile struct axgbe_tx_desc *desc;
828 : : uint16_t idx;
829 : : uint64_t mask;
830 : : int start_index;
831 : : uint64_t l2_len = 0;
832 : : uint64_t l3_len = 0;
833 : : uint64_t l4_len = 0;
834 : : uint64_t tso_segz = 0;
835 : : uint64_t total_hdr_len;
836 : : int tso = 0;
837 : :
838 : : /*Parameters required for tso*/
839 : 0 : l2_len = mbuf->l2_len;
840 : 0 : l3_len = mbuf->l3_len;
841 : 0 : l4_len = mbuf->l4_len;
842 : 0 : total_hdr_len = l2_len + l3_len + l4_len;
843 : 0 : tso_segz = mbuf->tso_segsz;
844 : :
845 [ # # ]: 0 : if (txq->pdata->tso_tx)
846 : : tso = 1;
847 : : else
848 : : tso = 0;
849 : :
850 : 0 : AXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_CR, MSS, tso_segz);
851 : :
852 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->cur);
853 : 0 : desc = &txq->desc[idx];
854 : :
855 : : /* Saving the start index for setting the OWN bit finally */
856 : : start_index = idx;
857 [ # # ]: 0 : if (tso) {
858 : : /* Update buffer address and length */
859 : 0 : desc->baddr = rte_mbuf_data_iova(mbuf);
860 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, HL_B1L,
861 : : total_hdr_len);
862 : : } else {
863 : : /* Update buffer address and length */
864 : 0 : desc->baddr = rte_mbuf_data_iova(mbuf);
865 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, HL_B1L,
866 : : mbuf->pkt_len);
867 : : /* Total msg length to transmit */
868 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, FL,
869 : : mbuf->pkt_len);
870 : : }
871 : : /* Timestamp enablement check */
872 [ # # ]: 0 : if (mbuf->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST)
873 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, TTSE, 1);
874 : : rte_wmb();
875 : : /* Mark it as First and Last Descriptor */
876 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, FD, 1);
877 : : /* Mark it as a NORMAL descriptor */
878 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CTXT, 0);
879 [ # # ]: 0 : if (tso) {
880 : : /*Register settings for TSO*/
881 : : /* Enable TSO */
882 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, TSE, 1);
883 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, TPL,
884 : : ((mbuf->pkt_len) - total_hdr_len));
885 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, THL,
886 : : (l4_len / 4));
887 : : rte_wmb();
888 : 0 : txq->cur++;
889 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->cur);
890 : 0 : desc = &txq->desc[idx];
891 : 0 : desc->baddr = rte_mbuf_data_iova(mbuf);
892 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, HL_B1L,
893 : : (mbuf->pkt_len) - total_hdr_len);
894 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN, 1);
895 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, LD, 1);
896 : : /* Mark it as a NORMAL descriptor */
897 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CTXT, 0);
898 : : } else {
899 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, LD, 1);
900 : : }
901 : : /* configure h/w Offload */
902 : 0 : mask = mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK;
903 [ # # ]: 0 : if (mask == RTE_MBUF_F_TX_TCP_CKSUM || mask == RTE_MBUF_F_TX_UDP_CKSUM)
904 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CIC, 0x3);
905 [ # # ]: 0 : else if (mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
906 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CIC, 0x1);
907 : : rte_wmb();
908 : :
909 [ # # ]: 0 : if (mbuf->ol_flags & (RTE_MBUF_F_TX_VLAN | RTE_MBUF_F_TX_QINQ)) {
910 : : /* Mark it as a CONTEXT descriptor */
911 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_CONTEXT_DESC3,
912 : : CTXT, 1);
913 : : /* Set the VLAN tag */
914 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_CONTEXT_DESC3,
915 : : VT, mbuf->vlan_tci);
916 : : /* Indicate this descriptor contains the VLAN tag */
917 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_CONTEXT_DESC3,
918 : : VLTV, 1);
919 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, VTIR,
920 : : TX_NORMAL_DESC2_VLAN_INSERT);
921 : : } else {
922 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, VTIR, 0x0);
923 : : }
924 : :
925 [ # # ]: 0 : if (!tso) {
926 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN, 1);
927 : : rte_wmb();
928 : : } else {
929 : : /* Set OWN bit for the first descriptor */
930 : 0 : desc = &txq->desc[start_index];
931 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN, 1);
932 : : rte_wmb();
933 : : }
934 : :
935 : : /* Save mbuf */
936 : 0 : txq->sw_ring[idx] = mbuf;
937 : : /* Update current index*/
938 : 0 : txq->cur++;
939 : : /* Update stats */
940 : 0 : txq->bytes += mbuf->pkt_len;
941 : :
942 : 0 : return 0;
943 : : }
944 : :
945 : : /* Tx Descriptor formation for segmented mbuf
946 : : * Each mbuf will require multiple descriptors
947 : : */
948 : :
949 : : static int
950 : 0 : axgbe_xmit_hw_seg(struct axgbe_tx_queue *txq,
951 : : struct rte_mbuf *mbuf)
952 : : {
953 : : volatile struct axgbe_tx_desc *desc;
954 : : uint16_t idx;
955 : : uint64_t mask;
956 : : int start_index;
957 : : uint32_t pkt_len = 0;
958 : : int nb_desc_free;
959 : : struct rte_mbuf *tx_pkt;
960 : : uint32_t tso = 0;
961 : :
962 : 0 : nb_desc_free = txq->nb_desc - (txq->cur - txq->dirty);
963 : :
964 [ # # ]: 0 : if (mbuf->nb_segs > nb_desc_free) {
965 : 0 : axgbe_xmit_cleanup_seg(txq);
966 : 0 : nb_desc_free = txq->nb_desc - (txq->cur - txq->dirty);
967 [ # # ]: 0 : if (unlikely(mbuf->nb_segs > nb_desc_free))
968 : : return RTE_ETH_TX_DESC_UNAVAIL;
969 : : }
970 : :
971 [ # # ]: 0 : if (txq->pdata->tso_tx)
972 : : tso = 1;
973 : : else
974 : : tso = 0;
975 : :
976 : : if (tso) {
977 : 0 : axgbe_xmit_hw(txq, mbuf);
978 : : } else {
979 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->cur);
980 : 0 : desc = &txq->desc[idx];
981 : : /* Saving the start index for setting the OWN bit finally */
982 : : start_index = idx;
983 : : tx_pkt = mbuf;
984 : : /* Max_pkt len = 9018 ; need to update it according to Jumbo pkt size */
985 [ # # ]: 0 : pkt_len = tx_pkt->pkt_len;
986 : :
987 : : /* Update buffer address and length */
988 : 0 : desc->baddr = rte_mbuf_data_iova(tx_pkt);
989 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, HL_B1L,
990 : : tx_pkt->data_len);
991 : : /* Total msg length to transmit */
992 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, FL,
993 : : tx_pkt->pkt_len);
994 : : /* Timestamp enablement check */
995 [ # # ]: 0 : if (mbuf->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST)
996 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, TTSE, 1);
997 : : rte_wmb();
998 : : /* Mark it as First Descriptor */
999 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, FD, 1);
1000 : : /* Mark it as a NORMAL descriptor */
1001 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CTXT, 0);
1002 : : /* configure h/w Offload */
1003 : 0 : mask = mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK;
1004 [ # # ]: 0 : if (mask == RTE_MBUF_F_TX_TCP_CKSUM || mask == RTE_MBUF_F_TX_UDP_CKSUM)
1005 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CIC, 0x3);
1006 [ # # ]: 0 : else if (mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
1007 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CIC, 0x1);
1008 : : rte_wmb();
1009 [ # # ]: 0 : if (mbuf->ol_flags & (RTE_MBUF_F_TX_VLAN | RTE_MBUF_F_TX_QINQ)) {
1010 : : /* Mark it as a CONTEXT descriptor */
1011 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_CONTEXT_DESC3,
1012 : : CTXT, 1);
1013 : : /* Set the VLAN tag */
1014 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_CONTEXT_DESC3,
1015 : : VT, mbuf->vlan_tci);
1016 : : /* Indicate this descriptor contains the VLAN tag */
1017 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_CONTEXT_DESC3,
1018 : : VLTV, 1);
1019 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, VTIR,
1020 : : TX_NORMAL_DESC2_VLAN_INSERT);
1021 : : } else {
1022 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, VTIR, 0x0);
1023 : : }
1024 : : rte_wmb();
1025 : : /* Save mbuf */
1026 : 0 : txq->sw_ring[idx] = tx_pkt;
1027 : : /* Update current index*/
1028 : 0 : txq->cur++;
1029 : 0 : tx_pkt = tx_pkt->next;
1030 [ # # ]: 0 : while (tx_pkt != NULL) {
1031 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->cur);
1032 : 0 : desc = &txq->desc[idx];
1033 : : /* Update buffer address and length */
1034 : 0 : desc->baddr = rte_mbuf_data_iova(tx_pkt);
1035 : 0 : AXGMAC_SET_BITS_LE(desc->desc2,
1036 : : TX_NORMAL_DESC2, HL_B1L, tx_pkt->data_len);
1037 : : rte_wmb();
1038 : : /* Mark it as a NORMAL descriptor */
1039 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CTXT, 0);
1040 : : /* configure h/w Offload */
1041 : 0 : mask = mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK;
1042 : 0 : if (mask == RTE_MBUF_F_TX_TCP_CKSUM ||
1043 [ # # ]: 0 : mask == RTE_MBUF_F_TX_UDP_CKSUM)
1044 : 0 : AXGMAC_SET_BITS_LE(desc->desc3,
1045 : : TX_NORMAL_DESC3, CIC, 0x3);
1046 [ # # ]: 0 : else if (mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
1047 : 0 : AXGMAC_SET_BITS_LE(desc->desc3,
1048 : : TX_NORMAL_DESC3, CIC, 0x1);
1049 : : rte_wmb();
1050 : : /* Set OWN bit */
1051 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN, 1);
1052 : : rte_wmb();
1053 : : /* Save mbuf */
1054 : 0 : txq->sw_ring[idx] = tx_pkt;
1055 : : /* Update current index*/
1056 : 0 : txq->cur++;
1057 : 0 : tx_pkt = tx_pkt->next;
1058 : : }
1059 : :
1060 : : /* Set LD bit for the last descriptor */
1061 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, LD, 1);
1062 : : rte_wmb();
1063 : :
1064 : : /* Update stats */
1065 : 0 : txq->bytes += pkt_len;
1066 : :
1067 : : /* Set OWN bit for the first descriptor */
1068 : 0 : desc = &txq->desc[start_index];
1069 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN, 1);
1070 : : rte_wmb();
1071 : : }
1072 : : return 0;
1073 : : }
1074 : :
1075 : : /* Eal supported tx wrapper- Segmented*/
1076 : : uint16_t
1077 : 0 : axgbe_xmit_pkts_seg(void *tx_queue, struct rte_mbuf **tx_pkts,
1078 : : uint16_t nb_pkts)
1079 : : {
1080 : : PMD_INIT_FUNC_TRACE();
1081 : :
1082 : : struct axgbe_tx_queue *txq;
1083 : : uint16_t nb_desc_free;
1084 : : uint16_t nb_pkt_sent = 0;
1085 : : uint16_t idx;
1086 : : uint32_t tail_addr;
1087 : : struct rte_mbuf *mbuf = NULL;
1088 : :
1089 [ # # ]: 0 : if (unlikely(nb_pkts == 0))
1090 : : return nb_pkts;
1091 : :
1092 : : txq = (struct axgbe_tx_queue *)tx_queue;
1093 : :
1094 : 0 : nb_desc_free = txq->nb_desc - (txq->cur - txq->dirty);
1095 [ # # ]: 0 : if (unlikely(nb_desc_free <= txq->free_thresh)) {
1096 : 0 : axgbe_xmit_cleanup_seg(txq);
1097 : 0 : nb_desc_free = txq->nb_desc - (txq->cur - txq->dirty);
1098 [ # # ]: 0 : if (unlikely(nb_desc_free == 0))
1099 : : return 0;
1100 : : }
1101 : :
1102 [ # # ]: 0 : while (nb_pkts--) {
1103 : 0 : mbuf = *tx_pkts++;
1104 : :
1105 [ # # ]: 0 : if (axgbe_xmit_hw_seg(txq, mbuf))
1106 : 0 : goto out;
1107 : 0 : nb_pkt_sent++;
1108 : : }
1109 : 0 : out:
1110 : : /* Sync read and write */
1111 : : rte_mb();
1112 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->cur);
1113 : 0 : tail_addr = low32_value(txq->ring_phys_addr +
1114 : 0 : idx * sizeof(struct axgbe_tx_desc));
1115 : : /* Update tail reg with next immediate address to kick Tx DMA channel*/
1116 : 0 : AXGMAC_DMA_IOWRITE(txq, DMA_CH_TDTR_LO, tail_addr);
1117 : 0 : txq->pkts += nb_pkt_sent;
1118 : 0 : return nb_pkt_sent;
1119 : : }
1120 : :
1121 : : /* Eal supported tx wrapper*/
1122 : : uint16_t
1123 : 0 : axgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
1124 : : uint16_t nb_pkts)
1125 : : {
1126 : : PMD_INIT_FUNC_TRACE();
1127 : :
1128 [ # # ]: 0 : if (unlikely(nb_pkts == 0))
1129 : : return nb_pkts;
1130 : :
1131 : : struct axgbe_tx_queue *txq;
1132 : : uint16_t nb_desc_free;
1133 : : uint16_t nb_pkt_sent = 0;
1134 : : uint16_t idx;
1135 : : uint32_t tail_addr;
1136 : : struct rte_mbuf *mbuf;
1137 : :
1138 : : txq = (struct axgbe_tx_queue *)tx_queue;
1139 : 0 : nb_desc_free = txq->nb_desc - (txq->cur - txq->dirty);
1140 : :
1141 [ # # ]: 0 : if (unlikely(nb_desc_free <= txq->free_thresh)) {
1142 : 0 : axgbe_xmit_cleanup(txq);
1143 : 0 : nb_desc_free = txq->nb_desc - (txq->cur - txq->dirty);
1144 [ # # ]: 0 : if (unlikely(nb_desc_free == 0))
1145 : : return 0;
1146 : : }
1147 : 0 : nb_pkts = RTE_MIN(nb_desc_free, nb_pkts);
1148 [ # # ]: 0 : while (nb_pkts--) {
1149 : 0 : mbuf = *tx_pkts++;
1150 [ # # ]: 0 : if (axgbe_xmit_hw(txq, mbuf))
1151 : 0 : goto out;
1152 : 0 : nb_pkt_sent++;
1153 : : }
1154 : 0 : out:
1155 : : /* Sync read and write */
1156 : : rte_mb();
1157 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->cur);
1158 : 0 : tail_addr = low32_value(txq->ring_phys_addr +
1159 : 0 : idx * sizeof(struct axgbe_tx_desc));
1160 : : /* Update tail reg with next immediate address to kick Tx DMA channel*/
1161 : 0 : AXGMAC_DMA_IOWRITE(txq, DMA_CH_TDTR_LO, tail_addr);
1162 : 0 : txq->pkts += nb_pkt_sent;
1163 : 0 : return nb_pkt_sent;
1164 : : }
1165 : :
1166 : 0 : void axgbe_dev_clear_queues(struct rte_eth_dev *dev)
1167 : : {
1168 : : PMD_INIT_FUNC_TRACE();
1169 : : uint8_t i;
1170 : : struct axgbe_rx_queue *rxq;
1171 : : struct axgbe_tx_queue *txq;
1172 : :
1173 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
1174 : 0 : rxq = dev->data->rx_queues[i];
1175 : :
1176 [ # # ]: 0 : if (rxq) {
1177 : 0 : axgbe_rx_queue_release(rxq);
1178 : 0 : dev->data->rx_queues[i] = NULL;
1179 : : }
1180 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
1181 : : }
1182 : :
1183 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
1184 : 0 : txq = dev->data->tx_queues[i];
1185 : :
1186 [ # # ]: 0 : if (txq) {
1187 : 0 : axgbe_tx_queue_release(txq);
1188 : 0 : dev->data->tx_queues[i] = NULL;
1189 : : }
1190 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
1191 : : }
1192 : 0 : }
1193 : :
1194 : : int
1195 : 0 : axgbe_dev_rx_descriptor_status(void *rx_queue, uint16_t offset)
1196 : : {
1197 : : struct axgbe_rx_queue *rxq = rx_queue;
1198 : : volatile union axgbe_rx_desc *desc;
1199 : : uint16_t idx;
1200 : :
1201 : :
1202 [ # # ]: 0 : if (unlikely(offset >= rxq->nb_desc))
1203 : : return -EINVAL;
1204 : :
1205 [ # # ]: 0 : if (offset >= rxq->nb_desc - rxq->dirty)
1206 : : return RTE_ETH_RX_DESC_UNAVAIL;
1207 : :
1208 : 0 : idx = AXGBE_GET_DESC_IDX(rxq, rxq->cur);
1209 : 0 : desc = &rxq->desc[idx + offset];
1210 : :
1211 [ # # ]: 0 : if (!AXGMAC_GET_BITS_LE(desc->write.desc3, RX_NORMAL_DESC3, OWN))
1212 : 0 : return RTE_ETH_RX_DESC_DONE;
1213 : :
1214 : : return RTE_ETH_RX_DESC_AVAIL;
1215 : : }
1216 : :
1217 : : int
1218 : 0 : axgbe_dev_tx_descriptor_status(void *tx_queue, uint16_t offset)
1219 : : {
1220 : : struct axgbe_tx_queue *txq = tx_queue;
1221 : : volatile struct axgbe_tx_desc *desc;
1222 : : uint16_t idx;
1223 : :
1224 : :
1225 [ # # ]: 0 : if (unlikely(offset >= txq->nb_desc))
1226 : : return -EINVAL;
1227 : :
1228 [ # # ]: 0 : if (offset >= txq->nb_desc - txq->dirty)
1229 : : return RTE_ETH_TX_DESC_UNAVAIL;
1230 : :
1231 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->dirty + txq->free_batch_cnt - 1);
1232 : 0 : desc = &txq->desc[idx + offset];
1233 : :
1234 [ # # ]: 0 : if (!AXGMAC_GET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN))
1235 : 0 : return RTE_ETH_TX_DESC_DONE;
1236 : :
1237 : : return RTE_ETH_TX_DESC_FULL;
1238 : : }
|