ethdev: add return values to callback process API
[dpdk.git] / drivers / net / e1000 / igb_ethdev.c
index 8506864..da03d9b 100644 (file)
@@ -213,9 +213,6 @@ static int eth_igb_rss_reta_query(struct rte_eth_dev *dev,
                                  struct rte_eth_rss_reta_entry64 *reta_conf,
                                  uint16_t reta_size);
 
-static int eth_igb_syn_filter_set(struct rte_eth_dev *dev,
-                       struct rte_eth_syn_filter *filter,
-                       bool add);
 static int eth_igb_syn_filter_get(struct rte_eth_dev *dev,
                        struct rte_eth_syn_filter *filter);
 static int eth_igb_syn_filter_handle(struct rte_eth_dev *dev,
@@ -225,9 +222,6 @@ static int igb_add_2tuple_filter(struct rte_eth_dev *dev,
                        struct rte_eth_ntuple_filter *ntuple_filter);
 static int igb_remove_2tuple_filter(struct rte_eth_dev *dev,
                        struct rte_eth_ntuple_filter *ntuple_filter);
-static int eth_igb_add_del_flex_filter(struct rte_eth_dev *dev,
-                       struct rte_eth_flex_filter *filter,
-                       bool add);
 static int eth_igb_get_flex_filter(struct rte_eth_dev *dev,
                        struct rte_eth_flex_filter *filter);
 static int eth_igb_flex_filter_handle(struct rte_eth_dev *dev,
@@ -237,17 +231,11 @@ static int igb_add_5tuple_filter_82576(struct rte_eth_dev *dev,
                        struct rte_eth_ntuple_filter *ntuple_filter);
 static int igb_remove_5tuple_filter_82576(struct rte_eth_dev *dev,
                        struct rte_eth_ntuple_filter *ntuple_filter);
-static int igb_add_del_ntuple_filter(struct rte_eth_dev *dev,
-                       struct rte_eth_ntuple_filter *filter,
-                       bool add);
 static int igb_get_ntuple_filter(struct rte_eth_dev *dev,
                        struct rte_eth_ntuple_filter *filter);
 static int igb_ntuple_filter_handle(struct rte_eth_dev *dev,
                                enum rte_filter_op filter_op,
                                void *arg);
-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);
@@ -781,6 +769,22 @@ static int igb_ntuple_filter_uninit(struct rte_eth_dev *eth_dev)
        return 0;
 }
 
+/* Remove all flex filters of the device */
+static int igb_flex_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_flex_filter *p_flex;
+
+       while ((p_flex = TAILQ_FIRST(&filter_info->flex_list))) {
+               TAILQ_REMOVE(&filter_info->flex_list, p_flex, entries);
+               rte_free(p_flex);
+       }
+       filter_info->flex_mask = 0;
+
+       return 0;
+}
+
 static int
 eth_igb_dev_init(struct rte_eth_dev *eth_dev)
 {
@@ -939,6 +943,12 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
        TAILQ_INIT(&filter_info->twotuple_list);
        TAILQ_INIT(&filter_info->fivetuple_list);
 
+       TAILQ_INIT(&igb_filter_ntuple_list);
+       TAILQ_INIT(&igb_filter_ethertype_list);
+       TAILQ_INIT(&igb_filter_syn_list);
+       TAILQ_INIT(&igb_filter_flex_list);
+       TAILQ_INIT(&igb_flow_list);
+
        return 0;
 
 err_late:
@@ -991,9 +1001,20 @@ eth_igb_dev_uninit(struct rte_eth_dev *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);
 
+       /* remove all flex filters of the device */
+       igb_flex_filter_uninit(eth_dev);
+
+       /* clear all the filters list */
+       igb_filterlist_flush(eth_dev);
+
        return 0;
 }
 
@@ -1496,11 +1517,8 @@ static void
 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 = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_eth_link link;
-       struct e1000_flex_filter *p_flex;
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 
        igb_intr_disable(hw);
@@ -1529,13 +1547,6 @@ eth_igb_stop(struct rte_eth_dev *dev)
        memset(&link, 0, sizeof(link));
        rte_igb_dev_atomic_write_link_status(dev, &link);
 
-       /* Remove all flex filters of the device */
-       while ((p_flex = TAILQ_FIRST(&filter_info->flex_list))) {
-               TAILQ_REMOVE(&filter_info->flex_list, p_flex, entries);
-               rte_free(p_flex);
-       }
-       filter_info->flex_mask = 0;
-
        if (!rte_intr_allow_others(intr_handle))
                /* resume to the default handler */
                rte_intr_callback_register(intr_handle,
@@ -2887,7 +2898,8 @@ eth_igb_interrupt_action(struct rte_eth_dev *dev,
                E1000_WRITE_REG(hw, E1000_TCTL, tctl);
                E1000_WRITE_REG(hw, E1000_RCTL, rctl);
                E1000_WRITE_FLUSH(hw);
-               _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
+               _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC,
+                                             NULL, NULL);
        }
 
        return 0;
@@ -2946,7 +2958,8 @@ void igbvf_mbx_process(struct rte_eth_dev *dev)
 
        /* PF reset VF event */
        if (in_msg == E1000_PF_CONTROL_MSG)
-               _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET, NULL);
+               _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET,
+                                             NULL, NULL);
 }
 
 static int
@@ -3566,14 +3579,7 @@ eth_igb_rss_reta_query(struct rte_eth_dev *dev,
        return 0;
 }
 
-#define MAC_TYPE_FILTER_SUP(type)    do {\
-       if ((type) != e1000_82580 && (type) != e1000_i350 &&\
-               (type) != e1000_82576 && (type) != e1000_i210 &&\
-               (type) != e1000_i211)\
-               return -ENOTSUP;\
-} while (0)
-
-static int
+int
 eth_igb_syn_filter_set(struct rte_eth_dev *dev,
                        struct rte_eth_syn_filter *filter,
                        bool add)
@@ -3676,12 +3682,6 @@ eth_igb_syn_filter_handle(struct rte_eth_dev *dev,
        return ret;
 }
 
-#define MAC_TYPE_FILTER_SUP_EXT(type)    do {\
-       if ((type) != e1000_82580 && (type) != e1000_i350 &&\
-               (type) != e1000_i210 && (type) != e1000_i211)\
-               return -ENOSYS; \
-} while (0)
-
 /* translate elements in struct rte_eth_ntuple_filter to struct e1000_2tuple_filter_info*/
 static inline int
 ntuple_filter_to_2tuple(struct rte_eth_ntuple_filter *filter,
@@ -3855,6 +3855,24 @@ igb_add_2tuple_filter(struct rte_eth_dev *dev,
        return 0;
 }
 
+int
+igb_delete_2tuple_filter(struct rte_eth_dev *dev,
+                       struct e1000_2tuple_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);
+
+       filter_info->twotuple_mask &= ~(1 << filter->index);
+       TAILQ_REMOVE(&filter_info->twotuple_list, filter, entries);
+       rte_free(filter);
+
+       E1000_WRITE_REG(hw, E1000_TTQF(filter->index), E1000_TTQF_DISABLE_MASK);
+       E1000_WRITE_REG(hw, E1000_IMIR(filter->index), 0);
+       E1000_WRITE_REG(hw, E1000_IMIREXT(filter->index), 0);
+       return 0;
+}
+
 /*
  * igb_remove_2tuple_filter - remove a 2tuple filter
  *
@@ -3870,7 +3888,6 @@ static int
 igb_remove_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_info filter_2tuple;
@@ -3890,16 +3907,50 @@ igb_remove_2tuple_filter(struct rte_eth_dev *dev,
                return -ENOENT;
        }
 
-       filter_info->twotuple_mask &= ~(1 << filter->index);
-       TAILQ_REMOVE(&filter_info->twotuple_list, filter, entries);
-       rte_free(filter);
+       igb_delete_2tuple_filter(dev, filter);
 
-       E1000_WRITE_REG(hw, E1000_TTQF(filter->index), E1000_TTQF_DISABLE_MASK);
-       E1000_WRITE_REG(hw, E1000_IMIR(filter->index), 0);
-       E1000_WRITE_REG(hw, E1000_IMIREXT(filter->index), 0);
        return 0;
 }
 
+/* inject a igb flex filter to HW */
+static inline void
+igb_inject_flex_filter(struct rte_eth_dev *dev,
+                          struct e1000_flex_filter *filter)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t wufc, queueing;
+       uint32_t reg_off;
+       uint8_t i, j = 0;
+
+       wufc = E1000_READ_REG(hw, E1000_WUFC);
+       if (filter->index < E1000_MAX_FHFT)
+               reg_off = E1000_FHFT(filter->index);
+       else
+               reg_off = E1000_FHFT_EXT(filter->index - E1000_MAX_FHFT);
+
+       E1000_WRITE_REG(hw, E1000_WUFC, wufc | E1000_WUFC_FLEX_HQ |
+                       (E1000_WUFC_FLX0 << filter->index));
+       queueing = filter->filter_info.len |
+               (filter->queue << E1000_FHFT_QUEUEING_QUEUE_SHIFT) |
+               (filter->filter_info.priority <<
+                       E1000_FHFT_QUEUEING_PRIO_SHIFT);
+       E1000_WRITE_REG(hw, reg_off + E1000_FHFT_QUEUEING_OFFSET,
+                       queueing);
+
+       for (i = 0; i < E1000_FLEX_FILTERS_MASK_SIZE; i++) {
+               E1000_WRITE_REG(hw, reg_off,
+                               filter->filter_info.dwords[j]);
+               reg_off += sizeof(uint32_t);
+               E1000_WRITE_REG(hw, reg_off,
+                               filter->filter_info.dwords[++j]);
+               reg_off += sizeof(uint32_t);
+               E1000_WRITE_REG(hw, reg_off,
+                       (uint32_t)filter->filter_info.mask[i]);
+               reg_off += sizeof(uint32_t) * 2;
+               ++j;
+       }
+}
+
 static inline struct e1000_flex_filter *
 eth_igb_flex_filter_lookup(struct e1000_flex_filter_list *filter_list,
                        struct e1000_flex_filter_info *key)
