This patch adds following igb NIC filters implement for intel NIC 82580 and i350
  syn filter, ethertype filter, 2tuple filter, flex filter

Signed-off-by: jingjing.wu <jingjing.wu at intel.com>
---
 lib/librte_pmd_e1000/e1000_ethdev.h |  38 +++
 lib/librte_pmd_e1000/igb_ethdev.c   | 512 ++++++++++++++++++++++++++++++++++++
 2 files changed, 550 insertions(+)

diff --git a/lib/librte_pmd_e1000/e1000_ethdev.h 
b/lib/librte_pmd_e1000/e1000_ethdev.h
index d09064e..6b11289 100644
--- a/lib/librte_pmd_e1000/e1000_ethdev.h
+++ b/lib/librte_pmd_e1000/e1000_ethdev.h
@@ -52,6 +52,44 @@
 #define E1000_CTRL_EXT_EXTEND_VLAN  (1<<26)    /* EXTENDED VLAN */
 #define IGB_VFTA_SIZE 128

+#define IGB_MAX_RX_QUEUE_NUM   8
+
+#define E1000_SYN_FILTER_ENABLE                0x00000001 /** syn filter 
enable field*/
+#define E1000_SYN_FILTER_QUEUE      0x0000000E /** syn filter queue field*/
+#define E1000_SYN_FILTER_QUEUE_SHIFT      1 /** syn filter queue field*/
+#define E1000_RFCTL_SYNQFP                     0x00080000 /** SYNQFP in RFCTL 
register*/
+
+#define E1000_ETQF_ETHERTYPE 0x0000FFFF
+#define E1000_ETQF_QUEUE        0x00070000
+#define E1000_ETQF_QUEUE_SHIFT 16
+#define E1000_MAX_ETQF_FILTERS 8
+
+#define E1000_IMIR_DSTPORT             0x0000FFFF
+#define E1000_IMIR_PRIORITY    0xE0000000
+#define E1000_IMIR_EXT_SIZE_BP 0x00001000
+#define E1000_IMIR_EXT_CTRL_UGR        0x00002000
+#define E1000_IMIR_EXT_CTRL_ACK        0x00004000
+#define E1000_IMIR_EXT_CTRL_PSH        0x00008000
+#define E1000_IMIR_EXT_CTRL_RST        0x00010000
+#define E1000_IMIR_EXT_CTRL_SYN        0x00020000
+#define E1000_IMIR_EXT_CTRL_FIN        0x00040000
+#define E1000_IMIR_EXT_CTRL_BP 0x00080000
+#define E1000_MAX_TTQF_FILTERS         8
+#define E1000_2TUPLE_MAX_PRI   7
+
+#define E1000_MAX_FLEXIBLE_FILTERS 8
+#define E1000_MAX_FHFT 4
+#define E1000_MAX_FHFT_EXT 4
+#define E1000_MAX_FLEX_FILTER_PRI 7
+#define E1000_MAX_FLEX_FILTER_LEN 128
+#define E1000_FHFT_QUEUEING_LEN                0x0000007F
+#define E1000_FHFT_QUEUEING_QUEUE      0x00000700
+#define E1000_FHFT_QUEUEING_PRIO       0x00070000
+#define E1000_FHFT_QUEUEING_OFFSET             0xFC
+#define E1000_FHFT_QUEUEING_QUEUE_SHIFT                8
+#define E1000_FHFT_QUEUEING_PRIO_SHIFT                 16
+#define IXGBE_WUFC_FLEX_HQ     0x00004000
+
 /* structure for interrupt relative data */
 struct e1000_interrupt {
        uint32_t flags;
diff --git a/lib/librte_pmd_e1000/igb_ethdev.c 
b/lib/librte_pmd_e1000/igb_ethdev.c
index 673b4de..478688f 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -123,6 +123,28 @@ static int 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);

+static int eth_igb_set_syn_filter(struct rte_eth_dev *dev,
+                                          struct rte_syn_filter *filter, 
uint8_t rx_queue);
+static int eth_igb_get_syn_filter(struct rte_eth_dev *dev,
+                                          struct rte_syn_filter *filter, 
uint8_t *rx_queue);
+static int eth_igb_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t 
index, 
+                                          struct rte_ethertype_filter *filter, 
uint8_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, 
uint8_t *rx_queue);
+static int eth_igb_add_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+                                          struct rte_2tuple_filter *filter, 
uint8_t rx_queue);
+static int eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev,
+                                          uint16_t index);
+static int eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+                                          struct rte_2tuple_filter *filter, 
uint8_t *rx_queue);
+static int eth_igb_add_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+                                          struct rte_flex_filter *filter, 
uint8_t rx_queue);
+static int eth_igb_remove_flex_filter(struct rte_eth_dev *dev,
+                                          uint16_t index);
+static int eth_igb_get_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+                                          struct rte_flex_filter *filter, 
uint8_t *rx_queue);
+
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
  */
