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); |
