mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 02:24:24 +02:00
Quite a few more updates:
- cfg80211/mac80211:
- various security(-ish) fixes
- fix A-MSDU subframe handling
- fix multi-link element parsing
- ath10: avoid sending commands to dead device
- ath11k:
- fix WMI buffer leaks on error conditions
- fix UAF in RX MSDU coalesce path
- allow peer ID 0 on RX path (legal for mobile devices)
- reinitialize shared SRNG pointers on restart
- ath12k:
- fix 20 MHz-only parsing of EHT-MCS map
- iwlwifi:
- fix TSO segmentation explosion
- don't TX to dead device
- fix warning in WoWLAN
- fix TX rates on old devices
- disconnect on beacon loss only if also no other traffic
- fill NULL-ptr deref
- fix STEP_URM hardware access
-----BEGIN PGP SIGNATURE-----
iQIyBAABCgAdFiEEpeA8sTs3M8SN2hR410qiO8sPaAAFAmoPJEkACgkQ10qiO8sP
aACQrw/4vU+lbZNW19OyaJMd4h+44gUW+UGJixOzputQCBc6JGUlRsxgceWq5Ws5
5x2LTOX7S1wcvKm0VuSvkIRP3e9YHcgB60iBtsJ3ozz4RCoCFiSu8Bb2RdkGtRTp
7CKMK9NNuovOJncBzfyANq4ujsGs/58BmGbhXbaZ0ACfLUauesCCUtM7iQZE1k7t
lBqtk8ezkz1L8006w5vR7VR8g4KCCofQTEAOASmx450ZeGAiHMlWVKdMFFHV3zWj
ZDXopvLaMtduLNq9xqGYCRhAIZqOv1axgL7w9RRxsi2gWHv71kLqyz0IzgbFmh1m
ZxUSQ45+MHVYCHxs7HHCcTR5gqQlx47j5Wi3tuLUH8yoSZ8dPeWjmQMvIEswfZql
WNq18o6mcK+L3Yg87+oxiiJ7V/euaM//0+ZGtqhbiB+2FyHZhO42BqALTy7e4swS
kmEl8gCj2lgCbD2AHJQ9VpOJwoNdNuLYoJqg9IiIu/CYqQF80FGO8e6HZXBXsJkL
3KAPQIXkMMMkSjtpTg/GdHDiFqv/7lF8u3FgED7w7M1ZVQYNUc13KiDwPALFV0pu
bBbRktB6lvF6ShW9XrTrmn9lT0iiWHxr5YctWoys4+Ofr5V7PUzxNVDxDuzSVCZ0
apLYZ7uwSXO37q99p/azs47dzYp7tpnwKd4rpQuUTl/9bYErUA==
=vzwG
-----END PGP SIGNATURE-----
Merge tag 'wireless-2026-05-21' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless
Johannes Berg says:
====================
Quite a few more updates:
- cfg80211/mac80211:
- various security(-ish) fixes
- fix A-MSDU subframe handling
- fix multi-link element parsing
- ath10: avoid sending commands to dead device
- ath11k:
- fix WMI buffer leaks on error conditions
- fix UAF in RX MSDU coalesce path
- allow peer ID 0 on RX path (legal for mobile devices)
- reinitialize shared SRNG pointers on restart
- ath12k:
- fix 20 MHz-only parsing of EHT-MCS map
- iwlwifi:
- fix TSO segmentation explosion
- don't TX to dead device
- fix warning in WoWLAN
- fix TX rates on old devices
- disconnect on beacon loss only if also no other traffic
- fill NULL-ptr deref
- fix STEP_URM hardware access
* tag 'wireless-2026-05-21' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless: (24 commits)
wifi: cfg80211: wext: validate chandef in monitor mode
wifi: mac80211: consume only present negotiated TTLM maps
wifi: wilc1000: fix dma_buffer leak on bus acquire failure
wifi: mac80211: capture fast-RX rate before mesh reuses skb->cb
wifi: mac80211: fix multi-link element inheritance
wifi: mac80211: fix MLE defragmentation
wifi: mac80211: don't override max_amsdu_subframes
wifi: mac80211: bounds-check link_id in ieee80211_ml_epcs
wifi: ath12k: fix EHT TX MCS limitation due to wrong 20 MHz-only parsing
wifi: ath11k: clear shared SRNG pointer state on restart
wifi: ath11k: fix use after free in ath11k_dp_rx_msdu_coalesce()
wifi: ath11k: fix peer resolution on rx path when peer_id=0
wifi: iwlwifi: mld: disconnect only after 6 beacons without Rx
wifi: iwlwifi: mld: don't WARN on WoWLAN suspend w/o BSS vif
wifi: iwlwifi: use correct function to read STEP_URM register
wifi: iwlwifi: mvm: fix driver-set TX rates on old devices
wifi: iwlwifi: mld: don't dereference a pointer before NULL checking it
wifi: iwlwifi: mld: stop TX during firmware restart
wifi: iwlwifi: mld: fix TSO segmentation explosion when AMSDU is disabled
wifi: ath10k: skip WMI and beacon transmission when device is wedged
...
====================
Link: https://patch.msgid.link/20260521152903.374070-3-johannes@sipsolutions.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
0e3c08f1b7
|
|
@ -3,7 +3,6 @@
|
|||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*/
|
||||
|
||||
|
|
@ -1947,15 +1946,15 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
|
|||
ret = -ESHUTDOWN;
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"drop wmi command %d, hardware is wedged\n", cmd_id);
|
||||
} else {
|
||||
/* try to send pending beacons first. they take priority */
|
||||
ath10k_wmi_tx_beacons_nowait(ar);
|
||||
|
||||
ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);
|
||||
|
||||
if (ret && test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
|
||||
ret = -ESHUTDOWN;
|
||||
}
|
||||
/* try to send pending beacons first. they take priority */
|
||||
ath10k_wmi_tx_beacons_nowait(ar);
|
||||
|
||||
ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);
|
||||
|
||||
if (ret && test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
|
||||
ret = -ESHUTDOWN;
|
||||
|
||||
(ret != -EAGAIN);
|
||||
}), 3 * HZ);
|
||||
|
||||
|
|
|
|||
|
|
@ -1761,6 +1761,7 @@ static int ath11k_dp_rx_msdu_coalesce(struct ath11k *ar,
|
|||
int buf_first_hdr_len, buf_first_len;
|
||||
struct hal_rx_desc *ldesc;
|
||||
int space_extra, rem_len, buf_len;
|
||||
bool is_continuation;
|
||||
u32 hal_rx_desc_sz = ar->ab->hw_params.hal_desc_sz;
|
||||
|
||||
/* As the msdu is spread across multiple rx buffers,
|
||||
|
|
@ -1810,7 +1811,8 @@ static int ath11k_dp_rx_msdu_coalesce(struct ath11k *ar,
|
|||
rem_len = msdu_len - buf_first_len;
|
||||
while ((skb = __skb_dequeue(msdu_list)) != NULL && rem_len > 0) {
|
||||
rxcb = ATH11K_SKB_RXCB(skb);
|
||||
if (rxcb->is_continuation)
|
||||
is_continuation = rxcb->is_continuation;
|
||||
if (is_continuation)
|
||||
buf_len = DP_RX_BUFFER_SIZE - hal_rx_desc_sz;
|
||||
else
|
||||
buf_len = rem_len;
|
||||
|
|
@ -1828,7 +1830,7 @@ static int ath11k_dp_rx_msdu_coalesce(struct ath11k *ar,
|
|||
dev_kfree_skb_any(skb);
|
||||
|
||||
rem_len -= buf_len;
|
||||
if (!rxcb->is_continuation)
|
||||
if (!is_continuation)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -2214,8 +2216,7 @@ ath11k_dp_rx_h_find_peer(struct ath11k_base *ab, struct sk_buff *msdu)
|
|||
|
||||
lockdep_assert_held(&ab->base_lock);
|
||||
|
||||
if (rxcb->peer_id)
|
||||
peer = ath11k_peer_find_by_id(ab, rxcb->peer_id);
|
||||
peer = ath11k_peer_find_by_id(ab, rxcb->peer_id);
|
||||
|
||||
if (peer)
|
||||
return peer;
|
||||
|
|
|
|||
|
|
@ -1387,14 +1387,22 @@ EXPORT_SYMBOL(ath11k_hal_srng_deinit);
|
|||
|
||||
void ath11k_hal_srng_clear(struct ath11k_base *ab)
|
||||
{
|
||||
/* No need to memset rdp and wrp memory since each individual
|
||||
* segment would get cleared in ath11k_hal_srng_src_hw_init()
|
||||
* and ath11k_hal_srng_dst_hw_init().
|
||||
/*
|
||||
* Preserve the shared pointer buffers, but clear the previous
|
||||
* firmware instance's hp/tp state before handing them back to FW.
|
||||
* LMAC rings reuse this shared memory without going through the
|
||||
* normal SRNG hw-init path that zeros non-LMAC ring pointers.
|
||||
*/
|
||||
memset(ab->hal.srng_list, 0,
|
||||
sizeof(ab->hal.srng_list));
|
||||
memset(ab->hal.shadow_reg_addr, 0,
|
||||
sizeof(ab->hal.shadow_reg_addr));
|
||||
if (ab->hal.rdp.vaddr)
|
||||
memset(ab->hal.rdp.vaddr, 0,
|
||||
sizeof(*ab->hal.rdp.vaddr) * HAL_SRNG_RING_ID_MAX);
|
||||
if (ab->hal.wrp.vaddr)
|
||||
memset(ab->hal.wrp.vaddr, 0,
|
||||
sizeof(*ab->hal.wrp.vaddr) * HAL_SRNG_NUM_LMAC_RINGS);
|
||||
ab->hal.avail_blk_resource = 0;
|
||||
ab->hal.current_blk_index = 0;
|
||||
ab->hal.num_shadow_reg_configured = 0;
|
||||
|
|
|
|||
|
|
@ -1467,11 +1467,8 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
|
|||
case HAL_RX_MPDU_START: {
|
||||
struct hal_rx_mpdu_info *mpdu_info =
|
||||
(struct hal_rx_mpdu_info *)tlv_data;
|
||||
u16 peer_id;
|
||||
|
||||
peer_id = ath11k_hal_rx_mpduinfo_get_peerid(ab, mpdu_info);
|
||||
if (peer_id)
|
||||
ppdu_info->peer_id = peer_id;
|
||||
ppdu_info->peer_id = ath11k_hal_rx_mpduinfo_get_peerid(ab, mpdu_info);
|
||||
break;
|
||||
}
|
||||
case HAL_RXPCU_PPDU_END_INFO: {
|
||||
|
|
|
|||
|
|
@ -457,6 +457,7 @@ static int ath11k_tm_cmd_wmi_ftm(struct ath11k *ar, struct nlattr *tb[])
|
|||
ret = ath11k_wmi_cmd_send(wmi, skb, cmd_id);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send wmi ftm command: %d\n", ret);
|
||||
dev_kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9299,7 +9299,7 @@ int ath11k_wmi_hw_data_filter_cmd(struct ath11k *ar, u32 vdev_id,
|
|||
{
|
||||
struct wmi_hw_data_filter_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
|
|
@ -9324,7 +9324,13 @@ int ath11k_wmi_hw_data_filter_cmd(struct ath11k *ar, u32 vdev_id,
|
|||
"hw data filter enable %d filter_bitmap 0x%x\n",
|
||||
enable, filter_bitmap);
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_HW_DATA_FILTER_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar)
|
||||
|
|
@ -9332,6 +9338,7 @@ int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar)
|
|||
struct wmi_wow_host_wakeup_ind *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
|
|
@ -9345,14 +9352,20 @@ int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar)
|
|||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow host wakeup ind\n");
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_wow_enable(struct ath11k *ar)
|
||||
{
|
||||
struct wmi_wow_enable_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
|
|
@ -9367,7 +9380,13 @@ int ath11k_wmi_wow_enable(struct ath11k *ar)
|
|||
cmd->pause_iface_config = WOW_IFACE_PAUSE_ENABLED;
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow enable\n");
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_WOW_ENABLE_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar,
|
||||
|
|
@ -9376,7 +9395,7 @@ int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar,
|
|||
struct sk_buff *skb;
|
||||
struct wmi_scan_prob_req_oui_cmd *cmd;
|
||||
u32 prob_req_oui;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
prob_req_oui = (((u32)mac_addr[0]) << 16) |
|
||||
(((u32)mac_addr[1]) << 8) | mac_addr[2];
|
||||
|
|
@ -9395,7 +9414,13 @@ int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar,
|
|||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "scan prob req oui %d\n",
|
||||
prob_req_oui);
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SCAN_PROB_REQ_OUI_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SCAN_PROB_REQ_OUI_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_SCAN_PROB_REQ_OUI_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_wow_add_wakeup_event(struct ath11k *ar, u32 vdev_id,
|
||||
|
|
@ -9405,6 +9430,7 @@ int ath11k_wmi_wow_add_wakeup_event(struct ath11k *ar, u32 vdev_id,
|
|||
struct wmi_wow_add_del_event_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
|
|
@ -9422,7 +9448,13 @@ int ath11k_wmi_wow_add_wakeup_event(struct ath11k *ar, u32 vdev_id,
|
|||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow add wakeup event %s enable %d vdev_id %d\n",
|
||||
wow_wakeup_event(event), enable, vdev_id);
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_wow_add_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id,
|
||||
|
|
@ -9435,6 +9467,7 @@ int ath11k_wmi_wow_add_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id,
|
|||
struct sk_buff *skb;
|
||||
u8 *ptr;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd) +
|
||||
sizeof(*tlv) + /* array struct */
|
||||
|
|
@ -9527,7 +9560,13 @@ int ath11k_wmi_wow_add_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id,
|
|||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow add pattern vdev_id %d pattern_id %d pattern_offset %d\n",
|
||||
vdev_id, pattern_id, pattern_offset);
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_WOW_ADD_WAKE_PATTERN_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_wow_del_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id)
|
||||
|
|
@ -9535,6 +9574,7 @@ int ath11k_wmi_wow_del_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id)
|
|||
struct wmi_wow_del_pattern_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
|
|
@ -9553,7 +9593,13 @@ int ath11k_wmi_wow_del_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id)
|
|||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow del pattern vdev_id %d pattern_id %d\n",
|
||||
vdev_id, pattern_id);
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_WOW_DEL_WAKE_PATTERN_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
|
|
@ -9697,6 +9743,7 @@ int ath11k_wmi_wow_config_pno(struct ath11k *ar, u32 vdev_id,
|
|||
struct wmi_pno_scan_req *pno_scan)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
if (pno_scan->enable)
|
||||
skb = ath11k_wmi_op_gen_config_pno_start(ar, vdev_id, pno_scan);
|
||||
|
|
@ -9706,7 +9753,13 @@ int ath11k_wmi_wow_config_pno(struct ath11k *ar, u32 vdev_id,
|
|||
if (IS_ERR_OR_NULL(skb))
|
||||
return -ENOMEM;
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_wmi_fill_ns_offload(struct ath11k *ar,
|
||||
|
|
@ -9824,6 +9877,7 @@ int ath11k_wmi_arp_ns_offload(struct ath11k *ar,
|
|||
u8 *buf_ptr;
|
||||
size_t len;
|
||||
u8 ns_cnt, ns_ext_tuples = 0;
|
||||
int ret;
|
||||
|
||||
offload = &arvif->arp_ns_offload;
|
||||
ns_cnt = offload->ipv6_count;
|
||||
|
|
@ -9862,7 +9916,13 @@ int ath11k_wmi_arp_ns_offload(struct ath11k *ar,
|
|||
if (ns_ext_tuples)
|
||||
ath11k_wmi_fill_ns_offload(ar, offload, &buf_ptr, enable, 1);
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_SET_ARP_NS_OFFLOAD_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_gtk_rekey_offload(struct ath11k *ar,
|
||||
|
|
@ -9870,7 +9930,7 @@ int ath11k_wmi_gtk_rekey_offload(struct ath11k *ar,
|
|||
{
|
||||
struct wmi_gtk_rekey_offload_cmd *cmd;
|
||||
struct ath11k_rekey_data *rekey_data = &arvif->rekey_data;
|
||||
int len;
|
||||
int ret, len;
|
||||
struct sk_buff *skb;
|
||||
__le64 replay_ctr;
|
||||
|
||||
|
|
@ -9904,14 +9964,20 @@ int ath11k_wmi_gtk_rekey_offload(struct ath11k *ar,
|
|||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "offload gtk rekey vdev: %d %d\n",
|
||||
arvif->vdev_id, enable);
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_GTK_OFFLOAD_CMDID offload\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_gtk_rekey_getinfo(struct ath11k *ar,
|
||||
struct ath11k_vif *arvif)
|
||||
{
|
||||
struct wmi_gtk_rekey_offload_cmd *cmd;
|
||||
int len;
|
||||
int ret, len;
|
||||
struct sk_buff *skb;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
|
|
@ -9928,7 +9994,13 @@ int ath11k_wmi_gtk_rekey_getinfo(struct ath11k *ar,
|
|||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "get gtk rekey vdev_id: %d\n",
|
||||
arvif->vdev_id);
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_GTK_OFFLOAD_CMDID getinfo\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_pdev_set_bios_sar_table_param(struct ath11k *ar, const u8 *sar_val)
|
||||
|
|
@ -9938,6 +10010,7 @@ int ath11k_wmi_pdev_set_bios_sar_table_param(struct ath11k *ar, const u8 *sar_va
|
|||
struct sk_buff *skb;
|
||||
u8 *buf_ptr;
|
||||
u32 len, sar_len_aligned, rsvd_len_aligned;
|
||||
int ret;
|
||||
|
||||
sar_len_aligned = roundup(BIOS_SAR_TABLE_LEN, sizeof(u32));
|
||||
rsvd_len_aligned = roundup(BIOS_SAR_RSVD1_LEN, sizeof(u32));
|
||||
|
|
@ -9968,7 +10041,13 @@ int ath11k_wmi_pdev_set_bios_sar_table_param(struct ath11k *ar, const u8 *sar_va
|
|||
tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) |
|
||||
FIELD_PREP(WMI_TLV_LEN, rsvd_len_aligned);
|
||||
|
||||
return ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_BIOS_SAR_TABLE_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_BIOS_SAR_TABLE_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_PDEV_SET_BIOS_SAR_TABLE_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar)
|
||||
|
|
@ -9979,6 +10058,7 @@ int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar)
|
|||
struct sk_buff *skb;
|
||||
u8 *buf_ptr;
|
||||
u32 len, rsvd_len_aligned;
|
||||
int ret;
|
||||
|
||||
rsvd_len_aligned = roundup(BIOS_SAR_RSVD2_LEN, sizeof(u32));
|
||||
len = sizeof(*cmd) + TLV_HDR_SIZE + rsvd_len_aligned;
|
||||
|
|
@ -9998,7 +10078,13 @@ int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar)
|
|||
tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) |
|
||||
FIELD_PREP(WMI_TLV_LEN, rsvd_len_aligned);
|
||||
|
||||
return ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_sta_keepalive(struct ath11k *ar,
|
||||
|
|
@ -10009,6 +10095,7 @@ int ath11k_wmi_sta_keepalive(struct ath11k *ar,
|
|||
struct wmi_sta_keepalive_arp_resp *arp;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd) + sizeof(*arp);
|
||||
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
|
||||
|
|
@ -10040,7 +10127,13 @@ int ath11k_wmi_sta_keepalive(struct ath11k *ar,
|
|||
"sta keepalive vdev %d enabled %d method %d interval %d\n",
|
||||
arg->vdev_id, arg->enabled, arg->method, arg->interval);
|
||||
|
||||
return ath11k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_STA_KEEPALIVE_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ath11k_wmi_supports_6ghz_cc_ext(struct ath11k *ar)
|
||||
|
|
|
|||
|
|
@ -3446,7 +3446,9 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
|
|||
arg->peer_eht_mcs_count++;
|
||||
fallthrough;
|
||||
default:
|
||||
if (!(link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
|
||||
if ((vif->type == NL80211_IFTYPE_AP ||
|
||||
vif->type == NL80211_IFTYPE_MESH_POINT) &&
|
||||
!(link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
|
||||
bw_20 = &eht_cap->eht_mcs_nss_supp.only_20mhz;
|
||||
|
||||
|
|
@ -3475,7 +3477,9 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
|
|||
arg->punct_bitmap = ~arvif->punct_bitmap;
|
||||
arg->eht_disable_mcs15 = link_conf->eht_disable_mcs15;
|
||||
|
||||
if (!(link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
|
||||
if ((vif->type == NL80211_IFTYPE_AP ||
|
||||
vif->type == NL80211_IFTYPE_MESH_POINT) &&
|
||||
!(link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
|
||||
if (bw_20->rx_tx_mcs13_max_nss)
|
||||
max_nss = max(max_nss, u8_get_bits(bw_20->rx_tx_mcs13_max_nss,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2024-2026 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_constants_h__
|
||||
#define __iwl_mld_constants_h__
|
||||
|
||||
#define IWL_MLD_MISSED_BEACONS_SINCE_RX_THOLD 4
|
||||
#define IWL_MLD_MISSED_BEACONS_SINCE_RX_THOLD 6
|
||||
#define IWL_MLD_MISSED_BEACONS_THRESHOLD 8
|
||||
#define IWL_MLD_MISSED_BEACONS_THRESHOLD_LONG 19
|
||||
#define IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS 5
|
||||
|
|
|
|||
|
|
@ -1930,12 +1930,12 @@ int iwl_mld_wowlan_suspend(struct iwl_mld *mld, struct cfg80211_wowlan *wowlan)
|
|||
if (WARN_ON(!wowlan))
|
||||
return 1;
|
||||
|
||||
IWL_DEBUG_WOWLAN(mld, "Starting the wowlan suspend flow\n");
|
||||
|
||||
bss_vif = iwl_mld_get_bss_vif(mld);
|
||||
if (WARN_ON(!bss_vif))
|
||||
if (!bss_vif)
|
||||
return 1;
|
||||
|
||||
IWL_DEBUG_WOWLAN(mld, "Starting the wowlan suspend flow\n");
|
||||
|
||||
if (!bss_vif->cfg.assoc) {
|
||||
int ret;
|
||||
/* If we're not associated, this must be netdetect */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2024-2026 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "constants.h"
|
||||
|
|
@ -504,7 +504,6 @@ void iwl_mld_remove_link(struct iwl_mld *mld,
|
|||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(bss_conf->vif);
|
||||
struct iwl_mld_link *link = iwl_mld_link_from_mac80211(bss_conf);
|
||||
bool is_deflink = link == &mld_vif->deflink;
|
||||
u8 fw_id = link->fw_id;
|
||||
|
||||
if (WARN_ON(!link || link->active))
|
||||
return;
|
||||
|
|
@ -512,15 +511,15 @@ void iwl_mld_remove_link(struct iwl_mld *mld,
|
|||
iwl_mld_rm_link_from_fw(mld, bss_conf);
|
||||
/* Continue cleanup on failure */
|
||||
|
||||
if (!is_deflink)
|
||||
kfree_rcu(link, rcu_head);
|
||||
|
||||
RCU_INIT_POINTER(mld_vif->link[bss_conf->link_id], NULL);
|
||||
|
||||
if (WARN_ON(fw_id >= mld->fw->ucode_capa.num_links))
|
||||
if (WARN_ON(link->fw_id >= mld->fw->ucode_capa.num_links))
|
||||
return;
|
||||
|
||||
RCU_INIT_POINTER(mld->fw_id_to_bss_conf[fw_id], NULL);
|
||||
RCU_INIT_POINTER(mld->fw_id_to_bss_conf[link->fw_id], NULL);
|
||||
|
||||
if (!is_deflink)
|
||||
kfree_rcu(link, rcu_head);
|
||||
}
|
||||
|
||||
void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
|
||||
|
|
|
|||
|
|
@ -834,7 +834,7 @@ static int iwl_mld_tx_tso_segment(struct iwl_mld *mld, struct sk_buff *skb,
|
|||
return -EINVAL;
|
||||
|
||||
max_tid_amsdu_len = sta->cur->max_tid_amsdu_len[tid];
|
||||
if (!max_tid_amsdu_len)
|
||||
if (!max_tid_amsdu_len || max_tid_amsdu_len == 1)
|
||||
return iwl_tx_tso_segment(skb, 1, netdev_flags, mpdus_skbs);
|
||||
|
||||
/* Sub frame header + SNAP + IP header + TCP header + MSS */
|
||||
|
|
@ -846,6 +846,9 @@ static int iwl_mld_tx_tso_segment(struct iwl_mld *mld, struct sk_buff *skb,
|
|||
*/
|
||||
num_subframes = (max_tid_amsdu_len + pad) / (subf_len + pad);
|
||||
|
||||
if (WARN_ON_ONCE(!num_subframes))
|
||||
return iwl_tx_tso_segment(skb, 1, netdev_flags, mpdus_skbs);
|
||||
|
||||
if (sta->max_amsdu_subframes &&
|
||||
num_subframes > sta->max_amsdu_subframes)
|
||||
num_subframes = sta->max_amsdu_subframes;
|
||||
|
|
@ -970,6 +973,16 @@ void iwl_mld_tx_from_txq(struct iwl_mld *mld, struct ieee80211_txq *txq)
|
|||
struct sk_buff *skb = NULL;
|
||||
u8 zero_addr[ETH_ALEN] = {};
|
||||
|
||||
/*
|
||||
* Don't transmit during firmware restart. The firmware is dead,
|
||||
* so iwl_trans_tx() would return -EIO for each frame. Avoid the
|
||||
* overhead of dequeuing from mac80211 only to immediately free
|
||||
* the skbs, and the potential memory pressure from rapid skb
|
||||
* allocation churn during high-throughput restart scenarios.
|
||||
*/
|
||||
if (unlikely(mld->fw_status.in_hw_restart))
|
||||
return;
|
||||
|
||||
/*
|
||||
* No need for threads to be pending here, they can leave the first
|
||||
* taker all the work.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2026 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -927,13 +927,18 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
|
|||
|
||||
u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx)
|
||||
{
|
||||
u16 flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
|
||||
bool is_new_rate = iwl_fw_lookup_cmd_ver(fw, BEACON_TEMPLATE_CMD, 0) > 10;
|
||||
u16 flags = 0;
|
||||
|
||||
if (rate_idx <= IWL_LAST_CCK_RATE)
|
||||
flags |= is_new_rate ? IWL_MAC_BEACON_CCK
|
||||
: IWL_MAC_BEACON_CCK_V1;
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(fw, TX_CMD, 0) > 8)
|
||||
flags |= iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
|
||||
else
|
||||
flags |= iwl_fw_rate_idx_to_plcp(rate_idx);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
|
@ -962,6 +967,7 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
|
|||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct ieee80211_tx_info *info;
|
||||
u32 rate_n_flags = 0;
|
||||
u8 rate;
|
||||
u32 tx_flags;
|
||||
|
||||
|
|
@ -981,18 +987,21 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
|
|||
IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION)) {
|
||||
iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx);
|
||||
|
||||
tx_params->rate_n_flags =
|
||||
cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
|
||||
RATE_MCS_ANT_POS);
|
||||
rate_n_flags |= BIT(mvm->mgmt_last_antenna_idx) <<
|
||||
RATE_MCS_ANT_POS;
|
||||
}
|
||||
|
||||
rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
|
||||
|
||||
tx_params->rate_n_flags |=
|
||||
cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate));
|
||||
if (rate == IWL_FIRST_CCK_RATE)
|
||||
tx_params->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1);
|
||||
if (rate < IWL_FIRST_OFDM_RATE)
|
||||
rate_n_flags |= RATE_MCS_MOD_TYPE_CCK;
|
||||
else
|
||||
rate_n_flags |= RATE_MCS_MOD_TYPE_LEGACY_OFDM;
|
||||
|
||||
rate_n_flags |= iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate);
|
||||
|
||||
tx_params->rate_n_flags = iwl_mvm_v3_rate_to_fw(rate_n_flags,
|
||||
mvm->fw_rates_ver);
|
||||
}
|
||||
|
||||
int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2026 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -159,15 +159,9 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
|
|||
|
||||
u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx)
|
||||
{
|
||||
if (iwl_fw_lookup_cmd_ver(fw, TX_CMD, 0) > 8)
|
||||
/* In the new rate legacy rates are indexed:
|
||||
* 0 - 3 for CCK and 0 - 7 for OFDM.
|
||||
*/
|
||||
return (rate_idx >= IWL_FIRST_OFDM_RATE ?
|
||||
rate_idx - IWL_FIRST_OFDM_RATE :
|
||||
rate_idx);
|
||||
|
||||
return iwl_fw_rate_idx_to_plcp(rate_idx);
|
||||
return rate_idx >= IWL_FIRST_OFDM_RATE ?
|
||||
rate_idx - IWL_FIRST_OFDM_RATE :
|
||||
rate_idx;
|
||||
}
|
||||
|
||||
u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac)
|
||||
|
|
|
|||
|
|
@ -398,9 +398,9 @@ void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans)
|
|||
mutex_unlock(&trans_pcie->mutex);
|
||||
|
||||
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
|
||||
trans->step_urm = !!(iwl_read_umac_prph(trans,
|
||||
CNVI_PMU_STEP_FLOW) &
|
||||
CNVI_PMU_STEP_FLOW_FORCE_URM);
|
||||
trans->step_urm = !!(iwl_read_prph(trans,
|
||||
CNVI_PMU_STEP_FLOW) &
|
||||
CNVI_PMU_STEP_FLOW_FORCE_URM);
|
||||
}
|
||||
|
||||
static bool iwl_pcie_set_ltr(struct iwl_trans *trans)
|
||||
|
|
|
|||
|
|
@ -1265,7 +1265,7 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
|
|||
|
||||
ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto fail;
|
||||
|
||||
wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®);
|
||||
reg &= ~BIT(10);
|
||||
|
|
|
|||
|
|
@ -2344,8 +2344,9 @@ static int sta_apply_parameters(struct ieee80211_local *local,
|
|||
sta->sta.max_sp = params->max_sp;
|
||||
}
|
||||
|
||||
ieee80211_sta_set_max_amsdu_subframes(sta, params->ext_capab,
|
||||
params->ext_capab_len);
|
||||
if (params->ext_capab)
|
||||
ieee80211_sta_set_max_amsdu_subframes(sta, params->ext_capab,
|
||||
params->ext_capab_len);
|
||||
|
||||
/*
|
||||
* cfg80211 validates this (1-2007) and allows setting the AID
|
||||
|
|
|
|||
|
|
@ -8164,6 +8164,7 @@ ieee80211_parse_neg_ttlm(struct ieee80211_sub_if_data *sdata,
|
|||
"No active links for TID %d", tid);
|
||||
return -EINVAL;
|
||||
}
|
||||
pos += map_size;
|
||||
} else {
|
||||
map = 0;
|
||||
}
|
||||
|
|
@ -8182,7 +8183,6 @@ ieee80211_parse_neg_ttlm(struct ieee80211_sub_if_data *sdata,
|
|||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
pos += map_size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -11232,6 +11232,9 @@ static void ieee80211_ml_epcs(struct ieee80211_sub_if_data *sdata,
|
|||
control = get_unaligned_le16(pos);
|
||||
link_id = control & IEEE80211_MLE_STA_EPCS_CONTROL_LINK_ID;
|
||||
|
||||
if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
|
||||
continue;
|
||||
|
||||
link = sdata_dereference(sdata->link[link_id], sdata);
|
||||
if (!link)
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,22 @@
|
|||
#include "led.h"
|
||||
#include "wep.h"
|
||||
|
||||
static const u8 empty_non_inheritance[] = {
|
||||
WLAN_EID_EXTENSION, 1, WLAN_EID_EXT_NON_INHERITANCE,
|
||||
/*
|
||||
* cfg80211_is_element_inherited() hardcodes elements that
|
||||
* cannot be inherited, so we just need an empty one to be
|
||||
* calling it at all.
|
||||
*/
|
||||
};
|
||||
|
||||
struct ieee80211_elem_defrag {
|
||||
const struct element *elem;
|
||||
/* container start/len */
|
||||
const u8 *start;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
struct ieee80211_elems_parse {
|
||||
/* must be first for kfree to work */
|
||||
struct ieee802_11_elems elems;
|
||||
|
|
@ -41,11 +57,7 @@ struct ieee80211_elems_parse {
|
|||
/* The basic Multi-Link element in the original elements */
|
||||
const struct element *ml_basic_elem;
|
||||
|
||||
/* The reconfiguration Multi-Link element in the original elements */
|
||||
const struct element *ml_reconf_elem;
|
||||
|
||||
/* The EPCS Multi-Link element in the original elements */
|
||||
const struct element *ml_epcs_elem;
|
||||
struct ieee80211_elem_defrag ml_reconf, ml_epcs;
|
||||
|
||||
bool multi_link_inner;
|
||||
bool skip_vendor;
|
||||
|
|
@ -162,10 +174,14 @@ ieee80211_parse_extension_element(u32 *crc,
|
|||
}
|
||||
break;
|
||||
case IEEE80211_ML_CONTROL_TYPE_RECONF:
|
||||
elems_parse->ml_reconf_elem = elem;
|
||||
elems_parse->ml_reconf.elem = elem;
|
||||
elems_parse->ml_reconf.start = params->start;
|
||||
elems_parse->ml_reconf.len = params->len;
|
||||
break;
|
||||
case IEEE80211_ML_CONTROL_TYPE_PRIO_ACCESS:
|
||||
elems_parse->ml_epcs_elem = elem;
|
||||
elems_parse->ml_epcs.elem = elem;
|
||||
elems_parse->ml_epcs.start = params->start;
|
||||
elems_parse->ml_epcs.len = params->len;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -916,7 +932,7 @@ ieee80211_prep_mle_link_parse(struct ieee80211_elems_parse *elems_parse,
|
|||
{
|
||||
struct ieee802_11_elems *elems = &elems_parse->elems;
|
||||
struct ieee80211_mle_per_sta_profile *prof;
|
||||
const struct element *tmp;
|
||||
const struct element *tmp, *ret;
|
||||
ssize_t ml_len;
|
||||
const u8 *end;
|
||||
|
||||
|
|
@ -986,50 +1002,40 @@ ieee80211_prep_mle_link_parse(struct ieee80211_elems_parse *elems_parse,
|
|||
sub->from_ap = params->from_ap;
|
||||
sub->link_id = -1;
|
||||
|
||||
return cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
|
||||
sub->start, sub->len);
|
||||
ret = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
|
||||
sub->start, sub->len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Since we know we want and found a profile, apply an empty
|
||||
* non-inheritance if the profile didn't have one, so that any
|
||||
* element that shouldn't be inherited by spec isn't.
|
||||
*/
|
||||
return (const void *)empty_non_inheritance;
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211_mle_defrag_reconf(struct ieee80211_elems_parse *elems_parse)
|
||||
static const void *
|
||||
ieee80211_mle_defrag(struct ieee80211_elems_parse *elems_parse,
|
||||
struct ieee80211_elem_defrag *defrag,
|
||||
size_t *out_len)
|
||||
{
|
||||
struct ieee802_11_elems *elems = &elems_parse->elems;
|
||||
const void *ret;
|
||||
ssize_t ml_len;
|
||||
|
||||
ml_len = cfg80211_defragment_element(elems_parse->ml_reconf_elem,
|
||||
elems->ie_start,
|
||||
elems->total_len,
|
||||
ml_len = cfg80211_defragment_element(defrag->elem,
|
||||
defrag->start, defrag->len,
|
||||
elems_parse->scratch_pos,
|
||||
elems_parse->scratch +
|
||||
elems_parse->scratch_len -
|
||||
elems_parse->scratch_pos,
|
||||
WLAN_EID_FRAGMENT);
|
||||
if (ml_len < 0)
|
||||
return;
|
||||
elems->ml_reconf = (void *)elems_parse->scratch_pos;
|
||||
elems->ml_reconf_len = ml_len;
|
||||
elems_parse->scratch_pos += ml_len;
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211_mle_defrag_epcs(struct ieee80211_elems_parse *elems_parse)
|
||||
{
|
||||
struct ieee802_11_elems *elems = &elems_parse->elems;
|
||||
ssize_t ml_len;
|
||||
|
||||
ml_len = cfg80211_defragment_element(elems_parse->ml_epcs_elem,
|
||||
elems->ie_start,
|
||||
elems->total_len,
|
||||
elems_parse->scratch_pos,
|
||||
elems_parse->scratch +
|
||||
elems_parse->scratch_len -
|
||||
elems_parse->scratch_pos,
|
||||
WLAN_EID_FRAGMENT);
|
||||
if (ml_len < 0)
|
||||
return;
|
||||
elems->ml_epcs = (void *)elems_parse->scratch_pos;
|
||||
elems->ml_epcs_len = ml_len;
|
||||
return NULL;
|
||||
ret = elems_parse->scratch_pos;
|
||||
*out_len = ml_len;
|
||||
elems_parse->scratch_pos += ml_len;
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct ieee802_11_elems *
|
||||
|
|
@ -1042,6 +1048,7 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
|
|||
size_t scratch_len = 3 * params->len;
|
||||
bool multi_link_inner = false;
|
||||
|
||||
BUILD_BUG_ON(sizeof(empty_non_inheritance) != empty_non_inheritance[1] + 2);
|
||||
BUILD_BUG_ON(offsetof(typeof(*elems_parse), elems) != 0);
|
||||
|
||||
/* cannot parse for both a specific link and non-transmitted BSS */
|
||||
|
|
@ -1089,6 +1096,17 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
|
|||
|
||||
non_inherit = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
|
||||
sub.start, nontx_len);
|
||||
/*
|
||||
* If it's a non-transmitted BSS, we shouldn't pick
|
||||
* any elements in the outer parsing that shouldn't
|
||||
* be inherited. If the profile has a non-inheritance
|
||||
* element this automatically happens, but if not then
|
||||
* provide an empty one so that the hard-coded elements
|
||||
* in cfg80211_is_element_inherited() are ignored, but
|
||||
* it must be called.
|
||||
*/
|
||||
if (params->bss->transmitted_bss && !non_inherit)
|
||||
non_inherit = (const void *)empty_non_inheritance;
|
||||
} else {
|
||||
/* must always parse to get elems_parse->ml_basic_elem */
|
||||
non_inherit = ieee80211_prep_mle_link_parse(elems_parse, params,
|
||||
|
|
@ -1109,9 +1127,12 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
|
|||
_ieee802_11_parse_elems_full(&sub, elems_parse, NULL);
|
||||
}
|
||||
|
||||
ieee80211_mle_defrag_reconf(elems_parse);
|
||||
|
||||
ieee80211_mle_defrag_epcs(elems_parse);
|
||||
elems->ml_reconf = ieee80211_mle_defrag(elems_parse,
|
||||
&elems_parse->ml_reconf,
|
||||
&elems->ml_reconf_len);
|
||||
elems->ml_epcs = ieee80211_mle_defrag(elems_parse,
|
||||
&elems_parse->ml_epcs,
|
||||
&elems->ml_epcs_len);
|
||||
|
||||
if (elems->tim && !elems->parse_error) {
|
||||
const struct ieee80211_tim_ie *tim_ie = elems->tim;
|
||||
|
|
|
|||
|
|
@ -4984,6 +4984,7 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
|
|||
u8 sa[ETH_ALEN];
|
||||
} addrs __aligned(2);
|
||||
struct ieee80211_sta_rx_stats *stats;
|
||||
u32 encoded_rate;
|
||||
|
||||
/* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write
|
||||
* to a common data structure; drivers can implement that per queue
|
||||
|
|
@ -5091,11 +5092,14 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
|
|||
/* push the addresses in front */
|
||||
memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs));
|
||||
|
||||
/* capture before mesh forward may memset or free skb->cb */
|
||||
encoded_rate = sta_stats_encode_rate(status);
|
||||
|
||||
res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
|
||||
switch (res) {
|
||||
case RX_QUEUED:
|
||||
stats->last_rx = jiffies;
|
||||
stats->last_rate = sta_stats_encode_rate(status);
|
||||
stats->last_rate = encoded_rate;
|
||||
return true;
|
||||
case RX_CONTINUE:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -2462,6 +2462,9 @@ size_t cfg80211_merge_profile(const u8 *ie, size_t ielen,
|
|||
memcpy(merged_ie + copied_len, next_sub->data,
|
||||
next_sub->datalen);
|
||||
copied_len += next_sub->datalen;
|
||||
|
||||
mbssid_elem = next_mbssid;
|
||||
sub_elem = next_sub;
|
||||
}
|
||||
|
||||
return copied_len;
|
||||
|
|
|
|||
|
|
@ -789,6 +789,8 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
|
|||
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
|
||||
if (!chandef.chan)
|
||||
return -EINVAL;
|
||||
if (!cfg80211_chandef_valid(&chandef))
|
||||
return -EINVAL;
|
||||
return cfg80211_set_monitor_channel(rdev, dev, &chandef);
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
freq = cfg80211_wext_freq(wextfreq);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user