Skip to content

Commit 2546335

Browse files
Baochen Qianggregkh
authored andcommitted
wifi: ath10k: fix station lookup failure during disconnect
[ Upstream commit 9a34a59 ] 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: a203dbe ("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> Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de> Tested-by: Paul Menzel <pmenzel@molgen.mpg.de> Link: https://patch.msgid.link/20260325-ath10k-station-lookup-failure-v1-1-2e0c970f25d5@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 76f2eba commit 2546335

1 file changed

Lines changed: 15 additions & 11 deletions

File tree

drivers/net/wireless/ath/ath10k/wmi-tlv.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Copyright (c) 2005-2011 Atheros Communications Inc.
44
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
55
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
6-
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
6+
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
77
*/
88
#include "core.h"
99
#include "debug.h"
@@ -14,6 +14,7 @@
1414
#include "wmi-tlv.h"
1515
#include "p2p.h"
1616
#include "testmode.h"
17+
#include "txrx.h"
1718
#include <linux/bitfield.h>
1819

1920
/***************/
@@ -224,8 +225,9 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16
224225
const void *ptr, void *data)
225226
{
226227
const struct wmi_tlv_peer_stats_info *stat = ptr;
227-
struct ieee80211_sta *sta;
228+
u32 vdev_id = *(u32 *)data;
228229
struct ath10k_sta *arsta;
230+
struct ath10k_peer *peer;
229231

230232
if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO)
231233
return -EPROTO;
@@ -241,20 +243,20 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16
241243
__le32_to_cpu(stat->last_tx_rate_code),
242244
__le32_to_cpu(stat->last_tx_bitrate_kbps));
243245

244-
rcu_read_lock();
245-
sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL);
246-
if (!sta) {
247-
rcu_read_unlock();
248-
ath10k_warn(ar, "not found station for peer stats\n");
246+
guard(spinlock_bh)(&ar->data_lock);
247+
248+
peer = ath10k_peer_find(ar, vdev_id, stat->peer_macaddr.addr);
249+
if (!peer || !peer->sta) {
250+
ath10k_warn(ar, "not found %s with vdev id %u mac addr %pM for peer stats\n",
251+
peer ? "sta" : "peer", vdev_id, stat->peer_macaddr.addr);
249252
return -EINVAL;
250253
}
251254

252-
arsta = (struct ath10k_sta *)sta->drv_priv;
255+
arsta = (struct ath10k_sta *)peer->sta->drv_priv;
253256
arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code);
254257
arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps);
255258
arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code);
256259
arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps);
257-
rcu_read_unlock();
258260

259261
return 0;
260262
}
@@ -266,6 +268,7 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
266268
const struct wmi_tlv_peer_stats_info_ev *ev;
267269
const void *data;
268270
u32 num_peer_stats;
271+
u32 vdev_id;
269272
int ret;
270273

271274
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,
284287
}
285288

286289
num_peer_stats = __le32_to_cpu(ev->num_peers);
290+
vdev_id = __le32_to_cpu(ev->vdev_id);
287291

288292
ath10k_dbg(ar, ATH10K_DBG_WMI,
289293
"wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n",
290-
__le32_to_cpu(ev->vdev_id),
294+
vdev_id,
291295
num_peer_stats,
292296
__le32_to_cpu(ev->more_data));
293297

294298
ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data),
295-
ath10k_wmi_tlv_parse_peer_stats_info, NULL);
299+
ath10k_wmi_tlv_parse_peer_stats_info, &vdev_id);
296300
if (ret)
297301
ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret);
298302

0 commit comments

Comments
 (0)