aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ti/wlcore/ps.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ti/wlcore/ps.c')
-rw-r--r--drivers/net/wireless/ti/wlcore/ps.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c
index 756eee2257b..46d36fd30eb 100644
--- a/drivers/net/wireless/ti/wlcore/ps.c
+++ b/drivers/net/wireless/ti/wlcore/ps.c
@@ -28,11 +28,14 @@
#define WL1271_WAKEUP_TIMEOUT 500
+#define ELP_ENTRY_DELAY 5
+
void wl1271_elp_work(struct work_struct *work)
{
struct delayed_work *dwork;
struct wl1271 *wl;
struct wl12xx_vif *wlvif;
+ int ret;
dwork = container_of(work, struct delayed_work, work);
wl = container_of(dwork, struct wl1271, elp_work);
@@ -61,7 +64,12 @@ void wl1271_elp_work(struct work_struct *work)
}
wl1271_debug(DEBUG_PSM, "chip to elp");
- wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP);
+ ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP);
+ if (ret < 0) {
+ wl12xx_queue_recovery_work(wl);
+ goto out;
+ }
+
set_bit(WL1271_FLAG_IN_ELP, &wl->flags);
out:
@@ -72,8 +80,9 @@ out:
void wl1271_ps_elp_sleep(struct wl1271 *wl)
{
struct wl12xx_vif *wlvif;
+ u32 timeout;
- if (wl->quirks & WLCORE_QUIRK_NO_ELP)
+ if (wl->sleep_auth != WL1271_PSM_ELP)
return;
/* we shouldn't get consecutive sleep requests */
@@ -89,8 +98,13 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
return;
}
+ if (wl->conf.conn.forced_ps)
+ timeout = ELP_ENTRY_DELAY;
+ else
+ timeout = wl->conf.conn.dynamic_ps_timeout;
+
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
- msecs_to_jiffies(wl->conf.conn.dynamic_ps_timeout));
+ msecs_to_jiffies(timeout));
}
int wl1271_ps_elp_wakeup(struct wl1271 *wl)
@@ -127,7 +141,11 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
wl->elp_compl = &compl;
spin_unlock_irqrestore(&wl->wl_lock, flags);
- wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
+ ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
+ if (ret < 0) {
+ wl12xx_queue_recovery_work(wl);
+ goto err;
+ }
if (!pending) {
ret = wait_for_completion_timeout(
@@ -185,8 +203,12 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
set_bit(WLVIF_FLAG_IN_PS, &wlvif->flags);
- /* enable beacon early termination. Not relevant for 5GHz */
- if (wlvif->band == IEEE80211_BAND_2GHZ) {
+ /*
+ * enable beacon early termination.
+ * Not relevant for 5GHz and for high rates.
+ */
+ if ((wlvif->band == IEEE80211_BAND_2GHZ) &&
+ (wlvif->basic_rate < CONF_HW_BIT_RATE_9MBPS)) {
ret = wl1271_acx_bet_enable(wl, wlvif, true);
if (ret < 0)
return ret;
@@ -196,7 +218,8 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
wl1271_debug(DEBUG_PSM, "leaving psm");
/* disable beacon early termination */
- if (wlvif->band == IEEE80211_BAND_2GHZ) {
+ if ((wlvif->band == IEEE80211_BAND_2GHZ) &&
+ (wlvif->basic_rate < CONF_HW_BIT_RATE_9MBPS)) {
ret = wl1271_acx_bet_enable(wl, wlvif, false);
if (ret < 0)
return ret;