update copyright date to 2013
[dpdk.git] / lib / librte_pmd_ixgbe / ixgbe_rxtx.c
old mode 100644 (file)
new mode 100755 (executable)
index ea51973..07830b7
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  * 
- *   Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
  *   All rights reserved.
  * 
  *   Redistribution and use in source and binary forms, with or without 
@@ -79,6 +79,9 @@
 #include "ixgbe_ethdev.h"
 #include "ixgbe/ixgbe_dcb.h"
 
+
+#define RTE_PMD_IXGBE_TX_MAX_BURST 32
+
 #ifdef RTE_LIBRTE_IXGBE_RX_ALLOW_BULK_ALLOC
 #define RTE_PMD_IXGBE_RX_MAX_BURST 32
 #endif
@@ -160,10 +163,11 @@ enum ixgbe_advctx_num {
 /**
  * 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 */
-       uint32_t vlan_macip_lens; /**< vlan, mac ip length. */
+       union rte_vlan_macip vlan_macip_lens; /**< vlan, mac ip length. */
 };
 
 /**
@@ -186,11 +190,14 @@ struct igb_tx_queue {
        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];
@@ -221,6 +228,268 @@ struct igb_tx_queue {
  *  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.
+ */
+static inline int
+ixgbe_tx_free_bufs(struct igb_tx_queue *txq)
+{
+       struct igb_tx_entry *txep;
+       uint32_t status;
+       int i;
+
+       /* check DD bit on threshold descriptor */
+       status = txq->tx_ring[txq->tx_next_dd].wb.status;
+       if (! (status & IXGBE_ADVTXD_STAT_DD))
+               return 0;
+
+       /*
+        * first buffer to free from S/W ring is at index
+        * tx_next_dd - (tx_rs_thresh-1)
+        */
+       txep = &(txq->sw_ring[txq->tx_next_dd - (txq->tx_rs_thresh - 1)]);
+
+       /* prefetch the mbufs that are about to be freed */
+       for (i = 0; i < txq->tx_rs_thresh; ++i)
+               rte_prefetch0((txep + i)->mbuf);
+
+       /* free buffers one at a time */
+       if ((txq->txq_flags & (uint32_t)ETH_TXQ_FLAGS_NOREFCOUNT) != 0) {
+               for (i = 0; i < txq->tx_rs_thresh; ++i, ++txep) {
+                       rte_mempool_put(txep->mbuf->pool, txep->mbuf);
+                       txep->mbuf = NULL;
+               }
+       } else {
+               for (i = 0; i < txq->tx_rs_thresh; ++i, ++txep) {
+                       rte_pktmbuf_free_seg(txep->mbuf);
+                       txep->mbuf = NULL;
+               }
+       }
+
+       /* buffers were freed, update counters */
+       txq->nb_tx_free += txq->tx_rs_thresh;
+       txq->tx_next_dd += txq->tx_rs_thresh;
+       if (txq->tx_next_dd >= txq->nb_tx_desc)
+               txq->tx_next_dd = txq->tx_rs_thresh - 1;
+
+       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)
+{
+       uint64_t buf_dma_addr;
+       uint32_t pkt_len;
+       int i;
+
+       for (i = 0; i < 4; ++i, ++txdp, ++pkts) {
+               buf_dma_addr = RTE_MBUF_DATA_DMA_ADDR(*pkts);
+               pkt_len = (*pkts)->pkt.data_len;
+
+               /* write data to descriptor */
+               txdp->read.buffer_addr = buf_dma_addr;
+               txdp->read.cmd_type_len =
+                               ((uint32_t)DCMD_DTYP_FLAGS | pkt_len);
+               txdp->read.olinfo_status =
+                               (pkt_len << IXGBE_ADVTXD_PAYLEN_SHIFT);
+       }
+}
+
+/* Populate 1 descriptor with data from 1 mbuf */
+static inline void
+tx1(volatile union ixgbe_adv_tx_desc *txdp, struct rte_mbuf **pkts)
+{
+       uint64_t buf_dma_addr;
+       uint32_t pkt_len;
+
+       buf_dma_addr = RTE_MBUF_DATA_DMA_ADDR(*pkts);
+       pkt_len = (*pkts)->pkt.data_len;
+
+       /* write data to descriptor */
+       txdp->read.buffer_addr = buf_dma_addr;
+       txdp->read.cmd_type_len =
+                       ((uint32_t)DCMD_DTYP_FLAGS | pkt_len);
+       txdp->read.olinfo_status =
+                       (pkt_len << IXGBE_ADVTXD_PAYLEN_SHIFT);
+}
+
+/*
+ * Fill H/W descriptor ring with mbuf data.
+ * Copy mbuf pointers to the S/W ring.
+ */
+static inline void
+ixgbe_tx_fill_hw_ring(struct igb_tx_queue *txq, struct rte_mbuf **pkts,
+                     uint16_t nb_pkts)
+{
+       volatile union ixgbe_adv_tx_desc *txdp = &(txq->tx_ring[txq->tx_tail]);
+       struct igb_tx_entry *txep = &(txq->sw_ring[txq->tx_tail]);
+       const int N_PER_LOOP = 4;
+       const int N_PER_LOOP_MASK = N_PER_LOOP-1;
+       int mainpart, leftover;
+       int i, j;
+
+       /*
+        * Process most of the packets in chunks of N pkts.  Any
+        * leftover packets will get processed one at a time.
+        */
+       mainpart = (nb_pkts & ((uint32_t) ~N_PER_LOOP_MASK));
+       leftover = (nb_pkts & ((uint32_t)  N_PER_LOOP_MASK));
+       for (i = 0; i < mainpart; i += N_PER_LOOP) {
+               /* Copy N mbuf pointers to the S/W ring */
+               for (j = 0; j < N_PER_LOOP; ++j) {
+                       (txep + i + j)->mbuf = *(pkts + i + j);
+               }
+               tx4(txdp + i, pkts + i);
+       }
+
+       if (unlikely(leftover > 0)) {
+               for (i = 0; i < leftover; ++i) {
+                       (txep + mainpart + i)->mbuf = *(pkts + mainpart + i);
+                       tx1(txdp + mainpart + i, pkts + mainpart + i);
+               }
+       }
+}
+
+static inline uint16_t
+tx_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
+            uint16_t nb_pkts)
+{
+       struct igb_tx_queue *txq = (struct igb_tx_queue *)tx_queue;
+       volatile union ixgbe_adv_tx_desc *tx_r = txq->tx_ring;
+       uint16_t n = 0;
+
+       /*
+        * Begin scanning the H/W ring for done descriptors when the
+        * number of available descriptors drops below tx_free_thresh.  For
+        * each done descriptor, free the associated buffer.
+        */
+       if (txq->nb_tx_free < txq->tx_free_thresh)
+               ixgbe_tx_free_bufs(txq);
+
+       /* Only use descriptors that are available */
+       nb_pkts = RTE_MIN(txq->nb_tx_free, nb_pkts);
+       if (unlikely(nb_pkts == 0))
+               return 0;
+
+       /* Use exactly nb_pkts descriptors */
+       txq->nb_tx_free -= nb_pkts;
+
+       /*
+        * At this point, we know there are enough descriptors in the
+        * ring to transmit all the packets.  This assumes that each
+        * mbuf contains a single segment, and that no new offloads
+        * are expected, which would require a new context descriptor.
+        */
+
+       /*
+        * See if we're going to wrap-around. If so, handle the top
+        * of the descriptor ring first, then do the bottom.  If not,
+        * the processing looks just like the "bottom" part anyway...
+        */
+       if ((txq->tx_tail + nb_pkts) > txq->nb_tx_desc) {
+               n = txq->nb_tx_desc - txq->tx_tail;
+               ixgbe_tx_fill_hw_ring(txq, tx_pkts, n);
+
+               /*
+                * We know that the last descriptor in the ring will need to
+                * have its RS bit set because tx_rs_thresh has to be
+                * a divisor of the ring size
+                */
+               tx_r[txq->tx_next_rs].read.cmd_type_len |=
+                       rte_cpu_to_le_32(IXGBE_ADVTXD_DCMD_RS);
+               txq->tx_next_rs = txq->tx_rs_thresh - 1;
+
+               txq->tx_tail = 0;
+       }
+
+       /* Fill H/W descriptor ring with mbuf data */
+       ixgbe_tx_fill_hw_ring(txq, tx_pkts + n, nb_pkts - n);
+       txq->tx_tail += (nb_pkts - n);
+
+       /*
+        * Determine if RS bit should be set
+        * This is what we actually want:
+        *   if ((txq->tx_tail - 1) >= txq->tx_next_rs)
+        * but instead of subtracting 1 and doing >=, we can just do
+        * greater than without subtracting.
+        */
+       if (txq->tx_tail > txq->tx_next_rs) {
+               tx_r[txq->tx_next_rs].read.cmd_type_len |=
+                       rte_cpu_to_le_32(IXGBE_ADVTXD_DCMD_RS);
+               txq->tx_next_rs += txq->tx_rs_thresh;
+               if (txq->tx_next_rs >= txq->nb_tx_desc)
+                       txq->tx_next_rs = txq->tx_rs_thresh - 1;
+       }
+
+       /*
+        * Check for wrap-around. This would only happen if we used
+        * up to the last descriptor in the ring, no more, no less.
+        */
+       if (txq->tx_tail >= txq->nb_tx_desc)
+               txq->tx_tail = 0;
+
+       /* update tail pointer */
+       rte_wmb();
+       IXGBE_PCI_REG_WRITE(txq->tdt_reg_addr, txq->tx_tail);
+
+       return nb_pkts;
+}
+
+uint16_t
+ixgbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,
+                      uint16_t nb_pkts)
+{
+       uint16_t nb_tx;
+
+       /* Try to transmit at least chunks of TX_MAX_BURST pkts */
+       if (likely(nb_pkts <= RTE_PMD_IXGBE_TX_MAX_BURST))
+               return tx_xmit_pkts(tx_queue, tx_pkts, nb_pkts);
+
+       /* transmit more than the max burst, in chunks of TX_MAX_BURST */
+       nb_tx = 0;
+       while (nb_pkts) {
+               uint16_t ret, n;
+               n = RTE_MIN(nb_pkts, RTE_PMD_IXGBE_TX_MAX_BURST);
+               ret = tx_xmit_pkts(tx_queue, &(tx_pkts[nb_tx]), n);
+               nb_tx += ret;
+               nb_pkts -= ret;
+               if (ret < n)
+                       break;
+       }
+
+       return nb_tx;
+}
+
 static inline void
 ixgbe_set_xmit_ctx(struct igb_tx_queue* txq,
                volatile struct ixgbe_adv_tx_context_desc *ctx_txd,
@@ -273,7 +542,8 @@ ixgbe_set_xmit_ctx(struct igb_tx_queue* txq,
 
        txq->ctx_cache[ctx_idx].flags = ol_flags;
        txq->ctx_cache[ctx_idx].cmp_mask = cmp_mask;
-       txq->ctx_cache[ctx_idx].vlan_macip_lens = vlan_macip_lens & cmp_mask;
+       txq->ctx_cache[ctx_idx].vlan_macip_lens.data =
+               vlan_macip_lens & cmp_mask;
 
        ctx_txd->type_tucmd_mlhl = rte_cpu_to_le_32(type_tucmd_mlhl);
        ctx_txd->vlan_macip_lens = rte_cpu_to_le_32(vlan_macip_lens);
@@ -291,7 +561,7 @@ what_advctx_update(struct igb_tx_queue *txq, uint16_t flags,
 {
        /* If match with the current used context */
        if (likely((txq->ctx_cache[txq->ctx_curr].flags == flags) &&
-               (txq->ctx_cache[txq->ctx_curr].vlan_macip_lens ==
+               (txq->ctx_cache[txq->ctx_curr].vlan_macip_lens.data ==
                (txq->ctx_cache[txq->ctx_curr].cmp_mask & vlan_macip_lens)))) {
                        return txq->ctx_curr;
        }
@@ -299,7 +569,7 @@ what_advctx_update(struct igb_tx_queue *txq, uint16_t flags,
        /* What if match with the next context  */
        txq->ctx_curr ^= 1;
        if (likely((txq->ctx_cache[txq->ctx_curr].flags == flags) &&
-               (txq->ctx_cache[txq->ctx_curr].vlan_macip_lens ==
+               (txq->ctx_cache[txq->ctx_curr].vlan_macip_lens.data ==
                (txq->ctx_cache[txq->ctx_curr].cmp_mask & vlan_macip_lens)))) {
                        return txq->ctx_curr;
        }
@@ -416,7 +686,7 @@ ixgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
        uint16_t nb_used;
        uint16_t tx_ol_req;
        uint32_t vlan_macip_lens;
-       uint32_t ctx;
+       uint32_t ctx = 0;
        uint32_t new_ctx;
 
        txq = tx_queue;
@@ -443,15 +713,14 @@ ixgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
                 * are needed for offload functionality.
                 */
                ol_flags = tx_pkt->ol_flags;
-               vlan_macip_lens = tx_pkt->pkt.vlan_tci << 16 |
-                               tx_pkt->pkt.l2_len << IXGBE_ADVTXD_MACLEN_SHIFT |
-                               tx_pkt->pkt.l3_len;
+               vlan_macip_lens = tx_pkt->pkt.vlan_macip.data;
 
                /* If hardware offload required */
                tx_ol_req = ol_flags & PKT_TX_OFFLOAD_MASK;
                if (tx_ol_req) {
                        /* If new context need be built or reuse the exist ctx. */
-                       ctx = what_advctx_update(txq, tx_ol_req, vlan_macip_lens);
+                       ctx = what_advctx_update(txq, tx_ol_req,
+                               vlan_macip_lens);
                        /* Only allocate context descriptor if required*/
                        new_ctx = (ctx == IXGBE_CTX_NUM);
                        ctx = txq->ctx_curr;
@@ -956,7 +1225,7 @@ rx_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 /* split requests into chunks of size RTE_PMD_IXGBE_RX_MAX_BURST */
 uint16_t
 ixgbe_recv_pkts_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts,
-               uint16_t nb_pkts)
+                          uint16_t nb_pkts)
 {
        uint16_t nb_rx;
 
@@ -1116,7 +1385,8 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 
                hlen_type_rss = rte_le_to_cpu_32(rxd.wb.lower.lo_dword.data);
                /* Only valid if PKT_RX_VLAN_PKT set in pkt_flags */
-               rxm->pkt.vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan);
+               rxm->pkt.vlan_macip.f.vlan_tci =
+                       rte_le_to_cpu_16(rxd.wb.upper.vlan);
 
                pkt_flags = rx_desc_hlen_type_rss_to_pkt_flags(hlen_type_rss);
                pkt_flags = (pkt_flags | rx_desc_status_to_pkt_flags(staterr));
@@ -1358,7 +1628,7 @@ ixgbe_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
                 * The vlan_tci field is only valid when PKT_RX_VLAN_PKT is
                 * set in the pkt_flags field.
                 */
-               first_seg->pkt.vlan_tci =
+               first_seg->pkt.vlan_macip.f.vlan_tci =
                                rte_le_to_cpu_16(rxd.wb.upper.vlan);
                hlen_type_rss = rte_le_to_cpu_32(rxd.wb.lower.lo_dword.data);
                pkt_flags = rx_desc_hlen_type_rss_to_pkt_flags(hlen_type_rss);
@@ -1497,9 +1767,9 @@ static void
 ixgbe_tx_queue_release(struct igb_tx_queue *txq)
 {
        if (txq != NULL) {
-       ixgbe_tx_queue_release_mbufs(txq);
-       rte_free(txq->sw_ring);
-       rte_free(txq);
+               ixgbe_tx_queue_release_mbufs(txq);
+               rte_free(txq->sw_ring);
+               rte_free(txq);
        }
 }
 
@@ -1532,6 +1802,9 @@ ixgbe_reset_tx_queue(struct igb_tx_queue *txq)
                prev = i;
        }
 
+       txq->tx_next_dd = txq->tx_rs_thresh - 1;
+       txq->tx_next_rs = txq->tx_rs_thresh - 1;
+
        txq->tx_tail = 0;
        txq->nb_tx_used = 0;
        /*
@@ -1584,6 +1857,7 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
         *  tx_rs_thresh must be greater than 0.
         *  tx_rs_thresh must be less than the size of the ring minus 2.
         *  tx_rs_thresh must be less than or equal to tx_free_thresh.
+        *  tx_rs_thresh must be a divisor of the ring size.
         *  tx_free_thresh must be greater than 0.
         *  tx_free_thresh must be less than the size of the ring minus 3.
         * One descriptor in the TX ring is used as a sentinel to avoid a
@@ -1598,7 +1872,7 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
                RTE_LOG(ERR, PMD,
                             "tx_rs_thresh must be less than the "
                             "number of TX descriptors minus 2. "
-                            "(tx_rs_thresh=%u port=%d queue=%d)",
+                            "(tx_rs_thresh=%u port=%d queue=%d)\n",
                             tx_rs_thresh, dev->data->port_id, queue_idx);
                return -(EINVAL);
        }
@@ -1607,7 +1881,7 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
                             "tx_rs_thresh must be less than the "
                             "tx_free_thresh must be less than the "
                             "number of TX descriptors minus 3. "
-                            "(tx_free_thresh=%u port=%d queue=%d)",
+                            "(tx_free_thresh=%u port=%d queue=%d)\n",
                             tx_free_thresh, dev->data->port_id, queue_idx);
                return -(EINVAL);
        }
@@ -1616,11 +1890,19 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
                             "tx_rs_thresh must be less than or equal to "
                             "tx_free_thresh. "
                             "(tx_free_thresh=%u tx_rs_thresh=%u "
-                            "port=%d queue=%d)",
+                            "port=%d queue=%d)\n",
                             tx_free_thresh, tx_rs_thresh,
                             dev->data->port_id, queue_idx);
                return -(EINVAL);
        }
+       if ((nb_desc % tx_rs_thresh) != 0) {
+               RTE_LOG(ERR, PMD,
+                            "tx_rs_thresh must be a divisor of the"
+                            "number of TX descriptors. "
+                            "(tx_rs_thresh=%u port=%d queue=%d)\n",
+                            tx_rs_thresh, dev->data->port_id, queue_idx);
+               return -(EINVAL);
+       }
 
        /*
         * If rs_bit_thresh is greater than 1, then TX WTHRESH should be
@@ -1630,10 +1912,9 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
         */
        if ((tx_rs_thresh > 1) && (tx_conf->tx_thresh.wthresh != 0)) {
                RTE_LOG(ERR, PMD,
-                            "TX WTHRESH should be set to 0 if "
+                            "TX WTHRESH must be set to 0 if "
                             "tx_rs_thresh is greater than 1. "
-                            "TX WTHRESH will be set to 0. "
-                            "(tx_rs_thresh=%u port=%d queue=%d)",
+                            "(tx_rs_thresh=%u port=%d queue=%d)\n",
                             tx_rs_thresh,
                             dev->data->port_id, queue_idx);
                return -(EINVAL);
@@ -1670,6 +1951,7 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
        txq->wthresh = tx_conf->tx_thresh.wthresh;
        txq->queue_id = queue_idx;
        txq->port_id = dev->data->port_id;
+       txq->txq_flags = tx_conf->txq_flags;
 
        /*
         * Modification to set VFTDT for virtual function if vf is detected
@@ -1697,7 +1979,12 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
 
        dev->data->tx_queues[queue_idx] = txq;
 
-       dev->tx_pkt_burst = ixgbe_xmit_pkts;
+       /* 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))
+               dev->tx_pkt_burst = ixgbe_xmit_pkts_simple;
+       else
+               dev->tx_pkt_burst = ixgbe_xmit_pkts;
 
        return (0);
 }
@@ -1730,9 +2017,11 @@ ixgbe_rx_queue_release_mbufs(struct igb_rx_queue *rxq)
 static void
 ixgbe_rx_queue_release(struct igb_rx_queue *rxq)
 {
-       ixgbe_rx_queue_release_mbufs(rxq);
-       rte_free(rxq->sw_ring);
-       rte_free(rxq);
+       if (rxq != NULL) {
+               ixgbe_rx_queue_release_mbufs(rxq);
+               rte_free(rxq->sw_ring);
+               rte_free(rxq);
+       }
 }
 
 void
@@ -1780,11 +2069,12 @@ check_rx_burst_bulk_alloc_preconditions(struct igb_rx_queue *rxq)
        return ret;
 }
 
-/* (Re)set dynamic igb_rx_queue fields to defaults */
+/* Reset dynamic igb_rx_queue fields back to defaults */
 static void
 ixgbe_reset_rx_queue(struct igb_rx_queue *rxq)
 {
        unsigned i;
+       uint16_t len;
 
        /*
         * By default, the Rx queue setup function allocates enough memory for
@@ -1845,6 +2135,8 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev,
        const struct rte_memzone *rz;
        struct igb_rx_queue *rxq;
        struct ixgbe_hw     *hw;
+       int use_def_burst_func = 1;
+       uint16_t len;
 
        PMD_INIT_FUNC_TRACE();
        hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -1876,9 +2168,10 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev,
        rxq->port_id = dev->data->port_id;
        rxq->crc_len = (uint8_t) ((dev->data->dev_conf.rxmode.hw_strip_crc) ? 0 :
                                  ETHER_CRC_LEN);
+       rxq->drop_en = rx_conf->rx_drop_en;
 
        /*
-        * Allocate TX ring hardware descriptors. A memzone large enough to
+        * Allocate RX ring hardware descriptors. A memzone large enough to
         * handle the maximum ring size is allocated in order to allow for
         * resizing in later calls to the queue setup function.
         */
@@ -1911,7 +2204,7 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev,
        len = nb_desc;
 #endif
        rxq->sw_ring = rte_zmalloc("rxq->sw_ring",
-                                  sizeof(struct igb_rx_entry) * nb_desc,
+                                  sizeof(struct igb_rx_entry) * len,
                                   CACHE_LINE_SIZE);
        if (rxq->sw_ring == NULL) {
                ixgbe_rx_queue_release(rxq);
@@ -1954,17 +2247,22 @@ ixgbe_dev_clear_queues(struct rte_eth_dev *dev)
 {
        unsigned i;
 
+       PMD_INIT_FUNC_TRACE();
 
        for (i = 0; i < dev->data->nb_tx_queues; i++) {
                struct igb_tx_queue *txq = dev->data->tx_queues[i];
-               ixgbe_tx_queue_release_mbufs(txq);
-               ixgbe_reset_tx_queue(txq);
+               if (txq != NULL) {
+                       ixgbe_tx_queue_release_mbufs(txq);
+                       ixgbe_reset_tx_queue(txq);
+               }
        }
 
        for (i = 0; i < dev->data->nb_rx_queues; i++) {
                struct igb_rx_queue *rxq = dev->data->rx_queues[i];
-               ixgbe_rx_queue_release_mbufs(rxq);
-               ixgbe_reset_rx_queue(rxq);
+               if (rxq != NULL) {
+                       ixgbe_rx_queue_release_mbufs(rxq);
+                       ixgbe_reset_rx_queue(rxq);
+               }
        }
 }
 
@@ -2678,6 +2976,14 @@ ixgbe_alloc_rx_queue_mbufs(struct igb_rx_queue *rxq)
                                     (unsigned) rxq->queue_id);
                        return (-ENOMEM);
                }
+
+               rte_mbuf_refcnt_set(mbuf, 1);
+               mbuf->type = RTE_MBUF_PKT;
+               mbuf->pkt.next = NULL;
+               mbuf->pkt.data = (char *)mbuf->buf_addr + RTE_PKTMBUF_HEADROOM;
+               mbuf->pkt.nb_segs = 1;
+               mbuf->pkt.in_port = rxq->port_id;
+
                dma_addr =
                        rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mbuf));
                rxd = &rxq->rx_ring[i];
@@ -2801,6 +3107,10 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev)
 #endif
                        srrctl = IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
 
+               /* Set if packets are dropped when no descriptors available */
+               if (rxq->drop_en)
+                       srrctl |= IXGBE_SRRCTL_DROP_EN;
+
                /*
                 * Configure the RX buffer size in the BSIZEPACKET field of
                 * the SRRCTL register of the queue.
@@ -2817,7 +3127,8 @@ ixgbe_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){
+               if (dev->data->dev_conf.rxmode.max_rx_pkt_len +
+                               IXGBE_RX_BUF_THRESHOLD > buf_size){
                        dev->data->scattered_rx = 1;
                        dev->rx_pkt_burst = ixgbe_recv_scattered_pkts;
                }
@@ -2915,7 +3226,7 @@ ixgbe_dev_tx_init(struct rte_eth_dev *dev)
                        case ixgbe_mac_82598EB:
                                txctrl = IXGBE_READ_REG(hw,
                                                        IXGBE_DCA_TXCTRL(i));
-                               txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+                               txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
                                IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i),
                                                txctrl);
                                break;
@@ -2925,7 +3236,7 @@ ixgbe_dev_tx_init(struct rte_eth_dev *dev)
                        default:
                                txctrl = IXGBE_READ_REG(hw,
                                                IXGBE_DCA_TXCTRL_82599(i));
-                               txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+                               txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
                                IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i),
                                                txctrl);
                                break;
@@ -3051,9 +3362,9 @@ ixgbevf_dev_rx_init(struct rte_eth_dev *dev)
 
                /* Allocate buffers for descriptor rings */
                ret = ixgbe_alloc_rx_queue_mbufs(rxq);
-               if (ret){
-                       return -1;
-               }
+               if (ret)
+                       return ret;
+
                /* Setup the Base and Length of the Rx Descriptor Rings */
                bus_addr = rxq->rx_ring_phys_addr;
 
@@ -3091,6 +3402,10 @@ ixgbevf_dev_rx_init(struct rte_eth_dev *dev)
 #endif
                        srrctl = IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
 
+               /* Set if packets are dropped when no descriptors available */
+               if (rxq->drop_en)
+                       srrctl |= IXGBE_SRRCTL_DROP_EN;
+
                /*
                 * Configure the RX buffer size in the BSIZEPACKET field of
                 * the SRRCTL register of the queue.
@@ -3116,6 +3431,7 @@ ixgbevf_dev_rx_init(struct rte_eth_dev *dev)
                        dev->rx_pkt_burst = ixgbe_recv_scattered_pkts;
                }
        }
+
        return 0;
 }
 
@@ -3154,7 +3470,7 @@ ixgbevf_dev_tx_init(struct rte_eth_dev *dev)
                 */
                txctrl = IXGBE_READ_REG(hw,
                                IXGBE_VFDCA_TXCTRL(i));
-               txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+               txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
                IXGBE_WRITE_REG(hw, IXGBE_VFDCA_TXCTRL(i),
                                txctrl);
        }