18590b93dSRavi Kumar /* SPDX-License-Identifier: BSD-3-Clause 28590b93dSRavi Kumar * Copyright(c) 2018 Advanced Micro Devices, Inc. All rights reserved. 38590b93dSRavi Kumar * Copyright(c) 2018 Synopsys, Inc. All rights reserved. 48590b93dSRavi Kumar */ 58590b93dSRavi Kumar 68590b93dSRavi Kumar #include "axgbe_ethdev.h" 78590b93dSRavi Kumar #include "axgbe_rxtx.h" 88590b93dSRavi Kumar #include "axgbe_phy.h" 98590b93dSRavi Kumar 108590b93dSRavi Kumar #include <rte_time.h> 118590b93dSRavi Kumar #include <rte_mempool.h> 128590b93dSRavi Kumar #include <rte_mbuf.h> 138590b93dSRavi Kumar 148590b93dSRavi Kumar /* Useful to avoid shifting for every descriptor prepration*/ 158590b93dSRavi Kumar #define TX_DESC_CTRL_FLAGS 0xb000000000000000 16e0444948SSelwin Sebastian #define TX_DESC_CTRL_FLAG_TMST 0x40000000 178590b93dSRavi Kumar #define TX_FREE_BULK 8 188590b93dSRavi Kumar #define TX_FREE_BULK_CHECK (TX_FREE_BULK - 1) 198590b93dSRavi Kumar 208590b93dSRavi Kumar static inline void 218590b93dSRavi Kumar axgbe_vec_tx(volatile struct axgbe_tx_desc *desc, 228590b93dSRavi Kumar struct rte_mbuf *mbuf) 238590b93dSRavi Kumar { 24e0444948SSelwin Sebastian uint64_t tmst_en = 0; 25e0444948SSelwin Sebastian /* Timestamp enablement check */ 26*daa02b5cSOlivier Matz if (mbuf->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) 27e0444948SSelwin Sebastian tmst_en = TX_DESC_CTRL_FLAG_TMST; 288590b93dSRavi Kumar __m128i descriptor = _mm_set_epi64x((uint64_t)mbuf->pkt_len << 32 | 29e0444948SSelwin Sebastian TX_DESC_CTRL_FLAGS | mbuf->data_len 30e0444948SSelwin Sebastian | tmst_en, 318590b93dSRavi Kumar mbuf->buf_iova 328590b93dSRavi Kumar + mbuf->data_off); 338590b93dSRavi Kumar _mm_store_si128((__m128i *)desc, descriptor); 348590b93dSRavi Kumar } 358590b93dSRavi Kumar 368590b93dSRavi Kumar static void 378590b93dSRavi Kumar axgbe_xmit_cleanup_vec(struct axgbe_tx_queue *txq) 388590b93dSRavi Kumar { 398590b93dSRavi Kumar volatile struct axgbe_tx_desc *desc; 408590b93dSRavi Kumar int idx, i; 418590b93dSRavi Kumar 428590b93dSRavi Kumar idx = AXGBE_GET_DESC_IDX(txq, txq->dirty + txq->free_batch_cnt 438590b93dSRavi Kumar - 1); 448590b93dSRavi Kumar desc = &txq->desc[idx]; 458590b93dSRavi Kumar if (desc->desc3 & AXGBE_DESC_OWN) 468590b93dSRavi Kumar return; 478590b93dSRavi Kumar /* memset avoided for desc ctrl fields since in vec_tx path 488590b93dSRavi Kumar * all 128 bits are populated 498590b93dSRavi Kumar */ 508590b93dSRavi Kumar for (i = 0; i < txq->free_batch_cnt; i++, idx--) 518590b93dSRavi Kumar rte_pktmbuf_free_seg(txq->sw_ring[idx]); 528590b93dSRavi Kumar 538590b93dSRavi Kumar 548590b93dSRavi Kumar txq->dirty += txq->free_batch_cnt; 558590b93dSRavi Kumar txq->nb_desc_free += txq->free_batch_cnt; 568590b93dSRavi Kumar } 578590b93dSRavi Kumar 588590b93dSRavi Kumar uint16_t 598590b93dSRavi Kumar axgbe_xmit_pkts_vec(void *tx_queue, struct rte_mbuf **tx_pkts, 608590b93dSRavi Kumar uint16_t nb_pkts) 618590b93dSRavi Kumar { 628590b93dSRavi Kumar PMD_INIT_FUNC_TRACE(); 638590b93dSRavi Kumar 648590b93dSRavi Kumar struct axgbe_tx_queue *txq; 658590b93dSRavi Kumar uint16_t idx, nb_commit, loop, i; 668590b93dSRavi Kumar uint32_t tail_addr; 678590b93dSRavi Kumar 688590b93dSRavi Kumar txq = (struct axgbe_tx_queue *)tx_queue; 698590b93dSRavi Kumar if (txq->nb_desc_free < txq->free_thresh) { 708590b93dSRavi Kumar axgbe_xmit_cleanup_vec(txq); 718590b93dSRavi Kumar if (unlikely(txq->nb_desc_free == 0)) 728590b93dSRavi Kumar return 0; 738590b93dSRavi Kumar } 748590b93dSRavi Kumar nb_pkts = RTE_MIN(txq->nb_desc_free, nb_pkts); 758590b93dSRavi Kumar nb_commit = nb_pkts; 768590b93dSRavi Kumar idx = AXGBE_GET_DESC_IDX(txq, txq->cur); 778590b93dSRavi Kumar loop = txq->nb_desc - idx; 788590b93dSRavi Kumar if (nb_commit >= loop) { 798590b93dSRavi Kumar for (i = 0; i < loop; ++i, ++idx, ++tx_pkts) { 808590b93dSRavi Kumar axgbe_vec_tx(&txq->desc[idx], *tx_pkts); 818590b93dSRavi Kumar txq->sw_ring[idx] = *tx_pkts; 828590b93dSRavi Kumar } 838590b93dSRavi Kumar nb_commit -= loop; 848590b93dSRavi Kumar idx = 0; 858590b93dSRavi Kumar } 868590b93dSRavi Kumar for (i = 0; i < nb_commit; ++i, ++idx, ++tx_pkts) { 878590b93dSRavi Kumar axgbe_vec_tx(&txq->desc[idx], *tx_pkts); 888590b93dSRavi Kumar txq->sw_ring[idx] = *tx_pkts; 898590b93dSRavi Kumar } 908590b93dSRavi Kumar txq->cur += nb_pkts; 918590b93dSRavi Kumar tail_addr = (uint32_t)(txq->ring_phys_addr + 928590b93dSRavi Kumar idx * sizeof(struct axgbe_tx_desc)); 938590b93dSRavi Kumar /* Update tail reg with next immediate address to kick Tx DMA channel*/ 948590b93dSRavi Kumar rte_write32(tail_addr, (void *)txq->dma_tail_reg); 958590b93dSRavi Kumar txq->pkts += nb_pkts; 968590b93dSRavi Kumar txq->nb_desc_free -= nb_pkts; 978590b93dSRavi Kumar 988590b93dSRavi Kumar return nb_pkts; 998590b93dSRavi Kumar } 100