ice_dcbnl_devreset() spins on ice_is_reset_in_progress() while holding RTNL,
taken by dcb_doit(), and pf->tc_mutex, taken by its dcbnl caller. The reset
rebuild needs RTNL in ice_ena_vsi() and pf->tc_mutex in ice_dcb_rebuild(),
both called from ice_rebuild(). So the waiter keeps the reset from ever
finishing, and thus keeps waiting.

Nothing is gained by the wait anyway: a reset in flight normally rebuilds
the DCB config and reopens the netdev on its own, which is all the
ifdown/ifup here is for. Bail out instead.

The reset bits are cleared only after ice_rebuild() returns, so a call can
still see them set after the rebuild has finished, and skip the ifdown/ifup.
That is harmless: ice_pf_dcb_cfg() has already reconfigured the VSIs, only
the stack-level notifications of the bounce are lost.

Fixes: b94b013eb626 ("ice: Implement DCBNL support")
Signed-off-by: Przemek Kitszel <[email protected]>
---
 drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c 
b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c
index bb5cc0a2ba69..9cdb9581fdc3 100644
--- a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c
+++ b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c
@@ -15,8 +15,9 @@ static void ice_dcbnl_devreset(struct net_device *netdev)
 {
        struct ice_pf *pf = ice_netdev_to_pf(netdev);
 
-       while (ice_is_reset_in_progress(pf->state))
-               usleep_range(1000, 2000);
+       /* waiting for a reset in flight would block it on the locks we hold */
+       if (ice_is_reset_in_progress(pf->state))
+               return;
 
        dev_close(netdev);
        netdev_state_change(netdev);
-- 
2.54.0

Reply via email to