Skip to content

Commit 9f74a3d

Browse files
dmertmankuba-moo
authored andcommitted
ice: Fix VF Reset paths when interface in a failed over aggregate
There is an error when an 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 rebuild or reconfigure the VF resources. 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 or reconfigure. Then after the process is complete, move the resources back to the currently active interface. There are multiple paths that can be used depending on what triggered the event, so create a helper function to move the queues and use paired calls to the helper (back to origin, process, then move back to active interface) under the same lag_mutex lock. Fixes: 1e0f988 ("ice: Flesh out implementation of support for SRIOV on bonded interface") Signed-off-by: Dave Ertman <david.m.ertman@intel.com> Tested-by: Sujai Buvaneswaran <sujai.buvaneswaran@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com> Link: https://lore.kernel.org/r/20231127212340.1137657-1-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 300fbb2 commit 9f74a3d

File tree

4 files changed

+118
-50
lines changed

4 files changed

+118
-50
lines changed

drivers/net/ethernet/intel/ice/ice_lag.c

Lines changed: 72 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,50 @@ ice_lag_move_vf_node_tc(struct ice_lag *lag, u8 oldport, u8 newport,
569569
dev_dbg(dev, "Problem restarting traffic for LAG node move\n");
570570
}
571571

572+
/**
573+
* ice_lag_build_netdev_list - populate the lag struct's netdev list
574+
* @lag: local lag struct
575+
* @ndlist: pointer to netdev list to populate
576+
*/
577+
static void ice_lag_build_netdev_list(struct ice_lag *lag,
578+
struct ice_lag_netdev_list *ndlist)
579+
{
580+
struct ice_lag_netdev_list *nl;
581+
struct net_device *tmp_nd;
582+
583+
INIT_LIST_HEAD(&ndlist->node);
584+
rcu_read_lock();
585+
for_each_netdev_in_bond_rcu(lag->upper_netdev, tmp_nd) {
586+
nl = kzalloc(sizeof(*nl), GFP_ATOMIC);
587+
if (!nl)
588+
break;
589+
590+
nl->netdev = tmp_nd;
591+
list_add(&nl->node, &ndlist->node);
592+
}
593+
rcu_read_unlock();
594+
lag->netdev_head = &ndlist->node;
595+
}
596+
597+
/**
598+
* ice_lag_destroy_netdev_list - free lag struct's netdev list
599+
* @lag: pointer to local lag struct
600+
* @ndlist: pointer to lag struct netdev list
601+
*/
602+
static void ice_lag_destroy_netdev_list(struct ice_lag *lag,
603+
struct ice_lag_netdev_list *ndlist)
604+
{
605+
struct ice_lag_netdev_list *entry, *n;
606+
607+
rcu_read_lock();
608+
list_for_each_entry_safe(entry, n, &ndlist->node, node) {
609+
list_del(&entry->node);
610+
kfree(entry);
611+
}
612+
rcu_read_unlock();
613+
lag->netdev_head = NULL;
614+
}
615+
572616
/**
573617
* ice_lag_move_single_vf_nodes - Move Tx scheduling nodes for single VF
574618
* @lag: primary interface LAG struct
@@ -597,7 +641,6 @@ ice_lag_move_single_vf_nodes(struct ice_lag *lag, u8 oldport, u8 newport,
597641
void ice_lag_move_new_vf_nodes(struct ice_vf *vf)
598642
{
599643
struct ice_lag_netdev_list ndlist;
600-
struct list_head *tmp, *n;
601644
u8 pri_port, act_port;
602645
struct ice_lag *lag;
603646
struct ice_vsi *vsi;
@@ -621,38 +664,15 @@ void ice_lag_move_new_vf_nodes(struct ice_vf *vf)
621664
pri_port = pf->hw.port_info->lport;
622665
act_port = lag->active_port;
623666

624-
if (lag->upper_netdev) {
625-
struct ice_lag_netdev_list *nl;
626-
struct net_device *tmp_nd;
627-
628-
INIT_LIST_HEAD(&ndlist.node);
629-
rcu_read_lock();
630-
for_each_netdev_in_bond_rcu(lag->upper_netdev, tmp_nd) {
631-
nl = kzalloc(sizeof(*nl), GFP_ATOMIC);
632-
if (!nl)
633-
break;
634-
635-
nl->netdev = tmp_nd;
636-
list_add(&nl->node, &ndlist.node);
637-
}
638-
rcu_read_unlock();
639-
}
640-
641-
lag->netdev_head = &ndlist.node;
667+
if (lag->upper_netdev)
668+
ice_lag_build_netdev_list(lag, &ndlist);
642669

643670
if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG) &&
644671
lag->bonded && lag->primary && pri_port != act_port &&
645672
!list_empty(lag->netdev_head))
646673
ice_lag_move_single_vf_nodes(lag, pri_port, act_port, vsi->idx);
647674

648-
list_for_each_safe(tmp, n, &ndlist.node) {
649-
struct ice_lag_netdev_list *entry;
650-
651-
entry = list_entry(tmp, struct ice_lag_netdev_list, node);
652-
list_del(&entry->node);
653-
kfree(entry);
654-
}
655-
lag->netdev_head = NULL;
675+
ice_lag_destroy_netdev_list(lag, &ndlist);
656676

657677
new_vf_unlock:
658678
mutex_unlock(&pf->lag_mutex);
@@ -679,6 +699,29 @@ static void ice_lag_move_vf_nodes(struct ice_lag *lag, u8 oldport, u8 newport)
679699
ice_lag_move_single_vf_nodes(lag, oldport, newport, i);
680700
}
681701

702+
/**
703+
* ice_lag_move_vf_nodes_cfg - move vf nodes outside LAG netdev event context
704+
* @lag: local lag struct
705+
* @src_prt: lport value for source port
706+
* @dst_prt: lport value for destination port
707+
*
708+
* This function is used to move nodes during an out-of-netdev-event situation,
709+
* primarily when the driver needs to reconfigure or recreate resources.
710+
*
711+
* Must be called while holding the lag_mutex to avoid lag events from
712+
* processing while out-of-sync moves are happening. Also, paired moves,
713+
* such as used in a reset flow, should both be called under the same mutex
714+
* lock to avoid changes between start of reset and end of reset.
715+
*/
716+
void ice_lag_move_vf_nodes_cfg(struct ice_lag *lag, u8 src_prt, u8 dst_prt)
717+
{
718+
struct ice_lag_netdev_list ndlist;
719+
720+
ice_lag_build_netdev_list(lag, &ndlist);
721+
ice_lag_move_vf_nodes(lag, src_prt, dst_prt);
722+
ice_lag_destroy_netdev_list(lag, &ndlist);
723+
}
724+
682725
#define ICE_LAG_SRIOV_CP_RECIPE 10
683726
#define ICE_LAG_SRIOV_TRAIN_PKT_LEN 16
684727

