From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by dpdk.org (Postfix) with ESMTP id A2051231C for ; Tue, 20 May 2014 05:53:40 +0200 (CEST) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga102.fm.intel.com with ESMTP; 19 May 2014 20:53:49 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.98,871,1392192000"; d="scan'208";a="541839446" Received: from shilc102.sh.intel.com ([10.239.39.44]) by fmsmga002.fm.intel.com with ESMTP; 19 May 2014 20:53:47 -0700 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shilc102.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id s4K3rhGf006590; Tue, 20 May 2014 11:53:45 +0800 Received: from shecgisg004.sh.intel.com (localhost [127.0.0.1]) by shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id s4K3rdkb018791; Tue, 20 May 2014 11:53:41 +0800 Received: (from wujingji@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id s4K3rdmK018787; Tue, 20 May 2014 11:53:39 +0800 From: Jingjing Wu To: dev@dpdk.org Date: Tue, 20 May 2014 11:53:27 +0800 Message-Id: <1400558009-18667-3-git-send-email-jingjing.wu@intel.com> X-Mailer: git-send-email 1.7.0.7 In-Reply-To: <1400558009-18667-1-git-send-email-jingjing.wu@intel.com> References: <1400558009-18667-1-git-send-email-jingjing.wu@intel.com> Subject: [dpdk-dev] [PATCH 2/4][PMD][GENERIC_FILTER]add igb NIC filters of generic filter feature X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 May 2014 03:53:42 -0000 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 --- 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