diff options
author | Thomas Falcon <tlfalcon@linux.ibm.com> | 2019-08-27 11:10:04 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-09-21 07:17:05 +0200 |
commit | 6cce2adae3e17e75109d9a1088f1b1bb69d778b1 (patch) | |
tree | 894aadbfa77358d31485d4f1eda53cf7c475465f | |
parent | 080ca754f5dbc8cc65b69902a81c901708adaf53 (diff) | |
download | linux-stable-6cce2adae3e17e75109d9a1088f1b1bb69d778b1.tar.gz linux-stable-6cce2adae3e17e75109d9a1088f1b1bb69d778b1.tar.bz2 linux-stable-6cce2adae3e17e75109d9a1088f1b1bb69d778b1.zip |
ibmvnic: Do not process reset during or after device removal
[ 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>
-rw-r--r-- | drivers/net/ethernet/ibm/ibmvnic.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 255de7d68cd3..5a57be66a487 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1998,6 +1998,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); @@ -2022,7 +2026,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(); |