net/igb: restore ether type filter
[dpdk.git] / drivers / net / e1000 / igb_ethdev.c
index 59a8bfd..80025de 100644 (file)
@@ -45,6 +45,7 @@
 #include <rte_pci.h>
 #include <rte_ether.h>
 #include <rte_ethdev.h>
+#include <rte_ethdev_pci.h>
 #include <rte_memory.h>
 #include <rte_memzone.h>
 #include <rte_eal.h>
@@ -115,11 +116,19 @@ static void eth_igb_stats_get(struct rte_eth_dev *dev,
                                struct rte_eth_stats *rte_stats);
 static int eth_igb_xstats_get(struct rte_eth_dev *dev,
                              struct rte_eth_xstat *xstats, unsigned n);
+static int eth_igb_xstats_get_by_id(struct rte_eth_dev *dev,
+               const uint64_t *ids,
+               uint64_t *values, unsigned int n);
 static int eth_igb_xstats_get_names(struct rte_eth_dev *dev,
                                    struct rte_eth_xstat_name *xstats_names,
-                                   unsigned limit);
+                                   unsigned int size);
+static int eth_igb_xstats_get_names_by_id(struct rte_eth_dev *dev,
+               struct rte_eth_xstat_name *xstats_names, const uint64_t *ids,
+               unsigned int limit);
 static void eth_igb_stats_reset(struct rte_eth_dev *dev);
 static void eth_igb_xstats_reset(struct rte_eth_dev *dev);
+static int eth_igb_fw_version_get(struct rte_eth_dev *dev,
+                                  char *fw_version, size_t fw_size);
 static void eth_igb_infos_get(struct rte_eth_dev *dev,
                              struct rte_eth_dev_info *dev_info);
 static const uint32_t *eth_igb_supported_ptypes_get(struct rte_eth_dev *dev);
@@ -134,8 +143,7 @@ static int eth_igb_rxq_interrupt_setup(struct rte_eth_dev *dev);
 static int eth_igb_interrupt_get_status(struct rte_eth_dev *dev);
 static int eth_igb_interrupt_action(struct rte_eth_dev *dev,
                                    struct rte_intr_handle *handle);
-static void eth_igb_interrupt_handler(struct rte_intr_handle *handle,
-                                                       void *param);
+static void eth_igb_interrupt_handler(void *param);
 static int  igb_hardware_init(struct e1000_hw *hw);
 static void igb_hw_control_acquire(struct e1000_hw *hw);
 static void igb_hw_control_release(struct e1000_hw *hw);
@@ -163,9 +171,9 @@ static int eth_igb_led_off(struct rte_eth_dev *dev);
 
 static void igb_intr_disable(struct e1000_hw *hw);
 static int  igb_get_rx_buffer_size(struct e1000_hw *hw);
-static void eth_igb_rar_set(struct rte_eth_dev *dev,
-               struct ether_addr *mac_addr,
-               uint32_t index, uint32_t pool);
+static int eth_igb_rar_set(struct rte_eth_dev *dev,
+                          struct ether_addr *mac_addr,
+                          uint32_t index, uint32_t pool);
 static void eth_igb_rar_clear(struct rte_eth_dev *dev, uint32_t index);
 static void eth_igb_default_mac_addr_set(struct rte_eth_dev *dev,
                struct ether_addr *addr);
