@@ -1113,7 +1113,16 @@ struct cfg80211_mbssid_elems {
* Token (measurement type 11)
* @lci_len: LCI data length
* @civicloc_len: Civic location data length
+ * @ht_cap: HT capabilities (or %NULL if HT isn't enabled)
+ * @vht_cap: VHT capabilities (or %NULL if VHT isn't enabled)
+ * @he_cap: HE capabilities (or %NULL if HE isn't enabled)
+ * @he_oper: HE operation IE (or %NULL if HE isn't enabled)
+ * @ht_required: stations must support HT
+ * @vht_required: stations must support VHT
+ * @he_required: stations must support HE
+ * @sae_h2e_required: stations must support direct H2E technique in SAE
*/
+
struct cfg80211_beacon_data {
const u8 *head, *tail;
const u8 *beacon_ies;
@@ -1132,6 +1141,12 @@ struct cfg80211_beacon_data {
size_t probe_resp_len;
size_t lci_len;
size_t civicloc_len;
+
+ const struct ieee80211_ht_cap *ht_cap;
+ const struct ieee80211_vht_cap *vht_cap;
+ const struct ieee80211_he_cap_elem *he_cap;
+ const struct ieee80211_he_operation *he_oper;
+ bool ht_required, vht_required, he_required, sae_h2e_required;
};
struct mac_address {
@@ -1223,18 +1238,10 @@ enum cfg80211_ap_settings_flags {
* @pbss: If set, start as a PCP instead of AP. Relevant for DMG
* networks.
* @beacon_rate: bitrate to be used for beacons
- * @ht_cap: HT capabilities (or %NULL if HT isn't enabled)
- * @vht_cap: VHT capabilities (or %NULL if VHT isn't enabled)
- * @he_cap: HE capabilities (or %NULL if HE isn't enabled)
- * @ht_required: stations must support HT
- * @vht_required: stations must support VHT
* @twt_responder: Enable Target Wait Time
- * @he_required: stations must support HE
- * @sae_h2e_required: stations must support direct H2E technique in SAE
* @flags: flags, as defined in enum cfg80211_ap_settings_flags
* @he_obss_pd: OBSS Packet Detection settings
* @he_bss_color: BSS Color settings
- * @he_oper: HE operation IE (or %NULL if HE isn't enabled)
* @fils_discovery: FILS discovery transmission parameters
* @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters
* @mbssid_config: AP settings for multiple bssid
@@ -1259,11 +1266,6 @@ struct cfg80211_ap_settings {
bool pbss;
struct cfg80211_bitrate_mask beacon_rate;
- const struct ieee80211_ht_cap *ht_cap;
- const struct ieee80211_vht_cap *vht_cap;
- const struct ieee80211_he_cap_elem *he_cap;
- const struct ieee80211_he_operation *he_oper;
- bool ht_required, vht_required, he_required, sae_h2e_required;
bool twt_responder;
u32 flags;
struct ieee80211_he_obss_pd he_obss_pd;
@@ -997,6 +997,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
struct beacon_data *new, *old;
int new_head_len, new_tail_len;
int size, err;
+ bool bss_clr_enabled;
u32 changed = BSS_CHANGED_BEACON;
old = sdata_dereference(sdata->u.ap.beacon, sdata);
@@ -1084,6 +1085,15 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_FTM_RESPONDER;
}
+ if (params->he_cap && params->he_oper) {
+ bss_clr_enabled = !le32_get_bits(params->he_oper->he_oper_params,
+ IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED);
+ if (sdata->vif.bss_conf.he_bss_color.enabled != bss_clr_enabled) {
+ sdata->vif.bss_conf.he_bss_color.enabled = bss_clr_enabled;
+ changed |= BSS_CHANGED_HE_BSS_COLOR;
+ }
+ }
+
rcu_assign_pointer(sdata->u.ap.beacon, new);
if (old)
@@ -1123,13 +1133,13 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
prev_beacon_int = sdata->vif.bss_conf.beacon_int;
sdata->vif.bss_conf.beacon_int = params->beacon_interval;
- if (params->he_cap && params->he_oper) {
+ if (params->beacon.he_cap && params->beacon.he_oper) {
sdata->vif.bss_conf.he_support = true;
sdata->vif.bss_conf.htc_trig_based_pkt_ext =
- le32_get_bits(params->he_oper->he_oper_params,
+ le32_get_bits(params->beacon.he_oper->he_oper_params,
IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK);
sdata->vif.bss_conf.frame_time_rts_th =
- le32_get_bits(params->he_oper->he_oper_params,
+ le32_get_bits(params->beacon.he_oper->he_oper_params,
IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK);
changed |= BSS_CHANGED_HE_OBSS_PD;
@@ -5124,6 +5124,58 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
return elems;
}
+static void nl80211_check_ap_rate_selectors(struct cfg80211_beacon_data *bcn,
+ const struct element *rates)
+{
+ int i;
+
+ if (!rates)
+ return;
+
+ for (i = 0; i < rates->datalen; i++) {
+ if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
+ bcn->ht_required = true;
+ if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
+ bcn->vht_required = true;
+ if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_HE_PHY)
+ bcn->he_required = true;
+ if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_SAE_H2E)
+ bcn->sae_h2e_required = true;
+ }
+}
+
+/*
+ * Since the nl80211 API didn't include, from the beginning, attributes about
+ * HT/VHT requirements/capabilities, we parse them out of the IEs for the
+ * benefit of drivers that rebuild IEs in the firmware.
+ */
+static void nl80211_calculate_ap_params(struct cfg80211_beacon_data *bcn)
+{
+ size_t ies_len = bcn->tail_len;
+ const u8 *ies = bcn->tail;
+ const struct element *rates;
+ const struct element *cap;
+
+ rates = cfg80211_find_elem(WLAN_EID_SUPP_RATES, ies, ies_len);
+ nl80211_check_ap_rate_selectors(bcn, rates);
+
+ rates = cfg80211_find_elem(WLAN_EID_EXT_SUPP_RATES, ies, ies_len);
+ nl80211_check_ap_rate_selectors(bcn, rates);
+
+ cap = cfg80211_find_elem(WLAN_EID_HT_CAPABILITY, ies, ies_len);
+ if (cap && cap->datalen >= sizeof(*bcn->ht_cap))
+ bcn->ht_cap = (void *)cap->data;
+ cap = cfg80211_find_elem(WLAN_EID_VHT_CAPABILITY, ies, ies_len);
+ if (cap && cap->datalen >= sizeof(*bcn->vht_cap))
+ bcn->vht_cap = (void *)cap->data;
+ cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_CAPABILITY, ies, ies_len);
+ if (cap && cap->datalen >= sizeof(*bcn->he_cap) + 1)
+ bcn->he_cap = (void *)(cap->data + 1);
+ cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_OPERATION, ies, ies_len);
+ if (cap && cap->datalen >= sizeof(*bcn->he_oper) + 1)
+ bcn->he_oper = (void *)(cap->data + 1);
+}
+
static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
struct nlattr *attrs[],
struct cfg80211_beacon_data *bcn)
@@ -5215,6 +5267,8 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
bcn->mbssid_ies = mbssid;
}
+ nl80211_calculate_ap_params(bcn);
+
return 0;
}
@@ -5345,59 +5399,6 @@ nl80211_parse_unsol_bcast_probe_resp(struct cfg80211_registered_device *rdev,
return 0;
}
-static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
- const struct element *rates)
-{
- int i;
-
- if (!rates)
- return;
-
- for (i = 0; i < rates->datalen; i++) {
- if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
- params->ht_required = true;
- if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
- params->vht_required = true;
- if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_HE_PHY)
- params->he_required = true;
- if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_SAE_H2E)
- params->sae_h2e_required = true;
- }
-}
-
-/*
- * Since the nl80211 API didn't include, from the beginning, attributes about
- * HT/VHT requirements/capabilities, we parse them out of the IEs for the
- * benefit of drivers that rebuild IEs in the firmware.
- */
-static void nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
-{
- const struct cfg80211_beacon_data *bcn = ¶ms->beacon;
- size_t ies_len = bcn->tail_len;
- const u8 *ies = bcn->tail;
- const struct element *rates;
- const struct element *cap;
-
- rates = cfg80211_find_elem(WLAN_EID_SUPP_RATES, ies, ies_len);
- nl80211_check_ap_rate_selectors(params, rates);
-
- rates = cfg80211_find_elem(WLAN_EID_EXT_SUPP_RATES, ies, ies_len);
- nl80211_check_ap_rate_selectors(params, rates);
-
- cap = cfg80211_find_elem(WLAN_EID_HT_CAPABILITY, ies, ies_len);
- if (cap && cap->datalen >= sizeof(*params->ht_cap))
- params->ht_cap = (void *)cap->data;
- cap = cfg80211_find_elem(WLAN_EID_VHT_CAPABILITY, ies, ies_len);
- if (cap && cap->datalen >= sizeof(*params->vht_cap))
- params->vht_cap = (void *)cap->data;
- cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_CAPABILITY, ies, ies_len);
- if (cap && cap->datalen >= sizeof(*params->he_cap) + 1)
- params->he_cap = (void *)(cap->data + 1);
- cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_OPERATION, ies, ies_len);
- if (cap && cap->datalen >= sizeof(*params->he_oper) + 1)
- params->he_oper = (void *)(cap->data + 1);
-}
-
static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
struct cfg80211_ap_settings *params)
{
@@ -5712,8 +5713,6 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- nl80211_calculate_ap_params(params);
-
if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
params->flags |= AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;