* [PATCH ath-current] wifi: ath10k: fix station lookup failure during disconnect
@ 2026-03-25 3:05 Baochen Qiang
2026-03-26 23:31 ` Paul Menzel
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Baochen Qiang @ 2026-03-25 3:05 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath10k, pmenzel, Baochen Qiang
Recent commit [1] moved station statistics collection to an earlier stage
of the disconnect flow. With this change in place, ath10k fails to resolve
the station entry when handling a peer stats event triggered during
disconnect, resulting in log messages such as:
wlp58s0: deauthenticating from 74:1a:e0:e7:b4:c8 by local choice (Reason: 3=DEAUTH_LEAVING)
ath10k_pci 0000:3a:00.0: not found station for peer stats
ath10k_pci 0000:3a:00.0: failed to parse stats info tlv: -22
The failure occurs because ath10k relies on ieee80211_find_sta_by_ifaddr()
for station lookup. That function uses local->sta_hash, but by the time
the peer stats request is triggered during disconnect, mac80211 has
already removed the station from that hash table, leading to lookup
failure.
Before commit [1], this issue was not visible because the transition from
IEEE80211_STA_NONE to IEEE80211_STA_NOTEXIST prevented ath10k from sending
a peer stats request at all: ath10k_mac_sta_get_peer_stats_info() would
fail early to find the peer and skip requesting statistics.
Fix this by switching the lookup path to ath10k_peer_find(), which queries
ath10k's internal peer table. At the point where the firmware emits the
peer stats event, the peer entry is still present in the driver's list,
ensuring lookup succeeds.
Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00309-QCARMSWPZ-1
Fixes: a203dbeeca15 ("wifi: mac80211: collect station statistics earlier when disconnect") # [1]
Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
Closes: https://lore.kernel.org/ath10k/57671b89-ec9f-4e6c-992c-45eb8e75929c@molgen.mpg.de
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index ec8e91707f84..01f2d1fa9d7d 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -3,7 +3,7 @@
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
- * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "core.h"
#include "debug.h"
@@ -14,6 +14,7 @@
#include "wmi-tlv.h"
#include "p2p.h"
#include "testmode.h"
+#include "txrx.h"
#include <linux/bitfield.h>
/***************/
@@ -224,8 +225,9 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16
const void *ptr, void *data)
{
const struct wmi_tlv_peer_stats_info *stat = ptr;
- struct ieee80211_sta *sta;
+ u32 vdev_id = *(u32 *)data;
struct ath10k_sta *arsta;
+ struct ath10k_peer *peer;
if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO)
return -EPROTO;
@@ -241,20 +243,20 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16
__le32_to_cpu(stat->last_tx_rate_code),
__le32_to_cpu(stat->last_tx_bitrate_kbps));
- rcu_read_lock();
- sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL);
- if (!sta) {
- rcu_read_unlock();
- ath10k_warn(ar, "not found station for peer stats\n");
+ guard(spinlock_bh)(&ar->data_lock);
+
+ peer = ath10k_peer_find(ar, vdev_id, stat->peer_macaddr.addr);
+ if (!peer || !peer->sta) {
+ ath10k_warn(ar, "not found %s with vdev id %u mac addr %pM for peer stats\n",
+ peer ? "sta" : "peer", vdev_id, stat->peer_macaddr.addr);
return -EINVAL;
}
- arsta = (struct ath10k_sta *)sta->drv_priv;
+ arsta = (struct ath10k_sta *)peer->sta->drv_priv;
arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code);
arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps);
arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code);
arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps);
- rcu_read_unlock();
return 0;
}
@@ -266,6 +268,7 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
const struct wmi_tlv_peer_stats_info_ev *ev;
const void *data;
u32 num_peer_stats;
+ u32 vdev_id;
int ret;
tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
@@ -284,15 +287,16 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
}
num_peer_stats = __le32_to_cpu(ev->num_peers);
+ vdev_id = __le32_to_cpu(ev->vdev_id);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n",
- __le32_to_cpu(ev->vdev_id),
+ vdev_id,
num_peer_stats,
__le32_to_cpu(ev->more_data));
ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data),
- ath10k_wmi_tlv_parse_peer_stats_info, NULL);
+ ath10k_wmi_tlv_parse_peer_stats_info, &vdev_id);
if (ret)
ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret);
---
base-commit: 4242625f272974dd1947f73b10d884eab3b277cd
change-id: 20260325-ath10k-station-lookup-failure-be4dd6e81100
Best regards,
--
Baochen Qiang <baochen.qiang@oss.qualcomm.com>
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH ath-current] wifi: ath10k: fix station lookup failure during disconnect
2026-03-25 3:05 [PATCH ath-current] wifi: ath10k: fix station lookup failure during disconnect Baochen Qiang
@ 2026-03-26 23:31 ` Paul Menzel
2026-03-27 2:54 ` Baochen Qiang
2026-03-31 4:54 ` Rameshkumar Sundaram
2026-04-08 0:50 ` Jeff Johnson
2 siblings, 1 reply; 8+ messages in thread
From: Paul Menzel @ 2026-03-26 23:31 UTC (permalink / raw)
To: Baochen Qiang, Jeff Johnson; +Cc: linux-wireless, ath10k
Dear Baochen,
Thank you for sending the patch out.
Am 25.03.26 um 04:05 schrieb Baochen Qiang:
> Recent commit [1] moved station statistics collection to an earlier stage
> of the disconnect flow. With this change in place, ath10k fails to resolve
> the station entry when handling a peer stats event triggered during
> disconnect, resulting in log messages such as:
>
> wlp58s0: deauthenticating from 74:1a:e0:e7:b4:c8 by local choice (Reason: 3=DEAUTH_LEAVING)
> ath10k_pci 0000:3a:00.0: not found station for peer stats
> ath10k_pci 0000:3a:00.0: failed to parse stats info tlv: -22
>
> The failure occurs because ath10k relies on ieee80211_find_sta_by_ifaddr()
> for station lookup. That function uses local->sta_hash, but by the time
> the peer stats request is triggered during disconnect, mac80211 has
> already removed the station from that hash table, leading to lookup
> failure.
>
> Before commit [1], this issue was not visible because the transition from
> IEEE80211_STA_NONE to IEEE80211_STA_NOTEXIST prevented ath10k from sending
> a peer stats request at all: ath10k_mac_sta_get_peer_stats_info() would
> fail early to find the peer and skip requesting statistics.
>
> Fix this by switching the lookup path to ath10k_peer_find(), which queries
> ath10k's internal peer table. At the point where the firmware emits the
> peer stats event, the peer entry is still present in the driver's list,
> ensuring lookup succeeds.
Out of curiosity, how can the statistics be printed?
> Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00309-QCARMSWPZ-1
>
> Fixes: a203dbeeca15 ("wifi: mac80211: collect station statistics earlier when disconnect") # [1]
> Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
> Closes: https://lore.kernel.org/ath10k/57671b89-ec9f-4e6c-992c-45eb8e75929c@molgen.mpg.de
> Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
> ---
> drivers/net/wireless/ath/ath10k/wmi-tlv.c | 26 +++++++++++++++-----------
> 1 file changed, 15 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
> index ec8e91707f84..01f2d1fa9d7d 100644
> --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
> +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
> @@ -3,7 +3,7 @@
> * Copyright (c) 2005-2011 Atheros Communications Inc.
> * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
> * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
> - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> */
> #include "core.h"
> #include "debug.h"
> @@ -14,6 +14,7 @@
> #include "wmi-tlv.h"
> #include "p2p.h"
> #include "testmode.h"
> +#include "txrx.h"
> #include <linux/bitfield.h>
>
> /***************/
> @@ -224,8 +225,9 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16
> const void *ptr, void *data)
> {
> const struct wmi_tlv_peer_stats_info *stat = ptr;
> - struct ieee80211_sta *sta;
> + u32 vdev_id = *(u32 *)data;
> struct ath10k_sta *arsta;
> + struct ath10k_peer *peer;
>
> if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO)
> return -EPROTO;
> @@ -241,20 +243,20 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16
> __le32_to_cpu(stat->last_tx_rate_code),
> __le32_to_cpu(stat->last_tx_bitrate_kbps));
>
> - rcu_read_lock();
> - sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL);
> - if (!sta) {
> - rcu_read_unlock();
> - ath10k_warn(ar, "not found station for peer stats\n");
> + guard(spinlock_bh)(&ar->data_lock);
> +
> + peer = ath10k_peer_find(ar, vdev_id, stat->peer_macaddr.addr);
> + if (!peer || !peer->sta) {
> + ath10k_warn(ar, "not found %s with vdev id %u mac addr %pM for peer stats\n",
> + peer ? "sta" : "peer", vdev_id, stat->peer_macaddr.addr);
> return -EINVAL;
> }
>
> - arsta = (struct ath10k_sta *)sta->drv_priv;
> + arsta = (struct ath10k_sta *)peer->sta->drv_priv;
> arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code);
> arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps);
> arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code);
> arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps);
> - rcu_read_unlock();
>
> return 0;
> }
> @@ -266,6 +268,7 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
> const struct wmi_tlv_peer_stats_info_ev *ev;
> const void *data;
> u32 num_peer_stats;
> + u32 vdev_id;
> int ret;
>
> tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
> @@ -284,15 +287,16 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
> }
>
> num_peer_stats = __le32_to_cpu(ev->num_peers);
> + vdev_id = __le32_to_cpu(ev->vdev_id);
>
> ath10k_dbg(ar, ATH10K_DBG_WMI,
> "wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n",
> - __le32_to_cpu(ev->vdev_id),
> + vdev_id,
> num_peer_stats,
> __le32_to_cpu(ev->more_data));
>
> ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data),
> - ath10k_wmi_tlv_parse_peer_stats_info, NULL);
> + ath10k_wmi_tlv_parse_peer_stats_info, &vdev_id);
> if (ret)
> ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret);
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Tested-by: Paul Menzel <pmenzel@molgen.mpg.de>
Kind regards,
Paul
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH ath-current] wifi: ath10k: fix station lookup failure during disconnect
2026-03-26 23:31 ` Paul Menzel
@ 2026-03-27 2:54 ` Baochen Qiang
2026-03-27 8:43 ` Paul Menzel
0 siblings, 1 reply; 8+ messages in thread
From: Baochen Qiang @ 2026-03-27 2:54 UTC (permalink / raw)
To: Paul Menzel, Jeff Johnson; +Cc: linux-wireless, ath10k
On 3/27/2026 7:31 AM, Paul Menzel wrote:
> Dear Baochen,
>
>
> Thank you for sending the patch out.
>
> Am 25.03.26 um 04:05 schrieb Baochen Qiang:
>> Recent commit [1] moved station statistics collection to an earlier stage
>> of the disconnect flow. With this change in place, ath10k fails to resolve
>> the station entry when handling a peer stats event triggered during
>> disconnect, resulting in log messages such as:
>>
>> wlp58s0: deauthenticating from 74:1a:e0:e7:b4:c8 by local choice (Reason: 3=DEAUTH_LEAVING)
>> ath10k_pci 0000:3a:00.0: not found station for peer stats
>> ath10k_pci 0000:3a:00.0: failed to parse stats info tlv: -22
>>
>> The failure occurs because ath10k relies on ieee80211_find_sta_by_ifaddr()
>> for station lookup. That function uses local->sta_hash, but by the time
>> the peer stats request is triggered during disconnect, mac80211 has
>> already removed the station from that hash table, leading to lookup
>> failure.
>>
>> Before commit [1], this issue was not visible because the transition from
>> IEEE80211_STA_NONE to IEEE80211_STA_NOTEXIST prevented ath10k from sending
>> a peer stats request at all: ath10k_mac_sta_get_peer_stats_info() would
>> fail early to find the peer and skip requesting statistics.
>>
>> Fix this by switching the lookup path to ath10k_peer_find(), which queries
>> ath10k's internal peer table. At the point where the firmware emits the
>> peer stats event, the peer entry is still present in the driver's list,
>> ensuring lookup succeeds.
>
> Out of curiosity, how can the statistics be printed?
not quite understand your question, can you be more detailed ?
>
>> Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00309-QCARMSWPZ-1
>>
>> Fixes: a203dbeeca15 ("wifi: mac80211: collect station statistics earlier when
>> disconnect") # [1]
>> Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
>> Closes: https://lore.kernel.org/ath10k/57671b89-ec9f-4e6c-992c-45eb8e75929c@molgen.mpg.de
>> Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
>> ---
>> drivers/net/wireless/ath/ath10k/wmi-tlv.c | 26 +++++++++++++++-----------
>> 1 file changed, 15 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/
>> ath10k/wmi-tlv.c
>> index ec8e91707f84..01f2d1fa9d7d 100644
>> --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
>> +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
>> @@ -3,7 +3,7 @@
>> * Copyright (c) 2005-2011 Atheros Communications Inc.
>> * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
>> * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
>> - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
>> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
>> */
>> #include "core.h"
>> #include "debug.h"
>> @@ -14,6 +14,7 @@
>> #include "wmi-tlv.h"
>> #include "p2p.h"
>> #include "testmode.h"
>> +#include "txrx.h"
>> #include <linux/bitfield.h>
>> /***************/
>> @@ -224,8 +225,9 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar,
>> u16 tag, u16
>> const void *ptr, void *data)
>> {
>> const struct wmi_tlv_peer_stats_info *stat = ptr;
>> - struct ieee80211_sta *sta;
>> + u32 vdev_id = *(u32 *)data;
>> struct ath10k_sta *arsta;
>> + struct ath10k_peer *peer;
>> if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO)
>> return -EPROTO;
>> @@ -241,20 +243,20 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar,
>> u16 tag, u16
>> __le32_to_cpu(stat->last_tx_rate_code),
>> __le32_to_cpu(stat->last_tx_bitrate_kbps));
>> - rcu_read_lock();
>> - sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL);
>> - if (!sta) {
>> - rcu_read_unlock();
>> - ath10k_warn(ar, "not found station for peer stats\n");
>> + guard(spinlock_bh)(&ar->data_lock);
>> +
>> + peer = ath10k_peer_find(ar, vdev_id, stat->peer_macaddr.addr);
>> + if (!peer || !peer->sta) {
>> + ath10k_warn(ar, "not found %s with vdev id %u mac addr %pM for peer stats\n",
>> + peer ? "sta" : "peer", vdev_id, stat->peer_macaddr.addr);
>> return -EINVAL;
>> }
>> - arsta = (struct ath10k_sta *)sta->drv_priv;
>> + arsta = (struct ath10k_sta *)peer->sta->drv_priv;
>> arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code);
>> arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps);
>> arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code);
>> arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps);
>> - rcu_read_unlock();
>> return 0;
>> }
>> @@ -266,6 +268,7 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
>> const struct wmi_tlv_peer_stats_info_ev *ev;
>> const void *data;
>> u32 num_peer_stats;
>> + u32 vdev_id;
>> int ret;
>> tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
>> @@ -284,15 +287,16 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
>> }
>> num_peer_stats = __le32_to_cpu(ev->num_peers);
>> + vdev_id = __le32_to_cpu(ev->vdev_id);
>> ath10k_dbg(ar, ATH10K_DBG_WMI,
>> "wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n",
>> - __le32_to_cpu(ev->vdev_id),
>> + vdev_id,
>> num_peer_stats,
>> __le32_to_cpu(ev->more_data));
>> ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data),
>> - ath10k_wmi_tlv_parse_peer_stats_info, NULL);
>> + ath10k_wmi_tlv_parse_peer_stats_info, &vdev_id);
>> if (ret)
>> ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret);
>
> Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
> Tested-by: Paul Menzel <pmenzel@molgen.mpg.de>
>
>
> Kind regards,
>
> Paul
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH ath-current] wifi: ath10k: fix station lookup failure during disconnect
2026-03-27 2:54 ` Baochen Qiang
@ 2026-03-27 8:43 ` Paul Menzel
2026-03-27 9:11 ` Baochen Qiang
0 siblings, 1 reply; 8+ messages in thread
From: Paul Menzel @ 2026-03-27 8:43 UTC (permalink / raw)
To: Baochen Qiang, Jeff Johnson; +Cc: linux-wireless, ath10k
Dear Baochen,
Am 27.03.26 um 03:54 schrieb Baochen Qiang:
> On 3/27/2026 7:31 AM, Paul Menzel wrote:
[…]
>> Am 25.03.26 um 04:05 schrieb Baochen Qiang:
>>> Recent commit [1] moved station statistics collection to an earlier stage
>>> of the disconnect flow. With this change in place, ath10k fails to resolve
>>> the station entry when handling a peer stats event triggered during
>>> disconnect, resulting in log messages such as:
>>>
>>> wlp58s0: deauthenticating from 74:1a:e0:e7:b4:c8 by local choice (Reason: 3=DEAUTH_LEAVING)
>>> ath10k_pci 0000:3a:00.0: not found station for peer stats
>>> ath10k_pci 0000:3a:00.0: failed to parse stats info tlv: -22
>>>
>>> The failure occurs because ath10k relies on ieee80211_find_sta_by_ifaddr()
>>> for station lookup. That function uses local->sta_hash, but by the time
>>> the peer stats request is triggered during disconnect, mac80211 has
>>> already removed the station from that hash table, leading to lookup
>>> failure.
>>>
>>> Before commit [1], this issue was not visible because the transition from
>>> IEEE80211_STA_NONE to IEEE80211_STA_NOTEXIST prevented ath10k from sending
>>> a peer stats request at all: ath10k_mac_sta_get_peer_stats_info() would
>>> fail early to find the peer and skip requesting statistics.
>>>
>>> Fix this by switching the lookup path to ath10k_peer_find(), which queries
>>> ath10k's internal peer table. At the point where the firmware emits the
>>> peer stats event, the peer entry is still present in the driver's list,
>>> ensuring lookup succeeds.
>>
>> Out of curiosity, how can the statistics be printed?
>
> not quite understand your question, can you be more detailed?
The commit message starts with:
“… moved station statistics collection to an earlier stage …”
I was wondering how to print/dump these statistics.
Kind regards,
Paul
>>> Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00309-QCARMSWPZ-1
>>>
>>> Fixes: a203dbeeca15 ("wifi: mac80211: collect station statistics earlier when disconnect") # [1]
>>> Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
>>> Closes: https://lore.kernel.org/ath10k/57671b89-ec9f-4e6c-992c-45eb8e75929c@molgen.mpg.de
>>> Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
>>> ---
>>> drivers/net/wireless/ath/ath10k/wmi-tlv.c | 26 +++++++++++++++-----------
>>> 1 file changed, 15 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/
>>> ath10k/wmi-tlv.c
>>> index ec8e91707f84..01f2d1fa9d7d 100644
>>> --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
>>> +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
>>> @@ -3,7 +3,7 @@
>>> * Copyright (c) 2005-2011 Atheros Communications Inc.
>>> * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
>>> * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
>>> - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
>>> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
>>> */
>>> #include "core.h"
>>> #include "debug.h"
>>> @@ -14,6 +14,7 @@
>>> #include "wmi-tlv.h"
>>> #include "p2p.h"
>>> #include "testmode.h"
>>> +#include "txrx.h"
>>> #include <linux/bitfield.h>
>>> /***************/
>>> @@ -224,8 +225,9 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16
>>> const void *ptr, void *data)
>>> {
>>> const struct wmi_tlv_peer_stats_info *stat = ptr;
>>> - struct ieee80211_sta *sta;
>>> + u32 vdev_id = *(u32 *)data;
>>> struct ath10k_sta *arsta;
>>> + struct ath10k_peer *peer;
>>> if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO)
>>> return -EPROTO;
>>> @@ -241,20 +243,20 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16
>>> __le32_to_cpu(stat->last_tx_rate_code),
>>> __le32_to_cpu(stat->last_tx_bitrate_kbps));
>>> - rcu_read_lock();
>>> - sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL);
>>> - if (!sta) {
>>> - rcu_read_unlock();
>>> - ath10k_warn(ar, "not found station for peer stats\n");
>>> + guard(spinlock_bh)(&ar->data_lock);
>>> +
>>> + peer = ath10k_peer_find(ar, vdev_id, stat->peer_macaddr.addr);
>>> + if (!peer || !peer->sta) {
>>> + ath10k_warn(ar, "not found %s with vdev id %u mac addr %pM for peer stats\n",
>>> + peer ? "sta" : "peer", vdev_id, stat->peer_macaddr.addr);
>>> return -EINVAL;
>>> }
>>> - arsta = (struct ath10k_sta *)sta->drv_priv;
>>> + arsta = (struct ath10k_sta *)peer->sta->drv_priv;
>>> arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code);
>>> arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps);
>>> arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code);
>>> arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps);
>>> - rcu_read_unlock();
>>> return 0;
>>> }
>>> @@ -266,6 +268,7 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
>>> const struct wmi_tlv_peer_stats_info_ev *ev;
>>> const void *data;
>>> u32 num_peer_stats;
>>> + u32 vdev_id;
>>> int ret;
>>> tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
>>> @@ -284,15 +287,16 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
>>> }
>>> num_peer_stats = __le32_to_cpu(ev->num_peers);
>>> + vdev_id = __le32_to_cpu(ev->vdev_id);
>>> ath10k_dbg(ar, ATH10K_DBG_WMI,
>>> "wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n",
>>> - __le32_to_cpu(ev->vdev_id),
>>> + vdev_id,
>>> num_peer_stats,
>>> __le32_to_cpu(ev->more_data));
>>> ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data),
>>> - ath10k_wmi_tlv_parse_peer_stats_info, NULL);
>>> + ath10k_wmi_tlv_parse_peer_stats_info, &vdev_id);
>>> if (ret)
>>> ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret);
>>
>> Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
>> Tested-by: Paul Menzel <pmenzel@molgen.mpg.de>
>>
>>
>> Kind regards,
>>
>> Paul
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH ath-current] wifi: ath10k: fix station lookup failure during disconnect
2026-03-27 8:43 ` Paul Menzel
@ 2026-03-27 9:11 ` Baochen Qiang
2026-03-27 9:27 ` Paul Menzel
0 siblings, 1 reply; 8+ messages in thread
From: Baochen Qiang @ 2026-03-27 9:11 UTC (permalink / raw)
To: Paul Menzel, Jeff Johnson; +Cc: linux-wireless, ath10k
On 3/27/2026 4:43 PM, Paul Menzel wrote:
> Dear Baochen,
>
>
> Am 27.03.26 um 03:54 schrieb Baochen Qiang:
>
>> On 3/27/2026 7:31 AM, Paul Menzel wrote:
>
> […]
>
>>> Am 25.03.26 um 04:05 schrieb Baochen Qiang:
>>>> Recent commit [1] moved station statistics collection to an earlier stage
>>>> of the disconnect flow. With this change in place, ath10k fails to resolve
>>>> the station entry when handling a peer stats event triggered during
>>>> disconnect, resulting in log messages such as:
>>>>
>>>> wlp58s0: deauthenticating from 74:1a:e0:e7:b4:c8 by local choice (Reason:
>>>> 3=DEAUTH_LEAVING)
>>>> ath10k_pci 0000:3a:00.0: not found station for peer stats
>>>> ath10k_pci 0000:3a:00.0: failed to parse stats info tlv: -22
>>>>
>>>> The failure occurs because ath10k relies on ieee80211_find_sta_by_ifaddr()
>>>> for station lookup. That function uses local->sta_hash, but by the time
>>>> the peer stats request is triggered during disconnect, mac80211 has
>>>> already removed the station from that hash table, leading to lookup
>>>> failure.
>>>>
>>>> Before commit [1], this issue was not visible because the transition from
>>>> IEEE80211_STA_NONE to IEEE80211_STA_NOTEXIST prevented ath10k from sending
>>>> a peer stats request at all: ath10k_mac_sta_get_peer_stats_info() would
>>>> fail early to find the peer and skip requesting statistics.
>>>>
>>>> Fix this by switching the lookup path to ath10k_peer_find(), which queries
>>>> ath10k's internal peer table. At the point where the firmware emits the
>>>> peer stats event, the peer entry is still present in the driver's list,
>>>> ensuring lookup succeeds.
>>>
>>> Out of curiosity, how can the statistics be printed?
>>
>> not quite understand your question, can you be more detailed?
>
> The commit message starts with:
>
> “… moved station statistics collection to an earlier stage …”
>
> I was wondering how to print/dump these statistics.
still not quite understand, but let me try to answer:
mac80211 collects stats and send it to userspace over nl80211, userpsace tools like iw can
print it out.
>
>
> Kind regards,
>
> Paul
>
>
>>>> Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00309-QCARMSWPZ-1
>>>>
>>>> Fixes: a203dbeeca15 ("wifi: mac80211: collect station statistics earlier when
>>>> disconnect") # [1]
>>>> Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
>>>> Closes: https://lore.kernel.org/ath10k/57671b89-ec9f-4e6c-992c-45eb8e75929c@molgen.mpg.de
>>>> Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
>>>> ---
>>>> drivers/net/wireless/ath/ath10k/wmi-tlv.c | 26 +++++++++++++++-----------
>>>> 1 file changed, 15 insertions(+), 11 deletions(-)
>>>>
>>>> diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/
>>>> ath10k/wmi-tlv.c
>>>> index ec8e91707f84..01f2d1fa9d7d 100644
>>>> --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
>>>> +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
>>>> @@ -3,7 +3,7 @@
>>>> * Copyright (c) 2005-2011 Atheros Communications Inc.
>>>> * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
>>>> * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
>>>> - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
>>>> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
>>>> */
>>>> #include "core.h"
>>>> #include "debug.h"
>>>> @@ -14,6 +14,7 @@
>>>> #include "wmi-tlv.h"
>>>> #include "p2p.h"
>>>> #include "testmode.h"
>>>> +#include "txrx.h"
>>>> #include <linux/bitfield.h>
>>>> /***************/
>>>> @@ -224,8 +225,9 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar,
>>>> u16 tag, u16
>>>> const void *ptr, void *data)
>>>> {
>>>> const struct wmi_tlv_peer_stats_info *stat = ptr;
>>>> - struct ieee80211_sta *sta;
>>>> + u32 vdev_id = *(u32 *)data;
>>>> struct ath10k_sta *arsta;
>>>> + struct ath10k_peer *peer;
>>>> if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO)
>>>> return -EPROTO;
>>>> @@ -241,20 +243,20 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k
>>>> *ar, u16 tag, u16
>>>> __le32_to_cpu(stat->last_tx_rate_code),
>>>> __le32_to_cpu(stat->last_tx_bitrate_kbps));
>>>> - rcu_read_lock();
>>>> - sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL);
>>>> - if (!sta) {
>>>> - rcu_read_unlock();
>>>> - ath10k_warn(ar, "not found station for peer stats\n");
>>>> + guard(spinlock_bh)(&ar->data_lock);
>>>> +
>>>> + peer = ath10k_peer_find(ar, vdev_id, stat->peer_macaddr.addr);
>>>> + if (!peer || !peer->sta) {
>>>> + ath10k_warn(ar, "not found %s with vdev id %u mac addr %pM for peer stats\n",
>>>> + peer ? "sta" : "peer", vdev_id, stat->peer_macaddr.addr);
>>>> return -EINVAL;
>>>> }
>>>> - arsta = (struct ath10k_sta *)sta->drv_priv;
>>>> + arsta = (struct ath10k_sta *)peer->sta->drv_priv;
>>>> arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code);
>>>> arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps);
>>>> arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code);
>>>> arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps);
>>>> - rcu_read_unlock();
>>>> return 0;
>>>> }
>>>> @@ -266,6 +268,7 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
>>>> const struct wmi_tlv_peer_stats_info_ev *ev;
>>>> const void *data;
>>>> u32 num_peer_stats;
>>>> + u32 vdev_id;
>>>> int ret;
>>>> tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
>>>> @@ -284,15 +287,16 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k
>>>> *ar,
>>>> }
>>>> num_peer_stats = __le32_to_cpu(ev->num_peers);
>>>> + vdev_id = __le32_to_cpu(ev->vdev_id);
>>>> ath10k_dbg(ar, ATH10K_DBG_WMI,
>>>> "wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n",
>>>> - __le32_to_cpu(ev->vdev_id),
>>>> + vdev_id,
>>>> num_peer_stats,
>>>> __le32_to_cpu(ev->more_data));
>>>> ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data),
>>>> - ath10k_wmi_tlv_parse_peer_stats_info, NULL);
>>>> + ath10k_wmi_tlv_parse_peer_stats_info, &vdev_id);
>>>> if (ret)
>>>> ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret);
>>>
>>> Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
>>> Tested-by: Paul Menzel <pmenzel@molgen.mpg.de>
>>>
>>>
>>> Kind regards,
>>>
>>> Paul
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH ath-current] wifi: ath10k: fix station lookup failure during disconnect
2026-03-27 9:11 ` Baochen Qiang
@ 2026-03-27 9:27 ` Paul Menzel
0 siblings, 0 replies; 8+ messages in thread
From: Paul Menzel @ 2026-03-27 9:27 UTC (permalink / raw)
To: Baochen Qiang, Jeff Johnson; +Cc: linux-wireless, ath10k
Dear Baochen,
Thank you for your reply.
Am 27.03.26 um 10:11 schrieb Baochen Qiang:
> On 3/27/2026 4:43 PM, Paul Menzel wrote:
>> Am 27.03.26 um 03:54 schrieb Baochen Qiang:
>>
>>> On 3/27/2026 7:31 AM, Paul Menzel wrote:
>>
>> […]
>>
>>>> Am 25.03.26 um 04:05 schrieb Baochen Qiang:
>>>>> Recent commit [1] moved station statistics collection to an earlier stage
>>>>> of the disconnect flow. With this change in place, ath10k fails to resolve
>>>>> the station entry when handling a peer stats event triggered during
>>>>> disconnect, resulting in log messages such as:
>>>>>
>>>>> wlp58s0: deauthenticating from 74:1a:e0:e7:b4:c8 by local choice (Reason: 3=DEAUTH_LEAVING)
>>>>> ath10k_pci 0000:3a:00.0: not found station for peer stats
>>>>> ath10k_pci 0000:3a:00.0: failed to parse stats info tlv: -22
>>>>>
>>>>> The failure occurs because ath10k relies on ieee80211_find_sta_by_ifaddr()
>>>>> for station lookup. That function uses local->sta_hash, but by the time
>>>>> the peer stats request is triggered during disconnect, mac80211 has
>>>>> already removed the station from that hash table, leading to lookup
>>>>> failure.
>>>>>
>>>>> Before commit [1], this issue was not visible because the transition from
>>>>> IEEE80211_STA_NONE to IEEE80211_STA_NOTEXIST prevented ath10k from sending
>>>>> a peer stats request at all: ath10k_mac_sta_get_peer_stats_info() would
>>>>> fail early to find the peer and skip requesting statistics.
>>>>>
>>>>> Fix this by switching the lookup path to ath10k_peer_find(), which queries
>>>>> ath10k's internal peer table. At the point where the firmware emits the
>>>>> peer stats event, the peer entry is still present in the driver's list,
>>>>> ensuring lookup succeeds.
>>>>
>>>> Out of curiosity, how can the statistics be printed?
>>>
>>> not quite understand your question, can you be more detailed?
>>
>> The commit message starts with:
>>
>> “… moved station statistics collection to an earlier stage …”
>>
>> I was wondering how to print/dump these statistics.
>
> still not quite understand, but let me try to answer:
>
> mac80211 collects stats and send it to userspace over nl80211,
> userpsace tools like iw can print it out.
Thank you. It looks like, one way is `sudo iw dev wlp58s0 station dump`.
>>>>> Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00309-QCARMSWPZ-1
>>>>>
>>>>> Fixes: a203dbeeca15 ("wifi: mac80211: collect station statistics earlier when disconnect") # [1]
>>>>> Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
>>>>> Closes: https://lore.kernel.org/ath10k/57671b89-ec9f-4e6c-992c-45eb8e75929c@molgen.mpg.de
>>>>> Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
>>>>> ---
>>>>> drivers/net/wireless/ath/ath10k/wmi-tlv.c | 26 +++++++++++++++-----------
>>>>> 1 file changed, 15 insertions(+), 11 deletions(-)
>>>>>
>>>>> diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/
>>>>> ath10k/wmi-tlv.c
>>>>> index ec8e91707f84..01f2d1fa9d7d 100644
>>>>> --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
>>>>> +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
>>>>> @@ -3,7 +3,7 @@
>>>>> * Copyright (c) 2005-2011 Atheros Communications Inc.
>>>>> * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
>>>>> * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
>>>>> - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
>>>>> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
>>>>> */
>>>>> #include "core.h"
>>>>> #include "debug.h"
>>>>> @@ -14,6 +14,7 @@
>>>>> #include "wmi-tlv.h"
>>>>> #include "p2p.h"
>>>>> #include "testmode.h"
>>>>> +#include "txrx.h"
>>>>> #include <linux/bitfield.h>
>>>>> /***************/
>>>>> @@ -224,8 +225,9 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar,
>>>>> u16 tag, u16
>>>>> const void *ptr, void *data)
>>>>> {
>>>>> const struct wmi_tlv_peer_stats_info *stat = ptr;
>>>>> - struct ieee80211_sta *sta;
>>>>> + u32 vdev_id = *(u32 *)data;
>>>>> struct ath10k_sta *arsta;
>>>>> + struct ath10k_peer *peer;
>>>>> if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO)
>>>>> return -EPROTO;
>>>>> @@ -241,20 +243,20 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k
>>>>> *ar, u16 tag, u16
>>>>> __le32_to_cpu(stat->last_tx_rate_code),
>>>>> __le32_to_cpu(stat->last_tx_bitrate_kbps));
>>>>> - rcu_read_lock();
>>>>> - sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL);
>>>>> - if (!sta) {
>>>>> - rcu_read_unlock();
>>>>> - ath10k_warn(ar, "not found station for peer stats\n");
>>>>> + guard(spinlock_bh)(&ar->data_lock);
>>>>> +
>>>>> + peer = ath10k_peer_find(ar, vdev_id, stat->peer_macaddr.addr);
>>>>> + if (!peer || !peer->sta) {
>>>>> + ath10k_warn(ar, "not found %s with vdev id %u mac addr %pM for peer stats\n",
>>>>> + peer ? "sta" : "peer", vdev_id, stat->peer_macaddr.addr);
>>>>> return -EINVAL;
>>>>> }
>>>>> - arsta = (struct ath10k_sta *)sta->drv_priv;
>>>>> + arsta = (struct ath10k_sta *)peer->sta->drv_priv;
>>>>> arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code);
>>>>> arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps);
>>>>> arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code);
>>>>> arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps);
>>>>> - rcu_read_unlock();
>>>>> return 0;
>>>>> }
>>>>> @@ -266,6 +268,7 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
>>>>> const struct wmi_tlv_peer_stats_info_ev *ev;
>>>>> const void *data;
>>>>> u32 num_peer_stats;
>>>>> + u32 vdev_id;
>>>>> int ret;
>>>>> tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
>>>>> @@ -284,15 +287,16 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
>>>>> }
>>>>> num_peer_stats = __le32_to_cpu(ev->num_peers);
>>>>> + vdev_id = __le32_to_cpu(ev->vdev_id);
>>>>> ath10k_dbg(ar, ATH10K_DBG_WMI,
>>>>> "wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n",
>>>>> - __le32_to_cpu(ev->vdev_id),
>>>>> + vdev_id,
>>>>> num_peer_stats,
>>>>> __le32_to_cpu(ev->more_data));
>>>>> ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data),
>>>>> - ath10k_wmi_tlv_parse_peer_stats_info, NULL);
>>>>> + ath10k_wmi_tlv_parse_peer_stats_info, &vdev_id);
>>>>> if (ret)
>>>>> ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret);
>>>>
>>>> Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
>>>> Tested-by: Paul Menzel <pmenzel@molgen.mpg.de>
Kind regards,
Paul
PS: For the record:
```
$ sudo iw dev wlp58s0 station dump
Station 8c:6a:8d:xx:xx:xx (on wlp58s0)
authorized: yes
authenticated: yes
associated: yes
preamble: long
WMM/WME: yes
MFP: no
TDLS peer: no
inactive time: 136 ms
rx bytes: 42923460
rx packets: 30379
tx bytes: 527970
tx packets: 4543
tx retries: 0
tx failed: 0
beacon loss: 0
beacon rx: 254
rx drop misc: 104
signal: -35 [-43, -39] dBm
signal avg: -35 [-44, -37] dBm
beacon signal avg: -35 dBm
tx bitrate: 144.4 MBit/s MCS 15 short GI
tx duration: 1386481 us
rx bitrate: 144.4 MBit/s MCS 15 short GI
rx duration: 0 us
airtime weight: 256
DTIM period: 1
beacon interval:100
short slot time:yes
connected time: 61 seconds
associated at [boottime]: 6663.920s
associated at: 1774603392069 ms
current time: 1774603452468 ms
```
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH ath-current] wifi: ath10k: fix station lookup failure during disconnect
2026-03-25 3:05 [PATCH ath-current] wifi: ath10k: fix station lookup failure during disconnect Baochen Qiang
2026-03-26 23:31 ` Paul Menzel
@ 2026-03-31 4:54 ` Rameshkumar Sundaram
2026-04-08 0:50 ` Jeff Johnson
2 siblings, 0 replies; 8+ messages in thread
From: Rameshkumar Sundaram @ 2026-03-31 4:54 UTC (permalink / raw)
To: Baochen Qiang, Jeff Johnson; +Cc: linux-wireless, ath10k, pmenzel
On 3/25/2026 8:35 AM, Baochen Qiang wrote:
> Recent commit [1] moved station statistics collection to an earlier stage
> of the disconnect flow. With this change in place, ath10k fails to resolve
> the station entry when handling a peer stats event triggered during
> disconnect, resulting in log messages such as:
>
> wlp58s0: deauthenticating from 74:1a:e0:e7:b4:c8 by local choice (Reason: 3=DEAUTH_LEAVING)
> ath10k_pci 0000:3a:00.0: not found station for peer stats
> ath10k_pci 0000:3a:00.0: failed to parse stats info tlv: -22
>
> The failure occurs because ath10k relies on ieee80211_find_sta_by_ifaddr()
> for station lookup. That function uses local->sta_hash, but by the time
> the peer stats request is triggered during disconnect, mac80211 has
> already removed the station from that hash table, leading to lookup
> failure.
>
> Before commit [1], this issue was not visible because the transition from
> IEEE80211_STA_NONE to IEEE80211_STA_NOTEXIST prevented ath10k from sending
> a peer stats request at all: ath10k_mac_sta_get_peer_stats_info() would
> fail early to find the peer and skip requesting statistics.
>
> Fix this by switching the lookup path to ath10k_peer_find(), which queries
> ath10k's internal peer table. At the point where the firmware emits the
> peer stats event, the peer entry is still present in the driver's list,
> ensuring lookup succeeds.
>
> Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00309-QCARMSWPZ-1
>
> Fixes: a203dbeeca15 ("wifi: mac80211: collect station statistics earlier when disconnect") # [1]
> Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
> Closes: https://lore.kernel.org/ath10k/57671b89-ec9f-4e6c-992c-45eb8e75929c@molgen.mpg.de
> Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
> ---
> drivers/net/wireless/ath/ath10k/wmi-tlv.c | 26 +++++++++++++++-----------
> 1 file changed, 15 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
> index ec8e91707f84..01f2d1fa9d7d 100644
> --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
> +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
> @@ -3,7 +3,7 @@
> * Copyright (c) 2005-2011 Atheros Communications Inc.
> * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
> * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
> - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> */
> #include "core.h"
> #include "debug.h"
> @@ -14,6 +14,7 @@
> #include "wmi-tlv.h"
> #include "p2p.h"
> #include "testmode.h"
> +#include "txrx.h"
> #include <linux/bitfield.h>
>
> /***************/
> @@ -224,8 +225,9 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16
> const void *ptr, void *data)
> {
> const struct wmi_tlv_peer_stats_info *stat = ptr;
> - struct ieee80211_sta *sta;
> + u32 vdev_id = *(u32 *)data;
> struct ath10k_sta *arsta;
> + struct ath10k_peer *peer;
>
> if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO)
> return -EPROTO;
> @@ -241,20 +243,20 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16
> __le32_to_cpu(stat->last_tx_rate_code),
> __le32_to_cpu(stat->last_tx_bitrate_kbps));
>
> - rcu_read_lock();
> - sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL);
> - if (!sta) {
> - rcu_read_unlock();
> - ath10k_warn(ar, "not found station for peer stats\n");
> + guard(spinlock_bh)(&ar->data_lock);
> +
> + peer = ath10k_peer_find(ar, vdev_id, stat->peer_macaddr.addr);
> + if (!peer || !peer->sta) {
> + ath10k_warn(ar, "not found %s with vdev id %u mac addr %pM for peer stats\n",
> + peer ? "sta" : "peer", vdev_id, stat->peer_macaddr.addr);
> return -EINVAL;
> }
>
> - arsta = (struct ath10k_sta *)sta->drv_priv;
> + arsta = (struct ath10k_sta *)peer->sta->drv_priv;
> arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code);
> arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps);
> arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code);
> arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps);
> - rcu_read_unlock();
>
> return 0;
> }
> @@ -266,6 +268,7 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
> const struct wmi_tlv_peer_stats_info_ev *ev;
> const void *data;
> u32 num_peer_stats;
> + u32 vdev_id;
> int ret;
>
> tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
> @@ -284,15 +287,16 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
> }
>
> num_peer_stats = __le32_to_cpu(ev->num_peers);
> + vdev_id = __le32_to_cpu(ev->vdev_id);
>
> ath10k_dbg(ar, ATH10K_DBG_WMI,
> "wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n",
> - __le32_to_cpu(ev->vdev_id),
> + vdev_id,
> num_peer_stats,
> __le32_to_cpu(ev->more_data));
>
> ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data),
> - ath10k_wmi_tlv_parse_peer_stats_info, NULL);
> + ath10k_wmi_tlv_parse_peer_stats_info, &vdev_id);
> if (ret)
> ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret);
>
>
> ---
> base-commit: 4242625f272974dd1947f73b10d884eab3b277cd
> change-id: 20260325-ath10k-station-lookup-failure-be4dd6e81100
>
Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH ath-current] wifi: ath10k: fix station lookup failure during disconnect
2026-03-25 3:05 [PATCH ath-current] wifi: ath10k: fix station lookup failure during disconnect Baochen Qiang
2026-03-26 23:31 ` Paul Menzel
2026-03-31 4:54 ` Rameshkumar Sundaram
@ 2026-04-08 0:50 ` Jeff Johnson
2 siblings, 0 replies; 8+ messages in thread
From: Jeff Johnson @ 2026-04-08 0:50 UTC (permalink / raw)
To: Jeff Johnson, Baochen Qiang; +Cc: linux-wireless, ath10k, pmenzel
On Wed, 25 Mar 2026 11:05:01 +0800, Baochen Qiang wrote:
> Recent commit [1] moved station statistics collection to an earlier stage
> of the disconnect flow. With this change in place, ath10k fails to resolve
> the station entry when handling a peer stats event triggered during
> disconnect, resulting in log messages such as:
>
> wlp58s0: deauthenticating from 74:1a:e0:e7:b4:c8 by local choice (Reason: 3=DEAUTH_LEAVING)
> ath10k_pci 0000:3a:00.0: not found station for peer stats
> ath10k_pci 0000:3a:00.0: failed to parse stats info tlv: -22
>
> [...]
Applied, thanks!
[1/1] wifi: ath10k: fix station lookup failure during disconnect
commit: 9a34a59c6086ae731a06b3e61b0951feef758648
Best regards,
--
Jeff Johnson <jeff.johnson@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-04-08 0:50 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-25 3:05 [PATCH ath-current] wifi: ath10k: fix station lookup failure during disconnect Baochen Qiang
2026-03-26 23:31 ` Paul Menzel
2026-03-27 2:54 ` Baochen Qiang
2026-03-27 8:43 ` Paul Menzel
2026-03-27 9:11 ` Baochen Qiang
2026-03-27 9:27 ` Paul Menzel
2026-03-31 4:54 ` Rameshkumar Sundaram
2026-04-08 0:50 ` Jeff Johnson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox