143b7e5eaSJiawen Wu /* SPDX-License-Identifier: BSD-3-Clause 243b7e5eaSJiawen Wu * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd. 343b7e5eaSJiawen Wu * Copyright(c) 2010-2017 Intel Corporation 443b7e5eaSJiawen Wu */ 543b7e5eaSJiawen Wu 643b7e5eaSJiawen Wu #include <sys/queue.h> 743b7e5eaSJiawen Wu 843b7e5eaSJiawen Wu #include <stdint.h> 943b7e5eaSJiawen Wu #include <rte_ethdev.h> 1043b7e5eaSJiawen Wu #include <ethdev_driver.h> 1143b7e5eaSJiawen Wu #include <rte_malloc.h> 129f320614SJiawen Wu #include <rte_net.h> 13e94c20c3SJiawen Wu #include <rte_vect.h> 1443b7e5eaSJiawen Wu 1543b7e5eaSJiawen Wu #include "ngbe_logs.h" 1643b7e5eaSJiawen Wu #include "base/ngbe.h" 1743b7e5eaSJiawen Wu #include "ngbe_ethdev.h" 1843b7e5eaSJiawen Wu #include "ngbe_rxtx.h" 1943b7e5eaSJiawen Wu 2024cd85f7SJiawen Wu #ifdef RTE_LIBRTE_IEEE1588 2160ad04e2SGagandeep Singh #define NGBE_TX_IEEE1588_TMST RTE_MBUF_F_TX_IEEE1588_TMST 2224cd85f7SJiawen Wu #else 2324cd85f7SJiawen Wu #define NGBE_TX_IEEE1588_TMST 0 2424cd85f7SJiawen Wu #endif 2524cd85f7SJiawen Wu 269f320614SJiawen Wu /* Bit Mask to indicate what bits required for building Tx context */ 279f320614SJiawen Wu static const u64 NGBE_TX_OFFLOAD_MASK = (RTE_MBUF_F_TX_IP_CKSUM | 289f320614SJiawen Wu RTE_MBUF_F_TX_IPV6 | 299f320614SJiawen Wu RTE_MBUF_F_TX_IPV4 | 3059b46438SJiawen Wu RTE_MBUF_F_TX_VLAN | 319f320614SJiawen Wu RTE_MBUF_F_TX_L4_MASK | 329f320614SJiawen Wu RTE_MBUF_F_TX_TCP_SEG | 3324cd85f7SJiawen Wu NGBE_TX_IEEE1588_TMST); 3424cd85f7SJiawen Wu 359f320614SJiawen Wu #define NGBE_TX_OFFLOAD_NOTSUP_MASK \ 369f320614SJiawen Wu (RTE_MBUF_F_TX_OFFLOAD_MASK ^ NGBE_TX_OFFLOAD_MASK) 379f320614SJiawen Wu 3893dfebd2SJiawen Wu /* 3993dfebd2SJiawen Wu * Prefetch a cache line into all cache levels. 4093dfebd2SJiawen Wu */ 4193dfebd2SJiawen Wu #define rte_ngbe_prefetch(p) rte_prefetch0(p) 4293dfebd2SJiawen Wu 4393dfebd2SJiawen Wu /********************************************************************* 4493dfebd2SJiawen Wu * 45aad91eddSJiawen Wu * Tx functions 46aad91eddSJiawen Wu * 47aad91eddSJiawen Wu **********************************************************************/ 48aad91eddSJiawen Wu 49aad91eddSJiawen Wu /* 50aad91eddSJiawen Wu * Check for descriptors with their DD bit set and free mbufs. 51aad91eddSJiawen Wu * Return the total number of buffers freed. 52aad91eddSJiawen Wu */ 53aad91eddSJiawen Wu static __rte_always_inline int 54aad91eddSJiawen Wu ngbe_tx_free_bufs(struct ngbe_tx_queue *txq) 55aad91eddSJiawen Wu { 56aad91eddSJiawen Wu struct ngbe_tx_entry *txep; 57aad91eddSJiawen Wu uint32_t status; 58aad91eddSJiawen Wu int i, nb_free = 0; 59aad91eddSJiawen Wu struct rte_mbuf *m, *free[RTE_NGBE_TX_MAX_FREE_BUF_SZ]; 60aad91eddSJiawen Wu 61aad91eddSJiawen Wu /* check DD bit on threshold descriptor */ 62aad91eddSJiawen Wu status = txq->tx_ring[txq->tx_next_dd].dw3; 63aad91eddSJiawen Wu if (!(status & rte_cpu_to_le_32(NGBE_TXD_DD))) { 64aad91eddSJiawen Wu if (txq->nb_tx_free >> 1 < txq->tx_free_thresh) 65aad91eddSJiawen Wu ngbe_set32_masked(txq->tdc_reg_addr, 66aad91eddSJiawen Wu NGBE_TXCFG_FLUSH, NGBE_TXCFG_FLUSH); 67aad91eddSJiawen Wu return 0; 68aad91eddSJiawen Wu } 69aad91eddSJiawen Wu 70aad91eddSJiawen Wu /* 71aad91eddSJiawen Wu * first buffer to free from S/W ring is at index 72aad91eddSJiawen Wu * tx_next_dd - (tx_free_thresh-1) 73aad91eddSJiawen Wu */ 74aad91eddSJiawen Wu txep = &txq->sw_ring[txq->tx_next_dd - (txq->tx_free_thresh - 1)]; 75aad91eddSJiawen Wu for (i = 0; i < txq->tx_free_thresh; ++i, ++txep) { 76aad91eddSJiawen Wu /* free buffers one at a time */ 77aad91eddSJiawen Wu m = rte_pktmbuf_prefree_seg(txep->mbuf); 78aad91eddSJiawen Wu txep->mbuf = NULL; 79aad91eddSJiawen Wu 80aad91eddSJiawen Wu if (unlikely(m == NULL)) 81aad91eddSJiawen Wu continue; 82aad91eddSJiawen Wu 83aad91eddSJiawen Wu if (nb_free >= RTE_NGBE_TX_MAX_FREE_BUF_SZ || 84aad91eddSJiawen Wu (nb_free > 0 && m->pool != free[0]->pool)) { 85aad91eddSJiawen Wu rte_mempool_put_bulk(free[0]->pool, 86aad91eddSJiawen Wu (void **)free, nb_free); 87aad91eddSJiawen Wu nb_free = 0; 88aad91eddSJiawen Wu } 89aad91eddSJiawen Wu 90aad91eddSJiawen Wu free[nb_free++] = m; 91aad91eddSJiawen Wu } 92aad91eddSJiawen Wu 93aad91eddSJiawen Wu if (nb_free > 0) 94aad91eddSJiawen Wu rte_mempool_put_bulk(free[0]->pool, (void **)free, nb_free); 95aad91eddSJiawen Wu 96aad91eddSJiawen Wu /* buffers were freed, update counters */ 97aad91eddSJiawen Wu txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_free_thresh); 98aad91eddSJiawen Wu txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_free_thresh); 99aad91eddSJiawen Wu if (txq->tx_next_dd >= txq->nb_tx_desc) 100aad91eddSJiawen Wu txq->tx_next_dd = (uint16_t)(txq->tx_free_thresh - 1); 101aad91eddSJiawen Wu 102aad91eddSJiawen Wu return txq->tx_free_thresh; 103aad91eddSJiawen Wu } 104aad91eddSJiawen Wu 105aad91eddSJiawen Wu /* Populate 4 descriptors with data from 4 mbufs */ 106aad91eddSJiawen Wu static inline void 107aad91eddSJiawen Wu tx4(volatile struct ngbe_tx_desc *txdp, struct rte_mbuf **pkts) 108aad91eddSJiawen Wu { 109aad91eddSJiawen Wu uint64_t buf_dma_addr; 110aad91eddSJiawen Wu uint32_t pkt_len; 111aad91eddSJiawen Wu int i; 112aad91eddSJiawen Wu 113aad91eddSJiawen Wu for (i = 0; i < 4; ++i, ++txdp, ++pkts) { 114aad91eddSJiawen Wu buf_dma_addr = rte_mbuf_data_iova(*pkts); 115aad91eddSJiawen Wu pkt_len = (*pkts)->data_len; 1168d75bf03SJiawen Wu if (pkt_len < RTE_ETHER_HDR_LEN) 1178d75bf03SJiawen Wu pkt_len = NGBE_FRAME_SIZE_DFT; 118aad91eddSJiawen Wu 119aad91eddSJiawen Wu /* write data to descriptor */ 120aad91eddSJiawen Wu txdp->qw0 = rte_cpu_to_le_64(buf_dma_addr); 121aad91eddSJiawen Wu txdp->dw2 = cpu_to_le32(NGBE_TXD_FLAGS | 122aad91eddSJiawen Wu NGBE_TXD_DATLEN(pkt_len)); 123aad91eddSJiawen Wu txdp->dw3 = cpu_to_le32(NGBE_TXD_PAYLEN(pkt_len)); 124aad91eddSJiawen Wu 125aad91eddSJiawen Wu rte_prefetch0(&(*pkts)->pool); 126aad91eddSJiawen Wu } 127aad91eddSJiawen Wu } 128aad91eddSJiawen Wu 129aad91eddSJiawen Wu /* Populate 1 descriptor with data from 1 mbuf */ 130aad91eddSJiawen Wu static inline void 131aad91eddSJiawen Wu tx1(volatile struct ngbe_tx_desc *txdp, struct rte_mbuf **pkts) 132aad91eddSJiawen Wu { 133aad91eddSJiawen Wu uint64_t buf_dma_addr; 134aad91eddSJiawen Wu uint32_t pkt_len; 135aad91eddSJiawen Wu 136aad91eddSJiawen Wu buf_dma_addr = rte_mbuf_data_iova(*pkts); 137aad91eddSJiawen Wu pkt_len = (*pkts)->data_len; 1388d75bf03SJiawen Wu if (pkt_len < RTE_ETHER_HDR_LEN) 1398d75bf03SJiawen Wu pkt_len = NGBE_FRAME_SIZE_DFT; 140aad91eddSJiawen Wu 141aad91eddSJiawen Wu /* write data to descriptor */ 142aad91eddSJiawen Wu txdp->qw0 = cpu_to_le64(buf_dma_addr); 143aad91eddSJiawen Wu txdp->dw2 = cpu_to_le32(NGBE_TXD_FLAGS | 144aad91eddSJiawen Wu NGBE_TXD_DATLEN(pkt_len)); 145aad91eddSJiawen Wu txdp->dw3 = cpu_to_le32(NGBE_TXD_PAYLEN(pkt_len)); 146aad91eddSJiawen Wu 147aad91eddSJiawen Wu rte_prefetch0(&(*pkts)->pool); 148aad91eddSJiawen Wu } 149aad91eddSJiawen Wu 150aad91eddSJiawen Wu /* 151aad91eddSJiawen Wu * Fill H/W descriptor ring with mbuf data. 152aad91eddSJiawen Wu * Copy mbuf pointers to the S/W ring. 153aad91eddSJiawen Wu */ 154aad91eddSJiawen Wu static inline void 155aad91eddSJiawen Wu ngbe_tx_fill_hw_ring(struct ngbe_tx_queue *txq, struct rte_mbuf **pkts, 156aad91eddSJiawen Wu uint16_t nb_pkts) 157aad91eddSJiawen Wu { 158aad91eddSJiawen Wu volatile struct ngbe_tx_desc *txdp = &txq->tx_ring[txq->tx_tail]; 159aad91eddSJiawen Wu struct ngbe_tx_entry *txep = &txq->sw_ring[txq->tx_tail]; 160aad91eddSJiawen Wu const int N_PER_LOOP = 4; 161aad91eddSJiawen Wu const int N_PER_LOOP_MASK = N_PER_LOOP - 1; 162aad91eddSJiawen Wu int mainpart, leftover; 163aad91eddSJiawen Wu int i, j; 164aad91eddSJiawen Wu 165aad91eddSJiawen Wu /* 166aad91eddSJiawen Wu * Process most of the packets in chunks of N pkts. Any 167aad91eddSJiawen Wu * leftover packets will get processed one at a time. 168aad91eddSJiawen Wu */ 169aad91eddSJiawen Wu mainpart = (nb_pkts & ((uint32_t)~N_PER_LOOP_MASK)); 170aad91eddSJiawen Wu leftover = (nb_pkts & ((uint32_t)N_PER_LOOP_MASK)); 171aad91eddSJiawen Wu for (i = 0; i < mainpart; i += N_PER_LOOP) { 172aad91eddSJiawen Wu /* Copy N mbuf pointers to the S/W ring */ 173aad91eddSJiawen Wu for (j = 0; j < N_PER_LOOP; ++j) 174aad91eddSJiawen Wu (txep + i + j)->mbuf = *(pkts + i + j); 175aad91eddSJiawen Wu tx4(txdp + i, pkts + i); 176aad91eddSJiawen Wu } 177aad91eddSJiawen Wu 178aad91eddSJiawen Wu if (unlikely(leftover > 0)) { 179aad91eddSJiawen Wu for (i = 0; i < leftover; ++i) { 180aad91eddSJiawen Wu (txep + mainpart + i)->mbuf = *(pkts + mainpart + i); 181aad91eddSJiawen Wu tx1(txdp + mainpart + i, pkts + mainpart + i); 182aad91eddSJiawen Wu } 183aad91eddSJiawen Wu } 184aad91eddSJiawen Wu } 185aad91eddSJiawen Wu 186aad91eddSJiawen Wu static inline uint16_t 187aad91eddSJiawen Wu tx_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 188aad91eddSJiawen Wu uint16_t nb_pkts) 189aad91eddSJiawen Wu { 190aad91eddSJiawen Wu struct ngbe_tx_queue *txq = (struct ngbe_tx_queue *)tx_queue; 191aad91eddSJiawen Wu uint16_t n = 0; 192aad91eddSJiawen Wu 193aad91eddSJiawen Wu /* 194aad91eddSJiawen Wu * Begin scanning the H/W ring for done descriptors when the 195aad91eddSJiawen Wu * number of available descriptors drops below tx_free_thresh. 196aad91eddSJiawen Wu * For each done descriptor, free the associated buffer. 197aad91eddSJiawen Wu */ 198aad91eddSJiawen Wu if (txq->nb_tx_free < txq->tx_free_thresh) 199aad91eddSJiawen Wu ngbe_tx_free_bufs(txq); 200aad91eddSJiawen Wu 201aad91eddSJiawen Wu /* Only use descriptors that are available */ 202aad91eddSJiawen Wu nb_pkts = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts); 203aad91eddSJiawen Wu if (unlikely(nb_pkts == 0)) 204aad91eddSJiawen Wu return 0; 205aad91eddSJiawen Wu 206aad91eddSJiawen Wu /* Use exactly nb_pkts descriptors */ 207aad91eddSJiawen Wu txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_pkts); 208aad91eddSJiawen Wu 209aad91eddSJiawen Wu /* 210aad91eddSJiawen Wu * At this point, we know there are enough descriptors in the 211aad91eddSJiawen Wu * ring to transmit all the packets. This assumes that each 212aad91eddSJiawen Wu * mbuf contains a single segment, and that no new offloads 213aad91eddSJiawen Wu * are expected, which would require a new context descriptor. 214aad91eddSJiawen Wu */ 215aad91eddSJiawen Wu 216aad91eddSJiawen Wu /* 217aad91eddSJiawen Wu * See if we're going to wrap-around. If so, handle the top 218aad91eddSJiawen Wu * of the descriptor ring first, then do the bottom. If not, 219aad91eddSJiawen Wu * the processing looks just like the "bottom" part anyway... 220aad91eddSJiawen Wu */ 221aad91eddSJiawen Wu if ((txq->tx_tail + nb_pkts) > txq->nb_tx_desc) { 222aad91eddSJiawen Wu n = (uint16_t)(txq->nb_tx_desc - txq->tx_tail); 223aad91eddSJiawen Wu ngbe_tx_fill_hw_ring(txq, tx_pkts, n); 224aad91eddSJiawen Wu txq->tx_tail = 0; 225aad91eddSJiawen Wu } 226aad91eddSJiawen Wu 227aad91eddSJiawen Wu /* Fill H/W descriptor ring with mbuf data */ 228aad91eddSJiawen Wu ngbe_tx_fill_hw_ring(txq, tx_pkts + n, (uint16_t)(nb_pkts - n)); 229aad91eddSJiawen Wu txq->tx_tail = (uint16_t)(txq->tx_tail + (nb_pkts - n)); 230aad91eddSJiawen Wu 231aad91eddSJiawen Wu /* 232aad91eddSJiawen Wu * Check for wrap-around. This would only happen if we used 233aad91eddSJiawen Wu * up to the last descriptor in the ring, no more, no less. 234aad91eddSJiawen Wu */ 235aad91eddSJiawen Wu if (txq->tx_tail >= txq->nb_tx_desc) 236aad91eddSJiawen Wu txq->tx_tail = 0; 237aad91eddSJiawen Wu 238aad91eddSJiawen Wu PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u tx_tail=%u nb_tx=%u", 239aad91eddSJiawen Wu (uint16_t)txq->port_id, (uint16_t)txq->queue_id, 240aad91eddSJiawen Wu (uint16_t)txq->tx_tail, (uint16_t)nb_pkts); 241aad91eddSJiawen Wu 242aad91eddSJiawen Wu /* update tail pointer */ 243aad91eddSJiawen Wu rte_wmb(); 244aad91eddSJiawen Wu ngbe_set32_relaxed(txq->tdt_reg_addr, txq->tx_tail); 245aad91eddSJiawen Wu 246aad91eddSJiawen Wu return nb_pkts; 247aad91eddSJiawen Wu } 248aad91eddSJiawen Wu 249aad91eddSJiawen Wu uint16_t 250aad91eddSJiawen Wu ngbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, 251aad91eddSJiawen Wu uint16_t nb_pkts) 252aad91eddSJiawen Wu { 253aad91eddSJiawen Wu uint16_t nb_tx; 254aad91eddSJiawen Wu 255aad91eddSJiawen Wu /* Try to transmit at least chunks of TX_MAX_BURST pkts */ 256aad91eddSJiawen Wu if (likely(nb_pkts <= RTE_PMD_NGBE_TX_MAX_BURST)) 257aad91eddSJiawen Wu return tx_xmit_pkts(tx_queue, tx_pkts, nb_pkts); 258aad91eddSJiawen Wu 259aad91eddSJiawen Wu /* transmit more than the max burst, in chunks of TX_MAX_BURST */ 260aad91eddSJiawen Wu nb_tx = 0; 261aad91eddSJiawen Wu while (nb_pkts != 0) { 262aad91eddSJiawen Wu uint16_t ret, n; 263aad91eddSJiawen Wu 264aad91eddSJiawen Wu n = (uint16_t)RTE_MIN(nb_pkts, RTE_PMD_NGBE_TX_MAX_BURST); 265aad91eddSJiawen Wu ret = tx_xmit_pkts(tx_queue, &tx_pkts[nb_tx], n); 266aad91eddSJiawen Wu nb_tx = (uint16_t)(nb_tx + ret); 267aad91eddSJiawen Wu nb_pkts = (uint16_t)(nb_pkts - ret); 268aad91eddSJiawen Wu if (ret < n) 269aad91eddSJiawen Wu break; 270aad91eddSJiawen Wu } 271aad91eddSJiawen Wu 272aad91eddSJiawen Wu return nb_tx; 273aad91eddSJiawen Wu } 274aad91eddSJiawen Wu 275e94c20c3SJiawen Wu static uint16_t 276e94c20c3SJiawen Wu ngbe_xmit_pkts_vec(void *tx_queue, struct rte_mbuf **tx_pkts, 277e94c20c3SJiawen Wu uint16_t nb_pkts) 278e94c20c3SJiawen Wu { 279e94c20c3SJiawen Wu struct ngbe_tx_queue *txq = (struct ngbe_tx_queue *)tx_queue; 280e94c20c3SJiawen Wu uint16_t nb_tx = 0; 281e94c20c3SJiawen Wu 282e94c20c3SJiawen Wu while (nb_pkts) { 283e94c20c3SJiawen Wu uint16_t ret, num; 284e94c20c3SJiawen Wu 285e94c20c3SJiawen Wu num = (uint16_t)RTE_MIN(nb_pkts, txq->tx_free_thresh); 286e94c20c3SJiawen Wu ret = ngbe_xmit_fixed_burst_vec(tx_queue, &tx_pkts[nb_tx], num); 287e94c20c3SJiawen Wu nb_tx += ret; 288e94c20c3SJiawen Wu nb_pkts -= ret; 289e94c20c3SJiawen Wu if (ret < num) 290e94c20c3SJiawen Wu break; 291e94c20c3SJiawen Wu } 292e94c20c3SJiawen Wu 293e94c20c3SJiawen Wu return nb_tx; 294e94c20c3SJiawen Wu } 295e94c20c3SJiawen Wu 2969f320614SJiawen Wu static inline void 2979f320614SJiawen Wu ngbe_set_xmit_ctx(struct ngbe_tx_queue *txq, 2989f320614SJiawen Wu volatile struct ngbe_tx_ctx_desc *ctx_txd, 2999f320614SJiawen Wu uint64_t ol_flags, union ngbe_tx_offload tx_offload) 3009f320614SJiawen Wu { 3019f320614SJiawen Wu union ngbe_tx_offload tx_offload_mask; 3029f320614SJiawen Wu uint32_t type_tucmd_mlhl; 3039f320614SJiawen Wu uint32_t mss_l4len_idx; 3049f320614SJiawen Wu uint32_t ctx_idx; 3059f320614SJiawen Wu uint32_t vlan_macip_lens; 3069f320614SJiawen Wu uint32_t tunnel_seed; 3079f320614SJiawen Wu 3089f320614SJiawen Wu ctx_idx = txq->ctx_curr; 3099f320614SJiawen Wu tx_offload_mask.data[0] = 0; 3109f320614SJiawen Wu tx_offload_mask.data[1] = 0; 3119f320614SJiawen Wu 3129f320614SJiawen Wu /* Specify which HW CTX to upload. */ 3139f320614SJiawen Wu mss_l4len_idx = NGBE_TXD_IDX(ctx_idx); 3149f320614SJiawen Wu type_tucmd_mlhl = NGBE_TXD_CTXT; 3159f320614SJiawen Wu 3169f320614SJiawen Wu tx_offload_mask.ptid |= ~0; 3179f320614SJiawen Wu type_tucmd_mlhl |= NGBE_TXD_PTID(tx_offload.ptid); 3189f320614SJiawen Wu 3199f320614SJiawen Wu /* check if TCP segmentation required for this packet */ 3209f320614SJiawen Wu if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) { 3219f320614SJiawen Wu tx_offload_mask.l2_len |= ~0; 3229f320614SJiawen Wu tx_offload_mask.l3_len |= ~0; 3239f320614SJiawen Wu tx_offload_mask.l4_len |= ~0; 3249f320614SJiawen Wu tx_offload_mask.tso_segsz |= ~0; 3259f320614SJiawen Wu mss_l4len_idx |= NGBE_TXD_MSS(tx_offload.tso_segsz); 3269f320614SJiawen Wu mss_l4len_idx |= NGBE_TXD_L4LEN(tx_offload.l4_len); 3279f320614SJiawen Wu } else { /* no TSO, check if hardware checksum is needed */ 3289f320614SJiawen Wu if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM) { 3299f320614SJiawen Wu tx_offload_mask.l2_len |= ~0; 3309f320614SJiawen Wu tx_offload_mask.l3_len |= ~0; 3319f320614SJiawen Wu } 3329f320614SJiawen Wu 3339f320614SJiawen Wu switch (ol_flags & RTE_MBUF_F_TX_L4_MASK) { 3349f320614SJiawen Wu case RTE_MBUF_F_TX_UDP_CKSUM: 3359f320614SJiawen Wu mss_l4len_idx |= 3369f320614SJiawen Wu NGBE_TXD_L4LEN(sizeof(struct rte_udp_hdr)); 3379f320614SJiawen Wu tx_offload_mask.l2_len |= ~0; 3389f320614SJiawen Wu tx_offload_mask.l3_len |= ~0; 3399f320614SJiawen Wu break; 3409f320614SJiawen Wu case RTE_MBUF_F_TX_TCP_CKSUM: 3419f320614SJiawen Wu mss_l4len_idx |= 3429f320614SJiawen Wu NGBE_TXD_L4LEN(sizeof(struct rte_tcp_hdr)); 3439f320614SJiawen Wu tx_offload_mask.l2_len |= ~0; 3449f320614SJiawen Wu tx_offload_mask.l3_len |= ~0; 3459f320614SJiawen Wu break; 3469f320614SJiawen Wu case RTE_MBUF_F_TX_SCTP_CKSUM: 3479f320614SJiawen Wu mss_l4len_idx |= 3489f320614SJiawen Wu NGBE_TXD_L4LEN(sizeof(struct rte_sctp_hdr)); 3499f320614SJiawen Wu tx_offload_mask.l2_len |= ~0; 3509f320614SJiawen Wu tx_offload_mask.l3_len |= ~0; 3519f320614SJiawen Wu break; 3529f320614SJiawen Wu default: 3539f320614SJiawen Wu break; 3549f320614SJiawen Wu } 3559f320614SJiawen Wu } 3569f320614SJiawen Wu 3579f320614SJiawen Wu vlan_macip_lens = NGBE_TXD_IPLEN(tx_offload.l3_len >> 1); 3589f320614SJiawen Wu vlan_macip_lens |= NGBE_TXD_MACLEN(tx_offload.l2_len); 3599f320614SJiawen Wu 36059b46438SJiawen Wu if (ol_flags & RTE_MBUF_F_TX_VLAN) { 36159b46438SJiawen Wu tx_offload_mask.vlan_tci |= ~0; 36259b46438SJiawen Wu vlan_macip_lens |= NGBE_TXD_VLAN(tx_offload.vlan_tci); 36359b46438SJiawen Wu } 36459b46438SJiawen Wu 365fa402b1eSJiawen Wu tunnel_seed = 0; 366fa402b1eSJiawen Wu 3679f320614SJiawen Wu txq->ctx_cache[ctx_idx].flags = ol_flags; 3689f320614SJiawen Wu txq->ctx_cache[ctx_idx].tx_offload.data[0] = 3699f320614SJiawen Wu tx_offload_mask.data[0] & tx_offload.data[0]; 3709f320614SJiawen Wu txq->ctx_cache[ctx_idx].tx_offload.data[1] = 3719f320614SJiawen Wu tx_offload_mask.data[1] & tx_offload.data[1]; 3729f320614SJiawen Wu txq->ctx_cache[ctx_idx].tx_offload_mask = tx_offload_mask; 3739f320614SJiawen Wu 3749f320614SJiawen Wu ctx_txd->dw0 = rte_cpu_to_le_32(vlan_macip_lens); 3759f320614SJiawen Wu ctx_txd->dw1 = rte_cpu_to_le_32(tunnel_seed); 3769f320614SJiawen Wu ctx_txd->dw2 = rte_cpu_to_le_32(type_tucmd_mlhl); 3779f320614SJiawen Wu ctx_txd->dw3 = rte_cpu_to_le_32(mss_l4len_idx); 3789f320614SJiawen Wu } 3799f320614SJiawen Wu 3809f320614SJiawen Wu /* 3819f320614SJiawen Wu * Check which hardware context can be used. Use the existing match 3829f320614SJiawen Wu * or create a new context descriptor. 3839f320614SJiawen Wu */ 3849f320614SJiawen Wu static inline uint32_t 3859f320614SJiawen Wu what_ctx_update(struct ngbe_tx_queue *txq, uint64_t flags, 3869f320614SJiawen Wu union ngbe_tx_offload tx_offload) 3879f320614SJiawen Wu { 3889f320614SJiawen Wu /* If match with the current used context */ 3899f320614SJiawen Wu if (likely(txq->ctx_cache[txq->ctx_curr].flags == flags && 3909f320614SJiawen Wu (txq->ctx_cache[txq->ctx_curr].tx_offload.data[0] == 3919f320614SJiawen Wu (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data[0] 3929f320614SJiawen Wu & tx_offload.data[0])) && 3939f320614SJiawen Wu (txq->ctx_cache[txq->ctx_curr].tx_offload.data[1] == 3949f320614SJiawen Wu (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data[1] 3959f320614SJiawen Wu & tx_offload.data[1])))) 3969f320614SJiawen Wu return txq->ctx_curr; 3979f320614SJiawen Wu 3989f320614SJiawen Wu /* What if match with the next context */ 3999f320614SJiawen Wu txq->ctx_curr ^= 1; 4009f320614SJiawen Wu if (likely(txq->ctx_cache[txq->ctx_curr].flags == flags && 4019f320614SJiawen Wu (txq->ctx_cache[txq->ctx_curr].tx_offload.data[0] == 4029f320614SJiawen Wu (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data[0] 4039f320614SJiawen Wu & tx_offload.data[0])) && 4049f320614SJiawen Wu (txq->ctx_cache[txq->ctx_curr].tx_offload.data[1] == 4059f320614SJiawen Wu (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data[1] 4069f320614SJiawen Wu & tx_offload.data[1])))) 4079f320614SJiawen Wu return txq->ctx_curr; 4089f320614SJiawen Wu 4099f320614SJiawen Wu /* Mismatch, use the previous context */ 4109f320614SJiawen Wu return NGBE_CTX_NUM; 4119f320614SJiawen Wu } 4129f320614SJiawen Wu 4139f320614SJiawen Wu static inline uint32_t 4149f320614SJiawen Wu tx_desc_cksum_flags_to_olinfo(uint64_t ol_flags) 4159f320614SJiawen Wu { 4169f320614SJiawen Wu uint32_t tmp = 0; 4179f320614SJiawen Wu 4189f320614SJiawen Wu if ((ol_flags & RTE_MBUF_F_TX_L4_MASK) != RTE_MBUF_F_TX_L4_NO_CKSUM) { 4199f320614SJiawen Wu tmp |= NGBE_TXD_CC; 4209f320614SJiawen Wu tmp |= NGBE_TXD_L4CS; 4219f320614SJiawen Wu } 4229f320614SJiawen Wu if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM) { 4239f320614SJiawen Wu tmp |= NGBE_TXD_CC; 4249f320614SJiawen Wu tmp |= NGBE_TXD_IPCS; 4259f320614SJiawen Wu } 4269f320614SJiawen Wu if (ol_flags & RTE_MBUF_F_TX_OUTER_IP_CKSUM) { 4279f320614SJiawen Wu tmp |= NGBE_TXD_CC; 4289f320614SJiawen Wu tmp |= NGBE_TXD_EIPCS; 4299f320614SJiawen Wu } 4309f320614SJiawen Wu if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) { 4319f320614SJiawen Wu tmp |= NGBE_TXD_CC; 4329f320614SJiawen Wu /* implies IPv4 cksum */ 4339f320614SJiawen Wu if (ol_flags & RTE_MBUF_F_TX_IPV4) 4349f320614SJiawen Wu tmp |= NGBE_TXD_IPCS; 4359f320614SJiawen Wu tmp |= NGBE_TXD_L4CS; 4369f320614SJiawen Wu } 43759b46438SJiawen Wu if (ol_flags & RTE_MBUF_F_TX_VLAN) 43859b46438SJiawen Wu tmp |= NGBE_TXD_CC; 4399f320614SJiawen Wu 4409f320614SJiawen Wu return tmp; 4419f320614SJiawen Wu } 4429f320614SJiawen Wu 4439f320614SJiawen Wu static inline uint32_t 4449f320614SJiawen Wu tx_desc_ol_flags_to_cmdtype(uint64_t ol_flags) 4459f320614SJiawen Wu { 4469f320614SJiawen Wu uint32_t cmdtype = 0; 4479f320614SJiawen Wu 44859b46438SJiawen Wu if (ol_flags & RTE_MBUF_F_TX_VLAN) 44959b46438SJiawen Wu cmdtype |= NGBE_TXD_VLE; 4509f320614SJiawen Wu if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) 4519f320614SJiawen Wu cmdtype |= NGBE_TXD_TSE; 4529f320614SJiawen Wu return cmdtype; 4539f320614SJiawen Wu } 4549f320614SJiawen Wu 455fa402b1eSJiawen Wu static inline uint32_t 456fa402b1eSJiawen Wu tx_desc_ol_flags_to_ptype(uint64_t oflags) 4579f320614SJiawen Wu { 458fa402b1eSJiawen Wu uint32_t ptype; 4599f320614SJiawen Wu 4609f320614SJiawen Wu /* L2 level */ 4619f320614SJiawen Wu ptype = RTE_PTYPE_L2_ETHER; 46259b46438SJiawen Wu if (oflags & RTE_MBUF_F_TX_VLAN) 46359b46438SJiawen Wu ptype |= RTE_PTYPE_L2_ETHER_VLAN; 4649f320614SJiawen Wu 4659f320614SJiawen Wu /* L3 level */ 4669f320614SJiawen Wu if (oflags & (RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IP_CKSUM)) 467fa402b1eSJiawen Wu ptype |= RTE_PTYPE_L3_IPV4; 4689f320614SJiawen Wu else if (oflags & (RTE_MBUF_F_TX_IPV6)) 469fa402b1eSJiawen Wu ptype |= RTE_PTYPE_L3_IPV6; 4709f320614SJiawen Wu 4719f320614SJiawen Wu /* L4 level */ 4729f320614SJiawen Wu switch (oflags & (RTE_MBUF_F_TX_L4_MASK)) { 4739f320614SJiawen Wu case RTE_MBUF_F_TX_TCP_CKSUM: 474fa402b1eSJiawen Wu ptype |= RTE_PTYPE_L4_TCP; 4759f320614SJiawen Wu break; 4769f320614SJiawen Wu case RTE_MBUF_F_TX_UDP_CKSUM: 477fa402b1eSJiawen Wu ptype |= RTE_PTYPE_L4_UDP; 4789f320614SJiawen Wu break; 4799f320614SJiawen Wu case RTE_MBUF_F_TX_SCTP_CKSUM: 480fa402b1eSJiawen Wu ptype |= RTE_PTYPE_L4_SCTP; 4819f320614SJiawen Wu break; 4829f320614SJiawen Wu } 4839f320614SJiawen Wu 4849f320614SJiawen Wu if (oflags & RTE_MBUF_F_TX_TCP_SEG) 485fa402b1eSJiawen Wu ptype |= RTE_PTYPE_L4_TCP; 4869f320614SJiawen Wu 487fa402b1eSJiawen Wu return ptype; 4889f320614SJiawen Wu } 4899f320614SJiawen Wu 490fa402b1eSJiawen Wu static inline uint8_t 491fa402b1eSJiawen Wu tx_desc_ol_flags_to_ptid(uint64_t oflags) 492fa402b1eSJiawen Wu { 493fa402b1eSJiawen Wu uint32_t ptype; 494fa402b1eSJiawen Wu 495fa402b1eSJiawen Wu ptype = tx_desc_ol_flags_to_ptype(oflags); 496fa402b1eSJiawen Wu 4979f320614SJiawen Wu return ngbe_encode_ptype(ptype); 4989f320614SJiawen Wu } 4999f320614SJiawen Wu 5009f320614SJiawen Wu /* Reset transmit descriptors after they have been used */ 5019f320614SJiawen Wu static inline int 5029f320614SJiawen Wu ngbe_xmit_cleanup(struct ngbe_tx_queue *txq) 5039f320614SJiawen Wu { 5049f320614SJiawen Wu struct ngbe_tx_entry *sw_ring = txq->sw_ring; 5059f320614SJiawen Wu volatile struct ngbe_tx_desc *txr = txq->tx_ring; 5069f320614SJiawen Wu uint16_t last_desc_cleaned = txq->last_desc_cleaned; 5079f320614SJiawen Wu uint16_t nb_tx_desc = txq->nb_tx_desc; 5089f320614SJiawen Wu uint16_t desc_to_clean_to; 5099f320614SJiawen Wu uint16_t nb_tx_to_clean; 5109f320614SJiawen Wu uint32_t status; 5119f320614SJiawen Wu 5129f320614SJiawen Wu /* Determine the last descriptor needing to be cleaned */ 5139f320614SJiawen Wu desc_to_clean_to = (uint16_t)(last_desc_cleaned + txq->tx_free_thresh); 5149f320614SJiawen Wu if (desc_to_clean_to >= nb_tx_desc) 5159f320614SJiawen Wu desc_to_clean_to = (uint16_t)(desc_to_clean_to - nb_tx_desc); 5169f320614SJiawen Wu 5179f320614SJiawen Wu /* Check to make sure the last descriptor to clean is done */ 5189f320614SJiawen Wu desc_to_clean_to = sw_ring[desc_to_clean_to].last_id; 5199f320614SJiawen Wu status = txr[desc_to_clean_to].dw3; 5209f320614SJiawen Wu if (!(status & rte_cpu_to_le_32(NGBE_TXD_DD))) { 5219f320614SJiawen Wu PMD_TX_LOG(DEBUG, 5229f320614SJiawen Wu "Tx descriptor %4u is not done" 5239f320614SJiawen Wu "(port=%d queue=%d)", 5249f320614SJiawen Wu desc_to_clean_to, 5259f320614SJiawen Wu txq->port_id, txq->queue_id); 5269f320614SJiawen Wu if (txq->nb_tx_free >> 1 < txq->tx_free_thresh) 5279f320614SJiawen Wu ngbe_set32_masked(txq->tdc_reg_addr, 5289f320614SJiawen Wu NGBE_TXCFG_FLUSH, NGBE_TXCFG_FLUSH); 5299f320614SJiawen Wu /* Failed to clean any descriptors, better luck next time */ 5309f320614SJiawen Wu return -(1); 5319f320614SJiawen Wu } 5329f320614SJiawen Wu 5339f320614SJiawen Wu /* Figure out how many descriptors will be cleaned */ 5349f320614SJiawen Wu if (last_desc_cleaned > desc_to_clean_to) 5359f320614SJiawen Wu nb_tx_to_clean = (uint16_t)((nb_tx_desc - last_desc_cleaned) + 5369f320614SJiawen Wu desc_to_clean_to); 5379f320614SJiawen Wu else 5389f320614SJiawen Wu nb_tx_to_clean = (uint16_t)(desc_to_clean_to - 5399f320614SJiawen Wu last_desc_cleaned); 5409f320614SJiawen Wu 5419f320614SJiawen Wu PMD_TX_LOG(DEBUG, 5429f320614SJiawen Wu "Cleaning %4u Tx descriptors: %4u to %4u (port=%d queue=%d)", 5439f320614SJiawen Wu nb_tx_to_clean, last_desc_cleaned, desc_to_clean_to, 5449f320614SJiawen Wu txq->port_id, txq->queue_id); 5459f320614SJiawen Wu 5469f320614SJiawen Wu /* 5479f320614SJiawen Wu * The last descriptor to clean is done, so that means all the 5489f320614SJiawen Wu * descriptors from the last descriptor that was cleaned 5499f320614SJiawen Wu * up to the last descriptor with the RS bit set 5509f320614SJiawen Wu * are done. Only reset the threshold descriptor. 5519f320614SJiawen Wu */ 5529f320614SJiawen Wu txr[desc_to_clean_to].dw3 = 0; 5539f320614SJiawen Wu 5549f320614SJiawen Wu /* Update the txq to reflect the last descriptor that was cleaned */ 5559f320614SJiawen Wu txq->last_desc_cleaned = desc_to_clean_to; 5569f320614SJiawen Wu txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + nb_tx_to_clean); 5579f320614SJiawen Wu 5589f320614SJiawen Wu /* No Error */ 5599f320614SJiawen Wu return 0; 5609f320614SJiawen Wu } 5619f320614SJiawen Wu 5628d75bf03SJiawen Wu static inline bool 5638d75bf03SJiawen Wu ngbe_check_pkt_err(struct rte_mbuf *tx_pkt) 5648d75bf03SJiawen Wu { 5658d75bf03SJiawen Wu uint32_t total_len = 0, nb_seg = 0; 5668d75bf03SJiawen Wu struct rte_mbuf *mseg; 5678d75bf03SJiawen Wu 5688d75bf03SJiawen Wu mseg = tx_pkt; 5698d75bf03SJiawen Wu do { 5708d75bf03SJiawen Wu if (mseg->data_len == 0) 5718d75bf03SJiawen Wu return true; 5728d75bf03SJiawen Wu total_len += mseg->data_len; 5738d75bf03SJiawen Wu nb_seg++; 5748d75bf03SJiawen Wu mseg = mseg->next; 5758d75bf03SJiawen Wu } while (mseg != NULL); 5768d75bf03SJiawen Wu 5778d75bf03SJiawen Wu if (tx_pkt->pkt_len != total_len || tx_pkt->pkt_len == 0) 5788d75bf03SJiawen Wu return true; 5798d75bf03SJiawen Wu 5808d75bf03SJiawen Wu if (tx_pkt->nb_segs != nb_seg || tx_pkt->nb_segs > 64) 5818d75bf03SJiawen Wu return true; 5828d75bf03SJiawen Wu 5838d75bf03SJiawen Wu return false; 5848d75bf03SJiawen Wu } 5858d75bf03SJiawen Wu 5869f320614SJiawen Wu uint16_t 5879f320614SJiawen Wu ngbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 5889f320614SJiawen Wu uint16_t nb_pkts) 5899f320614SJiawen Wu { 5909f320614SJiawen Wu struct ngbe_tx_queue *txq; 5919f320614SJiawen Wu struct ngbe_tx_entry *sw_ring; 5929f320614SJiawen Wu struct ngbe_tx_entry *txe, *txn; 5939f320614SJiawen Wu volatile struct ngbe_tx_desc *txr; 5949f320614SJiawen Wu volatile struct ngbe_tx_desc *txd; 5959f320614SJiawen Wu struct rte_mbuf *tx_pkt; 5969f320614SJiawen Wu struct rte_mbuf *m_seg; 5979f320614SJiawen Wu uint64_t buf_dma_addr; 5989f320614SJiawen Wu uint32_t olinfo_status; 5999f320614SJiawen Wu uint32_t cmd_type_len; 6009f320614SJiawen Wu uint32_t pkt_len; 6019f320614SJiawen Wu uint16_t slen; 6029f320614SJiawen Wu uint64_t ol_flags; 6039f320614SJiawen Wu uint16_t tx_id; 6049f320614SJiawen Wu uint16_t tx_last; 6059f320614SJiawen Wu uint16_t nb_tx; 6069f320614SJiawen Wu uint16_t nb_used; 6079f320614SJiawen Wu uint64_t tx_ol_req; 6089f320614SJiawen Wu uint32_t ctx = 0; 6099f320614SJiawen Wu uint32_t new_ctx; 6109f320614SJiawen Wu union ngbe_tx_offload tx_offload; 6119f320614SJiawen Wu 6129f320614SJiawen Wu tx_offload.data[0] = 0; 6139f320614SJiawen Wu tx_offload.data[1] = 0; 6149f320614SJiawen Wu txq = tx_queue; 6159f320614SJiawen Wu sw_ring = txq->sw_ring; 6169f320614SJiawen Wu txr = txq->tx_ring; 6179f320614SJiawen Wu tx_id = txq->tx_tail; 6189f320614SJiawen Wu txe = &sw_ring[tx_id]; 6199f320614SJiawen Wu 6209f320614SJiawen Wu /* Determine if the descriptor ring needs to be cleaned. */ 6219f320614SJiawen Wu if (txq->nb_tx_free < txq->tx_free_thresh) 6229f320614SJiawen Wu ngbe_xmit_cleanup(txq); 6239f320614SJiawen Wu 6249f320614SJiawen Wu rte_prefetch0(&txe->mbuf->pool); 6259f320614SJiawen Wu 6269f320614SJiawen Wu /* Tx loop */ 6279f320614SJiawen Wu for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) { 6289f320614SJiawen Wu new_ctx = 0; 6299f320614SJiawen Wu tx_pkt = *tx_pkts++; 6308d75bf03SJiawen Wu if (ngbe_check_pkt_err(tx_pkt)) { 6318d75bf03SJiawen Wu rte_pktmbuf_free(tx_pkt); 6323eba2f28SJiawen Wu txq->desc_error++; 6338d75bf03SJiawen Wu continue; 6348d75bf03SJiawen Wu } 6358d75bf03SJiawen Wu 6369f320614SJiawen Wu pkt_len = tx_pkt->pkt_len; 6379f320614SJiawen Wu 6389f320614SJiawen Wu /* 6399f320614SJiawen Wu * Determine how many (if any) context descriptors 6409f320614SJiawen Wu * are needed for offload functionality. 6419f320614SJiawen Wu */ 6429f320614SJiawen Wu ol_flags = tx_pkt->ol_flags; 6439f320614SJiawen Wu 6449f320614SJiawen Wu /* If hardware offload required */ 6459f320614SJiawen Wu tx_ol_req = ol_flags & NGBE_TX_OFFLOAD_MASK; 6469f320614SJiawen Wu if (tx_ol_req) { 647fa402b1eSJiawen Wu tx_offload.ptid = tx_desc_ol_flags_to_ptid(tx_ol_req); 6489f320614SJiawen Wu tx_offload.l2_len = tx_pkt->l2_len; 6499f320614SJiawen Wu tx_offload.l3_len = tx_pkt->l3_len; 6509f320614SJiawen Wu tx_offload.l4_len = tx_pkt->l4_len; 65159b46438SJiawen Wu tx_offload.vlan_tci = tx_pkt->vlan_tci; 6529f320614SJiawen Wu tx_offload.tso_segsz = tx_pkt->tso_segsz; 6539f320614SJiawen Wu 6549f320614SJiawen Wu /* If new context need be built or reuse the exist ctx*/ 6559f320614SJiawen Wu ctx = what_ctx_update(txq, tx_ol_req, tx_offload); 6569f320614SJiawen Wu /* Only allocate context descriptor if required */ 6579f320614SJiawen Wu new_ctx = (ctx == NGBE_CTX_NUM); 6589f320614SJiawen Wu ctx = txq->ctx_curr; 6599f320614SJiawen Wu } 6609f320614SJiawen Wu 6619f320614SJiawen Wu /* 6629f320614SJiawen Wu * Keep track of how many descriptors are used this loop 6639f320614SJiawen Wu * This will always be the number of segments + the number of 6649f320614SJiawen Wu * Context descriptors required to transmit the packet 6659f320614SJiawen Wu */ 6669f320614SJiawen Wu nb_used = (uint16_t)(tx_pkt->nb_segs + new_ctx); 6679f320614SJiawen Wu 6689f320614SJiawen Wu /* 6699f320614SJiawen Wu * The number of descriptors that must be allocated for a 6709f320614SJiawen Wu * packet is the number of segments of that packet, plus 1 6719f320614SJiawen Wu * Context Descriptor for the hardware offload, if any. 6729f320614SJiawen Wu * Determine the last Tx descriptor to allocate in the Tx ring 6739f320614SJiawen Wu * for the packet, starting from the current position (tx_id) 6749f320614SJiawen Wu * in the ring. 6759f320614SJiawen Wu */ 6769f320614SJiawen Wu tx_last = (uint16_t)(tx_id + nb_used - 1); 6779f320614SJiawen Wu 6789f320614SJiawen Wu /* Circular ring */ 6799f320614SJiawen Wu if (tx_last >= txq->nb_tx_desc) 6809f320614SJiawen Wu tx_last = (uint16_t)(tx_last - txq->nb_tx_desc); 6819f320614SJiawen Wu 6829f320614SJiawen Wu PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u pktlen=%u" 6839f320614SJiawen Wu " tx_first=%u tx_last=%u", 6849f320614SJiawen Wu (uint16_t)txq->port_id, 6859f320614SJiawen Wu (uint16_t)txq->queue_id, 6869f320614SJiawen Wu (uint32_t)pkt_len, 6879f320614SJiawen Wu (uint16_t)tx_id, 6889f320614SJiawen Wu (uint16_t)tx_last); 6899f320614SJiawen Wu 6909f320614SJiawen Wu /* 6919f320614SJiawen Wu * Make sure there are enough Tx descriptors available to 6929f320614SJiawen Wu * transmit the entire packet. 6939f320614SJiawen Wu * nb_used better be less than or equal to txq->tx_free_thresh 6949f320614SJiawen Wu */ 6959f320614SJiawen Wu if (nb_used > txq->nb_tx_free) { 6969f320614SJiawen Wu PMD_TX_LOG(DEBUG, 6979f320614SJiawen Wu "Not enough free Tx descriptors " 6989f320614SJiawen Wu "nb_used=%4u nb_free=%4u " 6999f320614SJiawen Wu "(port=%d queue=%d)", 7009f320614SJiawen Wu nb_used, txq->nb_tx_free, 7019f320614SJiawen Wu txq->port_id, txq->queue_id); 7029f320614SJiawen Wu 7039f320614SJiawen Wu if (ngbe_xmit_cleanup(txq) != 0) { 7049f320614SJiawen Wu /* Could not clean any descriptors */ 7059f320614SJiawen Wu if (nb_tx == 0) 7069f320614SJiawen Wu return 0; 7079f320614SJiawen Wu goto end_of_tx; 7089f320614SJiawen Wu } 7099f320614SJiawen Wu 7109f320614SJiawen Wu /* nb_used better be <= txq->tx_free_thresh */ 7119f320614SJiawen Wu if (unlikely(nb_used > txq->tx_free_thresh)) { 7129f320614SJiawen Wu PMD_TX_LOG(DEBUG, 7139f320614SJiawen Wu "The number of descriptors needed to " 7149f320614SJiawen Wu "transmit the packet exceeds the " 7159f320614SJiawen Wu "RS bit threshold. This will impact " 7169f320614SJiawen Wu "performance." 7179f320614SJiawen Wu "nb_used=%4u nb_free=%4u " 7189f320614SJiawen Wu "tx_free_thresh=%4u. " 7199f320614SJiawen Wu "(port=%d queue=%d)", 7209f320614SJiawen Wu nb_used, txq->nb_tx_free, 7219f320614SJiawen Wu txq->tx_free_thresh, 7229f320614SJiawen Wu txq->port_id, txq->queue_id); 7239f320614SJiawen Wu /* 7249f320614SJiawen Wu * Loop here until there are enough Tx 7259f320614SJiawen Wu * descriptors or until the ring cannot be 7269f320614SJiawen Wu * cleaned. 7279f320614SJiawen Wu */ 7289f320614SJiawen Wu while (nb_used > txq->nb_tx_free) { 7299f320614SJiawen Wu if (ngbe_xmit_cleanup(txq) != 0) { 7309f320614SJiawen Wu /* 7319f320614SJiawen Wu * Could not clean any 7329f320614SJiawen Wu * descriptors 7339f320614SJiawen Wu */ 7349f320614SJiawen Wu if (nb_tx == 0) 7359f320614SJiawen Wu return 0; 7369f320614SJiawen Wu goto end_of_tx; 7379f320614SJiawen Wu } 7389f320614SJiawen Wu } 7399f320614SJiawen Wu } 7409f320614SJiawen Wu } 7419f320614SJiawen Wu 7429f320614SJiawen Wu /* 7439f320614SJiawen Wu * By now there are enough free Tx descriptors to transmit 7449f320614SJiawen Wu * the packet. 7459f320614SJiawen Wu */ 7469f320614SJiawen Wu 7479f320614SJiawen Wu /* 7489f320614SJiawen Wu * Set common flags of all Tx Data Descriptors. 7499f320614SJiawen Wu * 7509f320614SJiawen Wu * The following bits must be set in the first Data Descriptor 7519f320614SJiawen Wu * and are ignored in the other ones: 7529f320614SJiawen Wu * - NGBE_TXD_FCS 7539f320614SJiawen Wu * 7549f320614SJiawen Wu * The following bits must only be set in the last Data 7559f320614SJiawen Wu * Descriptor: 7569f320614SJiawen Wu * - NGBE_TXD_EOP 7579f320614SJiawen Wu */ 7589f320614SJiawen Wu cmd_type_len = NGBE_TXD_FCS; 7599f320614SJiawen Wu 76024cd85f7SJiawen Wu #ifdef RTE_LIBRTE_IEEE1588 76160ad04e2SGagandeep Singh if (ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) 76224cd85f7SJiawen Wu cmd_type_len |= NGBE_TXD_1588; 76324cd85f7SJiawen Wu #endif 76424cd85f7SJiawen Wu 7659f320614SJiawen Wu olinfo_status = 0; 7669f320614SJiawen Wu if (tx_ol_req) { 7679f320614SJiawen Wu if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) { 7689f320614SJiawen Wu /* when TSO is on, paylen in descriptor is the 7699f320614SJiawen Wu * not the packet len but the tcp payload len 7709f320614SJiawen Wu */ 7719f320614SJiawen Wu pkt_len -= (tx_offload.l2_len + 7729f320614SJiawen Wu tx_offload.l3_len + tx_offload.l4_len); 7739f320614SJiawen Wu } 7749f320614SJiawen Wu 7759f320614SJiawen Wu /* 7769f320614SJiawen Wu * Setup the Tx Context Descriptor if required 7779f320614SJiawen Wu */ 7789f320614SJiawen Wu if (new_ctx) { 7799f320614SJiawen Wu volatile struct ngbe_tx_ctx_desc *ctx_txd; 7809f320614SJiawen Wu 7819f320614SJiawen Wu ctx_txd = (volatile struct ngbe_tx_ctx_desc *) 7829f320614SJiawen Wu &txr[tx_id]; 7839f320614SJiawen Wu 7849f320614SJiawen Wu txn = &sw_ring[txe->next_id]; 7859f320614SJiawen Wu rte_prefetch0(&txn->mbuf->pool); 7869f320614SJiawen Wu 7879f320614SJiawen Wu if (txe->mbuf != NULL) { 7889f320614SJiawen Wu rte_pktmbuf_free_seg(txe->mbuf); 7899f320614SJiawen Wu txe->mbuf = NULL; 7909f320614SJiawen Wu } 7919f320614SJiawen Wu 7929f320614SJiawen Wu ngbe_set_xmit_ctx(txq, ctx_txd, tx_ol_req, 7939f320614SJiawen Wu tx_offload); 7949f320614SJiawen Wu 7959f320614SJiawen Wu txe->last_id = tx_last; 7969f320614SJiawen Wu tx_id = txe->next_id; 7979f320614SJiawen Wu txe = txn; 7989f320614SJiawen Wu } 7999f320614SJiawen Wu 8009f320614SJiawen Wu /* 8019f320614SJiawen Wu * Setup the Tx Data Descriptor, 8029f320614SJiawen Wu * This path will go through 8039f320614SJiawen Wu * whatever new/reuse the context descriptor 8049f320614SJiawen Wu */ 8059f320614SJiawen Wu cmd_type_len |= tx_desc_ol_flags_to_cmdtype(ol_flags); 8069f320614SJiawen Wu olinfo_status |= 8079f320614SJiawen Wu tx_desc_cksum_flags_to_olinfo(ol_flags); 8089f320614SJiawen Wu olinfo_status |= NGBE_TXD_IDX(ctx); 8099f320614SJiawen Wu } 8109f320614SJiawen Wu 8119f320614SJiawen Wu olinfo_status |= NGBE_TXD_PAYLEN(pkt_len); 8129f320614SJiawen Wu 8139f320614SJiawen Wu m_seg = tx_pkt; 8149f320614SJiawen Wu do { 8159f320614SJiawen Wu txd = &txr[tx_id]; 8169f320614SJiawen Wu txn = &sw_ring[txe->next_id]; 8179f320614SJiawen Wu rte_prefetch0(&txn->mbuf->pool); 8189f320614SJiawen Wu 8199f320614SJiawen Wu if (txe->mbuf != NULL) 8209f320614SJiawen Wu rte_pktmbuf_free_seg(txe->mbuf); 8219f320614SJiawen Wu txe->mbuf = m_seg; 8229f320614SJiawen Wu 8239f320614SJiawen Wu /* 8249f320614SJiawen Wu * Set up Transmit Data Descriptor. 8259f320614SJiawen Wu */ 8269f320614SJiawen Wu slen = m_seg->data_len; 8279f320614SJiawen Wu buf_dma_addr = rte_mbuf_data_iova(m_seg); 8289f320614SJiawen Wu txd->qw0 = rte_cpu_to_le_64(buf_dma_addr); 8299f320614SJiawen Wu txd->dw2 = rte_cpu_to_le_32(cmd_type_len | slen); 8309f320614SJiawen Wu txd->dw3 = rte_cpu_to_le_32(olinfo_status); 8319f320614SJiawen Wu txe->last_id = tx_last; 8329f320614SJiawen Wu tx_id = txe->next_id; 8339f320614SJiawen Wu txe = txn; 8349f320614SJiawen Wu m_seg = m_seg->next; 8359f320614SJiawen Wu } while (m_seg != NULL); 8369f320614SJiawen Wu 8379f320614SJiawen Wu /* 8389f320614SJiawen Wu * The last packet data descriptor needs End Of Packet (EOP) 8399f320614SJiawen Wu */ 8409f320614SJiawen Wu cmd_type_len |= NGBE_TXD_EOP; 8419f320614SJiawen Wu txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_used); 8429f320614SJiawen Wu 8439f320614SJiawen Wu txd->dw2 |= rte_cpu_to_le_32(cmd_type_len); 8449f320614SJiawen Wu } 8459f320614SJiawen Wu 8469f320614SJiawen Wu end_of_tx: 8479f320614SJiawen Wu 8489f320614SJiawen Wu rte_wmb(); 8499f320614SJiawen Wu 8509f320614SJiawen Wu /* 8519f320614SJiawen Wu * Set the Transmit Descriptor Tail (TDT) 8529f320614SJiawen Wu */ 8539f320614SJiawen Wu PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u tx_tail=%u nb_tx=%u", 8549f320614SJiawen Wu (uint16_t)txq->port_id, (uint16_t)txq->queue_id, 8559f320614SJiawen Wu (uint16_t)tx_id, (uint16_t)nb_tx); 8569f320614SJiawen Wu ngbe_set32_relaxed(txq->tdt_reg_addr, tx_id); 8579f320614SJiawen Wu txq->tx_tail = tx_id; 8589f320614SJiawen Wu 8599f320614SJiawen Wu return nb_tx; 8609f320614SJiawen Wu } 8619f320614SJiawen Wu 8629f320614SJiawen Wu /********************************************************************* 8639f320614SJiawen Wu * 8649f320614SJiawen Wu * Tx prep functions 8659f320614SJiawen Wu * 8669f320614SJiawen Wu **********************************************************************/ 8679f320614SJiawen Wu uint16_t 8689f320614SJiawen Wu ngbe_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) 8699f320614SJiawen Wu { 8709f320614SJiawen Wu int i, ret; 8719f320614SJiawen Wu uint64_t ol_flags; 8729f320614SJiawen Wu struct rte_mbuf *m; 8739f320614SJiawen Wu struct ngbe_tx_queue *txq = (struct ngbe_tx_queue *)tx_queue; 8749f320614SJiawen Wu 8759f320614SJiawen Wu for (i = 0; i < nb_pkts; i++) { 8769f320614SJiawen Wu m = tx_pkts[i]; 8779f320614SJiawen Wu ol_flags = m->ol_flags; 8789f320614SJiawen Wu 8799f320614SJiawen Wu /** 8809f320614SJiawen Wu * Check if packet meets requirements for number of segments 8819f320614SJiawen Wu * 8829f320614SJiawen Wu * NOTE: for ngbe it's always (40 - WTHRESH) for both TSO and 8839f320614SJiawen Wu * non-TSO 8849f320614SJiawen Wu */ 8859f320614SJiawen Wu 8869f320614SJiawen Wu if (m->nb_segs > NGBE_TX_MAX_SEG - txq->wthresh) { 8879f320614SJiawen Wu rte_errno = -EINVAL; 8889f320614SJiawen Wu return i; 8899f320614SJiawen Wu } 8909f320614SJiawen Wu 8919f320614SJiawen Wu if (ol_flags & NGBE_TX_OFFLOAD_NOTSUP_MASK) { 8929f320614SJiawen Wu rte_errno = -ENOTSUP; 8939f320614SJiawen Wu return i; 8949f320614SJiawen Wu } 8959f320614SJiawen Wu 8969f320614SJiawen Wu #ifdef RTE_ETHDEV_DEBUG_TX 8979f320614SJiawen Wu ret = rte_validate_tx_offload(m); 8989f320614SJiawen Wu if (ret != 0) { 8999f320614SJiawen Wu rte_errno = ret; 9009f320614SJiawen Wu return i; 9019f320614SJiawen Wu } 9029f320614SJiawen Wu #endif 9039f320614SJiawen Wu ret = rte_net_intel_cksum_prepare(m); 9049f320614SJiawen Wu if (ret != 0) { 9059f320614SJiawen Wu rte_errno = ret; 9069f320614SJiawen Wu return i; 9079f320614SJiawen Wu } 9089f320614SJiawen Wu } 9099f320614SJiawen Wu 9109f320614SJiawen Wu return i; 9119f320614SJiawen Wu } 9129f320614SJiawen Wu 913aad91eddSJiawen Wu /********************************************************************* 914aad91eddSJiawen Wu * 91593dfebd2SJiawen Wu * Rx functions 91693dfebd2SJiawen Wu * 91793dfebd2SJiawen Wu **********************************************************************/ 918f6aef1daSJiawen Wu static inline uint32_t 919f6aef1daSJiawen Wu ngbe_rxd_pkt_info_to_pkt_type(uint32_t pkt_info, uint16_t ptid_mask) 920f6aef1daSJiawen Wu { 921f6aef1daSJiawen Wu uint16_t ptid = NGBE_RXD_PTID(pkt_info); 922f6aef1daSJiawen Wu 923f6aef1daSJiawen Wu ptid &= ptid_mask; 924f6aef1daSJiawen Wu 925f6aef1daSJiawen Wu return ngbe_decode_ptype(ptid); 926f6aef1daSJiawen Wu } 927f6aef1daSJiawen Wu 928ffc959f5SJiawen Wu static inline uint64_t 9290779d7f6SJiawen Wu ngbe_rxd_pkt_info_to_pkt_flags(uint32_t pkt_info) 9300779d7f6SJiawen Wu { 93127595cd8STyler Retzlaff static alignas(RTE_CACHE_LINE_SIZE) uint64_t ip_rss_types_map[16] = { 9320779d7f6SJiawen Wu 0, RTE_MBUF_F_RX_RSS_HASH, RTE_MBUF_F_RX_RSS_HASH, RTE_MBUF_F_RX_RSS_HASH, 9330779d7f6SJiawen Wu 0, RTE_MBUF_F_RX_RSS_HASH, 0, RTE_MBUF_F_RX_RSS_HASH, 9340779d7f6SJiawen Wu RTE_MBUF_F_RX_RSS_HASH, 0, 0, 0, 9350779d7f6SJiawen Wu 0, 0, 0, RTE_MBUF_F_RX_FDIR, 9360779d7f6SJiawen Wu }; 93724cd85f7SJiawen Wu #ifdef RTE_LIBRTE_IEEE1588 93824cd85f7SJiawen Wu static uint64_t ip_pkt_etqf_map[8] = { 93960ad04e2SGagandeep Singh 0, 0, 0, RTE_MBUF_F_RX_IEEE1588_PTP, 94024cd85f7SJiawen Wu 0, 0, 0, 0, 94124cd85f7SJiawen Wu }; 94224cd85f7SJiawen Wu int etfid = ngbe_etflt_id(NGBE_RXD_PTID(pkt_info)); 94324cd85f7SJiawen Wu if (likely(-1 != etfid)) 94424cd85f7SJiawen Wu return ip_pkt_etqf_map[etfid] | 94524cd85f7SJiawen Wu ip_rss_types_map[NGBE_RXD_RSSTYPE(pkt_info)]; 94624cd85f7SJiawen Wu else 9470779d7f6SJiawen Wu return ip_rss_types_map[NGBE_RXD_RSSTYPE(pkt_info)]; 94824cd85f7SJiawen Wu #else 94924cd85f7SJiawen Wu return ip_rss_types_map[NGBE_RXD_RSSTYPE(pkt_info)]; 95024cd85f7SJiawen Wu #endif 9510779d7f6SJiawen Wu } 9520779d7f6SJiawen Wu 9530779d7f6SJiawen Wu static inline uint64_t 95459b46438SJiawen Wu rx_desc_status_to_pkt_flags(uint32_t rx_status, uint64_t vlan_flags) 95559b46438SJiawen Wu { 95659b46438SJiawen Wu uint64_t pkt_flags; 95759b46438SJiawen Wu 95859b46438SJiawen Wu /* 95959b46438SJiawen Wu * Check if VLAN present only. 96059b46438SJiawen Wu * Do not check whether L3/L4 rx checksum done by NIC or not, 96159b46438SJiawen Wu * That can be found from rte_eth_rxmode.offloads flag 96259b46438SJiawen Wu */ 96359b46438SJiawen Wu pkt_flags = (rx_status & NGBE_RXD_STAT_VLAN && 96459b46438SJiawen Wu vlan_flags & RTE_MBUF_F_RX_VLAN_STRIPPED) 96559b46438SJiawen Wu ? vlan_flags : 0; 96659b46438SJiawen Wu 96724cd85f7SJiawen Wu #ifdef RTE_LIBRTE_IEEE1588 96824cd85f7SJiawen Wu if (rx_status & NGBE_RXD_STAT_1588) 96960ad04e2SGagandeep Singh pkt_flags = pkt_flags | RTE_MBUF_F_RX_IEEE1588_TMST; 97024cd85f7SJiawen Wu #endif 97159b46438SJiawen Wu return pkt_flags; 97259b46438SJiawen Wu } 97359b46438SJiawen Wu 97459b46438SJiawen Wu static inline uint64_t 975ffc959f5SJiawen Wu rx_desc_error_to_pkt_flags(uint32_t rx_status) 976ffc959f5SJiawen Wu { 977ffc959f5SJiawen Wu uint64_t pkt_flags = 0; 978ffc959f5SJiawen Wu 979ffc959f5SJiawen Wu /* checksum offload can't be disabled */ 980ffc959f5SJiawen Wu if (rx_status & NGBE_RXD_STAT_IPCS) 981ffc959f5SJiawen Wu pkt_flags |= (rx_status & NGBE_RXD_ERR_IPCS 982ffc959f5SJiawen Wu ? RTE_MBUF_F_RX_IP_CKSUM_BAD : RTE_MBUF_F_RX_IP_CKSUM_GOOD); 983ffc959f5SJiawen Wu 984ffc959f5SJiawen Wu if (rx_status & NGBE_RXD_STAT_L4CS) 985ffc959f5SJiawen Wu pkt_flags |= (rx_status & NGBE_RXD_ERR_L4CS 986ffc959f5SJiawen Wu ? RTE_MBUF_F_RX_L4_CKSUM_BAD : RTE_MBUF_F_RX_L4_CKSUM_GOOD); 987ffc959f5SJiawen Wu 988ffc959f5SJiawen Wu if (rx_status & NGBE_RXD_STAT_EIPCS && 989ffc959f5SJiawen Wu rx_status & NGBE_RXD_ERR_EIPCS) 990ffc959f5SJiawen Wu pkt_flags |= RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD; 991ffc959f5SJiawen Wu 992ffc959f5SJiawen Wu return pkt_flags; 993ffc959f5SJiawen Wu } 994ffc959f5SJiawen Wu 99579f3128dSJiawen Wu /* 99679f3128dSJiawen Wu * LOOK_AHEAD defines how many desc statuses to check beyond the 99779f3128dSJiawen Wu * current descriptor. 99879f3128dSJiawen Wu * It must be a pound define for optimal performance. 99979f3128dSJiawen Wu * Do not change the value of LOOK_AHEAD, as the ngbe_rx_scan_hw_ring 100079f3128dSJiawen Wu * function only works with LOOK_AHEAD=8. 100179f3128dSJiawen Wu */ 100279f3128dSJiawen Wu #define LOOK_AHEAD 8 100379f3128dSJiawen Wu #if (LOOK_AHEAD != 8) 100479f3128dSJiawen Wu #error "PMD NGBE: LOOK_AHEAD must be 8\n" 100579f3128dSJiawen Wu #endif 100679f3128dSJiawen Wu static inline int 100779f3128dSJiawen Wu ngbe_rx_scan_hw_ring(struct ngbe_rx_queue *rxq) 100879f3128dSJiawen Wu { 100979f3128dSJiawen Wu volatile struct ngbe_rx_desc *rxdp; 101079f3128dSJiawen Wu struct ngbe_rx_entry *rxep; 101179f3128dSJiawen Wu struct rte_mbuf *mb; 101279f3128dSJiawen Wu uint16_t pkt_len; 1013ffc959f5SJiawen Wu uint64_t pkt_flags; 101479f3128dSJiawen Wu int nb_dd; 101579f3128dSJiawen Wu uint32_t s[LOOK_AHEAD]; 101679f3128dSJiawen Wu uint32_t pkt_info[LOOK_AHEAD]; 101779f3128dSJiawen Wu int i, j, nb_rx = 0; 101879f3128dSJiawen Wu uint32_t status; 101979f3128dSJiawen Wu 102079f3128dSJiawen Wu /* get references to current descriptor and S/W ring entry */ 102179f3128dSJiawen Wu rxdp = &rxq->rx_ring[rxq->rx_tail]; 102279f3128dSJiawen Wu rxep = &rxq->sw_ring[rxq->rx_tail]; 102379f3128dSJiawen Wu 102479f3128dSJiawen Wu status = rxdp->qw1.lo.status; 102579f3128dSJiawen Wu /* check to make sure there is at least 1 packet to receive */ 102679f3128dSJiawen Wu if (!(status & rte_cpu_to_le_32(NGBE_RXD_STAT_DD))) 102779f3128dSJiawen Wu return 0; 102879f3128dSJiawen Wu 102979f3128dSJiawen Wu /* 103079f3128dSJiawen Wu * Scan LOOK_AHEAD descriptors at a time to determine which descriptors 103179f3128dSJiawen Wu * reference packets that are ready to be received. 103279f3128dSJiawen Wu */ 103379f3128dSJiawen Wu for (i = 0; i < RTE_PMD_NGBE_RX_MAX_BURST; 103479f3128dSJiawen Wu i += LOOK_AHEAD, rxdp += LOOK_AHEAD, rxep += LOOK_AHEAD) { 103579f3128dSJiawen Wu /* Read desc statuses backwards to avoid race condition */ 103679f3128dSJiawen Wu for (j = 0; j < LOOK_AHEAD; j++) 103779f3128dSJiawen Wu s[j] = rte_le_to_cpu_32(rxdp[j].qw1.lo.status); 103879f3128dSJiawen Wu 1039a74c5001SJiawen Wu rte_atomic_thread_fence(rte_memory_order_acquire); 104079f3128dSJiawen Wu 104179f3128dSJiawen Wu /* Compute how many status bits were set */ 104279f3128dSJiawen Wu for (nb_dd = 0; nb_dd < LOOK_AHEAD && 104379f3128dSJiawen Wu (s[nb_dd] & NGBE_RXD_STAT_DD); nb_dd++) 104479f3128dSJiawen Wu ; 104579f3128dSJiawen Wu 104679f3128dSJiawen Wu for (j = 0; j < nb_dd; j++) 104779f3128dSJiawen Wu pkt_info[j] = rte_le_to_cpu_32(rxdp[j].qw0.dw0); 104879f3128dSJiawen Wu 104979f3128dSJiawen Wu nb_rx += nb_dd; 105079f3128dSJiawen Wu 105179f3128dSJiawen Wu /* Translate descriptor info to mbuf format */ 105279f3128dSJiawen Wu for (j = 0; j < nb_dd; ++j) { 105379f3128dSJiawen Wu mb = rxep[j].mbuf; 105464b36e4aSJiawen Wu pkt_len = rte_le_to_cpu_16(rxdp[j].qw1.hi.len) - 105564b36e4aSJiawen Wu rxq->crc_len; 105679f3128dSJiawen Wu mb->data_len = pkt_len; 105779f3128dSJiawen Wu mb->pkt_len = pkt_len; 105859b46438SJiawen Wu mb->vlan_tci = rte_le_to_cpu_16(rxdp[j].qw1.hi.tag); 105979f3128dSJiawen Wu 1060ffc959f5SJiawen Wu /* convert descriptor fields to rte mbuf flags */ 106159b46438SJiawen Wu pkt_flags = rx_desc_status_to_pkt_flags(s[j], 106259b46438SJiawen Wu rxq->vlan_flags); 106359b46438SJiawen Wu pkt_flags |= rx_desc_error_to_pkt_flags(s[j]); 10640779d7f6SJiawen Wu pkt_flags |= 10650779d7f6SJiawen Wu ngbe_rxd_pkt_info_to_pkt_flags(pkt_info[j]); 1066ffc959f5SJiawen Wu mb->ol_flags = pkt_flags; 106779f3128dSJiawen Wu mb->packet_type = 106879f3128dSJiawen Wu ngbe_rxd_pkt_info_to_pkt_type(pkt_info[j], 106979f3128dSJiawen Wu NGBE_PTID_MASK); 10700779d7f6SJiawen Wu 10710779d7f6SJiawen Wu if (likely(pkt_flags & RTE_MBUF_F_RX_RSS_HASH)) 10720779d7f6SJiawen Wu mb->hash.rss = 10730779d7f6SJiawen Wu rte_le_to_cpu_32(rxdp[j].qw0.dw1); 107479f3128dSJiawen Wu } 107579f3128dSJiawen Wu 107679f3128dSJiawen Wu /* Move mbuf pointers from the S/W ring to the stage */ 107779f3128dSJiawen Wu for (j = 0; j < LOOK_AHEAD; ++j) 107879f3128dSJiawen Wu rxq->rx_stage[i + j] = rxep[j].mbuf; 107979f3128dSJiawen Wu 108079f3128dSJiawen Wu /* stop if all requested packets could not be received */ 108179f3128dSJiawen Wu if (nb_dd != LOOK_AHEAD) 108279f3128dSJiawen Wu break; 108379f3128dSJiawen Wu } 108479f3128dSJiawen Wu 108579f3128dSJiawen Wu /* clear software ring entries so we can cleanup correctly */ 108679f3128dSJiawen Wu for (i = 0; i < nb_rx; ++i) 108779f3128dSJiawen Wu rxq->sw_ring[rxq->rx_tail + i].mbuf = NULL; 108879f3128dSJiawen Wu 108979f3128dSJiawen Wu return nb_rx; 109079f3128dSJiawen Wu } 109179f3128dSJiawen Wu 109279f3128dSJiawen Wu static inline int 109379f3128dSJiawen Wu ngbe_rx_alloc_bufs(struct ngbe_rx_queue *rxq, bool reset_mbuf) 109479f3128dSJiawen Wu { 109579f3128dSJiawen Wu volatile struct ngbe_rx_desc *rxdp; 109679f3128dSJiawen Wu struct ngbe_rx_entry *rxep; 109779f3128dSJiawen Wu struct rte_mbuf *mb; 109879f3128dSJiawen Wu uint16_t alloc_idx; 109979f3128dSJiawen Wu __le64 dma_addr; 110079f3128dSJiawen Wu int diag, i; 110179f3128dSJiawen Wu 110279f3128dSJiawen Wu /* allocate buffers in bulk directly into the S/W ring */ 110379f3128dSJiawen Wu alloc_idx = rxq->rx_free_trigger - (rxq->rx_free_thresh - 1); 110479f3128dSJiawen Wu rxep = &rxq->sw_ring[alloc_idx]; 110579f3128dSJiawen Wu diag = rte_mempool_get_bulk(rxq->mb_pool, (void *)rxep, 110679f3128dSJiawen Wu rxq->rx_free_thresh); 110779f3128dSJiawen Wu if (unlikely(diag != 0)) 110879f3128dSJiawen Wu return -ENOMEM; 110979f3128dSJiawen Wu 111079f3128dSJiawen Wu rxdp = &rxq->rx_ring[alloc_idx]; 111179f3128dSJiawen Wu for (i = 0; i < rxq->rx_free_thresh; ++i) { 111279f3128dSJiawen Wu /* populate the static rte mbuf fields */ 111379f3128dSJiawen Wu mb = rxep[i].mbuf; 111479f3128dSJiawen Wu if (reset_mbuf) 111579f3128dSJiawen Wu mb->port = rxq->port_id; 111679f3128dSJiawen Wu 111779f3128dSJiawen Wu rte_mbuf_refcnt_set(mb, 1); 111879f3128dSJiawen Wu mb->data_off = RTE_PKTMBUF_HEADROOM; 111979f3128dSJiawen Wu 112079f3128dSJiawen Wu /* populate the descriptors */ 112179f3128dSJiawen Wu dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(mb)); 112279f3128dSJiawen Wu NGBE_RXD_HDRADDR(&rxdp[i], 0); 112379f3128dSJiawen Wu NGBE_RXD_PKTADDR(&rxdp[i], dma_addr); 112479f3128dSJiawen Wu } 112579f3128dSJiawen Wu 112679f3128dSJiawen Wu /* update state of internal queue structure */ 112779f3128dSJiawen Wu rxq->rx_free_trigger = rxq->rx_free_trigger + rxq->rx_free_thresh; 112879f3128dSJiawen Wu if (rxq->rx_free_trigger >= rxq->nb_rx_desc) 112979f3128dSJiawen Wu rxq->rx_free_trigger = rxq->rx_free_thresh - 1; 113079f3128dSJiawen Wu 113179f3128dSJiawen Wu /* no errors */ 113279f3128dSJiawen Wu return 0; 113379f3128dSJiawen Wu } 113479f3128dSJiawen Wu 113579f3128dSJiawen Wu static inline uint16_t 113679f3128dSJiawen Wu ngbe_rx_fill_from_stage(struct ngbe_rx_queue *rxq, struct rte_mbuf **rx_pkts, 113779f3128dSJiawen Wu uint16_t nb_pkts) 113879f3128dSJiawen Wu { 113979f3128dSJiawen Wu struct rte_mbuf **stage = &rxq->rx_stage[rxq->rx_next_avail]; 114079f3128dSJiawen Wu int i; 114179f3128dSJiawen Wu 114279f3128dSJiawen Wu /* how many packets are ready to return? */ 114379f3128dSJiawen Wu nb_pkts = (uint16_t)RTE_MIN(nb_pkts, rxq->rx_nb_avail); 114479f3128dSJiawen Wu 114579f3128dSJiawen Wu /* copy mbuf pointers to the application's packet list */ 114679f3128dSJiawen Wu for (i = 0; i < nb_pkts; ++i) 114779f3128dSJiawen Wu rx_pkts[i] = stage[i]; 114879f3128dSJiawen Wu 114979f3128dSJiawen Wu /* update internal queue state */ 115079f3128dSJiawen Wu rxq->rx_nb_avail = (uint16_t)(rxq->rx_nb_avail - nb_pkts); 115179f3128dSJiawen Wu rxq->rx_next_avail = (uint16_t)(rxq->rx_next_avail + nb_pkts); 115279f3128dSJiawen Wu 115379f3128dSJiawen Wu return nb_pkts; 115479f3128dSJiawen Wu } 115579f3128dSJiawen Wu 115679f3128dSJiawen Wu static inline uint16_t 115779f3128dSJiawen Wu ngbe_rx_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, 115879f3128dSJiawen Wu uint16_t nb_pkts) 115979f3128dSJiawen Wu { 116079f3128dSJiawen Wu struct ngbe_rx_queue *rxq = (struct ngbe_rx_queue *)rx_queue; 116179f3128dSJiawen Wu struct rte_eth_dev *dev = &rte_eth_devices[rxq->port_id]; 116279f3128dSJiawen Wu uint16_t nb_rx = 0; 116379f3128dSJiawen Wu 116479f3128dSJiawen Wu /* Any previously recv'd pkts will be returned from the Rx stage */ 116579f3128dSJiawen Wu if (rxq->rx_nb_avail) 116679f3128dSJiawen Wu return ngbe_rx_fill_from_stage(rxq, rx_pkts, nb_pkts); 116779f3128dSJiawen Wu 116879f3128dSJiawen Wu /* Scan the H/W ring for packets to receive */ 116979f3128dSJiawen Wu nb_rx = (uint16_t)ngbe_rx_scan_hw_ring(rxq); 117079f3128dSJiawen Wu 117179f3128dSJiawen Wu /* update internal queue state */ 117279f3128dSJiawen Wu rxq->rx_next_avail = 0; 117379f3128dSJiawen Wu rxq->rx_nb_avail = nb_rx; 117479f3128dSJiawen Wu rxq->rx_tail = (uint16_t)(rxq->rx_tail + nb_rx); 117579f3128dSJiawen Wu 117679f3128dSJiawen Wu /* if required, allocate new buffers to replenish descriptors */ 117779f3128dSJiawen Wu if (rxq->rx_tail > rxq->rx_free_trigger) { 117879f3128dSJiawen Wu uint16_t cur_free_trigger = rxq->rx_free_trigger; 117979f3128dSJiawen Wu 118079f3128dSJiawen Wu if (ngbe_rx_alloc_bufs(rxq, true) != 0) { 118179f3128dSJiawen Wu int i, j; 118279f3128dSJiawen Wu 118379f3128dSJiawen Wu PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u " 118479f3128dSJiawen Wu "queue_id=%u", (uint16_t)rxq->port_id, 118579f3128dSJiawen Wu (uint16_t)rxq->queue_id); 118679f3128dSJiawen Wu 118779f3128dSJiawen Wu dev->data->rx_mbuf_alloc_failed += 118879f3128dSJiawen Wu rxq->rx_free_thresh; 118979f3128dSJiawen Wu 119079f3128dSJiawen Wu /* 119179f3128dSJiawen Wu * Need to rewind any previous receives if we cannot 119279f3128dSJiawen Wu * allocate new buffers to replenish the old ones. 119379f3128dSJiawen Wu */ 119479f3128dSJiawen Wu rxq->rx_nb_avail = 0; 119579f3128dSJiawen Wu rxq->rx_tail = (uint16_t)(rxq->rx_tail - nb_rx); 119679f3128dSJiawen Wu for (i = 0, j = rxq->rx_tail; i < nb_rx; ++i, ++j) 119779f3128dSJiawen Wu rxq->sw_ring[j].mbuf = rxq->rx_stage[i]; 119879f3128dSJiawen Wu 119979f3128dSJiawen Wu return 0; 120079f3128dSJiawen Wu } 120179f3128dSJiawen Wu 120279f3128dSJiawen Wu /* update tail pointer */ 120379f3128dSJiawen Wu rte_wmb(); 120479f3128dSJiawen Wu ngbe_set32_relaxed(rxq->rdt_reg_addr, cur_free_trigger); 120579f3128dSJiawen Wu } 120679f3128dSJiawen Wu 120779f3128dSJiawen Wu if (rxq->rx_tail >= rxq->nb_rx_desc) 120879f3128dSJiawen Wu rxq->rx_tail = 0; 120979f3128dSJiawen Wu 121079f3128dSJiawen Wu /* received any packets this loop? */ 121179f3128dSJiawen Wu if (rxq->rx_nb_avail) 121279f3128dSJiawen Wu return ngbe_rx_fill_from_stage(rxq, rx_pkts, nb_pkts); 121379f3128dSJiawen Wu 121479f3128dSJiawen Wu return 0; 121579f3128dSJiawen Wu } 121679f3128dSJiawen Wu 121779f3128dSJiawen Wu /* split requests into chunks of size RTE_PMD_NGBE_RX_MAX_BURST */ 121879f3128dSJiawen Wu uint16_t 121979f3128dSJiawen Wu ngbe_recv_pkts_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, 122079f3128dSJiawen Wu uint16_t nb_pkts) 122179f3128dSJiawen Wu { 122279f3128dSJiawen Wu uint16_t nb_rx; 122379f3128dSJiawen Wu 122479f3128dSJiawen Wu if (unlikely(nb_pkts == 0)) 122579f3128dSJiawen Wu return 0; 122679f3128dSJiawen Wu 122779f3128dSJiawen Wu if (likely(nb_pkts <= RTE_PMD_NGBE_RX_MAX_BURST)) 122879f3128dSJiawen Wu return ngbe_rx_recv_pkts(rx_queue, rx_pkts, nb_pkts); 122979f3128dSJiawen Wu 123079f3128dSJiawen Wu /* request is relatively large, chunk it up */ 123179f3128dSJiawen Wu nb_rx = 0; 123279f3128dSJiawen Wu while (nb_pkts) { 123379f3128dSJiawen Wu uint16_t ret, n; 123479f3128dSJiawen Wu 123579f3128dSJiawen Wu n = (uint16_t)RTE_MIN(nb_pkts, RTE_PMD_NGBE_RX_MAX_BURST); 123679f3128dSJiawen Wu ret = ngbe_rx_recv_pkts(rx_queue, &rx_pkts[nb_rx], n); 123779f3128dSJiawen Wu nb_rx = (uint16_t)(nb_rx + ret); 123879f3128dSJiawen Wu nb_pkts = (uint16_t)(nb_pkts - ret); 123979f3128dSJiawen Wu if (ret < n) 124079f3128dSJiawen Wu break; 124179f3128dSJiawen Wu } 124279f3128dSJiawen Wu 124379f3128dSJiawen Wu return nb_rx; 124479f3128dSJiawen Wu } 124579f3128dSJiawen Wu 124693dfebd2SJiawen Wu uint16_t 124793dfebd2SJiawen Wu ngbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, 124893dfebd2SJiawen Wu uint16_t nb_pkts) 124993dfebd2SJiawen Wu { 125093dfebd2SJiawen Wu struct ngbe_rx_queue *rxq; 125193dfebd2SJiawen Wu volatile struct ngbe_rx_desc *rx_ring; 125293dfebd2SJiawen Wu volatile struct ngbe_rx_desc *rxdp; 125393dfebd2SJiawen Wu struct ngbe_rx_entry *sw_ring; 125493dfebd2SJiawen Wu struct ngbe_rx_entry *rxe; 125593dfebd2SJiawen Wu struct rte_mbuf *rxm; 125693dfebd2SJiawen Wu struct rte_mbuf *nmb; 125793dfebd2SJiawen Wu struct ngbe_rx_desc rxd; 125893dfebd2SJiawen Wu uint64_t dma_addr; 125993dfebd2SJiawen Wu uint32_t staterr; 1260f6aef1daSJiawen Wu uint32_t pkt_info; 126193dfebd2SJiawen Wu uint16_t pkt_len; 126293dfebd2SJiawen Wu uint16_t rx_id; 126393dfebd2SJiawen Wu uint16_t nb_rx; 126493dfebd2SJiawen Wu uint16_t nb_hold; 1265ffc959f5SJiawen Wu uint64_t pkt_flags; 126693dfebd2SJiawen Wu 126793dfebd2SJiawen Wu nb_rx = 0; 126893dfebd2SJiawen Wu nb_hold = 0; 126993dfebd2SJiawen Wu rxq = rx_queue; 127093dfebd2SJiawen Wu rx_id = rxq->rx_tail; 127193dfebd2SJiawen Wu rx_ring = rxq->rx_ring; 127293dfebd2SJiawen Wu sw_ring = rxq->sw_ring; 127393dfebd2SJiawen Wu struct rte_eth_dev *dev = &rte_eth_devices[rxq->port_id]; 127493dfebd2SJiawen Wu while (nb_rx < nb_pkts) { 127593dfebd2SJiawen Wu /* 127693dfebd2SJiawen Wu * The order of operations here is important as the DD status 127793dfebd2SJiawen Wu * bit must not be read after any other descriptor fields. 127893dfebd2SJiawen Wu * rx_ring and rxdp are pointing to volatile data so the order 127993dfebd2SJiawen Wu * of accesses cannot be reordered by the compiler. If they were 128093dfebd2SJiawen Wu * not volatile, they could be reordered which could lead to 128193dfebd2SJiawen Wu * using invalid descriptor fields when read from rxd. 1282a74c5001SJiawen Wu * 1283a74c5001SJiawen Wu * Meanwhile, to prevent the CPU from executing out of order, we 1284a74c5001SJiawen Wu * need to use a proper memory barrier to ensure the memory 1285a74c5001SJiawen Wu * ordering below. 128693dfebd2SJiawen Wu */ 128793dfebd2SJiawen Wu rxdp = &rx_ring[rx_id]; 128893dfebd2SJiawen Wu staterr = rxdp->qw1.lo.status; 128993dfebd2SJiawen Wu if (!(staterr & rte_cpu_to_le_32(NGBE_RXD_STAT_DD))) 129093dfebd2SJiawen Wu break; 1291a74c5001SJiawen Wu 1292a74c5001SJiawen Wu /* 1293a74c5001SJiawen Wu * Use acquire fence to ensure that status_error which includes 1294a74c5001SJiawen Wu * DD bit is loaded before loading of other descriptor words. 1295a74c5001SJiawen Wu */ 1296a74c5001SJiawen Wu rte_atomic_thread_fence(rte_memory_order_acquire); 1297a74c5001SJiawen Wu 129893dfebd2SJiawen Wu rxd = *rxdp; 129993dfebd2SJiawen Wu 130093dfebd2SJiawen Wu /* 130193dfebd2SJiawen Wu * End of packet. 130293dfebd2SJiawen Wu * 130393dfebd2SJiawen Wu * If the NGBE_RXD_STAT_EOP flag is not set, the Rx packet 130493dfebd2SJiawen Wu * is likely to be invalid and to be dropped by the various 130593dfebd2SJiawen Wu * validation checks performed by the network stack. 130693dfebd2SJiawen Wu * 130793dfebd2SJiawen Wu * Allocate a new mbuf to replenish the RX ring descriptor. 130893dfebd2SJiawen Wu * If the allocation fails: 130993dfebd2SJiawen Wu * - arrange for that Rx descriptor to be the first one 131093dfebd2SJiawen Wu * being parsed the next time the receive function is 131193dfebd2SJiawen Wu * invoked [on the same queue]. 131293dfebd2SJiawen Wu * 131393dfebd2SJiawen Wu * - Stop parsing the Rx ring and return immediately. 131493dfebd2SJiawen Wu * 131593dfebd2SJiawen Wu * This policy do not drop the packet received in the Rx 131693dfebd2SJiawen Wu * descriptor for which the allocation of a new mbuf failed. 131793dfebd2SJiawen Wu * Thus, it allows that packet to be later retrieved if 131893dfebd2SJiawen Wu * mbuf have been freed in the mean time. 131993dfebd2SJiawen Wu * As a side effect, holding Rx descriptors instead of 132093dfebd2SJiawen Wu * systematically giving them back to the NIC may lead to 132193dfebd2SJiawen Wu * Rx ring exhaustion situations. 132293dfebd2SJiawen Wu * However, the NIC can gracefully prevent such situations 132393dfebd2SJiawen Wu * to happen by sending specific "back-pressure" flow control 132493dfebd2SJiawen Wu * frames to its peer(s). 132593dfebd2SJiawen Wu */ 132693dfebd2SJiawen Wu PMD_RX_LOG(DEBUG, 132793dfebd2SJiawen Wu "port_id=%u queue_id=%u rx_id=%u ext_err_stat=0x%08x pkt_len=%u", 132893dfebd2SJiawen Wu (uint16_t)rxq->port_id, (uint16_t)rxq->queue_id, 132993dfebd2SJiawen Wu (uint16_t)rx_id, (uint32_t)staterr, 133093dfebd2SJiawen Wu (uint16_t)rte_le_to_cpu_16(rxd.qw1.hi.len)); 133193dfebd2SJiawen Wu 133293dfebd2SJiawen Wu nmb = rte_mbuf_raw_alloc(rxq->mb_pool); 133393dfebd2SJiawen Wu if (nmb == NULL) { 133493dfebd2SJiawen Wu PMD_RX_LOG(DEBUG, 133593dfebd2SJiawen Wu "Rx mbuf alloc failed port_id=%u queue_id=%u", 133693dfebd2SJiawen Wu (uint16_t)rxq->port_id, 133793dfebd2SJiawen Wu (uint16_t)rxq->queue_id); 133893dfebd2SJiawen Wu dev->data->rx_mbuf_alloc_failed++; 133993dfebd2SJiawen Wu break; 134093dfebd2SJiawen Wu } 134193dfebd2SJiawen Wu 134293dfebd2SJiawen Wu nb_hold++; 134393dfebd2SJiawen Wu rxe = &sw_ring[rx_id]; 134493dfebd2SJiawen Wu rx_id++; 134593dfebd2SJiawen Wu if (rx_id == rxq->nb_rx_desc) 134693dfebd2SJiawen Wu rx_id = 0; 134793dfebd2SJiawen Wu 134893dfebd2SJiawen Wu /* Prefetch next mbuf while processing current one. */ 134993dfebd2SJiawen Wu rte_ngbe_prefetch(sw_ring[rx_id].mbuf); 135093dfebd2SJiawen Wu 135193dfebd2SJiawen Wu /* 135293dfebd2SJiawen Wu * When next Rx descriptor is on a cache-line boundary, 135393dfebd2SJiawen Wu * prefetch the next 4 Rx descriptors and the next 8 pointers 135493dfebd2SJiawen Wu * to mbufs. 135593dfebd2SJiawen Wu */ 135693dfebd2SJiawen Wu if ((rx_id & 0x3) == 0) { 135793dfebd2SJiawen Wu rte_ngbe_prefetch(&rx_ring[rx_id]); 135893dfebd2SJiawen Wu rte_ngbe_prefetch(&sw_ring[rx_id]); 135993dfebd2SJiawen Wu } 136093dfebd2SJiawen Wu 136193dfebd2SJiawen Wu rxm = rxe->mbuf; 136293dfebd2SJiawen Wu rxe->mbuf = nmb; 136393dfebd2SJiawen Wu dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(nmb)); 136493dfebd2SJiawen Wu NGBE_RXD_HDRADDR(rxdp, 0); 136593dfebd2SJiawen Wu NGBE_RXD_PKTADDR(rxdp, dma_addr); 136693dfebd2SJiawen Wu 136793dfebd2SJiawen Wu /* 136893dfebd2SJiawen Wu * Initialize the returned mbuf. 1369ffc959f5SJiawen Wu * 1) setup generic mbuf fields: 137093dfebd2SJiawen Wu * - number of segments, 137193dfebd2SJiawen Wu * - next segment, 137293dfebd2SJiawen Wu * - packet length, 137393dfebd2SJiawen Wu * - Rx port identifier. 1374ffc959f5SJiawen Wu * 2) integrate hardware offload data, if any: 13750779d7f6SJiawen Wu * - RSS flag & hash, 1376ffc959f5SJiawen Wu * - IP checksum flag, 137759b46438SJiawen Wu * - VLAN TCI, if any, 1378ffc959f5SJiawen Wu * - error flags. 137993dfebd2SJiawen Wu */ 138064b36e4aSJiawen Wu pkt_len = (uint16_t)(rte_le_to_cpu_16(rxd.qw1.hi.len) - 138164b36e4aSJiawen Wu rxq->crc_len); 138293dfebd2SJiawen Wu rxm->data_off = RTE_PKTMBUF_HEADROOM; 138393dfebd2SJiawen Wu rte_packet_prefetch((char *)rxm->buf_addr + rxm->data_off); 138493dfebd2SJiawen Wu rxm->nb_segs = 1; 138593dfebd2SJiawen Wu rxm->next = NULL; 138693dfebd2SJiawen Wu rxm->pkt_len = pkt_len; 138793dfebd2SJiawen Wu rxm->data_len = pkt_len; 138893dfebd2SJiawen Wu rxm->port = rxq->port_id; 138993dfebd2SJiawen Wu 1390f6aef1daSJiawen Wu pkt_info = rte_le_to_cpu_32(rxd.qw0.dw0); 139159b46438SJiawen Wu /* Only valid if RTE_MBUF_F_RX_VLAN set in pkt_flags */ 139259b46438SJiawen Wu rxm->vlan_tci = rte_le_to_cpu_16(rxd.qw1.hi.tag); 139359b46438SJiawen Wu 139459b46438SJiawen Wu pkt_flags = rx_desc_status_to_pkt_flags(staterr, 139559b46438SJiawen Wu rxq->vlan_flags); 139659b46438SJiawen Wu pkt_flags |= rx_desc_error_to_pkt_flags(staterr); 13970779d7f6SJiawen Wu pkt_flags |= ngbe_rxd_pkt_info_to_pkt_flags(pkt_info); 1398ffc959f5SJiawen Wu rxm->ol_flags = pkt_flags; 1399f6aef1daSJiawen Wu rxm->packet_type = ngbe_rxd_pkt_info_to_pkt_type(pkt_info, 1400f6aef1daSJiawen Wu NGBE_PTID_MASK); 1401f6aef1daSJiawen Wu 14020779d7f6SJiawen Wu if (likely(pkt_flags & RTE_MBUF_F_RX_RSS_HASH)) 14030779d7f6SJiawen Wu rxm->hash.rss = rte_le_to_cpu_32(rxd.qw0.dw1); 14040779d7f6SJiawen Wu 140593dfebd2SJiawen Wu /* 140693dfebd2SJiawen Wu * Store the mbuf address into the next entry of the array 140793dfebd2SJiawen Wu * of returned packets. 140893dfebd2SJiawen Wu */ 140993dfebd2SJiawen Wu rx_pkts[nb_rx++] = rxm; 141093dfebd2SJiawen Wu } 141193dfebd2SJiawen Wu rxq->rx_tail = rx_id; 141293dfebd2SJiawen Wu 141393dfebd2SJiawen Wu /* 141493dfebd2SJiawen Wu * If the number of free Rx descriptors is greater than the Rx free 141593dfebd2SJiawen Wu * threshold of the queue, advance the Receive Descriptor Tail (RDT) 141693dfebd2SJiawen Wu * register. 141793dfebd2SJiawen Wu * Update the RDT with the value of the last processed Rx descriptor 141893dfebd2SJiawen Wu * minus 1, to guarantee that the RDT register is never equal to the 141993dfebd2SJiawen Wu * RDH register, which creates a "full" ring situation from the 142093dfebd2SJiawen Wu * hardware point of view... 142193dfebd2SJiawen Wu */ 142293dfebd2SJiawen Wu nb_hold = (uint16_t)(nb_hold + rxq->nb_rx_hold); 142393dfebd2SJiawen Wu if (nb_hold > rxq->rx_free_thresh) { 142493dfebd2SJiawen Wu PMD_RX_LOG(DEBUG, 142593dfebd2SJiawen Wu "port_id=%u queue_id=%u rx_tail=%u nb_hold=%u nb_rx=%u", 142693dfebd2SJiawen Wu (uint16_t)rxq->port_id, (uint16_t)rxq->queue_id, 142793dfebd2SJiawen Wu (uint16_t)rx_id, (uint16_t)nb_hold, 142893dfebd2SJiawen Wu (uint16_t)nb_rx); 142993dfebd2SJiawen Wu rx_id = (uint16_t)((rx_id == 0) ? 143093dfebd2SJiawen Wu (rxq->nb_rx_desc - 1) : (rx_id - 1)); 143193dfebd2SJiawen Wu ngbe_set32(rxq->rdt_reg_addr, rx_id); 143293dfebd2SJiawen Wu nb_hold = 0; 143393dfebd2SJiawen Wu } 143493dfebd2SJiawen Wu rxq->nb_rx_hold = nb_hold; 143593dfebd2SJiawen Wu return nb_rx; 143693dfebd2SJiawen Wu } 143793dfebd2SJiawen Wu 1438ffc959f5SJiawen Wu /** 1439ffc959f5SJiawen Wu * ngbe_fill_cluster_head_buf - fill the first mbuf of the returned packet 1440ffc959f5SJiawen Wu * 1441ffc959f5SJiawen Wu * Fill the following info in the HEAD buffer of the Rx cluster: 1442ffc959f5SJiawen Wu * - RX port identifier 1443ffc959f5SJiawen Wu * - hardware offload data, if any: 14440779d7f6SJiawen Wu * - RSS flag & hash 1445ffc959f5SJiawen Wu * - IP checksum flag 144659b46438SJiawen Wu * - VLAN TCI, if any 1447ffc959f5SJiawen Wu * - error flags 1448ffc959f5SJiawen Wu * @head HEAD of the packet cluster 1449ffc959f5SJiawen Wu * @desc HW descriptor to get data from 1450ffc959f5SJiawen Wu * @rxq Pointer to the Rx queue 1451ffc959f5SJiawen Wu */ 145279f3128dSJiawen Wu static inline void 145379f3128dSJiawen Wu ngbe_fill_cluster_head_buf(struct rte_mbuf *head, struct ngbe_rx_desc *desc, 145479f3128dSJiawen Wu struct ngbe_rx_queue *rxq, uint32_t staterr) 145579f3128dSJiawen Wu { 145679f3128dSJiawen Wu uint32_t pkt_info; 1457ffc959f5SJiawen Wu uint64_t pkt_flags; 145879f3128dSJiawen Wu 145979f3128dSJiawen Wu head->port = rxq->port_id; 146079f3128dSJiawen Wu 146159b46438SJiawen Wu /* The vlan_tci field is only valid when RTE_MBUF_F_RX_VLAN is 146259b46438SJiawen Wu * set in the pkt_flags field. 146359b46438SJiawen Wu */ 146459b46438SJiawen Wu head->vlan_tci = rte_le_to_cpu_16(desc->qw1.hi.tag); 146579f3128dSJiawen Wu pkt_info = rte_le_to_cpu_32(desc->qw0.dw0); 146659b46438SJiawen Wu pkt_flags = rx_desc_status_to_pkt_flags(staterr, rxq->vlan_flags); 146759b46438SJiawen Wu pkt_flags |= rx_desc_error_to_pkt_flags(staterr); 14680779d7f6SJiawen Wu pkt_flags |= ngbe_rxd_pkt_info_to_pkt_flags(pkt_info); 1469ffc959f5SJiawen Wu head->ol_flags = pkt_flags; 147079f3128dSJiawen Wu head->packet_type = ngbe_rxd_pkt_info_to_pkt_type(pkt_info, 147179f3128dSJiawen Wu NGBE_PTID_MASK); 14720779d7f6SJiawen Wu 14730779d7f6SJiawen Wu if (likely(pkt_flags & RTE_MBUF_F_RX_RSS_HASH)) 14740779d7f6SJiawen Wu head->hash.rss = rte_le_to_cpu_32(desc->qw0.dw1); 147579f3128dSJiawen Wu } 147679f3128dSJiawen Wu 147779f3128dSJiawen Wu /** 147879f3128dSJiawen Wu * ngbe_recv_pkts_sc - receive handler for scatter case. 147979f3128dSJiawen Wu * 148079f3128dSJiawen Wu * @rx_queue Rx queue handle 148179f3128dSJiawen Wu * @rx_pkts table of received packets 148279f3128dSJiawen Wu * @nb_pkts size of rx_pkts table 148379f3128dSJiawen Wu * @bulk_alloc if TRUE bulk allocation is used for a HW ring refilling 148479f3128dSJiawen Wu * 148579f3128dSJiawen Wu * Returns the number of received packets/clusters (according to the "bulk 148679f3128dSJiawen Wu * receive" interface). 148779f3128dSJiawen Wu */ 148879f3128dSJiawen Wu static inline uint16_t 148979f3128dSJiawen Wu ngbe_recv_pkts_sc(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts, 149079f3128dSJiawen Wu bool bulk_alloc) 149179f3128dSJiawen Wu { 149279f3128dSJiawen Wu struct ngbe_rx_queue *rxq = rx_queue; 149379f3128dSJiawen Wu struct rte_eth_dev *dev = &rte_eth_devices[rxq->port_id]; 149479f3128dSJiawen Wu volatile struct ngbe_rx_desc *rx_ring = rxq->rx_ring; 149579f3128dSJiawen Wu struct ngbe_rx_entry *sw_ring = rxq->sw_ring; 149679f3128dSJiawen Wu struct ngbe_scattered_rx_entry *sw_sc_ring = rxq->sw_sc_ring; 149779f3128dSJiawen Wu uint16_t rx_id = rxq->rx_tail; 149879f3128dSJiawen Wu uint16_t nb_rx = 0; 149979f3128dSJiawen Wu uint16_t nb_hold = rxq->nb_rx_hold; 150079f3128dSJiawen Wu uint16_t prev_id = rxq->rx_tail; 150179f3128dSJiawen Wu 150279f3128dSJiawen Wu while (nb_rx < nb_pkts) { 150379f3128dSJiawen Wu bool eop; 150479f3128dSJiawen Wu struct ngbe_rx_entry *rxe; 150579f3128dSJiawen Wu struct ngbe_scattered_rx_entry *sc_entry; 150679f3128dSJiawen Wu struct ngbe_scattered_rx_entry *next_sc_entry = NULL; 150779f3128dSJiawen Wu struct ngbe_rx_entry *next_rxe = NULL; 150879f3128dSJiawen Wu struct rte_mbuf *first_seg; 150979f3128dSJiawen Wu struct rte_mbuf *rxm; 151079f3128dSJiawen Wu struct rte_mbuf *nmb = NULL; 151179f3128dSJiawen Wu struct ngbe_rx_desc rxd; 151279f3128dSJiawen Wu uint16_t data_len; 151379f3128dSJiawen Wu uint16_t next_id; 151479f3128dSJiawen Wu volatile struct ngbe_rx_desc *rxdp; 151579f3128dSJiawen Wu uint32_t staterr; 151679f3128dSJiawen Wu 151779f3128dSJiawen Wu next_desc: 151879f3128dSJiawen Wu rxdp = &rx_ring[rx_id]; 151979f3128dSJiawen Wu staterr = rte_le_to_cpu_32(rxdp->qw1.lo.status); 152079f3128dSJiawen Wu 152179f3128dSJiawen Wu if (!(staterr & NGBE_RXD_STAT_DD)) 152279f3128dSJiawen Wu break; 152379f3128dSJiawen Wu 1524a74c5001SJiawen Wu /* 1525a74c5001SJiawen Wu * Use acquire fence to ensure that status_error which includes 1526a74c5001SJiawen Wu * DD bit is loaded before loading of other descriptor words. 1527a74c5001SJiawen Wu */ 1528a74c5001SJiawen Wu rte_atomic_thread_fence(rte_memory_order_acquire); 1529a74c5001SJiawen Wu 153079f3128dSJiawen Wu rxd = *rxdp; 153179f3128dSJiawen Wu 153279f3128dSJiawen Wu PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_id=%u " 153379f3128dSJiawen Wu "staterr=0x%x data_len=%u", 153479f3128dSJiawen Wu rxq->port_id, rxq->queue_id, rx_id, staterr, 153579f3128dSJiawen Wu rte_le_to_cpu_16(rxd.qw1.hi.len)); 153679f3128dSJiawen Wu 153779f3128dSJiawen Wu if (!bulk_alloc) { 153879f3128dSJiawen Wu nmb = rte_mbuf_raw_alloc(rxq->mb_pool); 153979f3128dSJiawen Wu if (nmb == NULL) { 154079f3128dSJiawen Wu PMD_RX_LOG(DEBUG, "Rx mbuf alloc failed " 154179f3128dSJiawen Wu "port_id=%u queue_id=%u", 154279f3128dSJiawen Wu rxq->port_id, rxq->queue_id); 154379f3128dSJiawen Wu 154479f3128dSJiawen Wu dev->data->rx_mbuf_alloc_failed++; 154579f3128dSJiawen Wu break; 154679f3128dSJiawen Wu } 154779f3128dSJiawen Wu } else if (nb_hold > rxq->rx_free_thresh) { 154879f3128dSJiawen Wu uint16_t next_rdt = rxq->rx_free_trigger; 154979f3128dSJiawen Wu 155079f3128dSJiawen Wu if (!ngbe_rx_alloc_bufs(rxq, false)) { 155179f3128dSJiawen Wu rte_wmb(); 155279f3128dSJiawen Wu ngbe_set32_relaxed(rxq->rdt_reg_addr, 155379f3128dSJiawen Wu next_rdt); 155479f3128dSJiawen Wu nb_hold -= rxq->rx_free_thresh; 155579f3128dSJiawen Wu } else { 155679f3128dSJiawen Wu PMD_RX_LOG(DEBUG, "Rx bulk alloc failed " 155779f3128dSJiawen Wu "port_id=%u queue_id=%u", 155879f3128dSJiawen Wu rxq->port_id, rxq->queue_id); 155979f3128dSJiawen Wu 156079f3128dSJiawen Wu dev->data->rx_mbuf_alloc_failed++; 156179f3128dSJiawen Wu break; 156279f3128dSJiawen Wu } 156379f3128dSJiawen Wu } 156479f3128dSJiawen Wu 156579f3128dSJiawen Wu nb_hold++; 156679f3128dSJiawen Wu rxe = &sw_ring[rx_id]; 156779f3128dSJiawen Wu eop = staterr & NGBE_RXD_STAT_EOP; 156879f3128dSJiawen Wu 156979f3128dSJiawen Wu next_id = rx_id + 1; 157079f3128dSJiawen Wu if (next_id == rxq->nb_rx_desc) 157179f3128dSJiawen Wu next_id = 0; 157279f3128dSJiawen Wu 157379f3128dSJiawen Wu /* Prefetch next mbuf while processing current one. */ 157479f3128dSJiawen Wu rte_ngbe_prefetch(sw_ring[next_id].mbuf); 157579f3128dSJiawen Wu 157679f3128dSJiawen Wu /* 157779f3128dSJiawen Wu * When next Rx descriptor is on a cache-line boundary, 157879f3128dSJiawen Wu * prefetch the next 4 RX descriptors and the next 4 pointers 157979f3128dSJiawen Wu * to mbufs. 158079f3128dSJiawen Wu */ 158179f3128dSJiawen Wu if ((next_id & 0x3) == 0) { 158279f3128dSJiawen Wu rte_ngbe_prefetch(&rx_ring[next_id]); 158379f3128dSJiawen Wu rte_ngbe_prefetch(&sw_ring[next_id]); 158479f3128dSJiawen Wu } 158579f3128dSJiawen Wu 158679f3128dSJiawen Wu rxm = rxe->mbuf; 158779f3128dSJiawen Wu 158879f3128dSJiawen Wu if (!bulk_alloc) { 158979f3128dSJiawen Wu __le64 dma = 159079f3128dSJiawen Wu rte_cpu_to_le_64(rte_mbuf_data_iova_default(nmb)); 159179f3128dSJiawen Wu /* 159279f3128dSJiawen Wu * Update Rx descriptor with the physical address of the 159379f3128dSJiawen Wu * new data buffer of the new allocated mbuf. 159479f3128dSJiawen Wu */ 159579f3128dSJiawen Wu rxe->mbuf = nmb; 159679f3128dSJiawen Wu 159779f3128dSJiawen Wu rxm->data_off = RTE_PKTMBUF_HEADROOM; 159879f3128dSJiawen Wu NGBE_RXD_HDRADDR(rxdp, 0); 159979f3128dSJiawen Wu NGBE_RXD_PKTADDR(rxdp, dma); 160079f3128dSJiawen Wu } else { 160179f3128dSJiawen Wu rxe->mbuf = NULL; 160279f3128dSJiawen Wu } 160379f3128dSJiawen Wu 160479f3128dSJiawen Wu /* 160579f3128dSJiawen Wu * Set data length & data buffer address of mbuf. 160679f3128dSJiawen Wu */ 160779f3128dSJiawen Wu data_len = rte_le_to_cpu_16(rxd.qw1.hi.len); 160879f3128dSJiawen Wu rxm->data_len = data_len; 160979f3128dSJiawen Wu 161079f3128dSJiawen Wu if (!eop) { 161179f3128dSJiawen Wu uint16_t nextp_id; 161279f3128dSJiawen Wu 161379f3128dSJiawen Wu nextp_id = next_id; 161479f3128dSJiawen Wu next_sc_entry = &sw_sc_ring[nextp_id]; 161579f3128dSJiawen Wu next_rxe = &sw_ring[nextp_id]; 161679f3128dSJiawen Wu rte_ngbe_prefetch(next_rxe); 161779f3128dSJiawen Wu } 161879f3128dSJiawen Wu 161979f3128dSJiawen Wu sc_entry = &sw_sc_ring[rx_id]; 162079f3128dSJiawen Wu first_seg = sc_entry->fbuf; 162179f3128dSJiawen Wu sc_entry->fbuf = NULL; 162279f3128dSJiawen Wu 162379f3128dSJiawen Wu /* 162479f3128dSJiawen Wu * If this is the first buffer of the received packet, 162579f3128dSJiawen Wu * set the pointer to the first mbuf of the packet and 162679f3128dSJiawen Wu * initialize its context. 162779f3128dSJiawen Wu * Otherwise, update the total length and the number of segments 162879f3128dSJiawen Wu * of the current scattered packet, and update the pointer to 162979f3128dSJiawen Wu * the last mbuf of the current packet. 163079f3128dSJiawen Wu */ 163179f3128dSJiawen Wu if (first_seg == NULL) { 163279f3128dSJiawen Wu first_seg = rxm; 163379f3128dSJiawen Wu first_seg->pkt_len = data_len; 163479f3128dSJiawen Wu first_seg->nb_segs = 1; 163579f3128dSJiawen Wu } else { 163679f3128dSJiawen Wu first_seg->pkt_len += data_len; 163779f3128dSJiawen Wu first_seg->nb_segs++; 163879f3128dSJiawen Wu } 163979f3128dSJiawen Wu 164079f3128dSJiawen Wu prev_id = rx_id; 164179f3128dSJiawen Wu rx_id = next_id; 164279f3128dSJiawen Wu 164379f3128dSJiawen Wu /* 164479f3128dSJiawen Wu * If this is not the last buffer of the received packet, update 164579f3128dSJiawen Wu * the pointer to the first mbuf at the NEXTP entry in the 164679f3128dSJiawen Wu * sw_sc_ring and continue to parse the Rx ring. 164779f3128dSJiawen Wu */ 164879f3128dSJiawen Wu if (!eop && next_rxe) { 164979f3128dSJiawen Wu rxm->next = next_rxe->mbuf; 165079f3128dSJiawen Wu next_sc_entry->fbuf = first_seg; 165179f3128dSJiawen Wu goto next_desc; 165279f3128dSJiawen Wu } 165379f3128dSJiawen Wu 165479f3128dSJiawen Wu /* Initialize the first mbuf of the returned packet */ 165579f3128dSJiawen Wu ngbe_fill_cluster_head_buf(first_seg, &rxd, rxq, staterr); 165679f3128dSJiawen Wu 165764b36e4aSJiawen Wu /* Deal with the case, when HW CRC srip is disabled. */ 165864b36e4aSJiawen Wu first_seg->pkt_len -= rxq->crc_len; 165964b36e4aSJiawen Wu if (unlikely(rxm->data_len <= rxq->crc_len)) { 166064b36e4aSJiawen Wu struct rte_mbuf *lp; 166164b36e4aSJiawen Wu 166264b36e4aSJiawen Wu for (lp = first_seg; lp->next != rxm; lp = lp->next) 166364b36e4aSJiawen Wu ; 166464b36e4aSJiawen Wu 166564b36e4aSJiawen Wu first_seg->nb_segs--; 166664b36e4aSJiawen Wu lp->data_len -= rxq->crc_len - rxm->data_len; 166764b36e4aSJiawen Wu lp->next = NULL; 166864b36e4aSJiawen Wu rte_pktmbuf_free_seg(rxm); 166964b36e4aSJiawen Wu } else { 167064b36e4aSJiawen Wu rxm->data_len -= rxq->crc_len; 167164b36e4aSJiawen Wu } 167264b36e4aSJiawen Wu 167379f3128dSJiawen Wu /* Prefetch data of first segment, if configured to do so. */ 167479f3128dSJiawen Wu rte_packet_prefetch((char *)first_seg->buf_addr + 167579f3128dSJiawen Wu first_seg->data_off); 167679f3128dSJiawen Wu 167779f3128dSJiawen Wu /* 167879f3128dSJiawen Wu * Store the mbuf address into the next entry of the array 167979f3128dSJiawen Wu * of returned packets. 168079f3128dSJiawen Wu */ 168179f3128dSJiawen Wu rx_pkts[nb_rx++] = first_seg; 168279f3128dSJiawen Wu } 168379f3128dSJiawen Wu 168479f3128dSJiawen Wu /* 168579f3128dSJiawen Wu * Record index of the next Rx descriptor to probe. 168679f3128dSJiawen Wu */ 168779f3128dSJiawen Wu rxq->rx_tail = rx_id; 168879f3128dSJiawen Wu 168979f3128dSJiawen Wu /* 169079f3128dSJiawen Wu * If the number of free Rx descriptors is greater than the Rx free 169179f3128dSJiawen Wu * threshold of the queue, advance the Receive Descriptor Tail (RDT) 169279f3128dSJiawen Wu * register. 169379f3128dSJiawen Wu * Update the RDT with the value of the last processed Rx descriptor 169479f3128dSJiawen Wu * minus 1, to guarantee that the RDT register is never equal to the 169579f3128dSJiawen Wu * RDH register, which creates a "full" ring situation from the 169679f3128dSJiawen Wu * hardware point of view... 169779f3128dSJiawen Wu */ 169879f3128dSJiawen Wu if (!bulk_alloc && nb_hold > rxq->rx_free_thresh) { 169979f3128dSJiawen Wu PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_tail=%u " 170079f3128dSJiawen Wu "nb_hold=%u nb_rx=%u", 170179f3128dSJiawen Wu rxq->port_id, rxq->queue_id, rx_id, nb_hold, nb_rx); 170279f3128dSJiawen Wu 170379f3128dSJiawen Wu rte_wmb(); 170479f3128dSJiawen Wu ngbe_set32_relaxed(rxq->rdt_reg_addr, prev_id); 170579f3128dSJiawen Wu nb_hold = 0; 170679f3128dSJiawen Wu } 170779f3128dSJiawen Wu 170879f3128dSJiawen Wu rxq->nb_rx_hold = nb_hold; 170979f3128dSJiawen Wu return nb_rx; 171079f3128dSJiawen Wu } 171179f3128dSJiawen Wu 171279f3128dSJiawen Wu uint16_t 171379f3128dSJiawen Wu ngbe_recv_pkts_sc_single_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, 171479f3128dSJiawen Wu uint16_t nb_pkts) 171579f3128dSJiawen Wu { 171679f3128dSJiawen Wu return ngbe_recv_pkts_sc(rx_queue, rx_pkts, nb_pkts, false); 171779f3128dSJiawen Wu } 171879f3128dSJiawen Wu 171979f3128dSJiawen Wu uint16_t 172079f3128dSJiawen Wu ngbe_recv_pkts_sc_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, 172179f3128dSJiawen Wu uint16_t nb_pkts) 172279f3128dSJiawen Wu { 172379f3128dSJiawen Wu return ngbe_recv_pkts_sc(rx_queue, rx_pkts, nb_pkts, true); 172479f3128dSJiawen Wu } 172593dfebd2SJiawen Wu 1726a58e7c31SJiawen Wu /********************************************************************* 1727a58e7c31SJiawen Wu * 1728a58e7c31SJiawen Wu * Queue management functions 1729a58e7c31SJiawen Wu * 1730a58e7c31SJiawen Wu **********************************************************************/ 1731a58e7c31SJiawen Wu 1732a58e7c31SJiawen Wu static void 1733a58e7c31SJiawen Wu ngbe_tx_queue_release_mbufs(struct ngbe_tx_queue *txq) 1734a58e7c31SJiawen Wu { 1735a58e7c31SJiawen Wu unsigned int i; 1736a58e7c31SJiawen Wu 1737a58e7c31SJiawen Wu if (txq->sw_ring != NULL) { 1738a58e7c31SJiawen Wu for (i = 0; i < txq->nb_tx_desc; i++) { 1739a58e7c31SJiawen Wu if (txq->sw_ring[i].mbuf != NULL) { 1740a58e7c31SJiawen Wu rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf); 1741a58e7c31SJiawen Wu txq->sw_ring[i].mbuf = NULL; 1742a58e7c31SJiawen Wu } 1743a58e7c31SJiawen Wu } 1744a58e7c31SJiawen Wu } 1745a58e7c31SJiawen Wu } 1746a58e7c31SJiawen Wu 1747d0759b50SJiawen Wu static int 1748d0759b50SJiawen Wu ngbe_tx_done_cleanup_full(struct ngbe_tx_queue *txq, uint32_t free_cnt) 1749d0759b50SJiawen Wu { 1750d0759b50SJiawen Wu struct ngbe_tx_entry *swr_ring = txq->sw_ring; 1751d0759b50SJiawen Wu uint16_t i, tx_last, tx_id; 1752d0759b50SJiawen Wu uint16_t nb_tx_free_last; 1753d0759b50SJiawen Wu uint16_t nb_tx_to_clean; 1754d0759b50SJiawen Wu uint32_t pkt_cnt; 1755d0759b50SJiawen Wu 1756d0759b50SJiawen Wu /* Start free mbuf from the next of tx_tail */ 1757d0759b50SJiawen Wu tx_last = txq->tx_tail; 1758d0759b50SJiawen Wu tx_id = swr_ring[tx_last].next_id; 1759d0759b50SJiawen Wu 1760d0759b50SJiawen Wu if (txq->nb_tx_free == 0 && ngbe_xmit_cleanup(txq)) 1761d0759b50SJiawen Wu return 0; 1762d0759b50SJiawen Wu 1763d0759b50SJiawen Wu nb_tx_to_clean = txq->nb_tx_free; 1764d0759b50SJiawen Wu nb_tx_free_last = txq->nb_tx_free; 1765d0759b50SJiawen Wu if (!free_cnt) 1766d0759b50SJiawen Wu free_cnt = txq->nb_tx_desc; 1767d0759b50SJiawen Wu 1768d0759b50SJiawen Wu /* Loop through swr_ring to count the amount of 1769d0759b50SJiawen Wu * freeable mubfs and packets. 1770d0759b50SJiawen Wu */ 1771d0759b50SJiawen Wu for (pkt_cnt = 0; pkt_cnt < free_cnt; ) { 1772d0759b50SJiawen Wu for (i = 0; i < nb_tx_to_clean && 1773d0759b50SJiawen Wu pkt_cnt < free_cnt && 1774d0759b50SJiawen Wu tx_id != tx_last; i++) { 1775d0759b50SJiawen Wu if (swr_ring[tx_id].mbuf != NULL) { 1776d0759b50SJiawen Wu rte_pktmbuf_free_seg(swr_ring[tx_id].mbuf); 1777d0759b50SJiawen Wu swr_ring[tx_id].mbuf = NULL; 1778d0759b50SJiawen Wu 1779d0759b50SJiawen Wu /* 1780d0759b50SJiawen Wu * last segment in the packet, 1781d0759b50SJiawen Wu * increment packet count 1782d0759b50SJiawen Wu */ 1783d0759b50SJiawen Wu pkt_cnt += (swr_ring[tx_id].last_id == tx_id); 1784d0759b50SJiawen Wu } 1785d0759b50SJiawen Wu 1786d0759b50SJiawen Wu tx_id = swr_ring[tx_id].next_id; 1787d0759b50SJiawen Wu } 1788d0759b50SJiawen Wu 1789d0759b50SJiawen Wu if (pkt_cnt < free_cnt) { 1790d0759b50SJiawen Wu if (ngbe_xmit_cleanup(txq)) 1791d0759b50SJiawen Wu break; 1792d0759b50SJiawen Wu 1793d0759b50SJiawen Wu nb_tx_to_clean = txq->nb_tx_free - nb_tx_free_last; 1794d0759b50SJiawen Wu nb_tx_free_last = txq->nb_tx_free; 1795d0759b50SJiawen Wu } 1796d0759b50SJiawen Wu } 1797d0759b50SJiawen Wu 1798d0759b50SJiawen Wu return (int)pkt_cnt; 1799d0759b50SJiawen Wu } 1800d0759b50SJiawen Wu 1801d0759b50SJiawen Wu static int 1802d0759b50SJiawen Wu ngbe_tx_done_cleanup_simple(struct ngbe_tx_queue *txq, 1803d0759b50SJiawen Wu uint32_t free_cnt) 1804d0759b50SJiawen Wu { 1805d0759b50SJiawen Wu int i, n, cnt; 1806d0759b50SJiawen Wu 1807d0759b50SJiawen Wu if (free_cnt == 0 || free_cnt > txq->nb_tx_desc) 1808d0759b50SJiawen Wu free_cnt = txq->nb_tx_desc; 1809d0759b50SJiawen Wu 1810d0759b50SJiawen Wu cnt = free_cnt - free_cnt % txq->tx_free_thresh; 1811d0759b50SJiawen Wu 1812d0759b50SJiawen Wu for (i = 0; i < cnt; i += n) { 1813d0759b50SJiawen Wu if (txq->nb_tx_desc - txq->nb_tx_free < txq->tx_free_thresh) 1814d0759b50SJiawen Wu break; 1815d0759b50SJiawen Wu 1816d0759b50SJiawen Wu n = ngbe_tx_free_bufs(txq); 1817d0759b50SJiawen Wu 1818d0759b50SJiawen Wu if (n == 0) 1819d0759b50SJiawen Wu break; 1820d0759b50SJiawen Wu } 1821d0759b50SJiawen Wu 1822d0759b50SJiawen Wu return i; 1823d0759b50SJiawen Wu } 1824d0759b50SJiawen Wu 1825d0759b50SJiawen Wu int 1826d0759b50SJiawen Wu ngbe_dev_tx_done_cleanup(void *tx_queue, uint32_t free_cnt) 1827d0759b50SJiawen Wu { 1828d0759b50SJiawen Wu struct ngbe_tx_queue *txq = (struct ngbe_tx_queue *)tx_queue; 1829d0759b50SJiawen Wu if (txq->offloads == 0 && 1830d0759b50SJiawen Wu txq->tx_free_thresh >= RTE_PMD_NGBE_TX_MAX_BURST) 1831d0759b50SJiawen Wu return ngbe_tx_done_cleanup_simple(txq, free_cnt); 1832d0759b50SJiawen Wu 1833d0759b50SJiawen Wu return ngbe_tx_done_cleanup_full(txq, free_cnt); 1834d0759b50SJiawen Wu } 1835d0759b50SJiawen Wu 1836a58e7c31SJiawen Wu static void 1837a58e7c31SJiawen Wu ngbe_tx_free_swring(struct ngbe_tx_queue *txq) 1838a58e7c31SJiawen Wu { 1839a58e7c31SJiawen Wu if (txq != NULL) 1840a58e7c31SJiawen Wu rte_free(txq->sw_ring); 1841a58e7c31SJiawen Wu } 1842a58e7c31SJiawen Wu 1843a58e7c31SJiawen Wu static void 1844a58e7c31SJiawen Wu ngbe_tx_queue_release(struct ngbe_tx_queue *txq) 1845a58e7c31SJiawen Wu { 1846a58e7c31SJiawen Wu if (txq != NULL) { 1847a58e7c31SJiawen Wu if (txq->ops != NULL) { 1848a58e7c31SJiawen Wu txq->ops->release_mbufs(txq); 1849a58e7c31SJiawen Wu txq->ops->free_swring(txq); 1850fea7422fSJiawen Wu rte_memzone_free(txq->mz); 1851a58e7c31SJiawen Wu } 1852a58e7c31SJiawen Wu rte_free(txq); 1853a58e7c31SJiawen Wu } 1854a58e7c31SJiawen Wu } 1855a58e7c31SJiawen Wu 1856a58e7c31SJiawen Wu void 18577483341aSXueming Li ngbe_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 1858a58e7c31SJiawen Wu { 18597483341aSXueming Li ngbe_tx_queue_release(dev->data->tx_queues[qid]); 1860a58e7c31SJiawen Wu } 1861a58e7c31SJiawen Wu 1862a58e7c31SJiawen Wu /* (Re)set dynamic ngbe_tx_queue fields to defaults */ 1863a58e7c31SJiawen Wu static void 1864a58e7c31SJiawen Wu ngbe_reset_tx_queue(struct ngbe_tx_queue *txq) 1865a58e7c31SJiawen Wu { 1866a58e7c31SJiawen Wu static const struct ngbe_tx_desc zeroed_desc = {0}; 1867a58e7c31SJiawen Wu struct ngbe_tx_entry *txe = txq->sw_ring; 1868a58e7c31SJiawen Wu uint16_t prev, i; 1869a58e7c31SJiawen Wu 1870a58e7c31SJiawen Wu /* Zero out HW ring memory */ 1871a58e7c31SJiawen Wu for (i = 0; i < txq->nb_tx_desc; i++) 1872a58e7c31SJiawen Wu txq->tx_ring[i] = zeroed_desc; 1873a58e7c31SJiawen Wu 1874a58e7c31SJiawen Wu /* Initialize SW ring entries */ 1875a58e7c31SJiawen Wu prev = (uint16_t)(txq->nb_tx_desc - 1); 1876a58e7c31SJiawen Wu for (i = 0; i < txq->nb_tx_desc; i++) { 1877a58e7c31SJiawen Wu /* the ring can also be modified by hardware */ 1878a58e7c31SJiawen Wu volatile struct ngbe_tx_desc *txd = &txq->tx_ring[i]; 1879a58e7c31SJiawen Wu 1880a58e7c31SJiawen Wu txd->dw3 = rte_cpu_to_le_32(NGBE_TXD_DD); 1881a58e7c31SJiawen Wu txe[i].mbuf = NULL; 1882a58e7c31SJiawen Wu txe[i].last_id = i; 1883a58e7c31SJiawen Wu txe[prev].next_id = i; 1884a58e7c31SJiawen Wu prev = i; 1885a58e7c31SJiawen Wu } 1886a58e7c31SJiawen Wu 1887a58e7c31SJiawen Wu txq->tx_next_dd = (uint16_t)(txq->tx_free_thresh - 1); 1888a58e7c31SJiawen Wu txq->tx_tail = 0; 1889a58e7c31SJiawen Wu 1890a58e7c31SJiawen Wu /* 1891a58e7c31SJiawen Wu * Always allow 1 descriptor to be un-allocated to avoid 1892a58e7c31SJiawen Wu * a H/W race condition 1893a58e7c31SJiawen Wu */ 1894a58e7c31SJiawen Wu txq->last_desc_cleaned = (uint16_t)(txq->nb_tx_desc - 1); 1895a58e7c31SJiawen Wu txq->nb_tx_free = (uint16_t)(txq->nb_tx_desc - 1); 1896a58e7c31SJiawen Wu txq->ctx_curr = 0; 1897a58e7c31SJiawen Wu memset((void *)&txq->ctx_cache, 0, 1898a58e7c31SJiawen Wu NGBE_CTX_NUM * sizeof(struct ngbe_ctx_info)); 1899a58e7c31SJiawen Wu } 1900a58e7c31SJiawen Wu 1901a58e7c31SJiawen Wu static const struct ngbe_txq_ops def_txq_ops = { 1902a58e7c31SJiawen Wu .release_mbufs = ngbe_tx_queue_release_mbufs, 1903a58e7c31SJiawen Wu .free_swring = ngbe_tx_free_swring, 1904a58e7c31SJiawen Wu .reset = ngbe_reset_tx_queue, 1905a58e7c31SJiawen Wu }; 1906a58e7c31SJiawen Wu 19079f320614SJiawen Wu /* Takes an ethdev and a queue and sets up the tx function to be used based on 19089f320614SJiawen Wu * the queue parameters. Used in tx_queue_setup by primary process and then 19099f320614SJiawen Wu * in dev_init by secondary process when attaching to an existing ethdev. 19109f320614SJiawen Wu */ 19119f320614SJiawen Wu void 19129f320614SJiawen Wu ngbe_set_tx_function(struct rte_eth_dev *dev, struct ngbe_tx_queue *txq) 19139f320614SJiawen Wu { 19149f320614SJiawen Wu /* Use a simple Tx queue (no offloads, no multi segs) if possible */ 19159f320614SJiawen Wu if (txq->offloads == 0 && 19169f320614SJiawen Wu txq->tx_free_thresh >= RTE_PMD_NGBE_TX_MAX_BURST) { 19179f320614SJiawen Wu PMD_INIT_LOG(DEBUG, "Using simple tx code path"); 19189f320614SJiawen Wu dev->tx_pkt_prepare = NULL; 1919e94c20c3SJiawen Wu if (txq->tx_free_thresh <= RTE_NGBE_TX_MAX_FREE_BUF_SZ && 1920e94c20c3SJiawen Wu rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128 && 1921e94c20c3SJiawen Wu (rte_eal_process_type() != RTE_PROC_PRIMARY || 1922e94c20c3SJiawen Wu ngbe_txq_vec_setup(txq) == 0)) { 1923e94c20c3SJiawen Wu PMD_INIT_LOG(DEBUG, "Vector tx enabled."); 1924e94c20c3SJiawen Wu dev->tx_pkt_burst = ngbe_xmit_pkts_vec; 1925e94c20c3SJiawen Wu } else { 1926e94c20c3SJiawen Wu dev->tx_pkt_burst = ngbe_xmit_pkts_simple; 1927e94c20c3SJiawen Wu } 19289f320614SJiawen Wu } else { 19299f320614SJiawen Wu PMD_INIT_LOG(DEBUG, "Using full-featured tx code path"); 19309f320614SJiawen Wu PMD_INIT_LOG(DEBUG, 19319f320614SJiawen Wu " - offloads = 0x%" PRIx64, 19329f320614SJiawen Wu txq->offloads); 19339f320614SJiawen Wu PMD_INIT_LOG(DEBUG, 19349f320614SJiawen Wu " - tx_free_thresh = %lu [RTE_PMD_NGBE_TX_MAX_BURST=%lu]", 19359f320614SJiawen Wu (unsigned long)txq->tx_free_thresh, 19369f320614SJiawen Wu (unsigned long)RTE_PMD_NGBE_TX_MAX_BURST); 19379f320614SJiawen Wu dev->tx_pkt_burst = ngbe_xmit_pkts; 19389f320614SJiawen Wu dev->tx_pkt_prepare = ngbe_prep_pkts; 19399f320614SJiawen Wu } 19409f320614SJiawen Wu } 19419f320614SJiawen Wu 1942d148a87eSJiawen Wu static const struct { 1943d148a87eSJiawen Wu eth_tx_burst_t pkt_burst; 1944d148a87eSJiawen Wu const char *info; 1945d148a87eSJiawen Wu } ngbe_tx_burst_infos[] = { 1946d148a87eSJiawen Wu { ngbe_xmit_pkts_simple, "Scalar Simple"}, 1947d148a87eSJiawen Wu { ngbe_xmit_pkts, "Scalar"}, 1948e94c20c3SJiawen Wu #ifdef RTE_ARCH_X86 1949e94c20c3SJiawen Wu { ngbe_xmit_pkts_vec, "Vector SSE" }, 1950e94c20c3SJiawen Wu #elif defined(RTE_ARCH_ARM) 1951e94c20c3SJiawen Wu { ngbe_xmit_pkts_vec, "Vector Neon" }, 1952e94c20c3SJiawen Wu #endif 1953d148a87eSJiawen Wu }; 1954d148a87eSJiawen Wu 1955d148a87eSJiawen Wu int 1956d148a87eSJiawen Wu ngbe_tx_burst_mode_get(struct rte_eth_dev *dev, __rte_unused uint16_t queue_id, 1957d148a87eSJiawen Wu struct rte_eth_burst_mode *mode) 1958d148a87eSJiawen Wu { 1959d148a87eSJiawen Wu eth_tx_burst_t pkt_burst = dev->tx_pkt_burst; 1960d148a87eSJiawen Wu int ret = -EINVAL; 1961d148a87eSJiawen Wu unsigned int i; 1962d148a87eSJiawen Wu 1963d148a87eSJiawen Wu for (i = 0; i < RTE_DIM(ngbe_tx_burst_infos); ++i) { 1964d148a87eSJiawen Wu if (pkt_burst == ngbe_tx_burst_infos[i].pkt_burst) { 1965d148a87eSJiawen Wu snprintf(mode->info, sizeof(mode->info), "%s", 1966d148a87eSJiawen Wu ngbe_tx_burst_infos[i].info); 1967d148a87eSJiawen Wu ret = 0; 1968d148a87eSJiawen Wu break; 1969d148a87eSJiawen Wu } 1970d148a87eSJiawen Wu } 1971d148a87eSJiawen Wu 1972d148a87eSJiawen Wu return ret; 1973d148a87eSJiawen Wu } 1974d148a87eSJiawen Wu 19759f320614SJiawen Wu uint64_t 19769f320614SJiawen Wu ngbe_get_tx_port_offloads(struct rte_eth_dev *dev) 19779f320614SJiawen Wu { 19789f320614SJiawen Wu uint64_t tx_offload_capa; 197959b46438SJiawen Wu struct ngbe_hw *hw = ngbe_dev_hw(dev); 19809f320614SJiawen Wu 19819f320614SJiawen Wu tx_offload_capa = 198259b46438SJiawen Wu RTE_ETH_TX_OFFLOAD_VLAN_INSERT | 19839f320614SJiawen Wu RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | 19849f320614SJiawen Wu RTE_ETH_TX_OFFLOAD_UDP_CKSUM | 19859f320614SJiawen Wu RTE_ETH_TX_OFFLOAD_TCP_CKSUM | 19869f320614SJiawen Wu RTE_ETH_TX_OFFLOAD_SCTP_CKSUM | 19879f320614SJiawen Wu RTE_ETH_TX_OFFLOAD_TCP_TSO | 19889f320614SJiawen Wu RTE_ETH_TX_OFFLOAD_UDP_TSO | 19899f320614SJiawen Wu RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 19909f320614SJiawen Wu 199159b46438SJiawen Wu if (hw->is_pf) 199259b46438SJiawen Wu tx_offload_capa |= RTE_ETH_TX_OFFLOAD_QINQ_INSERT; 199359b46438SJiawen Wu 19949f320614SJiawen Wu return tx_offload_capa; 19959f320614SJiawen Wu } 19969f320614SJiawen Wu 1997a58e7c31SJiawen Wu int 1998a58e7c31SJiawen Wu ngbe_dev_tx_queue_setup(struct rte_eth_dev *dev, 1999a58e7c31SJiawen Wu uint16_t queue_idx, 2000a58e7c31SJiawen Wu uint16_t nb_desc, 2001a58e7c31SJiawen Wu unsigned int socket_id, 2002a58e7c31SJiawen Wu const struct rte_eth_txconf *tx_conf) 2003a58e7c31SJiawen Wu { 2004a58e7c31SJiawen Wu const struct rte_memzone *tz; 2005a58e7c31SJiawen Wu struct ngbe_tx_queue *txq; 2006a58e7c31SJiawen Wu struct ngbe_hw *hw; 2007a58e7c31SJiawen Wu uint16_t tx_free_thresh; 20089f320614SJiawen Wu uint64_t offloads; 2009a58e7c31SJiawen Wu 2010a58e7c31SJiawen Wu PMD_INIT_FUNC_TRACE(); 2011a58e7c31SJiawen Wu hw = ngbe_dev_hw(dev); 2012a58e7c31SJiawen Wu 20139f320614SJiawen Wu offloads = tx_conf->offloads | dev->data->dev_conf.txmode.offloads; 20149f320614SJiawen Wu 2015a58e7c31SJiawen Wu /* 2016a58e7c31SJiawen Wu * The Tx descriptor ring will be cleaned after txq->tx_free_thresh 2017a58e7c31SJiawen Wu * descriptors are used or if the number of descriptors required 2018a58e7c31SJiawen Wu * to transmit a packet is greater than the number of free Tx 2019a58e7c31SJiawen Wu * descriptors. 2020a58e7c31SJiawen Wu * One descriptor in the Tx ring is used as a sentinel to avoid a 2021a58e7c31SJiawen Wu * H/W race condition, hence the maximum threshold constraints. 2022a58e7c31SJiawen Wu * When set to zero use default values. 2023a58e7c31SJiawen Wu */ 2024a58e7c31SJiawen Wu tx_free_thresh = (uint16_t)((tx_conf->tx_free_thresh) ? 2025a58e7c31SJiawen Wu tx_conf->tx_free_thresh : DEFAULT_TX_FREE_THRESH); 2026a58e7c31SJiawen Wu if (tx_free_thresh >= (nb_desc - 3)) { 2027a58e7c31SJiawen Wu PMD_INIT_LOG(ERR, 2028a58e7c31SJiawen Wu "tx_free_thresh must be less than the number of TX descriptors minus 3. (tx_free_thresh=%u port=%d queue=%d)", 2029a58e7c31SJiawen Wu (unsigned int)tx_free_thresh, 2030a58e7c31SJiawen Wu (int)dev->data->port_id, (int)queue_idx); 2031a58e7c31SJiawen Wu return -(EINVAL); 2032a58e7c31SJiawen Wu } 2033a58e7c31SJiawen Wu 2034a58e7c31SJiawen Wu if (nb_desc % tx_free_thresh != 0) { 2035a58e7c31SJiawen Wu PMD_INIT_LOG(ERR, 2036a58e7c31SJiawen Wu "tx_free_thresh must be a divisor of the number of Tx descriptors. (tx_free_thresh=%u port=%d queue=%d)", 2037a58e7c31SJiawen Wu (unsigned int)tx_free_thresh, 2038a58e7c31SJiawen Wu (int)dev->data->port_id, (int)queue_idx); 2039a58e7c31SJiawen Wu return -(EINVAL); 2040a58e7c31SJiawen Wu } 2041a58e7c31SJiawen Wu 2042a58e7c31SJiawen Wu /* Free memory prior to re-allocation if needed... */ 2043a58e7c31SJiawen Wu if (dev->data->tx_queues[queue_idx] != NULL) { 2044a58e7c31SJiawen Wu ngbe_tx_queue_release(dev->data->tx_queues[queue_idx]); 2045a58e7c31SJiawen Wu dev->data->tx_queues[queue_idx] = NULL; 2046a58e7c31SJiawen Wu } 2047a58e7c31SJiawen Wu 2048a58e7c31SJiawen Wu /* First allocate the Tx queue data structure */ 2049a58e7c31SJiawen Wu txq = rte_zmalloc_socket("ethdev Tx queue", 2050a58e7c31SJiawen Wu sizeof(struct ngbe_tx_queue), 2051a58e7c31SJiawen Wu RTE_CACHE_LINE_SIZE, socket_id); 2052a58e7c31SJiawen Wu if (txq == NULL) 2053a58e7c31SJiawen Wu return -ENOMEM; 2054a58e7c31SJiawen Wu 2055a58e7c31SJiawen Wu /* 2056a58e7c31SJiawen Wu * Allocate Tx ring hardware descriptors. A memzone large enough to 2057a58e7c31SJiawen Wu * handle the maximum ring size is allocated in order to allow for 2058a58e7c31SJiawen Wu * resizing in later calls to the queue setup function. 2059a58e7c31SJiawen Wu */ 2060a58e7c31SJiawen Wu tz = rte_eth_dma_zone_reserve(dev, "tx_ring", queue_idx, 2061a58e7c31SJiawen Wu sizeof(struct ngbe_tx_desc) * NGBE_RING_DESC_MAX, 2062a58e7c31SJiawen Wu NGBE_ALIGN, socket_id); 2063a58e7c31SJiawen Wu if (tz == NULL) { 2064a58e7c31SJiawen Wu ngbe_tx_queue_release(txq); 2065a58e7c31SJiawen Wu return -ENOMEM; 2066a58e7c31SJiawen Wu } 2067a58e7c31SJiawen Wu 2068fea7422fSJiawen Wu txq->mz = tz; 2069a58e7c31SJiawen Wu txq->nb_tx_desc = nb_desc; 2070a58e7c31SJiawen Wu txq->tx_free_thresh = tx_free_thresh; 2071a58e7c31SJiawen Wu txq->pthresh = tx_conf->tx_thresh.pthresh; 2072a58e7c31SJiawen Wu txq->hthresh = tx_conf->tx_thresh.hthresh; 2073a58e7c31SJiawen Wu txq->wthresh = tx_conf->tx_thresh.wthresh; 2074a58e7c31SJiawen Wu txq->queue_id = queue_idx; 207560229dcfSJiawen Wu txq->reg_idx = (uint16_t)((RTE_ETH_DEV_SRIOV(dev).active == 0) ? 207660229dcfSJiawen Wu queue_idx : RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx + queue_idx); 2077a58e7c31SJiawen Wu txq->port_id = dev->data->port_id; 20789f320614SJiawen Wu txq->offloads = offloads; 2079a58e7c31SJiawen Wu txq->ops = &def_txq_ops; 2080a58e7c31SJiawen Wu txq->tx_deferred_start = tx_conf->tx_deferred_start; 2081a58e7c31SJiawen Wu 2082a58e7c31SJiawen Wu txq->tdt_reg_addr = NGBE_REG_ADDR(hw, NGBE_TXWP(txq->reg_idx)); 2083a58e7c31SJiawen Wu txq->tdc_reg_addr = NGBE_REG_ADDR(hw, NGBE_TXCFG(txq->reg_idx)); 2084a58e7c31SJiawen Wu 2085a58e7c31SJiawen Wu txq->tx_ring_phys_addr = TMZ_PADDR(tz); 2086a58e7c31SJiawen Wu txq->tx_ring = (struct ngbe_tx_desc *)TMZ_VADDR(tz); 2087a58e7c31SJiawen Wu 2088a58e7c31SJiawen Wu /* Allocate software ring */ 2089a58e7c31SJiawen Wu txq->sw_ring = rte_zmalloc_socket("txq->sw_ring", 2090a58e7c31SJiawen Wu sizeof(struct ngbe_tx_entry) * nb_desc, 2091a58e7c31SJiawen Wu RTE_CACHE_LINE_SIZE, socket_id); 2092a58e7c31SJiawen Wu if (txq->sw_ring == NULL) { 2093a58e7c31SJiawen Wu ngbe_tx_queue_release(txq); 2094a58e7c31SJiawen Wu return -ENOMEM; 2095a58e7c31SJiawen Wu } 2096a58e7c31SJiawen Wu PMD_INIT_LOG(DEBUG, 2097a58e7c31SJiawen Wu "sw_ring=%p hw_ring=%p dma_addr=0x%" PRIx64, 2098a58e7c31SJiawen Wu txq->sw_ring, txq->tx_ring, txq->tx_ring_phys_addr); 2099a58e7c31SJiawen Wu 21009f320614SJiawen Wu /* set up scalar Tx function as appropriate */ 21019f320614SJiawen Wu ngbe_set_tx_function(dev, txq); 21029f320614SJiawen Wu 2103a58e7c31SJiawen Wu txq->ops->reset(txq); 21043eba2f28SJiawen Wu txq->desc_error = 0; 2105a58e7c31SJiawen Wu 2106a58e7c31SJiawen Wu dev->data->tx_queues[queue_idx] = txq; 2107a58e7c31SJiawen Wu 2108a58e7c31SJiawen Wu return 0; 2109a58e7c31SJiawen Wu } 2110a58e7c31SJiawen Wu 211143b7e5eaSJiawen Wu /** 211243b7e5eaSJiawen Wu * ngbe_free_sc_cluster - free the not-yet-completed scattered cluster 211343b7e5eaSJiawen Wu * 211443b7e5eaSJiawen Wu * The "next" pointer of the last segment of (not-yet-completed) RSC clusters 211543b7e5eaSJiawen Wu * in the sw_sc_ring is not set to NULL but rather points to the next 211643b7e5eaSJiawen Wu * mbuf of this RSC aggregation (that has not been completed yet and still 211743b7e5eaSJiawen Wu * resides on the HW ring). So, instead of calling for rte_pktmbuf_free() we 211843b7e5eaSJiawen Wu * will just free first "nb_segs" segments of the cluster explicitly by calling 211943b7e5eaSJiawen Wu * an rte_pktmbuf_free_seg(). 212043b7e5eaSJiawen Wu * 212143b7e5eaSJiawen Wu * @m scattered cluster head 212243b7e5eaSJiawen Wu */ 212343b7e5eaSJiawen Wu static void 212443b7e5eaSJiawen Wu ngbe_free_sc_cluster(struct rte_mbuf *m) 212543b7e5eaSJiawen Wu { 212643b7e5eaSJiawen Wu uint16_t i, nb_segs = m->nb_segs; 212743b7e5eaSJiawen Wu struct rte_mbuf *next_seg; 212843b7e5eaSJiawen Wu 212943b7e5eaSJiawen Wu for (i = 0; i < nb_segs; i++) { 213043b7e5eaSJiawen Wu next_seg = m->next; 213143b7e5eaSJiawen Wu rte_pktmbuf_free_seg(m); 213243b7e5eaSJiawen Wu m = next_seg; 213343b7e5eaSJiawen Wu } 213443b7e5eaSJiawen Wu } 213543b7e5eaSJiawen Wu 213643b7e5eaSJiawen Wu static void 213743b7e5eaSJiawen Wu ngbe_rx_queue_release_mbufs(struct ngbe_rx_queue *rxq) 213843b7e5eaSJiawen Wu { 213943b7e5eaSJiawen Wu unsigned int i; 214043b7e5eaSJiawen Wu 2141e94c20c3SJiawen Wu /* SSE Vector driver has a different way of releasing mbufs. */ 2142e94c20c3SJiawen Wu if (rxq->rx_using_sse) { 2143e94c20c3SJiawen Wu ngbe_rx_queue_release_mbufs_vec(rxq); 2144e94c20c3SJiawen Wu return; 2145e94c20c3SJiawen Wu } 2146e94c20c3SJiawen Wu 214743b7e5eaSJiawen Wu if (rxq->sw_ring != NULL) { 214843b7e5eaSJiawen Wu for (i = 0; i < rxq->nb_rx_desc; i++) { 214943b7e5eaSJiawen Wu if (rxq->sw_ring[i].mbuf != NULL) { 215043b7e5eaSJiawen Wu rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf); 215143b7e5eaSJiawen Wu rxq->sw_ring[i].mbuf = NULL; 215243b7e5eaSJiawen Wu } 215343b7e5eaSJiawen Wu } 215443b7e5eaSJiawen Wu for (i = 0; i < rxq->rx_nb_avail; ++i) { 215543b7e5eaSJiawen Wu struct rte_mbuf *mb; 215643b7e5eaSJiawen Wu 215743b7e5eaSJiawen Wu mb = rxq->rx_stage[rxq->rx_next_avail + i]; 215843b7e5eaSJiawen Wu rte_pktmbuf_free_seg(mb); 215943b7e5eaSJiawen Wu } 216043b7e5eaSJiawen Wu rxq->rx_nb_avail = 0; 216143b7e5eaSJiawen Wu } 216243b7e5eaSJiawen Wu 216343b7e5eaSJiawen Wu if (rxq->sw_sc_ring != NULL) 216443b7e5eaSJiawen Wu for (i = 0; i < rxq->nb_rx_desc; i++) 216543b7e5eaSJiawen Wu if (rxq->sw_sc_ring[i].fbuf != NULL) { 216643b7e5eaSJiawen Wu ngbe_free_sc_cluster(rxq->sw_sc_ring[i].fbuf); 216743b7e5eaSJiawen Wu rxq->sw_sc_ring[i].fbuf = NULL; 216843b7e5eaSJiawen Wu } 216943b7e5eaSJiawen Wu } 217043b7e5eaSJiawen Wu 217143b7e5eaSJiawen Wu static void 217243b7e5eaSJiawen Wu ngbe_rx_queue_release(struct ngbe_rx_queue *rxq) 217343b7e5eaSJiawen Wu { 217443b7e5eaSJiawen Wu if (rxq != NULL) { 217543b7e5eaSJiawen Wu ngbe_rx_queue_release_mbufs(rxq); 217643b7e5eaSJiawen Wu rte_free(rxq->sw_ring); 217743b7e5eaSJiawen Wu rte_free(rxq->sw_sc_ring); 2178fea7422fSJiawen Wu rte_memzone_free(rxq->mz); 217943b7e5eaSJiawen Wu rte_free(rxq); 218043b7e5eaSJiawen Wu } 218143b7e5eaSJiawen Wu } 218243b7e5eaSJiawen Wu 218343b7e5eaSJiawen Wu void 21847483341aSXueming Li ngbe_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 218543b7e5eaSJiawen Wu { 21867483341aSXueming Li ngbe_rx_queue_release(dev->data->rx_queues[qid]); 218743b7e5eaSJiawen Wu } 218843b7e5eaSJiawen Wu 218943b7e5eaSJiawen Wu /* 219043b7e5eaSJiawen Wu * Check if Rx Burst Bulk Alloc function can be used. 219143b7e5eaSJiawen Wu * Return 219243b7e5eaSJiawen Wu * 0: the preconditions are satisfied and the bulk allocation function 219343b7e5eaSJiawen Wu * can be used. 219443b7e5eaSJiawen Wu * -EINVAL: the preconditions are NOT satisfied and the default Rx burst 219543b7e5eaSJiawen Wu * function must be used. 219643b7e5eaSJiawen Wu */ 219743b7e5eaSJiawen Wu static inline int 219843b7e5eaSJiawen Wu check_rx_burst_bulk_alloc_preconditions(struct ngbe_rx_queue *rxq) 219943b7e5eaSJiawen Wu { 220043b7e5eaSJiawen Wu int ret = 0; 220143b7e5eaSJiawen Wu 220243b7e5eaSJiawen Wu /* 220343b7e5eaSJiawen Wu * Make sure the following pre-conditions are satisfied: 220443b7e5eaSJiawen Wu * rxq->rx_free_thresh >= RTE_PMD_NGBE_RX_MAX_BURST 220543b7e5eaSJiawen Wu * rxq->rx_free_thresh < rxq->nb_rx_desc 220643b7e5eaSJiawen Wu * (rxq->nb_rx_desc % rxq->rx_free_thresh) == 0 220743b7e5eaSJiawen Wu * Scattered packets are not supported. This should be checked 220843b7e5eaSJiawen Wu * outside of this function. 220943b7e5eaSJiawen Wu */ 221043b7e5eaSJiawen Wu if (rxq->rx_free_thresh < RTE_PMD_NGBE_RX_MAX_BURST) { 221143b7e5eaSJiawen Wu PMD_INIT_LOG(DEBUG, 221243b7e5eaSJiawen Wu "Rx Burst Bulk Alloc Preconditions: rxq->rx_free_thresh=%d, RTE_PMD_NGBE_RX_MAX_BURST=%d", 221343b7e5eaSJiawen Wu rxq->rx_free_thresh, RTE_PMD_NGBE_RX_MAX_BURST); 221443b7e5eaSJiawen Wu ret = -EINVAL; 221543b7e5eaSJiawen Wu } else if (rxq->rx_free_thresh >= rxq->nb_rx_desc) { 221643b7e5eaSJiawen Wu PMD_INIT_LOG(DEBUG, 221743b7e5eaSJiawen Wu "Rx Burst Bulk Alloc Preconditions: rxq->rx_free_thresh=%d, rxq->nb_rx_desc=%d", 221843b7e5eaSJiawen Wu rxq->rx_free_thresh, rxq->nb_rx_desc); 221943b7e5eaSJiawen Wu ret = -EINVAL; 222043b7e5eaSJiawen Wu } else if ((rxq->nb_rx_desc % rxq->rx_free_thresh) != 0) { 222143b7e5eaSJiawen Wu PMD_INIT_LOG(DEBUG, 222243b7e5eaSJiawen Wu "Rx Burst Bulk Alloc Preconditions: rxq->nb_rx_desc=%d, rxq->rx_free_thresh=%d", 222343b7e5eaSJiawen Wu rxq->nb_rx_desc, rxq->rx_free_thresh); 222443b7e5eaSJiawen Wu ret = -EINVAL; 222543b7e5eaSJiawen Wu } 222643b7e5eaSJiawen Wu 222743b7e5eaSJiawen Wu return ret; 222843b7e5eaSJiawen Wu } 222943b7e5eaSJiawen Wu 223043b7e5eaSJiawen Wu /* Reset dynamic ngbe_rx_queue fields back to defaults */ 223143b7e5eaSJiawen Wu static void 223243b7e5eaSJiawen Wu ngbe_reset_rx_queue(struct ngbe_adapter *adapter, struct ngbe_rx_queue *rxq) 223343b7e5eaSJiawen Wu { 223443b7e5eaSJiawen Wu static const struct ngbe_rx_desc zeroed_desc = { 223543b7e5eaSJiawen Wu {{0}, {0} }, {{0}, {0} } }; 223643b7e5eaSJiawen Wu unsigned int i; 223743b7e5eaSJiawen Wu uint16_t len = rxq->nb_rx_desc; 223843b7e5eaSJiawen Wu 223943b7e5eaSJiawen Wu /* 224043b7e5eaSJiawen Wu * By default, the Rx queue setup function allocates enough memory for 224143b7e5eaSJiawen Wu * NGBE_RING_DESC_MAX. The Rx Burst bulk allocation function requires 224243b7e5eaSJiawen Wu * extra memory at the end of the descriptor ring to be zero'd out. 224343b7e5eaSJiawen Wu */ 224443b7e5eaSJiawen Wu if (adapter->rx_bulk_alloc_allowed) 224543b7e5eaSJiawen Wu /* zero out extra memory */ 224643b7e5eaSJiawen Wu len += RTE_PMD_NGBE_RX_MAX_BURST; 224743b7e5eaSJiawen Wu 224843b7e5eaSJiawen Wu /* 224943b7e5eaSJiawen Wu * Zero out HW ring memory. Zero out extra memory at the end of 225043b7e5eaSJiawen Wu * the H/W ring so look-ahead logic in Rx Burst bulk alloc function 225143b7e5eaSJiawen Wu * reads extra memory as zeros. 225243b7e5eaSJiawen Wu */ 225343b7e5eaSJiawen Wu for (i = 0; i < len; i++) 225443b7e5eaSJiawen Wu rxq->rx_ring[i] = zeroed_desc; 225543b7e5eaSJiawen Wu 225643b7e5eaSJiawen Wu /* 225743b7e5eaSJiawen Wu * initialize extra software ring entries. Space for these extra 225843b7e5eaSJiawen Wu * entries is always allocated 225943b7e5eaSJiawen Wu */ 226043b7e5eaSJiawen Wu memset(&rxq->fake_mbuf, 0x0, sizeof(rxq->fake_mbuf)); 226143b7e5eaSJiawen Wu for (i = rxq->nb_rx_desc; i < len; ++i) 226243b7e5eaSJiawen Wu rxq->sw_ring[i].mbuf = &rxq->fake_mbuf; 226343b7e5eaSJiawen Wu 226443b7e5eaSJiawen Wu rxq->rx_nb_avail = 0; 226543b7e5eaSJiawen Wu rxq->rx_next_avail = 0; 226643b7e5eaSJiawen Wu rxq->rx_free_trigger = (uint16_t)(rxq->rx_free_thresh - 1); 226743b7e5eaSJiawen Wu rxq->rx_tail = 0; 226843b7e5eaSJiawen Wu rxq->nb_rx_hold = 0; 2269fea7422fSJiawen Wu rte_pktmbuf_free(rxq->pkt_first_seg); 227043b7e5eaSJiawen Wu rxq->pkt_first_seg = NULL; 227143b7e5eaSJiawen Wu rxq->pkt_last_seg = NULL; 2272e94c20c3SJiawen Wu 2273e94c20c3SJiawen Wu #if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM) 2274e94c20c3SJiawen Wu rxq->rxrearm_start = 0; 2275e94c20c3SJiawen Wu rxq->rxrearm_nb = 0; 2276e94c20c3SJiawen Wu #endif 227743b7e5eaSJiawen Wu } 227843b7e5eaSJiawen Wu 227979f3128dSJiawen Wu uint64_t 228059b46438SJiawen Wu ngbe_get_rx_queue_offloads(struct rte_eth_dev *dev __rte_unused) 228159b46438SJiawen Wu { 228259b46438SJiawen Wu return RTE_ETH_RX_OFFLOAD_VLAN_STRIP; 228359b46438SJiawen Wu } 228459b46438SJiawen Wu 228559b46438SJiawen Wu uint64_t 228659b46438SJiawen Wu ngbe_get_rx_port_offloads(struct rte_eth_dev *dev) 228779f3128dSJiawen Wu { 2288ffc959f5SJiawen Wu uint64_t offloads; 228959b46438SJiawen Wu struct ngbe_hw *hw = ngbe_dev_hw(dev); 2290ffc959f5SJiawen Wu 2291ffc959f5SJiawen Wu offloads = RTE_ETH_RX_OFFLOAD_IPV4_CKSUM | 2292ffc959f5SJiawen Wu RTE_ETH_RX_OFFLOAD_UDP_CKSUM | 2293ffc959f5SJiawen Wu RTE_ETH_RX_OFFLOAD_TCP_CKSUM | 229464b36e4aSJiawen Wu RTE_ETH_RX_OFFLOAD_KEEP_CRC | 229559b46438SJiawen Wu RTE_ETH_RX_OFFLOAD_VLAN_FILTER | 22964fbb5f20SJiawen Wu RTE_ETH_RX_OFFLOAD_RSS_HASH | 2297ffc959f5SJiawen Wu RTE_ETH_RX_OFFLOAD_SCATTER; 2298ffc959f5SJiawen Wu 229959b46438SJiawen Wu if (hw->is_pf) 230059b46438SJiawen Wu offloads |= (RTE_ETH_RX_OFFLOAD_QINQ_STRIP | 230159b46438SJiawen Wu RTE_ETH_RX_OFFLOAD_VLAN_EXTEND); 230259b46438SJiawen Wu 2303ffc959f5SJiawen Wu return offloads; 230479f3128dSJiawen Wu } 230579f3128dSJiawen Wu 230643b7e5eaSJiawen Wu int 230743b7e5eaSJiawen Wu ngbe_dev_rx_queue_setup(struct rte_eth_dev *dev, 230843b7e5eaSJiawen Wu uint16_t queue_idx, 230943b7e5eaSJiawen Wu uint16_t nb_desc, 231043b7e5eaSJiawen Wu unsigned int socket_id, 231143b7e5eaSJiawen Wu const struct rte_eth_rxconf *rx_conf, 231243b7e5eaSJiawen Wu struct rte_mempool *mp) 231343b7e5eaSJiawen Wu { 231443b7e5eaSJiawen Wu const struct rte_memzone *rz; 231543b7e5eaSJiawen Wu struct ngbe_rx_queue *rxq; 231643b7e5eaSJiawen Wu struct ngbe_hw *hw; 231743b7e5eaSJiawen Wu uint16_t len; 231843b7e5eaSJiawen Wu struct ngbe_adapter *adapter = ngbe_dev_adapter(dev); 231959b46438SJiawen Wu uint64_t offloads; 232043b7e5eaSJiawen Wu 232143b7e5eaSJiawen Wu PMD_INIT_FUNC_TRACE(); 232243b7e5eaSJiawen Wu hw = ngbe_dev_hw(dev); 232343b7e5eaSJiawen Wu 232459b46438SJiawen Wu offloads = rx_conf->offloads | dev->data->dev_conf.rxmode.offloads; 232559b46438SJiawen Wu 232643b7e5eaSJiawen Wu /* Free memory prior to re-allocation if needed... */ 232743b7e5eaSJiawen Wu if (dev->data->rx_queues[queue_idx] != NULL) { 232843b7e5eaSJiawen Wu ngbe_rx_queue_release(dev->data->rx_queues[queue_idx]); 232943b7e5eaSJiawen Wu dev->data->rx_queues[queue_idx] = NULL; 233043b7e5eaSJiawen Wu } 233143b7e5eaSJiawen Wu 233243b7e5eaSJiawen Wu /* First allocate the Rx queue data structure */ 233343b7e5eaSJiawen Wu rxq = rte_zmalloc_socket("ethdev RX queue", 233443b7e5eaSJiawen Wu sizeof(struct ngbe_rx_queue), 233543b7e5eaSJiawen Wu RTE_CACHE_LINE_SIZE, socket_id); 233643b7e5eaSJiawen Wu if (rxq == NULL) 233743b7e5eaSJiawen Wu return -ENOMEM; 233843b7e5eaSJiawen Wu rxq->mb_pool = mp; 233943b7e5eaSJiawen Wu rxq->nb_rx_desc = nb_desc; 234043b7e5eaSJiawen Wu rxq->rx_free_thresh = rx_conf->rx_free_thresh; 234143b7e5eaSJiawen Wu rxq->queue_id = queue_idx; 234260229dcfSJiawen Wu rxq->reg_idx = (uint16_t)((RTE_ETH_DEV_SRIOV(dev).active == 0) ? 234360229dcfSJiawen Wu queue_idx : RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx + queue_idx); 234443b7e5eaSJiawen Wu rxq->port_id = dev->data->port_id; 234564b36e4aSJiawen Wu if (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC) 234664b36e4aSJiawen Wu rxq->crc_len = RTE_ETHER_CRC_LEN; 234764b36e4aSJiawen Wu else 234864b36e4aSJiawen Wu rxq->crc_len = 0; 234943b7e5eaSJiawen Wu rxq->drop_en = rx_conf->rx_drop_en; 235043b7e5eaSJiawen Wu rxq->rx_deferred_start = rx_conf->rx_deferred_start; 235159b46438SJiawen Wu rxq->offloads = offloads; 235243b7e5eaSJiawen Wu 235343b7e5eaSJiawen Wu /* 235443b7e5eaSJiawen Wu * Allocate Rx ring hardware descriptors. A memzone large enough to 235543b7e5eaSJiawen Wu * handle the maximum ring size is allocated in order to allow for 235643b7e5eaSJiawen Wu * resizing in later calls to the queue setup function. 235743b7e5eaSJiawen Wu */ 235843b7e5eaSJiawen Wu rz = rte_eth_dma_zone_reserve(dev, "rx_ring", queue_idx, 235943b7e5eaSJiawen Wu RX_RING_SZ, NGBE_ALIGN, socket_id); 236043b7e5eaSJiawen Wu if (rz == NULL) { 236143b7e5eaSJiawen Wu ngbe_rx_queue_release(rxq); 236243b7e5eaSJiawen Wu return -ENOMEM; 236343b7e5eaSJiawen Wu } 236443b7e5eaSJiawen Wu 2365fea7422fSJiawen Wu rxq->mz = rz; 236643b7e5eaSJiawen Wu /* 236743b7e5eaSJiawen Wu * Zero init all the descriptors in the ring. 236843b7e5eaSJiawen Wu */ 236943b7e5eaSJiawen Wu memset(rz->addr, 0, RX_RING_SZ); 237043b7e5eaSJiawen Wu 237143b7e5eaSJiawen Wu rxq->rdt_reg_addr = NGBE_REG_ADDR(hw, NGBE_RXWP(rxq->reg_idx)); 237243b7e5eaSJiawen Wu rxq->rdh_reg_addr = NGBE_REG_ADDR(hw, NGBE_RXRP(rxq->reg_idx)); 237343b7e5eaSJiawen Wu 237443b7e5eaSJiawen Wu rxq->rx_ring_phys_addr = TMZ_PADDR(rz); 237543b7e5eaSJiawen Wu rxq->rx_ring = (struct ngbe_rx_desc *)TMZ_VADDR(rz); 237643b7e5eaSJiawen Wu 237743b7e5eaSJiawen Wu /* 237843b7e5eaSJiawen Wu * Certain constraints must be met in order to use the bulk buffer 237943b7e5eaSJiawen Wu * allocation Rx burst function. If any of Rx queues doesn't meet them 238043b7e5eaSJiawen Wu * the feature should be disabled for the whole port. 238143b7e5eaSJiawen Wu */ 238243b7e5eaSJiawen Wu if (check_rx_burst_bulk_alloc_preconditions(rxq)) { 238343b7e5eaSJiawen Wu PMD_INIT_LOG(DEBUG, 238443b7e5eaSJiawen Wu "queue[%d] doesn't meet Rx Bulk Alloc preconditions - canceling the feature for the whole port[%d]", 238543b7e5eaSJiawen Wu rxq->queue_id, rxq->port_id); 238643b7e5eaSJiawen Wu adapter->rx_bulk_alloc_allowed = false; 238743b7e5eaSJiawen Wu } 238843b7e5eaSJiawen Wu 238943b7e5eaSJiawen Wu /* 239043b7e5eaSJiawen Wu * Allocate software ring. Allow for space at the end of the 239143b7e5eaSJiawen Wu * S/W ring to make sure look-ahead logic in bulk alloc Rx burst 239243b7e5eaSJiawen Wu * function does not access an invalid memory region. 239343b7e5eaSJiawen Wu */ 239443b7e5eaSJiawen Wu len = nb_desc; 239543b7e5eaSJiawen Wu if (adapter->rx_bulk_alloc_allowed) 239643b7e5eaSJiawen Wu len += RTE_PMD_NGBE_RX_MAX_BURST; 239743b7e5eaSJiawen Wu 239843b7e5eaSJiawen Wu rxq->sw_ring = rte_zmalloc_socket("rxq->sw_ring", 239943b7e5eaSJiawen Wu sizeof(struct ngbe_rx_entry) * len, 240043b7e5eaSJiawen Wu RTE_CACHE_LINE_SIZE, socket_id); 240143b7e5eaSJiawen Wu if (rxq->sw_ring == NULL) { 240243b7e5eaSJiawen Wu ngbe_rx_queue_release(rxq); 240343b7e5eaSJiawen Wu return -ENOMEM; 240443b7e5eaSJiawen Wu } 240543b7e5eaSJiawen Wu 240643b7e5eaSJiawen Wu /* 240743b7e5eaSJiawen Wu * Always allocate even if it's not going to be needed in order to 240843b7e5eaSJiawen Wu * simplify the code. 240943b7e5eaSJiawen Wu * 241043b7e5eaSJiawen Wu * This ring is used in Scattered Rx cases and Scattered Rx may 241143b7e5eaSJiawen Wu * be requested in ngbe_dev_rx_init(), which is called later from 241243b7e5eaSJiawen Wu * dev_start() flow. 241343b7e5eaSJiawen Wu */ 241443b7e5eaSJiawen Wu rxq->sw_sc_ring = 241543b7e5eaSJiawen Wu rte_zmalloc_socket("rxq->sw_sc_ring", 241643b7e5eaSJiawen Wu sizeof(struct ngbe_scattered_rx_entry) * len, 241743b7e5eaSJiawen Wu RTE_CACHE_LINE_SIZE, socket_id); 241843b7e5eaSJiawen Wu if (rxq->sw_sc_ring == NULL) { 241943b7e5eaSJiawen Wu ngbe_rx_queue_release(rxq); 242043b7e5eaSJiawen Wu return -ENOMEM; 242143b7e5eaSJiawen Wu } 242243b7e5eaSJiawen Wu 242343b7e5eaSJiawen Wu PMD_INIT_LOG(DEBUG, 242443b7e5eaSJiawen Wu "sw_ring=%p sw_sc_ring=%p hw_ring=%p dma_addr=0x%" PRIx64, 242543b7e5eaSJiawen Wu rxq->sw_ring, rxq->sw_sc_ring, rxq->rx_ring, 242643b7e5eaSJiawen Wu rxq->rx_ring_phys_addr); 242743b7e5eaSJiawen Wu 2428e94c20c3SJiawen Wu if (!rte_is_power_of_2(nb_desc)) { 2429e94c20c3SJiawen Wu PMD_INIT_LOG(DEBUG, "queue[%d] doesn't meet Vector Rx " 2430e94c20c3SJiawen Wu "preconditions - canceling the feature for " 2431e94c20c3SJiawen Wu "the whole port[%d]", 2432e94c20c3SJiawen Wu rxq->queue_id, rxq->port_id); 2433e94c20c3SJiawen Wu adapter->rx_vec_allowed = false; 2434e94c20c3SJiawen Wu } else { 2435e94c20c3SJiawen Wu ngbe_rxq_vec_setup(rxq); 2436e94c20c3SJiawen Wu } 2437e94c20c3SJiawen Wu 243843b7e5eaSJiawen Wu dev->data->rx_queues[queue_idx] = rxq; 243943b7e5eaSJiawen Wu 244043b7e5eaSJiawen Wu ngbe_reset_rx_queue(adapter, rxq); 244143b7e5eaSJiawen Wu 244243b7e5eaSJiawen Wu return 0; 244343b7e5eaSJiawen Wu } 244443b7e5eaSJiawen Wu 2445b7aad633SJiawen Wu uint32_t 2446b7aad633SJiawen Wu ngbe_dev_rx_queue_count(void *rx_queue) 2447b7aad633SJiawen Wu { 2448b7aad633SJiawen Wu #define NGBE_RXQ_SCAN_INTERVAL 4 2449b7aad633SJiawen Wu volatile struct ngbe_rx_desc *rxdp; 2450b7aad633SJiawen Wu struct ngbe_rx_queue *rxq = rx_queue; 2451b7aad633SJiawen Wu uint32_t desc = 0; 2452b7aad633SJiawen Wu 2453b7aad633SJiawen Wu rxdp = &rxq->rx_ring[rxq->rx_tail]; 2454b7aad633SJiawen Wu 2455b7aad633SJiawen Wu while ((desc < rxq->nb_rx_desc) && 2456b7aad633SJiawen Wu (rxdp->qw1.lo.status & 2457b7aad633SJiawen Wu rte_cpu_to_le_32(NGBE_RXD_STAT_DD))) { 2458b7aad633SJiawen Wu desc += NGBE_RXQ_SCAN_INTERVAL; 2459b7aad633SJiawen Wu rxdp += NGBE_RXQ_SCAN_INTERVAL; 2460b7aad633SJiawen Wu if (rxq->rx_tail + desc >= rxq->nb_rx_desc) 2461b7aad633SJiawen Wu rxdp = &(rxq->rx_ring[rxq->rx_tail + 2462b7aad633SJiawen Wu desc - rxq->nb_rx_desc]); 2463b7aad633SJiawen Wu } 2464b7aad633SJiawen Wu 2465b7aad633SJiawen Wu return desc; 2466b7aad633SJiawen Wu } 2467b7aad633SJiawen Wu 2468b7aad633SJiawen Wu int 2469b7aad633SJiawen Wu ngbe_dev_rx_descriptor_status(void *rx_queue, uint16_t offset) 2470b7aad633SJiawen Wu { 2471b7aad633SJiawen Wu struct ngbe_rx_queue *rxq = rx_queue; 2472b7aad633SJiawen Wu volatile uint32_t *status; 2473b7aad633SJiawen Wu uint32_t nb_hold, desc; 2474b7aad633SJiawen Wu 2475b7aad633SJiawen Wu if (unlikely(offset >= rxq->nb_rx_desc)) 2476b7aad633SJiawen Wu return -EINVAL; 2477b7aad633SJiawen Wu 2478e94c20c3SJiawen Wu #if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM) 2479e94c20c3SJiawen Wu if (rxq->rx_using_sse) 2480e94c20c3SJiawen Wu nb_hold = rxq->rxrearm_nb; 2481e94c20c3SJiawen Wu else 2482e94c20c3SJiawen Wu #endif 2483b7aad633SJiawen Wu nb_hold = rxq->nb_rx_hold; 2484b7aad633SJiawen Wu if (offset >= rxq->nb_rx_desc - nb_hold) 2485b7aad633SJiawen Wu return RTE_ETH_RX_DESC_UNAVAIL; 2486b7aad633SJiawen Wu 2487b7aad633SJiawen Wu desc = rxq->rx_tail + offset; 2488b7aad633SJiawen Wu if (desc >= rxq->nb_rx_desc) 2489b7aad633SJiawen Wu desc -= rxq->nb_rx_desc; 2490b7aad633SJiawen Wu 2491b7aad633SJiawen Wu status = &rxq->rx_ring[desc].qw1.lo.status; 2492b7aad633SJiawen Wu if (*status & rte_cpu_to_le_32(NGBE_RXD_STAT_DD)) 2493b7aad633SJiawen Wu return RTE_ETH_RX_DESC_DONE; 2494b7aad633SJiawen Wu 2495b7aad633SJiawen Wu return RTE_ETH_RX_DESC_AVAIL; 2496b7aad633SJiawen Wu } 2497b7aad633SJiawen Wu 2498b7aad633SJiawen Wu int 2499b7aad633SJiawen Wu ngbe_dev_tx_descriptor_status(void *tx_queue, uint16_t offset) 2500b7aad633SJiawen Wu { 2501b7aad633SJiawen Wu struct ngbe_tx_queue *txq = tx_queue; 2502b7aad633SJiawen Wu volatile uint32_t *status; 2503b7aad633SJiawen Wu uint32_t desc; 2504b7aad633SJiawen Wu 2505b7aad633SJiawen Wu if (unlikely(offset >= txq->nb_tx_desc)) 2506b7aad633SJiawen Wu return -EINVAL; 2507b7aad633SJiawen Wu 2508b7aad633SJiawen Wu desc = txq->tx_tail + offset; 2509b7aad633SJiawen Wu if (desc >= txq->nb_tx_desc) { 2510b7aad633SJiawen Wu desc -= txq->nb_tx_desc; 2511b7aad633SJiawen Wu if (desc >= txq->nb_tx_desc) 2512b7aad633SJiawen Wu desc -= txq->nb_tx_desc; 2513b7aad633SJiawen Wu } 2514b7aad633SJiawen Wu 2515b7aad633SJiawen Wu status = &txq->tx_ring[desc].dw3; 2516b7aad633SJiawen Wu if (*status & rte_cpu_to_le_32(NGBE_TXD_DD)) 2517b7aad633SJiawen Wu return RTE_ETH_TX_DESC_DONE; 2518b7aad633SJiawen Wu 2519b7aad633SJiawen Wu return RTE_ETH_TX_DESC_FULL; 2520b7aad633SJiawen Wu } 2521b7aad633SJiawen Wu 25223518df57SJiawen Wu void 25233518df57SJiawen Wu ngbe_dev_clear_queues(struct rte_eth_dev *dev) 25243518df57SJiawen Wu { 25253518df57SJiawen Wu unsigned int i; 25263518df57SJiawen Wu struct ngbe_adapter *adapter = ngbe_dev_adapter(dev); 25273518df57SJiawen Wu 25283518df57SJiawen Wu PMD_INIT_FUNC_TRACE(); 25293518df57SJiawen Wu 25303518df57SJiawen Wu for (i = 0; i < dev->data->nb_tx_queues; i++) { 25313518df57SJiawen Wu struct ngbe_tx_queue *txq = dev->data->tx_queues[i]; 25323518df57SJiawen Wu 25333518df57SJiawen Wu if (txq != NULL) { 25343518df57SJiawen Wu txq->ops->release_mbufs(txq); 25353518df57SJiawen Wu txq->ops->reset(txq); 25369179018eSJie Hai dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 25373518df57SJiawen Wu } 25383518df57SJiawen Wu } 25393518df57SJiawen Wu 25403518df57SJiawen Wu for (i = 0; i < dev->data->nb_rx_queues; i++) { 25413518df57SJiawen Wu struct ngbe_rx_queue *rxq = dev->data->rx_queues[i]; 25423518df57SJiawen Wu 25433518df57SJiawen Wu if (rxq != NULL) { 25443518df57SJiawen Wu ngbe_rx_queue_release_mbufs(rxq); 25453518df57SJiawen Wu ngbe_reset_rx_queue(adapter, rxq); 25469179018eSJie Hai dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 25473518df57SJiawen Wu } 25483518df57SJiawen Wu } 25493518df57SJiawen Wu } 25503518df57SJiawen Wu 2551cc63194eSJiawen Wu void 2552cc63194eSJiawen Wu ngbe_dev_free_queues(struct rte_eth_dev *dev) 2553cc63194eSJiawen Wu { 2554cc63194eSJiawen Wu unsigned int i; 2555cc63194eSJiawen Wu 2556cc63194eSJiawen Wu PMD_INIT_FUNC_TRACE(); 2557cc63194eSJiawen Wu 2558cc63194eSJiawen Wu for (i = 0; i < dev->data->nb_rx_queues; i++) { 25597483341aSXueming Li ngbe_dev_rx_queue_release(dev, i); 2560cc63194eSJiawen Wu dev->data->rx_queues[i] = NULL; 2561cc63194eSJiawen Wu } 2562cc63194eSJiawen Wu dev->data->nb_rx_queues = 0; 2563cc63194eSJiawen Wu 2564cc63194eSJiawen Wu for (i = 0; i < dev->data->nb_tx_queues; i++) { 25657483341aSXueming Li ngbe_dev_tx_queue_release(dev, i); 2566cc63194eSJiawen Wu dev->data->tx_queues[i] = NULL; 2567cc63194eSJiawen Wu } 2568cc63194eSJiawen Wu dev->data->nb_tx_queues = 0; 2569cc63194eSJiawen Wu } 2570cc63194eSJiawen Wu 25710779d7f6SJiawen Wu /** 25720779d7f6SJiawen Wu * Receive Side Scaling (RSS) 25730779d7f6SJiawen Wu * 25740779d7f6SJiawen Wu * Principles: 25750779d7f6SJiawen Wu * The source and destination IP addresses of the IP header and the source 25760779d7f6SJiawen Wu * and destination ports of TCP/UDP headers, if any, of received packets are 25770779d7f6SJiawen Wu * hashed against a configurable random key to compute a 32-bit RSS hash result. 25780779d7f6SJiawen Wu * The seven (7) LSBs of the 32-bit hash result are used as an index into a 25790779d7f6SJiawen Wu * 128-entry redirection table (RETA). Each entry of the RETA provides a 3-bit 25800779d7f6SJiawen Wu * RSS output index which is used as the Rx queue index where to store the 25810779d7f6SJiawen Wu * received packets. 25820779d7f6SJiawen Wu * The following output is supplied in the Rx write-back descriptor: 25830779d7f6SJiawen Wu * - 32-bit result of the Microsoft RSS hash function, 25840779d7f6SJiawen Wu * - 4-bit RSS type field. 25850779d7f6SJiawen Wu */ 25860779d7f6SJiawen Wu 25870779d7f6SJiawen Wu /* 25880779d7f6SJiawen Wu * Used as the default key. 25890779d7f6SJiawen Wu */ 25900779d7f6SJiawen Wu static uint8_t rss_intel_key[40] = { 25910779d7f6SJiawen Wu 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 25920779d7f6SJiawen Wu 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0, 25930779d7f6SJiawen Wu 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4, 25940779d7f6SJiawen Wu 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, 25950779d7f6SJiawen Wu 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA, 25960779d7f6SJiawen Wu }; 25970779d7f6SJiawen Wu 25980779d7f6SJiawen Wu static void 25990779d7f6SJiawen Wu ngbe_rss_disable(struct rte_eth_dev *dev) 26000779d7f6SJiawen Wu { 26010779d7f6SJiawen Wu struct ngbe_hw *hw = ngbe_dev_hw(dev); 26020779d7f6SJiawen Wu 26030779d7f6SJiawen Wu wr32m(hw, NGBE_RACTL, NGBE_RACTL_RSSENA, 0); 26040779d7f6SJiawen Wu } 26050779d7f6SJiawen Wu 26060779d7f6SJiawen Wu int 26070779d7f6SJiawen Wu ngbe_dev_rss_hash_update(struct rte_eth_dev *dev, 26080779d7f6SJiawen Wu struct rte_eth_rss_conf *rss_conf) 26090779d7f6SJiawen Wu { 26100779d7f6SJiawen Wu struct ngbe_hw *hw = ngbe_dev_hw(dev); 26110779d7f6SJiawen Wu uint8_t *hash_key; 26120779d7f6SJiawen Wu uint32_t mrqc; 26130779d7f6SJiawen Wu uint32_t rss_key; 26140779d7f6SJiawen Wu uint64_t rss_hf; 26150779d7f6SJiawen Wu uint16_t i; 26160779d7f6SJiawen Wu 26170779d7f6SJiawen Wu if (!hw->is_pf) { 26180779d7f6SJiawen Wu PMD_DRV_LOG(ERR, "RSS hash update is not supported on this " 26190779d7f6SJiawen Wu "NIC."); 26200779d7f6SJiawen Wu return -ENOTSUP; 26210779d7f6SJiawen Wu } 26220779d7f6SJiawen Wu 26230779d7f6SJiawen Wu hash_key = rss_conf->rss_key; 26240779d7f6SJiawen Wu if (hash_key) { 26250779d7f6SJiawen Wu /* Fill in RSS hash key */ 26260779d7f6SJiawen Wu for (i = 0; i < 10; i++) { 26270779d7f6SJiawen Wu rss_key = LS32(hash_key[(i * 4) + 0], 0, 0xFF); 26280779d7f6SJiawen Wu rss_key |= LS32(hash_key[(i * 4) + 1], 8, 0xFF); 26290779d7f6SJiawen Wu rss_key |= LS32(hash_key[(i * 4) + 2], 16, 0xFF); 26300779d7f6SJiawen Wu rss_key |= LS32(hash_key[(i * 4) + 3], 24, 0xFF); 26310779d7f6SJiawen Wu wr32a(hw, NGBE_REG_RSSKEY, i, rss_key); 26320779d7f6SJiawen Wu } 26330779d7f6SJiawen Wu } 26340779d7f6SJiawen Wu 26350779d7f6SJiawen Wu /* Set configured hashing protocols */ 26360779d7f6SJiawen Wu rss_hf = rss_conf->rss_hf & NGBE_RSS_OFFLOAD_ALL; 26370779d7f6SJiawen Wu 26380779d7f6SJiawen Wu mrqc = rd32(hw, NGBE_RACTL); 26390779d7f6SJiawen Wu mrqc &= ~NGBE_RACTL_RSSMASK; 26400779d7f6SJiawen Wu if (rss_hf & RTE_ETH_RSS_IPV4) 26410779d7f6SJiawen Wu mrqc |= NGBE_RACTL_RSSIPV4; 26420779d7f6SJiawen Wu if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) 26430779d7f6SJiawen Wu mrqc |= NGBE_RACTL_RSSIPV4TCP; 26440779d7f6SJiawen Wu if (rss_hf & RTE_ETH_RSS_IPV6 || 26450779d7f6SJiawen Wu rss_hf & RTE_ETH_RSS_IPV6_EX) 26460779d7f6SJiawen Wu mrqc |= NGBE_RACTL_RSSIPV6; 26470779d7f6SJiawen Wu if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP || 26480779d7f6SJiawen Wu rss_hf & RTE_ETH_RSS_IPV6_TCP_EX) 26490779d7f6SJiawen Wu mrqc |= NGBE_RACTL_RSSIPV6TCP; 26500779d7f6SJiawen Wu if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) 26510779d7f6SJiawen Wu mrqc |= NGBE_RACTL_RSSIPV4UDP; 26520779d7f6SJiawen Wu if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP || 26530779d7f6SJiawen Wu rss_hf & RTE_ETH_RSS_IPV6_UDP_EX) 26540779d7f6SJiawen Wu mrqc |= NGBE_RACTL_RSSIPV6UDP; 26550779d7f6SJiawen Wu 26560779d7f6SJiawen Wu if (rss_hf) 26570779d7f6SJiawen Wu mrqc |= NGBE_RACTL_RSSENA; 26580779d7f6SJiawen Wu else 26590779d7f6SJiawen Wu mrqc &= ~NGBE_RACTL_RSSENA; 26600779d7f6SJiawen Wu 26610779d7f6SJiawen Wu wr32(hw, NGBE_RACTL, mrqc); 26620779d7f6SJiawen Wu 26630779d7f6SJiawen Wu return 0; 26640779d7f6SJiawen Wu } 26650779d7f6SJiawen Wu 26660779d7f6SJiawen Wu int 26670779d7f6SJiawen Wu ngbe_dev_rss_hash_conf_get(struct rte_eth_dev *dev, 26680779d7f6SJiawen Wu struct rte_eth_rss_conf *rss_conf) 26690779d7f6SJiawen Wu { 26700779d7f6SJiawen Wu struct ngbe_hw *hw = ngbe_dev_hw(dev); 26710779d7f6SJiawen Wu uint8_t *hash_key; 26720779d7f6SJiawen Wu uint32_t mrqc; 26730779d7f6SJiawen Wu uint32_t rss_key; 26740779d7f6SJiawen Wu uint64_t rss_hf; 26750779d7f6SJiawen Wu uint16_t i; 26760779d7f6SJiawen Wu 26770779d7f6SJiawen Wu hash_key = rss_conf->rss_key; 26780779d7f6SJiawen Wu if (hash_key) { 26790779d7f6SJiawen Wu /* Return RSS hash key */ 26800779d7f6SJiawen Wu for (i = 0; i < 10; i++) { 26810779d7f6SJiawen Wu rss_key = rd32a(hw, NGBE_REG_RSSKEY, i); 26820779d7f6SJiawen Wu hash_key[(i * 4) + 0] = RS32(rss_key, 0, 0xFF); 26830779d7f6SJiawen Wu hash_key[(i * 4) + 1] = RS32(rss_key, 8, 0xFF); 26840779d7f6SJiawen Wu hash_key[(i * 4) + 2] = RS32(rss_key, 16, 0xFF); 26850779d7f6SJiawen Wu hash_key[(i * 4) + 3] = RS32(rss_key, 24, 0xFF); 26860779d7f6SJiawen Wu } 26870779d7f6SJiawen Wu } 26880779d7f6SJiawen Wu 26890779d7f6SJiawen Wu rss_hf = 0; 26900779d7f6SJiawen Wu 26910779d7f6SJiawen Wu mrqc = rd32(hw, NGBE_RACTL); 26920779d7f6SJiawen Wu if (mrqc & NGBE_RACTL_RSSIPV4) 26930779d7f6SJiawen Wu rss_hf |= RTE_ETH_RSS_IPV4; 26940779d7f6SJiawen Wu if (mrqc & NGBE_RACTL_RSSIPV4TCP) 26950779d7f6SJiawen Wu rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP; 26960779d7f6SJiawen Wu if (mrqc & NGBE_RACTL_RSSIPV6) 26970779d7f6SJiawen Wu rss_hf |= RTE_ETH_RSS_IPV6 | 26980779d7f6SJiawen Wu RTE_ETH_RSS_IPV6_EX; 26990779d7f6SJiawen Wu if (mrqc & NGBE_RACTL_RSSIPV6TCP) 27000779d7f6SJiawen Wu rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP | 27010779d7f6SJiawen Wu RTE_ETH_RSS_IPV6_TCP_EX; 27020779d7f6SJiawen Wu if (mrqc & NGBE_RACTL_RSSIPV4UDP) 27030779d7f6SJiawen Wu rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP; 27040779d7f6SJiawen Wu if (mrqc & NGBE_RACTL_RSSIPV6UDP) 27050779d7f6SJiawen Wu rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP | 27060779d7f6SJiawen Wu RTE_ETH_RSS_IPV6_UDP_EX; 27070779d7f6SJiawen Wu if (!(mrqc & NGBE_RACTL_RSSENA)) 27080779d7f6SJiawen Wu rss_hf = 0; 27090779d7f6SJiawen Wu 27100779d7f6SJiawen Wu rss_hf &= NGBE_RSS_OFFLOAD_ALL; 27110779d7f6SJiawen Wu 27120779d7f6SJiawen Wu rss_conf->rss_hf = rss_hf; 27130779d7f6SJiawen Wu return 0; 27140779d7f6SJiawen Wu } 27150779d7f6SJiawen Wu 27160779d7f6SJiawen Wu static void 27170779d7f6SJiawen Wu ngbe_rss_configure(struct rte_eth_dev *dev) 27180779d7f6SJiawen Wu { 27190779d7f6SJiawen Wu struct rte_eth_rss_conf rss_conf; 27200779d7f6SJiawen Wu struct ngbe_adapter *adapter = ngbe_dev_adapter(dev); 27210779d7f6SJiawen Wu struct ngbe_hw *hw = ngbe_dev_hw(dev); 27220779d7f6SJiawen Wu uint32_t reta; 27230779d7f6SJiawen Wu uint16_t i; 27240779d7f6SJiawen Wu uint16_t j; 27250779d7f6SJiawen Wu 27260779d7f6SJiawen Wu PMD_INIT_FUNC_TRACE(); 27270779d7f6SJiawen Wu 27280779d7f6SJiawen Wu /* 27290779d7f6SJiawen Wu * Fill in redirection table 27300779d7f6SJiawen Wu * The byte-swap is needed because NIC registers are in 27310779d7f6SJiawen Wu * little-endian order. 27320779d7f6SJiawen Wu */ 27330779d7f6SJiawen Wu if (adapter->rss_reta_updated == 0) { 27340779d7f6SJiawen Wu reta = 0; 27350779d7f6SJiawen Wu for (i = 0, j = 0; i < RTE_ETH_RSS_RETA_SIZE_128; i++, j++) { 27360779d7f6SJiawen Wu if (j == dev->data->nb_rx_queues) 27370779d7f6SJiawen Wu j = 0; 27380779d7f6SJiawen Wu reta = (reta >> 8) | LS32(j, 24, 0xFF); 27390779d7f6SJiawen Wu if ((i & 3) == 3) 27400779d7f6SJiawen Wu wr32a(hw, NGBE_REG_RSSTBL, i >> 2, reta); 27410779d7f6SJiawen Wu } 27420779d7f6SJiawen Wu } 27430779d7f6SJiawen Wu /* 27440779d7f6SJiawen Wu * Configure the RSS key and the RSS protocols used to compute 27450779d7f6SJiawen Wu * the RSS hash of input packets. 27460779d7f6SJiawen Wu */ 27470779d7f6SJiawen Wu rss_conf = dev->data->dev_conf.rx_adv_conf.rss_conf; 27480779d7f6SJiawen Wu if (rss_conf.rss_key == NULL) 27490779d7f6SJiawen Wu rss_conf.rss_key = rss_intel_key; /* Default hash key */ 27500779d7f6SJiawen Wu ngbe_dev_rss_hash_update(dev, &rss_conf); 27510779d7f6SJiawen Wu } 27520779d7f6SJiawen Wu 275359b46438SJiawen Wu void ngbe_configure_port(struct rte_eth_dev *dev) 275459b46438SJiawen Wu { 275559b46438SJiawen Wu struct ngbe_hw *hw = ngbe_dev_hw(dev); 275659b46438SJiawen Wu int i = 0; 275759b46438SJiawen Wu uint16_t tpids[8] = {RTE_ETHER_TYPE_VLAN, RTE_ETHER_TYPE_QINQ, 275859b46438SJiawen Wu 0x9100, 0x9200, 275959b46438SJiawen Wu 0x0000, 0x0000, 276059b46438SJiawen Wu 0x0000, 0x0000}; 276159b46438SJiawen Wu 276259b46438SJiawen Wu PMD_INIT_FUNC_TRACE(); 276359b46438SJiawen Wu 276459b46438SJiawen Wu /* default outer vlan tpid */ 276559b46438SJiawen Wu wr32(hw, NGBE_EXTAG, 276659b46438SJiawen Wu NGBE_EXTAG_ETAG(RTE_ETHER_TYPE_ETAG) | 276759b46438SJiawen Wu NGBE_EXTAG_VLAN(RTE_ETHER_TYPE_QINQ)); 276859b46438SJiawen Wu 276959b46438SJiawen Wu /* default inner vlan tpid */ 277059b46438SJiawen Wu wr32m(hw, NGBE_VLANCTL, 277159b46438SJiawen Wu NGBE_VLANCTL_TPID_MASK, 277259b46438SJiawen Wu NGBE_VLANCTL_TPID(RTE_ETHER_TYPE_VLAN)); 277359b46438SJiawen Wu wr32m(hw, NGBE_DMATXCTRL, 277459b46438SJiawen Wu NGBE_DMATXCTRL_TPID_MASK, 277559b46438SJiawen Wu NGBE_DMATXCTRL_TPID(RTE_ETHER_TYPE_VLAN)); 277659b46438SJiawen Wu 277759b46438SJiawen Wu /* default vlan tpid filters */ 277859b46438SJiawen Wu for (i = 0; i < 8; i++) { 277959b46438SJiawen Wu wr32m(hw, NGBE_TAGTPID(i / 2), 278059b46438SJiawen Wu (i % 2 ? NGBE_TAGTPID_MSB_MASK 278159b46438SJiawen Wu : NGBE_TAGTPID_LSB_MASK), 278259b46438SJiawen Wu (i % 2 ? NGBE_TAGTPID_MSB(tpids[i]) 278359b46438SJiawen Wu : NGBE_TAGTPID_LSB(tpids[i]))); 278459b46438SJiawen Wu } 278559b46438SJiawen Wu } 278659b46438SJiawen Wu 278762fc35e6SJiawen Wu static int 278862fc35e6SJiawen Wu ngbe_alloc_rx_queue_mbufs(struct ngbe_rx_queue *rxq) 278962fc35e6SJiawen Wu { 279062fc35e6SJiawen Wu struct ngbe_rx_entry *rxe = rxq->sw_ring; 279162fc35e6SJiawen Wu uint64_t dma_addr; 279262fc35e6SJiawen Wu unsigned int i; 279362fc35e6SJiawen Wu 279462fc35e6SJiawen Wu /* Initialize software ring entries */ 279562fc35e6SJiawen Wu for (i = 0; i < rxq->nb_rx_desc; i++) { 279662fc35e6SJiawen Wu /* the ring can also be modified by hardware */ 279762fc35e6SJiawen Wu volatile struct ngbe_rx_desc *rxd; 279862fc35e6SJiawen Wu struct rte_mbuf *mbuf = rte_mbuf_raw_alloc(rxq->mb_pool); 279962fc35e6SJiawen Wu 280062fc35e6SJiawen Wu if (mbuf == NULL) { 280162fc35e6SJiawen Wu PMD_INIT_LOG(ERR, "Rx mbuf alloc failed queue_id=%u port_id=%u", 280262fc35e6SJiawen Wu (unsigned int)rxq->queue_id, 280362fc35e6SJiawen Wu (unsigned int)rxq->port_id); 280462fc35e6SJiawen Wu return -ENOMEM; 280562fc35e6SJiawen Wu } 280662fc35e6SJiawen Wu 280762fc35e6SJiawen Wu mbuf->data_off = RTE_PKTMBUF_HEADROOM; 280862fc35e6SJiawen Wu mbuf->port = rxq->port_id; 280962fc35e6SJiawen Wu 281062fc35e6SJiawen Wu dma_addr = 281162fc35e6SJiawen Wu rte_cpu_to_le_64(rte_mbuf_data_iova_default(mbuf)); 281262fc35e6SJiawen Wu rxd = &rxq->rx_ring[i]; 281362fc35e6SJiawen Wu NGBE_RXD_HDRADDR(rxd, 0); 281462fc35e6SJiawen Wu NGBE_RXD_PKTADDR(rxd, dma_addr); 281562fc35e6SJiawen Wu rxe[i].mbuf = mbuf; 281662fc35e6SJiawen Wu } 281762fc35e6SJiawen Wu 281862fc35e6SJiawen Wu return 0; 281962fc35e6SJiawen Wu } 282062fc35e6SJiawen Wu 28210779d7f6SJiawen Wu static int 28220779d7f6SJiawen Wu ngbe_dev_mq_rx_configure(struct rte_eth_dev *dev) 28230779d7f6SJiawen Wu { 282460229dcfSJiawen Wu if (RTE_ETH_DEV_SRIOV(dev).active == 0) { 28250779d7f6SJiawen Wu switch (dev->data->dev_conf.rxmode.mq_mode) { 28260779d7f6SJiawen Wu case RTE_ETH_MQ_RX_RSS: 28270779d7f6SJiawen Wu ngbe_rss_configure(dev); 28280779d7f6SJiawen Wu break; 28290779d7f6SJiawen Wu 28300779d7f6SJiawen Wu case RTE_ETH_MQ_RX_NONE: 28310779d7f6SJiawen Wu default: 28320779d7f6SJiawen Wu /* if mq_mode is none, disable rss mode.*/ 28330779d7f6SJiawen Wu ngbe_rss_disable(dev); 28340779d7f6SJiawen Wu break; 28350779d7f6SJiawen Wu } 283660229dcfSJiawen Wu } 28370779d7f6SJiawen Wu 28380779d7f6SJiawen Wu return 0; 28390779d7f6SJiawen Wu } 28400779d7f6SJiawen Wu 284179f3128dSJiawen Wu void 284279f3128dSJiawen Wu ngbe_set_rx_function(struct rte_eth_dev *dev) 284379f3128dSJiawen Wu { 2844e94c20c3SJiawen Wu uint16_t i, rx_using_sse; 284579f3128dSJiawen Wu struct ngbe_adapter *adapter = ngbe_dev_adapter(dev); 284679f3128dSJiawen Wu 2847e94c20c3SJiawen Wu /* 2848e94c20c3SJiawen Wu * In order to allow Vector Rx there are a few configuration 2849e94c20c3SJiawen Wu * conditions to be met and Rx Bulk Allocation should be allowed. 2850e94c20c3SJiawen Wu */ 2851e94c20c3SJiawen Wu if (ngbe_rx_vec_dev_conf_condition_check(dev) || 2852e94c20c3SJiawen Wu !adapter->rx_bulk_alloc_allowed || 2853e94c20c3SJiawen Wu rte_vect_get_max_simd_bitwidth() < RTE_VECT_SIMD_128) { 2854e94c20c3SJiawen Wu PMD_INIT_LOG(DEBUG, 2855e94c20c3SJiawen Wu "Port[%d] doesn't meet Vector Rx preconditions", 2856e94c20c3SJiawen Wu dev->data->port_id); 2857e94c20c3SJiawen Wu adapter->rx_vec_allowed = false; 2858e94c20c3SJiawen Wu } 2859e94c20c3SJiawen Wu 286079f3128dSJiawen Wu if (dev->data->scattered_rx) { 286179f3128dSJiawen Wu /* 286279f3128dSJiawen Wu * Set the scattered callback: there are bulk and 286379f3128dSJiawen Wu * single allocation versions. 286479f3128dSJiawen Wu */ 2865e94c20c3SJiawen Wu if (adapter->rx_vec_allowed) { 2866e94c20c3SJiawen Wu PMD_INIT_LOG(DEBUG, 2867e94c20c3SJiawen Wu "Using Vector Scattered Rx callback (port=%d).", 2868e94c20c3SJiawen Wu dev->data->port_id); 2869e94c20c3SJiawen Wu dev->rx_pkt_burst = ngbe_recv_scattered_pkts_vec; 2870e94c20c3SJiawen Wu } else if (adapter->rx_bulk_alloc_allowed) { 287179f3128dSJiawen Wu PMD_INIT_LOG(DEBUG, "Using a Scattered with bulk " 287279f3128dSJiawen Wu "allocation callback (port=%d).", 287379f3128dSJiawen Wu dev->data->port_id); 287479f3128dSJiawen Wu dev->rx_pkt_burst = ngbe_recv_pkts_sc_bulk_alloc; 287579f3128dSJiawen Wu } else { 287679f3128dSJiawen Wu PMD_INIT_LOG(DEBUG, "Using Regular (non-vector, " 287779f3128dSJiawen Wu "single allocation) " 287879f3128dSJiawen Wu "Scattered Rx callback " 287979f3128dSJiawen Wu "(port=%d).", 288079f3128dSJiawen Wu dev->data->port_id); 288179f3128dSJiawen Wu 288279f3128dSJiawen Wu dev->rx_pkt_burst = ngbe_recv_pkts_sc_single_alloc; 288379f3128dSJiawen Wu } 288479f3128dSJiawen Wu /* 288579f3128dSJiawen Wu * Below we set "simple" callbacks according to port/queues parameters. 288679f3128dSJiawen Wu * If parameters allow we are going to choose between the following 288779f3128dSJiawen Wu * callbacks: 2888e94c20c3SJiawen Wu * - Vector 288979f3128dSJiawen Wu * - Bulk Allocation 289079f3128dSJiawen Wu * - Single buffer allocation (the simplest one) 289179f3128dSJiawen Wu */ 2892e94c20c3SJiawen Wu } else if (adapter->rx_vec_allowed) { 2893e94c20c3SJiawen Wu PMD_INIT_LOG(DEBUG, "Vector rx enabled, please make sure Rx " 2894e94c20c3SJiawen Wu "burst size no less than %d (port=%d).", 2895e94c20c3SJiawen Wu RTE_NGBE_DESCS_PER_LOOP, 2896e94c20c3SJiawen Wu dev->data->port_id); 2897e94c20c3SJiawen Wu dev->rx_pkt_burst = ngbe_recv_pkts_vec; 289879f3128dSJiawen Wu } else if (adapter->rx_bulk_alloc_allowed) { 289979f3128dSJiawen Wu PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions are " 290079f3128dSJiawen Wu "satisfied. Rx Burst Bulk Alloc function " 290179f3128dSJiawen Wu "will be used on port=%d.", 290279f3128dSJiawen Wu dev->data->port_id); 290379f3128dSJiawen Wu 290479f3128dSJiawen Wu dev->rx_pkt_burst = ngbe_recv_pkts_bulk_alloc; 290579f3128dSJiawen Wu } else { 290679f3128dSJiawen Wu PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions are not " 290779f3128dSJiawen Wu "satisfied, or Scattered Rx is requested " 290879f3128dSJiawen Wu "(port=%d).", 290979f3128dSJiawen Wu dev->data->port_id); 291079f3128dSJiawen Wu 291179f3128dSJiawen Wu dev->rx_pkt_burst = ngbe_recv_pkts; 291279f3128dSJiawen Wu } 2913e94c20c3SJiawen Wu 2914e94c20c3SJiawen Wu rx_using_sse = (dev->rx_pkt_burst == ngbe_recv_scattered_pkts_vec || 2915e94c20c3SJiawen Wu dev->rx_pkt_burst == ngbe_recv_pkts_vec); 2916e94c20c3SJiawen Wu 2917e94c20c3SJiawen Wu for (i = 0; i < dev->data->nb_rx_queues; i++) { 2918e94c20c3SJiawen Wu struct ngbe_rx_queue *rxq = dev->data->rx_queues[i]; 2919e94c20c3SJiawen Wu 2920e94c20c3SJiawen Wu rxq->rx_using_sse = rx_using_sse; 2921e94c20c3SJiawen Wu } 292279f3128dSJiawen Wu } 292379f3128dSJiawen Wu 2924d148a87eSJiawen Wu static const struct { 2925d148a87eSJiawen Wu eth_rx_burst_t pkt_burst; 2926d148a87eSJiawen Wu const char *info; 2927d148a87eSJiawen Wu } ngbe_rx_burst_infos[] = { 2928d148a87eSJiawen Wu { ngbe_recv_pkts_sc_single_alloc, "Scalar Scattered"}, 2929d148a87eSJiawen Wu { ngbe_recv_pkts_sc_bulk_alloc, "Scalar Scattered Bulk Alloc"}, 2930d148a87eSJiawen Wu { ngbe_recv_pkts_bulk_alloc, "Scalar Bulk Alloc"}, 2931d148a87eSJiawen Wu { ngbe_recv_pkts, "Scalar"}, 2932e94c20c3SJiawen Wu #ifdef RTE_ARCH_X86 2933e94c20c3SJiawen Wu { ngbe_recv_scattered_pkts_vec, "Vector SSE Scattered" }, 2934e94c20c3SJiawen Wu { ngbe_recv_pkts_vec, "Vector SSE" }, 2935e94c20c3SJiawen Wu #elif defined(RTE_ARCH_ARM64) 2936e94c20c3SJiawen Wu { ngbe_recv_scattered_pkts_vec, "Vector Neon Scattered" }, 2937e94c20c3SJiawen Wu { ngbe_recv_pkts_vec, "Vector Neon" }, 2938e94c20c3SJiawen Wu #endif 2939d148a87eSJiawen Wu }; 2940d148a87eSJiawen Wu 2941d148a87eSJiawen Wu int 2942d148a87eSJiawen Wu ngbe_rx_burst_mode_get(struct rte_eth_dev *dev, __rte_unused uint16_t queue_id, 2943d148a87eSJiawen Wu struct rte_eth_burst_mode *mode) 2944d148a87eSJiawen Wu { 2945d148a87eSJiawen Wu eth_rx_burst_t pkt_burst = dev->rx_pkt_burst; 2946d148a87eSJiawen Wu int ret = -EINVAL; 2947d148a87eSJiawen Wu unsigned int i; 2948d148a87eSJiawen Wu 2949d148a87eSJiawen Wu for (i = 0; i < RTE_DIM(ngbe_rx_burst_infos); ++i) { 2950d148a87eSJiawen Wu if (pkt_burst == ngbe_rx_burst_infos[i].pkt_burst) { 2951d148a87eSJiawen Wu snprintf(mode->info, sizeof(mode->info), "%s", 2952d148a87eSJiawen Wu ngbe_rx_burst_infos[i].info); 2953d148a87eSJiawen Wu ret = 0; 2954d148a87eSJiawen Wu break; 2955d148a87eSJiawen Wu } 2956d148a87eSJiawen Wu } 2957d148a87eSJiawen Wu 2958d148a87eSJiawen Wu return ret; 2959d148a87eSJiawen Wu } 2960d148a87eSJiawen Wu 29613518df57SJiawen Wu /* 29623518df57SJiawen Wu * Initializes Receive Unit. 29633518df57SJiawen Wu */ 29643518df57SJiawen Wu int 29653518df57SJiawen Wu ngbe_dev_rx_init(struct rte_eth_dev *dev) 29663518df57SJiawen Wu { 296762fc35e6SJiawen Wu struct ngbe_hw *hw; 296862fc35e6SJiawen Wu struct ngbe_rx_queue *rxq; 296962fc35e6SJiawen Wu uint64_t bus_addr; 297062fc35e6SJiawen Wu uint32_t fctrl; 297162fc35e6SJiawen Wu uint32_t hlreg0; 297262fc35e6SJiawen Wu uint32_t srrctl; 297364b36e4aSJiawen Wu uint32_t rdrxctl; 2974ffc959f5SJiawen Wu uint32_t rxcsum; 297562fc35e6SJiawen Wu uint16_t buf_size; 297662fc35e6SJiawen Wu uint16_t i; 297779f3128dSJiawen Wu struct rte_eth_rxmode *rx_conf = &dev->data->dev_conf.rxmode; 29783518df57SJiawen Wu 297962fc35e6SJiawen Wu PMD_INIT_FUNC_TRACE(); 298062fc35e6SJiawen Wu hw = ngbe_dev_hw(dev); 298162fc35e6SJiawen Wu 298262fc35e6SJiawen Wu /* 298362fc35e6SJiawen Wu * Make sure receives are disabled while setting 298462fc35e6SJiawen Wu * up the Rx context (registers, descriptor rings, etc.). 298562fc35e6SJiawen Wu */ 29865f1ab0d5SJiawen Wu 29875f1ab0d5SJiawen Wu if (!(hw->ncsi_enabled || hw->wol_enabled)) 298862fc35e6SJiawen Wu wr32m(hw, NGBE_MACRXCFG, NGBE_MACRXCFG_ENA, 0); 29895f1ab0d5SJiawen Wu 299062fc35e6SJiawen Wu wr32m(hw, NGBE_PBRXCTL, NGBE_PBRXCTL_ENA, 0); 299162fc35e6SJiawen Wu 299262fc35e6SJiawen Wu /* Enable receipt of broadcasted frames */ 299362fc35e6SJiawen Wu fctrl = rd32(hw, NGBE_PSRCTL); 299462fc35e6SJiawen Wu fctrl |= NGBE_PSRCTL_BCA; 299562fc35e6SJiawen Wu wr32(hw, NGBE_PSRCTL, fctrl); 299662fc35e6SJiawen Wu 299764b36e4aSJiawen Wu /* 299864b36e4aSJiawen Wu * Configure CRC stripping, if any. 299964b36e4aSJiawen Wu */ 300062fc35e6SJiawen Wu hlreg0 = rd32(hw, NGBE_SECRXCTL); 300164b36e4aSJiawen Wu if (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC) 300264b36e4aSJiawen Wu hlreg0 &= ~NGBE_SECRXCTL_CRCSTRIP; 300364b36e4aSJiawen Wu else 300464b36e4aSJiawen Wu hlreg0 |= NGBE_SECRXCTL_CRCSTRIP; 300562fc35e6SJiawen Wu hlreg0 &= ~NGBE_SECRXCTL_XDSA; 300662fc35e6SJiawen Wu wr32(hw, NGBE_SECRXCTL, hlreg0); 300762fc35e6SJiawen Wu 3008586e6028SJiawen Wu /* 3009586e6028SJiawen Wu * Configure jumbo frame support, if any. 3010586e6028SJiawen Wu */ 301162fc35e6SJiawen Wu wr32m(hw, NGBE_FRMSZ, NGBE_FRMSZ_MAX_MASK, 3012586e6028SJiawen Wu NGBE_FRMSZ_MAX(dev->data->mtu + NGBE_ETH_OVERHEAD)); 301362fc35e6SJiawen Wu 301459b46438SJiawen Wu /* 3015d4a3fe69SJiawen Wu * If loopback mode is configured, set LPBK bit. 3016d4a3fe69SJiawen Wu */ 3017d4a3fe69SJiawen Wu hlreg0 = rd32(hw, NGBE_PSRCTL); 3018d4a3fe69SJiawen Wu if (hw->is_pf && dev->data->dev_conf.lpbk_mode) 3019d4a3fe69SJiawen Wu hlreg0 |= NGBE_PSRCTL_LBENA; 3020d4a3fe69SJiawen Wu else 3021d4a3fe69SJiawen Wu hlreg0 &= ~NGBE_PSRCTL_LBENA; 3022d4a3fe69SJiawen Wu 3023d4a3fe69SJiawen Wu wr32(hw, NGBE_PSRCTL, hlreg0); 3024d4a3fe69SJiawen Wu 3025d4a3fe69SJiawen Wu /* 302659b46438SJiawen Wu * Assume no header split and no VLAN strip support 302759b46438SJiawen Wu * on any Rx queue first . 302859b46438SJiawen Wu */ 302959b46438SJiawen Wu rx_conf->offloads &= ~RTE_ETH_RX_OFFLOAD_VLAN_STRIP; 303059b46438SJiawen Wu 303162fc35e6SJiawen Wu /* Setup Rx queues */ 303262fc35e6SJiawen Wu for (i = 0; i < dev->data->nb_rx_queues; i++) { 303362fc35e6SJiawen Wu rxq = dev->data->rx_queues[i]; 303462fc35e6SJiawen Wu 303564b36e4aSJiawen Wu /* 303664b36e4aSJiawen Wu * Reset crc_len in case it was changed after queue setup by a 303764b36e4aSJiawen Wu * call to configure. 303864b36e4aSJiawen Wu */ 303964b36e4aSJiawen Wu if (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC) 304064b36e4aSJiawen Wu rxq->crc_len = RTE_ETHER_CRC_LEN; 304164b36e4aSJiawen Wu else 304264b36e4aSJiawen Wu rxq->crc_len = 0; 304364b36e4aSJiawen Wu 304462fc35e6SJiawen Wu /* Setup the Base and Length of the Rx Descriptor Rings */ 304562fc35e6SJiawen Wu bus_addr = rxq->rx_ring_phys_addr; 304662fc35e6SJiawen Wu wr32(hw, NGBE_RXBAL(rxq->reg_idx), 304762fc35e6SJiawen Wu (uint32_t)(bus_addr & BIT_MASK32)); 304862fc35e6SJiawen Wu wr32(hw, NGBE_RXBAH(rxq->reg_idx), 304962fc35e6SJiawen Wu (uint32_t)(bus_addr >> 32)); 305062fc35e6SJiawen Wu wr32(hw, NGBE_RXRP(rxq->reg_idx), 0); 305162fc35e6SJiawen Wu wr32(hw, NGBE_RXWP(rxq->reg_idx), 0); 305262fc35e6SJiawen Wu 305362fc35e6SJiawen Wu srrctl = NGBE_RXCFG_RNGLEN(rxq->nb_rx_desc); 305462fc35e6SJiawen Wu 305562fc35e6SJiawen Wu /* Set if packets are dropped when no descriptors available */ 305662fc35e6SJiawen Wu if (rxq->drop_en) 305762fc35e6SJiawen Wu srrctl |= NGBE_RXCFG_DROP; 305862fc35e6SJiawen Wu 305962fc35e6SJiawen Wu /* 306062fc35e6SJiawen Wu * Configure the Rx buffer size in the PKTLEN field of 306162fc35e6SJiawen Wu * the RXCFG register of the queue. 306262fc35e6SJiawen Wu * The value is in 1 KB resolution. Valid values can be from 306362fc35e6SJiawen Wu * 1 KB to 16 KB. 306462fc35e6SJiawen Wu */ 306562fc35e6SJiawen Wu buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mb_pool) - 306662fc35e6SJiawen Wu RTE_PKTMBUF_HEADROOM); 306762fc35e6SJiawen Wu buf_size = ROUND_DOWN(buf_size, 0x1 << 10); 306862fc35e6SJiawen Wu srrctl |= NGBE_RXCFG_PKTLEN(buf_size); 306962fc35e6SJiawen Wu 307062fc35e6SJiawen Wu wr32(hw, NGBE_RXCFG(rxq->reg_idx), srrctl); 307159b46438SJiawen Wu 307259b46438SJiawen Wu /* It adds dual VLAN length for supporting dual VLAN */ 307359b46438SJiawen Wu if (dev->data->mtu + NGBE_ETH_OVERHEAD + 307425cf2630SFerruh Yigit 2 * RTE_VLAN_HLEN > buf_size) 307559b46438SJiawen Wu dev->data->scattered_rx = 1; 307659b46438SJiawen Wu if (rxq->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) 307759b46438SJiawen Wu rx_conf->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP; 307862fc35e6SJiawen Wu } 307962fc35e6SJiawen Wu 308079f3128dSJiawen Wu if (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_SCATTER) 308179f3128dSJiawen Wu dev->data->scattered_rx = 1; 30820779d7f6SJiawen Wu 30830779d7f6SJiawen Wu /* 30840779d7f6SJiawen Wu * Device configured with multiple RX queues. 30850779d7f6SJiawen Wu */ 30860779d7f6SJiawen Wu ngbe_dev_mq_rx_configure(dev); 30870779d7f6SJiawen Wu 3088ffc959f5SJiawen Wu /* 3089ffc959f5SJiawen Wu * Setup the Checksum Register. 30900779d7f6SJiawen Wu * Disable Full-Packet Checksum which is mutually exclusive with RSS. 3091ffc959f5SJiawen Wu * Enable IP/L4 checksum computation by hardware if requested to do so. 3092ffc959f5SJiawen Wu */ 3093ffc959f5SJiawen Wu rxcsum = rd32(hw, NGBE_PSRCTL); 3094ffc959f5SJiawen Wu rxcsum |= NGBE_PSRCTL_PCSD; 3095ffc959f5SJiawen Wu if (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM) 3096ffc959f5SJiawen Wu rxcsum |= NGBE_PSRCTL_L4CSUM; 3097ffc959f5SJiawen Wu else 3098ffc959f5SJiawen Wu rxcsum &= ~NGBE_PSRCTL_L4CSUM; 3099ffc959f5SJiawen Wu 3100ffc959f5SJiawen Wu wr32(hw, NGBE_PSRCTL, rxcsum); 310179f3128dSJiawen Wu 310264b36e4aSJiawen Wu if (hw->is_pf) { 310364b36e4aSJiawen Wu rdrxctl = rd32(hw, NGBE_SECRXCTL); 310464b36e4aSJiawen Wu if (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC) 310564b36e4aSJiawen Wu rdrxctl &= ~NGBE_SECRXCTL_CRCSTRIP; 310664b36e4aSJiawen Wu else 310764b36e4aSJiawen Wu rdrxctl |= NGBE_SECRXCTL_CRCSTRIP; 310864b36e4aSJiawen Wu wr32(hw, NGBE_SECRXCTL, rdrxctl); 310964b36e4aSJiawen Wu } 311064b36e4aSJiawen Wu 311179f3128dSJiawen Wu ngbe_set_rx_function(dev); 311279f3128dSJiawen Wu 311362fc35e6SJiawen Wu return 0; 31143518df57SJiawen Wu } 31153518df57SJiawen Wu 31163518df57SJiawen Wu /* 31173518df57SJiawen Wu * Initializes Transmit Unit. 31183518df57SJiawen Wu */ 31193518df57SJiawen Wu void 31203518df57SJiawen Wu ngbe_dev_tx_init(struct rte_eth_dev *dev) 31213518df57SJiawen Wu { 3122001c7823SJiawen Wu struct ngbe_hw *hw; 3123001c7823SJiawen Wu struct ngbe_tx_queue *txq; 3124001c7823SJiawen Wu uint64_t bus_addr; 3125001c7823SJiawen Wu uint16_t i; 3126001c7823SJiawen Wu 3127001c7823SJiawen Wu PMD_INIT_FUNC_TRACE(); 3128001c7823SJiawen Wu hw = ngbe_dev_hw(dev); 3129001c7823SJiawen Wu 3130001c7823SJiawen Wu wr32m(hw, NGBE_SECTXCTL, NGBE_SECTXCTL_ODSA, NGBE_SECTXCTL_ODSA); 3131001c7823SJiawen Wu wr32m(hw, NGBE_SECTXCTL, NGBE_SECTXCTL_XDSA, 0); 3132001c7823SJiawen Wu 3133001c7823SJiawen Wu /* Setup the Base and Length of the Tx Descriptor Rings */ 3134001c7823SJiawen Wu for (i = 0; i < dev->data->nb_tx_queues; i++) { 3135001c7823SJiawen Wu txq = dev->data->tx_queues[i]; 3136001c7823SJiawen Wu 3137001c7823SJiawen Wu bus_addr = txq->tx_ring_phys_addr; 3138001c7823SJiawen Wu wr32(hw, NGBE_TXBAL(txq->reg_idx), 3139001c7823SJiawen Wu (uint32_t)(bus_addr & BIT_MASK32)); 3140001c7823SJiawen Wu wr32(hw, NGBE_TXBAH(txq->reg_idx), 3141001c7823SJiawen Wu (uint32_t)(bus_addr >> 32)); 3142001c7823SJiawen Wu wr32m(hw, NGBE_TXCFG(txq->reg_idx), NGBE_TXCFG_BUFLEN_MASK, 3143001c7823SJiawen Wu NGBE_TXCFG_BUFLEN(txq->nb_tx_desc)); 3144001c7823SJiawen Wu /* Setup the HW Tx Head and TX Tail descriptor pointers */ 3145001c7823SJiawen Wu wr32(hw, NGBE_TXRP(txq->reg_idx), 0); 3146001c7823SJiawen Wu wr32(hw, NGBE_TXWP(txq->reg_idx), 0); 3147001c7823SJiawen Wu } 31483518df57SJiawen Wu } 31493518df57SJiawen Wu 31503518df57SJiawen Wu /* 3151d4a3fe69SJiawen Wu * Set up link loopback mode Tx->Rx. 3152d4a3fe69SJiawen Wu */ 3153d4a3fe69SJiawen Wu static inline void 3154d4a3fe69SJiawen Wu ngbe_setup_loopback_link(struct ngbe_hw *hw) 3155d4a3fe69SJiawen Wu { 3156d4a3fe69SJiawen Wu PMD_INIT_FUNC_TRACE(); 3157d4a3fe69SJiawen Wu 3158d4a3fe69SJiawen Wu wr32m(hw, NGBE_MACRXCFG, NGBE_MACRXCFG_LB, NGBE_MACRXCFG_LB); 3159d4a3fe69SJiawen Wu 3160d4a3fe69SJiawen Wu msec_delay(50); 3161d4a3fe69SJiawen Wu } 3162d4a3fe69SJiawen Wu 3163d4a3fe69SJiawen Wu /* 31643518df57SJiawen Wu * Start Transmit and Receive Units. 31653518df57SJiawen Wu */ 31663518df57SJiawen Wu int 31673518df57SJiawen Wu ngbe_dev_rxtx_start(struct rte_eth_dev *dev) 31683518df57SJiawen Wu { 3169001c7823SJiawen Wu struct ngbe_hw *hw; 3170001c7823SJiawen Wu struct ngbe_tx_queue *txq; 317162fc35e6SJiawen Wu struct ngbe_rx_queue *rxq; 3172001c7823SJiawen Wu uint32_t dmatxctl; 317362fc35e6SJiawen Wu uint32_t rxctrl; 3174001c7823SJiawen Wu uint16_t i; 3175001c7823SJiawen Wu int ret = 0; 3176001c7823SJiawen Wu 3177001c7823SJiawen Wu PMD_INIT_FUNC_TRACE(); 3178001c7823SJiawen Wu hw = ngbe_dev_hw(dev); 3179001c7823SJiawen Wu 3180001c7823SJiawen Wu for (i = 0; i < dev->data->nb_tx_queues; i++) { 3181001c7823SJiawen Wu txq = dev->data->tx_queues[i]; 3182001c7823SJiawen Wu /* Setup Transmit Threshold Registers */ 3183001c7823SJiawen Wu wr32m(hw, NGBE_TXCFG(txq->reg_idx), 3184001c7823SJiawen Wu NGBE_TXCFG_HTHRESH_MASK | 3185001c7823SJiawen Wu NGBE_TXCFG_WTHRESH_MASK, 3186001c7823SJiawen Wu NGBE_TXCFG_HTHRESH(txq->hthresh) | 3187001c7823SJiawen Wu NGBE_TXCFG_WTHRESH(txq->wthresh)); 3188001c7823SJiawen Wu } 3189001c7823SJiawen Wu 3190001c7823SJiawen Wu dmatxctl = rd32(hw, NGBE_DMATXCTRL); 3191001c7823SJiawen Wu dmatxctl |= NGBE_DMATXCTRL_ENA; 3192001c7823SJiawen Wu wr32(hw, NGBE_DMATXCTRL, dmatxctl); 3193001c7823SJiawen Wu 3194001c7823SJiawen Wu for (i = 0; i < dev->data->nb_tx_queues; i++) { 3195001c7823SJiawen Wu txq = dev->data->tx_queues[i]; 3196001c7823SJiawen Wu if (txq->tx_deferred_start == 0) { 3197001c7823SJiawen Wu ret = ngbe_dev_tx_queue_start(dev, i); 3198001c7823SJiawen Wu if (ret < 0) 3199001c7823SJiawen Wu return ret; 3200001c7823SJiawen Wu } 3201001c7823SJiawen Wu } 32023518df57SJiawen Wu 320362fc35e6SJiawen Wu for (i = 0; i < dev->data->nb_rx_queues; i++) { 320462fc35e6SJiawen Wu rxq = dev->data->rx_queues[i]; 320562fc35e6SJiawen Wu if (rxq->rx_deferred_start == 0) { 320662fc35e6SJiawen Wu ret = ngbe_dev_rx_queue_start(dev, i); 320762fc35e6SJiawen Wu if (ret < 0) 320862fc35e6SJiawen Wu return ret; 320962fc35e6SJiawen Wu } 321062fc35e6SJiawen Wu } 321162fc35e6SJiawen Wu 321262fc35e6SJiawen Wu /* Enable Receive engine */ 321362fc35e6SJiawen Wu rxctrl = rd32(hw, NGBE_PBRXCTL); 321462fc35e6SJiawen Wu rxctrl |= NGBE_PBRXCTL_ENA; 321562fc35e6SJiawen Wu hw->mac.enable_rx_dma(hw, rxctrl); 321662fc35e6SJiawen Wu 3217d4a3fe69SJiawen Wu /* If loopback mode is enabled, set up the link accordingly */ 3218d4a3fe69SJiawen Wu if (hw->is_pf && dev->data->dev_conf.lpbk_mode) 3219d4a3fe69SJiawen Wu ngbe_setup_loopback_link(hw); 3220d4a3fe69SJiawen Wu 322162fc35e6SJiawen Wu return 0; 322262fc35e6SJiawen Wu } 322362fc35e6SJiawen Wu 322462fc35e6SJiawen Wu void 322562fc35e6SJiawen Wu ngbe_dev_save_rx_queue(struct ngbe_hw *hw, uint16_t rx_queue_id) 322662fc35e6SJiawen Wu { 322762fc35e6SJiawen Wu u32 *reg = &hw->q_rx_regs[rx_queue_id * 8]; 322862fc35e6SJiawen Wu *(reg++) = rd32(hw, NGBE_RXBAL(rx_queue_id)); 322962fc35e6SJiawen Wu *(reg++) = rd32(hw, NGBE_RXBAH(rx_queue_id)); 323062fc35e6SJiawen Wu *(reg++) = rd32(hw, NGBE_RXCFG(rx_queue_id)); 323162fc35e6SJiawen Wu } 323262fc35e6SJiawen Wu 323362fc35e6SJiawen Wu void 323462fc35e6SJiawen Wu ngbe_dev_store_rx_queue(struct ngbe_hw *hw, uint16_t rx_queue_id) 323562fc35e6SJiawen Wu { 323662fc35e6SJiawen Wu u32 *reg = &hw->q_rx_regs[rx_queue_id * 8]; 323762fc35e6SJiawen Wu wr32(hw, NGBE_RXBAL(rx_queue_id), *(reg++)); 323862fc35e6SJiawen Wu wr32(hw, NGBE_RXBAH(rx_queue_id), *(reg++)); 323962fc35e6SJiawen Wu wr32(hw, NGBE_RXCFG(rx_queue_id), *(reg++) & ~NGBE_RXCFG_ENA); 32403518df57SJiawen Wu } 3241001c7823SJiawen Wu 3242001c7823SJiawen Wu void 3243001c7823SJiawen Wu ngbe_dev_save_tx_queue(struct ngbe_hw *hw, uint16_t tx_queue_id) 3244001c7823SJiawen Wu { 3245001c7823SJiawen Wu u32 *reg = &hw->q_tx_regs[tx_queue_id * 8]; 3246001c7823SJiawen Wu *(reg++) = rd32(hw, NGBE_TXBAL(tx_queue_id)); 3247001c7823SJiawen Wu *(reg++) = rd32(hw, NGBE_TXBAH(tx_queue_id)); 3248001c7823SJiawen Wu *(reg++) = rd32(hw, NGBE_TXCFG(tx_queue_id)); 3249001c7823SJiawen Wu } 3250001c7823SJiawen Wu 3251001c7823SJiawen Wu void 3252001c7823SJiawen Wu ngbe_dev_store_tx_queue(struct ngbe_hw *hw, uint16_t tx_queue_id) 3253001c7823SJiawen Wu { 3254001c7823SJiawen Wu u32 *reg = &hw->q_tx_regs[tx_queue_id * 8]; 3255001c7823SJiawen Wu wr32(hw, NGBE_TXBAL(tx_queue_id), *(reg++)); 3256001c7823SJiawen Wu wr32(hw, NGBE_TXBAH(tx_queue_id), *(reg++)); 3257001c7823SJiawen Wu wr32(hw, NGBE_TXCFG(tx_queue_id), *(reg++) & ~NGBE_TXCFG_ENA); 3258001c7823SJiawen Wu } 3259001c7823SJiawen Wu 3260001c7823SJiawen Wu /* 326162fc35e6SJiawen Wu * Start Receive Units for specified queue. 326262fc35e6SJiawen Wu */ 326362fc35e6SJiawen Wu int 326462fc35e6SJiawen Wu ngbe_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id) 326562fc35e6SJiawen Wu { 326662fc35e6SJiawen Wu struct ngbe_hw *hw = ngbe_dev_hw(dev); 326762fc35e6SJiawen Wu struct ngbe_rx_queue *rxq; 326862fc35e6SJiawen Wu uint32_t rxdctl; 326962fc35e6SJiawen Wu int poll_ms; 327062fc35e6SJiawen Wu 327162fc35e6SJiawen Wu PMD_INIT_FUNC_TRACE(); 327262fc35e6SJiawen Wu 327362fc35e6SJiawen Wu rxq = dev->data->rx_queues[rx_queue_id]; 327462fc35e6SJiawen Wu 327562fc35e6SJiawen Wu /* Allocate buffers for descriptor rings */ 327662fc35e6SJiawen Wu if (ngbe_alloc_rx_queue_mbufs(rxq) != 0) { 327762fc35e6SJiawen Wu PMD_INIT_LOG(ERR, "Could not alloc mbuf for queue:%d", 327862fc35e6SJiawen Wu rx_queue_id); 327962fc35e6SJiawen Wu return -1; 328062fc35e6SJiawen Wu } 328162fc35e6SJiawen Wu rxdctl = rd32(hw, NGBE_RXCFG(rxq->reg_idx)); 328262fc35e6SJiawen Wu rxdctl |= NGBE_RXCFG_ENA; 328362fc35e6SJiawen Wu wr32(hw, NGBE_RXCFG(rxq->reg_idx), rxdctl); 328462fc35e6SJiawen Wu 328562fc35e6SJiawen Wu /* Wait until Rx Enable ready */ 328662fc35e6SJiawen Wu poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS; 328762fc35e6SJiawen Wu do { 328862fc35e6SJiawen Wu rte_delay_ms(1); 328962fc35e6SJiawen Wu rxdctl = rd32(hw, NGBE_RXCFG(rxq->reg_idx)); 329062fc35e6SJiawen Wu } while (--poll_ms && !(rxdctl & NGBE_RXCFG_ENA)); 329162fc35e6SJiawen Wu if (poll_ms == 0) 329262fc35e6SJiawen Wu PMD_INIT_LOG(ERR, "Could not enable Rx Queue %d", rx_queue_id); 329362fc35e6SJiawen Wu rte_wmb(); 329462fc35e6SJiawen Wu wr32(hw, NGBE_RXRP(rxq->reg_idx), 0); 329562fc35e6SJiawen Wu wr32(hw, NGBE_RXWP(rxq->reg_idx), rxq->nb_rx_desc - 1); 329662fc35e6SJiawen Wu dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED; 329762fc35e6SJiawen Wu 329862fc35e6SJiawen Wu return 0; 329962fc35e6SJiawen Wu } 330062fc35e6SJiawen Wu 330162fc35e6SJiawen Wu /* 330262fc35e6SJiawen Wu * Stop Receive Units for specified queue. 330362fc35e6SJiawen Wu */ 330462fc35e6SJiawen Wu int 330562fc35e6SJiawen Wu ngbe_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id) 330662fc35e6SJiawen Wu { 330762fc35e6SJiawen Wu struct ngbe_hw *hw = ngbe_dev_hw(dev); 330862fc35e6SJiawen Wu struct ngbe_adapter *adapter = ngbe_dev_adapter(dev); 330962fc35e6SJiawen Wu struct ngbe_rx_queue *rxq; 331062fc35e6SJiawen Wu uint32_t rxdctl; 331162fc35e6SJiawen Wu int poll_ms; 331262fc35e6SJiawen Wu 331362fc35e6SJiawen Wu PMD_INIT_FUNC_TRACE(); 331462fc35e6SJiawen Wu 331562fc35e6SJiawen Wu rxq = dev->data->rx_queues[rx_queue_id]; 331662fc35e6SJiawen Wu 331762fc35e6SJiawen Wu ngbe_dev_save_rx_queue(hw, rxq->reg_idx); 331862fc35e6SJiawen Wu wr32m(hw, NGBE_RXCFG(rxq->reg_idx), NGBE_RXCFG_ENA, 0); 331962fc35e6SJiawen Wu 332062fc35e6SJiawen Wu /* Wait until Rx Enable bit clear */ 332162fc35e6SJiawen Wu poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS; 332262fc35e6SJiawen Wu do { 332362fc35e6SJiawen Wu rte_delay_ms(1); 332462fc35e6SJiawen Wu rxdctl = rd32(hw, NGBE_RXCFG(rxq->reg_idx)); 332562fc35e6SJiawen Wu } while (--poll_ms && (rxdctl & NGBE_RXCFG_ENA)); 332662fc35e6SJiawen Wu if (poll_ms == 0) 332762fc35e6SJiawen Wu PMD_INIT_LOG(ERR, "Could not disable Rx Queue %d", rx_queue_id); 332862fc35e6SJiawen Wu 332962fc35e6SJiawen Wu rte_delay_us(RTE_NGBE_WAIT_100_US); 333062fc35e6SJiawen Wu ngbe_dev_store_rx_queue(hw, rxq->reg_idx); 333162fc35e6SJiawen Wu 333262fc35e6SJiawen Wu ngbe_rx_queue_release_mbufs(rxq); 333362fc35e6SJiawen Wu ngbe_reset_rx_queue(adapter, rxq); 333462fc35e6SJiawen Wu dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED; 333562fc35e6SJiawen Wu 333662fc35e6SJiawen Wu return 0; 333762fc35e6SJiawen Wu } 333862fc35e6SJiawen Wu 333962fc35e6SJiawen Wu /* 3340001c7823SJiawen Wu * Start Transmit Units for specified queue. 3341001c7823SJiawen Wu */ 3342001c7823SJiawen Wu int 3343001c7823SJiawen Wu ngbe_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id) 3344001c7823SJiawen Wu { 3345001c7823SJiawen Wu struct ngbe_hw *hw = ngbe_dev_hw(dev); 3346001c7823SJiawen Wu struct ngbe_tx_queue *txq; 3347001c7823SJiawen Wu uint32_t txdctl; 3348001c7823SJiawen Wu int poll_ms; 3349001c7823SJiawen Wu 3350001c7823SJiawen Wu PMD_INIT_FUNC_TRACE(); 3351001c7823SJiawen Wu 3352001c7823SJiawen Wu txq = dev->data->tx_queues[tx_queue_id]; 3353001c7823SJiawen Wu wr32m(hw, NGBE_TXCFG(txq->reg_idx), NGBE_TXCFG_ENA, NGBE_TXCFG_ENA); 3354001c7823SJiawen Wu 3355001c7823SJiawen Wu /* Wait until Tx Enable ready */ 3356001c7823SJiawen Wu poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS; 3357001c7823SJiawen Wu do { 3358001c7823SJiawen Wu rte_delay_ms(1); 3359001c7823SJiawen Wu txdctl = rd32(hw, NGBE_TXCFG(txq->reg_idx)); 3360001c7823SJiawen Wu } while (--poll_ms && !(txdctl & NGBE_TXCFG_ENA)); 3361001c7823SJiawen Wu if (poll_ms == 0) 3362001c7823SJiawen Wu PMD_INIT_LOG(ERR, "Could not enable Tx Queue %d", 3363001c7823SJiawen Wu tx_queue_id); 3364001c7823SJiawen Wu 3365001c7823SJiawen Wu rte_wmb(); 3366001c7823SJiawen Wu wr32(hw, NGBE_TXWP(txq->reg_idx), txq->tx_tail); 3367001c7823SJiawen Wu dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED; 3368001c7823SJiawen Wu 3369001c7823SJiawen Wu return 0; 3370001c7823SJiawen Wu } 3371001c7823SJiawen Wu 3372001c7823SJiawen Wu /* 3373001c7823SJiawen Wu * Stop Transmit Units for specified queue. 3374001c7823SJiawen Wu */ 3375001c7823SJiawen Wu int 3376001c7823SJiawen Wu ngbe_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id) 3377001c7823SJiawen Wu { 3378001c7823SJiawen Wu struct ngbe_hw *hw = ngbe_dev_hw(dev); 3379001c7823SJiawen Wu struct ngbe_tx_queue *txq; 3380001c7823SJiawen Wu uint32_t txdctl; 3381001c7823SJiawen Wu uint32_t txtdh, txtdt; 3382001c7823SJiawen Wu int poll_ms; 3383001c7823SJiawen Wu 3384001c7823SJiawen Wu PMD_INIT_FUNC_TRACE(); 3385001c7823SJiawen Wu 3386001c7823SJiawen Wu txq = dev->data->tx_queues[tx_queue_id]; 3387001c7823SJiawen Wu 3388001c7823SJiawen Wu /* Wait until Tx queue is empty */ 3389001c7823SJiawen Wu poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS; 3390001c7823SJiawen Wu do { 3391001c7823SJiawen Wu rte_delay_us(RTE_NGBE_WAIT_100_US); 3392001c7823SJiawen Wu txtdh = rd32(hw, NGBE_TXRP(txq->reg_idx)); 3393001c7823SJiawen Wu txtdt = rd32(hw, NGBE_TXWP(txq->reg_idx)); 3394001c7823SJiawen Wu } while (--poll_ms && (txtdh != txtdt)); 3395001c7823SJiawen Wu if (poll_ms == 0) 3396001c7823SJiawen Wu PMD_INIT_LOG(ERR, "Tx Queue %d is not empty when stopping.", 3397001c7823SJiawen Wu tx_queue_id); 3398001c7823SJiawen Wu 3399001c7823SJiawen Wu ngbe_dev_save_tx_queue(hw, txq->reg_idx); 3400001c7823SJiawen Wu wr32m(hw, NGBE_TXCFG(txq->reg_idx), NGBE_TXCFG_ENA, 0); 3401001c7823SJiawen Wu 3402001c7823SJiawen Wu /* Wait until Tx Enable bit clear */ 3403001c7823SJiawen Wu poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS; 3404001c7823SJiawen Wu do { 3405001c7823SJiawen Wu rte_delay_ms(1); 3406001c7823SJiawen Wu txdctl = rd32(hw, NGBE_TXCFG(txq->reg_idx)); 3407001c7823SJiawen Wu } while (--poll_ms && (txdctl & NGBE_TXCFG_ENA)); 3408001c7823SJiawen Wu if (poll_ms == 0) 3409001c7823SJiawen Wu PMD_INIT_LOG(ERR, "Could not disable Tx Queue %d", 3410001c7823SJiawen Wu tx_queue_id); 3411001c7823SJiawen Wu 3412001c7823SJiawen Wu rte_delay_us(RTE_NGBE_WAIT_100_US); 3413001c7823SJiawen Wu ngbe_dev_store_tx_queue(hw, txq->reg_idx); 3414001c7823SJiawen Wu 3415001c7823SJiawen Wu if (txq->ops != NULL) { 3416001c7823SJiawen Wu txq->ops->release_mbufs(txq); 3417001c7823SJiawen Wu txq->ops->reset(txq); 3418001c7823SJiawen Wu } 3419001c7823SJiawen Wu dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED; 3420001c7823SJiawen Wu 3421001c7823SJiawen Wu return 0; 3422001c7823SJiawen Wu } 3423eec3e736SJiawen Wu 3424eec3e736SJiawen Wu void 3425eec3e736SJiawen Wu ngbe_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, 3426eec3e736SJiawen Wu struct rte_eth_rxq_info *qinfo) 3427eec3e736SJiawen Wu { 3428eec3e736SJiawen Wu struct ngbe_rx_queue *rxq; 3429eec3e736SJiawen Wu 3430eec3e736SJiawen Wu rxq = dev->data->rx_queues[queue_id]; 3431eec3e736SJiawen Wu 3432eec3e736SJiawen Wu qinfo->mp = rxq->mb_pool; 3433eec3e736SJiawen Wu qinfo->scattered_rx = dev->data->scattered_rx; 3434eec3e736SJiawen Wu qinfo->nb_desc = rxq->nb_rx_desc; 3435eec3e736SJiawen Wu 3436eec3e736SJiawen Wu qinfo->conf.rx_free_thresh = rxq->rx_free_thresh; 3437eec3e736SJiawen Wu qinfo->conf.rx_drop_en = rxq->drop_en; 3438eec3e736SJiawen Wu qinfo->conf.rx_deferred_start = rxq->rx_deferred_start; 3439eec3e736SJiawen Wu qinfo->conf.offloads = rxq->offloads; 3440eec3e736SJiawen Wu } 3441eec3e736SJiawen Wu 3442eec3e736SJiawen Wu void 3443eec3e736SJiawen Wu ngbe_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, 3444eec3e736SJiawen Wu struct rte_eth_txq_info *qinfo) 3445eec3e736SJiawen Wu { 3446eec3e736SJiawen Wu struct ngbe_tx_queue *txq; 3447eec3e736SJiawen Wu 3448eec3e736SJiawen Wu txq = dev->data->tx_queues[queue_id]; 3449eec3e736SJiawen Wu 3450eec3e736SJiawen Wu qinfo->nb_desc = txq->nb_tx_desc; 3451eec3e736SJiawen Wu 3452eec3e736SJiawen Wu qinfo->conf.tx_thresh.pthresh = txq->pthresh; 3453eec3e736SJiawen Wu qinfo->conf.tx_thresh.hthresh = txq->hthresh; 3454eec3e736SJiawen Wu qinfo->conf.tx_thresh.wthresh = txq->wthresh; 3455eec3e736SJiawen Wu 3456eec3e736SJiawen Wu qinfo->conf.tx_free_thresh = txq->tx_free_thresh; 3457eec3e736SJiawen Wu qinfo->conf.offloads = txq->offloads; 3458eec3e736SJiawen Wu qinfo->conf.tx_deferred_start = txq->tx_deferred_start; 3459eec3e736SJiawen Wu } 3460e94c20c3SJiawen Wu 3461*711a06e8SZaiyu Wang /* 3462*711a06e8SZaiyu Wang * [VF] Initializes Receive Unit. 3463*711a06e8SZaiyu Wang */ 3464*711a06e8SZaiyu Wang int 3465*711a06e8SZaiyu Wang ngbevf_dev_rx_init(struct rte_eth_dev *dev) 3466*711a06e8SZaiyu Wang { 3467*711a06e8SZaiyu Wang struct ngbe_hw *hw; 3468*711a06e8SZaiyu Wang struct ngbe_rx_queue *rxq; 3469*711a06e8SZaiyu Wang struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; 3470*711a06e8SZaiyu Wang uint64_t bus_addr; 3471*711a06e8SZaiyu Wang uint32_t srrctl; 3472*711a06e8SZaiyu Wang uint16_t buf_size; 3473*711a06e8SZaiyu Wang uint16_t i; 3474*711a06e8SZaiyu Wang int ret; 3475*711a06e8SZaiyu Wang 3476*711a06e8SZaiyu Wang PMD_INIT_FUNC_TRACE(); 3477*711a06e8SZaiyu Wang hw = ngbe_dev_hw(dev); 3478*711a06e8SZaiyu Wang 3479*711a06e8SZaiyu Wang if (rte_is_power_of_2(dev->data->nb_rx_queues) == 0) { 3480*711a06e8SZaiyu Wang PMD_INIT_LOG(ERR, "The number of Rx queue invalid, " 3481*711a06e8SZaiyu Wang "it should be power of 2"); 3482*711a06e8SZaiyu Wang return -1; 3483*711a06e8SZaiyu Wang } 3484*711a06e8SZaiyu Wang 3485*711a06e8SZaiyu Wang if (dev->data->nb_rx_queues > hw->mac.max_rx_queues) { 3486*711a06e8SZaiyu Wang PMD_INIT_LOG(ERR, "The number of Rx queue invalid, " 3487*711a06e8SZaiyu Wang "it should be equal to or less than %d", 3488*711a06e8SZaiyu Wang hw->mac.max_rx_queues); 3489*711a06e8SZaiyu Wang return -1; 3490*711a06e8SZaiyu Wang } 3491*711a06e8SZaiyu Wang 3492*711a06e8SZaiyu Wang /* 3493*711a06e8SZaiyu Wang * When the VF driver issues a NGBE_VF_RESET request, the PF driver 3494*711a06e8SZaiyu Wang * disables the VF receipt of packets if the PF MTU is > 1500. 3495*711a06e8SZaiyu Wang * This is done to deal with limitations that imposes 3496*711a06e8SZaiyu Wang * the PF and all VFs to share the same MTU. 3497*711a06e8SZaiyu Wang * Then, the PF driver enables again the VF receipt of packet when 3498*711a06e8SZaiyu Wang * the VF driver issues a NGBE_VF_SET_LPE request. 3499*711a06e8SZaiyu Wang * In the meantime, the VF device cannot be used, even if the VF driver 3500*711a06e8SZaiyu Wang * and the Guest VM network stack are ready to accept packets with a 3501*711a06e8SZaiyu Wang * size up to the PF MTU. 3502*711a06e8SZaiyu Wang * As a work-around to this PF behaviour, force the call to 3503*711a06e8SZaiyu Wang * ngbevf_rlpml_set_vf even if jumbo frames are not used. This way, 3504*711a06e8SZaiyu Wang * VF packets received can work in all cases. 3505*711a06e8SZaiyu Wang */ 3506*711a06e8SZaiyu Wang if (ngbevf_rlpml_set_vf(hw, 3507*711a06e8SZaiyu Wang (uint16_t)dev->data->mtu + NGBE_ETH_OVERHEAD)) { 3508*711a06e8SZaiyu Wang PMD_INIT_LOG(ERR, "Set max packet length to %d failed.", 3509*711a06e8SZaiyu Wang dev->data->mtu + NGBE_ETH_OVERHEAD); 3510*711a06e8SZaiyu Wang 3511*711a06e8SZaiyu Wang return -EINVAL; 3512*711a06e8SZaiyu Wang } 3513*711a06e8SZaiyu Wang 3514*711a06e8SZaiyu Wang /* 3515*711a06e8SZaiyu Wang * Assume no header split and no VLAN strip support 3516*711a06e8SZaiyu Wang * on any Rx queue first . 3517*711a06e8SZaiyu Wang */ 3518*711a06e8SZaiyu Wang rxmode->offloads &= ~RTE_ETH_RX_OFFLOAD_VLAN_STRIP; 3519*711a06e8SZaiyu Wang /* Setup RX queues */ 3520*711a06e8SZaiyu Wang for (i = 0; i < dev->data->nb_rx_queues; i++) { 3521*711a06e8SZaiyu Wang rxq = dev->data->rx_queues[i]; 3522*711a06e8SZaiyu Wang 3523*711a06e8SZaiyu Wang /* Allocate buffers for descriptor rings */ 3524*711a06e8SZaiyu Wang ret = ngbe_alloc_rx_queue_mbufs(rxq); 3525*711a06e8SZaiyu Wang if (ret) 3526*711a06e8SZaiyu Wang return ret; 3527*711a06e8SZaiyu Wang 3528*711a06e8SZaiyu Wang /* Setup the Base and Length of the Rx Descriptor Rings */ 3529*711a06e8SZaiyu Wang bus_addr = rxq->rx_ring_phys_addr; 3530*711a06e8SZaiyu Wang 3531*711a06e8SZaiyu Wang wr32(hw, NGBE_RXBAL(i), 3532*711a06e8SZaiyu Wang (uint32_t)(bus_addr & BIT_MASK32)); 3533*711a06e8SZaiyu Wang wr32(hw, NGBE_RXBAH(i), 3534*711a06e8SZaiyu Wang (uint32_t)(bus_addr >> 32)); 3535*711a06e8SZaiyu Wang wr32(hw, NGBE_RXRP(i), 0); 3536*711a06e8SZaiyu Wang wr32(hw, NGBE_RXWP(i), 0); 3537*711a06e8SZaiyu Wang 3538*711a06e8SZaiyu Wang /* Configure the RXCFG register */ 3539*711a06e8SZaiyu Wang srrctl = NGBE_RXCFG_RNGLEN(rxq->nb_rx_desc); 3540*711a06e8SZaiyu Wang 3541*711a06e8SZaiyu Wang /* Set if packets are dropped when no descriptors available */ 3542*711a06e8SZaiyu Wang if (rxq->drop_en) 3543*711a06e8SZaiyu Wang srrctl |= NGBE_RXCFG_DROP; 3544*711a06e8SZaiyu Wang 3545*711a06e8SZaiyu Wang /* 3546*711a06e8SZaiyu Wang * Configure the RX buffer size in the PKTLEN field of 3547*711a06e8SZaiyu Wang * the RXCFG register of the queue. 3548*711a06e8SZaiyu Wang * The value is in 1 KB resolution. Valid values can be from 3549*711a06e8SZaiyu Wang * 1 KB to 16 KB. 3550*711a06e8SZaiyu Wang */ 3551*711a06e8SZaiyu Wang buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mb_pool) - 3552*711a06e8SZaiyu Wang RTE_PKTMBUF_HEADROOM); 3553*711a06e8SZaiyu Wang buf_size = ROUND_UP(buf_size, 1 << 10); 3554*711a06e8SZaiyu Wang srrctl |= NGBE_RXCFG_PKTLEN(buf_size); 3555*711a06e8SZaiyu Wang 3556*711a06e8SZaiyu Wang /* 3557*711a06e8SZaiyu Wang * VF modification to write virtual function RXCFG register 3558*711a06e8SZaiyu Wang */ 3559*711a06e8SZaiyu Wang wr32(hw, NGBE_RXCFG(i), srrctl); 3560*711a06e8SZaiyu Wang 3561*711a06e8SZaiyu Wang if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER || 3562*711a06e8SZaiyu Wang /* It adds dual VLAN length for supporting dual VLAN */ 3563*711a06e8SZaiyu Wang (dev->data->mtu + NGBE_ETH_OVERHEAD + 3564*711a06e8SZaiyu Wang 2 * RTE_VLAN_HLEN) > buf_size) { 3565*711a06e8SZaiyu Wang if (!dev->data->scattered_rx) 3566*711a06e8SZaiyu Wang PMD_INIT_LOG(DEBUG, "forcing scatter mode"); 3567*711a06e8SZaiyu Wang dev->data->scattered_rx = 1; 3568*711a06e8SZaiyu Wang } 3569*711a06e8SZaiyu Wang 3570*711a06e8SZaiyu Wang if (rxq->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) 3571*711a06e8SZaiyu Wang rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP; 3572*711a06e8SZaiyu Wang } 3573*711a06e8SZaiyu Wang 3574*711a06e8SZaiyu Wang ngbe_set_rx_function(dev); 3575*711a06e8SZaiyu Wang 3576*711a06e8SZaiyu Wang return 0; 3577*711a06e8SZaiyu Wang } 3578*711a06e8SZaiyu Wang 3579*711a06e8SZaiyu Wang /* 3580*711a06e8SZaiyu Wang * [VF] Initializes Transmit Unit. 3581*711a06e8SZaiyu Wang */ 3582*711a06e8SZaiyu Wang void 3583*711a06e8SZaiyu Wang ngbevf_dev_tx_init(struct rte_eth_dev *dev) 3584*711a06e8SZaiyu Wang { 3585*711a06e8SZaiyu Wang struct ngbe_hw *hw; 3586*711a06e8SZaiyu Wang struct ngbe_tx_queue *txq; 3587*711a06e8SZaiyu Wang uint64_t bus_addr; 3588*711a06e8SZaiyu Wang uint16_t i; 3589*711a06e8SZaiyu Wang 3590*711a06e8SZaiyu Wang PMD_INIT_FUNC_TRACE(); 3591*711a06e8SZaiyu Wang hw = ngbe_dev_hw(dev); 3592*711a06e8SZaiyu Wang 3593*711a06e8SZaiyu Wang /* Setup the Base and Length of the Tx Descriptor Rings */ 3594*711a06e8SZaiyu Wang for (i = 0; i < dev->data->nb_tx_queues; i++) { 3595*711a06e8SZaiyu Wang txq = dev->data->tx_queues[i]; 3596*711a06e8SZaiyu Wang bus_addr = txq->tx_ring_phys_addr; 3597*711a06e8SZaiyu Wang wr32(hw, NGBE_TXBAL(i), 3598*711a06e8SZaiyu Wang (uint32_t)(bus_addr & BIT_MASK32)); 3599*711a06e8SZaiyu Wang wr32(hw, NGBE_TXBAH(i), 3600*711a06e8SZaiyu Wang (uint32_t)(bus_addr >> 32)); 3601*711a06e8SZaiyu Wang wr32m(hw, NGBE_TXCFG(i), NGBE_TXCFG_BUFLEN_MASK, 3602*711a06e8SZaiyu Wang NGBE_TXCFG_BUFLEN(txq->nb_tx_desc)); 3603*711a06e8SZaiyu Wang /* Setup the HW Tx Head and TX Tail descriptor pointers */ 3604*711a06e8SZaiyu Wang wr32(hw, NGBE_TXRP(i), 0); 3605*711a06e8SZaiyu Wang wr32(hw, NGBE_TXWP(i), 0); 3606*711a06e8SZaiyu Wang } 3607*711a06e8SZaiyu Wang } 3608*711a06e8SZaiyu Wang 3609*711a06e8SZaiyu Wang /* 3610*711a06e8SZaiyu Wang * [VF] Start Transmit and Receive Units. 3611*711a06e8SZaiyu Wang */ 3612*711a06e8SZaiyu Wang void 3613*711a06e8SZaiyu Wang ngbevf_dev_rxtx_start(struct rte_eth_dev *dev) 3614*711a06e8SZaiyu Wang { 3615*711a06e8SZaiyu Wang struct ngbe_hw *hw; 3616*711a06e8SZaiyu Wang struct ngbe_tx_queue *txq; 3617*711a06e8SZaiyu Wang struct ngbe_rx_queue *rxq; 3618*711a06e8SZaiyu Wang uint32_t txdctl; 3619*711a06e8SZaiyu Wang uint32_t rxdctl; 3620*711a06e8SZaiyu Wang uint16_t i; 3621*711a06e8SZaiyu Wang int poll_ms; 3622*711a06e8SZaiyu Wang 3623*711a06e8SZaiyu Wang PMD_INIT_FUNC_TRACE(); 3624*711a06e8SZaiyu Wang hw = ngbe_dev_hw(dev); 3625*711a06e8SZaiyu Wang 3626*711a06e8SZaiyu Wang for (i = 0; i < dev->data->nb_tx_queues; i++) { 3627*711a06e8SZaiyu Wang txq = dev->data->tx_queues[i]; 3628*711a06e8SZaiyu Wang /* Setup Transmit Threshold Registers */ 3629*711a06e8SZaiyu Wang wr32m(hw, NGBE_TXCFG(txq->reg_idx), 3630*711a06e8SZaiyu Wang NGBE_TXCFG_HTHRESH_MASK | 3631*711a06e8SZaiyu Wang NGBE_TXCFG_WTHRESH_MASK, 3632*711a06e8SZaiyu Wang NGBE_TXCFG_HTHRESH(txq->hthresh) | 3633*711a06e8SZaiyu Wang NGBE_TXCFG_WTHRESH(txq->wthresh)); 3634*711a06e8SZaiyu Wang } 3635*711a06e8SZaiyu Wang 3636*711a06e8SZaiyu Wang for (i = 0; i < dev->data->nb_tx_queues; i++) { 3637*711a06e8SZaiyu Wang wr32m(hw, NGBE_TXCFG(i), NGBE_TXCFG_ENA, NGBE_TXCFG_ENA); 3638*711a06e8SZaiyu Wang 3639*711a06e8SZaiyu Wang poll_ms = 10; 3640*711a06e8SZaiyu Wang /* Wait until TX Enable ready */ 3641*711a06e8SZaiyu Wang do { 3642*711a06e8SZaiyu Wang rte_delay_ms(1); 3643*711a06e8SZaiyu Wang txdctl = rd32(hw, NGBE_TXCFG(i)); 3644*711a06e8SZaiyu Wang } while (--poll_ms && !(txdctl & NGBE_TXCFG_ENA)); 3645*711a06e8SZaiyu Wang if (!poll_ms) 3646*711a06e8SZaiyu Wang PMD_INIT_LOG(ERR, "Could not enable Tx Queue %d", i); 3647*711a06e8SZaiyu Wang else 3648*711a06e8SZaiyu Wang dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 3649*711a06e8SZaiyu Wang } 3650*711a06e8SZaiyu Wang for (i = 0; i < dev->data->nb_rx_queues; i++) { 3651*711a06e8SZaiyu Wang rxq = dev->data->rx_queues[i]; 3652*711a06e8SZaiyu Wang 3653*711a06e8SZaiyu Wang wr32m(hw, NGBE_RXCFG(i), NGBE_RXCFG_ENA, NGBE_RXCFG_ENA); 3654*711a06e8SZaiyu Wang 3655*711a06e8SZaiyu Wang /* Wait until RX Enable ready */ 3656*711a06e8SZaiyu Wang poll_ms = 10; 3657*711a06e8SZaiyu Wang do { 3658*711a06e8SZaiyu Wang rte_delay_ms(1); 3659*711a06e8SZaiyu Wang rxdctl = rd32(hw, NGBE_RXCFG(i)); 3660*711a06e8SZaiyu Wang } while (--poll_ms && !(rxdctl & NGBE_RXCFG_ENA)); 3661*711a06e8SZaiyu Wang if (!poll_ms) 3662*711a06e8SZaiyu Wang PMD_INIT_LOG(ERR, "Could not enable Rx Queue %d", i); 3663*711a06e8SZaiyu Wang else 3664*711a06e8SZaiyu Wang dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 3665*711a06e8SZaiyu Wang rte_wmb(); 3666*711a06e8SZaiyu Wang wr32(hw, NGBE_RXWP(i), rxq->nb_rx_desc - 1); 3667*711a06e8SZaiyu Wang } 3668*711a06e8SZaiyu Wang } 3669*711a06e8SZaiyu Wang 3670e94c20c3SJiawen Wu /* Stubs needed for linkage when RTE_ARCH_PPC_64, RTE_ARCH_RISCV or 3671e94c20c3SJiawen Wu * RTE_ARCH_LOONGARCH is set. 3672e94c20c3SJiawen Wu */ 3673e94c20c3SJiawen Wu #if defined(RTE_ARCH_PPC_64) || defined(RTE_ARCH_RISCV) || \ 3674e94c20c3SJiawen Wu defined(RTE_ARCH_LOONGARCH) 3675e94c20c3SJiawen Wu int 3676e94c20c3SJiawen Wu ngbe_rx_vec_dev_conf_condition_check(__rte_unused struct rte_eth_dev *dev) 3677e94c20c3SJiawen Wu { 3678e94c20c3SJiawen Wu return -1; 3679e94c20c3SJiawen Wu } 3680e94c20c3SJiawen Wu 3681e94c20c3SJiawen Wu uint16_t 3682e94c20c3SJiawen Wu ngbe_recv_pkts_vec(__rte_unused void *rx_queue, 3683e94c20c3SJiawen Wu __rte_unused struct rte_mbuf **rx_pkts, 3684e94c20c3SJiawen Wu __rte_unused uint16_t nb_pkts) 3685e94c20c3SJiawen Wu { 3686e94c20c3SJiawen Wu return 0; 3687e94c20c3SJiawen Wu } 3688e94c20c3SJiawen Wu 3689e94c20c3SJiawen Wu uint16_t 3690e94c20c3SJiawen Wu ngbe_recv_scattered_pkts_vec(__rte_unused void *rx_queue, 3691e94c20c3SJiawen Wu __rte_unused struct rte_mbuf **rx_pkts, 3692e94c20c3SJiawen Wu __rte_unused uint16_t nb_pkts) 3693e94c20c3SJiawen Wu { 3694e94c20c3SJiawen Wu return 0; 3695e94c20c3SJiawen Wu } 3696e94c20c3SJiawen Wu 3697e94c20c3SJiawen Wu int 3698e94c20c3SJiawen Wu ngbe_rxq_vec_setup(__rte_unused struct ngbe_rx_queue *rxq) 3699e94c20c3SJiawen Wu { 3700e94c20c3SJiawen Wu return -1; 3701e94c20c3SJiawen Wu } 3702e94c20c3SJiawen Wu 3703e94c20c3SJiawen Wu uint16_t 3704e94c20c3SJiawen Wu ngbe_xmit_fixed_burst_vec(__rte_unused void *tx_queue, 3705e94c20c3SJiawen Wu __rte_unused struct rte_mbuf **tx_pkts, 3706e94c20c3SJiawen Wu __rte_unused uint16_t nb_pkts) 3707e94c20c3SJiawen Wu { 3708e94c20c3SJiawen Wu return 0; 3709e94c20c3SJiawen Wu } 3710e94c20c3SJiawen Wu 3711e94c20c3SJiawen Wu int 3712e94c20c3SJiawen Wu ngbe_txq_vec_setup(__rte_unused struct ngbe_tx_queue *txq) 3713e94c20c3SJiawen Wu { 3714e94c20c3SJiawen Wu return -1; 3715e94c20c3SJiawen Wu } 3716e94c20c3SJiawen Wu 3717e94c20c3SJiawen Wu void 3718e94c20c3SJiawen Wu ngbe_rx_queue_release_mbufs_vec(__rte_unused struct ngbe_rx_queue *rxq) 3719e94c20c3SJiawen Wu { 3720e94c20c3SJiawen Wu } 3721e94c20c3SJiawen Wu #endif 3722