}
static ieee80211_conn_flags_t
-ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
+ieee80211_determine_chantype(struct ieee80211_link_data *link,
struct ieee80211_supported_band *sband,
struct ieee80211_channel *channel,
u32 vht_cap_info,
const struct ieee80211_s1g_oper_ie *s1g_oper,
struct cfg80211_chan_def *chandef, bool tracking)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
struct cfg80211_chan_def vht_chandef;
struct ieee80211_sta_ht_cap sta_ht_cap;
ieee80211_conn_flags_t ret;
}
vht_chandef = *chandef;
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
he_oper &&
(le32_to_cpu(he_oper->he_oper_params) &
IEEE80211_HE_OPERATION_VHT_OPER_INFO)) {
if (!ieee80211_chandef_vht_oper(&sdata->local->hw, vht_cap_info,
&he_oper_vht_cap, ht_oper,
&vht_chandef)) {
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE))
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE))
sdata_info(sdata,
"HE AP VHT information is invalid, disabling HE\n");
ret = IEEE80211_CONN_DISABLE_HE | IEEE80211_CONN_DISABLE_EHT;
vht_cap_info,
vht_oper, ht_oper,
&vht_chandef)) {
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
sdata_info(sdata,
"AP VHT information is invalid, disabling VHT\n");
ret = IEEE80211_CONN_DISABLE_VHT;
}
if (!cfg80211_chandef_valid(&vht_chandef)) {
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
sdata_info(sdata,
"AP VHT information is invalid, disabling VHT\n");
ret = IEEE80211_CONN_DISABLE_VHT;
}
if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) {
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
sdata_info(sdata,
"AP VHT information doesn't match HT, disabling VHT\n");
ret = IEEE80211_CONN_DISABLE_VHT;
false, &eht_chandef);
if (!cfg80211_chandef_valid(&eht_chandef)) {
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT))
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT))
sdata_info(sdata,
"AP EHT information is invalid, disabling EHT\n");
ret = IEEE80211_CONN_DISABLE_EHT;
}
if (!cfg80211_chandef_compatible(chandef, &eht_chandef)) {
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT))
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT))
sdata_info(sdata,
"AP EHT information is incompatible, disabling EHT\n");
ret = IEEE80211_CONN_DISABLE_EHT;
* less common and wouldn't completely prevent using the AP.
*/
if (tracking &&
- cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef))
+ cfg80211_chandef_identical(chandef, &link->conf->chandef))
return ret;
/* don't print the message below for VHT mismatch if VHT is disabled */
return ret;
}
-static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
+static int ieee80211_config_bw(struct ieee80211_link_data *link,
struct sta_info *sta,
const struct ieee80211_ht_cap *ht_cap,
const struct ieee80211_vht_cap *vht_cap,
const struct ieee80211_s1g_oper_ie *s1g_oper,
const u8 *bssid, u32 *changed)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_channel *chan = sdata->vif.bss_conf.chandef.chan;
+ struct ieee80211_channel *chan = link->conf->chandef.chan;
struct ieee80211_supported_band *sband =
local->hw.wiphy->bands[chan->band];
struct cfg80211_chan_def chandef;
int ret;
/* if HT was/is disabled, don't track any bandwidth changes */
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT || !ht_oper)
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT || !ht_oper)
return 0;
/* don't check VHT if we associated as non-VHT station */
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)
vht_oper = NULL;
/* don't check HE if we associated as non-HE station */
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE ||
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE ||
!ieee80211_get_he_iftype_cap(sband,
ieee80211_vif_type_p2p(&sdata->vif))) {
he_oper = NULL;
}
/* don't check EHT if we associated as non-EHT station */
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT ||
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT ||
!ieee80211_get_eht_iftype_cap(sband,
ieee80211_vif_type_p2p(&sdata->vif)))
eht_oper = NULL;
* this may be applicable even if channel is identical
*/
ht_opmode = le16_to_cpu(ht_oper->operation_mode);
- if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
+ if (link->conf->ht_operation_mode != ht_opmode) {
*changed |= BSS_CHANGED_HT;
- sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
+ link->conf->ht_operation_mode = ht_opmode;
}
if (vht_cap)
vht_cap_info = le32_to_cpu(vht_cap->vht_cap_info);
/* calculate new channel (type) based on HT/VHT/HE operation IEs */
- flags = ieee80211_determine_chantype(sdata, sband, chan, vht_cap_info,
+ flags = ieee80211_determine_chantype(link, sband, chan, vht_cap_info,
ht_oper, vht_oper,
he_oper, eht_oper,
s1g_oper, &chandef, true);
* reasons) then switching to a 40 MHz channel now won't do us
* any good -- we couldn't use it with the AP.
*/
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_80P80MHZ &&
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_80P80MHZ &&
chandef.width == NL80211_CHAN_WIDTH_80P80)
flags |= ieee80211_chandef_downgrade(&chandef);
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_160MHZ &&
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_160MHZ &&
chandef.width == NL80211_CHAN_WIDTH_160)
flags |= ieee80211_chandef_downgrade(&chandef);
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_40MHZ &&
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_40MHZ &&
chandef.width > NL80211_CHAN_WIDTH_20)
flags |= ieee80211_chandef_downgrade(&chandef);
- if (cfg80211_chandef_identical(&chandef, &sdata->vif.bss_conf.chandef))
+ if (cfg80211_chandef_identical(&chandef, &link->conf->chandef))
return 0;
- sdata_info(sdata,
- "AP %pM changed bandwidth, new config is %d.%03d MHz, "
- "width %d (%d.%03d/%d MHz)\n",
- sdata->deflink.u.mgd.bssid, chandef.chan->center_freq,
- chandef.chan->freq_offset, chandef.width,
- chandef.center_freq1, chandef.freq1_offset,
- chandef.center_freq2);
-
- if (flags != (sdata->deflink.u.mgd.conn_flags &
+ link_info(link,
+ "AP %pM changed bandwidth, new config is %d.%03d MHz, width %d (%d.%03d/%d MHz)\n",
+ link->u.mgd.bssid, chandef.chan->center_freq,
+ chandef.chan->freq_offset, chandef.width,
+ chandef.center_freq1, chandef.freq1_offset,
+ chandef.center_freq2);
+
+ if (flags != (link->u.mgd.conn_flags &
(IEEE80211_CONN_DISABLE_HT |
IEEE80211_CONN_DISABLE_VHT |
IEEE80211_CONN_DISABLE_HE |
!cfg80211_chandef_valid(&chandef)) {
sdata_info(sdata,
"AP %pM changed caps/bw in a way we can't support (0x%x/0x%x) - disconnect\n",
- sdata->deflink.u.mgd.bssid, flags, ifmgd->flags);
+ link->u.mgd.bssid, flags, ifmgd->flags);
return -EINVAL;
}
- ret = ieee80211_link_change_bandwidth(&sdata->deflink, &chandef, changed);
+ ret = ieee80211_link_change_bandwidth(link, &chandef, changed);
if (ret) {
sdata_info(sdata,
"AP %pM changed bandwidth to incompatible one - disconnect\n",
- sdata->deflink.u.mgd.bssid);
+ link->u.mgd.bssid);
return ret;
}
/* frame sending functions */
-static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
+static void ieee80211_add_ht_ie(struct ieee80211_link_data *link,
struct sk_buff *skb, u8 ap_ht_param,
struct ieee80211_supported_band *sband,
struct ieee80211_channel *channel,
enum ieee80211_smps_mode smps)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
u8 *pos;
u32 flags = channel->flags;
u16 cap;
* capable of 40 MHz -- some broken APs will never fall
* back to trying to transmit in 20 MHz.
*/
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_40MHZ) {
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_40MHZ) {
cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
cap &= ~IEEE80211_HT_CAP_SGI_40;
}
* and builds the IE.
* Note - the function may set the owner of the MU-MIMO capability
*/
-static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
+static void ieee80211_add_vht_ie(struct ieee80211_link_data *link,
struct sk_buff *skb,
struct ieee80211_supported_band *sband,
struct ieee80211_vht_cap *ap_vht_cap)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_local *local = sdata->local;
u8 *pos;
u32 cap;
/* determine capability flags */
cap = vht_cap.cap;
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_80P80MHZ) {
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_80P80MHZ) {
u32 bw = cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
}
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_160MHZ) {
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_160MHZ) {
cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;
cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
}
if (disable_mu_mimo)
cap &= ~IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
else
- sdata->vif.bss_conf.mu_mimo_owner = true;
+ link->conf->mu_mimo_owner = true;
}
mask = IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
/* This function determines HE capability flags for the association
* and builds the IE.
*/
-static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
+static void ieee80211_add_he_ie(struct ieee80211_link_data *link,
struct sk_buff *skb,
struct ieee80211_supported_band *sband)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
u8 *pos, *pre_he_pos;
const struct ieee80211_sta_he_cap *he_cap = NULL;
struct ieee80211_chanctx_conf *chanctx_conf;
bool reg_cap = false;
rcu_read_lock();
- chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
+ chanctx_conf = rcu_dereference(link->conf->chanctx_conf);
if (!WARN_ON_ONCE(!chanctx_conf))
reg_cap = cfg80211_chandef_usable(sdata->wdev.wiphy,
&chanctx_conf->def,
he_cap->he_cap_elem.phy_cap_info);
pos = skb_put(skb, he_cap_size);
pre_he_pos = pos;
- pos = ieee80211_ie_build_he_cap(sdata->deflink.u.mgd.conn_flags,
+ pos = ieee80211_ie_build_he_cap(link->u.mgd.conn_flags,
pos, he_cap, pos + he_cap_size);
/* trim excess if any */
skb_trim(skb, skb->len - (pre_he_pos + he_cap_size - pos));
ieee80211_ie_build_he_6ghz_cap(sdata, skb);
}
-static void ieee80211_add_eht_ie(struct ieee80211_sub_if_data *sdata,
+static void ieee80211_add_eht_ie(struct ieee80211_link_data *link,
struct sk_buff *skb,
struct ieee80211_supported_band *sband)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
u8 *pos;
const struct ieee80211_sta_he_cap *he_cap;
const struct ieee80211_sta_eht_cap *eht_cap;
bool reg_cap = false;
rcu_read_lock();
- chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
+ chanctx_conf = rcu_dereference(link->conf->chanctx_conf);
if (!WARN_ON_ONCE(!chanctx_conf))
reg_cap = cfg80211_chandef_usable(sdata->wdev.wiphy,
&chanctx_conf->def,
enum nl80211_iftype iftype = ieee80211_vif_type_p2p(&sdata->vif);
const struct ieee80211_sband_iftype_data *iftd;
struct ieee80211_prep_tx_info info = {};
+ struct ieee80211_link_data *link = &sdata->deflink;
int ret;
/* we know it's writable, cast away the const */
sdata_assert_lock(sdata);
rcu_read_lock();
- chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
+ chanctx_conf = rcu_dereference(link->conf->chanctx_conf);
if (WARN_ON(!chanctx_conf)) {
rcu_read_unlock();
return -EINVAL;
/* Set MBSSID support for HE AP if needed */
if (ieee80211_hw_check(&local->hw, SUPPORTS_ONLY_HE_MULTI_BSSID) &&
- !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && assoc_data->ie_len &&
+ !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && assoc_data->ie_len &&
ext_capa && ext_capa->datalen >= 3)
ext_capa->data[2] |= WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT;
offset = noffset;
}
- if (WARN_ON_ONCE((sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) &&
- !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)))
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
+ if (WARN_ON_ONCE((link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) &&
+ !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)))
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
if (sband->band != NL80211_BAND_6GHZ &&
- !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT))
- ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param,
- sband, chan, sdata->deflink.smps_mode);
+ !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT))
+ ieee80211_add_ht_ie(link, skb, assoc_data->ap_ht_param,
+ sband, chan, link->smps_mode);
/* if present, add any custom IEs that go before VHT */
if (assoc_data->ie_len) {
}
if (sband->band != NL80211_BAND_6GHZ &&
- !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
- ieee80211_add_vht_ie(sdata, skb, sband,
+ !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
+ ieee80211_add_vht_ie(link, skb, sband,
&assoc_data->ap_vht_cap);
/*
* If AP doesn't support HT, mark HE and EHT as disabled.
* If on the 5GHz band, make sure it supports VHT.
*/
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT ||
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT ||
(sband->band == NL80211_BAND_5GHZ &&
- sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE |
+ link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE |
IEEE80211_CONN_DISABLE_EHT;
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE)) {
- ieee80211_add_he_ie(sdata, skb, sband);
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE)) {
+ ieee80211_add_he_ie(link, skb, sband);
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT))
- ieee80211_add_eht_ie(sdata, skb, sband);
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT))
+ ieee80211_add_eht_ie(link, skb, sband);
}
/* if present, add any custom non-vendor IEs that go after HE */
/* spectrum management related things */
static void ieee80211_chswitch_work(struct work_struct *work)
{
- struct ieee80211_sub_if_data *sdata =
- container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
+ struct ieee80211_link_data *link =
+ container_of(work, struct ieee80211_link_data, u.mgd.chswitch_work);
+ struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
int ret;
if (!ifmgd->associated)
goto out;
- if (!sdata->vif.bss_conf.csa_active)
+ if (!link->conf->csa_active)
goto out;
/*
* completed successfully
*/
- if (sdata->deflink.reserved_chanctx) {
+ if (link->reserved_chanctx) {
/*
* with multi-vif csa driver may call ieee80211_csa_finish()
* many times while waiting for other interfaces to use their
* reservations
*/
- if (sdata->deflink.reserved_ready)
+ if (link->reserved_ready)
goto out;
- ret = ieee80211_link_use_reserved_context(&sdata->deflink);
+ ret = ieee80211_link_use_reserved_context(link);
if (ret) {
sdata_info(sdata,
"failed to use reserved channel context, disconnecting (err=%d)\n",
goto out;
}
- if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef,
- &sdata->deflink.csa_chandef)) {
+ if (!cfg80211_chandef_identical(&link->conf->chandef,
+ &link->csa_chandef)) {
sdata_info(sdata,
"failed to finalize channel switch, disconnecting\n");
ieee80211_queue_work(&sdata->local->hw,
goto out;
}
- sdata->deflink.u.mgd.csa_waiting_bcn = true;
+ link->u.mgd.csa_waiting_bcn = true;
ieee80211_sta_reset_beacon_monitor(sdata);
ieee80211_sta_reset_conn_monitor(sdata);
sdata_unlock(sdata);
}
-static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_chswitch_post_beacon(struct ieee80211_link_data *link)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
int ret;
sdata_assert_lock(sdata);
- WARN_ON(!sdata->vif.bss_conf.csa_active);
+ WARN_ON(!link->conf->csa_active);
- if (sdata->deflink.csa_block_tx) {
+ if (link->csa_block_tx) {
ieee80211_wake_vif_queues(local, sdata,
IEEE80211_QUEUE_STOP_REASON_CSA);
- sdata->deflink.csa_block_tx = false;
+ link->csa_block_tx = false;
}
- sdata->vif.bss_conf.csa_active = false;
- sdata->deflink.u.mgd.csa_waiting_bcn = false;
+ link->conf->csa_active = false;
+ link->u.mgd.csa_waiting_bcn = false;
/*
* If the CSA IE is still present on the beacon after the switch,
* we need to consider it as a new CSA (possibly to self).
*/
- sdata->deflink.u.mgd.beacon_crc_valid = false;
+ link->u.mgd.beacon_crc_valid = false;
ret = drv_post_channel_switch(sdata);
if (ret) {
return;
}
- cfg80211_ch_switch_notify(sdata->dev, &sdata->deflink.reserved_chandef,
- 0);
+ cfg80211_ch_switch_notify(sdata->dev, &link->reserved_chandef, 0);
}
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ if (WARN_ON(sdata->vif.valid_links))
+ success = false;
+
trace_api_chswitch_done(sdata, success);
if (!success) {
sdata_info(sdata,
ieee80211_queue_work(&sdata->local->hw,
&ifmgd->csa_connection_drop_work);
} else {
- ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
+ ieee80211_queue_work(&sdata->local->hw,
+ &sdata->deflink.u.mgd.chswitch_work);
}
}
EXPORT_SYMBOL(ieee80211_chswitch_done);
static void ieee80211_chswitch_timer(struct timer_list *t)
{
- struct ieee80211_sub_if_data *sdata =
- from_timer(sdata, t, u.mgd.chswitch_timer);
+ struct ieee80211_link_data *link =
+ from_timer(link, t, u.mgd.chswitch_timer);
- ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
+ ieee80211_queue_work(&link->sdata->local->hw,
+ &link->u.mgd.chswitch_work);
}
static void
-ieee80211_sta_abort_chanswitch(struct ieee80211_sub_if_data *sdata)
+ieee80211_sta_abort_chanswitch(struct ieee80211_link_data *link)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_local *local = sdata->local;
if (!local->ops->abort_channel_switch)
mutex_lock(&local->mtx);
mutex_lock(&local->chanctx_mtx);
- ieee80211_link_unreserve_chanctx(&sdata->deflink);
+ ieee80211_link_unreserve_chanctx(link);
mutex_unlock(&local->chanctx_mtx);
- if (sdata->deflink.csa_block_tx)
+ if (link->csa_block_tx)
ieee80211_wake_vif_queues(local, sdata,
IEEE80211_QUEUE_STOP_REASON_CSA);
- sdata->deflink.csa_block_tx = false;
- sdata->vif.bss_conf.csa_active = false;
+ link->csa_block_tx = false;
+ link->conf->csa_active = false;
mutex_unlock(&local->mtx);
}
static void
-ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
+ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
u64 timestamp, u32 device_timestamp,
struct ieee802_11_elems *elems,
bool beacon)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct cfg80211_bss *cbss = sdata->deflink.u.mgd.bss;
+ struct cfg80211_bss *cbss = link->u.mgd.bss;
struct ieee80211_chanctx_conf *conf;
struct ieee80211_chanctx *chanctx;
enum nl80211_band current_band;
bss = (void *)cbss->priv;
res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band,
bss->vht_cap_info,
- sdata->deflink.u.mgd.conn_flags,
- sdata->deflink.u.mgd.bssid, &csa_ie);
+ link->u.mgd.conn_flags,
+ link->u.mgd.bssid, &csa_ie);
if (!res) {
ch_switch.timestamp = timestamp;
if (res < 0)
goto lock_and_drop_connection;
- if (beacon && sdata->vif.bss_conf.csa_active &&
- !sdata->deflink.u.mgd.csa_waiting_bcn) {
+ if (beacon && link->conf->csa_active &&
+ !link->u.mgd.csa_waiting_bcn) {
if (res)
- ieee80211_sta_abort_chanswitch(sdata);
+ ieee80211_sta_abort_chanswitch(link);
else
drv_channel_switch_rx_beacon(sdata, &ch_switch);
return;
- } else if (sdata->vif.bss_conf.csa_active || res) {
+ } else if (link->conf->csa_active || res) {
/* disregard subsequent announcements if already processing */
return;
}
- if (sdata->vif.bss_conf.chandef.chan->band !=
+ if (link->conf->chandef.chan->band !=
csa_ie.chandef.chan->band) {
sdata_info(sdata,
"AP %pM switches to different band (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
- sdata->deflink.u.mgd.bssid,
+ link->u.mgd.bssid,
csa_ie.chandef.chan->center_freq,
csa_ie.chandef.width, csa_ie.chandef.center_freq1,
csa_ie.chandef.center_freq2);
"AP %pM switches to unsupported channel "
"(%d.%03d MHz, width:%d, CF1/2: %d.%03d/%d MHz), "
"disconnecting\n",
- sdata->deflink.u.mgd.bssid,
+ link->u.mgd.bssid,
csa_ie.chandef.chan->center_freq,
csa_ie.chandef.chan->freq_offset,
csa_ie.chandef.width, csa_ie.chandef.center_freq1,
}
if (cfg80211_chandef_identical(&csa_ie.chandef,
- &sdata->vif.bss_conf.chandef) &&
+ &link->conf->chandef) &&
(!csa_ie.mode || !beacon)) {
- if (sdata->deflink.u.mgd.csa_ignored_same_chan)
+ if (link->u.mgd.csa_ignored_same_chan)
return;
sdata_info(sdata,
"AP %pM tries to chanswitch to same channel, ignore\n",
- sdata->deflink.u.mgd.bssid);
- sdata->deflink.u.mgd.csa_ignored_same_chan = true;
+ link->u.mgd.bssid);
+ link->u.mgd.csa_ignored_same_chan = true;
return;
}
mutex_lock(&local->mtx);
mutex_lock(&local->chanctx_mtx);
- conf = rcu_dereference_protected(sdata->vif.bss_conf.chanctx_conf,
+ conf = rcu_dereference_protected(link->conf->chanctx_conf,
lockdep_is_held(&local->chanctx_mtx));
if (!conf) {
sdata_info(sdata,
goto drop_connection;
}
- res = ieee80211_link_reserve_chanctx(&sdata->deflink, &csa_ie.chandef,
+ res = ieee80211_link_reserve_chanctx(link, &csa_ie.chandef,
chanctx->mode, false);
if (res) {
sdata_info(sdata,
}
mutex_unlock(&local->chanctx_mtx);
- sdata->vif.bss_conf.csa_active = true;
- sdata->deflink.csa_chandef = csa_ie.chandef;
- sdata->deflink.csa_block_tx = csa_ie.mode;
- sdata->deflink.u.mgd.csa_ignored_same_chan = false;
- sdata->deflink.u.mgd.beacon_crc_valid = false;
+ link->conf->csa_active = true;
+ link->csa_chandef = csa_ie.chandef;
+ link->csa_block_tx = csa_ie.mode;
+ link->u.mgd.csa_ignored_same_chan = false;
+ link->u.mgd.beacon_crc_valid = false;
- if (sdata->deflink.csa_block_tx)
+ if (link->csa_block_tx)
ieee80211_stop_vif_queues(local, sdata,
IEEE80211_QUEUE_STOP_REASON_CSA);
mutex_unlock(&local->mtx);
/* channel switch handled in software */
if (csa_ie.count <= 1)
- ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work);
+ ieee80211_queue_work(&local->hw, &link->u.mgd.chswitch_work);
else
- mod_timer(&ifmgd->chswitch_timer,
+ mod_timer(&link->u.mgd.chswitch_timer,
TU_TO_EXP_TIME((csa_ie.count - 1) *
cbss->beacon_interval));
return;
* send a deauthentication frame. Those two fields will be
* reset when the disconnection worker runs.
*/
- sdata->vif.bss_conf.csa_active = true;
- sdata->deflink.csa_block_tx = csa_ie.mode;
+ link->conf->csa_active = true;
+ link->csa_block_tx = csa_ie.mode;
ieee80211_queue_work(&local->hw, &ifmgd->csa_connection_drop_work);
mutex_unlock(&local->chanctx_mtx);
*pwr_level = (__s8)cisco_dtpc_ie[4];
}
-static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
+static u32 ieee80211_handle_pwr_constr(struct ieee80211_link_data *link,
struct ieee80211_channel *channel,
struct ieee80211_mgmt *mgmt,
const u8 *country_ie, u8 country_ie_len,
const u8 *pwr_constr_ie,
const u8 *cisco_dtpc_ie)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
bool has_80211h_pwr = false, has_cisco_pwr = false;
int chan_pwr = 0, pwr_reduction_80211h = 0;
int pwr_level_cisco, pwr_level_80211h;
(!has_cisco_pwr || pwr_level_80211h <= pwr_level_cisco)) {
new_ap_level = pwr_level_80211h;
- if (sdata->deflink.ap_power_level == new_ap_level)
+ if (link->ap_power_level == new_ap_level)
return 0;
sdata_dbg(sdata,
"Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
pwr_level_80211h, chan_pwr, pwr_reduction_80211h,
- sdata->deflink.u.mgd.bssid);
+ link->u.mgd.bssid);
} else { /* has_cisco_pwr is always true here. */
new_ap_level = pwr_level_cisco;
- if (sdata->deflink.ap_power_level == new_ap_level)
+ if (link->ap_power_level == new_ap_level)
return 0;
sdata_dbg(sdata,
"Limiting TX power to %d dBm as advertised by %pM\n",
- pwr_level_cisco, sdata->deflink.u.mgd.bssid);
+ pwr_level_cisco, link->u.mgd.bssid);
}
- sdata->deflink.ap_power_level = new_ap_level;
+ link->ap_power_level = new_ap_level;
if (__ieee80211_recalc_txpower(sdata))
return BSS_CHANGED_TXPOWER;
return 0;
void ieee80211_dfs_cac_timer_work(struct work_struct *work)
{
struct delayed_work *delayed_work = to_delayed_work(work);
- struct ieee80211_sub_if_data *sdata =
- container_of(delayed_work, struct ieee80211_sub_if_data,
- deflink.dfs_cac_timer_work);
- struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef;
+ struct ieee80211_link_data *link =
+ container_of(delayed_work, struct ieee80211_link_data,
+ dfs_cac_timer_work);
+ struct cfg80211_chan_def chandef = link->conf->chandef;
+ struct ieee80211_sub_if_data *sdata = link->sdata;
mutex_lock(&sdata->local->mtx);
if (sdata->wdev.cac_started) {
- ieee80211_link_release_channel(&sdata->deflink);
+ ieee80211_link_release_channel(link);
cfg80211_cac_event(sdata->dev, &chandef,
NL80211_RADAR_CAC_FINISHED,
GFP_KERNEL);
{
struct ieee80211_bss *bss = (void *)cbss->priv;
struct ieee80211_local *local = sdata->local;
- struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
+ struct ieee80211_link_data *link = &sdata->deflink;
+ struct ieee80211_bss_conf *bss_conf = link->conf;
struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg;
bss_info_changed |= BSS_CHANGED_ASSOC;
beacon_loss_count * bss_conf->beacon_int));
sdata->u.mgd.associated = true;
- sdata->deflink.u.mgd.bss = cbss;
- memcpy(sdata->deflink.u.mgd.bssid, cbss->bssid, ETH_ALEN);
+ link->u.mgd.bss = cbss;
+ memcpy(link->u.mgd.bssid, cbss->bssid, ETH_ALEN);
memcpy(sdata->vif.cfg.ap_addr, cbss->bssid, ETH_ALEN);
ieee80211_check_rate_mask(sdata);
(u8 *) &bss_conf->p2p_noa_attr,
sizeof(bss_conf->p2p_noa_attr));
if (ret >= 2) {
- sdata->deflink.u.mgd.p2p_noa_index =
+ link->u.mgd.p2p_noa_index =
bss_conf->p2p_noa_attr.index;
bss_info_changed |= BSS_CHANGED_P2P_PS;
}
ieee80211_led_assoc(local, 1);
- if (sdata->deflink.u.mgd.have_beacon) {
+ if (link->u.mgd.have_beacon) {
/*
* If the AP is buggy we may get here with no DTIM period
* known, so assume it's 1 which is the only safe assumption
* in that case, although if the TIM IE is broken powersave
* probably just won't work at all.
*/
- bss_conf->dtim_period = sdata->deflink.u.mgd.dtim_period ?: 1;
+ bss_conf->dtim_period = link->u.mgd.dtim_period ?: 1;
bss_conf->beacon_rate = bss->beacon_rate;
bss_info_changed |= BSS_CHANGED_BEACON_INFO;
} else {
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
+ struct ieee80211_link_data *link = &sdata->deflink;
u32 changed = 0;
struct ieee80211_prep_tx_info info = {
.subtype = stype,
ieee80211_stop_poll(sdata);
ifmgd->associated = false;
- sdata->deflink.u.mgd.bss = NULL;
+ link->u.mgd.bss = NULL;
netif_carrier_off(sdata->dev);
/*
* driver requested so.
*/
if (ieee80211_hw_check(&local->hw, DEAUTH_NEED_MGD_TX_PREP) &&
- !sdata->deflink.u.mgd.have_beacon) {
+ !link->u.mgd.have_beacon) {
drv_mgd_prepare_tx(sdata->local, sdata, &info);
}
- ieee80211_send_deauth_disassoc(sdata, sdata->deflink.u.mgd.bssid,
- sdata->deflink.u.mgd.bssid, stype, reason,
+ ieee80211_send_deauth_disassoc(sdata, link->u.mgd.bssid,
+ link->u.mgd.bssid, stype, reason,
tx, frame_buf);
}
drv_mgd_complete_tx(sdata->local, sdata, &info);
/* clear bssid only after building the needed mgmt frames */
- eth_zero_addr(sdata->deflink.u.mgd.bssid);
+ eth_zero_addr(link->u.mgd.bssid);
eth_zero_addr(sdata->vif.cfg.ap_addr);
sdata->vif.cfg.ssid_len = 0;
changed |= BSS_CHANGED_ASSOC;
sdata->vif.cfg.assoc = false;
- sdata->deflink.u.mgd.p2p_noa_index = -1;
- memset(&sdata->vif.bss_conf.p2p_noa_attr, 0,
- sizeof(sdata->vif.bss_conf.p2p_noa_attr));
+ link->u.mgd.p2p_noa_index = -1;
+ memset(&link->conf->p2p_noa_attr, 0,
+ sizeof(link->conf->p2p_noa_attr));
/* on the next assoc, re-program HT/VHT parameters */
memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask));
/* reset MU-MIMO ownership and group data */
- memset(sdata->vif.bss_conf.mu_group.membership, 0,
- sizeof(sdata->vif.bss_conf.mu_group.membership));
- memset(sdata->vif.bss_conf.mu_group.position, 0,
- sizeof(sdata->vif.bss_conf.mu_group.position));
+ memset(link->conf->mu_group.membership, 0,
+ sizeof(link->conf->mu_group.membership));
+ memset(link->conf->mu_group.position, 0,
+ sizeof(link->conf->mu_group.position));
changed |= BSS_CHANGED_MU_GROUPS;
- sdata->vif.bss_conf.mu_mimo_owner = false;
+ link->conf->mu_mimo_owner = false;
- sdata->deflink.ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
+ link->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
del_timer_sync(&local->dynamic_ps_timer);
cancel_work_sync(&local->dynamic_ps_enable_work);
if (sdata->vif.cfg.arp_addr_cnt)
changed |= BSS_CHANGED_ARP_FILTER;
- sdata->vif.bss_conf.qos = false;
+ link->conf->qos = false;
changed |= BSS_CHANGED_QOS;
/* The BSSID (not really interesting) and HT changed */
del_timer_sync(&sdata->u.mgd.conn_mon_timer);
del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
del_timer_sync(&sdata->u.mgd.timer);
- del_timer_sync(&sdata->u.mgd.chswitch_timer);
+ del_timer_sync(&link->u.mgd.chswitch_timer);
- sdata->vif.bss_conf.dtim_period = 0;
- sdata->vif.bss_conf.beacon_rate = NULL;
+ link->conf->dtim_period = 0;
+ link->conf->beacon_rate = NULL;
- sdata->deflink.u.mgd.have_beacon = false;
- sdata->deflink.u.mgd.tracking_signal_avg = false;
+ link->u.mgd.have_beacon = false;
+ link->u.mgd.tracking_signal_avg = false;
ifmgd->flags = 0;
- sdata->deflink.u.mgd.conn_flags = 0;
+ link->u.mgd.conn_flags = 0;
mutex_lock(&local->mtx);
- ieee80211_link_release_channel(&sdata->deflink);
+ ieee80211_link_release_channel(link);
- sdata->vif.bss_conf.csa_active = false;
- sdata->deflink.u.mgd.csa_waiting_bcn = false;
- sdata->deflink.u.mgd.csa_ignored_same_chan = false;
- if (sdata->deflink.csa_block_tx) {
+ link->conf->csa_active = false;
+ link->u.mgd.csa_waiting_bcn = false;
+ link->u.mgd.csa_ignored_same_chan = false;
+ if (link->csa_block_tx) {
ieee80211_wake_vif_queues(local, sdata,
IEEE80211_QUEUE_STOP_REASON_CSA);
- sdata->deflink.csa_block_tx = false;
+ link->csa_block_tx = false;
}
mutex_unlock(&local->mtx);
u8 unicast_limit = max(1, max_probe_tries - 3);
struct sta_info *sta;
+ if (WARN_ON(sdata->vif.valid_links))
+ return;
+
/*
* Try sending broadcast probe requests for the last three
* probe requests after the first ones failed since some
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
bool already = false;
+ if (WARN_ON(sdata->vif.valid_links))
+ return;
+
if (!ieee80211_sdata_running(sdata))
return;
const struct element *ssid;
int ssid_len;
- if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
+ if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION ||
+ sdata->vif.valid_links))
return NULL;
sdata_assert_lock(sdata);
u.mgd.beacon_connection_loss_work);
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- if (ifmgd->associated)
- sdata->deflink.u.mgd.beacon_loss_count++;
-
if (ifmgd->connection_loss) {
sdata_info(sdata, "Connection to AP %pM lost\n",
sdata->vif.cfg.ap_addr);
__ieee80211_disconnect(sdata);
ifmgd->driver_disconnect = false;
} else {
+ if (ifmgd->associated)
+ sdata->deflink.u.mgd.beacon_loss_count++;
ieee80211_mgd_probe_ap(sdata, true);
}
}
del_timer_sync(&sdata->u.mgd.timer);
sta_info_destroy_addr(sdata, auth_data->bss->bssid);
+ /* FIXME: other links are destroyed? */
+ sdata->deflink.u.mgd.conn_flags = 0;
eth_zero_addr(sdata->deflink.u.mgd.bssid);
ieee80211_link_info_change_notify(sdata, &sdata->deflink,
BSS_CHANGED_BSSID);
sdata->u.mgd.flags = 0;
- sdata->deflink.u.mgd.conn_flags = 0;
mutex_lock(&sdata->local->mtx);
ieee80211_link_release_channel(&sdata->deflink);
mutex_unlock(&sdata->local->mtx);
del_timer_sync(&sdata->u.mgd.timer);
sta_info_destroy_addr(sdata, assoc_data->bss->bssid);
+ /* FIXME: other links are destroyed? */
+ sdata->deflink.u.mgd.conn_flags = 0;
eth_zero_addr(sdata->deflink.u.mgd.bssid);
ieee80211_link_info_change_notify(sdata, &sdata->deflink,
BSS_CHANGED_BSSID);
sdata->u.mgd.flags = 0;
- sdata->deflink.u.mgd.conn_flags = 0;
sdata->vif.bss_conf.mu_mimo_owner = false;
mutex_lock(&sdata->local->mtx);
IEEE80211_HE_MAC_CAP0_TWT_RES;
}
-static int ieee80211_recalc_twt_req(struct ieee80211_sub_if_data *sdata,
+static int ieee80211_recalc_twt_req(struct ieee80211_link_data *link,
struct sta_info *sta,
struct ieee802_11_elems *elems)
{
bool twt = ieee80211_twt_req_supported(sta, elems);
- if (sdata->vif.bss_conf.twt_requester != twt) {
- sdata->vif.bss_conf.twt_requester = twt;
+ if (link->conf->twt_requester != twt) {
+ link->conf->twt_requester = twt;
return BSS_CHANGED_TWT;
}
return 0;
struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ;
bool is_s1g = cbss->channel->band == NL80211_BAND_S1GHZ;
+ struct ieee80211_link_data *link = &sdata->deflink;
u32 changed = 0;
u8 *pos;
int err;
*/
if (!is_6ghz &&
((assoc_data->wmm && !elems->wmm_param) ||
- (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) &&
+ (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) &&
(!elems->ht_cap_elem || !elems->ht_operation)) ||
- (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) &&
+ (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) &&
(!elems->vht_cap_elem || !elems->vht_operation)))) {
const struct cfg80211_bss_ies *ies;
struct ieee802_11_elems *bss_elems;
* have to include the IEs in the (re)association response.
*/
if (!elems->ht_cap_elem && bss_elems->ht_cap_elem &&
- !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) {
+ !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) {
elems->ht_cap_elem = bss_elems->ht_cap_elem;
sdata_info(sdata,
"AP bug: HT capability missing from AssocResp\n");
}
if (!elems->ht_operation && bss_elems->ht_operation &&
- !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) {
+ !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) {
elems->ht_operation = bss_elems->ht_operation;
sdata_info(sdata,
"AP bug: HT operation missing from AssocResp\n");
}
if (!elems->vht_cap_elem && bss_elems->vht_cap_elem &&
- !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) {
+ !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) {
elems->vht_cap_elem = bss_elems->vht_cap_elem;
sdata_info(sdata,
"AP bug: VHT capa missing from AssocResp\n");
}
if (!elems->vht_operation && bss_elems->vht_operation &&
- !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) {
+ !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) {
elems->vht_operation = bss_elems->vht_operation;
sdata_info(sdata,
"AP bug: VHT operation missing from AssocResp\n");
* We previously checked these in the beacon/probe response, so
* they should be present here. This is just a safety net.
*/
- if (!is_6ghz && !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) &&
+ if (!is_6ghz && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) &&
(!elems->wmm_param || !elems->ht_cap_elem || !elems->ht_operation)) {
sdata_info(sdata,
"HT AP is missing WMM params or HT capability/operation\n");
goto out;
}
- if (!is_6ghz && !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) &&
+ if (!is_6ghz && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) &&
(!elems->vht_cap_elem || !elems->vht_operation)) {
sdata_info(sdata,
"VHT AP is missing VHT capability/operation\n");
goto out;
}
- if (is_6ghz && !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
+ if (is_6ghz && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
!elems->he_6ghz_capa) {
sdata_info(sdata,
"HE 6 GHz AP is missing HE 6 GHz band capability\n");
goto out;
}
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
(!elems->he_cap || !elems->he_operation)) {
mutex_unlock(&sdata->local->sta_mtx);
sdata_info(sdata,
}
/* Set up internal HT/VHT capabilities */
- if (elems->ht_cap_elem && !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT))
+ if (elems->ht_cap_elem && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT))
ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
elems->ht_cap_elem,
&sta->deflink);
- if (elems->vht_cap_elem && !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
+ if (elems->vht_cap_elem && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
elems->vht_cap_elem,
&sta->deflink);
- if (elems->he_operation && !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
+ if (elems->he_operation && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
elems->he_cap) {
ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
elems->he_cap,
else
bss_conf->twt_protected = false;
- changed |= ieee80211_recalc_twt_req(sdata, sta, elems);
+ changed |= ieee80211_recalc_twt_req(link, sta, elems);
if (elems->eht_operation && elems->eht_cap &&
- !(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT)) {
+ !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT)) {
ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband,
elems->he_cap,
elems->he_cap_len,
* that effect because the AP values is an unsigned
* 4-bit value.
*/
- sdata->deflink.u.mgd.wmm_last_param_set = -1;
- sdata->deflink.u.mgd.mu_edca_last_param_set = -1;
+ link->u.mgd.wmm_last_param_set = -1;
+ link->u.mgd.mu_edca_last_param_set = -1;
if (ifmgd->flags & IEEE80211_STA_DISABLE_WMM) {
- ieee80211_set_wmm_default(&sdata->deflink, false, false);
- } else if (!ieee80211_sta_wmm_params(local, &sdata->deflink,
- elems->wmm_param,
+ ieee80211_set_wmm_default(link, false, false);
+ } else if (!ieee80211_sta_wmm_params(local, link, elems->wmm_param,
elems->wmm_param_len,
elems->mu_edca_param_set)) {
/* still enable QoS since we might have HT/VHT */
- ieee80211_set_wmm_default(&sdata->deflink, false, true);
+ ieee80211_set_wmm_default(link, false, true);
/* set the disable-WMM flag in this case to disable
* tracking WMM parameter changes in the beacon if
* the parameters weren't actually valid. Doing so
kfree(elems);
}
-static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
+static void ieee80211_rx_bss_info(struct ieee80211_link_data *link,
struct ieee80211_mgmt *mgmt, size_t len,
struct ieee80211_rx_status *rx_status)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_local *local = sdata->local;
struct ieee80211_bss *bss;
struct ieee80211_channel *channel;
bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, channel);
if (bss) {
- sdata->vif.bss_conf.beacon_rate = bss->beacon_rate;
+ link->conf->beacon_rate = bss->beacon_rate;
ieee80211_rx_bss_put(local, bss);
}
}
-static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
+static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_link_data *link,
struct sk_buff *skb)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_mgmt *mgmt = (void *)skb->data;
struct ieee80211_if_managed *ifmgd;
struct ieee80211_rx_status *rx_status = (void *) skb->cb;
if (baselen > len)
return;
- ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
+ ieee80211_rx_bss_info(link, mgmt, len, rx_status);
if (ifmgd->associated &&
- ether_addr_equal(mgmt->bssid, sdata->deflink.u.mgd.bssid))
+ ether_addr_equal(mgmt->bssid, link->u.mgd.bssid))
ieee80211_reset_ap_probe(sdata);
}
(1ULL << WLAN_EID_HT_OPERATION) |
(1ULL << WLAN_EID_EXT_CHANSWITCH_ANN);
-static void ieee80211_handle_beacon_sig(struct ieee80211_sub_if_data *sdata,
+static void ieee80211_handle_beacon_sig(struct ieee80211_link_data *link,
struct ieee80211_if_managed *ifmgd,
struct ieee80211_bss_conf *bss_conf,
struct ieee80211_local *local,
struct ieee80211_rx_status *rx_status)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
+
/* Track average RSSI from the Beacon frames of the current AP */
- if (!sdata->deflink.u.mgd.tracking_signal_avg) {
- sdata->deflink.u.mgd.tracking_signal_avg = true;
- ewma_beacon_signal_init(&sdata->deflink.u.mgd.ave_beacon_signal);
- sdata->deflink.u.mgd.last_cqm_event_signal = 0;
- sdata->deflink.u.mgd.count_beacon_signal = 1;
- sdata->deflink.u.mgd.last_ave_beacon_signal = 0;
+ if (!link->u.mgd.tracking_signal_avg) {
+ link->u.mgd.tracking_signal_avg = true;
+ ewma_beacon_signal_init(&link->u.mgd.ave_beacon_signal);
+ link->u.mgd.last_cqm_event_signal = 0;
+ link->u.mgd.count_beacon_signal = 1;
+ link->u.mgd.last_ave_beacon_signal = 0;
} else {
- sdata->deflink.u.mgd.count_beacon_signal++;
+ link->u.mgd.count_beacon_signal++;
}
- ewma_beacon_signal_add(&sdata->deflink.u.mgd.ave_beacon_signal,
+ ewma_beacon_signal_add(&link->u.mgd.ave_beacon_signal,
-rx_status->signal);
if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold &&
- sdata->deflink.u.mgd.count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
- int sig = -ewma_beacon_signal_read(&sdata->deflink.u.mgd.ave_beacon_signal);
- int last_sig = sdata->deflink.u.mgd.last_ave_beacon_signal;
+ link->u.mgd.count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
+ int sig = -ewma_beacon_signal_read(&link->u.mgd.ave_beacon_signal);
+ int last_sig = link->u.mgd.last_ave_beacon_signal;
struct ieee80211_event event = {
.type = RSSI_EVENT,
};
*/
if (sig > ifmgd->rssi_max_thold &&
(last_sig <= ifmgd->rssi_min_thold || last_sig == 0)) {
- sdata->deflink.u.mgd.last_ave_beacon_signal = sig;
+ link->u.mgd.last_ave_beacon_signal = sig;
event.u.rssi.data = RSSI_EVENT_HIGH;
drv_event_callback(local, sdata, &event);
} else if (sig < ifmgd->rssi_min_thold &&
(last_sig >= ifmgd->rssi_max_thold ||
last_sig == 0)) {
- sdata->deflink.u.mgd.last_ave_beacon_signal = sig;
+ link->u.mgd.last_ave_beacon_signal = sig;
event.u.rssi.data = RSSI_EVENT_LOW;
drv_event_callback(local, sdata, &event);
}
}
if (bss_conf->cqm_rssi_thold &&
- sdata->deflink.u.mgd.count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT &&
+ link->u.mgd.count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT &&
!(sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) {
- int sig = -ewma_beacon_signal_read(&sdata->deflink.u.mgd.ave_beacon_signal);
- int last_event = sdata->deflink.u.mgd.last_cqm_event_signal;
+ int sig = -ewma_beacon_signal_read(&link->u.mgd.ave_beacon_signal);
+ int last_event = link->u.mgd.last_cqm_event_signal;
int thold = bss_conf->cqm_rssi_thold;
int hyst = bss_conf->cqm_rssi_hyst;
if (sig < thold &&
(last_event == 0 || sig < last_event - hyst)) {
- sdata->deflink.u.mgd.last_cqm_event_signal = sig;
+ link->u.mgd.last_cqm_event_signal = sig;
ieee80211_cqm_rssi_notify(
&sdata->vif,
NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
sig, GFP_KERNEL);
} else if (sig > thold &&
(last_event == 0 || sig > last_event + hyst)) {
- sdata->deflink.u.mgd.last_cqm_event_signal = sig;
+ link->u.mgd.last_cqm_event_signal = sig;
ieee80211_cqm_rssi_notify(
&sdata->vif,
NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
}
if (bss_conf->cqm_rssi_low &&
- sdata->deflink.u.mgd.count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
- int sig = -ewma_beacon_signal_read(&sdata->deflink.u.mgd.ave_beacon_signal);
- int last_event = sdata->deflink.u.mgd.last_cqm_event_signal;
+ link->u.mgd.count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
+ int sig = -ewma_beacon_signal_read(&link->u.mgd.ave_beacon_signal);
+ int last_event = link->u.mgd.last_cqm_event_signal;
int low = bss_conf->cqm_rssi_low;
int high = bss_conf->cqm_rssi_high;
if (sig < low &&
(last_event == 0 || last_event >= low)) {
- sdata->deflink.u.mgd.last_cqm_event_signal = sig;
+ link->u.mgd.last_cqm_event_signal = sig;
ieee80211_cqm_rssi_notify(
&sdata->vif,
NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
sig, GFP_KERNEL);
} else if (sig > high &&
(last_event == 0 || last_event <= high)) {
- sdata->deflink.u.mgd.last_cqm_event_signal = sig;
+ link->u.mgd.last_cqm_event_signal = sig;
ieee80211_cqm_rssi_notify(
&sdata->vif,
NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
return ether_addr_equal(tx_bssid, bss->transmitted_bss->bssid);
}
-static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
+static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
struct ieee80211_hdr *hdr, size_t len,
struct ieee80211_rx_status *rx_status)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg;
return;
rcu_read_lock();
- chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
+ chanctx_conf = rcu_dereference(link->conf->chanctx_conf);
if (!chanctx_conf) {
rcu_read_unlock();
return;
if (!elems)
return;
- ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
+ ieee80211_rx_bss_info(link, mgmt, len, rx_status);
if (elems->dtim_period)
- sdata->deflink.u.mgd.dtim_period = elems->dtim_period;
- sdata->deflink.u.mgd.have_beacon = true;
+ link->u.mgd.dtim_period = elems->dtim_period;
+ link->u.mgd.have_beacon = true;
ifmgd->assoc_data->need_beacon = false;
if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
- sdata->vif.bss_conf.sync_tsf =
+ link->conf->sync_tsf =
le64_to_cpu(mgmt->u.beacon.timestamp);
- sdata->vif.bss_conf.sync_device_ts =
+ link->conf->sync_device_ts =
rx_status->device_timestamp;
- sdata->vif.bss_conf.sync_dtim_count = elems->dtim_count;
+ link->conf->sync_dtim_count = elems->dtim_count;
}
if (elems->mbssid_config_ie)
}
if (!ifmgd->associated ||
- !ieee80211_rx_our_beacon(bssid, sdata->deflink.u.mgd.bss))
+ !ieee80211_rx_our_beacon(bssid, link->u.mgd.bss))
return;
- bssid = sdata->deflink.u.mgd.bssid;
+ bssid = link->u.mgd.bssid;
if (!(rx_status->flag & RX_FLAG_NO_SIGNAL_VAL))
- ieee80211_handle_beacon_sig(sdata, ifmgd, bss_conf,
+ ieee80211_handle_beacon_sig(link, ifmgd, bss_conf,
local, rx_status);
if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) {
IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
(u8 *) &noa, sizeof(noa));
if (ret >= 2) {
- if (sdata->deflink.u.mgd.p2p_noa_index != noa.index) {
+ if (link->u.mgd.p2p_noa_index != noa.index) {
/* valid noa_attr and index changed */
- sdata->deflink.u.mgd.p2p_noa_index = noa.index;
+ link->u.mgd.p2p_noa_index = noa.index;
memcpy(&bss_conf->p2p_noa_attr, &noa, sizeof(noa));
changed |= BSS_CHANGED_P2P_PS;
/*
* make sure we update all information, the CRC
* mechanism doesn't look at P2P attributes.
*/
- sdata->deflink.u.mgd.beacon_crc_valid = false;
+ link->u.mgd.beacon_crc_valid = false;
}
- } else if (sdata->deflink.u.mgd.p2p_noa_index != -1) {
+ } else if (link->u.mgd.p2p_noa_index != -1) {
/* noa_attr not found and we had valid noa_attr before */
- sdata->deflink.u.mgd.p2p_noa_index = -1;
+ link->u.mgd.p2p_noa_index = -1;
memset(&bss_conf->p2p_noa_attr, 0, sizeof(bss_conf->p2p_noa_attr));
changed |= BSS_CHANGED_P2P_PS;
- sdata->deflink.u.mgd.beacon_crc_valid = false;
+ link->u.mgd.beacon_crc_valid = false;
}
}
- if (sdata->deflink.u.mgd.csa_waiting_bcn)
- ieee80211_chswitch_post_beacon(sdata);
+ if (link->u.mgd.csa_waiting_bcn)
+ ieee80211_chswitch_post_beacon(link);
/*
* Update beacon timing and dtim count on every beacon appearance. This
*/
if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY) &&
!ieee80211_is_s1g_beacon(hdr->frame_control)) {
- sdata->vif.bss_conf.sync_tsf =
+ link->conf->sync_tsf =
le64_to_cpu(mgmt->u.beacon.timestamp);
- sdata->vif.bss_conf.sync_device_ts =
+ link->conf->sync_device_ts =
rx_status->device_timestamp;
- sdata->vif.bss_conf.sync_dtim_count = elems->dtim_count;
+ link->conf->sync_dtim_count = elems->dtim_count;
}
- if ((ncrc == sdata->deflink.u.mgd.beacon_crc && sdata->deflink.u.mgd.beacon_crc_valid) ||
+ if ((ncrc == link->u.mgd.beacon_crc && link->u.mgd.beacon_crc_valid) ||
ieee80211_is_s1g_short_beacon(mgmt->frame_control))
goto free;
- sdata->deflink.u.mgd.beacon_crc = ncrc;
- sdata->deflink.u.mgd.beacon_crc_valid = true;
+ link->u.mgd.beacon_crc = ncrc;
+ link->u.mgd.beacon_crc_valid = true;
- ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
+ ieee80211_rx_bss_info(link, mgmt, len, rx_status);
- ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
+ ieee80211_sta_process_chanswitch(link, rx_status->mactime,
rx_status->device_timestamp,
elems, true);
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) &&
- ieee80211_sta_wmm_params(local, &sdata->deflink, elems->wmm_param,
+ ieee80211_sta_wmm_params(local, link, elems->wmm_param,
elems->wmm_param_len,
elems->mu_edca_param_set))
changed |= BSS_CHANGED_QOS;
* If we haven't had a beacon before, tell the driver about the
* DTIM period (and beacon timing if desired) now.
*/
- if (!sdata->deflink.u.mgd.have_beacon) {
+ if (!link->u.mgd.have_beacon) {
/* a few bogus AP send dtim_period = 0 or no TIM IE */
bss_conf->dtim_period = elems->dtim_period ?: 1;
changed |= BSS_CHANGED_BEACON_INFO;
- sdata->deflink.u.mgd.have_beacon = true;
+ link->u.mgd.have_beacon = true;
mutex_lock(&local->iflist_mtx);
ieee80211_recalc_ps(local);
mutex_lock(&local->sta_mtx);
sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
- changed |= ieee80211_recalc_twt_req(sdata, sta, elems);
+ changed |= ieee80211_recalc_twt_req(link, sta, elems);
- if (ieee80211_config_bw(sdata, sta, elems->ht_cap_elem,
+ if (ieee80211_config_bw(link, sta, elems->ht_cap_elem,
elems->vht_cap_elem, elems->ht_operation,
elems->vht_operation, elems->he_operation,
elems->eht_operation,
}
if (sta && elems->opmode_notif)
- ieee80211_vht_handle_opmode(sdata,
- &sta->deflink,
+ ieee80211_vht_handle_opmode(sdata, &sta->deflink,
*elems->opmode_notif,
rx_status->band);
mutex_unlock(&local->sta_mtx);
- changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt,
+ changed |= ieee80211_handle_pwr_constr(link, chan, mgmt,
elems->country_elem,
elems->country_elem_len,
elems->pwr_constr_elem,
elems->cisco_dtpc_elem);
- ieee80211_link_info_change_notify(sdata, &sdata->deflink,
- changed);
+ ieee80211_link_info_change_notify(sdata, link, changed);
free:
kfree(elems);
}
void ieee80211_sta_rx_queued_ext(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
+ struct ieee80211_link_data *link = &sdata->deflink;
struct ieee80211_rx_status *rx_status;
struct ieee80211_hdr *hdr;
u16 fc;
sdata_lock(sdata);
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_S1G_BEACON:
- ieee80211_rx_mgmt_beacon(sdata, hdr, skb->len, rx_status);
+ ieee80211_rx_mgmt_beacon(link, hdr, skb->len, rx_status);
break;
}
sdata_unlock(sdata);
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
+ struct ieee80211_link_data *link = &sdata->deflink;
struct ieee80211_rx_status *rx_status;
struct ieee80211_mgmt *mgmt;
u16 fc;
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_BEACON:
- ieee80211_rx_mgmt_beacon(sdata, (void *)mgmt,
+ ieee80211_rx_mgmt_beacon(link, (void *)mgmt,
skb->len, rx_status);
break;
case IEEE80211_STYPE_PROBE_RESP:
- ieee80211_rx_mgmt_probe_resp(sdata, skb);
+ ieee80211_rx_mgmt_probe_resp(link, skb);
break;
case IEEE80211_STYPE_AUTH:
ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
ies_len, true, mgmt->bssid, NULL);
if (elems && !elems->parse_error)
- ieee80211_sta_process_chanswitch(sdata,
+ ieee80211_sta_process_chanswitch(link,
rx_status->mactime,
rx_status->device_timestamp,
elems, false);
elems->ext_chansw_ie =
&mgmt->u.action.u.ext_chan_switch.data;
- ieee80211_sta_process_chanswitch(sdata,
+ ieee80211_sta_process_chanswitch(link,
rx_status->mactime,
rx_status->device_timestamp,
elems, false);
struct ieee80211_sub_if_data *sdata =
from_timer(sdata, t, u.mgd.bcn_mon_timer);
+ if (WARN_ON(sdata->vif.valid_links))
+ return;
+
if (sdata->vif.bss_conf.csa_active &&
!sdata->deflink.u.mgd.csa_waiting_bcn)
return;
struct sta_info *sta;
unsigned long timeout;
+ if (WARN_ON(sdata->vif.valid_links))
+ return;
+
if (sdata->vif.bss_conf.csa_active &&
!sdata->deflink.u.mgd.csa_waiting_bcn)
return;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work);
- INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
INIT_WORK(&ifmgd->beacon_connection_loss_work,
ieee80211_beacon_connection_loss_work);
INIT_WORK(&ifmgd->csa_connection_drop_work,
timer_setup(&ifmgd->timer, ieee80211_sta_timer, 0);
timer_setup(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, 0);
timer_setup(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer, 0);
- timer_setup(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, 0);
INIT_DELAYED_WORK(&ifmgd->tx_tspec_wk,
ieee80211_sta_handle_tspec_ac_params_wk);
link->u.mgd.req_smps = IEEE80211_SMPS_AUTOMATIC;
else
link->u.mgd.req_smps = IEEE80211_SMPS_OFF;
+
+ INIT_WORK(&link->u.mgd.chswitch_work, ieee80211_chswitch_work);
+ timer_setup(&link->u.mgd.chswitch_timer, ieee80211_chswitch_timer, 0);
}
/* scan finished notification */
rcu_read_unlock();
}
-static u8 ieee80211_max_rx_chains(struct ieee80211_sub_if_data *sdata,
+static u8 ieee80211_max_rx_chains(struct ieee80211_link_data *link,
struct cfg80211_bss *cbss)
{
struct ieee80211_he_mcs_nss_supp *he_mcs_nss_supp;
bool support_160;
u8 chains = 1;
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)
return chains;
ht_cap_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_HT_CAPABILITY);
*/
}
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)
return chains;
vht_cap_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_VHT_CAPABILITY);
chains = max(chains, nss);
}
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE)
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE)
return chains;
ies = rcu_dereference(cbss->ies);
}
static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_link_data *link,
struct cfg80211_bss *cbss)
{
struct ieee80211_local *local = sdata->local;
sband = local->hw.wiphy->bands[cbss->channel->band];
- sdata->deflink.u.mgd.conn_flags &= ~(IEEE80211_CONN_DISABLE_40MHZ |
- IEEE80211_CONN_DISABLE_80P80MHZ |
- IEEE80211_CONN_DISABLE_160MHZ);
+ link->u.mgd.conn_flags &= ~(IEEE80211_CONN_DISABLE_40MHZ |
+ IEEE80211_CONN_DISABLE_80P80MHZ |
+ IEEE80211_CONN_DISABLE_160MHZ);
/* disable HT/VHT/HE if we don't support them */
if (!sband->ht_cap.ht_supported && !is_6ghz) {
mlme_dbg(sdata, "HT not supported, disabling HT/VHT/HE/EHT\n");
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
}
if (!sband->vht_cap.vht_supported && is_5ghz) {
mlme_dbg(sdata, "VHT not supported, disabling VHT/HE/EHT\n");
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
}
if (!ieee80211_get_he_iftype_cap(sband,
ieee80211_vif_type_p2p(&sdata->vif))) {
mlme_dbg(sdata, "HE not supported, disabling HE and EHT\n");
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
}
if (!ieee80211_get_eht_iftype_cap(sband,
ieee80211_vif_type_p2p(&sdata->vif))) {
mlme_dbg(sdata, "EHT not supported, disabling EHT\n");
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
}
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) && !is_6ghz) {
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) && !is_6ghz) {
ht_oper = elems->ht_operation;
ht_cap = elems->ht_cap_elem;
if (!ht_cap) {
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
ht_oper = NULL;
}
}
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) && !is_6ghz) {
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) && !is_6ghz) {
vht_oper = elems->vht_operation;
if (vht_oper && !ht_oper) {
vht_oper = NULL;
sdata_info(sdata,
"AP advertised VHT without HT, disabling HT/VHT/HE\n");
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
}
if (!elems->vht_cap_elem) {
sdata_info(sdata,
"bad VHT capabilities, disabling VHT\n");
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
vht_oper = NULL;
}
}
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE)) {
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE)) {
he_oper = elems->he_operation;
if (is_6ghz) {
struct ieee80211_bss_conf *bss_conf;
u8 i, j = 0;
- bss_conf = &sdata->vif.bss_conf;
+ bss_conf = link->conf;
if (elems->pwr_constr_elem)
bss_conf->pwr_reduction = *elems->pwr_constr_elem;
if (!ieee80211_verify_peer_he_mcs_support(sdata, ies, he_oper) ||
!ieee80211_verify_sta_he_mcs_support(sdata, sband, he_oper))
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE |
- IEEE80211_CONN_DISABLE_EHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE |
+ IEEE80211_CONN_DISABLE_EHT;
}
/*
* both the 6 GHz operation information (from the HE operation IE) and
* EHT operation.
*/
- if (!(sdata->deflink.u.mgd.conn_flags &
+ if (!(link->u.mgd.conn_flags &
(IEEE80211_CONN_DISABLE_HE |
IEEE80211_CONN_DISABLE_EHT)) &&
he_oper) {
if (!have_80mhz) {
sdata_info(sdata, "80 MHz not supported, disabling VHT\n");
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
}
if (sband->band == NL80211_BAND_S1GHZ) {
"AP missing S1G operation element?\n");
}
- sdata->deflink.u.mgd.conn_flags |=
- ieee80211_determine_chantype(sdata, sband,
+ link->u.mgd.conn_flags |=
+ ieee80211_determine_chantype(link, sband,
cbss->channel,
bss->vht_cap_info,
ht_oper, vht_oper,
s1g_oper,
&chandef, false);
- sdata->deflink.needed_rx_chains =
- min(ieee80211_max_rx_chains(sdata, cbss), local->rx_chains);
+ link->needed_rx_chains =
+ min(ieee80211_max_rx_chains(link, cbss), local->rx_chains);
rcu_read_unlock();
/* the element data was RCU protected so no longer valid anyway */
kfree(elems);
elems = NULL;
- if (sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE && is_6ghz) {
+ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE && is_6ghz) {
sdata_info(sdata, "Rejecting non-HE 6/7 GHz connection");
return -EINVAL;
}
/* will change later if needed */
- sdata->deflink.smps_mode = IEEE80211_SMPS_OFF;
+ link->smps_mode = IEEE80211_SMPS_OFF;
mutex_lock(&local->mtx);
/*
* on incompatible channels, e.g. 80+80 and 160 sharing the
* same control channel) try to use a smaller bandwidth.
*/
- ret = ieee80211_link_use_channel(&sdata->deflink, &chandef,
+ ret = ieee80211_link_use_channel(link, &chandef,
IEEE80211_CHANCTX_SHARED);
/* don't downgrade for 5 and 10 MHz channels, though. */
goto out;
while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
- sdata->deflink.u.mgd.conn_flags |=
+ link->u.mgd.conn_flags |=
ieee80211_chandef_downgrade(&chandef);
- ret = ieee80211_link_use_channel(&sdata->deflink, &chandef,
+ ret = ieee80211_link_use_channel(link, &chandef,
IEEE80211_CHANCTX_SHARED);
}
out:
struct ieee80211_bss *bss = (void *)cbss->priv;
struct sta_info *new_sta = NULL;
struct ieee80211_supported_band *sband;
+ struct ieee80211_link_data *link = &sdata->deflink;
bool have_sta = false;
int err;
int min_rate = INT_MAX, min_rate_index = -1;
const struct cfg80211_bss_ies *ies;
int shift = ieee80211_vif_get_shift(&sdata->vif);
+ struct ieee80211_link_sta *link_sta = &new_sta->sta.deflink;
+
+ memcpy(link_sta->addr, cbss->bssid, ETH_ALEN);
/* TODO: S1G Basic Rate Set is expressed elsewhere */
if (cbss->channel->band == NL80211_BAND_S1GHZ) {
}
if (rates)
- new_sta->sta.deflink.supp_rates[cbss->channel->band] = rates;
+ link_sta->supp_rates[cbss->channel->band] = rates;
else
sdata_info(sdata,
"No rates found, keeping mandatory only\n");
- sdata->vif.bss_conf.basic_rates = basic_rates;
+ link->conf->basic_rates = basic_rates;
/* cf. IEEE 802.11 9.2.12 */
if (cbss->channel->band == NL80211_BAND_2GHZ &&
sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
skip_rates:
- memcpy(sdata->deflink.u.mgd.bssid, cbss->bssid, ETH_ALEN);
+ memcpy(link->u.mgd.bssid, cbss->bssid, ETH_ALEN);
/* set timing information */
- sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;
+ link->conf->beacon_int = cbss->beacon_interval;
rcu_read_lock();
ies = rcu_dereference(cbss->beacon_ies);
if (ies) {
- sdata->vif.bss_conf.sync_tsf = ies->tsf;
- sdata->vif.bss_conf.sync_device_ts =
+ link->conf->sync_tsf = ies->tsf;
+ link->conf->sync_device_ts =
bss->device_ts_beacon;
ieee80211_get_dtim(ies,
- &sdata->vif.bss_conf.sync_dtim_count,
+ &link->conf->sync_dtim_count,
NULL);
} else if (!ieee80211_hw_check(&sdata->local->hw,
TIMING_BEACON_ONLY)) {
ies = rcu_dereference(cbss->proberesp_ies);
/* must be non-NULL since beacon IEs were NULL */
- sdata->vif.bss_conf.sync_tsf = ies->tsf;
- sdata->vif.bss_conf.sync_device_ts =
+ link->conf->sync_tsf = ies->tsf;
+ link->conf->sync_device_ts =
bss->device_ts_presp;
- sdata->vif.bss_conf.sync_dtim_count = 0;
+ link->conf->sync_dtim_count = 0;
} else {
- sdata->vif.bss_conf.sync_tsf = 0;
- sdata->vif.bss_conf.sync_device_ts = 0;
- sdata->vif.bss_conf.sync_dtim_count = 0;
+ link->conf->sync_tsf = 0;
+ link->conf->sync_device_ts = 0;
+ link->conf->sync_dtim_count = 0;
}
rcu_read_unlock();
}
if (new_sta || override) {
- err = ieee80211_prep_channel(sdata, cbss);
+ err = ieee80211_prep_channel(sdata, link, cbss);
if (err) {
if (new_sta)
sta_info_free(local, new_sta);
* tell driver about BSSID, basic rates and timing
* this was set up above, before setting the channel
*/
- ieee80211_link_info_change_notify(sdata, &sdata->deflink,
+ ieee80211_link_info_change_notify(sdata, link,
BSS_CHANGED_BSSID |
BSS_CHANGED_BASIC_RATES |
BSS_CHANGED_BEACON_INT);
return err;
}
} else
- WARN_ON_ONCE(!ether_addr_equal(sdata->deflink.u.mgd.bssid, cbss->bssid));
+ WARN_ON_ONCE(!ether_addr_equal(link->u.mgd.bssid, cbss->bssid));
/* Cancel scan to ensure that nothing interferes with connection */
if (local->scanning)
int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
struct cfg80211_auth_request *req)
{
+ struct ieee80211_link_data *link = &sdata->deflink;
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_mgd_auth_data *auth_data;
return 0;
err_clear:
- eth_zero_addr(sdata->deflink.u.mgd.bssid);
+ eth_zero_addr(link->u.mgd.bssid);
ieee80211_link_info_change_notify(sdata, &sdata->deflink,
BSS_CHANGED_BSSID);
ifmgd->auth_data = NULL;
struct ieee80211_supported_band *sband;
struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg;
const struct element *ssid_elem, *ht_elem, *vht_elem;
+ struct ieee80211_link_data *link = &sdata->deflink;
int i, err;
bool override = false;
/* prepare assoc data */
- sdata->deflink.u.mgd.beacon_crc_valid = false;
+ link->u.mgd.beacon_crc_valid = false;
assoc_data->wmm = bss->wmm_used &&
(local->hw.queues >= IEEE80211_NUM_ACS);
if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) {
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
netdev_info(sdata->dev,
"disabling HT/VHT/HE due to WEP/TKIP use\n");
}
/* also disable HT/VHT/HE/EHT if the AP doesn't use WMM */
if (!bss->wmm_used) {
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
netdev_info(sdata->dev,
"disabling HT/VHT/HE as WMM/QoS is not supported by the AP\n");
}
assoc_data->ap_ht_param =
((struct ieee80211_ht_operation *)(ht_elem->data))->ht_param;
else if (!is_6ghz)
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
vht_elem = ieee80211_bss_get_elem(req->bss, WLAN_EID_VHT_CAPABILITY);
if (vht_elem && vht_elem->datalen >= sizeof(struct ieee80211_vht_cap)) {
memcpy(&assoc_data->ap_vht_cap, vht_elem->data,
} else if (is_5ghz) {
sdata_info(sdata,
"VHT capa missing/short, disabling VHT/HE/EHT\n");
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT |
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT |
IEEE80211_CONN_DISABLE_HE |
IEEE80211_CONN_DISABLE_EHT;
}
/* kick off associate process */
ifmgd->assoc_data = assoc_data;
- sdata->deflink.u.mgd.dtim_period = 0;
- sdata->deflink.u.mgd.have_beacon = false;
+ link->u.mgd.dtim_period = 0;
+ link->u.mgd.have_beacon = false;
/* override HT/VHT configuration only if the AP and we support it */
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) {
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) {
struct ieee80211_sta_ht_cap sta_ht_cap;
if (req->flags & ASSOC_REQ_DISABLE_HT)
ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap);
/* check for 40 MHz disable override */
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_40MHZ) &&
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_40MHZ) &&
sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
!(sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
override = true;
- if (!(sdata->deflink.u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) &&
+ if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) &&
req->flags & ASSOC_REQ_DISABLE_VHT)
override = true;
}
if (req->flags & ASSOC_REQ_DISABLE_HT) {
mlme_dbg(sdata, "HT disabled by flag, disabling HT/VHT/HE\n");
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
}
if (req->flags & ASSOC_REQ_DISABLE_VHT) {
mlme_dbg(sdata, "VHT disabled by flag, disabling VHT\n");
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT;
}
if (req->flags & ASSOC_REQ_DISABLE_HE) {
mlme_dbg(sdata, "HE disabled by flag, disabling HE/EHT\n");
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
}
if (req->flags & ASSOC_REQ_DISABLE_EHT)
- sdata->deflink.u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
+ link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT;
err = ieee80211_prep_connection(sdata, req->bss, true, override);
if (err)
goto err_clear;
- if (sdata->deflink.u.mgd.req_smps == IEEE80211_SMPS_AUTOMATIC) {
+ if (link->u.mgd.req_smps == IEEE80211_SMPS_AUTOMATIC) {
if (ifmgd->powersave)
- sdata->deflink.smps_mode = IEEE80211_SMPS_DYNAMIC;
+ link->smps_mode = IEEE80211_SMPS_DYNAMIC;
else
- sdata->deflink.smps_mode = IEEE80211_SMPS_OFF;
+ link->smps_mode = IEEE80211_SMPS_OFF;
} else {
- sdata->deflink.smps_mode = sdata->deflink.u.mgd.req_smps;
+ link->smps_mode = link->u.mgd.req_smps;
}
rcu_read_lock();
* should this be more if we miss one?
*/
sdata_info(sdata, "waiting for beacon from %pM\n",
- sdata->deflink.u.mgd.bssid);
+ link->u.mgd.bssid);
assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval);
assoc_data->timeout_started = true;
assoc_data->need_beacon = true;
u8 dtim_count = 0;
ieee80211_get_dtim(beacon_ies, &dtim_count,
- &sdata->deflink.u.mgd.dtim_period);
+ &link->u.mgd.dtim_period);
- sdata->deflink.u.mgd.have_beacon = true;
+ link->u.mgd.have_beacon = true;
assoc_data->timeout = jiffies;
assoc_data->timeout_started = true;
if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
- sdata->vif.bss_conf.sync_tsf = beacon_ies->tsf;
- sdata->vif.bss_conf.sync_device_ts =
+ link->conf->sync_tsf = beacon_ies->tsf;
+ link->conf->sync_device_ts =
bss->device_ts_beacon;
- sdata->vif.bss_conf.sync_dtim_count = dtim_count;
+ link->conf->sync_dtim_count = dtim_count;
}
elem = cfg80211_find_ext_elem(WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION,
beacon_ies->data, beacon_ies->len);
if (elem && elem->datalen >= 3)
- sdata->vif.bss_conf.profile_periodicity = elem->data[2];
+ link->conf->profile_periodicity = elem->data[2];
else
- sdata->vif.bss_conf.profile_periodicity = 0;
+ link->conf->profile_periodicity = 0;
elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY,
beacon_ies->data, beacon_ies->len);
if (elem && elem->datalen >= 11 &&
(elem->data[10] & WLAN_EXT_CAPA11_EMA_SUPPORT))
- sdata->vif.bss_conf.ema_ap = true;
+ link->conf->ema_ap = true;
else
- sdata->vif.bss_conf.ema_ap = false;
+ link->conf->ema_ap = false;
} else {
assoc_data->timeout = jiffies;
assoc_data->timeout_started = true;
return 0;
err_clear:
- eth_zero_addr(sdata->deflink.u.mgd.bssid);
+ eth_zero_addr(link->u.mgd.bssid);
ieee80211_link_info_change_notify(sdata, &sdata->deflink,
BSS_CHANGED_BSSID);
ifmgd->assoc_data = NULL;
void ieee80211_mgd_stop_link(struct ieee80211_link_data *link)
{
cancel_work_sync(&link->u.mgd.request_smps_work);
+ cancel_work_sync(&link->u.mgd.chswitch_work);
}
void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
cancel_work_sync(&ifmgd->monitor_work);
cancel_work_sync(&ifmgd->beacon_connection_loss_work);
cancel_work_sync(&ifmgd->csa_connection_drop_work);
- cancel_work_sync(&ifmgd->chswitch_work);
cancel_delayed_work_sync(&ifmgd->tdls_peer_del_work);
sdata_lock(sdata);