diff options
author | Auke Kok <auke-jan.h.kok@intel.com> | 2006-06-27 12:06:28 -0400 |
---|---|---|
committer | Auke Kok <juke-jan.h.kok@intel.com> | 2006-06-27 12:06:28 -0400 |
commit | 2db10a081c5c1082d58809a1bcf1a6073f4db160 (patch) | |
tree | f54772ef60f2c5bf5f8d602a83d6dc508158a0e0 /drivers | |
parent | acfbc9fde2ec7f304398f6ad7644002e07bf84bc (diff) |
e1000: rework driver hardware reset locking
After studying the driver mac reset code it was found that there
were multiple race conditions possible to reset the unit twice or
bring it e1000_up() double. This fixes all occurences where the
driver needs to reset the mac.
We also remove irq requesting/releasing into _open and _close so
that while the device is _up we will never touch the irq's. This fixes
the double free irq bug that people saw.
To make sure that the watchdog task doesn't cause another race we let
it run as a non-scheduled task.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/e1000/e1000.h | 8 | ||||
-rw-r--r-- | drivers/net/e1000/e1000_ethtool.c | 46 | ||||
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 126 |
3 files changed, 105 insertions, 75 deletions
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 2bc34fbfa69c..2b96ad0482ef 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h | |||
@@ -69,7 +69,6 @@ | |||
69 | #ifdef NETIF_F_TSO | 69 | #ifdef NETIF_F_TSO |
70 | #include <net/checksum.h> | 70 | #include <net/checksum.h> |
71 | #endif | 71 | #endif |
72 | #include <linux/workqueue.h> | ||
73 | #include <linux/mii.h> | 72 | #include <linux/mii.h> |
74 | #include <linux/ethtool.h> | 73 | #include <linux/ethtool.h> |
75 | #include <linux/if_vlan.h> | 74 | #include <linux/if_vlan.h> |
@@ -255,7 +254,6 @@ struct e1000_adapter { | |||
255 | spinlock_t tx_queue_lock; | 254 | spinlock_t tx_queue_lock; |
256 | #endif | 255 | #endif |
257 | atomic_t irq_sem; | 256 | atomic_t irq_sem; |
258 | struct work_struct watchdog_task; | ||
259 | struct work_struct reset_task; | 257 | struct work_struct reset_task; |
260 | uint8_t fc_autoneg; | 258 | uint8_t fc_autoneg; |
261 | 259 | ||
@@ -340,8 +338,13 @@ struct e1000_adapter { | |||
340 | #ifdef NETIF_F_TSO | 338 | #ifdef NETIF_F_TSO |
341 | boolean_t tso_force; | 339 | boolean_t tso_force; |
342 | #endif | 340 | #endif |
341 | unsigned long flags; | ||
343 | }; | 342 | }; |
344 | 343 | ||
344 | enum e1000_state_t { | ||
345 | __E1000_DRIVER_TESTING, | ||
346 | __E1000_RESETTING, | ||
347 | }; | ||
345 | 348 | ||
346 | /* e1000_main.c */ | 349 | /* e1000_main.c */ |
347 | extern char e1000_driver_name[]; | 350 | extern char e1000_driver_name[]; |
@@ -349,6 +352,7 @@ extern char e1000_driver_version[]; | |||
349 | int e1000_up(struct e1000_adapter *adapter); | 352 | int e1000_up(struct e1000_adapter *adapter); |
350 | void e1000_down(struct e1000_adapter *adapter); | 353 | void e1000_down(struct e1000_adapter *adapter); |
351 | void e1000_reset(struct e1000_adapter *adapter); | 354 | void e1000_reset(struct e1000_adapter *adapter); |
355 | void e1000_reinit_locked(struct e1000_adapter *adapter); | ||
352 | int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); | 356 | int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); |
353 | void e1000_free_all_tx_resources(struct e1000_adapter *adapter); | 357 | void e1000_free_all_tx_resources(struct e1000_adapter *adapter); |
354 | int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); | 358 | int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); |
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 845d293b2f6a..cf5c5f46341f 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c | |||
@@ -203,11 +203,9 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) | |||
203 | 203 | ||
204 | /* reset the link */ | 204 | /* reset the link */ |
205 | 205 | ||
206 | if (netif_running(adapter->netdev)) { | 206 | if (netif_running(adapter->netdev)) |
207 | e1000_down(adapter); | 207 | e1000_reinit_locked(adapter); |
208 | e1000_reset(adapter); | 208 | else |
209 | e1000_up(adapter); | ||
210 | } else | ||
211 | e1000_reset(adapter); | 209 | e1000_reset(adapter); |
212 | 210 | ||
213 | return 0; | 211 | return 0; |
@@ -254,10 +252,9 @@ e1000_set_pauseparam(struct net_device *netdev, | |||
254 | hw->original_fc = hw->fc; | 252 | hw->original_fc = hw->fc; |
255 | 253 | ||
256 | if (adapter->fc_autoneg == AUTONEG_ENABLE) { | 254 | if (adapter->fc_autoneg == AUTONEG_ENABLE) { |
257 | if (netif_running(adapter->netdev)) { | 255 | if (netif_running(adapter->netdev)) |
258 | e1000_down(adapter); | 256 | e1000_reinit_locked(adapter); |
259 | e1000_up(adapter); | 257 | else |
260 | } else | ||
261 | e1000_reset(adapter); | 258 | e1000_reset(adapter); |
262 | } else | 259 | } else |
263 | return ((hw->media_type == e1000_media_type_fiber) ? | 260 | return ((hw->media_type == e1000_media_type_fiber) ? |
@@ -279,10 +276,9 @@ e1000_set_rx_csum(struct net_device *netdev, uint32_t data) | |||
279 | struct e1000_adapter *adapter = netdev_priv(netdev); | 276 | struct e1000_adapter *adapter = netdev_priv(netdev); |
280 | adapter->rx_csum = data; | 277 | adapter->rx_csum = data; |
281 | 278 | ||
282 | if (netif_running(netdev)) { | 279 | if (netif_running(netdev)) |
283 | e1000_down(adapter); | 280 | e1000_reinit_locked(adapter); |
284 | e1000_up(adapter); | 281 | else |
285 | } else | ||
286 | e1000_reset(adapter); | 282 | e1000_reset(adapter); |
287 | return 0; | 283 | return 0; |
288 | } | 284 | } |
@@ -631,6 +627,9 @@ e1000_set_ringparam(struct net_device *netdev, | |||
631 | tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues; | 627 | tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues; |
632 | rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues; | 628 | rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues; |
633 | 629 | ||
630 | while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) | ||
631 | msleep(1); | ||
632 | |||
634 | if (netif_running(adapter->netdev)) | 633 | if (netif_running(adapter->netdev)) |
635 | e1000_down(adapter); | 634 | e1000_down(adapter); |
636 | 635 | ||
@@ -691,9 +690,11 @@ e1000_set_ringparam(struct net_device *netdev, | |||
691 | adapter->rx_ring = rx_new; | 690 | adapter->rx_ring = rx_new; |
692 | adapter->tx_ring = tx_new; | 691 | adapter->tx_ring = tx_new; |
693 | if ((err = e1000_up(adapter))) | 692 | if ((err = e1000_up(adapter))) |
694 | return err; | 693 | goto err_setup; |
695 | } | 694 | } |
696 | 695 | ||
696 | clear_bit(__E1000_RESETTING, &adapter->flags); | ||
697 | |||
697 | return 0; | 698 | return 0; |
698 | err_setup_tx: | 699 | err_setup_tx: |
699 | e1000_free_all_rx_resources(adapter); | 700 | e1000_free_all_rx_resources(adapter); |
@@ -701,6 +702,8 @@ err_setup_rx: | |||
701 | adapter->rx_ring = rx_old; | 702 | adapter->rx_ring = rx_old; |
702 | adapter->tx_ring = tx_old; | 703 | adapter->tx_ring = tx_old; |
703 | e1000_up(adapter); | 704 | e1000_up(adapter); |
705 | err_setup: | ||
706 | clear_bit(__E1000_RESETTING, &adapter->flags); | ||
704 | return err; | 707 | return err; |
705 | } | 708 | } |
706 | 709 | ||
@@ -1568,6 +1571,7 @@ e1000_diag_test(struct net_device *netdev, | |||
1568 | struct e1000_adapter *adapter = netdev_priv(netdev); | 1571 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1569 | boolean_t if_running = netif_running(netdev); | 1572 | boolean_t if_running = netif_running(netdev); |
1570 | 1573 | ||
1574 | set_bit(__E1000_DRIVER_TESTING, &adapter->flags); | ||
1571 | if (eth_test->flags == ETH_TEST_FL_OFFLINE) { | 1575 | if (eth_test->flags == ETH_TEST_FL_OFFLINE) { |
1572 | /* Offline tests */ | 1576 | /* Offline tests */ |
1573 | 1577 | ||
@@ -1582,7 +1586,8 @@ e1000_diag_test(struct net_device *netdev, | |||
1582 | eth_test->flags |= ETH_TEST_FL_FAILED; | 1586 | eth_test->flags |= ETH_TEST_FL_FAILED; |
1583 | 1587 | ||
1584 | if (if_running) | 1588 | if (if_running) |
1585 | e1000_down(adapter); | 1589 | /* indicate we're in test mode */ |
1590 | dev_close(netdev); | ||
1586 | else | 1591 | else |
1587 | e1000_reset(adapter); | 1592 | e1000_reset(adapter); |
1588 | 1593 | ||
@@ -1607,8 +1612,9 @@ e1000_diag_test(struct net_device *netdev, | |||
1607 | adapter->hw.autoneg = autoneg; | 1612 | adapter->hw.autoneg = autoneg; |
1608 | 1613 | ||
1609 | e1000_reset(adapter); | 1614 | e1000_reset(adapter); |
1615 | clear_bit(__E1000_DRIVER_TESTING, &adapter->flags); | ||
1610 | if (if_running) | 1616 | if (if_running) |
1611 | e1000_up(adapter); | 1617 | dev_open(netdev); |
1612 | } else { | 1618 | } else { |
1613 | /* Online tests */ | 1619 | /* Online tests */ |
1614 | if (e1000_link_test(adapter, &data[4])) | 1620 | if (e1000_link_test(adapter, &data[4])) |
@@ -1619,6 +1625,8 @@ e1000_diag_test(struct net_device *netdev, | |||
1619 | data[1] = 0; | 1625 | data[1] = 0; |
1620 | data[2] = 0; | 1626 | data[2] = 0; |
1621 | data[3] = 0; | 1627 | data[3] = 0; |
1628 | |||
1629 | clear_bit(__E1000_DRIVER_TESTING, &adapter->flags); | ||
1622 | } | 1630 | } |
1623 | msleep_interruptible(4 * 1000); | 1631 | msleep_interruptible(4 * 1000); |
1624 | } | 1632 | } |
@@ -1807,10 +1815,8 @@ static int | |||
1807 | e1000_nway_reset(struct net_device *netdev) | 1815 | e1000_nway_reset(struct net_device *netdev) |
1808 | { | 1816 | { |
1809 | struct e1000_adapter *adapter = netdev_priv(netdev); | 1817 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1810 | if (netif_running(netdev)) { | 1818 | if (netif_running(netdev)) |
1811 | e1000_down(adapter); | 1819 | e1000_reinit_locked(adapter); |
1812 | e1000_up(adapter); | ||
1813 | } | ||
1814 | return 0; | 1820 | return 0; |
1815 | } | 1821 | } |
1816 | 1822 | ||
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index a373ccb308d8..52d698bb2595 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -133,7 +133,6 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter, | |||
133 | static void e1000_set_multi(struct net_device *netdev); | 133 | static void e1000_set_multi(struct net_device *netdev); |
134 | static void e1000_update_phy_info(unsigned long data); | 134 | static void e1000_update_phy_info(unsigned long data); |
135 | static void e1000_watchdog(unsigned long data); | 135 | static void e1000_watchdog(unsigned long data); |
136 | static void e1000_watchdog_task(struct e1000_adapter *adapter); | ||
137 | static void e1000_82547_tx_fifo_stall(unsigned long data); | 136 | static void e1000_82547_tx_fifo_stall(unsigned long data); |
138 | static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev); | 137 | static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev); |
139 | static struct net_device_stats * e1000_get_stats(struct net_device *netdev); | 138 | static struct net_device_stats * e1000_get_stats(struct net_device *netdev); |
@@ -261,6 +260,44 @@ e1000_exit_module(void) | |||
261 | 260 | ||
262 | module_exit(e1000_exit_module); | 261 | module_exit(e1000_exit_module); |
263 | 262 | ||
263 | static int e1000_request_irq(struct e1000_adapter *adapter) | ||
264 | { | ||
265 | struct net_device *netdev = adapter->netdev; | ||
266 | int flags, err = 0; | ||
267 | |||
268 | flags = SA_SHIRQ | SA_SAMPLE_RANDOM; | ||
269 | #ifdef CONFIG_PCI_MSI | ||
270 | if (adapter->hw.mac_type > e1000_82547_rev_2) { | ||
271 | adapter->have_msi = TRUE; | ||
272 | if ((err = pci_enable_msi(adapter->pdev))) { | ||
273 | DPRINTK(PROBE, ERR, | ||
274 | "Unable to allocate MSI interrupt Error: %d\n", err); | ||
275 | adapter->have_msi = FALSE; | ||
276 | } | ||
277 | } | ||
278 | if (adapter->have_msi) | ||
279 | flags &= ~SA_SHIRQ; | ||
280 | #endif | ||
281 | if ((err = request_irq(adapter->pdev->irq, &e1000_intr, flags, | ||
282 | netdev->name, netdev))) | ||
283 | DPRINTK(PROBE, ERR, | ||
284 | "Unable to allocate interrupt Error: %d\n", err); | ||
285 | |||
286 | return err; | ||
287 | } | ||
288 | |||
289 | static void e1000_free_irq(struct e1000_adapter *adapter) | ||
290 | { | ||
291 | struct net_device *netdev = adapter->netdev; | ||
292 | |||
293 | free_irq(adapter->pdev->irq, netdev); | ||
294 | |||
295 | #ifdef CONFIG_PCI_MSI | ||
296 | if (adapter->have_msi) | ||
297 | pci_disable_msi(adapter->pdev); | ||
298 | #endif | ||
299 | } | ||
300 | |||
264 | /** | 301 | /** |
265 | * e1000_irq_disable - Mask off interrupt generation on the NIC | 302 | * e1000_irq_disable - Mask off interrupt generation on the NIC |
266 | * @adapter: board private structure | 303 | * @adapter: board private structure |
@@ -387,7 +424,7 @@ int | |||
387 | e1000_up(struct e1000_adapter *adapter) | 424 | e1000_up(struct e1000_adapter *adapter) |
388 | { | 425 | { |
389 | struct net_device *netdev = adapter->netdev; | 426 | struct net_device *netdev = adapter->netdev; |
390 | int i, err; | 427 | int i; |
391 | 428 | ||
392 | /* hardware has been reset, we need to reload some things */ | 429 | /* hardware has been reset, we need to reload some things */ |
393 | 430 | ||
@@ -415,24 +452,6 @@ e1000_up(struct e1000_adapter *adapter) | |||
415 | E1000_DESC_UNUSED(ring)); | 452 | E1000_DESC_UNUSED(ring)); |
416 | } | 453 | } |
417 | 454 | ||
418 | #ifdef CONFIG_PCI_MSI | ||
419 | if (adapter->hw.mac_type > e1000_82547_rev_2) { | ||
420 | adapter->have_msi = TRUE; | ||
421 | if ((err = pci_enable_msi(adapter->pdev))) { | ||
422 | DPRINTK(PROBE, ERR, | ||
423 | "Unable to allocate MSI interrupt Error: %d\n", err); | ||
424 | adapter->have_msi = FALSE; | ||
425 | } | ||
426 | } | ||
427 | #endif | ||
428 | if ((err = request_irq(adapter->pdev->irq, &e1000_intr, | ||
429 | SA_SHIRQ | SA_SAMPLE_RANDOM, | ||
430 | netdev->name, netdev))) { | ||
431 | DPRINTK(PROBE, ERR, | ||
432 | "Unable to allocate interrupt Error: %d\n", err); | ||
433 | return err; | ||
434 | } | ||
435 | |||
436 | adapter->tx_queue_len = netdev->tx_queue_len; | 455 | adapter->tx_queue_len = netdev->tx_queue_len; |
437 | 456 | ||
438 | mod_timer(&adapter->watchdog_timer, jiffies); | 457 | mod_timer(&adapter->watchdog_timer, jiffies); |
@@ -450,16 +469,10 @@ e1000_down(struct e1000_adapter *adapter) | |||
450 | { | 469 | { |
451 | struct net_device *netdev = adapter->netdev; | 470 | struct net_device *netdev = adapter->netdev; |
452 | boolean_t mng_mode_enabled = (adapter->hw.mac_type >= e1000_82571) && | 471 | boolean_t mng_mode_enabled = (adapter->hw.mac_type >= e1000_82571) && |
453 | e1000_check_mng_mode(&adapter->hw); | 472 | e1000_check_mng_mode(&adapter->hw); |
454 | 473 | ||
455 | e1000_irq_disable(adapter); | 474 | e1000_irq_disable(adapter); |
456 | 475 | ||
457 | free_irq(adapter->pdev->irq, netdev); | ||
458 | #ifdef CONFIG_PCI_MSI | ||
459 | if (adapter->hw.mac_type > e1000_82547_rev_2 && | ||
460 | adapter->have_msi == TRUE) | ||
461 | pci_disable_msi(adapter->pdev); | ||
462 | #endif | ||
463 | del_timer_sync(&adapter->tx_fifo_stall_timer); | 476 | del_timer_sync(&adapter->tx_fifo_stall_timer); |
464 | del_timer_sync(&adapter->watchdog_timer); | 477 | del_timer_sync(&adapter->watchdog_timer); |
465 | del_timer_sync(&adapter->phy_info_timer); | 478 | del_timer_sync(&adapter->phy_info_timer); |
@@ -496,6 +509,17 @@ e1000_down(struct e1000_adapter *adapter) | |||
496 | } | 509 | } |
497 | 510 | ||
498 | void | 511 | void |
512 | e1000_reinit_locked(struct e1000_adapter *adapter) | ||
513 | { | ||
514 | WARN_ON(in_interrupt()); | ||
515 | while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) | ||
516 | msleep(1); | ||
517 | e1000_down(adapter); | ||
518 | e1000_up(adapter); | ||
519 | clear_bit(__E1000_RESETTING, &adapter->flags); | ||
520 | } | ||
521 | |||
522 | void | ||
499 | e1000_reset(struct e1000_adapter *adapter) | 523 | e1000_reset(struct e1000_adapter *adapter) |
500 | { | 524 | { |
501 | uint32_t pba, manc; | 525 | uint32_t pba, manc; |
@@ -758,9 +782,6 @@ e1000_probe(struct pci_dev *pdev, | |||
758 | adapter->watchdog_timer.function = &e1000_watchdog; | 782 | adapter->watchdog_timer.function = &e1000_watchdog; |
759 | adapter->watchdog_timer.data = (unsigned long) adapter; | 783 | adapter->watchdog_timer.data = (unsigned long) adapter; |
760 | 784 | ||
761 | INIT_WORK(&adapter->watchdog_task, | ||
762 | (void (*)(void *))e1000_watchdog_task, adapter); | ||
763 | |||
764 | init_timer(&adapter->phy_info_timer); | 785 | init_timer(&adapter->phy_info_timer); |
765 | adapter->phy_info_timer.function = &e1000_update_phy_info; | 786 | adapter->phy_info_timer.function = &e1000_update_phy_info; |
766 | adapter->phy_info_timer.data = (unsigned long) adapter; | 787 | adapter->phy_info_timer.data = (unsigned long) adapter; |
@@ -1078,6 +1099,10 @@ e1000_open(struct net_device *netdev) | |||
1078 | struct e1000_adapter *adapter = netdev_priv(netdev); | 1099 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1079 | int err; | 1100 | int err; |
1080 | 1101 | ||
1102 | /* disallow open during test */ | ||
1103 | if (test_bit(__E1000_DRIVER_TESTING, &adapter->flags)) | ||
1104 | return -EBUSY; | ||
1105 | |||
1081 | /* allocate transmit descriptors */ | 1106 | /* allocate transmit descriptors */ |
1082 | 1107 | ||
1083 | if ((err = e1000_setup_all_tx_resources(adapter))) | 1108 | if ((err = e1000_setup_all_tx_resources(adapter))) |
@@ -1088,6 +1113,10 @@ e1000_open(struct net_device *netdev) | |||
1088 | if ((err = e1000_setup_all_rx_resources(adapter))) | 1113 | if ((err = e1000_setup_all_rx_resources(adapter))) |
1089 | goto err_setup_rx; | 1114 | goto err_setup_rx; |
1090 | 1115 | ||
1116 | err = e1000_request_irq(adapter); | ||
1117 | if (err) | ||
1118 | goto err_up; | ||
1119 | |||
1091 | if ((err = e1000_up(adapter))) | 1120 | if ((err = e1000_up(adapter))) |
1092 | goto err_up; | 1121 | goto err_up; |
1093 | adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; | 1122 | adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; |
@@ -1131,7 +1160,9 @@ e1000_close(struct net_device *netdev) | |||
1131 | { | 1160 | { |
1132 | struct e1000_adapter *adapter = netdev_priv(netdev); | 1161 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1133 | 1162 | ||
1163 | WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); | ||
1134 | e1000_down(adapter); | 1164 | e1000_down(adapter); |
1165 | e1000_free_irq(adapter); | ||
1135 | 1166 | ||
1136 | e1000_free_all_tx_resources(adapter); | 1167 | e1000_free_all_tx_resources(adapter); |
1137 | e1000_free_all_rx_resources(adapter); | 1168 | e1000_free_all_rx_resources(adapter); |
@@ -2201,14 +2232,6 @@ static void | |||
2201 | e1000_watchdog(unsigned long data) | 2232 | e1000_watchdog(unsigned long data) |
2202 | { | 2233 | { |
2203 | struct e1000_adapter *adapter = (struct e1000_adapter *) data; | 2234 | struct e1000_adapter *adapter = (struct e1000_adapter *) data; |
2204 | |||
2205 | /* Do the rest outside of interrupt context */ | ||
2206 | schedule_work(&adapter->watchdog_task); | ||
2207 | } | ||
2208 | |||
2209 | static void | ||
2210 | e1000_watchdog_task(struct e1000_adapter *adapter) | ||
2211 | { | ||
2212 | struct net_device *netdev = adapter->netdev; | 2235 | struct net_device *netdev = adapter->netdev; |
2213 | struct e1000_tx_ring *txdr = adapter->tx_ring; | 2236 | struct e1000_tx_ring *txdr = adapter->tx_ring; |
2214 | uint32_t link, tctl; | 2237 | uint32_t link, tctl; |
@@ -2919,8 +2942,7 @@ e1000_reset_task(struct net_device *netdev) | |||
2919 | { | 2942 | { |
2920 | struct e1000_adapter *adapter = netdev_priv(netdev); | 2943 | struct e1000_adapter *adapter = netdev_priv(netdev); |
2921 | 2944 | ||
2922 | e1000_down(adapter); | 2945 | e1000_reinit_locked(adapter); |
2923 | e1000_up(adapter); | ||
2924 | } | 2946 | } |
2925 | 2947 | ||
2926 | /** | 2948 | /** |
@@ -3026,10 +3048,8 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu) | |||
3026 | 3048 | ||
3027 | netdev->mtu = new_mtu; | 3049 | netdev->mtu = new_mtu; |
3028 | 3050 | ||
3029 | if (netif_running(netdev)) { | 3051 | if (netif_running(netdev)) |
3030 | e1000_down(adapter); | 3052 | e1000_reinit_locked(adapter); |
3031 | e1000_up(adapter); | ||
3032 | } | ||
3033 | 3053 | ||
3034 | adapter->hw.max_frame_size = max_frame; | 3054 | adapter->hw.max_frame_size = max_frame; |
3035 | 3055 | ||
@@ -4180,10 +4200,9 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | |||
4180 | return retval; | 4200 | return retval; |
4181 | } | 4201 | } |
4182 | } | 4202 | } |
4183 | if (netif_running(adapter->netdev)) { | 4203 | if (netif_running(adapter->netdev)) |
4184 | e1000_down(adapter); | 4204 | e1000_reinit_locked(adapter); |
4185 | e1000_up(adapter); | 4205 | else |
4186 | } else | ||
4187 | e1000_reset(adapter); | 4206 | e1000_reset(adapter); |
4188 | break; | 4207 | break; |
4189 | case M88E1000_PHY_SPEC_CTRL: | 4208 | case M88E1000_PHY_SPEC_CTRL: |
@@ -4200,10 +4219,9 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | |||
4200 | case PHY_CTRL: | 4219 | case PHY_CTRL: |
4201 | if (mii_reg & MII_CR_POWER_DOWN) | 4220 | if (mii_reg & MII_CR_POWER_DOWN) |
4202 | break; | 4221 | break; |
4203 | if (netif_running(adapter->netdev)) { | 4222 | if (netif_running(adapter->netdev)) |
4204 | e1000_down(adapter); | 4223 | e1000_reinit_locked(adapter); |
4205 | e1000_up(adapter); | 4224 | else |
4206 | } else | ||
4207 | e1000_reset(adapter); | 4225 | e1000_reset(adapter); |
4208 | break; | 4226 | break; |
4209 | } | 4227 | } |
@@ -4462,8 +4480,10 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) | |||
4462 | 4480 | ||
4463 | netif_device_detach(netdev); | 4481 | netif_device_detach(netdev); |
4464 | 4482 | ||
4465 | if (netif_running(netdev)) | 4483 | if (netif_running(netdev)) { |
4484 | WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); | ||
4466 | e1000_down(adapter); | 4485 | e1000_down(adapter); |
4486 | } | ||
4467 | 4487 | ||
4468 | #ifdef CONFIG_PM | 4488 | #ifdef CONFIG_PM |
4469 | /* Implement our own version of pci_save_state(pdev) because pci- | 4489 | /* Implement our own version of pci_save_state(pdev) because pci- |