diff options
author | Juuso Oikarinen <juuso.oikarinen@nokia.com> | 2009-10-13 12:47:46 +0300 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-10-27 16:48:09 -0400 |
commit | 11f70f9715f0d8f99eac42d69689e8df15283fea (patch) | |
tree | 92f5e45ca20e554948800aa3beacab00604e8b74 | |
parent | eb5b28d021a1b96050f7af46e9140eb0051cc6d8 (diff) |
wl1271: Implement beacon early termination support
Add support to enable beacon early termination in the firmware. Early
Beacon termination is a feature which allows the radio to be turned off
after TIM IE to save power.
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_acx.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_acx.h | 12 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_conf.h | 23 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_ps.c | 10 |
5 files changed, 77 insertions, 2 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 880c82894f6..44a1237fa79 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -1062,3 +1062,33 @@ out: return ret; } + +int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) +{ + struct wl1271_acx_bet_enable *acx = NULL; + int ret = 0; + + wl1271_debug(DEBUG_ACX, "acx bet enable"); + + if (enable && wl->conf.conn.bet_enable == CONF_BET_MODE_DISABLE) + goto out; + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) { + ret = -ENOMEM; + goto out; + } + + acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE; + acx->max_consecutive = wl->conf.conn.bet_max_consecutive; + + ret = wl1271_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx bet enable failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 73ef2bdf3b7..29fd3635e38 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -946,6 +946,15 @@ struct wl1271_acx_rx_config_opt { u8 reserved; } __attribute__ ((packed)); + +struct wl1271_acx_bet_enable { + struct acx_header header; + + u8 enable; + u8 max_consecutive; + u8 padding[2]; +} __attribute__ ((packed)); + enum { ACX_WAKE_UP_CONDITIONS = 0x0002, ACX_MEM_CFG = 0x0003, @@ -1043,7 +1052,7 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid); int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask); int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); int wl1271_acx_cts_protect(struct wl1271 *wl, - enum acx_ctsprotect_type ctsprotect); + enum acx_ctsprotect_type ctsprotect); int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates); int wl1271_acx_ac_cfg(struct wl1271 *wl); @@ -1054,5 +1063,6 @@ int wl1271_acx_mem_cfg(struct wl1271 *wl); int wl1271_acx_init_mem_config(struct wl1271 *wl); int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); int wl1271_acx_smart_reflex(struct wl1271 *wl); +int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); #endif /* __WL1271_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 5333a273125..00ffa667932 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -603,6 +603,11 @@ enum conf_bcn_filt_mode { CONF_BCN_FILT_MODE_ENABLED = 1 }; +enum conf_bet_mode { + CONF_BET_MODE_DISABLE = 0, + CONF_BET_MODE_ENABLE = 1, +}; + struct conf_conn_settings { /* * Firmware wakeup conditions configuration. The host may set only @@ -689,6 +694,24 @@ struct conf_conn_settings { * Configuration of signal average weights. */ struct conf_sig_weights sig_weights; + + /* + * Specifies if beacon early termination procedure is enabled or + * disabled. + * + * Range: CONF_BET_MODE_* + */ + u8 bet_enable; + + /* + * Specifies the maximum number of consecutive beacons that may be + * early terminated. After this number is reached at least one full + * beacon must be correctly received in FW before beacon ET + * resumes. + * + * Range 0 - 255 + */ + u8 bet_max_consecutive; }; #define CONF_SR_ERR_TBL_MAX_VALUES 14 diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 7f1093cd816..3d2e999ef15 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -219,7 +219,9 @@ static struct conf_drv_settings default_conf = { .rssi_pkt_avg_weight = 10, .snr_bcn_avg_weight = 10, .snr_pkt_avg_weight = 10 - } + }, + .bet_enable = CONF_BET_MODE_ENABLE, + .bet_max_consecutive = 100 }, .init = { .sr_err_tbl = { diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index bb8745d9bd6..507cd91d7ee 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c @@ -130,6 +130,11 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) if (ret < 0) return ret; + /* enable beacon early termination */ + ret = wl1271_acx_bet_enable(wl, true); + if (ret < 0) + return ret; + ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); if (ret < 0) return ret; @@ -147,6 +152,11 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) if (ret < 0) return ret; + /* disable beacon early termination */ + ret = wl1271_acx_bet_enable(wl, false); + if (ret < 0) + return ret; + /* disable beacon filtering */ ret = wl1271_acx_beacon_filter_opt(wl, false); if (ret < 0) |