@@ -193,6 +215,17 @@ static struct eth_dev_ops eth_igb_ops = {
        .mac_addr_remove      = eth_igb_rar_clear,
        .reta_update          = eth_igb_rss_reta_update,
        .reta_query           = eth_igb_rss_reta_query,
+       .set_syn_filter              = eth_igb_set_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,
+       .add_flex_filter             = eth_igb_add_flex_filter,
+       .remove_flex_filter              = eth_igb_remove_flex_filter,
+       .get_flex_filter                 = eth_igb_get_flex_filter,
 };

 /*
@@ -2182,3 +2215,482 @@ 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) \
+               return -ENOSYS;\
+}while(0)
+
+/*
+ *set the syn filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * syn: 1 means enable, 0 means disable.
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *     - On success, zero.
+ *     - On failure, a negative value.
+ */
+static int
+eth_igb_set_syn_filter(struct rte_eth_dev *dev,
+                                          struct rte_syn_filter *filter, 
uint8_t rx_queue)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t synqf, rfctl;
+
+       MAC_TYPE_FILTER_SUP(hw->mac.type);
+       
+       if (rx_queue >= IGB_MAX_RX_QUEUE_NUM)
+               return (-EINVAL);
+
+       synqf = E1000_READ_REG(hw, E1000_SYNQF(0));
+       rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+       
+    if (filter->enable){
+               if (synqf & E1000_SYN_FILTER_ENABLE)
+                       return (-EINVAL);
+               synqf = (uint32_t)(((rx_queue << E1000_SYN_FILTER_QUEUE_SHIFT) 
& E1000_SYN_FILTER_QUEUE) |
+                                               E1000_SYN_FILTER_ENABLE);
+    }else
+               synqf = 0;
+       
+       if (filter->hig_pri)
+               rfctl |= E1000_RFCTL_SYNQFP;
+       else
+               rfctl &= ~E1000_RFCTL_SYNQFP;
+       
+       E1000_WRITE_REG(hw, E1000_SYNQF(0), synqf);
+       E1000_WRITE_REG(hw, E1000_RFCTL, rfctl);
+       return 0;
+}
+
+/*
+ *get the syn filter's info
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * *syn: pointer to syn value (1 means enable, 0 means disable).
+ * *rx_queue: pointer to the queue id the filter assigned to
+ *
+ * @return
+ *     - On success, zero.
+ *     - On failure, a negative value.
+ */
+static int
+eth_igb_get_syn_filter(struct rte_eth_dev *dev,
+                                          struct rte_syn_filter *filter, 
uint8_t *rx_queue)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t synqf, rfctl;
+       
+       MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+       synqf = E1000_READ_REG(hw, E1000_SYNQF(0));
+       rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+       filter->enable = (synqf & E1000_SYN_FILTER_ENABLE)? 1 : 0;
+       filter->hig_pri = (rfctl & E1000_RFCTL_SYNQFP) ? 1 : 0;
+       *rx_queue = (uint8_t)((synqf & E1000_SYN_FILTER_QUEUE)>> 
E1000_SYN_FILTER_QUEUE_SHIFT);
+
+       return 0;
+}
+
+/*
+ *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, 
uint8_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 support in 
E1000.\n",
+                       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;
+}
+
+/*
+ *gets 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, 
uint8_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);
+}
+
+/*
+ *add a 2tuple 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_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+                                          struct rte_2tuple_filter *filter, 
uint8_t rx_queue)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t ttqf, imir = 0;
+       uint32_t imir_ext = 0;
+       
+       MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+       if (index >= E1000_MAX_TTQF_FILTERS ||
+               rx_queue >= IGB_MAX_RX_QUEUE_NUM || filter->priority > 
E1000_2TUPLE_MAX_PRI)
+               return (-EINVAL);  /**filter index is out of range*/
+       if  (filter->tcp_flags > TCP_FLAG_ALL)
+               return (-EINVAL);  /**flags is invalid*/
+       
+       ttqf = E1000_READ_REG(hw, E1000_TTQF(index));
+       if (ttqf & E1000_TTQF_QUEUE_ENABLE)
+               return (-EINVAL);  /**filter index is in use*/
+
+       imir = (uint32_t)(filter->dst_port & E1000_IMIR_DSTPORT);
+       if (filter->dst_port_mask == 1) /**1b means not compare*/
+               imir |= E1000_IMIR_PORT_BP;
+       else
+               imir &= ~E1000_IMIR_PORT_BP;
+
+       imir |= filter->priority << E1000_IMIR_PRIORITY_SHIFT;
+
+       ttqf = 0;
+       ttqf |= E1000_TTQF_QUEUE_ENABLE;
+       ttqf |= (uint32_t)(rx_queue << E1000_TTQF_QUEUE_SHIFT);
+       ttqf |= (uint32_t)(filter->protocol & E1000_TTQF_PROTOCOL_MASK);
+       if (filter->protocol_mask == 1)
+               ttqf |= E1000_TTQF_MASK_ENABLE;
+       else
+               ttqf &= ~E1000_TTQF_MASK_ENABLE;
+
+       imir_ext |= E1000_IMIR_EXT_SIZE_BP;
+       /*tcp flags bits setting*/
+       if (filter->tcp_flags & TCP_FLAG_ALL){
+               if (filter->tcp_flags & TCP_UGR_FLAG)
+                       imir_ext |= E1000_IMIR_EXT_CTRL_UGR;
+               if (filter->tcp_flags & TCP_ACK_FLAG)
+                       imir_ext |= E1000_IMIR_EXT_CTRL_ACK;
+               if (filter->tcp_flags & TCP_PSH_FLAG)
+                       imir_ext |= E1000_IMIR_EXT_CTRL_PSH;
+               if (filter->tcp_flags & TCP_RST_FLAG)
+                       imir_ext |= E1000_IMIR_EXT_CTRL_RST;
+               if (filter->tcp_flags & TCP_SYN_FLAG)
+                       imir_ext |= E1000_IMIR_EXT_CTRL_SYN;
+               if (filter->tcp_flags & TCP_FIN_FLAG)
+                       imir_ext |= E1000_IMIR_EXT_CTRL_FIN;
+               imir_ext &= ~E1000_IMIR_EXT_CTRL_BP;
+       }
+       else
+               imir_ext |= E1000_IMIR_EXT_CTRL_BP;
+       E1000_WRITE_REG(hw, E1000_IMIR(index), imir);
+       E1000_WRITE_REG(hw, E1000_TTQF(index), ttqf);
+       E1000_WRITE_REG(hw, E1000_IMIREXT(index), imir_ext);
+
+       return 0;
+}
+
+/*
+ *remove a 2tuple 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_2tuple_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_TTQF_FILTERS)
+               return (-EINVAL);  /**filter index is out of range*/
+       
+       E1000_WRITE_REG(hw, E1000_TTQF(index), 0);
+       E1000_WRITE_REG(hw, E1000_IMIR(index), 0);
+       E1000_WRITE_REG(hw, E1000_IMIREXT(index), 0);
+       return 0;
+
+}
+
+/*
+ *get a 2tuple filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: pointer of the queue id the filter assigned to
+ *
+ * @return
+ *     - On success, zero.
+ *     - On failure, a negative value.
+ */
+static int
+eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+                                          struct rte_2tuple_filter *filter, 
uint8_t *rx_queue)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t imir, ttqf;
+       
+       MAC_TYPE_FILTER_SUP(hw->mac.type);
+       
+       if (index >= E1000_MAX_TTQF_FILTERS)
+               return (-EINVAL);  /**filter index is out of range*/
+       
+       ttqf = E1000_READ_REG(hw, E1000_TTQF(index));
+       if (ttqf & E1000_TTQF_QUEUE_ENABLE){
+               imir = E1000_READ_REG(hw, E1000_IMIR(index));
+               filter->protocol = ttqf & E1000_TTQF_PROTOCOL_MASK;
+               filter->protocol_mask = (ttqf & E1000_TTQF_MASK_ENABLE) ? 1 : 0;
+               *rx_queue = (ttqf & E1000_TTQF_RX_QUEUE_MASK) >> 
E1000_TTQF_QUEUE_SHIFT;
+               filter->dst_port = (uint16_t)(imir & E1000_IMIR_DSTPORT);
+               filter->dst_port_mask = (imir & E1000_IMIR_PORT_BP) ? 1 : 0;
+               filter->priority = (imir & E1000_IMIR_PRIORITY) >> 
E1000_IMIR_PRIORITY_SHIFT;
+               return 0;
+       }
+       return (-ENOENT);
+}
+
+/*
+ *add a flex 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_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+                                          struct rte_flex_filter *filter, 
uint8_t rx_queue)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t wufc, en_bits = 0;
+       uint32_t queueing = 0;
+       uint32_t reg_off = 0;
+       uint8_t i, j= 0;
+
+       MAC_TYPE_FILTER_SUP(hw->mac.type);
+       
+       if (index >= E1000_MAX_FLEXIBLE_FILTERS)
+               return (-EINVAL);  /**filter index is out of range*/
+       
+       if (filter->len == 0 || filter->len > E1000_MAX_FLEX_FILTER_LEN||
+               filter->len % 8 != 0 || filter->priority > 
E1000_MAX_FLEX_FILTER_PRI)
+               return (-EINVAL);
+
+       
+       wufc = E1000_READ_REG(hw, E1000_WUFC);
+       en_bits = IXGBE_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index);
+       if ((wufc & en_bits) == en_bits)
+               return (-EINVAL);  /**the filter is  enabled*/
+       
+       E1000_WRITE_REG(hw, E1000_WUFC, wufc | IXGBE_WUFC_FLEX_HQ | 
(E1000_WUFC_FLX0 << index));
+       
+       j = 0;
+       if (index < E1000_MAX_FHFT)
+               reg_off = E1000_FHFT(index);
+       else
+               reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT);
+
+       for (i = 0; i < 16; i++){
+               E1000_WRITE_REG(hw, reg_off + i*4*4, filter->dwords[j]);
+               E1000_WRITE_REG(hw, reg_off + (i*4+1)*4, filter->dwords[++j]);
+               E1000_WRITE_REG(hw, reg_off + (i*4+2)*4, 
(uint32_t)filter->mask[i]);
+               ++j;
+       }
+       queueing |= filter->len | (rx_queue << E1000_FHFT_QUEUEING_QUEUE_SHIFT) 
|
+               (filter->priority << E1000_FHFT_QUEUEING_PRIO_SHIFT);
+       E1000_WRITE_REG(hw, reg_off + E1000_FHFT_QUEUEING_OFFSET, queueing);
+       return 0;
+}
+
+/*
+ *remove a flex 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_flex_filter(struct rte_eth_dev *dev,
+                                          uint16_t index)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t wufc, reg_off = 0;
+       uint8_t i;
+
+       MAC_TYPE_FILTER_SUP(hw->mac.type);
+       
+       if (index >= E1000_MAX_FLEXIBLE_FILTERS)
+               return (-EINVAL);  /**filter index is out of range*/
+       
+       wufc = E1000_READ_REG(hw, E1000_WUFC);
+       E1000_WRITE_REG(hw, E1000_WUFC, wufc &(~(E1000_WUFC_FLX0 << index)));
+       
+       if (index < E1000_MAX_FHFT)
+               reg_off = E1000_FHFT(index);
+       else
+               reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT);
+       
+       for (i = 0; i < 64; i++)
+               E1000_WRITE_REG(hw, reg_off + i*4, 0);
+       return 0;
+}
+
+/*
+ *get a flex filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: the pointer of the queue id the filter assigned to
+ *
+ * @return
+ *     - On success, zero.
+ *     - On failure, a negative value.
+ */
+static int
+eth_igb_get_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+                                          struct rte_flex_filter *filter, 
uint8_t *rx_queue)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t wufc, queueing, wufc_en = 0;
+       uint8_t i,j;
+
+       MAC_TYPE_FILTER_SUP(hw->mac.type);
+       
+       if (index >= E1000_MAX_FLEXIBLE_FILTERS)
+               return (-EINVAL);  /**filter index is out of range*/
+       
+       wufc = E1000_READ_REG(hw,E1000_WUFC);
+       wufc_en = IXGBE_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index);
+       
+       if ((wufc & wufc_en) == wufc_en){
+               uint32_t reg_off = 0;
+               
+               j = 0;
+               if (index < E1000_MAX_FHFT)
+                       reg_off = E1000_FHFT(index);
+               else
+                       reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT);
+               
+               for (i = 0; i < 16; i++, j = i * 2){
+                       filter->dwords[j] = E1000_READ_REG(hw, reg_off + i*4*4);
+                       filter->dwords[j+1] = E1000_READ_REG(hw, reg_off + 
(i*4+1)*4);
+                       filter->mask[i] = E1000_READ_REG(hw, reg_off + 
(i*4+2)*4);
+               }
+               queueing =      E1000_READ_REG(hw, reg_off + 
E1000_FHFT_QUEUEING_OFFSET);
+               filter->len = queueing & E1000_FHFT_QUEUEING_LEN;
+               filter->priority = (queueing & E1000_FHFT_QUEUEING_PRIO) >> 
E1000_FHFT_QUEUEING_PRIO_SHIFT;
+               *rx_queue = (queueing & E1000_FHFT_QUEUEING_QUEUE) >> 
E1000_FHFT_QUEUEING_QUEUE_SHIFT;
+               return 0;
+       }
+       return (-ENOENT);
+}
-- 
1.8.1.4

Reply via email to