@@ -281,9 +289,9 @@ static void eth_igb_assign_msix_vector(struct e1000_hw *hw, int8_t direction,
 static void eth_igb_write_ivar(struct e1000_hw *hw, uint8_t msix_vector,
                               uint8_t index, uint8_t offset);
 static void eth_igb_configure_msix_intr(struct rte_eth_dev *dev);
-static void eth_igbvf_interrupt_handler(struct rte_intr_handle *handle,
-                                       void *param);
+static void eth_igbvf_interrupt_handler(void *param);
 static void igbvf_mbx_process(struct rte_eth_dev *dev);
+static int igb_filter_restore(struct rte_eth_dev *dev);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -370,6 +378,8 @@ static const struct rte_eth_desc_lim tx_desc_lim = {
        .nb_max = E1000_MAX_RING_DESC,
        .nb_min = E1000_MIN_RING_DESC,
        .nb_align = IGB_RXD_ALIGN,
+       .nb_seg_max = IGB_TX_MAX_SEG,
+       .nb_mtu_seg_max = IGB_TX_MAX_MTU_SEG,
 };
 
 static const struct eth_dev_ops eth_igb_ops = {
@@ -386,9 +396,12 @@ static const struct eth_dev_ops eth_igb_ops = {
        .link_update          = eth_igb_link_update,
        .stats_get            = eth_igb_stats_get,
        .xstats_get           = eth_igb_xstats_get,
+       .xstats_get_by_id     = eth_igb_xstats_get_by_id,
+       .xstats_get_names_by_id = eth_igb_xstats_get_names_by_id,
        .xstats_get_names     = eth_igb_xstats_get_names,
        .stats_reset          = eth_igb_stats_reset,
        .xstats_reset         = eth_igb_xstats_reset,
+       .fw_version_get       = eth_igb_fw_version_get,
        .dev_infos_get        = eth_igb_infos_get,
        .dev_supported_ptypes_get = eth_igb_supported_ptypes_get,
        .mtu_set              = eth_igb_mtu_set,
@@ -401,8 +414,11 @@ static const struct eth_dev_ops eth_igb_ops = {
        .rx_queue_release     = eth_igb_rx_queue_release,
        .rx_queue_count       = eth_igb_rx_queue_count,
        .rx_descriptor_done   = eth_igb_rx_descriptor_done,
+       .rx_descriptor_status = eth_igb_rx_descriptor_status,
+       .tx_descriptor_status = eth_igb_tx_descriptor_status,
        .tx_queue_setup       = eth_igb_tx_queue_setup,
        .tx_queue_release     = eth_igb_tx_queue_release,
+       .tx_done_cleanup      = eth_igb_tx_done_cleanup,
        .dev_led_on           = eth_igb_led_on,
        .dev_led_off          = eth_igb_led_off,
        .flow_ctrl_get        = eth_igb_flow_ctrl_get,
@@ -741,11 +757,35 @@ igb_reset_swfw_lock(struct e1000_hw *hw)
        return E1000_SUCCESS;
 }
 
+/* Remove all ntuple filters of the device */
+static int igb_ntuple_filter_uninit(struct rte_eth_dev *eth_dev)
+{
+       struct e1000_filter_info *filter_info =
+               E1000_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private);
+       struct e1000_5tuple_filter *p_5tuple;
+       struct e1000_2tuple_filter *p_2tuple;
+
+       while ((p_5tuple = TAILQ_FIRST(&filter_info->fivetuple_list))) {
+               TAILQ_REMOVE(&filter_info->fivetuple_list,
+                       p_5tuple, entries);
+                       rte_free(p_5tuple);
+       }
+       filter_info->fivetuple_mask = 0;
+       while ((p_2tuple = TAILQ_FIRST(&filter_info->twotuple_list))) {
+               TAILQ_REMOVE(&filter_info->twotuple_list,
+                       p_2tuple, entries);
+                       rte_free(p_2tuple);
+       }
+       filter_info->twotuple_mask = 0;
+
+       return 0;
+}
+
 static int
 eth_igb_dev_init(struct rte_eth_dev *eth_dev)
 {
        int error = 0;
-       struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(eth_dev);
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
        struct e1000_hw *hw =
                E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
        struct e1000_vfta * shadow_vfta =
@@ -760,6 +800,7 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
        eth_dev->dev_ops = &eth_igb_ops;
        eth_dev->rx_pkt_burst = &eth_igb_recv_pkts;
        eth_dev->tx_pkt_burst = &eth_igb_xmit_pkts;
+       eth_dev->tx_pkt_prepare = &eth_igb_prep_pkts;
 
        /* for secondary processes, we don't initialise any further as primary
         * has already done this work. Only check we don't need a different
@@ -771,6 +812,7 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
        }
 
        rte_eth_copy_pci_info(eth_dev, pci_dev);
+       eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
 
        hw->hw_addr= (void *)pci_dev->mem_resource[0].addr;
 
@@ -889,12 +931,13 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
        /* enable support intr */
        igb_intr_enable(eth_dev);
 
+       /* initialize filter info */
+       memset(filter_info, 0,
+              sizeof(struct e1000_filter_info));
+
        TAILQ_INIT(&filter_info->flex_list);
-       filter_info->flex_mask = 0;
        TAILQ_INIT(&filter_info->twotuple_list);
-       filter_info->twotuple_mask = 0;
        TAILQ_INIT(&filter_info->fivetuple_list);
-       filter_info->fivetuple_mask = 0;
 
        return 0;
 
@@ -912,6 +955,8 @@ eth_igb_dev_uninit(struct rte_eth_dev *eth_dev)
        struct e1000_hw *hw;
        struct e1000_adapter *adapter =
                E1000_DEV_PRIVATE(eth_dev->data->dev_private);
+       struct e1000_filter_info *filter_info =
+               E1000_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private);
 
        PMD_INIT_FUNC_TRACE();
 
@@ -919,7 +964,7 @@ eth_igb_dev_uninit(struct rte_eth_dev *eth_dev)
                return -EPERM;
 
        hw = E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
-       pci_dev = E1000_DEV_TO_PCI(eth_dev);
+       pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
        intr_handle = &pci_dev->intr_handle;
 
        if (adapter->stopped == 0)
@@ -943,6 +988,17 @@ eth_igb_dev_uninit(struct rte_eth_dev *eth_dev)
        rte_intr_callback_unregister(intr_handle,
                                     eth_igb_interrupt_handler, eth_dev);
 
+       /* clear the SYN filter info */
+       filter_info->syn_info = 0;
+
+       /* clear the ethertype filters info */
+       filter_info->ethertype_mask = 0;
+       memset(filter_info->ethertype_filters, 0,
+               E1000_MAX_ETQF_FILTERS * sizeof(struct igb_ethertype_filter));
+
+       /* remove all ntuple filters of the device */
+       igb_ntuple_filter_uninit(eth_dev);
+
        return 0;
 }
 
@@ -966,6 +1022,7 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev)
        eth_dev->dev_ops = &igbvf_eth_dev_ops;
        eth_dev->rx_pkt_burst = &eth_igb_recv_pkts;
        eth_dev->tx_pkt_burst = &eth_igb_xmit_pkts;
+       eth_dev->tx_pkt_prepare = &eth_igb_prep_pkts;
 
        /* for secondary processes, we don't initialise any further as primary
         * has already done this work. Only check we don't need a different
@@ -976,8 +1033,9 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev)
                return 0;
        }
 
-       pci_dev = E1000_DEV_TO_PCI(eth_dev);
+       pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
        rte_eth_copy_pci_info(eth_dev, pci_dev);
+       eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
 
        hw->device_id = pci_dev->id.device_id;
        hw->vendor_id = pci_dev->id.vendor_id;
@@ -1014,12 +1072,6 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev)
        /* Generate a random MAC address, if none was assigned by PF. */
        if (is_zero_ether_addr(perm_addr)) {
                eth_random_addr(perm_addr->addr_bytes);
-               diag = e1000_rar_set(hw, perm_addr->addr_bytes, 0);
-               if (diag) {
-                       rte_free(eth_dev->data->mac_addrs);
-                       eth_dev->data->mac_addrs = NULL;
-                       return diag;
-               }
                PMD_INIT_LOG(INFO, "\tVF MAC address not assigned by Host PF");
                PMD_INIT_LOG(INFO, "\tAssign randomly generated MAC address "
                             "%02x:%02x:%02x:%02x:%02x:%02x",
@@ -1031,6 +1083,12 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev)
                             perm_addr->addr_bytes[5]);
        }
 
+       diag = e1000_rar_set(hw, perm_addr->addr_bytes, 0);
+       if (diag) {
+               rte_free(eth_dev->data->mac_addrs);
+               eth_dev->data->mac_addrs = NULL;
+               return diag;
+       }
        /* Copy the permanent MAC address */
        ether_addr_copy((struct ether_addr *) hw->mac.perm_addr,
                        &eth_dev->data->mac_addrs[0]);
@@ -1052,7 +1110,7 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
 {
        struct e1000_adapter *adapter =
                E1000_DEV_PRIVATE(eth_dev->data->dev_private);
-       struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(eth_dev);
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 
        PMD_INIT_FUNC_TRACE();
 
@@ -1078,32 +1136,46 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
        return 0;
 }
 
