mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 17:42:41 +00:00
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 <arif.alam@netexperience.com>
Signed-off-by: Marek Kwaczynski <marek@shasta.cloud>
117 lines
3.9 KiB
Diff
117 lines
3.9 KiB
Diff
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) {
|