@@ -2051,7 +2094,6 @@ void ice_lag_rebuild(struct ice_pf *pf)
20512094
{
20522095
struct ice_lag_netdev_list ndlist;
20532096
struct ice_lag *lag, *prim_lag;
2054-
struct list_head *tmp, *n;
20552097
u8 act_port, loc_port;
20562098

20572099
if (!pf->lag || !pf->lag->bonded)
@@ -2063,21 +2105,7 @@ void ice_lag_rebuild(struct ice_pf *pf)
20632105
if (lag->primary) {
20642106
prim_lag = lag;
20652107
} else {
2066-
struct ice_lag_netdev_list *nl;
2067-
struct net_device *tmp_nd;
2068-
2069-
INIT_LIST_HEAD(&ndlist.node);
2070-
rcu_read_lock();
2071-
for_each_netdev_in_bond_rcu(lag->upper_netdev, tmp_nd) {
2072-
nl = kzalloc(sizeof(*nl), GFP_ATOMIC);
2073-
if (!nl)
2074-
break;
2075-
2076-
nl->netdev = tmp_nd;
2077-
list_add(&nl->node, &ndlist.node);
2078-
}
2079-
rcu_read_unlock();
2080-
lag->netdev_head = &ndlist.node;
2108+
ice_lag_build_netdev_list(lag, &ndlist);
20812109
prim_lag = ice_lag_find_primary(lag);
20822110
}
20832111

@@ -2107,13 +2135,7 @@ void ice_lag_rebuild(struct ice_pf *pf)
21072135

21082136
ice_clear_rdma_cap(pf);
21092137
lag_rebuild_out:
2110-
list_for_each_safe(tmp, n, &ndlist.node) {
2111-
struct ice_lag_netdev_list *entry;
2112-
2113-
entry = list_entry(tmp, struct ice_lag_netdev_list, node);
2114-
list_del(&entry->node);
2115-
kfree(entry);
2116-
}
2138+
ice_lag_destroy_netdev_list(lag, &ndlist);
21172139
mutex_unlock(&pf->lag_mutex);
21182140
}
21192141

