summaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
authorJohannes Berg2014-01-24 14:41:44 +0100
committerJohannes Berg2014-02-04 21:58:15 +0100
commitb4ba544c8c1349afd44e10aebec03c90e9b71d98 (patch)
tree0c918d83b412f4155f3ea882626b0422315d32c5 /net/mac80211/rx.c
parentmac80211: remove set but unused variables (diff)
downloadkernel-qcow2-linux-b4ba544c8c1349afd44e10aebec03c90e9b71d98.tar.gz
kernel-qcow2-linux-b4ba544c8c1349afd44e10aebec03c90e9b71d98.tar.xz
kernel-qcow2-linux-b4ba544c8c1349afd44e10aebec03c90e9b71d98.zip
mac80211: fix bufferable MMPDU RX handling
Action, disassoc and deauth frames are bufferable, and as such don't have the PM bit in the frame control field reserved which means we need to react to the bit when receiving in such a frame. Fix this by introducing a new helper ieee80211_is_bufferable_mmpdu() and using it for the RX path that currently ignores the PM bit in any non-data frames for doze->wake transitions, but listens to it in all frames for wake->doze transitions, both of which are wrong. Also use the new helper in the TX path to clean up the code. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c19
1 files changed, 8 insertions, 11 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 3b7a750ebc70..79a89fe9d616 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1311,18 +1311,15 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
!ieee80211_has_morefrags(hdr->frame_control) &&
!(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
(rx->sdata->vif.type == NL80211_IFTYPE_AP ||
- rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
+ rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
+ /* PM bit is only checked in frames where it isn't reserved,
+ * in AP mode it's reserved in non-bufferable management frames
+ * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field)
+ */
+ (!ieee80211_is_mgmt(hdr->frame_control) ||
+ ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
- /*
- * Ignore doze->wake transitions that are
- * indicated by non-data frames, the standard
- * is unclear here, but for example going to
- * PS mode and then scanning would cause a
- * doze->wake transition for the probe request,
- * and that is clearly undesirable.
- */
- if (ieee80211_is_data(hdr->frame_control) &&
- !ieee80211_has_pm(hdr->frame_control))
+ if (!ieee80211_has_pm(hdr->frame_control))
sta_ps_end(sta);
} else {
if (ieee80211_has_pm(hdr->frame_control))