summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2012-06-21 18:10:49 +0300
committerLuciano Coelho <coelho@ti.com>2012-06-23 09:32:31 +0300
commitea0a3cf95ed8839ce6f11bf9a050e6333bfc27d6 (patch)
tree0875b9b16efc71867399521662eb208f9147844a /drivers
parent1d23396d9df0a9543b2ba5c288f4914ad1f19e46 (diff)
downloadlinux-stable-ea0a3cf95ed8839ce6f11bf9a050e6333bfc27d6.tar.gz
linux-stable-ea0a3cf95ed8839ce6f11bf9a050e6333bfc27d6.tar.bz2
linux-stable-ea0a3cf95ed8839ce6f11bf9a050e6333bfc27d6.zip
wlcore: force recovery on resume if suspended without recovering
If an error is detected after mac80211 is already suspended, the recovery work will not be queued. This will leave the driver in a bad state on resume. Detect this in the resume op and re-queue a recovery. Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 0df28d5cb331..0b51522d8eae 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -1707,7 +1707,7 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
struct wl1271 *wl = hw->priv;
struct wl12xx_vif *wlvif;
unsigned long flags;
- bool run_irq_work = false;
+ bool run_irq_work = false, pending_recovery;
wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d",
wl->wow_enabled);
@@ -1723,17 +1723,33 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
run_irq_work = true;
spin_unlock_irqrestore(&wl->wl_lock, flags);
+ /* test the recovery flag before calling any SDIO functions */
+ pending_recovery = test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS,
+ &wl->flags);
+
if (run_irq_work) {
wl1271_debug(DEBUG_MAC80211,
"run postponed irq_work directly");
- wl1271_irq(0, wl);
+
+ /* don't talk to the HW if recovery is pending */
+ if (!pending_recovery)
+ wl1271_irq(0, wl);
+
wlcore_enable_interrupts(wl);
}
mutex_lock(&wl->mutex);
+ if (pending_recovery) {
+ wl1271_warning("queuing forgotten recovery on resume");
+ ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ goto out;
+ }
+
wl12xx_for_each_wlvif(wl, wlvif) {
wl1271_configure_resume(wl, wlvif);
}
+
+out:
wl->wow_enabled = false;
mutex_unlock(&wl->mutex);