-static struct eth_driver rte_igb_pmd = {
-       .pci_drv = {
-               .id_table = pci_id_igb_map,
-               .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
-                       RTE_PCI_DRV_DETACHABLE,
-               .probe = rte_eth_dev_pci_probe,
-               .remove = rte_eth_dev_pci_remove,
-       },
-       .eth_dev_init = eth_igb_dev_init,
-       .eth_dev_uninit = eth_igb_dev_uninit,
-       .dev_private_size = sizeof(struct e1000_adapter),
+static int eth_igb_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+       struct rte_pci_device *pci_dev)
+{
+       return rte_eth_dev_pci_generic_probe(pci_dev,
+               sizeof(struct e1000_adapter), eth_igb_dev_init);
+}
+
+static int eth_igb_pci_remove(struct rte_pci_device *pci_dev)
+{
+       return rte_eth_dev_pci_generic_remove(pci_dev, eth_igb_dev_uninit);
+}
+
+static struct rte_pci_driver rte_igb_pmd = {
+       .id_table = pci_id_igb_map,
+       .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
+       .probe = eth_igb_pci_probe,
+       .remove = eth_igb_pci_remove,
 };
 
+
+static int eth_igbvf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+       struct rte_pci_device *pci_dev)
+{
+       return rte_eth_dev_pci_generic_probe(pci_dev,
+               sizeof(struct e1000_adapter), eth_igbvf_dev_init);
+}
+
+static int eth_igbvf_pci_remove(struct rte_pci_device *pci_dev)
+{
+       return rte_eth_dev_pci_generic_remove(pci_dev, eth_igbvf_dev_uninit);
+}
+
 /*
  * virtual function driver struct
  */
-static struct eth_driver rte_igbvf_pmd = {
-       .pci_drv = {
-               .id_table = pci_id_igbvf_map,
-               .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
-               .probe = rte_eth_dev_pci_probe,
-               .remove = rte_eth_dev_pci_remove,
-       },
-       .eth_dev_init = eth_igbvf_dev_init,
-       .eth_dev_uninit = eth_igbvf_dev_uninit,
-       .dev_private_size = sizeof(struct e1000_adapter),
+static struct rte_pci_driver rte_igbvf_pmd = {
+       .id_table = pci_id_igbvf_map,
+       .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+       .probe = eth_igbvf_pci_probe,
+       .remove = eth_igbvf_pci_remove,
 };
 
 static void
@@ -1219,7 +1291,7 @@ eth_igb_start(struct rte_eth_dev *dev)
                E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct e1000_adapter *adapter =
                E1000_DEV_PRIVATE(dev->data->dev_private);
-       struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(dev);
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        int ret, mask;
        uint32_t intr_vector = 0;
@@ -1284,7 +1356,7 @@ eth_igb_start(struct rte_eth_dev *dev)
                                    dev->data->nb_rx_queues * sizeof(int), 0);
                if (intr_handle->intr_vec == NULL) {
                        PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
-                                    " intr_vec\n", dev->data->nb_rx_queues);
+                                    " intr_vec", dev->data->nb_rx_queues);
                        return -ENOMEM;
                }
        }
@@ -1391,7 +1463,7 @@ eth_igb_start(struct rte_eth_dev *dev)
                                             (void *)dev);
                if (dev->data->dev_conf.intr_conf.lsc != 0)
                        PMD_INIT_LOG(INFO, "lsc won't enable because of"
-                                    " no intr multiplex\n");
+                                    " no intr multiplex");
        }
 
        /* check if rxq interrupt is enabled */
@@ -1405,6 +1477,9 @@ eth_igb_start(struct rte_eth_dev *dev)
        /* resume enabled intr since hw reset */
        igb_intr_enable(dev);
 
+       /* restore all types filter */
+       igb_filter_restore(dev);
+
        PMD_INIT_LOG(DEBUG, "<<");
 
        return 0;
@@ -1428,11 +1503,9 @@ eth_igb_stop(struct rte_eth_dev *dev)
        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);
-       struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(dev);
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_eth_link link;
        struct e1000_flex_filter *p_flex;
-       struct e1000_5tuple_filter *p_5tuple, *p_5tuple_next;
-       struct e1000_2tuple_filter *p_2tuple, *p_2tuple_next;
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 
        igb_intr_disable(hw);
@@ -1468,24 +1541,6 @@ eth_igb_stop(struct rte_eth_dev *dev)
        }
        filter_info->flex_mask = 0;
 
-       /* Remove all ntuple filters of the device */
-       for (p_5tuple = TAILQ_FIRST(&filter_info->fivetuple_list);
-            p_5tuple != NULL; p_5tuple = p_5tuple_next) {
-               p_5tuple_next = TAILQ_NEXT(p_5tuple, entries);
-               TAILQ_REMOVE(&filter_info->fivetuple_list,
-                            p_5tuple, entries);
-               rte_free(p_5tuple);
-       }
-       filter_info->fivetuple_mask = 0;
-       for (p_2tuple = TAILQ_FIRST(&filter_info->twotuple_list);
-            p_2tuple != NULL; p_2tuple = p_2tuple_next) {
-               p_2tuple_next = TAILQ_NEXT(p_2tuple, entries);
-               TAILQ_REMOVE(&filter_info->twotuple_list,
-                            p_2tuple, entries);
-               rte_free(p_2tuple);
-       }
-       filter_info->twotuple_mask = 0;
-
        if (!rte_intr_allow_others(intr_handle))
                /* resume to the default handler */
                rte_intr_callback_register(intr_handle,
@@ -1533,7 +1588,7 @@ eth_igb_close(struct rte_eth_dev *dev)
        struct e1000_adapter *adapter =
                E1000_DEV_PRIVATE(dev->data->dev_private);
        struct rte_eth_link link;
-       struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(dev);
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 
        eth_igb_stop(dev);
@@ -1820,7 +1875,7 @@ eth_igb_xstats_reset(struct rte_eth_dev *dev)
 
 static int eth_igb_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
        struct rte_eth_xstat_name *xstats_names,
-       __rte_unused unsigned limit)
+       __rte_unused unsigned int size)
 {
        unsigned i;
 
@@ -1837,6 +1892,41 @@ static int eth_igb_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
        return IGB_NB_XSTATS;
 }
 
