diff options
author | Juuso Oikarinen <juuso.oikarinen@nokia.com> | 2009-10-08 21:56:21 +0300 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-10-27 16:47:49 -0400 |
commit | 37b70a81855e4a2e66716804ae55ff717520e7fb (patch) | |
tree | aa6c7c9ea6928542d1124a3fd8c6c4010caa10a6 /drivers/net/wireless/wl12xx | |
parent | 1e2b79761d551c545225e1fa6e7d144f7e804898 (diff) |
wl1271: Implement delayed entry into ELP
Implement delayed entry into ELP. This will promote the following:
- Less redundant sleep/wake cycles (better perf)
- Avoids known firmware issues with going to ELP too fast after an
operation
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Vidhya Govindan <vidhya.govindan@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_ps.c | 46 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_ps.h | 2 |
4 files changed, 35 insertions, 15 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index e575dcc9df2..c455dcbae52 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -373,6 +373,7 @@ struct wl1271 { bool elp; struct completion *elp_compl; + struct delayed_work elp_work; /* we can be in psm, but not in elp, we have to differentiate */ bool psm; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 3d629daf224..cc5c3285dea 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1226,6 +1226,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) skb_queue_head_init(&wl->tx_queue); INIT_WORK(&wl->filter_work, wl1271_filter_work); + INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); wl->channel = WL1271_DEFAULT_CHANNEL; wl->scanning = false; wl->default_key = 0; diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index 1dc74b0c773..0f6ea16cae8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c @@ -27,25 +27,43 @@ #define WL1271_WAKEUP_TIMEOUT 500 -/* Routines to toggle sleep mode while in ELP */ -void wl1271_ps_elp_sleep(struct wl1271 *wl) +void wl1271_elp_work(struct work_struct *work) { + struct delayed_work *dwork; + struct wl1271 *wl; + + dwork = container_of(work, struct delayed_work, work); + wl = container_of(dwork, struct wl1271, elp_work); + + wl1271_debug(DEBUG_PSM, "elp work"); + + mutex_lock(&wl->mutex); + /* - * FIXME: due to a problem in the firmware (causing a firmware - * crash), ELP entry is prevented below. Remove the "true" to - * re-enable ELP entry. + * FIXME: below, by means of the "true", ELP has been disabled for now + * to work around a firmware bug. To be enabled upon receiving a new + * firmware version. */ if (true || wl->elp || !wl->psm) - return; + goto out; - /* - * Go to ELP unless there is work already pending - pending work - * will immediately wakeup the chipset anyway. - */ - if (!work_pending(&wl->irq_work) && !work_pending(&wl->tx_work)) { - wl1271_debug(DEBUG_PSM, "chip to elp"); - wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); - wl->elp = true; + wl1271_debug(DEBUG_PSM, "chip to elp"); + wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); + wl->elp = true; + +out: + mutex_unlock(&wl->mutex); +} + +#define ELP_ENTRY_DELAY 5 + +/* Routines to toggle sleep mode while in ELP */ +void wl1271_ps_elp_sleep(struct wl1271 *wl) +{ + if (wl->psm) { + cancel_delayed_work(&wl->elp_work); + ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, + msecs_to_jiffies(ELP_ENTRY_DELAY)); } } diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h index de2bd3c7dc9..779653d0ae8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.h +++ b/drivers/net/wireless/wl12xx/wl1271_ps.h @@ -30,6 +30,6 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode); void wl1271_ps_elp_sleep(struct wl1271 *wl); int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); - +void wl1271_elp_work(struct work_struct *work); #endif /* __WL1271_PS_H__ */ |