Message ID | 20240826014942.87783-4-quic_bqiang@quicinc.com |
---|---|
State | New |
Headers | show |
Series | wifi: ath11k: fix memory leak in reset scenario | expand |
On 8/25/2024 6:49 PM, Baochen Qiang wrote: > Currently ath12k_sta::rx_stats/tx_stats would only get freed when the station > transit from NONE to NOTEXIST state within ath11k_mac_op_sta_state(). However > in reset scenario, there is no chance for it to go through such transition. > Further, after reset, when a new connection to AP starts, ath12k_sta is zerod > in NOTEXIST to NONE transition, making rx_stats/tx_stats leaked: > > Kmemleak reports: > unreferenced object 0xffff9a3cd0a23400 (size 1024): > backtrace (crc 21ee4c52): > kmalloc_trace_noprof+0x2ba/0x360 > ath11k_mac_op_sta_state+0x1b6/0xca0 [ath11k] > drv_sta_state+0x11e/0x9c0 [mac80211] > sta_info_insert_rcu+0x469/0x880 [mac80211] > sta_info_insert+0x10/0x80 [mac80211] > ieee80211_prep_connection+0x295/0x950 [mac80211] > ieee80211_mgd_auth+0x230/0x5a0 [mac80211] > cfg80211_mlme_auth+0xeb/0x2a0 [cfg80211] > > Add a new function which frees them, and call it during reset to fix this issue. > > Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.30 > > Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") > Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com> Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 03187df26000..586217de9581 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -1972,6 +1972,7 @@ void ath11k_core_halt(struct ath11k *ar) ar->allocated_vdev_map = 0; ath11k_mac_scan_finish(ar); + ath11k_mac_station_cleanup_all(ar); ath11k_mac_peer_cleanup_all(ar); cancel_delayed_work_sync(&ar->scan.timeout); cancel_work_sync(&ar->regd_update_work); diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index f21d37cefb65..a02fd07f8f1c 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -9512,6 +9512,15 @@ static int ath11k_mac_station_add(struct ath11k *ar, return ret; } +static void ath11k_mac_station_free_stats(struct ath11k_sta *arsta) +{ + kfree(arsta->tx_stats); + arsta->tx_stats = NULL; + + kfree(arsta->rx_stats); + arsta->rx_stats = NULL; +} + static int ath11k_mac_station_remove(struct ath11k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta) @@ -9545,15 +9554,23 @@ static int ath11k_mac_station_remove(struct ath11k *ar, ath11k_mac_dec_num_stations(arvif, sta); - kfree(arsta->tx_stats); - arsta->tx_stats = NULL; - - kfree(arsta->rx_stats); - arsta->rx_stats = NULL; + ath11k_mac_station_free_stats(arsta); return ret; } +static void ath11k_mac_station_cleanup(void *data, struct ieee80211_sta *sta) +{ + ath11k_mac_station_free_stats(ath11k_sta_to_arsta(sta)); +} + +void ath11k_mac_station_cleanup_all(struct ath11k *ar) +{ + ieee80211_iterate_stations_atomic(ar->hw, + ath11k_mac_station_cleanup, + NULL); +} + static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h index f5800fbecff8..17d0bbfc52bf 100644 --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef ATH11K_MAC_H @@ -179,4 +179,5 @@ int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif, void ath11k_mac_fill_reg_tpc_info(struct ath11k *ar, struct ieee80211_vif *vif, struct ieee80211_chanctx_conf *ctx); +void ath11k_mac_station_cleanup_all(struct ath11k *ar); #endif
Currently ath12k_sta::rx_stats/tx_stats would only get freed when the station transit from NONE to NOTEXIST state within ath11k_mac_op_sta_state(). However in reset scenario, there is no chance for it to go through such transition. Further, after reset, when a new connection to AP starts, ath12k_sta is zerod in NOTEXIST to NONE transition, making rx_stats/tx_stats leaked: Kmemleak reports: unreferenced object 0xffff9a3cd0a23400 (size 1024): backtrace (crc 21ee4c52): kmalloc_trace_noprof+0x2ba/0x360 ath11k_mac_op_sta_state+0x1b6/0xca0 [ath11k] drv_sta_state+0x11e/0x9c0 [mac80211] sta_info_insert_rcu+0x469/0x880 [mac80211] sta_info_insert+0x10/0x80 [mac80211] ieee80211_prep_connection+0x295/0x950 [mac80211] ieee80211_mgd_auth+0x230/0x5a0 [mac80211] cfg80211_mlme_auth+0xeb/0x2a0 [cfg80211] Add a new function which frees them, and call it during reset to fix this issue. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.30 Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com> --- drivers/net/wireless/ath/ath11k/core.c | 1 + drivers/net/wireless/ath/ath11k/mac.c | 27 +++++++++++++++++++++----- drivers/net/wireless/ath/ath11k/mac.h | 3 ++- 3 files changed, 25 insertions(+), 6 deletions(-)