X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_pmd_ixgbe%2Fixgbe_rxtx.c;h=303144b451e8c26a411b1bb0eb0b77dbd301d238;hb=88fccb7a05c64cbb10f2c82d61fafc68f2f2150d;hp=9b7ba2c778aea2e9eb15e150469773ecc508426b;hpb=dec6f7a6450fda99673c48794491e434931e6909;p=dpdk.git diff --git a/lib/librte_pmd_ixgbe/ixgbe_rxtx.c b/lib/librte_pmd_ixgbe/ixgbe_rxtx.c index 9b7ba2c778..303144b451 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_rxtx.c +++ b/lib/librte_pmd_ixgbe/ixgbe_rxtx.c @@ -1,40 +1,38 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: * - * * Redistributions of source code must retain the above copyright + * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * */ #include -#include #include #include #include @@ -78,13 +76,11 @@ #include "ixgbe/ixgbe_vf.h" #include "ixgbe_ethdev.h" #include "ixgbe/ixgbe_dcb.h" +#include "ixgbe/ixgbe_common.h" -#define RTE_PMD_IXGBE_TX_MAX_BURST 32 +#include "ixgbe_rxtx.h" -#ifdef RTE_LIBRTE_IXGBE_RX_ALLOW_BULK_ALLOC -#define RTE_PMD_IXGBE_RX_MAX_BURST 32 -#endif static inline struct rte_mbuf * rte_rxmbuf_alloc(struct rte_mempool *mp) @@ -96,114 +92,6 @@ rte_rxmbuf_alloc(struct rte_mempool *mp) return (m); } -#define RTE_MBUF_DATA_DMA_ADDR(mb) \ - (uint64_t) ((mb)->buf_physaddr + (uint64_t)((char *)((mb)->pkt.data) - \ - (char *)(mb)->buf_addr)) - -#define RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mb) \ - (uint64_t) ((mb)->buf_physaddr + RTE_PKTMBUF_HEADROOM) - -/** - * Structure associated with each descriptor of the RX ring of a RX queue. - */ -struct igb_rx_entry { - struct rte_mbuf *mbuf; /**< mbuf associated with RX descriptor. */ -}; - -/** - * Structure associated with each descriptor of the TX ring of a TX queue. - */ -struct igb_tx_entry { - struct rte_mbuf *mbuf; /**< mbuf associated with TX desc, if any. */ - uint16_t next_id; /**< Index of next descriptor in ring. */ - uint16_t last_id; /**< Index of last scattered descriptor. */ -}; - -/** - * Structure associated with each RX queue. - */ -struct igb_rx_queue { - struct rte_mempool *mb_pool; /**< mbuf pool to populate RX ring. */ - volatile union ixgbe_adv_rx_desc *rx_ring; /**< RX ring virtual address. */ - uint64_t rx_ring_phys_addr; /**< RX ring DMA address. */ - volatile uint32_t *rdt_reg_addr; /**< RDT register address. */ - volatile uint32_t *rdh_reg_addr; /**< RDH register address. */ - struct igb_rx_entry *sw_ring; /**< address of RX software ring. */ - struct rte_mbuf *pkt_first_seg; /**< First segment of current packet. */ - struct rte_mbuf *pkt_last_seg; /**< Last segment of current packet. */ - uint16_t nb_rx_desc; /**< number of RX descriptors. */ - uint16_t rx_tail; /**< current value of RDT register. */ - uint16_t nb_rx_hold; /**< number of held free RX desc. */ -#ifdef RTE_LIBRTE_IXGBE_RX_ALLOW_BULK_ALLOC - uint16_t rx_nb_avail; /**< nr of staged pkts ready to ret to app */ - uint16_t rx_next_avail; /**< idx of next staged pkt to ret to app */ - uint16_t rx_free_trigger; /**< triggers rx buffer allocation */ -#endif - uint16_t rx_free_thresh; /**< max free RX desc to hold. */ - uint16_t queue_id; /**< RX queue index. */ - uint8_t port_id; /**< Device port identifier. */ - uint8_t crc_len; /**< 0 if CRC stripped, 4 otherwise. */ - uint8_t drop_en; /**< If not 0, set SRRCTL.Drop_En. */ -#ifdef RTE_LIBRTE_IXGBE_RX_ALLOW_BULK_ALLOC - /** need to alloc dummy mbuf, for wraparound when scanning hw ring */ - struct rte_mbuf fake_mbuf; - /** hold packets to return to application */ - struct rte_mbuf *rx_stage[RTE_PMD_IXGBE_RX_MAX_BURST*2]; -#endif -}; - -/** - * IXGBE CTX Constants - */ -enum ixgbe_advctx_num { - IXGBE_CTX_0 = 0, /**< CTX0 */ - IXGBE_CTX_1 = 1, /**< CTX1 */ - IXGBE_CTX_NUM = 2, /**< CTX NUMBER */ -}; - -/** - * Structure to check if new context need be built - */ - -struct ixgbe_advctx_info { - uint16_t flags; /**< ol_flags for context build. */ - uint32_t cmp_mask; /**< compare mask for vlan_macip_lens */ - union rte_vlan_macip vlan_macip_lens; /**< vlan, mac ip length. */ -}; - -/** - * Structure associated with each TX queue. - */ -struct igb_tx_queue { - /** TX ring virtual address. */ - volatile union ixgbe_adv_tx_desc *tx_ring; - uint64_t tx_ring_phys_addr; /**< TX ring DMA address. */ - struct igb_tx_entry *sw_ring; /**< virtual address of SW ring. */ - volatile uint32_t *tdt_reg_addr; /**< Address of TDT register. */ - uint16_t nb_tx_desc; /**< number of TX descriptors. */ - uint16_t tx_tail; /**< current value of TDT reg. */ - uint16_t tx_free_thresh;/**< minimum TX before freeing. */ - /** Number of TX descriptors to use before RS bit is set. */ - uint16_t tx_rs_thresh; - /** Number of TX descriptors used since RS bit was set. */ - uint16_t nb_tx_used; - /** Index to last TX descriptor to have been cleaned. */ - uint16_t last_desc_cleaned; - /** Total number of TX descriptors ready to be allocated. */ - uint16_t nb_tx_free; - uint16_t tx_next_dd; /**< next desc to scan for DD bit */ - uint16_t tx_next_rs; /**< next desc to set RS bit */ - uint16_t queue_id; /**< TX queue index. */ - uint8_t port_id; /**< Device port identifier. */ - uint8_t pthresh; /**< Prefetch threshold register. */ - uint8_t hthresh; /**< Host threshold register. */ - uint8_t wthresh; /**< Write-back threshold reg. */ - uint32_t txq_flags; /**< Holds flags for this TXq */ - uint32_t ctx_curr; /**< Hardware context states. */ - /** Hardware context0 history. */ - struct ixgbe_advctx_info ctx_cache[IXGBE_CTX_NUM]; -}; - #if 1 #define RTE_PMD_USE_PREFETCH @@ -218,32 +106,12 @@ struct igb_tx_queue { #define rte_ixgbe_prefetch(p) do {} while(0) #endif -#ifdef RTE_PMD_PACKET_PREFETCH -#define rte_packet_prefetch(p) rte_prefetch1(p) -#else -#define rte_packet_prefetch(p) do {} while(0) -#endif - /********************************************************************* * * TX functions * **********************************************************************/ -/* - * The "simple" TX queue functions require that the following - * flags are set when the TX queue is configured: - * - ETH_TXQ_FLAGS_NOMULTSEGS - * - ETH_TXQ_FLAGS_NOVLANOFFL - * - ETH_TXQ_FLAGS_NOXSUMSCTP - * - ETH_TXQ_FLAGS_NOXSUMUDP - * - ETH_TXQ_FLAGS_NOXSUMTCP - * and that the RS bit threshold (tx_rs_thresh) is at least equal to - * RTE_PMD_IXGBE_TX_MAX_BURST. - */ -#define IXGBE_SIMPLE_FLAGS ((uint32_t)ETH_TXQ_FLAGS_NOMULTSEGS | \ - ETH_TXQ_FLAGS_NOOFFLOADS) - /* * Check for descriptors with their DD bit set and free mbufs. * Return the total number of buffers freed. @@ -292,19 +160,6 @@ ixgbe_tx_free_bufs(struct igb_tx_queue *txq) return txq->tx_rs_thresh; } -/* - * Populate descriptors with the following info: - * 1.) buffer_addr = phys_addr + headroom - * 2.) cmd_type_len = DCMD_DTYP_FLAGS | pkt_len - * 3.) olinfo_status = pkt_len << PAYLEN_SHIFT - */ - -/* Defines for Tx descriptor */ -#define DCMD_DTYP_FLAGS (IXGBE_ADVTXD_DTYP_DATA |\ - IXGBE_ADVTXD_DCMD_IFCS |\ - IXGBE_ADVTXD_DCMD_DEXT |\ - IXGBE_ADVTXD_DCMD_EOP) - /* Populate 4 descriptors with data from 4 mbufs */ static inline void tx4(volatile union ixgbe_adv_tx_desc *txdp, struct rte_mbuf **pkts) @@ -1062,12 +917,11 @@ ixgbe_rx_scan_hw_ring(struct igb_rx_queue *rxq) for (j = LOOK_AHEAD-1; j >= 0; --j) s[j] = rxdp[j].wb.upper.status_error; - /* Clear everything but the status bits (LSB) */ + /* Compute how many status bits were set */ + nb_dd = 0; for (j = 0; j < LOOK_AHEAD; ++j) - s[j] &= IXGBE_RXDADV_STAT_DD; + nb_dd += s[j] & IXGBE_RXDADV_STAT_DD; - /* Compute how many status bits were set */ - nb_dd = s[0]+s[1]+s[2]+s[3]+s[4]+s[5]+s[6]+s[7]; nb_rx += nb_dd; /* Translate descriptor info to mbuf format */ @@ -1757,8 +1611,13 @@ ring_dma_zone_reserve(struct rte_eth_dev *dev, const char *ring_name, if (mz) return mz; +#ifdef RTE_LIBRTE_XEN_DOM0 + return rte_memzone_reserve_bounded(z_name, ring_size, + socket_id, 0, IXGBE_ALIGN, RTE_PGSIZE_2M); +#else return rte_memzone_reserve_aligned(z_name, ring_size, - socket_id, 0, IXGBE_ALIGN); + socket_id, 0, IXGBE_ALIGN); +#endif } static void @@ -1777,11 +1636,19 @@ ixgbe_tx_queue_release_mbufs(struct igb_tx_queue *txq) } static void -ixgbe_tx_queue_release(struct igb_tx_queue *txq) +ixgbe_tx_free_swring(struct igb_tx_queue *txq) { - if (txq != NULL) { - ixgbe_tx_queue_release_mbufs(txq); + if (txq != NULL && + txq->sw_ring != NULL) rte_free(txq->sw_ring); +} + +static void +ixgbe_tx_queue_release(struct igb_tx_queue *txq) +{ + if (txq != NULL && txq->ops != NULL) { + txq->ops->release_mbufs(txq); + txq->ops->free_swring(txq); rte_free(txq); } } @@ -1796,12 +1663,14 @@ ixgbe_dev_tx_queue_release(void *txq) static void ixgbe_reset_tx_queue(struct igb_tx_queue *txq) { + static const union ixgbe_adv_tx_desc zeroed_desc = { .read = { + .buffer_addr = 0}}; struct igb_tx_entry *txe = txq->sw_ring; uint16_t prev, i; /* Zero out HW ring memory */ - for (i = 0; i < sizeof(union ixgbe_adv_tx_desc) * txq->nb_tx_desc; i++) { - ((volatile char *)txq->tx_ring)[i] = 0; + for (i = 0; i < txq->nb_tx_desc; i++) { + txq->tx_ring[i] = zeroed_desc; } /* Initialize SW ring entries */ @@ -1831,6 +1700,12 @@ ixgbe_reset_tx_queue(struct igb_tx_queue *txq) IXGBE_CTX_NUM * sizeof(struct ixgbe_advctx_info)); } +static struct ixgbe_txq_ops def_txq_ops = { + .release_mbufs = ixgbe_tx_queue_release_mbufs, + .free_swring = ixgbe_tx_free_swring, + .reset = ixgbe_reset_tx_queue, +}; + int ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, @@ -1956,8 +1831,11 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, txq->hthresh = tx_conf->tx_thresh.hthresh; txq->wthresh = tx_conf->tx_thresh.wthresh; txq->queue_id = queue_idx; + txq->reg_idx = (uint16_t)((RTE_ETH_DEV_SRIOV(dev).active == 0) ? + queue_idx : RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx + queue_idx); txq->port_id = dev->data->port_id; txq->txq_flags = tx_conf->txq_flags; + txq->ops = &def_txq_ops; /* * Modification to set VFTDT for virtual function if vf is detected @@ -1965,15 +1843,18 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, if (hw->mac.type == ixgbe_mac_82599_vf) txq->tdt_reg_addr = IXGBE_PCI_REG_ADDR(hw, IXGBE_VFTDT(queue_idx)); else - txq->tdt_reg_addr = IXGBE_PCI_REG_ADDR(hw, IXGBE_TDT(queue_idx)); - + txq->tdt_reg_addr = IXGBE_PCI_REG_ADDR(hw, IXGBE_TDT(txq->reg_idx)); +#ifndef RTE_LIBRTE_XEN_DOM0 txq->tx_ring_phys_addr = (uint64_t) tz->phys_addr; +#else + txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr); +#endif txq->tx_ring = (union ixgbe_adv_tx_desc *) tz->addr; /* Allocate software ring */ txq->sw_ring = rte_zmalloc_socket("txq->sw_ring", - sizeof(struct igb_tx_entry) * nb_desc, - CACHE_LINE_SIZE, socket_id); + sizeof(struct igb_tx_entry) * nb_desc, + CACHE_LINE_SIZE, socket_id); if (txq->sw_ring == NULL) { ixgbe_tx_queue_release(txq); return (-ENOMEM); @@ -1981,15 +1862,19 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%"PRIx64"\n", txq->sw_ring, txq->tx_ring, txq->tx_ring_phys_addr); - ixgbe_reset_tx_queue(txq); - - dev->data->tx_queues[queue_idx] = txq; - /* Use a simple Tx queue (no offloads, no multi segs) if possible */ if (((txq->txq_flags & IXGBE_SIMPLE_FLAGS) == IXGBE_SIMPLE_FLAGS) && (txq->tx_rs_thresh >= RTE_PMD_IXGBE_TX_MAX_BURST)) { PMD_INIT_LOG(INFO, "Using simple tx code path\n"); - dev->tx_pkt_burst = ixgbe_xmit_pkts_simple; +#ifdef RTE_IXGBE_INC_VECTOR + if (txq->tx_rs_thresh <= RTE_IXGBE_TX_MAX_FREE_BUF_SZ && + ixgbe_txq_vec_setup(txq, socket_id) == 0) { + PMD_INIT_LOG(INFO, "Vector tx enabled.\n"); + dev->tx_pkt_burst = ixgbe_xmit_pkts_vec; + } + else +#endif + dev->tx_pkt_burst = ixgbe_xmit_pkts_simple; } else { PMD_INIT_LOG(INFO, "Using full-featured tx code path\n"); PMD_INIT_LOG(INFO, " - txq_flags = %lx [IXGBE_SIMPLE_FLAGS=%lx]\n", (long unsigned)txq->txq_flags, (long unsigned)IXGBE_SIMPLE_FLAGS); @@ -1997,6 +1882,11 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, dev->tx_pkt_burst = ixgbe_xmit_pkts; } + txq->ops->reset(txq); + + dev->data->tx_queues[queue_idx] = txq; + + return (0); } @@ -2088,6 +1978,8 @@ check_rx_burst_bulk_alloc_preconditions(__rte_unused struct igb_rx_queue *rxq) static void ixgbe_reset_rx_queue(struct igb_rx_queue *rxq) { + static const union ixgbe_adv_rx_desc zeroed_desc = { .read = { + .pkt_addr = 0}}; unsigned i; uint16_t len; @@ -2115,8 +2007,8 @@ ixgbe_reset_rx_queue(struct igb_rx_queue *rxq) * the H/W ring so look-ahead logic in Rx Burst bulk alloc function * reads extra memory as zeros. */ - for (i = 0; i < len * sizeof(union ixgbe_adv_rx_desc); i++) { - ((volatile char *)rxq->rx_ring)[i] = 0; + for (i = 0; i < len; i++) { + rxq->rx_ring[i] = zeroed_desc; } #ifdef RTE_LIBRTE_IXGBE_RX_ALLOW_BULK_ALLOC @@ -2180,6 +2072,8 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev, rxq->nb_rx_desc = nb_desc; rxq->rx_free_thresh = rx_conf->rx_free_thresh; rxq->queue_id = queue_idx; + rxq->reg_idx = (uint16_t)((RTE_ETH_DEV_SRIOV(dev).active == 0) ? + queue_idx : RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx + queue_idx); rxq->port_id = dev->data->port_id; rxq->crc_len = (uint8_t) ((dev->data->dev_conf.rxmode.hw_strip_crc) ? 0 : ETHER_CRC_LEN); @@ -2191,21 +2085,37 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev, * resizing in later calls to the queue setup function. */ rz = ring_dma_zone_reserve(dev, "rx_ring", queue_idx, - IXGBE_MAX_RING_DESC * sizeof(union ixgbe_adv_rx_desc), - socket_id); + RX_RING_SZ, socket_id); if (rz == NULL) { ixgbe_rx_queue_release(rxq); return (-ENOMEM); } + /* - * Modified to setup VFRDT for Virtual Function + * Zero init all the descriptors in the ring. */ - if (hw->mac.type == ixgbe_mac_82599_vf) - rxq->rdt_reg_addr = IXGBE_PCI_REG_ADDR(hw, IXGBE_VFRDT(queue_idx)); - else - rxq->rdt_reg_addr = IXGBE_PCI_REG_ADDR(hw, IXGBE_RDT(queue_idx)); + memset (rz->addr, 0, RX_RING_SZ); + /* + * Modified to setup VFRDT for Virtual Function + */ + if (hw->mac.type == ixgbe_mac_82599_vf) { + rxq->rdt_reg_addr = + IXGBE_PCI_REG_ADDR(hw, IXGBE_VFRDT(queue_idx)); + rxq->rdh_reg_addr = + IXGBE_PCI_REG_ADDR(hw, IXGBE_VFRDH(queue_idx)); + } + else { + rxq->rdt_reg_addr = + IXGBE_PCI_REG_ADDR(hw, IXGBE_RDT(rxq->reg_idx)); + rxq->rdh_reg_addr = + IXGBE_PCI_REG_ADDR(hw, IXGBE_RDH(rxq->reg_idx)); + } +#ifndef RTE_LIBRTE_XEN_DOM0 rxq->rx_ring_phys_addr = (uint64_t) rz->phys_addr; +#else + rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr); +#endif rxq->rx_ring = (union ixgbe_adv_rx_desc *) rz->addr; /* @@ -2229,7 +2139,7 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev, rxq->sw_ring, rxq->rx_ring, rxq->rx_ring_phys_addr); /* - * Certain constaints must be met in order to use the bulk buffer + * Certain constraints must be met in order to use the bulk buffer * allocation Rx burst function. */ use_def_burst_func = check_rx_burst_bulk_alloc_preconditions(rxq); @@ -2242,6 +2152,13 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev, "used on port=%d, queue=%d.\n", rxq->port_id, rxq->queue_id); dev->rx_pkt_burst = ixgbe_recv_pkts_bulk_alloc; +#ifdef RTE_IXGBE_INC_VECTOR + if (!ixgbe_rx_vec_condition_check(dev)) { + PMD_INIT_LOG(INFO, "Vector rx enabled.\n"); + ixgbe_rxq_vec_setup(rxq, socket_id); + dev->rx_pkt_burst = ixgbe_recv_pkts_vec; + } +#endif #endif } else { PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions " @@ -2257,29 +2174,49 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev, return 0; } -uint32_t ixgbe_dev_rx_queue_count(struct rte_eth_dev *dev, - uint16_t rx_queue_id) +uint32_t +ixgbe_dev_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id) { +#define IXGBE_RXQ_SCAN_INTERVAL 4 + volatile union ixgbe_adv_rx_desc *rxdp; struct igb_rx_queue *rxq; - uint32_t nb_pkts_available; - uint32_t rx_rdh; - uint32_t rx_id; + uint32_t desc = 0; if (rx_queue_id >= dev->data->nb_rx_queues) { - PMD_RX_LOG(DEBUG,"Invalid RX queue_id=%d\n", rx_queue_id); - return 0; + PMD_RX_LOG(ERR, "Invalid RX queue id=%d\n", rx_queue_id); + return 0; } rxq = dev->data->rx_queues[rx_queue_id]; - rx_id = (uint16_t)((rxq->rx_tail == 0) ? - (rxq->nb_rx_desc - 1) : (rxq->rx_tail - 1)); - rx_rdh = IXGBE_PCI_REG(rxq->rdh_reg_addr); - if (rx_rdh > rx_id) - nb_pkts_available = rx_rdh - rx_id; - else - nb_pkts_available = rx_rdh - rx_id + rxq->nb_rx_desc; - - return (nb_pkts_available); + rxdp = &(rxq->rx_ring[rxq->rx_tail]); + + while ((desc < rxq->nb_rx_desc) && + (rxdp->wb.upper.status_error & IXGBE_RXDADV_STAT_DD)) { + desc += IXGBE_RXQ_SCAN_INTERVAL; + rxdp += IXGBE_RXQ_SCAN_INTERVAL; + if (rxq->rx_tail + desc >= rxq->nb_rx_desc) + rxdp = &(rxq->rx_ring[rxq->rx_tail + + desc - rxq->nb_rx_desc]); + } + + return desc; +} + +int +ixgbe_dev_rx_descriptor_done(void *rx_queue, uint16_t offset) +{ + volatile union ixgbe_adv_rx_desc *rxdp; + struct igb_rx_queue *rxq = rx_queue; + uint32_t desc; + + if (unlikely(offset >= rxq->nb_rx_desc)) + return 0; + desc = rxq->rx_tail + offset; + if (desc >= rxq->nb_rx_desc) + desc -= rxq->nb_rx_desc; + + rxdp = &rxq->rx_ring[desc]; + return !!(rxdp->wb.upper.status_error & IXGBE_RXDADV_STAT_DD); } void @@ -2292,8 +2229,8 @@ ixgbe_dev_clear_queues(struct rte_eth_dev *dev) for (i = 0; i < dev->data->nb_tx_queues; i++) { struct igb_tx_queue *txq = dev->data->tx_queues[i]; if (txq != NULL) { - ixgbe_tx_queue_release_mbufs(txq); - ixgbe_reset_tx_queue(txq); + txq->ops->release_mbufs(txq); + txq->ops->reset(txq); } } @@ -2477,6 +2414,7 @@ ixgbe_vmdq_dcb_configure(struct rte_eth_dev *dev) } else { vt_ctl |= IXGBE_VT_CTL_DIS_DEFPL; } + IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vt_ctl); /* RTRUP2TC: mapping user priorities to traffic classes (TCs) */ @@ -2832,7 +2770,7 @@ ixgbe_dcb_hw_configure(struct rte_eth_dev *dev, IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); switch(dev->data->dev_conf.rxmode.mq_mode){ - case ETH_VMDQ_DCB: + case ETH_MQ_RX_VMDQ_DCB: dcb_config->vt_mode = true; if (hw->mac.type != ixgbe_mac_82598EB) { config_dcb_rx = DCB_RX_CONFIG; @@ -2845,7 +2783,7 @@ ixgbe_dcb_hw_configure(struct rte_eth_dev *dev, ixgbe_vmdq_dcb_configure(dev); } break; - case ETH_DCB_RX: + case ETH_MQ_RX_DCB: dcb_config->vt_mode = false; config_dcb_rx = DCB_RX_CONFIG; /* Get dcb TX configuration parameters from rte_eth_conf */ @@ -2858,7 +2796,7 @@ ixgbe_dcb_hw_configure(struct rte_eth_dev *dev, break; } switch (dev->data->dev_conf.txmode.mq_mode) { - case ETH_VMDQ_DCB_TX: + case ETH_MQ_TX_VMDQ_DCB: dcb_config->vt_mode = true; config_dcb_tx = DCB_TX_CONFIG; /* get DCB and VT TX configuration parameters from rte_eth_conf */ @@ -2867,9 +2805,9 @@ ixgbe_dcb_hw_configure(struct rte_eth_dev *dev, ixgbe_vmdq_dcb_hw_tx_config(dev,dcb_config); break; - case ETH_DCB_TX: + case ETH_MQ_TX_DCB: dcb_config->vt_mode = false; - config_dcb_tx = DCB_RX_CONFIG; + config_dcb_tx = DCB_TX_CONFIG; /*get DCB TX configuration parameters from rte_eth_conf*/ ixgbe_dcb_tx_config(dev,dcb_config); /*Configure general DCB TX parameters*/ @@ -2996,15 +2934,135 @@ void ixgbe_configure_dcb(struct rte_eth_dev *dev) { struct ixgbe_dcb_config *dcb_cfg = IXGBE_DEV_PRIVATE_TO_DCB_CFG(dev->data->dev_private); + struct rte_eth_conf *dev_conf = &(dev->data->dev_conf); PMD_INIT_FUNC_TRACE(); + + /* check support mq_mode for DCB */ + if ((dev_conf->rxmode.mq_mode != ETH_MQ_RX_VMDQ_DCB) && + (dev_conf->rxmode.mq_mode != ETH_MQ_RX_DCB)) + return; + + if (dev->data->nb_rx_queues != ETH_DCB_NUM_QUEUES) + return; + /** Configure DCB hardware **/ - if(((dev->data->dev_conf.rxmode.mq_mode != ETH_RSS) && - (dev->data->nb_rx_queues == ETH_DCB_NUM_QUEUES))|| - ((dev->data->dev_conf.txmode.mq_mode != ETH_DCB_NONE) && - (dev->data->nb_tx_queues == ETH_DCB_NUM_QUEUES))) { - ixgbe_dcb_hw_configure(dev,dcb_cfg); + ixgbe_dcb_hw_configure(dev,dcb_cfg); + + return; +} + +/* + * VMDq only support for 10 GbE NIC. + */ +static void +ixgbe_vmdq_rx_hw_configure(struct rte_eth_dev *dev) +{ + struct rte_eth_vmdq_rx_conf *cfg; + struct ixgbe_hw *hw; + enum rte_eth_nb_pools num_pools; + uint32_t mrqc, vt_ctl, vlanctrl; + int i; + + PMD_INIT_FUNC_TRACE(); + hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + cfg = &dev->data->dev_conf.rx_adv_conf.vmdq_rx_conf; + num_pools = cfg->nb_queue_pools; + + ixgbe_rss_disable(dev); + + /* MRQC: enable vmdq */ + mrqc = IXGBE_MRQC_VMDQEN; + IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); + + /* PFVTCTL: turn on virtualisation and set the default pool */ + vt_ctl = IXGBE_VT_CTL_VT_ENABLE | IXGBE_VT_CTL_REPLEN; + if (cfg->enable_default_pool) + vt_ctl |= (cfg->default_pool << IXGBE_VT_CTL_POOL_SHIFT); + else + vt_ctl |= IXGBE_VT_CTL_DIS_DEFPL; + + IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vt_ctl); + + /* VLNCTRL: enable vlan filtering and allow all vlan tags through */ + vlanctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); + vlanctrl |= IXGBE_VLNCTRL_VFE ; /* enable vlan filters */ + IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlanctrl); + + /* VFTA - enable all vlan filters */ + for (i = 0; i < NUM_VFTA_REGISTERS; i++) + IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), UINT32_MAX); + + /* VFRE: pool enabling for receive - 64 */ + IXGBE_WRITE_REG(hw, IXGBE_VFRE(0), UINT32_MAX); + if (num_pools == ETH_64_POOLS) + IXGBE_WRITE_REG(hw, IXGBE_VFRE(1), UINT32_MAX); + + /* + * MPSAR - allow pools to read specific mac addresses + * In this case, all pools should be able to read from mac addr 0 + */ + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(0), UINT32_MAX); + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(0), UINT32_MAX); + + /* PFVLVF, PFVLVFB: set up filters for vlan tags as configured */ + for (i = 0; i < cfg->nb_pool_maps; i++) { + /* set vlan id in VF register and set the valid bit */ + IXGBE_WRITE_REG(hw, IXGBE_VLVF(i), (IXGBE_VLVF_VIEN | \ + (cfg->pool_map[i].vlan_id & IXGBE_RXD_VLAN_ID_MASK))); + /* + * Put the allowed pools in VFB reg. As we only have 16 or 64 + * pools, we only need to use the first half of the register + * i.e. bits 0-31 + */ + if (((cfg->pool_map[i].pools >> 32) & UINT32_MAX) == 0) + IXGBE_WRITE_REG(hw, IXGBE_VLVFB(i*2), \ + (cfg->pool_map[i].pools & UINT32_MAX)); + else + IXGBE_WRITE_REG(hw, IXGBE_VLVFB((i*2+1)), \ + ((cfg->pool_map[i].pools >> 32) \ + & UINT32_MAX)); + } + + IXGBE_WRITE_FLUSH(hw); +} + +/* + * ixgbe_dcb_config_tx_hw_config - Configure general VMDq TX parameters + * @hw: pointer to hardware structure + */ +static void +ixgbe_vmdq_tx_hw_configure(struct ixgbe_hw *hw) +{ + uint32_t reg; + uint32_t q; + + PMD_INIT_FUNC_TRACE(); + /*PF VF Transmit Enable*/ + IXGBE_WRITE_REG(hw, IXGBE_VFTE(0), UINT32_MAX); + IXGBE_WRITE_REG(hw, IXGBE_VFTE(1), UINT32_MAX); + + /* Disable the Tx desc arbiter so that MTQC can be changed */ + reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS); + reg |= IXGBE_RTTDCS_ARBDIS; + IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg); + + reg = IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF; + IXGBE_WRITE_REG(hw, IXGBE_MTQC, reg); + + /* Disable drop for all queues */ + for (q = 0; q < IXGBE_MAX_RX_QUEUE_NUM; q++) + IXGBE_WRITE_REG(hw, IXGBE_QDE, + (IXGBE_QDE_WRITE | (q << IXGBE_QDE_IDX_SHIFT))); + + /* Enable the Tx desc arbiter */ + reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS); + reg &= ~IXGBE_RTTDCS_ARBDIS; + IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg); + + IXGBE_WRITE_FLUSH(hw); + return; } @@ -3043,6 +3101,120 @@ ixgbe_alloc_rx_queue_mbufs(struct igb_rx_queue *rxq) return 0; } +static int +ixgbe_dev_mq_rx_configure(struct rte_eth_dev *dev) +{ + struct ixgbe_hw *hw = + IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + if (hw->mac.type == ixgbe_mac_82598EB) + return 0; + + if (RTE_ETH_DEV_SRIOV(dev).active == 0) { + /* + * SRIOV inactive scheme + * any DCB/RSS w/o VMDq multi-queue setting + */ + switch (dev->data->dev_conf.rxmode.mq_mode) { + case ETH_MQ_RX_RSS: + ixgbe_rss_configure(dev); + break; + + case ETH_MQ_RX_VMDQ_DCB: + ixgbe_vmdq_dcb_configure(dev); + break; + + case ETH_MQ_RX_VMDQ_ONLY: + ixgbe_vmdq_rx_hw_configure(dev); + break; + + case ETH_MQ_RX_NONE: + /* if mq_mode is none, disable rss mode.*/ + default: ixgbe_rss_disable(dev); + } + } else { + switch (RTE_ETH_DEV_SRIOV(dev).active) { + /* + * SRIOV active scheme + * FIXME if support DCB/RSS together with VMDq & SRIOV + */ + case ETH_64_POOLS: + IXGBE_WRITE_REG(hw, IXGBE_MRQC, IXGBE_MRQC_VMDQEN); + break; + + case ETH_32_POOLS: + IXGBE_WRITE_REG(hw, IXGBE_MRQC, IXGBE_MRQC_VMDQRT4TCEN); + break; + + case ETH_16_POOLS: + IXGBE_WRITE_REG(hw, IXGBE_MRQC, IXGBE_MRQC_VMDQRT8TCEN); + break; + default: + RTE_LOG(ERR, PMD, "invalid pool number in IOV mode\n"); + } + } + + return 0; +} + +static int +ixgbe_dev_mq_tx_configure(struct rte_eth_dev *dev) +{ + struct ixgbe_hw *hw = + IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t mtqc; + uint32_t rttdcs; + + if (hw->mac.type == ixgbe_mac_82598EB) + return 0; + + /* disable arbiter before setting MTQC */ + rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); + rttdcs |= IXGBE_RTTDCS_ARBDIS; + IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); + + if (RTE_ETH_DEV_SRIOV(dev).active == 0) { + /* + * SRIOV inactive scheme + * any DCB w/o VMDq multi-queue setting + */ + if (dev->data->dev_conf.txmode.mq_mode == ETH_MQ_TX_VMDQ_ONLY) + ixgbe_vmdq_tx_hw_configure(hw); + else { + mtqc = IXGBE_MTQC_64Q_1PB; + IXGBE_WRITE_REG(hw, IXGBE_MTQC, mtqc); + } + } else { + switch (RTE_ETH_DEV_SRIOV(dev).active) { + + /* + * SRIOV active scheme + * FIXME if support DCB together with VMDq & SRIOV + */ + case ETH_64_POOLS: + mtqc = IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF; + break; + case ETH_32_POOLS: + mtqc = IXGBE_MTQC_VT_ENA | IXGBE_MTQC_32VF; + break; + case ETH_16_POOLS: + mtqc = IXGBE_MTQC_VT_ENA | IXGBE_MTQC_RT_ENA | + IXGBE_MTQC_8TC_8TQ; + break; + default: + mtqc = IXGBE_MTQC_64Q_1PB; + RTE_LOG(ERR, PMD, "invalid pool number in IOV mode\n"); + } + IXGBE_WRITE_REG(hw, IXGBE_MTQC, mtqc); + } + + /* re-enable arbiter */ + rttdcs &= ~IXGBE_RTTDCS_ARBDIS; + IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); + + return 0; +} + /* * Initializes Receive Unit. */ @@ -3063,7 +3235,7 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev) uint16_t buf_size; uint16_t i; int ret; - + PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); @@ -3102,6 +3274,15 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev) } else hlreg0 &= ~IXGBE_HLREG0_JUMBOEN; + /* + * If loopback mode is configured for 82599, set LPBK bit. + */ + if (hw->mac.type == ixgbe_mac_82599EB && + dev->data->dev_conf.lpbk_mode == IXGBE_LPBK_82599_TX_RX) + hlreg0 |= IXGBE_HLREG0_LPBK; + else + hlreg0 &= ~IXGBE_HLREG0_LPBK; + IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); /* Setup RX queues */ @@ -3123,14 +3304,14 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev) /* Setup the Base and Length of the Rx Descriptor Rings */ bus_addr = rxq->rx_ring_phys_addr; - IXGBE_WRITE_REG(hw, IXGBE_RDBAL(i), + IXGBE_WRITE_REG(hw, IXGBE_RDBAL(rxq->reg_idx), (uint32_t)(bus_addr & 0x00000000ffffffffULL)); - IXGBE_WRITE_REG(hw, IXGBE_RDBAH(i), + IXGBE_WRITE_REG(hw, IXGBE_RDBAH(rxq->reg_idx), (uint32_t)(bus_addr >> 32)); - IXGBE_WRITE_REG(hw, IXGBE_RDLEN(i), + IXGBE_WRITE_REG(hw, IXGBE_RDLEN(rxq->reg_idx), rxq->nb_rx_desc * sizeof(union ixgbe_adv_rx_desc)); - IXGBE_WRITE_REG(hw, IXGBE_RDH(i), 0); - IXGBE_WRITE_REG(hw, IXGBE_RDT(i), 0); + IXGBE_WRITE_REG(hw, IXGBE_RDH(rxq->reg_idx), 0); + IXGBE_WRITE_REG(hw, IXGBE_RDT(rxq->reg_idx), 0); /* Configure the SRRCTL register */ #ifdef RTE_HEADER_SPLIT_ENABLE @@ -3145,7 +3326,7 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev) IXGBE_PSRTYPE_UDPHDR | IXGBE_PSRTYPE_IPV4HDR | IXGBE_PSRTYPE_IPV6HDR; - IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(i), psrtype); + IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(rxq->reg_idx), psrtype); } srrctl = ((dev->data->dev_conf.rxmode.split_hdr_size << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & @@ -3165,42 +3346,28 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev) * The value is in 1 KB resolution. Valid values can be from * 1 KB to 16 KB. */ - mbp_priv = (struct rte_pktmbuf_pool_private *) - ((char *)rxq->mb_pool + sizeof(struct rte_mempool)); + mbp_priv = rte_mempool_get_priv(rxq->mb_pool); buf_size = (uint16_t) (mbp_priv->mbuf_data_room_size - RTE_PKTMBUF_HEADROOM); srrctl |= ((buf_size >> IXGBE_SRRCTL_BSIZEPKT_SHIFT) & IXGBE_SRRCTL_BSIZEPKT_MASK); - IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(i), srrctl); + IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxq->reg_idx), srrctl); buf_size = (uint16_t) ((srrctl & IXGBE_SRRCTL_BSIZEPKT_MASK) << IXGBE_SRRCTL_BSIZEPKT_SHIFT); - if (dev->data->dev_conf.rxmode.max_rx_pkt_len + - IXGBE_RX_BUF_THRESHOLD > buf_size){ + + /* It adds dual VLAN length for supporting dual VLAN */ + if ((dev->data->dev_conf.rxmode.max_rx_pkt_len + + 2 * IXGBE_VLAN_TAG_SIZE) > buf_size){ dev->data->scattered_rx = 1; dev->rx_pkt_burst = ixgbe_recv_scattered_pkts; } } /* - * Configure RSS if device configured with multiple RX queues. + * Device configured with multiple RX queues. */ - if (hw->mac.type == ixgbe_mac_82599EB) { - if (dev->data->nb_rx_queues > 1) - switch (dev->data->dev_conf.rxmode.mq_mode) { - case ETH_RSS: - ixgbe_rss_configure(dev); - break; - - case ETH_VMDQ_DCB: - ixgbe_vmdq_dcb_configure(dev); - break; - - default: ixgbe_rss_disable(dev); - } - else - ixgbe_rss_disable(dev); - } + ixgbe_dev_mq_rx_configure(dev); /* * Setup the Checksum Register. @@ -3225,7 +3392,7 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev) rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE; IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); } - + return 0; } @@ -3240,7 +3407,6 @@ ixgbe_dev_tx_init(struct rte_eth_dev *dev) uint64_t bus_addr; uint32_t hlreg0; uint32_t txctrl; - uint32_t rttdcs; uint16_t i; PMD_INIT_FUNC_TRACE(); @@ -3256,15 +3422,15 @@ ixgbe_dev_tx_init(struct rte_eth_dev *dev) txq = dev->data->tx_queues[i]; bus_addr = txq->tx_ring_phys_addr; - IXGBE_WRITE_REG(hw, IXGBE_TDBAL(i), + IXGBE_WRITE_REG(hw, IXGBE_TDBAL(txq->reg_idx), (uint32_t)(bus_addr & 0x00000000ffffffffULL)); - IXGBE_WRITE_REG(hw, IXGBE_TDBAH(i), + IXGBE_WRITE_REG(hw, IXGBE_TDBAH(txq->reg_idx), (uint32_t)(bus_addr >> 32)); - IXGBE_WRITE_REG(hw, IXGBE_TDLEN(i), + IXGBE_WRITE_REG(hw, IXGBE_TDLEN(txq->reg_idx), txq->nb_tx_desc * sizeof(union ixgbe_adv_tx_desc)); /* Setup the HW Tx Head and TX Tail descriptor pointers */ - IXGBE_WRITE_REG(hw, IXGBE_TDH(i), 0); - IXGBE_WRITE_REG(hw, IXGBE_TDT(i), 0); + IXGBE_WRITE_REG(hw, IXGBE_TDH(txq->reg_idx), 0); + IXGBE_WRITE_REG(hw, IXGBE_TDT(txq->reg_idx), 0); /* * Disable Tx Head Writeback RO bit, since this hoses @@ -3273,9 +3439,9 @@ ixgbe_dev_tx_init(struct rte_eth_dev *dev) switch (hw->mac.type) { case ixgbe_mac_82598EB: txctrl = IXGBE_READ_REG(hw, - IXGBE_DCA_TXCTRL(i)); + IXGBE_DCA_TXCTRL(txq->reg_idx)); txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; - IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(txq->reg_idx), txctrl); break; @@ -3283,28 +3449,46 @@ ixgbe_dev_tx_init(struct rte_eth_dev *dev) case ixgbe_mac_X540: default: txctrl = IXGBE_READ_REG(hw, - IXGBE_DCA_TXCTRL_82599(i)); + IXGBE_DCA_TXCTRL_82599(txq->reg_idx)); txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; - IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(txq->reg_idx), txctrl); break; } } - if (hw->mac.type != ixgbe_mac_82598EB) { - /* disable arbiter before setting MTQC */ - rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); - rttdcs |= IXGBE_RTTDCS_ARBDIS; - IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); - - IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB); + /* Device configured with multiple TX queues. */ + ixgbe_dev_mq_tx_configure(dev); +} - /* re-enable arbiter */ - rttdcs &= ~IXGBE_RTTDCS_ARBDIS; - IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); +/* + * Set up link for 82599 loopback mode Tx->Rx. + */ +static inline void +ixgbe_setup_loopback_link_82599(struct ixgbe_hw *hw) +{ + DEBUGFUNC("ixgbe_setup_loopback_link_82599"); + + if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { + if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM) != + IXGBE_SUCCESS) { + PMD_INIT_LOG(ERR, "Could not enable loopback mode\n"); + /* ignore error */ + return; + } } + + /* Restart link */ + IXGBE_WRITE_REG(hw, + IXGBE_AUTOC, + IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU); + ixgbe_reset_pipeline_82599(hw); + + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); + msec_delay(50); } + /* * Start Transmit and Receive Units. */ @@ -3327,11 +3511,11 @@ ixgbe_dev_rxtx_start(struct rte_eth_dev *dev) for (i = 0; i < dev->data->nb_tx_queues; i++) { txq = dev->data->tx_queues[i]; /* Setup Transmit Threshold Registers */ - txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i)); + txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txq->reg_idx)); txdctl |= txq->pthresh & 0x7F; txdctl |= ((txq->hthresh & 0x7F) << 8); txdctl |= ((txq->wthresh & 0x7F) << 16); - IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), txdctl); + IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txq->reg_idx), txdctl); } if (hw->mac.type != ixgbe_mac_82598EB) { @@ -3341,16 +3525,17 @@ ixgbe_dev_rxtx_start(struct rte_eth_dev *dev) } for (i = 0; i < dev->data->nb_tx_queues; i++) { - txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i)); + txq = dev->data->tx_queues[i]; + txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txq->reg_idx)); txdctl |= IXGBE_TXDCTL_ENABLE; - IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), txdctl); + IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txq->reg_idx), txdctl); /* Wait until TX Enable ready */ if (hw->mac.type == ixgbe_mac_82599EB) { poll_ms = 10; do { rte_delay_ms(1); - txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i)); + txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txq->reg_idx)); } while (--poll_ms && !(txdctl & IXGBE_TXDCTL_ENABLE)); if (!poll_ms) PMD_INIT_LOG(ERR, "Could not enable " @@ -3359,21 +3544,21 @@ ixgbe_dev_rxtx_start(struct rte_eth_dev *dev) } for (i = 0; i < dev->data->nb_rx_queues; i++) { rxq = dev->data->rx_queues[i]; - rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); + rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxq->reg_idx)); rxdctl |= IXGBE_RXDCTL_ENABLE; - IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), rxdctl); + IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxq->reg_idx), rxdctl); /* Wait until RX Enable ready */ poll_ms = 10; do { rte_delay_ms(1); - rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); + rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxq->reg_idx)); } while (--poll_ms && !(rxdctl & IXGBE_RXDCTL_ENABLE)); if (!poll_ms) PMD_INIT_LOG(ERR, "Could not enable " "Rx Queue %d\n", i); rte_wmb(); - IXGBE_WRITE_REG(hw, IXGBE_RDT(i), rxq->nb_rx_desc - 1); + IXGBE_WRITE_REG(hw, IXGBE_RDT(rxq->reg_idx), rxq->nb_rx_desc - 1); } /* Enable Receive engine */ @@ -3382,6 +3567,12 @@ ixgbe_dev_rxtx_start(struct rte_eth_dev *dev) rxctrl |= IXGBE_RXCTRL_DMBYPS; rxctrl |= IXGBE_RXCTRL_RXEN; hw->mac.ops.enable_rx_dma(hw, rxctrl); + + /* If loopback mode is enabled for 82599, set up the link accordingly */ + if (hw->mac.type == ixgbe_mac_82599EB && + dev->data->dev_conf.lpbk_mode == IXGBE_LPBK_82599_TX_RX) + ixgbe_setup_loopback_link_82599(hw); + } @@ -3403,6 +3594,10 @@ ixgbevf_dev_rx_init(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + /* setup MTU */ + ixgbevf_rlpml_set_vf(hw, + (uint16_t)dev->data->dev_conf.rxmode.max_rx_pkt_len); + /* Setup RX queues */ dev->rx_pkt_burst = ixgbe_recv_pkts; for (i = 0; i < dev->data->nb_rx_queues; i++) { @@ -3460,8 +3655,7 @@ ixgbevf_dev_rx_init(struct rte_eth_dev *dev) * The value is in 1 KB resolution. Valid values can be from * 1 KB to 16 KB. */ - mbp_priv = (struct rte_pktmbuf_pool_private *) - ((char *)rxq->mb_pool + sizeof(struct rte_mempool)); + mbp_priv = rte_mempool_get_priv(rxq->mb_pool); buf_size = (uint16_t) (mbp_priv->mbuf_data_room_size - RTE_PKTMBUF_HEADROOM); srrctl |= ((buf_size >> IXGBE_SRRCTL_BSIZEPKT_SHIFT) & @@ -3474,7 +3668,10 @@ ixgbevf_dev_rx_init(struct rte_eth_dev *dev) buf_size = (uint16_t) ((srrctl & IXGBE_SRRCTL_BSIZEPKT_MASK) << IXGBE_SRRCTL_BSIZEPKT_SHIFT); - if (dev->data->dev_conf.rxmode.max_rx_pkt_len > buf_size){ + + /* It adds dual VLAN length for supporting dual VLAN */ + if ((dev->data->dev_conf.rxmode.max_rx_pkt_len + + 2 * IXGBE_VLAN_TAG_SIZE) > buf_size) { dev->data->scattered_rx = 1; dev->rx_pkt_burst = ixgbe_recv_scattered_pkts; }