From: Thomas Falcon tlfalcon@linux.ibm.com
[ Upstream commit 36f1031c51a2538e5558fb44c6d6b88f98d3c0f2 ]
Currently, the ibmvnic driver will not schedule device resets if the device is being removed, but does not check the device state before the reset is actually processed. This leads to a race where a reset is scheduled with a valid device state but is processed after the driver has been removed, resulting in an oops.
Fix this by checking the device state before processing a queued reset event.
Reported-by: Abdul Haleem abdhalee@linux.vnet.ibm.com Tested-by: Abdul Haleem abdhalee@linux.vnet.ibm.com Signed-off-by: Thomas Falcon tlfalcon@linux.ibm.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ibm/ibmvnic.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 0ae43d27cdcff..af1e8671515e0 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1996,6 +1996,10 @@ static void __ibmvnic_reset(struct work_struct *work)
rwi = get_next_rwi(adapter); while (rwi) { + if (adapter->state == VNIC_REMOVING || + adapter->state == VNIC_REMOVED) + goto out; + if (adapter->force_reset_recovery) { adapter->force_reset_recovery = false; rc = do_hard_reset(adapter, rwi, reset_state); @@ -2020,7 +2024,7 @@ static void __ibmvnic_reset(struct work_struct *work) netdev_dbg(adapter->netdev, "Reset failed\n"); free_all_rwi(adapter); } - +out: adapter->resetting = false; if (we_lock_rtnl) rtnl_unlock();