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 : :
631 : : return 0;
632 : : }
633 : :
634 : 0 : int axgbe_dev_fw_version_get(struct rte_eth_dev *eth_dev,
635 : : char *fw_version, size_t fw_size)
636 : : {
637 : : struct axgbe_port *pdata;
638 : : struct axgbe_hw_features *hw_feat;
639 : : int ret;
640 : :
641 : 0 : pdata = (struct axgbe_port *)eth_dev->data->dev_private;
642 : : hw_feat = &pdata->hw_feat;
643 : :
644 : 0 : ret = snprintf(fw_version, fw_size, "%d.%d.%d",
645 : 0 : AXGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER),
646 : 0 : AXGMAC_GET_BITS(hw_feat->version, MAC_VR, DEVID),
647 [ # # ]: 0 : AXGMAC_GET_BITS(hw_feat->version, MAC_VR, SNPSVER));
648 [ # # ]: 0 : if (ret < 0)
649 : : return -EINVAL;
650 : :
651 : 0 : ret += 1; /* add the size of '\0' */
652 [ # # ]: 0 : if (fw_size < (size_t)ret)
653 : : return ret;
654 : : else
655 : 0 : return 0;
656 : : }
657 : :
658 : 0 : static void axgbe_txq_prepare_tx_stop(struct axgbe_port *pdata,
659 : : unsigned int queue)
660 : : {
661 : : unsigned int tx_status;
662 : : unsigned long tx_timeout;
663 : :
664 : : /* The Tx engine cannot be stopped if it is actively processing
665 : : * packets. Wait for the Tx queue to empty the Tx fifo. Don't
666 : : * wait forever though...
667 : : */
668 : 0 : tx_timeout = rte_get_timer_cycles() + (AXGBE_DMA_STOP_TIMEOUT *
669 : : rte_get_timer_hz());
670 [ # # ]: 0 : while (time_before(rte_get_timer_cycles(), tx_timeout)) {
671 : 0 : tx_status = AXGMAC_MTL_IOREAD(pdata, queue, MTL_Q_TQDR);
672 [ # # ]: 0 : if ((AXGMAC_GET_BITS(tx_status, MTL_Q_TQDR, TRCSTS) != 1) &&
673 [ # # ]: 0 : (AXGMAC_GET_BITS(tx_status, MTL_Q_TQDR, TXQSTS) == 0))
674 : : break;
675 : :
676 : 0 : rte_delay_us(900);
677 : : }
678 : :
679 [ # # ]: 0 : if (!time_before(rte_get_timer_cycles(), tx_timeout))
680 : 0 : PMD_DRV_LOG_LINE(ERR,
681 : : "timed out waiting for Tx queue %u to empty",
682 : : queue);
683 : 0 : }
684 : :
685 : 0 : static void axgbe_prepare_tx_stop(struct axgbe_port *pdata,
686 : : unsigned int queue)
687 : : {
688 : : unsigned int tx_dsr, tx_pos, tx_qidx;
689 : : unsigned int tx_status;
690 : : unsigned long tx_timeout;
691 : :
692 [ # # ]: 0 : if (AXGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) > 0x20)
693 : 0 : return axgbe_txq_prepare_tx_stop(pdata, queue);
694 : :
695 : : /* Calculate the status register to read and the position within */
696 [ # # ]: 0 : if (queue < DMA_DSRX_FIRST_QUEUE) {
697 : : tx_dsr = DMA_DSR0;
698 : 0 : tx_pos = (queue * DMA_DSR_Q_WIDTH) + DMA_DSR0_TPS_START;
699 : : } else {
700 : 0 : tx_qidx = queue - DMA_DSRX_FIRST_QUEUE;
701 : :
702 : 0 : tx_dsr = DMA_DSR1 + ((tx_qidx / DMA_DSRX_QPR) * DMA_DSRX_INC);
703 : 0 : tx_pos = ((tx_qidx % DMA_DSRX_QPR) * DMA_DSR_Q_WIDTH) +
704 : : DMA_DSRX_TPS_START;
705 : : }
706 : :
707 : : /* The Tx engine cannot be stopped if it is actively processing
708 : : * descriptors. Wait for the Tx engine to enter the stopped or
709 : : * suspended state. Don't wait forever though...
710 : : */
711 : 0 : tx_timeout = rte_get_timer_cycles() + (AXGBE_DMA_STOP_TIMEOUT *
712 : : rte_get_timer_hz());
713 [ # # ]: 0 : while (time_before(rte_get_timer_cycles(), tx_timeout)) {
714 : 0 : tx_status = AXGMAC_IOREAD(pdata, tx_dsr);
715 : 0 : tx_status = GET_BITS(tx_status, tx_pos, DMA_DSR_TPS_WIDTH);
716 : 0 : if ((tx_status == DMA_TPS_STOPPED) ||
717 [ # # ]: 0 : (tx_status == DMA_TPS_SUSPENDED))
718 : : break;
719 : :
720 : 0 : rte_delay_us(900);
721 : : }
722 : :
723 [ # # ]: 0 : if (!time_before(rte_get_timer_cycles(), tx_timeout))
724 : 0 : PMD_DRV_LOG_LINE(ERR,
725 : : "timed out waiting for Tx DMA channel %u to stop",
726 : : queue);
727 : : }
728 : :
729 : 0 : void axgbe_dev_disable_tx(struct rte_eth_dev *dev)
730 : : {
731 : : struct axgbe_tx_queue *txq;
732 : 0 : struct axgbe_port *pdata = dev->data->dev_private;
733 : : unsigned int i;
734 : :
735 : : /* Prepare for stopping DMA channel */
736 [ # # ]: 0 : for (i = 0; i < pdata->tx_q_count; i++) {
737 : : txq = dev->data->tx_queues[i];
738 : 0 : axgbe_prepare_tx_stop(pdata, i);
739 : : }
740 : : /* Disable MAC Tx */
741 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
742 : : /* Disable each Tx queue*/
743 [ # # ]: 0 : for (i = 0; i < pdata->tx_q_count; i++)
744 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TXQEN,
745 : : 0);
746 : : /* Disable each Tx DMA channel */
747 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
748 : 0 : txq = dev->data->tx_queues[i];
749 : 0 : AXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, ST, 0);
750 : : }
751 : 0 : }
752 : :
753 : 0 : void axgbe_dev_enable_tx(struct rte_eth_dev *dev)
754 : : {
755 : : struct axgbe_tx_queue *txq;
756 : 0 : struct axgbe_port *pdata = dev->data->dev_private;
757 : : unsigned int i;
758 : :
759 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
760 : 0 : txq = dev->data->tx_queues[i];
761 : : /* Enable Tx DMA channel */
762 : 0 : AXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, ST, 1);
763 : : }
764 : : /* Enable Tx queue*/
765 [ # # ]: 0 : for (i = 0; i < pdata->tx_q_count; i++)
766 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TXQEN,
767 : : MTL_Q_ENABLED);
768 : : /* Enable MAC Tx */
769 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 1);
770 : 0 : }
771 : :
772 : : /* Free Tx conformed mbufs segments */
773 : : static void
774 : 0 : axgbe_xmit_cleanup_seg(struct axgbe_tx_queue *txq)
775 : : {
776 : : volatile struct axgbe_tx_desc *desc;
777 : : uint16_t idx;
778 : :
779 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->dirty);
780 [ # # ]: 0 : while (txq->cur != txq->dirty) {
781 [ # # ]: 0 : if (unlikely(idx == txq->nb_desc))
782 : : idx = 0;
783 : 0 : desc = &txq->desc[idx];
784 : : /* Check for ownership */
785 [ # # ]: 0 : if (AXGMAC_GET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN))
786 : : return;
787 : 0 : memset((void *)&desc->desc2, 0, 8);
788 : : /* Free mbuf */
789 : 0 : rte_pktmbuf_free_seg(txq->sw_ring[idx]);
790 : 0 : txq->sw_ring[idx++] = NULL;
791 : 0 : txq->dirty++;
792 : : }
793 : : }
794 : :
795 : : /* Free Tx conformed mbufs */
796 : 0 : static void axgbe_xmit_cleanup(struct axgbe_tx_queue *txq)
797 : : {
798 : : volatile struct axgbe_tx_desc *desc;
799 : : uint16_t idx;
800 : :
801 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->dirty);
802 [ # # ]: 0 : while (txq->cur != txq->dirty) {
803 [ # # ]: 0 : if (unlikely(idx == txq->nb_desc))
804 : : idx = 0;
805 : 0 : desc = &txq->desc[idx];
806 : : /* Check for ownership */
807 [ # # ]: 0 : if (AXGMAC_GET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN))
808 : : return;
809 : 0 : memset((void *)&desc->desc2, 0, 8);
810 : : /* Free mbuf */
811 : 0 : rte_pktmbuf_free(txq->sw_ring[idx]);
812 : 0 : txq->sw_ring[idx++] = NULL;
813 : 0 : txq->dirty++;
814 : : }
815 : : }
816 : :
817 : : /* Tx Descriptor formation
818 : : * Considering each mbuf requires one desc
819 : : * mbuf is linear
820 : : */
821 : 0 : static int axgbe_xmit_hw(struct axgbe_tx_queue *txq,
822 : : struct rte_mbuf *mbuf)
823 : : {
824 : : volatile struct axgbe_tx_desc *desc;
825 : : uint16_t idx;
826 : : uint64_t mask;
827 : :
828 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->cur);
829 [ # # ]: 0 : desc = &txq->desc[idx];
830 : :
831 : : /* Update buffer address and length */
832 : 0 : desc->baddr = rte_mbuf_data_iova(mbuf);
833 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, HL_B1L,
834 : : mbuf->pkt_len);
835 : : /* Total msg length to transmit */
836 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, FL,
837 : : mbuf->pkt_len);
838 : : /* Timestamp enablement check */
839 [ # # ]: 0 : if (mbuf->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST)
840 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, TTSE, 1);
841 : : rte_wmb();
842 : : /* Mark it as First and Last Descriptor */
843 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, FD, 1);
844 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, LD, 1);
845 : : /* Mark it as a NORMAL descriptor */
846 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CTXT, 0);
847 : : /* configure h/w Offload */
848 : 0 : mask = mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK;
849 [ # # ]: 0 : if (mask == RTE_MBUF_F_TX_TCP_CKSUM || mask == RTE_MBUF_F_TX_UDP_CKSUM)
850 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CIC, 0x3);
851 [ # # ]: 0 : else if (mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
852 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CIC, 0x1);
853 : : rte_wmb();
854 : :
855 [ # # ]: 0 : if (mbuf->ol_flags & (RTE_MBUF_F_TX_VLAN | RTE_MBUF_F_TX_QINQ)) {
856 : : /* Mark it as a CONTEXT descriptor */
857 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_CONTEXT_DESC3,
858 : : CTXT, 1);
859 : : /* Set the VLAN tag */
860 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_CONTEXT_DESC3,
861 : : VT, mbuf->vlan_tci);
862 : : /* Indicate this descriptor contains the VLAN tag */
863 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_CONTEXT_DESC3,
864 : : VLTV, 1);
865 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, VTIR,
866 : : TX_NORMAL_DESC2_VLAN_INSERT);
867 : : } else {
868 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, VTIR, 0x0);
869 : : }
870 : : rte_wmb();
871 : :
872 : : /* Set OWN bit */
873 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN, 1);
874 : : rte_wmb();
875 : :
876 : :
877 : : /* Save mbuf */
878 : 0 : txq->sw_ring[idx] = mbuf;
879 : : /* Update current index*/
880 : 0 : txq->cur++;
881 : : /* Update stats */
882 : 0 : txq->bytes += mbuf->pkt_len;
883 : :
884 : 0 : return 0;
885 : : }
886 : :
887 : : /* Tx Descriptor formation for segmented mbuf
888 : : * Each mbuf will require multiple descriptors
889 : : */
890 : :
891 : : static int
892 : 0 : axgbe_xmit_hw_seg(struct axgbe_tx_queue *txq,
893 : : struct rte_mbuf *mbuf)
894 : : {
895 : : volatile struct axgbe_tx_desc *desc;
896 : : uint16_t idx;
897 : : uint64_t mask;
898 : : int start_index;
899 : : uint32_t pkt_len = 0;
900 : : int nb_desc_free;
901 : : struct rte_mbuf *tx_pkt;
902 : :
903 : 0 : nb_desc_free = txq->nb_desc - (txq->cur - txq->dirty);
904 : :
905 [ # # ]: 0 : if (mbuf->nb_segs > nb_desc_free) {
906 : 0 : axgbe_xmit_cleanup_seg(txq);
907 : 0 : nb_desc_free = txq->nb_desc - (txq->cur - txq->dirty);
908 [ # # ]: 0 : if (unlikely(mbuf->nb_segs > nb_desc_free))
909 : : return RTE_ETH_TX_DESC_UNAVAIL;
910 : : }
911 : :
912 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->cur);
913 : 0 : desc = &txq->desc[idx];
914 : : /* Saving the start index for setting the OWN bit finally */
915 : : start_index = idx;
916 : :
917 : : tx_pkt = mbuf;
918 : : /* Max_pkt len = 9018 ; need to update it according to Jumbo pkt size */
919 [ # # ]: 0 : pkt_len = tx_pkt->pkt_len;
920 : :
921 : : /* Update buffer address and length */
922 : 0 : desc->baddr = rte_mbuf_data_iova(tx_pkt);
923 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, HL_B1L,
924 : : tx_pkt->data_len);
925 : : /* Total msg length to transmit */
926 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, FL,
927 : : tx_pkt->pkt_len);
928 : : /* Timestamp enablement check */
929 [ # # ]: 0 : if (mbuf->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST)
930 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, TTSE, 1);
931 : :
932 : : rte_wmb();
933 : : /* Mark it as First Descriptor */
934 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, FD, 1);
935 : : /* Mark it as a NORMAL descriptor */
936 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CTXT, 0);
937 : : /* configure h/w Offload */
938 : 0 : mask = mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK;
939 [ # # ]: 0 : if (mask == RTE_MBUF_F_TX_TCP_CKSUM || mask == RTE_MBUF_F_TX_UDP_CKSUM)
940 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CIC, 0x3);
941 [ # # ]: 0 : else if (mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
942 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CIC, 0x1);
943 : : rte_wmb();
944 : :
945 [ # # ]: 0 : if (mbuf->ol_flags & (RTE_MBUF_F_TX_VLAN | RTE_MBUF_F_TX_QINQ)) {
946 : : /* Mark it as a CONTEXT descriptor */
947 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_CONTEXT_DESC3,
948 : : CTXT, 1);
949 : : /* Set the VLAN tag */
950 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_CONTEXT_DESC3,
951 : : VT, mbuf->vlan_tci);
952 : : /* Indicate this descriptor contains the VLAN tag */
953 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_CONTEXT_DESC3,
954 : : VLTV, 1);
955 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, VTIR,
956 : : TX_NORMAL_DESC2_VLAN_INSERT);
957 : : } else {
958 : 0 : AXGMAC_SET_BITS_LE(desc->desc2, TX_NORMAL_DESC2, VTIR, 0x0);
959 : : }
960 : : rte_wmb();
961 : :
962 : : /* Save mbuf */
963 : 0 : txq->sw_ring[idx] = tx_pkt;
964 : : /* Update current index*/
965 : 0 : txq->cur++;
966 : :
967 : 0 : tx_pkt = tx_pkt->next;
968 : :
969 [ # # ]: 0 : while (tx_pkt != NULL) {
970 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->cur);
971 : 0 : desc = &txq->desc[idx];
972 : :
973 : : /* Update buffer address and length */
974 : 0 : desc->baddr = rte_mbuf_data_iova(tx_pkt);
975 : :
976 : 0 : AXGMAC_SET_BITS_LE(desc->desc2,
977 : : TX_NORMAL_DESC2, HL_B1L, tx_pkt->data_len);
978 : :
979 : : rte_wmb();
980 : :
981 : : /* Mark it as a NORMAL descriptor */
982 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, CTXT, 0);
983 : : /* configure h/w Offload */
984 : 0 : mask = mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK;
985 : 0 : if (mask == RTE_MBUF_F_TX_TCP_CKSUM ||
986 [ # # ]: 0 : mask == RTE_MBUF_F_TX_UDP_CKSUM)
987 : 0 : AXGMAC_SET_BITS_LE(desc->desc3,
988 : : TX_NORMAL_DESC3, CIC, 0x3);
989 [ # # ]: 0 : else if (mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
990 : 0 : AXGMAC_SET_BITS_LE(desc->desc3,
991 : : TX_NORMAL_DESC3, CIC, 0x1);
992 : :
993 : : rte_wmb();
994 : :
995 : : /* Set OWN bit */
996 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN, 1);
997 : : rte_wmb();
998 : :
999 : : /* Save mbuf */
1000 : 0 : txq->sw_ring[idx] = tx_pkt;
1001 : : /* Update current index*/
1002 : 0 : txq->cur++;
1003 : :
1004 : 0 : tx_pkt = tx_pkt->next;
1005 : : }
1006 : :
1007 : : /* Set LD bit for the last descriptor */
1008 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, LD, 1);
1009 : : rte_wmb();
1010 : :
1011 : : /* Update stats */
1012 : 0 : txq->bytes += pkt_len;
1013 : :
1014 : : /* Set OWN bit for the first descriptor */
1015 : 0 : desc = &txq->desc[start_index];
1016 : 0 : AXGMAC_SET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN, 1);
1017 : : rte_wmb();
1018 : :
1019 : 0 : return 0;
1020 : : }
1021 : :
1022 : : /* Eal supported tx wrapper- Segmented*/
1023 : : uint16_t
1024 : 0 : axgbe_xmit_pkts_seg(void *tx_queue, struct rte_mbuf **tx_pkts,
1025 : : uint16_t nb_pkts)
1026 : : {
1027 : : PMD_INIT_FUNC_TRACE();
1028 : :
1029 : : struct axgbe_tx_queue *txq;
1030 : : uint16_t nb_desc_free;
1031 : : uint16_t nb_pkt_sent = 0;
1032 : : uint16_t idx;
1033 : : uint32_t tail_addr;
1034 : : struct rte_mbuf *mbuf = NULL;
1035 : :
1036 [ # # ]: 0 : if (unlikely(nb_pkts == 0))
1037 : : return nb_pkts;
1038 : :
1039 : : txq = (struct axgbe_tx_queue *)tx_queue;
1040 : :
1041 : 0 : nb_desc_free = txq->nb_desc - (txq->cur - txq->dirty);
1042 [ # # ]: 0 : if (unlikely(nb_desc_free <= txq->free_thresh)) {
1043 : 0 : axgbe_xmit_cleanup_seg(txq);
1044 : 0 : nb_desc_free = txq->nb_desc - (txq->cur - txq->dirty);
1045 [ # # ]: 0 : if (unlikely(nb_desc_free == 0))
1046 : : return 0;
1047 : : }
1048 : :
1049 [ # # ]: 0 : while (nb_pkts--) {
1050 : 0 : mbuf = *tx_pkts++;
1051 : :
1052 [ # # ]: 0 : if (axgbe_xmit_hw_seg(txq, mbuf))
1053 : 0 : goto out;
1054 : 0 : nb_pkt_sent++;
1055 : : }
1056 : 0 : out:
1057 : : /* Sync read and write */
1058 : : rte_mb();
1059 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->cur);
1060 : 0 : tail_addr = low32_value(txq->ring_phys_addr +
1061 : 0 : idx * sizeof(struct axgbe_tx_desc));
1062 : : /* Update tail reg with next immediate address to kick Tx DMA channel*/
1063 : 0 : AXGMAC_DMA_IOWRITE(txq, DMA_CH_TDTR_LO, tail_addr);
1064 : 0 : txq->pkts += nb_pkt_sent;
1065 : 0 : return nb_pkt_sent;
1066 : : }
1067 : :
1068 : : /* Eal supported tx wrapper*/
1069 : : uint16_t
1070 : 0 : axgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
1071 : : uint16_t nb_pkts)
1072 : : {
1073 : : PMD_INIT_FUNC_TRACE();
1074 : :
1075 [ # # ]: 0 : if (unlikely(nb_pkts == 0))
1076 : : return nb_pkts;
1077 : :
1078 : : struct axgbe_tx_queue *txq;
1079 : : uint16_t nb_desc_free;
1080 : : uint16_t nb_pkt_sent = 0;
1081 : : uint16_t idx;
1082 : : uint32_t tail_addr;
1083 : : struct rte_mbuf *mbuf;
1084 : :
1085 : : txq = (struct axgbe_tx_queue *)tx_queue;
1086 : 0 : nb_desc_free = txq->nb_desc - (txq->cur - txq->dirty);
1087 : :
1088 [ # # ]: 0 : if (unlikely(nb_desc_free <= txq->free_thresh)) {
1089 : 0 : axgbe_xmit_cleanup(txq);
1090 : 0 : nb_desc_free = txq->nb_desc - (txq->cur - txq->dirty);
1091 [ # # ]: 0 : if (unlikely(nb_desc_free == 0))
1092 : : return 0;
1093 : : }
1094 : 0 : nb_pkts = RTE_MIN(nb_desc_free, nb_pkts);
1095 [ # # ]: 0 : while (nb_pkts--) {
1096 : 0 : mbuf = *tx_pkts++;
1097 [ # # ]: 0 : if (axgbe_xmit_hw(txq, mbuf))
1098 : 0 : goto out;
1099 : 0 : nb_pkt_sent++;
1100 : : }
1101 : 0 : out:
1102 : : /* Sync read and write */
1103 : : rte_mb();
1104 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->cur);
1105 : 0 : tail_addr = low32_value(txq->ring_phys_addr +
1106 : 0 : idx * sizeof(struct axgbe_tx_desc));
1107 : : /* Update tail reg with next immediate address to kick Tx DMA channel*/
1108 : 0 : AXGMAC_DMA_IOWRITE(txq, DMA_CH_TDTR_LO, tail_addr);
1109 : 0 : txq->pkts += nb_pkt_sent;
1110 : 0 : return nb_pkt_sent;
1111 : : }
1112 : :
1113 : 0 : void axgbe_dev_clear_queues(struct rte_eth_dev *dev)
1114 : : {
1115 : : PMD_INIT_FUNC_TRACE();
1116 : : uint8_t i;
1117 : : struct axgbe_rx_queue *rxq;
1118 : : struct axgbe_tx_queue *txq;
1119 : :
1120 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
1121 : 0 : rxq = dev->data->rx_queues[i];
1122 : :
1123 [ # # ]: 0 : if (rxq) {
1124 : 0 : axgbe_rx_queue_release(rxq);
1125 : 0 : dev->data->rx_queues[i] = NULL;
1126 : : }
1127 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
1128 : : }
1129 : :
1130 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
1131 : 0 : txq = dev->data->tx_queues[i];
1132 : :
1133 [ # # ]: 0 : if (txq) {
1134 : 0 : axgbe_tx_queue_release(txq);
1135 : 0 : dev->data->tx_queues[i] = NULL;
1136 : : }
1137 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
1138 : : }
1139 : 0 : }
1140 : :
1141 : : int
1142 : 0 : axgbe_dev_rx_descriptor_status(void *rx_queue, uint16_t offset)
1143 : : {
1144 : : struct axgbe_rx_queue *rxq = rx_queue;
1145 : : volatile union axgbe_rx_desc *desc;
1146 : : uint16_t idx;
1147 : :
1148 : :
1149 [ # # ]: 0 : if (unlikely(offset >= rxq->nb_desc))
1150 : : return -EINVAL;
1151 : :
1152 [ # # ]: 0 : if (offset >= rxq->nb_desc - rxq->dirty)
1153 : : return RTE_ETH_RX_DESC_UNAVAIL;
1154 : :
1155 : 0 : idx = AXGBE_GET_DESC_IDX(rxq, rxq->cur);
1156 : 0 : desc = &rxq->desc[idx + offset];
1157 : :
1158 [ # # ]: 0 : if (!AXGMAC_GET_BITS_LE(desc->write.desc3, RX_NORMAL_DESC3, OWN))
1159 : 0 : return RTE_ETH_RX_DESC_DONE;
1160 : :
1161 : : return RTE_ETH_RX_DESC_AVAIL;
1162 : : }
1163 : :
1164 : : int
1165 : 0 : axgbe_dev_tx_descriptor_status(void *tx_queue, uint16_t offset)
1166 : : {
1167 : : struct axgbe_tx_queue *txq = tx_queue;
1168 : : volatile struct axgbe_tx_desc *desc;
1169 : : uint16_t idx;
1170 : :
1171 : :
1172 [ # # ]: 0 : if (unlikely(offset >= txq->nb_desc))
1173 : : return -EINVAL;
1174 : :
1175 [ # # ]: 0 : if (offset >= txq->nb_desc - txq->dirty)
1176 : : return RTE_ETH_TX_DESC_UNAVAIL;
1177 : :
1178 : 0 : idx = AXGBE_GET_DESC_IDX(txq, txq->dirty + txq->free_batch_cnt - 1);
1179 : 0 : desc = &txq->desc[idx + offset];
1180 : :
1181 [ # # ]: 0 : if (!AXGMAC_GET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN))
1182 : 0 : return RTE_ETH_TX_DESC_DONE;
1183 : :
1184 : : return RTE_ETH_TX_DESC_FULL;
1185 : : }
|