Commit 6ad1c94e authored by Jakub Kicinski's avatar Jakub Kicinski

eth: alx: take rtnl_lock on resume

Zbynek reports that alx trips an rtnl assertion on resume:

 RTNL: assertion failed at net/core/dev.c (2891)
 RIP: 0010:netif_set_real_num_tx_queues+0x1ac/0x1c0
 Call Trace:
  <TASK>
  __alx_open+0x230/0x570 [alx]
  alx_resume+0x54/0x80 [alx]
  ? pci_legacy_resume+0x80/0x80
  dpm_run_callback+0x4a/0x150
  device_resume+0x8b/0x190
  async_resume+0x19/0x30
  async_run_entry_fn+0x30/0x130
  process_one_work+0x1e5/0x3b0

indeed the driver does not hold rtnl_lock during its internal close
and re-open functions during suspend/resume. Note that this is not
a huge bug as the driver implements its own locking, and does not
implement changing the number of queues, but we need to silence
the splat.

Fixes: 4a5fe57e ("alx: use fine-grained locking instead of RTNL")
Reported-and-tested-by: default avatarZbynek Michl <zbynek.michl@gmail.com>
Reviewed-by: default avatarNiels Dossche <dossche.niels@gmail.com>
Link: https://lore.kernel.org/r/20220928181236.1053043-1-kuba@kernel.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 0e3f7293
...@@ -1912,11 +1912,14 @@ static int alx_suspend(struct device *dev) ...@@ -1912,11 +1912,14 @@ static int alx_suspend(struct device *dev)
if (!netif_running(alx->dev)) if (!netif_running(alx->dev))
return 0; return 0;
rtnl_lock();
netif_device_detach(alx->dev); netif_device_detach(alx->dev);
mutex_lock(&alx->mtx); mutex_lock(&alx->mtx);
__alx_stop(alx); __alx_stop(alx);
mutex_unlock(&alx->mtx); mutex_unlock(&alx->mtx);
rtnl_unlock();
return 0; return 0;
} }
...@@ -1927,6 +1930,7 @@ static int alx_resume(struct device *dev) ...@@ -1927,6 +1930,7 @@ static int alx_resume(struct device *dev)
struct alx_hw *hw = &alx->hw; struct alx_hw *hw = &alx->hw;
int err; int err;
rtnl_lock();
mutex_lock(&alx->mtx); mutex_lock(&alx->mtx);
alx_reset_phy(hw); alx_reset_phy(hw);
...@@ -1943,6 +1947,7 @@ static int alx_resume(struct device *dev) ...@@ -1943,6 +1947,7 @@ static int alx_resume(struct device *dev)
unlock: unlock:
mutex_unlock(&alx->mtx); mutex_unlock(&alx->mtx);
rtnl_unlock();
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment