pci: use lookup tailq api
[dpdk.git] / lib / librte_pmd_ixgbe / ixgbe_rxtx.c
index 5c36bff..811493e 100644 (file)
 #include "ixgbe/ixgbe_common.h"
 #include "ixgbe_rxtx.h"
 
-#define IXGBE_RSS_OFFLOAD_ALL ( \
-               ETH_RSS_IPV4 | \
-               ETH_RSS_IPV4_TCP | \
-               ETH_RSS_IPV6 | \
-               ETH_RSS_IPV6_EX | \
-               ETH_RSS_IPV6_TCP | \
-               ETH_RSS_IPV6_TCP_EX | \
-               ETH_RSS_IPV4_UDP | \
-               ETH_RSS_IPV6_UDP | \
-               ETH_RSS_IPV6_UDP_EX)
-
 /* Bit Mask to indicate what bits required for building TX context */
 #define IXGBE_TX_OFFLOAD_MASK (                         \
                PKT_TX_VLAN_PKT |                \
@@ -1771,6 +1760,40 @@ static struct ixgbe_txq_ops def_txq_ops = {
        .reset = ixgbe_reset_tx_queue,
 };
 
+/* Takes an ethdev and a queue and sets up the tx function to be used based on
+ * the queue parameters. Used in tx_queue_setup by primary process and then
+ * in dev_init by secondary process when attaching to an existing ethdev.
+ */
+void
+set_tx_function(struct rte_eth_dev *dev, struct igb_tx_queue *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");
+#ifdef RTE_IXGBE_INC_VECTOR
+               if (txq->tx_rs_thresh <= RTE_IXGBE_TX_MAX_FREE_BUF_SZ &&
+                               (rte_eal_process_type() != RTE_PROC_PRIMARY ||
+                                       ixgbe_txq_vec_setup(txq) == 0)) {
+                       PMD_INIT_LOG(INFO, "Vector tx enabled.");
+                       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");
+               PMD_INIT_LOG(INFO,
+                               " - txq_flags = %lx " "[IXGBE_SIMPLE_FLAGS=%lx]",
+                               (unsigned long)txq->txq_flags,
+                               (unsigned long)IXGBE_SIMPLE_FLAGS);
+               PMD_INIT_LOG(INFO,
+                               " - tx_rs_thresh = %lu " "[RTE_PMD_IXGBE_TX_MAX_BURST=%lu]",
+                               (unsigned long)txq->tx_rs_thresh,
+                               (unsigned long)RTE_PMD_IXGBE_TX_MAX_BURST);
+               dev->tx_pkt_burst = ixgbe_xmit_pkts;
+       }
+}
+
 int
 ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
                         uint16_t queue_idx,
@@ -1911,7 +1934,10 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
        /*
         * Modification to set VFTDT for virtual function if vf is detected
         */
-       if (hw->mac.type == ixgbe_mac_82599_vf)
+       if (hw->mac.type == ixgbe_mac_82599_vf ||
+           hw->mac.type == ixgbe_mac_X540_vf ||
+           hw->mac.type == ixgbe_mac_X550_vf ||
+           hw->mac.type == ixgbe_mac_X550EM_x_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(txq->reg_idx));
@@ -1933,31 +1959,8 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
        PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%"PRIx64,
                     txq->sw_ring, txq->tx_ring, txq->tx_ring_phys_addr);
 
-       /* 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");
-#ifdef RTE_IXGBE_INC_VECTOR
-               if (txq->tx_rs_thresh <= RTE_IXGBE_TX_MAX_FREE_BUF_SZ &&
-                   ixgbe_txq_vec_setup(txq) == 0) {
-                       PMD_INIT_LOG(INFO, "Vector tx enabled.");
-                       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");
-               PMD_INIT_LOG(INFO, " - txq_flags = %lx "
-                            "[IXGBE_SIMPLE_FLAGS=%lx]",
-                            (long unsigned)txq->txq_flags,
-                            (long unsigned)IXGBE_SIMPLE_FLAGS);
-               PMD_INIT_LOG(INFO, " - tx_rs_thresh = %lu "
-                            "[RTE_PMD_IXGBE_TX_MAX_BURST=%lu]",
-                            (long unsigned)txq->tx_rs_thresh,
-                            (long unsigned)RTE_PMD_IXGBE_TX_MAX_BURST);
-               dev->tx_pkt_burst = ixgbe_xmit_pkts;
-       }
+       /* set up vector or scalar TX function as appropriate */
+       set_tx_function(dev, txq);
 
        txq->ops->reset(txq);
 
