diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 990a60889eef..921a97d5479e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -829,10 +829,14 @@ static ssize_t i40e_dbg_command_write(struct file *filp, } else if (strncmp(cmd_buf, "add relay", 9) == 0) { struct i40e_veb *veb; + u8 enabled_tc = 0x1; int uplink_seid; cnt = sscanf(&cmd_buf[9], "%i %i", &uplink_seid, &vsi_seid); - if (cnt != 2) { + if (cnt == 0) { + uplink_seid = 0; + vsi_seid = 0; + } else if (cnt != 2) { dev_info(&pf->pdev->dev, "add relay: bad command string, cnt=%d\n", cnt); @@ -844,23 +848,28 @@ static ssize_t i40e_dbg_command_write(struct file *filp, goto command_write_done; } - vsi = i40e_dbg_find_vsi(pf, vsi_seid); - if (!vsi) { - dev_info(&pf->pdev->dev, - "add relay: VSI %d not found\n", vsi_seid); - goto command_write_done; - } - veb = i40e_pf_get_veb_by_seid(pf, uplink_seid); if (!veb && uplink_seid != 0 && uplink_seid != pf->mac_seid) { dev_info(&pf->pdev->dev, "add relay: relay uplink %d not found\n", uplink_seid); goto command_write_done; + } else if (uplink_seid) { + vsi = i40e_pf_get_vsi_by_seid(pf, vsi_seid); + if (!vsi) { + dev_info(&pf->pdev->dev, + "add relay: VSI %d not found\n", + vsi_seid); + goto command_write_done; + } + enabled_tc = vsi->tc_config.enabled_tc; + } else if (vsi_seid) { + dev_info(&pf->pdev->dev, + "add relay: VSI must be 0 for floating relay\n"); + goto command_write_done; } - veb = i40e_veb_setup(pf, 0, uplink_seid, vsi_seid, - vsi->tc_config.enabled_tc); + veb = i40e_veb_setup(pf, 0, uplink_seid, vsi_seid, enabled_tc); if (veb) dev_info(&pf->pdev->dev, "added relay %d\n", veb->seid); else diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index e495a212d076..31d1b1ff07b0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -10372,41 +10372,48 @@ static int i40e_reconstitute_veb(struct i40e_veb *veb) struct i40e_vsi *vsi; int v, ret; - /* build VSI that owns this VEB, temporarily attached to base VEB */ - i40e_pf_for_each_vsi(pf, v, vsi) - if (vsi->veb_idx == veb->idx && - vsi->flags & I40E_VSI_FLAG_VEB_OWNER) { - ctl_vsi = vsi; - break; - } + if (veb->uplink_seid) { + /* Look for VSI that owns this VEB, temporarily attached to base VEB */ + i40e_pf_for_each_vsi(pf, v, vsi) + if (vsi->veb_idx == veb->idx && + vsi->flags & I40E_VSI_FLAG_VEB_OWNER) { + ctl_vsi = vsi; + break; + } - if (!ctl_vsi) { - dev_info(&pf->pdev->dev, - "missing owner VSI for veb_idx %d\n", veb->idx); - ret = -ENOENT; - goto end_reconstitute; + if (!ctl_vsi) { + dev_info(&pf->pdev->dev, + "missing owner VSI for veb_idx %d\n", + veb->idx); + ret = -ENOENT; + goto end_reconstitute; + } + if (ctl_vsi != pf->vsi[pf->lan_vsi]) + ctl_vsi->uplink_seid = + pf->vsi[pf->lan_vsi]->uplink_seid; + + ret = i40e_add_vsi(ctl_vsi); + if (ret) { + dev_info(&pf->pdev->dev, + "rebuild of veb_idx %d owner VSI failed: %d\n", + veb->idx, ret); + goto end_reconstitute; + } + i40e_vsi_reset_stats(ctl_vsi); } - if (ctl_vsi != pf->vsi[pf->lan_vsi]) - ctl_vsi->uplink_seid = pf->vsi[pf->lan_vsi]->uplink_seid; - ret = i40e_add_vsi(ctl_vsi); - if (ret) { - dev_info(&pf->pdev->dev, - "rebuild of veb_idx %d owner VSI failed: %d\n", - veb->idx, ret); - goto end_reconstitute; - } - i40e_vsi_reset_stats(ctl_vsi); /* create the VEB in the switch and move the VSI onto the VEB */ ret = i40e_add_veb(veb, ctl_vsi); if (ret) goto end_reconstitute; - if (test_bit(I40E_FLAG_VEB_MODE_ENA, pf->flags)) - veb->bridge_mode = BRIDGE_MODE_VEB; - else - veb->bridge_mode = BRIDGE_MODE_VEPA; - i40e_config_bridge_mode(veb); + if (veb->uplink_seid) { + if (test_bit(I40E_FLAG_VEB_MODE_ENA, pf->flags)) + veb->bridge_mode = BRIDGE_MODE_VEB; + else + veb->bridge_mode = BRIDGE_MODE_VEPA; + i40e_config_bridge_mode(veb); + } /* create the remaining VSIs attached to this VEB */ i40e_pf_for_each_vsi(pf, v, vsi) { @@ -14702,29 +14709,29 @@ void i40e_veb_release(struct i40e_veb *veb) /* find the remaining VSI and check for extras */ i40e_pf_for_each_vsi(pf, i, vsi_it) if (vsi_it->uplink_seid == veb->seid) { - vsi = vsi_it; + if (vsi_it->flags & I40E_VSI_FLAG_VEB_OWNER) + vsi = vsi_it; n++; } - if (n != 1) { + /* Floating VEB has to be empty and regular one must have + * single owner VSI. + */ + if ((veb->uplink_seid && n != 1) || (!veb->uplink_seid && n != 0)) { dev_info(&pf->pdev->dev, "can't remove VEB %d with %d VSIs left\n", veb->seid, n); return; } - /* move the remaining VSI to uplink veb */ - vsi->flags &= ~I40E_VSI_FLAG_VEB_OWNER; + /* For regular VEB move the owner VSI to uplink VEB */ if (veb->uplink_seid) { + vsi->flags &= ~I40E_VSI_FLAG_VEB_OWNER; vsi->uplink_seid = veb->uplink_seid; if (veb->uplink_seid == pf->mac_seid) vsi->veb_idx = I40E_NO_VEB; else vsi->veb_idx = veb->veb_idx; - } else { - /* floating VEB */ - vsi->uplink_seid = pf->vsi[pf->lan_vsi]->uplink_seid; - vsi->veb_idx = pf->vsi[pf->lan_vsi]->veb_idx; } i40e_aq_delete_element(&pf->hw, veb->seid, NULL); @@ -14742,8 +14749,8 @@ static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi) bool enable_stats = !!test_bit(I40E_FLAG_VEB_STATS_ENA, pf->flags); int ret; - ret = i40e_aq_add_veb(&pf->hw, veb->uplink_seid, vsi->seid, - veb->enabled_tc, false, + ret = i40e_aq_add_veb(&pf->hw, veb->uplink_seid, vsi ? vsi->seid : 0, + veb->enabled_tc, vsi ? false : true, &veb->seid, enable_stats, NULL); /* get a VEB from the hardware */ @@ -14775,9 +14782,11 @@ static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi) return -ENOENT; } - vsi->uplink_seid = veb->seid; - vsi->veb_idx = veb->idx; - vsi->flags |= I40E_VSI_FLAG_VEB_OWNER; + if (vsi) { + vsi->uplink_seid = veb->seid; + vsi->veb_idx = veb->idx; + vsi->flags |= I40E_VSI_FLAG_VEB_OWNER; + } return 0; }