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
14*7be78d02SJosh Soref /* Useful to avoid shifting for every descriptor preparation */
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
axgbe_vec_tx(volatile struct axgbe_tx_desc * desc,struct rte_mbuf * mbuf)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 */
26daa02b5cSOlivier 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
axgbe_xmit_cleanup_vec(struct axgbe_tx_queue * txq)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
axgbe_xmit_pkts_vec(void * tx_queue,struct rte_mbuf ** tx_pkts,uint16_t nb_pkts)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