Commit bb9e44d0 authored by Bruce Allan's avatar Bruce Allan Committed by Jeff Kirsher

e1000e: prevent oops when adapter is being closed and reset simultaneously

When the adapter is closed while it is simultaneously going through a
reset, it can cause a null-pointer dereference when the two different code
paths simultaneously cleanup up the Tx/Rx resources.
Signed-off-by: default avatarBruce Allan <bruce.w.allan@intel.com>
Tested-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent aacc1bea
...@@ -161,6 +161,12 @@ struct e1000_info; ...@@ -161,6 +161,12 @@ struct e1000_info;
/* Time to wait before putting the device into D3 if there's no link (in ms). */ /* Time to wait before putting the device into D3 if there's no link (in ms). */
#define LINK_TIMEOUT 100 #define LINK_TIMEOUT 100
/*
* Count for polling __E1000_RESET condition every 10-20msec.
* Experimentation has shown the reset can take approximately 210msec.
*/
#define E1000_CHECK_RESET_COUNT 25
#define DEFAULT_RDTR 0 #define DEFAULT_RDTR 0
#define DEFAULT_RADV 8 #define DEFAULT_RADV 8
#define BURST_RDTR 0x20 #define BURST_RDTR 0x20
......
...@@ -3968,6 +3968,10 @@ static int e1000_close(struct net_device *netdev) ...@@ -3968,6 +3968,10 @@ static int e1000_close(struct net_device *netdev)
{ {
struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_adapter *adapter = netdev_priv(netdev);
struct pci_dev *pdev = adapter->pdev; struct pci_dev *pdev = adapter->pdev;
int count = E1000_CHECK_RESET_COUNT;
while (test_bit(__E1000_RESETTING, &adapter->state) && count--)
usleep_range(10000, 20000);
WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); WARN_ON(test_bit(__E1000_RESETTING, &adapter->state));
...@@ -5472,6 +5476,11 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, ...@@ -5472,6 +5476,11 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
netif_device_detach(netdev); netif_device_detach(netdev);
if (netif_running(netdev)) { if (netif_running(netdev)) {
int count = E1000_CHECK_RESET_COUNT;
while (test_bit(__E1000_RESETTING, &adapter->state) && count--)
usleep_range(10000, 20000);
WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); WARN_ON(test_bit(__E1000_RESETTING, &adapter->state));
e1000e_down(adapter); e1000e_down(adapter);
e1000_free_irq(adapter); e1000_free_irq(adapter);
......
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