]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
e1000e: prevent oops when adapter is being closed and reset simultaneously
authorBruce Allan <bruce.w.allan@intel.com>
Wed, 21 Mar 2012 00:39:12 +0000 (00:39 +0000)
committerJoe Jin <joe.jin@oracle.com>
Thu, 17 May 2012 07:56:40 +0000 (15:56 +0800)
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.

(cherry picked from commit bb9e44d0d0f45da356c39e485edacff6e14ba961)
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: Joe Jin <joe.jin@oracle.com>
drivers/net/e1000e/e1000.h
drivers/net/e1000e/netdev.c

index fa104c4c9104d8ea12bdda31f802279fed879442..a46f997895617aced098663956ff07cdf28acb2a 100644 (file)
@@ -161,6 +161,12 @@ struct e1000_info;
 /* Time to wait before putting the device into D3 if there's no link (in ms). */
 #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_RADV                   8
 #define BURST_RDTR                     0x20
index 15036a3248375be7d18d8b46143c462580822998..cea99d0d5a54d4f98f1a873c8315831073d71a2f 100644 (file)
@@ -3922,6 +3922,10 @@ static int e1000_close(struct net_device *netdev)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        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));
 
@@ -5415,6 +5419,11 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
        netif_device_detach(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));
                e1000e_down(adapter);
                e1000_free_irq(adapter);