]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: ath11k: move some firmware stats related functions outside of debugfs
authorBaochen Qiang <quic_bqiang@quicinc.com>
Thu, 20 Feb 2025 08:24:45 +0000 (16:24 +0800)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Sat, 7 Jun 2025 14:36:03 +0000 (07:36 -0700)
Commit b488c766442f ("ath11k: report rssi of each chain to mac80211 for QCA6390/WCN6855")
and commit c3b39553fc77 ("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: b488c766442f ("ath11k: report rssi of each chain to mac80211 for QCA6390/WCN6855")
Fixes: c3b39553fc77 ("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>
drivers/net/wireless/ath/ath11k/debugfs.c
drivers/net/wireless/ath/ath11k/debugfs.h
drivers/net/wireless/ath/ath11k/mac.c
drivers/net/wireless/ath/ath11k/mac.h
drivers/net/wireless/ath/ath11k/wmi.c

index ccf0e62c7d7aedd4b0dc8bb678ebe37f677c0b3a..5d46f8e4c231fb75577d997e24730f8c87033ec7 100644 (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;
index a39e458637b01366b430e138bbc53126196b512f..ed7fec177588f69659b0dd9bdf66d83b511f36f0 100644 (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,
index 5e098780cf236526b8f9d2f6b5e2078315f7e9c6..1550533b55876ff410dadb105301a795a99cd8bb 100644 (file)
@@ -8997,6 +8997,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,
@@ -9034,8 +9114,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);
        }
 
@@ -9043,8 +9123,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,
index f5800fbecff89e0a8e509cdbee005f3858d6b97a..5e61eea1bb0378a071c81b0b27133d75643a1d3b 100644 (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
index 27cb0bb06b93c8906367555de8354679f0621195..98811726d33bf19c47c59c54eecb4c1a50f44b68 100644 (file)
@@ -8158,6 +8158,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;
 
@@ -8184,7 +8189,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) {
@@ -8193,9 +8199,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);