diff options
author | Juuso Oikarinen <juuso.oikarinen@nokia.com> | 2009-11-17 11:48:37 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-11-18 17:09:20 -0500 |
commit | d5da79ac1f5050cccaa68d814ccce292371f25fa (patch) | |
tree | 2774979009bbc0a4efd5ea3d3a4bb5c03287c6c6 | |
parent | 6b21a2cd315e2e56a1748bd3ef9d910fe4f2e711 (diff) |
wl1251: Implement delayed entry into ELP mode
Implement (slightly) delayed entry into ELP. This will cure several
problems:
- It works around a firmware race condition if ELP is entered too fast
after commands (resulting in ELP timeout -traces)
- It will reduce the number of sleep-wake cycles between already
scheduled events such as interrupts and tx, hence improving
performance (less delay in switching between RX and TX)
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Vidhya Govindan <vidhya.govindan@nokia.com>
Signed-off-by: Kalle Valo <kalle.valo@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251_main.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251_ps.c | 34 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251_ps.h | 1 |
4 files changed, 33 insertions, 5 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index fc2871c5a25b..a839466664f0 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h | |||
@@ -354,6 +354,8 @@ struct wl1251 { | |||
354 | /* is firmware in elp mode */ | 354 | /* is firmware in elp mode */ |
355 | bool elp; | 355 | bool elp; |
356 | 356 | ||
357 | struct delayed_work elp_work; | ||
358 | |||
357 | /* we can be in psm, but not in elp, we have to differentiate */ | 359 | /* we can be in psm, but not in elp, we have to differentiate */ |
358 | bool psm; | 360 | bool psm; |
359 | 361 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 900e6e2796fc..b5e3bdb08448 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -1367,6 +1367,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void) | |||
1367 | skb_queue_head_init(&wl->tx_queue); | 1367 | skb_queue_head_init(&wl->tx_queue); |
1368 | 1368 | ||
1369 | INIT_WORK(&wl->filter_work, wl1251_filter_work); | 1369 | INIT_WORK(&wl->filter_work, wl1251_filter_work); |
1370 | INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work); | ||
1370 | wl->channel = WL1251_DEFAULT_CHANNEL; | 1371 | wl->channel = WL1251_DEFAULT_CHANNEL; |
1371 | wl->scanning = false; | 1372 | wl->scanning = false; |
1372 | wl->default_key = 0; | 1373 | wl->default_key = 0; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c index c3e348a12322..9931b197ff77 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ b/drivers/net/wireless/wl12xx/wl1251_ps.c | |||
@@ -28,17 +28,41 @@ | |||
28 | 28 | ||
29 | #define WL1251_WAKEUP_TIMEOUT 2000 | 29 | #define WL1251_WAKEUP_TIMEOUT 2000 |
30 | 30 | ||
31 | /* Routines to toggle sleep mode while in ELP */ | 31 | void wl1251_elp_work(struct work_struct *work) |
32 | void wl1251_ps_elp_sleep(struct wl1251 *wl) | ||
33 | { | 32 | { |
33 | struct delayed_work *dwork; | ||
34 | struct wl1251 *wl; | ||
35 | |||
36 | dwork = container_of(work, struct delayed_work, work); | ||
37 | wl = container_of(dwork, struct wl1251, elp_work); | ||
38 | |||
39 | wl1251_debug(DEBUG_PSM, "elp work"); | ||
40 | |||
41 | mutex_lock(&wl->mutex); | ||
42 | |||
34 | if (wl->elp || !wl->psm) | 43 | if (wl->elp || !wl->psm) |
35 | return; | 44 | goto out; |
36 | 45 | ||
37 | wl1251_debug(DEBUG_PSM, "chip to elp"); | 46 | wl1251_debug(DEBUG_PSM, "chip to elp"); |
38 | |||
39 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); | 47 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); |
40 | |||
41 | wl->elp = true; | 48 | wl->elp = true; |
49 | |||
50 | out: | ||
51 | mutex_unlock(&wl->mutex); | ||
52 | } | ||
53 | |||
54 | #define ELP_ENTRY_DELAY 5 | ||
55 | |||
56 | /* Routines to toggle sleep mode while in ELP */ | ||
57 | void wl1251_ps_elp_sleep(struct wl1251 *wl) | ||
58 | { | ||
59 | unsigned long delay; | ||
60 | |||
61 | if (wl->psm) { | ||
62 | cancel_delayed_work(&wl->elp_work); | ||
63 | delay = msecs_to_jiffies(ELP_ENTRY_DELAY); | ||
64 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay); | ||
65 | } | ||
42 | } | 66 | } |
43 | 67 | ||
44 | int wl1251_ps_elp_wakeup(struct wl1251 *wl) | 68 | int wl1251_ps_elp_wakeup(struct wl1251 *wl) |
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.h b/drivers/net/wireless/wl12xx/wl1251_ps.h index db036fe12f25..c688ac57aee4 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.h +++ b/drivers/net/wireless/wl12xx/wl1251_ps.h | |||
@@ -31,6 +31,7 @@ | |||
31 | int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode); | 31 | int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode); |
32 | void wl1251_ps_elp_sleep(struct wl1251 *wl); | 32 | void wl1251_ps_elp_sleep(struct wl1251 *wl); |
33 | int wl1251_ps_elp_wakeup(struct wl1251 *wl); | 33 | int wl1251_ps_elp_wakeup(struct wl1251 *wl); |
34 | void wl1251_elp_work(struct work_struct *work); | ||
34 | 35 | ||
35 | 36 | ||
36 | #endif /* __WL1251_PS_H__ */ | 37 | #endif /* __WL1251_PS_H__ */ |