Commit f1d63a59 authored by Eyal Shapira's avatar Eyal Shapira Committed by Luciano Coelho

wl12xx: add support for HW dynamic PS

FW now supports dynamic PS so we don't need to use mac80211 support.
FW will go to PSM after a specified timeout with no Rx/Tx traffic.
- Changed FW API to include new PS mode (AUTO_MODE) and including timeout parameter
- The default PS mode would be dynamic PS
- Default timeout is 100ms (same as it used to be in mac80211)
- Avoid using mac80211 APIs to disable/enable dynamic PS as we're not
using mac80211 PS control anymore.
- COEX is handled by the FW while in dynamic PS so removed
handling of SOFT_GEMINI
Signed-off-by: default avatarEyal Shapira <eyal@wizery.com>
Signed-off-by: default avatarEliad Peller <eliad@wizery.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent d6bf9ada
...@@ -996,7 +996,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) ...@@ -996,7 +996,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable)
} }
int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 ps_mode) u8 ps_mode, u16 auto_ps_timeout)
{ {
struct wl1271_cmd_ps_params *ps_params = NULL; struct wl1271_cmd_ps_params *ps_params = NULL;
int ret = 0; int ret = 0;
...@@ -1011,6 +1011,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, ...@@ -1011,6 +1011,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
ps_params->role_id = wlvif->role_id; ps_params->role_id = wlvif->role_id;
ps_params->ps_mode = ps_mode; ps_params->ps_mode = ps_mode;
ps_params->auto_ps_timeout = auto_ps_timeout;
ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
sizeof(*ps_params), 0); sizeof(*ps_params), 0);
......
...@@ -51,7 +51,7 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); ...@@ -51,7 +51,7 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 ps_mode); u8 ps_mode, u16 auto_ps_timeout);
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
size_t len); size_t len);
int wl1271_cmd_template_set(struct wl1271 *wl, u8 role_id, int wl1271_cmd_template_set(struct wl1271 *wl, u8 role_id,
...@@ -400,6 +400,7 @@ struct wl1271_tim { ...@@ -400,6 +400,7 @@ struct wl1271_tim {
} __packed; } __packed;
enum wl1271_cmd_ps_mode { enum wl1271_cmd_ps_mode {
STATION_AUTO_PS_MODE, /* Dynamic Power Save */
STATION_ACTIVE_MODE, STATION_ACTIVE_MODE,
STATION_POWER_SAVE_MODE STATION_POWER_SAVE_MODE
}; };
...@@ -409,7 +410,7 @@ struct wl1271_cmd_ps_params { ...@@ -409,7 +410,7 @@ struct wl1271_cmd_ps_params {
u8 role_id; u8 role_id;
u8 ps_mode; /* STATION_* */ u8 ps_mode; /* STATION_* */
u8 padding[2]; u16 auto_ps_timeout;
} __packed; } __packed;
/* HW encryption keys */ /* HW encryption keys */
......
...@@ -914,6 +914,12 @@ struct conf_conn_settings { ...@@ -914,6 +914,12 @@ struct conf_conn_settings {
*/ */
u8 psm_entry_nullfunc_retries; u8 psm_entry_nullfunc_retries;
/*
* Specifies the dynamic PS timeout in ms that will be used
* by the FW when in AUTO_PS mode
*/
u16 dynamic_ps_timeout;
/* /*
* *
* Specifies the interval of the connection keep-alive null-func * Specifies the interval of the connection keep-alive null-func
......
...@@ -78,21 +78,13 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) ...@@ -78,21 +78,13 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
u8 enable) u8 enable)
{ {
struct ieee80211_vif *vif;
struct wl12xx_vif *wlvif; struct wl12xx_vif *wlvif;
if (enable) { if (enable) {
/* disable dynamic PS when requested by the firmware */
wl12xx_for_each_wlvif_sta(wl, wlvif) {
vif = wl12xx_wlvif_to_vif(wlvif);
ieee80211_disable_dyn_ps(vif);
}
set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
} else { } else {
clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
wl12xx_for_each_wlvif_sta(wl, wlvif) { wl12xx_for_each_wlvif_sta(wl, wlvif) {
vif = wl12xx_wlvif_to_vif(wlvif);
ieee80211_enable_dyn_ps(vif);
wl1271_recalc_rx_streaming(wl, wlvif); wl1271_recalc_rx_streaming(wl, wlvif);
} }
} }
......
/* /*
* This file is part of wl1271 * This file is part of wl1271
* *
...@@ -240,6 +241,7 @@ static struct conf_drv_settings default_conf = { ...@@ -240,6 +241,7 @@ static struct conf_drv_settings default_conf = {
.psm_entry_retries = 8, .psm_entry_retries = 8,
.psm_exit_retries = 16, .psm_exit_retries = 16,
.psm_entry_nullfunc_retries = 3, .psm_entry_nullfunc_retries = 3,
.dynamic_ps_timeout = 100,
.keep_alive_interval = 55000, .keep_alive_interval = 55000,
.max_listen_interval = 20, .max_listen_interval = 20,
}, },
...@@ -2142,10 +2144,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, ...@@ -2142,10 +2144,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
wl1271_info("down"); wl1271_info("down");
/* enable dyn ps just in case (if left on due to fw crash etc) */
if (wlvif->bss_type == BSS_TYPE_STA_BSS)
ieee80211_enable_dyn_ps(vif);
if (wl->scan.state != WL1271_SCAN_STATE_IDLE && if (wl->scan.state != WL1271_SCAN_STATE_IDLE &&
wl->scan_vif == vif) { wl->scan_vif == vif) {
wl->scan.state = WL1271_SCAN_STATE_IDLE; wl->scan.state = WL1271_SCAN_STATE_IDLE;
...@@ -3694,9 +3692,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, ...@@ -3694,9 +3692,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
dev_kfree_skb(wlvif->probereq); dev_kfree_skb(wlvif->probereq);
wlvif->probereq = NULL; wlvif->probereq = NULL;
/* re-enable dynamic ps - just in case */
ieee80211_enable_dyn_ps(vif);
/* revert back to minimum rates for the current band */ /* revert back to minimum rates for the current band */
wl1271_set_band_rate(wl, wlvif); wl1271_set_band_rate(wl, wlvif);
wlvif->basic_rate = wlvif->basic_rate =
...@@ -3827,10 +3822,9 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, ...@@ -3827,10 +3822,9 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
/* If we want to go in PSM but we're not there yet */ /* If we want to go in PSM but we're not there yet */
if (test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags) && if (test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags) &&
!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { !test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) {
enum wl1271_cmd_ps_mode mode;
mode = STATION_POWER_SAVE_MODE; ret = wl1271_ps_set_mode(wl, wlvif,
ret = wl1271_ps_set_mode(wl, wlvif, mode, STATION_AUTO_PS_MODE,
wlvif->basic_rate, wlvif->basic_rate,
true); true);
if (ret < 0) if (ret < 0)
...@@ -4976,6 +4970,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) ...@@ -4976,6 +4970,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
IEEE80211_HW_SUPPORTS_UAPSD | IEEE80211_HW_SUPPORTS_UAPSD |
IEEE80211_HW_HAS_RATE_CONTROL | IEEE80211_HW_HAS_RATE_CONTROL |
IEEE80211_HW_CONNECTION_MONITOR | IEEE80211_HW_CONNECTION_MONITOR |
......
...@@ -163,10 +163,12 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, ...@@ -163,10 +163,12 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
enum wl1271_cmd_ps_mode mode, u32 rates, bool send) enum wl1271_cmd_ps_mode mode, u32 rates, bool send)
{ {
int ret; int ret;
u16 timeout = wl->conf.conn.dynamic_ps_timeout;
switch (mode) { switch (mode) {
case STATION_POWER_SAVE_MODE: case STATION_AUTO_PS_MODE:
wl1271_debug(DEBUG_PSM, "entering psm"); wl1271_debug(DEBUG_PSM, "entering psm (mode=%d,timeout=%u)",
mode, timeout);
ret = wl1271_acx_wake_up_conditions(wl, wlvif); ret = wl1271_acx_wake_up_conditions(wl, wlvif);
if (ret < 0) { if (ret < 0) {
...@@ -174,14 +176,13 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, ...@@ -174,14 +176,13 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return ret; return ret;
} }
ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_POWER_SAVE_MODE); ret = wl1271_cmd_ps_mode(wl, wlvif, mode, timeout);
if (ret < 0) if (ret < 0)
return ret; return ret;
set_bit(WLVIF_FLAG_PSM, &wlvif->flags); set_bit(WLVIF_FLAG_PSM, &wlvif->flags);
break; break;
case STATION_ACTIVE_MODE: case STATION_ACTIVE_MODE:
default:
wl1271_debug(DEBUG_PSM, "leaving psm"); wl1271_debug(DEBUG_PSM, "leaving psm");
/* disable beacon early termination */ /* disable beacon early termination */
...@@ -191,12 +192,16 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, ...@@ -191,12 +192,16 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return ret; return ret;
} }
ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_ACTIVE_MODE); ret = wl1271_cmd_ps_mode(wl, wlvif, mode, 0);
if (ret < 0) if (ret < 0)
return ret; return ret;
clear_bit(WLVIF_FLAG_PSM, &wlvif->flags); clear_bit(WLVIF_FLAG_PSM, &wlvif->flags);
break; break;
case STATION_POWER_SAVE_MODE:
default:
wl1271_warning("trying to set ps to unsupported mode %d", mode);
ret = -EINVAL;
} }
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment