summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath10k/debug.c
diff options
context:
space:
mode:
authorMaharaja Kennadyrajan <mkenna@codeaurora.org>2018-03-14 12:14:08 +0200
committerKalle Valo <kvalo@codeaurora.org>2018-03-26 18:08:56 +0300
commitbc64d05220f3e34cf432a166b83c8fff14cd7a3d (patch)
treea24aa520e64a468251560ded2be042442a95492f /drivers/net/wireless/ath/ath10k/debug.c
parentcaee728ab761fa1255ff636aec13c87a3d01364d (diff)
downloadlinux-bc64d05220f3e34cf432a166b83c8fff14cd7a3d.tar.bz2
ath10k: debugfs support to get final TPC stats for 10.4 variants
Export the final Transmit Power Control (TPC) value, which is the minimum of control power and existing TPC value to user space via a new debugfs file "tpc_stats_final" to help with debugging. It works with the new wmi cmd and event introduced in 10.4 firmware branch. WMI command ID: WMI_PDEV_GET_TPC_TABLE_CMDID WMI event ID: WMI_PDEV_TPC_TABLE_EVENTID cat /sys/kernel/debug/ieee80211/phyX/ath10k/tpc_stats_final $ cat /sys/kernel/debug/ieee80211/phyX/ath10k/tpc_stats_final TPC config for channel 5180 mode 10 CTL = 0x 0 Reg. Domain = 58 Antenna Gain = 0 Reg. Max Antenna Gain = 0 Power Limit = 60 Reg. Max Power = 60 Num tx chains = 2 Num supported rates = 109 ******************* CDD POWER TABLE **************** No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3 0 CCK 0x40 0 0 1 CCK 0x41 0 0 [...] 107 HTCUP 0x 0 46 46 108 HTCUP 0x 0 46 46 ******************* STBC POWER TABLE **************** No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3 0 CCK 0x40 0 0 1 CCK 0x41 0 0 [...] 107 HTCUP 0x 0 46 46 108 HTCUP 0x 0 46 46 *********************************** TXBF not supported ********************************** The existing tpc_stats debugfs file provides the dump which is minimum of target power and regulatory domain. cat /sys/kernel/debug/ieee80211/phyX/ath10k/tpc_stats Hardware_used: QCA4019 Firmware version: firmware-5.bin_10.4-3.0-00209 Signed-off-by: Maharaja Kennadyrajan <mkenna@codeaurora.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/debug.c')
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 1b9c092d210f..bac832ce1873 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1480,6 +1480,19 @@ void ath10k_debug_tpc_stats_process(struct ath10k *ar,
spin_unlock_bh(&ar->data_lock);
}
+void
+ath10k_debug_tpc_stats_final_process(struct ath10k *ar,
+ struct ath10k_tpc_stats_final *tpc_stats)
+{
+ spin_lock_bh(&ar->data_lock);
+
+ kfree(ar->debug.tpc_stats_final);
+ ar->debug.tpc_stats_final = tpc_stats;
+ complete(&ar->debug.tpc_complete);
+
+ spin_unlock_bh(&ar->data_lock);
+}
+
static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
unsigned int j, char *buf, size_t *len)
{
@@ -2185,6 +2198,95 @@ static const struct file_operations fops_sta_tid_stats_mask = {
.llseek = default_llseek,
};
+static int ath10k_debug_tpc_stats_final_request(struct ath10k *ar)
+{
+ int ret;
+ unsigned long time_left;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ reinit_completion(&ar->debug.tpc_complete);
+
+ ret = ath10k_wmi_pdev_get_tpc_table_cmdid(ar, WMI_TPC_CONFIG_PARAM);
+ if (ret) {
+ ath10k_warn(ar, "failed to request tpc table cmdid: %d\n", ret);
+ return ret;
+ }
+
+ time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
+ 1 * HZ);
+ if (time_left == 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int ath10k_tpc_stats_final_open(struct inode *inode, struct file *file)
+{
+ struct ath10k *ar = inode->i_private;
+ void *buf;
+ int ret;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state != ATH10K_STATE_ON) {
+ ret = -ENETDOWN;
+ goto err_unlock;
+ }
+
+ buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto err_unlock;
+ }
+
+ ret = ath10k_debug_tpc_stats_final_request(ar);
+ if (ret) {
+ ath10k_warn(ar, "failed to request tpc stats final: %d\n",
+ ret);
+ goto err_free;
+ }
+
+ ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
+ file->private_data = buf;
+
+ mutex_unlock(&ar->conf_mutex);
+ return 0;
+
+err_free:
+ vfree(buf);
+
+err_unlock:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+static int ath10k_tpc_stats_final_release(struct inode *inode,
+ struct file *file)
+{
+ vfree(file->private_data);
+
+ return 0;
+}
+
+static ssize_t ath10k_tpc_stats_final_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ const char *buf = file->private_data;
+ unsigned int len = strlen(buf);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_tpc_stats_final = {
+ .open = ath10k_tpc_stats_final_open,
+ .release = ath10k_tpc_stats_final_release,
+ .read = ath10k_tpc_stats_final_read,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
int ath10k_debug_create(struct ath10k *ar)
{
ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
@@ -2305,6 +2407,11 @@ int ath10k_debug_register(struct ath10k *ar)
ar->debug.debugfs_phy,
ar, &fops_sta_tid_stats_mask);
+ if (test_bit(WMI_SERVICE_TPC_STATS_FINAL, ar->wmi.svc_map))
+ debugfs_create_file("tpc_stats_final", 0400,
+ ar->debug.debugfs_phy, ar,
+ &fops_tpc_stats_final);
+
return 0;
}