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 | |
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')
-rw-r--r-- | drivers/net/e1000/e1000.h | 3 | ||||
-rw-r--r-- | drivers/net/e1000/e1000_ethtool.c | 6 | ||||
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 28 |
3 files changed, 23 insertions, 14 deletions
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index a9501e7b8ef9..7ecce438d258 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h | |||
@@ -345,8 +345,9 @@ struct e1000_adapter { | |||
345 | }; | 345 | }; |
346 | 346 | ||
347 | enum e1000_state_t { | 347 | enum e1000_state_t { |
348 | __E1000_DRIVER_TESTING, | 348 | __E1000_TESTING, |
349 | __E1000_RESETTING, | 349 | __E1000_RESETTING, |
350 | __E1000_DOWN | ||
350 | }; | 351 | }; |
351 | 352 | ||
352 | #endif /* _E1000_H_ */ | 353 | #endif /* _E1000_H_ */ |
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 5edf8a099ceb..2cc949a34451 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c | |||
@@ -1624,7 +1624,7 @@ e1000_diag_test(struct net_device *netdev, | |||
1624 | struct e1000_adapter *adapter = netdev_priv(netdev); | 1624 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1625 | boolean_t if_running = netif_running(netdev); | 1625 | boolean_t if_running = netif_running(netdev); |
1626 | 1626 | ||
1627 | set_bit(__E1000_DRIVER_TESTING, &adapter->flags); | 1627 | set_bit(__E1000_TESTING, &adapter->flags); |
1628 | if (eth_test->flags == ETH_TEST_FL_OFFLINE) { | 1628 | if (eth_test->flags == ETH_TEST_FL_OFFLINE) { |
1629 | /* Offline tests */ | 1629 | /* Offline tests */ |
1630 | 1630 | ||
@@ -1669,7 +1669,7 @@ e1000_diag_test(struct net_device *netdev, | |||
1669 | adapter->hw.autoneg = autoneg; | 1669 | adapter->hw.autoneg = autoneg; |
1670 | 1670 | ||
1671 | e1000_reset(adapter); | 1671 | e1000_reset(adapter); |
1672 | clear_bit(__E1000_DRIVER_TESTING, &adapter->flags); | 1672 | clear_bit(__E1000_TESTING, &adapter->flags); |
1673 | if (if_running) | 1673 | if (if_running) |
1674 | dev_open(netdev); | 1674 | dev_open(netdev); |
1675 | } else { | 1675 | } else { |
@@ -1684,7 +1684,7 @@ e1000_diag_test(struct net_device *netdev, | |||
1684 | data[2] = 0; | 1684 | data[2] = 0; |
1685 | data[3] = 0; | 1685 | data[3] = 0; |
1686 | 1686 | ||
1687 | clear_bit(__E1000_DRIVER_TESTING, &adapter->flags); | 1687 | clear_bit(__E1000_TESTING, &adapter->flags); |
1688 | } | 1688 | } |
1689 | msleep_interruptible(4 * 1000); | 1689 | msleep_interruptible(4 * 1000); |
1690 | } | 1690 | } |
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 |