summaryrefslogtreecommitdiff
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c60
1 files changed, 46 insertions, 14 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index c81091a5cc3a..5d04d7d550b0 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -5,7 +5,7 @@
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2025 Intel Corporation
+ * Copyright (C) 2018-2026 Intel Corporation
*/
#include <linux/ieee80211.h>
@@ -680,10 +680,18 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
* association has completed, this rejects that attempt
* so it will set the key again after association.
*
+ * With (re)association frame encryption enabled, cfg80211
+ * may deliver keys to mac80211 before the station has
+ * associated. In that case, accept the key if the station
+ * is an Enhanced Privacy Protection (EPP) peer.
+ * If (re)association frame encryption support is not present,
+ * cfg80211 will not allow key installation in non‑AP STA mode.
+ *
* TODO: accept the key if we have a station entry and
- * add it to the device after the station.
+ * add it to the device after the station associates.
*/
- if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) {
+ if (!sta || (!sta->sta.epp_peer &&
+ !test_sta_flag(sta, WLAN_STA_ASSOC))) {
ieee80211_key_free_unused(key);
return -ENOENT;
}
@@ -1600,6 +1608,13 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
link_conf->eht_mu_beamformer = false;
}
+ if (params->uhr_oper) {
+ if (!link_conf->eht_support)
+ return -EOPNOTSUPP;
+
+ link_conf->uhr_support = true;
+ }
+
if (sdata->vif.type == NL80211_IFTYPE_AP &&
params->mbssid_config.tx_wdev) {
err = ieee80211_set_ap_mbssid_options(sdata,
@@ -1908,7 +1923,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
if (sdata->wdev.links[link_id].cac_started) {
chandef = link_conf->chanreq.oper;
- wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
+ wiphy_hrtimer_work_cancel(wiphy, &link->dfs_cac_timer_work);
cfg80211_cac_event(sdata->dev, &chandef,
NL80211_RADAR_CAC_ABORTED,
GFP_KERNEL, link_id);
@@ -2077,6 +2092,7 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
params->vht_capa ||
params->he_capa ||
params->eht_capa ||
+ params->uhr_capa ||
params->s1g_capa ||
params->opmode_notif_used;
@@ -2125,8 +2141,7 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
if (params->supported_rates &&
params->supported_rates_len &&
- !ieee80211_parse_bitrates(link->conf->chanreq.oper.width,
- sband, params->supported_rates,
+ !ieee80211_parse_bitrates(sband, params->supported_rates,
params->supported_rates_len,
&link_sta->pub->supp_rates[sband->band]))
return -EINVAL;
@@ -2156,6 +2171,12 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
params->eht_capa_len,
link_sta);
+ if (params->uhr_capa)
+ ieee80211_uhr_cap_ie_to_sta_uhr_cap(sdata, sband,
+ params->uhr_capa,
+ params->uhr_capa_len,
+ link_sta);
+
if (params->s1g_capa)
ieee80211_s1g_cap_to_sta_s1g_cap(sdata, params->s1g_capa,
link_sta);
@@ -2199,6 +2220,9 @@ static int sta_apply_parameters(struct ieee80211_local *local,
mask = params->sta_flags_mask;
set = params->sta_flags_set;
+ if (params->epp_peer)
+ sta->sta.epp_peer = true;
+
if (ieee80211_vif_is_mesh(&sdata->vif)) {
/*
* In mesh mode, ASSOCIATED isn't part of the nl80211
@@ -2987,8 +3011,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
return -EINVAL;
if (params->basic_rates) {
- if (!ieee80211_parse_bitrates(link->conf->chanreq.oper.width,
- wiphy->bands[sband->band],
+ if (!ieee80211_parse_bitrates(sband,
params->basic_rates,
params->basic_rates_len,
&link->conf->basic_rates))
@@ -3865,8 +3888,8 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
if (err)
return err;
- wiphy_delayed_work_queue(wiphy, &link_data->dfs_cac_timer_work,
- msecs_to_jiffies(cac_time_ms));
+ wiphy_hrtimer_work_queue(wiphy, &link_data->dfs_cac_timer_work,
+ ms_to_ktime(cac_time_ms));
return 0;
}
@@ -3885,7 +3908,7 @@ static void ieee80211_end_cac(struct wiphy *wiphy,
if (!link_data)
continue;
- wiphy_delayed_work_cancel(wiphy,
+ wiphy_hrtimer_work_cancel(wiphy,
&link_data->dfs_cac_timer_work);
if (sdata->wdev.links[link_id].cac_started) {
@@ -4151,12 +4174,21 @@ static int __ieee80211_csa_finalize(struct ieee80211_link_data *link_data)
static void ieee80211_csa_finalize(struct ieee80211_link_data *link_data)
{
struct ieee80211_sub_if_data *sdata = link_data->sdata;
+ int link_id = -1;
if (__ieee80211_csa_finalize(link_data)) {
sdata_info(sdata, "failed to finalize CSA on link %d, disconnecting\n",
link_data->link_id);
- cfg80211_stop_iface(sdata->local->hw.wiphy, &sdata->wdev,
- GFP_KERNEL);
+ if (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_P2P_GO)
+ /*
+ * link_id is expected only for AP/P2P_GO type
+ * currently
+ */
+ link_id = link_data->link_id;
+
+ cfg80211_stop_link(sdata->local->hw.wiphy, &sdata->wdev,
+ link_id, GFP_KERNEL);
}
}
@@ -4400,7 +4432,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
goto out;
/* if reservation is invalid then this will fail */
- err = ieee80211_check_combinations(sdata, NULL, chanctx->mode, 0, -1);
+ err = ieee80211_check_combinations(sdata, NULL, 0, 0, -1);
if (err) {
ieee80211_link_unreserve_chanctx(link_data);
goto out;