wifi: ath12k: fix station lookup failure when disconnecting from AP

In ath12k_wmi_tlv_fw_stats_data_parse() and
ath12k_wmi_tlv_rssi_chain_parse(), the driver uses
ieee80211_find_sta_by_ifaddr() to look up the station associated with the
incoming firmware statistics. This works under normal conditions but fails
during AP disconnection, resulting in log messages like:

 wlan0: deauthenticating from xxxxxx by local choice (Reason: 3=DEAUTH_LEAVING)
 wlan0: moving STA xxxxxx to state 3
 wlan0: moving STA xxxxxx to state 2
 wlan0: moving STA xxxxxx to state 1
 ath12k_pci 0000:02:00.0: not found station bssid xxxxxx for vdev stat
 ath12k_pci 0000:02:00.0: not found station of bssid xxxxxx for rssi chain
 ath12k_pci 0000:02:00.0: failed to pull fw stats: -71
 ath12k_pci 0000:02:00.0: time out while waiting for get fw stats
 wlan0: Removed STA xxxxxx
 wlan0: Destroyed STA xxxxxx

The failure happens because the station has already been removed from
ieee80211_local::sta_hash by the time firmware statistics are requested
through drv_sta_statistics().

Switch the lookup to ath12k_link_sta_find_by_addr(), which searches the
driver's link station hash table that still has the station recorded
at that time.  This also implicitly fixes another issue: the current code
always uses deflink regardless of which link the statistics belong to,
which is incorrect in MLO scenarios. The new helper returns the correct
link station.

Additionally, raise the log level on lookup failures. With the updated
helper, such failures should no longer occur under normal conditions.

Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3

Fixes: 79e7b04b53 ("wifi: ath12k: report station mode signal strength")
Fixes: 6af5bc381b ("wifi: ath12k: report station mode per-chain signal strength")
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20260129-ath12k-fw-stats-fixes-v1-2-55d66064f4d5@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
This commit is contained in:
Baochen Qiang 2026-01-29 10:24:06 +08:00 committed by Jeff Johnson
parent 8f153eb745
commit 7259b1a0e5

View file

@ -8241,8 +8241,6 @@ static int ath12k_wmi_tlv_fw_stats_data_parse(struct ath12k_base *ab,
struct ath12k_fw_stats *stats = parse->stats;
struct ath12k *ar;
struct ath12k_link_vif *arvif;
struct ieee80211_sta *sta;
struct ath12k_sta *ahsta;
struct ath12k_link_sta *arsta;
int i, ret = 0;
const void *data = ptr;
@ -8278,21 +8276,19 @@ static int ath12k_wmi_tlv_fw_stats_data_parse(struct ath12k_base *ab,
arvif = ath12k_mac_get_arvif(ar, le32_to_cpu(src->vdev_id));
if (arvif) {
sta = ieee80211_find_sta_by_ifaddr(ath12k_ar_to_hw(ar),
arvif->bssid,
NULL);
if (sta) {
ahsta = ath12k_sta_to_ahsta(sta);
arsta = &ahsta->deflink;
spin_lock_bh(&ab->base_lock);
arsta = ath12k_link_sta_find_by_addr(ab, arvif->bssid);
if (arsta) {
arsta->rssi_beacon = le32_to_cpu(src->beacon_snr);
ath12k_dbg(ab, ATH12K_DBG_WMI,
"wmi stats vdev id %d snr %d\n",
src->vdev_id, src->beacon_snr);
} else {
ath12k_dbg(ab, ATH12K_DBG_WMI,
"not found station bssid %pM for vdev stat\n",
arvif->bssid);
ath12k_warn(ab,
"not found link sta with bssid %pM for vdev stat\n",
arvif->bssid);
}
spin_unlock_bh(&ab->base_lock);
}
data += sizeof(*src);
@ -8363,8 +8359,6 @@ static int ath12k_wmi_tlv_rssi_chain_parse(struct ath12k_base *ab,
struct ath12k_fw_stats *stats = parse->stats;
struct ath12k_link_vif *arvif;
struct ath12k_link_sta *arsta;
struct ieee80211_sta *sta;
struct ath12k_sta *ahsta;
struct ath12k *ar;
int vdev_id;
int j;
@ -8400,19 +8394,15 @@ static int ath12k_wmi_tlv_rssi_chain_parse(struct ath12k_base *ab,
"stats bssid %pM vif %p\n",
arvif->bssid, arvif->ahvif->vif);
sta = ieee80211_find_sta_by_ifaddr(ath12k_ar_to_hw(ar),
arvif->bssid,
NULL);
if (!sta) {
ath12k_dbg(ab, ATH12K_DBG_WMI,
"not found station of bssid %pM for rssi chain\n",
arvif->bssid);
guard(spinlock_bh)(&ab->base_lock);
arsta = ath12k_link_sta_find_by_addr(ab, arvif->bssid);
if (!arsta) {
ath12k_warn(ab,
"not found link sta with bssid %pM for rssi chain\n",
arvif->bssid);
return -EPROTO;
}
ahsta = ath12k_sta_to_ahsta(sta);
arsta = &ahsta->deflink;
BUILD_BUG_ON(ARRAY_SIZE(arsta->chain_signal) >
ARRAY_SIZE(stats_rssi->rssi_avg_beacon));