From 2e10edc741dfad8e0218113e4a719e972f5f2b97 Mon Sep 17 00:00:00 2001 From: Marek Kwaczynski Date: Thu, 27 Mar 2025 08:00:39 +0100 Subject: [PATCH] ipq807x_v5.4/mac80211: ath11k: fix peer addition/deletion error on sta band migration Fix removing rhash when station is roaming between radios and apply logic from opensource driver during adding/removing peer. Fixes: 7374c39d ("ath11k: fix STA roaming between radios") Fixes: WIFI-14457 Signed-off-by: Arif Alam Signed-off-by: Marek Kwaczynski --- .../a-001-fix-roaming-between-phys.patch | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 feeds/ipq807x_v5.4/mac80211/patches/pending/a-001-fix-roaming-between-phys.patch diff --git a/feeds/ipq807x_v5.4/mac80211/patches/pending/a-001-fix-roaming-between-phys.patch b/feeds/ipq807x_v5.4/mac80211/patches/pending/a-001-fix-roaming-between-phys.patch new file mode 100644 index 000000000..dba432a92 --- /dev/null +++ b/feeds/ipq807x_v5.4/mac80211/patches/pending/a-001-fix-roaming-between-phys.patch @@ -0,0 +1,116 @@ +Index: backports-20210222_001-5.4.164-b157d2276/drivers/net/wireless/ath/ath11k/peer.c +=================================================================== +--- backports-20210222_001-5.4.164-b157d2276.orig/drivers/net/wireless/ath/ath11k/peer.c ++++ backports-20210222_001-5.4.164-b157d2276/drivers/net/wireless/ath/ath11k/peer.c +@@ -789,8 +789,6 @@ int ath11k_peer_delete(struct ath11k *ar + #endif + lockdep_assert_held(&ar->conf_mutex); + +- reinit_completion(&ar->peer_delete_done); +- + ath11k_nss_peer_delete(ar->ab, vdev_id, addr); + #ifdef CCPTCFG_ATH11K_NSS_SUPPORTPTCFG_ATH11K_NSS_SUPPORT + mutex_lock(&ar->ab->base_ast_lock); +@@ -799,33 +797,60 @@ int ath11k_peer_delete(struct ath11k *ar + spin_lock_bh(&ar->ab->base_lock); + + peer = ath11k_peer_find_by_addr(ar->ab, addr); +- if (peer) { ++ /* Check if the found peer is what we want to remove. ++ * While the sta is transitioning to another band we may ++ * have 2 peer with the same addr assigned to different ++ * vdev_id. Make sure we are deleting the correct peer. ++ */ ++ if (peer && peer->vdev_id == vdev_id) ++ ath11k_peer_rhash_delete(ar->ab, peer); ++ ++ /* Fallback to peer list search if the correct peer can't be found. ++ * Skip the deletion of the peer from the rhash since it has already ++ * been deleted in peer add. ++ */ ++ if (!peer) ++ peer = ath11k_peer_find(ar->ab, vdev_id, addr); ++ ++ ++ if (!peer) { ++ spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ar->ab->tbl_mtx_lock); + #ifdef CPTCFG_ATH11K_NSS_SUPPORT +- peer->delete_in_progress = true; +- if (peer->self_ast_entry) { +- ath11k_peer_del_ast(ar, peer->self_ast_entry); +- peer->self_ast_entry = NULL; +- } ++ mutex_unlock(&ar->ab->base_ast_lock); ++#endif ++ ath11k_warn(ar->ab, ++ "failed to find peer vdev_id %d addr %pM in delete\n", ++ vdev_id, addr); ++ return -EINVAL; ++ } ++ ++#ifdef CPTCFG_ATH11K_NSS_SUPPORT ++ peer->delete_in_progress = true; ++ if (peer->self_ast_entry) { ++ ath11k_peer_del_ast(ar, peer->self_ast_entry); ++ peer->self_ast_entry = NULL; ++ } + +- list_for_each_entry_safe(ast_entry, tmp_ast, +- &peer->ast_entry_list, ase_list) +- if ((ast_entry->type == ATH11K_AST_TYPE_WDS) || +- (ast_entry->type == ATH11K_AST_TYPE_MEC)) { +- if (!list_empty(&ast_entry->wmi_list)) { +- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, +- "%s deleting unprocessed ast entry %pM of peer %pM from wmi list\n", +- __func__, ast_entry->addr, addr); +- list_del_init(&ast_entry->wmi_list); +- } ++ list_for_each_entry_safe(ast_entry, tmp_ast, ++ &peer->ast_entry_list, ase_list) ++ if ((ast_entry->type == ATH11K_AST_TYPE_WDS) || ++ (ast_entry->type == ATH11K_AST_TYPE_MEC)) { ++ if (!list_empty(&ast_entry->wmi_list)) { ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, ++ "%s deleting unprocessed ast entry %pM of peer %pM from wmi list\n", ++ __func__, ast_entry->addr, addr); ++ list_del_init(&ast_entry->wmi_list); + } ++ } + #endif +- ath11k_peer_rhash_delete(ar->ab, peer); +- } + spin_unlock_bh(&ar->ab->base_lock); + mutex_unlock(&ar->ab->tbl_mtx_lock); + #ifdef CPTCFG_ATH11K_NSS_SUPPORT + mutex_unlock(&ar->ab->base_ast_lock); + #endif ++ reinit_completion(&ar->peer_delete_done); ++ + ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id); + if (ret) { + ath11k_warn(ar->ab, +@@ -866,14 +891,20 @@ int ath11k_peer_create(struct ath11k *ar + "failed to create peer due to insufficient peer entry resource in firmware\n"); + return -ENOBUFS; + } +- ++ mutex_lock(&ar->ab->tbl_mtx_lock); + spin_lock_bh(&ar->ab->base_lock); + peer = ath11k_peer_find_by_addr(ar->ab, param->peer_addr); + if (peer) { +- spin_unlock_bh(&ar->ab->base_lock); +- return -EINVAL; ++ if (peer->vdev_id == param->vdev_id) { ++ spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ar->ab->tbl_mtx_lock); ++ return -EINVAL; ++ } ++ ath11k_peer_rhash_delete(ar->ab, peer); + } ++ + spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ar->ab->tbl_mtx_lock); + + ret = ath11k_wmi_send_peer_create_cmd(ar, param); + if (ret) {