+static int eth_igb_xstats_get_names_by_id(struct rte_eth_dev *dev,
+               struct rte_eth_xstat_name *xstats_names, const uint64_t *ids,
+               unsigned int limit)
+{
+       unsigned int i;
+
+       if (!ids) {
+               if (xstats_names == NULL)
+                       return IGB_NB_XSTATS;
+
+               for (i = 0; i < IGB_NB_XSTATS; i++)
+                       snprintf(xstats_names[i].name,
+                                       sizeof(xstats_names[i].name),
+                                       "%s", rte_igb_stats_strings[i].name);
+
+               return IGB_NB_XSTATS;
+
+       } else {
+               struct rte_eth_xstat_name xstats_names_copy[IGB_NB_XSTATS];
+
+               eth_igb_xstats_get_names_by_id(dev, xstats_names_copy, NULL,
+                               IGB_NB_XSTATS);
+
+               for (i = 0; i < limit; i++) {
+                       if (ids[i] >= IGB_NB_XSTATS) {
+                               PMD_INIT_LOG(ERR, "id value isn't valid");
+                               return -1;
+                       }
+                       strcpy(xstats_names[i].name,
+                                       xstats_names_copy[ids[i]].name);
+               }
+               return limit;
+       }
+}
+
 static int
 eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
                   unsigned n)
@@ -1867,6 +1957,53 @@ eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
        return IGB_NB_XSTATS;
 }
 
+static int
+eth_igb_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids,
+               uint64_t *values, unsigned int n)
+{
+       unsigned int i;
+
+       if (!ids) {
+               struct e1000_hw *hw =
+                       E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+               struct e1000_hw_stats *hw_stats =
+                       E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+               if (n < IGB_NB_XSTATS)
+                       return IGB_NB_XSTATS;
+
+               igb_read_stats_registers(hw, hw_stats);
+
+               /* If this is a reset xstats is NULL, and we have cleared the
+                * registers by reading them.
+                */
+               if (!values)
+                       return 0;
+
+               /* Extended stats */
+               for (i = 0; i < IGB_NB_XSTATS; i++)
+                       values[i] = *(uint64_t *)(((char *)hw_stats) +
+                                       rte_igb_stats_strings[i].offset);
+
+               return IGB_NB_XSTATS;
+
+       } else {
+               uint64_t values_copy[IGB_NB_XSTATS];
+
+               eth_igb_xstats_get_by_id(dev, NULL, values_copy,
+                               IGB_NB_XSTATS);
+
+               for (i = 0; i < n; i++) {
+                       if (ids[i] >= IGB_NB_XSTATS) {
+                               PMD_INIT_LOG(ERR, "id value isn't valid");
+                               return -1;
+                       }
+                       values[i] = values_copy[ids[i]];
+               }
+               return n;
+       }
+}
+
 static void
 igbvf_read_stats_registers(struct e1000_hw *hw, struct e1000_vf_stats *hw_stats)
 {
@@ -1980,12 +2117,64 @@ eth_igbvf_stats_reset(struct rte_eth_dev *dev)
               offsetof(struct e1000_vf_stats, gprc));
 }
 
+static int
+eth_igb_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
+                      size_t fw_size)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct e1000_fw_version fw;
+       int ret;
+
+       e1000_get_fw_version(hw, &fw);
+
+       switch (hw->mac.type) {
+       case e1000_i210:
+       case e1000_i211:
+               if (!(e1000_get_flash_presence_i210(hw))) {
+                       ret = snprintf(fw_version, fw_size,
+                                "%2d.%2d-%d",
+                                fw.invm_major, fw.invm_minor,
+                                fw.invm_img_type);
+                       break;
+               }
+               /* fall through */
+       default:
+               /* if option rom is valid, display its version too */
+               if (fw.or_valid) {
+                       ret = snprintf(fw_version, fw_size,
+                                "%d.%d, 0x%08x, %d.%d.%d",
+                                fw.eep_major, fw.eep_minor, fw.etrack_id,
+                                fw.or_major, fw.or_build, fw.or_patch);
+               /* no option rom */
+               } else {
+                       if (fw.etrack_id != 0X0000) {
+                               ret = snprintf(fw_version, fw_size,
+                                        "%d.%d, 0x%08x",
+                                        fw.eep_major, fw.eep_minor,
+                                        fw.etrack_id);
+                       } else {
+                               ret = snprintf(fw_version, fw_size,
+                                        "%d.%d.%d",
+                                        fw.eep_major, fw.eep_minor,
+                                        fw.eep_build);
+                       }
+               }
+               break;
+       }
+
+       ret += 1; /* add the size of '\0' */
+       if (fw_size < (u32)ret)
+               return ret;
+       else
+               return 0;
+}
+
 static void
 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);
 
-       dev_info->pci_dev = dev->pci_dev;
+       dev_info->pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        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;
@@ -2114,7 +2303,7 @@ 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->pci_dev = dev->pci_dev;
+       dev_info->pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        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;
@@ -2646,7 +2835,7 @@ eth_igb_interrupt_action(struct rte_eth_dev *dev,
                E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct e1000_interrupt *intr =
                E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
-       struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(dev);
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        uint32_t tctl, rctl;
        struct rte_eth_link link;
        int ret;
@@ -2721,12 +2910,12 @@ eth_igb_interrupt_action(struct rte_eth_dev *dev,
  *  void
  */
 static void
-eth_igb_interrupt_handler(struct rte_intr_handle *handle, void *param)
+eth_igb_interrupt_handler(void *param)
 {
        struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
 
        eth_igb_interrupt_get_status(dev);
-       eth_igb_interrupt_action(dev, handle);
+       eth_igb_interrupt_action(dev, dev->intr_handle);
 }
 
 static int
@@ -2783,13 +2972,12 @@ eth_igbvf_interrupt_action(struct rte_eth_dev *dev, struct rte_intr_handle *intr
 }
 
 static void
-eth_igbvf_interrupt_handler(struct rte_intr_handle *handle,
-                           void *param)
+eth_igbvf_interrupt_handler(void *param)
 {
        struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
 
        eth_igbvf_interrupt_get_status(dev);
-       eth_igbvf_interrupt_action(dev, handle);
+       eth_igbvf_interrupt_action(dev, dev->intr_handle);
 }
 
 static int
@@ -2913,9 +3101,9 @@ eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
 }
 
 #define E1000_RAH_POOLSEL_SHIFT      (18)
-static void
+static int
 eth_igb_rar_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
-               uint32_t index, __rte_unused uint32_t pool)
+               uint32_t index, uint32_t pool)
 {
        struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        uint32_t rah;
@@ -2924,6 +3112,7 @@ eth_igb_rar_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
        rah = E1000_READ_REG(hw, E1000_RAH(index));
        rah |= (0x1 << (E1000_RAH_POOLSEL_SHIFT + pool));
        E1000_WRITE_REG(hw, E1000_RAH(index), rah);
+       return 0;
 }
 
 static void
