summaryrefslogtreecommitdiff
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c142
1 files changed, 78 insertions, 64 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 3b5827ea438e..e56ad4b9330f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -45,7 +45,7 @@
#define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10)
#define IEEE80211_ASSOC_MAX_TRIES 3
-#define IEEE80211_ADV_TTLM_SAFETY_BUFFER_MS msecs_to_jiffies(100)
+#define IEEE80211_ADV_TTLM_SAFETY_BUFFER_MS (100 * USEC_PER_MSEC)
#define IEEE80211_ADV_TTLM_ST_UNDERFLOW 0xff00
#define IEEE80211_NEG_TTLM_REQ_TIMEOUT (HZ / 5)
@@ -276,11 +276,8 @@ ieee80211_determine_ap_chan(struct ieee80211_sub_if_data *sdata,
return IEEE80211_CONN_MODE_VHT;
}
} else if (!vht_oper || !elems->vht_cap_elem) {
- if (sband->band == NL80211_BAND_5GHZ) {
- sdata_info(sdata,
- "VHT information is missing, disabling VHT\n");
+ if (sband->band == NL80211_BAND_5GHZ)
return IEEE80211_CONN_MODE_HT;
- }
no_vht = true;
} else if (sband->band == NL80211_BAND_2GHZ) {
no_vht = true;
@@ -1002,6 +999,9 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata,
.from_ap = true,
.start = ies->data,
.len = ies->len,
+ .type = ies->from_beacon ?
+ IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON :
+ IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP,
};
struct ieee802_11_elems *elems;
struct ieee80211_supported_band *sband;
@@ -2508,6 +2508,16 @@ static void ieee80211_csa_switch_work(struct wiphy *wiphy,
link->u.mgd.csa.waiting_bcn = true;
+ /*
+ * The next beacon really should always be different, so this should
+ * have no effect whatsoever. However, some APs (we observed this in
+ * an Asus AXE11000), the beacon after the CSA might be identical to
+ * the last beacon on the old channel - in this case we'd ignore it.
+ * Resetting the CRC will lead us to handle it better (albeit with a
+ * disconnect, but clearly the AP is broken.)
+ */
+ link->u.mgd.beacon_crc_valid = false;
+
/* apply new TPE restrictions immediately on the new channel */
if (link->u.mgd.csa.ap_chandef.chan->band == NL80211_BAND_6GHZ &&
link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_HE) {
@@ -2594,7 +2604,7 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success,
return;
}
- wiphy_delayed_work_queue(sdata->local->hw.wiphy,
+ wiphy_hrtimer_work_queue(sdata->local->hw.wiphy,
&link->u.mgd.csa.switch_work, 0);
}
@@ -2753,7 +2763,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
.timestamp = timestamp,
.device_timestamp = device_timestamp,
};
- unsigned long now;
+ u32 csa_time_tu;
+ ktime_t now;
int res;
lockdep_assert_wiphy(local->hw.wiphy);
@@ -2983,10 +2994,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
csa_ie.mode);
/* we may have to handle timeout for deactivated link in software */
- now = jiffies;
- link->u.mgd.csa.time = now +
- TU_TO_JIFFIES((max_t(int, csa_ie.count, 1) - 1) *
- link->conf->beacon_int);
+ now = ktime_get_boottime();
+ csa_time_tu = (max_t(int, csa_ie.count, 1) - 1) * link->conf->beacon_int;
+ link->u.mgd.csa.time = now + us_to_ktime(ieee80211_tu_to_usec(csa_time_tu));
if (ieee80211_vif_link_active(&sdata->vif, link->link_id) &&
local->ops->channel_switch) {
@@ -3001,7 +3011,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
}
/* channel switch handled in software */
- wiphy_delayed_work_queue(local->hw.wiphy,
+ wiphy_hrtimer_work_queue(local->hw.wiphy,
&link->u.mgd.csa.switch_work,
link->u.mgd.csa.time - now);
return;
@@ -4242,14 +4252,14 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
memset(&sdata->u.mgd.ttlm_info, 0,
sizeof(sdata->u.mgd.ttlm_info));
- wiphy_delayed_work_cancel(sdata->local->hw.wiphy, &ifmgd->ttlm_work);
+ wiphy_hrtimer_work_cancel(sdata->local->hw.wiphy, &ifmgd->ttlm_work);
memset(&sdata->vif.neg_ttlm, 0, sizeof(sdata->vif.neg_ttlm));
wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
&ifmgd->neg_ttlm_timeout_work);
sdata->u.mgd.removed_links = 0;
- wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
+ wiphy_hrtimer_work_cancel(sdata->local->hw.wiphy,
&sdata->u.mgd.ml_reconf_work);
wiphy_work_cancel(sdata->local->hw.wiphy,
@@ -5170,7 +5180,9 @@ static void ieee80211_epcs_teardown(struct ieee80211_sub_if_data *sdata)
continue;
}
- elems = ieee802_11_parse_elems(ies->data, ies->len, false,
+ elems = ieee802_11_parse_elems(ies->data, ies->len,
+ IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_BEACON,
NULL);
if (!elems) {
rcu_read_unlock();
@@ -5216,6 +5228,7 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
.len = elem_len,
.link_id = link_id == assoc_data->assoc_link_id ? -1 : link_id,
.from_ap = true,
+ .type = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_TYPE,
};
bool is_5ghz = cbss->channel->band == NL80211_BAND_5GHZ;
bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ;
@@ -6021,24 +6034,6 @@ ieee80211_determine_our_sta_mode_assoc(struct ieee80211_sub_if_data *sdata,
conn->bw_limit, tmp.bw_limit);
}
-static enum ieee80211_ap_reg_power
-ieee80211_ap_power_type(u8 control)
-{
- switch (u8_get_bits(control, IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO)) {
- case IEEE80211_6GHZ_CTRL_REG_LPI_AP:
- case IEEE80211_6GHZ_CTRL_REG_INDOOR_LPI_AP:
- return IEEE80211_REG_LPI_AP;
- case IEEE80211_6GHZ_CTRL_REG_SP_AP:
- case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP:
- case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP_OLD:
- return IEEE80211_REG_SP_AP;
- case IEEE80211_6GHZ_CTRL_REG_VLP_AP:
- return IEEE80211_REG_VLP_AP;
- default:
- return IEEE80211_REG_UNSET_AP;
- }
-}
-
static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
struct ieee80211_link_data *link,
int link_id,
@@ -6081,7 +6076,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
he_6ghz_oper = ieee80211_he_6ghz_oper(elems->he_operation);
if (he_6ghz_oper)
link->conf->power_type =
- ieee80211_ap_power_type(he_6ghz_oper->control);
+ cfg80211_6ghz_power_type(he_6ghz_oper->control,
+ cbss->channel->flags);
else
link_info(link,
"HE 6 GHz operation missing (on %d MHz), expect issues\n",
@@ -6112,9 +6108,10 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
ret = ieee80211_link_use_channel(link, &chanreq,
IEEE80211_CHANCTX_SHARED);
- /* don't downgrade for 5 and 10 MHz channels, though. */
+ /* don't downgrade for 5/10/S1G MHz channels, though. */
if (chanreq.oper.width == NL80211_CHAN_WIDTH_5 ||
- chanreq.oper.width == NL80211_CHAN_WIDTH_10)
+ chanreq.oper.width == NL80211_CHAN_WIDTH_10 ||
+ cfg80211_chandef_is_s1g(&chanreq.oper))
return ret;
while (ret && chanreq.oper.width != NL80211_CHAN_WIDTH_20_NOHT) {
@@ -6349,6 +6346,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
.bss = NULL,
.link_id = -1,
.from_ap = true,
+ .type = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_TYPE,
};
struct ieee802_11_elems *elems;
int ac;
@@ -6610,8 +6608,8 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_link_data *link,
* Response frame shall be set to the broadcast address [..]"
* So, on 6GHz band we should also accept broadcast responses.
*/
- channel = ieee80211_get_channel(sdata->local->hw.wiphy,
- rx_status->freq);
+ channel = ieee80211_get_channel_khz(sdata->local->hw.wiphy,
+ ieee80211_rx_status_to_khz(rx_status));
if (!channel)
return;
@@ -6876,7 +6874,7 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata,
/* In case the removal was cancelled, abort it */
if (sdata->u.mgd.removed_links) {
sdata->u.mgd.removed_links = 0;
- wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
+ wiphy_hrtimer_work_cancel(sdata->local->hw.wiphy,
&sdata->u.mgd.ml_reconf_work);
}
return;
@@ -6906,9 +6904,9 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata,
}
sdata->u.mgd.removed_links = removed_links;
- wiphy_delayed_work_queue(sdata->local->hw.wiphy,
+ wiphy_hrtimer_work_queue(sdata->local->hw.wiphy,
&sdata->u.mgd.ml_reconf_work,
- TU_TO_JIFFIES(delay));
+ us_to_ktime(ieee80211_tu_to_usec(delay)));
}
static int ieee80211_ttlm_set_links(struct ieee80211_sub_if_data *sdata,
@@ -7095,7 +7093,7 @@ static void ieee80211_process_adv_ttlm(struct ieee80211_sub_if_data *sdata,
/* if a planned TID-to-link mapping was cancelled -
* abort it
*/
- wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
+ wiphy_hrtimer_work_cancel(sdata->local->hw.wiphy,
&sdata->u.mgd.ttlm_work);
} else if (sdata->u.mgd.ttlm_info.active) {
/* if no TID-to-link element, set to default mapping in
@@ -7130,7 +7128,7 @@ static void ieee80211_process_adv_ttlm(struct ieee80211_sub_if_data *sdata,
if (ttlm_info.switch_time) {
u16 beacon_ts_tu, st_tu, delay;
- u32 delay_jiffies;
+ u64 delay_usec;
u64 mask;
/* The t2l map switch time is indicated with a partial
@@ -7152,23 +7150,23 @@ static void ieee80211_process_adv_ttlm(struct ieee80211_sub_if_data *sdata,
if (delay > IEEE80211_ADV_TTLM_ST_UNDERFLOW)
return;
- delay_jiffies = TU_TO_JIFFIES(delay);
+ delay_usec = ieee80211_tu_to_usec(delay);
/* Link switching can take time, so schedule it
* 100ms before to be ready on time
*/
- if (delay_jiffies > IEEE80211_ADV_TTLM_SAFETY_BUFFER_MS)
- delay_jiffies -=
+ if (delay_usec > IEEE80211_ADV_TTLM_SAFETY_BUFFER_MS)
+ delay_usec -=
IEEE80211_ADV_TTLM_SAFETY_BUFFER_MS;
else
- delay_jiffies = 0;
+ delay_usec = 0;
sdata->u.mgd.ttlm_info = ttlm_info;
- wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
+ wiphy_hrtimer_work_cancel(sdata->local->hw.wiphy,
&sdata->u.mgd.ttlm_work);
- wiphy_delayed_work_queue(sdata->local->hw.wiphy,
+ wiphy_hrtimer_work_queue(sdata->local->hw.wiphy,
&sdata->u.mgd.ttlm_work,
- delay_jiffies);
+ us_to_ktime(delay_usec));
return;
}
}
@@ -7257,7 +7255,9 @@ ieee80211_mgd_check_cross_link_csa(struct ieee80211_sub_if_data *sdata,
(prof->sta_info_len - 1),
len -
(prof->sta_info_len - 1),
- false, NULL);
+ IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_BEACON,
+ NULL);
/* memory allocation failed - let's hope that's transient */
if (!prof_elems)
@@ -7361,6 +7361,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
.mode = link->u.mgd.conn.mode,
.link_id = -1,
.from_ap = true,
+ .type = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_TYPE,
};
lockdep_assert_wiphy(local->hw.wiphy);
@@ -7963,7 +7964,10 @@ void ieee80211_process_neg_ttlm_req(struct ieee80211_sub_if_data *sdata,
ies_len = len - offsetof(struct ieee80211_mgmt,
u.action.u.ttlm_req.variable);
elems = ieee802_11_parse_elems(mgmt->u.action.u.ttlm_req.variable,
- ies_len, true, NULL);
+ ies_len,
+ IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION,
+ NULL);
if (!elems) {
ttlm_res = NEG_TTLM_RES_REJECT;
goto out;
@@ -8169,9 +8173,11 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
break;
/* CSA IE cannot be overridden, no need for BSSID */
- elems = ieee802_11_parse_elems(
- mgmt->u.action.u.chan_switch.variable,
- ies_len, true, NULL);
+ elems = ieee802_11_parse_elems(mgmt->u.action.u.chan_switch.variable,
+ ies_len,
+ IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION,
+ NULL);
if (elems && !elems->parse_error) {
enum ieee80211_csa_source src =
@@ -8198,9 +8204,11 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
* extended CSA IE can't be overridden, no need for
* BSSID
*/
- elems = ieee802_11_parse_elems(
- mgmt->u.action.u.ext_chan_switch.variable,
- ies_len, true, NULL);
+ elems = ieee802_11_parse_elems(mgmt->u.action.u.ext_chan_switch.variable,
+ ies_len,
+ IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION,
+ NULL);
if (elems && !elems->parse_error) {
enum ieee80211_csa_source src;
@@ -8793,7 +8801,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
ieee80211_csa_connection_drop_work);
wiphy_delayed_work_init(&ifmgd->tdls_peer_del_work,
ieee80211_tdls_peer_del_work);
- wiphy_delayed_work_init(&ifmgd->ml_reconf_work,
+ wiphy_hrtimer_work_init(&ifmgd->ml_reconf_work,
ieee80211_ml_reconf_work);
wiphy_delayed_work_init(&ifmgd->reconf.wk,
ieee80211_ml_sta_reconf_timeout);
@@ -8802,7 +8810,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
timer_setup(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer, 0);
wiphy_delayed_work_init(&ifmgd->tx_tspec_wk,
ieee80211_sta_handle_tspec_ac_params_wk);
- wiphy_delayed_work_init(&ifmgd->ttlm_work,
+ wiphy_hrtimer_work_init(&ifmgd->ttlm_work,
ieee80211_tid_to_link_map_work);
wiphy_delayed_work_init(&ifmgd->neg_ttlm_timeout_work,
ieee80211_neg_ttlm_timeout_work);
@@ -8849,7 +8857,7 @@ void ieee80211_mgd_setup_link(struct ieee80211_link_data *link)
else
link->u.mgd.req_smps = IEEE80211_SMPS_OFF;
- wiphy_delayed_work_init(&link->u.mgd.csa.switch_work,
+ wiphy_hrtimer_work_init(&link->u.mgd.csa.switch_work,
ieee80211_csa_switch_work);
ieee80211_clear_tpe(&link->conf->tpe);
@@ -10064,7 +10072,7 @@ void ieee80211_mgd_stop_link(struct ieee80211_link_data *link)
&link->u.mgd.request_smps_work);
wiphy_work_cancel(link->sdata->local->hw.wiphy,
&link->u.mgd.recalc_smps);
- wiphy_delayed_work_cancel(link->sdata->local->hw.wiphy,
+ wiphy_hrtimer_work_cancel(link->sdata->local->hw.wiphy,
&link->u.mgd.csa.switch_work);
}
@@ -10978,7 +10986,10 @@ static void ieee80211_ml_epcs(struct ieee80211_sub_if_data *sdata,
pos = scratch + sizeof(control);
len -= sizeof(control);
- link_elems = ieee802_11_parse_elems(pos, len, false, NULL);
+ link_elems = ieee802_11_parse_elems(pos, len,
+ IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION,
+ NULL);
if (!link_elems)
continue;
@@ -11029,7 +11040,10 @@ void ieee80211_process_epcs_ena_resp(struct ieee80211_sub_if_data *sdata,
u.action.u.epcs.variable) -
IEEE80211_EPCS_ENA_RESP_BODY_LEN;
- elems = ieee802_11_parse_elems(pos, ies_len, true, NULL);
+ elems = ieee802_11_parse_elems(pos, ies_len,
+ IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION,
+ NULL);
if (!elems)
return;