@@ -664,7 +664,7 @@ void ice_lag_move_new_vf_nodes(struct ice_vf *vf)
* @oldport: lport of previous interface
* @newport: lport of destination interface
*/
-static void ice_lag_move_vf_nodes(struct ice_lag *lag, u8 oldport, u8 newport)
+void ice_lag_move_vf_nodes(struct ice_lag *lag, u8 oldport, u8 newport)
{
struct ice_pf *pf;
int i;
@@ -65,4 +65,5 @@ int ice_init_lag(struct ice_pf *pf);
void ice_deinit_lag(struct ice_pf *pf);
void ice_lag_rebuild(struct ice_pf *pf);
bool ice_lag_is_switchdev_running(struct ice_pf *pf);
+void ice_lag_move_vf_nodes(struct ice_lag *lag, u8 oldport, u8 newport);
#endif /* _ICE_LAG_H_ */
@@ -828,13 +828,19 @@ static void ice_notify_vf_reset(struct ice_vf *vf)
*/
int ice_reset_vf(struct ice_vf *vf, u32 flags)
{
+ struct ice_lag_netdev_list ndlist;
struct ice_pf *pf = vf->pf;
+ struct list_head *tmp, *n;
+ struct ice_lag *lag;
struct ice_vsi *vsi;
struct device *dev;
+ u8 act_pt, pri_pt;
int err = 0;
bool rsd;
dev = ice_pf_to_dev(pf);
+ act_pt = ICE_LAG_INVALID_PORT;
+ pri_pt = pf->hw.port_info->lport;
if (flags & ICE_VF_RESET_NOTIFY)
ice_notify_vf_reset(vf);
@@ -845,6 +851,33 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
return 0;
}
+ lag = pf->lag;
+ mutex_lock(&pf->lag_mutex);
+ if (lag && lag->bonded && lag->primary) {
+ act_pt = lag->active_port;
+ if (act_pt != pri_pt && act_pt != ICE_LAG_INVALID_PORT &&
+ lag->upper_netdev) {
+ struct ice_lag_netdev_list *nl;
+ struct net_device *tmp_nd;
+
+ INIT_LIST_HEAD(&ndlist.node);
+ rcu_read_lock();
+ for_each_netdev_in_bond_rcu(lag->upper_netdev, tmp_nd) {
+ nl = kzalloc(sizeof(*nl), GFP_KERNEL);
+ if (!nl)
+ break;
+
+ nl->netdev = tmp_nd;
+ list_add(&nl->node, &ndlist.node);
+ }
+ rcu_read_unlock();
+ lag->netdev_head = &ndlist.node;
+ ice_lag_move_vf_nodes(lag, act_pt, pri_pt);
+ } else {
+ act_pt = ICE_LAG_INVALID_PORT;
+ }
+ }
+
if (flags & ICE_VF_RESET_LOCK)
mutex_lock(&vf->cfg_lock);
else
@@ -937,6 +970,20 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
if (flags & ICE_VF_RESET_LOCK)
mutex_unlock(&vf->cfg_lock);
+ if (lag && lag->bonded && lag->primary &&
+ act_pt != ICE_LAG_INVALID_PORT) {
+ ice_lag_move_vf_nodes(lag, pri_pt, act_pt);
+ list_for_each_safe(tmp, n, &ndlist.node) {
+ struct ice_lag_netdev_list *entry;
+
+ entry = list_entry(tmp, struct ice_lag_netdev_list, node);
+ list_del(&entry->node);
+ kfree(entry);
+ }
+ lag->netdev_head = NULL;
+ }
+ mutex_unlock(&pf->lag_mutex);
+
return err;
}
There is an error interface has the following conditions: - PF is in an aggregate (bond) - PF has VFs created on it - bond is in a state where it is failed-over to the secondary interface - A VF reset is issued on one or more of those VFs The issue is generated by the originating PF trying to tear down the VF resources and recreate them for the reset. Since the bond is failed over to the secondary interface the queue contexts are in a modified state. To fix this issue, have the originating interface reclaim its resources prior to the tear-down and rebuild for the reset. Then after the reset is complete, move the resources back to the active interface. Signed-off-by: Dave Ertman <david.m.ertman@intel.com> --- drivers/net/ethernet/intel/ice/ice_lag.c | 2 +- drivers/net/ethernet/intel/ice/ice_lag.h | 1 + drivers/net/ethernet/intel/ice/ice_vf_lib.c | 47 +++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-)