@@ -2198,7 +2201,10 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev,
        /*
         * Modified to setup VFRDT for Virtual Function
         */
-       if (hw->mac.type == ixgbe_mac_82599_vf) {
+       if (hw->mac.type == ixgbe_mac_82599_vf ||
+           hw->mac.type == ixgbe_mac_X540_vf ||
+           hw->mac.type == ixgbe_mac_X550_vf ||
+           hw->mac.type == ixgbe_mac_X550EM_x_vf) {
                rxq->rdt_reg_addr =
                        IXGBE_PCI_REG_ADDR(hw, IXGBE_VFRDT(queue_idx));
                rxq->rdh_reg_addr =
@@ -2255,7 +2261,8 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev,
                             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)) {
+               if (!ixgbe_rx_vec_condition_check(dev) &&
+                   (rte_is_power_of_2(nb_desc))) {
                        PMD_INIT_LOG(INFO, "Vector rx enabled, please make "
                                     "sure RX burst size no less than 32.");
                        dev->rx_pkt_burst = ixgbe_recv_pkts_vec;
@@ -2419,19 +2426,19 @@ ixgbe_hw_rss_hash_set(struct ixgbe_hw *hw, struct rte_eth_rss_conf *rss_conf)
        mrqc = IXGBE_MRQC_RSSEN; /* Enable RSS */
        if (rss_hf & ETH_RSS_IPV4)
                mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4;
-       if (rss_hf & ETH_RSS_IPV4_TCP)
+       if (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP)
                mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP;
        if (rss_hf & ETH_RSS_IPV6)
                mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6;
        if (rss_hf & ETH_RSS_IPV6_EX)
                mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX;
-       if (rss_hf & ETH_RSS_IPV6_TCP)
+       if (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP)
                mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
        if (rss_hf & ETH_RSS_IPV6_TCP_EX)
                mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP;
-       if (rss_hf & ETH_RSS_IPV4_UDP)
+       if (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP)
                mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
-       if (rss_hf & ETH_RSS_IPV6_UDP)
+       if (rss_hf & ETH_RSS_NONFRAG_IPV6_UDP)
                mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
        if (rss_hf & ETH_RSS_IPV6_UDP_EX)
                mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
@@ -2505,19 +2512,19 @@ ixgbe_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
        if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV4)
                rss_hf |= ETH_RSS_IPV4;
        if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV4_TCP)
-               rss_hf |= ETH_RSS_IPV4_TCP;
+               rss_hf |= ETH_RSS_NONFRAG_IPV4_TCP;
        if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6)
                rss_hf |= ETH_RSS_IPV6;
        if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_EX)
                rss_hf |= ETH_RSS_IPV6_EX;
        if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_TCP)
-               rss_hf |= ETH_RSS_IPV6_TCP;
+               rss_hf |= ETH_RSS_NONFRAG_IPV6_TCP;
        if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP)
                rss_hf |= ETH_RSS_IPV6_TCP_EX;
        if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV4_UDP)
-               rss_hf |= ETH_RSS_IPV4_UDP;
+               rss_hf |= ETH_RSS_NONFRAG_IPV4_UDP;
        if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_UDP)
-               rss_hf |= ETH_RSS_IPV6_UDP;
+               rss_hf |= ETH_RSS_NONFRAG_IPV6_UDP;
        if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP)
                rss_hf |= ETH_RSS_IPV6_UDP_EX;
        rss_conf->rss_hf = rss_hf;