@@ -3915,18 +3966,48 @@ eth_igb_flex_filter_lookup(struct e1000_flex_filter_list *filter_list,
        return NULL;
 }
 
-static int
+/* remove a flex byte filter
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * filter: the pointer of the filter will be removed.
+ */
+void
+igb_remove_flex_filter(struct rte_eth_dev *dev,
+                       struct e1000_flex_filter *filter)
+{
+       struct e1000_filter_info *filter_info =
+               E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t wufc, i;
+       uint32_t reg_off;
+
+       wufc = E1000_READ_REG(hw, E1000_WUFC);
+       if (filter->index < E1000_MAX_FHFT)
+               reg_off = E1000_FHFT(filter->index);
+       else
+               reg_off = E1000_FHFT_EXT(filter->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 &
+               (~(E1000_WUFC_FLX0 << filter->index)));
+
+       filter_info->flex_mask &= ~(1 << filter->index);
+       TAILQ_REMOVE(&filter_info->flex_list, filter, entries);
+       rte_free(filter);
+}
+
+int
 eth_igb_add_del_flex_filter(struct rte_eth_dev *dev,
                        struct rte_eth_flex_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);
        struct e1000_flex_filter *flex_filter, *it;
-       uint32_t wufc, queueing, mask;
-       uint32_t reg_off;
-       uint8_t shift, i, j = 0;
+       uint32_t mask;
+       uint8_t shift, i;
 
        flex_filter = rte_zmalloc("e1000_flex_filter",
                        sizeof(struct e1000_flex_filter), 0);
@@ -3946,15 +4027,20 @@ eth_igb_add_del_flex_filter(struct rte_eth_dev *dev,
                flex_filter->filter_info.mask[i] = mask;
        }
 
