| From 277d916fc2e959c3f106904116bb4f7b1148d47a Mon Sep 17 00:00:00 2001 |
| From: Felix Fietkau <nbd@openwrt.org> |
| Date: Mon, 16 Dec 2013 21:39:50 +0100 |
| Subject: mac80211: move "bufferable MMPDU" check to fix AP mode scan |
| |
| From: Felix Fietkau <nbd@openwrt.org> |
| |
| commit 277d916fc2e959c3f106904116bb4f7b1148d47a upstream. |
| |
| The check needs to apply to both multicast and unicast packets, |
| otherwise probe requests on AP mode scans are sent through the multicast |
| buffer queue, which adds long delays (often longer than the scanning |
| interval). |
| |
| Signed-off-by: Felix Fietkau <nbd@openwrt.org> |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| net/mac80211/tx.c | 23 +++++++++++++---------- |
| 1 file changed, 13 insertions(+), 10 deletions(-) |
| |
| --- a/net/mac80211/tx.c |
| +++ b/net/mac80211/tx.c |
| @@ -447,7 +447,6 @@ ieee80211_tx_h_unicast_ps_buf(struct iee |
| { |
| struct sta_info *sta = tx->sta; |
| struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
| - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
| struct ieee80211_local *local = tx->local; |
| |
| if (unlikely(!sta)) |
| @@ -458,15 +457,6 @@ ieee80211_tx_h_unicast_ps_buf(struct iee |
| !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) { |
| int ac = skb_get_queue_mapping(tx->skb); |
| |
| - /* only deauth, disassoc and action are bufferable MMPDUs */ |
| - if (ieee80211_is_mgmt(hdr->frame_control) && |
| - !ieee80211_is_deauth(hdr->frame_control) && |
| - !ieee80211_is_disassoc(hdr->frame_control) && |
| - !ieee80211_is_action(hdr->frame_control)) { |
| - info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; |
| - return TX_CONTINUE; |
| - } |
| - |
| ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n", |
| sta->sta.addr, sta->sta.aid, ac); |
| if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) |
| @@ -509,9 +499,22 @@ ieee80211_tx_h_unicast_ps_buf(struct iee |
| static ieee80211_tx_result debug_noinline |
| ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) |
| { |
| + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
| + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
| + |
| if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) |
| return TX_CONTINUE; |
| |
| + /* only deauth, disassoc and action are bufferable MMPDUs */ |
| + if (ieee80211_is_mgmt(hdr->frame_control) && |
| + !ieee80211_is_deauth(hdr->frame_control) && |
| + !ieee80211_is_disassoc(hdr->frame_control) && |
| + !ieee80211_is_action(hdr->frame_control)) { |
| + if (tx->flags & IEEE80211_TX_UNICAST) |
| + info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; |
| + return TX_CONTINUE; |
| + } |
| + |
| if (tx->flags & IEEE80211_TX_UNICAST) |
| return ieee80211_tx_h_unicast_ps_buf(tx); |
| else |