ixgbe: fix link issue in loopback mode
[dpdk.git] / lib / librte_pmd_e1000 / igb_ethdev.c
index 92ac4a8..2a268b8 100644 (file)
 #include "e1000/e1000_api.h"
 #include "e1000_ethdev.h"
 
+/*
+ * Default values for port configuration
+ */
+#define IGB_DEFAULT_RX_FREE_THRESH  32
+#define IGB_DEFAULT_RX_PTHRESH      8
+#define IGB_DEFAULT_RX_HTHRESH      8
+#define IGB_DEFAULT_RX_WTHRESH      0
+
+#define IGB_DEFAULT_TX_PTHRESH      32
+#define IGB_DEFAULT_TX_HTHRESH      0
+#define IGB_DEFAULT_TX_WTHRESH      0
+
+/* Bit shift and mask */
+#define IGB_4_BIT_WIDTH  (CHAR_BIT / 2)
+#define IGB_4_BIT_MASK   RTE_LEN2MASK(IGB_4_BIT_WIDTH, uint8_t)
+#define IGB_8_BIT_WIDTH  CHAR_BIT
+#define IGB_8_BIT_MASK   UINT8_MAX
+
 static int  eth_igb_configure(struct rte_eth_dev *dev);
 static int  eth_igb_start(struct rte_eth_dev *dev);
 static void eth_igb_stop(struct rte_eth_dev *dev);
@@ -71,6 +89,8 @@ static void eth_igb_stats_get(struct rte_eth_dev *dev,
                                struct rte_eth_stats *rte_stats);
 static void eth_igb_stats_reset(struct rte_eth_dev *dev);
 static void eth_igb_infos_get(struct rte_eth_dev *dev,
+                             struct rte_eth_dev_info *dev_info);
+static void eth_igbvf_infos_get(struct rte_eth_dev *dev,
                                struct rte_eth_dev_info *dev_info);
 static int  eth_igb_flow_ctrl_get(struct rte_eth_dev *dev,
                                struct rte_eth_fc_conf *fc_conf);
@@ -87,6 +107,8 @@ static void igb_hw_control_release(struct e1000_hw *hw);
 static void igb_init_manageability(struct e1000_hw *hw);
 static void igb_release_manageability(struct e1000_hw *hw);
 
+static int  eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
+
 static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev,
                uint16_t vlan_id, int on);
 static void eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid_id);
@@ -122,23 +144,16 @@ static int igbvf_vlan_filter_set(struct rte_eth_dev *dev,
 static int igbvf_set_vfta(struct e1000_hw *hw, uint16_t vid, bool on);
 static void igbvf_set_vfta_all(struct rte_eth_dev *dev, bool on);
 static int eth_igb_rss_reta_update(struct rte_eth_dev *dev,
-                struct rte_eth_rss_reta *reta_conf);
+                                  struct rte_eth_rss_reta_entry64 *reta_conf,
+                                  uint16_t reta_size);
 static int eth_igb_rss_reta_query(struct rte_eth_dev *dev,
-               struct rte_eth_rss_reta *reta_conf);
-
+                                 struct rte_eth_rss_reta_entry64 *reta_conf,
+                                 uint16_t reta_size);
 static int eth_igb_add_syn_filter(struct rte_eth_dev *dev,
                        struct rte_syn_filter *filter, uint16_t rx_queue);
 static int eth_igb_remove_syn_filter(struct rte_eth_dev *dev);
 static int eth_igb_get_syn_filter(struct rte_eth_dev *dev,
                        struct rte_syn_filter *filter, uint16_t *rx_queue);
-static int eth_igb_add_ethertype_filter(struct rte_eth_dev *dev,
-                       uint16_t index,
-                       struct rte_ethertype_filter *filter, uint16_t rx_queue);
-static int eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev,
-                       uint16_t index);
-static int eth_igb_get_ethertype_filter(struct rte_eth_dev *dev,
-                       uint16_t index,
-                       struct rte_ethertype_filter *filter, uint16_t *rx_queue);
 static int eth_igb_add_2tuple_filter(struct rte_eth_dev *dev,
                        uint16_t index,
                        struct rte_2tuple_filter *filter, uint16_t rx_queue);
