Skip to content

Commit d02af27

Browse files
committed
Johannes Berg says: ==================== A small set of fixes: - avoid CSA warnings during link removal (by changing link bitmap after remove) - fix # of spatial streams initialisation - fix queues getting stuck in some CSA cases and resume failures - fix interface address when switching monitor mode - fix MBSS change flags 32-bit stack corruption - more UBSAN __counted_by "fixes" ... - fix link ID netlink validation * tag 'wireless-2024-12-10' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless: wifi: cfg80211: sme: init n_channels before channels[] access wifi: mac80211: fix station NSS capability initialization order wifi: mac80211: fix vif addr when switching from monitor to station wifi: mac80211: fix a queue stall in certain cases of CSA wifi: mac80211: wake the queues in case of failure in resume wifi: cfg80211: clear link ID from bitmap during link delete after clean up wifi: mac80211: init cnt before accessing elem in ieee80211_copy_mbssid_beacon wifi: mac80211: fix mbss changed flags corruption on 32 bit systems wifi: nl80211: fix NL80211_ATTR_MLO_LINK_ID off-by-one ==================== Link: https://patch.msgid.link/20241210130145.28618-3-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 06d64ab + f1d3334 commit d02af27

File tree

11 files changed

+76
-62
lines changed

11 files changed

+76
-62
lines changed

drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1972,7 +1972,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
19721972
if (csa_err_mask & (CS_ERR_COUNT_ERROR |
19731973
CS_ERR_LONG_DELAY_AFTER_CS |
19741974
CS_ERR_TX_BLOCK_TIMER_EXPIRED))
1975-
ieee80211_channel_switch_disconnect(vif, true);
1975+
ieee80211_channel_switch_disconnect(vif);
19761976
rcu_read_unlock();
19771977
}
19781978

include/net/mac80211.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,6 +1987,8 @@ enum ieee80211_neg_ttlm_res {
19871987
* @neg_ttlm: negotiated TID to link mapping info.
19881988
* see &struct ieee80211_neg_ttlm.
19891989
* @addr: address of this interface
1990+
* @addr_valid: indicates if the address is actively used. Set to false for
1991+
* passive monitor interfaces, true in all other cases.
19901992
* @p2p: indicates whether this AP or STA interface is a p2p
19911993
* interface, i.e. a GO or p2p-sta respectively
19921994
* @netdev_features: tx netdev features supported by the hardware for this
@@ -2026,6 +2028,7 @@ struct ieee80211_vif {
20262028
u16 valid_links, active_links, dormant_links, suspended_links;
20272029
struct ieee80211_neg_ttlm neg_ttlm;
20282030
u8 addr[ETH_ALEN] __aligned(2);
2031+
bool addr_valid;
20292032
bool p2p;
20302033

20312034
u8 cab_queue;
@@ -6795,14 +6798,12 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success,
67956798
/**
67966799
* ieee80211_channel_switch_disconnect - disconnect due to channel switch error
67976800
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
6798-
* @block_tx: if %true, do not send deauth frame.
67996801
*
68006802
* Instruct mac80211 to disconnect due to a channel switch error. The channel
68016803
* switch can request to block the tx and so, we need to make sure we do not send
68026804
* a deauth frame in this case.
68036805
*/
6804-
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif,
6805-
bool block_tx);
6806+
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif);
68066807

