aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/bnx2.c15
-rw-r--r--drivers/net/bnx2.h1
2 files changed, 15 insertions, 1 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 3a9d6a8b90a2..635a5856102b 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -3975,12 +3975,17 @@ bnx2_reset_task(void *data)
3975{ 3975{
3976 struct bnx2 *bp = data; 3976 struct bnx2 *bp = data;
3977 3977
3978 if (!netif_running(bp->dev))
3979 return;
3980
3981 bp->in_reset_task = 1;
3978 bnx2_netif_stop(bp); 3982 bnx2_netif_stop(bp);
3979 3983
3980 bnx2_init_nic(bp); 3984 bnx2_init_nic(bp);
3981 3985
3982 atomic_set(&bp->intr_sem, 1); 3986 atomic_set(&bp->intr_sem, 1);
3983 bnx2_netif_start(bp); 3987 bnx2_netif_start(bp);
3988 bp->in_reset_task = 0;
3984} 3989}
3985 3990
3986static void 3991static void
@@ -4172,7 +4177,13 @@ bnx2_close(struct net_device *dev)
4172 struct bnx2 *bp = dev->priv; 4177 struct bnx2 *bp = dev->priv;
4173 u32 reset_code; 4178 u32 reset_code;
4174 4179
4175 flush_scheduled_work(); 4180 /* Calling flush_scheduled_work() may deadlock because
4181 * linkwatch_event() may be on the workqueue and it will try to get
4182 * the rtnl_lock which we are holding.
4183 */
4184 while (bp->in_reset_task)
4185 msleep(1);
4186
4176 bnx2_netif_stop(bp); 4187 bnx2_netif_stop(bp);
4177 del_timer_sync(&bp->timer); 4188 del_timer_sync(&bp->timer);
4178 if (bp->wol) 4189 if (bp->wol)
@@ -5453,6 +5464,8 @@ bnx2_remove_one(struct pci_dev *pdev)
5453 struct net_device *dev = pci_get_drvdata(pdev); 5464 struct net_device *dev = pci_get_drvdata(pdev);
5454 struct bnx2 *bp = dev->priv; 5465 struct bnx2 *bp = dev->priv;
5455 5466
5467 flush_scheduled_work();
5468
5456 unregister_netdev(dev); 5469 unregister_netdev(dev);
5457 5470
5458 if (bp->regview) 5471 if (bp->regview)
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 8214a2853d0d..63b94ca0018b 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -3874,6 +3874,7 @@ struct bnx2 {
3874 int timer_interval; 3874 int timer_interval;
3875 struct timer_list timer; 3875 struct timer_list timer;
3876 struct work_struct reset_task; 3876 struct work_struct reset_task;
3877 int in_reset_task;
3877 3878
3878 /* Used to synchronize phy accesses. */ 3879 /* Used to synchronize phy accesses. */
3879 spinlock_t phy_lock; 3880 spinlock_t phy_lock;