@@ -163,6 +178,18 @@ static int eth_igb_remove_5tuple_filter(struct rte_eth_dev *dev,
 static int eth_igb_get_5tuple_filter(struct rte_eth_dev *dev,
                        uint16_t index,
                        struct rte_5tuple_filter *filter, uint16_t *rx_queue);
+static int igb_add_del_ethertype_filter(struct rte_eth_dev *dev,
+                       struct rte_eth_ethertype_filter *filter,
+                       bool add);
+static int igb_ethertype_filter_handle(struct rte_eth_dev *dev,
+                               enum rte_filter_op filter_op,
+                               void *arg);
+static int igb_get_ethertype_filter(struct rte_eth_dev *dev,
+                       struct rte_eth_ethertype_filter *filter);
+static int eth_igb_filter_ctrl(struct rte_eth_dev *dev,
+                    enum rte_filter_type filter_type,
+                    enum rte_filter_op filter_op,
+                    void *arg);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -218,6 +245,7 @@ static struct eth_dev_ops eth_igb_ops = {
        .stats_get            = eth_igb_stats_get,
        .stats_reset          = eth_igb_stats_reset,
        .dev_infos_get        = eth_igb_infos_get,
+       .mtu_set              = eth_igb_mtu_set,
        .vlan_filter_set      = eth_igb_vlan_filter_set,
        .vlan_tpid_set        = eth_igb_vlan_tpid_set,
        .vlan_offload_set     = eth_igb_vlan_offload_set,
@@ -240,9 +268,6 @@ static struct eth_dev_ops eth_igb_ops = {
        .add_syn_filter          = eth_igb_add_syn_filter,
        .remove_syn_filter       = eth_igb_remove_syn_filter,
        .get_syn_filter          = eth_igb_get_syn_filter,
-       .add_ethertype_filter    = eth_igb_add_ethertype_filter,
-       .remove_ethertype_filter = eth_igb_remove_ethertype_filter,
-       .get_ethertype_filter    = eth_igb_get_ethertype_filter,
        .add_2tuple_filter       = eth_igb_add_2tuple_filter,
        .remove_2tuple_filter    = eth_igb_remove_2tuple_filter,
        .get_2tuple_filter       = eth_igb_get_2tuple_filter,
@@ -252,6 +277,7 @@ static struct eth_dev_ops eth_igb_ops = {
        .add_5tuple_filter       = eth_igb_add_5tuple_filter,
        .remove_5tuple_filter    = eth_igb_remove_5tuple_filter,
        .get_5tuple_filter       = eth_igb_get_5tuple_filter,
+       .filter_ctrl             = eth_igb_filter_ctrl,
 };
 
 /*
@@ -267,7 +293,7 @@ static struct eth_dev_ops igbvf_eth_dev_ops = {
        .stats_get            = eth_igbvf_stats_get,
        .stats_reset          = eth_igbvf_stats_reset,
        .vlan_filter_set      = igbvf_vlan_filter_set,
-       .dev_infos_get        = eth_igb_infos_get,
+       .dev_infos_get        = eth_igbvf_infos_get,
        .rx_queue_setup       = eth_igb_rx_queue_setup,
        .rx_queue_release     = eth_igb_rx_queue_release,
        .tx_queue_setup       = eth_igb_tx_queue_setup,
@@ -397,7 +423,7 @@ igb_reset_swfw_lock(struct e1000_hw *hw)
         * So force the release of the faulty lock.
         */
        if (e1000_get_hw_semaphore_generic(hw) < 0) {
-               DEBUGOUT("SMBI lock released");
+               PMD_DRV_LOG(DEBUG, "SMBI lock released");
        }
        e1000_put_hw_semaphore_generic(hw);
 
@@ -413,7 +439,8 @@ igb_reset_swfw_lock(struct e1000_hw *hw)
                if (hw->bus.func > E1000_FUNC_1)
                        mask <<= 2;
                if (hw->mac.ops.acquire_swfw_sync(hw, mask) < 0) {
-                       DEBUGOUT1("SWFW phy%d lock released", hw->bus.func);
+                       PMD_DRV_LOG(DEBUG, "SWFW phy%d lock released",
+                                   hw->bus.func);
                }
                hw->mac.ops.release_swfw_sync(hw, mask);
 
@@ -425,7 +452,7 @@ igb_reset_swfw_lock(struct e1000_hw *hw)
                 */
                mask = E1000_SWFW_EEP_SM;
                if (hw->mac.ops.acquire_swfw_sync(hw, mask) < 0) {
-                       DEBUGOUT("SWFW common locks released");
+                       PMD_DRV_LOG(DEBUG, "SWFW common locks released");
                }
                hw->mac.ops.release_swfw_sync(hw, mask);
        }
@@ -561,7 +588,7 @@ eth_igb_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
        E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
        E1000_WRITE_FLUSH(hw);
 
-       PMD_INIT_LOG(INFO, "port_id %d vendorID=0x%x deviceID=0x%x\n",
+       PMD_INIT_LOG(INFO, "port_id %d vendorID=0x%x deviceID=0x%x",
                     eth_dev->data->port_id, pci_dev->id.vendor_id,
                     pci_dev->id.device_id);
 
@@ -594,7 +621,7 @@ eth_igbvf_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
                E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
        int diag;
 
-       PMD_INIT_LOG(DEBUG, "eth_igbvf_dev_init");
+       PMD_INIT_FUNC_TRACE();
 
        eth_dev->dev_ops = &igbvf_eth_dev_ops;
        eth_dev->rx_pkt_burst = &eth_igb_recv_pkts;
@@ -615,7 +642,7 @@ eth_igbvf_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
        hw->vendor_id = pci_dev->id.vendor_id;
        hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
 
-       /* Initialize the shared code */
+       /* Initialize the shared code (base driver) */
        diag = e1000_setup_init_funcs(hw, TRUE);
        if (diag != 0) {
                PMD_INIT_LOG(ERR, "Shared code init failed for igbvf: %d",
@@ -646,11 +673,10 @@ eth_igbvf_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
        ether_addr_copy((struct ether_addr *) hw->mac.perm_addr,
                        &eth_dev->data->mac_addrs[0]);
 
-       PMD_INIT_LOG(DEBUG, "\nport %d vendorID=0x%x deviceID=0x%x "
-                       "mac.type=%s\n",
-                       eth_dev->data->port_id, pci_dev->id.vendor_id,
-                       pci_dev->id.device_id,
-                       "igb_mac_82576_vf");
+       PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x "
+                    "mac.type=%s",
+                    eth_dev->data->port_id, pci_dev->id.vendor_id,
+                    pci_dev->id.device_id, "igb_mac_82576_vf");
 
        return 0;
 }
@@ -659,7 +685,7 @@ static struct eth_driver rte_igb_pmd = {
        {
                .name = "rte_igb_pmd",
                .id_table = pci_id_igb_map,
-               .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+               .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
        },
        .eth_dev_init = eth_igb_dev_init,
        .dev_private_size = sizeof(struct e1000_adapter),
@@ -704,7 +730,7 @@ igb_vmdq_vlan_hw_filter_enable(struct rte_eth_dev *dev)
 static int
 rte_igbvf_pmd_init(const char *name __rte_unused, const char *params __rte_unused)
 {
-       DEBUGFUNC("rte_igbvf_pmd_init");
+       PMD_INIT_FUNC_TRACE();
 
        rte_eth_driver_register(&rte_igbvf_pmd);
        return (0);
@@ -716,11 +742,9 @@ eth_igb_configure(struct rte_eth_dev *dev)
        struct e1000_interrupt *intr =
                E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
 
-       PMD_INIT_LOG(DEBUG, ">>");
-
+       PMD_INIT_FUNC_TRACE();
        intr->flags |= E1000_FLAG_NEED_LINK_UPDATE;
-
-       PMD_INIT_LOG(DEBUG, "<<");
+       PMD_INIT_FUNC_TRACE();
 
        return (0);
 }
@@ -733,7 +757,7 @@ eth_igb_start(struct rte_eth_dev *dev)
        int ret, i, mask;
        uint32_t ctrl_ext;
 
-       PMD_INIT_LOG(DEBUG, ">>");
+       PMD_INIT_FUNC_TRACE();
 
        /* Power up the phy. Needed to make the link go Up */
        e1000_power_up_phy(hw);
@@ -815,7 +839,8 @@ eth_igb_start(struct rte_eth_dev *dev)
         * value of Write-Back Threshold registers.
         */
        if ((hw->mac.type == e1000_82576) || (hw->mac.type == e1000_82580) ||
-               (hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i210)) {
+               (hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i210) ||
+               (hw->mac.type == e1000_i211)) {
                uint32_t ivar;
 
                /* Enable all RX & TX queues in the IVAR registers */
@@ -884,9 +909,9 @@ eth_igb_start(struct rte_eth_dev *dev)
        return (0);
 
 error_invalid_config:
-       PMD_INIT_LOG(ERR, "Invalid link_speed/link_duplex (%u/%u) for port %u\n",
-                       dev->data->dev_conf.link_speed,
-                       dev->data->dev_conf.link_duplex, dev->data->port_id);
+       PMD_INIT_LOG(ERR, "Invalid link_speed/link_duplex (%u/%u) for port %u",
+                    dev->data->dev_conf.link_speed,
+                    dev->data->dev_conf.link_duplex, dev->data->port_id);
        igb_dev_clear_queues(dev);
        return (-EINVAL);
 }
@@ -963,7 +988,7 @@ igb_get_rx_buffer_size(struct e1000_hw *hw)
                rx_buf_size = (E1000_READ_REG(hw, E1000_RXPBS) & 0xf);
                rx_buf_size = (uint32_t) e1000_rxpbs_adjust_82580(rx_buf_size);
                rx_buf_size = (rx_buf_size << 10);
-       } else if (hw->mac.type == e1000_i210) {
+       } else if (hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211) {
                rx_buf_size = (E1000_READ_REG(hw, E1000_RXPBS) & 0x3f) << 10;
        } else {
                rx_buf_size = (E1000_READ_REG(hw, E1000_PBA) & 0xffff) << 10;
@@ -1225,7 +1250,6 @@ eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
        if (rte_stats == NULL)
                return;
 
-       memset(rte_stats, 0, sizeof(*rte_stats));
        rte_stats->ipackets = hw_stats->gprc;
        rte_stats->ibytes = hw_stats->gorc;
        rte_stats->opackets = hw_stats->gptc;
@@ -1254,8 +1278,7 @@ eth_igbvf_stats_reset(struct rte_eth_dev *dev)
 }
 
 static void
-eth_igb_infos_get(struct rte_eth_dev *dev,
-                   struct rte_eth_dev_info *dev_info)
+eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
        struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
@@ -1285,18 +1308,21 @@ eth_igb_infos_get(struct rte_eth_dev *dev,
                dev_info->max_rx_queues = 16;
                dev_info->max_tx_queues = 16;
                dev_info->max_vmdq_pools = ETH_8_POOLS;
+               dev_info->vmdq_queue_num = 16;
                break;
 
        case e1000_82580:
                dev_info->max_rx_queues = 8;
                dev_info->max_tx_queues = 8;
                dev_info->max_vmdq_pools = ETH_8_POOLS;
+               dev_info->vmdq_queue_num = 8;
                break;
 
        case e1000_i350:
                dev_info->max_rx_queues = 8;
                dev_info->max_tx_queues = 8;
                dev_info->max_vmdq_pools = ETH_8_POOLS;
+               dev_info->vmdq_queue_num = 8;
                break;
 
        case e1000_i354:
@@ -1310,24 +1336,87 @@ eth_igb_infos_get(struct rte_eth_dev *dev,
                dev_info->max_vmdq_pools = 0;
                break;
 
-       case e1000_vfadapt:
+       case e1000_i211:
                dev_info->max_rx_queues = 2;
                dev_info->max_tx_queues = 2;
                dev_info->max_vmdq_pools = 0;
                break;
 
+       default:
+               /* Should not happen */
+               break;
+       }
+       dev_info->reta_size = ETH_RSS_RETA_SIZE_128;
+
+       dev_info->default_rxconf = (struct rte_eth_rxconf) {
+               .rx_thresh = {
+                       .pthresh = IGB_DEFAULT_RX_PTHRESH,
+                       .hthresh = IGB_DEFAULT_RX_HTHRESH,
+                       .wthresh = IGB_DEFAULT_RX_WTHRESH,
+               },
+               .rx_free_thresh = IGB_DEFAULT_RX_FREE_THRESH,
+               .rx_drop_en = 0,
+       };
+
+       dev_info->default_txconf = (struct rte_eth_txconf) {
+               .tx_thresh = {
+                       .pthresh = IGB_DEFAULT_TX_PTHRESH,
+                       .hthresh = IGB_DEFAULT_TX_HTHRESH,
+                       .wthresh = IGB_DEFAULT_TX_WTHRESH,
+               },
+               .txq_flags = 0,
+       };
+}
+
+static void
+eth_igbvf_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       dev_info->min_rx_bufsize = 256; /* See BSIZE field of RCTL register. */
+       dev_info->max_rx_pktlen  = 0x3FFF; /* See RLPML register. */
+       dev_info->max_mac_addrs = hw->mac.rar_entry_count;
+       dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP |
+                               DEV_RX_OFFLOAD_IPV4_CKSUM |
+                               DEV_RX_OFFLOAD_UDP_CKSUM  |
+                               DEV_RX_OFFLOAD_TCP_CKSUM;
+       dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT |
+                               DEV_TX_OFFLOAD_IPV4_CKSUM  |
+                               DEV_TX_OFFLOAD_UDP_CKSUM   |
+                               DEV_TX_OFFLOAD_TCP_CKSUM   |
+                               DEV_TX_OFFLOAD_SCTP_CKSUM;
+       switch (hw->mac.type) {
+       case e1000_vfadapt:
+               dev_info->max_rx_queues = 2;
+               dev_info->max_tx_queues = 2;
+               break;
        case e1000_vfadapt_i350:
                dev_info->max_rx_queues = 1;
                dev_info->max_tx_queues = 1;
-               dev_info->max_vmdq_pools = 0;
                break;
-
        default:
                /* Should not happen */
-               dev_info->max_rx_queues = 0;
-               dev_info->max_tx_queues = 0;
-               dev_info->max_vmdq_pools = 0;
+               break;
        }
+
+       dev_info->default_rxconf = (struct rte_eth_rxconf) {
+               .rx_thresh = {
+                       .pthresh = IGB_DEFAULT_RX_PTHRESH,
+                       .hthresh = IGB_DEFAULT_RX_HTHRESH,
+                       .wthresh = IGB_DEFAULT_RX_WTHRESH,
+               },
+               .rx_free_thresh = IGB_DEFAULT_RX_FREE_THRESH,
+               .rx_drop_en = 0,
+       };
+
+       dev_info->default_txconf = (struct rte_eth_txconf) {
+               .tx_thresh = {
+                       .pthresh = IGB_DEFAULT_TX_PTHRESH,
+                       .hthresh = IGB_DEFAULT_TX_HTHRESH,
+                       .wthresh = IGB_DEFAULT_TX_WTHRESH,
+               },
+               .txq_flags = 0,
+       };
 }
 
 /* return 0 means link status changed, -1 means not changed */
@@ -1786,19 +1875,20 @@ eth_igb_interrupt_action(struct rte_eth_dev *dev)
                rte_igb_dev_atomic_read_link_status(dev, &link);
                if (link.link_status) {
                        PMD_INIT_LOG(INFO,
-                               " Port %d: Link Up - speed %u Mbps - %s\n",
-                               dev->data->port_id, (unsigned)link.link_speed,
-                               link.link_duplex == ETH_LINK_FULL_DUPLEX ?
-                                       "full-duplex" : "half-duplex");
+                                    " Port %d: Link Up - speed %u Mbps - %s",
+                                    dev->data->port_id,
+                                    (unsigned)link.link_speed,
+                                    link.link_duplex == ETH_LINK_FULL_DUPLEX ?
+                                    "full-duplex" : "half-duplex");
                } else {
-                       PMD_INIT_LOG(INFO, " Port %d: Link Down\n",
-                                               dev->data->port_id);
+                       PMD_INIT_LOG(INFO, " Port %d: Link Down",
+                                    dev->data->port_id);
                }
                PMD_INIT_LOG(INFO, "PCI Address: %04d:%02d:%02d:%d",
-                                       dev->pci_dev->addr.domain,
-                                       dev->pci_dev->addr.bus,
-                                       dev->pci_dev->addr.devid,
-                                       dev->pci_dev->addr.function);
+                            dev->pci_dev->addr.domain,
+                            dev->pci_dev->addr.bus,
+                            dev->pci_dev->addr.devid,
+                            dev->pci_dev->addr.function);
                tctl = E1000_READ_REG(hw, E1000_TCTL);
                rctl = E1000_READ_REG(hw, E1000_RCTL);
                if (link.link_status) {
@@ -1871,6 +1961,7 @@ eth_igb_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
        fc_conf->high_water = hw->fc.high_water;
        fc_conf->low_water = hw->fc.low_water;
        fc_conf->send_xon = hw->fc.send_xon;
+       fc_conf->autoneg = hw->mac.autoneg;
 
        /*
         * Return rx_pause and tx_pause status according to actual setting of
@@ -1915,15 +2006,17 @@ eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
        uint32_t rctl;
 
        hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       if (fc_conf->autoneg != hw->mac.autoneg)
+               return -ENOTSUP;
        rx_buf_size = igb_get_rx_buffer_size(hw);
-       PMD_INIT_LOG(DEBUG, "Rx packet buffer size = 0x%x \n", rx_buf_size);
+       PMD_INIT_LOG(DEBUG, "Rx packet buffer size = 0x%x", rx_buf_size);
 
        /* At least reserve one Ethernet frame for watermark */
        max_high_water = rx_buf_size - ETHER_MAX_LEN;
        if ((fc_conf->high_water > max_high_water) ||
-               (fc_conf->high_water < fc_conf->low_water)) {
-               PMD_INIT_LOG(ERR, "e1000 incorrect high/low water value \n");
-               PMD_INIT_LOG(ERR, "high water must <=  0x%x \n", max_high_water);
+           (fc_conf->high_water < fc_conf->low_water)) {
+               PMD_INIT_LOG(ERR, "e1000 incorrect high/low water value");
+               PMD_INIT_LOG(ERR, "high water must <=  0x%x", max_high_water);
                return (-EINVAL);
        }
 
@@ -1953,7 +2046,7 @@ eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
                return 0;
        }
 
