summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/commands.c4
-rw-r--r--include/net/cfg80211.h19
-rw-r--r--net/mac80211/cfg.c10
-rw-r--r--net/wireless/nl80211.c117
4 files changed, 91 insertions, 59 deletions
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index d9c4dd6beaec..77929ed9ef78 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -261,8 +261,8 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
cmd->p2p_ctwindow = s->p2p_ctwindow;
cmd->p2p_opp_ps = s->p2p_opp_ps;
cmd->pbss = s->pbss;
- cmd->ht_required = s->ht_required;
- cmd->vht_required = s->vht_required;
+ cmd->ht_required = s->beacon.ht_required;
+ cmd->vht_required = s->beacon.vht_required;
cmd->twt_responder = s->twt_responder;
if (s->he_obss_pd.enable) {
cmd->sr_params.sr_control |= QLINK_SR_SRG_INFORMATION_PRESENT;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 8bebf45af95d..7070e577342b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1396,6 +1396,11 @@ struct cfg80211_rnr_elems {
* @he_bss_color: BSS Color settings
* @he_bss_color_valid: indicates whether bss color
* attribute is present in beacon data or not.
+ * @ht_required: stations must support HT
+ * @vht_required: stations must support VHT
+ * @he_oper: HE operation IE (or %NULL if HE isn't enabled)
+ * @eht_oper: EHT operation IE (or %NULL if EHT isn't enabled)
+ * @uhr_oper: UHR operation (or %NULL if UHR isn't enabled)
*/
struct cfg80211_beacon_data {
unsigned int link_id;
@@ -1420,6 +1425,11 @@ struct cfg80211_beacon_data {
size_t civicloc_len;
struct cfg80211_he_bss_color he_bss_color;
bool he_bss_color_valid;
+
+ bool ht_required, vht_required;
+ const struct ieee80211_he_operation *he_oper;
+ const struct ieee80211_eht_operation *eht_oper;
+ const struct ieee80211_uhr_operation *uhr_oper;
};
struct mac_address {
@@ -1524,14 +1534,9 @@ struct cfg80211_s1g_short_beacon {
* @vht_cap: VHT capabilities (or %NULL if VHT isn't enabled)
* @he_cap: HE capabilities (or %NULL if HE isn't enabled)
* @eht_cap: EHT capabilities (or %NULL if EHT isn't enabled)
- * @eht_oper: EHT operation IE (or %NULL if EHT isn't enabled)
- * @uhr_oper: UHR operation (or %NULL if UHR isn't enabled)
- * @ht_required: stations must support HT
- * @vht_required: stations must support VHT
* @twt_responder: Enable Target Wait Time
* @flags: flags, as defined in &enum nl80211_ap_settings_flags
* @he_obss_pd: OBSS Packet Detection 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
@@ -1560,11 +1565,7 @@ struct cfg80211_ap_settings {
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;
const struct ieee80211_eht_cap_elem *eht_cap;
- const struct ieee80211_eht_operation *eht_oper;
- const struct ieee80211_uhr_operation *uhr_oper;
- bool ht_required, vht_required;
bool twt_responder;
u32 flags;
struct ieee80211_he_obss_pd he_obss_pd;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 15a68d3f8e73..bc4a8e5ad039 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1541,13 +1541,13 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
}
- if (params->he_cap && params->he_oper) {
+ if (params->he_cap && params->beacon.he_oper) {
link_conf->he_support = true;
link_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);
link_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;
@@ -1596,7 +1596,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ |
IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ);
link_conf->eht_disable_mcs15 =
- u8_get_bits(params->eht_oper->params,
+ u8_get_bits(params->beacon.eht_oper->params,
IEEE80211_EHT_OPER_MCS15_DISABLE);
} else {
link_conf->eht_su_beamformer = false;
@@ -1604,7 +1604,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
link_conf->eht_mu_beamformer = false;
}
- if (params->uhr_oper) {
+ if (params->beacon.uhr_oper) {
if (!link_conf->eht_support)
return -EOPNOTSUPP;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9892cbc182b9..d1bede3d0a14 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6628,7 +6628,7 @@ 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,
+static void nl80211_check_ap_rate_selectors(struct cfg80211_beacon_data *bcn,
const struct element *rates)
{
int i;
@@ -6638,31 +6638,23 @@ static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
for (i = 0; i < rates->datalen; i++) {
if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
- params->ht_required = true;
+ bcn->ht_required = true;
if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
- params->vht_required = true;
+ bcn->vht_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.
+ * HT/VHT/... capabilities, we parse them out of the elements and check for
+ * validity for use by drivers/mac80211.
*/
-static int nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
+static int nl80211_calculate_ap_capabilities(struct cfg80211_ap_settings *params)
{
- const struct cfg80211_beacon_data *bcn = &params->beacon;
- size_t ies_len = bcn->tail_len;
- const u8 *ies = bcn->tail;
- const struct element *rates;
+ size_t ies_len = params->beacon.tail_len;
+ const u8 *ies = params->beacon.tail;
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;
@@ -6672,31 +6664,62 @@ static int nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
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);
- /* takes extension ID into account */
- if (cap->datalen < ieee80211_he_oper_size((void *)params->he_oper))
- return -EINVAL;
- }
cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_CAPABILITY, ies, ies_len);
if (cap) {
- if (!cap->datalen)
- return -EINVAL;
params->eht_cap = (void *)(cap->data + 1);
if (!ieee80211_eht_capa_size_ok((const u8 *)params->he_cap,
(const u8 *)params->eht_cap,
cap->datalen - 1, true))
return -EINVAL;
}
- cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_OPERATION, ies, ies_len);
- if (cap) {
- if (!cap->datalen)
+
+ return 0;
+}
+
+/*
+ * Since the nl80211 API didn't include, from the beginning, attributes about
+ * HT/VHT/... operation, we parse them out of the elements and check for
+ * validity for use by drivers/mac80211.
+ */
+static int nl80211_calculate_ap_operation(struct genl_info *info,
+ struct cfg80211_beacon_data *bcn)
+{
+ size_t ies_len = bcn->tail_len;
+ const u8 *ies = bcn->tail;
+ const struct element *rates;
+ const struct element *op;
+
+ 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);
+
+ op = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_OPERATION, ies, ies_len);
+ if (op && op->datalen >= sizeof(*bcn->he_oper) + 1) {
+ bcn->he_oper = (void *)(op->data + 1);
+ /* takes extension ID into account */
+ if (op->datalen < ieee80211_he_oper_size((void *)bcn->he_oper))
return -EINVAL;
- params->eht_oper = (void *)(cap->data + 1);
- if (!ieee80211_eht_oper_size_ok((const u8 *)params->eht_oper,
- cap->datalen - 1))
+ }
+
+ op = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_OPERATION, ies, ies_len);
+ if (op) {
+ if (!ieee80211_eht_oper_size_ok(op->data + 1,
+ op->datalen - 1))
+ return -EINVAL;
+ bcn->eht_oper = (void *)(op->data + 1);
+ }
+
+ op = cfg80211_find_ext_elem(WLAN_EID_EXT_UHR_OPER, ies, ies_len);
+ if (op) {
+ /* need full UHR operation separately */
+ if (!info->attrs[NL80211_ATTR_UHR_OPERATION])
return -EINVAL;
+ bcn->uhr_oper = nla_data(info->attrs[NL80211_ATTR_UHR_OPERATION]);
+ } else if (info->attrs[NL80211_ATTR_UHR_OPERATION]) {
+ GENL_SET_ERR_MSG(info, "unexpected UHR operation");
+ return -EINVAL;
}
return 0;
@@ -6826,19 +6849,16 @@ out:
nlmsg_free(msg);
}
-static int nl80211_validate_ap_phy_operation(struct cfg80211_ap_settings *params)
+static int nl80211_validate_ap_phy_operation(struct ieee80211_channel *channel,
+ struct cfg80211_beacon_data *bcn)
{
- struct ieee80211_channel *channel = params->chandef.chan;
-
- if ((params->he_cap || params->he_oper) &&
- (channel->flags & IEEE80211_CHAN_NO_HE))
+ if (bcn->he_oper && (channel->flags & IEEE80211_CHAN_NO_HE))
return -EOPNOTSUPP;
- if ((params->eht_cap || params->eht_oper) &&
- (channel->flags & IEEE80211_CHAN_NO_EHT))
+ if (bcn->eht_oper && (channel->flags & IEEE80211_CHAN_NO_EHT))
return -EOPNOTSUPP;
- if (params->uhr_oper && (channel->flags & IEEE80211_CHAN_NO_UHR))
+ if (bcn->uhr_oper && (channel->flags & IEEE80211_CHAN_NO_UHR))
return -EOPNOTSUPP;
return 0;
@@ -7136,14 +7156,16 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- err = nl80211_calculate_ap_params(params);
+ err = nl80211_calculate_ap_capabilities(params);
if (err)
goto out;
- if (info->attrs[NL80211_ATTR_UHR_OPERATION])
- params->uhr_oper = nla_data(info->attrs[NL80211_ATTR_UHR_OPERATION]);
+ err = nl80211_calculate_ap_operation(info, &params->beacon);
+ if (err)
+ goto out;
- err = nl80211_validate_ap_phy_operation(params);
+ err = nl80211_validate_ap_phy_operation(params->chandef.chan,
+ &params->beacon);
if (err)
goto out;
@@ -7218,6 +7240,15 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
if (err)
goto out;
+ err = nl80211_calculate_ap_operation(info, &params->beacon);
+ if (err)
+ goto out;
+
+ err = nl80211_validate_ap_phy_operation(wdev->links[link_id].ap.chandef.chan,
+ &params->beacon);
+ if (err)
+ goto out;
+
/* recheck beaconing is permitted with possibly changed power type */
beacon_check.iftype = wdev->iftype;
beacon_check.relax = true;