@@ -3326,6 +3333,67 @@ ixgbe_alloc_rx_queue_mbufs(struct igb_rx_queue *rxq)
        return 0;
 }
 
+static int
+ixgbe_config_vf_rss(struct rte_eth_dev *dev)
+{
+       struct ixgbe_hw *hw;
+       uint32_t mrqc;
+
+       ixgbe_rss_configure(dev);
+
+       hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       /* MRQC: enable VF RSS */
+       mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC);
+       mrqc &= ~IXGBE_MRQC_MRQE_MASK;
+       switch (RTE_ETH_DEV_SRIOV(dev).active) {
+       case ETH_64_POOLS:
+               mrqc |= IXGBE_MRQC_VMDQRSS64EN;
+               break;
+
+       case ETH_32_POOLS:
+               mrqc |= IXGBE_MRQC_VMDQRSS32EN;
+               break;
+
+       default:
+               PMD_INIT_LOG(ERR, "Invalid pool number in IOV mode with VMDQ RSS");
+               return -EINVAL;
+       }
+
+       IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
+
+       return 0;
+}
+
+static int
+ixgbe_config_vf_default(struct rte_eth_dev *dev)
+{
+       struct ixgbe_hw *hw =
+               IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       switch (RTE_ETH_DEV_SRIOV(dev).active) {
+       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:
+               PMD_INIT_LOG(ERR,
+                       "invalid pool number in IOV mode");
+               break;
+       }
+       return 0;
+}
+
 static int
 ixgbe_dev_mq_rx_configure(struct rte_eth_dev *dev)
 {
@@ -3358,24 +3426,25 @@ ixgbe_dev_mq_rx_configure(struct rte_eth_dev *dev)
                        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
+                * Support 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);
+               switch (dev->data->dev_conf.rxmode.mq_mode) {
+               case ETH_MQ_RX_RSS:
+               case ETH_MQ_RX_VMDQ_RSS:
+                       ixgbe_config_vf_rss(dev);
                        break;
 
-               case ETH_16_POOLS:
-                       IXGBE_WRITE_REG(hw, IXGBE_MRQC, IXGBE_MRQC_VMDQRT8TCEN);
-                       break;
+               /* FIXME if support DCB/RSS together with VMDq & SRIOV */
+               case ETH_MQ_RX_VMDQ_DCB:
+               case ETH_MQ_RX_VMDQ_DCB_RSS:
+                       PMD_INIT_LOG(ERR,
+                               "Could not support DCB with VMDq & SRIOV");
+                       return -1;
                default:
-                       PMD_INIT_LOG(ERR, "invalid pool number in IOV mode");
+                       ixgbe_config_vf_default(dev);
+                       break;
                }
        }
 
@@ -3548,9 +3617,9 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev)
                                IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(rxq->reg_idx), psrtype);
                        }
                        srrctl = ((dev->data->dev_conf.rxmode.split_hdr_size <<
-                                  IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
-                                 IXGBE_SRRCTL_BSIZEHDR_MASK);
-                       srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
+                               IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
+                               IXGBE_SRRCTL_BSIZEHDR_MASK);
+                       srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
                } else
 #endif
                        srrctl = IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
@@ -3575,31 +3644,23 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev)
                buf_size = (uint16_t) ((srrctl & IXGBE_SRRCTL_BSIZEPKT_MASK) <<
                                       IXGBE_SRRCTL_BSIZEPKT_SHIFT);
 
