blob: 4cd2a0fd49d6e53c08c7d2af5b1d1542f811affd [file] [log] [blame]
Kalle Valo5e3dd152013-06-12 20:52:10 +03001/*
2 * Copyright (c) 2005-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <linux/module.h>
19#include <linux/debugfs.h>
Ben Greear384914b2014-08-25 08:37:32 +030020#include <linux/vmalloc.h>
Johannes Berg12c27152014-11-21 18:58:49 +020021#include <linux/utsname.h>
Kalle Valo3e580442015-11-25 15:38:34 +020022#include <linux/crc32.h>
23#include <linux/firmware.h>
Arun Khandavalli727000e2016-12-21 14:19:21 +020024#include <linux/devcoredump.h>
Kalle Valo5e3dd152013-06-12 20:52:10 +030025
26#include "core.h"
27#include "debug.h"
Kalle Valo7869b4f2014-09-24 14:16:58 +030028#include "hif.h"
Michal Kaziord7579d12014-12-03 10:10:54 +020029#include "wmi-ops.h"
Kalle Valo5e3dd152013-06-12 20:52:10 +030030
Kalle Valoa3d135e2013-09-03 11:44:10 +030031/* ms */
32#define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
33
Marty Faltesekf67b107d2016-10-10 19:00:04 +030034#define ATH10K_DEBUG_CAL_DATA_LEN 12064
35
Ben Greear384914b2014-08-25 08:37:32 +030036#define ATH10K_FW_CRASH_DUMP_VERSION 1
37
38/**
39 * enum ath10k_fw_crash_dump_type - types of data in the dump file
40 * @ATH10K_FW_CRASH_DUMP_REGDUMP: Register crash dump in binary format
41 */
42enum ath10k_fw_crash_dump_type {
43 ATH10K_FW_CRASH_DUMP_REGISTERS = 0,
Mohammed Shafi Shajakhanc75c3982017-01-16 17:31:08 +020044 ATH10K_FW_CRASH_DUMP_CE_DATA = 1,
Ben Greear384914b2014-08-25 08:37:32 +030045
46 ATH10K_FW_CRASH_DUMP_MAX,
47};
48
49struct ath10k_tlv_dump_data {
50 /* see ath10k_fw_crash_dump_type above */
51 __le32 type;
52
53 /* in bytes */
54 __le32 tlv_len;
55
56 /* pad to 32-bit boundaries as needed */
57 u8 tlv_data[];
58} __packed;
59
60struct ath10k_dump_file_data {
61 /* dump file information */
62
63 /* "ATH10K-FW-DUMP" */
64 char df_magic[16];
65
66 __le32 len;
67
68 /* file dump version */
69 __le32 version;
70
71 /* some info we can get from ath10k struct that might help */
72
73 u8 uuid[16];
74
75 __le32 chip_id;
76
77 /* 0 for now, in place for later hardware */
78 __le32 bus_type;
79
80 __le32 target_version;
81 __le32 fw_version_major;
82 __le32 fw_version_minor;
83 __le32 fw_version_release;
84 __le32 fw_version_build;
85 __le32 phy_capability;
86 __le32 hw_min_tx_power;
87 __le32 hw_max_tx_power;
88 __le32 ht_cap_info;
89 __le32 vht_cap_info;
90 __le32 num_rf_chains;
91
92 /* firmware version string */
93 char fw_ver[ETHTOOL_FWVERS_LEN];
94
95 /* Kernel related information */
96
97 /* time-of-day stamp */
98 __le64 tv_sec;
99
100 /* time-of-day stamp, nano-seconds */
101 __le64 tv_nsec;
102
103 /* LINUX_VERSION_CODE */
104 __le32 kernel_ver_code;
105
106 /* VERMAGIC_STRING */
107 char kernel_ver[64];
108
109 /* room for growth w/out changing binary format */
110 u8 unused[128];
111
112 /* struct ath10k_tlv_dump_data + more */
113 u8 data[0];
114} __packed;
115
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700116void ath10k_info(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300117{
118 struct va_format vaf = {
119 .fmt = fmt,
120 };
121 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300122
123 va_start(args, fmt);
124 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700125 dev_info(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300126 trace_ath10k_log_info(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300127 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300128}
129EXPORT_SYMBOL(ath10k_info);
130
Kalle Valo23f591e2015-11-25 15:38:27 +0200131void ath10k_debug_print_hwfw_info(struct ath10k *ar)
Kalle Valo8a0c7972014-08-25 08:37:45 +0300132{
Kalle Valo7ebf7212016-04-20 19:44:51 +0300133 const struct firmware *firmware;
Michal Kazior84e3df62015-08-05 06:55:37 +0200134 char fw_features[128] = {};
Michal Kazior8866c722016-03-17 10:52:08 +0100135 u32 crc = 0;
Michal Kaziorb27bc5a2015-06-15 14:46:40 +0300136
137 ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
138
Kalle Valo8605c022015-11-25 15:38:19 +0200139 ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x",
Kalle Valo8a0c7972014-08-25 08:37:45 +0300140 ar->hw_params.name,
141 ar->target_version,
142 ar->chip_id,
Kalle Valo8605c022015-11-25 15:38:19 +0200143 ar->id.subsystem_vendor, ar->id.subsystem_device);
Kalle Valof0de90b2015-11-25 15:38:12 +0200144
Kalle Valof0de90b2015-11-25 15:38:12 +0200145 ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n",
Masahiro Yamada97f26452016-08-03 13:45:50 -0700146 IS_ENABLED(CONFIG_ATH10K_DEBUG),
147 IS_ENABLED(CONFIG_ATH10K_DEBUGFS),
148 IS_ENABLED(CONFIG_ATH10K_TRACING),
149 IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED),
150 IS_ENABLED(CONFIG_NL80211_TESTMODE));
Kalle Valof0de90b2015-11-25 15:38:12 +0200151
Kalle Valo7ebf7212016-04-20 19:44:51 +0300152 firmware = ar->normal_mode_fw.fw_file.firmware;
153 if (firmware)
154 crc = crc32_le(0, firmware->data, firmware->size);
Michal Kazior8866c722016-03-17 10:52:08 +0100155
Kalle Valo3e580442015-11-25 15:38:34 +0200156 ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",
Kalle Valo23f591e2015-11-25 15:38:27 +0200157 ar->hw->wiphy->fw_version,
158 ar->fw_api,
Kalle Valo3e580442015-11-25 15:38:34 +0200159 fw_features,
Michal Kazior8866c722016-03-17 10:52:08 +0100160 crc);
Kalle Valo23f591e2015-11-25 15:38:27 +0200161}
162
163void ath10k_debug_print_board_info(struct ath10k *ar)
164{
165 char boardinfo[100];
166
167 if (ar->id.bmi_ids_valid)
168 scnprintf(boardinfo, sizeof(boardinfo), "%d:%d",
169 ar->id.bmi_chip_id, ar->id.bmi_board_id);
170 else
171 scnprintf(boardinfo, sizeof(boardinfo), "N/A");
172
Kalle Valo3e580442015-11-25 15:38:34 +0200173 ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x",
Kalle Valo23f591e2015-11-25 15:38:27 +0200174 ar->bd_api,
Kalle Valo3e580442015-11-25 15:38:34 +0200175 boardinfo,
Kalle Valo7ebf7212016-04-20 19:44:51 +0300176 crc32_le(0, ar->normal_mode_fw.board->data,
177 ar->normal_mode_fw.board->size));
Kalle Valo23f591e2015-11-25 15:38:27 +0200178}
179
180void ath10k_debug_print_boot_info(struct ath10k *ar)
181{
Kalle Valof0de90b2015-11-25 15:38:12 +0200182 ath10k_info(ar, "htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d\n",
Kalle Valo8a0c7972014-08-25 08:37:45 +0300183 ar->htt.target_version_major,
Michal Kazior34b28b62014-09-23 10:22:52 +0200184 ar->htt.target_version_minor,
Kalle Valobf3c13a2016-04-20 19:45:33 +0300185 ar->normal_mode_fw.fw_file.wmi_op_version,
Kalle Valo77561f92016-04-20 19:45:47 +0300186 ar->normal_mode_fw.fw_file.htt_op_version,
Michal Kaziorcfd10612014-11-25 15:16:05 +0100187 ath10k_cal_mode_str(ar->cal_mode),
Michal Kaziorb27bc5a2015-06-15 14:46:40 +0300188 ar->max_num_stations,
David Liuccec9032015-07-24 20:25:32 +0300189 test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
Kalle Valof0de90b2015-11-25 15:38:12 +0200190 !test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags));
Kalle Valo8a0c7972014-08-25 08:37:45 +0300191}
Kalle Valo23f591e2015-11-25 15:38:27 +0200192
193void ath10k_print_driver_info(struct ath10k *ar)
194{
195 ath10k_debug_print_hwfw_info(ar);
196 ath10k_debug_print_board_info(ar);
197 ath10k_debug_print_boot_info(ar);
198}
Kalle Valo8a0c7972014-08-25 08:37:45 +0300199EXPORT_SYMBOL(ath10k_print_driver_info);
200
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700201void ath10k_err(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300202{
203 struct va_format vaf = {
204 .fmt = fmt,
205 };
206 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300207
208 va_start(args, fmt);
209 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700210 dev_err(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300211 trace_ath10k_log_err(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300212 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300213}
214EXPORT_SYMBOL(ath10k_err);
215
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700216void ath10k_warn(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300217{
218 struct va_format vaf = {
219 .fmt = fmt,
220 };
221 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300222
223 va_start(args, fmt);
224 vaf.va = &args;
Michal Kazior7aa7a722014-08-25 12:09:38 +0200225 dev_warn_ratelimited(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300226 trace_ath10k_log_warn(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300227
228 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300229}
230EXPORT_SYMBOL(ath10k_warn);
231
232#ifdef CONFIG_ATH10K_DEBUGFS
233
Kalle Valo5e3dd152013-06-12 20:52:10 +0300234static ssize_t ath10k_read_wmi_services(struct file *file,
235 char __user *user_buf,
236 size_t count, loff_t *ppos)
237{
238 struct ath10k *ar = file->private_data;
239 char *buf;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200240 size_t len = 0, buf_len = 4096;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300241 const char *name;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300242 ssize_t ret_cnt;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300243 bool enabled;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300244 int i;
245
246 buf = kzalloc(buf_len, GFP_KERNEL);
247 if (!buf)
248 return -ENOMEM;
249
250 mutex_lock(&ar->conf_mutex);
251
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100252 spin_lock_bh(&ar->data_lock);
Michal Kaziorc4f8c832014-09-04 10:18:32 +0200253 for (i = 0; i < WMI_SERVICE_MAX; i++) {
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100254 enabled = test_bit(i, ar->wmi.svc_map);
Michal Kaziorcff990c2014-08-04 09:18:33 +0300255 name = wmi_service_name(i);
256
257 if (!name) {
258 if (enabled)
259 len += scnprintf(buf + len, buf_len - len,
260 "%-40s %s (bit %d)\n",
261 "unknown", "enabled", i);
262
263 continue;
264 }
Kalle Valo5e3dd152013-06-12 20:52:10 +0300265
266 len += scnprintf(buf + len, buf_len - len,
Michal Kaziorcff990c2014-08-04 09:18:33 +0300267 "%-40s %s\n",
268 name, enabled ? "enabled" : "-");
Kalle Valo5e3dd152013-06-12 20:52:10 +0300269 }
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100270 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300271
272 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
273
274 mutex_unlock(&ar->conf_mutex);
275
276 kfree(buf);
277 return ret_cnt;
278}
279
280static const struct file_operations fops_wmi_services = {
281 .read = ath10k_read_wmi_services,
282 .open = simple_open,
283 .owner = THIS_MODULE,
284 .llseek = default_llseek,
285};
286
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530287static void ath10k_fw_stats_pdevs_free(struct list_head *head)
Michal Kazior53268492014-09-25 12:33:50 +0200288{
289 struct ath10k_fw_stats_pdev *i, *tmp;
290
291 list_for_each_entry_safe(i, tmp, head, list) {
292 list_del(&i->list);
293 kfree(i);
294 }
295}
296
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530297static void ath10k_fw_stats_vdevs_free(struct list_head *head)
Michal Kazior7b6b1532015-02-15 16:50:40 +0200298{
299 struct ath10k_fw_stats_vdev *i, *tmp;
300
301 list_for_each_entry_safe(i, tmp, head, list) {
302 list_del(&i->list);
303 kfree(i);
304 }
305}
306
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530307static void ath10k_fw_stats_peers_free(struct list_head *head)
Michal Kazior53268492014-09-25 12:33:50 +0200308{
309 struct ath10k_fw_stats_peer *i, *tmp;
310
311 list_for_each_entry_safe(i, tmp, head, list) {
312 list_del(&i->list);
313 kfree(i);
314 }
315}
316
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300317static void ath10k_fw_extd_stats_peers_free(struct list_head *head)
318{
319 struct ath10k_fw_extd_stats_peer *i, *tmp;
320
321 list_for_each_entry_safe(i, tmp, head, list) {
322 list_del(&i->list);
323 kfree(i);
324 }
325}
326
Michal Kazior53268492014-09-25 12:33:50 +0200327static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
328{
329 spin_lock_bh(&ar->data_lock);
330 ar->debug.fw_stats_done = false;
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300331 ar->debug.fw_stats.extended = false;
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530332 ath10k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
333 ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
334 ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300335 ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +0200336 spin_unlock_bh(&ar->data_lock);
337}
338
Michal Kazior60ef4012014-09-25 12:33:48 +0200339void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300340{
Michal Kazior53268492014-09-25 12:33:50 +0200341 struct ath10k_fw_stats stats = {};
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +0530342 bool is_start, is_started, is_end;
Michal Kazior53268492014-09-25 12:33:50 +0200343 size_t num_peers;
Michal Kazior7b6b1532015-02-15 16:50:40 +0200344 size_t num_vdevs;
Michal Kaziord15fb522014-09-25 12:33:47 +0200345 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300346
Michal Kazior53268492014-09-25 12:33:50 +0200347 INIT_LIST_HEAD(&stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200348 INIT_LIST_HEAD(&stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200349 INIT_LIST_HEAD(&stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300350 INIT_LIST_HEAD(&stats.peers_extd);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300351
Michal Kazior53268492014-09-25 12:33:50 +0200352 spin_lock_bh(&ar->data_lock);
353 ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
Michal Kaziord15fb522014-09-25 12:33:47 +0200354 if (ret) {
355 ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
Raja Mani5db879a2015-07-09 14:19:43 +0530356 goto free;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300357 }
358
Michal Kazior53268492014-09-25 12:33:50 +0200359 /* Stat data may exceed htc-wmi buffer limit. In such case firmware
360 * splits the stats data and delivers it in a ping-pong fashion of
361 * request cmd-update event.
362 *
363 * However there is no explicit end-of-data. Instead start-of-data is
364 * used as an implicit one. This works as follows:
365 * a) discard stat update events until one with pdev stats is
366 * delivered - this skips session started at end of (b)
367 * b) consume stat update events until another one with pdev stats is
368 * delivered which is treated as end-of-data and is itself discarded
369 */
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +0530370 if (ath10k_peer_stats_enabled(ar))
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300371 ath10k_sta_update_rx_duration(ar, &stats);
Mohammed Shafi Shajakhan74135f52016-02-03 21:07:42 +0530372
Mohammed Shafi Shajakhane0b6ce02016-02-03 21:07:43 +0530373 if (ar->debug.fw_stats_done) {
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +0530374 if (!ath10k_peer_stats_enabled(ar))
Mohammed Shafi Shajakhane0b6ce02016-02-03 21:07:43 +0530375 ath10k_warn(ar, "received unsolicited stats update event\n");
376
Michal Kazior53268492014-09-25 12:33:50 +0200377 goto free;
378 }
379
Manikanta Pubbisettybc6f9ae2015-10-16 15:54:52 +0300380 num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers);
381 num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200382 is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
383 !list_empty(&stats.pdevs));
384 is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
385 !list_empty(&stats.pdevs));
386
387 if (is_start)
388 list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
389
390 if (is_end)
391 ar->debug.fw_stats_done = true;
392
393 is_started = !list_empty(&ar->debug.fw_stats.pdevs);
394
395 if (is_started && !is_end) {
396 if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) {
397 /* Although this is unlikely impose a sane limit to
398 * prevent firmware from DoS-ing the host.
399 */
Mohammed Shafi Shajakhand57e7f22016-01-13 21:16:32 +0530400 ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
Christian Lamparterc1e33302016-12-05 22:52:45 +0100401 ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +0200402 ath10k_warn(ar, "dropping fw peer stats\n");
403 goto free;
404 }
405
Michal Kazior7b6b1532015-02-15 16:50:40 +0200406 if (num_vdevs >= BITS_PER_LONG) {
Mohammed Shafi Shajakhand57e7f22016-01-13 21:16:32 +0530407 ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200408 ath10k_warn(ar, "dropping fw vdev stats\n");
409 goto free;
410 }
411
Christian Lamparterc1e33302016-12-05 22:52:45 +0100412 if (!list_empty(&stats.peers))
413 list_splice_tail_init(&stats.peers_extd,
414 &ar->debug.fw_stats.peers_extd);
415
Michal Kazior53268492014-09-25 12:33:50 +0200416 list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200417 list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200418 }
419
Michal Kazior60ef4012014-09-25 12:33:48 +0200420 complete(&ar->debug.fw_stats_complete);
Michal Kaziord15fb522014-09-25 12:33:47 +0200421
Michal Kazior53268492014-09-25 12:33:50 +0200422free:
423 /* In some cases lists have been spliced and cleared. Free up
424 * resources if that is not the case.
425 */
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530426 ath10k_fw_stats_pdevs_free(&stats.pdevs);
427 ath10k_fw_stats_vdevs_free(&stats.vdevs);
428 ath10k_fw_stats_peers_free(&stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300429 ath10k_fw_extd_stats_peers_free(&stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +0200430
Michal Kaziord15fb522014-09-25 12:33:47 +0200431 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300432}
433
Michal Kazior53268492014-09-25 12:33:50 +0200434static int ath10k_debug_fw_stats_request(struct ath10k *ar)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300435{
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300436 unsigned long timeout, time_left;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300437 int ret;
438
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200439 lockdep_assert_held(&ar->conf_mutex);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300440
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300441 timeout = jiffies + msecs_to_jiffies(1 * HZ);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300442
Michal Kazior53268492014-09-25 12:33:50 +0200443 ath10k_debug_fw_stats_reset(ar);
444
445 for (;;) {
446 if (time_after(jiffies, timeout))
447 return -ETIMEDOUT;
448
449 reinit_completion(&ar->debug.fw_stats_complete);
450
Yanbo Li6274cd42015-04-01 22:53:21 +0300451 ret = ath10k_wmi_request_stats(ar, ar->fw_stats_req_mask);
Michal Kazior53268492014-09-25 12:33:50 +0200452 if (ret) {
453 ath10k_warn(ar, "could not request stats (%d)\n", ret);
454 return ret;
455 }
456
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300457 time_left =
458 wait_for_completion_timeout(&ar->debug.fw_stats_complete,
459 1 * HZ);
460 if (!time_left)
Michal Kazior53268492014-09-25 12:33:50 +0200461 return -ETIMEDOUT;
462
463 spin_lock_bh(&ar->data_lock);
464 if (ar->debug.fw_stats_done) {
465 spin_unlock_bh(&ar->data_lock);
466 break;
467 }
468 spin_unlock_bh(&ar->data_lock);
469 }
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200470
471 return 0;
472}
473
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200474static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
475{
476 struct ath10k *ar = inode->i_private;
477 void *buf = NULL;
478 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300479
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200480 mutex_lock(&ar->conf_mutex);
481
482 if (ar->state != ATH10K_STATE_ON) {
483 ret = -ENETDOWN;
484 goto err_unlock;
485 }
486
487 buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);
488 if (!buf) {
489 ret = -ENOMEM;
490 goto err_unlock;
491 }
492
Michal Kazior53268492014-09-25 12:33:50 +0200493 ret = ath10k_debug_fw_stats_request(ar);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200494 if (ret) {
495 ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
496 goto err_free;
497 }
498
Manikanta Pubbisettybc6f9ae2015-10-16 15:54:52 +0300499 ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
500 if (ret) {
501 ath10k_warn(ar, "failed to fill fw stats: %d\n", ret);
502 goto err_free;
503 }
504
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200505 file->private_data = buf;
506
Kalle Valo5e3dd152013-06-12 20:52:10 +0300507 mutex_unlock(&ar->conf_mutex);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200508 return 0;
509
510err_free:
511 vfree(buf);
512
513err_unlock:
514 mutex_unlock(&ar->conf_mutex);
515 return ret;
516}
517
518static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
519{
520 vfree(file->private_data);
521
522 return 0;
523}
524
525static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
526 size_t count, loff_t *ppos)
527{
528 const char *buf = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200529 size_t len = strlen(buf);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200530
531 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300532}
533
534static const struct file_operations fops_fw_stats = {
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200535 .open = ath10k_fw_stats_open,
536 .release = ath10k_fw_stats_release,
Michal Kazior60ef4012014-09-25 12:33:48 +0200537 .read = ath10k_fw_stats_read,
Kalle Valo5e3dd152013-06-12 20:52:10 +0300538 .owner = THIS_MODULE,
539 .llseek = default_llseek,
540};
541
Ben Greearf51dbe72014-09-29 14:41:46 +0300542static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
543 char __user *user_buf,
544 size_t count, loff_t *ppos)
545{
546 struct ath10k *ar = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200547 int ret;
548 size_t len = 0, buf_len = 500;
Ben Greearf51dbe72014-09-29 14:41:46 +0300549 char *buf;
550
Ben Greearf51dbe72014-09-29 14:41:46 +0300551 buf = kmalloc(buf_len, GFP_KERNEL);
552 if (!buf)
553 return -ENOMEM;
554
555 spin_lock_bh(&ar->data_lock);
556
Ben Greearf51dbe72014-09-29 14:41:46 +0300557 len += scnprintf(buf + len, buf_len - len,
558 "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
559 len += scnprintf(buf + len, buf_len - len,
560 "fw_warm_reset_counter\t\t%d\n",
561 ar->stats.fw_warm_reset_counter);
562 len += scnprintf(buf + len, buf_len - len,
563 "fw_cold_reset_counter\t\t%d\n",
564 ar->stats.fw_cold_reset_counter);
565
566 spin_unlock_bh(&ar->data_lock);
567
568 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
569
570 kfree(buf);
571
572 return ret;
573}
574
575static const struct file_operations fops_fw_reset_stats = {
576 .open = simple_open,
577 .read = ath10k_debug_fw_reset_stats_read,
578 .owner = THIS_MODULE,
579 .llseek = default_llseek,
580};
581
Ben Greeard5aebc72014-09-10 18:59:28 +0300582/* This is a clean assert crash in firmware. */
583static int ath10k_debug_fw_assert(struct ath10k *ar)
584{
585 struct wmi_vdev_install_key_cmd *cmd;
586 struct sk_buff *skb;
587
588 skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
589 if (!skb)
590 return -ENOMEM;
591
592 cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
593 memset(cmd, 0, sizeof(*cmd));
594
595 /* big enough number so that firmware asserts */
596 cmd->vdev_id = __cpu_to_le32(0x7ffe);
597
598 return ath10k_wmi_cmd_send(ar, skb,
599 ar->wmi.cmd->vdev_install_key_cmdid);
600}
601
Michal Kazior278c4a82013-07-22 14:08:51 +0200602static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
603 char __user *user_buf,
604 size_t count, loff_t *ppos)
605{
Kalle Valo75cb96d2014-09-14 12:50:44 +0300606 const char buf[] =
607 "To simulate firmware crash write one of the keywords to this file:\n"
608 "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
609 "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
Michal Kazior605cdba2014-10-28 10:34:37 +0100610 "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"
611 "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
Marek Puzyniak8c656992014-03-21 17:46:56 +0200612
Michal Kazior278c4a82013-07-22 14:08:51 +0200613 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
614}
615
Marek Puzyniak8c656992014-03-21 17:46:56 +0200616/* Simulate firmware crash:
617 * 'soft': Call wmi command causing firmware hang. This firmware hang is
618 * recoverable by warm firmware reset.
619 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
620 * vdev id. This is hard firmware crash because it is recoverable only by cold
621 * firmware reset.
622 */
Michal Kazior278c4a82013-07-22 14:08:51 +0200623static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
624 const char __user *user_buf,
625 size_t count, loff_t *ppos)
626{
627 struct ath10k *ar = file->private_data;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200628 char buf[32];
Michal Kazior278c4a82013-07-22 14:08:51 +0200629 int ret;
630
Michal Kazior278c4a82013-07-22 14:08:51 +0200631 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200632
633 /* make sure that buf is null terminated */
634 buf[sizeof(buf) - 1] = 0;
Michal Kazior278c4a82013-07-22 14:08:51 +0200635
Mohammed Shafi Shajakhanf5e30752016-05-28 11:25:41 +0300636 /* drop the possible '\n' from the end */
637 if (buf[count - 1] == '\n')
638 buf[count - 1] = 0;
639
640 mutex_lock(&ar->conf_mutex);
641
Michal Kazior278c4a82013-07-22 14:08:51 +0200642 if (ar->state != ATH10K_STATE_ON &&
643 ar->state != ATH10K_STATE_RESTARTED) {
644 ret = -ENETDOWN;
645 goto exit;
646 }
647
Marek Puzyniak8c656992014-03-21 17:46:56 +0200648 if (!strcmp(buf, "soft")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200649 ath10k_info(ar, "simulating soft firmware crash\n");
Marek Puzyniak8c656992014-03-21 17:46:56 +0200650 ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
651 } else if (!strcmp(buf, "hard")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200652 ath10k_info(ar, "simulating hard firmware crash\n");
Ben Greear611b3682014-07-25 11:56:40 +0300653 /* 0x7fff is vdev id, and it is always out of range for all
654 * firmware variants in order to force a firmware crash.
655 */
656 ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
Kalle Valo5b07e072014-09-14 12:50:06 +0300657 ar->wmi.vdev_param->rts_threshold,
658 0);
Ben Greeard5aebc72014-09-10 18:59:28 +0300659 } else if (!strcmp(buf, "assert")) {
660 ath10k_info(ar, "simulating firmware assert crash\n");
661 ret = ath10k_debug_fw_assert(ar);
Michal Kazior605cdba2014-10-28 10:34:37 +0100662 } else if (!strcmp(buf, "hw-restart")) {
663 ath10k_info(ar, "user requested hw restart\n");
664 queue_work(ar->workqueue, &ar->restart_work);
665 ret = 0;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200666 } else {
667 ret = -EINVAL;
668 goto exit;
669 }
Michal Kazior278c4a82013-07-22 14:08:51 +0200670
Marek Puzyniak8c656992014-03-21 17:46:56 +0200671 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200672 ath10k_warn(ar, "failed to simulate firmware crash: %d\n", ret);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200673 goto exit;
674 }
675
676 ret = count;
Michal Kazior278c4a82013-07-22 14:08:51 +0200677
678exit:
679 mutex_unlock(&ar->conf_mutex);
680 return ret;
681}
682
683static const struct file_operations fops_simulate_fw_crash = {
684 .read = ath10k_read_simulate_fw_crash,
685 .write = ath10k_write_simulate_fw_crash,
686 .open = simple_open,
687 .owner = THIS_MODULE,
688 .llseek = default_llseek,
689};
690
Kalle Valo763b8cd2013-09-01 11:22:21 +0300691static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf,
692 size_t count, loff_t *ppos)
693{
694 struct ath10k *ar = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200695 size_t len;
Kalle Valo763b8cd2013-09-01 11:22:21 +0300696 char buf[50];
697
698 len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id);
699
700 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
701}
702
703static const struct file_operations fops_chip_id = {
704 .read = ath10k_read_chip_id,
705 .open = simple_open,
706 .owner = THIS_MODULE,
707 .llseek = default_llseek,
708};
709
Ben Greear384914b2014-08-25 08:37:32 +0300710struct ath10k_fw_crash_data *
711ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
712{
713 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
714
715 lockdep_assert_held(&ar->data_lock);
716
717 crash_data->crashed_since_read = true;
718 uuid_le_gen(&crash_data->uuid);
719 getnstimeofday(&crash_data->timestamp);
720
721 return crash_data;
722}
723EXPORT_SYMBOL(ath10k_debug_get_new_fw_crash_data);
724
Arun Khandavalli727000e2016-12-21 14:19:21 +0200725static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar,
726 bool mark_read)
Ben Greear384914b2014-08-25 08:37:32 +0300727{
728 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
Mohammed Shafi Shajakhanc75c3982017-01-16 17:31:08 +0200729 struct ath10k_ce_crash_hdr *ce_hdr;
Ben Greear384914b2014-08-25 08:37:32 +0300730 struct ath10k_dump_file_data *dump_data;
731 struct ath10k_tlv_dump_data *dump_tlv;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200732 size_t hdr_len = sizeof(*dump_data);
733 size_t len, sofar = 0;
Ben Greear384914b2014-08-25 08:37:32 +0300734 unsigned char *buf;
735
736 len = hdr_len;
737 len += sizeof(*dump_tlv) + sizeof(crash_data->registers);
Mohammed Shafi Shajakhanc75c3982017-01-16 17:31:08 +0200738 len += sizeof(*dump_tlv) + sizeof(*ce_hdr) +
739 CE_COUNT * sizeof(ce_hdr->entries[0]);
Ben Greear384914b2014-08-25 08:37:32 +0300740
741 sofar += hdr_len;
742
743 /* This is going to get big when we start dumping FW RAM and such,
744 * so go ahead and use vmalloc.
745 */
746 buf = vzalloc(len);
747 if (!buf)
748 return NULL;
749
750 spin_lock_bh(&ar->data_lock);
751
752 if (!crash_data->crashed_since_read) {
753 spin_unlock_bh(&ar->data_lock);
754 vfree(buf);
755 return NULL;
756 }
757
758 dump_data = (struct ath10k_dump_file_data *)(buf);
759 strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP",
760 sizeof(dump_data->df_magic));
761 dump_data->len = cpu_to_le32(len);
762
763 dump_data->version = cpu_to_le32(ATH10K_FW_CRASH_DUMP_VERSION);
764
765 memcpy(dump_data->uuid, &crash_data->uuid, sizeof(dump_data->uuid));
766 dump_data->chip_id = cpu_to_le32(ar->chip_id);
767 dump_data->bus_type = cpu_to_le32(0);
768 dump_data->target_version = cpu_to_le32(ar->target_version);
769 dump_data->fw_version_major = cpu_to_le32(ar->fw_version_major);
770 dump_data->fw_version_minor = cpu_to_le32(ar->fw_version_minor);
771 dump_data->fw_version_release = cpu_to_le32(ar->fw_version_release);
772 dump_data->fw_version_build = cpu_to_le32(ar->fw_version_build);
773 dump_data->phy_capability = cpu_to_le32(ar->phy_capability);
774 dump_data->hw_min_tx_power = cpu_to_le32(ar->hw_min_tx_power);
775 dump_data->hw_max_tx_power = cpu_to_le32(ar->hw_max_tx_power);
776 dump_data->ht_cap_info = cpu_to_le32(ar->ht_cap_info);
777 dump_data->vht_cap_info = cpu_to_le32(ar->vht_cap_info);
778 dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains);
779
780 strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
781 sizeof(dump_data->fw_ver));
782
Johannes Berg12c27152014-11-21 18:58:49 +0200783 dump_data->kernel_ver_code = 0;
784 strlcpy(dump_data->kernel_ver, init_utsname()->release,
Ben Greear384914b2014-08-25 08:37:32 +0300785 sizeof(dump_data->kernel_ver));
786
787 dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
788 dump_data->tv_nsec = cpu_to_le64(crash_data->timestamp.tv_nsec);
789
790 /* Gather crash-dump */
791 dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
792 dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_REGISTERS);
793 dump_tlv->tlv_len = cpu_to_le32(sizeof(crash_data->registers));
794 memcpy(dump_tlv->tlv_data, &crash_data->registers,
795 sizeof(crash_data->registers));
796 sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers);
797
Mohammed Shafi Shajakhanc75c3982017-01-16 17:31:08 +0200798 dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
799 dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_CE_DATA);
800 dump_tlv->tlv_len = cpu_to_le32(sizeof(*ce_hdr) +
801 CE_COUNT * sizeof(ce_hdr->entries[0]));
802 ce_hdr = (struct ath10k_ce_crash_hdr *)(dump_tlv->tlv_data);
803 ce_hdr->ce_count = cpu_to_le32(CE_COUNT);
804 memset(ce_hdr->reserved, 0, sizeof(ce_hdr->reserved));
805 memcpy(ce_hdr->entries, crash_data->ce_crash_data,
806 CE_COUNT * sizeof(ce_hdr->entries[0]));
807 sofar += sizeof(*dump_tlv) + sizeof(*ce_hdr) +
808 CE_COUNT * sizeof(ce_hdr->entries[0]);
809
Arun Khandavalli727000e2016-12-21 14:19:21 +0200810 ar->debug.fw_crash_data->crashed_since_read = !mark_read;
Ben Greear384914b2014-08-25 08:37:32 +0300811
812 spin_unlock_bh(&ar->data_lock);
813
814 return dump_data;
815}
816
Arun Khandavalli727000e2016-12-21 14:19:21 +0200817int ath10k_debug_fw_devcoredump(struct ath10k *ar)
818{
819 struct ath10k_dump_file_data *dump;
820 void *dump_ptr;
821 u32 dump_len;
822
823 /* To keep the dump file available also for debugfs don't mark the
824 * file read, only debugfs should do that.
825 */
826 dump = ath10k_build_dump_file(ar, false);
827 if (!dump) {
828 ath10k_warn(ar, "no crash dump data found for devcoredump");
829 return -ENODATA;
830 }
831
832 /* Make a copy of the dump file for dev_coredumpv() as during the
833 * transition period we need to own the original file. Once
834 * fw_crash_dump debugfs file is removed no need to have a copy
835 * anymore.
836 */
837 dump_len = le32_to_cpu(dump->len);
838 dump_ptr = vzalloc(dump_len);
839
840 if (!dump_ptr)
841 return -ENOMEM;
842
843 memcpy(dump_ptr, dump, dump_len);
844
845 dev_coredumpv(ar->dev, dump_ptr, dump_len, GFP_KERNEL);
846
847 return 0;
848}
849
Ben Greear384914b2014-08-25 08:37:32 +0300850static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file)
851{
852 struct ath10k *ar = inode->i_private;
853 struct ath10k_dump_file_data *dump;
854
Arun Khandavalli727000e2016-12-21 14:19:21 +0200855 ath10k_warn(ar, "fw_crash_dump debugfs file is deprecated, please use /sys/class/devcoredump instead.");
856
857 dump = ath10k_build_dump_file(ar, true);
Ben Greear384914b2014-08-25 08:37:32 +0300858 if (!dump)
859 return -ENODATA;
860
861 file->private_data = dump;
862
863 return 0;
864}
865
866static ssize_t ath10k_fw_crash_dump_read(struct file *file,
867 char __user *user_buf,
868 size_t count, loff_t *ppos)
869{
870 struct ath10k_dump_file_data *dump_file = file->private_data;
871
872 return simple_read_from_buffer(user_buf, count, ppos,
873 dump_file,
874 le32_to_cpu(dump_file->len));
875}
876
877static int ath10k_fw_crash_dump_release(struct inode *inode,
878 struct file *file)
879{
880 vfree(file->private_data);
881
882 return 0;
883}
884
885static const struct file_operations fops_fw_crash_dump = {
886 .open = ath10k_fw_crash_dump_open,
887 .read = ath10k_fw_crash_dump_read,
888 .release = ath10k_fw_crash_dump_release,
889 .owner = THIS_MODULE,
890 .llseek = default_llseek,
891};
892
Yanbo Li077a3802014-11-25 12:24:33 +0200893static ssize_t ath10k_reg_addr_read(struct file *file,
894 char __user *user_buf,
895 size_t count, loff_t *ppos)
896{
897 struct ath10k *ar = file->private_data;
898 u8 buf[32];
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200899 size_t len = 0;
Yanbo Li077a3802014-11-25 12:24:33 +0200900 u32 reg_addr;
901
902 mutex_lock(&ar->conf_mutex);
903 reg_addr = ar->debug.reg_addr;
904 mutex_unlock(&ar->conf_mutex);
905
906 len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);
907
908 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
909}
910
911static ssize_t ath10k_reg_addr_write(struct file *file,
912 const char __user *user_buf,
913 size_t count, loff_t *ppos)
914{
915 struct ath10k *ar = file->private_data;
916 u32 reg_addr;
917 int ret;
918
919 ret = kstrtou32_from_user(user_buf, count, 0, &reg_addr);
920 if (ret)
921 return ret;
922
923 if (!IS_ALIGNED(reg_addr, 4))
924 return -EFAULT;
925
926 mutex_lock(&ar->conf_mutex);
927 ar->debug.reg_addr = reg_addr;
928 mutex_unlock(&ar->conf_mutex);
929
930 return count;
931}
932
933static const struct file_operations fops_reg_addr = {
934 .read = ath10k_reg_addr_read,
935 .write = ath10k_reg_addr_write,
936 .open = simple_open,
937 .owner = THIS_MODULE,
938 .llseek = default_llseek,
939};
940
941static ssize_t ath10k_reg_value_read(struct file *file,
942 char __user *user_buf,
943 size_t count, loff_t *ppos)
944{
945 struct ath10k *ar = file->private_data;
946 u8 buf[48];
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200947 size_t len;
Yanbo Li077a3802014-11-25 12:24:33 +0200948 u32 reg_addr, reg_val;
949 int ret;
950
951 mutex_lock(&ar->conf_mutex);
952
953 if (ar->state != ATH10K_STATE_ON &&
954 ar->state != ATH10K_STATE_UTF) {
955 ret = -ENETDOWN;
956 goto exit;
957 }
958
959 reg_addr = ar->debug.reg_addr;
960
961 reg_val = ath10k_hif_read32(ar, reg_addr);
962 len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);
963
964 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
965
966exit:
967 mutex_unlock(&ar->conf_mutex);
968
969 return ret;
970}
971
972static ssize_t ath10k_reg_value_write(struct file *file,
973 const char __user *user_buf,
974 size_t count, loff_t *ppos)
975{
976 struct ath10k *ar = file->private_data;
977 u32 reg_addr, reg_val;
978 int ret;
979
980 mutex_lock(&ar->conf_mutex);
981
982 if (ar->state != ATH10K_STATE_ON &&
983 ar->state != ATH10K_STATE_UTF) {
984 ret = -ENETDOWN;
985 goto exit;
986 }
987
988 reg_addr = ar->debug.reg_addr;
989
990 ret = kstrtou32_from_user(user_buf, count, 0, &reg_val);
991 if (ret)
992 goto exit;
993
994 ath10k_hif_write32(ar, reg_addr, reg_val);
995
996 ret = count;
997
998exit:
999 mutex_unlock(&ar->conf_mutex);
1000
1001 return ret;
1002}
1003
1004static const struct file_operations fops_reg_value = {
1005 .read = ath10k_reg_value_read,
1006 .write = ath10k_reg_value_write,
1007 .open = simple_open,
1008 .owner = THIS_MODULE,
1009 .llseek = default_llseek,
1010};
1011
Yanbo Li9f65ad22014-11-25 12:24:48 +02001012static ssize_t ath10k_mem_value_read(struct file *file,
1013 char __user *user_buf,
1014 size_t count, loff_t *ppos)
1015{
1016 struct ath10k *ar = file->private_data;
1017 u8 *buf;
1018 int ret;
1019
1020 if (*ppos < 0)
1021 return -EINVAL;
1022
1023 if (!count)
1024 return 0;
1025
1026 mutex_lock(&ar->conf_mutex);
1027
1028 buf = vmalloc(count);
1029 if (!buf) {
1030 ret = -ENOMEM;
1031 goto exit;
1032 }
1033
1034 if (ar->state != ATH10K_STATE_ON &&
1035 ar->state != ATH10K_STATE_UTF) {
1036 ret = -ENETDOWN;
1037 goto exit;
1038 }
1039
1040 ret = ath10k_hif_diag_read(ar, *ppos, buf, count);
1041 if (ret) {
1042 ath10k_warn(ar, "failed to read address 0x%08x via diagnose window fnrom debugfs: %d\n",
1043 (u32)(*ppos), ret);
1044 goto exit;
1045 }
1046
1047 ret = copy_to_user(user_buf, buf, count);
1048 if (ret) {
1049 ret = -EFAULT;
1050 goto exit;
1051 }
1052
1053 count -= ret;
1054 *ppos += count;
1055 ret = count;
1056
1057exit:
1058 vfree(buf);
1059 mutex_unlock(&ar->conf_mutex);
1060
1061 return ret;
1062}
1063
1064static ssize_t ath10k_mem_value_write(struct file *file,
1065 const char __user *user_buf,
1066 size_t count, loff_t *ppos)
1067{
1068 struct ath10k *ar = file->private_data;
1069 u8 *buf;
1070 int ret;
1071
1072 if (*ppos < 0)
1073 return -EINVAL;
1074
1075 if (!count)
1076 return 0;
1077
1078 mutex_lock(&ar->conf_mutex);
1079
1080 buf = vmalloc(count);
1081 if (!buf) {
1082 ret = -ENOMEM;
1083 goto exit;
1084 }
1085
1086 if (ar->state != ATH10K_STATE_ON &&
1087 ar->state != ATH10K_STATE_UTF) {
1088 ret = -ENETDOWN;
1089 goto exit;
1090 }
1091
1092 ret = copy_from_user(buf, user_buf, count);
1093 if (ret) {
1094 ret = -EFAULT;
1095 goto exit;
1096 }
1097
1098 ret = ath10k_hif_diag_write(ar, *ppos, buf, count);
1099 if (ret) {
1100 ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",
1101 (u32)(*ppos), ret);
1102 goto exit;
1103 }
1104
1105 *ppos += count;
1106 ret = count;
1107
1108exit:
1109 vfree(buf);
1110 mutex_unlock(&ar->conf_mutex);
1111
1112 return ret;
1113}
1114
1115static const struct file_operations fops_mem_value = {
1116 .read = ath10k_mem_value_read,
1117 .write = ath10k_mem_value_write,
1118 .open = simple_open,
1119 .owner = THIS_MODULE,
1120 .llseek = default_llseek,
1121};
1122
Kalle Valoa3d135e2013-09-03 11:44:10 +03001123static int ath10k_debug_htt_stats_req(struct ath10k *ar)
1124{
1125 u64 cookie;
1126 int ret;
1127
1128 lockdep_assert_held(&ar->conf_mutex);
1129
1130 if (ar->debug.htt_stats_mask == 0)
1131 /* htt stats are disabled */
1132 return 0;
1133
1134 if (ar->state != ATH10K_STATE_ON)
1135 return 0;
1136
1137 cookie = get_jiffies_64();
1138
1139 ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask,
1140 cookie);
1141 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001142 ath10k_warn(ar, "failed to send htt stats request: %d\n", ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001143 return ret;
1144 }
1145
1146 queue_delayed_work(ar->workqueue, &ar->debug.htt_stats_dwork,
1147 msecs_to_jiffies(ATH10K_DEBUG_HTT_STATS_INTERVAL));
1148
1149 return 0;
1150}
1151
1152static void ath10k_debug_htt_stats_dwork(struct work_struct *work)
1153{
1154 struct ath10k *ar = container_of(work, struct ath10k,
1155 debug.htt_stats_dwork.work);
1156
1157 mutex_lock(&ar->conf_mutex);
1158
1159 ath10k_debug_htt_stats_req(ar);
1160
1161 mutex_unlock(&ar->conf_mutex);
1162}
1163
1164static ssize_t ath10k_read_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001165 char __user *user_buf,
1166 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001167{
1168 struct ath10k *ar = file->private_data;
1169 char buf[32];
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001170 size_t len;
Kalle Valoa3d135e2013-09-03 11:44:10 +03001171
1172 len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask);
1173
1174 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1175}
1176
1177static ssize_t ath10k_write_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001178 const char __user *user_buf,
1179 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001180{
1181 struct ath10k *ar = file->private_data;
1182 unsigned long mask;
1183 int ret;
1184
1185 ret = kstrtoul_from_user(user_buf, count, 0, &mask);
1186 if (ret)
1187 return ret;
1188
1189 /* max 8 bit masks (for now) */
1190 if (mask > 0xff)
1191 return -E2BIG;
1192
1193 mutex_lock(&ar->conf_mutex);
1194
1195 ar->debug.htt_stats_mask = mask;
1196
1197 ret = ath10k_debug_htt_stats_req(ar);
1198 if (ret)
1199 goto out;
1200
1201 ret = count;
1202
1203out:
1204 mutex_unlock(&ar->conf_mutex);
1205
1206 return ret;
1207}
1208
1209static const struct file_operations fops_htt_stats_mask = {
1210 .read = ath10k_read_htt_stats_mask,
1211 .write = ath10k_write_htt_stats_mask,
1212 .open = simple_open,
1213 .owner = THIS_MODULE,
1214 .llseek = default_llseek,
1215};
1216
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001217static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
1218 char __user *user_buf,
1219 size_t count, loff_t *ppos)
1220{
1221 struct ath10k *ar = file->private_data;
1222 char buf[64];
Mohammed Shafi Shajakhan81ec3c02015-11-30 22:29:39 +05301223 u8 amsdu, ampdu;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001224 size_t len;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001225
1226 mutex_lock(&ar->conf_mutex);
1227
David Liuccec9032015-07-24 20:25:32 +03001228 amsdu = ar->htt.max_num_amsdu;
1229 ampdu = ar->htt.max_num_ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001230 mutex_unlock(&ar->conf_mutex);
1231
1232 len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
1233
1234 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1235}
1236
1237static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
1238 const char __user *user_buf,
1239 size_t count, loff_t *ppos)
1240{
1241 struct ath10k *ar = file->private_data;
1242 int res;
1243 char buf[64];
1244 unsigned int amsdu, ampdu;
1245
1246 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
1247
1248 /* make sure that buf is null terminated */
1249 buf[sizeof(buf) - 1] = 0;
1250
1251 res = sscanf(buf, "%u %u", &amsdu, &ampdu);
1252
1253 if (res != 2)
1254 return -EINVAL;
1255
1256 mutex_lock(&ar->conf_mutex);
1257
1258 res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
1259 if (res)
1260 goto out;
1261
1262 res = count;
David Liuccec9032015-07-24 20:25:32 +03001263 ar->htt.max_num_amsdu = amsdu;
1264 ar->htt.max_num_ampdu = ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001265
1266out:
1267 mutex_unlock(&ar->conf_mutex);
1268 return res;
1269}
1270
1271static const struct file_operations fops_htt_max_amsdu_ampdu = {
1272 .read = ath10k_read_htt_max_amsdu_ampdu,
1273 .write = ath10k_write_htt_max_amsdu_ampdu,
1274 .open = simple_open,
1275 .owner = THIS_MODULE,
1276 .llseek = default_llseek,
1277};
1278
Kalle Valof118a3e2014-01-03 12:59:31 +02001279static ssize_t ath10k_read_fw_dbglog(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001280 char __user *user_buf,
1281 size_t count, loff_t *ppos)
Kalle Valof118a3e2014-01-03 12:59:31 +02001282{
1283 struct ath10k *ar = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001284 size_t len;
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301285 char buf[96];
Kalle Valof118a3e2014-01-03 12:59:31 +02001286
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301287 len = scnprintf(buf, sizeof(buf), "0x%16llx %u\n",
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301288 ar->debug.fw_dbglog_mask, ar->debug.fw_dbglog_level);
Kalle Valof118a3e2014-01-03 12:59:31 +02001289
1290 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1291}
1292
1293static ssize_t ath10k_write_fw_dbglog(struct file *file,
1294 const char __user *user_buf,
1295 size_t count, loff_t *ppos)
1296{
1297 struct ath10k *ar = file->private_data;
Kalle Valof118a3e2014-01-03 12:59:31 +02001298 int ret;
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301299 char buf[96];
1300 unsigned int log_level;
1301 u64 mask;
Kalle Valof118a3e2014-01-03 12:59:31 +02001302
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301303 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
1304
1305 /* make sure that buf is null terminated */
1306 buf[sizeof(buf) - 1] = 0;
1307
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301308 ret = sscanf(buf, "%llx %u", &mask, &log_level);
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301309
1310 if (!ret)
1311 return -EINVAL;
1312
1313 if (ret == 1)
1314 /* default if user did not specify */
1315 log_level = ATH10K_DBGLOG_LEVEL_WARN;
Kalle Valof118a3e2014-01-03 12:59:31 +02001316
1317 mutex_lock(&ar->conf_mutex);
1318
1319 ar->debug.fw_dbglog_mask = mask;
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301320 ar->debug.fw_dbglog_level = log_level;
Kalle Valof118a3e2014-01-03 12:59:31 +02001321
1322 if (ar->state == ATH10K_STATE_ON) {
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301323 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1324 ar->debug.fw_dbglog_level);
Kalle Valof118a3e2014-01-03 12:59:31 +02001325 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001326 ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n",
Kalle Valof118a3e2014-01-03 12:59:31 +02001327 ret);
1328 goto exit;
1329 }
1330 }
1331
1332 ret = count;
1333
1334exit:
1335 mutex_unlock(&ar->conf_mutex);
1336
1337 return ret;
1338}
1339
Ben Greear6cddcc72014-09-29 14:41:46 +03001340/* TODO: Would be nice to always support ethtool stats, would need to
1341 * move the stats storage out of ath10k_debug, or always have ath10k_debug
1342 * struct available..
1343 */
1344
1345/* This generally cooresponds to the debugfs fw_stats file */
1346static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
1347 "tx_pkts_nic",
1348 "tx_bytes_nic",
1349 "rx_pkts_nic",
1350 "rx_bytes_nic",
1351 "d_noise_floor",
1352 "d_cycle_count",
1353 "d_phy_error",
1354 "d_rts_bad",
1355 "d_rts_good",
1356 "d_tx_power", /* in .5 dbM I think */
1357 "d_rx_crc_err", /* fcs_bad */
1358 "d_no_beacon",
1359 "d_tx_mpdus_queued",
1360 "d_tx_msdu_queued",
1361 "d_tx_msdu_dropped",
1362 "d_local_enqued",
1363 "d_local_freed",
1364 "d_tx_ppdu_hw_queued",
1365 "d_tx_ppdu_reaped",
1366 "d_tx_fifo_underrun",
1367 "d_tx_ppdu_abort",
1368 "d_tx_mpdu_requed",
1369 "d_tx_excessive_retries",
1370 "d_tx_hw_rate",
1371 "d_tx_dropped_sw_retries",
1372 "d_tx_illegal_rate",
1373 "d_tx_continuous_xretries",
1374 "d_tx_timeout",
1375 "d_tx_mpdu_txop_limit",
1376 "d_pdev_resets",
1377 "d_rx_mid_ppdu_route_change",
1378 "d_rx_status",
1379 "d_rx_extra_frags_ring0",
1380 "d_rx_extra_frags_ring1",
1381 "d_rx_extra_frags_ring2",
1382 "d_rx_extra_frags_ring3",
1383 "d_rx_msdu_htt",
1384 "d_rx_mpdu_htt",
1385 "d_rx_msdu_stack",
1386 "d_rx_mpdu_stack",
1387 "d_rx_phy_err",
1388 "d_rx_phy_err_drops",
1389 "d_rx_mpdu_errors", /* FCS, MIC, ENC */
1390 "d_fw_crash_count",
1391 "d_fw_warm_reset_count",
1392 "d_fw_cold_reset_count",
1393};
1394
1395#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
1396
1397void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
1398 struct ieee80211_vif *vif,
1399 u32 sset, u8 *data)
1400{
1401 if (sset == ETH_SS_STATS)
1402 memcpy(data, *ath10k_gstrings_stats,
1403 sizeof(ath10k_gstrings_stats));
1404}
1405
1406int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
1407 struct ieee80211_vif *vif, int sset)
1408{
1409 if (sset == ETH_SS_STATS)
1410 return ATH10K_SSTATS_LEN;
1411
1412 return 0;
1413}
1414
1415void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
1416 struct ieee80211_vif *vif,
1417 struct ethtool_stats *stats, u64 *data)
1418{
1419 struct ath10k *ar = hw->priv;
1420 static const struct ath10k_fw_stats_pdev zero_stats = {};
1421 const struct ath10k_fw_stats_pdev *pdev_stats;
1422 int i = 0, ret;
1423
1424 mutex_lock(&ar->conf_mutex);
1425
1426 if (ar->state == ATH10K_STATE_ON) {
1427 ret = ath10k_debug_fw_stats_request(ar);
1428 if (ret) {
1429 /* just print a warning and try to use older results */
1430 ath10k_warn(ar,
1431 "failed to get fw stats for ethtool: %d\n",
1432 ret);
1433 }
1434 }
1435
1436 pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,
1437 struct ath10k_fw_stats_pdev,
1438 list);
1439 if (!pdev_stats) {
1440 /* no results available so just return zeroes */
1441 pdev_stats = &zero_stats;
1442 }
1443
1444 spin_lock_bh(&ar->data_lock);
1445
1446 data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
1447 data[i++] = 0; /* tx bytes */
1448 data[i++] = pdev_stats->htt_mpdus;
1449 data[i++] = 0; /* rx bytes */
1450 data[i++] = pdev_stats->ch_noise_floor;
1451 data[i++] = pdev_stats->cycle_count;
1452 data[i++] = pdev_stats->phy_err_count;
1453 data[i++] = pdev_stats->rts_bad;
1454 data[i++] = pdev_stats->rts_good;
1455 data[i++] = pdev_stats->chan_tx_power;
1456 data[i++] = pdev_stats->fcs_bad;
1457 data[i++] = pdev_stats->no_beacons;
1458 data[i++] = pdev_stats->mpdu_enqued;
1459 data[i++] = pdev_stats->msdu_enqued;
1460 data[i++] = pdev_stats->wmm_drop;
1461 data[i++] = pdev_stats->local_enqued;
1462 data[i++] = pdev_stats->local_freed;
1463 data[i++] = pdev_stats->hw_queued;
1464 data[i++] = pdev_stats->hw_reaped;
1465 data[i++] = pdev_stats->underrun;
1466 data[i++] = pdev_stats->tx_abort;
1467 data[i++] = pdev_stats->mpdus_requed;
1468 data[i++] = pdev_stats->tx_ko;
1469 data[i++] = pdev_stats->data_rc;
1470 data[i++] = pdev_stats->sw_retry_failure;
1471 data[i++] = pdev_stats->illgl_rate_phy_err;
1472 data[i++] = pdev_stats->pdev_cont_xretry;
1473 data[i++] = pdev_stats->pdev_tx_timeout;
1474 data[i++] = pdev_stats->txop_ovf;
1475 data[i++] = pdev_stats->pdev_resets;
1476 data[i++] = pdev_stats->mid_ppdu_route_change;
1477 data[i++] = pdev_stats->status_rcvd;
1478 data[i++] = pdev_stats->r0_frags;
1479 data[i++] = pdev_stats->r1_frags;
1480 data[i++] = pdev_stats->r2_frags;
1481 data[i++] = pdev_stats->r3_frags;
1482 data[i++] = pdev_stats->htt_msdus;
1483 data[i++] = pdev_stats->htt_mpdus;
1484 data[i++] = pdev_stats->loc_msdus;
1485 data[i++] = pdev_stats->loc_mpdus;
1486 data[i++] = pdev_stats->phy_errs;
1487 data[i++] = pdev_stats->phy_err_drop;
1488 data[i++] = pdev_stats->mpdu_errs;
1489 data[i++] = ar->stats.fw_crash_counter;
1490 data[i++] = ar->stats.fw_warm_reset_counter;
1491 data[i++] = ar->stats.fw_cold_reset_counter;
1492
1493 spin_unlock_bh(&ar->data_lock);
1494
1495 mutex_unlock(&ar->conf_mutex);
1496
1497 WARN_ON(i != ATH10K_SSTATS_LEN);
1498}
1499
Kalle Valof118a3e2014-01-03 12:59:31 +02001500static const struct file_operations fops_fw_dbglog = {
1501 .read = ath10k_read_fw_dbglog,
1502 .write = ath10k_write_fw_dbglog,
1503 .open = simple_open,
1504 .owner = THIS_MODULE,
1505 .llseek = default_llseek,
1506};
1507
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001508static int ath10k_debug_cal_data_fetch(struct ath10k *ar)
Kalle Valo7869b4f2014-09-24 14:16:58 +03001509{
Kalle Valo7869b4f2014-09-24 14:16:58 +03001510 u32 hi_addr;
1511 __le32 addr;
1512 int ret;
1513
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001514 lockdep_assert_held(&ar->conf_mutex);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001515
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001516 if (WARN_ON(ar->hw_params.cal_data_len > ATH10K_DEBUG_CAL_DATA_LEN))
1517 return -EINVAL;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001518
1519 hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
1520
1521 ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
1522 if (ret) {
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001523 ath10k_warn(ar, "failed to read hi_board_data address: %d\n",
1524 ret);
1525 return ret;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001526 }
1527
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001528 ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), ar->debug.cal_data,
Raja Mani0b8e3c42016-03-18 11:44:22 +02001529 ar->hw_params.cal_data_len);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001530 if (ret) {
1531 ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001532 return ret;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001533 }
1534
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001535 return 0;
1536}
Kalle Valo7869b4f2014-09-24 14:16:58 +03001537
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001538static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
1539{
1540 struct ath10k *ar = inode->i_private;
1541
1542 mutex_lock(&ar->conf_mutex);
1543
1544 if (ar->state == ATH10K_STATE_ON ||
1545 ar->state == ATH10K_STATE_UTF) {
1546 ath10k_debug_cal_data_fetch(ar);
1547 }
1548
1549 file->private_data = ar;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001550 mutex_unlock(&ar->conf_mutex);
1551
1552 return 0;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001553}
1554
1555static ssize_t ath10k_debug_cal_data_read(struct file *file,
1556 char __user *user_buf,
1557 size_t count, loff_t *ppos)
1558{
Raja Mani0b8e3c42016-03-18 11:44:22 +02001559 struct ath10k *ar = file->private_data;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001560
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001561 mutex_lock(&ar->conf_mutex);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001562
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001563 count = simple_read_from_buffer(user_buf, count, ppos,
1564 ar->debug.cal_data,
1565 ar->hw_params.cal_data_len);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001566
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001567 mutex_unlock(&ar->conf_mutex);
1568
1569 return count;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001570}
1571
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05301572static ssize_t ath10k_write_ani_enable(struct file *file,
1573 const char __user *user_buf,
1574 size_t count, loff_t *ppos)
1575{
1576 struct ath10k *ar = file->private_data;
1577 int ret;
1578 u8 enable;
1579
1580 if (kstrtou8_from_user(user_buf, count, 0, &enable))
1581 return -EINVAL;
1582
1583 mutex_lock(&ar->conf_mutex);
1584
1585 if (ar->ani_enabled == enable) {
1586 ret = count;
1587 goto exit;
1588 }
1589
1590 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->ani_enable,
1591 enable);
1592 if (ret) {
1593 ath10k_warn(ar, "ani_enable failed from debugfs: %d\n", ret);
1594 goto exit;
1595 }
1596 ar->ani_enabled = enable;
1597
1598 ret = count;
1599
1600exit:
1601 mutex_unlock(&ar->conf_mutex);
1602
1603 return ret;
1604}
1605
1606static ssize_t ath10k_read_ani_enable(struct file *file, char __user *user_buf,
1607 size_t count, loff_t *ppos)
1608{
1609 struct ath10k *ar = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001610 size_t len;
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05301611 char buf[32];
1612
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001613 len = scnprintf(buf, sizeof(buf), "%d\n", ar->ani_enabled);
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05301614
1615 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1616}
1617
1618static const struct file_operations fops_ani_enable = {
1619 .read = ath10k_read_ani_enable,
1620 .write = ath10k_write_ani_enable,
1621 .open = simple_open,
1622 .owner = THIS_MODULE,
1623 .llseek = default_llseek,
1624};
1625
Kalle Valo7869b4f2014-09-24 14:16:58 +03001626static const struct file_operations fops_cal_data = {
1627 .open = ath10k_debug_cal_data_open,
1628 .read = ath10k_debug_cal_data_read,
Kalle Valo7869b4f2014-09-24 14:16:58 +03001629 .owner = THIS_MODULE,
1630 .llseek = default_llseek,
1631};
1632
Peter Oha7bd3e92014-12-02 13:07:14 +02001633static ssize_t ath10k_read_nf_cal_period(struct file *file,
1634 char __user *user_buf,
1635 size_t count, loff_t *ppos)
1636{
1637 struct ath10k *ar = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001638 size_t len;
Peter Oha7bd3e92014-12-02 13:07:14 +02001639 char buf[32];
1640
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001641 len = scnprintf(buf, sizeof(buf), "%d\n", ar->debug.nf_cal_period);
Peter Oha7bd3e92014-12-02 13:07:14 +02001642
1643 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1644}
1645
1646static ssize_t ath10k_write_nf_cal_period(struct file *file,
1647 const char __user *user_buf,
1648 size_t count, loff_t *ppos)
1649{
1650 struct ath10k *ar = file->private_data;
1651 unsigned long period;
1652 int ret;
1653
1654 ret = kstrtoul_from_user(user_buf, count, 0, &period);
1655 if (ret)
1656 return ret;
1657
1658 if (period > WMI_PDEV_PARAM_CAL_PERIOD_MAX)
1659 return -EINVAL;
1660
1661 /* there's no way to switch back to the firmware default */
1662 if (period == 0)
1663 return -EINVAL;
1664
1665 mutex_lock(&ar->conf_mutex);
1666
1667 ar->debug.nf_cal_period = period;
1668
1669 if (ar->state != ATH10K_STATE_ON) {
1670 /* firmware is not running, nothing else to do */
1671 ret = count;
1672 goto exit;
1673 }
1674
1675 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->cal_period,
1676 ar->debug.nf_cal_period);
1677 if (ret) {
1678 ath10k_warn(ar, "cal period cfg failed from debugfs: %d\n",
1679 ret);
1680 goto exit;
1681 }
1682
1683 ret = count;
1684
1685exit:
1686 mutex_unlock(&ar->conf_mutex);
1687
1688 return ret;
1689}
1690
1691static const struct file_operations fops_nf_cal_period = {
1692 .read = ath10k_read_nf_cal_period,
1693 .write = ath10k_write_nf_cal_period,
1694 .open = simple_open,
1695 .owner = THIS_MODULE,
1696 .llseek = default_llseek,
1697};
1698
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001699#define ATH10K_TPC_CONFIG_BUF_SIZE (1024 * 1024)
1700
1701static int ath10k_debug_tpc_stats_request(struct ath10k *ar)
1702{
1703 int ret;
1704 unsigned long time_left;
1705
1706 lockdep_assert_held(&ar->conf_mutex);
1707
1708 reinit_completion(&ar->debug.tpc_complete);
1709
1710 ret = ath10k_wmi_pdev_get_tpc_config(ar, WMI_TPC_CONFIG_PARAM);
1711 if (ret) {
1712 ath10k_warn(ar, "failed to request tpc config: %d\n", ret);
1713 return ret;
1714 }
1715
1716 time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
1717 1 * HZ);
1718 if (time_left == 0)
1719 return -ETIMEDOUT;
1720
1721 return 0;
1722}
1723
1724void ath10k_debug_tpc_stats_process(struct ath10k *ar,
1725 struct ath10k_tpc_stats *tpc_stats)
1726{
1727 spin_lock_bh(&ar->data_lock);
1728
1729 kfree(ar->debug.tpc_stats);
1730 ar->debug.tpc_stats = tpc_stats;
1731 complete(&ar->debug.tpc_complete);
1732
1733 spin_unlock_bh(&ar->data_lock);
1734}
1735
1736static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001737 unsigned int j, char *buf, size_t *len)
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001738{
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001739 int i;
1740 size_t buf_len;
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001741 static const char table_str[][5] = { "CDD",
1742 "STBC",
1743 "TXBF" };
1744 static const char pream_str[][6] = { "CCK",
1745 "OFDM",
1746 "HT20",
1747 "HT40",
1748 "VHT20",
1749 "VHT40",
1750 "VHT80",
1751 "HTCUP" };
1752
1753 buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1754 *len += scnprintf(buf + *len, buf_len - *len,
1755 "********************************\n");
1756 *len += scnprintf(buf + *len, buf_len - *len,
1757 "******************* %s POWER TABLE ****************\n",
1758 table_str[j]);
1759 *len += scnprintf(buf + *len, buf_len - *len,
1760 "********************************\n");
1761 *len += scnprintf(buf + *len, buf_len - *len,
1762 "No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3\n");
1763
1764 for (i = 0; i < tpc_stats->rate_max; i++) {
1765 *len += scnprintf(buf + *len, buf_len - *len,
1766 "%8d %s 0x%2x %s\n", i,
1767 pream_str[tpc_stats->tpc_table[j].pream_idx[i]],
1768 tpc_stats->tpc_table[j].rate_code[i],
1769 tpc_stats->tpc_table[j].tpc_value[i]);
1770 }
1771
1772 *len += scnprintf(buf + *len, buf_len - *len,
1773 "***********************************\n");
1774}
1775
1776static void ath10k_tpc_stats_fill(struct ath10k *ar,
1777 struct ath10k_tpc_stats *tpc_stats,
1778 char *buf)
1779{
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001780 int j;
1781 size_t len, buf_len;
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001782
1783 len = 0;
1784 buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1785
1786 spin_lock_bh(&ar->data_lock);
1787
1788 if (!tpc_stats) {
1789 ath10k_warn(ar, "failed to get tpc stats\n");
1790 goto unlock;
1791 }
1792
1793 len += scnprintf(buf + len, buf_len - len, "\n");
1794 len += scnprintf(buf + len, buf_len - len,
1795 "*************************************\n");
1796 len += scnprintf(buf + len, buf_len - len,
1797 "TPC config for channel %4d mode %d\n",
1798 tpc_stats->chan_freq,
1799 tpc_stats->phy_mode);
1800 len += scnprintf(buf + len, buf_len - len,
1801 "*************************************\n");
1802 len += scnprintf(buf + len, buf_len - len,
1803 "CTL = 0x%2x Reg. Domain = %2d\n",
1804 tpc_stats->ctl,
1805 tpc_stats->reg_domain);
1806 len += scnprintf(buf + len, buf_len - len,
1807 "Antenna Gain = %2d Reg. Max Antenna Gain = %2d\n",
1808 tpc_stats->twice_antenna_gain,
1809 tpc_stats->twice_antenna_reduction);
1810 len += scnprintf(buf + len, buf_len - len,
1811 "Power Limit = %2d Reg. Max Power = %2d\n",
1812 tpc_stats->power_limit,
1813 tpc_stats->twice_max_rd_power / 2);
1814 len += scnprintf(buf + len, buf_len - len,
1815 "Num tx chains = %2d Num supported rates = %2d\n",
1816 tpc_stats->num_tx_chain,
1817 tpc_stats->rate_max);
1818
Maharaja Kennadyrajane871fb62017-03-31 17:39:40 +05301819 for (j = 0; j < WMI_TPC_FLAG; j++) {
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001820 switch (j) {
1821 case WMI_TPC_TABLE_TYPE_CDD:
1822 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1823 len += scnprintf(buf + len, buf_len - len,
1824 "CDD not supported\n");
1825 break;
1826 }
1827
1828 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1829 break;
1830 case WMI_TPC_TABLE_TYPE_STBC:
1831 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1832 len += scnprintf(buf + len, buf_len - len,
1833 "STBC not supported\n");
1834 break;
1835 }
1836
1837 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1838 break;
1839 case WMI_TPC_TABLE_TYPE_TXBF:
1840 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1841 len += scnprintf(buf + len, buf_len - len,
1842 "TXBF not supported\n***************************\n");
1843 break;
1844 }
1845
1846 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1847 break;
1848 default:
1849 len += scnprintf(buf + len, buf_len - len,
1850 "Invalid Type\n");
1851 break;
1852 }
1853 }
1854
1855unlock:
1856 spin_unlock_bh(&ar->data_lock);
1857
1858 if (len >= buf_len)
1859 buf[len - 1] = 0;
1860 else
1861 buf[len] = 0;
1862}
1863
1864static int ath10k_tpc_stats_open(struct inode *inode, struct file *file)
1865{
1866 struct ath10k *ar = inode->i_private;
1867 void *buf = NULL;
1868 int ret;
1869
1870 mutex_lock(&ar->conf_mutex);
1871
1872 if (ar->state != ATH10K_STATE_ON) {
1873 ret = -ENETDOWN;
1874 goto err_unlock;
1875 }
1876
1877 buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
1878 if (!buf) {
1879 ret = -ENOMEM;
1880 goto err_unlock;
1881 }
1882
1883 ret = ath10k_debug_tpc_stats_request(ar);
1884 if (ret) {
1885 ath10k_warn(ar, "failed to request tpc config stats: %d\n",
1886 ret);
1887 goto err_free;
1888 }
1889
1890 ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
1891 file->private_data = buf;
1892
1893 mutex_unlock(&ar->conf_mutex);
1894 return 0;
1895
1896err_free:
1897 vfree(buf);
1898
1899err_unlock:
1900 mutex_unlock(&ar->conf_mutex);
1901 return ret;
1902}
1903
1904static int ath10k_tpc_stats_release(struct inode *inode, struct file *file)
1905{
1906 vfree(file->private_data);
1907
1908 return 0;
1909}
1910
1911static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf,
1912 size_t count, loff_t *ppos)
1913{
1914 const char *buf = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001915 size_t len = strlen(buf);
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001916
1917 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1918}
1919
1920static const struct file_operations fops_tpc_stats = {
1921 .open = ath10k_tpc_stats_open,
1922 .release = ath10k_tpc_stats_release,
1923 .read = ath10k_tpc_stats_read,
1924 .owner = THIS_MODULE,
1925 .llseek = default_llseek,
1926};
1927
Kalle Valodb66ea02013-09-03 11:44:03 +03001928int ath10k_debug_start(struct ath10k *ar)
1929{
Kalle Valoa3d135e2013-09-03 11:44:10 +03001930 int ret;
1931
Kalle Valo60631c52013-10-08 21:45:25 +03001932 lockdep_assert_held(&ar->conf_mutex);
1933
Kalle Valoa3d135e2013-09-03 11:44:10 +03001934 ret = ath10k_debug_htt_stats_req(ar);
1935 if (ret)
1936 /* continue normally anyway, this isn't serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001937 ath10k_warn(ar, "failed to start htt stats workqueue: %d\n",
1938 ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001939
Kalle Valof118a3e2014-01-03 12:59:31 +02001940 if (ar->debug.fw_dbglog_mask) {
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301941 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1942 ATH10K_DBGLOG_LEVEL_WARN);
Kalle Valof118a3e2014-01-03 12:59:31 +02001943 if (ret)
1944 /* not serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001945 ath10k_warn(ar, "failed to enable dbglog during start: %d",
Kalle Valof118a3e2014-01-03 12:59:31 +02001946 ret);
1947 }
1948
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001949 if (ar->debug.pktlog_filter) {
1950 ret = ath10k_wmi_pdev_pktlog_enable(ar,
1951 ar->debug.pktlog_filter);
1952 if (ret)
1953 /* not serious */
1954 ath10k_warn(ar,
1955 "failed to enable pktlog filter %x: %d\n",
1956 ar->debug.pktlog_filter, ret);
1957 } else {
1958 ret = ath10k_wmi_pdev_pktlog_disable(ar);
1959 if (ret)
1960 /* not serious */
1961 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
1962 }
1963
Peter Oha7bd3e92014-12-02 13:07:14 +02001964 if (ar->debug.nf_cal_period) {
1965 ret = ath10k_wmi_pdev_set_param(ar,
1966 ar->wmi.pdev_param->cal_period,
1967 ar->debug.nf_cal_period);
1968 if (ret)
1969 /* not serious */
1970 ath10k_warn(ar, "cal period cfg failed from debug start: %d\n",
1971 ret);
1972 }
1973
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001974 return ret;
Kalle Valodb66ea02013-09-03 11:44:03 +03001975}
1976
1977void ath10k_debug_stop(struct ath10k *ar)
1978{
Kalle Valo60631c52013-10-08 21:45:25 +03001979 lockdep_assert_held(&ar->conf_mutex);
1980
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001981 ath10k_debug_cal_data_fetch(ar);
1982
Kalle Valo60631c52013-10-08 21:45:25 +03001983 /* Must not use _sync to avoid deadlock, we do that in
1984 * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid
Marcin Rokickid6dfe25c2017-02-20 14:39:57 +01001985 * warning from del_timer().
1986 */
Kalle Valo60631c52013-10-08 21:45:25 +03001987 if (ar->debug.htt_stats_mask != 0)
1988 cancel_delayed_work(&ar->debug.htt_stats_dwork);
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001989
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001990 ath10k_wmi_pdev_pktlog_disable(ar);
Kalle Valodb66ea02013-09-03 11:44:03 +03001991}
1992
Janusz Dziedzic9702c682013-11-20 09:59:41 +02001993static ssize_t ath10k_write_simulate_radar(struct file *file,
1994 const char __user *user_buf,
1995 size_t count, loff_t *ppos)
1996{
1997 struct ath10k *ar = file->private_data;
Mohammed Shafi Shajakhanca07baa2017-02-22 21:03:11 +05301998 struct ath10k_vif *arvif;
1999
2000 /* Just check for for the first vif alone, as all the vifs will be
2001 * sharing the same channel and if the channel is disabled, all the
2002 * vifs will share the same 'is_started' state.
2003 */
2004 arvif = list_first_entry(&ar->arvifs, typeof(*arvif), list);
2005 if (!arvif->is_started)
2006 return -EINVAL;
Janusz Dziedzic9702c682013-11-20 09:59:41 +02002007
2008 ieee80211_radar_detected(ar->hw);
2009
2010 return count;
2011}
2012
2013static const struct file_operations fops_simulate_radar = {
2014 .write = ath10k_write_simulate_radar,
2015 .open = simple_open,
2016 .owner = THIS_MODULE,
2017 .llseek = default_llseek,
2018};
2019
2020#define ATH10K_DFS_STAT(s, p) (\
2021 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
2022 ar->debug.dfs_stats.p))
2023
2024#define ATH10K_DFS_POOL_STAT(s, p) (\
2025 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
2026 ar->debug.dfs_pool_stats.p))
2027
2028static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf,
2029 size_t count, loff_t *ppos)
2030{
2031 int retval = 0, len = 0;
2032 const int size = 8000;
2033 struct ath10k *ar = file->private_data;
2034 char *buf;
2035
2036 buf = kzalloc(size, GFP_KERNEL);
2037 if (buf == NULL)
2038 return -ENOMEM;
2039
2040 if (!ar->dfs_detector) {
2041 len += scnprintf(buf + len, size - len, "DFS not enabled\n");
2042 goto exit;
2043 }
2044
2045 ar->debug.dfs_pool_stats =
2046 ar->dfs_detector->get_stats(ar->dfs_detector);
2047
2048 len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");
2049
2050 ATH10K_DFS_STAT("reported phy errors", phy_errors);
2051 ATH10K_DFS_STAT("pulse events reported", pulses_total);
2052 ATH10K_DFS_STAT("DFS pulses detected", pulses_detected);
2053 ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded);
2054 ATH10K_DFS_STAT("Radars detected", radar_detected);
2055
2056 len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");
2057 ATH10K_DFS_POOL_STAT("Pool references", pool_reference);
2058 ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated);
2059 ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error);
2060 ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used);
2061 ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated);
2062 ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error);
2063 ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used);
2064
2065exit:
2066 if (len > size)
2067 len = size;
2068
2069 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
2070 kfree(buf);
2071
2072 return retval;
2073}
2074
2075static const struct file_operations fops_dfs_stats = {
2076 .read = ath10k_read_dfs_stats,
2077 .open = simple_open,
2078 .owner = THIS_MODULE,
2079 .llseek = default_llseek,
2080};
2081
Rajkumar Manoharan90174452014-10-03 08:02:33 +03002082static ssize_t ath10k_write_pktlog_filter(struct file *file,
2083 const char __user *ubuf,
2084 size_t count, loff_t *ppos)
2085{
2086 struct ath10k *ar = file->private_data;
2087 u32 filter;
2088 int ret;
2089
2090 if (kstrtouint_from_user(ubuf, count, 0, &filter))
2091 return -EINVAL;
2092
2093 mutex_lock(&ar->conf_mutex);
2094
2095 if (ar->state != ATH10K_STATE_ON) {
2096 ar->debug.pktlog_filter = filter;
2097 ret = count;
2098 goto out;
2099 }
2100
Anilkumar Kolli9ddc4862016-03-11 11:46:39 +05302101 if (filter == ar->debug.pktlog_filter) {
2102 ret = count;
2103 goto out;
2104 }
2105
2106 if (filter) {
Rajkumar Manoharan90174452014-10-03 08:02:33 +03002107 ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
2108 if (ret) {
2109 ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
2110 ar->debug.pktlog_filter, ret);
2111 goto out;
2112 }
2113 } else {
2114 ret = ath10k_wmi_pdev_pktlog_disable(ar);
2115 if (ret) {
2116 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
2117 goto out;
2118 }
2119 }
2120
2121 ar->debug.pktlog_filter = filter;
2122 ret = count;
2123
2124out:
2125 mutex_unlock(&ar->conf_mutex);
2126 return ret;
2127}
2128
2129static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf,
2130 size_t count, loff_t *ppos)
2131{
2132 char buf[32];
2133 struct ath10k *ar = file->private_data;
2134 int len = 0;
2135
2136 mutex_lock(&ar->conf_mutex);
2137 len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
2138 ar->debug.pktlog_filter);
2139 mutex_unlock(&ar->conf_mutex);
2140
2141 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2142}
2143
2144static const struct file_operations fops_pktlog_filter = {
2145 .read = ath10k_read_pktlog_filter,
2146 .write = ath10k_write_pktlog_filter,
2147 .open = simple_open
2148};
2149
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302150static ssize_t ath10k_write_quiet_period(struct file *file,
2151 const char __user *ubuf,
2152 size_t count, loff_t *ppos)
2153{
2154 struct ath10k *ar = file->private_data;
2155 u32 period;
2156
2157 if (kstrtouint_from_user(ubuf, count, 0, &period))
2158 return -EINVAL;
2159
2160 if (period < ATH10K_QUIET_PERIOD_MIN) {
2161 ath10k_warn(ar, "Quiet period %u can not be lesser than 25ms\n",
2162 period);
2163 return -EINVAL;
2164 }
2165 mutex_lock(&ar->conf_mutex);
2166 ar->thermal.quiet_period = period;
Rajkumar Manoharan8515b5c2015-03-15 20:36:22 +05302167 ath10k_thermal_set_throttling(ar);
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302168 mutex_unlock(&ar->conf_mutex);
2169
2170 return count;
2171}
2172
2173static ssize_t ath10k_read_quiet_period(struct file *file, char __user *ubuf,
2174 size_t count, loff_t *ppos)
2175{
2176 char buf[32];
2177 struct ath10k *ar = file->private_data;
2178 int len = 0;
2179
2180 mutex_lock(&ar->conf_mutex);
2181 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2182 ar->thermal.quiet_period);
2183 mutex_unlock(&ar->conf_mutex);
2184
2185 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2186}
2187
2188static const struct file_operations fops_quiet_period = {
2189 .read = ath10k_read_quiet_period,
2190 .write = ath10k_write_quiet_period,
2191 .open = simple_open
2192};
2193
Yanbo Li844fa572015-10-31 11:07:21 +02002194static ssize_t ath10k_write_btcoex(struct file *file,
2195 const char __user *ubuf,
2196 size_t count, loff_t *ppos)
2197{
2198 struct ath10k *ar = file->private_data;
2199 char buf[32];
2200 size_t buf_size;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302201 int ret;
Yanbo Li844fa572015-10-31 11:07:21 +02002202 bool val;
Rajkumar Manoharan39136242016-05-27 20:15:59 +05302203 u32 pdev_param;
Yanbo Li844fa572015-10-31 11:07:21 +02002204
2205 buf_size = min(count, (sizeof(buf) - 1));
2206 if (copy_from_user(buf, ubuf, buf_size))
2207 return -EFAULT;
2208
2209 buf[buf_size] = '\0';
2210
2211 if (strtobool(buf, &val) != 0)
2212 return -EINVAL;
2213
2214 mutex_lock(&ar->conf_mutex);
2215
Mohammed Shafi Shajakhanc28e6f02016-02-23 12:58:36 +05302216 if (ar->state != ATH10K_STATE_ON &&
2217 ar->state != ATH10K_STATE_RESTARTED) {
2218 ret = -ENETDOWN;
2219 goto exit;
2220 }
2221
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302222 if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) {
2223 ret = count;
Yanbo Li844fa572015-10-31 11:07:21 +02002224 goto exit;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302225 }
Yanbo Li844fa572015-10-31 11:07:21 +02002226
Rajkumar Manoharan39136242016-05-27 20:15:59 +05302227 pdev_param = ar->wmi.pdev_param->enable_btcoex;
2228 if (test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM,
2229 ar->running_fw->fw_file.fw_features)) {
2230 ret = ath10k_wmi_pdev_set_param(ar, pdev_param, val);
2231 if (ret) {
2232 ath10k_warn(ar, "failed to enable btcoex: %d\n", ret);
2233 ret = count;
2234 goto exit;
2235 }
2236 } else {
2237 ath10k_info(ar, "restarting firmware due to btcoex change");
2238 queue_work(ar->workqueue, &ar->restart_work);
2239 }
2240
Yanbo Li844fa572015-10-31 11:07:21 +02002241 if (val)
2242 set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
2243 else
2244 clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
2245
Mohammed Shafi Shajakhanc28e6f02016-02-23 12:58:36 +05302246 ret = count;
Yanbo Li844fa572015-10-31 11:07:21 +02002247
2248exit:
2249 mutex_unlock(&ar->conf_mutex);
2250
Mohammed Shafi Shajakhanc28e6f02016-02-23 12:58:36 +05302251 return ret;
Yanbo Li844fa572015-10-31 11:07:21 +02002252}
2253
2254static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
2255 size_t count, loff_t *ppos)
2256{
2257 char buf[32];
2258 struct ath10k *ar = file->private_data;
2259 int len = 0;
2260
2261 mutex_lock(&ar->conf_mutex);
2262 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2263 test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));
2264 mutex_unlock(&ar->conf_mutex);
2265
2266 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2267}
2268
2269static const struct file_operations fops_btcoex = {
2270 .read = ath10k_read_btcoex,
2271 .write = ath10k_write_btcoex,
2272 .open = simple_open
2273};
2274
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302275static ssize_t ath10k_write_peer_stats(struct file *file,
2276 const char __user *ubuf,
2277 size_t count, loff_t *ppos)
2278{
2279 struct ath10k *ar = file->private_data;
2280 char buf[32];
2281 size_t buf_size;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302282 int ret;
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302283 bool val;
2284
2285 buf_size = min(count, (sizeof(buf) - 1));
2286 if (copy_from_user(buf, ubuf, buf_size))
2287 return -EFAULT;
2288
2289 buf[buf_size] = '\0';
2290
2291 if (strtobool(buf, &val) != 0)
2292 return -EINVAL;
2293
2294 mutex_lock(&ar->conf_mutex);
2295
2296 if (ar->state != ATH10K_STATE_ON &&
2297 ar->state != ATH10K_STATE_RESTARTED) {
2298 ret = -ENETDOWN;
2299 goto exit;
2300 }
2301
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302302 if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val)) {
2303 ret = count;
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302304 goto exit;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302305 }
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302306
2307 if (val)
2308 set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
2309 else
2310 clear_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
2311
2312 ath10k_info(ar, "restarting firmware due to Peer stats change");
2313
2314 queue_work(ar->workqueue, &ar->restart_work);
2315 ret = count;
2316
2317exit:
2318 mutex_unlock(&ar->conf_mutex);
2319 return ret;
2320}
2321
2322static ssize_t ath10k_read_peer_stats(struct file *file, char __user *ubuf,
2323 size_t count, loff_t *ppos)
2324
2325{
2326 char buf[32];
2327 struct ath10k *ar = file->private_data;
2328 int len = 0;
2329
2330 mutex_lock(&ar->conf_mutex);
2331 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2332 test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags));
2333 mutex_unlock(&ar->conf_mutex);
2334
2335 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2336}
2337
2338static const struct file_operations fops_peer_stats = {
2339 .read = ath10k_read_peer_stats,
2340 .write = ath10k_write_peer_stats,
2341 .open = simple_open
2342};
2343
Kalle Valo9e100c42015-11-25 15:38:41 +02002344static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
2345 char __user *user_buf,
2346 size_t count, loff_t *ppos)
2347{
2348 struct ath10k *ar = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02002349 size_t len = 0, buf_len = 4096;
Kalle Valo9e100c42015-11-25 15:38:41 +02002350 ssize_t ret_cnt;
2351 char *buf;
2352
2353 buf = kzalloc(buf_len, GFP_KERNEL);
2354 if (!buf)
2355 return -ENOMEM;
2356
2357 mutex_lock(&ar->conf_mutex);
2358
Kalle Valo9e100c42015-11-25 15:38:41 +02002359 len += scnprintf(buf + len, buf_len - len,
2360 "firmware-N.bin\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002361 crc32_le(0, ar->normal_mode_fw.fw_file.firmware->data,
2362 ar->normal_mode_fw.fw_file.firmware->size));
Kalle Valo9e100c42015-11-25 15:38:41 +02002363 len += scnprintf(buf + len, buf_len - len,
2364 "athwlan\t\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002365 crc32_le(0, ar->normal_mode_fw.fw_file.firmware_data,
2366 ar->normal_mode_fw.fw_file.firmware_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002367 len += scnprintf(buf + len, buf_len - len,
2368 "otp\t\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002369 crc32_le(0, ar->normal_mode_fw.fw_file.otp_data,
2370 ar->normal_mode_fw.fw_file.otp_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002371 len += scnprintf(buf + len, buf_len - len,
2372 "codeswap\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002373 crc32_le(0, ar->normal_mode_fw.fw_file.codeswap_data,
2374 ar->normal_mode_fw.fw_file.codeswap_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002375 len += scnprintf(buf + len, buf_len - len,
2376 "board-N.bin\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002377 crc32_le(0, ar->normal_mode_fw.board->data,
2378 ar->normal_mode_fw.board->size));
Kalle Valo9e100c42015-11-25 15:38:41 +02002379 len += scnprintf(buf + len, buf_len - len,
2380 "board\t\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002381 crc32_le(0, ar->normal_mode_fw.board_data,
2382 ar->normal_mode_fw.board_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002383
2384 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
2385
2386 mutex_unlock(&ar->conf_mutex);
2387
2388 kfree(buf);
2389 return ret_cnt;
2390}
2391
2392static const struct file_operations fops_fw_checksums = {
2393 .read = ath10k_debug_fw_checksums_read,
2394 .open = simple_open,
2395 .owner = THIS_MODULE,
2396 .llseek = default_llseek,
2397};
2398
Kalle Valo5e3dd152013-06-12 20:52:10 +03002399int ath10k_debug_create(struct ath10k *ar)
2400{
Ben Greear384914b2014-08-25 08:37:32 +03002401 ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002402 if (!ar->debug.fw_crash_data)
2403 return -ENOMEM;
Ben Greear384914b2014-08-25 08:37:32 +03002404
Marty Faltesekf67b107d2016-10-10 19:00:04 +03002405 ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
2406 if (!ar->debug.cal_data)
2407 return -ENOMEM;
2408
Michal Kazior53268492014-09-25 12:33:50 +02002409 INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +02002410 INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +02002411 INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +03002412 INIT_LIST_HEAD(&ar->debug.fw_stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +02002413
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002414 return 0;
2415}
2416
2417void ath10k_debug_destroy(struct ath10k *ar)
2418{
2419 vfree(ar->debug.fw_crash_data);
2420 ar->debug.fw_crash_data = NULL;
Michal Kazior53268492014-09-25 12:33:50 +02002421
Marty Faltesekf67b107d2016-10-10 19:00:04 +03002422 vfree(ar->debug.cal_data);
2423 ar->debug.cal_data = NULL;
2424
Michal Kazior53268492014-09-25 12:33:50 +02002425 ath10k_debug_fw_stats_reset(ar);
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002426
2427 kfree(ar->debug.tpc_stats);
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002428}
2429
2430int ath10k_debug_register(struct ath10k *ar)
2431{
Kalle Valo5e3dd152013-06-12 20:52:10 +03002432 ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
2433 ar->hw->wiphy->debugfsdir);
Michal Kazioradb43b22014-09-04 12:36:45 +02002434 if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
2435 if (IS_ERR(ar->debug.debugfs_phy))
2436 return PTR_ERR(ar->debug.debugfs_phy);
Kalle Valod8bb26b2014-09-14 12:50:33 +03002437
2438 return -ENOMEM;
Michal Kazioradb43b22014-09-04 12:36:45 +02002439 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03002440
Kalle Valoa3d135e2013-09-03 11:44:10 +03002441 INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
2442 ath10k_debug_htt_stats_dwork);
2443
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002444 init_completion(&ar->debug.tpc_complete);
Michal Kazior60ef4012014-09-25 12:33:48 +02002445 init_completion(&ar->debug.fw_stats_complete);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002446
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002447 debugfs_create_file("fw_stats", 0400, ar->debug.debugfs_phy, ar,
Kalle Valo5e3dd152013-06-12 20:52:10 +03002448 &fops_fw_stats);
2449
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002450 debugfs_create_file("fw_reset_stats", 0400, ar->debug.debugfs_phy, ar,
2451 &fops_fw_reset_stats);
Ben Greearf51dbe72014-09-29 14:41:46 +03002452
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002453 debugfs_create_file("wmi_services", 0400, ar->debug.debugfs_phy, ar,
Kalle Valo5e3dd152013-06-12 20:52:10 +03002454 &fops_wmi_services);
2455
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002456 debugfs_create_file("simulate_fw_crash", 0600, ar->debug.debugfs_phy, ar,
2457 &fops_simulate_fw_crash);
Michal Kazior278c4a82013-07-22 14:08:51 +02002458
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002459 debugfs_create_file("fw_crash_dump", 0400, ar->debug.debugfs_phy, ar,
2460 &fops_fw_crash_dump);
Ben Greear384914b2014-08-25 08:37:32 +03002461
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002462 debugfs_create_file("reg_addr", 0600, ar->debug.debugfs_phy, ar,
2463 &fops_reg_addr);
Yanbo Li077a3802014-11-25 12:24:33 +02002464
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002465 debugfs_create_file("reg_value", 0600, ar->debug.debugfs_phy, ar,
2466 &fops_reg_value);
Yanbo Li077a3802014-11-25 12:24:33 +02002467
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002468 debugfs_create_file("mem_value", 0600, ar->debug.debugfs_phy, ar,
2469 &fops_mem_value);
Yanbo Li9f65ad22014-11-25 12:24:48 +02002470
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002471 debugfs_create_file("chip_id", 0400, ar->debug.debugfs_phy, ar,
2472 &fops_chip_id);
Kalle Valo763b8cd2013-09-01 11:22:21 +03002473
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002474 debugfs_create_file("htt_stats_mask", 0600, ar->debug.debugfs_phy, ar,
2475 &fops_htt_stats_mask);
Kalle Valoa3d135e2013-09-03 11:44:10 +03002476
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002477 debugfs_create_file("htt_max_amsdu_ampdu", 0600, ar->debug.debugfs_phy, ar,
Janusz Dziedzicd3856232014-06-02 21:19:46 +03002478 &fops_htt_max_amsdu_ampdu);
2479
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002480 debugfs_create_file("fw_dbglog", 0600, ar->debug.debugfs_phy, ar,
2481 &fops_fw_dbglog);
Kalle Valof118a3e2014-01-03 12:59:31 +02002482
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002483 debugfs_create_file("cal_data", 0400, ar->debug.debugfs_phy, ar,
2484 &fops_cal_data);
Kalle Valo7869b4f2014-09-24 14:16:58 +03002485
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002486 debugfs_create_file("ani_enable", 0600, ar->debug.debugfs_phy, ar,
2487 &fops_ani_enable);
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05302488
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002489 debugfs_create_file("nf_cal_period", 0600, ar->debug.debugfs_phy, ar,
2490 &fops_nf_cal_period);
Peter Oha7bd3e92014-12-02 13:07:14 +02002491
Masahiro Yamada97f26452016-08-03 13:45:50 -07002492 if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002493 debugfs_create_file("dfs_simulate_radar", 0200, ar->debug.debugfs_phy,
2494 ar, &fops_simulate_radar);
Janusz Dziedzic9702c682013-11-20 09:59:41 +02002495
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002496 debugfs_create_bool("dfs_block_radar_events", 0200,
Marek Puzyniak7d9b40b2013-11-20 10:00:28 +02002497 ar->debug.debugfs_phy,
2498 &ar->dfs_block_radar_events);
2499
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002500 debugfs_create_file("dfs_stats", 0400, ar->debug.debugfs_phy, ar,
Janusz Dziedzic9702c682013-11-20 09:59:41 +02002501 &fops_dfs_stats);
2502 }
2503
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002504 debugfs_create_file("pktlog_filter", 0644, ar->debug.debugfs_phy, ar,
2505 &fops_pktlog_filter);
Rajkumar Manoharan90174452014-10-03 08:02:33 +03002506
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002507 debugfs_create_file("quiet_period", 0644, ar->debug.debugfs_phy, ar,
2508 &fops_quiet_period);
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302509
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002510 debugfs_create_file("tpc_stats", 0400, ar->debug.debugfs_phy, ar,
2511 &fops_tpc_stats);
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002512
Yanbo Li844fa572015-10-31 11:07:21 +02002513 if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002514 debugfs_create_file("btcoex", 0644, ar->debug.debugfs_phy, ar,
2515 &fops_btcoex);
Yanbo Li844fa572015-10-31 11:07:21 +02002516
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302517 if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002518 debugfs_create_file("peer_stats", 0644, ar->debug.debugfs_phy, ar,
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302519 &fops_peer_stats);
2520
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002521 debugfs_create_file("fw_checksums", 0400, ar->debug.debugfs_phy, ar,
2522 &fops_fw_checksums);
Kalle Valo9e100c42015-11-25 15:38:41 +02002523
Kalle Valo5e3dd152013-06-12 20:52:10 +03002524 return 0;
2525}
Kalle Valodb66ea02013-09-03 11:44:03 +03002526
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002527void ath10k_debug_unregister(struct ath10k *ar)
Kalle Valo60631c52013-10-08 21:45:25 +03002528{
2529 cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
2530}
2531
Kalle Valo5e3dd152013-06-12 20:52:10 +03002532#endif /* CONFIG_ATH10K_DEBUGFS */
2533
2534#ifdef CONFIG_ATH10K_DEBUG
Michal Kazior7aa7a722014-08-25 12:09:38 +02002535void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
2536 const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +03002537{
2538 struct va_format vaf;
2539 va_list args;
2540
2541 va_start(args, fmt);
2542
2543 vaf.fmt = fmt;
2544 vaf.va = &args;
2545
2546 if (ath10k_debug_mask & mask)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002547 dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002548
Michal Kaziord35a6c12014-09-02 11:00:21 +03002549 trace_ath10k_log_dbg(ar, mask, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002550
2551 va_end(args);
2552}
2553EXPORT_SYMBOL(ath10k_dbg);
2554
Michal Kazior7aa7a722014-08-25 12:09:38 +02002555void ath10k_dbg_dump(struct ath10k *ar,
2556 enum ath10k_debug_mask mask,
Kalle Valo5e3dd152013-06-12 20:52:10 +03002557 const char *msg, const char *prefix,
2558 const void *buf, size_t len)
2559{
Michal Kazior45724a82014-09-23 10:22:53 +02002560 char linebuf[256];
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02002561 size_t linebuflen;
Michal Kazior45724a82014-09-23 10:22:53 +02002562 const void *ptr;
2563
Kalle Valo5e3dd152013-06-12 20:52:10 +03002564 if (ath10k_debug_mask & mask) {
2565 if (msg)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002566 ath10k_dbg(ar, mask, "%s\n", msg);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002567
Michal Kazior45724a82014-09-23 10:22:53 +02002568 for (ptr = buf; (ptr - buf) < len; ptr += 16) {
2569 linebuflen = 0;
2570 linebuflen += scnprintf(linebuf + linebuflen,
2571 sizeof(linebuf) - linebuflen,
2572 "%s%08x: ",
2573 (prefix ? prefix : ""),
2574 (unsigned int)(ptr - buf));
2575 hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
2576 linebuf + linebuflen,
2577 sizeof(linebuf) - linebuflen, true);
2578 dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
2579 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03002580 }
2581
2582 /* tracing code doesn't like null strings :/ */
Michal Kaziord35a6c12014-09-02 11:00:21 +03002583 trace_ath10k_log_dbg_dump(ar, msg ? msg : "", prefix ? prefix : "",
Kalle Valo5e3dd152013-06-12 20:52:10 +03002584 buf, len);
2585}
2586EXPORT_SYMBOL(ath10k_dbg_dump);
2587
2588#endif /* CONFIG_ATH10K_DEBUG */