-       wufc = E1000_READ_REG(hw, E1000_WUFC);
+       it = eth_igb_flex_filter_lookup(&filter_info->flex_list,
+                               &flex_filter->filter_info);
+       if (it == NULL && !add) {
+               PMD_DRV_LOG(ERR, "filter doesn't exist.");
+               rte_free(flex_filter);
+               return -ENOENT;
+       }
+       if (it != NULL && add) {
+               PMD_DRV_LOG(ERR, "filter exists.");
+               rte_free(flex_filter);
+               return -EEXIST;
+       }
 
        if (add) {
-               if (eth_igb_flex_filter_lookup(&filter_info->flex_list,
-                               &flex_filter->filter_info) != NULL) {
-                       PMD_DRV_LOG(ERR, "filter exists.");
-                       rte_free(flex_filter);
-                       return -EEXIST;
-               }
                flex_filter->queue = filter->queue;
                /*
                 * look for an unused flex filter index
@@ -3976,52 +4062,10 @@ 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 |
-                       (filter->queue << E1000_FHFT_QUEUEING_QUEUE_SHIFT) |
-                       (filter->priority << E1000_FHFT_QUEUEING_PRIO_SHIFT);
-               E1000_WRITE_REG(hw, reg_off + E1000_FHFT_QUEUEING_OFFSET,
-                               queueing);
-               for (i = 0; i < E1000_FLEX_FILTERS_MASK_SIZE; i++) {
-                       E1000_WRITE_REG(hw, reg_off,
-                                       flex_filter->filter_info.dwords[j]);
-                       reg_off += sizeof(uint32_t);
-                       E1000_WRITE_REG(hw, reg_off,
-                                       flex_filter->filter_info.dwords[++j]);
-                       reg_off += sizeof(uint32_t);
-                       E1000_WRITE_REG(hw, reg_off,
-                               (uint32_t)flex_filter->filter_info.mask[i]);
-                       reg_off += sizeof(uint32_t) * 2;
-                       ++j;
-               }
-       } else {
-               it = eth_igb_flex_filter_lookup(&filter_info->flex_list,
-                               &flex_filter->filter_info);
-               if (it == NULL) {
-                       PMD_DRV_LOG(ERR, "filter doesn't exist.");
-                       rte_free(flex_filter);
-                       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 &
-                       (~(E1000_WUFC_FLX0 << it->index)));
+               igb_inject_flex_filter(dev, flex_filter);
 
-               filter_info->flex_mask &= ~(1 << it->index);
-               TAILQ_REMOVE(&filter_info->flex_list, it, entries);
-               rte_free(it);
+       } else {
+               igb_remove_flex_filter(dev, it);
                rte_free(flex_filter);
        }
 
@@ -4348,6 +4392,28 @@ igb_add_5tuple_filter_82576(struct rte_eth_dev *dev,
        return 0;
 }
 
+int
+igb_delete_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);
+       struct e1000_filter_info *filter_info =
+               E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+
+       filter_info->fivetuple_mask &= ~(1 << filter->index);
+       TAILQ_REMOVE(&filter_info->fivetuple_list, filter, entries);
+       rte_free(filter);
+
+       E1000_WRITE_REG(hw, E1000_FTQF(filter->index),
+                       E1000_FTQF_VF_BP | E1000_FTQF_MASK);
+       E1000_WRITE_REG(hw, E1000_DAQF(filter->index), 0);
+       E1000_WRITE_REG(hw, E1000_SAQF(filter->index), 0);
+       E1000_WRITE_REG(hw, E1000_SPQF(filter->index), 0);
+       E1000_WRITE_REG(hw, E1000_IMIR(filter->index), 0);
+       E1000_WRITE_REG(hw, E1000_IMIREXT(filter->index), 0);
+       return 0;
+}
+
 /*
  * igb_remove_5tuple_filter_82576 - remove a 5tuple filter
  *
@@ -4363,7 +4429,6 @@ static int
 igb_remove_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_info filter_5tuple;
@@ -4383,17 +4448,8 @@ igb_remove_5tuple_filter_82576(struct rte_eth_dev *dev,
                return -ENOENT;
        }
 
-       filter_info->fivetuple_mask &= ~(1 << filter->index);
-       TAILQ_REMOVE(&filter_info->fivetuple_list, filter, entries);
-       rte_free(filter);
+       igb_delete_5tuple_filter_82576(dev, filter);
 
-       E1000_WRITE_REG(hw, E1000_FTQF(filter->index),
-                       E1000_FTQF_VF_BP | E1000_FTQF_MASK);
-       E1000_WRITE_REG(hw, E1000_DAQF(filter->index), 0);
-       E1000_WRITE_REG(hw, E1000_SAQF(filter->index), 0);
-       E1000_WRITE_REG(hw, E1000_SPQF(filter->index), 0);
-       E1000_WRITE_REG(hw, E1000_IMIR(filter->index), 0);
-       E1000_WRITE_REG(hw, E1000_IMIREXT(filter->index), 0);
        return 0;
 }
 
@@ -4459,7 +4515,7 @@ eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
  *    - On success, zero.
  *    - On failure, a negative value.
  */
-static int
+int
 igb_add_del_ntuple_filter(struct rte_eth_dev *dev,
                        struct rte_eth_ntuple_filter *ntuple_filter,
                        bool add)
@@ -4625,7 +4681,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;
        }
@@ -4634,33 +4690,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
+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)
@@ -4700,16 +4758,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)
@@ -4804,7 +4861,7 @@ eth_igb_filter_ctrl(struct rte_eth_dev *dev,
                     enum rte_filter_op filter_op,
                     void *arg)
 {
-       int ret = -EINVAL;
+       int ret = 0;
 
        switch (filter_type) {
        case RTE_ETH_FILTER_NTUPLE:
@@ -4819,6 +4876,11 @@ eth_igb_filter_ctrl(struct rte_eth_dev *dev,
        case RTE_ETH_FILTER_FLEXIBLE:
                ret = eth_igb_flex_filter_handle(dev, filter_op, arg);
                break;
+       case RTE_ETH_FILTER_GENERIC:
+               if (filter_op != RTE_ETH_FILTER_GET)
+                       return -EINVAL;
+               *(const void **)arg = &igb_flow_ops;
+               break;
        default:
                PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
                                                        filter_type);
@@ -5506,12 +5568,45 @@ igb_syn_filter_restore(struct rte_eth_dev *dev)
        }
 }
 
+/* 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 flex byte filter */
+static inline void
+igb_flex_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_flex_filter *flex_filter;
+
+       TAILQ_FOREACH(flex_filter, &filter_info->flex_list, entries) {
+               igb_inject_flex_filter(dev, flex_filter);
+       }
+}
+
 /* 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);
+       igb_flex_filter_restore(dev);
 
        return 0;
 }