@@ -3062,7 +3251,7 @@ igbvf_dev_start(struct rte_eth_dev *dev)
                E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct e1000_adapter *adapter =
                E1000_DEV_PRIVATE(dev->data->dev_private);
-       struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(dev);
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        int ret;
        uint32_t intr_vector = 0;
@@ -3099,7 +3288,7 @@ igbvf_dev_start(struct rte_eth_dev *dev)
                                    dev->data->nb_rx_queues * sizeof(int), 0);
                if (!intr_handle->intr_vec) {
                        PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
-                                    " intr_vec\n", dev->data->nb_rx_queues);
+                                    " intr_vec", dev->data->nb_rx_queues);
                        return -ENOMEM;
                }
        }
@@ -3118,7 +3307,7 @@ igbvf_dev_start(struct rte_eth_dev *dev)
 static void
 igbvf_dev_stop(struct rte_eth_dev *dev)
 {
-       struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(dev);
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 
        PMD_INIT_FUNC_TRACE();
@@ -3318,7 +3507,7 @@ eth_igb_rss_reta_update(struct rte_eth_dev *dev,
        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);
+                       "(%d)", reta_size, ETH_RSS_RETA_SIZE_128);
                return -EINVAL;
        }
 
@@ -3359,7 +3548,7 @@ eth_igb_rss_reta_query(struct rte_eth_dev *dev,
        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);
+                       "(%d)", reta_size, ETH_RSS_RETA_SIZE_128);
                return -EINVAL;
        }
 
@@ -3384,7 +3573,8 @@ 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)\
+               (type) != e1000_82576 && (type) != e1000_i210 &&\
+               (type) != e1000_i211)\
                return -ENOTSUP;\
 } while (0)
 
@@ -3394,6 +3584,8 @@ eth_igb_syn_filter_set(struct rte_eth_dev *dev,
                        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 synqf, rfctl;
 
        if (filter->queue >= IGB_MAX_RX_QUEUE_NUM)
@@ -3421,6 +3613,7 @@ eth_igb_syn_filter_set(struct rte_eth_dev *dev,
                synqf = 0;
        }
 
+       filter_info->syn_info = synqf;
        E1000_WRITE_REG(hw, E1000_SYNQF(0), synqf);
        E1000_WRITE_FLUSH(hw);
        return 0;
@@ -3480,7 +3673,7 @@ eth_igb_syn_filter_handle(struct rte_eth_dev *dev,
                                (struct rte_eth_syn_filter *)arg);
                break;
        default:
-               PMD_DRV_LOG(ERR, "unsupported operation %u\n", filter_op);
+               PMD_DRV_LOG(ERR, "unsupported operation %u", filter_op);
                ret = -EINVAL;
                break;
        }
@@ -3489,7 +3682,8 @@ eth_igb_syn_filter_handle(struct rte_eth_dev *dev,
 }
 
 #define MAC_TYPE_FILTER_SUP_EXT(type)    do {\
-       if ((type) != e1000_82580 && (type) != e1000_i350)\
+       if ((type) != e1000_82580 && (type) != e1000_i350 &&\
+               (type) != e1000_i210 && (type) != e1000_i211)\
                return -ENOSYS; \
 } while (0)
 
@@ -3555,6 +3749,54 @@ igb_2tuple_filter_lookup(struct e1000_2tuple_filter_list *filter_list,
        return NULL;
 }
 
