X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fi40e%2Fi40e_ethdev.c;h=fcf150e127003f190104b08dab391a8566f1cf3c;hb=6a11a1eac0b6dcd52580eef99cf6f09e3361cc3b;hp=11c02b1888b4d78dd6d5a82e18b4472c355669b8;hpb=8bccf4774c3007726b45b73318732ea29dc435ce;p=dpdk.git diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 11c02b1888..fcf150e127 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -17,8 +17,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -39,12 +39,12 @@ #include "i40e_pf.h" #include "i40e_regs.h" #include "rte_pmd_i40e.h" +#include "i40e_hash.h" #define ETH_I40E_FLOATING_VEB_ARG "enable_floating_veb" #define ETH_I40E_FLOATING_VEB_LIST_ARG "floating_veb_list" #define ETH_I40E_SUPPORT_MULTI_DRIVER "support-multi-driver" #define ETH_I40E_QUEUE_NUM_PER_VF_ARG "queue-num-per-vf" -#define ETH_I40E_USE_LATEST_VEC "use-latest-supported-vec" #define ETH_I40E_VF_MSG_CFG "vf_msg_cfg" #define I40E_CLEAR_PXE_WAIT_MS 200 @@ -202,12 +202,12 @@ #define I40E_TRANSLATE_INSET 0 #define I40E_TRANSLATE_REG 1 -#define I40E_INSET_IPV4_TOS_MASK 0x0009FF00UL -#define I40E_INSET_IPv4_TTL_MASK 0x000D00FFUL -#define I40E_INSET_IPV4_PROTO_MASK 0x000DFF00UL -#define I40E_INSET_IPV6_TC_MASK 0x0009F00FUL -#define I40E_INSET_IPV6_HOP_LIMIT_MASK 0x000CFF00UL -#define I40E_INSET_IPV6_NEXT_HDR_MASK 0x000C00FFUL +#define I40E_INSET_IPV4_TOS_MASK 0x0000FF00UL +#define I40E_INSET_IPV4_TTL_MASK 0x000000FFUL +#define I40E_INSET_IPV4_PROTO_MASK 0x0000FF00UL +#define I40E_INSET_IPV6_TC_MASK 0x0000F00FUL +#define I40E_INSET_IPV6_HOP_LIMIT_MASK 0x0000FF00UL +#define I40E_INSET_IPV6_NEXT_HDR_MASK 0x000000FFUL /* PCI offset for querying capability */ #define PCI_DEV_CAP_REG 0xA4 @@ -220,12 +220,31 @@ /* Bit mask of Extended Tag enable/disable */ #define PCI_DEV_CTRL_EXT_TAG_MASK (1 << PCI_DEV_CTRL_EXT_TAG_SHIFT) +#define I40E_GLQF_PIT_IPV4_START 2 +#define I40E_GLQF_PIT_IPV4_COUNT 2 +#define I40E_GLQF_PIT_IPV6_START 4 +#define I40E_GLQF_PIT_IPV6_COUNT 2 + +#define I40E_GLQF_PIT_SOURCE_OFF_GET(a) \ + (((a) & I40E_GLQF_PIT_SOURCE_OFF_MASK) >> \ + I40E_GLQF_PIT_SOURCE_OFF_SHIFT) + +#define I40E_GLQF_PIT_DEST_OFF_GET(a) \ + (((a) & I40E_GLQF_PIT_DEST_OFF_MASK) >> \ + I40E_GLQF_PIT_DEST_OFF_SHIFT) + +#define I40E_GLQF_PIT_FSIZE_GET(a) (((a) & I40E_GLQF_PIT_FSIZE_MASK) >> \ + I40E_GLQF_PIT_FSIZE_SHIFT) + +#define I40E_GLQF_PIT_BUILD(off, mask) (((off) << 16) | (mask)) +#define I40E_FDIR_FIELD_OFFSET(a) ((a) >> 1) + static int eth_i40e_dev_init(struct rte_eth_dev *eth_dev, void *init_params); static int eth_i40e_dev_uninit(struct rte_eth_dev *eth_dev); static int i40e_dev_configure(struct rte_eth_dev *dev); static int i40e_dev_start(struct rte_eth_dev *dev); -static void i40e_dev_stop(struct rte_eth_dev *dev); -static void i40e_dev_close(struct rte_eth_dev *dev); +static int i40e_dev_stop(struct rte_eth_dev *dev); +static int i40e_dev_close(struct rte_eth_dev *dev); static int i40e_dev_reset(struct rte_eth_dev *dev); static int i40e_dev_promiscuous_enable(struct rte_eth_dev *dev); static int i40e_dev_promiscuous_disable(struct rte_eth_dev *dev); @@ -319,13 +338,8 @@ static int i40e_dev_udp_tunnel_port_add(struct rte_eth_dev *dev, static int i40e_dev_udp_tunnel_port_del(struct rte_eth_dev *dev, struct rte_eth_udp_tunnel *udp_tunnel); static void i40e_filter_input_set_init(struct i40e_pf *pf); -static int i40e_ethertype_filter_handle(struct rte_eth_dev *dev, - enum rte_filter_op filter_op, - void *arg); -static int i40e_dev_filter_ctrl(struct rte_eth_dev *dev, - enum rte_filter_type filter_type, - enum rte_filter_op filter_op, - void *arg); +static int i40e_dev_flow_ops_get(struct rte_eth_dev *dev, + const struct rte_flow_ops **ops); static int i40e_dev_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info); static int i40e_dev_sync_phy_type(struct i40e_hw *hw); @@ -399,14 +413,12 @@ static void i40e_ethertype_filter_restore(struct i40e_pf *pf); static void i40e_tunnel_filter_restore(struct i40e_pf *pf); static void i40e_filter_restore(struct i40e_pf *pf); static void i40e_notify_all_vfs_link_status(struct rte_eth_dev *dev); -static int i40e_pf_config_rss(struct i40e_pf *pf); static const char *const valid_keys[] = { ETH_I40E_FLOATING_VEB_ARG, ETH_I40E_FLOATING_VEB_LIST_ARG, ETH_I40E_SUPPORT_MULTI_DRIVER, ETH_I40E_QUEUE_NUM_PER_VF_ARG, - ETH_I40E_USE_LATEST_VEC, ETH_I40E_VF_MSG_CFG, NULL}; @@ -474,10 +486,6 @@ static const struct eth_dev_ops i40e_eth_dev_ops = { .rx_queue_intr_enable = i40e_dev_rx_queue_intr_enable, .rx_queue_intr_disable = i40e_dev_rx_queue_intr_disable, .rx_queue_release = i40e_dev_rx_queue_release, - .rx_queue_count = i40e_dev_rx_queue_count, - .rx_descriptor_done = i40e_dev_rx_descriptor_done, - .rx_descriptor_status = i40e_dev_rx_descriptor_status, - .tx_descriptor_status = i40e_dev_tx_descriptor_status, .tx_queue_setup = i40e_dev_tx_queue_setup, .tx_queue_release = i40e_dev_tx_queue_release, .dev_led_on = i40e_dev_led_on, @@ -493,7 +501,7 @@ static const struct eth_dev_ops i40e_eth_dev_ops = { .rss_hash_conf_get = i40e_dev_rss_hash_conf_get, .udp_tunnel_port_add = i40e_dev_udp_tunnel_port_add, .udp_tunnel_port_del = i40e_dev_udp_tunnel_port_del, - .filter_ctrl = i40e_dev_filter_ctrl, + .flow_ops_get = i40e_dev_flow_ops_get, .rxq_info_get = i40e_rxq_info_get, .txq_info_get = i40e_txq_info_get, .rx_burst_mode_get = i40e_rx_burst_mode_get, @@ -517,6 +525,7 @@ static const struct eth_dev_ops i40e_eth_dev_ops = { .mtu_set = i40e_dev_mtu_set, .tm_ops_get = i40e_tm_ops_get, .tx_done_cleanup = i40e_tx_done_cleanup, + .get_monitor_addr = i40e_get_monitor_addr, }; /* store statistics names and its offset in stats structure */ @@ -647,6 +656,13 @@ eth_i40e_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, return retval; } + if (eth_da.nb_representor_ports > 0 && + eth_da.type != RTE_ETH_REPRESENTOR_VF) { + PMD_DRV_LOG(ERR, "unsupported representor type: %s\n", + pci_dev->device.devargs->args); + return -ENOTSUP; + } + retval = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name, sizeof(struct i40e_adapter), eth_dev_pci_specific_init, pci_dev, @@ -770,6 +786,21 @@ static inline void i40e_config_automask(struct i40e_pf *pf) I40E_WRITE_REG(hw, I40E_GLINT_CTL, val); } +static inline void i40e_clear_automask(struct i40e_pf *pf) +{ + struct i40e_hw *hw = I40E_PF_TO_HW(pf); + uint32_t val; + + val = I40E_READ_REG(hw, I40E_GLINT_CTL); + val &= ~(I40E_GLINT_CTL_DIS_AUTOMASK_PF0_MASK | + I40E_GLINT_CTL_DIS_AUTOMASK_VF0_MASK); + + if (!pf->support_multi_driver) + val &= ~I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK; + + I40E_WRITE_REG(hw, I40E_GLINT_CTL, val); +} + #define I40E_FLOW_CONTROL_ETHERTYPE 0x8808 /* @@ -1308,62 +1339,6 @@ i40e_aq_debug_write_global_register(struct i40e_hw *hw, return i40e_aq_debug_write_register(hw, reg_addr, reg_val, cmd_details); } -static int -i40e_parse_latest_vec_handler(__rte_unused const char *key, - const char *value, - void *opaque) -{ - struct i40e_adapter *ad = opaque; - int use_latest_vec; - - use_latest_vec = atoi(value); - - if (use_latest_vec != 0 && use_latest_vec != 1) - PMD_DRV_LOG(WARNING, "Value should be 0 or 1, set it as 1!"); - - ad->use_latest_vec = (uint8_t)use_latest_vec; - - return 0; -} - -static int -i40e_use_latest_vec(struct rte_eth_dev *dev) -{ - struct i40e_adapter *ad = - I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); - struct rte_kvargs *kvlist; - int kvargs_count; - - ad->use_latest_vec = false; - - if (!dev->device->devargs) - return 0; - - kvlist = rte_kvargs_parse(dev->device->devargs->args, valid_keys); - if (!kvlist) - return -EINVAL; - - kvargs_count = rte_kvargs_count(kvlist, ETH_I40E_USE_LATEST_VEC); - if (!kvargs_count) { - rte_kvargs_free(kvlist); - return 0; - } - - if (kvargs_count > 1) - PMD_DRV_LOG(WARNING, "More than one argument \"%s\" and only " - "the first invalid or last valid one is used !", - ETH_I40E_USE_LATEST_VEC); - - if (rte_kvargs_process(kvlist, ETH_I40E_USE_LATEST_VEC, - i40e_parse_latest_vec_handler, ad) < 0) { - rte_kvargs_free(kvlist); - return -EINVAL; - } - - rte_kvargs_free(kvlist); - return 0; -} - static int read_vf_msg_config(__rte_unused const char *key, const char *value, @@ -1448,6 +1423,10 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused) PMD_INIT_FUNC_TRACE(); dev->dev_ops = &i40e_eth_dev_ops; + dev->rx_queue_count = i40e_dev_rx_queue_count; + dev->rx_descriptor_done = i40e_dev_rx_descriptor_done; + dev->rx_descriptor_status = i40e_dev_rx_descriptor_status; + dev->tx_descriptor_status = i40e_dev_tx_descriptor_status; dev->rx_pkt_burst = i40e_recv_pkts; dev->tx_pkt_burst = i40e_xmit_pkts; dev->tx_pkt_prepare = i40e_prep_pkts; @@ -1465,6 +1444,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused) intr_handle = &pci_dev->intr_handle; rte_eth_copy_pci_info(dev, pci_dev); + dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; pf->adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); pf->adapter->eth_dev = dev; @@ -1509,8 +1489,6 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused) i40e_parse_vf_msg_config(dev, &pf->vf_msg_cfg); /* Check if need to support multi-driver */ i40e_support_multi_driver(dev); - /* Check if users want the latest supported vec path */ - i40e_use_latest_vec(dev); /* Make sure all is clean before doing PF reset */ i40e_clear_hw(hw); @@ -1536,8 +1514,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused) PMD_INIT_LOG(ERR, "Failed to init adminq: %d", ret); return -EIO; } - /* Firmware of SFP x722 does not support adminq option */ - if (hw->device_id == I40E_DEV_ID_SFP_X722) + /* Firmware of SFP x722 does not support 802.1ad frames ability */ + if (hw->device_id == I40E_DEV_ID_SFP_X722 || + hw->device_id == I40E_DEV_ID_SFP_I_X722) hw->flags &= ~I40E_HW_FLAG_802_1AD_CAPABLE; PMD_INIT_LOG(INFO, "FW %d.%d API %d.%d NVM %02d.%02d.%02d eetrack %04x", @@ -1699,11 +1678,6 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused) rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.perm_addr, &dev->data->mac_addrs[0]); - /* Pass the information to the rte_eth_dev_close() that it should also - * release the private port resources. - */ - dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE; - /* Init dcb to sw mode by default */ ret = i40e_dcb_init_configure(dev, TRUE); if (ret != I40E_SUCCESS) { @@ -1771,10 +1745,6 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused) /* initialize queue region configuration */ i40e_init_queue_region_conf(dev); - /* initialize RSS configuration from rte_flow */ - memset(&pf->rss_info, 0, - sizeof(struct i40e_rte_flow_rss_conf)); - /* reset all stats of the device, including pf and main vsi */ i40e_dev_stats_reset(dev); @@ -2547,7 +2517,7 @@ rx_err: return ret; } -static void +static int i40e_dev_stop(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); @@ -2558,7 +2528,7 @@ i40e_dev_stop(struct rte_eth_dev *dev) int i; if (hw->adapter_stopped == 1) - return; + return 0; if (dev->data->dev_conf.intr_conf.rxq == 0) { rte_eal_alarm_cancel(i40e_dev_alarm_handler, dev); @@ -2604,11 +2574,14 @@ i40e_dev_stop(struct rte_eth_dev *dev) pf->tm_conf.committed = false; hw->adapter_stopped = 1; + dev->data->dev_started = 0; pf->adapter->rss_reta_updated = 0; + + return 0; } -static void +static int i40e_dev_close(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); @@ -2625,13 +2598,15 @@ i40e_dev_close(struct rte_eth_dev *dev) int retries = 0; PMD_INIT_FUNC_TRACE(); + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return 0; ret = rte_eth_switch_domain_free(pf->switch_domain_id); if (ret) PMD_INIT_LOG(WARNING, "failed to free switch domain: %d", ret); - i40e_dev_stop(dev); + ret = i40e_dev_stop(dev); /* Remove all mirror rules */ while ((p_mirror = TAILQ_FIRST(&pf->mirror_list))) { @@ -2695,10 +2670,6 @@ i40e_dev_close(struct rte_eth_dev *dev) (reg | I40E_PFGEN_CTRL_PFSWR_MASK)); I40E_WRITE_FLUSH(hw); - dev->dev_ops = NULL; - dev->rx_pkt_burst = NULL; - dev->tx_pkt_burst = NULL; - /* Clear PXE mode */ i40e_clear_pxe_mode(hw); @@ -2747,7 +2718,10 @@ i40e_dev_close(struct rte_eth_dev *dev) /* Remove all Traffic Manager configuration */ i40e_tm_conf_uninit(dev); + i40e_clear_automask(pf); + hw->adapter_closed = 1; + return ret; } /* @@ -3014,7 +2988,10 @@ update_link_aq(struct i40e_hw *hw, struct rte_eth_link *link, link->link_speed = ETH_SPEED_NUM_40G; break; default: - link->link_speed = ETH_SPEED_NUM_NONE; + if (link->link_status) + link->link_speed = ETH_SPEED_NUM_UNKNOWN; + else + link->link_speed = ETH_SPEED_NUM_NONE; break; } } @@ -3049,6 +3026,21 @@ i40e_dev_link_update(struct rte_eth_dev *dev, return ret; } +static void +i40e_stat_update_48_in_64(struct i40e_hw *hw, uint32_t hireg, + uint32_t loreg, bool offset_loaded, uint64_t *offset, + uint64_t *stat, uint64_t *prev_stat) +{ + i40e_stat_update_48(hw, hireg, loreg, offset_loaded, offset, stat); + /* enlarge the limitation when statistics counters overflowed */ + if (offset_loaded) { + if (I40E_RXTX_BYTES_L_48_BIT(*prev_stat) > *stat) + *stat += (uint64_t)1 << I40E_48_BIT_WIDTH; + *stat += I40E_RXTX_BYTES_H_16_BIT(*prev_stat); + } + *prev_stat = *stat; +} + /* Get all the statistics of a VSI */ void i40e_update_vsi_stats(struct i40e_vsi *vsi) @@ -3058,9 +3050,9 @@ i40e_update_vsi_stats(struct i40e_vsi *vsi) struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); int idx = rte_le_to_cpu_16(vsi->info.stat_counter_idx); - i40e_stat_update_48(hw, I40E_GLV_GORCH(idx), I40E_GLV_GORCL(idx), - vsi->offset_loaded, &oes->rx_bytes, - &nes->rx_bytes); + i40e_stat_update_48_in_64(hw, I40E_GLV_GORCH(idx), I40E_GLV_GORCL(idx), + vsi->offset_loaded, &oes->rx_bytes, + &nes->rx_bytes, &vsi->prev_rx_bytes); i40e_stat_update_48(hw, I40E_GLV_UPRCH(idx), I40E_GLV_UPRCL(idx), vsi->offset_loaded, &oes->rx_unicast, &nes->rx_unicast); @@ -3081,9 +3073,9 @@ i40e_update_vsi_stats(struct i40e_vsi *vsi) i40e_stat_update_32(hw, I40E_GLV_RUPP(idx), vsi->offset_loaded, &oes->rx_unknown_protocol, &nes->rx_unknown_protocol); - i40e_stat_update_48(hw, I40E_GLV_GOTCH(idx), I40E_GLV_GOTCL(idx), - vsi->offset_loaded, &oes->tx_bytes, - &nes->tx_bytes); + i40e_stat_update_48_in_64(hw, I40E_GLV_GOTCH(idx), I40E_GLV_GOTCL(idx), + vsi->offset_loaded, &oes->tx_bytes, + &nes->tx_bytes, &vsi->prev_tx_bytes); i40e_stat_update_48(hw, I40E_GLV_UPTCH(idx), I40E_GLV_UPTCL(idx), vsi->offset_loaded, &oes->tx_unicast, &nes->tx_unicast); @@ -3125,17 +3117,18 @@ i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw) struct i40e_hw_port_stats *os = &pf->stats_offset; /* old stats */ /* Get rx/tx bytes of internal transfer packets */ - i40e_stat_update_48(hw, I40E_GLV_GORCH(hw->port), - I40E_GLV_GORCL(hw->port), - pf->offset_loaded, - &pf->internal_stats_offset.rx_bytes, - &pf->internal_stats.rx_bytes); - - i40e_stat_update_48(hw, I40E_GLV_GOTCH(hw->port), - I40E_GLV_GOTCL(hw->port), - pf->offset_loaded, - &pf->internal_stats_offset.tx_bytes, - &pf->internal_stats.tx_bytes); + i40e_stat_update_48_in_64(hw, I40E_GLV_GORCH(hw->port), + I40E_GLV_GORCL(hw->port), + pf->offset_loaded, + &pf->internal_stats_offset.rx_bytes, + &pf->internal_stats.rx_bytes, + &pf->internal_prev_rx_bytes); + i40e_stat_update_48_in_64(hw, I40E_GLV_GOTCH(hw->port), + I40E_GLV_GOTCL(hw->port), + pf->offset_loaded, + &pf->internal_stats_offset.tx_bytes, + &pf->internal_stats.tx_bytes, + &pf->internal_prev_tx_bytes); /* Get total internal rx packet count */ i40e_stat_update_48(hw, I40E_GLV_UPRCH(hw->port), I40E_GLV_UPRCL(hw->port), @@ -3175,10 +3168,10 @@ i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw) pf->internal_stats.rx_broadcast) * RTE_ETHER_CRC_LEN; /* Get statistics of struct i40e_eth_stats */ - i40e_stat_update_48(hw, I40E_GLPRT_GORCH(hw->port), - I40E_GLPRT_GORCL(hw->port), - pf->offset_loaded, &os->eth.rx_bytes, - &ns->eth.rx_bytes); + i40e_stat_update_48_in_64(hw, I40E_GLPRT_GORCH(hw->port), + I40E_GLPRT_GORCL(hw->port), + pf->offset_loaded, &os->eth.rx_bytes, + &ns->eth.rx_bytes, &pf->prev_rx_bytes); i40e_stat_update_48(hw, I40E_GLPRT_UPRCH(hw->port), I40E_GLPRT_UPRCL(hw->port), pf->offset_loaded, &os->eth.rx_unicast, @@ -3233,10 +3226,10 @@ i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw) pf->offset_loaded, &os->eth.rx_unknown_protocol, &ns->eth.rx_unknown_protocol); - i40e_stat_update_48(hw, I40E_GLPRT_GOTCH(hw->port), - I40E_GLPRT_GOTCL(hw->port), - pf->offset_loaded, &os->eth.tx_bytes, - &ns->eth.tx_bytes); + i40e_stat_update_48_in_64(hw, I40E_GLPRT_GOTCH(hw->port), + I40E_GLPRT_GOTCL(hw->port), + pf->offset_loaded, &os->eth.tx_bytes, + &ns->eth.tx_bytes, &pf->prev_tx_bytes); i40e_stat_update_48(hw, I40E_GLPRT_UPTCH(hw->port), I40E_GLPRT_UPTCL(hw->port), pf->offset_loaded, &os->eth.tx_unicast, @@ -4312,9 +4305,9 @@ i40e_macaddr_add(struct rte_eth_dev *dev, rte_memcpy(&mac_filter.mac_addr, mac_addr, RTE_ETHER_ADDR_LEN); if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER) - mac_filter.filter_type = RTE_MACVLAN_PERFECT_MATCH; + mac_filter.filter_type = I40E_MACVLAN_PERFECT_MATCH; else - mac_filter.filter_type = RTE_MAC_PERFECT_MATCH; + mac_filter.filter_type = I40E_MAC_PERFECT_MATCH; if (pool == 0) vsi = pf->main_vsi; @@ -4369,119 +4362,6 @@ i40e_macaddr_remove(struct rte_eth_dev *dev, uint32_t index) } } -/* Set perfect match or hash match of MAC and VLAN for a VF */ -static int -i40e_vf_mac_filter_set(struct i40e_pf *pf, - struct rte_eth_mac_filter *filter, - bool add) -{ - struct i40e_hw *hw; - struct i40e_mac_filter_info mac_filter; - struct rte_ether_addr old_mac; - struct rte_ether_addr *new_mac; - struct i40e_pf_vf *vf = NULL; - uint16_t vf_id; - int ret; - - if (pf == NULL) { - PMD_DRV_LOG(ERR, "Invalid PF argument."); - return -EINVAL; - } - hw = I40E_PF_TO_HW(pf); - - if (filter == NULL) { - PMD_DRV_LOG(ERR, "Invalid mac filter argument."); - return -EINVAL; - } - - new_mac = &filter->mac_addr; - - if (rte_is_zero_ether_addr(new_mac)) { - PMD_DRV_LOG(ERR, "Invalid ethernet address."); - return -EINVAL; - } - - vf_id = filter->dst_id; - - if (vf_id > pf->vf_num - 1 || !pf->vfs) { - PMD_DRV_LOG(ERR, "Invalid argument."); - return -EINVAL; - } - vf = &pf->vfs[vf_id]; - - if (add && rte_is_same_ether_addr(new_mac, &pf->dev_addr)) { - PMD_DRV_LOG(INFO, "Ignore adding permanent MAC address."); - return -EINVAL; - } - - if (add) { - rte_memcpy(&old_mac, hw->mac.addr, RTE_ETHER_ADDR_LEN); - rte_memcpy(hw->mac.addr, new_mac->addr_bytes, - RTE_ETHER_ADDR_LEN); - rte_memcpy(&mac_filter.mac_addr, &filter->mac_addr, - RTE_ETHER_ADDR_LEN); - - mac_filter.filter_type = filter->filter_type; - ret = i40e_vsi_add_mac(vf->vsi, &mac_filter); - if (ret != I40E_SUCCESS) { - PMD_DRV_LOG(ERR, "Failed to add MAC filter."); - return -1; - } - rte_ether_addr_copy(new_mac, &pf->dev_addr); - } else { - rte_memcpy(hw->mac.addr, hw->mac.perm_addr, - RTE_ETHER_ADDR_LEN); - ret = i40e_vsi_delete_mac(vf->vsi, &filter->mac_addr); - if (ret != I40E_SUCCESS) { - PMD_DRV_LOG(ERR, "Failed to delete MAC filter."); - return -1; - } - - /* Clear device address as it has been removed */ - if (rte_is_same_ether_addr(&pf->dev_addr, new_mac)) - memset(&pf->dev_addr, 0, sizeof(struct rte_ether_addr)); - } - - return 0; -} - -/* MAC filter handle */ -static int -i40e_mac_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, - void *arg) -{ - struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); - struct rte_eth_mac_filter *filter; - struct i40e_hw *hw = I40E_PF_TO_HW(pf); - int ret = I40E_NOT_SUPPORTED; - - filter = (struct rte_eth_mac_filter *)(arg); - - switch (filter_op) { - case RTE_ETH_FILTER_NOP: - ret = I40E_SUCCESS; - break; - case RTE_ETH_FILTER_ADD: - i40e_pf_disable_irq0(hw); - if (filter->is_vf) - ret = i40e_vf_mac_filter_set(pf, filter, 1); - i40e_pf_enable_irq0(hw); - break; - case RTE_ETH_FILTER_DELETE: - i40e_pf_disable_irq0(hw); - if (filter->is_vf) - ret = i40e_vf_mac_filter_set(pf, filter, 0); - i40e_pf_enable_irq0(hw); - break; - default: - PMD_DRV_LOG(ERR, "unknown operation %u", filter_op); - ret = I40E_ERR_PARAM; - break; - } - - return ret; -} - static int i40e_get_rss_lut(struct i40e_vsi *vsi, uint8_t *lut, uint16_t lut_size) { @@ -4525,7 +4405,6 @@ i40e_set_rss_lut(struct i40e_vsi *vsi, uint8_t *lut, uint16_t lut_size) { struct i40e_pf *pf; struct i40e_hw *hw; - int ret; if (!vsi || !lut) return -EINVAL; @@ -4534,12 +4413,16 @@ i40e_set_rss_lut(struct i40e_vsi *vsi, uint8_t *lut, uint16_t lut_size) hw = I40E_VSI_TO_HW(vsi); if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) { - ret = i40e_aq_set_rss_lut(hw, vsi->vsi_id, - vsi->type != I40E_VSI_SRIOV, - lut, lut_size); - if (ret) { - PMD_DRV_LOG(ERR, "Failed to set RSS lookup table"); - return ret; + enum i40e_status_code status; + + status = i40e_aq_set_rss_lut(hw, vsi->vsi_id, + vsi->type != I40E_VSI_SRIOV, + lut, lut_size); + if (status) { + PMD_DRV_LOG(ERR, + "Failed to update RSS lookup table, error status: %d", + status); + return -EIO; } } else { uint32_t *lut_dw = (uint32_t *)lut; @@ -5633,7 +5516,7 @@ i40e_update_default_filter_setting(struct i40e_vsi *vsi) mac = &f->mac_info.mac_addr; rte_memcpy(&mac->addr_bytes, hw->mac.perm_addr, ETH_ADDR_LEN); - f->mac_info.filter_type = RTE_MACVLAN_PERFECT_MATCH; + f->mac_info.filter_type = I40E_MACVLAN_PERFECT_MATCH; TAILQ_INSERT_TAIL(&vsi->mac_list, f, next); vsi->mac_num++; @@ -5641,7 +5524,7 @@ i40e_update_default_filter_setting(struct i40e_vsi *vsi) } rte_memcpy(&filter.mac_addr, (struct rte_ether_addr *)(hw->mac.perm_addr), ETH_ADDR_LEN); - filter.filter_type = RTE_MACVLAN_PERFECT_MATCH; + filter.filter_type = I40E_MACVLAN_PERFECT_MATCH; return i40e_vsi_add_mac(vsi, &filter); } @@ -6107,7 +5990,7 @@ i40e_vsi_setup(struct i40e_pf *pf, /* MAC/VLAN configuration */ rte_memcpy(&filter.mac_addr, &broadcast, RTE_ETHER_ADDR_LEN); - filter.filter_type = RTE_MACVLAN_PERFECT_MATCH; + filter.filter_type = I40E_MACVLAN_PERFECT_MATCH; ret = i40e_vsi_add_mac(vsi, &filter); if (ret != I40E_SUCCESS) { @@ -6135,15 +6018,15 @@ i40e_vsi_config_vlan_filter(struct i40e_vsi *vsi, bool on) struct i40e_mac_filter *f; void *temp; struct i40e_mac_filter_info *mac_filter; - enum rte_mac_filter_type desired_filter; + enum i40e_mac_filter_type desired_filter; int ret = I40E_SUCCESS; if (on) { /* Filter to match MAC and VLAN */ - desired_filter = RTE_MACVLAN_PERFECT_MATCH; + desired_filter = I40E_MACVLAN_PERFECT_MATCH; } else { /* Filter to match only MAC */ - desired_filter = RTE_MAC_PERFECT_MATCH; + desired_filter = I40E_MAC_PERFECT_MATCH; } num = vsi->mac_num; @@ -6702,9 +6585,13 @@ i40e_stat_update_48(struct i40e_hw *hw, { uint64_t new_data; - new_data = (uint64_t)I40E_READ_REG(hw, loreg); - new_data |= ((uint64_t)(I40E_READ_REG(hw, hireg) & - I40E_16_BIT_MASK)) << I40E_32_BIT_WIDTH; + if (hw->device_id == I40E_DEV_ID_QEMU) { + new_data = (uint64_t)I40E_READ_REG(hw, loreg); + new_data |= ((uint64_t)(I40E_READ_REG(hw, hireg) & + I40E_16_BIT_MASK)) << I40E_32_BIT_WIDTH; + } else { + new_data = I40E_READ_REG64(hw, loreg); + } if (!offset_loaded) *offset = new_data; @@ -6843,7 +6730,7 @@ i40e_dev_handle_aq_msg(struct rte_eth_dev *dev) case i40e_aqc_opc_get_link_status: ret = i40e_dev_link_update(dev, 0); if (!ret) - _rte_eth_dev_callback_process(dev, + rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL); break; default: @@ -7086,18 +6973,18 @@ i40e_add_macvlan_filters(struct i40e_vsi *vsi, rte_cpu_to_le_16(filter[num + i].vlan_id); switch (filter[num + i].filter_type) { - case RTE_MAC_PERFECT_MATCH: + case I40E_MAC_PERFECT_MATCH: flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH | I40E_AQC_MACVLAN_ADD_IGNORE_VLAN; break; - case RTE_MACVLAN_PERFECT_MATCH: + case I40E_MACVLAN_PERFECT_MATCH: flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH; break; - case RTE_MAC_HASH_MATCH: + case I40E_MAC_HASH_MATCH: flags = I40E_AQC_MACVLAN_ADD_HASH_MATCH | I40E_AQC_MACVLAN_ADD_IGNORE_VLAN; break; - case RTE_MACVLAN_HASH_MATCH: + case I40E_MACVLAN_HASH_MATCH: flags = I40E_AQC_MACVLAN_ADD_HASH_MATCH; break; default: @@ -7161,18 +7048,18 @@ i40e_remove_macvlan_filters(struct i40e_vsi *vsi, rte_cpu_to_le_16(filter[num + i].vlan_id); switch (filter[num + i].filter_type) { - case RTE_MAC_PERFECT_MATCH: + case I40E_MAC_PERFECT_MATCH: flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH | I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; break; - case RTE_MACVLAN_PERFECT_MATCH: + case I40E_MACVLAN_PERFECT_MATCH: flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH; break; - case RTE_MAC_HASH_MATCH: + case I40E_MAC_HASH_MATCH: flags = I40E_AQC_MACVLAN_DEL_HASH_MATCH | I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; break; - case RTE_MACVLAN_HASH_MATCH: + case I40E_MACVLAN_HASH_MATCH: flags = I40E_AQC_MACVLAN_DEL_HASH_MATCH; break; default: @@ -7517,8 +7404,8 @@ i40e_vsi_add_mac(struct i40e_vsi *vsi, struct i40e_mac_filter_info *mac_filter) f = i40e_find_mac_filter(vsi, &mac_filter->mac_addr); if (f != NULL) return I40E_SUCCESS; - if ((mac_filter->filter_type == RTE_MACVLAN_PERFECT_MATCH) || - (mac_filter->filter_type == RTE_MACVLAN_HASH_MATCH)) { + if (mac_filter->filter_type == I40E_MACVLAN_PERFECT_MATCH || + mac_filter->filter_type == I40E_MACVLAN_HASH_MATCH) { /** * If vlan_num is 0, that's the first time to add mac, @@ -7529,8 +7416,8 @@ i40e_vsi_add_mac(struct i40e_vsi *vsi, struct i40e_mac_filter_info *mac_filter) vsi->vlan_num = 1; } vlan_num = vsi->vlan_num; - } else if ((mac_filter->filter_type == RTE_MAC_PERFECT_MATCH) || - (mac_filter->filter_type == RTE_MAC_HASH_MATCH)) + } else if (mac_filter->filter_type == I40E_MAC_PERFECT_MATCH || + mac_filter->filter_type == I40E_MAC_HASH_MATCH) vlan_num = 1; mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0); @@ -7545,8 +7432,8 @@ i40e_vsi_add_mac(struct i40e_vsi *vsi, struct i40e_mac_filter_info *mac_filter) ETH_ADDR_LEN); } - if (mac_filter->filter_type == RTE_MACVLAN_PERFECT_MATCH || - mac_filter->filter_type == RTE_MACVLAN_HASH_MATCH) { + if (mac_filter->filter_type == I40E_MACVLAN_PERFECT_MATCH || + mac_filter->filter_type == I40E_MACVLAN_HASH_MATCH) { ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num, &mac_filter->mac_addr); if (ret != I40E_SUCCESS) @@ -7583,7 +7470,7 @@ i40e_vsi_delete_mac(struct i40e_vsi *vsi, struct rte_ether_addr *addr) struct i40e_mac_filter *f; struct i40e_macvlan_filter *mv_f; int i, vlan_num; - enum rte_mac_filter_type filter_type; + enum i40e_mac_filter_type filter_type; int ret = I40E_SUCCESS; /* Can't find it, return an error */ @@ -7593,14 +7480,14 @@ i40e_vsi_delete_mac(struct i40e_vsi *vsi, struct rte_ether_addr *addr) vlan_num = vsi->vlan_num; filter_type = f->mac_info.filter_type; - if (filter_type == RTE_MACVLAN_PERFECT_MATCH || - filter_type == RTE_MACVLAN_HASH_MATCH) { + if (filter_type == I40E_MACVLAN_PERFECT_MATCH || + filter_type == I40E_MACVLAN_HASH_MATCH) { if (vlan_num == 0) { PMD_DRV_LOG(ERR, "VLAN number shouldn't be 0"); return I40E_ERR_PARAM; } - } else if (filter_type == RTE_MAC_PERFECT_MATCH || - filter_type == RTE_MAC_HASH_MATCH) + } else if (filter_type == I40E_MAC_PERFECT_MATCH || + filter_type == I40E_MAC_HASH_MATCH) vlan_num = 1; mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0); @@ -7614,8 +7501,8 @@ i40e_vsi_delete_mac(struct i40e_vsi *vsi, struct rte_ether_addr *addr) rte_memcpy(&mv_f[i].macaddr, &f->mac_info.mac_addr, ETH_ADDR_LEN); } - if (filter_type == RTE_MACVLAN_PERFECT_MATCH || - filter_type == RTE_MACVLAN_HASH_MATCH) { + if (filter_type == I40E_MACVLAN_PERFECT_MATCH || + filter_type == I40E_MACVLAN_HASH_MATCH) { ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num, addr); if (ret != I40E_SUCCESS) goto DONE; @@ -7672,7 +7559,7 @@ i40e_parse_hena(const struct i40e_adapter *adapter, uint64_t flags) } /* Disable RSS */ -static void +void i40e_pf_disable_rss(struct i40e_pf *pf) { struct i40e_hw *hw = I40E_PF_TO_HW(pf); @@ -7690,7 +7577,6 @@ i40e_set_rss_key(struct i40e_vsi *vsi, uint8_t *key, uint8_t key_len) uint16_t key_idx = (vsi->type == I40E_VSI_SRIOV) ? I40E_VFQF_HKEY_MAX_INDEX : I40E_PFQF_HKEY_MAX_INDEX; - int ret = 0; if (!key || key_len == 0) { PMD_DRV_LOG(DEBUG, "No key to be configured"); @@ -7703,11 +7589,16 @@ i40e_set_rss_key(struct i40e_vsi *vsi, uint8_t *key, uint8_t key_len) if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) { struct i40e_aqc_get_set_rss_key_data *key_dw = - (struct i40e_aqc_get_set_rss_key_data *)key; + (struct i40e_aqc_get_set_rss_key_data *)key; + enum i40e_status_code status = + i40e_aq_set_rss_key(hw, vsi->vsi_id, key_dw); - ret = i40e_aq_set_rss_key(hw, vsi->vsi_id, key_dw); - if (ret) - PMD_INIT_LOG(ERR, "Failed to configure RSS key via AQ"); + if (status) { + PMD_DRV_LOG(ERR, + "Failed to configure RSS key via AQ, error status: %d", + status); + return -EIO; + } } else { uint32_t *hash_key = (uint32_t *)key; uint16_t i; @@ -7727,7 +7618,7 @@ i40e_set_rss_key(struct i40e_vsi *vsi, uint8_t *key, uint8_t key_len) I40E_WRITE_FLUSH(hw); } - return ret; + return 0; } static int @@ -7962,184 +7853,45 @@ i40e_sw_tunnel_filter_del(struct i40e_pf *pf, return 0; } -int -i40e_dev_tunnel_filter_set(struct i40e_pf *pf, - struct rte_eth_tunnel_filter_conf *tunnel_filter, - uint8_t add) +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_TR_WORD0 0x48 +#define I40E_TR_VXLAN_GRE_KEY_MASK 0x4 +#define I40E_TR_GENEVE_KEY_MASK 0x8 +#define I40E_TR_GENERIC_UDP_TUNNEL_MASK 0x40 +#define I40E_TR_GRE_KEY_MASK 0x400 +#define I40E_TR_GRE_KEY_WITH_XSUM_MASK 0x800 +#define I40E_TR_GRE_NO_KEY_MASK 0x8000 +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49 +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41 +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80 +#define I40E_DIRECTION_INGRESS_KEY 0x8000 +#define I40E_TR_L4_TYPE_TCP 0x2 +#define I40E_TR_L4_TYPE_UDP 0x4 +#define I40E_TR_L4_TYPE_SCTP 0x8 + +static enum +i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf) { - uint16_t ip_type; - uint32_t ipv4_addr, ipv4_addr_le; - uint8_t i, tun_type = 0; - /* internal varialbe to convert ipv6 byte order */ - uint32_t convert_ipv6[4]; - int val, ret = 0; + struct i40e_aqc_replace_cloud_filters_cmd filter_replace; + struct i40e_aqc_replace_cloud_filters_cmd_buf filter_replace_buf; struct i40e_hw *hw = I40E_PF_TO_HW(pf); - struct i40e_vsi *vsi = pf->main_vsi; - struct i40e_aqc_cloud_filters_element_bb *cld_filter; - struct i40e_aqc_cloud_filters_element_bb *pfilter; - struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel; - struct i40e_tunnel_filter *tunnel, *node; - struct i40e_tunnel_filter check_filter; /* Check if filter exists */ - - cld_filter = rte_zmalloc("tunnel_filter", - sizeof(struct i40e_aqc_add_rm_cloud_filt_elem_ext), - 0); - - if (NULL == cld_filter) { - PMD_DRV_LOG(ERR, "Failed to alloc memory."); - return -ENOMEM; - } - pfilter = cld_filter; - - rte_ether_addr_copy(&tunnel_filter->outer_mac, - (struct rte_ether_addr *)&pfilter->element.outer_mac); - rte_ether_addr_copy(&tunnel_filter->inner_mac, - (struct rte_ether_addr *)&pfilter->element.inner_mac); + struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev; + enum i40e_status_code status = I40E_SUCCESS; - pfilter->element.inner_vlan = - rte_cpu_to_le_16(tunnel_filter->inner_vlan); - if (tunnel_filter->ip_type == RTE_TUNNEL_IPTYPE_IPV4) { - ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV4; - ipv4_addr = rte_be_to_cpu_32(tunnel_filter->ip_addr.ipv4_addr); - ipv4_addr_le = rte_cpu_to_le_32(ipv4_addr); - rte_memcpy(&pfilter->element.ipaddr.v4.data, - &ipv4_addr_le, - sizeof(pfilter->element.ipaddr.v4.data)); - } else { - ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV6; - for (i = 0; i < 4; i++) { - convert_ipv6[i] = - rte_cpu_to_le_32(rte_be_to_cpu_32(tunnel_filter->ip_addr.ipv6_addr[i])); - } - rte_memcpy(&pfilter->element.ipaddr.v6.data, - &convert_ipv6, - sizeof(pfilter->element.ipaddr.v6.data)); + if (pf->support_multi_driver) { + PMD_DRV_LOG(ERR, "Replace l1 filter is not supported."); + return I40E_NOT_SUPPORTED; } - /* check tunneled type */ - switch (tunnel_filter->tunnel_type) { - case RTE_TUNNEL_TYPE_VXLAN: - tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_VXLAN; - break; - case RTE_TUNNEL_TYPE_NVGRE: - tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC; - break; - case RTE_TUNNEL_TYPE_IP_IN_GRE: - tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP; - break; - case RTE_TUNNEL_TYPE_VXLAN_GPE: - tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_VXLAN_GPE; - break; - default: - /* Other tunnel types is not supported. */ - PMD_DRV_LOG(ERR, "tunnel type is not supported."); - rte_free(cld_filter); - return -EINVAL; - } + memset(&filter_replace, 0, + sizeof(struct i40e_aqc_replace_cloud_filters_cmd)); + memset(&filter_replace_buf, 0, + sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf)); - val = i40e_dev_get_filter_type(tunnel_filter->filter_type, - &pfilter->element.flags); - if (val < 0) { - rte_free(cld_filter); - return -EINVAL; - } - - pfilter->element.flags |= rte_cpu_to_le_16( - I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE | - ip_type | (tun_type << I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)); - pfilter->element.tenant_id = rte_cpu_to_le_32(tunnel_filter->tenant_id); - pfilter->element.queue_number = - rte_cpu_to_le_16(tunnel_filter->queue_id); - - /* Check if there is the filter in SW list */ - memset(&check_filter, 0, sizeof(check_filter)); - i40e_tunnel_filter_convert(cld_filter, &check_filter); - node = i40e_sw_tunnel_filter_lookup(tunnel_rule, &check_filter.input); - if (add && node) { - PMD_DRV_LOG(ERR, "Conflict with existing tunnel rules!"); - rte_free(cld_filter); - return -EINVAL; - } - - if (!add && !node) { - PMD_DRV_LOG(ERR, "There's no corresponding tunnel filter!"); - rte_free(cld_filter); - return -EINVAL; - } - - if (add) { - ret = i40e_aq_add_cloud_filters(hw, - vsi->seid, &cld_filter->element, 1); - if (ret < 0) { - PMD_DRV_LOG(ERR, "Failed to add a tunnel filter."); - rte_free(cld_filter); - return -ENOTSUP; - } - tunnel = rte_zmalloc("tunnel_filter", sizeof(*tunnel), 0); - if (tunnel == NULL) { - PMD_DRV_LOG(ERR, "Failed to alloc memory."); - rte_free(cld_filter); - return -ENOMEM; - } - - rte_memcpy(tunnel, &check_filter, sizeof(check_filter)); - ret = i40e_sw_tunnel_filter_insert(pf, tunnel); - if (ret < 0) - rte_free(tunnel); - } else { - ret = i40e_aq_rem_cloud_filters(hw, vsi->seid, - &cld_filter->element, 1); - if (ret < 0) { - PMD_DRV_LOG(ERR, "Failed to delete a tunnel filter."); - rte_free(cld_filter); - return -ENOTSUP; - } - ret = i40e_sw_tunnel_filter_del(pf, &node->input); - } - - rte_free(cld_filter); - return ret; -} - -#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_TR_WORD0 0x48 -#define I40E_TR_VXLAN_GRE_KEY_MASK 0x4 -#define I40E_TR_GENEVE_KEY_MASK 0x8 -#define I40E_TR_GENERIC_UDP_TUNNEL_MASK 0x40 -#define I40E_TR_GRE_KEY_MASK 0x400 -#define I40E_TR_GRE_KEY_WITH_XSUM_MASK 0x800 -#define I40E_TR_GRE_NO_KEY_MASK 0x8000 -#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49 -#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41 -#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80 -#define I40E_DIRECTION_INGRESS_KEY 0x8000 -#define I40E_TR_L4_TYPE_TCP 0x2 -#define I40E_TR_L4_TYPE_UDP 0x4 -#define I40E_TR_L4_TYPE_SCTP 0x8 - -static enum -i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf) -{ - struct i40e_aqc_replace_cloud_filters_cmd filter_replace; - struct i40e_aqc_replace_cloud_filters_cmd_buf filter_replace_buf; - struct i40e_hw *hw = I40E_PF_TO_HW(pf); - struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev; - enum i40e_status_code status = I40E_SUCCESS; - - if (pf->support_multi_driver) { - PMD_DRV_LOG(ERR, "Replace l1 filter is not supported."); - return I40E_NOT_SUPPORTED; - } - - memset(&filter_replace, 0, - sizeof(struct i40e_aqc_replace_cloud_filters_cmd)); - memset(&filter_replace_buf, 0, - sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf)); - - /* create L1 filter */ - filter_replace.old_filter_type = - I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC; - filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_0X11; - filter_replace.tr_bit = 0; + /* create L1 filter */ + filter_replace.old_filter_type = + I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC; + filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_0X11; + filter_replace.tr_bit = 0; /* Prepare the buffer, 3 entries */ filter_replace_buf.data[0] = @@ -9020,7 +8772,7 @@ i40e_dev_udp_tunnel_port_del(struct rte_eth_dev *dev, } /* Calculate the maximum number of contiguous PF queues that are configured */ -static int +int i40e_pf_calc_configured_queues_num(struct i40e_pf *pf) { struct rte_eth_dev_data *data = pf->dev_data; @@ -9039,19 +8791,72 @@ i40e_pf_calc_configured_queues_num(struct i40e_pf *pf) return num; } -/* Configure RSS */ -static int -i40e_pf_config_rss(struct i40e_pf *pf) +/* Reset the global configure of hash function and input sets */ +static void +i40e_pf_global_rss_reset(struct i40e_pf *pf) { - enum rte_eth_rx_mq_mode mq_mode = pf->dev_data->dev_conf.rxmode.mq_mode; struct i40e_hw *hw = I40E_PF_TO_HW(pf); - struct rte_eth_rss_conf rss_conf; - uint32_t i, lut = 0; - uint16_t j, num; + uint32_t reg, reg_val; + int i; - /* - * If both VMDQ and RSS enabled, not all of PF queues are configured. - * It's necessary to calculate the actual PF queues that are configured. + /* Reset global RSS function sets */ + reg_val = i40e_read_rx_ctl(hw, I40E_GLQF_CTL); + if (!(reg_val & I40E_GLQF_CTL_HTOEP_MASK)) { + reg_val |= I40E_GLQF_CTL_HTOEP_MASK; + i40e_write_global_rx_ctl(hw, I40E_GLQF_CTL, reg_val); + } + + for (i = 0; i <= I40E_FILTER_PCTYPE_L2_PAYLOAD; i++) { + uint64_t inset; + int j, pctype; + + if (hw->mac.type == I40E_MAC_X722) + pctype = i40e_read_rx_ctl(hw, I40E_GLQF_FD_PCTYPES(i)); + else + pctype = i; + + /* Reset pctype insets */ + inset = i40e_get_default_input_set(i); + if (inset) { + pf->hash_input_set[pctype] = inset; + inset = i40e_translate_input_set_reg(hw->mac.type, + inset); + + reg = I40E_GLQF_HASH_INSET(0, pctype); + i40e_check_write_global_reg(hw, reg, (uint32_t)inset); + reg = I40E_GLQF_HASH_INSET(1, pctype); + i40e_check_write_global_reg(hw, reg, + (uint32_t)(inset >> 32)); + + /* Clear unused mask registers of the pctype */ + for (j = 0; j < I40E_INSET_MASK_NUM_REG; j++) { + reg = I40E_GLQF_HASH_MSK(j, pctype); + i40e_check_write_global_reg(hw, reg, 0); + } + } + + /* Reset pctype symmetric sets */ + reg = I40E_GLQF_HSYM(pctype); + reg_val = i40e_read_rx_ctl(hw, reg); + if (reg_val & I40E_GLQF_HSYM_SYMH_ENA_MASK) { + reg_val &= ~I40E_GLQF_HSYM_SYMH_ENA_MASK; + i40e_write_global_rx_ctl(hw, reg, reg_val); + } + } + I40E_WRITE_FLUSH(hw); +} + +int +i40e_pf_reset_rss_reta(struct i40e_pf *pf) +{ + struct i40e_hw *hw = &pf->adapter->hw; + uint8_t lut[ETH_RSS_RETA_SIZE_512]; + uint32_t i; + int num; + + /* If both VMDQ and RSS enabled, not all of PF queues are + * configured. It's necessary to calculate the actual PF + * queues that are configured. */ if (pf->dev_data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG) num = i40e_pf_calc_configured_queues_num(pf); @@ -9059,81 +8864,88 @@ i40e_pf_config_rss(struct i40e_pf *pf) num = pf->dev_data->nb_rx_queues; num = RTE_MIN(num, I40E_MAX_Q_PER_TC); - PMD_INIT_LOG(INFO, "Max of contiguous %u PF queues are configured", - num); + if (num <= 0) + return 0; - if (num == 0) { - PMD_INIT_LOG(ERR, - "No PF queues are configured to enable RSS for port %u", - pf->dev_data->port_id); - return -ENOTSUP; - } + for (i = 0; i < hw->func_caps.rss_table_size; i++) + lut[i] = (uint8_t)(i % (uint32_t)num); - if (pf->adapter->rss_reta_updated == 0) { - for (i = 0, j = 0; i < hw->func_caps.rss_table_size; i++, j++) { - if (j == num) - j = 0; - lut = (lut << 8) | (j & ((0x1 << - hw->func_caps.rss_table_entry_width) - 1)); - if ((i & 3) == 3) - I40E_WRITE_REG(hw, I40E_PFQF_HLUT(i >> 2), - rte_bswap32(lut)); - } - } + return i40e_set_rss_lut(pf->main_vsi, lut, (uint16_t)i); +} - rss_conf = pf->dev_data->dev_conf.rx_adv_conf.rss_conf; - if ((rss_conf.rss_hf & pf->adapter->flow_types_mask) == 0 || - !(mq_mode & ETH_MQ_RX_RSS_FLAG)) { - i40e_pf_disable_rss(pf); - return 0; - } - if (rss_conf.rss_key == NULL || rss_conf.rss_key_len < - (I40E_PFQF_HKEY_MAX_INDEX + 1) * sizeof(uint32_t)) { - /* Random default keys */ +int +i40e_pf_reset_rss_key(struct i40e_pf *pf) +{ + const uint8_t key_len = (I40E_PFQF_HKEY_MAX_INDEX + 1) * + sizeof(uint32_t); + uint8_t *rss_key; + + /* Reset key */ + rss_key = pf->dev_data->dev_conf.rx_adv_conf.rss_conf.rss_key; + if (!rss_key || + pf->dev_data->dev_conf.rx_adv_conf.rss_conf.rss_key_len < key_len) { static uint32_t rss_key_default[] = {0x6b793944, 0x23504cb5, 0x5bea75b6, 0x309f4f12, 0x3dc0a2b8, 0x024ddcdf, 0x339b8ca0, 0x4c4af64a, 0x34fac605, 0x55d85839, 0x3a58997d, 0x2ec938e1, 0x66031581}; - rss_conf.rss_key = (uint8_t *)rss_key_default; - rss_conf.rss_key_len = (I40E_PFQF_HKEY_MAX_INDEX + 1) * - sizeof(uint32_t); + rss_key = (uint8_t *)rss_key_default; } - return i40e_hw_rss_hash_set(pf, &rss_conf); + return i40e_set_rss_key(pf->main_vsi, rss_key, key_len); } static int -i40e_tunnel_filter_param_check(struct i40e_pf *pf, - struct rte_eth_tunnel_filter_conf *filter) +i40e_pf_rss_reset(struct i40e_pf *pf) { - if (pf == NULL || filter == NULL) { - PMD_DRV_LOG(ERR, "Invalid parameter"); - return -EINVAL; - } + struct i40e_hw *hw = I40E_PF_TO_HW(pf); - if (filter->queue_id >= pf->dev_data->nb_rx_queues) { - PMD_DRV_LOG(ERR, "Invalid queue ID"); - return -EINVAL; - } + int ret; - if (filter->inner_vlan > RTE_ETHER_MAX_VLAN_ID) { - PMD_DRV_LOG(ERR, "Invalid inner VLAN ID"); - return -EINVAL; - } + pf->hash_filter_enabled = 0; + i40e_pf_disable_rss(pf); + i40e_set_symmetric_hash_enable_per_port(hw, 0); - if ((filter->filter_type & ETH_TUNNEL_FILTER_OMAC) && - (rte_is_zero_ether_addr(&filter->outer_mac))) { - PMD_DRV_LOG(ERR, "Cannot add NULL outer MAC address"); - return -EINVAL; + if (!pf->support_multi_driver) + i40e_pf_global_rss_reset(pf); + + /* Reset RETA table */ + if (pf->adapter->rss_reta_updated == 0) { + ret = i40e_pf_reset_rss_reta(pf); + if (ret) + return ret; } - if ((filter->filter_type & ETH_TUNNEL_FILTER_IMAC) && - (rte_is_zero_ether_addr(&filter->inner_mac))) { - PMD_DRV_LOG(ERR, "Cannot add NULL inner MAC address"); - return -EINVAL; + return i40e_pf_reset_rss_key(pf); +} + +/* Configure RSS */ +int +i40e_pf_config_rss(struct i40e_pf *pf) +{ + struct i40e_hw *hw; + enum rte_eth_rx_mq_mode mq_mode; + uint64_t rss_hf, hena; + int ret; + + ret = i40e_pf_rss_reset(pf); + if (ret) { + PMD_DRV_LOG(ERR, "Reset RSS failed, RSS has been disabled"); + return ret; } + rss_hf = pf->dev_data->dev_conf.rx_adv_conf.rss_conf.rss_hf; + mq_mode = pf->dev_data->dev_conf.rxmode.mq_mode; + if (!(rss_hf & pf->adapter->flow_types_mask) || + !(mq_mode & ETH_MQ_RX_RSS_FLAG)) + return 0; + + hw = I40E_PF_TO_HW(pf); + hena = i40e_config_hena(pf->adapter, rss_hf); + i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (uint32_t)hena); + i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), (uint32_t)(hena >> 32)); + I40E_WRITE_FLUSH(hw); + return 0; } @@ -9181,279 +8993,27 @@ i40e_dev_set_gre_key_len(struct i40e_hw *hw, uint8_t len) return ret; } -static int -i40e_dev_global_config_set(struct i40e_hw *hw, struct rte_eth_global_cfg *cfg) -{ - int ret = -EINVAL; - - if (!hw || !cfg) - return -EINVAL; - - switch (cfg->cfg_type) { - case RTE_ETH_GLOBAL_CFG_TYPE_GRE_KEY_LEN: - ret = i40e_dev_set_gre_key_len(hw, cfg->cfg.gre_key_len); - break; - default: - PMD_DRV_LOG(ERR, "Unknown config type %u", cfg->cfg_type); - break; - } - - return ret; -} - -static int -i40e_filter_ctrl_global_config(struct rte_eth_dev *dev, - enum rte_filter_op filter_op, - void *arg) -{ - struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); - int ret = I40E_ERR_PARAM; - - switch (filter_op) { - case RTE_ETH_FILTER_SET: - ret = i40e_dev_global_config_set(hw, - (struct rte_eth_global_cfg *)arg); - break; - default: - PMD_DRV_LOG(ERR, "unknown operation %u", filter_op); - break; - } - - return ret; -} - -static int -i40e_tunnel_filter_handle(struct rte_eth_dev *dev, - enum rte_filter_op filter_op, - void *arg) -{ - struct rte_eth_tunnel_filter_conf *filter; - struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); - int ret = I40E_SUCCESS; - - filter = (struct rte_eth_tunnel_filter_conf *)(arg); - - if (i40e_tunnel_filter_param_check(pf, filter) < 0) - return I40E_ERR_PARAM; - - switch (filter_op) { - case RTE_ETH_FILTER_NOP: - if (!(pf->flags & I40E_FLAG_VXLAN)) - ret = I40E_NOT_SUPPORTED; - break; - case RTE_ETH_FILTER_ADD: - ret = i40e_dev_tunnel_filter_set(pf, filter, 1); - break; - case RTE_ETH_FILTER_DELETE: - ret = i40e_dev_tunnel_filter_set(pf, filter, 0); - break; - default: - PMD_DRV_LOG(ERR, "unknown operation %u", filter_op); - ret = I40E_ERR_PARAM; - break; - } - - return ret; -} - -/* Get the symmetric hash enable configurations per port */ -static void -i40e_get_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t *enable) -{ - uint32_t reg = i40e_read_rx_ctl(hw, I40E_PRTQF_CTL_0); - - *enable = reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK ? 1 : 0; -} - /* Set the symmetric hash enable configurations per port */ -static void +void i40e_set_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t enable) { uint32_t reg = i40e_read_rx_ctl(hw, I40E_PRTQF_CTL_0); if (enable > 0) { - if (reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK) { - PMD_DRV_LOG(INFO, - "Symmetric hash has already been enabled"); + if (reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK) return; - } + reg |= I40E_PRTQF_CTL_0_HSYM_ENA_MASK; } else { - if (!(reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK)) { - PMD_DRV_LOG(INFO, - "Symmetric hash has already been disabled"); + if (!(reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK)) return; - } + reg &= ~I40E_PRTQF_CTL_0_HSYM_ENA_MASK; } i40e_write_rx_ctl(hw, I40E_PRTQF_CTL_0, reg); I40E_WRITE_FLUSH(hw); } -/* - * Get global configurations of hash function type and symmetric hash enable - * per flow type (pctype). Note that global configuration means it affects all - * the ports on the same NIC. - */ -static int -i40e_get_hash_filter_global_config(struct i40e_hw *hw, - struct rte_eth_hash_global_conf *g_cfg) -{ - struct i40e_adapter *adapter = (struct i40e_adapter *)hw->back; - uint32_t reg; - uint16_t i, j; - - memset(g_cfg, 0, sizeof(*g_cfg)); - reg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL); - if (reg & I40E_GLQF_CTL_HTOEP_MASK) - g_cfg->hash_func = RTE_ETH_HASH_FUNCTION_TOEPLITZ; - else - g_cfg->hash_func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR; - PMD_DRV_LOG(DEBUG, "Hash function is %s", - (reg & I40E_GLQF_CTL_HTOEP_MASK) ? "Toeplitz" : "Simple XOR"); - - /* - * As i40e supports less than 64 flow types, only first 64 bits need to - * be checked. - */ - for (i = 1; i < RTE_SYM_HASH_MASK_ARRAY_SIZE; i++) { - g_cfg->valid_bit_mask[i] = 0ULL; - g_cfg->sym_hash_enable_mask[i] = 0ULL; - } - - g_cfg->valid_bit_mask[0] = adapter->flow_types_mask; - - for (i = RTE_ETH_FLOW_UNKNOWN + 1; i < UINT64_BIT; i++) { - if (!adapter->pctypes_tbl[i]) - continue; - for (j = I40E_FILTER_PCTYPE_INVALID + 1; - j < I40E_FILTER_PCTYPE_MAX; j++) { - if (adapter->pctypes_tbl[i] & (1ULL << j)) { - reg = i40e_read_rx_ctl(hw, I40E_GLQF_HSYM(j)); - if (reg & I40E_GLQF_HSYM_SYMH_ENA_MASK) { - g_cfg->sym_hash_enable_mask[0] |= - (1ULL << i); - } - } - } - } - - return 0; -} - -static int -i40e_hash_global_config_check(const struct i40e_adapter *adapter, - const struct rte_eth_hash_global_conf *g_cfg) -{ - uint32_t i; - uint64_t mask0, i40e_mask = adapter->flow_types_mask; - - if (g_cfg->hash_func != RTE_ETH_HASH_FUNCTION_TOEPLITZ && - g_cfg->hash_func != RTE_ETH_HASH_FUNCTION_SIMPLE_XOR && - g_cfg->hash_func != RTE_ETH_HASH_FUNCTION_DEFAULT) { - PMD_DRV_LOG(ERR, "Unsupported hash function type %d", - g_cfg->hash_func); - return -EINVAL; - } - - /* - * As i40e supports less than 64 flow types, only first 64 bits need to - * be checked. - */ - mask0 = g_cfg->valid_bit_mask[0]; - for (i = 0; i < RTE_SYM_HASH_MASK_ARRAY_SIZE; i++) { - if (i == 0) { - /* Check if any unsupported flow type configured */ - if ((mask0 | i40e_mask) ^ i40e_mask) - goto mask_err; - } else { - if (g_cfg->valid_bit_mask[i]) - goto mask_err; - } - } - - return 0; - -mask_err: - PMD_DRV_LOG(ERR, "i40e unsupported flow type bit(s) configured"); - - return -EINVAL; -} - -/* - * Set global configurations of hash function type and symmetric hash enable - * per flow type (pctype). Note any modifying global configuration will affect - * all the ports on the same NIC. - */ -static int -i40e_set_hash_filter_global_config(struct i40e_hw *hw, - struct rte_eth_hash_global_conf *g_cfg) -{ - struct i40e_adapter *adapter = (struct i40e_adapter *)hw->back; - struct i40e_pf *pf = &((struct i40e_adapter *)hw->back)->pf; - int ret; - uint16_t i, j; - uint32_t reg; - uint64_t mask0 = g_cfg->valid_bit_mask[0] & adapter->flow_types_mask; - - if (pf->support_multi_driver) { - PMD_DRV_LOG(ERR, "Hash global configuration is not supported."); - return -ENOTSUP; - } - - /* Check the input parameters */ - ret = i40e_hash_global_config_check(adapter, g_cfg); - if (ret < 0) - return ret; - - /* - * As i40e supports less than 64 flow types, only first 64 bits need to - * be configured. - */ - for (i = RTE_ETH_FLOW_UNKNOWN + 1; mask0 && i < UINT64_BIT; i++) { - if (mask0 & (1UL << i)) { - reg = (g_cfg->sym_hash_enable_mask[0] & (1ULL << i)) ? - I40E_GLQF_HSYM_SYMH_ENA_MASK : 0; - - for (j = I40E_FILTER_PCTYPE_INVALID + 1; - j < I40E_FILTER_PCTYPE_MAX; j++) { - if (adapter->pctypes_tbl[i] & (1ULL << j)) - i40e_write_global_rx_ctl(hw, - I40E_GLQF_HSYM(j), - reg); - } - } - } - - reg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL); - if (g_cfg->hash_func == RTE_ETH_HASH_FUNCTION_TOEPLITZ) { - /* Toeplitz */ - if (reg & I40E_GLQF_CTL_HTOEP_MASK) { - PMD_DRV_LOG(DEBUG, - "Hash function already set to Toeplitz"); - goto out; - } - reg |= I40E_GLQF_CTL_HTOEP_MASK; - } else if (g_cfg->hash_func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) { - /* Simple XOR */ - if (!(reg & I40E_GLQF_CTL_HTOEP_MASK)) { - PMD_DRV_LOG(DEBUG, - "Hash function already set to Simple XOR"); - goto out; - } - reg &= ~I40E_GLQF_CTL_HTOEP_MASK; - } else - /* Use the default, and keep it as it is */ - goto out; - - i40e_write_global_rx_ctl(hw, I40E_GLQF_CTL, reg); - -out: - I40E_WRITE_FLUSH(hw); - - return 0; -} - /** * Valid input sets for hash and flow director filters per PCTYPE */ @@ -9792,103 +9352,6 @@ i40e_get_default_input_set(uint16_t pctype) return default_inset_table[pctype]; } -/** - * Parse the input set from index to logical bit masks - */ -static int -i40e_parse_input_set(uint64_t *inset, - enum i40e_filter_pctype pctype, - enum rte_eth_input_set_field *field, - uint16_t size) -{ - uint16_t i, j; - int ret = -EINVAL; - - static const struct { - enum rte_eth_input_set_field field; - uint64_t inset; - } inset_convert_table[] = { - {RTE_ETH_INPUT_SET_NONE, I40E_INSET_NONE}, - {RTE_ETH_INPUT_SET_L2_SRC_MAC, I40E_INSET_SMAC}, - {RTE_ETH_INPUT_SET_L2_DST_MAC, I40E_INSET_DMAC}, - {RTE_ETH_INPUT_SET_L2_OUTER_VLAN, I40E_INSET_VLAN_OUTER}, - {RTE_ETH_INPUT_SET_L2_INNER_VLAN, I40E_INSET_VLAN_INNER}, - {RTE_ETH_INPUT_SET_L2_ETHERTYPE, I40E_INSET_LAST_ETHER_TYPE}, - {RTE_ETH_INPUT_SET_L3_SRC_IP4, I40E_INSET_IPV4_SRC}, - {RTE_ETH_INPUT_SET_L3_DST_IP4, I40E_INSET_IPV4_DST}, - {RTE_ETH_INPUT_SET_L3_IP4_TOS, I40E_INSET_IPV4_TOS}, - {RTE_ETH_INPUT_SET_L3_IP4_PROTO, I40E_INSET_IPV4_PROTO}, - {RTE_ETH_INPUT_SET_L3_IP4_TTL, I40E_INSET_IPV4_TTL}, - {RTE_ETH_INPUT_SET_L3_SRC_IP6, I40E_INSET_IPV6_SRC}, - {RTE_ETH_INPUT_SET_L3_DST_IP6, I40E_INSET_IPV6_DST}, - {RTE_ETH_INPUT_SET_L3_IP6_TC, I40E_INSET_IPV6_TC}, - {RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER, - I40E_INSET_IPV6_NEXT_HDR}, - {RTE_ETH_INPUT_SET_L3_IP6_HOP_LIMITS, - I40E_INSET_IPV6_HOP_LIMIT}, - {RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT, I40E_INSET_SRC_PORT}, - {RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT, I40E_INSET_SRC_PORT}, - {RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT, I40E_INSET_SRC_PORT}, - {RTE_ETH_INPUT_SET_L4_UDP_DST_PORT, I40E_INSET_DST_PORT}, - {RTE_ETH_INPUT_SET_L4_TCP_DST_PORT, I40E_INSET_DST_PORT}, - {RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT, I40E_INSET_DST_PORT}, - {RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG, - I40E_INSET_SCTP_VT}, - {RTE_ETH_INPUT_SET_TUNNEL_L2_INNER_DST_MAC, - I40E_INSET_TUNNEL_DMAC}, - {RTE_ETH_INPUT_SET_TUNNEL_L2_INNER_VLAN, - I40E_INSET_VLAN_TUNNEL}, - {RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY, - I40E_INSET_TUNNEL_ID}, - {RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY, I40E_INSET_TUNNEL_ID}, - {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD, - I40E_INSET_FLEX_PAYLOAD_W1}, - {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD, - I40E_INSET_FLEX_PAYLOAD_W2}, - {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD, - I40E_INSET_FLEX_PAYLOAD_W3}, - {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD, - I40E_INSET_FLEX_PAYLOAD_W4}, - {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD, - I40E_INSET_FLEX_PAYLOAD_W5}, - {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD, - I40E_INSET_FLEX_PAYLOAD_W6}, - {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD, - I40E_INSET_FLEX_PAYLOAD_W7}, - {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD, - I40E_INSET_FLEX_PAYLOAD_W8}, - }; - - if (!inset || !field || size > RTE_ETH_INSET_SIZE_MAX) - return ret; - - /* Only one item allowed for default or all */ - if (size == 1) { - if (field[0] == RTE_ETH_INPUT_SET_DEFAULT) { - *inset = i40e_get_default_input_set(pctype); - return 0; - } else if (field[0] == RTE_ETH_INPUT_SET_NONE) { - *inset = I40E_INSET_NONE; - return 0; - } - } - - for (i = 0, *inset = 0; i < size; i++) { - for (j = 0; j < RTE_DIM(inset_convert_table); j++) { - if (field[i] == inset_convert_table[j].field) { - *inset |= inset_convert_table[j].inset; - break; - } - } - - /* It contains unsupported input set, return immediately */ - if (j == RTE_DIM(inset_convert_table)) - return ret; - } - - return 0; -} - /** * Translate the input set from bit masks to register aware bit masks * and vice versa @@ -9978,49 +9441,116 @@ i40e_translate_input_set_reg(enum i40e_mac_type type, uint64_t input) return val; } +static int +i40e_get_inset_field_offset(struct i40e_hw *hw, uint32_t pit_reg_start, + uint32_t pit_reg_count, uint32_t hdr_off) +{ + const uint32_t pit_reg_end = pit_reg_start + pit_reg_count; + uint32_t field_off = I40E_FDIR_FIELD_OFFSET(hdr_off); + uint32_t i, reg_val, src_off, count; + + for (i = pit_reg_start; i < pit_reg_end; i++) { + reg_val = i40e_read_rx_ctl(hw, I40E_GLQF_PIT(i)); + + src_off = I40E_GLQF_PIT_SOURCE_OFF_GET(reg_val); + count = I40E_GLQF_PIT_FSIZE_GET(reg_val); + + if (src_off <= field_off && (src_off + count) > field_off) + break; + } + + if (i >= pit_reg_end) { + PMD_DRV_LOG(ERR, + "Hardware GLQF_PIT configuration does not support this field mask"); + return -1; + } + + return I40E_GLQF_PIT_DEST_OFF_GET(reg_val) + field_off - src_off; +} + int -i40e_generate_inset_mask_reg(uint64_t inset, uint32_t *mask, uint8_t nb_elem) +i40e_generate_inset_mask_reg(struct i40e_hw *hw, uint64_t inset, + uint32_t *mask, uint8_t nb_elem) { - uint8_t i, idx = 0; - uint64_t inset_need_mask = inset; + static const uint64_t mask_inset[] = { + I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL, + I40E_INSET_IPV6_NEXT_HDR | I40E_INSET_IPV6_HOP_LIMIT }; static const struct { uint64_t inset; uint32_t mask; - } inset_mask_map[] = { - {I40E_INSET_IPV4_TOS, I40E_INSET_IPV4_TOS_MASK}, - {I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL, 0}, - {I40E_INSET_IPV4_PROTO, I40E_INSET_IPV4_PROTO_MASK}, - {I40E_INSET_IPV4_TTL, I40E_INSET_IPv4_TTL_MASK}, - {I40E_INSET_IPV6_TC, I40E_INSET_IPV6_TC_MASK}, - {I40E_INSET_IPV6_NEXT_HDR | I40E_INSET_IPV6_HOP_LIMIT, 0}, - {I40E_INSET_IPV6_NEXT_HDR, I40E_INSET_IPV6_NEXT_HDR_MASK}, - {I40E_INSET_IPV6_HOP_LIMIT, I40E_INSET_IPV6_HOP_LIMIT_MASK}, + uint32_t offset; + } inset_mask_offset_map[] = { + { I40E_INSET_IPV4_TOS, I40E_INSET_IPV4_TOS_MASK, + offsetof(struct rte_ipv4_hdr, type_of_service) }, + + { I40E_INSET_IPV4_PROTO, I40E_INSET_IPV4_PROTO_MASK, + offsetof(struct rte_ipv4_hdr, next_proto_id) }, + + { I40E_INSET_IPV4_TTL, I40E_INSET_IPV4_TTL_MASK, + offsetof(struct rte_ipv4_hdr, time_to_live) }, + + { I40E_INSET_IPV6_TC, I40E_INSET_IPV6_TC_MASK, + offsetof(struct rte_ipv6_hdr, vtc_flow) }, + + { I40E_INSET_IPV6_NEXT_HDR, I40E_INSET_IPV6_NEXT_HDR_MASK, + offsetof(struct rte_ipv6_hdr, proto) }, + + { I40E_INSET_IPV6_HOP_LIMIT, I40E_INSET_IPV6_HOP_LIMIT_MASK, + offsetof(struct rte_ipv6_hdr, hop_limits) }, }; - if (!inset || !mask || !nb_elem) + uint32_t i; + int idx = 0; + + assert(mask); + if (!inset) return 0; - for (i = 0, idx = 0; i < RTE_DIM(inset_mask_map); i++) { + for (i = 0; i < RTE_DIM(mask_inset); i++) { /* Clear the inset bit, if no MASK is required, * for example proto + ttl */ - if ((inset & inset_mask_map[i].inset) == - inset_mask_map[i].inset && inset_mask_map[i].mask == 0) - inset_need_mask &= ~inset_mask_map[i].inset; - if (!inset_need_mask) - return 0; + if ((mask_inset[i] & inset) == mask_inset[i]) { + inset &= ~mask_inset[i]; + if (!inset) + return 0; + } } - for (i = 0, idx = 0; i < RTE_DIM(inset_mask_map); i++) { - if ((inset_need_mask & inset_mask_map[i].inset) == - inset_mask_map[i].inset) { - if (idx >= nb_elem) { - PMD_DRV_LOG(ERR, "exceed maximal number of bitmasks"); - return -EINVAL; - } - mask[idx] = inset_mask_map[i].mask; - idx++; + + for (i = 0; i < RTE_DIM(inset_mask_offset_map); i++) { + uint32_t pit_start, pit_count; + int offset; + + if (!(inset_mask_offset_map[i].inset & inset)) + continue; + + if (inset_mask_offset_map[i].inset & + (I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | + I40E_INSET_IPV4_TTL)) { + pit_start = I40E_GLQF_PIT_IPV4_START; + pit_count = I40E_GLQF_PIT_IPV4_COUNT; + } else { + pit_start = I40E_GLQF_PIT_IPV6_START; + pit_count = I40E_GLQF_PIT_IPV6_COUNT; } + + offset = i40e_get_inset_field_offset(hw, pit_start, pit_count, + inset_mask_offset_map[i].offset); + + if (offset < 0) + return -EINVAL; + + if (idx >= nb_elem) { + PMD_DRV_LOG(ERR, + "Configuration of inset mask out of range %u", + nb_elem); + return -ERANGE; + } + + mask[idx] = I40E_GLQF_PIT_BUILD((uint32_t)offset, + inset_mask_offset_map[i].mask); + idx++; } return idx; @@ -10074,7 +9604,7 @@ i40e_filter_input_set_init(struct i40e_pf *pf) input_set = i40e_get_default_input_set(pctype); - num = i40e_generate_inset_mask_reg(input_set, mask_reg, + num = i40e_generate_inset_mask_reg(hw, input_set, mask_reg, I40E_INSET_MASK_NUM_REG); if (num < 0) return; @@ -10129,57 +9659,32 @@ i40e_filter_input_set_init(struct i40e_pf *pf) } int -i40e_hash_filter_inset_select(struct i40e_hw *hw, - struct rte_eth_input_set_conf *conf) +i40e_set_hash_inset(struct i40e_hw *hw, uint64_t input_set, + uint32_t pctype, bool add) { struct i40e_pf *pf = &((struct i40e_adapter *)hw->back)->pf; - enum i40e_filter_pctype pctype; - uint64_t input_set, inset_reg = 0; uint32_t mask_reg[I40E_INSET_MASK_NUM_REG] = {0}; - int ret, i, num; - - if (!conf) { - PMD_DRV_LOG(ERR, "Invalid pointer"); - return -EFAULT; - } - if (conf->op != RTE_ETH_INPUT_SET_SELECT && - conf->op != RTE_ETH_INPUT_SET_ADD) { - PMD_DRV_LOG(ERR, "Unsupported input set operation"); - return -EINVAL; - } + uint64_t inset_reg = 0; + int num, i; if (pf->support_multi_driver) { - PMD_DRV_LOG(ERR, "Hash input set setting is not supported."); - return -ENOTSUP; - } - - pctype = i40e_flowtype_to_pctype(pf->adapter, conf->flow_type); - if (pctype == I40E_FILTER_PCTYPE_INVALID) { - PMD_DRV_LOG(ERR, "invalid flow_type input."); - return -EINVAL; - } - - 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)pctype)); + PMD_DRV_LOG(ERR, + "Modify input set is not permitted when multi-driver enabled."); + return -EPERM; } - ret = i40e_parse_input_set(&input_set, pctype, conf->field, - conf->inset_size); - if (ret) { - PMD_DRV_LOG(ERR, "Failed to parse input set"); - return -EINVAL; - } + /* For X722, get translated pctype in fd pctype register */ + if (hw->mac.type == I40E_MAC_X722) + pctype = i40e_read_rx_ctl(hw, I40E_GLQF_FD_PCTYPES(pctype)); - if (conf->op == RTE_ETH_INPUT_SET_ADD) { + if (add) { /* get inset value in register */ inset_reg = i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, pctype)); inset_reg <<= I40E_32_BIT_WIDTH; inset_reg |= i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, pctype)); input_set |= pf->hash_input_set[pctype]; } - num = i40e_generate_inset_mask_reg(input_set, mask_reg, + num = i40e_generate_inset_mask_reg(hw, input_set, mask_reg, I40E_INSET_MASK_NUM_REG); if (num < 0) return -EINVAL; @@ -10198,186 +9703,11 @@ i40e_hash_filter_inset_select(struct i40e_hw *hw, /*clear unused mask registers of the pctype */ for (i = num; i < I40E_INSET_MASK_NUM_REG; i++) i40e_check_write_global_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), - 0); - I40E_WRITE_FLUSH(hw); - - pf->hash_input_set[pctype] = input_set; - return 0; -} - -int -i40e_fdir_filter_inset_select(struct i40e_pf *pf, - struct rte_eth_input_set_conf *conf) -{ - struct i40e_hw *hw = I40E_PF_TO_HW(pf); - enum i40e_filter_pctype pctype; - uint64_t input_set, inset_reg = 0; - uint32_t mask_reg[I40E_INSET_MASK_NUM_REG] = {0}; - int ret, i, num; - - if (!hw || !conf) { - PMD_DRV_LOG(ERR, "Invalid pointer"); - return -EFAULT; - } - if (conf->op != RTE_ETH_INPUT_SET_SELECT && - conf->op != RTE_ETH_INPUT_SET_ADD) { - PMD_DRV_LOG(ERR, "Unsupported input set operation"); - return -EINVAL; - } - - pctype = i40e_flowtype_to_pctype(pf->adapter, conf->flow_type); - - if (pctype == I40E_FILTER_PCTYPE_INVALID) { - PMD_DRV_LOG(ERR, "invalid flow_type input."); - return -EINVAL; - } - - ret = i40e_parse_input_set(&input_set, pctype, conf->field, - conf->inset_size); - if (ret) { - PMD_DRV_LOG(ERR, "Failed to parse input set"); - return -EINVAL; - } - - /* get inset value in register */ - inset_reg = i40e_read_rx_ctl(hw, I40E_PRTQF_FD_INSET(pctype, 1)); - inset_reg <<= I40E_32_BIT_WIDTH; - inset_reg |= i40e_read_rx_ctl(hw, I40E_PRTQF_FD_INSET(pctype, 0)); - - /* Can not change the inset reg for flex payload for fdir, - * it is done by writing I40E_PRTQF_FD_FLXINSET - * in i40e_set_flex_mask_on_pctype. - */ - if (conf->op == RTE_ETH_INPUT_SET_SELECT) - inset_reg &= I40E_REG_INSET_FLEX_PAYLOAD_WORDS; - else - input_set |= pf->fdir.input_set[pctype]; - num = i40e_generate_inset_mask_reg(input_set, mask_reg, - I40E_INSET_MASK_NUM_REG); - if (num < 0) - return -EINVAL; - if (pf->support_multi_driver && num > 0) { - PMD_DRV_LOG(ERR, "FDIR bit mask is not supported."); - return -ENOTSUP; - } - - inset_reg |= i40e_translate_input_set_reg(hw->mac.type, input_set); - - i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 0), - (uint32_t)(inset_reg & UINT32_MAX)); - i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 1), - (uint32_t)((inset_reg >> - I40E_32_BIT_WIDTH) & UINT32_MAX)); - - if (!pf->support_multi_driver) { - for (i = 0; i < num; i++) - i40e_check_write_global_reg(hw, - I40E_GLQF_FD_MSK(i, pctype), - mask_reg[i]); - /*clear unused mask registers of the pctype */ - for (i = num; i < I40E_INSET_MASK_NUM_REG; i++) - i40e_check_write_global_reg(hw, - I40E_GLQF_FD_MSK(i, pctype), - 0); - } else { - PMD_DRV_LOG(ERR, "FDIR bit mask is not supported."); - } - I40E_WRITE_FLUSH(hw); - - pf->fdir.input_set[pctype] = input_set; - return 0; -} - -static int -i40e_hash_filter_get(struct i40e_hw *hw, struct rte_eth_hash_filter_info *info) -{ - int ret = 0; - - if (!hw || !info) { - PMD_DRV_LOG(ERR, "Invalid pointer"); - return -EFAULT; - } - - switch (info->info_type) { - case RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT: - i40e_get_symmetric_hash_enable_per_port(hw, - &(info->info.enable)); - break; - case RTE_ETH_HASH_FILTER_GLOBAL_CONFIG: - ret = i40e_get_hash_filter_global_config(hw, - &(info->info.global_conf)); - break; - default: - PMD_DRV_LOG(ERR, "Hash filter info type (%d) not supported", - info->info_type); - ret = -EINVAL; - break; - } - - return ret; -} - -static int -i40e_hash_filter_set(struct i40e_hw *hw, struct rte_eth_hash_filter_info *info) -{ - int ret = 0; - - if (!hw || !info) { - PMD_DRV_LOG(ERR, "Invalid pointer"); - return -EFAULT; - } - - switch (info->info_type) { - case RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT: - i40e_set_symmetric_hash_enable_per_port(hw, info->info.enable); - break; - case RTE_ETH_HASH_FILTER_GLOBAL_CONFIG: - ret = i40e_set_hash_filter_global_config(hw, - &(info->info.global_conf)); - break; - case RTE_ETH_HASH_FILTER_INPUT_SET_SELECT: - ret = i40e_hash_filter_inset_select(hw, - &(info->info.input_set_conf)); - break; - - default: - PMD_DRV_LOG(ERR, "Hash filter info type (%d) not supported", - info->info_type); - ret = -EINVAL; - break; - } - - return ret; -} - -/* Operations for hash function */ -static int -i40e_hash_filter_ctrl(struct rte_eth_dev *dev, - enum rte_filter_op filter_op, - void *arg) -{ - struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); - int ret = 0; - - switch (filter_op) { - case RTE_ETH_FILTER_NOP: - break; - case RTE_ETH_FILTER_GET: - ret = i40e_hash_filter_get(hw, - (struct rte_eth_hash_filter_info *)arg); - break; - case RTE_ETH_FILTER_SET: - ret = i40e_hash_filter_set(hw, - (struct rte_eth_hash_filter_info *)arg); - break; - default: - PMD_DRV_LOG(WARNING, "Filter operation (%d) not supported", - filter_op); - ret = -ENOTSUP; - break; - } + 0); + I40E_WRITE_FLUSH(hw); - return ret; + pf->hash_input_set[pctype] = input_set; + return 0; } /* Convert ethertype filter structure */ @@ -10545,89 +9875,15 @@ i40e_ethertype_filter_set(struct i40e_pf *pf, return ret; } -/* - * Handle operations for ethertype filter. - */ -static int -i40e_ethertype_filter_handle(struct rte_eth_dev *dev, - enum rte_filter_op filter_op, - void *arg) -{ - struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); - int ret = 0; - - if (filter_op == RTE_ETH_FILTER_NOP) - return ret; - - if (arg == NULL) { - PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u", - filter_op); - return -EINVAL; - } - - switch (filter_op) { - case RTE_ETH_FILTER_ADD: - ret = i40e_ethertype_filter_set(pf, - (struct rte_eth_ethertype_filter *)arg, - TRUE); - break; - case RTE_ETH_FILTER_DELETE: - ret = i40e_ethertype_filter_set(pf, - (struct rte_eth_ethertype_filter *)arg, - FALSE); - break; - default: - PMD_DRV_LOG(ERR, "unsupported operation %u", filter_op); - ret = -ENOSYS; - break; - } - return ret; -} - static int -i40e_dev_filter_ctrl(struct rte_eth_dev *dev, - enum rte_filter_type filter_type, - enum rte_filter_op filter_op, - void *arg) +i40e_dev_flow_ops_get(struct rte_eth_dev *dev, + const struct rte_flow_ops **ops) { - int ret = 0; - if (dev == NULL) return -EINVAL; - switch (filter_type) { - case RTE_ETH_FILTER_NONE: - /* For global configuration */ - ret = i40e_filter_ctrl_global_config(dev, filter_op, arg); - break; - case RTE_ETH_FILTER_HASH: - ret = i40e_hash_filter_ctrl(dev, filter_op, arg); - break; - case RTE_ETH_FILTER_MACVLAN: - ret = i40e_mac_filter_handle(dev, filter_op, arg); - break; - case RTE_ETH_FILTER_ETHERTYPE: - ret = i40e_ethertype_filter_handle(dev, filter_op, arg); - break; - case RTE_ETH_FILTER_TUNNEL: - ret = i40e_tunnel_filter_handle(dev, filter_op, arg); - break; - case RTE_ETH_FILTER_FDIR: - ret = i40e_fdir_ctrl_func(dev, filter_op, arg); - break; - case RTE_ETH_FILTER_GENERIC: - if (filter_op != RTE_ETH_FILTER_GET) - return -EINVAL; - *(const void **)arg = &i40e_flow_ops; - break; - default: - PMD_DRV_LOG(WARNING, "Filter type (%d) not supported", - filter_type); - ret = -EINVAL; - break; - } - - return ret; + *ops = &i40e_flow_ops; + return 0; } /* @@ -12506,7 +11762,7 @@ i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) return -EBUSY; } - if (frame_size > RTE_ETHER_MAX_LEN) + if (frame_size > I40E_ETH_MAX_LEN) dev_data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME; else @@ -12606,25 +11862,13 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf) } } -/* Restore RSS filter */ -static inline void -i40e_rss_filter_restore(struct i40e_pf *pf) -{ - struct i40e_rss_conf_list *list = &pf->rss_config_list; - struct i40e_rss_filter *filter; - - TAILQ_FOREACH(filter, list, next) { - i40e_config_rss_filter(pf, &filter->rss_filter_info, TRUE); - } -} - static void i40e_filter_restore(struct i40e_pf *pf) { i40e_ethertype_filter_restore(pf); i40e_tunnel_filter_restore(pf); i40e_fdir_filter_restore(pf); - i40e_rss_filter_restore(pf); + (void)i40e_hash_filter_restore(pf); } bool @@ -13202,551 +12446,6 @@ i40e_cloud_filter_qinq_create(struct i40e_pf *pf) return ret; } -int -i40e_rss_conf_init(struct i40e_rte_flow_rss_conf *out, - const struct rte_flow_action_rss *in) -{ - if (in->key_len > RTE_DIM(out->key) || - in->queue_num > RTE_DIM(out->queue)) - return -EINVAL; - if (!in->key && in->key_len) - return -EINVAL; - out->conf = (struct rte_flow_action_rss){ - .func = in->func, - .level = in->level, - .types = in->types, - .key_len = in->key_len, - .queue_num = in->queue_num, - .queue = memcpy(out->queue, in->queue, - sizeof(*in->queue) * in->queue_num), - }; - if (in->key) - out->conf.key = memcpy(out->key, in->key, in->key_len); - return 0; -} - -/* Write HENA register to enable hash */ -static int -i40e_rss_hash_set(struct i40e_pf *pf, struct i40e_rte_flow_rss_conf *rss_conf) -{ - struct i40e_hw *hw = I40E_PF_TO_HW(pf); - uint8_t *key = (void *)(uintptr_t)rss_conf->conf.key; - uint64_t hena; - int ret; - - ret = i40e_set_rss_key(pf->main_vsi, key, - rss_conf->conf.key_len); - if (ret) - return ret; - - hena = i40e_config_hena(pf->adapter, rss_conf->conf.types); - i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (uint32_t)hena); - i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), (uint32_t)(hena >> 32)); - I40E_WRITE_FLUSH(hw); - - return 0; -} - -/* Configure hash input set */ -static int -i40e_rss_conf_hash_inset(struct i40e_pf *pf, uint64_t types) -{ - struct i40e_hw *hw = I40E_PF_TO_HW(pf); - struct rte_eth_input_set_conf conf; - uint64_t mask0; - int ret = 0; - uint32_t j; - int i; - static const struct { - uint64_t type; - enum rte_eth_input_set_field field; - } inset_match_table[] = { - {ETH_RSS_FRAG_IPV4 | ETH_RSS_L3_SRC_ONLY, - RTE_ETH_INPUT_SET_L3_SRC_IP4}, - {ETH_RSS_FRAG_IPV4 | ETH_RSS_L3_DST_ONLY, - RTE_ETH_INPUT_SET_L3_DST_IP4}, - {ETH_RSS_FRAG_IPV4 | ETH_RSS_L4_SRC_ONLY, - RTE_ETH_INPUT_SET_UNKNOWN}, - {ETH_RSS_FRAG_IPV4 | ETH_RSS_L4_DST_ONLY, - RTE_ETH_INPUT_SET_UNKNOWN}, - - {ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L3_SRC_ONLY, - RTE_ETH_INPUT_SET_L3_SRC_IP4}, - {ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L3_DST_ONLY, - RTE_ETH_INPUT_SET_L3_DST_IP4}, - {ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L4_SRC_ONLY, - RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT}, - {ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L4_DST_ONLY, - RTE_ETH_INPUT_SET_L4_TCP_DST_PORT}, - - {ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L3_SRC_ONLY, - RTE_ETH_INPUT_SET_L3_SRC_IP4}, - {ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L3_DST_ONLY, - RTE_ETH_INPUT_SET_L3_DST_IP4}, - {ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L4_SRC_ONLY, - RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT}, - {ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L4_DST_ONLY, - RTE_ETH_INPUT_SET_L4_UDP_DST_PORT}, - - {ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L3_SRC_ONLY, - RTE_ETH_INPUT_SET_L3_SRC_IP4}, - {ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L3_DST_ONLY, - RTE_ETH_INPUT_SET_L3_DST_IP4}, - {ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L4_SRC_ONLY, - RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT}, - {ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L4_DST_ONLY, - RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT}, - - {ETH_RSS_NONFRAG_IPV4_OTHER | ETH_RSS_L3_SRC_ONLY, - RTE_ETH_INPUT_SET_L3_SRC_IP4}, - {ETH_RSS_NONFRAG_IPV4_OTHER | ETH_RSS_L3_DST_ONLY, - RTE_ETH_INPUT_SET_L3_DST_IP4}, - {ETH_RSS_NONFRAG_IPV4_OTHER | ETH_RSS_L4_SRC_ONLY, - RTE_ETH_INPUT_SET_UNKNOWN}, - {ETH_RSS_NONFRAG_IPV4_OTHER | ETH_RSS_L4_DST_ONLY, - RTE_ETH_INPUT_SET_UNKNOWN}, - - {ETH_RSS_FRAG_IPV6 | ETH_RSS_L3_SRC_ONLY, - RTE_ETH_INPUT_SET_L3_SRC_IP6}, - {ETH_RSS_FRAG_IPV6 | ETH_RSS_L3_DST_ONLY, - RTE_ETH_INPUT_SET_L3_DST_IP6}, - {ETH_RSS_FRAG_IPV6 | ETH_RSS_L4_SRC_ONLY, - RTE_ETH_INPUT_SET_UNKNOWN}, - {ETH_RSS_FRAG_IPV6 | ETH_RSS_L4_DST_ONLY, - RTE_ETH_INPUT_SET_UNKNOWN}, - - {ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L3_SRC_ONLY, - RTE_ETH_INPUT_SET_L3_SRC_IP6}, - {ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L3_DST_ONLY, - RTE_ETH_INPUT_SET_L3_DST_IP6}, - {ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L4_SRC_ONLY, - RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT}, - {ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L4_DST_ONLY, - RTE_ETH_INPUT_SET_L4_TCP_DST_PORT}, - - {ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L3_SRC_ONLY, - RTE_ETH_INPUT_SET_L3_SRC_IP6}, - {ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L3_DST_ONLY, - RTE_ETH_INPUT_SET_L3_DST_IP6}, - {ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L4_SRC_ONLY, - RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT}, - {ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L4_DST_ONLY, - RTE_ETH_INPUT_SET_L4_UDP_DST_PORT}, - - {ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L3_SRC_ONLY, - RTE_ETH_INPUT_SET_L3_SRC_IP6}, - {ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L3_DST_ONLY, - RTE_ETH_INPUT_SET_L3_DST_IP6}, - {ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L4_SRC_ONLY, - RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT}, - {ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L4_DST_ONLY, - RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT}, - - {ETH_RSS_NONFRAG_IPV6_OTHER | ETH_RSS_L3_SRC_ONLY, - RTE_ETH_INPUT_SET_L3_SRC_IP6}, - {ETH_RSS_NONFRAG_IPV6_OTHER | ETH_RSS_L3_DST_ONLY, - RTE_ETH_INPUT_SET_L3_DST_IP6}, - {ETH_RSS_NONFRAG_IPV6_OTHER | ETH_RSS_L4_SRC_ONLY, - RTE_ETH_INPUT_SET_UNKNOWN}, - {ETH_RSS_NONFRAG_IPV6_OTHER | ETH_RSS_L4_DST_ONLY, - RTE_ETH_INPUT_SET_UNKNOWN}, - }; - - mask0 = types & pf->adapter->flow_types_mask; - conf.op = RTE_ETH_INPUT_SET_SELECT; - conf.inset_size = 0; - for (i = RTE_ETH_FLOW_UNKNOWN + 1; i < RTE_ETH_FLOW_MAX; i++) { - if (mask0 & (1ULL << i)) { - conf.flow_type = i; - break; - } - } - - for (j = 0; j < RTE_DIM(inset_match_table); j++) { - if ((types & inset_match_table[j].type) == - inset_match_table[j].type) { - if (inset_match_table[j].field == - RTE_ETH_INPUT_SET_UNKNOWN) - return -EINVAL; - - conf.field[conf.inset_size] = - inset_match_table[j].field; - conf.inset_size++; - } - } - - if (conf.inset_size) { - ret = i40e_hash_filter_inset_select(hw, &conf); - if (ret) - return ret; - } - - return ret; -} - -/* Look up the conflicted rule then mark it as invalid */ -static void -i40e_rss_mark_invalid_rule(struct i40e_pf *pf, - struct i40e_rte_flow_rss_conf *conf) -{ - struct i40e_rss_filter *rss_item; - uint64_t rss_inset; - - /* Clear input set bits before comparing the pctype */ - rss_inset = ~(ETH_RSS_L3_SRC_ONLY | ETH_RSS_L3_DST_ONLY | - ETH_RSS_L4_SRC_ONLY | ETH_RSS_L4_DST_ONLY); - - /* Look up the conflicted rule then mark it as invalid */ - TAILQ_FOREACH(rss_item, &pf->rss_config_list, next) { - if (!rss_item->rss_filter_info.valid) - continue; - - if (conf->conf.queue_num && - rss_item->rss_filter_info.conf.queue_num) - rss_item->rss_filter_info.valid = false; - - if (conf->conf.types && - (rss_item->rss_filter_info.conf.types & - rss_inset) == - (conf->conf.types & rss_inset)) - rss_item->rss_filter_info.valid = false; - - if (conf->conf.func == - RTE_ETH_HASH_FUNCTION_SIMPLE_XOR && - rss_item->rss_filter_info.conf.func == - RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) - rss_item->rss_filter_info.valid = false; - } -} - -/* Configure RSS hash function */ -static int -i40e_rss_config_hash_function(struct i40e_pf *pf, - struct i40e_rte_flow_rss_conf *conf) -{ - struct i40e_hw *hw = I40E_PF_TO_HW(pf); - uint32_t reg, i; - uint64_t mask0; - uint16_t j; - - if (conf->conf.func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) { - reg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL); - if (!(reg & I40E_GLQF_CTL_HTOEP_MASK)) { - PMD_DRV_LOG(DEBUG, "Hash function already set to Simple XOR"); - I40E_WRITE_FLUSH(hw); - i40e_rss_mark_invalid_rule(pf, conf); - - return 0; - } - reg &= ~I40E_GLQF_CTL_HTOEP_MASK; - - i40e_write_global_rx_ctl(hw, I40E_GLQF_CTL, reg); - I40E_WRITE_FLUSH(hw); - i40e_rss_mark_invalid_rule(pf, conf); - } else if (conf->conf.func == - RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) { - mask0 = conf->conf.types & pf->adapter->flow_types_mask; - - i40e_set_symmetric_hash_enable_per_port(hw, 1); - for (i = RTE_ETH_FLOW_UNKNOWN + 1; i < UINT64_BIT; i++) { - if (mask0 & (1UL << i)) - break; - } - - if (i == UINT64_BIT) - return -EINVAL; - - for (j = I40E_FILTER_PCTYPE_INVALID + 1; - j < I40E_FILTER_PCTYPE_MAX; j++) { - if (pf->adapter->pctypes_tbl[i] & (1ULL << j)) - i40e_write_global_rx_ctl(hw, - I40E_GLQF_HSYM(j), - I40E_GLQF_HSYM_SYMH_ENA_MASK); - } - } - - return 0; -} - -/* Enable RSS according to the configuration */ -static int -i40e_rss_enable_hash(struct i40e_pf *pf, - struct i40e_rte_flow_rss_conf *conf) -{ - struct i40e_rte_flow_rss_conf *rss_info = &pf->rss_info; - struct i40e_rte_flow_rss_conf rss_conf; - - if (!(conf->conf.types & pf->adapter->flow_types_mask)) - return -ENOTSUP; - - memset(&rss_conf, 0, sizeof(rss_conf)); - rte_memcpy(&rss_conf, conf, sizeof(rss_conf)); - - /* Configure hash input set */ - if (i40e_rss_conf_hash_inset(pf, conf->conf.types)) - return -EINVAL; - - if (rss_conf.conf.key == NULL || rss_conf.conf.key_len < - (I40E_PFQF_HKEY_MAX_INDEX + 1) * sizeof(uint32_t)) { - /* Random default keys */ - static uint32_t rss_key_default[] = {0x6b793944, - 0x23504cb5, 0x5bea75b6, 0x309f4f12, 0x3dc0a2b8, - 0x024ddcdf, 0x339b8ca0, 0x4c4af64a, 0x34fac605, - 0x55d85839, 0x3a58997d, 0x2ec938e1, 0x66031581}; - - rss_conf.conf.key = (uint8_t *)rss_key_default; - rss_conf.conf.key_len = (I40E_PFQF_HKEY_MAX_INDEX + 1) * - sizeof(uint32_t); - PMD_DRV_LOG(INFO, - "No valid RSS key config for i40e, using default\n"); - } - - rss_conf.conf.types |= rss_info->conf.types; - i40e_rss_hash_set(pf, &rss_conf); - - if (conf->conf.func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) - i40e_rss_config_hash_function(pf, conf); - - i40e_rss_mark_invalid_rule(pf, conf); - - return 0; -} - -/* Configure RSS queue region */ -static int -i40e_rss_config_queue_region(struct i40e_pf *pf, - struct i40e_rte_flow_rss_conf *conf) -{ - struct i40e_hw *hw = I40E_PF_TO_HW(pf); - uint32_t lut = 0; - uint16_t j, num; - uint32_t i; - - /* If both VMDQ and RSS enabled, not all of PF queues are configured. - * It's necessary to calculate the actual PF queues that are configured. - */ - if (pf->dev_data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG) - num = i40e_pf_calc_configured_queues_num(pf); - else - num = pf->dev_data->nb_rx_queues; - - num = RTE_MIN(num, conf->conf.queue_num); - PMD_DRV_LOG(INFO, "Max of contiguous %u PF queues are configured", - num); - - if (num == 0) { - PMD_DRV_LOG(ERR, - "No PF queues are configured to enable RSS for port %u", - pf->dev_data->port_id); - return -ENOTSUP; - } - - /* Fill in redirection table */ - for (i = 0, j = 0; i < hw->func_caps.rss_table_size; i++, j++) { - if (j == num) - j = 0; - lut = (lut << 8) | (conf->conf.queue[j] & ((0x1 << - hw->func_caps.rss_table_entry_width) - 1)); - if ((i & 3) == 3) - I40E_WRITE_REG(hw, I40E_PFQF_HLUT(i >> 2), lut); - } - - i40e_rss_mark_invalid_rule(pf, conf); - - return 0; -} - -/* Configure RSS hash function to default */ -static int -i40e_rss_clear_hash_function(struct i40e_pf *pf, - struct i40e_rte_flow_rss_conf *conf) -{ - struct i40e_hw *hw = I40E_PF_TO_HW(pf); - uint32_t i, reg; - uint64_t mask0; - uint16_t j; - - if (conf->conf.func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) { - reg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL); - if (reg & I40E_GLQF_CTL_HTOEP_MASK) { - PMD_DRV_LOG(DEBUG, - "Hash function already set to Toeplitz"); - I40E_WRITE_FLUSH(hw); - - return 0; - } - reg |= I40E_GLQF_CTL_HTOEP_MASK; - - i40e_write_global_rx_ctl(hw, I40E_GLQF_CTL, reg); - I40E_WRITE_FLUSH(hw); - } else if (conf->conf.func == - RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) { - mask0 = conf->conf.types & pf->adapter->flow_types_mask; - - for (i = RTE_ETH_FLOW_UNKNOWN + 1; i < UINT64_BIT; i++) { - if (mask0 & (1UL << i)) - break; - } - - if (i == UINT64_BIT) - return -EINVAL; - - for (j = I40E_FILTER_PCTYPE_INVALID + 1; - j < I40E_FILTER_PCTYPE_MAX; j++) { - if (pf->adapter->pctypes_tbl[i] & (1ULL << j)) - i40e_write_global_rx_ctl(hw, - I40E_GLQF_HSYM(j), - 0); - } - } - - return 0; -} - -/* Disable RSS hash and configure default input set */ -static int -i40e_rss_disable_hash(struct i40e_pf *pf, - struct i40e_rte_flow_rss_conf *conf) -{ - struct i40e_rte_flow_rss_conf *rss_info = &pf->rss_info; - struct i40e_hw *hw = I40E_PF_TO_HW(pf); - struct i40e_rte_flow_rss_conf rss_conf; - uint32_t i; - - memset(&rss_conf, 0, sizeof(rss_conf)); - rte_memcpy(&rss_conf, conf, sizeof(rss_conf)); - - /* Disable RSS hash */ - rss_conf.conf.types = rss_info->conf.types & ~(conf->conf.types); - i40e_rss_hash_set(pf, &rss_conf); - - for (i = RTE_ETH_FLOW_IPV4; i <= RTE_ETH_FLOW_L2_PAYLOAD; i++) { - if (!(pf->adapter->flow_types_mask & (1ULL << i)) || - !(conf->conf.types & (1ULL << i))) - continue; - - /* Configure default input set */ - struct rte_eth_input_set_conf input_conf = { - .op = RTE_ETH_INPUT_SET_SELECT, - .flow_type = i, - .inset_size = 1, - }; - input_conf.field[0] = RTE_ETH_INPUT_SET_DEFAULT; - i40e_hash_filter_inset_select(hw, &input_conf); - } - - rss_info->conf.types = rss_conf.conf.types; - - i40e_rss_clear_hash_function(pf, conf); - - return 0; -} - -/* Configure RSS queue region to default */ -static int -i40e_rss_clear_queue_region(struct i40e_pf *pf) -{ - struct i40e_hw *hw = I40E_PF_TO_HW(pf); - struct i40e_rte_flow_rss_conf *rss_info = &pf->rss_info; - uint16_t queue[I40E_MAX_Q_PER_TC]; - uint32_t num_rxq, i; - uint32_t lut = 0; - uint16_t j, num; - - num_rxq = RTE_MIN(pf->dev_data->nb_rx_queues, I40E_MAX_Q_PER_TC); - - for (j = 0; j < num_rxq; j++) - queue[j] = j; - - /* If both VMDQ and RSS enabled, not all of PF queues are configured. - * It's necessary to calculate the actual PF queues that are configured. - */ - if (pf->dev_data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG) - num = i40e_pf_calc_configured_queues_num(pf); - else - num = pf->dev_data->nb_rx_queues; - - num = RTE_MIN(num, num_rxq); - PMD_DRV_LOG(INFO, "Max of contiguous %u PF queues are configured", - num); - - if (num == 0) { - PMD_DRV_LOG(ERR, - "No PF queues are configured to enable RSS for port %u", - pf->dev_data->port_id); - return -ENOTSUP; - } - - /* Fill in redirection table */ - for (i = 0, j = 0; i < hw->func_caps.rss_table_size; i++, j++) { - if (j == num) - j = 0; - lut = (lut << 8) | (queue[j] & ((0x1 << - hw->func_caps.rss_table_entry_width) - 1)); - if ((i & 3) == 3) - I40E_WRITE_REG(hw, I40E_PFQF_HLUT(i >> 2), lut); - } - - rss_info->conf.queue_num = 0; - memset(&rss_info->conf.queue, 0, sizeof(uint16_t)); - - return 0; -} - -int -i40e_config_rss_filter(struct i40e_pf *pf, - struct i40e_rte_flow_rss_conf *conf, bool add) -{ - struct i40e_rte_flow_rss_conf *rss_info = &pf->rss_info; - struct rte_flow_action_rss update_conf = rss_info->conf; - int ret = 0; - - if (add) { - if (conf->conf.queue_num) { - /* Configure RSS queue region */ - ret = i40e_rss_config_queue_region(pf, conf); - if (ret) - return ret; - - update_conf.queue_num = conf->conf.queue_num; - update_conf.queue = conf->conf.queue; - } else if (conf->conf.func == - RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) { - /* Configure hash function */ - ret = i40e_rss_config_hash_function(pf, conf); - if (ret) - return ret; - - update_conf.func = conf->conf.func; - } else { - /* Configure hash enable and input set */ - ret = i40e_rss_enable_hash(pf, conf); - if (ret) - return ret; - - update_conf.types |= conf->conf.types; - update_conf.key = conf->conf.key; - update_conf.key_len = conf->conf.key_len; - } - - /* Update RSS info in pf */ - if (i40e_rss_conf_init(rss_info, &update_conf)) - return -EINVAL; - } else { - if (!conf->valid) - return 0; - - if (conf->conf.queue_num) - i40e_rss_clear_queue_region(pf); - else if (conf->conf.func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) - i40e_rss_clear_hash_function(pf, conf); - else - i40e_rss_disable_hash(pf, conf); - } - - return 0; -} - RTE_LOG_REGISTER(i40e_logtype_init, pmd.net.i40e.init, NOTICE); RTE_LOG_REGISTER(i40e_logtype_driver, pmd.net.i40e.driver, NOTICE); #ifdef RTE_LIBRTE_I40E_DEBUG_RX @@ -13763,5 +12462,4 @@ RTE_PMD_REGISTER_PARAM_STRING(net_i40e, ETH_I40E_FLOATING_VEB_ARG "=1" ETH_I40E_FLOATING_VEB_LIST_ARG "=" ETH_I40E_QUEUE_NUM_PER_VF_ARG "=1|2|4|8|16" - ETH_I40E_SUPPORT_MULTI_DRIVER "=1" - ETH_I40E_USE_LATEST_VEC "=0|1"); + ETH_I40E_SUPPORT_MULTI_DRIVER "=1");