|
@@ -43,6 +43,10 @@ void wl1271_elp_work(struct work_struct *work)
|
|
|
if (unlikely(wl->state == WL1271_STATE_OFF))
|
|
|
goto out;
|
|
|
|
|
|
+ /* our work might have been already cancelled */
|
|
|
+ if (unlikely(!test_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)))
|
|
|
+ goto out;
|
|
|
+
|
|
|
if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) ||
|
|
|
(!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
|
|
|
!test_bit(WL1271_FLAG_IDLE, &wl->flags)))
|
|
@@ -61,12 +65,16 @@ out:
|
|
|
/* Routines to toggle sleep mode while in ELP */
|
|
|
void wl1271_ps_elp_sleep(struct wl1271 *wl)
|
|
|
{
|
|
|
- if (test_bit(WL1271_FLAG_PSM, &wl->flags) ||
|
|
|
- test_bit(WL1271_FLAG_IDLE, &wl->flags)) {
|
|
|
- cancel_delayed_work(&wl->elp_work);
|
|
|
- ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
|
|
|
- msecs_to_jiffies(ELP_ENTRY_DELAY));
|
|
|
- }
|
|
|
+ /* we shouldn't get consecutive sleep requests */
|
|
|
+ if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)))
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
|
|
|
+ !test_bit(WL1271_FLAG_IDLE, &wl->flags))
|
|
|
+ return;
|
|
|
+
|
|
|
+ ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
|
|
|
+ msecs_to_jiffies(ELP_ENTRY_DELAY));
|
|
|
}
|
|
|
|
|
|
int wl1271_ps_elp_wakeup(struct wl1271 *wl)
|
|
@@ -77,6 +85,16 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
|
|
|
u32 start_time = jiffies;
|
|
|
bool pending = false;
|
|
|
|
|
|
+ /*
|
|
|
+ * we might try to wake up even if we didn't go to sleep
|
|
|
+ * before (e.g. on boot)
|
|
|
+ */
|
|
|
+ if (!test_and_clear_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* don't cancel_sync as it might contend for a mutex and deadlock */
|
|
|
+ cancel_delayed_work(&wl->elp_work);
|
|
|
+
|
|
|
if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
|
|
|
return 0;
|
|
|
|