Commit c54d209c authored by Brett Creeley's avatar Brett Creeley Committed by Jeff Kirsher

ice: Wait for VF to be reset/ready before configuration

The configuration/command below is failing when the VF in the xml
file is already bound to the host iavf driver.

pci_0000_af_0_0.xml:

<interface type='hostdev' managed='yes'>
<source>
<address type='pci' domain='0x0000' bus='0xaf' slot='0x0' function='0x0'/>
</source>
<mac address='00:de:ad:00:11:01'/>
</interface>

> virsh attach-device domain_name pci_0000_af_0_0.xml
error: Failed to attach device from pci_0000_af_0_0.xml
error: Cannot set interface MAC/vlanid to 00:de:ad:00:11:01/0 for
	ifname ens1f1 vf 0: Device or resource busy

This is failing because the VF has not been completely removed/reset
after being unbound (via the virsh command above) from the host iavf
driver and ice_set_vf_mac() checks if the VF is disabled before waiting
for the reset to finish.

Fix this by waiting for the VF remove/reset process to happen before
checking if the VF is disabled. Also, since many functions for VF
administration on the PF were more or less calling the same 3 functions
(ice_wait_on_vf_reset(), ice_is_vf_disabled(), and ice_check_vf_init())
move these into the helper function ice_check_vf_ready_for_cfg(). Then
call this function in any flow that attempts to configure/query a VF
from the PF.

