diff mbox series

[iwl-next] ice: Fix VF Reset when interface in a failed over aggregate

Message ID 20231024183714.1680327-1-david.m.ertman@intel.com
State Changes Requested
Delegated to: Anthony Nguyen
Headers show
Series [iwl-next] ice: Fix VF Reset when interface in a failed over aggregate | expand

Commit Message

Dave Ertman Oct. 24, 2023, 6:37 p.m. UTC
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(-)

Comments

Buvaneswaran, Sujai Oct. 30, 2023, 7:51 a.m. UTC | #1
> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of
> Dave Ertman
> Sent: Wednesday, October 25, 2023 12:07 AM
> To: intel-wired-lan@lists.osuosl.org
> Subject: [Intel-wired-lan] [PATCH iwl-next] ice: Fix VF Reset when interface in
> a failed over aggregate
> 
> 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(-)
> 
We are observing traffic failure while testing this patch. VF to client and VF-VF ping stops working when VF reset is done using below command after LAG failover.

echo 1 > /sys/bus/pci/devices/0000\:0a\:01.0/reset
diff mbox series

Patch

diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c
index b980f89dc892..9b915c0da06a 100644
--- a/drivers/net/ethernet/intel/ice/ice_lag.c
+++ b/drivers/net/ethernet/intel/ice/ice_lag.c
@@ -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;
diff --git a/drivers/net/ethernet/intel/ice/ice_lag.h b/drivers/net/ethernet/intel/ice/ice_lag.h
index 9557e8605a07..b5e920c03ceb 100644
--- a/drivers/net/ethernet/intel/ice/ice_lag.h
+++ b/drivers/net/ethernet/intel/ice/ice_lag.h
@@ -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_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
index aca1f2ea5034..8d97acacc1b2 100644
--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
@@ -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;
 }