Commit d9f83f22 authored by Shaul Triebitz's avatar Shaul Triebitz Committed by Johannes Berg

wifi: mac80211: use link in start/stop ap

Use link and link_conf according to the link_id
provided by cfg in start_ap/stop_ap and change_beacon.
Also use them in the functions called by them.
Note that for a non MLD device, the link_id is 0,
and link[0] and link_conf[0] equal to deflink and
bss_conf respectively (what was there before).

Also, call vif_info_change for BSS related changes (SSID), and
link_info_change for LINK related changes (instead of the
legacy bss_info_change).
Signed-off-by: default avatarShaul Triebitz <shaul.triebitz@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 0d8c4a3c
...@@ -114,14 +114,15 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, ...@@ -114,14 +114,15 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
} }
static int ieee80211_set_ap_mbssid_options(struct ieee80211_sub_if_data *sdata, static int ieee80211_set_ap_mbssid_options(struct ieee80211_sub_if_data *sdata,
struct cfg80211_mbssid_config params) struct cfg80211_mbssid_config params,
struct ieee80211_bss_conf *link_conf)
{ {
struct ieee80211_sub_if_data *tx_sdata; struct ieee80211_sub_if_data *tx_sdata;
sdata->vif.mbssid_tx_vif = NULL; sdata->vif.mbssid_tx_vif = NULL;
sdata->vif.bss_conf.bssid_index = 0; link_conf->bssid_index = 0;
sdata->vif.bss_conf.nontransmitted = false; link_conf->nontransmitted = false;
sdata->vif.bss_conf.ema_ap = false; link_conf->ema_ap = false;
if (sdata->vif.type != NL80211_IFTYPE_AP || !params.tx_wdev) if (sdata->vif.type != NL80211_IFTYPE_AP || !params.tx_wdev)
return -EINVAL; return -EINVAL;
...@@ -134,11 +135,11 @@ static int ieee80211_set_ap_mbssid_options(struct ieee80211_sub_if_data *sdata, ...@@ -134,11 +135,11 @@ static int ieee80211_set_ap_mbssid_options(struct ieee80211_sub_if_data *sdata,
sdata->vif.mbssid_tx_vif = &sdata->vif; sdata->vif.mbssid_tx_vif = &sdata->vif;
} else { } else {
sdata->vif.mbssid_tx_vif = &tx_sdata->vif; sdata->vif.mbssid_tx_vif = &tx_sdata->vif;
sdata->vif.bss_conf.nontransmitted = true; link_conf->nontransmitted = true;
sdata->vif.bss_conf.bssid_index = params.index; link_conf->bssid_index = params.index;
} }
if (params.ema) if (params.ema)
sdata->vif.bss_conf.ema_ap = true; link_conf->ema_ap = true;
return 0; return 0;
} }
...@@ -861,14 +862,15 @@ static int ...@@ -861,14 +862,15 @@ static int
ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
const u8 *resp, size_t resp_len, const u8 *resp, size_t resp_len,
const struct ieee80211_csa_settings *csa, const struct ieee80211_csa_settings *csa,
const struct ieee80211_color_change_settings *cca) const struct ieee80211_color_change_settings *cca,
struct ieee80211_link_data *link)
{ {
struct probe_resp *new, *old; struct probe_resp *new, *old;
if (!resp || !resp_len) if (!resp || !resp_len)
return 1; return 1;
old = sdata_dereference(sdata->deflink.u.ap.probe_resp, sdata); old = sdata_dereference(link->u.ap.probe_resp, sdata);
new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL); new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL);
if (!new) if (!new)
...@@ -884,7 +886,7 @@ ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, ...@@ -884,7 +886,7 @@ ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
else if (cca) else if (cca)
new->cntdwn_counter_offsets[0] = cca->counter_offset_presp; new->cntdwn_counter_offsets[0] = cca->counter_offset_presp;
rcu_assign_pointer(sdata->deflink.u.ap.probe_resp, new); rcu_assign_pointer(link->u.ap.probe_resp, new);
if (old) if (old)
kfree_rcu(old, rcu_head); kfree_rcu(old, rcu_head);
...@@ -892,7 +894,9 @@ ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, ...@@ -892,7 +894,9 @@ ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
} }
static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata, static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata,
struct cfg80211_fils_discovery *params) struct cfg80211_fils_discovery *params,
struct ieee80211_link_data *link,
struct ieee80211_bss_conf *link_conf)
{ {
struct fils_discovery_data *new, *old = NULL; struct fils_discovery_data *new, *old = NULL;
struct ieee80211_fils_discovery *fd; struct ieee80211_fils_discovery *fd;
...@@ -900,17 +904,17 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata, ...@@ -900,17 +904,17 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata,
if (!params->tmpl || !params->tmpl_len) if (!params->tmpl || !params->tmpl_len)
return -EINVAL; return -EINVAL;
fd = &sdata->vif.bss_conf.fils_discovery; fd = &link_conf->fils_discovery;
fd->min_interval = params->min_interval; fd->min_interval = params->min_interval;
fd->max_interval = params->max_interval; fd->max_interval = params->max_interval;
old = sdata_dereference(sdata->deflink.u.ap.fils_discovery, sdata); old = sdata_dereference(link->u.ap.fils_discovery, sdata);
new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL); new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
if (!new) if (!new)
return -ENOMEM; return -ENOMEM;
new->len = params->tmpl_len; new->len = params->tmpl_len;
memcpy(new->data, params->tmpl, params->tmpl_len); memcpy(new->data, params->tmpl, params->tmpl_len);
rcu_assign_pointer(sdata->deflink.u.ap.fils_discovery, new); rcu_assign_pointer(link->u.ap.fils_discovery, new);
if (old) if (old)
kfree_rcu(old, rcu_head); kfree_rcu(old, rcu_head);
...@@ -920,27 +924,27 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata, ...@@ -920,27 +924,27 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata,
static int static int
ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata, ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata,
struct cfg80211_unsol_bcast_probe_resp *params) struct cfg80211_unsol_bcast_probe_resp *params,
struct ieee80211_link_data *link,
struct ieee80211_bss_conf *link_conf)
{ {
struct unsol_bcast_probe_resp_data *new, *old = NULL; struct unsol_bcast_probe_resp_data *new, *old = NULL;
if (!params->tmpl || !params->tmpl_len) if (!params->tmpl || !params->tmpl_len)
return -EINVAL; return -EINVAL;
old = sdata_dereference(sdata->deflink.u.ap.unsol_bcast_probe_resp, old = sdata_dereference(link->u.ap.unsol_bcast_probe_resp, sdata);
sdata);
new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL); new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
if (!new) if (!new)
return -ENOMEM; return -ENOMEM;
new->len = params->tmpl_len; new->len = params->tmpl_len;
memcpy(new->data, params->tmpl, params->tmpl_len); memcpy(new->data, params->tmpl, params->tmpl_len);
rcu_assign_pointer(sdata->deflink.u.ap.unsol_bcast_probe_resp, new); rcu_assign_pointer(link->u.ap.unsol_bcast_probe_resp, new);
if (old) if (old)
kfree_rcu(old, rcu_head); kfree_rcu(old, rcu_head);
sdata->vif.bss_conf.unsol_bcast_probe_resp_interval = link_conf->unsol_bcast_probe_resp_interval = params->interval;
params->interval;
return 0; return 0;
} }
...@@ -948,18 +952,17 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata, ...@@ -948,18 +952,17 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata,
static int ieee80211_set_ftm_responder_params( static int ieee80211_set_ftm_responder_params(
struct ieee80211_sub_if_data *sdata, struct ieee80211_sub_if_data *sdata,
const u8 *lci, size_t lci_len, const u8 *lci, size_t lci_len,
const u8 *civicloc, size_t civicloc_len) const u8 *civicloc, size_t civicloc_len,
struct ieee80211_bss_conf *link_conf)
{ {
struct ieee80211_ftm_responder_params *new, *old; struct ieee80211_ftm_responder_params *new, *old;
struct ieee80211_bss_conf *bss_conf;
u8 *pos; u8 *pos;
int len; int len;
if (!lci_len && !civicloc_len) if (!lci_len && !civicloc_len)
return 0; return 0;
bss_conf = &sdata->vif.bss_conf; old = link_conf->ftmr_params;
old = bss_conf->ftmr_params;
len = lci_len + civicloc_len; len = lci_len + civicloc_len;
new = kzalloc(sizeof(*new) + len, GFP_KERNEL); new = kzalloc(sizeof(*new) + len, GFP_KERNEL);
...@@ -981,7 +984,7 @@ static int ieee80211_set_ftm_responder_params( ...@@ -981,7 +984,7 @@ static int ieee80211_set_ftm_responder_params(
pos += civicloc_len; pos += civicloc_len;
} }
bss_conf->ftmr_params = new; link_conf->ftmr_params = new;
kfree(old); kfree(old);
return 0; return 0;
...@@ -1014,8 +1017,11 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -1014,8 +1017,11 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
int new_head_len, new_tail_len; int new_head_len, new_tail_len;
int size, err; int size, err;
u32 changed = BSS_CHANGED_BEACON; u32 changed = BSS_CHANGED_BEACON;
struct ieee80211_link_data *link = sdata->link[params->link_id];
struct ieee80211_bss_conf *link_conf =
sdata->vif.link_conf[params->link_id];
old = sdata_dereference(sdata->deflink.u.ap.beacon, sdata); old = sdata_dereference(link->u.ap.beacon, sdata);
/* Need to have a beacon head if we don't have one yet */ /* Need to have a beacon head if we don't have one yet */
if (!params->head && !old) if (!params->head && !old)
...@@ -1069,7 +1075,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -1069,7 +1075,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
pos += struct_size(new->mbssid_ies, elem, mbssid->cnt); pos += struct_size(new->mbssid_ies, elem, mbssid->cnt);
ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies, mbssid); ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies, mbssid);
/* update bssid_indicator */ /* update bssid_indicator */
sdata->vif.bss_conf.bssid_indicator = link_conf->bssid_indicator =
ilog2(__roundup_pow_of_two(mbssid->cnt + 1)); ilog2(__roundup_pow_of_two(mbssid->cnt + 1));
} }
...@@ -1097,7 +1103,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -1097,7 +1103,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
memcpy(new->tail, old->tail, new_tail_len); memcpy(new->tail, old->tail, new_tail_len);
err = ieee80211_set_probe_resp(sdata, params->probe_resp, err = ieee80211_set_probe_resp(sdata, params->probe_resp,
params->probe_resp_len, csa, cca); params->probe_resp_len, csa, cca, link);
if (err < 0) { if (err < 0) {
kfree(new); kfree(new);
return err; return err;
...@@ -1106,12 +1112,13 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -1106,12 +1112,13 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_AP_PROBE_RESP; changed |= BSS_CHANGED_AP_PROBE_RESP;
if (params->ftm_responder != -1) { if (params->ftm_responder != -1) {
sdata->vif.bss_conf.ftm_responder = params->ftm_responder; link_conf->ftm_responder = params->ftm_responder;
err = ieee80211_set_ftm_responder_params(sdata, err = ieee80211_set_ftm_responder_params(sdata,
params->lci, params->lci,
params->lci_len, params->lci_len,
params->civicloc, params->civicloc,
params->civicloc_len); params->civicloc_len,
link_conf);
if (err < 0) { if (err < 0) {
kfree(new); kfree(new);
...@@ -1121,7 +1128,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -1121,7 +1128,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_FTM_RESPONDER; changed |= BSS_CHANGED_FTM_RESPONDER;
} }
rcu_assign_pointer(sdata->deflink.u.ap.beacon, new); rcu_assign_pointer(link->u.ap.beacon, new);
sdata->u.ap.active = true; sdata->u.ap.active = true;
if (old) if (old)
...@@ -1140,33 +1147,35 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1140,33 +1147,35 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
u32 changed = BSS_CHANGED_BEACON_INT | u32 changed = BSS_CHANGED_BEACON_INT |
BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON_ENABLED |
BSS_CHANGED_BEACON | BSS_CHANGED_BEACON |
BSS_CHANGED_SSID |
BSS_CHANGED_P2P_PS | BSS_CHANGED_P2P_PS |
BSS_CHANGED_TXPOWER | BSS_CHANGED_TXPOWER |
BSS_CHANGED_TWT; BSS_CHANGED_TWT;
int i, err; int i, err;
int prev_beacon_int; int prev_beacon_int;
unsigned int link_id = params->beacon.link_id;
struct ieee80211_link_data *link = sdata->link[link_id];
struct ieee80211_bss_conf *link_conf = sdata->vif.link_conf[link_id];
old = sdata_dereference(sdata->deflink.u.ap.beacon, sdata); old = sdata_dereference(link->u.ap.beacon, sdata);
if (old) if (old)
return -EALREADY; return -EALREADY;
if (params->smps_mode != NL80211_SMPS_OFF) if (params->smps_mode != NL80211_SMPS_OFF)
return -ENOTSUPP; return -ENOTSUPP;
sdata->deflink.smps_mode = IEEE80211_SMPS_OFF; link->smps_mode = IEEE80211_SMPS_OFF;
sdata->deflink.needed_rx_chains = sdata->local->rx_chains; link->needed_rx_chains = sdata->local->rx_chains;
prev_beacon_int = sdata->vif.bss_conf.beacon_int; prev_beacon_int = link_conf->beacon_int;
sdata->vif.bss_conf.beacon_int = params->beacon_interval; link_conf->beacon_int = params->beacon_interval;
if (params->he_cap && params->he_oper) { if (params->he_cap && params->he_oper) {
sdata->vif.bss_conf.he_support = true; link_conf->he_support = true;
sdata->vif.bss_conf.htc_trig_based_pkt_ext = link_conf->htc_trig_based_pkt_ext =
le32_get_bits(params->he_oper->he_oper_params, le32_get_bits(params->he_oper->he_oper_params,
IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK); IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK);
sdata->vif.bss_conf.frame_time_rts_th = link_conf->frame_time_rts_th =
le32_get_bits(params->he_oper->he_oper_params, le32_get_bits(params->he_oper->he_oper_params,
IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK); IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK);
changed |= BSS_CHANGED_HE_OBSS_PD; changed |= BSS_CHANGED_HE_OBSS_PD;
...@@ -1178,21 +1187,20 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1178,21 +1187,20 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
if (sdata->vif.type == NL80211_IFTYPE_AP && if (sdata->vif.type == NL80211_IFTYPE_AP &&
params->mbssid_config.tx_wdev) { params->mbssid_config.tx_wdev) {
err = ieee80211_set_ap_mbssid_options(sdata, err = ieee80211_set_ap_mbssid_options(sdata,
params->mbssid_config); params->mbssid_config,
link_conf);
if (err) if (err)
return err; return err;
} }
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
err = ieee80211_link_use_channel(sdata->link[params->beacon.link_id], err = ieee80211_link_use_channel(link, &params->chandef,
&params->chandef,
IEEE80211_CHANCTX_SHARED); IEEE80211_CHANCTX_SHARED);
if (!err) if (!err)
ieee80211_link_copy_chanctx_to_vlans(sdata->link[params->beacon.link_id], ieee80211_link_copy_chanctx_to_vlans(link, false);
false);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
if (err) { if (err) {
sdata->vif.bss_conf.beacon_int = prev_beacon_int; link_conf->beacon_int = prev_beacon_int;
return err; return err;
} }
...@@ -1218,12 +1226,12 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1218,12 +1226,12 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
params->crypto.control_port_no_preauth; params->crypto.control_port_no_preauth;
} }
sdata->vif.bss_conf.dtim_period = params->dtim_period; link_conf->dtim_period = params->dtim_period;
sdata->vif.bss_conf.enable_beacon = true; link_conf->enable_beacon = true;
sdata->vif.bss_conf.allow_p2p_go_ps = sdata->vif.p2p; link_conf->allow_p2p_go_ps = sdata->vif.p2p;
sdata->vif.bss_conf.twt_responder = params->twt_responder; link_conf->twt_responder = params->twt_responder;
sdata->vif.bss_conf.he_obss_pd = params->he_obss_pd; link_conf->he_obss_pd = params->he_obss_pd;
sdata->vif.bss_conf.he_bss_color = params->beacon.he_bss_color; link_conf->he_bss_color = params->beacon.he_bss_color;
sdata->vif.cfg.s1g = params->chandef.chan->band == sdata->vif.cfg.s1g = params->chandef.chan->band ==
NL80211_BAND_S1GHZ; NL80211_BAND_S1GHZ;
...@@ -1231,15 +1239,15 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1231,15 +1239,15 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
if (params->ssid_len) if (params->ssid_len)
memcpy(sdata->vif.cfg.ssid, params->ssid, memcpy(sdata->vif.cfg.ssid, params->ssid,
params->ssid_len); params->ssid_len);
sdata->vif.bss_conf.hidden_ssid = link_conf->hidden_ssid =
(params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE);
memset(&sdata->vif.bss_conf.p2p_noa_attr, 0, memset(&link_conf->p2p_noa_attr, 0,
sizeof(sdata->vif.bss_conf.p2p_noa_attr)); sizeof(link_conf->p2p_noa_attr));
sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow = link_conf->p2p_noa_attr.oppps_ctwindow =
params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK; params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
if (params->p2p_opp_ps) if (params->p2p_opp_ps)
sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |= link_conf->p2p_noa_attr.oppps_ctwindow |=
IEEE80211_P2P_OPPPS_ENABLE_BIT; IEEE80211_P2P_OPPPS_ENABLE_BIT;
sdata->beacon_rate_set = false; sdata->beacon_rate_set = false;
...@@ -1254,7 +1262,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1254,7 +1262,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
} }
if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL))
sdata->vif.bss_conf.beacon_tx_rate = params->beacon_rate; link_conf->beacon_tx_rate = params->beacon_rate;
err = ieee80211_assign_beacon(sdata, &params->beacon, NULL, NULL); err = ieee80211_assign_beacon(sdata, &params->beacon, NULL, NULL);
if (err < 0) if (err < 0)
...@@ -1263,7 +1271,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1263,7 +1271,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
if (params->fils_discovery.max_interval) { if (params->fils_discovery.max_interval) {
err = ieee80211_set_fils_discovery(sdata, err = ieee80211_set_fils_discovery(sdata,
&params->fils_discovery); &params->fils_discovery,
link, link_conf);
if (err < 0) if (err < 0)
goto error; goto error;
changed |= BSS_CHANGED_FILS_DISCOVERY; changed |= BSS_CHANGED_FILS_DISCOVERY;
...@@ -1271,7 +1280,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1271,7 +1280,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
if (params->unsol_bcast_probe_resp.interval) { if (params->unsol_bcast_probe_resp.interval) {
err = ieee80211_set_unsol_bcast_probe_resp(sdata, err = ieee80211_set_unsol_bcast_probe_resp(sdata,
&params->unsol_bcast_probe_resp); &params->unsol_bcast_probe_resp,
link, link_conf);
if (err < 0) if (err < 0)
goto error; goto error;
changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP; changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP;
...@@ -1279,17 +1289,18 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1279,17 +1289,18 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
err = drv_start_ap(sdata->local, sdata); err = drv_start_ap(sdata->local, sdata);
if (err) { if (err) {
old = sdata_dereference(sdata->deflink.u.ap.beacon, sdata); old = sdata_dereference(link->u.ap.beacon, sdata);
if (old) if (old)
kfree_rcu(old, rcu_head); kfree_rcu(old, rcu_head);
RCU_INIT_POINTER(sdata->deflink.u.ap.beacon, NULL); RCU_INIT_POINTER(link->u.ap.beacon, NULL);
sdata->u.ap.active = false; sdata->u.ap.active = false;
goto error; goto error;
} }
ieee80211_recalc_dtim(local, sdata); ieee80211_recalc_dtim(local, sdata);
ieee80211_bss_info_change_notify(sdata, changed); ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_SSID);
ieee80211_link_info_change_notify(sdata, link_id, changed);
netif_carrier_on(dev); netif_carrier_on(dev);
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
...@@ -1299,7 +1310,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1299,7 +1310,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
error: error:
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
ieee80211_link_release_channel(sdata->link[params->beacon.link_id]); ieee80211_link_release_channel(link);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
return err; return err;
...@@ -1308,21 +1319,22 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1308,21 +1319,22 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_beacon_data *params) struct cfg80211_beacon_data *params)
{ {
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_bss_conf *bss_conf;
struct beacon_data *old; struct beacon_data *old;
int err; int err;
struct ieee80211_bss_conf *link_conf =
sdata->vif.link_conf[params->link_id];
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
sdata_assert_lock(sdata); sdata_assert_lock(sdata);
/* don't allow changing the beacon while a countdown is in place - offset /* don't allow changing the beacon while a countdown is in place - offset
* of channel switch counter may change * of channel switch counter may change
*/ */
if (sdata->vif.bss_conf.csa_active || sdata->vif.bss_conf.color_change_active) if (link_conf->csa_active || link_conf->color_change_active)
return -EBUSY; return -EBUSY;
old = sdata_dereference(sdata->deflink.u.ap.beacon, sdata); old = sdata_dereference(sdata->link[params->link_id]->u.ap.beacon,
sdata);
if (!old) if (!old)
return -ENOENT; return -ENOENT;
...@@ -1330,10 +1342,9 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, ...@@ -1330,10 +1342,9 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
if (err < 0) if (err < 0)
return err; return err;
bss_conf = &sdata->vif.bss_conf;
if (params->he_bss_color_valid && if (params->he_bss_color_valid &&
params->he_bss_color.enabled != bss_conf->he_bss_color.enabled) { params->he_bss_color.enabled != link_conf->he_bss_color.enabled) {
bss_conf->he_bss_color.enabled = params->he_bss_color.enabled; link_conf->he_bss_color.enabled = params->he_bss_color.enabled;
err |= BSS_CHANGED_HE_BSS_COLOR; err |= BSS_CHANGED_HE_BSS_COLOR;
} }
...@@ -1341,14 +1352,14 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, ...@@ -1341,14 +1352,14 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
return 0; return 0;
} }
static void ieee80211_free_next_beacon(struct ieee80211_sub_if_data *sdata) static void ieee80211_free_next_beacon(struct ieee80211_link_data *link)
{ {
if (!sdata->deflink.u.ap.next_beacon) if (!link->u.ap.next_beacon)
return; return;
kfree(sdata->deflink.u.ap.next_beacon->mbssid_ies); kfree(link->u.ap.next_beacon->mbssid_ies);
kfree(sdata->deflink.u.ap.next_beacon); kfree(link->u.ap.next_beacon);
sdata->deflink.u.ap.next_beacon = NULL; link->u.ap.next_beacon = NULL;
} }
static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
...@@ -1362,32 +1373,34 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1362,32 +1373,34 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
struct fils_discovery_data *old_fils_discovery; struct fils_discovery_data *old_fils_discovery;
struct unsol_bcast_probe_resp_data *old_unsol_bcast_probe_resp; struct unsol_bcast_probe_resp_data *old_unsol_bcast_probe_resp;
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
struct ieee80211_link_data *link = sdata->link[link_id];
struct ieee80211_bss_conf *link_conf = sdata->vif.link_conf[link_id];
sdata_assert_lock(sdata); sdata_assert_lock(sdata);
old_beacon = sdata_dereference(sdata->deflink.u.ap.beacon, sdata); old_beacon = sdata_dereference(link->u.ap.beacon, sdata);
if (!old_beacon) if (!old_beacon)
return -ENOENT; return -ENOENT;
old_probe_resp = sdata_dereference(sdata->deflink.u.ap.probe_resp, old_probe_resp = sdata_dereference(link->u.ap.probe_resp,
sdata); sdata);
old_fils_discovery = sdata_dereference(sdata->deflink.u.ap.fils_discovery, old_fils_discovery = sdata_dereference(link->u.ap.fils_discovery,
sdata); sdata);
old_unsol_bcast_probe_resp = old_unsol_bcast_probe_resp =
sdata_dereference(sdata->deflink.u.ap.unsol_bcast_probe_resp, sdata_dereference(link->u.ap.unsol_bcast_probe_resp,
sdata); sdata);
/* abort any running channel switch */ /* abort any running channel switch */
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
sdata->vif.bss_conf.csa_active = false; link_conf->csa_active = false;
if (sdata->deflink.csa_block_tx) { if (link->csa_block_tx) {
ieee80211_wake_vif_queues(local, sdata, ieee80211_wake_vif_queues(local, sdata,
IEEE80211_QUEUE_STOP_REASON_CSA); IEEE80211_QUEUE_STOP_REASON_CSA);
sdata->deflink.csa_block_tx = false; link->csa_block_tx = false;
} }
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
ieee80211_free_next_beacon(sdata); ieee80211_free_next_beacon(link);
/* turn off carrier for this interface and dependent VLANs */ /* turn off carrier for this interface and dependent VLANs */
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
...@@ -1396,10 +1409,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1396,10 +1409,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
/* remove beacon and probe response */ /* remove beacon and probe response */
sdata->u.ap.active = false; sdata->u.ap.active = false;
RCU_INIT_POINTER(sdata->deflink.u.ap.beacon, NULL); RCU_INIT_POINTER(link->u.ap.beacon, NULL);
RCU_INIT_POINTER(sdata->deflink.u.ap.probe_resp, NULL); RCU_INIT_POINTER(link->u.ap.probe_resp, NULL);
RCU_INIT_POINTER(sdata->deflink.u.ap.fils_discovery, NULL); RCU_INIT_POINTER(link->u.ap.fils_discovery, NULL);
RCU_INIT_POINTER(sdata->deflink.u.ap.unsol_bcast_probe_resp, NULL); RCU_INIT_POINTER(link->u.ap.unsol_bcast_probe_resp, NULL);
kfree_rcu(old_beacon, rcu_head); kfree_rcu(old_beacon, rcu_head);
if (old_probe_resp) if (old_probe_resp)
kfree_rcu(old_probe_resp, rcu_head); kfree_rcu(old_probe_resp, rcu_head);
...@@ -1408,13 +1421,13 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1408,13 +1421,13 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
if (old_unsol_bcast_probe_resp) if (old_unsol_bcast_probe_resp)
kfree_rcu(old_unsol_bcast_probe_resp, rcu_head); kfree_rcu(old_unsol_bcast_probe_resp, rcu_head);
kfree(sdata->vif.bss_conf.ftmr_params); kfree(link_conf->ftmr_params);
sdata->vif.bss_conf.ftmr_params = NULL; link_conf->ftmr_params = NULL;
__sta_info_flush(sdata, true); __sta_info_flush(sdata, true);
ieee80211_free_keys(sdata, true); ieee80211_free_keys(sdata, true);
sdata->vif.bss_conf.enable_beacon = false; link_conf->enable_beacon = false;
sdata->beacon_rate_set = false; sdata->beacon_rate_set = false;
sdata->vif.cfg.ssid_len = 0; sdata->vif.cfg.ssid_len = 0;
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
...@@ -1422,8 +1435,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1422,8 +1435,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
BSS_CHANGED_BEACON_ENABLED); BSS_CHANGED_BEACON_ENABLED);
if (sdata->wdev.cac_started) { if (sdata->wdev.cac_started) {
chandef = sdata->vif.bss_conf.chandef; chandef = link_conf->chandef;
cancel_delayed_work_sync(&sdata->deflink.dfs_cac_timer_work); cancel_delayed_work_sync(&link->dfs_cac_timer_work);
cfg80211_cac_event(sdata->dev, &chandef, cfg80211_cac_event(sdata->dev, &chandef,
NL80211_RADAR_CAC_ABORTED, NL80211_RADAR_CAC_ABORTED,
GFP_KERNEL); GFP_KERNEL);
...@@ -1436,8 +1449,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1436,8 +1449,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
ieee80211_purge_tx_queue(&local->hw, &sdata->u.ap.ps.bc_buf); ieee80211_purge_tx_queue(&local->hw, &sdata->u.ap.ps.bc_buf);
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
ieee80211_link_copy_chanctx_to_vlans(sdata->link[link_id], true); ieee80211_link_copy_chanctx_to_vlans(link, true);
ieee80211_link_release_channel(sdata->link[link_id]); ieee80211_link_release_channel(link);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
return 0; return 0;
...@@ -3335,7 +3348,7 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -3335,7 +3348,7 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
err = ieee80211_assign_beacon(sdata, err = ieee80211_assign_beacon(sdata,
sdata->deflink.u.ap.next_beacon, sdata->deflink.u.ap.next_beacon,
NULL, NULL); NULL, NULL);
ieee80211_free_next_beacon(sdata); ieee80211_free_next_beacon(&sdata->deflink);
if (err < 0) if (err < 0)
return err; return err;
...@@ -3491,7 +3504,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -3491,7 +3504,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
IEEE80211_MAX_CNTDWN_COUNTERS_NUM) || IEEE80211_MAX_CNTDWN_COUNTERS_NUM) ||
(params->n_counter_offsets_presp > (params->n_counter_offsets_presp >
IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) { IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) {
ieee80211_free_next_beacon(sdata); ieee80211_free_next_beacon(&sdata->deflink);
return -EINVAL; return -EINVAL;
} }
...@@ -3503,7 +3516,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -3503,7 +3516,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
err = ieee80211_assign_beacon(sdata, &params->beacon_csa, &csa, NULL); err = ieee80211_assign_beacon(sdata, &params->beacon_csa, &csa, NULL);
if (err < 0) { if (err < 0) {
ieee80211_free_next_beacon(sdata); ieee80211_free_next_beacon(&sdata->deflink);
return err; return err;
} }
*changed |= err; *changed |= err;
...@@ -3594,7 +3607,7 @@ static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata) ...@@ -3594,7 +3607,7 @@ static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata)
{ {
sdata->vif.bss_conf.color_change_active = false; sdata->vif.bss_conf.color_change_active = false;
ieee80211_free_next_beacon(sdata); ieee80211_free_next_beacon(&sdata->deflink);
cfg80211_color_change_aborted_notify(sdata->dev); cfg80211_color_change_aborted_notify(sdata->dev);
} }
...@@ -4340,7 +4353,7 @@ ieee80211_set_after_color_change_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -4340,7 +4353,7 @@ ieee80211_set_after_color_change_beacon(struct ieee80211_sub_if_data *sdata,
ret = ieee80211_assign_beacon(sdata, ret = ieee80211_assign_beacon(sdata,
sdata->deflink.u.ap.next_beacon, sdata->deflink.u.ap.next_beacon,
NULL, NULL); NULL, NULL);
ieee80211_free_next_beacon(sdata); ieee80211_free_next_beacon(&sdata->deflink);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -4383,7 +4396,7 @@ ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -4383,7 +4396,7 @@ ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata,
err = ieee80211_assign_beacon(sdata, &params->beacon_color_change, err = ieee80211_assign_beacon(sdata, &params->beacon_color_change,
NULL, &color_change); NULL, &color_change);
if (err < 0) { if (err < 0) {
ieee80211_free_next_beacon(sdata); ieee80211_free_next_beacon(&sdata->deflink);
return err; return err;
} }
*changed |= err; *changed |= err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment