cfg80211: support immediate reconnect request hint
[linux-block.git] / net / mac80211 / mlme.c
index 6adfcb9c06dcc516cf215cdc5b0ea7ed1524099e..5a2828dccfa5b1c51aa86b64939e81f1aa027b42 100644 (file)
@@ -1417,6 +1417,17 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                return;
        }
 
+       if (sdata->vif.bss_conf.chandef.chan->band !=
+           csa_ie.chandef.chan->band) {
+               sdata_info(sdata,
+                          "AP %pM switches to different band (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
+                          ifmgd->associated->bssid,
+                          csa_ie.chandef.chan->center_freq,
+                          csa_ie.chandef.width, csa_ie.chandef.center_freq1,
+                          csa_ie.chandef.center_freq2);
+               goto lock_and_drop_connection;
+       }
+
        if (!cfg80211_chandef_usable(local->hw.wiphy, &csa_ie.chandef,
                                     IEEE80211_CHAN_DISABLED)) {
                sdata_info(sdata,
@@ -1429,9 +1440,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                           csa_ie.chandef.width, csa_ie.chandef.center_freq1,
                           csa_ie.chandef.freq1_offset,
                           csa_ie.chandef.center_freq2);
-               ieee80211_queue_work(&local->hw,
-                                    &ifmgd->csa_connection_drop_work);
-               return;
+               goto lock_and_drop_connection;
        }
 
        if (cfg80211_chandef_identical(&csa_ie.chandef,
@@ -1500,7 +1509,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        mutex_unlock(&local->mtx);
 
        cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef,
-                                         csa_ie.count);
+                                         csa_ie.count, csa_ie.mode);
 
        if (local->ops->channel_switch) {
                /* use driver's channel switch callback */
@@ -1516,6 +1525,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                          TU_TO_EXP_TIME((csa_ie.count - 1) *
                                         cbss->beacon_interval));
        return;
+ lock_and_drop_connection:
+       mutex_lock(&local->mtx);
+       mutex_lock(&local->chanctx_mtx);
  drop_connection:
        /*
         * This is just so that the disconnect flow will know that
@@ -2729,7 +2741,7 @@ static void ieee80211_report_disconnect(struct ieee80211_sub_if_data *sdata,
        };
 
        if (tx)
-               cfg80211_tx_mlme_mgmt(sdata->dev, buf, len);
+               cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, false);
        else
                cfg80211_rx_mlme_mgmt(sdata->dev, buf, len);
 
@@ -3199,8 +3211,8 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
                        *have_higher_than_11mbit = true;
 
                /*
-                * Skip HT, VHT and HE BSS membership selectors since they're
-                * not rates.
+                * Skip HT, VHT, HE and SAE H2E only BSS membership selectors
+                * since they're not rates.
                 *
                 * Note: Even though the membership selector and the basic
                 *       rate flag share the same bit, they are not exactly
@@ -3208,7 +3220,8 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
                 */
                if (supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY) ||
                    supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY) ||
-                   supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HE_PHY))
+                   supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HE_PHY) ||
+                   supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E))
                        continue;
 
                for (j = 0; j < sband->n_bitrates; j++) {
@@ -3494,14 +3507,6 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
                        le32_get_bits(elems->he_operation->he_oper_params,
                              IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK);
 
-               bss_conf->multi_sta_back_32bit =
-                       sta->sta.he_cap.he_cap_elem.mac_cap_info[2] &
-                       IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP;
-
-               bss_conf->ack_enabled =
-                       sta->sta.he_cap.he_cap_elem.mac_cap_info[2] &
-                       IEEE80211_HE_MAC_CAP2_ACK_EN;
-
                bss_conf->uora_exists = !!elems->uora_element;
                if (elems->uora_element)
                        bss_conf->uora_ocw_range = elems->uora_element[0];
@@ -4716,7 +4721,8 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
                if (ifmgd->auth_data)
                        ieee80211_destroy_auth_data(sdata, false);
                cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
-                                     IEEE80211_DEAUTH_FRAME_LEN);
+                                     IEEE80211_DEAUTH_FRAME_LEN,
+                                     false);
        }
 
        /* This is a bit of a hack - we should find a better and more generic