Add switch_mode argument for i40e PF to specify the specific FPGA that i40e PF is connected to. i40e PF get link status update via the connected FPGA.
Signed-off-by: Andy Pei <andy....@intel.com> --- Cc: qi.z.zh...@intel.com Cc: jingjing...@intel.com Cc: beilei.x...@intel.com Cc: ferruh.yi...@intel.com Cc: rosen...@intel.com Cc: xiaolong...@intel.com Cc: roy.fan.zh...@intel.com Cc: sta...@dpdk.org v2: * use a more specific subject for this patch. * delete modifications that are not relevant. * free memory allocted by strdup. * delete unnecessary initializations. * name function more precisely. * wrap relevant code to a function to avoid too many levels of block nesting. drivers/net/i40e/i40e_ethdev.c | 121 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 1 deletion(-) diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 3364455..abf95aa 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -44,6 +44,7 @@ #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_SWITCH_MODE_ARG "switch_mode" #define I40E_CLEAR_PXE_WAIT_MS 200 @@ -406,6 +407,7 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf, ETH_I40E_SUPPORT_MULTI_DRIVER, ETH_I40E_QUEUE_NUM_PER_VF_ARG, ETH_I40E_USE_LATEST_VEC, + ETH_I40E_SWITCH_MODE_ARG, NULL}; static const struct rte_pci_id pci_id_i40e_map[] = { @@ -2778,6 +2780,116 @@ void i40e_flex_payload_reg_set_default(struct i40e_hw *hw) } } +static int +i40e_pf_parse_switch_mode(const char *key __rte_unused, + const char *value, void *extra_args) +{ + if (!value || !extra_args) + return -EINVAL; + + *(char **)extra_args = strdup(value); + + if (!*(char **)extra_args) + return -ENOMEM; + + return 0; +} + +static struct rte_eth_dev * +i40e_eth_dev_get_by_switch_mode_name(const char *cfg_str) +{ + char switch_name[RTE_ETH_NAME_MAX_LEN]; + char port_name[RTE_ETH_NAME_MAX_LEN]; + char switch_ethdev_name[RTE_ETH_NAME_MAX_LEN]; + uint16_t port_id; + const char *p_src; + char *p_dst; + int ret; + + /* An example of cfg_str is "IPN3KE_0@b3:00.0_0" */ + if (!strncmp(cfg_str, "IPN3KE", strlen("IPN3KE"))) { + p_src = cfg_str; + PMD_DRV_LOG(DEBUG, "cfg_str is %s", cfg_str); + + /* move over "IPN3KE" */ + while ((*p_src != '_') && (*p_src)) + p_src++; + + /* move over the first underline */ + p_src++; + + p_dst = switch_name; + while ((*p_src != '_') && (*p_src)) { + if (*p_src == '@') { + *p_dst++ = '|'; + p_src++; + } else + *p_dst++ = *p_src++; + } + *p_dst = 0; + PMD_DRV_LOG(DEBUG, "switch_name is %s", switch_name); + + /* move over the second underline */ + p_src++; + + p_dst = port_name; + while (*p_src) + *p_dst++ = *p_src++; + *p_dst = 0; + PMD_DRV_LOG(DEBUG, "port_name is %s", port_name); + + snprintf(switch_ethdev_name, sizeof(switch_ethdev_name), + "net_%s_representor_%s", switch_name, port_name); + PMD_DRV_LOG(DEBUG, "switch_ethdev_name is %s", + switch_ethdev_name); + + ret = rte_eth_dev_get_port_by_name(switch_ethdev_name, + &port_id); + if (ret) + return NULL; + else + return &rte_eth_devices[port_id]; + } else + return NULL; +} + +static void +i40e_pf_linkstatus_get_from_switch_ethdev +(struct rte_devargs *devargs, struct rte_eth_link *link) +{ + struct rte_kvargs *kvlist = NULL; + struct rte_eth_dev *switch_ethdev; + char *switch_cfg_str = NULL; + + kvlist = rte_kvargs_parse(devargs->args, valid_keys); + if (kvlist) { + if (rte_kvargs_count(kvlist, ETH_I40E_SWITCH_MODE_ARG) == 1) { + if (!rte_kvargs_process(kvlist, + ETH_I40E_SWITCH_MODE_ARG, + &i40e_pf_parse_switch_mode, &switch_cfg_str)) { + switch_ethdev = + i40e_eth_dev_get_by_switch_mode_name( + switch_cfg_str); + + rte_free(switch_cfg_str); + + if (switch_ethdev) { + rte_eth_linkstatus_get(switch_ethdev, + link); + } else { + link->link_autoneg = + ETH_LINK_SPEED_FIXED; + link->link_duplex = + ETH_LINK_FULL_DUPLEX; + link->link_speed = ETH_SPEED_NUM_25G; + link->link_status = 0; + } + } + } + rte_kvargs_free(kvlist); + } +} + int i40e_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete) @@ -2785,6 +2897,8 @@ void i40e_flex_payload_reg_set_default(struct i40e_hw *hw) struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_link link; bool enable_lse = dev->data->dev_conf.intr_conf.lsc ? true : false; + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_devargs *devargs; int ret; memset(&link, 0, sizeof(link)); @@ -2799,6 +2913,10 @@ void i40e_flex_payload_reg_set_default(struct i40e_hw *hw) else update_link_aq(hw, &link, enable_lse, wait_to_complete); + devargs = pci_dev->device.devargs; + if (devargs) + i40e_pf_linkstatus_get_from_switch_ethdev(devargs, &link); + ret = rte_eth_linkstatus_set(dev, &link); i40e_notify_all_vfs_link_status(dev); @@ -12772,4 +12890,5 @@ struct i40e_customized_pctype* ETH_I40E_FLOATING_VEB_LIST_ARG "=<string>" 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_USE_LATEST_VEC "=0|1" + ETH_I40E_SWITCH_MODE_ARG "=IPN3KE"); -- 1.8.3.1