mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 08:45:51 +00:00
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 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEpeA8sTs3M8SN2hR410qiO8sPaAAFAmdYO1cACgkQ10qiO8sP aAC3Ug//aYzp6YDiEkmS0CWBKBa8sWDAXR64tUmtTAbWKq1W2JETTgpnR4mmSnA/ WfLjwd2cenbyiPbuIveBTD5cFUCmX8z1DM2C2WTmYEWCTMCCZj1YS6ZUXL7Z+1rI oCZy5dGsIHP8nUL85jaLiXXhiNpZYgyAqLnBawZ+JgNQ8V0a1AtTYW+Ysvu8sTwg qXyfTt7ZJGpYqNquDjiyLF2S06yBSgvyT01pXbV4Eny4u7X8d2nBIXmOMdO2CQK0 cFxAs5pXq37ROpjT1ocuvsTNviQ8y74YwhKPOAHENE2I0THcyL7NGk+eHCB5dDAh BijQ30AGdG+0wnBSFxWnZy9vbSXhsS3p8fzOS0th/3K3kuLo16INGhqMIQf4HkYt lNxYA+YL18uVy3dpvPKgDpNA9AKrzP0bCZRBnTUTWYyV/n7o/J9kSk7TuYjAkQZl 260gADBas1XIDE7MSvEWizFRzuurDE7RGIFk6pRLN4m1ueqynoLxNrgsOBEjvui6 4cKmnlnWwcczpUd5FDTTpNHTGDZblP/ruoPnJz4MrBwzJyJ7PNe87n/t9aqRq6SS 6LgOojt+dNZQCtrS51bhyVJhq2FhaEjhCAGtJ/TQkRrfAakX6jCEs7HDVoPkkuOX wt88PIUhDUCYkhmOmHXpIZGkdg3rJlk/d8+lbhyDI1htce3ptpQ= =qo16 -----END PGP SIGNATURE----- Merge tag 'wireless-2024-12-10' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless 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>
This commit is contained in:
commit
d02af27fa2
@ -1972,7 +1972,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
|
||||
if (csa_err_mask & (CS_ERR_COUNT_ERROR |
|
||||
CS_ERR_LONG_DELAY_AFTER_CS |
|
||||
CS_ERR_TX_BLOCK_TIMER_EXPIRED))
|
||||
ieee80211_channel_switch_disconnect(vif, true);
|
||||
ieee80211_channel_switch_disconnect(vif);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
|
@ -1987,6 +1987,8 @@ enum ieee80211_neg_ttlm_res {
|
||||
* @neg_ttlm: negotiated TID to link mapping info.
|
||||
* see &struct ieee80211_neg_ttlm.
|
||||
* @addr: address of this interface
|
||||
* @addr_valid: indicates if the address is actively used. Set to false for
|
||||
* passive monitor interfaces, true in all other cases.
|
||||
* @p2p: indicates whether this AP or STA interface is a p2p
|
||||
* interface, i.e. a GO or p2p-sta respectively
|
||||
* @netdev_features: tx netdev features supported by the hardware for this
|
||||
@ -2026,6 +2028,7 @@ struct ieee80211_vif {
|
||||
u16 valid_links, active_links, dormant_links, suspended_links;
|
||||
struct ieee80211_neg_ttlm neg_ttlm;
|
||||
u8 addr[ETH_ALEN] __aligned(2);
|
||||
bool addr_valid;
|
||||
bool p2p;
|
||||
|
||||
u8 cab_queue;
|
||||
@ -6795,14 +6798,12 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success,
|
||||
/**
|
||||
* ieee80211_channel_switch_disconnect - disconnect due to channel switch error
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
* @block_tx: if %true, do not send deauth frame.
|
||||
*
|
||||
* Instruct mac80211 to disconnect due to a channel switch error. The channel
|
||||
* switch can request to block the tx and so, we need to make sure we do not send
|
||||
* a deauth frame in this case.
|
||||
*/
|
||||
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif,
|
||||
bool block_tx);
|
||||
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* ieee80211_request_smps - request SM PS transition
|
||||
|
@ -1088,13 +1088,13 @@ ieee80211_copy_mbssid_beacon(u8 *pos, struct cfg80211_mbssid_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;
|
||||
}
|
||||
@ -1935,6 +1935,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
|
||||
params->eht_capa_len,
|
||||
link_sta);
|
||||
|
||||
ieee80211_sta_init_nss(link_sta);
|
||||
|
||||
if (params->opmode_notif_used) {
|
||||
/* returned value is only needed for rc update, but the
|
||||
* rc isn't initialized here yet, so ignore it
|
||||
@ -1944,8 +1946,6 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
|
||||
sband->band);
|
||||
}
|
||||
|
||||
ieee80211_sta_init_nss(link_sta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3726,13 +3726,12 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif, unsigned int link_id)
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_finish);
|
||||
|
||||
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif, bool block_tx)
|
||||
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
sdata->csa_blocked_queues = block_tx;
|
||||
sdata_info(sdata, "channel switch failed, disconnecting\n");
|
||||
wiphy_work_queue(local->hw.wiphy, &ifmgd->csa_connection_drop_work);
|
||||
}
|
||||
@ -5046,10 +5045,16 @@ static void ieee80211_del_intf_link(struct wiphy *wiphy,
|
||||
unsigned int link_id)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||
u16 new_links = wdev->valid_links & ~BIT(link_id);
|
||||
|
||||
lockdep_assert_wiphy(sdata->local->hw.wiphy);
|
||||
|
||||
ieee80211_vif_set_links(sdata, wdev->valid_links, 0);
|
||||
/* During the link teardown process, certain functions require the
|
||||
* link_id to remain in the valid_links bitmap. Therefore, instead
|
||||
* of removing the link_id from the bitmap, pass a masked value to
|
||||
* simulate as if link_id does not exist anymore.
|
||||
*/
|
||||
ieee80211_vif_set_links(sdata, new_links, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1104,8 +1104,6 @@ struct ieee80211_sub_if_data {
|
||||
|
||||
unsigned long state;
|
||||
|
||||
bool csa_blocked_queues;
|
||||
|
||||
char name[IFNAMSIZ];
|
||||
|
||||
struct ieee80211_fragment_cache frags;
|
||||
@ -2412,17 +2410,13 @@ void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_hdr *hdr, bool ack, u16 tx_time);
|
||||
|
||||
unsigned int
|
||||
ieee80211_get_vif_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
|
||||
unsigned long queues,
|
||||
enum queue_stop_reason reason,
|
||||
bool refcounted);
|
||||
void ieee80211_stop_vif_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
enum queue_stop_reason reason);
|
||||
void ieee80211_wake_vif_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
enum queue_stop_reason reason);
|
||||
void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
|
||||
unsigned long queues,
|
||||
enum queue_stop_reason reason,
|
||||
@ -2433,6 +2427,43 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
|
||||
void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
|
||||
enum queue_stop_reason reason,
|
||||
bool refcounted);
|
||||
static inline void
|
||||
ieee80211_stop_vif_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
enum queue_stop_reason reason)
|
||||
{
|
||||
ieee80211_stop_queues_by_reason(&local->hw,
|
||||
ieee80211_get_vif_queues(local, sdata),
|
||||
reason, true);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ieee80211_wake_vif_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
enum queue_stop_reason reason)
|
||||
{
|
||||
ieee80211_wake_queues_by_reason(&local->hw,
|
||||
ieee80211_get_vif_queues(local, sdata),
|
||||
reason, true);
|
||||
}
|
||||
static inline void
|
||||
ieee80211_stop_vif_queues_norefcount(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
enum queue_stop_reason reason)
|
||||
{
|
||||
ieee80211_stop_queues_by_reason(&local->hw,
|
||||
ieee80211_get_vif_queues(local, sdata),
|
||||
reason, false);
|
||||
}
|
||||
static inline void
|
||||
ieee80211_wake_vif_queues_norefcount(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
enum queue_stop_reason reason)
|
||||
{
|
||||
ieee80211_wake_queues_by_reason(&local->hw,
|
||||
ieee80211_get_vif_queues(local, sdata),
|
||||
reason, false);
|
||||
}
|
||||
void ieee80211_add_pending_skb(struct ieee80211_local *local,
|
||||
struct sk_buff *skb);
|
||||
void ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
|
@ -278,13 +278,8 @@ static int _ieee80211_change_mac(struct ieee80211_sub_if_data *sdata,
|
||||
ret = eth_mac_addr(sdata->dev, sa);
|
||||
|
||||
if (ret == 0) {
|
||||
if (check_dup) {
|
||||
memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
|
||||
ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
|
||||
} else {
|
||||
memset(sdata->vif.addr, 0, ETH_ALEN);
|
||||
memset(sdata->vif.bss_conf.addr, 0, ETH_ALEN);
|
||||
}
|
||||
memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
|
||||
ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
}
|
||||
}
|
||||
|
||||
sdata->vif.addr_valid = sdata->vif.type != NL80211_IFTYPE_MONITOR ||
|
||||
(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE);
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
/* 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)
|
||||
if (ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA))
|
||||
return;
|
||||
|
||||
ieee80211_stop_vif_queues(local, sdata,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
sdata->csa_blocked_queues = true;
|
||||
ieee80211_stop_vif_queues_norefcount(local, sdata,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
}
|
||||
|
||||
void ieee80211_vif_unblock_queues_csa(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
if (sdata->csa_blocked_queues) {
|
||||
ieee80211_wake_vif_queues(local, sdata,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
sdata->csa_blocked_queues = false;
|
||||
}
|
||||
ieee80211_wake_vif_queues_norefcount(local, sdata,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
}
|
||||
|
@ -1157,14 +1157,14 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
|
||||
u64 changed)
|
||||
{
|
||||
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||
unsigned long bits = changed;
|
||||
unsigned long bits[] = { BITMAP_FROM_U64(changed) };
|
||||
u32 bit;
|
||||
|
||||
if (!bits)
|
||||
if (!changed)
|
||||
return;
|
||||
|
||||
/* if we race with running work, worst case this work becomes a noop */
|
||||
for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE)
|
||||
for_each_set_bit(bit, bits, sizeof(changed) * BITS_PER_BYTE)
|
||||
set_bit(bit, ifmsh->mbss_changed);
|
||||
set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags);
|
||||
wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
|
||||
|
@ -2638,8 +2638,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
|
||||
*/
|
||||
link->conf->csa_active = true;
|
||||
link->u.mgd.csa.blocked_tx = csa_ie.mode;
|
||||
sdata->csa_blocked_queues =
|
||||
csa_ie.mode && !ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA);
|
||||
|
||||
wiphy_work_queue(sdata->local->hw.wiphy,
|
||||
&ifmgd->csa_connection_drop_work);
|
||||
|
@ -657,7 +657,7 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw)
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_wake_queues);
|
||||
|
||||
static unsigned int
|
||||
unsigned int
|
||||
ieee80211_get_vif_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
@ -669,7 +669,8 @@ ieee80211_get_vif_queues(struct ieee80211_local *local,
|
||||
queues = 0;
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
|
||||
queues |= BIT(sdata->vif.hw_queue[ac]);
|
||||
if (sdata->vif.hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
|
||||
queues |= BIT(sdata->vif.hw_queue[ac]);
|
||||
if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE)
|
||||
queues |= BIT(sdata->vif.cab_queue);
|
||||
} else {
|
||||
@ -724,24 +725,6 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
|
||||
__ieee80211_flush_queues(local, sdata, 0, drop);
|
||||
}
|
||||
|
||||
void ieee80211_stop_vif_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
enum queue_stop_reason reason)
|
||||
{
|
||||
ieee80211_stop_queues_by_reason(&local->hw,
|
||||
ieee80211_get_vif_queues(local, sdata),
|
||||
reason, true);
|
||||
}
|
||||
|
||||
void ieee80211_wake_vif_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
enum queue_stop_reason reason)
|
||||
{
|
||||
ieee80211_wake_queues_by_reason(&local->hw,
|
||||
ieee80211_get_vif_queues(local, sdata),
|
||||
reason, true);
|
||||
}
|
||||
|
||||
static void __iterate_interfaces(struct ieee80211_local *local,
|
||||
u32 iter_flags,
|
||||
void (*iterator)(void *data, u8 *mac,
|
||||
@ -1843,6 +1826,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n");
|
||||
else
|
||||
WARN(1, "Hardware became unavailable during restart.\n");
|
||||
ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND,
|
||||
false);
|
||||
ieee80211_handle_reconfig_failure(local);
|
||||
return res;
|
||||
}
|
||||
|
@ -814,7 +814,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
||||
[NL80211_ATTR_MLO_LINKS] =
|
||||
NLA_POLICY_NESTED_ARRAY(nl80211_policy),
|
||||
[NL80211_ATTR_MLO_LINK_ID] =
|
||||
NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS),
|
||||
NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS - 1),
|
||||
[NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
|
||||
[NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
|
||||
[NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
|
||||
|
@ -83,6 +83,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
|
||||
if (!request)
|
||||
return -ENOMEM;
|
||||
|
||||
request->n_channels = n_channels;
|
||||
if (wdev->conn->params.channel) {
|
||||
enum nl80211_band band = wdev->conn->params.channel->band;
|
||||
struct ieee80211_supported_band *sband =
|
||||
|
@ -2843,10 +2843,9 @@ void cfg80211_remove_link(struct wireless_dev *wdev, unsigned int link_id)
|
||||
break;
|
||||
}
|
||||
|
||||
wdev->valid_links &= ~BIT(link_id);
|
||||
|
||||
rdev_del_intf_link(rdev, wdev, link_id);
|
||||
|
||||
wdev->valid_links &= ~BIT(link_id);
|
||||
eth_zero_addr(wdev->links[link_id].addr);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user