diff options
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r-- | drivers/net/tg3.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f2d1dafde087..e7dc653d5bd6 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -69,8 +69,8 @@ | |||
69 | 69 | ||
70 | #define DRV_MODULE_NAME "tg3" | 70 | #define DRV_MODULE_NAME "tg3" |
71 | #define PFX DRV_MODULE_NAME ": " | 71 | #define PFX DRV_MODULE_NAME ": " |
72 | #define DRV_MODULE_VERSION "3.48" | 72 | #define DRV_MODULE_VERSION "3.49" |
73 | #define DRV_MODULE_RELDATE "Jan 16, 2006" | 73 | #define DRV_MODULE_RELDATE "Feb 2, 2006" |
74 | 74 | ||
75 | #define TG3_DEF_MAC_MODE 0 | 75 | #define TG3_DEF_MAC_MODE 0 |
76 | #define TG3_DEF_RX_MODE 0 | 76 | #define TG3_DEF_RX_MODE 0 |
@@ -3482,6 +3482,17 @@ static void tg3_reset_task(void *_data) | |||
3482 | struct tg3 *tp = _data; | 3482 | struct tg3 *tp = _data; |
3483 | unsigned int restart_timer; | 3483 | unsigned int restart_timer; |
3484 | 3484 | ||
3485 | tg3_full_lock(tp, 0); | ||
3486 | tp->tg3_flags |= TG3_FLAG_IN_RESET_TASK; | ||
3487 | |||
3488 | if (!netif_running(tp->dev)) { | ||
3489 | tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; | ||
3490 | tg3_full_unlock(tp); | ||
3491 | return; | ||
3492 | } | ||
3493 | |||
3494 | tg3_full_unlock(tp); | ||
3495 | |||
3485 | tg3_netif_stop(tp); | 3496 | tg3_netif_stop(tp); |
3486 | 3497 | ||
3487 | tg3_full_lock(tp, 1); | 3498 | tg3_full_lock(tp, 1); |
@@ -3494,10 +3505,12 @@ static void tg3_reset_task(void *_data) | |||
3494 | 3505 | ||
3495 | tg3_netif_start(tp); | 3506 | tg3_netif_start(tp); |
3496 | 3507 | ||
3497 | tg3_full_unlock(tp); | ||
3498 | |||
3499 | if (restart_timer) | 3508 | if (restart_timer) |
3500 | mod_timer(&tp->timer, jiffies + 1); | 3509 | mod_timer(&tp->timer, jiffies + 1); |
3510 | |||
3511 | tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; | ||
3512 | |||
3513 | tg3_full_unlock(tp); | ||
3501 | } | 3514 | } |
3502 | 3515 | ||
3503 | static void tg3_tx_timeout(struct net_device *dev) | 3516 | static void tg3_tx_timeout(struct net_device *dev) |
@@ -6786,6 +6799,13 @@ static int tg3_close(struct net_device *dev) | |||
6786 | { | 6799 | { |
6787 | struct tg3 *tp = netdev_priv(dev); | 6800 | struct tg3 *tp = netdev_priv(dev); |
6788 | 6801 | ||
6802 | /* Calling flush_scheduled_work() may deadlock because | ||
6803 | * linkwatch_event() may be on the workqueue and it will try to get | ||
6804 | * the rtnl_lock which we are holding. | ||
6805 | */ | ||
6806 | while (tp->tg3_flags & TG3_FLAG_IN_RESET_TASK) | ||
6807 | msleep(1); | ||
6808 | |||
6789 | netif_stop_queue(dev); | 6809 | netif_stop_queue(dev); |
6790 | 6810 | ||
6791 | del_timer_sync(&tp->timer); | 6811 | del_timer_sync(&tp->timer); |
@@ -10880,6 +10900,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) | |||
10880 | if (dev) { | 10900 | if (dev) { |
10881 | struct tg3 *tp = netdev_priv(dev); | 10901 | struct tg3 *tp = netdev_priv(dev); |
10882 | 10902 | ||
10903 | flush_scheduled_work(); | ||
10883 | unregister_netdev(dev); | 10904 | unregister_netdev(dev); |
10884 | if (tp->regs) { | 10905 | if (tp->regs) { |
10885 | iounmap(tp->regs); | 10906 | iounmap(tp->regs); |
@@ -10901,6 +10922,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) | |||
10901 | if (!netif_running(dev)) | 10922 | if (!netif_running(dev)) |
10902 | return 0; | 10923 | return 0; |
10903 | 10924 | ||
10925 | flush_scheduled_work(); | ||
10904 | tg3_netif_stop(tp); | 10926 | tg3_netif_stop(tp); |
10905 | 10927 | ||
10906 | del_timer_sync(&tp->timer); | 10928 | del_timer_sync(&tp->timer); |