summaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2017-10-29 05:51:07 -0400
committerJohannes Berg <johannes.berg@intel.com>2017-12-11 06:18:43 -0500
commit9fef65443388a66a2c19835e2848a6ecf162710b (patch)
treef930db7ff58a1cfe998bd0d8bae82cffba45048c /net/mac80211
parente16ea4bb516bc21ea2202f2107718b29218bea59 (diff)
mac80211: always update the PM state of a peer on MGMT / DATA frames
The 2016 version of the spec is more generic about when the AP should update the power management state of the peer: the AP shall update the state based on any management or data frames. This means that even non-bufferable management frames should be looked at to update to maintain the power management state of the peer. This can avoid problematic cases for example if a station disappears while being asleep and then re-appears. The AP would remember it as in power save, but the Authentication frame couldn't be used to set the peer as awake again. Note that this issues wasn't really critical since at some point (after the association) we would have removed the station and created another one with all the states cleared. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/rx.c17
1 files changed, 5 insertions, 12 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 70e9d2ca8bbe..b3cff69bfd66 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1607,23 +1607,16 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
1607 1607
1608 /* 1608 /*
1609 * Change STA power saving mode only at the end of a frame 1609 * Change STA power saving mode only at the end of a frame
1610 * exchange sequence. 1610 * exchange sequence, and only for a data or management
1611 * frame as specified in IEEE 802.11-2016 11.2.3.2
1611 */ 1612 */
1612 if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) && 1613 if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) &&
1613 !ieee80211_has_morefrags(hdr->frame_control) && 1614 !ieee80211_has_morefrags(hdr->frame_control) &&
1614 !ieee80211_is_back_req(hdr->frame_control) && 1615 (ieee80211_is_mgmt(hdr->frame_control) ||
1616 ieee80211_is_data(hdr->frame_control)) &&
1615 !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && 1617 !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
1616 (rx->sdata->vif.type == NL80211_IFTYPE_AP || 1618 (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
1617 rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && 1619 rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
1618 /*
1619 * PM bit is only checked in frames where it isn't reserved,
1620 * in AP mode it's reserved in non-bufferable management frames
1621 * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field)
1622 * BAR frames should be ignored as specified in
1623 * IEEE 802.11-2012 10.2.1.2.
1624 */
1625 (!ieee80211_is_mgmt(hdr->frame_control) ||
1626 ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
1627 if (test_sta_flag(sta, WLAN_STA_PS_STA)) { 1620 if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
1628 if (!ieee80211_has_pm(hdr->frame_control)) 1621 if (!ieee80211_has_pm(hdr->frame_control))
1629 sta_ps_end(sta); 1622 sta_ps_end(sta);