diff options
author | Eliad Peller <eliad@wizery.com> | 2011-04-02 19:01:59 -0400 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2011-05-02 03:25:27 -0400 |
commit | a665d6e260f0233aac73f74d15bb6a029cc5ec47 (patch) | |
tree | d795995e4796d1b14e9a096ac2ca0bbdaf43b78c /drivers/net/wireless/wl12xx | |
parent | c75bbcdb200e2815c855e42a4685d170858af306 (diff) |
wl12xx: avoid premature elp entrance
The elp_work is being enqueued on wl1271_ps_elp_sleep, but doesn't get
cancelled on wl1271_ps_elp_wakeup. This might cause immediate entrance
to elp when the wl->mutex is being released, rather than using the delayed
enqueueing optimization.
Cancel elp_work on wakeup request, and add a new WL1271_FLAG_ELP_REQUESTED
flag to further synchronize the elp actions.
[Fixed a couple of typos in some comments -- Luca]
Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx')
-rw-r--r-- | drivers/net/wireless/wl12xx/ps.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 1 |
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 */ |
62 | void wl1271_ps_elp_sleep(struct wl1271 *wl) | 66 | void 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 | ||
72 | int wl1271_ps_elp_wakeup(struct wl1271 *wl) | 80 | int 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, |