linux/drivers/net/wireless/ath/ath12k/debugfs.c

1516 lines
43 KiB
C
Raw Permalink Normal View History

// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
wifi: ath12k: Request vdev stats from firmware Add support to request and print vdev stats from firmware through WMI. Sample output: ------------- cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/fw_stats/vdev_stats ath12k VDEV stats ================= VDEV ID 0 VDEV MAC address 00:03:7f:6c:9c:1a beacon snr 96 data snr 255 num rx frames 0 num rts fail 0 num rts success 0 num rx err 0 num rx discard 0 num tx not acked 0 num tx frames [00] 0 num tx frames [01] 0 num tx frames [02] 0 num tx frames [03] 2 num tx frames retries [00] 0 num tx frames retries [01] 0 num tx frames retries [02] 0 num tx frames retries [03] 0 num tx frames failures [00] 0 num tx frames failures [01] 0 num tx frames failures [02] 0 num tx frames failures [03] 0 tx rate history [00] 0x00000000 tx rate history [01] 0x00000000 tx rate history [02] 0x00000000 tx rate history [03] 0x00000000 tx rate history [04] 0x00000000 tx rate history [05] 0x00000000 tx rate history [06] 0x00000000 tx rate history [07] 0x00000000 tx rate history [08] 0x00000000 tx rate history [09] 0x00000000 beacon rssi history [00] 0 beacon rssi history [01] 0 beacon rssi history [02] 0 beacon rssi history [03] 0 beacon rssi history [04] 0 beacon rssi history [05] 0 beacon rssi history [06] 0 beacon rssi history [07] 0 beacon rssi history [08] 0 beacon rssi history [09] 0 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250124185330.1244585-2-ramya.gnanasekar@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-25 00:23:28 +05:30
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "core.h"
wifi: ath12k: Add peer extended Rx statistics debugfs support Currently, peer extended Rx statistics are not supported. Therefore, expose peer extended Rx statistics support through debugfs, allowing users to enable or disable the collection of statistics information. After that the statistics information can be dumped through debugfs. Below are the debugfs commands exposed. Enable/Disable: echo <1/0> > /sys/kernel/debug/ieee80211/phyX/ath12k/ext_rx_stats Dump: cat /sys/kernel/debug/ieee80211/phyX/netdev:wlanX/stations/<peer MAC addr>/rx_stats Sample output: ============== RX peer stats: Num of MSDUs: 1087 Num of MSDUs with TCP L4: 0 Num of MSDUs with UDP L4: 13 Num of other MSDUs: 1074 Num of MSDUs part of AMPDU: 363 Num of MSDUs not part of AMPDU: 724 Num of MSDUs using STBC: 0 Num of MSDUs beamformed: 0 Num of MPDUs with FCS ok: 695 Num of MPDUs with FCS error: 0 preamble: 11A 395 11B 0 11N 0 11AC 0 11AX 692 11BE 0 reception type: SU 1087 MU_MIMO 0 MU_OFDMA 0 MU_OFDMA_MIMO 0 TID(0-15) Legacy TID(16):690 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 395 RX Duration:39537 DCM: 0 RU26: 0 RU52: 0 RU106: 0 RU242: 0 RU484: 0 RU996: 0 RX success packet stats: EHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 HE stats: MCS 0: 1 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 66 MCS 7: 46 MCS 8: 46 MCS 9: 34 MCS 10: 28 MCS 11: 471 VHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 HT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 MCS 16: 0 MCS 17: 0 MCS 18: 0 MCS 19: 0 MCS 20: 0 MCS 21: 0 MCS 22: 0 MCS 23: 0 MCS 24: 0 MCS 25: 0 MCS 26: 0 MCS 27: 0 MCS 28: 0 MCS 29: 0 MCS 30: 0 MCS 31: 0 Legacy stats: 1 Mbps: 0 2 Mbps: 0 5.5 Mbps: 0 6 Mbps: 395 9 Mbps: 0 11 Mbps: 0 12 Mbps: 0 18 Mbps: 0 24 Mbps: 0 36 Mbps: 0 48 Mbps: 0 54 Mbps: 0 NSS stats: 1x1: 1086 2x2: 0 3x3: 0 4x4: 0 5x5: 0 6x6: 0 7x7: 0 8x8: 0 GI: 0.8 us 0 0.4 us 396 1.6 us 691 3.2 us 0 BW: 20 MHz 785 40 MHz 2 80 MHz 300 160 MHz 0 320 MHz 0 20 Mhz gi 1 us 1x1 : 6:5 7:3 8:3 9:4 10:4 11:374 12:391 40 Mhz gi 1 us 1x1 : 12:2 80 Mhz gi 1 us 1x1 : 6:61 7:43 8:43 9:30 10:24 11:97 12:2 RX success byte stats: EHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 HE stats: MCS 0: 41 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 1435 MCS 7: 943 MCS 8: 697 MCS 9: 533 MCS 10: 492 MCS 11: 8159 VHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 HT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 MCS 16: 0 MCS 17: 0 MCS 18: 0 MCS 19: 0 MCS 20: 0 MCS 21: 0 MCS 22: 0 MCS 23: 0 MCS 24: 0 MCS 25: 0 MCS 26: 0 MCS 27: 0 MCS 28: 0 MCS 29: 0 MCS 30: 0 MCS 31: 0 Legacy stats: 1 Mbps: 0 2 Mbps: 0 5.5 Mbps: 0 6 Mbps: 16195 9 Mbps: 0 11 Mbps: 0 12 Mbps: 0 18 Mbps: 0 24 Mbps: 0 36 Mbps: 0 48 Mbps: 0 54 Mbps: 0 NSS stats: 1x1: 28454 2x2: 0 3x3: 0 4x4: 0 5x5: 0 6x6: 0 7x7: 0 8x8: 0 GI: 0.8 us 0 0.4 us 16236 1.6 us 12259 3.2 us 0 BW: 20 MHz 24108 40 MHz 82 80 MHz 4305 160 MHz 0 320 MHz 0 20 Mhz gi 1 us 1x1 : 6:205 7:123 8:123 9:164 10:164 11:7257 12:16031 40 Mhz gi 1 us 1x1 : 12:82 80 Mhz gi 1 us 1x1 : 6:1230 7:820 8:574 9:369 10:328 11:902 12:82 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Co-developed-by: P Praneesh <quic_ppranees@quicinc.com> Signed-off-by: P Praneesh <quic_ppranees@quicinc.com> Co-developed-by: Balamurugan Mahalingam <quic_bmahalin@quicinc.com> Signed-off-by: Balamurugan Mahalingam <quic_bmahalin@quicinc.com> Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com> Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com> Link: https://patch.msgid.link/20250206013854.174765-10-quic_periyasa@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-02-06 07:08:54 +05:30
#include "dp_tx.h"
wifi: ath12k: Request vdev stats from firmware Add support to request and print vdev stats from firmware through WMI. Sample output: ------------- cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/fw_stats/vdev_stats ath12k VDEV stats ================= VDEV ID 0 VDEV MAC address 00:03:7f:6c:9c:1a beacon snr 96 data snr 255 num rx frames 0 num rts fail 0 num rts success 0 num rx err 0 num rx discard 0 num tx not acked 0 num tx frames [00] 0 num tx frames [01] 0 num tx frames [02] 0 num tx frames [03] 2 num tx frames retries [00] 0 num tx frames retries [01] 0 num tx frames retries [02] 0 num tx frames retries [03] 0 num tx frames failures [00] 0 num tx frames failures [01] 0 num tx frames failures [02] 0 num tx frames failures [03] 0 tx rate history [00] 0x00000000 tx rate history [01] 0x00000000 tx rate history [02] 0x00000000 tx rate history [03] 0x00000000 tx rate history [04] 0x00000000 tx rate history [05] 0x00000000 tx rate history [06] 0x00000000 tx rate history [07] 0x00000000 tx rate history [08] 0x00000000 tx rate history [09] 0x00000000 beacon rssi history [00] 0 beacon rssi history [01] 0 beacon rssi history [02] 0 beacon rssi history [03] 0 beacon rssi history [04] 0 beacon rssi history [05] 0 beacon rssi history [06] 0 beacon rssi history [07] 0 beacon rssi history [08] 0 beacon rssi history [09] 0 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250124185330.1244585-2-ramya.gnanasekar@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-25 00:23:28 +05:30
#include "debug.h"
#include "debugfs.h"
#include "debugfs_htt_stats.h"
static ssize_t ath12k_write_simulate_radar(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath12k *ar = file->private_data;
int ret;
wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
ret = ath12k_wmi_simulate_radar(ar);
if (ret)
goto exit;
ret = count;
exit:
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return ret;
}
static const struct file_operations fops_simulate_radar = {
.write = ath12k_write_simulate_radar,
.open = simple_open
};
static ssize_t ath12k_read_simulate_fw_crash(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
const char buf[] =
"To simulate firmware crash write one of the keywords to this file:\n"
"`assert` - send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n";
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
}
static ssize_t
ath12k_write_simulate_fw_crash(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath12k_base *ab = file->private_data;
struct ath12k_pdev *pdev;
struct ath12k *ar = NULL;
char buf[32] = {};
int i, ret;
ssize_t rc;
/* filter partial writes and invalid commands */
if (*ppos != 0 || count >= sizeof(buf) || count == 0)
return -EINVAL;
rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
if (rc < 0)
return rc;
/* drop the possible '\n' from the end */
if (buf[*ppos - 1] == '\n')
buf[*ppos - 1] = '\0';
for (i = 0; i < ab->num_radios; i++) {
pdev = &ab->pdevs[i];
ar = pdev->ar;
if (ar)
break;
}
if (!ar)
return -ENETDOWN;
if (!strcmp(buf, "assert")) {
ath12k_info(ab, "simulating firmware assert crash\n");
ret = ath12k_wmi_force_fw_hang_cmd(ar,
ATH12K_WMI_FW_HANG_ASSERT_TYPE,
ATH12K_WMI_FW_HANG_DELAY);
} else {
return -EINVAL;
}
if (ret) {
ath12k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
return ret;
}
return count;
}
static const struct file_operations fops_simulate_fw_crash = {
.read = ath12k_read_simulate_fw_crash,
.write = ath12k_write_simulate_fw_crash,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
wifi: ath12k: Add Support to Calculate and Display TPC Values Transmit Power Control(TPC) stats should display per chain TPC value per radio. Add debugfs support to read and display TPC stats type and TPC stats. Take power values for each preamble type, rate and NSS combination from a particular index from each power arrays based on number of chains, NSS, modes, MCS and tx beamforming enabled/disabled parameters. Minimum of the values taken from reg power table, rates and Conformance Test Limit(CTL) array table should give the TPC which is in 0.25 dBm steps. Sample Output: ------------- echo 1 > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats_type cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats *************** TPC config ************** * powers are in 0.25 dBm steps reg domain-22 chan freq-5955 power limit-126 max reg-domain Power-252 No.of tx chain-4 No.of rates-1164 **************** SU WITH TXBF **************** TPC values for Active chains Rate idx Preamble Rate code 1-Chain 2-Chain 3-Chain 4-Chain 4 OFDM 0x000 39 15 1 -9 5 OFDM 0x001 39 15 1 -9 ..... 12 HT20 0x200 40 16 2 -8 13 HT20 0x201 40 16 2 -8 ..... 44 HT40 0x200 88 88 88 88 45 HT40 0x201 88 88 88 88 ..... 76 VHT20 0x300 40 16 2 -8 77 VHT20 0x301 40 16 2 -8 ..... 172 VHT40 0x300 88 88 88 88 173 VHT40 0x301 88 88 88 88 ..... 412 HE20 0x400 88 88 88 88 413 HE20 0x401 88 88 88 88 ..... 508 HE40 0x400 76 76 76 76 509 HE40 0x401 76 76 76 76 ..... 748 EHT20 0x50e 88 88 88 88 749 EHT20 0x50f 88 88 88 88 ..... 812 EHT40 0x50e 88 88 88 88 813 EHT40 0x50f 88 88 88 88 ..... Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sowmiya Sree Elavalagan <quic_ssreeela@quicinc.com> Co-developed-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Co-developed-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Signed-off-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250130061104.962124-3-quic_rdevanat@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-30 11:41:04 +05:30
static ssize_t ath12k_write_tpc_stats_type(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath12k *ar = file->private_data;
u8 type;
int ret;
ret = kstrtou8_from_user(user_buf, count, 0, &type);
if (ret)
return ret;
if (type >= WMI_HALPHY_PDEV_TX_STATS_MAX)
return -EINVAL;
spin_lock_bh(&ar->data_lock);
ar->debug.tpc_stats_type = type;
spin_unlock_bh(&ar->data_lock);
return count;
}
wifi: ath12k: Add Support to Parse TPC Event from Firmware Host receives four Transmit Power Control(TPC) events from firmware on sending TPC request. Fixed param TLV is present as part of all event to indicate the event count and end of event. TPC config parameters along with regulatory power array comes as first event. Rates array comes as second and third event as it cannot be packed in single event. Conformance Test Limit (CTL) power array comes as the fourth event. Firmware packs different sets of array params which includes array length and type inside master TLV as different subtlvs. And the actual content of array is packed one after the other inside a separate TLV as single buffer. Parse various events and save it in local structures. Create tpc_stats file using debugfs to store these local structures. Create function to handle TPC stats read to relay the information to the user. Command usage: cat > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sowmiya Sree Elavalagan <quic_ssreeela@quicinc.com> Co-developed-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Co-developed-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Signed-off-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250130061104.962124-2-quic_rdevanat@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-30 11:41:03 +05:30
static int ath12k_debug_tpc_stats_request(struct ath12k *ar)
{
enum wmi_halphy_ctrl_path_stats_id tpc_stats_sub_id;
struct ath12k_base *ab = ar->ab;
int ret;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
reinit_completion(&ar->debug.tpc_complete);
spin_lock_bh(&ar->data_lock);
ar->debug.tpc_request = true;
tpc_stats_sub_id = ar->debug.tpc_stats_type;
spin_unlock_bh(&ar->data_lock);
ret = ath12k_wmi_send_tpc_stats_request(ar, tpc_stats_sub_id);
if (ret) {
ath12k_warn(ab, "failed to request pdev tpc stats: %d\n", ret);
spin_lock_bh(&ar->data_lock);
ar->debug.tpc_request = false;
spin_unlock_bh(&ar->data_lock);
return ret;
}
return 0;
}
wifi: ath12k: Add Support to Calculate and Display TPC Values Transmit Power Control(TPC) stats should display per chain TPC value per radio. Add debugfs support to read and display TPC stats type and TPC stats. Take power values for each preamble type, rate and NSS combination from a particular index from each power arrays based on number of chains, NSS, modes, MCS and tx beamforming enabled/disabled parameters. Minimum of the values taken from reg power table, rates and Conformance Test Limit(CTL) array table should give the TPC which is in 0.25 dBm steps. Sample Output: ------------- echo 1 > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats_type cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats *************** TPC config ************** * powers are in 0.25 dBm steps reg domain-22 chan freq-5955 power limit-126 max reg-domain Power-252 No.of tx chain-4 No.of rates-1164 **************** SU WITH TXBF **************** TPC values for Active chains Rate idx Preamble Rate code 1-Chain 2-Chain 3-Chain 4-Chain 4 OFDM 0x000 39 15 1 -9 5 OFDM 0x001 39 15 1 -9 ..... 12 HT20 0x200 40 16 2 -8 13 HT20 0x201 40 16 2 -8 ..... 44 HT40 0x200 88 88 88 88 45 HT40 0x201 88 88 88 88 ..... 76 VHT20 0x300 40 16 2 -8 77 VHT20 0x301 40 16 2 -8 ..... 172 VHT40 0x300 88 88 88 88 173 VHT40 0x301 88 88 88 88 ..... 412 HE20 0x400 88 88 88 88 413 HE20 0x401 88 88 88 88 ..... 508 HE40 0x400 76 76 76 76 509 HE40 0x401 76 76 76 76 ..... 748 EHT20 0x50e 88 88 88 88 749 EHT20 0x50f 88 88 88 88 ..... 812 EHT40 0x50e 88 88 88 88 813 EHT40 0x50f 88 88 88 88 ..... Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sowmiya Sree Elavalagan <quic_ssreeela@quicinc.com> Co-developed-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Co-developed-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Signed-off-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250130061104.962124-3-quic_rdevanat@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-30 11:41:04 +05:30
static int ath12k_get_tpc_ctl_mode_idx(struct wmi_tpc_stats_arg *tpc_stats,
enum wmi_tpc_pream_bw pream_bw, int *mode_idx)
{
u32 chan_freq = le32_to_cpu(tpc_stats->tpc_config.chan_freq);
u8 band;
band = ((chan_freq > ATH12K_MIN_6GHZ_FREQ) ? NL80211_BAND_6GHZ :
((chan_freq > ATH12K_MIN_5GHZ_FREQ) ? NL80211_BAND_5GHZ :
wifi: ath12k: Add Support to Calculate and Display TPC Values Transmit Power Control(TPC) stats should display per chain TPC value per radio. Add debugfs support to read and display TPC stats type and TPC stats. Take power values for each preamble type, rate and NSS combination from a particular index from each power arrays based on number of chains, NSS, modes, MCS and tx beamforming enabled/disabled parameters. Minimum of the values taken from reg power table, rates and Conformance Test Limit(CTL) array table should give the TPC which is in 0.25 dBm steps. Sample Output: ------------- echo 1 > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats_type cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats *************** TPC config ************** * powers are in 0.25 dBm steps reg domain-22 chan freq-5955 power limit-126 max reg-domain Power-252 No.of tx chain-4 No.of rates-1164 **************** SU WITH TXBF **************** TPC values for Active chains Rate idx Preamble Rate code 1-Chain 2-Chain 3-Chain 4-Chain 4 OFDM 0x000 39 15 1 -9 5 OFDM 0x001 39 15 1 -9 ..... 12 HT20 0x200 40 16 2 -8 13 HT20 0x201 40 16 2 -8 ..... 44 HT40 0x200 88 88 88 88 45 HT40 0x201 88 88 88 88 ..... 76 VHT20 0x300 40 16 2 -8 77 VHT20 0x301 40 16 2 -8 ..... 172 VHT40 0x300 88 88 88 88 173 VHT40 0x301 88 88 88 88 ..... 412 HE20 0x400 88 88 88 88 413 HE20 0x401 88 88 88 88 ..... 508 HE40 0x400 76 76 76 76 509 HE40 0x401 76 76 76 76 ..... 748 EHT20 0x50e 88 88 88 88 749 EHT20 0x50f 88 88 88 88 ..... 812 EHT40 0x50e 88 88 88 88 813 EHT40 0x50f 88 88 88 88 ..... Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sowmiya Sree Elavalagan <quic_ssreeela@quicinc.com> Co-developed-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Co-developed-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Signed-off-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250130061104.962124-3-quic_rdevanat@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-30 11:41:04 +05:30
NL80211_BAND_2GHZ));
if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) {
switch (pream_bw) {
case WMI_TPC_PREAM_HT20:
case WMI_TPC_PREAM_VHT20:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT_VHT20_5GHZ_6GHZ;
break;
case WMI_TPC_PREAM_HE20:
case WMI_TPC_PREAM_EHT20:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT20_5GHZ_6GHZ;
break;
case WMI_TPC_PREAM_HT40:
case WMI_TPC_PREAM_VHT40:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT_VHT40_5GHZ_6GHZ;
break;
case WMI_TPC_PREAM_HE40:
case WMI_TPC_PREAM_EHT40:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT40_5GHZ_6GHZ;
break;
case WMI_TPC_PREAM_VHT80:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_VHT80_5GHZ_6GHZ;
break;
case WMI_TPC_PREAM_EHT60:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT80_SU_PUNC20;
break;
case WMI_TPC_PREAM_HE80:
case WMI_TPC_PREAM_EHT80:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT80_5GHZ_6GHZ;
break;
case WMI_TPC_PREAM_VHT160:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_VHT160_5GHZ_6GHZ;
break;
case WMI_TPC_PREAM_EHT120:
case WMI_TPC_PREAM_EHT140:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT160_SU_PUNC20;
break;
case WMI_TPC_PREAM_HE160:
case WMI_TPC_PREAM_EHT160:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT160_5GHZ_6GHZ;
break;
case WMI_TPC_PREAM_EHT200:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT320_SU_PUNC120;
break;
case WMI_TPC_PREAM_EHT240:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT320_SU_PUNC80;
break;
case WMI_TPC_PREAM_EHT280:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT320_SU_PUNC40;
break;
case WMI_TPC_PREAM_EHT320:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT320_5GHZ_6GHZ;
break;
default:
/* for 5GHZ and 6GHZ, default case will be for OFDM */
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_LEGACY_5GHZ_6GHZ;
break;
}
} else {
switch (pream_bw) {
case WMI_TPC_PREAM_OFDM:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_LEGACY_2GHZ;
break;
case WMI_TPC_PREAM_HT20:
case WMI_TPC_PREAM_VHT20:
case WMI_TPC_PREAM_HE20:
case WMI_TPC_PREAM_EHT20:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT20_2GHZ;
break;
case WMI_TPC_PREAM_HT40:
case WMI_TPC_PREAM_VHT40:
case WMI_TPC_PREAM_HE40:
case WMI_TPC_PREAM_EHT40:
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT40_2GHZ;
break;
default:
/* for 2GHZ, default case will be CCK */
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_CCK_2GHZ;
break;
}
}
return 0;
}
static s16 ath12k_tpc_get_rate(struct ath12k *ar,
struct wmi_tpc_stats_arg *tpc_stats,
u32 rate_idx, u32 num_chains, u32 rate_code,
enum wmi_tpc_pream_bw pream_bw,
enum wmi_halphy_ctrl_path_stats_id type,
u32 eht_rate_idx)
{
u32 tot_nss, tot_modes, txbf_on_off, index_offset1, index_offset2, index_offset3;
u8 chain_idx, stm_idx, num_streams;
bool is_mu, txbf_enabled = 0;
s8 rates_ctl_min, tpc_ctl;
s16 rates, tpc, reg_pwr;
u16 rate1, rate2;
int mode, ret;
num_streams = 1 + ATH12K_HW_NSS(rate_code);
chain_idx = num_chains - 1;
stm_idx = num_streams - 1;
mode = -1;
ret = ath12k_get_tpc_ctl_mode_idx(tpc_stats, pream_bw, &mode);
if (ret) {
ath12k_warn(ar->ab, "Invalid mode index received\n");
tpc = TPC_INVAL;
goto out;
}
if (num_chains < num_streams) {
tpc = TPC_INVAL;
goto out;
}
if (le32_to_cpu(tpc_stats->tpc_config.num_tx_chain) <= 1) {
tpc = TPC_INVAL;
goto out;
}
if (type == WMI_HALPHY_PDEV_TX_SUTXBF_STATS ||
type == WMI_HALPHY_PDEV_TX_MUTXBF_STATS)
txbf_enabled = 1;
if (type == WMI_HALPHY_PDEV_TX_MU_STATS ||
type == WMI_HALPHY_PDEV_TX_MUTXBF_STATS) {
is_mu = true;
} else {
is_mu = false;
}
/* Below is the min calculation of ctl array, rates array and
* regulator power table. tpc is minimum of all 3
*/
if (pream_bw >= WMI_TPC_PREAM_EHT20 && pream_bw <= WMI_TPC_PREAM_EHT320) {
rate2 = tpc_stats->rates_array2.rate_array[eht_rate_idx];
if (is_mu)
rates = u32_get_bits(rate2, ATH12K_TPC_RATE_ARRAY_MU);
else
rates = u32_get_bits(rate2, ATH12K_TPC_RATE_ARRAY_SU);
} else {
rate1 = tpc_stats->rates_array1.rate_array[rate_idx];
if (is_mu)
rates = u32_get_bits(rate1, ATH12K_TPC_RATE_ARRAY_MU);
else
rates = u32_get_bits(rate1, ATH12K_TPC_RATE_ARRAY_SU);
}
if (tpc_stats->tlvs_rcvd & WMI_TPC_CTL_PWR_ARRAY) {
tot_nss = le32_to_cpu(tpc_stats->ctl_array.tpc_ctl_pwr.d1);
tot_modes = le32_to_cpu(tpc_stats->ctl_array.tpc_ctl_pwr.d2);
txbf_on_off = le32_to_cpu(tpc_stats->ctl_array.tpc_ctl_pwr.d3);
index_offset1 = txbf_on_off * tot_modes * tot_nss;
index_offset2 = tot_modes * tot_nss;
index_offset3 = tot_nss;
tpc_ctl = *(tpc_stats->ctl_array.ctl_pwr_table +
chain_idx * index_offset1 + txbf_enabled * index_offset2
+ mode * index_offset3 + stm_idx);
} else {
tpc_ctl = TPC_MAX;
ath12k_warn(ar->ab,
"ctl array for tpc stats not received from fw\n");
}
rates_ctl_min = min_t(s16, rates, tpc_ctl);
reg_pwr = tpc_stats->max_reg_allowed_power.reg_pwr_array[chain_idx];
if (reg_pwr < 0)
reg_pwr = TPC_INVAL;
tpc = min_t(s16, rates_ctl_min, reg_pwr);
/* MODULATION_LIMIT is the maximum power limit,tpc should not exceed
* modulation limit even if min tpc of all three array is greater
* modulation limit
*/
tpc = min_t(s16, tpc, MODULATION_LIMIT);
out:
return tpc;
}
static u16 ath12k_get_ratecode(u16 pream_idx, u16 nss, u16 mcs_rate)
{
u16 mode_type = ~0;
/* Below assignments are just for printing purpose only */
switch (pream_idx) {
case WMI_TPC_PREAM_CCK:
mode_type = WMI_RATE_PREAMBLE_CCK;
break;
case WMI_TPC_PREAM_OFDM:
mode_type = WMI_RATE_PREAMBLE_OFDM;
break;
case WMI_TPC_PREAM_HT20:
case WMI_TPC_PREAM_HT40:
mode_type = WMI_RATE_PREAMBLE_HT;
break;
case WMI_TPC_PREAM_VHT20:
case WMI_TPC_PREAM_VHT40:
case WMI_TPC_PREAM_VHT80:
case WMI_TPC_PREAM_VHT160:
mode_type = WMI_RATE_PREAMBLE_VHT;
break;
case WMI_TPC_PREAM_HE20:
case WMI_TPC_PREAM_HE40:
case WMI_TPC_PREAM_HE80:
case WMI_TPC_PREAM_HE160:
mode_type = WMI_RATE_PREAMBLE_HE;
break;
case WMI_TPC_PREAM_EHT20:
case WMI_TPC_PREAM_EHT40:
case WMI_TPC_PREAM_EHT60:
case WMI_TPC_PREAM_EHT80:
case WMI_TPC_PREAM_EHT120:
case WMI_TPC_PREAM_EHT140:
case WMI_TPC_PREAM_EHT160:
case WMI_TPC_PREAM_EHT200:
case WMI_TPC_PREAM_EHT240:
case WMI_TPC_PREAM_EHT280:
case WMI_TPC_PREAM_EHT320:
mode_type = WMI_RATE_PREAMBLE_EHT;
if (mcs_rate == 0 || mcs_rate == 1)
mcs_rate += 14;
else
mcs_rate -= 2;
break;
default:
return mode_type;
}
return ((mode_type << 8) | ((nss & 0x7) << 5) | (mcs_rate & 0x1F));
}
static bool ath12k_he_supports_extra_mcs(struct ath12k *ar, int freq)
{
struct ath12k_pdev_cap *cap = &ar->pdev->cap;
struct ath12k_band_cap *cap_band;
bool extra_mcs_supported;
if (freq <= ATH12K_2GHZ_MAX_FREQUENCY)
cap_band = &cap->band[NL80211_BAND_2GHZ];
else if (freq <= ATH12K_5GHZ_MAX_FREQUENCY)
cap_band = &cap->band[NL80211_BAND_5GHZ];
else
cap_band = &cap->band[NL80211_BAND_6GHZ];
extra_mcs_supported = u32_get_bits(cap_band->he_cap_info[1],
HE_EXTRA_MCS_SUPPORT);
return extra_mcs_supported;
}
static int ath12k_tpc_fill_pream(struct ath12k *ar, char *buf, int buf_len, int len,
enum wmi_tpc_pream_bw pream_bw, u32 max_rix,
int max_nss, int max_rates, int pream_type,
enum wmi_halphy_ctrl_path_stats_id tpc_type,
int rate_idx, int eht_rate_idx)
{
struct wmi_tpc_stats_arg *tpc_stats = ar->debug.tpc_stats;
int nss, rates, chains;
u8 active_tx_chains;
u16 rate_code;
s16 tpc;
static const char *const pream_str[] = {
[WMI_TPC_PREAM_CCK] = "CCK",
[WMI_TPC_PREAM_OFDM] = "OFDM",
[WMI_TPC_PREAM_HT20] = "HT20",
[WMI_TPC_PREAM_HT40] = "HT40",
[WMI_TPC_PREAM_VHT20] = "VHT20",
[WMI_TPC_PREAM_VHT40] = "VHT40",
[WMI_TPC_PREAM_VHT80] = "VHT80",
[WMI_TPC_PREAM_VHT160] = "VHT160",
[WMI_TPC_PREAM_HE20] = "HE20",
[WMI_TPC_PREAM_HE40] = "HE40",
[WMI_TPC_PREAM_HE80] = "HE80",
[WMI_TPC_PREAM_HE160] = "HE160",
[WMI_TPC_PREAM_EHT20] = "EHT20",
[WMI_TPC_PREAM_EHT40] = "EHT40",
[WMI_TPC_PREAM_EHT60] = "EHT60",
[WMI_TPC_PREAM_EHT80] = "EHT80",
[WMI_TPC_PREAM_EHT120] = "EHT120",
[WMI_TPC_PREAM_EHT140] = "EHT140",
[WMI_TPC_PREAM_EHT160] = "EHT160",
[WMI_TPC_PREAM_EHT200] = "EHT200",
[WMI_TPC_PREAM_EHT240] = "EHT240",
[WMI_TPC_PREAM_EHT280] = "EHT280",
[WMI_TPC_PREAM_EHT320] = "EHT320"};
active_tx_chains = ar->num_tx_chains;
for (nss = 0; nss < max_nss; nss++) {
for (rates = 0; rates < max_rates; rates++, rate_idx++, max_rix++) {
/* FW send extra MCS(10&11) for VHT and HE rates,
* this is not used. Hence skipping it here
*/
if (pream_type == WMI_RATE_PREAMBLE_VHT &&
rates > ATH12K_VHT_MCS_MAX)
continue;
if (pream_type == WMI_RATE_PREAMBLE_HE &&
rates > ATH12K_HE_MCS_MAX)
continue;
if (pream_type == WMI_RATE_PREAMBLE_EHT &&
rates > ATH12K_EHT_MCS_MAX)
continue;
rate_code = ath12k_get_ratecode(pream_bw, nss, rates);
len += scnprintf(buf + len, buf_len - len,
"%d\t %s\t 0x%03x\t", max_rix,
pream_str[pream_bw], rate_code);
for (chains = 0; chains < active_tx_chains; chains++) {
if (nss > chains) {
len += scnprintf(buf + len,
buf_len - len,
"\t%s", "NA");
} else {
tpc = ath12k_tpc_get_rate(ar, tpc_stats,
rate_idx, chains + 1,
rate_code, pream_bw,
tpc_type,
eht_rate_idx);
if (tpc == TPC_INVAL) {
len += scnprintf(buf + len,
buf_len - len, "\tNA");
} else {
len += scnprintf(buf + len,
buf_len - len, "\t%d",
tpc);
}
}
}
len += scnprintf(buf + len, buf_len - len, "\n");
if (pream_type == WMI_RATE_PREAMBLE_EHT)
/*For fetching the next eht rates pwr from rates array2*/
++eht_rate_idx;
}
}
return len;
}
static int ath12k_tpc_stats_print(struct ath12k *ar,
struct wmi_tpc_stats_arg *tpc_stats,
char *buf, size_t len,
enum wmi_halphy_ctrl_path_stats_id type)
{
u32 eht_idx = 0, pream_idx = 0, rate_pream_idx = 0, total_rates = 0, max_rix = 0;
u32 chan_freq, num_tx_chain, caps, i, j = 1;
size_t buf_len = ATH12K_TPC_STATS_BUF_SIZE;
u8 nss, active_tx_chains;
bool he_ext_mcs;
static const char *const type_str[WMI_HALPHY_PDEV_TX_STATS_MAX] = {
[WMI_HALPHY_PDEV_TX_SU_STATS] = "SU",
[WMI_HALPHY_PDEV_TX_SUTXBF_STATS] = "SU WITH TXBF",
[WMI_HALPHY_PDEV_TX_MU_STATS] = "MU",
[WMI_HALPHY_PDEV_TX_MUTXBF_STATS] = "MU WITH TXBF"};
u8 max_rates[WMI_TPC_PREAM_MAX] = {
[WMI_TPC_PREAM_CCK] = ATH12K_CCK_RATES,
[WMI_TPC_PREAM_OFDM] = ATH12K_OFDM_RATES,
[WMI_TPC_PREAM_HT20] = ATH12K_HT_RATES,
[WMI_TPC_PREAM_HT40] = ATH12K_HT_RATES,
[WMI_TPC_PREAM_VHT20] = ATH12K_VHT_RATES,
[WMI_TPC_PREAM_VHT40] = ATH12K_VHT_RATES,
[WMI_TPC_PREAM_VHT80] = ATH12K_VHT_RATES,
[WMI_TPC_PREAM_VHT160] = ATH12K_VHT_RATES,
[WMI_TPC_PREAM_HE20] = ATH12K_HE_RATES,
[WMI_TPC_PREAM_HE40] = ATH12K_HE_RATES,
[WMI_TPC_PREAM_HE80] = ATH12K_HE_RATES,
[WMI_TPC_PREAM_HE160] = ATH12K_HE_RATES,
[WMI_TPC_PREAM_EHT20] = ATH12K_EHT_RATES,
[WMI_TPC_PREAM_EHT40] = ATH12K_EHT_RATES,
[WMI_TPC_PREAM_EHT60] = ATH12K_EHT_RATES,
[WMI_TPC_PREAM_EHT80] = ATH12K_EHT_RATES,
[WMI_TPC_PREAM_EHT120] = ATH12K_EHT_RATES,
[WMI_TPC_PREAM_EHT140] = ATH12K_EHT_RATES,
[WMI_TPC_PREAM_EHT160] = ATH12K_EHT_RATES,
[WMI_TPC_PREAM_EHT200] = ATH12K_EHT_RATES,
[WMI_TPC_PREAM_EHT240] = ATH12K_EHT_RATES,
[WMI_TPC_PREAM_EHT280] = ATH12K_EHT_RATES,
[WMI_TPC_PREAM_EHT320] = ATH12K_EHT_RATES};
static const u8 max_nss[WMI_TPC_PREAM_MAX] = {
[WMI_TPC_PREAM_CCK] = ATH12K_NSS_1,
[WMI_TPC_PREAM_OFDM] = ATH12K_NSS_1,
[WMI_TPC_PREAM_HT20] = ATH12K_NSS_4,
[WMI_TPC_PREAM_HT40] = ATH12K_NSS_4,
[WMI_TPC_PREAM_VHT20] = ATH12K_NSS_8,
[WMI_TPC_PREAM_VHT40] = ATH12K_NSS_8,
[WMI_TPC_PREAM_VHT80] = ATH12K_NSS_8,
[WMI_TPC_PREAM_VHT160] = ATH12K_NSS_4,
[WMI_TPC_PREAM_HE20] = ATH12K_NSS_8,
[WMI_TPC_PREAM_HE40] = ATH12K_NSS_8,
[WMI_TPC_PREAM_HE80] = ATH12K_NSS_8,
[WMI_TPC_PREAM_HE160] = ATH12K_NSS_4,
[WMI_TPC_PREAM_EHT20] = ATH12K_NSS_4,
[WMI_TPC_PREAM_EHT40] = ATH12K_NSS_4,
[WMI_TPC_PREAM_EHT60] = ATH12K_NSS_4,
[WMI_TPC_PREAM_EHT80] = ATH12K_NSS_4,
[WMI_TPC_PREAM_EHT120] = ATH12K_NSS_4,
[WMI_TPC_PREAM_EHT140] = ATH12K_NSS_4,
[WMI_TPC_PREAM_EHT160] = ATH12K_NSS_4,
[WMI_TPC_PREAM_EHT200] = ATH12K_NSS_4,
[WMI_TPC_PREAM_EHT240] = ATH12K_NSS_4,
[WMI_TPC_PREAM_EHT280] = ATH12K_NSS_4,
[WMI_TPC_PREAM_EHT320] = ATH12K_NSS_4};
u16 rate_idx[WMI_TPC_PREAM_MAX] = {}, eht_rate_idx[WMI_TPC_PREAM_MAX] = {};
static const u8 pream_type[WMI_TPC_PREAM_MAX] = {
[WMI_TPC_PREAM_CCK] = WMI_RATE_PREAMBLE_CCK,
[WMI_TPC_PREAM_OFDM] = WMI_RATE_PREAMBLE_OFDM,
[WMI_TPC_PREAM_HT20] = WMI_RATE_PREAMBLE_HT,
[WMI_TPC_PREAM_HT40] = WMI_RATE_PREAMBLE_HT,
[WMI_TPC_PREAM_VHT20] = WMI_RATE_PREAMBLE_VHT,
[WMI_TPC_PREAM_VHT40] = WMI_RATE_PREAMBLE_VHT,
[WMI_TPC_PREAM_VHT80] = WMI_RATE_PREAMBLE_VHT,
[WMI_TPC_PREAM_VHT160] = WMI_RATE_PREAMBLE_VHT,
[WMI_TPC_PREAM_HE20] = WMI_RATE_PREAMBLE_HE,
[WMI_TPC_PREAM_HE40] = WMI_RATE_PREAMBLE_HE,
[WMI_TPC_PREAM_HE80] = WMI_RATE_PREAMBLE_HE,
[WMI_TPC_PREAM_HE160] = WMI_RATE_PREAMBLE_HE,
[WMI_TPC_PREAM_EHT20] = WMI_RATE_PREAMBLE_EHT,
[WMI_TPC_PREAM_EHT40] = WMI_RATE_PREAMBLE_EHT,
[WMI_TPC_PREAM_EHT60] = WMI_RATE_PREAMBLE_EHT,
[WMI_TPC_PREAM_EHT80] = WMI_RATE_PREAMBLE_EHT,
[WMI_TPC_PREAM_EHT120] = WMI_RATE_PREAMBLE_EHT,
[WMI_TPC_PREAM_EHT140] = WMI_RATE_PREAMBLE_EHT,
[WMI_TPC_PREAM_EHT160] = WMI_RATE_PREAMBLE_EHT,
[WMI_TPC_PREAM_EHT200] = WMI_RATE_PREAMBLE_EHT,
[WMI_TPC_PREAM_EHT240] = WMI_RATE_PREAMBLE_EHT,
[WMI_TPC_PREAM_EHT280] = WMI_RATE_PREAMBLE_EHT,
[WMI_TPC_PREAM_EHT320] = WMI_RATE_PREAMBLE_EHT};
chan_freq = le32_to_cpu(tpc_stats->tpc_config.chan_freq);
num_tx_chain = le32_to_cpu(tpc_stats->tpc_config.num_tx_chain);
caps = le32_to_cpu(tpc_stats->tpc_config.caps);
active_tx_chains = ar->num_tx_chains;
he_ext_mcs = ath12k_he_supports_extra_mcs(ar, chan_freq);
/* mcs 12&13 is sent by FW for certain HWs in rate array, skipping it as
* it is not supported
*/
if (he_ext_mcs) {
for (i = WMI_TPC_PREAM_HE20; i <= WMI_TPC_PREAM_HE160; ++i)
max_rates[i] = ATH12K_HE_RATES;
}
if (type == WMI_HALPHY_PDEV_TX_MU_STATS ||
type == WMI_HALPHY_PDEV_TX_MUTXBF_STATS) {
pream_idx = WMI_TPC_PREAM_VHT20;
for (i = WMI_TPC_PREAM_CCK; i <= WMI_TPC_PREAM_HT40; ++i)
max_rix += max_nss[i] * max_rates[i];
}
/* Enumerate all the rate indices */
for (i = rate_pream_idx + 1; i < WMI_TPC_PREAM_MAX; i++) {
nss = (max_nss[i - 1] < num_tx_chain ?
max_nss[i - 1] : num_tx_chain);
rate_idx[i] = rate_idx[i - 1] + max_rates[i - 1] * nss;
if (pream_type[i] == WMI_RATE_PREAMBLE_EHT) {
eht_rate_idx[j] = eht_rate_idx[j - 1] + max_rates[i] * nss;
++j;
}
}
for (i = 0; i < WMI_TPC_PREAM_MAX; i++) {
nss = (max_nss[i] < num_tx_chain ?
max_nss[i] : num_tx_chain);
total_rates += max_rates[i] * nss;
}
len += scnprintf(buf + len, buf_len - len,
"No.of rates-%d\n", total_rates);
len += scnprintf(buf + len, buf_len - len,
"**************** %s ****************\n",
type_str[type]);
len += scnprintf(buf + len, buf_len - len,
"\t\t\t\tTPC values for Active chains\n");
len += scnprintf(buf + len, buf_len - len,
"Rate idx Preamble Rate code");
for (i = 1; i <= active_tx_chains; ++i) {
len += scnprintf(buf + len, buf_len - len,
"\t%d-Chain", i);
}
len += scnprintf(buf + len, buf_len - len, "\n");
for (i = pream_idx; i < WMI_TPC_PREAM_MAX; i++) {
if (chan_freq <= 2483) {
if (i == WMI_TPC_PREAM_VHT80 ||
i == WMI_TPC_PREAM_VHT160 ||
i == WMI_TPC_PREAM_HE80 ||
i == WMI_TPC_PREAM_HE160 ||
(i >= WMI_TPC_PREAM_EHT60 &&
i <= WMI_TPC_PREAM_EHT320)) {
max_rix += max_nss[i] * max_rates[i];
continue;
}
} else {
if (i == WMI_TPC_PREAM_CCK) {
max_rix += max_rates[i];
continue;
}
}
nss = (max_nss[i] < ar->num_tx_chains ? max_nss[i] : ar->num_tx_chains);
if (!(caps &
(1 << ATH12K_TPC_STATS_SUPPORT_BE_PUNC))) {
if (i == WMI_TPC_PREAM_EHT60 || i == WMI_TPC_PREAM_EHT120 ||
i == WMI_TPC_PREAM_EHT140 || i == WMI_TPC_PREAM_EHT200 ||
i == WMI_TPC_PREAM_EHT240 || i == WMI_TPC_PREAM_EHT280) {
max_rix += max_nss[i] * max_rates[i];
continue;
}
}
len = ath12k_tpc_fill_pream(ar, buf, buf_len, len, i, max_rix, nss,
max_rates[i], pream_type[i],
type, rate_idx[i], eht_rate_idx[eht_idx]);
if (pream_type[i] == WMI_RATE_PREAMBLE_EHT)
/*For fetch the next index eht rates from rates array2*/
++eht_idx;
max_rix += max_nss[i] * max_rates[i];
}
return len;
}
static void ath12k_tpc_stats_fill(struct ath12k *ar,
struct wmi_tpc_stats_arg *tpc_stats,
char *buf)
{
size_t buf_len = ATH12K_TPC_STATS_BUF_SIZE;
struct wmi_tpc_config_params *tpc;
size_t len = 0;
if (!tpc_stats) {
ath12k_warn(ar->ab, "failed to find tpc stats\n");
return;
}
spin_lock_bh(&ar->data_lock);
tpc = &tpc_stats->tpc_config;
len += scnprintf(buf + len, buf_len - len, "\n");
len += scnprintf(buf + len, buf_len - len,
"*************** TPC config **************\n");
len += scnprintf(buf + len, buf_len - len,
"* powers are in 0.25 dBm steps\n");
len += scnprintf(buf + len, buf_len - len,
"reg domain-%d\t\tchan freq-%d\n",
tpc->reg_domain, tpc->chan_freq);
len += scnprintf(buf + len, buf_len - len,
"power limit-%d\t\tmax reg-domain Power-%d\n",
le32_to_cpu(tpc->twice_max_reg_power) / 2, tpc->power_limit);
len += scnprintf(buf + len, buf_len - len,
"No.of tx chain-%d\t",
ar->num_tx_chains);
ath12k_tpc_stats_print(ar, tpc_stats, buf, len,
ar->debug.tpc_stats_type);
spin_unlock_bh(&ar->data_lock);
}
wifi: ath12k: Add Support to Parse TPC Event from Firmware Host receives four Transmit Power Control(TPC) events from firmware on sending TPC request. Fixed param TLV is present as part of all event to indicate the event count and end of event. TPC config parameters along with regulatory power array comes as first event. Rates array comes as second and third event as it cannot be packed in single event. Conformance Test Limit (CTL) power array comes as the fourth event. Firmware packs different sets of array params which includes array length and type inside master TLV as different subtlvs. And the actual content of array is packed one after the other inside a separate TLV as single buffer. Parse various events and save it in local structures. Create tpc_stats file using debugfs to store these local structures. Create function to handle TPC stats read to relay the information to the user. Command usage: cat > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sowmiya Sree Elavalagan <quic_ssreeela@quicinc.com> Co-developed-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Co-developed-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Signed-off-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250130061104.962124-2-quic_rdevanat@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-30 11:41:03 +05:30
static int ath12k_open_tpc_stats(struct inode *inode, struct file *file)
{
struct ath12k *ar = inode->i_private;
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
int ret;
guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
if (ah->state != ATH12K_HW_STATE_ON) {
ath12k_warn(ar->ab, "Interface not up\n");
return -ENETDOWN;
}
void *buf __free(kfree) = kzalloc(ATH12K_TPC_STATS_BUF_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = ath12k_debug_tpc_stats_request(ar);
if (ret) {
ath12k_warn(ar->ab, "failed to request tpc stats: %d\n",
ret);
return ret;
}
if (!wait_for_completion_timeout(&ar->debug.tpc_complete, TPC_STATS_WAIT_TIME)) {
spin_lock_bh(&ar->data_lock);
ath12k_wmi_free_tpc_stats_mem(ar);
ar->debug.tpc_request = false;
spin_unlock_bh(&ar->data_lock);
return -ETIMEDOUT;
}
wifi: ath12k: Add Support to Calculate and Display TPC Values Transmit Power Control(TPC) stats should display per chain TPC value per radio. Add debugfs support to read and display TPC stats type and TPC stats. Take power values for each preamble type, rate and NSS combination from a particular index from each power arrays based on number of chains, NSS, modes, MCS and tx beamforming enabled/disabled parameters. Minimum of the values taken from reg power table, rates and Conformance Test Limit(CTL) array table should give the TPC which is in 0.25 dBm steps. Sample Output: ------------- echo 1 > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats_type cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats *************** TPC config ************** * powers are in 0.25 dBm steps reg domain-22 chan freq-5955 power limit-126 max reg-domain Power-252 No.of tx chain-4 No.of rates-1164 **************** SU WITH TXBF **************** TPC values for Active chains Rate idx Preamble Rate code 1-Chain 2-Chain 3-Chain 4-Chain 4 OFDM 0x000 39 15 1 -9 5 OFDM 0x001 39 15 1 -9 ..... 12 HT20 0x200 40 16 2 -8 13 HT20 0x201 40 16 2 -8 ..... 44 HT40 0x200 88 88 88 88 45 HT40 0x201 88 88 88 88 ..... 76 VHT20 0x300 40 16 2 -8 77 VHT20 0x301 40 16 2 -8 ..... 172 VHT40 0x300 88 88 88 88 173 VHT40 0x301 88 88 88 88 ..... 412 HE20 0x400 88 88 88 88 413 HE20 0x401 88 88 88 88 ..... 508 HE40 0x400 76 76 76 76 509 HE40 0x401 76 76 76 76 ..... 748 EHT20 0x50e 88 88 88 88 749 EHT20 0x50f 88 88 88 88 ..... 812 EHT40 0x50e 88 88 88 88 813 EHT40 0x50f 88 88 88 88 ..... Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sowmiya Sree Elavalagan <quic_ssreeela@quicinc.com> Co-developed-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Co-developed-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Signed-off-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250130061104.962124-3-quic_rdevanat@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-30 11:41:04 +05:30
ath12k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
wifi: ath12k: Add Support to Parse TPC Event from Firmware Host receives four Transmit Power Control(TPC) events from firmware on sending TPC request. Fixed param TLV is present as part of all event to indicate the event count and end of event. TPC config parameters along with regulatory power array comes as first event. Rates array comes as second and third event as it cannot be packed in single event. Conformance Test Limit (CTL) power array comes as the fourth event. Firmware packs different sets of array params which includes array length and type inside master TLV as different subtlvs. And the actual content of array is packed one after the other inside a separate TLV as single buffer. Parse various events and save it in local structures. Create tpc_stats file using debugfs to store these local structures. Create function to handle TPC stats read to relay the information to the user. Command usage: cat > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sowmiya Sree Elavalagan <quic_ssreeela@quicinc.com> Co-developed-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Co-developed-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Signed-off-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250130061104.962124-2-quic_rdevanat@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-30 11:41:03 +05:30
file->private_data = no_free_ptr(buf);
spin_lock_bh(&ar->data_lock);
ath12k_wmi_free_tpc_stats_mem(ar);
spin_unlock_bh(&ar->data_lock);
return 0;
}
static ssize_t ath12k_read_tpc_stats(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
const char *buf = file->private_data;
size_t len = strlen(buf);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static int ath12k_release_tpc_stats(struct inode *inode,
struct file *file)
{
kfree(file->private_data);
return 0;
}
static const struct file_operations fops_tpc_stats = {
.open = ath12k_open_tpc_stats,
.release = ath12k_release_tpc_stats,
.read = ath12k_read_tpc_stats,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
wifi: ath12k: Add Support to Calculate and Display TPC Values Transmit Power Control(TPC) stats should display per chain TPC value per radio. Add debugfs support to read and display TPC stats type and TPC stats. Take power values for each preamble type, rate and NSS combination from a particular index from each power arrays based on number of chains, NSS, modes, MCS and tx beamforming enabled/disabled parameters. Minimum of the values taken from reg power table, rates and Conformance Test Limit(CTL) array table should give the TPC which is in 0.25 dBm steps. Sample Output: ------------- echo 1 > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats_type cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats *************** TPC config ************** * powers are in 0.25 dBm steps reg domain-22 chan freq-5955 power limit-126 max reg-domain Power-252 No.of tx chain-4 No.of rates-1164 **************** SU WITH TXBF **************** TPC values for Active chains Rate idx Preamble Rate code 1-Chain 2-Chain 3-Chain 4-Chain 4 OFDM 0x000 39 15 1 -9 5 OFDM 0x001 39 15 1 -9 ..... 12 HT20 0x200 40 16 2 -8 13 HT20 0x201 40 16 2 -8 ..... 44 HT40 0x200 88 88 88 88 45 HT40 0x201 88 88 88 88 ..... 76 VHT20 0x300 40 16 2 -8 77 VHT20 0x301 40 16 2 -8 ..... 172 VHT40 0x300 88 88 88 88 173 VHT40 0x301 88 88 88 88 ..... 412 HE20 0x400 88 88 88 88 413 HE20 0x401 88 88 88 88 ..... 508 HE40 0x400 76 76 76 76 509 HE40 0x401 76 76 76 76 ..... 748 EHT20 0x50e 88 88 88 88 749 EHT20 0x50f 88 88 88 88 ..... 812 EHT40 0x50e 88 88 88 88 813 EHT40 0x50f 88 88 88 88 ..... Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sowmiya Sree Elavalagan <quic_ssreeela@quicinc.com> Co-developed-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Co-developed-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Signed-off-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250130061104.962124-3-quic_rdevanat@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-30 11:41:04 +05:30
static const struct file_operations fops_tpc_stats_type = {
.write = ath12k_write_tpc_stats_type,
.open = simple_open,
.llseek = default_llseek,
};
wifi: ath12k: Add peer extended Rx statistics debugfs support Currently, peer extended Rx statistics are not supported. Therefore, expose peer extended Rx statistics support through debugfs, allowing users to enable or disable the collection of statistics information. After that the statistics information can be dumped through debugfs. Below are the debugfs commands exposed. Enable/Disable: echo <1/0> > /sys/kernel/debug/ieee80211/phyX/ath12k/ext_rx_stats Dump: cat /sys/kernel/debug/ieee80211/phyX/netdev:wlanX/stations/<peer MAC addr>/rx_stats Sample output: ============== RX peer stats: Num of MSDUs: 1087 Num of MSDUs with TCP L4: 0 Num of MSDUs with UDP L4: 13 Num of other MSDUs: 1074 Num of MSDUs part of AMPDU: 363 Num of MSDUs not part of AMPDU: 724 Num of MSDUs using STBC: 0 Num of MSDUs beamformed: 0 Num of MPDUs with FCS ok: 695 Num of MPDUs with FCS error: 0 preamble: 11A 395 11B 0 11N 0 11AC 0 11AX 692 11BE 0 reception type: SU 1087 MU_MIMO 0 MU_OFDMA 0 MU_OFDMA_MIMO 0 TID(0-15) Legacy TID(16):690 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 395 RX Duration:39537 DCM: 0 RU26: 0 RU52: 0 RU106: 0 RU242: 0 RU484: 0 RU996: 0 RX success packet stats: EHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 HE stats: MCS 0: 1 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 66 MCS 7: 46 MCS 8: 46 MCS 9: 34 MCS 10: 28 MCS 11: 471 VHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 HT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 MCS 16: 0 MCS 17: 0 MCS 18: 0 MCS 19: 0 MCS 20: 0 MCS 21: 0 MCS 22: 0 MCS 23: 0 MCS 24: 0 MCS 25: 0 MCS 26: 0 MCS 27: 0 MCS 28: 0 MCS 29: 0 MCS 30: 0 MCS 31: 0 Legacy stats: 1 Mbps: 0 2 Mbps: 0 5.5 Mbps: 0 6 Mbps: 395 9 Mbps: 0 11 Mbps: 0 12 Mbps: 0 18 Mbps: 0 24 Mbps: 0 36 Mbps: 0 48 Mbps: 0 54 Mbps: 0 NSS stats: 1x1: 1086 2x2: 0 3x3: 0 4x4: 0 5x5: 0 6x6: 0 7x7: 0 8x8: 0 GI: 0.8 us 0 0.4 us 396 1.6 us 691 3.2 us 0 BW: 20 MHz 785 40 MHz 2 80 MHz 300 160 MHz 0 320 MHz 0 20 Mhz gi 1 us 1x1 : 6:5 7:3 8:3 9:4 10:4 11:374 12:391 40 Mhz gi 1 us 1x1 : 12:2 80 Mhz gi 1 us 1x1 : 6:61 7:43 8:43 9:30 10:24 11:97 12:2 RX success byte stats: EHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 HE stats: MCS 0: 41 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 1435 MCS 7: 943 MCS 8: 697 MCS 9: 533 MCS 10: 492 MCS 11: 8159 VHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 HT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 MCS 16: 0 MCS 17: 0 MCS 18: 0 MCS 19: 0 MCS 20: 0 MCS 21: 0 MCS 22: 0 MCS 23: 0 MCS 24: 0 MCS 25: 0 MCS 26: 0 MCS 27: 0 MCS 28: 0 MCS 29: 0 MCS 30: 0 MCS 31: 0 Legacy stats: 1 Mbps: 0 2 Mbps: 0 5.5 Mbps: 0 6 Mbps: 16195 9 Mbps: 0 11 Mbps: 0 12 Mbps: 0 18 Mbps: 0 24 Mbps: 0 36 Mbps: 0 48 Mbps: 0 54 Mbps: 0 NSS stats: 1x1: 28454 2x2: 0 3x3: 0 4x4: 0 5x5: 0 6x6: 0 7x7: 0 8x8: 0 GI: 0.8 us 0 0.4 us 16236 1.6 us 12259 3.2 us 0 BW: 20 MHz 24108 40 MHz 82 80 MHz 4305 160 MHz 0 320 MHz 0 20 Mhz gi 1 us 1x1 : 6:205 7:123 8:123 9:164 10:164 11:7257 12:16031 40 Mhz gi 1 us 1x1 : 12:82 80 Mhz gi 1 us 1x1 : 6:1230 7:820 8:574 9:369 10:328 11:902 12:82 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Co-developed-by: P Praneesh <quic_ppranees@quicinc.com> Signed-off-by: P Praneesh <quic_ppranees@quicinc.com> Co-developed-by: Balamurugan Mahalingam <quic_bmahalin@quicinc.com> Signed-off-by: Balamurugan Mahalingam <quic_bmahalin@quicinc.com> Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com> Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com> Link: https://patch.msgid.link/20250206013854.174765-10-quic_periyasa@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-02-06 07:08:54 +05:30
static ssize_t ath12k_write_extd_rx_stats(struct file *file,
const char __user *ubuf,
size_t count, loff_t *ppos)
{
struct ath12k *ar = file->private_data;
struct htt_rx_ring_tlv_filter tlv_filter = {};
wifi: ath12k: Add peer extended Rx statistics debugfs support Currently, peer extended Rx statistics are not supported. Therefore, expose peer extended Rx statistics support through debugfs, allowing users to enable or disable the collection of statistics information. After that the statistics information can be dumped through debugfs. Below are the debugfs commands exposed. Enable/Disable: echo <1/0> > /sys/kernel/debug/ieee80211/phyX/ath12k/ext_rx_stats Dump: cat /sys/kernel/debug/ieee80211/phyX/netdev:wlanX/stations/<peer MAC addr>/rx_stats Sample output: ============== RX peer stats: Num of MSDUs: 1087 Num of MSDUs with TCP L4: 0 Num of MSDUs with UDP L4: 13 Num of other MSDUs: 1074 Num of MSDUs part of AMPDU: 363 Num of MSDUs not part of AMPDU: 724 Num of MSDUs using STBC: 0 Num of MSDUs beamformed: 0 Num of MPDUs with FCS ok: 695 Num of MPDUs with FCS error: 0 preamble: 11A 395 11B 0 11N 0 11AC 0 11AX 692 11BE 0 reception type: SU 1087 MU_MIMO 0 MU_OFDMA 0 MU_OFDMA_MIMO 0 TID(0-15) Legacy TID(16):690 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 395 RX Duration:39537 DCM: 0 RU26: 0 RU52: 0 RU106: 0 RU242: 0 RU484: 0 RU996: 0 RX success packet stats: EHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 HE stats: MCS 0: 1 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 66 MCS 7: 46 MCS 8: 46 MCS 9: 34 MCS 10: 28 MCS 11: 471 VHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 HT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 MCS 16: 0 MCS 17: 0 MCS 18: 0 MCS 19: 0 MCS 20: 0 MCS 21: 0 MCS 22: 0 MCS 23: 0 MCS 24: 0 MCS 25: 0 MCS 26: 0 MCS 27: 0 MCS 28: 0 MCS 29: 0 MCS 30: 0 MCS 31: 0 Legacy stats: 1 Mbps: 0 2 Mbps: 0 5.5 Mbps: 0 6 Mbps: 395 9 Mbps: 0 11 Mbps: 0 12 Mbps: 0 18 Mbps: 0 24 Mbps: 0 36 Mbps: 0 48 Mbps: 0 54 Mbps: 0 NSS stats: 1x1: 1086 2x2: 0 3x3: 0 4x4: 0 5x5: 0 6x6: 0 7x7: 0 8x8: 0 GI: 0.8 us 0 0.4 us 396 1.6 us 691 3.2 us 0 BW: 20 MHz 785 40 MHz 2 80 MHz 300 160 MHz 0 320 MHz 0 20 Mhz gi 1 us 1x1 : 6:5 7:3 8:3 9:4 10:4 11:374 12:391 40 Mhz gi 1 us 1x1 : 12:2 80 Mhz gi 1 us 1x1 : 6:61 7:43 8:43 9:30 10:24 11:97 12:2 RX success byte stats: EHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 HE stats: MCS 0: 41 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 1435 MCS 7: 943 MCS 8: 697 MCS 9: 533 MCS 10: 492 MCS 11: 8159 VHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 HT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 MCS 16: 0 MCS 17: 0 MCS 18: 0 MCS 19: 0 MCS 20: 0 MCS 21: 0 MCS 22: 0 MCS 23: 0 MCS 24: 0 MCS 25: 0 MCS 26: 0 MCS 27: 0 MCS 28: 0 MCS 29: 0 MCS 30: 0 MCS 31: 0 Legacy stats: 1 Mbps: 0 2 Mbps: 0 5.5 Mbps: 0 6 Mbps: 16195 9 Mbps: 0 11 Mbps: 0 12 Mbps: 0 18 Mbps: 0 24 Mbps: 0 36 Mbps: 0 48 Mbps: 0 54 Mbps: 0 NSS stats: 1x1: 28454 2x2: 0 3x3: 0 4x4: 0 5x5: 0 6x6: 0 7x7: 0 8x8: 0 GI: 0.8 us 0 0.4 us 16236 1.6 us 12259 3.2 us 0 BW: 20 MHz 24108 40 MHz 82 80 MHz 4305 160 MHz 0 320 MHz 0 20 Mhz gi 1 us 1x1 : 6:205 7:123 8:123 9:164 10:164 11:7257 12:16031 40 Mhz gi 1 us 1x1 : 12:82 80 Mhz gi 1 us 1x1 : 6:1230 7:820 8:574 9:369 10:328 11:902 12:82 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Co-developed-by: P Praneesh <quic_ppranees@quicinc.com> Signed-off-by: P Praneesh <quic_ppranees@quicinc.com> Co-developed-by: Balamurugan Mahalingam <quic_bmahalin@quicinc.com> Signed-off-by: Balamurugan Mahalingam <quic_bmahalin@quicinc.com> Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com> Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com> Link: https://patch.msgid.link/20250206013854.174765-10-quic_periyasa@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-02-06 07:08:54 +05:30
u32 ring_id, rx_filter = 0;
bool enable;
int ret, i;
if (kstrtobool_from_user(ubuf, count, &enable))
return -EINVAL;
wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
if (!ar->ab->hw_params->rxdma1_enable) {
ret = count;
goto exit;
}
if (ar->ah->state != ATH12K_HW_STATE_ON) {
ret = -ENETDOWN;
goto exit;
}
if (enable == ar->debug.extd_rx_stats) {
ret = count;
goto exit;
}
if (enable) {
rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END;
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS;
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT;
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE;
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START_USER_INFO;
tlv_filter.rx_filter = rx_filter;
tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
HTT_RX_FP_DATA_FILTER_FLASG3;
} else {
tlv_filter = ath12k_mac_mon_status_filter_default;
}
ar->debug.rx_filter = tlv_filter.rx_filter;
for (i = 0; i < ar->ab->hw_params->num_rxdma_per_pdev; i++) {
ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id;
ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id + i,
HAL_RXDMA_MONITOR_DST,
DP_RXDMA_REFILL_RING_SIZE,
&tlv_filter);
if (ret) {
ath12k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
goto exit;
}
}
ar->debug.extd_rx_stats = !!enable;
ret = count;
exit:
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return ret;
}
static ssize_t ath12k_read_extd_rx_stats(struct file *file,
char __user *ubuf,
size_t count, loff_t *ppos)
{
struct ath12k *ar = file->private_data;
char buf[32];
int len = 0;
wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
len = scnprintf(buf, sizeof(buf) - len, "%d\n",
ar->debug.extd_rx_stats);
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
}
static const struct file_operations fops_extd_rx_stats = {
.read = ath12k_read_extd_rx_stats,
.write = ath12k_write_extd_rx_stats,
.open = simple_open,
};
wifi: ath12k: Add support for link specific datapath stats Add support to record the number of frames enqueued, hardware descriptor type, encapsulation/encryption types used, frames dropped and completed. This is useful for understanding the datapath performance and tune the peak throughput. The link specific stats can be viewed through the below debugfs file cat /sys/kernel/debug/ieee80211/phy0/netdev:wlan1/link_stats link[0] Tx Unicast Frames Enqueued = 9 link[0] Tx Broadcast Frames Enqueued = 78689 link[0] Tx Frames Completed = 78698 link[0] Tx Frames Dropped = 0 link[0] Tx Frame descriptor Encap Type = raw:0 native wifi:78698 ethernet:0 link[0] Tx Frame descriptor Encrypt Type = 0:78698 1:0 2:0 3:0 4:0 5:0 6:0 7:0 8:0 9:0 10:0 11:0 link[0] Tx Frame descriptor Type = buffer:78698 extension:0 ------------------------------------------------------ link[1] Tx Unicast Frames Enqueued = 0 link[1] Tx Broadcast Frames Enqueued = 78689 link[1] Tx Frames Completed = 78689 link[1] Tx Frames Dropped = 0 link[1] Tx Frame descriptor Encap Type = raw:0 native wifi:78689 ethernet:0 link[1] Tx Frame descriptor Encrypt Type = 0:78689 1:0 2:0 3:0 4:0 5:0 6:0 7:0 8:0 9:0 10:0 11:0 link[1] Tx Frame descriptor Type = buffer:78689 extension:0 ------------------------------------------------------ Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Balamurugan Mahalingam <quic_bmahalin@quicinc.com> Link: https://patch.msgid.link/20250409155125.299380-1-quic_bmahalin@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-04-09 08:51:25 -07:00
static int ath12k_open_link_stats(struct inode *inode, struct file *file)
{
struct ath12k_vif *ahvif = inode->i_private;
size_t len = 0, buf_len = (PAGE_SIZE * 2);
struct ath12k_link_stats linkstat;
struct ath12k_link_vif *arvif;
unsigned long links_map;
struct wiphy *wiphy;
int link_id, i;
char *buf;
if (!ahvif)
return -EINVAL;
buf = kzalloc(buf_len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
wiphy = ahvif->ah->hw->wiphy;
wiphy_lock(wiphy);
links_map = ahvif->links_map;
for_each_set_bit(link_id, &links_map,
IEEE80211_MLD_MAX_NUM_LINKS) {
arvif = rcu_dereference_protected(ahvif->link[link_id],
lockdep_is_held(&wiphy->mtx));
spin_lock_bh(&arvif->link_stats_lock);
linkstat = arvif->link_stats;
spin_unlock_bh(&arvif->link_stats_lock);
len += scnprintf(buf + len, buf_len - len,
"link[%d] Tx Unicast Frames Enqueued = %d\n",
link_id, linkstat.tx_enqueued);
len += scnprintf(buf + len, buf_len - len,
"link[%d] Tx Broadcast Frames Enqueued = %d\n",
link_id, linkstat.tx_bcast_mcast);
len += scnprintf(buf + len, buf_len - len,
"link[%d] Tx Frames Completed = %d\n",
link_id, linkstat.tx_completed);
len += scnprintf(buf + len, buf_len - len,
"link[%d] Tx Frames Dropped = %d\n",
link_id, linkstat.tx_dropped);
len += scnprintf(buf + len, buf_len - len,
"link[%d] Tx Frame descriptor Encap Type = ",
link_id);
len += scnprintf(buf + len, buf_len - len,
" raw:%d",
linkstat.tx_encap_type[0]);
len += scnprintf(buf + len, buf_len - len,
" native_wifi:%d",
linkstat.tx_encap_type[1]);
len += scnprintf(buf + len, buf_len - len,
" ethernet:%d",
linkstat.tx_encap_type[2]);
len += scnprintf(buf + len, buf_len - len,
"\nlink[%d] Tx Frame descriptor Encrypt Type = ",
link_id);
for (i = 0; i < HAL_ENCRYPT_TYPE_MAX; i++) {
len += scnprintf(buf + len, buf_len - len,
" %d:%d", i,
linkstat.tx_encrypt_type[i]);
}
len += scnprintf(buf + len, buf_len - len,
"\nlink[%d] Tx Frame descriptor Type = buffer:%d extension:%d\n",
link_id, linkstat.tx_desc_type[0],
linkstat.tx_desc_type[1]);
len += scnprintf(buf + len, buf_len - len,
"------------------------------------------------------\n");
}
wiphy_unlock(wiphy);
file->private_data = buf;
return 0;
}
static int ath12k_release_link_stats(struct inode *inode, struct file *file)
{
kfree(file->private_data);
return 0;
}
static ssize_t ath12k_read_link_stats(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
const char *buf = file->private_data;
size_t len = strlen(buf);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static const struct file_operations ath12k_fops_link_stats = {
.open = ath12k_open_link_stats,
.release = ath12k_release_link_stats,
.read = ath12k_read_link_stats,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
debugfs_create_file("link_stats", 0400, vif->debugfs_dir, ahvif,
&ath12k_fops_link_stats);
}
wifi: ath12k: print device dp stats in debugfs Print the data path related device specific stats in debugfs. These device_dp_stats are exposed in the ath12k debugfs directory. Output of device_dp_stats: root@CDCWLEX0799743-LIN:/home/qctest# cat /sys/kernel/debug/ath12k/pci-0000\:58\:00.0/device_dp_stats DEVICE RX STATS: err ring pkts: 0 Invalid RBM: 0 RXDMA errors: Overflow: 0 MPDU len: 0 FCS: 0 Decrypt: 0 TKIP MIC: 0 Unencrypt: 0 MSDU len: 0 MSDU limit: 0 WiFi parse: 0 AMSDU parse: 0 SA timeout: 0 DA timeout: 0 Flow timeout: 0 Flush req: 0 AMSDU frag: 0 Multicast echo: 0 AMSDU mismatch: 0 Unauth WDS: 0 AMSDU or WDS: 0 REO errors: Desc addr zero: 0 Desc inval: 0 AMPDU in non BA: 0 Non BA dup: 0 BA dup: 0 Frame 2k jump: 0 BAR 2k jump: 0 Frame OOR: 155 BAR OOR: 0 No BA session: 0 Frame SN equal SSN: 0 PN check fail: 0 2k err: 0 PN err: 0 Desc blocked: 0 HAL REO errors: ring0: 0 ring1: 0 ring2: 0 ring3: 0 ring4: 0 ring5: 0 ring6: 0 ring7: 0 DEVICE TX STATS: TCL Ring Full Failures: ring0: 0 ring1: 0 ring2: 0 ring3: 0 Misc Transmit Failures: 0 tx_wbm_rel_source: 0:986 1:0 2:0 3:57 4:0 tqm_rel_reason: 0:1043 1:0 2:0 3:0 4:0 5:0 6:0 7:0 8:0 9:0 10:0 11:0 12:0 13:0 14:0 fw_tx_status: 0:57 1:0 2:0 3:0 4:0 5:0 6:0 tx_enqueued: 0:329 1:145 2:464 3:105 tx_completed: 0:329 1:145 2:464 3:105 radio0 tx_pending: 0 REO Rx Received: Ring1: 0:201 1:0 2:0 Ring2: 0:0 1:0 2:0 Ring3: 0:6152 1:0 2:0 Ring4: 0:9 1:0 2:0 Ring5: 0:0 1:0 2:0 Ring6: 0:0 1:0 2:0 Ring7: 0:0 1:0 2:0 Ring8: 0:0 1:0 2:0 Rx WBM REL SRC Errors: TQM: 0:0 1:0 2:0 Rxdma: 0:0 1:0 2:0 Reo: 0:155 1:0 2:0 FW: 0:0 1:0 2:0 SW: 0:0 1:0 2:0 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00210-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Vinith Kumar R <quic_vinithku@quicinc.com> Signed-off-by: Nithyanantham Paramasivam <nithyanantham.paramasivam@oss.qualcomm.com> Reviewed-by: Mahendran P <quic_mahep@quicinc.com> Link: https://patch.msgid.link/20250425012802.698914-4-nithyanantham.paramasivam@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-04-25 06:58:02 +05:30
static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath12k_base *ab = file->private_data;
struct ath12k_device_dp_stats *device_stats = &ab->device_stats;
int len = 0, i, j, ret;
struct ath12k *ar;
const int size = 4096;
static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
[HAL_REO_ENTR_RING_RXDMA_ECODE_OVERFLOW_ERR] = "Overflow",
[HAL_REO_ENTR_RING_RXDMA_ECODE_MPDU_LEN_ERR] = "MPDU len",
[HAL_REO_ENTR_RING_RXDMA_ECODE_FCS_ERR] = "FCS",
[HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR] = "Decrypt",
[HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR] = "TKIP MIC",
[HAL_REO_ENTR_RING_RXDMA_ECODE_UNECRYPTED_ERR] = "Unencrypt",
[HAL_REO_ENTR_RING_RXDMA_ECODE_MSDU_LEN_ERR] = "MSDU len",
[HAL_REO_ENTR_RING_RXDMA_ECODE_MSDU_LIMIT_ERR] = "MSDU limit",
[HAL_REO_ENTR_RING_RXDMA_ECODE_WIFI_PARSE_ERR] = "WiFi parse",
[HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_PARSE_ERR] = "AMSDU parse",
[HAL_REO_ENTR_RING_RXDMA_ECODE_SA_TIMEOUT_ERR] = "SA timeout",
[HAL_REO_ENTR_RING_RXDMA_ECODE_DA_TIMEOUT_ERR] = "DA timeout",
[HAL_REO_ENTR_RING_RXDMA_ECODE_FLOW_TIMEOUT_ERR] = "Flow timeout",
[HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR] = "Flush req",
[HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_FRAG_ERR] = "AMSDU frag",
[HAL_REO_ENTR_RING_RXDMA_ECODE_MULTICAST_ECHO_ERR] = "Multicast echo",
[HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_MISMATCH_ERR] = "AMSDU mismatch",
[HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR] = "Unauth WDS",
[HAL_REO_ENTR_RING_RXDMA_ECODE_GRPCAST_AMSDU_WDS_ERR] = "AMSDU or WDS"};
static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
[HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO] = "Desc addr zero",
[HAL_REO_DEST_RING_ERROR_CODE_DESC_INVALID] = "Desc inval",
[HAL_REO_DEST_RING_ERROR_CODE_AMPDU_IN_NON_BA] = "AMPDU in non BA",
[HAL_REO_DEST_RING_ERROR_CODE_NON_BA_DUPLICATE] = "Non BA dup",
[HAL_REO_DEST_RING_ERROR_CODE_BA_DUPLICATE] = "BA dup",
[HAL_REO_DEST_RING_ERROR_CODE_FRAME_2K_JUMP] = "Frame 2k jump",
[HAL_REO_DEST_RING_ERROR_CODE_BAR_2K_JUMP] = "BAR 2k jump",
[HAL_REO_DEST_RING_ERROR_CODE_FRAME_OOR] = "Frame OOR",
[HAL_REO_DEST_RING_ERROR_CODE_BAR_OOR] = "BAR OOR",
[HAL_REO_DEST_RING_ERROR_CODE_NO_BA_SESSION] = "No BA session",
[HAL_REO_DEST_RING_ERROR_CODE_FRAME_SN_EQUALS_SSN] = "Frame SN equal SSN",
[HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED] = "PN check fail",
[HAL_REO_DEST_RING_ERROR_CODE_2K_ERR_FLAG_SET] = "2k err",
[HAL_REO_DEST_RING_ERROR_CODE_PN_ERR_FLAG_SET] = "PN err",
[HAL_REO_DEST_RING_ERROR_CODE_DESC_BLOCKED] = "Desc blocked"};
static const char *wbm_rel_src[HAL_WBM_REL_SRC_MODULE_MAX] = {
[HAL_WBM_REL_SRC_MODULE_TQM] = "TQM",
[HAL_WBM_REL_SRC_MODULE_RXDMA] = "Rxdma",
[HAL_WBM_REL_SRC_MODULE_REO] = "Reo",
[HAL_WBM_REL_SRC_MODULE_FW] = "FW",
[HAL_WBM_REL_SRC_MODULE_SW] = "SW"};
char *buf __free(kfree) = kzalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
len += scnprintf(buf + len, size - len, "DEVICE RX STATS:\n\n");
len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
device_stats->err_ring_pkts);
len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
device_stats->invalid_rbm);
len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
len += scnprintf(buf + len, size - len, "%s: %u\n",
rxdma_err[i], device_stats->rxdma_error[i]);
len += scnprintf(buf + len, size - len, "\nREO errors:\n");
for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
len += scnprintf(buf + len, size - len, "%s: %u\n",
reo_err[i], device_stats->reo_error[i]);
len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
for (i = 0; i < DP_REO_DST_RING_MAX; i++)
len += scnprintf(buf + len, size - len,
"ring%d: %u\n", i,
device_stats->hal_reo_error[i]);
len += scnprintf(buf + len, size - len, "\nDEVICE TX STATS:\n");
len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
len += scnprintf(buf + len, size - len, "ring%d: %u\n",
i, device_stats->tx_err.desc_na[i]);
len += scnprintf(buf + len, size - len,
"\nMisc Transmit Failures: %d\n",
atomic_read(&device_stats->tx_err.misc_fail));
len += scnprintf(buf + len, size - len, "\ntx_wbm_rel_source:");
for (i = 0; i < HAL_WBM_REL_SRC_MODULE_MAX; i++)
len += scnprintf(buf + len, size - len, " %d:%u",
i, device_stats->tx_wbm_rel_source[i]);
len += scnprintf(buf + len, size - len, "\n");
len += scnprintf(buf + len, size - len, "\ntqm_rel_reason:");
for (i = 0; i < MAX_TQM_RELEASE_REASON; i++)
len += scnprintf(buf + len, size - len, " %d:%u",
i, device_stats->tqm_rel_reason[i]);
len += scnprintf(buf + len, size - len, "\n");
len += scnprintf(buf + len, size - len, "\nfw_tx_status:");
for (i = 0; i < MAX_FW_TX_STATUS; i++)
len += scnprintf(buf + len, size - len, " %d:%u",
i, device_stats->fw_tx_status[i]);
len += scnprintf(buf + len, size - len, "\n");
len += scnprintf(buf + len, size - len, "\ntx_enqueued:");
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
len += scnprintf(buf + len, size - len, " %d:%u", i,
device_stats->tx_enqueued[i]);
len += scnprintf(buf + len, size - len, "\n");
len += scnprintf(buf + len, size - len, "\ntx_completed:");
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
len += scnprintf(buf + len, size - len, " %d:%u",
i, device_stats->tx_completed[i]);
len += scnprintf(buf + len, size - len, "\n");
for (i = 0; i < ab->num_radios; i++) {
ar = ath12k_mac_get_ar_by_pdev_id(ab, DP_SW2HW_MACID(i));
if (ar) {
len += scnprintf(buf + len, size - len,
"\nradio%d tx_pending: %u\n", i,
atomic_read(&ar->dp.num_tx_pending));
}
}
len += scnprintf(buf + len, size - len, "\nREO Rx Received:\n");
for (i = 0; i < DP_REO_DST_RING_MAX; i++) {
len += scnprintf(buf + len, size - len, "Ring%d:", i + 1);
for (j = 0; j < ATH12K_MAX_DEVICES; j++) {
len += scnprintf(buf + len, size - len,
"\t%d:%u", j,
device_stats->reo_rx[i][j]);
}
len += scnprintf(buf + len, size - len, "\n");
}
len += scnprintf(buf + len, size - len, "\nRx WBM REL SRC Errors:\n");
for (i = 0; i < HAL_WBM_REL_SRC_MODULE_MAX; i++) {
len += scnprintf(buf + len, size - len, "%s:", wbm_rel_src[i]);
for (j = 0; j < ATH12K_MAX_DEVICES; j++) {
len += scnprintf(buf + len,
size - len,
"\t%d:%u", j,
device_stats->rx_wbm_rel_source[i][j]);
}
len += scnprintf(buf + len, size - len, "\n");
}
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
return ret;
}
static const struct file_operations fops_device_dp_stats = {
.read = ath12k_debugfs_dump_device_dp_stats,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
void ath12k_debugfs_pdev_create(struct ath12k_base *ab)
{
debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
&fops_simulate_fw_crash);
debugfs_create_file("device_dp_stats", 0400, ab->debugfs_soc, ab,
&fops_device_dp_stats);
}
void ath12k_debugfs_soc_create(struct ath12k_base *ab)
{
bool dput_needed;
char soc_name[64] = {};
struct dentry *debugfs_ath12k;
debugfs_ath12k = debugfs_lookup("ath12k", NULL);
if (debugfs_ath12k) {
/* a dentry from lookup() needs dput() after we don't use it */
dput_needed = true;
} else {
debugfs_ath12k = debugfs_create_dir("ath12k", NULL);
if (IS_ERR_OR_NULL(debugfs_ath12k))
return;
dput_needed = false;
}
scnprintf(soc_name, sizeof(soc_name), "%s-%s", ath12k_bus_str(ab->hif.bus),
dev_name(ab->dev));
ab->debugfs_soc = debugfs_create_dir(soc_name, debugfs_ath12k);
if (dput_needed)
dput(debugfs_ath12k);
}
void ath12k_debugfs_soc_destroy(struct ath12k_base *ab)
{
debugfs_remove_recursive(ab->debugfs_soc);
ab->debugfs_soc = NULL;
/* We are not removing ath12k directory on purpose, even if it
* would be empty. This simplifies the directory handling and it's
* a minor cosmetic issue to leave an empty ath12k directory to
* debugfs.
*/
}
wifi: ath12k: Request vdev stats from firmware Add support to request and print vdev stats from firmware through WMI. Sample output: ------------- cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/fw_stats/vdev_stats ath12k VDEV stats ================= VDEV ID 0 VDEV MAC address 00:03:7f:6c:9c:1a beacon snr 96 data snr 255 num rx frames 0 num rts fail 0 num rts success 0 num rx err 0 num rx discard 0 num tx not acked 0 num tx frames [00] 0 num tx frames [01] 0 num tx frames [02] 0 num tx frames [03] 2 num tx frames retries [00] 0 num tx frames retries [01] 0 num tx frames retries [02] 0 num tx frames retries [03] 0 num tx frames failures [00] 0 num tx frames failures [01] 0 num tx frames failures [02] 0 num tx frames failures [03] 0 tx rate history [00] 0x00000000 tx rate history [01] 0x00000000 tx rate history [02] 0x00000000 tx rate history [03] 0x00000000 tx rate history [04] 0x00000000 tx rate history [05] 0x00000000 tx rate history [06] 0x00000000 tx rate history [07] 0x00000000 tx rate history [08] 0x00000000 tx rate history [09] 0x00000000 beacon rssi history [00] 0 beacon rssi history [01] 0 beacon rssi history [02] 0 beacon rssi history [03] 0 beacon rssi history [04] 0 beacon rssi history [05] 0 beacon rssi history [06] 0 beacon rssi history [07] 0 beacon rssi history [08] 0 beacon rssi history [09] 0 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250124185330.1244585-2-ramya.gnanasekar@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-25 00:23:28 +05:30
static int ath12k_open_vdev_stats(struct inode *inode, struct file *file)
{
struct ath12k *ar = inode->i_private;
struct ath12k_fw_stats_req_params param;
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
int ret;
guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
if (!ah)
return -ENETDOWN;
if (ah->state != ATH12K_HW_STATE_ON)
return -ENETDOWN;
void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC);
if (!buf)
return -ENOMEM;
param.pdev_id = ath12k_mac_get_target_pdev_id(ar);
/* VDEV stats is always sent for all active VDEVs from FW */
param.vdev_id = 0;
param.stats_id = WMI_REQUEST_VDEV_STAT;
ret = ath12k_mac_get_fw_stats(ar, &param);
wifi: ath12k: Request vdev stats from firmware Add support to request and print vdev stats from firmware through WMI. Sample output: ------------- cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/fw_stats/vdev_stats ath12k VDEV stats ================= VDEV ID 0 VDEV MAC address 00:03:7f:6c:9c:1a beacon snr 96 data snr 255 num rx frames 0 num rts fail 0 num rts success 0 num rx err 0 num rx discard 0 num tx not acked 0 num tx frames [00] 0 num tx frames [01] 0 num tx frames [02] 0 num tx frames [03] 2 num tx frames retries [00] 0 num tx frames retries [01] 0 num tx frames retries [02] 0 num tx frames retries [03] 0 num tx frames failures [00] 0 num tx frames failures [01] 0 num tx frames failures [02] 0 num tx frames failures [03] 0 tx rate history [00] 0x00000000 tx rate history [01] 0x00000000 tx rate history [02] 0x00000000 tx rate history [03] 0x00000000 tx rate history [04] 0x00000000 tx rate history [05] 0x00000000 tx rate history [06] 0x00000000 tx rate history [07] 0x00000000 tx rate history [08] 0x00000000 tx rate history [09] 0x00000000 beacon rssi history [00] 0 beacon rssi history [01] 0 beacon rssi history [02] 0 beacon rssi history [03] 0 beacon rssi history [04] 0 beacon rssi history [05] 0 beacon rssi history [06] 0 beacon rssi history [07] 0 beacon rssi history [08] 0 beacon rssi history [09] 0 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250124185330.1244585-2-ramya.gnanasekar@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-25 00:23:28 +05:30
if (ret) {
ath12k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
return ret;
}
ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id,
buf);
file->private_data = no_free_ptr(buf);
return 0;
}
static int ath12k_release_vdev_stats(struct inode *inode, struct file *file)
{
kfree(file->private_data);
return 0;
}
static ssize_t ath12k_read_vdev_stats(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
const char *buf = file->private_data;
size_t len = strlen(buf);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static const struct file_operations fops_vdev_stats = {
.open = ath12k_open_vdev_stats,
.release = ath12k_release_vdev_stats,
.read = ath12k_read_vdev_stats,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static int ath12k_open_bcn_stats(struct inode *inode, struct file *file)
{
struct ath12k *ar = inode->i_private;
struct ath12k_link_vif *arvif;
struct ath12k_fw_stats_req_params param;
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
int ret;
guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
if (ah && ah->state != ATH12K_HW_STATE_ON)
return -ENETDOWN;
void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC);
if (!buf)
return -ENOMEM;
param.pdev_id = ath12k_mac_get_target_pdev_id(ar);
param.stats_id = WMI_REQUEST_BCN_STAT;
/* loop all active VDEVs for bcn stats */
list_for_each_entry(arvif, &ar->arvifs, list) {
if (!arvif->is_up)
continue;
param.vdev_id = arvif->vdev_id;
ret = ath12k_mac_get_fw_stats(ar, &param);
if (ret) {
ath12k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
return ret;
}
}
ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id,
buf);
/* since beacon stats request is looped for all active VDEVs, saved fw
* stats is not freed for each request until done for all active VDEVs
*/
spin_lock_bh(&ar->data_lock);
ath12k_fw_stats_bcn_free(&ar->fw_stats.bcn);
spin_unlock_bh(&ar->data_lock);
file->private_data = no_free_ptr(buf);
return 0;
}
static int ath12k_release_bcn_stats(struct inode *inode, struct file *file)
{
kfree(file->private_data);
return 0;
}
static ssize_t ath12k_read_bcn_stats(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
const char *buf = file->private_data;
size_t len = strlen(buf);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static const struct file_operations fops_bcn_stats = {
.open = ath12k_open_bcn_stats,
.release = ath12k_release_bcn_stats,
.read = ath12k_read_bcn_stats,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
wifi: ath12k: Request pdev stats from firmware Add support to request pdev stats from firmware through WMI and print the information Sample Output: ------------- cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/fw_stats/pdev_stats ath12k PDEV stats ================= Channel noise floor -85 Channel TX power 126 TX frame count 0 RX frame count 8637 RX clear count 37424 Cycle count 4372024 PHY error count 0 soc drop count 0 ath12k PDEV TX stats ==================== HTT cookies queued 0 HTT cookies disp. 0 MSDU queued 0 MPDU queued 0 MSDUs dropped 0 Local enqued 0 Local freed 0 HW queued 0 PPDUs reaped 0 Num underruns 0 PPDUs cleaned 0 MPDUs requeued 0 Excessive retries 0 HW rate 0 Sched self triggers 0 Dropped due to SW retries 0 Illegal rate phy errors 0 PDEV continuous xretry 0 TX timeout 9 PDEV resets 0 Stateless TIDs alloc failures 0 PHY underrun 0 MPDU is more than txop limit 0 ath12k PDEV RX stats ==================== Mid PPDU route change 0 Tot. number of statuses 0 Extra frags on rings 0 0 Extra frags on rings 1 0 Extra frags on rings 2 0 Extra frags on rings 3 0 MSDUs delivered to HTT 0 MPDUs delivered to HTT 0 MSDUs delivered to stack 0 MPDUs delivered to stack 0 Oversized AMSUs 0 PHY errors 0 PHY errors drops 0 MPDU errors (FCS, MIC, ENC) 0 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250124185330.1244585-4-ramya.gnanasekar@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-25 00:23:30 +05:30
static int ath12k_open_pdev_stats(struct inode *inode, struct file *file)
{
struct ath12k *ar = inode->i_private;
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
struct ath12k_base *ab = ar->ab;
struct ath12k_fw_stats_req_params param;
int ret;
guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
if (ah && ah->state != ATH12K_HW_STATE_ON)
return -ENETDOWN;
void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC);
if (!buf)
return -ENOMEM;
param.pdev_id = ath12k_mac_get_target_pdev_id(ar);
param.vdev_id = 0;
param.stats_id = WMI_REQUEST_PDEV_STAT;
ret = ath12k_mac_get_fw_stats(ar, &param);
wifi: ath12k: Request pdev stats from firmware Add support to request pdev stats from firmware through WMI and print the information Sample Output: ------------- cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/fw_stats/pdev_stats ath12k PDEV stats ================= Channel noise floor -85 Channel TX power 126 TX frame count 0 RX frame count 8637 RX clear count 37424 Cycle count 4372024 PHY error count 0 soc drop count 0 ath12k PDEV TX stats ==================== HTT cookies queued 0 HTT cookies disp. 0 MSDU queued 0 MPDU queued 0 MSDUs dropped 0 Local enqued 0 Local freed 0 HW queued 0 PPDUs reaped 0 Num underruns 0 PPDUs cleaned 0 MPDUs requeued 0 Excessive retries 0 HW rate 0 Sched self triggers 0 Dropped due to SW retries 0 Illegal rate phy errors 0 PDEV continuous xretry 0 TX timeout 9 PDEV resets 0 Stateless TIDs alloc failures 0 PHY underrun 0 MPDU is more than txop limit 0 ath12k PDEV RX stats ==================== Mid PPDU route change 0 Tot. number of statuses 0 Extra frags on rings 0 0 Extra frags on rings 1 0 Extra frags on rings 2 0 Extra frags on rings 3 0 MSDUs delivered to HTT 0 MPDUs delivered to HTT 0 MSDUs delivered to stack 0 MPDUs delivered to stack 0 Oversized AMSUs 0 PHY errors 0 PHY errors drops 0 MPDU errors (FCS, MIC, ENC) 0 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250124185330.1244585-4-ramya.gnanasekar@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-25 00:23:30 +05:30
if (ret) {
ath12k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
return ret;
}
ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id,
buf);
file->private_data = no_free_ptr(buf);
return 0;
}
static int ath12k_release_pdev_stats(struct inode *inode, struct file *file)
{
kfree(file->private_data);
return 0;
}
static ssize_t ath12k_read_pdev_stats(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
const char *buf = file->private_data;
size_t len = strlen(buf);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static const struct file_operations fops_pdev_stats = {
.open = ath12k_open_pdev_stats,
.release = ath12k_release_pdev_stats,
.read = ath12k_read_pdev_stats,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
wifi: ath12k: Request vdev stats from firmware Add support to request and print vdev stats from firmware through WMI. Sample output: ------------- cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/fw_stats/vdev_stats ath12k VDEV stats ================= VDEV ID 0 VDEV MAC address 00:03:7f:6c:9c:1a beacon snr 96 data snr 255 num rx frames 0 num rts fail 0 num rts success 0 num rx err 0 num rx discard 0 num tx not acked 0 num tx frames [00] 0 num tx frames [01] 0 num tx frames [02] 0 num tx frames [03] 2 num tx frames retries [00] 0 num tx frames retries [01] 0 num tx frames retries [02] 0 num tx frames retries [03] 0 num tx frames failures [00] 0 num tx frames failures [01] 0 num tx frames failures [02] 0 num tx frames failures [03] 0 tx rate history [00] 0x00000000 tx rate history [01] 0x00000000 tx rate history [02] 0x00000000 tx rate history [03] 0x00000000 tx rate history [04] 0x00000000 tx rate history [05] 0x00000000 tx rate history [06] 0x00000000 tx rate history [07] 0x00000000 tx rate history [08] 0x00000000 tx rate history [09] 0x00000000 beacon rssi history [00] 0 beacon rssi history [01] 0 beacon rssi history [02] 0 beacon rssi history [03] 0 beacon rssi history [04] 0 beacon rssi history [05] 0 beacon rssi history [06] 0 beacon rssi history [07] 0 beacon rssi history [08] 0 beacon rssi history [09] 0 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250124185330.1244585-2-ramya.gnanasekar@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-25 00:23:28 +05:30
static
void ath12k_debugfs_fw_stats_register(struct ath12k *ar)
{
struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
ar->debug.debugfs_pdev);
/* all stats debugfs files created are under "fw_stats" directory
* created per PDEV
*/
debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar,
&fops_vdev_stats);
debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
&fops_bcn_stats);
wifi: ath12k: Request pdev stats from firmware Add support to request pdev stats from firmware through WMI and print the information Sample Output: ------------- cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/fw_stats/pdev_stats ath12k PDEV stats ================= Channel noise floor -85 Channel TX power 126 TX frame count 0 RX frame count 8637 RX clear count 37424 Cycle count 4372024 PHY error count 0 soc drop count 0 ath12k PDEV TX stats ==================== HTT cookies queued 0 HTT cookies disp. 0 MSDU queued 0 MPDU queued 0 MSDUs dropped 0 Local enqued 0 Local freed 0 HW queued 0 PPDUs reaped 0 Num underruns 0 PPDUs cleaned 0 MPDUs requeued 0 Excessive retries 0 HW rate 0 Sched self triggers 0 Dropped due to SW retries 0 Illegal rate phy errors 0 PDEV continuous xretry 0 TX timeout 9 PDEV resets 0 Stateless TIDs alloc failures 0 PHY underrun 0 MPDU is more than txop limit 0 ath12k PDEV RX stats ==================== Mid PPDU route change 0 Tot. number of statuses 0 Extra frags on rings 0 0 Extra frags on rings 1 0 Extra frags on rings 2 0 Extra frags on rings 3 0 MSDUs delivered to HTT 0 MPDUs delivered to HTT 0 MSDUs delivered to stack 0 MPDUs delivered to stack 0 Oversized AMSUs 0 PHY errors 0 PHY errors drops 0 MPDU errors (FCS, MIC, ENC) 0 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250124185330.1244585-4-ramya.gnanasekar@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-25 00:23:30 +05:30
debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
&fops_pdev_stats);
wifi: ath12k: Request vdev stats from firmware Add support to request and print vdev stats from firmware through WMI. Sample output: ------------- cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/fw_stats/vdev_stats ath12k VDEV stats ================= VDEV ID 0 VDEV MAC address 00:03:7f:6c:9c:1a beacon snr 96 data snr 255 num rx frames 0 num rts fail 0 num rts success 0 num rx err 0 num rx discard 0 num tx not acked 0 num tx frames [00] 0 num tx frames [01] 0 num tx frames [02] 0 num tx frames [03] 2 num tx frames retries [00] 0 num tx frames retries [01] 0 num tx frames retries [02] 0 num tx frames retries [03] 0 num tx frames failures [00] 0 num tx frames failures [01] 0 num tx frames failures [02] 0 num tx frames failures [03] 0 tx rate history [00] 0x00000000 tx rate history [01] 0x00000000 tx rate history [02] 0x00000000 tx rate history [03] 0x00000000 tx rate history [04] 0x00000000 tx rate history [05] 0x00000000 tx rate history [06] 0x00000000 tx rate history [07] 0x00000000 tx rate history [08] 0x00000000 tx rate history [09] 0x00000000 beacon rssi history [00] 0 beacon rssi history [01] 0 beacon rssi history [02] 0 beacon rssi history [03] 0 beacon rssi history [04] 0 beacon rssi history [05] 0 beacon rssi history [06] 0 beacon rssi history [07] 0 beacon rssi history [08] 0 beacon rssi history [09] 0 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250124185330.1244585-2-ramya.gnanasekar@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-25 00:23:28 +05:30
ath12k_fw_stats_init(ar);
wifi: ath12k: Request vdev stats from firmware Add support to request and print vdev stats from firmware through WMI. Sample output: ------------- cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/fw_stats/vdev_stats ath12k VDEV stats ================= VDEV ID 0 VDEV MAC address 00:03:7f:6c:9c:1a beacon snr 96 data snr 255 num rx frames 0 num rts fail 0 num rts success 0 num rx err 0 num rx discard 0 num tx not acked 0 num tx frames [00] 0 num tx frames [01] 0 num tx frames [02] 0 num tx frames [03] 2 num tx frames retries [00] 0 num tx frames retries [01] 0 num tx frames retries [02] 0 num tx frames retries [03] 0 num tx frames failures [00] 0 num tx frames failures [01] 0 num tx frames failures [02] 0 num tx frames failures [03] 0 tx rate history [00] 0x00000000 tx rate history [01] 0x00000000 tx rate history [02] 0x00000000 tx rate history [03] 0x00000000 tx rate history [04] 0x00000000 tx rate history [05] 0x00000000 tx rate history [06] 0x00000000 tx rate history [07] 0x00000000 tx rate history [08] 0x00000000 tx rate history [09] 0x00000000 beacon rssi history [00] 0 beacon rssi history [01] 0 beacon rssi history [02] 0 beacon rssi history [03] 0 beacon rssi history [04] 0 beacon rssi history [05] 0 beacon rssi history [06] 0 beacon rssi history [07] 0 beacon rssi history [08] 0 beacon rssi history [09] 0 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250124185330.1244585-2-ramya.gnanasekar@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-25 00:23:28 +05:30
}
void ath12k_debugfs_register(struct ath12k *ar)
{
struct ath12k_base *ab = ar->ab;
struct ieee80211_hw *hw = ar->ah->hw;
char pdev_name[5];
char buf[100] = {};
scnprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
/* Create a symlink under ieee80211/phy* */
scnprintf(buf, sizeof(buf), "../../ath12k/%pd2", ar->debug.debugfs_pdev);
ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k",
hw->wiphy->debugfsdir,
buf);
if (ar->mac.sbands[NL80211_BAND_5GHZ].channels) {
debugfs_create_file("dfs_simulate_radar", 0200,
ar->debug.debugfs_pdev, ar,
&fops_simulate_radar);
}
wifi: ath12k: Add Support to Parse TPC Event from Firmware Host receives four Transmit Power Control(TPC) events from firmware on sending TPC request. Fixed param TLV is present as part of all event to indicate the event count and end of event. TPC config parameters along with regulatory power array comes as first event. Rates array comes as second and third event as it cannot be packed in single event. Conformance Test Limit (CTL) power array comes as the fourth event. Firmware packs different sets of array params which includes array length and type inside master TLV as different subtlvs. And the actual content of array is packed one after the other inside a separate TLV as single buffer. Parse various events and save it in local structures. Create tpc_stats file using debugfs to store these local structures. Create function to handle TPC stats read to relay the information to the user. Command usage: cat > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sowmiya Sree Elavalagan <quic_ssreeela@quicinc.com> Co-developed-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Co-developed-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Signed-off-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250130061104.962124-2-quic_rdevanat@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-30 11:41:03 +05:30
debugfs_create_file("tpc_stats", 0400, ar->debug.debugfs_pdev, ar,
&fops_tpc_stats);
wifi: ath12k: Add Support to Calculate and Display TPC Values Transmit Power Control(TPC) stats should display per chain TPC value per radio. Add debugfs support to read and display TPC stats type and TPC stats. Take power values for each preamble type, rate and NSS combination from a particular index from each power arrays based on number of chains, NSS, modes, MCS and tx beamforming enabled/disabled parameters. Minimum of the values taken from reg power table, rates and Conformance Test Limit(CTL) array table should give the TPC which is in 0.25 dBm steps. Sample Output: ------------- echo 1 > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats_type cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats *************** TPC config ************** * powers are in 0.25 dBm steps reg domain-22 chan freq-5955 power limit-126 max reg-domain Power-252 No.of tx chain-4 No.of rates-1164 **************** SU WITH TXBF **************** TPC values for Active chains Rate idx Preamble Rate code 1-Chain 2-Chain 3-Chain 4-Chain 4 OFDM 0x000 39 15 1 -9 5 OFDM 0x001 39 15 1 -9 ..... 12 HT20 0x200 40 16 2 -8 13 HT20 0x201 40 16 2 -8 ..... 44 HT40 0x200 88 88 88 88 45 HT40 0x201 88 88 88 88 ..... 76 VHT20 0x300 40 16 2 -8 77 VHT20 0x301 40 16 2 -8 ..... 172 VHT40 0x300 88 88 88 88 173 VHT40 0x301 88 88 88 88 ..... 412 HE20 0x400 88 88 88 88 413 HE20 0x401 88 88 88 88 ..... 508 HE40 0x400 76 76 76 76 509 HE40 0x401 76 76 76 76 ..... 748 EHT20 0x50e 88 88 88 88 749 EHT20 0x50f 88 88 88 88 ..... 812 EHT40 0x50e 88 88 88 88 813 EHT40 0x50f 88 88 88 88 ..... Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sowmiya Sree Elavalagan <quic_ssreeela@quicinc.com> Co-developed-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Co-developed-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Signed-off-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250130061104.962124-3-quic_rdevanat@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-30 11:41:04 +05:30
debugfs_create_file("tpc_stats_type", 0200, ar->debug.debugfs_pdev,
ar, &fops_tpc_stats_type);
init_completion(&ar->debug.tpc_complete);
wifi: ath12k: Add Support to Parse TPC Event from Firmware Host receives four Transmit Power Control(TPC) events from firmware on sending TPC request. Fixed param TLV is present as part of all event to indicate the event count and end of event. TPC config parameters along with regulatory power array comes as first event. Rates array comes as second and third event as it cannot be packed in single event. Conformance Test Limit (CTL) power array comes as the fourth event. Firmware packs different sets of array params which includes array length and type inside master TLV as different subtlvs. And the actual content of array is packed one after the other inside a separate TLV as single buffer. Parse various events and save it in local structures. Create tpc_stats file using debugfs to store these local structures. Create function to handle TPC stats read to relay the information to the user. Command usage: cat > /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/tpc_stats Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sowmiya Sree Elavalagan <quic_ssreeela@quicinc.com> Co-developed-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Co-developed-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Signed-off-by: Roopni Devanathan <quic_rdevanat@quicinc.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250130061104.962124-2-quic_rdevanat@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-30 11:41:03 +05:30
ath12k_debugfs_htt_stats_register(ar);
wifi: ath12k: Request vdev stats from firmware Add support to request and print vdev stats from firmware through WMI. Sample output: ------------- cat /sys/kernel/debug/ath12k/pci-0000\:06\:00.0/mac0/fw_stats/vdev_stats ath12k VDEV stats ================= VDEV ID 0 VDEV MAC address 00:03:7f:6c:9c:1a beacon snr 96 data snr 255 num rx frames 0 num rts fail 0 num rts success 0 num rx err 0 num rx discard 0 num tx not acked 0 num tx frames [00] 0 num tx frames [01] 0 num tx frames [02] 0 num tx frames [03] 2 num tx frames retries [00] 0 num tx frames retries [01] 0 num tx frames retries [02] 0 num tx frames retries [03] 0 num tx frames failures [00] 0 num tx frames failures [01] 0 num tx frames failures [02] 0 num tx frames failures [03] 0 tx rate history [00] 0x00000000 tx rate history [01] 0x00000000 tx rate history [02] 0x00000000 tx rate history [03] 0x00000000 tx rate history [04] 0x00000000 tx rate history [05] 0x00000000 tx rate history [06] 0x00000000 tx rate history [07] 0x00000000 tx rate history [08] 0x00000000 tx rate history [09] 0x00000000 beacon rssi history [00] 0 beacon rssi history [01] 0 beacon rssi history [02] 0 beacon rssi history [03] 0 beacon rssi history [04] 0 beacon rssi history [05] 0 beacon rssi history [06] 0 beacon rssi history [07] 0 beacon rssi history [08] 0 beacon rssi history [09] 0 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com> Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com> Link: https://patch.msgid.link/20250124185330.1244585-2-ramya.gnanasekar@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-01-25 00:23:28 +05:30
ath12k_debugfs_fw_stats_register(ar);
wifi: ath12k: Add peer extended Rx statistics debugfs support Currently, peer extended Rx statistics are not supported. Therefore, expose peer extended Rx statistics support through debugfs, allowing users to enable or disable the collection of statistics information. After that the statistics information can be dumped through debugfs. Below are the debugfs commands exposed. Enable/Disable: echo <1/0> > /sys/kernel/debug/ieee80211/phyX/ath12k/ext_rx_stats Dump: cat /sys/kernel/debug/ieee80211/phyX/netdev:wlanX/stations/<peer MAC addr>/rx_stats Sample output: ============== RX peer stats: Num of MSDUs: 1087 Num of MSDUs with TCP L4: 0 Num of MSDUs with UDP L4: 13 Num of other MSDUs: 1074 Num of MSDUs part of AMPDU: 363 Num of MSDUs not part of AMPDU: 724 Num of MSDUs using STBC: 0 Num of MSDUs beamformed: 0 Num of MPDUs with FCS ok: 695 Num of MPDUs with FCS error: 0 preamble: 11A 395 11B 0 11N 0 11AC 0 11AX 692 11BE 0 reception type: SU 1087 MU_MIMO 0 MU_OFDMA 0 MU_OFDMA_MIMO 0 TID(0-15) Legacy TID(16):690 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 395 RX Duration:39537 DCM: 0 RU26: 0 RU52: 0 RU106: 0 RU242: 0 RU484: 0 RU996: 0 RX success packet stats: EHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 HE stats: MCS 0: 1 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 66 MCS 7: 46 MCS 8: 46 MCS 9: 34 MCS 10: 28 MCS 11: 471 VHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 HT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 MCS 16: 0 MCS 17: 0 MCS 18: 0 MCS 19: 0 MCS 20: 0 MCS 21: 0 MCS 22: 0 MCS 23: 0 MCS 24: 0 MCS 25: 0 MCS 26: 0 MCS 27: 0 MCS 28: 0 MCS 29: 0 MCS 30: 0 MCS 31: 0 Legacy stats: 1 Mbps: 0 2 Mbps: 0 5.5 Mbps: 0 6 Mbps: 395 9 Mbps: 0 11 Mbps: 0 12 Mbps: 0 18 Mbps: 0 24 Mbps: 0 36 Mbps: 0 48 Mbps: 0 54 Mbps: 0 NSS stats: 1x1: 1086 2x2: 0 3x3: 0 4x4: 0 5x5: 0 6x6: 0 7x7: 0 8x8: 0 GI: 0.8 us 0 0.4 us 396 1.6 us 691 3.2 us 0 BW: 20 MHz 785 40 MHz 2 80 MHz 300 160 MHz 0 320 MHz 0 20 Mhz gi 1 us 1x1 : 6:5 7:3 8:3 9:4 10:4 11:374 12:391 40 Mhz gi 1 us 1x1 : 12:2 80 Mhz gi 1 us 1x1 : 6:61 7:43 8:43 9:30 10:24 11:97 12:2 RX success byte stats: EHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 HE stats: MCS 0: 41 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 1435 MCS 7: 943 MCS 8: 697 MCS 9: 533 MCS 10: 492 MCS 11: 8159 VHT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 HT stats: MCS 0: 0 MCS 1: 0 MCS 2: 0 MCS 3: 0 MCS 4: 0 MCS 5: 0 MCS 6: 0 MCS 7: 0 MCS 8: 0 MCS 9: 0 MCS 10: 0 MCS 11: 0 MCS 12: 0 MCS 13: 0 MCS 14: 0 MCS 15: 0 MCS 16: 0 MCS 17: 0 MCS 18: 0 MCS 19: 0 MCS 20: 0 MCS 21: 0 MCS 22: 0 MCS 23: 0 MCS 24: 0 MCS 25: 0 MCS 26: 0 MCS 27: 0 MCS 28: 0 MCS 29: 0 MCS 30: 0 MCS 31: 0 Legacy stats: 1 Mbps: 0 2 Mbps: 0 5.5 Mbps: 0 6 Mbps: 16195 9 Mbps: 0 11 Mbps: 0 12 Mbps: 0 18 Mbps: 0 24 Mbps: 0 36 Mbps: 0 48 Mbps: 0 54 Mbps: 0 NSS stats: 1x1: 28454 2x2: 0 3x3: 0 4x4: 0 5x5: 0 6x6: 0 7x7: 0 8x8: 0 GI: 0.8 us 0 0.4 us 16236 1.6 us 12259 3.2 us 0 BW: 20 MHz 24108 40 MHz 82 80 MHz 4305 160 MHz 0 320 MHz 0 20 Mhz gi 1 us 1x1 : 6:205 7:123 8:123 9:164 10:164 11:7257 12:16031 40 Mhz gi 1 us 1x1 : 12:82 80 Mhz gi 1 us 1x1 : 6:1230 7:820 8:574 9:369 10:328 11:902 12:82 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Co-developed-by: P Praneesh <quic_ppranees@quicinc.com> Signed-off-by: P Praneesh <quic_ppranees@quicinc.com> Co-developed-by: Balamurugan Mahalingam <quic_bmahalin@quicinc.com> Signed-off-by: Balamurugan Mahalingam <quic_bmahalin@quicinc.com> Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com> Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com> Link: https://patch.msgid.link/20250206013854.174765-10-quic_periyasa@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
2025-02-06 07:08:54 +05:30
debugfs_create_file("ext_rx_stats", 0644,
ar->debug.debugfs_pdev, ar,
&fops_extd_rx_stats);
}
void ath12k_debugfs_unregister(struct ath12k *ar)
{
if (!ar->debug.debugfs_pdev)
return;
/* Remove symlink under ieee80211/phy* */
debugfs_remove(ar->debug.debugfs_pdev_symlink);
debugfs_remove_recursive(ar->debug.debugfs_pdev);
ar->debug.debugfs_pdev_symlink = NULL;
ar->debug.debugfs_pdev = NULL;
}