blob: 39fe4f3350aa070d36b6e43dff410a39c5cad400 [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>
Kalle Valo5e3dd152013-06-12 20:52:10 +030024
25#include "core.h"
26#include "debug.h"
Kalle Valo7869b4f2014-09-24 14:16:58 +030027#include "hif.h"
Michal Kaziord7579d12014-12-03 10:10:54 +020028#include "wmi-ops.h"
Kalle Valo5e3dd152013-06-12 20:52:10 +030029
Kalle Valoa3d135e2013-09-03 11:44:10 +030030/* ms */
31#define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
32
Ben Greear384914b2014-08-25 08:37:32 +030033#define ATH10K_FW_CRASH_DUMP_VERSION 1
34
35/**
36 * enum ath10k_fw_crash_dump_type - types of data in the dump file
37 * @ATH10K_FW_CRASH_DUMP_REGDUMP: Register crash dump in binary format
38 */
39enum ath10k_fw_crash_dump_type {
40 ATH10K_FW_CRASH_DUMP_REGISTERS = 0,
41
42 ATH10K_FW_CRASH_DUMP_MAX,
43};
44
45struct ath10k_tlv_dump_data {
46 /* see ath10k_fw_crash_dump_type above */
47 __le32 type;
48
49 /* in bytes */
50 __le32 tlv_len;
51
52 /* pad to 32-bit boundaries as needed */
53 u8 tlv_data[];
54} __packed;
55
56struct ath10k_dump_file_data {
57 /* dump file information */
58
59 /* "ATH10K-FW-DUMP" */
60 char df_magic[16];
61
62 __le32 len;
63
64 /* file dump version */
65 __le32 version;
66
67 /* some info we can get from ath10k struct that might help */
68
69 u8 uuid[16];
70
71 __le32 chip_id;
72
73 /* 0 for now, in place for later hardware */
74 __le32 bus_type;
75
76 __le32 target_version;
77 __le32 fw_version_major;
78 __le32 fw_version_minor;
79 __le32 fw_version_release;
80 __le32 fw_version_build;
81 __le32 phy_capability;
82 __le32 hw_min_tx_power;
83 __le32 hw_max_tx_power;
84 __le32 ht_cap_info;
85 __le32 vht_cap_info;
86 __le32 num_rf_chains;
87
88 /* firmware version string */
89 char fw_ver[ETHTOOL_FWVERS_LEN];
90
91 /* Kernel related information */
92
93 /* time-of-day stamp */
94 __le64 tv_sec;
95
96 /* time-of-day stamp, nano-seconds */
97 __le64 tv_nsec;
98
99 /* LINUX_VERSION_CODE */
100 __le32 kernel_ver_code;
101
102 /* VERMAGIC_STRING */
103 char kernel_ver[64];
104
105 /* room for growth w/out changing binary format */
106 u8 unused[128];
107
108 /* struct ath10k_tlv_dump_data + more */
109 u8 data[0];
110} __packed;
111
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700112void ath10k_info(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300113{
114 struct va_format vaf = {
115 .fmt = fmt,
116 };
117 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300118
119 va_start(args, fmt);
120 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700121 dev_info(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300122 trace_ath10k_log_info(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300123 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300124}
125EXPORT_SYMBOL(ath10k_info);
126
Kalle Valo23f591e2015-11-25 15:38:27 +0200127void ath10k_debug_print_hwfw_info(struct ath10k *ar)
Kalle Valo8a0c7972014-08-25 08:37:45 +0300128{
Michal Kazior84e3df62015-08-05 06:55:37 +0200129 char fw_features[128] = {};
Michal Kaziorb27bc5a2015-06-15 14:46:40 +0300130
131 ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
132
Kalle Valo8605c022015-11-25 15:38:19 +0200133 ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x",
Kalle Valo8a0c7972014-08-25 08:37:45 +0300134 ar->hw_params.name,
135 ar->target_version,
136 ar->chip_id,
Kalle Valo8605c022015-11-25 15:38:19 +0200137 ar->id.subsystem_vendor, ar->id.subsystem_device);
Kalle Valof0de90b2015-11-25 15:38:12 +0200138
Kalle Valof0de90b2015-11-25 15:38:12 +0200139 ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n",
140 config_enabled(CONFIG_ATH10K_DEBUG),
141 config_enabled(CONFIG_ATH10K_DEBUGFS),
142 config_enabled(CONFIG_ATH10K_TRACING),
143 config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
144 config_enabled(CONFIG_NL80211_TESTMODE));
145
Kalle Valo3e580442015-11-25 15:38:34 +0200146 ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",
Kalle Valo23f591e2015-11-25 15:38:27 +0200147 ar->hw->wiphy->fw_version,
148 ar->fw_api,
Kalle Valo3e580442015-11-25 15:38:34 +0200149 fw_features,
150 crc32_le(0, ar->firmware->data, ar->firmware->size));
Kalle Valo23f591e2015-11-25 15:38:27 +0200151}
152
153void ath10k_debug_print_board_info(struct ath10k *ar)
154{
155 char boardinfo[100];
156
157 if (ar->id.bmi_ids_valid)
158 scnprintf(boardinfo, sizeof(boardinfo), "%d:%d",
159 ar->id.bmi_chip_id, ar->id.bmi_board_id);
160 else
161 scnprintf(boardinfo, sizeof(boardinfo), "N/A");
162
Kalle Valo3e580442015-11-25 15:38:34 +0200163 ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x",
Kalle Valo23f591e2015-11-25 15:38:27 +0200164 ar->bd_api,
Kalle Valo3e580442015-11-25 15:38:34 +0200165 boardinfo,
166 crc32_le(0, ar->board->data, ar->board->size));
Kalle Valo23f591e2015-11-25 15:38:27 +0200167}
168
169void ath10k_debug_print_boot_info(struct ath10k *ar)
170{
Kalle Valof0de90b2015-11-25 15:38:12 +0200171 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 +0300172 ar->htt.target_version_major,
Michal Kazior34b28b62014-09-23 10:22:52 +0200173 ar->htt.target_version_minor,
Kalle Valoffdd0752014-12-17 12:21:03 +0200174 ar->wmi.op_version,
Michal Kazior67c81f52015-06-15 14:46:41 +0300175 ar->htt.op_version,
Michal Kaziorcfd10612014-11-25 15:16:05 +0100176 ath10k_cal_mode_str(ar->cal_mode),
Michal Kaziorb27bc5a2015-06-15 14:46:40 +0300177 ar->max_num_stations,
David Liuccec9032015-07-24 20:25:32 +0300178 test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
Kalle Valof0de90b2015-11-25 15:38:12 +0200179 !test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags));
Kalle Valo8a0c7972014-08-25 08:37:45 +0300180}
Kalle Valo23f591e2015-11-25 15:38:27 +0200181
182void ath10k_print_driver_info(struct ath10k *ar)
183{
184 ath10k_debug_print_hwfw_info(ar);
185 ath10k_debug_print_board_info(ar);
186 ath10k_debug_print_boot_info(ar);
187}
Kalle Valo8a0c7972014-08-25 08:37:45 +0300188EXPORT_SYMBOL(ath10k_print_driver_info);
189
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700190void ath10k_err(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300191{
192 struct va_format vaf = {
193 .fmt = fmt,
194 };
195 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300196
197 va_start(args, fmt);
198 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700199 dev_err(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300200 trace_ath10k_log_err(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300201 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300202}
203EXPORT_SYMBOL(ath10k_err);
204
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700205void ath10k_warn(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300206{
207 struct va_format vaf = {
208 .fmt = fmt,
209 };
210 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300211
212 va_start(args, fmt);
213 vaf.va = &args;
Michal Kazior7aa7a722014-08-25 12:09:38 +0200214 dev_warn_ratelimited(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300215 trace_ath10k_log_warn(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300216
217 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300218}
219EXPORT_SYMBOL(ath10k_warn);
220
221#ifdef CONFIG_ATH10K_DEBUGFS
222
Kalle Valo5e3dd152013-06-12 20:52:10 +0300223static ssize_t ath10k_read_wmi_services(struct file *file,
224 char __user *user_buf,
225 size_t count, loff_t *ppos)
226{
227 struct ath10k *ar = file->private_data;
228 char *buf;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300229 unsigned int len = 0, buf_len = 4096;
230 const char *name;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300231 ssize_t ret_cnt;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300232 bool enabled;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300233 int i;
234
235 buf = kzalloc(buf_len, GFP_KERNEL);
236 if (!buf)
237 return -ENOMEM;
238
239 mutex_lock(&ar->conf_mutex);
240
241 if (len > buf_len)
242 len = buf_len;
243
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100244 spin_lock_bh(&ar->data_lock);
Michal Kaziorc4f8c832014-09-04 10:18:32 +0200245 for (i = 0; i < WMI_SERVICE_MAX; i++) {
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100246 enabled = test_bit(i, ar->wmi.svc_map);
Michal Kaziorcff990c2014-08-04 09:18:33 +0300247 name = wmi_service_name(i);
248
249 if (!name) {
250 if (enabled)
251 len += scnprintf(buf + len, buf_len - len,
252 "%-40s %s (bit %d)\n",
253 "unknown", "enabled", i);
254
255 continue;
256 }
Kalle Valo5e3dd152013-06-12 20:52:10 +0300257
258 len += scnprintf(buf + len, buf_len - len,
Michal Kaziorcff990c2014-08-04 09:18:33 +0300259 "%-40s %s\n",
260 name, enabled ? "enabled" : "-");
Kalle Valo5e3dd152013-06-12 20:52:10 +0300261 }
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100262 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300263
264 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
265
266 mutex_unlock(&ar->conf_mutex);
267
268 kfree(buf);
269 return ret_cnt;
270}
271
272static const struct file_operations fops_wmi_services = {
273 .read = ath10k_read_wmi_services,
274 .open = simple_open,
275 .owner = THIS_MODULE,
276 .llseek = default_llseek,
277};
278
Michal Kazior53268492014-09-25 12:33:50 +0200279static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
280{
281 struct ath10k_fw_stats_pdev *i, *tmp;
282
283 list_for_each_entry_safe(i, tmp, head, list) {
284 list_del(&i->list);
285 kfree(i);
286 }
287}
288
Michal Kazior7b6b1532015-02-15 16:50:40 +0200289static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head)
290{
291 struct ath10k_fw_stats_vdev *i, *tmp;
292
293 list_for_each_entry_safe(i, tmp, head, list) {
294 list_del(&i->list);
295 kfree(i);
296 }
297}
298
Michal Kazior53268492014-09-25 12:33:50 +0200299static void ath10k_debug_fw_stats_peers_free(struct list_head *head)
300{
301 struct ath10k_fw_stats_peer *i, *tmp;
302
303 list_for_each_entry_safe(i, tmp, head, list) {
304 list_del(&i->list);
305 kfree(i);
306 }
307}
308
309static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
310{
311 spin_lock_bh(&ar->data_lock);
312 ar->debug.fw_stats_done = false;
313 ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200314 ath10k_debug_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200315 ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers);
316 spin_unlock_bh(&ar->data_lock);
317}
318
Michal Kazior60ef4012014-09-25 12:33:48 +0200319void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300320{
Michal Kazior53268492014-09-25 12:33:50 +0200321 struct ath10k_fw_stats stats = {};
322 bool is_start, is_started, is_end;
323 size_t num_peers;
Michal Kazior7b6b1532015-02-15 16:50:40 +0200324 size_t num_vdevs;
Michal Kaziord15fb522014-09-25 12:33:47 +0200325 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300326
Michal Kazior53268492014-09-25 12:33:50 +0200327 INIT_LIST_HEAD(&stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200328 INIT_LIST_HEAD(&stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200329 INIT_LIST_HEAD(&stats.peers);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300330
Michal Kazior53268492014-09-25 12:33:50 +0200331 spin_lock_bh(&ar->data_lock);
332 ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
Michal Kaziord15fb522014-09-25 12:33:47 +0200333 if (ret) {
334 ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
Raja Mani5db879a2015-07-09 14:19:43 +0530335 goto free;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300336 }
337
Michal Kazior53268492014-09-25 12:33:50 +0200338 /* Stat data may exceed htc-wmi buffer limit. In such case firmware
339 * splits the stats data and delivers it in a ping-pong fashion of
340 * request cmd-update event.
341 *
342 * However there is no explicit end-of-data. Instead start-of-data is
343 * used as an implicit one. This works as follows:
344 * a) discard stat update events until one with pdev stats is
345 * delivered - this skips session started at end of (b)
346 * b) consume stat update events until another one with pdev stats is
347 * delivered which is treated as end-of-data and is itself discarded
348 */
349
350 if (ar->debug.fw_stats_done) {
351 ath10k_warn(ar, "received unsolicited stats update event\n");
352 goto free;
353 }
354
Manikanta Pubbisettybc6f9ae2015-10-16 15:54:52 +0300355 num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers);
356 num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200357 is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
358 !list_empty(&stats.pdevs));
359 is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
360 !list_empty(&stats.pdevs));
361
362 if (is_start)
363 list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
364
365 if (is_end)
366 ar->debug.fw_stats_done = true;
367
368 is_started = !list_empty(&ar->debug.fw_stats.pdevs);
369
370 if (is_started && !is_end) {
371 if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) {
372 /* Although this is unlikely impose a sane limit to
373 * prevent firmware from DoS-ing the host.
374 */
375 ath10k_warn(ar, "dropping fw peer stats\n");
376 goto free;
377 }
378
Michal Kazior7b6b1532015-02-15 16:50:40 +0200379 if (num_vdevs >= BITS_PER_LONG) {
380 ath10k_warn(ar, "dropping fw vdev stats\n");
381 goto free;
382 }
383
Michal Kazior53268492014-09-25 12:33:50 +0200384 list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200385 list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200386 }
387
Michal Kazior60ef4012014-09-25 12:33:48 +0200388 complete(&ar->debug.fw_stats_complete);
Michal Kaziord15fb522014-09-25 12:33:47 +0200389
Michal Kazior53268492014-09-25 12:33:50 +0200390free:
391 /* In some cases lists have been spliced and cleared. Free up
392 * resources if that is not the case.
393 */
394 ath10k_debug_fw_stats_pdevs_free(&stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200395 ath10k_debug_fw_stats_vdevs_free(&stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200396 ath10k_debug_fw_stats_peers_free(&stats.peers);
397
Michal Kaziord15fb522014-09-25 12:33:47 +0200398 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300399}
400
Michal Kazior53268492014-09-25 12:33:50 +0200401static int ath10k_debug_fw_stats_request(struct ath10k *ar)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300402{
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300403 unsigned long timeout, time_left;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300404 int ret;
405
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200406 lockdep_assert_held(&ar->conf_mutex);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300407
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300408 timeout = jiffies + msecs_to_jiffies(1 * HZ);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300409
Michal Kazior53268492014-09-25 12:33:50 +0200410 ath10k_debug_fw_stats_reset(ar);
411
412 for (;;) {
413 if (time_after(jiffies, timeout))
414 return -ETIMEDOUT;
415
416 reinit_completion(&ar->debug.fw_stats_complete);
417
Yanbo Li6274cd42015-04-01 22:53:21 +0300418 ret = ath10k_wmi_request_stats(ar, ar->fw_stats_req_mask);
Michal Kazior53268492014-09-25 12:33:50 +0200419 if (ret) {
420 ath10k_warn(ar, "could not request stats (%d)\n", ret);
421 return ret;
422 }
423
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300424 time_left =
425 wait_for_completion_timeout(&ar->debug.fw_stats_complete,
426 1 * HZ);
427 if (!time_left)
Michal Kazior53268492014-09-25 12:33:50 +0200428 return -ETIMEDOUT;
429
430 spin_lock_bh(&ar->data_lock);
431 if (ar->debug.fw_stats_done) {
432 spin_unlock_bh(&ar->data_lock);
433 break;
434 }
435 spin_unlock_bh(&ar->data_lock);
436 }
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200437
438 return 0;
439}
440
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200441static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
442{
443 struct ath10k *ar = inode->i_private;
444 void *buf = NULL;
445 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300446
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200447 mutex_lock(&ar->conf_mutex);
448
449 if (ar->state != ATH10K_STATE_ON) {
450 ret = -ENETDOWN;
451 goto err_unlock;
452 }
453
454 buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);
455 if (!buf) {
456 ret = -ENOMEM;
457 goto err_unlock;
458 }
459
Michal Kazior53268492014-09-25 12:33:50 +0200460 ret = ath10k_debug_fw_stats_request(ar);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200461 if (ret) {
462 ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
463 goto err_free;
464 }
465
Manikanta Pubbisettybc6f9ae2015-10-16 15:54:52 +0300466 ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
467 if (ret) {
468 ath10k_warn(ar, "failed to fill fw stats: %d\n", ret);
469 goto err_free;
470 }
471
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200472 file->private_data = buf;
473
Kalle Valo5e3dd152013-06-12 20:52:10 +0300474 mutex_unlock(&ar->conf_mutex);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200475 return 0;
476
477err_free:
478 vfree(buf);
479
480err_unlock:
481 mutex_unlock(&ar->conf_mutex);
482 return ret;
483}
484
485static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
486{
487 vfree(file->private_data);
488
489 return 0;
490}
491
492static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
493 size_t count, loff_t *ppos)
494{
495 const char *buf = file->private_data;
496 unsigned int len = strlen(buf);
497
498 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300499}
500
501static const struct file_operations fops_fw_stats = {
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200502 .open = ath10k_fw_stats_open,
503 .release = ath10k_fw_stats_release,
Michal Kazior60ef4012014-09-25 12:33:48 +0200504 .read = ath10k_fw_stats_read,
Kalle Valo5e3dd152013-06-12 20:52:10 +0300505 .owner = THIS_MODULE,
506 .llseek = default_llseek,
507};
508
Ben Greearf51dbe72014-09-29 14:41:46 +0300509static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
510 char __user *user_buf,
511 size_t count, loff_t *ppos)
512{
513 struct ath10k *ar = file->private_data;
514 int ret, len, buf_len;
515 char *buf;
516
517 buf_len = 500;
518 buf = kmalloc(buf_len, GFP_KERNEL);
519 if (!buf)
520 return -ENOMEM;
521
522 spin_lock_bh(&ar->data_lock);
523
524 len = 0;
525 len += scnprintf(buf + len, buf_len - len,
526 "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
527 len += scnprintf(buf + len, buf_len - len,
528 "fw_warm_reset_counter\t\t%d\n",
529 ar->stats.fw_warm_reset_counter);
530 len += scnprintf(buf + len, buf_len - len,
531 "fw_cold_reset_counter\t\t%d\n",
532 ar->stats.fw_cold_reset_counter);
533
534 spin_unlock_bh(&ar->data_lock);
535
536 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
537
538 kfree(buf);
539
540 return ret;
541}
542
543static const struct file_operations fops_fw_reset_stats = {
544 .open = simple_open,
545 .read = ath10k_debug_fw_reset_stats_read,
546 .owner = THIS_MODULE,
547 .llseek = default_llseek,
548};
549
Ben Greeard5aebc72014-09-10 18:59:28 +0300550/* This is a clean assert crash in firmware. */
551static int ath10k_debug_fw_assert(struct ath10k *ar)
552{
553 struct wmi_vdev_install_key_cmd *cmd;
554 struct sk_buff *skb;
555
556 skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
557 if (!skb)
558 return -ENOMEM;
559
560 cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
561 memset(cmd, 0, sizeof(*cmd));
562
563 /* big enough number so that firmware asserts */
564 cmd->vdev_id = __cpu_to_le32(0x7ffe);
565
566 return ath10k_wmi_cmd_send(ar, skb,
567 ar->wmi.cmd->vdev_install_key_cmdid);
568}
569
Michal Kazior278c4a82013-07-22 14:08:51 +0200570static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
571 char __user *user_buf,
572 size_t count, loff_t *ppos)
573{
Kalle Valo75cb96d2014-09-14 12:50:44 +0300574 const char buf[] =
575 "To simulate firmware crash write one of the keywords to this file:\n"
576 "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
577 "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
Michal Kazior605cdba2014-10-28 10:34:37 +0100578 "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"
579 "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
Marek Puzyniak8c656992014-03-21 17:46:56 +0200580
Michal Kazior278c4a82013-07-22 14:08:51 +0200581 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
582}
583
Marek Puzyniak8c656992014-03-21 17:46:56 +0200584/* Simulate firmware crash:
585 * 'soft': Call wmi command causing firmware hang. This firmware hang is
586 * recoverable by warm firmware reset.
587 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
588 * vdev id. This is hard firmware crash because it is recoverable only by cold
589 * firmware reset.
590 */
Michal Kazior278c4a82013-07-22 14:08:51 +0200591static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
592 const char __user *user_buf,
593 size_t count, loff_t *ppos)
594{
595 struct ath10k *ar = file->private_data;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200596 char buf[32];
Michal Kazior278c4a82013-07-22 14:08:51 +0200597 int ret;
598
599 mutex_lock(&ar->conf_mutex);
600
601 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200602
603 /* make sure that buf is null terminated */
604 buf[sizeof(buf) - 1] = 0;
Michal Kazior278c4a82013-07-22 14:08:51 +0200605
606 if (ar->state != ATH10K_STATE_ON &&
607 ar->state != ATH10K_STATE_RESTARTED) {
608 ret = -ENETDOWN;
609 goto exit;
610 }
611
Marek Puzyniak8c656992014-03-21 17:46:56 +0200612 /* drop the possible '\n' from the end */
613 if (buf[count - 1] == '\n') {
614 buf[count - 1] = 0;
615 count--;
616 }
Michal Kazior278c4a82013-07-22 14:08:51 +0200617
Marek Puzyniak8c656992014-03-21 17:46:56 +0200618 if (!strcmp(buf, "soft")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200619 ath10k_info(ar, "simulating soft firmware crash\n");
Marek Puzyniak8c656992014-03-21 17:46:56 +0200620 ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
621 } else if (!strcmp(buf, "hard")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200622 ath10k_info(ar, "simulating hard firmware crash\n");
Ben Greear611b3682014-07-25 11:56:40 +0300623 /* 0x7fff is vdev id, and it is always out of range for all
624 * firmware variants in order to force a firmware crash.
625 */
626 ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
Kalle Valo5b07e072014-09-14 12:50:06 +0300627 ar->wmi.vdev_param->rts_threshold,
628 0);
Ben Greeard5aebc72014-09-10 18:59:28 +0300629 } else if (!strcmp(buf, "assert")) {
630 ath10k_info(ar, "simulating firmware assert crash\n");
631 ret = ath10k_debug_fw_assert(ar);
Michal Kazior605cdba2014-10-28 10:34:37 +0100632 } else if (!strcmp(buf, "hw-restart")) {
633 ath10k_info(ar, "user requested hw restart\n");
634 queue_work(ar->workqueue, &ar->restart_work);
635 ret = 0;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200636 } else {
637 ret = -EINVAL;
638 goto exit;
639 }
Michal Kazior278c4a82013-07-22 14:08:51 +0200640
Marek Puzyniak8c656992014-03-21 17:46:56 +0200641 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200642 ath10k_warn(ar, "failed to simulate firmware crash: %d\n", ret);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200643 goto exit;
644 }
645
646 ret = count;
Michal Kazior278c4a82013-07-22 14:08:51 +0200647
648exit:
649 mutex_unlock(&ar->conf_mutex);
650 return ret;
651}
652
653static const struct file_operations fops_simulate_fw_crash = {
654 .read = ath10k_read_simulate_fw_crash,
655 .write = ath10k_write_simulate_fw_crash,
656 .open = simple_open,
657 .owner = THIS_MODULE,
658 .llseek = default_llseek,
659};
660
Kalle Valo763b8cd2013-09-01 11:22:21 +0300661static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf,
662 size_t count, loff_t *ppos)
663{
664 struct ath10k *ar = file->private_data;
665 unsigned int len;
666 char buf[50];
667
668 len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id);
669
670 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
671}
672
673static const struct file_operations fops_chip_id = {
674 .read = ath10k_read_chip_id,
675 .open = simple_open,
676 .owner = THIS_MODULE,
677 .llseek = default_llseek,
678};
679
Ben Greear384914b2014-08-25 08:37:32 +0300680struct ath10k_fw_crash_data *
681ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
682{
683 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
684
685 lockdep_assert_held(&ar->data_lock);
686
687 crash_data->crashed_since_read = true;
688 uuid_le_gen(&crash_data->uuid);
689 getnstimeofday(&crash_data->timestamp);
690
691 return crash_data;
692}
693EXPORT_SYMBOL(ath10k_debug_get_new_fw_crash_data);
694
695static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
696{
697 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
698 struct ath10k_dump_file_data *dump_data;
699 struct ath10k_tlv_dump_data *dump_tlv;
700 int hdr_len = sizeof(*dump_data);
701 unsigned int len, sofar = 0;
702 unsigned char *buf;
703
704 len = hdr_len;
705 len += sizeof(*dump_tlv) + sizeof(crash_data->registers);
706
707 sofar += hdr_len;
708
709 /* This is going to get big when we start dumping FW RAM and such,
710 * so go ahead and use vmalloc.
711 */
712 buf = vzalloc(len);
713 if (!buf)
714 return NULL;
715
716 spin_lock_bh(&ar->data_lock);
717
718 if (!crash_data->crashed_since_read) {
719 spin_unlock_bh(&ar->data_lock);
720 vfree(buf);
721 return NULL;
722 }
723
724 dump_data = (struct ath10k_dump_file_data *)(buf);
725 strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP",
726 sizeof(dump_data->df_magic));
727 dump_data->len = cpu_to_le32(len);
728
729 dump_data->version = cpu_to_le32(ATH10K_FW_CRASH_DUMP_VERSION);
730
731 memcpy(dump_data->uuid, &crash_data->uuid, sizeof(dump_data->uuid));
732 dump_data->chip_id = cpu_to_le32(ar->chip_id);
733 dump_data->bus_type = cpu_to_le32(0);
734 dump_data->target_version = cpu_to_le32(ar->target_version);
735 dump_data->fw_version_major = cpu_to_le32(ar->fw_version_major);
736 dump_data->fw_version_minor = cpu_to_le32(ar->fw_version_minor);
737 dump_data->fw_version_release = cpu_to_le32(ar->fw_version_release);
738 dump_data->fw_version_build = cpu_to_le32(ar->fw_version_build);
739 dump_data->phy_capability = cpu_to_le32(ar->phy_capability);
740 dump_data->hw_min_tx_power = cpu_to_le32(ar->hw_min_tx_power);
741 dump_data->hw_max_tx_power = cpu_to_le32(ar->hw_max_tx_power);
742 dump_data->ht_cap_info = cpu_to_le32(ar->ht_cap_info);
743 dump_data->vht_cap_info = cpu_to_le32(ar->vht_cap_info);
744 dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains);
745
746 strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
747 sizeof(dump_data->fw_ver));
748
Johannes Berg12c27152014-11-21 18:58:49 +0200749 dump_data->kernel_ver_code = 0;
750 strlcpy(dump_data->kernel_ver, init_utsname()->release,
Ben Greear384914b2014-08-25 08:37:32 +0300751 sizeof(dump_data->kernel_ver));
752
753 dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
754 dump_data->tv_nsec = cpu_to_le64(crash_data->timestamp.tv_nsec);
755
756 /* Gather crash-dump */
757 dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
758 dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_REGISTERS);
759 dump_tlv->tlv_len = cpu_to_le32(sizeof(crash_data->registers));
760 memcpy(dump_tlv->tlv_data, &crash_data->registers,
761 sizeof(crash_data->registers));
762 sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers);
763
764 ar->debug.fw_crash_data->crashed_since_read = false;
765
766 spin_unlock_bh(&ar->data_lock);
767
768 return dump_data;
769}
770
771static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file)
772{
773 struct ath10k *ar = inode->i_private;
774 struct ath10k_dump_file_data *dump;
775
776 dump = ath10k_build_dump_file(ar);
777 if (!dump)
778 return -ENODATA;
779
780 file->private_data = dump;
781
782 return 0;
783}
784
785static ssize_t ath10k_fw_crash_dump_read(struct file *file,
786 char __user *user_buf,
787 size_t count, loff_t *ppos)
788{
789 struct ath10k_dump_file_data *dump_file = file->private_data;
790
791 return simple_read_from_buffer(user_buf, count, ppos,
792 dump_file,
793 le32_to_cpu(dump_file->len));
794}
795
796static int ath10k_fw_crash_dump_release(struct inode *inode,
797 struct file *file)
798{
799 vfree(file->private_data);
800
801 return 0;
802}
803
804static const struct file_operations fops_fw_crash_dump = {
805 .open = ath10k_fw_crash_dump_open,
806 .read = ath10k_fw_crash_dump_read,
807 .release = ath10k_fw_crash_dump_release,
808 .owner = THIS_MODULE,
809 .llseek = default_llseek,
810};
811
Yanbo Li077a3802014-11-25 12:24:33 +0200812static ssize_t ath10k_reg_addr_read(struct file *file,
813 char __user *user_buf,
814 size_t count, loff_t *ppos)
815{
816 struct ath10k *ar = file->private_data;
817 u8 buf[32];
818 unsigned int len = 0;
819 u32 reg_addr;
820
821 mutex_lock(&ar->conf_mutex);
822 reg_addr = ar->debug.reg_addr;
823 mutex_unlock(&ar->conf_mutex);
824
825 len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);
826
827 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
828}
829
830static ssize_t ath10k_reg_addr_write(struct file *file,
831 const char __user *user_buf,
832 size_t count, loff_t *ppos)
833{
834 struct ath10k *ar = file->private_data;
835 u32 reg_addr;
836 int ret;
837
838 ret = kstrtou32_from_user(user_buf, count, 0, &reg_addr);
839 if (ret)
840 return ret;
841
842 if (!IS_ALIGNED(reg_addr, 4))
843 return -EFAULT;
844
845 mutex_lock(&ar->conf_mutex);
846 ar->debug.reg_addr = reg_addr;
847 mutex_unlock(&ar->conf_mutex);
848
849 return count;
850}
851
852static const struct file_operations fops_reg_addr = {
853 .read = ath10k_reg_addr_read,
854 .write = ath10k_reg_addr_write,
855 .open = simple_open,
856 .owner = THIS_MODULE,
857 .llseek = default_llseek,
858};
859
860static ssize_t ath10k_reg_value_read(struct file *file,
861 char __user *user_buf,
862 size_t count, loff_t *ppos)
863{
864 struct ath10k *ar = file->private_data;
865 u8 buf[48];
866 unsigned int len;
867 u32 reg_addr, reg_val;
868 int ret;
869
870 mutex_lock(&ar->conf_mutex);
871
872 if (ar->state != ATH10K_STATE_ON &&
873 ar->state != ATH10K_STATE_UTF) {
874 ret = -ENETDOWN;
875 goto exit;
876 }
877
878 reg_addr = ar->debug.reg_addr;
879
880 reg_val = ath10k_hif_read32(ar, reg_addr);
881 len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);
882
883 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
884
885exit:
886 mutex_unlock(&ar->conf_mutex);
887
888 return ret;
889}
890
891static ssize_t ath10k_reg_value_write(struct file *file,
892 const char __user *user_buf,
893 size_t count, loff_t *ppos)
894{
895 struct ath10k *ar = file->private_data;
896 u32 reg_addr, reg_val;
897 int ret;
898
899 mutex_lock(&ar->conf_mutex);
900
901 if (ar->state != ATH10K_STATE_ON &&
902 ar->state != ATH10K_STATE_UTF) {
903 ret = -ENETDOWN;
904 goto exit;
905 }
906
907 reg_addr = ar->debug.reg_addr;
908
909 ret = kstrtou32_from_user(user_buf, count, 0, &reg_val);
910 if (ret)
911 goto exit;
912
913 ath10k_hif_write32(ar, reg_addr, reg_val);
914
915 ret = count;
916
917exit:
918 mutex_unlock(&ar->conf_mutex);
919
920 return ret;
921}
922
923static const struct file_operations fops_reg_value = {
924 .read = ath10k_reg_value_read,
925 .write = ath10k_reg_value_write,
926 .open = simple_open,
927 .owner = THIS_MODULE,
928 .llseek = default_llseek,
929};
930
Yanbo Li9f65ad22014-11-25 12:24:48 +0200931static ssize_t ath10k_mem_value_read(struct file *file,
932 char __user *user_buf,
933 size_t count, loff_t *ppos)
934{
935 struct ath10k *ar = file->private_data;
936 u8 *buf;
937 int ret;
938
939 if (*ppos < 0)
940 return -EINVAL;
941
942 if (!count)
943 return 0;
944
945 mutex_lock(&ar->conf_mutex);
946
947 buf = vmalloc(count);
948 if (!buf) {
949 ret = -ENOMEM;
950 goto exit;
951 }
952
953 if (ar->state != ATH10K_STATE_ON &&
954 ar->state != ATH10K_STATE_UTF) {
955 ret = -ENETDOWN;
956 goto exit;
957 }
958
959 ret = ath10k_hif_diag_read(ar, *ppos, buf, count);
960 if (ret) {
961 ath10k_warn(ar, "failed to read address 0x%08x via diagnose window fnrom debugfs: %d\n",
962 (u32)(*ppos), ret);
963 goto exit;
964 }
965
966 ret = copy_to_user(user_buf, buf, count);
967 if (ret) {
968 ret = -EFAULT;
969 goto exit;
970 }
971
972 count -= ret;
973 *ppos += count;
974 ret = count;
975
976exit:
977 vfree(buf);
978 mutex_unlock(&ar->conf_mutex);
979
980 return ret;
981}
982
983static ssize_t ath10k_mem_value_write(struct file *file,
984 const char __user *user_buf,
985 size_t count, loff_t *ppos)
986{
987 struct ath10k *ar = file->private_data;
988 u8 *buf;
989 int ret;
990
991 if (*ppos < 0)
992 return -EINVAL;
993
994 if (!count)
995 return 0;
996
997 mutex_lock(&ar->conf_mutex);
998
999 buf = vmalloc(count);
1000 if (!buf) {
1001 ret = -ENOMEM;
1002 goto exit;
1003 }
1004
1005 if (ar->state != ATH10K_STATE_ON &&
1006 ar->state != ATH10K_STATE_UTF) {
1007 ret = -ENETDOWN;
1008 goto exit;
1009 }
1010
1011 ret = copy_from_user(buf, user_buf, count);
1012 if (ret) {
1013 ret = -EFAULT;
1014 goto exit;
1015 }
1016
1017 ret = ath10k_hif_diag_write(ar, *ppos, buf, count);
1018 if (ret) {
1019 ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",
1020 (u32)(*ppos), ret);
1021 goto exit;
1022 }
1023
1024 *ppos += count;
1025 ret = count;
1026
1027exit:
1028 vfree(buf);
1029 mutex_unlock(&ar->conf_mutex);
1030
1031 return ret;
1032}
1033
1034static const struct file_operations fops_mem_value = {
1035 .read = ath10k_mem_value_read,
1036 .write = ath10k_mem_value_write,
1037 .open = simple_open,
1038 .owner = THIS_MODULE,
1039 .llseek = default_llseek,
1040};
1041
Kalle Valoa3d135e2013-09-03 11:44:10 +03001042static int ath10k_debug_htt_stats_req(struct ath10k *ar)
1043{
1044 u64 cookie;
1045 int ret;
1046
1047 lockdep_assert_held(&ar->conf_mutex);
1048
1049 if (ar->debug.htt_stats_mask == 0)
1050 /* htt stats are disabled */
1051 return 0;
1052
1053 if (ar->state != ATH10K_STATE_ON)
1054 return 0;
1055
1056 cookie = get_jiffies_64();
1057
1058 ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask,
1059 cookie);
1060 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001061 ath10k_warn(ar, "failed to send htt stats request: %d\n", ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001062 return ret;
1063 }
1064
1065 queue_delayed_work(ar->workqueue, &ar->debug.htt_stats_dwork,
1066 msecs_to_jiffies(ATH10K_DEBUG_HTT_STATS_INTERVAL));
1067
1068 return 0;
1069}
1070
1071static void ath10k_debug_htt_stats_dwork(struct work_struct *work)
1072{
1073 struct ath10k *ar = container_of(work, struct ath10k,
1074 debug.htt_stats_dwork.work);
1075
1076 mutex_lock(&ar->conf_mutex);
1077
1078 ath10k_debug_htt_stats_req(ar);
1079
1080 mutex_unlock(&ar->conf_mutex);
1081}
1082
1083static ssize_t ath10k_read_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001084 char __user *user_buf,
1085 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001086{
1087 struct ath10k *ar = file->private_data;
1088 char buf[32];
1089 unsigned int len;
1090
1091 len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask);
1092
1093 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1094}
1095
1096static ssize_t ath10k_write_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001097 const char __user *user_buf,
1098 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001099{
1100 struct ath10k *ar = file->private_data;
1101 unsigned long mask;
1102 int ret;
1103
1104 ret = kstrtoul_from_user(user_buf, count, 0, &mask);
1105 if (ret)
1106 return ret;
1107
1108 /* max 8 bit masks (for now) */
1109 if (mask > 0xff)
1110 return -E2BIG;
1111
1112 mutex_lock(&ar->conf_mutex);
1113
1114 ar->debug.htt_stats_mask = mask;
1115
1116 ret = ath10k_debug_htt_stats_req(ar);
1117 if (ret)
1118 goto out;
1119
1120 ret = count;
1121
1122out:
1123 mutex_unlock(&ar->conf_mutex);
1124
1125 return ret;
1126}
1127
1128static const struct file_operations fops_htt_stats_mask = {
1129 .read = ath10k_read_htt_stats_mask,
1130 .write = ath10k_write_htt_stats_mask,
1131 .open = simple_open,
1132 .owner = THIS_MODULE,
1133 .llseek = default_llseek,
1134};
1135
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001136static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
1137 char __user *user_buf,
1138 size_t count, loff_t *ppos)
1139{
1140 struct ath10k *ar = file->private_data;
1141 char buf[64];
1142 u8 amsdu = 3, ampdu = 64;
1143 unsigned int len;
1144
1145 mutex_lock(&ar->conf_mutex);
1146
David Liuccec9032015-07-24 20:25:32 +03001147 amsdu = ar->htt.max_num_amsdu;
1148 ampdu = ar->htt.max_num_ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001149 mutex_unlock(&ar->conf_mutex);
1150
1151 len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
1152
1153 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1154}
1155
1156static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
1157 const char __user *user_buf,
1158 size_t count, loff_t *ppos)
1159{
1160 struct ath10k *ar = file->private_data;
1161 int res;
1162 char buf[64];
1163 unsigned int amsdu, ampdu;
1164
1165 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
1166
1167 /* make sure that buf is null terminated */
1168 buf[sizeof(buf) - 1] = 0;
1169
1170 res = sscanf(buf, "%u %u", &amsdu, &ampdu);
1171
1172 if (res != 2)
1173 return -EINVAL;
1174
1175 mutex_lock(&ar->conf_mutex);
1176
1177 res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
1178 if (res)
1179 goto out;
1180
1181 res = count;
David Liuccec9032015-07-24 20:25:32 +03001182 ar->htt.max_num_amsdu = amsdu;
1183 ar->htt.max_num_ampdu = ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001184
1185out:
1186 mutex_unlock(&ar->conf_mutex);
1187 return res;
1188}
1189
1190static const struct file_operations fops_htt_max_amsdu_ampdu = {
1191 .read = ath10k_read_htt_max_amsdu_ampdu,
1192 .write = ath10k_write_htt_max_amsdu_ampdu,
1193 .open = simple_open,
1194 .owner = THIS_MODULE,
1195 .llseek = default_llseek,
1196};
1197
Kalle Valof118a3e2014-01-03 12:59:31 +02001198static ssize_t ath10k_read_fw_dbglog(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001199 char __user *user_buf,
1200 size_t count, loff_t *ppos)
Kalle Valof118a3e2014-01-03 12:59:31 +02001201{
1202 struct ath10k *ar = file->private_data;
1203 unsigned int len;
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301204 char buf[64];
Kalle Valof118a3e2014-01-03 12:59:31 +02001205
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301206 len = scnprintf(buf, sizeof(buf), "0x%08x %u\n",
1207 ar->debug.fw_dbglog_mask, ar->debug.fw_dbglog_level);
Kalle Valof118a3e2014-01-03 12:59:31 +02001208
1209 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1210}
1211
1212static ssize_t ath10k_write_fw_dbglog(struct file *file,
1213 const char __user *user_buf,
1214 size_t count, loff_t *ppos)
1215{
1216 struct ath10k *ar = file->private_data;
Kalle Valof118a3e2014-01-03 12:59:31 +02001217 int ret;
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301218 char buf[64];
1219 unsigned int log_level, mask;
Kalle Valof118a3e2014-01-03 12:59:31 +02001220
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301221 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
1222
1223 /* make sure that buf is null terminated */
1224 buf[sizeof(buf) - 1] = 0;
1225
1226 ret = sscanf(buf, "%x %u", &mask, &log_level);
1227
1228 if (!ret)
1229 return -EINVAL;
1230
1231 if (ret == 1)
1232 /* default if user did not specify */
1233 log_level = ATH10K_DBGLOG_LEVEL_WARN;
Kalle Valof118a3e2014-01-03 12:59:31 +02001234
1235 mutex_lock(&ar->conf_mutex);
1236
1237 ar->debug.fw_dbglog_mask = mask;
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301238 ar->debug.fw_dbglog_level = log_level;
Kalle Valof118a3e2014-01-03 12:59:31 +02001239
1240 if (ar->state == ATH10K_STATE_ON) {
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301241 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1242 ar->debug.fw_dbglog_level);
Kalle Valof118a3e2014-01-03 12:59:31 +02001243 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001244 ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n",
Kalle Valof118a3e2014-01-03 12:59:31 +02001245 ret);
1246 goto exit;
1247 }
1248 }
1249
1250 ret = count;
1251
1252exit:
1253 mutex_unlock(&ar->conf_mutex);
1254
1255 return ret;
1256}
1257
Ben Greear6cddcc72014-09-29 14:41:46 +03001258/* TODO: Would be nice to always support ethtool stats, would need to
1259 * move the stats storage out of ath10k_debug, or always have ath10k_debug
1260 * struct available..
1261 */
1262
1263/* This generally cooresponds to the debugfs fw_stats file */
1264static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
1265 "tx_pkts_nic",
1266 "tx_bytes_nic",
1267 "rx_pkts_nic",
1268 "rx_bytes_nic",
1269 "d_noise_floor",
1270 "d_cycle_count",
1271 "d_phy_error",
1272 "d_rts_bad",
1273 "d_rts_good",
1274 "d_tx_power", /* in .5 dbM I think */
1275 "d_rx_crc_err", /* fcs_bad */
1276 "d_no_beacon",
1277 "d_tx_mpdus_queued",
1278 "d_tx_msdu_queued",
1279 "d_tx_msdu_dropped",
1280 "d_local_enqued",
1281 "d_local_freed",
1282 "d_tx_ppdu_hw_queued",
1283 "d_tx_ppdu_reaped",
1284 "d_tx_fifo_underrun",
1285 "d_tx_ppdu_abort",
1286 "d_tx_mpdu_requed",
1287 "d_tx_excessive_retries",
1288 "d_tx_hw_rate",
1289 "d_tx_dropped_sw_retries",
1290 "d_tx_illegal_rate",
1291 "d_tx_continuous_xretries",
1292 "d_tx_timeout",
1293 "d_tx_mpdu_txop_limit",
1294 "d_pdev_resets",
1295 "d_rx_mid_ppdu_route_change",
1296 "d_rx_status",
1297 "d_rx_extra_frags_ring0",
1298 "d_rx_extra_frags_ring1",
1299 "d_rx_extra_frags_ring2",
1300 "d_rx_extra_frags_ring3",
1301 "d_rx_msdu_htt",
1302 "d_rx_mpdu_htt",
1303 "d_rx_msdu_stack",
1304 "d_rx_mpdu_stack",
1305 "d_rx_phy_err",
1306 "d_rx_phy_err_drops",
1307 "d_rx_mpdu_errors", /* FCS, MIC, ENC */
1308 "d_fw_crash_count",
1309 "d_fw_warm_reset_count",
1310 "d_fw_cold_reset_count",
1311};
1312
1313#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
1314
1315void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
1316 struct ieee80211_vif *vif,
1317 u32 sset, u8 *data)
1318{
1319 if (sset == ETH_SS_STATS)
1320 memcpy(data, *ath10k_gstrings_stats,
1321 sizeof(ath10k_gstrings_stats));
1322}
1323
1324int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
1325 struct ieee80211_vif *vif, int sset)
1326{
1327 if (sset == ETH_SS_STATS)
1328 return ATH10K_SSTATS_LEN;
1329
1330 return 0;
1331}
1332
1333void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
1334 struct ieee80211_vif *vif,
1335 struct ethtool_stats *stats, u64 *data)
1336{
1337 struct ath10k *ar = hw->priv;
1338 static const struct ath10k_fw_stats_pdev zero_stats = {};
1339 const struct ath10k_fw_stats_pdev *pdev_stats;
1340 int i = 0, ret;
1341
1342 mutex_lock(&ar->conf_mutex);
1343
1344 if (ar->state == ATH10K_STATE_ON) {
1345 ret = ath10k_debug_fw_stats_request(ar);
1346 if (ret) {
1347 /* just print a warning and try to use older results */
1348 ath10k_warn(ar,
1349 "failed to get fw stats for ethtool: %d\n",
1350 ret);
1351 }
1352 }
1353
1354 pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,
1355 struct ath10k_fw_stats_pdev,
1356 list);
1357 if (!pdev_stats) {
1358 /* no results available so just return zeroes */
1359 pdev_stats = &zero_stats;
1360 }
1361
1362 spin_lock_bh(&ar->data_lock);
1363
1364 data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
1365 data[i++] = 0; /* tx bytes */
1366 data[i++] = pdev_stats->htt_mpdus;
1367 data[i++] = 0; /* rx bytes */
1368 data[i++] = pdev_stats->ch_noise_floor;
1369 data[i++] = pdev_stats->cycle_count;
1370 data[i++] = pdev_stats->phy_err_count;
1371 data[i++] = pdev_stats->rts_bad;
1372 data[i++] = pdev_stats->rts_good;
1373 data[i++] = pdev_stats->chan_tx_power;
1374 data[i++] = pdev_stats->fcs_bad;
1375 data[i++] = pdev_stats->no_beacons;
1376 data[i++] = pdev_stats->mpdu_enqued;
1377 data[i++] = pdev_stats->msdu_enqued;
1378 data[i++] = pdev_stats->wmm_drop;
1379 data[i++] = pdev_stats->local_enqued;
1380 data[i++] = pdev_stats->local_freed;
1381 data[i++] = pdev_stats->hw_queued;
1382 data[i++] = pdev_stats->hw_reaped;
1383 data[i++] = pdev_stats->underrun;
1384 data[i++] = pdev_stats->tx_abort;
1385 data[i++] = pdev_stats->mpdus_requed;
1386 data[i++] = pdev_stats->tx_ko;
1387 data[i++] = pdev_stats->data_rc;
1388 data[i++] = pdev_stats->sw_retry_failure;
1389 data[i++] = pdev_stats->illgl_rate_phy_err;
1390 data[i++] = pdev_stats->pdev_cont_xretry;
1391 data[i++] = pdev_stats->pdev_tx_timeout;
1392 data[i++] = pdev_stats->txop_ovf;
1393 data[i++] = pdev_stats->pdev_resets;
1394 data[i++] = pdev_stats->mid_ppdu_route_change;
1395 data[i++] = pdev_stats->status_rcvd;
1396 data[i++] = pdev_stats->r0_frags;
1397 data[i++] = pdev_stats->r1_frags;
1398 data[i++] = pdev_stats->r2_frags;
1399 data[i++] = pdev_stats->r3_frags;
1400 data[i++] = pdev_stats->htt_msdus;
1401 data[i++] = pdev_stats->htt_mpdus;
1402 data[i++] = pdev_stats->loc_msdus;
1403 data[i++] = pdev_stats->loc_mpdus;
1404 data[i++] = pdev_stats->phy_errs;
1405 data[i++] = pdev_stats->phy_err_drop;
1406 data[i++] = pdev_stats->mpdu_errs;
1407 data[i++] = ar->stats.fw_crash_counter;
1408 data[i++] = ar->stats.fw_warm_reset_counter;
1409 data[i++] = ar->stats.fw_cold_reset_counter;
1410
1411 spin_unlock_bh(&ar->data_lock);
1412
1413 mutex_unlock(&ar->conf_mutex);
1414
1415 WARN_ON(i != ATH10K_SSTATS_LEN);
1416}
1417
Kalle Valof118a3e2014-01-03 12:59:31 +02001418static const struct file_operations fops_fw_dbglog = {
1419 .read = ath10k_read_fw_dbglog,
1420 .write = ath10k_write_fw_dbglog,
1421 .open = simple_open,
1422 .owner = THIS_MODULE,
1423 .llseek = default_llseek,
1424};
1425
Kalle Valo7869b4f2014-09-24 14:16:58 +03001426static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
1427{
1428 struct ath10k *ar = inode->i_private;
1429 void *buf;
1430 u32 hi_addr;
1431 __le32 addr;
1432 int ret;
1433
1434 mutex_lock(&ar->conf_mutex);
1435
1436 if (ar->state != ATH10K_STATE_ON &&
1437 ar->state != ATH10K_STATE_UTF) {
1438 ret = -ENETDOWN;
1439 goto err;
1440 }
1441
1442 buf = vmalloc(QCA988X_CAL_DATA_LEN);
1443 if (!buf) {
1444 ret = -ENOMEM;
1445 goto err;
1446 }
1447
1448 hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
1449
1450 ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
1451 if (ret) {
1452 ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret);
1453 goto err_vfree;
1454 }
1455
1456 ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
1457 QCA988X_CAL_DATA_LEN);
1458 if (ret) {
1459 ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
1460 goto err_vfree;
1461 }
1462
1463 file->private_data = buf;
1464
1465 mutex_unlock(&ar->conf_mutex);
1466
1467 return 0;
1468
1469err_vfree:
1470 vfree(buf);
1471
1472err:
1473 mutex_unlock(&ar->conf_mutex);
1474
1475 return ret;
1476}
1477
1478static ssize_t ath10k_debug_cal_data_read(struct file *file,
1479 char __user *user_buf,
1480 size_t count, loff_t *ppos)
1481{
1482 void *buf = file->private_data;
1483
1484 return simple_read_from_buffer(user_buf, count, ppos,
1485 buf, QCA988X_CAL_DATA_LEN);
1486}
1487
1488static int ath10k_debug_cal_data_release(struct inode *inode,
1489 struct file *file)
1490{
1491 vfree(file->private_data);
1492
1493 return 0;
1494}
1495
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05301496static ssize_t ath10k_write_ani_enable(struct file *file,
1497 const char __user *user_buf,
1498 size_t count, loff_t *ppos)
1499{
1500 struct ath10k *ar = file->private_data;
1501 int ret;
1502 u8 enable;
1503
1504 if (kstrtou8_from_user(user_buf, count, 0, &enable))
1505 return -EINVAL;
1506
1507 mutex_lock(&ar->conf_mutex);
1508
1509 if (ar->ani_enabled == enable) {
1510 ret = count;
1511 goto exit;
1512 }
1513
1514 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->ani_enable,
1515 enable);
1516 if (ret) {
1517 ath10k_warn(ar, "ani_enable failed from debugfs: %d\n", ret);
1518 goto exit;
1519 }
1520 ar->ani_enabled = enable;
1521
1522 ret = count;
1523
1524exit:
1525 mutex_unlock(&ar->conf_mutex);
1526
1527 return ret;
1528}
1529
1530static ssize_t ath10k_read_ani_enable(struct file *file, char __user *user_buf,
1531 size_t count, loff_t *ppos)
1532{
1533 struct ath10k *ar = file->private_data;
1534 int len = 0;
1535 char buf[32];
1536
1537 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
1538 ar->ani_enabled);
1539
1540 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1541}
1542
1543static const struct file_operations fops_ani_enable = {
1544 .read = ath10k_read_ani_enable,
1545 .write = ath10k_write_ani_enable,
1546 .open = simple_open,
1547 .owner = THIS_MODULE,
1548 .llseek = default_llseek,
1549};
1550
Kalle Valo7869b4f2014-09-24 14:16:58 +03001551static const struct file_operations fops_cal_data = {
1552 .open = ath10k_debug_cal_data_open,
1553 .read = ath10k_debug_cal_data_read,
1554 .release = ath10k_debug_cal_data_release,
1555 .owner = THIS_MODULE,
1556 .llseek = default_llseek,
1557};
1558
Peter Oha7bd3e92014-12-02 13:07:14 +02001559static ssize_t ath10k_read_nf_cal_period(struct file *file,
1560 char __user *user_buf,
1561 size_t count, loff_t *ppos)
1562{
1563 struct ath10k *ar = file->private_data;
1564 unsigned int len;
1565 char buf[32];
1566
1567 len = scnprintf(buf, sizeof(buf), "%d\n",
1568 ar->debug.nf_cal_period);
1569
1570 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1571}
1572
1573static ssize_t ath10k_write_nf_cal_period(struct file *file,
1574 const char __user *user_buf,
1575 size_t count, loff_t *ppos)
1576{
1577 struct ath10k *ar = file->private_data;
1578 unsigned long period;
1579 int ret;
1580
1581 ret = kstrtoul_from_user(user_buf, count, 0, &period);
1582 if (ret)
1583 return ret;
1584
1585 if (period > WMI_PDEV_PARAM_CAL_PERIOD_MAX)
1586 return -EINVAL;
1587
1588 /* there's no way to switch back to the firmware default */
1589 if (period == 0)
1590 return -EINVAL;
1591
1592 mutex_lock(&ar->conf_mutex);
1593
1594 ar->debug.nf_cal_period = period;
1595
1596 if (ar->state != ATH10K_STATE_ON) {
1597 /* firmware is not running, nothing else to do */
1598 ret = count;
1599 goto exit;
1600 }
1601
1602 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->cal_period,
1603 ar->debug.nf_cal_period);
1604 if (ret) {
1605 ath10k_warn(ar, "cal period cfg failed from debugfs: %d\n",
1606 ret);
1607 goto exit;
1608 }
1609
1610 ret = count;
1611
1612exit:
1613 mutex_unlock(&ar->conf_mutex);
1614
1615 return ret;
1616}
1617
1618static const struct file_operations fops_nf_cal_period = {
1619 .read = ath10k_read_nf_cal_period,
1620 .write = ath10k_write_nf_cal_period,
1621 .open = simple_open,
1622 .owner = THIS_MODULE,
1623 .llseek = default_llseek,
1624};
1625
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001626#define ATH10K_TPC_CONFIG_BUF_SIZE (1024 * 1024)
1627
1628static int ath10k_debug_tpc_stats_request(struct ath10k *ar)
1629{
1630 int ret;
1631 unsigned long time_left;
1632
1633 lockdep_assert_held(&ar->conf_mutex);
1634
1635 reinit_completion(&ar->debug.tpc_complete);
1636
1637 ret = ath10k_wmi_pdev_get_tpc_config(ar, WMI_TPC_CONFIG_PARAM);
1638 if (ret) {
1639 ath10k_warn(ar, "failed to request tpc config: %d\n", ret);
1640 return ret;
1641 }
1642
1643 time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
1644 1 * HZ);
1645 if (time_left == 0)
1646 return -ETIMEDOUT;
1647
1648 return 0;
1649}
1650
1651void ath10k_debug_tpc_stats_process(struct ath10k *ar,
1652 struct ath10k_tpc_stats *tpc_stats)
1653{
1654 spin_lock_bh(&ar->data_lock);
1655
1656 kfree(ar->debug.tpc_stats);
1657 ar->debug.tpc_stats = tpc_stats;
1658 complete(&ar->debug.tpc_complete);
1659
1660 spin_unlock_bh(&ar->data_lock);
1661}
1662
1663static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
1664 unsigned int j, char *buf, unsigned int *len)
1665{
1666 unsigned int i, buf_len;
1667 static const char table_str[][5] = { "CDD",
1668 "STBC",
1669 "TXBF" };
1670 static const char pream_str[][6] = { "CCK",
1671 "OFDM",
1672 "HT20",
1673 "HT40",
1674 "VHT20",
1675 "VHT40",
1676 "VHT80",
1677 "HTCUP" };
1678
1679 buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1680 *len += scnprintf(buf + *len, buf_len - *len,
1681 "********************************\n");
1682 *len += scnprintf(buf + *len, buf_len - *len,
1683 "******************* %s POWER TABLE ****************\n",
1684 table_str[j]);
1685 *len += scnprintf(buf + *len, buf_len - *len,
1686 "********************************\n");
1687 *len += scnprintf(buf + *len, buf_len - *len,
1688 "No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3\n");
1689
1690 for (i = 0; i < tpc_stats->rate_max; i++) {
1691 *len += scnprintf(buf + *len, buf_len - *len,
1692 "%8d %s 0x%2x %s\n", i,
1693 pream_str[tpc_stats->tpc_table[j].pream_idx[i]],
1694 tpc_stats->tpc_table[j].rate_code[i],
1695 tpc_stats->tpc_table[j].tpc_value[i]);
1696 }
1697
1698 *len += scnprintf(buf + *len, buf_len - *len,
1699 "***********************************\n");
1700}
1701
1702static void ath10k_tpc_stats_fill(struct ath10k *ar,
1703 struct ath10k_tpc_stats *tpc_stats,
1704 char *buf)
1705{
1706 unsigned int len, j, buf_len;
1707
1708 len = 0;
1709 buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1710
1711 spin_lock_bh(&ar->data_lock);
1712
1713 if (!tpc_stats) {
1714 ath10k_warn(ar, "failed to get tpc stats\n");
1715 goto unlock;
1716 }
1717
1718 len += scnprintf(buf + len, buf_len - len, "\n");
1719 len += scnprintf(buf + len, buf_len - len,
1720 "*************************************\n");
1721 len += scnprintf(buf + len, buf_len - len,
1722 "TPC config for channel %4d mode %d\n",
1723 tpc_stats->chan_freq,
1724 tpc_stats->phy_mode);
1725 len += scnprintf(buf + len, buf_len - len,
1726 "*************************************\n");
1727 len += scnprintf(buf + len, buf_len - len,
1728 "CTL = 0x%2x Reg. Domain = %2d\n",
1729 tpc_stats->ctl,
1730 tpc_stats->reg_domain);
1731 len += scnprintf(buf + len, buf_len - len,
1732 "Antenna Gain = %2d Reg. Max Antenna Gain = %2d\n",
1733 tpc_stats->twice_antenna_gain,
1734 tpc_stats->twice_antenna_reduction);
1735 len += scnprintf(buf + len, buf_len - len,
1736 "Power Limit = %2d Reg. Max Power = %2d\n",
1737 tpc_stats->power_limit,
1738 tpc_stats->twice_max_rd_power / 2);
1739 len += scnprintf(buf + len, buf_len - len,
1740 "Num tx chains = %2d Num supported rates = %2d\n",
1741 tpc_stats->num_tx_chain,
1742 tpc_stats->rate_max);
1743
1744 for (j = 0; j < tpc_stats->num_tx_chain ; j++) {
1745 switch (j) {
1746 case WMI_TPC_TABLE_TYPE_CDD:
1747 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1748 len += scnprintf(buf + len, buf_len - len,
1749 "CDD not supported\n");
1750 break;
1751 }
1752
1753 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1754 break;
1755 case WMI_TPC_TABLE_TYPE_STBC:
1756 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1757 len += scnprintf(buf + len, buf_len - len,
1758 "STBC not supported\n");
1759 break;
1760 }
1761
1762 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1763 break;
1764 case WMI_TPC_TABLE_TYPE_TXBF:
1765 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1766 len += scnprintf(buf + len, buf_len - len,
1767 "TXBF not supported\n***************************\n");
1768 break;
1769 }
1770
1771 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1772 break;
1773 default:
1774 len += scnprintf(buf + len, buf_len - len,
1775 "Invalid Type\n");
1776 break;
1777 }
1778 }
1779
1780unlock:
1781 spin_unlock_bh(&ar->data_lock);
1782
1783 if (len >= buf_len)
1784 buf[len - 1] = 0;
1785 else
1786 buf[len] = 0;
1787}
1788
1789static int ath10k_tpc_stats_open(struct inode *inode, struct file *file)
1790{
1791 struct ath10k *ar = inode->i_private;
1792 void *buf = NULL;
1793 int ret;
1794
1795 mutex_lock(&ar->conf_mutex);
1796
1797 if (ar->state != ATH10K_STATE_ON) {
1798 ret = -ENETDOWN;
1799 goto err_unlock;
1800 }
1801
1802 buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
1803 if (!buf) {
1804 ret = -ENOMEM;
1805 goto err_unlock;
1806 }
1807
1808 ret = ath10k_debug_tpc_stats_request(ar);
1809 if (ret) {
1810 ath10k_warn(ar, "failed to request tpc config stats: %d\n",
1811 ret);
1812 goto err_free;
1813 }
1814
1815 ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
1816 file->private_data = buf;
1817
1818 mutex_unlock(&ar->conf_mutex);
1819 return 0;
1820
1821err_free:
1822 vfree(buf);
1823
1824err_unlock:
1825 mutex_unlock(&ar->conf_mutex);
1826 return ret;
1827}
1828
1829static int ath10k_tpc_stats_release(struct inode *inode, struct file *file)
1830{
1831 vfree(file->private_data);
1832
1833 return 0;
1834}
1835
1836static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf,
1837 size_t count, loff_t *ppos)
1838{
1839 const char *buf = file->private_data;
1840 unsigned int len = strlen(buf);
1841
1842 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1843}
1844
1845static const struct file_operations fops_tpc_stats = {
1846 .open = ath10k_tpc_stats_open,
1847 .release = ath10k_tpc_stats_release,
1848 .read = ath10k_tpc_stats_read,
1849 .owner = THIS_MODULE,
1850 .llseek = default_llseek,
1851};
1852
Kalle Valodb66ea02013-09-03 11:44:03 +03001853int ath10k_debug_start(struct ath10k *ar)
1854{
Kalle Valoa3d135e2013-09-03 11:44:10 +03001855 int ret;
1856
Kalle Valo60631c52013-10-08 21:45:25 +03001857 lockdep_assert_held(&ar->conf_mutex);
1858
Kalle Valoa3d135e2013-09-03 11:44:10 +03001859 ret = ath10k_debug_htt_stats_req(ar);
1860 if (ret)
1861 /* continue normally anyway, this isn't serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001862 ath10k_warn(ar, "failed to start htt stats workqueue: %d\n",
1863 ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001864
Kalle Valof118a3e2014-01-03 12:59:31 +02001865 if (ar->debug.fw_dbglog_mask) {
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301866 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1867 ATH10K_DBGLOG_LEVEL_WARN);
Kalle Valof118a3e2014-01-03 12:59:31 +02001868 if (ret)
1869 /* not serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001870 ath10k_warn(ar, "failed to enable dbglog during start: %d",
Kalle Valof118a3e2014-01-03 12:59:31 +02001871 ret);
1872 }
1873
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001874 if (ar->debug.pktlog_filter) {
1875 ret = ath10k_wmi_pdev_pktlog_enable(ar,
1876 ar->debug.pktlog_filter);
1877 if (ret)
1878 /* not serious */
1879 ath10k_warn(ar,
1880 "failed to enable pktlog filter %x: %d\n",
1881 ar->debug.pktlog_filter, ret);
1882 } else {
1883 ret = ath10k_wmi_pdev_pktlog_disable(ar);
1884 if (ret)
1885 /* not serious */
1886 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
1887 }
1888
Peter Oha7bd3e92014-12-02 13:07:14 +02001889 if (ar->debug.nf_cal_period) {
1890 ret = ath10k_wmi_pdev_set_param(ar,
1891 ar->wmi.pdev_param->cal_period,
1892 ar->debug.nf_cal_period);
1893 if (ret)
1894 /* not serious */
1895 ath10k_warn(ar, "cal period cfg failed from debug start: %d\n",
1896 ret);
1897 }
1898
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001899 return ret;
Kalle Valodb66ea02013-09-03 11:44:03 +03001900}
1901
1902void ath10k_debug_stop(struct ath10k *ar)
1903{
Kalle Valo60631c52013-10-08 21:45:25 +03001904 lockdep_assert_held(&ar->conf_mutex);
1905
1906 /* Must not use _sync to avoid deadlock, we do that in
1907 * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid
1908 * warning from del_timer(). */
1909 if (ar->debug.htt_stats_mask != 0)
1910 cancel_delayed_work(&ar->debug.htt_stats_dwork);
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001911
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001912 ath10k_wmi_pdev_pktlog_disable(ar);
Kalle Valodb66ea02013-09-03 11:44:03 +03001913}
1914
Janusz Dziedzic9702c682013-11-20 09:59:41 +02001915static ssize_t ath10k_write_simulate_radar(struct file *file,
1916 const char __user *user_buf,
1917 size_t count, loff_t *ppos)
1918{
1919 struct ath10k *ar = file->private_data;
1920
1921 ieee80211_radar_detected(ar->hw);
1922
1923 return count;
1924}
1925
1926static const struct file_operations fops_simulate_radar = {
1927 .write = ath10k_write_simulate_radar,
1928 .open = simple_open,
1929 .owner = THIS_MODULE,
1930 .llseek = default_llseek,
1931};
1932
1933#define ATH10K_DFS_STAT(s, p) (\
1934 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
1935 ar->debug.dfs_stats.p))
1936
1937#define ATH10K_DFS_POOL_STAT(s, p) (\
1938 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
1939 ar->debug.dfs_pool_stats.p))
1940
1941static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf,
1942 size_t count, loff_t *ppos)
1943{
1944 int retval = 0, len = 0;
1945 const int size = 8000;
1946 struct ath10k *ar = file->private_data;
1947 char *buf;
1948
1949 buf = kzalloc(size, GFP_KERNEL);
1950 if (buf == NULL)
1951 return -ENOMEM;
1952
1953 if (!ar->dfs_detector) {
1954 len += scnprintf(buf + len, size - len, "DFS not enabled\n");
1955 goto exit;
1956 }
1957
1958 ar->debug.dfs_pool_stats =
1959 ar->dfs_detector->get_stats(ar->dfs_detector);
1960
1961 len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");
1962
1963 ATH10K_DFS_STAT("reported phy errors", phy_errors);
1964 ATH10K_DFS_STAT("pulse events reported", pulses_total);
1965 ATH10K_DFS_STAT("DFS pulses detected", pulses_detected);
1966 ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded);
1967 ATH10K_DFS_STAT("Radars detected", radar_detected);
1968
1969 len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");
1970 ATH10K_DFS_POOL_STAT("Pool references", pool_reference);
1971 ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated);
1972 ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error);
1973 ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used);
1974 ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated);
1975 ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error);
1976 ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used);
1977
1978exit:
1979 if (len > size)
1980 len = size;
1981
1982 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1983 kfree(buf);
1984
1985 return retval;
1986}
1987
1988static const struct file_operations fops_dfs_stats = {
1989 .read = ath10k_read_dfs_stats,
1990 .open = simple_open,
1991 .owner = THIS_MODULE,
1992 .llseek = default_llseek,
1993};
1994
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001995static ssize_t ath10k_write_pktlog_filter(struct file *file,
1996 const char __user *ubuf,
1997 size_t count, loff_t *ppos)
1998{
1999 struct ath10k *ar = file->private_data;
2000 u32 filter;
2001 int ret;
2002
2003 if (kstrtouint_from_user(ubuf, count, 0, &filter))
2004 return -EINVAL;
2005
2006 mutex_lock(&ar->conf_mutex);
2007
2008 if (ar->state != ATH10K_STATE_ON) {
2009 ar->debug.pktlog_filter = filter;
2010 ret = count;
2011 goto out;
2012 }
2013
2014 if (filter && (filter != ar->debug.pktlog_filter)) {
2015 ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
2016 if (ret) {
2017 ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
2018 ar->debug.pktlog_filter, ret);
2019 goto out;
2020 }
2021 } else {
2022 ret = ath10k_wmi_pdev_pktlog_disable(ar);
2023 if (ret) {
2024 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
2025 goto out;
2026 }
2027 }
2028
2029 ar->debug.pktlog_filter = filter;
2030 ret = count;
2031
2032out:
2033 mutex_unlock(&ar->conf_mutex);
2034 return ret;
2035}
2036
2037static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf,
2038 size_t count, loff_t *ppos)
2039{
2040 char buf[32];
2041 struct ath10k *ar = file->private_data;
2042 int len = 0;
2043
2044 mutex_lock(&ar->conf_mutex);
2045 len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
2046 ar->debug.pktlog_filter);
2047 mutex_unlock(&ar->conf_mutex);
2048
2049 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2050}
2051
2052static const struct file_operations fops_pktlog_filter = {
2053 .read = ath10k_read_pktlog_filter,
2054 .write = ath10k_write_pktlog_filter,
2055 .open = simple_open
2056};
2057
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302058static ssize_t ath10k_write_quiet_period(struct file *file,
2059 const char __user *ubuf,
2060 size_t count, loff_t *ppos)
2061{
2062 struct ath10k *ar = file->private_data;
2063 u32 period;
2064
2065 if (kstrtouint_from_user(ubuf, count, 0, &period))
2066 return -EINVAL;
2067
2068 if (period < ATH10K_QUIET_PERIOD_MIN) {
2069 ath10k_warn(ar, "Quiet period %u can not be lesser than 25ms\n",
2070 period);
2071 return -EINVAL;
2072 }
2073 mutex_lock(&ar->conf_mutex);
2074 ar->thermal.quiet_period = period;
Rajkumar Manoharan8515b5c2015-03-15 20:36:22 +05302075 ath10k_thermal_set_throttling(ar);
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302076 mutex_unlock(&ar->conf_mutex);
2077
2078 return count;
2079}
2080
2081static ssize_t ath10k_read_quiet_period(struct file *file, char __user *ubuf,
2082 size_t count, loff_t *ppos)
2083{
2084 char buf[32];
2085 struct ath10k *ar = file->private_data;
2086 int len = 0;
2087
2088 mutex_lock(&ar->conf_mutex);
2089 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2090 ar->thermal.quiet_period);
2091 mutex_unlock(&ar->conf_mutex);
2092
2093 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2094}
2095
2096static const struct file_operations fops_quiet_period = {
2097 .read = ath10k_read_quiet_period,
2098 .write = ath10k_write_quiet_period,
2099 .open = simple_open
2100};
2101
Yanbo Li844fa572015-10-31 11:07:21 +02002102static ssize_t ath10k_write_btcoex(struct file *file,
2103 const char __user *ubuf,
2104 size_t count, loff_t *ppos)
2105{
2106 struct ath10k *ar = file->private_data;
2107 char buf[32];
2108 size_t buf_size;
2109 bool val;
2110
2111 buf_size = min(count, (sizeof(buf) - 1));
2112 if (copy_from_user(buf, ubuf, buf_size))
2113 return -EFAULT;
2114
2115 buf[buf_size] = '\0';
2116
2117 if (strtobool(buf, &val) != 0)
2118 return -EINVAL;
2119
2120 mutex_lock(&ar->conf_mutex);
2121
2122 if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val))
2123 goto exit;
2124
2125 if (val)
2126 set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
2127 else
2128 clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
2129
2130 if (ar->state != ATH10K_STATE_ON)
2131 goto exit;
2132
2133 ath10k_info(ar, "restarting firmware due to btcoex change");
2134
2135 queue_work(ar->workqueue, &ar->restart_work);
2136
2137exit:
2138 mutex_unlock(&ar->conf_mutex);
2139
2140 return count;
2141}
2142
2143static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
2144 size_t count, loff_t *ppos)
2145{
2146 char buf[32];
2147 struct ath10k *ar = file->private_data;
2148 int len = 0;
2149
2150 mutex_lock(&ar->conf_mutex);
2151 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2152 test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));
2153 mutex_unlock(&ar->conf_mutex);
2154
2155 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2156}
2157
2158static const struct file_operations fops_btcoex = {
2159 .read = ath10k_read_btcoex,
2160 .write = ath10k_write_btcoex,
2161 .open = simple_open
2162};
2163
Kalle Valo9e100c42015-11-25 15:38:41 +02002164static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
2165 char __user *user_buf,
2166 size_t count, loff_t *ppos)
2167{
2168 struct ath10k *ar = file->private_data;
2169 unsigned int len = 0, buf_len = 4096;
2170 ssize_t ret_cnt;
2171 char *buf;
2172
2173 buf = kzalloc(buf_len, GFP_KERNEL);
2174 if (!buf)
2175 return -ENOMEM;
2176
2177 mutex_lock(&ar->conf_mutex);
2178
2179 if (len > buf_len)
2180 len = buf_len;
2181
2182 len += scnprintf(buf + len, buf_len - len,
2183 "firmware-N.bin\t\t%08x\n",
2184 crc32_le(0, ar->firmware->data, ar->firmware->size));
2185 len += scnprintf(buf + len, buf_len - len,
2186 "athwlan\t\t\t%08x\n",
2187 crc32_le(0, ar->firmware_data, ar->firmware_len));
2188 len += scnprintf(buf + len, buf_len - len,
2189 "otp\t\t\t%08x\n",
2190 crc32_le(0, ar->otp_data, ar->otp_len));
2191 len += scnprintf(buf + len, buf_len - len,
2192 "codeswap\t\t%08x\n",
2193 crc32_le(0, ar->swap.firmware_codeswap_data,
2194 ar->swap.firmware_codeswap_len));
2195 len += scnprintf(buf + len, buf_len - len,
2196 "board-N.bin\t\t%08x\n",
2197 crc32_le(0, ar->board->data, ar->board->size));
2198 len += scnprintf(buf + len, buf_len - len,
2199 "board\t\t\t%08x\n",
2200 crc32_le(0, ar->board_data, ar->board_len));
2201
2202 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
2203
2204 mutex_unlock(&ar->conf_mutex);
2205
2206 kfree(buf);
2207 return ret_cnt;
2208}
2209
2210static const struct file_operations fops_fw_checksums = {
2211 .read = ath10k_debug_fw_checksums_read,
2212 .open = simple_open,
2213 .owner = THIS_MODULE,
2214 .llseek = default_llseek,
2215};
2216
Kalle Valo5e3dd152013-06-12 20:52:10 +03002217int ath10k_debug_create(struct ath10k *ar)
2218{
Ben Greear384914b2014-08-25 08:37:32 +03002219 ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002220 if (!ar->debug.fw_crash_data)
2221 return -ENOMEM;
Ben Greear384914b2014-08-25 08:37:32 +03002222
Michal Kazior53268492014-09-25 12:33:50 +02002223 INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +02002224 INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +02002225 INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
2226
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002227 return 0;
2228}
2229
2230void ath10k_debug_destroy(struct ath10k *ar)
2231{
2232 vfree(ar->debug.fw_crash_data);
2233 ar->debug.fw_crash_data = NULL;
Michal Kazior53268492014-09-25 12:33:50 +02002234
2235 ath10k_debug_fw_stats_reset(ar);
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002236
2237 kfree(ar->debug.tpc_stats);
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002238}
2239
2240int ath10k_debug_register(struct ath10k *ar)
2241{
Kalle Valo5e3dd152013-06-12 20:52:10 +03002242 ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
2243 ar->hw->wiphy->debugfsdir);
Michal Kazioradb43b22014-09-04 12:36:45 +02002244 if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
2245 if (IS_ERR(ar->debug.debugfs_phy))
2246 return PTR_ERR(ar->debug.debugfs_phy);
Kalle Valod8bb26b2014-09-14 12:50:33 +03002247
2248 return -ENOMEM;
Michal Kazioradb43b22014-09-04 12:36:45 +02002249 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03002250
Kalle Valoa3d135e2013-09-03 11:44:10 +03002251 INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
2252 ath10k_debug_htt_stats_dwork);
2253
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002254 init_completion(&ar->debug.tpc_complete);
Michal Kazior60ef4012014-09-25 12:33:48 +02002255 init_completion(&ar->debug.fw_stats_complete);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002256
2257 debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
2258 &fops_fw_stats);
2259
Ben Greearf51dbe72014-09-29 14:41:46 +03002260 debugfs_create_file("fw_reset_stats", S_IRUSR, ar->debug.debugfs_phy,
2261 ar, &fops_fw_reset_stats);
2262
Kalle Valo5e3dd152013-06-12 20:52:10 +03002263 debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
2264 &fops_wmi_services);
2265
Mohammed Shafi Shajakhan8bf1ba12015-11-24 22:26:37 +05302266 debugfs_create_file("simulate_fw_crash", S_IRUSR | S_IWUSR,
2267 ar->debug.debugfs_phy, ar, &fops_simulate_fw_crash);
Michal Kazior278c4a82013-07-22 14:08:51 +02002268
Ben Greear384914b2014-08-25 08:37:32 +03002269 debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
2270 ar, &fops_fw_crash_dump);
2271
Yanbo Li077a3802014-11-25 12:24:33 +02002272 debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR,
2273 ar->debug.debugfs_phy, ar, &fops_reg_addr);
2274
2275 debugfs_create_file("reg_value", S_IRUSR | S_IWUSR,
2276 ar->debug.debugfs_phy, ar, &fops_reg_value);
2277
Yanbo Li9f65ad22014-11-25 12:24:48 +02002278 debugfs_create_file("mem_value", S_IRUSR | S_IWUSR,
2279 ar->debug.debugfs_phy, ar, &fops_mem_value);
2280
Kalle Valo763b8cd2013-09-01 11:22:21 +03002281 debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
2282 ar, &fops_chip_id);
2283
Mohammed Shafi Shajakhan8bf1ba12015-11-24 22:26:37 +05302284 debugfs_create_file("htt_stats_mask", S_IRUSR | S_IWUSR,
2285 ar->debug.debugfs_phy, ar, &fops_htt_stats_mask);
Kalle Valoa3d135e2013-09-03 11:44:10 +03002286
Janusz Dziedzicd3856232014-06-02 21:19:46 +03002287 debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
2288 ar->debug.debugfs_phy, ar,
2289 &fops_htt_max_amsdu_ampdu);
2290
Mohammed Shafi Shajakhan8bf1ba12015-11-24 22:26:37 +05302291 debugfs_create_file("fw_dbglog", S_IRUSR | S_IWUSR,
2292 ar->debug.debugfs_phy, ar, &fops_fw_dbglog);
Kalle Valof118a3e2014-01-03 12:59:31 +02002293
Kalle Valo7869b4f2014-09-24 14:16:58 +03002294 debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
2295 ar, &fops_cal_data);
2296
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05302297 debugfs_create_file("ani_enable", S_IRUSR | S_IWUSR,
2298 ar->debug.debugfs_phy, ar, &fops_ani_enable);
2299
Peter Oha7bd3e92014-12-02 13:07:14 +02002300 debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR,
2301 ar->debug.debugfs_phy, ar, &fops_nf_cal_period);
2302
Janusz Dziedzic9702c682013-11-20 09:59:41 +02002303 if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
2304 debugfs_create_file("dfs_simulate_radar", S_IWUSR,
2305 ar->debug.debugfs_phy, ar,
2306 &fops_simulate_radar);
2307
Marek Puzyniak7d9b40b2013-11-20 10:00:28 +02002308 debugfs_create_bool("dfs_block_radar_events", S_IWUSR,
2309 ar->debug.debugfs_phy,
2310 &ar->dfs_block_radar_events);
2311
Janusz Dziedzic9702c682013-11-20 09:59:41 +02002312 debugfs_create_file("dfs_stats", S_IRUSR,
2313 ar->debug.debugfs_phy, ar,
2314 &fops_dfs_stats);
2315 }
2316
Rajkumar Manoharan90174452014-10-03 08:02:33 +03002317 debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR,
2318 ar->debug.debugfs_phy, ar, &fops_pktlog_filter);
2319
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302320 debugfs_create_file("quiet_period", S_IRUGO | S_IWUSR,
2321 ar->debug.debugfs_phy, ar, &fops_quiet_period);
2322
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002323 debugfs_create_file("tpc_stats", S_IRUSR,
2324 ar->debug.debugfs_phy, ar, &fops_tpc_stats);
2325
Yanbo Li844fa572015-10-31 11:07:21 +02002326 if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
2327 debugfs_create_file("btcoex", S_IRUGO | S_IWUSR,
2328 ar->debug.debugfs_phy, ar, &fops_btcoex);
2329
Kalle Valo9e100c42015-11-25 15:38:41 +02002330 debugfs_create_file("fw_checksums", S_IRUSR,
2331 ar->debug.debugfs_phy, ar, &fops_fw_checksums);
2332
Kalle Valo5e3dd152013-06-12 20:52:10 +03002333 return 0;
2334}
Kalle Valodb66ea02013-09-03 11:44:03 +03002335
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002336void ath10k_debug_unregister(struct ath10k *ar)
Kalle Valo60631c52013-10-08 21:45:25 +03002337{
2338 cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
2339}
2340
Kalle Valo5e3dd152013-06-12 20:52:10 +03002341#endif /* CONFIG_ATH10K_DEBUGFS */
2342
2343#ifdef CONFIG_ATH10K_DEBUG
Michal Kazior7aa7a722014-08-25 12:09:38 +02002344void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
2345 const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +03002346{
2347 struct va_format vaf;
2348 va_list args;
2349
2350 va_start(args, fmt);
2351
2352 vaf.fmt = fmt;
2353 vaf.va = &args;
2354
2355 if (ath10k_debug_mask & mask)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002356 dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002357
Michal Kaziord35a6c12014-09-02 11:00:21 +03002358 trace_ath10k_log_dbg(ar, mask, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002359
2360 va_end(args);
2361}
2362EXPORT_SYMBOL(ath10k_dbg);
2363
Michal Kazior7aa7a722014-08-25 12:09:38 +02002364void ath10k_dbg_dump(struct ath10k *ar,
2365 enum ath10k_debug_mask mask,
Kalle Valo5e3dd152013-06-12 20:52:10 +03002366 const char *msg, const char *prefix,
2367 const void *buf, size_t len)
2368{
Michal Kazior45724a82014-09-23 10:22:53 +02002369 char linebuf[256];
2370 unsigned int linebuflen;
2371 const void *ptr;
2372
Kalle Valo5e3dd152013-06-12 20:52:10 +03002373 if (ath10k_debug_mask & mask) {
2374 if (msg)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002375 ath10k_dbg(ar, mask, "%s\n", msg);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002376
Michal Kazior45724a82014-09-23 10:22:53 +02002377 for (ptr = buf; (ptr - buf) < len; ptr += 16) {
2378 linebuflen = 0;
2379 linebuflen += scnprintf(linebuf + linebuflen,
2380 sizeof(linebuf) - linebuflen,
2381 "%s%08x: ",
2382 (prefix ? prefix : ""),
2383 (unsigned int)(ptr - buf));
2384 hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
2385 linebuf + linebuflen,
2386 sizeof(linebuf) - linebuflen, true);
2387 dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
2388 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03002389 }
2390
2391 /* tracing code doesn't like null strings :/ */
Michal Kaziord35a6c12014-09-02 11:00:21 +03002392 trace_ath10k_log_dbg_dump(ar, msg ? msg : "", prefix ? prefix : "",
Kalle Valo5e3dd152013-06-12 20:52:10 +03002393 buf, len);
2394}
2395EXPORT_SYMBOL(ath10k_dbg_dump);
2396
2397#endif /* CONFIG_ATH10K_DEBUG */