X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fi40e%2Fi40e_fdir.c;h=ca423d9a53302dfe0653728ad36bed9e09b809e2;hb=6ced3dd72f5f7fe8f0d717edd0cee10f45a1eb84;hp=5a737ab126c8b206c98295e64157e25b8b51a9cf;hpb=8c5cb3c11513dc47b81ee2ee7f6153dff46ec5a1;p=dpdk.git diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 5a737ab126..ca423d9a53 100644 --- a/drivers/net/i40e/i40e_fdir.c +++ b/drivers/net/i40e/i40e_fdir.c @@ -73,9 +73,8 @@ #define I40E_FDIR_IPv6_PAYLOAD_LEN 380 #define I40E_FDIR_UDP_DEFAULT_LEN 400 -/* Wait count and interval for fdir filter programming */ -#define I40E_FDIR_WAIT_COUNT 10 -#define I40E_FDIR_WAIT_INTERVAL_US 1000 +/* Wait time for fdir filter programming */ +#define I40E_FDIR_MAX_WAIT_US 10000 /* Wait count and interval for fdir filter flush */ #define I40E_FDIR_FLUSH_RETRY 50 @@ -84,21 +83,6 @@ #define I40E_COUNTER_PF 2 /* Statistic counter index for one pf */ #define I40E_COUNTER_INDEX_FDIR(pf_id) (0 + (pf_id) * I40E_COUNTER_PF) -#define I40E_MAX_FLX_SOURCE_OFF 480 -#define I40E_FLX_OFFSET_IN_FIELD_VECTOR 50 - -#define NONUSE_FLX_PIT_DEST_OFF 63 -#define NONUSE_FLX_PIT_FSIZE 1 -#define MK_FLX_PIT(src_offset, fsize, dst_offset) ( \ - (((src_offset) << I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT) & \ - I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK) | \ - (((fsize) << I40E_PRTQF_FLX_PIT_FSIZE_SHIFT) & \ - I40E_PRTQF_FLX_PIT_FSIZE_MASK) | \ - ((((dst_offset) == NONUSE_FLX_PIT_DEST_OFF ? \ - NONUSE_FLX_PIT_DEST_OFF : \ - ((dst_offset) + I40E_FLX_OFFSET_IN_FIELD_VECTOR)) << \ - I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT) & \ - I40E_PRTQF_FLX_PIT_DEST_OFF_MASK)) #define I40E_FDIR_FLOWS ( \ (1 << RTE_ETH_FLOW_FRAG_IPV4) | \ @@ -113,13 +97,17 @@ (1 << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER) | \ (1 << RTE_ETH_FLOW_L2_PAYLOAD)) -#define I40E_FLEX_WORD_MASK(off) (0x80 >> (off)) - static int i40e_fdir_filter_programming(struct i40e_pf *pf, enum i40e_filter_pctype pctype, const struct rte_eth_fdir_filter *filter, bool add); -static int i40e_fdir_flush(struct rte_eth_dev *dev); +static int i40e_fdir_filter_convert(const struct rte_eth_fdir_filter *input, + struct i40e_fdir_filter *filter); +static struct i40e_fdir_filter * +i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info, + const struct rte_eth_fdir_input *input); +static int i40e_sw_fdir_filter_insert(struct i40e_pf *pf, + struct i40e_fdir_filter *filter); static int i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq) @@ -251,7 +239,7 @@ i40e_fdir_setup(struct i40e_pf *pf) /* reserve memory for the fdir programming packet */ snprintf(z_name, sizeof(z_name), "%s_%s_%d", - eth_dev->driver->pci_drv.driver.name, + eth_dev->data->drv_name, I40E_FDIR_MZ_NAME, eth_dev->data->port_id); mz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN, SOCKET_ID_ANY); @@ -294,8 +282,12 @@ i40e_fdir_teardown(struct i40e_pf *pf) vsi = pf->fdir.fdir_vsi; if (!vsi) return; - i40e_switch_tx_queue(hw, vsi->base_queue, FALSE); - i40e_switch_rx_queue(hw, vsi->base_queue, FALSE); + int err = i40e_switch_tx_queue(hw, vsi->base_queue, FALSE); + if (err) + PMD_DRV_LOG(DEBUG, "Failed to do FDIR TX switch off"); + err = i40e_switch_rx_queue(hw, vsi->base_queue, FALSE); + if (err) + PMD_DRV_LOG(DEBUG, "Failed to do FDIR RX switch off"); i40e_dev_rx_queue_release(pf->fdir.rxq); pf->fdir.rxq = NULL; i40e_dev_tx_queue_release(pf->fdir.txq); @@ -353,8 +345,15 @@ i40e_init_flx_pld(struct i40e_pf *pf) /* initialize the masks */ for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP; pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++) { - if (!I40E_VALID_PCTYPE((enum i40e_filter_pctype)pctype)) - continue; + if (hw->mac.type == I40E_MAC_X722) { + if (!I40E_VALID_PCTYPE_X722( + (enum i40e_filter_pctype)pctype)) + continue; + } else { + if (!I40E_VALID_PCTYPE( + (enum i40e_filter_pctype)pctype)) + continue; + } pf->fdir.flex_mask[pctype].word_mask = 0; i40e_write_rx_ctl(hw, I40E_PRTQF_FD_FLXINSET(pctype), 0); for (i = 0; i < I40E_FDIR_BITMASK_NUM_WORD; i++) { @@ -365,8 +364,6 @@ i40e_init_flx_pld(struct i40e_pf *pf) } } -#define I40E_WORD(hi, lo) (uint16_t)((((hi) << 8) & 0xFF00) | ((lo) & 0xFF)) - #define I40E_VALIDATE_FLEX_PIT(flex_pit1, flex_pit2) do { \ if ((flex_pit2).src_offset < \ (flex_pit1).src_offset + (flex_pit1).size) { \ @@ -664,14 +661,16 @@ i40e_fdir_configure(struct rte_eth_dev *dev) i40e_set_flx_pld_cfg(pf, &conf->flex_set[i]); /* configure flex mask*/ for (i = 0; i < conf->nb_flexmasks; i++) { -#ifdef X722_SUPPORT - /* get translated pctype value in fd pctype register */ - pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(hw, - I40E_GLQF_FD_PCTYPES((int)i40e_flowtype_to_pctype( - conf->flex_mask[i].flow_type))); -#else - pctype = i40e_flowtype_to_pctype(conf->flex_mask[i].flow_type); -#endif + if (hw->mac.type == I40E_MAC_X722) { + /* get translated pctype value in fd pctype register */ + pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl( + hw, I40E_GLQF_FD_PCTYPES( + (int)i40e_flowtype_to_pctype( + conf->flex_mask[i].flow_type))); + } else + pctype = i40e_flowtype_to_pctype( + conf->flex_mask[i].flow_type); + i40e_set_flex_mask_on_pctype(pf, pctype, &conf->flex_mask[i]); } @@ -1008,13 +1007,81 @@ i40e_check_fdir_programming_status(struct i40e_rx_queue *rxq) return ret; } +static int +i40e_fdir_filter_convert(const struct rte_eth_fdir_filter *input, + struct i40e_fdir_filter *filter) +{ + rte_memcpy(&filter->fdir, input, sizeof(struct rte_eth_fdir_filter)); + return 0; +} + +/* Check if there exists the flow director filter */ +static struct i40e_fdir_filter * +i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info, + const struct rte_eth_fdir_input *input) +{ + int ret; + + ret = rte_hash_lookup(fdir_info->hash_table, (const void *)input); + if (ret < 0) + return NULL; + + return fdir_info->hash_map[ret]; +} + +/* Add a flow director filter into the SW list */ +static int +i40e_sw_fdir_filter_insert(struct i40e_pf *pf, struct i40e_fdir_filter *filter) +{ + struct i40e_fdir_info *fdir_info = &pf->fdir; + int ret; + + ret = rte_hash_add_key(fdir_info->hash_table, + &filter->fdir.input); + if (ret < 0) { + PMD_DRV_LOG(ERR, + "Failed to insert fdir filter to hash table %d!", + ret); + return ret; + } + fdir_info->hash_map[ret] = filter; + + TAILQ_INSERT_TAIL(&fdir_info->fdir_list, filter, rules); + + return 0; +} + +/* Delete a flow director filter from the SW list */ +int +i40e_sw_fdir_filter_del(struct i40e_pf *pf, struct rte_eth_fdir_input *input) +{ + struct i40e_fdir_info *fdir_info = &pf->fdir; + struct i40e_fdir_filter *filter; + int ret; + + ret = rte_hash_del_key(fdir_info->hash_table, input); + if (ret < 0) { + PMD_DRV_LOG(ERR, + "Failed to delete fdir filter to hash table %d!", + ret); + return ret; + } + filter = fdir_info->hash_map[ret]; + fdir_info->hash_map[ret] = NULL; + + TAILQ_REMOVE(&fdir_info->fdir_list, filter, rules); + rte_free(filter); + + return 0; +} + /* * i40e_add_del_fdir_filter - add or remove a flow director filter. * @pf: board private structure * @filter: fdir filter entry * @add: 0 - delete, 1 - add */ -static int +int i40e_add_del_fdir_filter(struct rte_eth_dev *dev, const struct rte_eth_fdir_filter *filter, bool add) @@ -1023,6 +1090,9 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev, struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); unsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt; enum i40e_filter_pctype pctype; + struct i40e_fdir_info *fdir_info = &pf->fdir; + struct i40e_fdir_filter *fdir_filter, *node; + struct i40e_fdir_filter check_filter; /* Check if the filter exists */ int ret = 0; if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) { @@ -1045,6 +1115,22 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev, return -EINVAL; } + /* Check if there is the filter in SW list */ + memset(&check_filter, 0, sizeof(check_filter)); + i40e_fdir_filter_convert(filter, &check_filter); + node = i40e_sw_fdir_filter_lookup(fdir_info, &check_filter.fdir.input); + if (add && node) { + PMD_DRV_LOG(ERR, + "Conflict with existing flow director rules!"); + return -EINVAL; + } + + if (!add && !node) { + PMD_DRV_LOG(ERR, + "There's no corresponding flow firector filter!"); + return -EINVAL; + } + memset(pkt, 0, I40E_FDIR_PKT_LEN); ret = i40e_fdir_construct_pkt(pf, &filter->input, pkt); @@ -1053,14 +1139,14 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev, return ret; } -#ifdef X722_SUPPORT - /* get translated pctype value in fd pctype register */ - pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(hw, - I40E_GLQF_FD_PCTYPES((int)i40e_flowtype_to_pctype( - filter->input.flow_type))); -#else - pctype = i40e_flowtype_to_pctype(filter->input.flow_type); -#endif + if (hw->mac.type == I40E_MAC_X722) { + /* get translated pctype value in fd pctype register */ + pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl( + hw, I40E_GLQF_FD_PCTYPES( + (int)i40e_flowtype_to_pctype( + filter->input.flow_type))); + } else + pctype = i40e_flowtype_to_pctype(filter->input.flow_type); ret = i40e_fdir_filter_programming(pf, pctype, filter, add); if (ret < 0) { @@ -1068,6 +1154,16 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev, pctype); return ret; } + + if (add) { + fdir_filter = rte_zmalloc("fdir_filter", + sizeof(*fdir_filter), 0); + rte_memcpy(fdir_filter, &check_filter, sizeof(check_filter)); + ret = i40e_sw_fdir_filter_insert(pf, fdir_filter); + } else { + ret = i40e_sw_fdir_filter_del(pf, &node->fdir.input); + } + return ret; } @@ -1183,35 +1279,34 @@ i40e_fdir_filter_programming(struct i40e_pf *pf, /* Update the tx tail register */ rte_wmb(); I40E_PCI_REG_WRITE(txq->qtx_tail, txq->tx_tail); - - for (i = 0; i < I40E_FDIR_WAIT_COUNT; i++) { - rte_delay_us(I40E_FDIR_WAIT_INTERVAL_US); + for (i = 0; i < I40E_FDIR_MAX_WAIT_US; i++) { if ((txdp->cmd_type_offset_bsz & rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) == rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE)) break; + rte_delay_us(1); } - if (i >= I40E_FDIR_WAIT_COUNT) { + if (i >= I40E_FDIR_MAX_WAIT_US) { PMD_DRV_LOG(ERR, "Failed to program FDIR filter:" " time out to get DD on tx queue."); return -ETIMEDOUT; } /* totally delay 10 ms to check programming status*/ - rte_delay_us((I40E_FDIR_WAIT_COUNT - i) * I40E_FDIR_WAIT_INTERVAL_US); - if (i40e_check_fdir_programming_status(rxq) < 0) { - PMD_DRV_LOG(ERR, "Failed to program FDIR filter:" - " programming status reported."); - return -ENOSYS; + for (; i < I40E_FDIR_MAX_WAIT_US; i++) { + if (i40e_check_fdir_programming_status(rxq) >= 0) + return 0; + rte_delay_us(1); } - - return 0; + PMD_DRV_LOG(ERR, + "Failed to program FDIR filter: programming status reported."); + return -ETIMEDOUT; } /* * i40e_fdir_flush - clear all filters of Flow Director table * @pf: board private structure */ -static int +int i40e_fdir_flush(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); @@ -1290,6 +1385,7 @@ i40e_fdir_info_get_flex_mask(struct i40e_pf *pf, { struct i40e_fdir_flex_mask *mask; struct rte_eth_fdir_flex_mask *ptr = flex_mask; + struct i40e_hw *hw = I40E_PF_TO_HW(pf); uint16_t flow_type; uint8_t i, j; uint16_t off_bytes, mask_tmp; @@ -1298,8 +1394,13 @@ i40e_fdir_info_get_flex_mask(struct i40e_pf *pf, i <= I40E_FILTER_PCTYPE_L2_PAYLOAD; i++) { mask = &pf->fdir.flex_mask[i]; - if (!I40E_VALID_PCTYPE((enum i40e_filter_pctype)i)) - continue; + if (hw->mac.type == I40E_MAC_X722) { + if (!I40E_VALID_PCTYPE_X722((enum i40e_filter_pctype)i)) + continue; + } else { + if (!I40E_VALID_PCTYPE((enum i40e_filter_pctype)i)) + continue; + } flow_type = i40e_pctype_to_flowtype((enum i40e_filter_pctype)i); for (j = 0; j < I40E_FDIR_MAX_FLEXWORD_NUM; j++) { if (mask->word_mask & I40E_FLEX_WORD_MASK(j)) { @@ -1466,3 +1567,30 @@ i40e_fdir_ctrl_func(struct rte_eth_dev *dev, } return ret; } + +/* Restore flow director filter */ +void +i40e_fdir_filter_restore(struct i40e_pf *pf) +{ + struct rte_eth_dev *dev = I40E_VSI_TO_ETH_DEV(pf->main_vsi); + struct i40e_fdir_filter_list *fdir_list = &pf->fdir.fdir_list; + struct i40e_fdir_filter *f; + struct i40e_hw *hw = I40E_PF_TO_HW(pf); + uint32_t fdstat; + uint32_t guarant_cnt; /**< Number of filters in guaranteed spaces. */ + uint32_t best_cnt; /**< Number of filters in best effort spaces. */ + + TAILQ_FOREACH(f, fdir_list, rules) + i40e_add_del_fdir_filter(dev, &f->fdir, TRUE); + + fdstat = I40E_READ_REG(hw, I40E_PFQF_FDSTAT); + guarant_cnt = + (uint32_t)((fdstat & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >> + I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT); + best_cnt = + (uint32_t)((fdstat & I40E_PFQF_FDSTAT_BEST_CNT_MASK) >> + I40E_PFQF_FDSTAT_BEST_CNT_SHIFT); + + PMD_DRV_LOG(INFO, "FDIR: Guarant count: %d, Best count: %d", + guarant_cnt, best_cnt); +}