aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/s2io.c
diff options
context:
space:
mode:
authorFrancois Romieu <romieu@fr.zoreil.com>2007-02-15 17:37:50 -0500
committerJeff Garzik <jeff@garzik.org>2007-02-20 11:18:13 -0500
commit22747d6b41f31c71abc2b351bc9f6bfa6bae5d5e (patch)
tree543f2cd2d0d73795368edb945abed28a88d1cf73 /drivers/net/s2io.c
parent83cbb4d2577174e27a91e63a47a2a27c3af50d4e (diff)
s2io: RTNL and flush_scheduled_work deadlock
Mantra: don't use flush_scheduled_work with RTNL held. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/s2io.c')
-rw-r--r--drivers/net/s2io.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index e8e0d94e9bdd..fd85648d98d1 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -3758,7 +3758,6 @@ static int s2io_close(struct net_device *dev)
3758{ 3758{
3759 struct s2io_nic *sp = dev->priv; 3759 struct s2io_nic *sp = dev->priv;
3760 3760
3761 flush_scheduled_work();
3762 netif_stop_queue(dev); 3761 netif_stop_queue(dev);
3763 /* Reset card, kill tasklet and free Tx and Rx buffers. */ 3762 /* Reset card, kill tasklet and free Tx and Rx buffers. */
3764 s2io_card_down(sp); 3763 s2io_card_down(sp);
@@ -5847,9 +5846,14 @@ static void s2io_set_link(struct work_struct *work)
5847 register u64 val64; 5846 register u64 val64;
5848 u16 subid; 5847 u16 subid;
5849 5848
5849 rtnl_lock();
5850
5851 if (!netif_running(dev))
5852 goto out_unlock;
5853
5850 if (test_and_set_bit(0, &(nic->link_state))) { 5854 if (test_and_set_bit(0, &(nic->link_state))) {
5851 /* The card is being reset, no point doing anything */ 5855 /* The card is being reset, no point doing anything */
5852 return; 5856 goto out_unlock;
5853 } 5857 }
5854 5858
5855 subid = nic->pdev->subsystem_device; 5859 subid = nic->pdev->subsystem_device;
@@ -5903,6 +5907,9 @@ static void s2io_set_link(struct work_struct *work)
5903 s2io_link(nic, LINK_DOWN); 5907 s2io_link(nic, LINK_DOWN);
5904 } 5908 }
5905 clear_bit(0, &(nic->link_state)); 5909 clear_bit(0, &(nic->link_state));
5910
5911out_unlock:
5912 rtnl_lock();
5906} 5913}
5907 5914
5908static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, 5915static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
@@ -6356,6 +6363,11 @@ static void s2io_restart_nic(struct work_struct *work)
6356 struct s2io_nic *sp = container_of(work, struct s2io_nic, rst_timer_task); 6363 struct s2io_nic *sp = container_of(work, struct s2io_nic, rst_timer_task);
6357 struct net_device *dev = sp->dev; 6364 struct net_device *dev = sp->dev;
6358 6365
6366 rtnl_lock();
6367
6368 if (!netif_running(dev))
6369 goto out_unlock;
6370
6359 s2io_card_down(sp); 6371 s2io_card_down(sp);
6360 if (s2io_card_up(sp)) { 6372 if (s2io_card_up(sp)) {
6361 DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n", 6373 DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
@@ -6364,7 +6376,8 @@ static void s2io_restart_nic(struct work_struct *work)
6364 netif_wake_queue(dev); 6376 netif_wake_queue(dev);
6365 DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n", 6377 DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n",
6366 dev->name); 6378 dev->name);
6367 6379out_unlock:
6380 rtnl_unlock();
6368} 6381}
6369 6382
6370/** 6383/**
@@ -7173,6 +7186,8 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
7173 return; 7186 return;
7174 } 7187 }
7175 7188
7189 flush_scheduled_work();
7190
7176 sp = dev->priv; 7191 sp = dev->priv;
7177 unregister_netdev(dev); 7192 unregister_netdev(dev);
7178 7193