68076808
/**
68086809
* ieee80211_request_smps - request SM PS transition

net/mac80211/cfg.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,13 +1088,13 @@ ieee80211_copy_mbssid_beacon(u8 *pos, struct cfg80211_mbssid_elems *dst,
10881088
{
10891089
int i, offset = 0;
10901090

1091+
dst->cnt = src->cnt;
10911092
for (i = 0; i < src->cnt; i++) {
10921093
memcpy(pos + offset, src->elem[i].data, src->elem[i].len);
10931094
dst->elem[i].len = src->elem[i].len;
10941095
dst->elem[i].data = pos + offset;
10951096
offset += dst->elem[i].len;
10961097
}
1097-
dst->cnt = src->cnt;
10981098

10991099
return offset;
11001100
}
@@ -1935,6 +1935,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
19351935
params->eht_capa_len,
19361936
link_sta);
19371937

1938+
ieee80211_sta_init_nss(link_sta);
1939+
19381940
if (params->opmode_notif_used) {
19391941
/* returned value is only needed for rc update, but the
19401942
* rc isn't initialized here yet, so ignore it
@@ -1944,8 +1946,6 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
19441946
sband->band);
19451947
}
19461948

1947-
ieee80211_sta_init_nss(link_sta);
1948-
19491949
return 0;
19501950
}
19511951

@@ -3726,13 +3726,12 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif, unsigned int link_id)
37263726
}
37273727
EXPORT_SYMBOL(ieee80211_csa_finish);
37283728

3729-
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif, bool block_tx)
3729+
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif)
37303730
{
37313731
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
37323732
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
37333733
struct ieee80211_local *local = sdata->local;
37343734

3735-
sdata->csa_blocked_queues = block_tx;
37363735
sdata_info(sdata, "channel switch failed, disconnecting\n");
37373736
wiphy_work_queue(local->hw.wiphy, &ifmgd->csa_connection_drop_work);
37383737
}
@@ -5046,10 +5045,16 @@ static void ieee80211_del_intf_link(struct wiphy *wiphy,
50465045
unsigned int link_id)
50475046
{
50485047
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
5048+
u16 new_links = wdev->valid_links & ~BIT(link_id);
50495049

50505050
lockdep_assert_wiphy(sdata->local->hw.wiphy);
50515051

5052-
ieee80211_vif_set_links(sdata, wdev->valid_links, 0);
5052+
/* During the link teardown process, certain functions require the
5053+
* link_id to remain in the valid_links bitmap. Therefore, instead
5054+
* of removing the link_id from the bitmap, pass a masked value to
5055+
* simulate as if link_id does not exist anymore.
5056+
*/
5057+
ieee80211_vif_set_links(sdata, new_links, 0);
50535058
}
50545059

50555060
static int