+/* inject a igb 2tuple filter to HW */
+static inline void
+igb_inject_2uple_filter(struct rte_eth_dev *dev,
+                          struct e1000_2tuple_filter *filter)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t ttqf = E1000_TTQF_DISABLE_MASK;
+       uint32_t imir, imir_ext = E1000_IMIREXT_SIZE_BP;
+       int i;
+
+       i = filter->index;
+       imir = (uint32_t)(filter->filter_info.dst_port & E1000_IMIR_DSTPORT);
+       if (filter->filter_info.dst_port_mask == 1) /* 1b means not compare. */
+               imir |= E1000_IMIR_PORT_BP;
+       else
+               imir &= ~E1000_IMIR_PORT_BP;
+
+       imir |= filter->filter_info.priority << E1000_IMIR_PRIORITY_SHIFT;
+
+       ttqf |= E1000_TTQF_QUEUE_ENABLE;
+       ttqf |= (uint32_t)(filter->queue << E1000_TTQF_QUEUE_SHIFT);
+       ttqf |= (uint32_t)(filter->filter_info.proto &
+                                               E1000_TTQF_PROTOCOL_MASK);
+       if (filter->filter_info.proto_mask == 0)
+               ttqf &= ~E1000_TTQF_MASK_ENABLE;
+
+       /* tcp flags bits setting. */
+       if (filter->filter_info.tcp_flags & TCP_FLAG_ALL) {
+               if (filter->filter_info.tcp_flags & TCP_URG_FLAG)
+                       imir_ext |= E1000_IMIREXT_CTRL_URG;
+               if (filter->filter_info.tcp_flags & TCP_ACK_FLAG)
+                       imir_ext |= E1000_IMIREXT_CTRL_ACK;
+               if (filter->filter_info.tcp_flags & TCP_PSH_FLAG)
+                       imir_ext |= E1000_IMIREXT_CTRL_PSH;
+               if (filter->filter_info.tcp_flags & TCP_RST_FLAG)
+                       imir_ext |= E1000_IMIREXT_CTRL_RST;
+               if (filter->filter_info.tcp_flags & TCP_SYN_FLAG)
+                       imir_ext |= E1000_IMIREXT_CTRL_SYN;
+               if (filter->filter_info.tcp_flags & TCP_FIN_FLAG)
+                       imir_ext |= E1000_IMIREXT_CTRL_FIN;
+       } else {
+               imir_ext |= E1000_IMIREXT_CTRL_BP;
+       }
+       E1000_WRITE_REG(hw, E1000_IMIR(i), imir);
+       E1000_WRITE_REG(hw, E1000_TTQF(i), ttqf);
+       E1000_WRITE_REG(hw, E1000_IMIREXT(i), imir_ext);
+}
+
 /*
  * igb_add_2tuple_filter - add a 2tuple filter
  *
@@ -3570,12 +3812,9 @@ static int
 igb_add_2tuple_filter(struct rte_eth_dev *dev,
                        struct rte_eth_ntuple_filter *ntuple_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);
        struct e1000_2tuple_filter *filter;
-       uint32_t ttqf = E1000_TTQF_DISABLE_MASK;
-       uint32_t imir, imir_ext = E1000_IMIREXT_SIZE_BP;
        int i, ret;
 
        filter = rte_zmalloc("e1000_2tuple_filter",
@@ -3617,39 +3856,7 @@ igb_add_2tuple_filter(struct rte_eth_dev *dev,
                return -ENOSYS;
        }
 
-       imir = (uint32_t)(filter->filter_info.dst_port & E1000_IMIR_DSTPORT);
-       if (filter->filter_info.dst_port_mask == 1) /* 1b means not compare. */
-               imir |= E1000_IMIR_PORT_BP;
-       else
-               imir &= ~E1000_IMIR_PORT_BP;
-
-       imir |= filter->filter_info.priority << E1000_IMIR_PRIORITY_SHIFT;
-
-       ttqf |= E1000_TTQF_QUEUE_ENABLE;
-       ttqf |= (uint32_t)(filter->queue << E1000_TTQF_QUEUE_SHIFT);
-       ttqf |= (uint32_t)(filter->filter_info.proto & E1000_TTQF_PROTOCOL_MASK);
-       if (filter->filter_info.proto_mask == 0)
-               ttqf &= ~E1000_TTQF_MASK_ENABLE;
-
-       /* tcp flags bits setting. */
-       if (filter->filter_info.tcp_flags & TCP_FLAG_ALL) {
-               if (filter->filter_info.tcp_flags & TCP_URG_FLAG)
-                       imir_ext |= E1000_IMIREXT_CTRL_URG;
-               if (filter->filter_info.tcp_flags & TCP_ACK_FLAG)
-                       imir_ext |= E1000_IMIREXT_CTRL_ACK;
-               if (filter->filter_info.tcp_flags & TCP_PSH_FLAG)
-                       imir_ext |= E1000_IMIREXT_CTRL_PSH;
-               if (filter->filter_info.tcp_flags & TCP_RST_FLAG)
-                       imir_ext |= E1000_IMIREXT_CTRL_RST;
-               if (filter->filter_info.tcp_flags & TCP_SYN_FLAG)
-                       imir_ext |= E1000_IMIREXT_CTRL_SYN;
-               if (filter->filter_info.tcp_flags & TCP_FIN_FLAG)
-                       imir_ext |= E1000_IMIREXT_CTRL_FIN;
-       } else
-               imir_ext |= E1000_IMIREXT_CTRL_BP;
-       E1000_WRITE_REG(hw, E1000_IMIR(i), imir);
-       E1000_WRITE_REG(hw, E1000_TTQF(i), ttqf);
-       E1000_WRITE_REG(hw, E1000_IMIREXT(i), imir_ext);
+       igb_inject_2uple_filter(dev, filter);
        return 0;
 }
 
@@ -3745,10 +3952,6 @@ eth_igb_add_del_flex_filter(struct rte_eth_dev *dev,
        }
 
        wufc = E1000_READ_REG(hw, E1000_WUFC);
