summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ti/wlcore/io.c
diff options
context:
space:
mode:
authorIdo Yariv <ido@wizery.com>2012-06-26 18:08:58 (GMT)
committerJohn W. Linville <linville@tuxdriver.com>2012-07-10 16:10:14 (GMT)
commitc24ec83bcac50160c344b3eb0e4c601b6cb4f7e5 (patch)
treebdc42304657804346a0254c780a8572157f2cd31 /drivers/net/wireless/ti/wlcore/io.c
parentd8ae5a257c81e3977cbd2a50f190a601f51d3bdd (diff)
downloadlinux-c24ec83bcac50160c344b3eb0e4c601b6cb4f7e5.tar.xz
wlcore: Prevent processing of work items during op_stop
The interrupt line is disabled in op_stop using disable_irq. Since pending interrupts are synchronized, the mutex has to be released before disabling the interrupt to avoid a deadlock with the interrupt handler. In addition, the internal state of the driver is only set to 'off' after the interrupt is disabled. Otherwise, if an interrupt fires after the state is set but before the interrupt line is disabled, the interrupt handler will not be able to acknowledge the interrupt resulting in an interrupt storm. The driver's operations might be called during recovery. If these acquire the mutex after it was released by op_stop, but before the driver's state is changed, they may queue new work items instead of just failing. This is especially problematic in the case of scans, in which a new scan may be scheduled after all scan requests were cancelled. Signed-off-by: Ido Yariv <ido@wizery.com> Signed-off-by: Arik Nemtsov <arik@wizery.com>
Diffstat (limited to 'drivers/net/wireless/ti/wlcore/io.c')
-rw-r--r--drivers/net/wireless/ti/wlcore/io.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/net/wireless/ti/wlcore/io.c b/drivers/net/wireless/ti/wlcore/io.c
index 9976219..68e74ee 100644
--- a/drivers/net/wireless/ti/wlcore/io.c
+++ b/drivers/net/wireless/ti/wlcore/io.c
@@ -60,6 +60,12 @@ void wlcore_enable_interrupts(struct wl1271 *wl)
}
EXPORT_SYMBOL_GPL(wlcore_enable_interrupts);
+void wlcore_synchronize_interrupts(struct wl1271 *wl)
+{
+ synchronize_irq(wl->irq);
+}
+EXPORT_SYMBOL_GPL(wlcore_synchronize_interrupts);
+
int wlcore_translate_addr(struct wl1271 *wl, int addr)
{
struct wlcore_partition_set *part = &wl->curr_part;