aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c76
-rw-r--r--net/mac80211/debugfs_netdev.c2
-rw-r--r--net/mac80211/ieee80211_i.h32
-rw-r--r--net/mac80211/key.c63
-rw-r--r--net/mac80211/main.c14
-rw-r--r--net/mac80211/mesh.c2
-rw-r--r--net/mac80211/mlme.c116
-rw-r--r--net/mac80211/rx.c28
-rw-r--r--net/mac80211/tdls.c2
-rw-r--r--net/mac80211/tx.c109
-rw-r--r--net/mac80211/util.c31
-rw-r--r--net/wireless/mlme.c3
-rw-r--r--net/wireless/nl80211.c96
-rw-r--r--net/wireless/reg.c2
-rw-r--r--net/wireless/sme.c1
-rw-r--r--net/wireless/trace.h17
16 files changed, 481 insertions, 113 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b99e39cb808b..2ed07fa121ab 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1071,6 +1071,47 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata,
return 0;
}
+static int
+ieee80211_set_s1g_short_beacon(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_link_data *link,
+ struct cfg80211_s1g_short_beacon *params)
+{
+ struct s1g_short_beacon_data *new;
+ struct s1g_short_beacon_data *old =
+ sdata_dereference(link->u.ap.s1g_short_beacon, sdata);
+ size_t new_len =
+ sizeof(*new) + params->short_head_len + params->short_tail_len;
+
+ if (!params->update)
+ return 0;
+
+ if (!params->short_head)
+ return -EINVAL;
+
+ new = kzalloc(new_len, GFP_KERNEL);
+ if (!new)
+ return -ENOMEM;
+
+ /* Memory layout: | struct | head | tail | */
+ new->short_head = (u8 *)new + sizeof(*new);
+ new->short_head_len = params->short_head_len;
+ memcpy(new->short_head, params->short_head, params->short_head_len);
+
+ if (params->short_tail) {
+ new->short_tail = new->short_head + params->short_head_len;
+ new->short_tail_len = params->short_tail_len;
+ memcpy(new->short_tail, params->short_tail,
+ params->short_tail_len);
+ }
+
+ rcu_assign_pointer(link->u.ap.s1g_short_beacon, new);
+
+ if (old)
+ kfree_rcu(old, rcu_head);
+
+ return 0;
+}
+
static int ieee80211_set_ftm_responder_params(
struct ieee80211_sub_if_data *sdata,
const u8 *lci, size_t lci_len,
@@ -1135,13 +1176,13 @@ ieee80211_copy_rnr_beacon(u8 *pos, struct cfg80211_rnr_elems *dst,
{
int i, offset = 0;
+ dst->cnt = src->cnt;
for (i = 0; i < src->cnt; i++) {
memcpy(pos + offset, src->elem[i].data, src->elem[i].len);
dst->elem[i].len = src->elem[i].len;
dst->elem[i].data = pos + offset;
offset += dst->elem[i].len;
}
- dst->cnt = src->cnt;
return offset;
}
@@ -1341,6 +1382,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_link_data *link;
struct ieee80211_bss_conf *link_conf;
struct ieee80211_chan_req chanreq = { .oper = params->chandef };
+ u64 tsf;
lockdep_assert_wiphy(local->hw.wiphy);
@@ -1493,8 +1535,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
link_conf->twt_responder = params->twt_responder;
link_conf->he_obss_pd = params->he_obss_pd;
link_conf->he_bss_color = params->beacon.he_bss_color;
- sdata->vif.cfg.s1g = params->chandef.chan->band ==
- NL80211_BAND_S1GHZ;
+ link_conf->s1g_long_beacon_period = params->s1g_long_beacon_period;
+ sdata->vif.cfg.s1g = params->chandef.chan->band == NL80211_BAND_S1GHZ;
sdata->vif.cfg.ssid_len = params->ssid_len;
if (params->ssid_len)
@@ -1541,6 +1583,13 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
if (err < 0)
goto error;
+ if (sdata->vif.cfg.s1g) {
+ err = ieee80211_set_s1g_short_beacon(sdata, link,
+ &params->s1g_short_beacon);
+ if (err < 0)
+ goto error;
+ }
+
err = drv_start_ap(sdata->local, sdata, link_conf);
if (err) {
old = sdata_dereference(link->u.ap.beacon, sdata);
@@ -1555,7 +1604,12 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
goto error;
}
- ieee80211_recalc_dtim(local, sdata);
+ tsf = drv_get_tsf(local, sdata);
+ ieee80211_recalc_dtim(sdata, tsf);
+
+ if (link->u.ap.s1g_short_beacon)
+ ieee80211_recalc_sb_count(sdata, tsf);
+
ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_SSID);
ieee80211_link_info_change_notify(sdata, link, changed);
@@ -1619,6 +1673,13 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
if (err < 0)
return err;
+ if (link->u.ap.s1g_short_beacon) {
+ err = ieee80211_set_s1g_short_beacon(sdata, link,
+ &params->s1g_short_beacon);
+ if (err < 0)
+ return err;
+ }
+
if (beacon->he_bss_color_valid &&
beacon->he_bss_color.enabled != link_conf->he_bss_color.enabled) {
link_conf->he_bss_color.enabled = beacon->he_bss_color.enabled;
@@ -1650,6 +1711,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
struct probe_resp *old_probe_resp;
struct fils_discovery_data *old_fils_discovery;
struct unsol_bcast_probe_resp_data *old_unsol_bcast_probe_resp;
+ struct s1g_short_beacon_data *old_s1g_short_beacon;
struct cfg80211_chan_def chandef;
struct ieee80211_link_data *link =
sdata_dereference(sdata->link[link_id], sdata);
@@ -1668,6 +1730,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
old_unsol_bcast_probe_resp =
sdata_dereference(link->u.ap.unsol_bcast_probe_resp,
sdata);
+ old_s1g_short_beacon =
+ sdata_dereference(link->u.ap.s1g_short_beacon, sdata);
/* abort any running channel switch or color change */
link_conf->csa_active = false;
@@ -1690,6 +1754,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
RCU_INIT_POINTER(link->u.ap.probe_resp, NULL);
RCU_INIT_POINTER(link->u.ap.fils_discovery, NULL);
RCU_INIT_POINTER(link->u.ap.unsol_bcast_probe_resp, NULL);
+ RCU_INIT_POINTER(link->u.ap.s1g_short_beacon, NULL);
kfree_rcu(old_beacon, rcu_head);
if (old_probe_resp)
kfree_rcu(old_probe_resp, rcu_head);
@@ -1697,6 +1762,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
kfree_rcu(old_fils_discovery, rcu_head);
if (old_unsol_bcast_probe_resp)
kfree_rcu(old_unsol_bcast_probe_resp, rcu_head);
+ if (old_s1g_short_beacon)
+ kfree_rcu(old_s1g_short_beacon, rcu_head);
kfree(link_conf->ftmr_params);
link_conf->ftmr_params = NULL;
@@ -1720,6 +1787,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
link_conf->enable_beacon = false;
sdata->beacon_rate_set = false;
sdata->vif.cfg.ssid_len = 0;
+ sdata->vif.cfg.s1g = false;
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
ieee80211_link_info_change_notify(sdata, link,
BSS_CHANGED_BEACON_ENABLED);
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 54c479910d05..1dac78271045 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -704,7 +704,7 @@ static ssize_t ieee80211_if_parse_tsf(
}
}
- ieee80211_recalc_dtim(local, sdata);
+ ieee80211_recalc_dtim(sdata, drv_get_tsf(local, sdata));
return buflen;
}
IEEE80211_IF_FILE_RW(tsf);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 084e2673a27e..8afa2404eaa8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -296,6 +296,14 @@ struct unsol_bcast_probe_resp_data {
u8 data[];
};
+struct s1g_short_beacon_data {
+ struct rcu_head rcu_head;
+ u8 *short_head;
+ u8 *short_tail;
+ int short_head_len;
+ int short_tail_len;
+};
+
struct ps_data {
/* yes, this looks ugly, but guarantees that we can later use
* bitmap_empty :)
@@ -306,6 +314,7 @@ struct ps_data {
atomic_t num_sta_ps; /* number of stations in PS mode */
int dtim_count;
bool dtim_bc_mc;
+ int sb_count; /* num short beacons til next long beacon */
};
struct ieee80211_if_ap {
@@ -1042,6 +1051,7 @@ struct ieee80211_link_data_ap {
struct probe_resp __rcu *probe_resp;
struct fils_discovery_data __rcu *fils_discovery;
struct unsol_bcast_probe_resp_data __rcu *unsol_bcast_probe_resp;
+ struct s1g_short_beacon_data __rcu *s1g_short_beacon;
/* to be used after channel switch. */
struct cfg80211_beacon_data *next_beacon;
@@ -1242,7 +1252,9 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
if ((_link = rcu_dereference((___sdata)->link[___link_id])))
#define for_each_link_data(sdata, __link) \
- struct ieee80211_sub_if_data *__sdata = sdata; \
+ /* outer loop just to define the variable ... */ \
+ for (struct ieee80211_sub_if_data *__sdata = (sdata); __sdata; \
+ __sdata = NULL /* always stop */) \
for (int __link_id = 0; \
__link_id < ARRAY_SIZE((__sdata)->link); __link_id++) \
if ((!(__sdata)->vif.valid_links || \
@@ -1250,6 +1262,19 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
((__link) = sdata_dereference((__sdata)->link[__link_id], \
(__sdata))))
+/*
+ * for_each_link_data_rcu should be used under RCU read lock.
+ */
+#define for_each_link_data_rcu(sdata, __link) \
+ /* outer loop just to define the variable ... */ \
+ for (struct ieee80211_sub_if_data *__sdata = (sdata); __sdata; \
+ __sdata = NULL /* always stop */) \
+ for (int __link_id = 0; \
+ __link_id < ARRAY_SIZE((__sdata)->link); __link_id++) \
+ if ((!(__sdata)->vif.valid_links || \
+ (__sdata)->vif.valid_links & BIT(__link_id)) && \
+ ((__link) = rcu_dereference((__sdata)->link[__link_id]))) \
+
static inline int
ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems,
struct cfg80211_rnr_elems *rnr_elems,
@@ -2750,9 +2775,8 @@ void ieee80211_dfs_radar_detected_work(struct wiphy *wiphy,
struct wiphy_work *work);
int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
struct cfg80211_csa_settings *csa_settings);
-
-void ieee80211_recalc_dtim(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata);
+void ieee80211_recalc_sb_count(struct ieee80211_sub_if_data *sdata, u64 tsf);
+void ieee80211_recalc_dtim(struct ieee80211_sub_if_data *sdata, u64 tsf);
int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
const struct cfg80211_chan_def *chandef,
enum ieee80211_chanctx_mode chanmode,
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 997892da8886..b14e9cd9713f 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -6,7 +6,7 @@
* Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2015-2017 Intel Deutschland GmbH
- * Copyright 2018-2020, 2022-2024 Intel Corporation
+ * Copyright 2018-2020, 2022-2025 Intel Corporation
*/
#include <crypto/utils.h>
@@ -1354,38 +1354,14 @@ void ieee80211_set_key_rx_seq(struct ieee80211_key_conf *keyconf,
}
EXPORT_SYMBOL_GPL(ieee80211_set_key_rx_seq);
-void ieee80211_remove_key(struct ieee80211_key_conf *keyconf)
-{
- struct ieee80211_key *key;
-
- key = container_of(keyconf, struct ieee80211_key, conf);
-
- lockdep_assert_wiphy(key->local->hw.wiphy);
-
- /*
- * if key was uploaded, we assume the driver will/has remove(d)
- * it, so adjust bookkeeping accordingly
- */
- if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
- key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
-
- if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
- IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
- IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
- increment_tailroom_need_count(key->sdata);
- }
-
- ieee80211_key_free(key, false);
-}
-EXPORT_SYMBOL_GPL(ieee80211_remove_key);
-
struct ieee80211_key_conf *
ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
- struct ieee80211_key_conf *keyconf,
+ u8 idx, u8 *key_data, u8 key_len,
int link_id)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
+ struct ieee80211_key *prev_key;
struct ieee80211_key *key;
int err;
struct ieee80211_link_data *link_data =
@@ -1401,8 +1377,37 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
return ERR_PTR(-EINVAL);
- key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx,
- keyconf->keylen, keyconf->key,
+ if (WARN_ON(idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
+ NUM_DEFAULT_BEACON_KEYS))
+ return ERR_PTR(-EINVAL);
+
+ prev_key = wiphy_dereference(local->hw.wiphy,
+ link_data->gtk[idx]);
+ if (!prev_key) {
+ if (idx < NUM_DEFAULT_KEYS) {
+ for (int i = 0; i < NUM_DEFAULT_KEYS; i++) {
+ if (i == idx)
+ continue;
+ prev_key = wiphy_dereference(local->hw.wiphy,
+ link_data->gtk[i]);
+ if (prev_key)
+ break;
+ }
+ } else {
+ /* For IGTK we have 4 and 5 and for BIGTK - 6 and 7 */
+ prev_key = wiphy_dereference(local->hw.wiphy,
+ link_data->gtk[idx ^ 1]);
+ }
+ }
+
+ if (WARN_ON(!prev_key))
+ return ERR_PTR(-EINVAL);
+
+ if (WARN_ON(key_len < prev_key->conf.keylen))
+ return ERR_PTR(-EINVAL);
+
+ key = ieee80211_key_alloc(prev_key->conf.cipher, idx,
+ prev_key->conf.keylen, key_data,
0, NULL);
if (IS_ERR(key))
return ERR_CAST(key);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index ec60b82af007..9c8f18b258a6 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -408,9 +408,20 @@ void ieee80211_link_info_change_notify(struct ieee80211_sub_if_data *sdata,
WARN_ON_ONCE(changed & BSS_CHANGED_VIF_CFG_FLAGS);
- if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ if (!changed)
return;
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_AP_VLAN:
+ return;
+ case NL80211_IFTYPE_MONITOR:
+ if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
+ return;
+ break;
+ default:
+ break;
+ }
+
if (!check_sdata_in_driver(sdata))
return;
@@ -1334,7 +1345,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
GFP_KERNEL);
if (!local->int_scan_req)
return -ENOMEM;
- local->int_scan_req->n_channels = channels;
eth_broadcast_addr(local->int_scan_req->bssid);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index d00d9d413c5c..a4a715f6f1c3 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -1202,7 +1202,7 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
return -ENOMEM;
}
- ieee80211_recalc_dtim(local, sdata);
+ ieee80211_recalc_dtim(sdata, drv_get_tsf(local, sdata));
ieee80211_link_info_change_notify(sdata, &sdata->deflink, changed);
netif_carrier_on(sdata->dev);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 5298dbbb5341..1008eb8e9b13 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2505,6 +2505,21 @@ static void ieee80211_csa_switch_work(struct wiphy *wiphy,
}
}
+ /*
+ * It is not necessary to reset these timers if any link does not
+ * have an active CSA and that link still receives the beacons
+ * when other links have active CSA.
+ */
+ for_each_link_data(sdata, link) {
+ if (!link->conf->csa_active)
+ return;
+ }
+
+ /*
+ * Reset the beacon monitor and connection monitor timers when CSA
+ * is active for all links in MLO when channel switch occurs in all
+ * the links.
+ */
ieee80211_sta_reset_beacon_monitor(sdata);
ieee80211_sta_reset_conn_monitor(sdata);
}
@@ -4352,9 +4367,6 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
lockdep_assert_wiphy(sdata->local->hw.wiphy);
- if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif)))
- return;
-
/*
* Try sending broadcast probe requests for the last three
* probe requests after the first ones failed since some
@@ -4400,9 +4412,6 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
lockdep_assert_wiphy(sdata->local->hw.wiphy);
- if (WARN_ON_ONCE(ieee80211_vif_is_mld(&sdata->vif)))
- return;
-
if (!ieee80211_sdata_running(sdata))
return;
@@ -8473,16 +8482,32 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
}
}
+static bool
+ieee80211_is_csa_in_progress(struct ieee80211_sub_if_data *sdata)
+{
+ /*
+ * In MLO, check the CSA flags 'active' and 'waiting_bcn' for all
+ * the links.
+ */
+ struct ieee80211_link_data *link;
+
+ guard(rcu)();
+
+ for_each_link_data_rcu(sdata, link) {
+ if (!(link->conf->csa_active &&
+ !link->u.mgd.csa.waiting_bcn))
+ return false;
+ }
+
+ return true;
+}
+
static void ieee80211_sta_bcn_mon_timer(struct timer_list *t)
{
struct ieee80211_sub_if_data *sdata =
timer_container_of(sdata, t, u.mgd.bcn_mon_timer);
- if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif)))
- return;
-
- if (sdata->vif.bss_conf.csa_active &&
- !sdata->deflink.u.mgd.csa.waiting_bcn)
+ if (ieee80211_is_csa_in_progress(sdata))
return;
if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)
@@ -8493,36 +8518,69 @@ static void ieee80211_sta_bcn_mon_timer(struct timer_list *t)
&sdata->u.mgd.beacon_connection_loss_work);
}
+static unsigned long
+ieee80211_latest_active_link_conn_timeout(struct ieee80211_sub_if_data *sdata)
+{
+ unsigned long latest_timeout = jiffies;
+ unsigned int link_id;
+ struct sta_info *sta;
+
+ guard(rcu)();
+
+ sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
+ if (!sta)
+ return 0;
+
+ for (link_id = 0; link_id < ARRAY_SIZE(sta->link);
+ link_id++) {
+ struct link_sta_info *link_sta;
+ unsigned long timeout;
+
+ link_sta = rcu_dereference(sta->link[link_id]);
+ if (!link_sta)
+ continue;
+
+ timeout = link_sta->status_stats.last_ack;
+ if (time_before(timeout, link_sta->rx_stats.last_rx))
+ timeout = link_sta->rx_stats.last_rx;
+
+ timeout += IEEE80211_CONNECTION_IDLE_TIME;
+
+ /*
+ * latest_timeout holds the timeout of the link
+ * that will expire last among all links in an
+ * non-AP MLD STA. This ensures that the connection
+ * monitor timer is only reset if at least one link
+ * is still active, and it is scheduled to fire at
+ * the latest possible timeout.
+ */
+ if (time_after(timeout, latest_timeout))
+ latest_timeout = timeout;
+ }
+
+ return latest_timeout;
+}
+
static void ieee80211_sta_conn_mon_timer(struct timer_list *t)
{
struct ieee80211_sub_if_data *sdata =
timer_container_of(sdata, t, u.mgd.conn_mon_timer);
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
- unsigned long timeout;
+ unsigned long latest_timeout;
- if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif)))
+ if (ieee80211_is_csa_in_progress(sdata))
return;
- if (sdata->vif.bss_conf.csa_active &&
- !sdata->deflink.u.mgd.csa.waiting_bcn)
- return;
+ latest_timeout = ieee80211_latest_active_link_conn_timeout(sdata);
- sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
- if (!sta)
- return;
-
- timeout = sta->deflink.status_stats.last_ack;
- if (time_before(sta->deflink.status_stats.last_ack, sta->deflink.rx_stats.last_rx))
- timeout = sta->deflink.rx_stats.last_rx;
- timeout += IEEE80211_CONNECTION_IDLE_TIME;
-
- /* If timeout is after now, then update timer to fire at
+ /*
+ * If latest timeout is after now, then update timer to fire at
* the later date, but do not actually probe at this time.
*/
- if (time_is_after_jiffies(timeout)) {
- mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(timeout));
+ if (time_is_after_jiffies(latest_timeout)) {
+ mod_timer(&ifmgd->conn_mon_timer,
+ round_jiffies_up(latest_timeout));
return;
}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index b414c9e6e61b..4d4ff4d4917a 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1532,9 +1532,8 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
}
if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
- cfg80211_rx_spurious_frame(rx->sdata->dev,
- hdr->addr2,
- GFP_ATOMIC))
+ cfg80211_rx_spurious_frame(rx->sdata->dev, hdr->addr2,
+ rx->link_id, GFP_ATOMIC))
return RX_DROP_U_SPURIOUS;
return RX_DROP;
@@ -1872,7 +1871,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
if (!test_and_set_sta_flag(sta, WLAN_STA_4ADDR_EVENT))
cfg80211_rx_unexpected_4addr_frame(
rx->sdata->dev, sta->sta.addr,
- GFP_ATOMIC);
+ rx->link_id, GFP_ATOMIC);
return RX_DROP_U_UNEXPECTED_4ADDR_FRAME;
}
/*
@@ -3191,7 +3190,8 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
if (rx->sta &&
!test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT))
cfg80211_rx_unexpected_4addr_frame(
- rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC);
+ rx->sdata->dev, rx->sta->sta.addr, rx->link_id,
+ GFP_ATOMIC);
return RX_DROP;
}
@@ -5106,8 +5106,24 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
sta = sta_info_get_bss(rx->sdata, hdr->addr2);
- if (status->link_valid)
+ if (status->link_valid) {
link_id = status->link_id;
+ } else if (ieee80211_vif_is_mld(&rx->sdata->vif) &&
+ status->freq) {
+ struct ieee80211_link_data *link;
+ struct ieee80211_chanctx_conf *conf;
+
+ for_each_link_data_rcu(rx->sdata, link) {
+ conf = rcu_dereference(link->conf->chanctx_conf);
+ if (!conf || !conf->def.chan)
+ continue;
+
+ if (status->freq == conf->def.chan->center_freq) {
+ link_id = link->link_id;
+ break;
+ }
+ }
+ }
}
if (!ieee80211_rx_data_set_sta(rx, sta, link_id))
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index 94714f8ffd22..ba5fbacbeeda 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -1422,7 +1422,7 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
return -EOPNOTSUPP;
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
+ if (sdata->vif.type != NL80211_IFTYPE_STATION || !sdata->vif.cfg.assoc)
return -EINVAL;
switch (oper) {
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 6fa883a9250d..00671ae45b2f 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -612,6 +612,12 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
else
tx->key = NULL;
+ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
+ if (tx->key && tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
+ info->control.hw_key = &tx->key->conf;
+ return TX_CONTINUE;
+ }
+
if (tx->key) {
bool skip_hw = false;
@@ -1429,7 +1435,7 @@ static void ieee80211_txq_enqueue(struct ieee80211_local *local,
{
struct fq *fq = &local->fq;
struct fq_tin *tin = &txqi->tin;
- u32 flow_idx = fq_flow_idx(fq, skb);
+ u32 flow_idx;
ieee80211_set_skb_enqueue_time(skb);
@@ -1445,6 +1451,7 @@ static void ieee80211_txq_enqueue(struct ieee80211_local *local,
IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
__skb_queue_tail(&txqi->frags, skb);
} else {
+ flow_idx = fq_flow_idx(fq, skb);
fq_tin_enqueue(fq, tin, flow_idx, skb,
fq_skb_free_func);
}
@@ -3877,6 +3884,7 @@ begin:
* The key can be removed while the packet was queued, so need to call
* this here to get the current key.
*/
+ info->control.hw_key = NULL;
r = ieee80211_tx_h_select_key(&tx);
if (r != TX_CONTINUE) {
ieee80211_free_txskb(&local->hw, skb);
@@ -4099,7 +4107,9 @@ void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
spin_lock_bh(&local->active_txq_lock[txq->ac]);
- has_queue = force || txq_has_queue(txq);
+ has_queue = force ||
+ (!test_bit(IEEE80211_TXQ_STOP, &txqi->flags) &&
+ txq_has_queue(txq));
if (list_empty(&txqi->schedule_order) &&
(has_queue || ieee80211_txq_keep_active(txqi))) {
/* If airtime accounting is active, always enqueue STAs at the
@@ -5290,14 +5300,14 @@ ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon,
}
static struct sk_buff *
-ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_link_data *link,
- struct ieee80211_mutable_offsets *offs,
- bool is_template,
- struct beacon_data *beacon,
- struct ieee80211_chanctx_conf *chanctx_conf,
- u8 ema_index)
+__ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_link_data *link,
+ struct ieee80211_mutable_offsets *offs,
+ bool is_template,
+ struct beacon_data *beacon,
+ struct ieee80211_chanctx_conf *chanctx_conf,
+ u8 ema_index)
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
@@ -5358,6 +5368,71 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
return skb;
}
+static bool ieee80211_s1g_need_long_beacon(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_link_data *link)
+{
+ struct ps_data *ps = &sdata->u.ap.ps;
+
+ if (ps->sb_count == 0)
+ ps->sb_count = link->conf->s1g_long_beacon_period - 1;
+ else
+ ps->sb_count--;
+
+ return ps->sb_count == 0;
+}
+
+static struct sk_buff *
+ieee80211_s1g_short_beacon_get(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_link_data *link,
+ struct ieee80211_chanctx_conf *chanctx_conf,
+ struct s1g_short_beacon_data *sb,
+ bool is_template)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct ieee80211_if_ap *ap = &sdata->u.ap;
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(local->tx_headroom + sb->short_head_len +
+ sb->short_tail_len + 256 +
+ local->hw.extra_beacon_tailroom);
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, local->tx_headroom);
+ skb_put_data(skb, sb->short_head, sb->short_head_len);
+
+ ieee80211_beacon_add_tim(sdata, link, &ap->ps, skb, is_template);
+
+ if (sb->short_tail)
+ skb_put_data(skb, sb->short_tail, sb->short_tail_len);
+
+ ieee80211_beacon_get_finish(hw, vif, link, NULL, NULL, skb,
+ chanctx_conf, 0);
+ return skb;
+}
+
+static struct sk_buff *
+ieee80211_beacon_get_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_link_data *link,
+ struct ieee80211_mutable_offsets *offs,
+ bool is_template, struct beacon_data *beacon,
+ struct ieee80211_chanctx_conf *chanctx_conf,
+ u8 ema_index, struct s1g_short_beacon_data *s1g_sb)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+ if (!sdata->vif.cfg.s1g || !s1g_sb ||
+ ieee80211_s1g_need_long_beacon(sdata, link))
+ return __ieee80211_beacon_get_ap(hw, vif, link, offs,
+ is_template, beacon,
+ chanctx_conf, ema_index);
+
+ return ieee80211_s1g_short_beacon_get(hw, vif, link, chanctx_conf,
+ s1g_sb, is_template);
+}
+
static struct ieee80211_ema_beacons *
ieee80211_beacon_get_ap_ema_list(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -5381,7 +5456,7 @@ ieee80211_beacon_get_ap_ema_list(struct ieee80211_hw *hw,
ieee80211_beacon_get_ap(hw, vif, link,
&ema->bcn[ema->cnt].offs,
is_template, beacon,
- chanctx_conf, ema->cnt);
+ chanctx_conf, ema->cnt, NULL);
if (!ema->bcn[ema->cnt].skb)
break;
}
@@ -5410,6 +5485,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
struct ieee80211_sub_if_data *sdata = NULL;
struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_link_data *link;
+ struct s1g_short_beacon_data *s1g_short_bcn = NULL;
rcu_read_lock();
@@ -5431,6 +5507,13 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
if (!beacon)
goto out;
+ if (vif->cfg.s1g && link->u.ap.s1g_short_beacon) {
+ s1g_short_bcn =
+ rcu_dereference(link->u.ap.s1g_short_beacon);
+ if (!s1g_short_bcn)
+ goto out;
+ }
+
if (ema_beacons) {
*ema_beacons =
ieee80211_beacon_get_ap_ema_list(hw, vif, link,
@@ -5451,8 +5534,8 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
skb = ieee80211_beacon_get_ap(hw, vif, link, offs,
is_template, beacon,
- chanctx_conf,
- ema_index);
+ chanctx_conf, ema_index,
+ s1g_short_bcn);
}
} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 0d85a382746f..32f1bc5908c5 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3913,10 +3913,8 @@ int ieee80211_parse_p2p_noa(const struct ieee80211_p2p_noa_attr *attr,
}
EXPORT_SYMBOL(ieee80211_parse_p2p_noa);
-void ieee80211_recalc_dtim(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata)
+void ieee80211_recalc_dtim(struct ieee80211_sub_if_data *sdata, u64 tsf)
{
- u64 tsf = drv_get_tsf(local, sdata);
u64 dtim_count = 0;
u32 beacon_int = sdata->vif.bss_conf.beacon_int * 1024;
u8 dtim_period = sdata->vif.bss_conf.dtim_period;
@@ -3954,6 +3952,33 @@ void ieee80211_recalc_dtim(struct ieee80211_local *local,
ps->dtim_count = dtim_count;
}
+/*
+ * Given a long beacon period, calculate the current index into
+ * that period to determine the number of TSBTTs until the next TBTT.
+ * It is completely valid to have a short beacon period that differs
+ * from the dtim period (i.e a TBTT thats not a DTIM).
+ */
+void ieee80211_recalc_sb_count(struct ieee80211_sub_if_data *sdata, u64 tsf)
+{
+ u32 sb_idx;
+ struct ps_data *ps = &sdata->bss->ps;
+ u8 lb_period = sdata->vif.bss_conf.s1g_long_beacon_period;
+ u32 beacon_int = sdata->vif.bss_conf.beacon_int * 1024;
+
+ /* No mesh / IBSS support for short beaconing */
+ if (tsf == -1ULL || !lb_period ||
+ (sdata->vif.type != NL80211_IFTYPE_AP &&
+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
+ return;
+
+ /* find the current TSBTT index in our lb_period */
+ do_div(tsf, beacon_int);
+ sb_idx = do_div(tsf, lb_period);
+
+ /* num TSBTTs until the next TBTT */
+ ps->sb_count = sb_idx ? lb_period - sb_idx : 0;
+}
+
static u8 ieee80211_chanctx_radar_detect(struct ieee80211_local *local,
struct ieee80211_chanctx *ctx)
{
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index bb5bc6ff09d4..46394eb2086f 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -867,7 +867,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
mgmt = (const struct ieee80211_mgmt *)params->buf;
- if (!ieee80211_is_mgmt(mgmt->frame_control))
+ if (!ieee80211_is_mgmt(mgmt->frame_control) ||
+ ieee80211_has_order(mgmt->frame_control))
return -EINVAL;
stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 63f015ce9ad4..89519aa52893 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -482,6 +482,16 @@ nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
[NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
};
+static const struct nla_policy
+nl80211_s1g_short_beacon[NL80211_S1G_SHORT_BEACON_ATTR_MAX + 1] = {
+ [NL80211_S1G_SHORT_BEACON_ATTR_HEAD] =
+ NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head,
+ IEEE80211_MAX_DATA_LEN),
+ [NL80211_S1G_SHORT_BEACON_ATTR_TAIL] =
+ NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
+ IEEE80211_MAX_DATA_LEN),
+};
+
static const struct netlink_range_validation nl80211_punct_bitmap_range = {
.min = 0,
.max = 0xffff,
@@ -858,6 +868,9 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_EPCS] = { .type = NLA_FLAG },
[NL80211_ATTR_ASSOC_MLD_EXT_CAPA_OPS] = { .type = NLA_U16 },
[NL80211_ATTR_WIPHY_RADIO_INDEX] = { .type = NLA_U8 },
+ [NL80211_ATTR_S1G_LONG_BEACON_PERIOD] = NLA_POLICY_MIN(NLA_U8, 2),
+ [NL80211_ATTR_S1G_SHORT_BEACON] =
+ NLA_POLICY_NESTED(nl80211_s1g_short_beacon),
};
/* policy for the key attributes */
@@ -6202,6 +6215,41 @@ static int nl80211_validate_ap_phy_operation(struct cfg80211_ap_settings *params
return 0;
}
+static int
+nl80211_parse_s1g_short_beacon(struct cfg80211_registered_device *rdev,
+ struct nlattr *attrs,
+ struct cfg80211_s1g_short_beacon *sb)
+{
+ struct nlattr *tb[NL80211_S1G_SHORT_BEACON_ATTR_MAX + 1];
+ int ret;
+
+ if (!rdev->wiphy.bands[NL80211_BAND_S1GHZ])
+ return -EINVAL;
+
+ ret = nla_parse_nested(tb, NL80211_S1G_SHORT_BEACON_ATTR_MAX, attrs,
+ NULL, NULL);
+ if (ret)
+ return ret;
+
+ /* Short beacon tail is optional (i.e might only include the TIM) */
+ if (!tb[NL80211_S1G_SHORT_BEACON_ATTR_HEAD])
+ return -EINVAL;
+
+ sb->short_head = nla_data(tb[NL80211_S1G_SHORT_BEACON_ATTR_HEAD]);
+ sb->short_head_len = nla_len(tb[NL80211_S1G_SHORT_BEACON_ATTR_HEAD]);
+ sb->short_tail_len = 0;
+
+ if (tb[NL80211_S1G_SHORT_BEACON_ATTR_TAIL]) {
+ sb->short_tail =
+ nla_data(tb[NL80211_S1G_SHORT_BEACON_ATTR_TAIL]);
+ sb->short_tail_len =
+ nla_len(tb[NL80211_S1G_SHORT_BEACON_ATTR_TAIL]);
+ }
+
+ sb->update = true;
+ return 0;
+}
+
static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -6442,6 +6490,22 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
goto out;
}
+ if (info->attrs[NL80211_ATTR_S1G_SHORT_BEACON]) {
+ if (!info->attrs[NL80211_ATTR_S1G_LONG_BEACON_PERIOD]) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ params->s1g_long_beacon_period = nla_get_u8(
+ info->attrs[NL80211_ATTR_S1G_LONG_BEACON_PERIOD]);
+
+ err = nl80211_parse_s1g_short_beacon(
+ rdev, info->attrs[NL80211_ATTR_S1G_SHORT_BEACON],
+ &params->s1g_short_beacon);
+ if (err)
+ goto out;
+ }
+
err = nl80211_calculate_ap_params(params);
if (err)
goto out;
@@ -6550,6 +6614,14 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
goto out;
}
+ attr = info->attrs[NL80211_ATTR_S1G_SHORT_BEACON];
+ if (attr) {
+ err = nl80211_parse_s1g_short_beacon(rdev, attr,
+ &params->s1g_short_beacon);
+ if (err)
+ goto out;
+ }
+
err = rdev_change_beacon(rdev, dev, params);
out:
@@ -9975,7 +10047,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request = kzalloc(size, GFP_KERNEL);
if (!request)
return -ENOMEM;
- request->req.n_channels = n_channels;
if (n_ssids)
request->req.ssids = (void *)request + ssids_offset;
@@ -17488,6 +17559,7 @@ static int nl80211_set_sar_specs(struct sk_buff *skb, struct genl_info *info)
if (!sar_spec)
return -ENOMEM;
+ sar_spec->num_sub_specs = specs;
sar_spec->type = type;
specs = 0;
nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem) {
@@ -19684,7 +19756,7 @@ void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
EXPORT_SYMBOL(cfg80211_conn_failed);
static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
- const u8 *addr, gfp_t gfp)
+ const u8 *addr, int link_id, gfp_t gfp)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
@@ -19707,7 +19779,9 @@ static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
- nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
+ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
+ (link_id >= 0 &&
+ nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)))
goto nla_put_failure;
genlmsg_end(msg, hdr);
@@ -19719,13 +19793,13 @@ static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
return true;
}
-bool cfg80211_rx_spurious_frame(struct net_device *dev,
- const u8 *addr, gfp_t gfp)
+bool cfg80211_rx_spurious_frame(struct net_device *dev, const u8 *addr,
+ int link_id, gfp_t gfp)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
bool ret;
- trace_cfg80211_rx_spurious_frame(dev, addr);
+ trace_cfg80211_rx_spurious_frame(dev, addr, link_id);
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
@@ -19733,19 +19807,19 @@ bool cfg80211_rx_spurious_frame(struct net_device *dev,
return false;
}
ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME,
- addr, gfp);
+ addr, link_id, gfp);
trace_cfg80211_return_bool(ret);
return ret;
}
EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
-bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
- const u8 *addr, gfp_t gfp)
+bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, const u8 *addr,
+ int link_id, gfp_t gfp)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
bool ret;
- trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
+ trace_cfg80211_rx_unexpected_4addr_frame(dev, addr, link_id);
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
wdev->iftype != NL80211_IFTYPE_P2P_GO &&
@@ -19755,7 +19829,7 @@ bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
}
ret = __nl80211_unexpected_frame(dev,
NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
- addr, gfp);
+ addr, link_id, gfp);
trace_cfg80211_return_bool(ret);
return ret;
}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 2524bc187a19..3b0ac3437f81 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -4229,6 +4229,8 @@ static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
struct wireless_dev *wdev;
unsigned int link_id;
+ guard(wiphy)(&rdev->wiphy);
+
/* If we finished CAC or received radar, we should end any
* CAC running on the same channels.
* the check !cfg80211_chandef_dfs_usable contain 2 options:
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 6d7a7e7f0fc2..826ec0a6355f 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -83,7 +83,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
if (!request)
return -ENOMEM;
- request->req.n_channels = n_channels;
if (wdev->conn->params.channel) {
enum nl80211_band band = wdev->conn->params.channel->band;
struct ieee80211_supported_band *sband =
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index a07d88d61bec..34c584a215e5 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -3570,27 +3570,30 @@ TRACE_EVENT(cfg80211_cac_event,
);
DECLARE_EVENT_CLASS(cfg80211_rx_evt,
- TP_PROTO(struct net_device *netdev, const u8 *addr),
- TP_ARGS(netdev, addr),
+ TP_PROTO(struct net_device *netdev, const u8 *addr, int link_id),
+ TP_ARGS(netdev, addr, link_id),
TP_STRUCT__entry(
NETDEV_ENTRY
MAC_ENTRY(addr)
+ __field(int, link_id)
),
TP_fast_assign(
NETDEV_ASSIGN;
MAC_ASSIGN(addr, addr);
+ __entry->link_id = link_id;
),
- TP_printk(NETDEV_PR_FMT ", %pM", NETDEV_PR_ARG, __entry->addr)
+ TP_printk(NETDEV_PR_FMT ", %pM, link_id:%d", NETDEV_PR_ARG,
+ __entry->addr, __entry->link_id)
);
DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame,
- TP_PROTO(struct net_device *netdev, const u8 *addr),
- TP_ARGS(netdev, addr)
+ TP_PROTO(struct net_device *netdev, const u8 *addr, int link_id),
+ TP_ARGS(netdev, addr, link_id)
);
DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_unexpected_4addr_frame,
- TP_PROTO(struct net_device *netdev, const u8 *addr),
- TP_ARGS(netdev, addr)
+ TP_PROTO(struct net_device *netdev, const u8 *addr, int link_id),
+ TP_ARGS(netdev, addr, link_id)
);
TRACE_EVENT(cfg80211_ibss_joined,