-               /* It adds dual VLAN length for supporting dual VLAN */
-               if ((dev->data->dev_conf.rxmode.max_rx_pkt_len +
+               if (dev->data->dev_conf.rxmode.enable_scatter ||
+                   /* It adds dual VLAN length for supporting dual VLAN */
+                   (dev->data->dev_conf.rxmode.max_rx_pkt_len +
                                2 * IXGBE_VLAN_TAG_SIZE) > buf_size){
                        if (!dev->data->scattered_rx)
                                PMD_INIT_LOG(DEBUG, "forcing scatter mode");
                        dev->data->scattered_rx = 1;
 #ifdef RTE_IXGBE_INC_VECTOR
-                       dev->rx_pkt_burst = ixgbe_recv_scattered_pkts_vec;
-#else
-                       dev->rx_pkt_burst = ixgbe_recv_scattered_pkts;
+                       if (rte_is_power_of_2(rxq->nb_rx_desc))
+                               dev->rx_pkt_burst =
+                                       ixgbe_recv_scattered_pkts_vec;
+                       else
 #endif
+                               dev->rx_pkt_burst = ixgbe_recv_scattered_pkts;
                }
        }
 
-       if (dev->data->dev_conf.rxmode.enable_scatter) {
-               if (!dev->data->scattered_rx)
-                       PMD_INIT_LOG(DEBUG, "forcing scatter mode");
-#ifdef RTE_IXGBE_INC_VECTOR
-               dev->rx_pkt_burst = ixgbe_recv_scattered_pkts_vec;
-#else
-               dev->rx_pkt_burst = ixgbe_recv_scattered_pkts;
-#endif
-               dev->data->scattered_rx = 1;
-       }
-
        /*
         * Device configured with multiple RX queues.
         */
@@ -3731,7 +3792,7 @@ ixgbe_setup_loopback_link_82599(struct ixgbe_hw *hw)
 /*
  * Start Transmit and Receive Units.
  */
-void
+int
 ixgbe_dev_rxtx_start(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw     *hw;
@@ -3741,6 +3802,7 @@ ixgbe_dev_rxtx_start(struct rte_eth_dev *dev)
        uint32_t dmatxctl;
        uint32_t rxctrl;
        uint16_t i;
+       int ret = 0;
 
        PMD_INIT_FUNC_TRACE();
        hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -3763,14 +3825,20 @@ 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];
-               if (!txq->tx_deferred_start)
-                       ixgbe_dev_tx_queue_start(dev, i);
+               if (!txq->tx_deferred_start) {
+                       ret = ixgbe_dev_tx_queue_start(dev, i);
+                       if (ret < 0)
+                               return ret;
+               }
        }
 
        for (i = 0; i < dev->data->nb_rx_queues; i++) {
                rxq = dev->data->rx_queues[i];
-               if (!rxq->rx_deferred_start)
-                       ixgbe_dev_rx_queue_start(dev, i);
+               if (!rxq->rx_deferred_start) {
+                       ret = ixgbe_dev_rx_queue_start(dev, i);
+                       if (ret < 0)
+                               return ret;
+               }
        }
 
        /* Enable Receive engine */
@@ -3785,6 +3853,7 @@ ixgbe_dev_rxtx_start(struct rte_eth_dev *dev)
                        dev->data->dev_conf.lpbk_mode == IXGBE_LPBK_82599_TX_RX)
                ixgbe_setup_loopback_link_82599(hw);
 
