wifi: ath11k: move some firmware stats related functions outside of debugfs
[ Upstream commit 72610ed7d79da17ee09102534d6c696a4ea8a08e ] Commitb488c76644("ath11k: report rssi of each chain to mac80211 for QCA6390/WCN6855") and commitc3b39553fc("ath11k: add signal report to mac80211 for QCA6390 and WCN6855") call debugfs functions in mac ops. Those functions are no-ops if CONFIG_ATH11K_DEBUGFS is not enabled, thus cause wrong status reported. Move them to mac.c. Besides, since WMI_REQUEST_RSSI_PER_CHAIN_STAT and WMI_REQUEST_VDEV_STAT stats could also be requested via mac ops, process them directly in ath11k_update_stats_event(). Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37 Fixes:b488c76644("ath11k: report rssi of each chain to mac80211 for QCA6390/WCN6855") Fixes:c3b39553fc("ath11k: add signal report to mac80211 for QCA6390 and WCN6855") Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com> Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com> Link: https://patch.msgid.link/20250220082448.31039-5-quic_bqiang@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
d849e671ff
commit
7b1a7d35ee
@@ -93,58 +93,14 @@ void ath11k_debugfs_add_dbring_entry(struct ath11k *ar,
|
||||
spin_unlock_bh(&dbr_data->lock);
|
||||
}
|
||||
|
||||
static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar)
|
||||
{
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
|
||||
ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs);
|
||||
ar->fw_stats.num_vdev_recvd = 0;
|
||||
ar->fw_stats.num_bcn_recvd = 0;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_pdev *pdev;
|
||||
bool is_end = true;
|
||||
size_t total_vdevs_started = 0;
|
||||
int i;
|
||||
|
||||
/* WMI_REQUEST_PDEV_STAT request has been already processed */
|
||||
|
||||
if (stats->stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
|
||||
complete(&ar->fw_stats_done);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stats->stats_id == WMI_REQUEST_VDEV_STAT) {
|
||||
if (list_empty(&stats->vdevs)) {
|
||||
ath11k_warn(ab, "empty vdev stats");
|
||||
return;
|
||||
}
|
||||
/* FW sends all the active VDEV stats irrespective of PDEV,
|
||||
* hence limit until the count of all VDEVs started
|
||||
*/
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = rcu_dereference(ab->pdevs_active[i]);
|
||||
if (pdev && pdev->ar)
|
||||
total_vdevs_started += ar->num_started_vdevs;
|
||||
}
|
||||
|
||||
if (total_vdevs_started)
|
||||
is_end = ((++ar->fw_stats.num_vdev_recvd) ==
|
||||
total_vdevs_started);
|
||||
|
||||
list_splice_tail_init(&stats->vdevs,
|
||||
&ar->fw_stats.vdevs);
|
||||
|
||||
if (is_end)
|
||||
complete(&ar->fw_stats_done);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* WMI_REQUEST_PDEV_STAT, WMI_REQUEST_RSSI_PER_CHAIN_STAT and
|
||||
* WMI_REQUEST_VDEV_STAT requests have been already processed.
|
||||
*/
|
||||
if (stats->stats_id == WMI_REQUEST_BCN_STAT) {
|
||||
if (list_empty(&stats->bcn)) {
|
||||
ath11k_warn(ab, "empty bcn stats");
|
||||
@@ -165,76 +121,6 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *
|
||||
}
|
||||
}
|
||||
|
||||
static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
|
||||
struct stats_request_params *req_param)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
unsigned long time_left;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
ath11k_debugfs_fw_stats_reset(ar);
|
||||
|
||||
reinit_completion(&ar->fw_stats_complete);
|
||||
reinit_completion(&ar->fw_stats_done);
|
||||
|
||||
ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
|
||||
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "could not request fw stats (%d)\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ);
|
||||
if (!time_left)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* FW stats can get split when exceeding the stats data buffer limit.
|
||||
* In that case, since there is no end marking for the back-to-back
|
||||
* received 'update stats' event, we keep a 3 seconds timeout in case,
|
||||
* fw_stats_done is not marked yet
|
||||
*/
|
||||
time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ);
|
||||
if (!time_left)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
|
||||
u32 vdev_id, u32 stats_id)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct stats_request_params req_param;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH11K_STATE_ON) {
|
||||
ret = -ENETDOWN;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
req_param.pdev_id = pdev_id;
|
||||
req_param.vdev_id = vdev_id;
|
||||
req_param.stats_id = stats_id;
|
||||
|
||||
ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to request fw stats: %d\n", ret);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"debug get fw stat pdev id %d vdev id %d stats id 0x%x\n",
|
||||
pdev_id, vdev_id, stats_id);
|
||||
|
||||
err_unlock:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct ath11k *ar = inode->i_private;
|
||||
@@ -260,7 +146,7 @@ static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
|
||||
req_param.vdev_id = 0;
|
||||
req_param.stats_id = WMI_REQUEST_PDEV_STAT;
|
||||
|
||||
ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
|
||||
ret = ath11k_mac_fw_stats_request(ar, &req_param);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
|
||||
goto err_free;
|
||||
@@ -331,7 +217,7 @@ static int ath11k_open_vdev_stats(struct inode *inode, struct file *file)
|
||||
req_param.vdev_id = 0;
|
||||
req_param.stats_id = WMI_REQUEST_VDEV_STAT;
|
||||
|
||||
ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
|
||||
ret = ath11k_mac_fw_stats_request(ar, &req_param);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
|
||||
goto err_free;
|
||||
@@ -407,7 +293,7 @@ static int ath11k_open_bcn_stats(struct inode *inode, struct file *file)
|
||||
continue;
|
||||
|
||||
req_param.vdev_id = arvif->vdev_id;
|
||||
ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
|
||||
ret = ath11k_mac_fw_stats_request(ar, &req_param);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
|
||||
goto err_free;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2022, 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _ATH11K_DEBUGFS_H_
|
||||
@@ -273,8 +273,6 @@ void ath11k_debugfs_unregister(struct ath11k *ar);
|
||||
void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats);
|
||||
|
||||
void ath11k_debugfs_fw_stats_init(struct ath11k *ar);
|
||||
int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
|
||||
u32 vdev_id, u32 stats_id);
|
||||
|
||||
static inline bool ath11k_debugfs_is_pktlog_lite_mode_enabled(struct ath11k *ar)
|
||||
{
|
||||
@@ -381,12 +379,6 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ath11k_debugfs_get_fw_stats(struct ath11k *ar,
|
||||
u32 pdev_id, u32 vdev_id, u32 stats_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ath11k_debugfs_add_dbring_entry(struct ath11k *ar,
|
||||
enum wmi_direct_buffer_module id,
|
||||
|
||||
@@ -8938,6 +8938,86 @@ static void ath11k_mac_put_chain_rssi(struct station_info *sinfo,
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_mac_fw_stats_reset(struct ath11k *ar)
|
||||
{
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
|
||||
ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs);
|
||||
ar->fw_stats.num_vdev_recvd = 0;
|
||||
ar->fw_stats.num_bcn_recvd = 0;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
int ath11k_mac_fw_stats_request(struct ath11k *ar,
|
||||
struct stats_request_params *req_param)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
unsigned long time_left;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
ath11k_mac_fw_stats_reset(ar);
|
||||
|
||||
reinit_completion(&ar->fw_stats_complete);
|
||||
reinit_completion(&ar->fw_stats_done);
|
||||
|
||||
ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
|
||||
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "could not request fw stats (%d)\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ);
|
||||
if (!time_left)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* FW stats can get split when exceeding the stats data buffer limit.
|
||||
* In that case, since there is no end marking for the back-to-back
|
||||
* received 'update stats' event, we keep a 3 seconds timeout in case,
|
||||
* fw_stats_done is not marked yet
|
||||
*/
|
||||
time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ);
|
||||
if (!time_left)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_mac_get_fw_stats(struct ath11k *ar, u32 pdev_id,
|
||||
u32 vdev_id, u32 stats_id)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct stats_request_params req_param;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH11K_STATE_ON) {
|
||||
ret = -ENETDOWN;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
req_param.pdev_id = pdev_id;
|
||||
req_param.vdev_id = vdev_id;
|
||||
req_param.stats_id = stats_id;
|
||||
|
||||
ret = ath11k_mac_fw_stats_request(ar, &req_param);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to request fw stats: %d\n", ret);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"debug get fw stat pdev id %d vdev id %d stats id 0x%x\n",
|
||||
pdev_id, vdev_id, stats_id);
|
||||
|
||||
err_unlock:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
@@ -8975,8 +9055,8 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
|
||||
if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) &&
|
||||
arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA &&
|
||||
ar->ab->hw_params.supports_rssi_stats &&
|
||||
!ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0,
|
||||
WMI_REQUEST_RSSI_PER_CHAIN_STAT)) {
|
||||
!ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0,
|
||||
WMI_REQUEST_RSSI_PER_CHAIN_STAT)) {
|
||||
ath11k_mac_put_chain_rssi(sinfo, arsta, "fw stats", true);
|
||||
}
|
||||
|
||||
@@ -8984,8 +9064,8 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
|
||||
if (!signal &&
|
||||
arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA &&
|
||||
ar->ab->hw_params.supports_rssi_stats &&
|
||||
!(ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0,
|
||||
WMI_REQUEST_VDEV_STAT)))
|
||||
!(ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0,
|
||||
WMI_REQUEST_VDEV_STAT)))
|
||||
signal = arsta->rssi_beacon;
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
|
||||
@@ -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-2023, 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH11K_MAC_H
|
||||
@@ -179,4 +179,6 @@ 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);
|
||||
int ath11k_mac_fw_stats_request(struct ath11k *ar,
|
||||
struct stats_request_params *req_param);
|
||||
#endif
|
||||
|
||||
@@ -8157,6 +8157,11 @@ static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff
|
||||
static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
struct ath11k_fw_stats stats = {};
|
||||
size_t total_vdevs_started = 0;
|
||||
struct ath11k_pdev *pdev;
|
||||
bool is_end = true;
|
||||
int i;
|
||||
|
||||
struct ath11k *ar;
|
||||
int ret;
|
||||
|
||||
@@ -8183,7 +8188,8 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
/* WMI_REQUEST_PDEV_STAT can be requested via .get_txpower mac ops or via
|
||||
/* WMI_REQUEST_PDEV_STAT, WMI_REQUEST_VDEV_STAT and
|
||||
* WMI_REQUEST_RSSI_PER_CHAIN_STAT can be requested via mac ops or via
|
||||
* debugfs fw stats. Therefore, processing it separately.
|
||||
*/
|
||||
if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
|
||||
@@ -8192,9 +8198,40 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk
|
||||
goto complete;
|
||||
}
|
||||
|
||||
/* WMI_REQUEST_VDEV_STAT, WMI_REQUEST_BCN_STAT and WMI_REQUEST_RSSI_PER_CHAIN_STAT
|
||||
* are currently requested only via debugfs fw stats. Hence, processing these
|
||||
* in debugfs context
|
||||
if (stats.stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
|
||||
complete(&ar->fw_stats_done);
|
||||
goto complete;
|
||||
}
|
||||
|
||||
if (stats.stats_id == WMI_REQUEST_VDEV_STAT) {
|
||||
if (list_empty(&stats.vdevs)) {
|
||||
ath11k_warn(ab, "empty vdev stats");
|
||||
goto complete;
|
||||
}
|
||||
/* FW sends all the active VDEV stats irrespective of PDEV,
|
||||
* hence limit until the count of all VDEVs started
|
||||
*/
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = rcu_dereference(ab->pdevs_active[i]);
|
||||
if (pdev && pdev->ar)
|
||||
total_vdevs_started += ar->num_started_vdevs;
|
||||
}
|
||||
|
||||
if (total_vdevs_started)
|
||||
is_end = ((++ar->fw_stats.num_vdev_recvd) ==
|
||||
total_vdevs_started);
|
||||
|
||||
list_splice_tail_init(&stats.vdevs,
|
||||
&ar->fw_stats.vdevs);
|
||||
|
||||
if (is_end)
|
||||
complete(&ar->fw_stats_done);
|
||||
|
||||
goto complete;
|
||||
}
|
||||
|
||||
/* WMI_REQUEST_BCN_STAT is currently requested only via debugfs fw stats.
|
||||
* Hence, processing it in debugfs context
|
||||
*/
|
||||
ath11k_debugfs_fw_stats_process(ar, &stats);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user