net/mac80211/ieee80211_i.h

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,8 +1104,6 @@ struct ieee80211_sub_if_data {
11041104

11051105
unsigned long state;
11061106

1107-
bool csa_blocked_queues;
1108-
11091107
char name[IFNAMSIZ];
11101108

11111109
struct ieee80211_fragment_cache frags;
@@ -2412,17 +2410,13 @@ void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
24122410
struct ieee80211_sub_if_data *sdata);
24132411
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
24142412
struct ieee80211_hdr *hdr, bool ack, u16 tx_time);
2415-
2413+
unsigned int
2414+
ieee80211_get_vif_queues(struct ieee80211_local *local,
2415+
struct ieee80211_sub_if_data *sdata);
24162416
void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
24172417
unsigned long queues,
24182418
enum queue_stop_reason reason,
24192419
bool refcounted);
2420-
void ieee80211_stop_vif_queues(struct ieee80211_local *local,
2421-
struct ieee80211_sub_if_data *sdata,
2422-
enum queue_stop_reason reason);
2423-
void ieee80211_wake_vif_queues(struct ieee80211_local *local,
2424-
struct ieee80211_sub_if_data *sdata,
2425-
enum queue_stop_reason reason);
24262420
void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
24272421
unsigned long queues,
24282422
enum queue_stop_reason reason,
@@ -2433,6 +2427,43 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
24332427
void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
24342428
enum queue_stop_reason reason,
24352429
bool refcounted);
2430+
static inline void
2431+
ieee80211_stop_vif_queues(struct ieee80211_local *local,
2432+
struct ieee80211_sub_if_data *sdata,
2433+
enum queue_stop_reason reason)
2434+
{
2435+
ieee80211_stop_queues_by_reason(&local->hw,
2436+
ieee80211_get_vif_queues(local, sdata),
2437+
reason, true);
2438+
}
2439+
2440+
static inline void
2441+
ieee80211_wake_vif_queues(struct ieee80211_local *local,
2442+
struct ieee80211_sub_if_data *sdata,
2443+
enum queue_stop_reason reason)
2444+
{
2445+
ieee80211_wake_queues_by_reason(&local->hw,
2446+
ieee80211_get_vif_queues(local, sdata),
2447+
reason, true);
2448+
}
2449+
static inline void
2450+
ieee80211_stop_vif_queues_norefcount(struct ieee80211_local *local,
2451+
struct ieee80211_sub_if_data *sdata,
2452+
enum queue_stop_reason reason)
2453+
{
2454+
ieee80211_stop_queues_by_reason(&local->hw,
2455+
ieee80211_get_vif_queues(local, sdata),
2456+
reason, false);
2457+
}
2458+
static inline void
2459+
ieee80211_wake_vif_queues_norefcount(struct ieee80211_local *local,
2460+
struct ieee80211_sub_if_data *sdata,
2461+
enum queue_stop_reason reason)
2462+
{
2463+
ieee80211_wake_queues_by_reason(&local->hw,
2464+
ieee80211_get_vif_queues(local, sdata),
2465+
reason, false);
2466+
}
24362467
void ieee80211_add_pending_skb(struct ieee80211_local *local,
24372468
struct sk_buff *skb);
24382469
void ieee80211_add_pending_skbs(struct ieee80211_local *local,

net/mac80211/iface.c

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -278,13 +278,8 @@ static int _ieee80211_change_mac(struct ieee80211_sub_if_data *sdata,
278278
ret = eth_mac_addr(sdata->dev, sa);
279279

280280
if (ret == 0) {
281-
if (check_dup) {
282-
memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
283-
ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
284-
} else {
285-
memset(sdata->vif.addr, 0, ETH_ALEN);
286-
memset(sdata->vif.bss_conf.addr, 0, ETH_ALEN);
287-
}
281+
memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
282+
ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
288283
}
289284

290285
/* Regardless of eth_mac_addr() return we still want to add the
@@ -1323,6 +1318,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
13231318
}
13241319
}
13251320

1321+
sdata->vif.addr_valid = sdata->vif.type != NL80211_IFTYPE_MONITOR ||
1322+
(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE);
13261323
switch (sdata->vif.type) {
13271324
case NL80211_IFTYPE_AP_VLAN:
13281325
/* no need to tell driver, but set carrier and chanctx */
@@ -2374,18 +2371,14 @@ void ieee80211_vif_block_queues_csa(struct ieee80211_sub_if_data *sdata)
23742371
if (ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA))
23752372
return;
23762373

2377-
ieee80211_stop_vif_queues(local, sdata,
2378-
IEEE80211_QUEUE_STOP_REASON_CSA);
2379-
sdata->csa_blocked_queues = true;
2374+
ieee80211_stop_vif_queues_norefcount(local, sdata,
2375+
IEEE80211_QUEUE_STOP_REASON_CSA);
23802376
}
23812377

23822378
void ieee80211_vif_unblock_queues_csa(struct ieee80211_sub_if_data *sdata)
23832379
{
23842380
struct ieee80211_local *local = sdata->local;
23852381

2386-
if (sdata->csa_blocked_queues) {
2387-
ieee80211_wake_vif_queues(local, sdata,
2388-
IEEE80211_QUEUE_STOP_REASON_CSA);
2389-
sdata->csa_blocked_queues = false;
2390-
}
2382+
ieee80211_wake_vif_queues_norefcount(local, sdata,
2383+
IEEE80211_QUEUE_STOP_REASON_CSA);
23912384
}