+       return 0;
 }
 
 /*
@@ -3985,7 +4054,7 @@ ixgbevf_dev_rx_init(struct rte_eth_dev *dev)
        struct igb_rx_queue *rxq;
        struct rte_pktmbuf_pool_private *mbp_priv;
        uint64_t bus_addr;
-       uint32_t srrctl;
+       uint32_t srrctl, psrtype = 0;
        uint16_t buf_size;
        uint16_t i;
        int ret;
@@ -3993,6 +4062,19 @@ ixgbevf_dev_rx_init(struct rte_eth_dev *dev)
        PMD_INIT_FUNC_TRACE();
        hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
+       if (rte_is_power_of_2(dev->data->nb_rx_queues) == 0) {
+               PMD_INIT_LOG(ERR, "The number of Rx queue invalid, "
+                       "it should be power of 2");
+               return -1;
+       }
+
+       if (dev->data->nb_rx_queues > hw->mac.max_rx_queues) {
+               PMD_INIT_LOG(ERR, "The number of Rx queue invalid, "
+                       "it should be equal to or less than %d",
+                       hw->mac.max_rx_queues);
+               return -1;
+       }
+
        /*
         * When the VF driver issues a IXGBE_VF_RESET request, the PF driver
         * disables the VF receipt of packets if the PF MTU is > 1500.
@@ -4039,20 +4121,10 @@ ixgbevf_dev_rx_init(struct rte_eth_dev *dev)
                 * Configure Header Split
                 */
                if (dev->data->dev_conf.rxmode.header_split) {
-
-                       /* Must setup the PSRTYPE register */
-                       uint32_t psrtype;
-                       psrtype = IXGBE_PSRTYPE_TCPHDR |
-                               IXGBE_PSRTYPE_UDPHDR   |
-                               IXGBE_PSRTYPE_IPV4HDR  |
-                               IXGBE_PSRTYPE_IPV6HDR;
-
-                       IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE(i), psrtype);
-
                        srrctl = ((dev->data->dev_conf.rxmode.split_hdr_size <<
-                                  IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
-                                 IXGBE_SRRCTL_BSIZEHDR_MASK);
-                       srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
+                               IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
+                               IXGBE_SRRCTL_BSIZEHDR_MASK);
+                       srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
                } else
 #endif
                        srrctl = IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
@@ -4081,30 +4153,36 @@ ixgbevf_dev_rx_init(struct rte_eth_dev *dev)
                buf_size = (uint16_t) ((srrctl & IXGBE_SRRCTL_BSIZEPKT_MASK) <<
                                       IXGBE_SRRCTL_BSIZEPKT_SHIFT);
 
-               /* It adds dual VLAN length for supporting dual VLAN */
-               if ((dev->data->dev_conf.rxmode.max_rx_pkt_len +
+               if (dev->data->dev_conf.rxmode.enable_scatter ||
+                   /* It adds dual VLAN length for supporting dual VLAN */
+                   (dev->data->dev_conf.rxmode.max_rx_pkt_len +
                                2 * IXGBE_VLAN_TAG_SIZE) > buf_size) {
                        if (!dev->data->scattered_rx)
                                PMD_INIT_LOG(DEBUG, "forcing scatter mode");
                        dev->data->scattered_rx = 1;
 #ifdef RTE_IXGBE_INC_VECTOR
-                       dev->rx_pkt_burst = ixgbe_recv_scattered_pkts_vec;
-#else
-                       dev->rx_pkt_burst = ixgbe_recv_scattered_pkts;
+                       if (rte_is_power_of_2(rxq->nb_rx_desc))
+                               dev->rx_pkt_burst =
+                                       ixgbe_recv_scattered_pkts_vec;
+                       else
 #endif
+                               dev->rx_pkt_burst = ixgbe_recv_scattered_pkts;
                }
        }
 
-       if (dev->data->dev_conf.rxmode.enable_scatter) {
-               if (!dev->data->scattered_rx)
-                       PMD_INIT_LOG(DEBUG, "forcing scatter mode");
-#ifdef RTE_IXGBE_INC_VECTOR
-               dev->rx_pkt_burst = ixgbe_recv_scattered_pkts_vec;
-#else
-               dev->rx_pkt_burst = ixgbe_recv_scattered_pkts;
+#ifdef RTE_HEADER_SPLIT_ENABLE
+       if (dev->data->dev_conf.rxmode.header_split)
+               /* Must setup the PSRTYPE register */
+               psrtype = IXGBE_PSRTYPE_TCPHDR |
+                       IXGBE_PSRTYPE_UDPHDR   |
+                       IXGBE_PSRTYPE_IPV4HDR  |
+                       IXGBE_PSRTYPE_IPV6HDR;
 #endif
-               dev->data->scattered_rx = 1;
-       }
+
+       /* Set RQPL for VF RSS according to max Rx queue */
+       psrtype |= (dev->data->nb_rx_queues >> 1) <<
+               IXGBE_PSRTYPE_RQPL_SHIFT;
+       IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype);
 
        return 0;
 }