mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-09 17:35:33 +00:00
This is a work in progress patch.
num_peers was decremented at one place and list_del was called at another place. There are chances that they miss sync. So reset num_peers when out of sync Signed-off-by: Venkat Chimata <venkat@nearhop.com>
This commit is contained in:
@@ -0,0 +1,264 @@
|
||||
From 625b8692332ee44e514be88400646e900710644b Mon Sep 17 00:00:00 2001
|
||||
From: Venkat Chimata <venkat@nearhop.com>
|
||||
Date: Tue, 25 Nov 2025 20:34:34 +0530
|
||||
Subject: [PATCH] This is a work in progress patch.
|
||||
|
||||
num_peers was decremented at one place and list_del was called at another place.
|
||||
There are chances that they miss sync.
|
||||
|
||||
So reset num_peers when out of sync
|
||||
|
||||
Signed-off-by: Venkat Chimata <venkat@nearhop.com>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/mac.c | 39 ++++++++----
|
||||
drivers/net/wireless/ath/ath11k/peer.c | 82 +++++++++++++++++++++++---
|
||||
2 files changed, 102 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
|
||||
index f300c4f..a3eeac8 100644
|
||||
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
||||
@@ -5383,6 +5383,8 @@ static int ath11k_mac_station_add(struct ath11k *ar,
|
||||
peer_param.peer_addr = sta->addr;
|
||||
peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
|
||||
|
||||
+ ath11k_warn(ab, "%s: Peer will be added: %pM for VDEV: %d\n", __func__,
|
||||
+ sta->addr, arvif->vdev_id);
|
||||
ret = ath11k_peer_create(ar, arvif, sta, &peer_param);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "Failed to add peer: %pM for VDEV: %d\n",
|
||||
@@ -5457,7 +5459,13 @@ free_tx_stats:
|
||||
kfree(arsta->wbm_tx_stats);
|
||||
arsta->wbm_tx_stats = NULL;
|
||||
free_peer:
|
||||
- ath11k_peer_delete(ar, arvif->vdev_id, sta->addr);
|
||||
+ ret = ath11k_peer_delete(ar, arvif->vdev_id, sta->addr);
|
||||
+ if (ret)
|
||||
+ ath11k_warn(ar->ab, "%s: Failed to delete peer: %pM for VDEV: %d\n", __func__,
|
||||
+ sta->addr, arvif->vdev_id);
|
||||
+ else
|
||||
+ ath11k_warn(ar->ab, "%s: Removed peer: %pM for VDEV: %d\n", __func__,
|
||||
+ sta->addr, arvif->vdev_id);
|
||||
free_rx_stats:
|
||||
kfree(arsta->rx_stats);
|
||||
arsta->rx_stats = NULL;
|
||||
@@ -5735,18 +5743,15 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
|
||||
ath11k_warn(ar->ab, "Failed to delete peer: %pM for VDEV: %d\n",
|
||||
sta->addr, arvif->vdev_id);
|
||||
else
|
||||
- ath11k_dbg(ar->ab, ATH11K_DBG_PEER, "Removed peer: %pM for VDEV: %d\n",
|
||||
+ ath11k_warn(ar->ab, "%s: Removed peer: %pM for VDEV: %d\n", __func__,
|
||||
sta->addr, arvif->vdev_id);
|
||||
|
||||
ath11k_mac_dec_num_stations(arvif, sta);
|
||||
mutex_lock(&ar->ab->tbl_mtx_lock);
|
||||
spin_lock_bh(&ar->ab->base_lock);
|
||||
peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
|
||||
- /* Skip if peer deletion already in progress to prevent
|
||||
- * double-delete and num_peers underflow
|
||||
- */
|
||||
- if (peer && peer->sta == sta && !peer->delete_in_progress) {
|
||||
- ath11k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n",
|
||||
+ if (peer && peer->sta == sta) {
|
||||
+ ath11k_warn(ar->ab, "%s: Found peer entry %pM n vdev %i after it was supposedly removed\n", __func__,
|
||||
vif->addr, arvif->vdev_id);
|
||||
ath11k_peer_rhash_delete(ar->ab, peer);
|
||||
peer->sta = NULL;
|
||||
@@ -7746,6 +7751,8 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
peer_param.vdev_id = arvif->vdev_id;
|
||||
peer_param.peer_addr = vif->addr;
|
||||
peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
|
||||
+ ath11k_warn(ab, "%s: Peer will be added: %pM for VDEV: %d\n", __func__,
|
||||
+ vif->addr, arvif->vdev_id);
|
||||
ret = ath11k_peer_create(ar, arvif, NULL, &peer_param);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to vdev %d create peer for AP: %d\n",
|
||||
@@ -7947,8 +7954,11 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
|
||||
ret = ath11k_peer_delete(ar, arvif->vdev_id, vif->addr);
|
||||
if (ret)
|
||||
- ath11k_warn(ab, "failed to submit AP self-peer removal on vdev %d: %d\n",
|
||||
+ ath11k_warn(ab, "%s: failed to submit AP self-peer removal on vdev %d: %d\n", __func__,
|
||||
arvif->vdev_id, ret);
|
||||
+ else
|
||||
+ ath11k_warn(ar->ab, "%s: Removed peer: %pM for VDEV: %d\n", __func__,
|
||||
+ vif->addr, arvif->vdev_id);
|
||||
|
||||
list_for_each_entry_safe(ap_vlan_arvif, tmp, &arvif->ap_vlan_arvifs,
|
||||
list) {
|
||||
@@ -9305,6 +9315,8 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
param.peer_type = WMI_PEER_TYPE_DEFAULT;
|
||||
param.peer_addr = ar->mac_addr;
|
||||
|
||||
+ ath11k_warn(ab, "%s: Peer will be added: %pM for VDEV: %d\n", __func__,
|
||||
+ ar->mac_addr, arvif->vdev_id);
|
||||
ret = ath11k_peer_create(ar, arvif, NULL, ¶m);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to create peer after vdev start delay: %d",
|
||||
@@ -9380,8 +9392,15 @@ ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
|
||||
if (ab->hw_params.vdev_start_delay &&
|
||||
arvif->vdev_type == WMI_VDEV_TYPE_MONITOR &&
|
||||
- ath11k_peer_find_by_addr(ab, ar->mac_addr))
|
||||
- ath11k_peer_delete(ar, arvif->vdev_id, ar->mac_addr);
|
||||
+ ath11k_peer_find_by_addr(ab, ar->mac_addr)) {
|
||||
+ ret = ath11k_peer_delete(ar, arvif->vdev_id, ar->mac_addr);
|
||||
+ if (ret)
|
||||
+ ath11k_warn(ar->ab, "%s: Failed to delete peer: %pM for VDEV: %d\n", __func__,
|
||||
+ ar->mac_addr, arvif->vdev_id);
|
||||
+ else
|
||||
+ ath11k_warn(ar->ab, "%s: Removed peer: %pM for VDEV: %d\n", __func__,
|
||||
+ ar->mac_addr, arvif->vdev_id);
|
||||
+ }
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
|
||||
ret = ath11k_mac_monitor_stop(ar);
|
||||
diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c
|
||||
index 877ea30..9ec297f 100644
|
||||
--- a/drivers/net/wireless/ath/ath11k/peer.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/peer.c
|
||||
@@ -457,8 +457,8 @@ void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
- if (peer->peer_logging_enabled)
|
||||
- ath11k_dbg(ab, ATH11K_DBG_PEER, "peer unmap vdev %d peer %pM id %d\n",
|
||||
+// if (peer->peer_logging_enabled)
|
||||
+ ath11k_warn(ab, "peer unmap vdev %d peer %pM id %d\n",
|
||||
peer->vdev_id, peer->addr, peer_id);
|
||||
|
||||
/* Don't decrement num_peers here - it's already decremented in
|
||||
@@ -466,6 +466,7 @@ void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id)
|
||||
*/
|
||||
list_del(&peer->list);
|
||||
kfree(peer);
|
||||
+ ath11k_mac_get_ar_by_vdev_id(ab, peer->vdev_id);
|
||||
wake_up(&ab->peer_mapping_wq);
|
||||
|
||||
exit:
|
||||
@@ -617,7 +618,14 @@ void ath11k_peer_map_v2_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id,
|
||||
peer_free:
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
- ath11k_peer_delete(ar, vdev_id, mac_addr);
|
||||
+ ret = ath11k_peer_delete(ar, vdev_id, mac_addr);
|
||||
+ if (ret)
|
||||
+ ath11k_warn(ar->ab, "%s: Failed to delete peer: %pM for VDEV: %d\n", __func__,
|
||||
+ mac_addr, vdev_id);
|
||||
+ else
|
||||
+ ath11k_warn(ar->ab, "%s: Removed peer: %pM for VDEV: %d\n", __func__,
|
||||
+ mac_addr, vdev_id);
|
||||
+
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
@@ -893,9 +901,16 @@ int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr)
|
||||
list_del(&peer->list);
|
||||
kfree(peer);
|
||||
ar->num_peers--;
|
||||
- ath11k_dbg(ar->ab, ATH11K_DBG_PEER,
|
||||
+ ath11k_warn(ar->ab,
|
||||
"%s peer deleted (timeout) %pM vdev_id: %d num_peers: %d\n",
|
||||
__func__, addr, vdev_id, ar->num_peers);
|
||||
+ } else {
|
||||
+ // Peer already deleted
|
||||
+ // Who deleted it? Firmware unmap event after the timeout?
|
||||
+ ar->num_peers--;
|
||||
+ ath11k_warn(ar->ab,
|
||||
+ "%s peer already deleted (timeout) %pM vdev_id: %d num_peers: %d\n",
|
||||
+ __func__, addr, vdev_id, ar->num_peers);
|
||||
}
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
mutex_unlock(&ar->ab->tbl_mtx_lock);
|
||||
@@ -911,13 +926,13 @@ int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr)
|
||||
list_del(&peer->list);
|
||||
kfree(peer);
|
||||
ar->num_peers--;
|
||||
- ath11k_dbg(ar->ab, ATH11K_DBG_PEER,
|
||||
+ ath11k_warn(ar->ab,
|
||||
"%s peer deleted (no unmap event) %pM vdev_id: %d num_peers: %d\n",
|
||||
__func__, addr, vdev_id, ar->num_peers);
|
||||
} else {
|
||||
/* Peer already removed by unmap event - still need to decrement */
|
||||
ar->num_peers--;
|
||||
- ath11k_dbg(ar->ab, ATH11K_DBG_PEER,
|
||||
+ ath11k_warn(ar->ab,
|
||||
"%s peer deleted (via unmap event) %pM vdev_id: %d num_peers: %d\n",
|
||||
__func__, addr, vdev_id, ar->num_peers);
|
||||
}
|
||||
@@ -933,6 +948,31 @@ static int ath11k_wait_for_peer_created(struct ath11k *ar, int vdev_id, const u8
|
||||
return ath11k_wait_for_peer_common(ar->ab, vdev_id, addr, true);
|
||||
}
|
||||
|
||||
+static int ath11k_get_peer_count(struct rhashtable *ht)
|
||||
+{
|
||||
+ struct rhashtable_iter iter;
|
||||
+ struct rhash_head *pos;
|
||||
+ int count = 0;
|
||||
+
|
||||
+ rhashtable_walk_enter(ht, &iter);
|
||||
+ rhashtable_walk_start(&iter);
|
||||
+
|
||||
+ while ((pos = rhashtable_walk_next(&iter))) {
|
||||
+ if (IS_ERR(pos)) {
|
||||
+ if (PTR_ERR(pos) == -EAGAIN)
|
||||
+ continue; // retry due to resize
|
||||
+ break; // some other error
|
||||
+ }
|
||||
+ count++;
|
||||
+ }
|
||||
+
|
||||
+ rhashtable_walk_stop(&iter);
|
||||
+ rhashtable_walk_exit(&iter);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+
|
||||
int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
struct ieee80211_sta *sta, struct peer_create_params *param)
|
||||
{
|
||||
@@ -941,13 +981,37 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
struct ath11k_sta *arsta;
|
||||
int ret, fbret;
|
||||
u8 vdev_id = 0;
|
||||
+ int rhash_count;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
- if (ar->num_peers > (ar->max_num_peers - 1)) {
|
||||
+ mutex_lock(&ar->ab->tbl_mtx_lock);
|
||||
+ spin_lock_bh(&ar->ab->base_lock);
|
||||
+ rhash_count = ath11k_get_peer_count(ar->ab->rhead_peer_addr);
|
||||
+ spin_unlock_bh(&ar->ab->base_lock);
|
||||
+ mutex_unlock(&ar->ab->tbl_mtx_lock);
|
||||
+ ath11k_warn(ar->ab, "address = %pM rhash_count = %d ar->num_peers = %d "
|
||||
+ "ar->max_num_peers = %d ar->num_stations = %d\n", param->peer_addr, rhash_count, ar->num_peers, ar->max_num_peers, ar->num_stations);
|
||||
+ // Check for peer count desynchronization
|
||||
+ // If num_peers is negative or exceeds max_num_peers -1, recalculate from rhashtable
|
||||
+ if ((ar->num_peers < 0) || (ar->num_peers > (ar->max_num_peers - 1))) {
|
||||
+ // This can happen if rhash table and num_peers get out of sync
|
||||
+ // e.g. during peer delete for some unknown reason
|
||||
+ // Recalculate num_peers from rhash table
|
||||
ath11k_warn(ar->ab,
|
||||
- "failed to create peer due to insufficient peer entry resource in firmware\n");
|
||||
- return -ENOBUFS;
|
||||
+ "failed to create peer due to insufficient peer entry resource in firmware ar->num_peers = %d "
|
||||
+ "ar->max_num_peers = %d ar->num_stations = %d\n", ar->num_peers, ar->max_num_peers, ar->num_stations);
|
||||
+ mutex_lock(&ar->ab->tbl_mtx_lock);
|
||||
+ spin_lock_bh(&ar->ab->base_lock);
|
||||
+ rhash_count = ath11k_get_peer_count(ar->ab->rhead_peer_addr);
|
||||
+ spin_unlock_bh(&ar->ab->base_lock);
|
||||
+ mutex_unlock(&ar->ab->tbl_mtx_lock);
|
||||
+ if (rhash_count > ar->max_num_peers -1 ) {
|
||||
+ ath11k_warn(ar->ab,
|
||||
+ "rhash_count %d exceeds max_num_peers %d\n", rhash_count, ar->max_num_peers);
|
||||
+ return -ENOBUFS;
|
||||
+ }
|
||||
+ ar->num_peers = rhash_count;
|
||||
}
|
||||
|
||||
mutex_lock(&ar->ab->tbl_mtx_lock);
|
||||
--
|
||||
2.34.1
|
||||
|
||||
Reference in New Issue
Block a user