net/mac80211/mesh.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,14 +1157,14 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
11571157
u64 changed)
11581158
{
11591159
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
1160-
unsigned long bits = changed;
1160+
unsigned long bits[] = { BITMAP_FROM_U64(changed) };
11611161
u32 bit;
11621162

1163-
if (!bits)
1163+
if (!changed)
11641164
return;
11651165

11661166
/* if we race with running work, worst case this work becomes a noop */
1167-
for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE)
1167+
for_each_set_bit(bit, bits, sizeof(changed) * BITS_PER_BYTE)
11681168
set_bit(bit, ifmsh->mbss_changed);
11691169
set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags);
11701170
wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);

net/mac80211/mlme.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2638,8 +2638,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
26382638
*/
26392639
link->conf->csa_active = true;
26402640
link->u.mgd.csa.blocked_tx = csa_ie.mode;
2641-
sdata->csa_blocked_queues =
2642-
csa_ie.mode && !ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA);
26432641

26442642
wiphy_work_queue(sdata->local->hw.wiphy,
26452643
&ifmgd->csa_connection_drop_work);

net/mac80211/util.c

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw)
657657
}
658658
EXPORT_SYMBOL(ieee80211_wake_queues);
659659

660-
static unsigned int
660+
unsigned int
661661
ieee80211_get_vif_queues(struct ieee80211_local *local,
662662
struct ieee80211_sub_if_data *sdata)
663663
{
@@ -669,7 +669,8 @@ ieee80211_get_vif_queues(struct ieee80211_local *local,
669669
queues = 0;
670670

671671
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
672-
queues |= BIT(sdata->vif.hw_queue[ac]);
672+
if (sdata->vif.hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
673+
queues |= BIT(sdata->vif.hw_queue[ac]);
673674
if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE)
674675
queues |= BIT(sdata->vif.cab_queue);
675676
} else {
@@ -724,24 +725,6 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
724725
__ieee80211_flush_queues(local, sdata, 0, drop);
725726
}
726727

727-
void ieee80211_stop_vif_queues(struct ieee80211_local *local,
728-
struct ieee80211_sub_if_data *sdata,
729-
enum queue_stop_reason reason)
730-
{
731-
ieee80211_stop_queues_by_reason(&local->hw,
732-
ieee80211_get_vif_queues(local, sdata),
733-
reason, true);
734-
}
735-
736-
void ieee80211_wake_vif_queues(struct ieee80211_local *local,
737-
struct ieee80211_sub_if_data *sdata,
738-
enum queue_stop_reason reason)
739-
{
740-
ieee80211_wake_queues_by_reason(&local->hw,
741-
ieee80211_get_vif_queues(local, sdata),
742-
reason, true);
743-
}
744-
745728
static void __iterate_interfaces(struct ieee80211_local *local,
746729
u32 iter_flags,
747730
void (*iterator)(void *data, u8 *mac,
@@ -1843,6 +1826,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
18431826
WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n");
18441827
else
18451828
WARN(1, "Hardware became unavailable during restart.\n");
1829+
ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
1830+
IEEE80211_QUEUE_STOP_REASON_SUSPEND,
1831+
false);
18461832
ieee80211_handle_reconfig_failure(local);
18471833
return res;
18481834
}

net/wireless/nl80211.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
814814
[NL80211_ATTR_MLO_LINKS] =
815815
NLA_POLICY_NESTED_ARRAY(nl80211_policy),
816816
[NL80211_ATTR_MLO_LINK_ID] =
817-
NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS),
817+
NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS - 1),
818818
[NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
819819
[NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
820820
[NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },

net/wireless/sme.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
8383
if (!request)
8484
return -ENOMEM;
8585

86+
request->n_channels = n_channels;
8687
if (wdev->conn->params.channel) {
8788
enum nl80211_band band = wdev->conn->params.channel->band;
8889
struct ieee80211_supported_band *sband =

0 commit comments

Comments
 (0)