diff options
author | Francois Romieu <romieu@fr.zoreil.com> | 2007-02-15 17:37:50 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-20 11:18:13 -0500 |
commit | 22747d6b41f31c71abc2b351bc9f6bfa6bae5d5e (patch) | |
tree | 543f2cd2d0d73795368edb945abed28a88d1cf73 /drivers/net | |
parent | 83cbb4d2577174e27a91e63a47a2a27c3af50d4e (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')
-rw-r--r-- | drivers/net/s2io.c | 21 |
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 | |||
5911 | out_unlock: | ||
5912 | rtnl_lock(); | ||
5906 | } | 5913 | } |
5907 | 5914 | ||
5908 | static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, | 5915 | static 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 | 6379 | out_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 | ||