Lastly, increase the maximum wait time in ice_wait_on_vf_reset() to
800ms, and modify/add the #define(s) that determine the wait time.
This was done for robustness because in rare/stress cases VF removal can
take a max of ~800ms and previously the wait was a max of ~300ms.
Signed-off-by: default avatarBrett Creeley <brett.creeley@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 8a55c08d
...@@ -1873,6 +1873,48 @@ static int ice_vc_config_rss_lut(struct ice_vf *vf, u8 *msg) ...@@ -1873,6 +1873,48 @@ static int ice_vc_config_rss_lut(struct ice_vf *vf, u8 *msg)
NULL, 0); NULL, 0);
} }
/**
* ice_wait_on_vf_reset - poll to make sure a given VF is ready after reset
* @vf: The VF being resseting
*
* The max poll time is about ~800ms, which is about the maximum time it takes
* for a VF to be reset and/or a VF driver to be removed.
*/
static void ice_wait_on_vf_reset(struct ice_vf *vf)
{
int i;
for (i = 0; i < ICE_MAX_VF_RESET_TRIES; i++) {
if (test_bit(ICE_VF_STATE_INIT, vf->vf_states))
break;
msleep(ICE_MAX_VF_RESET_SLEEP_MS);
}
}
/**
* ice_check_vf_ready_for_cfg - check if VF is ready to be configured/queried
* @vf: VF to check if it's ready to be configured/queried
*
* The purpose of this function is to make sure the VF is not in reset, not
* disabled, and initialized so it can be configured and/or queried by a host
* administrator.
*/
static int ice_check_vf_ready_for_cfg(struct ice_vf *vf)
{
struct ice_pf *pf;
ice_wait_on_vf_reset(vf);
if (ice_is_vf_disabled(vf))
return -EINVAL;
pf = vf->pf;
if (ice_check_vf_init(pf, vf))
return -EBUSY;
return 0;
}
/** /**
* ice_set_vf_spoofchk * ice_set_vf_spoofchk
* @netdev: network interface device structure * @netdev: network interface device structure
...@@ -1890,16 +1932,16 @@ int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena) ...@@ -1890,16 +1932,16 @@ int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena)
enum ice_status status; enum ice_status status;
struct device *dev; struct device *dev;
struct ice_vf *vf; struct ice_vf *vf;
int ret = 0; int ret;
dev = ice_pf_to_dev(pf); dev = ice_pf_to_dev(pf);
if (ice_validate_vf_id(pf, vf_id)) if (ice_validate_vf_id(pf, vf_id))
return -EINVAL; return -EINVAL;
vf = &pf->vf[vf_id]; vf = &pf->vf[vf_id];
ret = ice_check_vf_ready_for_cfg(vf);
if (ice_check_vf_init(pf, vf)) if (ret)
return -EBUSY; return ret;
vf_vsi = pf->vsi[vf->lan_vsi_idx]; vf_vsi = pf->vsi[vf->lan_vsi_idx];
if (!vf_vsi) { if (!vf_vsi) {
...@@ -2696,7 +2738,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, ...@@ -2696,7 +2738,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
struct ice_vsi *vsi; struct ice_vsi *vsi;
struct device *dev; struct device *dev;
struct ice_vf *vf; struct ice_vf *vf;
int ret = 0; int ret;
dev = ice_pf_to_dev(pf); dev = ice_pf_to_dev(pf);
if (ice_validate_vf_id(pf, vf_id)) if (ice_validate_vf_id(pf, vf_id))
...@@ -2714,13 +2756,15 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, ...@@ -2714,13 +2756,15 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
vf = &pf->vf[vf_id]; vf = &pf->vf[vf_id];
vsi = pf->vsi[vf->lan_vsi_idx]; vsi = pf->vsi[vf->lan_vsi_idx];
if (ice_check_vf_init(pf, vf))
return -EBUSY; ret = ice_check_vf_ready_for_cfg(vf);
if (ret)
return ret;
if (le16_to_cpu(vsi->info.pvid) == vlanprio) { if (le16_to_cpu(vsi->info.pvid) == vlanprio) {
/* duplicate request, so just return success */ /* duplicate request, so just return success */
dev_dbg(dev, "Duplicate pvid %d request\n", vlanprio); dev_dbg(dev, "Duplicate pvid %d request\n", vlanprio);
return ret; return 0;
} }
/* If PVID, then remove all filters on the old VLAN */ /* If PVID, then remove all filters on the old VLAN */
...@@ -2731,7 +2775,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, ...@@ -2731,7 +2775,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
if (vlan_id || qos) { if (vlan_id || qos) {
ret = ice_vsi_manage_pvid(vsi, vlanprio, true); ret = ice_vsi_manage_pvid(vsi, vlanprio, true);
if (ret) if (ret)
goto error_set_pvid; return ret;
} else { } else {
ice_vsi_manage_pvid(vsi, 0, false); ice_vsi_manage_pvid(vsi, 0, false);
vsi->info.pvid = 0; vsi->info.pvid = 0;
...@@ -2744,7 +2788,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, ...@@ -2744,7 +2788,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
/* add new VLAN filter for each MAC */ /* add new VLAN filter for each MAC */
ret = ice_vsi_add_vlan(vsi, vlan_id); ret = ice_vsi_add_vlan(vsi, vlan_id);
if (ret) if (ret)
goto error_set_pvid; return ret;
} }
/* The Port VLAN needs to be saved across resets the same as the /* The Port VLAN needs to be saved across resets the same as the
...@@ -2752,8 +2796,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, ...@@ -2752,8 +2796,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
*/ */
vf->port_vlan_id = le16_to_cpu(vsi->info.pvid); vf->port_vlan_id = le16_to_cpu(vsi->info.pvid);
error_set_pvid: return 0;
return ret;
} }
/** /**
...@@ -3236,23 +3279,6 @@ ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi) ...@@ -3236,23 +3279,6 @@ ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi)
return 0; return 0;
} }
/**
* ice_wait_on_vf_reset
* @vf: The VF being resseting
*
* Poll to make sure a given VF is ready after reset
*/
static void ice_wait_on_vf_reset(struct ice_vf *vf)
{
int i;
for (i = 0; i < ICE_MAX_VF_RESET_WAIT; i++) {
if (test_bit(ICE_VF_STATE_INIT, vf->vf_states))
break;
msleep(20);
}
}
/** /**
* ice_set_vf_mac * ice_set_vf_mac
* @netdev: network interface device structure * @netdev: network interface device structure
...@@ -3265,29 +3291,21 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) ...@@ -3265,29 +3291,21 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
{ {
struct ice_pf *pf = ice_netdev_to_pf(netdev); struct ice_pf *pf = ice_netdev_to_pf(netdev);
struct ice_vf *vf; struct ice_vf *vf;
int ret = 0; int ret;
if (ice_validate_vf_id(pf, vf_id)) if (ice_validate_vf_id(pf, vf_id))
return -EINVAL; return -EINVAL;
vf = &pf->vf[vf_id];
/* Don't set MAC on disabled VF */
if (ice_is_vf_disabled(vf))
return -EINVAL;
/* In case VF is in reset mode, wait until it is completed. Depending
* on factors like queue disabling routine, this could take ~250ms
*/
ice_wait_on_vf_reset(vf);
if (ice_check_vf_init(pf, vf))
return -EBUSY;
if (is_zero_ether_addr(mac) || is_multicast_ether_addr(mac)) { if (is_zero_ether_addr(mac) || is_multicast_ether_addr(mac)) {
netdev_err(netdev, "%pM not a valid unicast address\n", mac); netdev_err(netdev, "%pM not a valid unicast address\n", mac);
return -EINVAL; return -EINVAL;
} }
vf = &pf->vf[vf_id];
ret = ice_check_vf_ready_for_cfg(vf);
if (ret)
return ret;
/* copy MAC into dflt_lan_addr and trigger a VF reset. The reset /* copy MAC into dflt_lan_addr and trigger a VF reset. The reset
* flow will use the updated dflt_lan_addr and add a MAC filter * flow will use the updated dflt_lan_addr and add a MAC filter
* using ice_add_mac. Also set pf_set_mac to indicate that the PF has * using ice_add_mac. Also set pf_set_mac to indicate that the PF has
...@@ -3299,7 +3317,7 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) ...@@ -3299,7 +3317,7 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
vf_id, mac); vf_id, mac);
ice_vc_reset_vf(vf); ice_vc_reset_vf(vf);
return ret; return 0;
} }
/** /**
...@@ -3314,22 +3332,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted) ...@@ -3314,22 +3332,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
{ {
struct ice_pf *pf = ice_netdev_to_pf(netdev); struct ice_pf *pf = ice_netdev_to_pf(netdev);
struct ice_vf *vf; struct ice_vf *vf;
int ret;
if (ice_validate_vf_id(pf, vf_id)) if (ice_validate_vf_id(pf, vf_id))
return -EINVAL; return -EINVAL;
vf = &pf->vf[vf_id]; vf = &pf->vf[vf_id];
/* Don't set Trusted Mode on disabled VF */ ret = ice_check_vf_ready_for_cfg(vf);
if (ice_is_vf_disabled(vf)) if (ret)
return -EINVAL; return ret;
/* In case VF is in reset mode, wait until it is completed. Depending
* on factors like queue disabling routine, this could take ~250ms
*/
ice_wait_on_vf_reset(vf);
if (ice_check_vf_init(pf, vf))
return -EBUSY;
/* Check if already trusted */ /* Check if already trusted */
if (trusted == vf->trusted) if (trusted == vf->trusted)
...@@ -3355,13 +3366,15 @@ int ice_set_vf_link_state(struct net_device *netdev, int vf_id, int link_state) ...@@ -3355,13 +3366,15 @@ int ice_set_vf_link_state(struct net_device *netdev, int vf_id, int link_state)
{ {
struct ice_pf *pf = ice_netdev_to_pf(netdev); struct ice_pf *pf = ice_netdev_to_pf(netdev);
struct ice_vf *vf; struct ice_vf *vf;
int ret;
if (ice_validate_vf_id(pf, vf_id)) if (ice_validate_vf_id(pf, vf_id))
return -EINVAL; return -EINVAL;
vf = &pf->vf[vf_id]; vf = &pf->vf[vf_id];
if (ice_check_vf_init(pf, vf)) ret = ice_check_vf_ready_for_cfg(vf);
return -EBUSY; if (ret)
return ret;
switch (link_state) { switch (link_state) {
case IFLA_VF_LINK_STATE_AUTO: case IFLA_VF_LINK_STATE_AUTO:
...@@ -3397,14 +3410,15 @@ int ice_get_vf_stats(struct net_device *netdev, int vf_id, ...@@ -3397,14 +3410,15 @@ int ice_get_vf_stats(struct net_device *netdev, int vf_id,
struct ice_eth_stats *stats; struct ice_eth_stats *stats;
struct ice_vsi *vsi; struct ice_vsi *vsi;
struct ice_vf *vf; struct ice_vf *vf;
int ret;
if (ice_validate_vf_id(pf, vf_id)) if (ice_validate_vf_id(pf, vf_id))
return -EINVAL; return -EINVAL;
vf = &pf->vf[vf_id]; vf = &pf->vf[vf_id];
ret = ice_check_vf_ready_for_cfg(vf);
if (ice_check_vf_init(pf, vf)) if (ret)
return -EBUSY; return ret;
vsi = pf->vsi[vf->lan_vsi_idx]; vsi = pf->vsi[vf->lan_vsi_idx];
if (!vsi) if (!vsi)
......
...@@ -38,7 +38,8 @@ ...@@ -38,7 +38,8 @@
#define ICE_MAX_POLICY_INTR_PER_VF 33 #define ICE_MAX_POLICY_INTR_PER_VF 33
#define ICE_MIN_INTR_PER_VF (ICE_MIN_QS_PER_VF + 1) #define ICE_MIN_INTR_PER_VF (ICE_MIN_QS_PER_VF + 1)
#define ICE_DFLT_INTR_PER_VF (ICE_DFLT_QS_PER_VF + 1) #define ICE_DFLT_INTR_PER_VF (ICE_DFLT_QS_PER_VF + 1)
#define ICE_MAX_VF_RESET_WAIT 15 #define ICE_MAX_VF_RESET_TRIES 40
#define ICE_MAX_VF_RESET_SLEEP_MS 20
#define ice_for_each_vf(pf, i) \ #define ice_for_each_vf(pf, i) \
for ((i) = 0; (i) < (pf)->num_alloc_vfs; (i)++) for ((i) = 0; (i) < (pf)->num_alloc_vfs; (i)++)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment