wl1271: Work around AP's with broken ps-poll functionality
Some AP's (such as Zyxel Prestige 600) have totally broken ps-poll functionality. When powersave is enabled, these AP's will set the TIM bit for a STA in beacons, but when the STA responds with a ps-poll, the AP does not respond with data. The wl1271 firmware is able to send an indication to the host, when this problem occurs. This patch adds implementation, which temporarily disables power-save in response to this indication, allowing the AP to transmit whatever data it has buffered for the STA / whatever data is inbound at that time. This patch does not make these AP's work reliably in PSM, but improves the chances of inbound data getting through. The side effect of this patch is increased power consumption when using a faulty AP. Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com> Reviewed-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com> Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
committed by
John W. Linville
parent
849923f43c
commit
90494a90be
@ -233,7 +233,8 @@ static struct conf_drv_settings default_conf = {
|
||||
.beacon_rx_timeout = 10000,
|
||||
.broadcast_timeout = 20000,
|
||||
.rx_broadcast_in_ps = 1,
|
||||
.ps_poll_threshold = 20,
|
||||
.ps_poll_threshold = 10,
|
||||
.ps_poll_recovery_period = 700,
|
||||
.bet_enable = CONF_BET_MODE_ENABLE,
|
||||
.bet_max_consecutive = 10,
|
||||
.psm_entry_retries = 3,
|
||||
@ -955,6 +956,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
|
||||
|
||||
cancel_work_sync(&wl->irq_work);
|
||||
cancel_work_sync(&wl->tx_work);
|
||||
cancel_delayed_work_sync(&wl->pspoll_work);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
@ -1260,6 +1262,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
wl1271_warning("idle mode change failed %d", ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* if mac80211 changes the PSM mode, make sure the mode is not
|
||||
* incorrectly changed after the pspoll failure active window.
|
||||
*/
|
||||
if (changed & IEEE80211_CONF_CHANGE_PS)
|
||||
clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags);
|
||||
|
||||
if (conf->flags & IEEE80211_CONF_PS &&
|
||||
!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
|
||||
set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
|
||||
@ -1766,6 +1775,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
wl->aid = bss_conf->aid;
|
||||
set_assoc = true;
|
||||
|
||||
wl->ps_poll_failures = 0;
|
||||
|
||||
/*
|
||||
* use basic rates from AP, and determine lowest rate
|
||||
* to use with control frames.
|
||||
@ -2390,6 +2401,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
|
||||
skb_queue_head_init(&wl->tx_queue);
|
||||
|
||||
INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
|
||||
INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work);
|
||||
wl->channel = WL1271_DEFAULT_CHANNEL;
|
||||
wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
|
||||
wl->default_key = 0;
|
||||
|
Reference in New Issue
Block a user