public inbox for linux-wireless@vger.kernel.org
 help / color / mirror / Atom feed
* [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