-       PMD_INIT_LOG(ERR, "e1000_setup_link_generic = 0x%x \n", err);
+       PMD_INIT_LOG(ERR, "e1000_setup_link_generic = 0x%x", err);
        return (-EIO);
 }
 
@@ -1988,7 +2081,7 @@ eth_igb_rar_clear(struct rte_eth_dev *dev, uint32_t index)
 static void
 igbvf_intr_disable(struct e1000_hw *hw)
 {
-       PMD_INIT_LOG(DEBUG, "igbvf_intr_disable");
+       PMD_INIT_FUNC_TRACE();
 
        /* Clear interrupt mask to stop from interrupts being generated */
        E1000_WRITE_REG(hw, E1000_EIMC, 0xFFFF);
@@ -2005,7 +2098,7 @@ igbvf_stop_adapter(struct rte_eth_dev *dev)
        struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
        memset(&dev_info, 0, sizeof(dev_info));
-       eth_igb_infos_get(dev, &dev_info);
+       eth_igbvf_infos_get(dev, &dev_info);
 
        /* Clear interrupt mask to stop from interrupts being generated */
        igbvf_intr_disable(hw);
@@ -2070,8 +2163,8 @@ igbvf_dev_configure(struct rte_eth_dev *dev)
 {
        struct rte_eth_conf* conf = &dev->data->dev_conf;
 
-       PMD_INIT_LOG(DEBUG, "\nConfigured Virtual Function port id: %d\n",
-               dev->data->port_id);
+       PMD_INIT_LOG(DEBUG, "Configured Virtual Function port id: %d",
+                    dev->data->port_id);
 
        /*
         * VF has no ability to enable/disable HW CRC
@@ -2079,12 +2172,12 @@ igbvf_dev_configure(struct rte_eth_dev *dev)
         */
 #ifndef RTE_LIBRTE_E1000_PF_DISABLE_STRIP_CRC
        if (!conf->rxmode.hw_strip_crc) {
-               PMD_INIT_LOG(INFO, "VF can't disable HW CRC Strip\n");
+               PMD_INIT_LOG(INFO, "VF can't disable HW CRC Strip");
                conf->rxmode.hw_strip_crc = 1;
        }
 #else
        if (conf->rxmode.hw_strip_crc) {
-               PMD_INIT_LOG(INFO, "VF can't enable HW CRC Strip\n");
+               PMD_INIT_LOG(INFO, "VF can't enable HW CRC Strip");
                conf->rxmode.hw_strip_crc = 0;
        }
 #endif
@@ -2099,7 +2192,7 @@ igbvf_dev_start(struct rte_eth_dev *dev)
                E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        int ret;
 
-       PMD_INIT_LOG(DEBUG, "igbvf_dev_start");
+       PMD_INIT_FUNC_TRACE();
 
        hw->mac.ops.reset_hw(hw);
 
@@ -2122,7 +2215,7 @@ igbvf_dev_start(struct rte_eth_dev *dev)
 static void
 igbvf_dev_stop(struct rte_eth_dev *dev)
 {
-       PMD_INIT_LOG(DEBUG, "igbvf_dev_stop");
+       PMD_INIT_FUNC_TRACE();
 
        igbvf_stop_adapter(dev);
 
@@ -2140,7 +2233,7 @@ igbvf_dev_close(struct rte_eth_dev *dev)
 {
        struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
-       PMD_INIT_LOG(DEBUG, "igbvf_dev_close");
+       PMD_INIT_FUNC_TRACE();
 
        e1000_reset_hw(hw);
 
@@ -2196,7 +2289,7 @@ igbvf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
        uint32_t vid_bit = 0;
        int ret = 0;
 
-       PMD_INIT_LOG(DEBUG, "igbvf_vlan_filter_set");
+       PMD_INIT_FUNC_TRACE();
 
        /*vind is not used in VF driver, set to 0, check ixgbe_set_vfta_vf*/
        ret = igbvf_set_vfta(hw, vlan_id, !!on);
@@ -2218,38 +2311,40 @@ igbvf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
 
 static int
 eth_igb_rss_reta_update(struct rte_eth_dev *dev,
-                                struct rte_eth_rss_reta *reta_conf)
+                       struct rte_eth_rss_reta_entry64 *reta_conf,
+                       uint16_t reta_size)
 {
-       uint8_t i,j,mask;
-       uint32_t reta;
-       struct e1000_hw *hw =
-                       E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint8_t i, j, mask;
+       uint32_t reta, r;
+       uint16_t idx, shift;
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
-       /*
-        * Update Redirection Table RETA[n],n=0...31,The redirection table has
-        * 128-entries in 32 registers
-        */
-       for(i = 0; i < ETH_RSS_RETA_NUM_ENTRIES; i += 4) {
-               if (i < ETH_RSS_RETA_NUM_ENTRIES/2)
-                       mask = (uint8_t)((reta_conf->mask_lo >> i) & 0xF);
+       if (reta_size != ETH_RSS_RETA_SIZE_128) {
+               PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
+                       "(%d) doesn't match the number hardware can supported "
+                       "(%d)\n", reta_size, ETH_RSS_RETA_SIZE_128);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < reta_size; i += IGB_4_BIT_WIDTH) {
+               idx = i / RTE_RETA_GROUP_SIZE;
+               shift = i % RTE_RETA_GROUP_SIZE;
+               mask = (uint8_t)((reta_conf[idx].mask >> shift) &
+                                               IGB_4_BIT_MASK);
+               if (!mask)
+                       continue;
+               if (mask == IGB_4_BIT_MASK)
+                       r = 0;
                else
-                       mask = (uint8_t)((reta_conf->mask_hi >>
-                               (i - ETH_RSS_RETA_NUM_ENTRIES/2)) & 0xF);
-               if (mask != 0) {
-                       reta = 0;
-                       /* If all 4 entries were set,don't need read RETA register */
-                       if (mask != 0xF)
-                               reta = E1000_READ_REG(hw,E1000_RETA(i >> 2));
-
-                       for (j = 0; j < 4; j++) {
-                               if (mask & (0x1 << j)) {
-                                       if (mask != 0xF)
-                                               reta &= ~(0xFF << 8 * j);
-                                       reta |= reta_conf->reta[i + j] << 8 * j;
-                               }
-                       }
-                       E1000_WRITE_REG(hw, E1000_RETA(i >> 2),reta);
+                       r = E1000_READ_REG(hw, E1000_RETA(i >> 2));
+               for (j = 0, reta = 0; j < IGB_4_BIT_WIDTH; j++) {
+                       if (mask & (0x1 << j))
+                               reta |= reta_conf[idx].reta[shift + j] <<
+                                                       (CHAR_BIT * j);
+                       else
+                               reta |= r & (IGB_8_BIT_MASK << (CHAR_BIT * j));
                }
+               E1000_WRITE_REG(hw, E1000_RETA(i >> 2), reta);
        }
 
        return 0;
@@ -2257,31 +2352,34 @@ eth_igb_rss_reta_update(struct rte_eth_dev *dev,
 
 static int
 eth_igb_rss_reta_query(struct rte_eth_dev *dev,
-                                struct rte_eth_rss_reta *reta_conf)
+                      struct rte_eth_rss_reta_entry64 *reta_conf,
+                      uint16_t reta_size)
 {
-       uint8_t i,j,mask;
+       uint8_t i, j, mask;
        uint32_t reta;
-       struct e1000_hw *hw =
-                       E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint16_t idx, shift;
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
-       /*
-        * Read Redirection Table RETA[n],n=0...31,The redirection table has
-        * 128-entries in 32 registers
-        */
-       for(i = 0; i < ETH_RSS_RETA_NUM_ENTRIES; i += 4) {
-               if (i < ETH_RSS_RETA_NUM_ENTRIES/2)
-                       mask = (uint8_t)((reta_conf->mask_lo >> i) & 0xF);
-               else
-                       mask = (uint8_t)((reta_conf->mask_hi >>
-                               (i - ETH_RSS_RETA_NUM_ENTRIES/2)) & 0xF);
-
-               if (mask != 0) {
-                       reta = E1000_READ_REG(hw,E1000_RETA(i >> 2));
-                       for (j = 0; j < 4; j++) {
-                               if (mask & (0x1 << j))
-                                       reta_conf->reta[i + j] =
-                                               (uint8_t)((reta >> 8 * j) & 0xFF);
-                       }
+       if (reta_size != ETH_RSS_RETA_SIZE_128) {
+               PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
+                       "(%d) doesn't match the number hardware can supported "
+                       "(%d)\n", reta_size, ETH_RSS_RETA_SIZE_128);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < reta_size; i += IGB_4_BIT_WIDTH) {
+               idx = i / RTE_RETA_GROUP_SIZE;
+               shift = i % RTE_RETA_GROUP_SIZE;
+               mask = (uint8_t)((reta_conf[idx].mask >> shift) &
+                                               IGB_4_BIT_MASK);
+               if (!mask)
+                       continue;
+               reta = E1000_READ_REG(hw, E1000_RETA(i >> 2));
+               for (j = 0; j < IGB_4_BIT_WIDTH; j++) {
+                       if (mask & (0x1 << j))
+                               reta_conf[idx].reta[shift + j] =
+                                       ((reta >> (CHAR_BIT * j)) &
+                                               IGB_8_BIT_MASK);
                }
        }
 
@@ -2291,7 +2389,7 @@ eth_igb_rss_reta_query(struct rte_eth_dev *dev,
 #define MAC_TYPE_FILTER_SUP(type)    do {\
        if ((type) != e1000_82580 && (type) != e1000_i350 &&\
                (type) != e1000_82576)\
-               return -ENOSYS;\
+               return -ENOTSUP;\
 } while (0)
 
 /*
@@ -2388,111 +2486,6 @@ eth_igb_get_syn_filter(struct rte_eth_dev *dev,
        return -ENOENT;
 }
 
-/*
- * add an ethertype filter
- *
- * @param
- * dev: Pointer to struct rte_eth_dev.
- * index: the index the filter allocates.
- * filter: ponter to the filter that will be added.
- * rx_queue: the queue id the filter assigned to.
- *
- * @return
- *    - On success, zero.
- *    - On failure, a negative value.
- */
-static int
-eth_igb_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
-                       struct rte_ethertype_filter *filter, uint16_t rx_queue)
-{
-       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       uint32_t etqf;
-
-       MAC_TYPE_FILTER_SUP(hw->mac.type);
-
-       if (index >= E1000_MAX_ETQF_FILTERS || rx_queue >= IGB_MAX_RX_QUEUE_NUM)
-               return -EINVAL;
-
-       etqf = E1000_READ_REG(hw, E1000_ETQF(index));
-       if (etqf & E1000_ETQF_FILTER_ENABLE)
-               return -EINVAL;  /* filter index is in use. */
-       else
-               etqf = 0;
-
-       etqf |= E1000_ETQF_FILTER_ENABLE | E1000_ETQF_QUEUE_ENABLE;
-       etqf |= (uint32_t)(filter->ethertype & E1000_ETQF_ETHERTYPE);
-       etqf |= rx_queue << E1000_ETQF_QUEUE_SHIFT;
-
-       if (filter->priority_en) {
-               PMD_INIT_LOG(ERR, "vlan and priority (%d) is not supported"
-                       " in E1000.", filter->priority);
-               return -EINVAL;
-       }
-
-       E1000_WRITE_REG(hw, E1000_ETQF(index), etqf);
-       return 0;
-}
-
-/*
- * remove an ethertype filter
- *
- * @param
- * dev: Pointer to struct rte_eth_dev.
- * index: the index the filter allocates.
- *
- * @return
- *    - On success, zero.
- *    - On failure, a negative value.
- */
-static int
-eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev, uint16_t index)
-{
-       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-       MAC_TYPE_FILTER_SUP(hw->mac.type);
-
-       if (index >= E1000_MAX_ETQF_FILTERS)
-               return -EINVAL;
-
-       E1000_WRITE_REG(hw, E1000_ETQF(index), 0);
-       return 0;
-}
-
-/*
- * get an ethertype filter
- *
- * @param
- * dev: Pointer to struct rte_eth_dev.
- * index: the index the filter allocates.
- * filter: ponter to the filter that will be gotten.
- * *rx_queue: the ponited of the queue id the filter assigned to.
- *
- * @return
- *    - On success, zero.
- *    - On failure, a negative value.
- */
-static int
-eth_igb_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
-                       struct rte_ethertype_filter *filter, uint16_t *rx_queue)
-{
-       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       uint32_t etqf;
-
-       MAC_TYPE_FILTER_SUP(hw->mac.type);
-
-       if (index >= E1000_MAX_ETQF_FILTERS)
-               return -EINVAL;
-
-       etqf = E1000_READ_REG(hw, E1000_ETQF(index));
-       if (etqf & E1000_ETQF_FILTER_ENABLE) {
-               filter->ethertype = etqf & E1000_ETQF_ETHERTYPE;
-               filter->priority_en = 0;
-               *rx_queue = (etqf & E1000_ETQF_QUEUE) >> E1000_ETQF_QUEUE_SHIFT;
-               return 0;
-       }
-       return -ENOENT;
-}
-
 #define MAC_TYPE_FILTER_SUP_EXT(type)    do {\
        if ((type) != e1000_82580 && (type) != e1000_i350)\
                return -ENOSYS; \
@@ -3002,6 +2995,257 @@ eth_igb_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
        return -ENOENT;
 }
 
+static int
+eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
+{
+       uint32_t rctl;
+       struct e1000_hw *hw;
+       struct rte_eth_dev_info dev_info;
+       uint32_t frame_size = mtu + (ETHER_HDR_LEN + ETHER_CRC_LEN +
+                                    VLAN_TAG_SIZE);
+
+       hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+#ifdef RTE_LIBRTE_82571_SUPPORT
+       /* XXX: not bigger than max_rx_pktlen */
+       if (hw->mac.type == e1000_82571)
+               return -ENOTSUP;
+#endif
+       eth_igb_infos_get(dev, &dev_info);
+
+       /* check that mtu is within the allowed range */
+       if ((mtu < ETHER_MIN_MTU) ||
+           (frame_size > dev_info.max_rx_pktlen))
+               return -EINVAL;
+
+       /* refuse mtu that requires the support of scattered packets when this
+        * feature has not been enabled before. */
+       if (!dev->data->scattered_rx &&
+           frame_size > dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM)
+               return -EINVAL;
+
+       rctl = E1000_READ_REG(hw, E1000_RCTL);
+
+       /* switch to jumbo mode if needed */
+       if (frame_size > ETHER_MAX_LEN) {
+               dev->data->dev_conf.rxmode.jumbo_frame = 1;
+               rctl |= E1000_RCTL_LPE;
+       } else {
+               dev->data->dev_conf.rxmode.jumbo_frame = 0;
+               rctl &= ~E1000_RCTL_LPE;
+       }
+       E1000_WRITE_REG(hw, E1000_RCTL, rctl);
+
+       /* update max frame size */
+       dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
+
+       E1000_WRITE_REG(hw, E1000_RLPML,
+                       dev->data->dev_conf.rxmode.max_rx_pkt_len);
+
+       return 0;
+}
+
+static inline int
+igb_ethertype_filter_lookup(struct e1000_filter_info *filter_info,
+                       uint16_t ethertype)
+{
+       int i;
+
+       for (i = 0; i < E1000_MAX_ETQF_FILTERS; i++) {
+               if (filter_info->ethertype_filters[i] == ethertype &&
+                   (filter_info->ethertype_mask & (1 << i)))
+                       return i;
+       }
+       return -1;
+}
+
+static inline int
+igb_ethertype_filter_insert(struct e1000_filter_info *filter_info,
+                       uint16_t ethertype)
+{
+       int i;
+
+       for (i = 0; i < E1000_MAX_ETQF_FILTERS; i++) {
+               if (!(filter_info->ethertype_mask & (1 << i))) {
+                       filter_info->ethertype_mask |= 1 << i;
+                       filter_info->ethertype_filters[i] = ethertype;
+                       return i;
+               }
+       }
+       return -1;
+}
+
+static inline int
+igb_ethertype_filter_remove(struct e1000_filter_info *filter_info,
+                       uint8_t idx)
+{
+       if (idx >= E1000_MAX_ETQF_FILTERS)
+               return -1;
+       filter_info->ethertype_mask &= ~(1 << idx);
+       filter_info->ethertype_filters[idx] = 0;
+       return idx;
+}
+
+
+static int
+igb_add_del_ethertype_filter(struct rte_eth_dev *dev,
+                       struct rte_eth_ethertype_filter *filter,
+                       bool add)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct e1000_filter_info *filter_info =
+               E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+       uint32_t etqf = 0;
+       int ret;
+
+       if (filter->ether_type == ETHER_TYPE_IPv4 ||
+               filter->ether_type == ETHER_TYPE_IPv6) {
+               PMD_DRV_LOG(ERR, "unsupported ether_type(0x%04x) in"
+                       " ethertype filter.", filter->ether_type);
+               return -EINVAL;
+       }
+
+       if (filter->flags & RTE_ETHTYPE_FLAGS_MAC) {
+               PMD_DRV_LOG(ERR, "mac compare is unsupported.");
+               return -EINVAL;
+       }
+       if (filter->flags & RTE_ETHTYPE_FLAGS_DROP) {
+               PMD_DRV_LOG(ERR, "drop option is unsupported.");
+               return -EINVAL;
+       }
+
+       ret = igb_ethertype_filter_lookup(filter_info, filter->ether_type);
+       if (ret >= 0 && add) {
+               PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter exists.",
+                           filter->ether_type);
+               return -EEXIST;
+       }
+       if (ret < 0 && !add) {
+               PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter doesn't exist.",
+                           filter->ether_type);
+               return -ENOENT;
+       }
+
+       if (add) {
+               ret = igb_ethertype_filter_insert(filter_info,
+                       filter->ether_type);
+               if (ret < 0) {
+                       PMD_DRV_LOG(ERR, "ethertype filters are full.");
+                       return -ENOSYS;
+               }
+
+               etqf |= E1000_ETQF_FILTER_ENABLE | E1000_ETQF_QUEUE_ENABLE;
+               etqf |= (uint32_t)(filter->ether_type & E1000_ETQF_ETHERTYPE);
+               etqf |= filter->queue << E1000_ETQF_QUEUE_SHIFT;
+       } else {
+               ret = igb_ethertype_filter_remove(filter_info, (uint8_t)ret);
+               if (ret < 0)
+                       return -ENOSYS;
+       }
+       E1000_WRITE_REG(hw, E1000_ETQF(ret), etqf);
+       E1000_WRITE_FLUSH(hw);
+
+       return 0;
+}
+
+static int
+igb_get_ethertype_filter(struct rte_eth_dev *dev,
+                       struct rte_eth_ethertype_filter *filter)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct e1000_filter_info *filter_info =
+               E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+       uint32_t etqf;
+       int ret;
+
+       ret = igb_ethertype_filter_lookup(filter_info, filter->ether_type);
+       if (ret < 0) {
+               PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter doesn't exist.",
+                           filter->ether_type);
+               return -ENOENT;
+       }
+
+       etqf = E1000_READ_REG(hw, E1000_ETQF(ret));
+       if (etqf & E1000_ETQF_FILTER_ENABLE) {
+               filter->ether_type = etqf & E1000_ETQF_ETHERTYPE;
+               filter->flags = 0;
+               filter->queue = (etqf & E1000_ETQF_QUEUE) >>
+                               E1000_ETQF_QUEUE_SHIFT;
+               return 0;
+       }
+
+       return -ENOENT;
+}
+
+/*
+ * igb_ethertype_filter_handle - Handle operations for ethertype filter.
+ * @dev: pointer to rte_eth_dev structure
+ * @filter_op:operation will be taken.
+ * @arg: a pointer to specific structure corresponding to the filter_op
+ */
+static int
+igb_ethertype_filter_handle(struct rte_eth_dev *dev,
+                               enum rte_filter_op filter_op,
+                               void *arg)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       int ret;
+
+       MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+       if (filter_op == RTE_ETH_FILTER_NOP)
+               return 0;
+
+       if (arg == NULL) {
+               PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u.",
+                           filter_op);
+               return -EINVAL;
+       }
+
+       switch (filter_op) {
+       case RTE_ETH_FILTER_ADD:
+               ret = igb_add_del_ethertype_filter(dev,
+                       (struct rte_eth_ethertype_filter *)arg,
+                       TRUE);
+               break;
+       case RTE_ETH_FILTER_DELETE:
+               ret = igb_add_del_ethertype_filter(dev,
+                       (struct rte_eth_ethertype_filter *)arg,
+                       FALSE);
+               break;
+       case RTE_ETH_FILTER_GET:
+               ret = igb_get_ethertype_filter(dev,
+                       (struct rte_eth_ethertype_filter *)arg);
+               break;
+       default:
+               PMD_DRV_LOG(ERR, "unsupported operation %u.", filter_op);
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static int
+eth_igb_filter_ctrl(struct rte_eth_dev *dev,
+                    enum rte_filter_type filter_type,
+                    enum rte_filter_op filter_op,
+                    void *arg)
+{
+       int ret = -EINVAL;
+
+       switch (filter_type) {
+       case RTE_ETH_FILTER_ETHERTYPE:
+               ret = igb_ethertype_filter_handle(dev, filter_op, arg);
+               break;
+       default:
+               PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
+                                                       filter_type);
+               break;
+       }
+
+       return ret;
+}
+
 static struct rte_driver pmd_igb_drv = {
        .type = PMD_PDEV,
        .init = rte_igb_pmd_init,