summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ieee80211.h14
-rw-r--r--net/mac80211/rx.c19
-rw-r--r--net/mac80211/tx.c5
3 files changed, 23 insertions, 15 deletions
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 923c478030a3..1e3912d1b029 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -597,6 +597,20 @@ static inline int ieee80211_is_qos_nullfunc(__le16 fc)
}
/**
+ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
+ * @fc: frame control field in little-endian byteorder
+ */
+static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc)
+{
+ /* IEEE 802.11-2012, definition of "bufferable management frame";
+ * note that this ignores the IBSS special case. */
+ return ieee80211_is_mgmt(fc) &&
+ (ieee80211_is_action(fc) ||
+ ieee80211_is_disassoc(fc) ||
+ ieee80211_is_deauth(fc));
+}
+
+/**
* ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set
* @seq_ctrl: frame sequence control bytes in little-endian byteorder
*/
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))
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 07a7f38dc348..5476a69b45c9 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -522,11 +522,8 @@ ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
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)) {
+ !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
if (tx->flags & IEEE80211_TX_UNICAST)
info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
return TX_CONTINUE;