diff options
author | Auke Kok <auke\-jan.h.kok@intel.com> | 2006-09-27 15:54:02 -0400 |
---|---|---|
committer | Auke Kok <juke-jan.h.kok@intel.com> | 2006-09-27 15:54:02 -0400 |
commit | 1314bbf3a3d911218fc153e14873e2e384d08084 (patch) | |
tree | 4b2517261087f6d1374fe84272dcf20cd184f701 /drivers/net/e1000/e1000_main.c | |
parent | 4f5f2317fbb3655edae21de3ada0f1692523eeef (diff) |
e1000: driver state fixes (race fix)
We were plagued by our interrupt handler posting a watchdog event which
could occur when our adapter was going down in case a late packet arrived
just before e1000_down() finished. This caused the watchdog timer to start
after the NIC was down and keep rescheduling it every N seconds. Once
the driver unloaded it would panic.
Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
Diffstat (limited to 'drivers/net/e1000/e1000_main.c')
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index e2615782966e..5098dd7df7cd 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -476,13 +476,14 @@ e1000_up(struct e1000_adapter *adapter) | |||
476 | 476 | ||
477 | adapter->tx_queue_len = netdev->tx_queue_len; | 477 | adapter->tx_queue_len = netdev->tx_queue_len; |
478 | 478 | ||
479 | mod_timer(&adapter->watchdog_timer, jiffies); | ||
480 | |||
481 | #ifdef CONFIG_E1000_NAPI | 479 | #ifdef CONFIG_E1000_NAPI |
482 | netif_poll_enable(netdev); | 480 | netif_poll_enable(netdev); |
483 | #endif | 481 | #endif |
484 | e1000_irq_enable(adapter); | 482 | e1000_irq_enable(adapter); |
485 | 483 | ||
484 | clear_bit(__E1000_DOWN, &adapter->flags); | ||
485 | |||
486 | mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); | ||
486 | return 0; | 487 | return 0; |
487 | } | 488 | } |
488 | 489 | ||
@@ -561,6 +562,10 @@ e1000_down(struct e1000_adapter *adapter) | |||
561 | { | 562 | { |
562 | struct net_device *netdev = adapter->netdev; | 563 | struct net_device *netdev = adapter->netdev; |
563 | 564 | ||
565 | /* signal that we're down so the interrupt handler does not | ||
566 | * reschedule our watchdog timer */ | ||
567 | set_bit(__E1000_DOWN, &adapter->flags); | ||
568 | |||
564 | e1000_irq_disable(adapter); | 569 | e1000_irq_disable(adapter); |
565 | 570 | ||
566 | del_timer_sync(&adapter->tx_fifo_stall_timer); | 571 | del_timer_sync(&adapter->tx_fifo_stall_timer); |
@@ -903,11 +908,6 @@ e1000_probe(struct pci_dev *pdev, | |||
903 | INIT_WORK(&adapter->reset_task, | 908 | INIT_WORK(&adapter->reset_task, |
904 | (void (*)(void *))e1000_reset_task, netdev); | 909 | (void (*)(void *))e1000_reset_task, netdev); |
905 | 910 | ||
906 | /* we're going to reset, so assume we have no link for now */ | ||
907 | |||
908 | netif_carrier_off(netdev); | ||
909 | netif_stop_queue(netdev); | ||
910 | |||
911 | e1000_check_options(adapter); | 911 | e1000_check_options(adapter); |
912 | 912 | ||
913 | /* Initial Wake on LAN setting | 913 | /* Initial Wake on LAN setting |
@@ -1014,6 +1014,10 @@ e1000_probe(struct pci_dev *pdev, | |||
1014 | if ((err = register_netdev(netdev))) | 1014 | if ((err = register_netdev(netdev))) |
1015 | goto err_register; | 1015 | goto err_register; |
1016 | 1016 | ||
1017 | /* tell the stack to leave us alone until e1000_open() is called */ | ||
1018 | netif_carrier_off(netdev); | ||
1019 | netif_stop_queue(netdev); | ||
1020 | |||
1017 | DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n"); | 1021 | DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n"); |
1018 | 1022 | ||
1019 | cards_found++; | 1023 | cards_found++; |
@@ -1200,6 +1204,8 @@ e1000_sw_init(struct e1000_adapter *adapter) | |||
1200 | atomic_set(&adapter->irq_sem, 1); | 1204 | atomic_set(&adapter->irq_sem, 1); |
1201 | spin_lock_init(&adapter->stats_lock); | 1205 | spin_lock_init(&adapter->stats_lock); |
1202 | 1206 | ||
1207 | set_bit(__E1000_DOWN, &adapter->flags); | ||
1208 | |||
1203 | return 0; | 1209 | return 0; |
1204 | } | 1210 | } |
1205 | 1211 | ||
@@ -1265,7 +1271,7 @@ e1000_open(struct net_device *netdev) | |||
1265 | int err; | 1271 | int err; |
1266 | 1272 | ||
1267 | /* disallow open during test */ | 1273 | /* disallow open during test */ |
1268 | if (test_bit(__E1000_DRIVER_TESTING, &adapter->flags)) | 1274 | if (test_bit(__E1000_TESTING, &adapter->flags)) |
1269 | return -EBUSY; | 1275 | return -EBUSY; |
1270 | 1276 | ||
1271 | /* allocate transmit descriptors */ | 1277 | /* allocate transmit descriptors */ |
@@ -3072,7 +3078,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
3072 | if (unlikely(adapter->hw.mac_type == e1000_82547)) { | 3078 | if (unlikely(adapter->hw.mac_type == e1000_82547)) { |
3073 | if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) { | 3079 | if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) { |
3074 | netif_stop_queue(netdev); | 3080 | netif_stop_queue(netdev); |
3075 | mod_timer(&adapter->tx_fifo_stall_timer, jiffies); | 3081 | mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1); |
3076 | spin_unlock_irqrestore(&tx_ring->tx_lock, flags); | 3082 | spin_unlock_irqrestore(&tx_ring->tx_lock, flags); |
3077 | return NETDEV_TX_BUSY; | 3083 | return NETDEV_TX_BUSY; |
3078 | } | 3084 | } |
@@ -3468,7 +3474,9 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) | |||
3468 | rctl = E1000_READ_REG(hw, RCTL); | 3474 | rctl = E1000_READ_REG(hw, RCTL); |
3469 | E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); | 3475 | E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); |
3470 | } | 3476 | } |
3471 | mod_timer(&adapter->watchdog_timer, jiffies); | 3477 | /* guard against interrupt when we're going down */ |
3478 | if (!test_bit(__E1000_DOWN, &adapter->flags)) | ||
3479 | mod_timer(&adapter->watchdog_timer, jiffies + 1); | ||
3472 | } | 3480 | } |
3473 | 3481 | ||
3474 | #ifdef CONFIG_E1000_NAPI | 3482 | #ifdef CONFIG_E1000_NAPI |