ath.git update for v6.17-rc5

Fix a long-standing issue with ath11k dropping group data packets
 during GTK rekey, and fix an omission in the ath12k multi-link EMLSR
 support introduced in v6.16.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQQ/mtSHzPUi16IfDEksFbugiYzLewUCaLeIKwAKCRAsFbugiYzL
 e4fPAP9JDoYJG5G/2/8dEvyQyCYzqkhzaqwCxV4wfUA+igwUugD8C8El/qu2TOxY
 /0ZPJ9AR86csDmEjQ38oG8elQzSOQQA=
 =scAW
 -----END PGP SIGNATURE-----

Merge tag 'ath-current-20250902' of git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath

Jeff Johnson says:
==================
ath.git update for v6.17-rc5

Fix a long-standing issue with ath11k dropping group data packets
during GTK rekey, and fix an omission in the ath12k multi-link EMLSR
support introduced in v6.16.
==================

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2025-09-03 09:40:04 +02:00
commit 27893dd634
3 changed files with 105 additions and 9 deletions

View File

@ -411,6 +411,8 @@ struct ath11k_vif {
bool do_not_send_tmpl;
struct ath11k_arp_ns_offload arp_ns_offload;
struct ath11k_rekey_data rekey_data;
u32 num_stations;
bool reinstall_group_keys;
struct ath11k_reg_tpc_power_info reg_tpc_info;

View File

@ -4317,6 +4317,40 @@ static int ath11k_clear_peer_keys(struct ath11k_vif *arvif,
return first_errno;
}
static int ath11k_set_group_keys(struct ath11k_vif *arvif)
{
struct ath11k *ar = arvif->ar;
struct ath11k_base *ab = ar->ab;
const u8 *addr = arvif->bssid;
int i, ret, first_errno = 0;
struct ath11k_peer *peer;
spin_lock_bh(&ab->base_lock);
peer = ath11k_peer_find(ab, arvif->vdev_id, addr);
spin_unlock_bh(&ab->base_lock);
if (!peer)
return -ENOENT;
for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
struct ieee80211_key_conf *key = peer->keys[i];
if (!key || (key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
continue;
ret = ath11k_install_key(arvif, key, SET_KEY, addr,
WMI_KEY_GROUP);
if (ret < 0 && first_errno == 0)
first_errno = ret;
if (ret < 0)
ath11k_warn(ab, "failed to set group key of idx %d for vdev %d: %d\n",
i, arvif->vdev_id, ret);
}
return first_errno;
}
static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
@ -4326,6 +4360,7 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
struct ath11k_peer *peer;
struct ath11k_sta *arsta;
bool is_ap_with_no_sta;
const u8 *peer_addr;
int ret = 0;
u32 flags = 0;
@ -4386,16 +4421,57 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
else
flags |= WMI_KEY_GROUP;
ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags);
if (ret) {
ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret);
goto exit;
}
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
"%s for peer %pM on vdev %d flags 0x%X, type = %d, num_sta %d\n",
cmd == SET_KEY ? "SET_KEY" : "DEL_KEY", peer_addr, arvif->vdev_id,
flags, arvif->vdev_type, arvif->num_stations);
ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
if (ret) {
ath11k_warn(ab, "failed to offload PN replay detection %d\n", ret);
goto exit;
/* Allow group key clearing only in AP mode when no stations are
* associated. There is a known race condition in firmware where
* group addressed packets may be dropped if the key is cleared
* and immediately set again during rekey.
*
* During GTK rekey, mac80211 issues a clear key (if the old key
* exists) followed by an install key operation for same key
* index. This causes ath11k to send two WMI commands in quick
* succession: one to clear the old key and another to install the
* new key in the same slot.
*
* Under certain conditionsespecially under high load or time
* sensitive scenarios, firmware may process these commands
* asynchronously in a way that firmware assumes the key is
* cleared whereas hardware has a valid key. This inconsistency
* between hardware and firmware leads to group addressed packet
* drops after rekey.
* Only setting the same key again can restore a valid key in
* firmware and allow packets to be transmitted.
*
* There is a use case where an AP can transition from Secure mode
* to open mode without a vdev restart by just deleting all
* associated peers and clearing key, Hence allow clear key for
* that case alone. Mark arvif->reinstall_group_keys in such cases
* and reinstall the same key when the first peer is added,
* allowing firmware to recover from the race if it had occurred.
*/
is_ap_with_no_sta = (vif->type == NL80211_IFTYPE_AP &&
!arvif->num_stations);
if ((flags & WMI_KEY_PAIRWISE) || cmd == SET_KEY || is_ap_with_no_sta) {
ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags);
if (ret) {
ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret);
goto exit;
}
ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
if (ret) {
ath11k_warn(ab, "failed to offload PN replay detection %d\n",
ret);
goto exit;
}
if ((flags & WMI_KEY_GROUP) && cmd == SET_KEY && is_ap_with_no_sta)
arvif->reinstall_group_keys = true;
}
spin_lock_bh(&ab->base_lock);
@ -4994,6 +5070,7 @@ static int ath11k_mac_inc_num_stations(struct ath11k_vif *arvif,
return -ENOBUFS;
ar->num_stations++;
arvif->num_stations++;
return 0;
}
@ -5009,6 +5086,7 @@ static void ath11k_mac_dec_num_stations(struct ath11k_vif *arvif,
return;
ar->num_stations--;
arvif->num_stations--;
}
static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar,
@ -9540,6 +9618,21 @@ static int ath11k_mac_station_add(struct ath11k *ar,
goto exit;
}
/* Driver allows the DEL KEY followed by SET KEY sequence for
* group keys for only when there is no clients associated, if at
* all firmware has entered the race during that window,
* reinstalling the same key when the first sta connects will allow
* firmware to recover from the race.
*/
if (arvif->num_stations == 1 && arvif->reinstall_group_keys) {
ath11k_dbg(ab, ATH11K_DBG_MAC, "set group keys on 1st station add for vdev %d\n",
arvif->vdev_id);
ret = ath11k_set_group_keys(arvif);
if (ret)
goto dec_num_station;
arvif->reinstall_group_keys = false;
}
arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);
if (!arsta->rx_stats) {
ret = -ENOMEM;

View File

@ -2423,6 +2423,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
eml_cap = arg->ml.eml_cap;
if (u16_get_bits(eml_cap, IEEE80211_EML_CAP_EMLSR_SUPP)) {
ml_params->flags |= cpu_to_le32(ATH12K_WMI_FLAG_MLO_EMLSR_SUPPORT);
/* Padding delay */
eml_pad_delay = ieee80211_emlsr_pad_delay_in_us(eml_cap);
ml_params->emlsr_padding_delay_us = cpu_to_le32(eml_pad_delay);