diff options
author | Helmut Schaa <helmut.schaa@googlemail.com> | 2012-01-30 09:18:00 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-01-30 15:48:20 -0500 |
commit | 608383bfc04aa222c3e9e896c32f56a5e5deaff0 (patch) | |
tree | cb608bbe456f3aaa030f90977f6f9e60f6b2a413 | |
parent | 2ab694d302b489c5aa49c360dc97149b77c96586 (diff) |
mac80211: Fix incorrect num_sta_ps decrement in ap_sta_ps_end
If the driver blocked this specific STA with the help of
ieee80211_sta_block_awake we won't clear WLAN_STA_PS_STA later but
still decrement num_sta_ps. Hence, the next data frame from this
STA will trigger ap_sta_ps_end again and also decrement num_sta_ps
again leading to an incorrect num_sta_ps counter.
This can result in problems with powersaving clients not waking up
from PS because the TIM calculation might be skipped due to the
incorrect num_sta_ps counter.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | net/mac80211/rx.c | 8 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 4 |
2 files changed, 5 insertions, 7 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 73d213810a37..ab29253fb4f2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1145,19 +1145,15 @@ static void ap_sta_ps_start(struct sta_info *sta) | |||
1145 | 1145 | ||
1146 | static void ap_sta_ps_end(struct sta_info *sta) | 1146 | static void ap_sta_ps_end(struct sta_info *sta) |
1147 | { | 1147 | { |
1148 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
1149 | |||
1150 | atomic_dec(&sdata->bss->num_sta_ps); | ||
1151 | |||
1152 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1148 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1153 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", | 1149 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", |
1154 | sdata->name, sta->sta.addr, sta->sta.aid); | 1150 | sta->sdata->name, sta->sta.addr, sta->sta.aid); |
1155 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1151 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1156 | 1152 | ||
1157 | if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | 1153 | if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { |
1158 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1154 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1159 | printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", | 1155 | printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", |
1160 | sdata->name, sta->sta.addr, sta->sta.aid); | 1156 | sta->sdata->name, sta->sta.addr, sta->sta.aid); |
1161 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1157 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1162 | return; | 1158 | return; |
1163 | } | 1159 | } |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 0c79593b1bbf..1fb4770a7d13 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -997,9 +997,11 @@ EXPORT_SYMBOL(ieee80211_find_sta); | |||
997 | static void clear_sta_ps_flags(void *_sta) | 997 | static void clear_sta_ps_flags(void *_sta) |
998 | { | 998 | { |
999 | struct sta_info *sta = _sta; | 999 | struct sta_info *sta = _sta; |
1000 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
1000 | 1001 | ||
1001 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | 1002 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); |
1002 | clear_sta_flag(sta, WLAN_STA_PS_STA); | 1003 | if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA)) |
1004 | atomic_dec(&sdata->bss->num_sta_ps); | ||
1003 | } | 1005 | } |
1004 | 1006 | ||
1005 | /* powersave support code */ | 1007 | /* powersave support code */ |