ice_vsi_rebuild() is a critical section in the reset path. Sometimes, rtnl-locked callbacks have to wait for it to finish. However, it is possible they will wait for an eternity, because the critical section contains calls to ice_queue_set_napi() that try to take rtnl_lock. Make ice_queue_set_napi() aware that some rtnl-locked code is waiting and skip taking the lock, if this is the case. Fixes: 080b0c8d6d26 ("ice: Fix ASSERT_RTNL() warning during certain scenarios") Reviewed-by: Igor Bagnucki <igor.bagnucki@xxxxxxxxx> Signed-off-by: Larysa Zaremba <larysa.zaremba@xxxxxxxxx> --- drivers/net/ethernet/intel/ice/ice.h | 1 + drivers/net/ethernet/intel/ice/ice_lib.c | 18 +++++++++++++++--- drivers/net/ethernet/intel/ice/ice_main.c | 5 ++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 76590cfcaf68..7c1e24afa34b 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -307,6 +307,7 @@ enum ice_pf_state { ICE_PHY_INIT_COMPLETE, ICE_FD_VF_FLUSH_CTX, /* set at FD Rx IRQ or timeout */ ICE_AUX_ERR_PENDING, + ICE_RTNL_WAITS_FOR_RESET, ICE_STATE_NBITS /* must be last */ }; diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 4774bcc4d5a8..a5dc6fc6e63d 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2740,12 +2740,24 @@ ice_queue_set_napi(struct ice_vsi *vsi, unsigned int queue_index, if (current_work() == &pf->serv_task || test_bit(ICE_PREPARED_FOR_RESET, pf->state) || test_bit(ICE_DOWN, pf->state) || - test_bit(ICE_SUSPENDED, pf->state)) + test_bit(ICE_SUSPENDED, pf->state)) { + bool rtnl_held_here = true; + + while (!rtnl_trylock()) { + if (test_bit(ICE_RTNL_WAITS_FOR_RESET, pf->state)) { + rtnl_held_here = false; + break; + } + usleep_range(1000, 2000); + } __ice_queue_set_napi(vsi->netdev, queue_index, type, napi, - false); - else + true); + if (rtnl_held_here) + rtnl_unlock(); + } else { __ice_queue_set_napi(vsi->netdev, queue_index, type, napi, true); + } } /** diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index cd8be3c3b956..37b3dd22cdc2 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3103,8 +3103,11 @@ static int ice_xdp(struct net_device *dev, struct netdev_bpf *xdp) return -EINVAL; } - while (test_and_set_bit(ICE_CFG_BUSY, pf->state)) + while (test_and_set_bit(ICE_CFG_BUSY, pf->state)) { + set_bit(ICE_RTNL_WAITS_FOR_RESET, pf->state); usleep_range(1000, 2000); + } + clear_bit(ICE_RTNL_WAITS_FOR_RESET, pf->state); switch (xdp->command) { case XDP_SETUP_PROG: -- 2.43.0