drivers/net/ethernet/intel/ice/ice_lag.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,5 @@ int ice_init_lag(struct ice_pf *pf);
6565
void ice_deinit_lag(struct ice_pf *pf);
6666
void ice_lag_rebuild(struct ice_pf *pf);
6767
bool ice_lag_is_switchdev_running(struct ice_pf *pf);
68+
void ice_lag_move_vf_nodes_cfg(struct ice_lag *lag, u8 src_prt, u8 dst_prt);
6869
#endif /* _ICE_LAG_H_ */

drivers/net/ethernet/intel/ice/ice_vf_lib.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,12 +829,16 @@ static void ice_notify_vf_reset(struct ice_vf *vf)
829829
int ice_reset_vf(struct ice_vf *vf, u32 flags)
830830
{
831831
struct ice_pf *pf = vf->pf;
832+
struct ice_lag *lag;
832833
struct ice_vsi *vsi;
834+
u8 act_prt, pri_prt;
833835
struct device *dev;
834836
int err = 0;
835837
bool rsd;
836838

837839
dev = ice_pf_to_dev(pf);
840+
act_prt = ICE_LAG_INVALID_PORT;
841+
pri_prt = pf->hw.port_info->lport;
838842

839843
if (flags & ICE_VF_RESET_NOTIFY)
840844
ice_notify_vf_reset(vf);
@@ -845,6 +849,17 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
845849
return 0;
846850
}
847851

852+
lag = pf->lag;
853+
mutex_lock(&pf->lag_mutex);
854+
if (lag && lag->bonded && lag->primary) {
855+
act_prt = lag->active_port;
856+
if (act_prt != pri_prt && act_prt != ICE_LAG_INVALID_PORT &&
857+
lag->upper_netdev)
858+
ice_lag_move_vf_nodes_cfg(lag, act_prt, pri_prt);
859+
else
860+
act_prt = ICE_LAG_INVALID_PORT;
861+
}
862+
848863
if (flags & ICE_VF_RESET_LOCK)
849864
mutex_lock(&vf->cfg_lock);
850865
else
@@ -937,6 +952,11 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
937952
if (flags & ICE_VF_RESET_LOCK)
938953
mutex_unlock(&vf->cfg_lock);
939954

955+
if (lag && lag->bonded && lag->primary &&
956+
act_prt != ICE_LAG_INVALID_PORT)
957+
ice_lag_move_vf_nodes_cfg(lag, pri_prt, act_prt);
958+
mutex_unlock(&pf->lag_mutex);
959+
940960
return err;
941961
}
942962

drivers/net/ethernet/intel/ice/ice_virtchnl.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,9 +1603,24 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
16031603
(struct virtchnl_vsi_queue_config_info *)msg;
16041604
struct virtchnl_queue_pair_info *qpi;
16051605
struct ice_pf *pf = vf->pf;
1606+
struct ice_lag *lag;
16061607
struct ice_vsi *vsi;
1608+
u8 act_prt, pri_prt;
16071609
int i = -1, q_idx;
16081610

1611+
lag = pf->lag;
1612+
mutex_lock(&pf->lag_mutex);
1613+
act_prt = ICE_LAG_INVALID_PORT;
1614+
pri_prt = pf->hw.port_info->lport;
1615+
if (lag && lag->bonded && lag->primary) {
1616+
act_prt = lag->active_port;
1617+
if (act_prt != pri_prt && act_prt != ICE_LAG_INVALID_PORT &&
1618+
lag->upper_netdev)
1619+
ice_lag_move_vf_nodes_cfg(lag, act_prt, pri_prt);
1620+
else
1621+
act_prt = ICE_LAG_INVALID_PORT;
1622+
}
1623+
16091624
if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
16101625
goto error_param;
16111626

@@ -1729,6 +1744,11 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
17291744
}
17301745
}
17311746

1747+
if (lag && lag->bonded && lag->primary &&
1748+
act_prt != ICE_LAG_INVALID_PORT)
1749+
ice_lag_move_vf_nodes_cfg(lag, pri_prt, act_prt);
1750+
mutex_unlock(&pf->lag_mutex);
1751+
17321752
/* send the response to the VF */
17331753
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
17341754
VIRTCHNL_STATUS_SUCCESS, NULL, 0);
@@ -1743,6 +1763,11 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
17431763
vf->vf_id, i);
17441764
}
17451765

1766+
if (lag && lag->bonded && lag->primary &&
1767+
act_prt != ICE_LAG_INVALID_PORT)
1768+
ice_lag_move_vf_nodes_cfg(lag, pri_prt, act_prt);
1769+
mutex_unlock(&pf->lag_mutex);
1770+
17461771
ice_lag_move_new_vf_nodes(vf);
17471772

17481773
/* send the response to the VF */

0 commit comments

Comments
 (0)