aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/status.c
diff options
context:
space:
mode:
authorVivek Natarajan <vnatarajan@atheros.com>2010-02-09 04:20:28 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-02-09 14:10:05 -0500
commit375177bf35efc08e1bd37bbda4cc0c8cc4db8500 (patch)
tree88774b1a46072fd3b0418b36d39d447b78fbfc51 /net/mac80211/status.c
parente15276a4b220c54db665cf46a92bd9ceb9aeb052 (diff)
mac80211: Retry null data frame for power save.
Even if the null data frame is not acked by the AP, mac80211 goes into power save. This might lead to loss of frames from the AP. Prevent this by restarting dynamic_ps_timer when ack is not received for null data frames. Cc: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Vivek Natarajan <vnatarajan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/status.c')
-rw-r--r--net/mac80211/status.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index e57ad6b1d7ea..ded98730c111 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -188,6 +188,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
188 rcu_read_lock(); 188 rcu_read_lock();
189 189
190 sband = local->hw.wiphy->bands[info->band]; 190 sband = local->hw.wiphy->bands[info->band];
191 fc = hdr->frame_control;
191 192
192 for_each_sta_info(local, hdr->addr1, sta, tmp) { 193 for_each_sta_info(local, hdr->addr1, sta, tmp) {
193 /* skip wrong virtual interface */ 194 /* skip wrong virtual interface */
@@ -205,8 +206,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
205 return; 206 return;
206 } 207 }
207 208
208 fc = hdr->frame_control;
209
210 if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && 209 if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
211 (ieee80211_is_data_qos(fc))) { 210 (ieee80211_is_data_qos(fc))) {
212 u16 tid, ssn; 211 u16 tid, ssn;
@@ -275,6 +274,20 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
275 local->dot11FailedCount++; 274 local->dot11FailedCount++;
276 } 275 }
277 276
277 if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc) &&
278 (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) &&
279 !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
280 local->ps_sdata && !(local->scanning)) {
281 if (info->flags & IEEE80211_TX_STAT_ACK) {
282 local->ps_sdata->u.mgd.flags |=
283 IEEE80211_STA_NULLFUNC_ACKED;
284 ieee80211_queue_work(&local->hw,
285 &local->dynamic_ps_enable_work);
286 } else
287 mod_timer(&local->dynamic_ps_timer, jiffies +
288 msecs_to_jiffies(10));
289 }
290
278 /* this was a transmitted frame, but now we want to reuse it */ 291 /* this was a transmitted frame, but now we want to reuse it */
279 skb_orphan(skb); 292 skb_orphan(skb);
280 293