aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/wl12xx/ps.c30
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h1
2 files changed, 25 insertions, 6 deletions
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index b8deada5d020..b59b67711a17 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -43,6 +43,10 @@ void wl1271_elp_work(struct work_struct *work)
43 if (unlikely(wl->state == WL1271_STATE_OFF)) 43 if (unlikely(wl->state == WL1271_STATE_OFF))
44 goto out; 44 goto out;
45 45
46 /* our work might have been already cancelled */
47 if (unlikely(!test_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)))
48 goto out;
49
46 if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || 50 if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) ||
47 (!test_bit(WL1271_FLAG_PSM, &wl->flags) && 51 (!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
48 !test_bit(WL1271_FLAG_IDLE, &wl->flags))) 52 !test_bit(WL1271_FLAG_IDLE, &wl->flags)))
@@ -61,12 +65,16 @@ out:
61/* Routines to toggle sleep mode while in ELP */ 65/* Routines to toggle sleep mode while in ELP */
62void wl1271_ps_elp_sleep(struct wl1271 *wl) 66void wl1271_ps_elp_sleep(struct wl1271 *wl)
63{ 67{
64 if (test_bit(WL1271_FLAG_PSM, &wl->flags) || 68 /* we shouldn't get consecutive sleep requests */
65 test_bit(WL1271_FLAG_IDLE, &wl->flags)) { 69 if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)))
66 cancel_delayed_work(&wl->elp_work); 70 return;
67 ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, 71
68 msecs_to_jiffies(ELP_ENTRY_DELAY)); 72 if (!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
69 } 73 !test_bit(WL1271_FLAG_IDLE, &wl->flags))
74 return;
75
76 ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
77 msecs_to_jiffies(ELP_ENTRY_DELAY));
70} 78}
71 79
72int wl1271_ps_elp_wakeup(struct wl1271 *wl) 80int wl1271_ps_elp_wakeup(struct wl1271 *wl)
@@ -77,6 +85,16 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
77 u32 start_time = jiffies; 85 u32 start_time = jiffies;
78 bool pending = false; 86 bool pending = false;
79 87
88 /*
89 * we might try to wake up even if we didn't go to sleep
90 * before (e.g. on boot)
91 */
92 if (!test_and_clear_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))
93 return 0;
94
95 /* don't cancel_sync as it might contend for a mutex and deadlock */
96 cancel_delayed_work(&wl->elp_work);
97
80 if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) 98 if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
81 return 0; 99 return 0;
82 100
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 7c521af58e7d..f3de96212b96 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -345,6 +345,7 @@ enum wl12xx_flags {
345 WL1271_FLAG_TX_QUEUE_STOPPED, 345 WL1271_FLAG_TX_QUEUE_STOPPED,
346 WL1271_FLAG_TX_PENDING, 346 WL1271_FLAG_TX_PENDING,
347 WL1271_FLAG_IN_ELP, 347 WL1271_FLAG_IN_ELP,
348 WL1271_FLAG_ELP_REQUESTED,
348 WL1271_FLAG_PSM, 349 WL1271_FLAG_PSM,
349 WL1271_FLAG_PSM_REQUESTED, 350 WL1271_FLAG_PSM_REQUESTED,
350 WL1271_FLAG_IRQ_RUNNING, 351 WL1271_FLAG_IRQ_RUNNING,