wifi: ath11k: move some firmware stats related functions outside of debugfs

[ Upstream commit 72610ed7d79da17ee09102534d6c696a4ea8a08e ]

Commit b488c76644 ("ath11k: report rssi of each chain to mac80211 for QCA6390/WCN6855")
and commit c3b39553fc ("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:
Baochen Qiang
2025-02-20 16:24:45 +08:00
committed by Greg Kroah-Hartman
parent d849e671ff
commit 7b1a7d35ee
5 changed files with 135 additions and 138 deletions

View File

@@ -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;

View File

@@ -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,

View File

@@ -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,

View File

@@ -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

View File

@@ -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);