diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 3a9d6a8b90a20a887b32f1e3befae76a183417ea..635a5856102b9d42c830a37067e21abfc0435b87 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -3975,12 +3975,17 @@ bnx2_reset_task(void *data)
 {
 	struct bnx2 *bp = data;
 
+	if (!netif_running(bp->dev))
+		return;
+
+	bp->in_reset_task = 1;
 	bnx2_netif_stop(bp);
 
 	bnx2_init_nic(bp);
 
 	atomic_set(&bp->intr_sem, 1);
 	bnx2_netif_start(bp);
+	bp->in_reset_task = 0;
 }
 
 static void
@@ -4172,7 +4177,13 @@ bnx2_close(struct net_device *dev)
 	struct bnx2 *bp = dev->priv;
 	u32 reset_code;
 
-	flush_scheduled_work();
+	/* Calling flush_scheduled_work() may deadlock because
+	 * linkwatch_event() may be on the workqueue and it will try to get
+	 * the rtnl_lock which we are holding.
+	 */
+	while (bp->in_reset_task)
+		msleep(1);
+
 	bnx2_netif_stop(bp);
 	del_timer_sync(&bp->timer);
 	if (bp->wol)
@@ -5453,6 +5464,8 @@ bnx2_remove_one(struct pci_dev *pdev)
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct bnx2 *bp = dev->priv;
 
+	flush_scheduled_work();
+
 	unregister_netdev(dev);
 
 	if (bp->regview)
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 8214a2853d0df92a71545348bb70a506fce23ee4..63b94ca0018b280998e64e5eaacf0e857be999df 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -3874,6 +3874,7 @@ struct bnx2 {
 	int			timer_interval;
 	struct			timer_list timer;
 	struct work_struct	reset_task;
+	int			in_reset_task;
 
 	/* Used to synchronize phy accesses. */
 	spinlock_t		phy_lock;