aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/hostap
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-06-12 05:22:02 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-12 05:22:02 -0400
commit4bb073c0e32a0862bdb5215d11af19f6c0180c98 (patch)
tree009d95592e3813346c75129bb19d140d393ca913 /drivers/net/wireless/hostap
parent7afb380db43ed137b7f67e0e3c3e5afd1ecde730 (diff)
net: Eliminate flush_scheduled_work() calls while RTNL is held.
If the RTNL is held when we invoke flush_scheduled_work() we could deadlock. One such case is linkwatch, it is a work struct which tries to grab the RTNL semaphore. The most common case are net driver ->stop() methods. The simplest conversion is to instead use cancel_{delayed_}work_sync() explicitly on the various work struct the driver uses. This is an OK transformation because these work structs are doing things like resetting the chip, restarting link negotiation, and so forth. And if we're bringing down the device, we're about to turn the chip off and reset it anways. So if we cancel a pending work event, that's fine here. Some drivers were working around this deadlock by using a msleep() polling loop of some sort, and those cases are converted to instead use cancel_{delayed_}work_sync() as well. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/hostap')
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 20d387f6658c..f7aec9309d04 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -682,7 +682,13 @@ static int prism2_close(struct net_device *dev)
682 netif_device_detach(dev); 682 netif_device_detach(dev);
683 } 683 }
684 684
685 flush_scheduled_work(); 685 cancel_work_sync(&local->reset_queue);
686 cancel_work_sync(&local->set_multicast_list_queue);
687 cancel_work_sync(&local->set_tim_queue);
688#ifndef PRISM2_NO_STATION_MODES
689 cancel_work_sync(&local->info_queue);
690#endif
691 cancel_work_sync(&local->comms_qual_update);
686 692
687 module_put(local->hw_module); 693 module_put(local->hw_module);
688 694