-       if (flex_filter->index < E1000_MAX_FHFT)
-               reg_off = E1000_FHFT(flex_filter->index);
-       else
-               reg_off = E1000_FHFT_EXT(flex_filter->index - E1000_MAX_FHFT);
 
        if (add) {
                if (eth_igb_flex_filter_lookup(&filter_info->flex_list,
@@ -3778,6 +3981,11 @@ eth_igb_add_del_flex_filter(struct rte_eth_dev *dev,
                        return -ENOSYS;
                }
 
+               if (flex_filter->index < E1000_MAX_FHFT)
+                       reg_off = E1000_FHFT(flex_filter->index);
+               else
+                       reg_off = E1000_FHFT_EXT(flex_filter->index - E1000_MAX_FHFT);
+
                E1000_WRITE_REG(hw, E1000_WUFC, wufc | E1000_WUFC_FLEX_HQ |
                                (E1000_WUFC_FLX0 << flex_filter->index));
                queueing = filter->len |
@@ -3806,6 +4014,11 @@ eth_igb_add_del_flex_filter(struct rte_eth_dev *dev,
                        return -ENOENT;
                }
 
+               if (it->index < E1000_MAX_FHFT)
+                       reg_off = E1000_FHFT(it->index);
+               else
+                       reg_off = E1000_FHFT_EXT(it->index - E1000_MAX_FHFT);
+
                for (i = 0; i < E1000_FHFT_SIZE_IN_DWD; i++)
                        E1000_WRITE_REG(hw, reg_off + i * sizeof(uint32_t), 0);
                E1000_WRITE_REG(hw, E1000_WUFC, wufc &
@@ -4017,6 +4230,64 @@ igb_5tuple_filter_lookup_82576(struct e1000_5tuple_filter_list *filter_list,
        return NULL;
 }
 
+/* inject a igb 5-tuple filter to HW */
+static inline void
+igb_inject_5tuple_filter_82576(struct rte_eth_dev *dev,
+                          struct e1000_5tuple_filter *filter)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t ftqf = E1000_FTQF_VF_BP | E1000_FTQF_MASK;
+       uint32_t spqf, imir, imir_ext = E1000_IMIREXT_SIZE_BP;
+       uint8_t i;
+
+       i = filter->index;
+       ftqf |= filter->filter_info.proto & E1000_FTQF_PROTOCOL_MASK;
+       if (filter->filter_info.src_ip_mask == 0) /* 0b means compare. */
+               ftqf &= ~E1000_FTQF_MASK_SOURCE_ADDR_BP;
+       if (filter->filter_info.dst_ip_mask == 0)
+               ftqf &= ~E1000_FTQF_MASK_DEST_ADDR_BP;
+       if (filter->filter_info.src_port_mask == 0)
+               ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP;
+       if (filter->filter_info.proto_mask == 0)
+               ftqf &= ~E1000_FTQF_MASK_PROTO_BP;
+       ftqf |= (filter->queue << E1000_FTQF_QUEUE_SHIFT) &
+               E1000_FTQF_QUEUE_MASK;
+       ftqf |= E1000_FTQF_QUEUE_ENABLE;
+       E1000_WRITE_REG(hw, E1000_FTQF(i), ftqf);
+       E1000_WRITE_REG(hw, E1000_DAQF(i), filter->filter_info.dst_ip);
+       E1000_WRITE_REG(hw, E1000_SAQF(i), filter->filter_info.src_ip);
+
+       spqf = filter->filter_info.src_port & E1000_SPQF_SRCPORT;
+       E1000_WRITE_REG(hw, E1000_SPQF(i), spqf);
+
+       imir = (uint32_t)(filter->filter_info.dst_port & E1000_IMIR_DSTPORT);
+       if (filter->filter_info.dst_port_mask == 1) /* 1b means not compare. */
+               imir |= E1000_IMIR_PORT_BP;
+       else
+               imir &= ~E1000_IMIR_PORT_BP;
+       imir |= filter->filter_info.priority << E1000_IMIR_PRIORITY_SHIFT;
+
+       /* tcp flags bits setting. */
+       if (filter->filter_info.tcp_flags & TCP_FLAG_ALL) {
+               if (filter->filter_info.tcp_flags & TCP_URG_FLAG)
+                       imir_ext |= E1000_IMIREXT_CTRL_URG;
+               if (filter->filter_info.tcp_flags & TCP_ACK_FLAG)
+                       imir_ext |= E1000_IMIREXT_CTRL_ACK;
+               if (filter->filter_info.tcp_flags & TCP_PSH_FLAG)
+                       imir_ext |= E1000_IMIREXT_CTRL_PSH;
+               if (filter->filter_info.tcp_flags & TCP_RST_FLAG)
+                       imir_ext |= E1000_IMIREXT_CTRL_RST;
+               if (filter->filter_info.tcp_flags & TCP_SYN_FLAG)
+                       imir_ext |= E1000_IMIREXT_CTRL_SYN;
+               if (filter->filter_info.tcp_flags & TCP_FIN_FLAG)
+                       imir_ext |= E1000_IMIREXT_CTRL_FIN;
+       } else {
+               imir_ext |= E1000_IMIREXT_CTRL_BP;
+       }
+       E1000_WRITE_REG(hw, E1000_IMIR(i), imir);
+       E1000_WRITE_REG(hw, E1000_IMIREXT(i), imir_ext);
+}
+
 /*
  * igb_add_5tuple_filter_82576 - add a 5tuple filter
  *
@@ -4032,12 +4303,9 @@ static int
 igb_add_5tuple_filter_82576(struct rte_eth_dev *dev,
                        struct rte_eth_ntuple_filter *ntuple_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);
        struct e1000_5tuple_filter *filter;
-       uint32_t ftqf = E1000_FTQF_VF_BP | E1000_FTQF_MASK;
-       uint32_t spqf, imir, imir_ext = E1000_IMIREXT_SIZE_BP;
        uint8_t i;
        int ret;
 
@@ -4081,50 +4349,7 @@ igb_add_5tuple_filter_82576(struct rte_eth_dev *dev,
                return -ENOSYS;
        }
 
-       ftqf |= filter->filter_info.proto & E1000_FTQF_PROTOCOL_MASK;
-       if (filter->filter_info.src_ip_mask == 0) /* 0b means compare. */
-               ftqf &= ~E1000_FTQF_MASK_SOURCE_ADDR_BP;
-       if (filter->filter_info.dst_ip_mask == 0)
-               ftqf &= ~E1000_FTQF_MASK_DEST_ADDR_BP;
-       if (filter->filter_info.src_port_mask == 0)
-               ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP;
-       if (filter->filter_info.proto_mask == 0)
-               ftqf &= ~E1000_FTQF_MASK_PROTO_BP;
-       ftqf |= (filter->queue << E1000_FTQF_QUEUE_SHIFT) &
-               E1000_FTQF_QUEUE_MASK;
-       ftqf |= E1000_FTQF_QUEUE_ENABLE;
-       E1000_WRITE_REG(hw, E1000_FTQF(i), ftqf);
-       E1000_WRITE_REG(hw, E1000_DAQF(i), filter->filter_info.dst_ip);
-       E1000_WRITE_REG(hw, E1000_SAQF(i), filter->filter_info.src_ip);
-
-       spqf = filter->filter_info.src_port & E1000_SPQF_SRCPORT;
-       E1000_WRITE_REG(hw, E1000_SPQF(i), spqf);
-
-       imir = (uint32_t)(filter->filter_info.dst_port & E1000_IMIR_DSTPORT);
-       if (filter->filter_info.dst_port_mask == 1) /* 1b means not compare. */
-               imir |= E1000_IMIR_PORT_BP;
-       else
-               imir &= ~E1000_IMIR_PORT_BP;
-       imir |= filter->filter_info.priority << E1000_IMIR_PRIORITY_SHIFT;
-
-       /* tcp flags bits setting. */
-       if (filter->filter_info.tcp_flags & TCP_FLAG_ALL) {
-               if (filter->filter_info.tcp_flags & TCP_URG_FLAG)
-                       imir_ext |= E1000_IMIREXT_CTRL_URG;
-               if (filter->filter_info.tcp_flags & TCP_ACK_FLAG)
-                       imir_ext |= E1000_IMIREXT_CTRL_ACK;
-               if (filter->filter_info.tcp_flags & TCP_PSH_FLAG)
-                       imir_ext |= E1000_IMIREXT_CTRL_PSH;
-               if (filter->filter_info.tcp_flags & TCP_RST_FLAG)
-                       imir_ext |= E1000_IMIREXT_CTRL_RST;
-               if (filter->filter_info.tcp_flags & TCP_SYN_FLAG)
-                       imir_ext |= E1000_IMIREXT_CTRL_SYN;
-               if (filter->filter_info.tcp_flags & TCP_FIN_FLAG)
-                       imir_ext |= E1000_IMIREXT_CTRL_FIN;
-       } else
-               imir_ext |= E1000_IMIREXT_CTRL_BP;
-       E1000_WRITE_REG(hw, E1000_IMIR(i), imir);
-       E1000_WRITE_REG(hw, E1000_IMIREXT(i), imir_ext);
+       igb_inject_5tuple_filter_82576(dev, filter);
        return 0;
 }
 
@@ -4261,7 +4486,9 @@ igb_add_del_ntuple_filter(struct rte_eth_dev *dev,
                break;
        case RTE_2TUPLE_FLAGS:
        case (RTE_2TUPLE_FLAGS | RTE_NTUPLE_FLAGS_TCP_FLAG):
-               if (hw->mac.type != e1000_82580 && hw->mac.type != e1000_i350)
+               if (hw->mac.type != e1000_82580 && hw->mac.type != e1000_i350 &&
+                       hw->mac.type != e1000_i210 &&
+                       hw->mac.type != e1000_i211)
                        return -ENOTSUP;
                if (add)
                        ret = igb_add_2tuple_filter(dev, ntuple_filter);
@@ -4403,7 +4630,7 @@ igb_ethertype_filter_lookup(struct e1000_filter_info *filter_info,
        int i;
 
        for (i = 0; i < E1000_MAX_ETQF_FILTERS; i++) {
-               if (filter_info->ethertype_filters[i] == ethertype &&
+               if (filter_info->ethertype_filters[i].ethertype == ethertype &&
                    (filter_info->ethertype_mask & (1 << i)))
                        return i;
        }
@@ -4412,33 +4639,35 @@ igb_ethertype_filter_lookup(struct e1000_filter_info *filter_info,
 
 static inline int
 igb_ethertype_filter_insert(struct e1000_filter_info *filter_info,
-                       uint16_t ethertype)
+                       uint16_t ethertype, uint32_t etqf)
 {
        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;
+                       filter_info->ethertype_filters[i].ethertype = ethertype;
+                       filter_info->ethertype_filters[i].etqf = etqf;
                        return i;
                }
        }
        return -1;
 }
 
-static inline int
+static 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;
+       filter_info->ethertype_filters[idx].ethertype = 0;
+       filter_info->ethertype_filters[idx].etqf = 0;
        return idx;
 }
 
 
-static int
+int
 igb_add_del_ethertype_filter(struct rte_eth_dev *dev,
                        struct rte_eth_ethertype_filter *filter,
                        bool add)
@@ -4478,16 +4707,15 @@ igb_add_del_ethertype_filter(struct rte_eth_dev *dev,
        }
 
        if (add) {
+               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;
                ret = igb_ethertype_filter_insert(filter_info,
-                       filter->ether_type);
+                               filter->ether_type, etqf);
                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)
@@ -5104,7 +5332,7 @@ eth_igb_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
 {
        struct e1000_hw *hw =
                E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(dev);
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        uint32_t mask = 1 << queue_id;
        uint32_t regval;
@@ -5177,7 +5405,7 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
        uint32_t vec = E1000_MISC_VEC_ID;
        uint32_t base = E1000_MISC_VEC_ID;
        uint32_t misc_shift = 0;
-       struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(dev);
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 
        /* won't configure msix register if no mapping is done
@@ -5249,9 +5477,73 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
        E1000_WRITE_FLUSH(hw);
 }
 
-RTE_PMD_REGISTER_PCI(net_e1000_igb, rte_igb_pmd.pci_drv);
+/* restore n-tuple filter */
+static inline void
+igb_ntuple_filter_restore(struct rte_eth_dev *dev)
+{
+       struct e1000_filter_info *filter_info =
+               E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+       struct e1000_5tuple_filter *p_5tuple;
+       struct e1000_2tuple_filter *p_2tuple;
+
+       TAILQ_FOREACH(p_5tuple, &filter_info->fivetuple_list, entries) {
+               igb_inject_5tuple_filter_82576(dev, p_5tuple);
+       }
+
+       TAILQ_FOREACH(p_2tuple, &filter_info->twotuple_list, entries) {
+               igb_inject_2uple_filter(dev, p_2tuple);
+       }
+}
+
+/* restore SYN filter */
+static inline void
+igb_syn_filter_restore(struct rte_eth_dev *dev)
+{
+       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 synqf;
+
+       synqf = filter_info->syn_info;
+
+       if (synqf & E1000_SYN_FILTER_ENABLE) {
+               E1000_WRITE_REG(hw, E1000_SYNQF(0), synqf);
+               E1000_WRITE_FLUSH(hw);
+       }
+}
+
+/* restore ethernet type filter */
+static inline void
+igb_ethertype_filter_restore(struct rte_eth_dev *dev)
+{
+       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);
+       int i;
+
+       for (i = 0; i < E1000_MAX_ETQF_FILTERS; i++) {
+               if (filter_info->ethertype_mask & (1 << i)) {
+                       E1000_WRITE_REG(hw, E1000_ETQF(i),
+                               filter_info->ethertype_filters[i].etqf);
+                       E1000_WRITE_FLUSH(hw);
+               }
+       }
+}
+
+/* restore all types filter */
+static int
+igb_filter_restore(struct rte_eth_dev *dev)
+{
+       igb_ntuple_filter_restore(dev);
+       igb_ethertype_filter_restore(dev);
+       igb_syn_filter_restore(dev);
+
+       return 0;
+}
+
+RTE_PMD_REGISTER_PCI(net_e1000_igb, rte_igb_pmd);
 RTE_PMD_REGISTER_PCI_TABLE(net_e1000_igb, pci_id_igb_map);
-RTE_PMD_REGISTER_KMOD_DEP(net_e1000_igb, "* igb_uio | uio_pci_generic | vfio");
-RTE_PMD_REGISTER_PCI(net_e1000_igb_vf, rte_igbvf_pmd.pci_drv);
+RTE_PMD_REGISTER_KMOD_DEP(net_e1000_igb, "* igb_uio | uio_pci_generic | vfio-pci");
+RTE_PMD_REGISTER_PCI(net_e1000_igb_vf, rte_igbvf_pmd);
 RTE_PMD_REGISTER_PCI_TABLE(net_e1000_igb_vf, pci_id_igbvf_map);
-RTE_PMD_REGISTER_KMOD_DEP(net_e1000_igb_vf, "* igb_uio | vfio");
+RTE_PMD_REGISTER_KMOD_DEP(net_e1000_igb_vf, "* igb_uio | vfio-pci");