s390/smp: move smp_cpus_done() to header file
[linux-2.6-microblaze.git] / net / mac80211 / mesh.c
index 36978a0..5f1ca25 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2008, 2009 open80211s Ltd.
- * Copyright (C) 2018 - 2019 Intel Corporation
+ * Copyright (C) 2018 - 2020 Intel Corporation
  * Authors:    Luis Carlos Cobo <luisca@cozybit.com>
  *            Javier Cardona <javier@cozybit.com>
  */
@@ -63,6 +63,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
        u32 basic_rates = 0;
        struct cfg80211_chan_def sta_chan_def;
        struct ieee80211_supported_band *sband;
+       u32 vht_cap_info = 0;
 
        /*
         * As support for each feature is added, check for matching
@@ -96,9 +97,14 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
        cfg80211_chandef_create(&sta_chan_def, sdata->vif.bss_conf.chandef.chan,
                                NL80211_CHAN_NO_HT);
        ieee80211_chandef_ht_oper(ie->ht_operation, &sta_chan_def);
-       ieee80211_chandef_vht_oper(&sdata->local->hw,
+
+       if (ie->vht_cap_elem)
+               vht_cap_info = le32_to_cpu(ie->vht_cap_elem->vht_cap_info);
+
+       ieee80211_chandef_vht_oper(&sdata->local->hw, vht_cap_info,
                                   ie->vht_operation, ie->ht_operation,
                                   &sta_chan_def);
+       ieee80211_chandef_he_6ghz_oper(sdata, ie->he_operation, &sta_chan_def);
 
        if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
                                         &sta_chan_def))
@@ -415,6 +421,10 @@ int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata,
        if (!sband)
                return -EINVAL;
 
+       /* HT not allowed in 6 GHz */
+       if (sband->band == NL80211_BAND_6GHZ)
+               return 0;
+
        if (!sband->ht_cap.ht_supported ||
            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
@@ -452,6 +462,10 @@ int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata,
        sband = local->hw.wiphy->bands[channel->band];
        ht_cap = &sband->ht_cap;
 
+       /* HT not allowed in 6 GHz */
+       if (sband->band == NL80211_BAND_6GHZ)
+               return 0;
+
        if (!ht_cap->ht_supported ||
            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
@@ -479,6 +493,10 @@ int mesh_add_vht_cap_ie(struct ieee80211_sub_if_data *sdata,
        if (!sband)
                return -EINVAL;
 
+       /* VHT not allowed in 6 GHz */
+       if (sband->band == NL80211_BAND_6GHZ)
+               return 0;
+
        if (!sband->vht_cap.vht_supported ||
            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
@@ -516,6 +534,10 @@ int mesh_add_vht_oper_ie(struct ieee80211_sub_if_data *sdata,
        sband = local->hw.wiphy->bands[channel->band];
        vht_cap = &sband->vht_cap;
 
+       /* VHT not allowed in 6 GHz */
+       if (sband->band == NL80211_BAND_6GHZ)
+               return 0;
+
        if (!vht_cap->vht_supported ||
            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
@@ -565,6 +587,7 @@ int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata,
 {
        const struct ieee80211_sta_he_cap *he_cap;
        struct ieee80211_supported_band *sband;
+       u32 len;
        u8 *pos;
 
        sband = ieee80211_get_sband(sdata);
@@ -578,12 +601,23 @@ int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata,
            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
                return 0;
 
-       if (skb_tailroom(skb) < 2 + 1 + sizeof(struct ieee80211_he_operation))
+       len = 2 + 1 + sizeof(struct ieee80211_he_operation);
+       if (sdata->vif.bss_conf.chandef.chan->band == NL80211_BAND_6GHZ)
+               len += sizeof(struct ieee80211_he_6ghz_oper);
+
+       if (skb_tailroom(skb) < len)
                return -ENOMEM;
 
-       pos = skb_put(skb, 2 + 1 + sizeof(struct ieee80211_he_operation));
-       ieee80211_ie_build_he_oper(pos);
+       pos = skb_put(skb, len);
+       ieee80211_ie_build_he_oper(pos, &sdata->vif.bss_conf.chandef);
+
+       return 0;
+}
 
+int mesh_add_he_6ghz_cap_ie(struct ieee80211_sub_if_data *sdata,
+                           struct sk_buff *skb)
+{
+       ieee80211_ie_build_he_6ghz_cap(sdata, skb);
        return 0;
 }
 
@@ -766,6 +800,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
                   2 + sizeof(struct ieee80211_vht_operation) +
                   ie_len_he_cap +
                   2 + 1 + sizeof(struct ieee80211_he_operation) +
+                          sizeof(struct ieee80211_he_6ghz_oper) +
+                  2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) +
                   ifmsh->ie_len;
 
        bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL);
@@ -885,6 +921,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
            mesh_add_vht_oper_ie(sdata, skb) ||
            mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) ||
            mesh_add_he_oper_ie(sdata, skb) ||
+           mesh_add_he_6ghz_cap_ie(sdata, skb) ||
            mesh_add_vendor_ies(sdata, skb))
                goto out_free;
 
@@ -994,6 +1031,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
        /* stop the beacon */
        ifmsh->mesh_id_len = 0;
        sdata->vif.bss_conf.enable_beacon = false;
+       sdata->beacon_rate_set = false;
        clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
 
@@ -1044,7 +1082,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        struct ieee80211_supported_band *sband;
        int err;
-       u32 sta_flags;
+       u32 sta_flags, vht_cap_info = 0;
 
        sdata_assert_lock(sdata);
 
@@ -1067,8 +1105,13 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
                break;
        }
 
+       if (elems->vht_cap_elem)
+               vht_cap_info =
+                       le32_to_cpu(elems->vht_cap_elem->vht_cap_info);
+
        memset(&params, 0, sizeof(params));
        err = ieee80211_parse_ch_switch_ie(sdata, elems, sband->band,
+                                          vht_cap_info,
                                           sta_flags, sdata->vif.addr,
                                           &csa_ie);
        if (err < 0)