mac80211: go out of PS before sending disassoc
authorEliad Peller <eliad@wizery.com>
Thu, 12 Jul 2012 14:35:33 +0000 (17:35 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 17 Jul 2012 10:17:42 +0000 (12:17 +0200)
on disassoc, ieee80211_set_disassoc() goes out of PS
before indicating BSS_CHANGED_ASSOC (not sure why this
is needed, but some drivers might count on the current
behavior).

However, it does it after sending the disassoc
frame, which results in null-data frame being sent
(in order to go out of ps) after we were already sent
the disassoc, which is invalid.

Fix it by going out of ps before sending the disassoc.

Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/mlme.c

index 4efcbf89a72d00ae0d1da2968cea2feeb8c23ac7..7c0613ce38bcf1c80c51b1ff708b4a302b5ce3c2 100644 (file)
@@ -1364,6 +1364,17 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        }
        mutex_unlock(&local->sta_mtx);
 
+       /*
+        * if we want to get out of ps before disassoc (why?) we have
+        * to do it before sending disassoc, as otherwise the null-packet
+        * won't be valid.
+        */
+       if (local->hw.conf.flags & IEEE80211_CONF_PS) {
+               local->hw.conf.flags &= ~IEEE80211_CONF_PS;
+               ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+       }
+       local->ps_sdata = NULL;
+
        /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */
        if (tx)
                drv_flush(local, false);
@@ -1396,12 +1407,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        del_timer_sync(&local->dynamic_ps_timer);
        cancel_work_sync(&local->dynamic_ps_enable_work);
 
-       if (local->hw.conf.flags & IEEE80211_CONF_PS) {
-               local->hw.conf.flags &= ~IEEE80211_CONF_PS;
-               ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
-       }
-       local->ps_sdata = NULL;
-
        /* Disable ARP filtering */
        if (sdata->vif.bss_conf.arp_filter_enabled) {
                sdata->vif.bss_conf.arp_filter_enabled = false;