blob: 2349cca31809d1794a9d68e7b790e94f66e6ec14 [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 Valo5e3dd152013-06-12 20:52:10 +030022
23#include "core.h"
24#include "debug.h"
Kalle Valo7869b4f2014-09-24 14:16:58 +030025#include "hif.h"
Michal Kaziord7579d12014-12-03 10:10:54 +020026#include "wmi-ops.h"
Kalle Valo5e3dd152013-06-12 20:52:10 +030027
Kalle Valoa3d135e2013-09-03 11:44:10 +030028/* ms */
29#define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
30
Ben Greear384914b2014-08-25 08:37:32 +030031#define ATH10K_FW_CRASH_DUMP_VERSION 1
32
33/**
34 * enum ath10k_fw_crash_dump_type - types of data in the dump file
35 * @ATH10K_FW_CRASH_DUMP_REGDUMP: Register crash dump in binary format
36 */
37enum ath10k_fw_crash_dump_type {
38 ATH10K_FW_CRASH_DUMP_REGISTERS = 0,
39
40 ATH10K_FW_CRASH_DUMP_MAX,
41};
42
43struct ath10k_tlv_dump_data {
44 /* see ath10k_fw_crash_dump_type above */
45 __le32 type;
46
47 /* in bytes */
48 __le32 tlv_len;
49
50 /* pad to 32-bit boundaries as needed */
51 u8 tlv_data[];
52} __packed;
53
54struct ath10k_dump_file_data {
55 /* dump file information */
56
57 /* "ATH10K-FW-DUMP" */
58 char df_magic[16];
59
60 __le32 len;
61
62 /* file dump version */
63 __le32 version;
64
65 /* some info we can get from ath10k struct that might help */
66
67 u8 uuid[16];
68
69 __le32 chip_id;
70
71 /* 0 for now, in place for later hardware */
72 __le32 bus_type;
73
74 __le32 target_version;
75 __le32 fw_version_major;
76 __le32 fw_version_minor;
77 __le32 fw_version_release;
78 __le32 fw_version_build;
79 __le32 phy_capability;
80 __le32 hw_min_tx_power;
81 __le32 hw_max_tx_power;
82 __le32 ht_cap_info;
83 __le32 vht_cap_info;
84 __le32 num_rf_chains;
85
86 /* firmware version string */
87 char fw_ver[ETHTOOL_FWVERS_LEN];
88
89 /* Kernel related information */
90
91 /* time-of-day stamp */
92 __le64 tv_sec;
93
94 /* time-of-day stamp, nano-seconds */
95 __le64 tv_nsec;
96
97 /* LINUX_VERSION_CODE */
98 __le32 kernel_ver_code;
99
100 /* VERMAGIC_STRING */
101 char kernel_ver[64];
102
103 /* room for growth w/out changing binary format */
104 u8 unused[128];
105
106 /* struct ath10k_tlv_dump_data + more */
107 u8 data[0];
108} __packed;
109
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700110void ath10k_info(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300111{
112 struct va_format vaf = {
113 .fmt = fmt,
114 };
115 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300116
117 va_start(args, fmt);
118 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700119 dev_info(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300120 trace_ath10k_log_info(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300121 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300122}
123EXPORT_SYMBOL(ath10k_info);
124
Kalle Valo8a0c7972014-08-25 08:37:45 +0300125void ath10k_print_driver_info(struct ath10k *ar)
126{
Michal Kazior84e3df62015-08-05 06:55:37 +0200127 char fw_features[128] = {};
Manikanta Pubbisetty0a51b342015-10-09 11:55:58 +0300128 char boardinfo[100];
Michal Kaziorb27bc5a2015-06-15 14:46:40 +0300129
130 ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
131
Manikanta Pubbisettydb0984e2015-10-09 11:55:59 +0300132 if (ar->id.bmi_ids_valid)
Kalle Valo8605c022015-11-25 15:38:19 +0200133 scnprintf(boardinfo, sizeof(boardinfo), "%d:%d",
Manikanta Pubbisettydb0984e2015-10-09 11:55:59 +0300134 ar->id.bmi_chip_id, ar->id.bmi_board_id);
135 else
Kalle Valo8605c022015-11-25 15:38:19 +0200136 scnprintf(boardinfo, sizeof(boardinfo), "N/A");
Manikanta Pubbisetty0a51b342015-10-09 11:55:58 +0300137
Kalle Valo8605c022015-11-25 15:38:19 +0200138 ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x",
Kalle Valo8a0c7972014-08-25 08:37:45 +0300139 ar->hw_params.name,
140 ar->target_version,
141 ar->chip_id,
Kalle Valo8605c022015-11-25 15:38:19 +0200142 ar->id.subsystem_vendor, ar->id.subsystem_device);
Kalle Valof0de90b2015-11-25 15:38:12 +0200143
144 ath10k_info(ar, "firmware ver %s api %d features %s\n",
Kalle Valo8a0c7972014-08-25 08:37:45 +0300145 ar->hw->wiphy->fw_version,
146 ar->fw_api,
Kalle Valof0de90b2015-11-25 15:38:12 +0200147 fw_features);
148
Kalle Valo8605c022015-11-25 15:38:19 +0200149 ath10k_info(ar, "board_file api %d bmi_id %s",
150 ar->bd_api,
151 boardinfo);
Kalle Valof0de90b2015-11-25 15:38:12 +0200152
153 ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n",
154 config_enabled(CONFIG_ATH10K_DEBUG),
155 config_enabled(CONFIG_ATH10K_DEBUGFS),
156 config_enabled(CONFIG_ATH10K_TRACING),
157 config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
158 config_enabled(CONFIG_NL80211_TESTMODE));
159
160 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 +0300161 ar->htt.target_version_major,
Michal Kazior34b28b62014-09-23 10:22:52 +0200162 ar->htt.target_version_minor,
Kalle Valoffdd0752014-12-17 12:21:03 +0200163 ar->wmi.op_version,
Michal Kazior67c81f52015-06-15 14:46:41 +0300164 ar->htt.op_version,
Michal Kaziorcfd10612014-11-25 15:16:05 +0100165 ath10k_cal_mode_str(ar->cal_mode),
Michal Kaziorb27bc5a2015-06-15 14:46:40 +0300166 ar->max_num_stations,
David Liuccec9032015-07-24 20:25:32 +0300167 test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
Kalle Valof0de90b2015-11-25 15:38:12 +0200168 !test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags));
Kalle Valo8a0c7972014-08-25 08:37:45 +0300169}
170EXPORT_SYMBOL(ath10k_print_driver_info);
171
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700172void ath10k_err(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300173{
174 struct va_format vaf = {
175 .fmt = fmt,
176 };
177 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300178
179 va_start(args, fmt);
180 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700181 dev_err(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300182 trace_ath10k_log_err(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300183 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300184}
185EXPORT_SYMBOL(ath10k_err);
186
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700187void ath10k_warn(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300188{
189 struct va_format vaf = {
190 .fmt = fmt,
191 };
192 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300193
194 va_start(args, fmt);
195 vaf.va = &args;
Michal Kazior7aa7a722014-08-25 12:09:38 +0200196 dev_warn_ratelimited(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300197 trace_ath10k_log_warn(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300198
199 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300200}
201EXPORT_SYMBOL(ath10k_warn);
202
203#ifdef CONFIG_ATH10K_DEBUGFS
204
Kalle Valo5e3dd152013-06-12 20:52:10 +0300205static ssize_t ath10k_read_wmi_services(struct file *file,
206 char __user *user_buf,
207 size_t count, loff_t *ppos)
208{
209 struct ath10k *ar = file->private_data;
210 char *buf;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300211 unsigned int len = 0, buf_len = 4096;
212 const char *name;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300213 ssize_t ret_cnt;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300214 bool enabled;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300215 int i;
216
217 buf = kzalloc(buf_len, GFP_KERNEL);
218 if (!buf)
219 return -ENOMEM;
220
221 mutex_lock(&ar->conf_mutex);
222
223 if (len > buf_len)
224 len = buf_len;
225
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100226 spin_lock_bh(&ar->data_lock);
Michal Kaziorc4f8c832014-09-04 10:18:32 +0200227 for (i = 0; i < WMI_SERVICE_MAX; i++) {
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100228 enabled = test_bit(i, ar->wmi.svc_map);
Michal Kaziorcff990c2014-08-04 09:18:33 +0300229 name = wmi_service_name(i);
230
231 if (!name) {
232 if (enabled)
233 len += scnprintf(buf + len, buf_len - len,
234 "%-40s %s (bit %d)\n",
235 "unknown", "enabled", i);
236
237 continue;
238 }
Kalle Valo5e3dd152013-06-12 20:52:10 +0300239
240 len += scnprintf(buf + len, buf_len - len,
Michal Kaziorcff990c2014-08-04 09:18:33 +0300241 "%-40s %s\n",
242 name, enabled ? "enabled" : "-");
Kalle Valo5e3dd152013-06-12 20:52:10 +0300243 }
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100244 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300245
246 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
247
248 mutex_unlock(&ar->conf_mutex);
249
250 kfree(buf);
251 return ret_cnt;
252}
253
254static const struct file_operations fops_wmi_services = {
255 .read = ath10k_read_wmi_services,
256 .open = simple_open,
257 .owner = THIS_MODULE,
258 .llseek = default_llseek,
259};
260
Michal Kazior53268492014-09-25 12:33:50 +0200261static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
262{
263 struct ath10k_fw_stats_pdev *i, *tmp;
264
265 list_for_each_entry_safe(i, tmp, head, list) {
266 list_del(&i->list);
267 kfree(i);
268 }
269}
270
Michal Kazior7b6b1532015-02-15 16:50:40 +0200271static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head)
272{
273 struct ath10k_fw_stats_vdev *i, *tmp;
274
275 list_for_each_entry_safe(i, tmp, head, list) {
276 list_del(&i->list);
277 kfree(i);
278 }
279}
280
Michal Kazior53268492014-09-25 12:33:50 +0200281static void ath10k_debug_fw_stats_peers_free(struct list_head *head)
282{
283 struct ath10k_fw_stats_peer *i, *tmp;
284
285 list_for_each_entry_safe(i, tmp, head, list) {
286 list_del(&i->list);
287 kfree(i);
288 }
289}
290
291static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
292{
293 spin_lock_bh(&ar->data_lock);
294 ar->debug.fw_stats_done = false;
295 ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200296 ath10k_debug_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200297 ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers);
298 spin_unlock_bh(&ar->data_lock);
299}
300
Michal Kazior60ef4012014-09-25 12:33:48 +0200301void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300302{
Michal Kazior53268492014-09-25 12:33:50 +0200303 struct ath10k_fw_stats stats = {};
304 bool is_start, is_started, is_end;
305 size_t num_peers;
Michal Kazior7b6b1532015-02-15 16:50:40 +0200306 size_t num_vdevs;
Michal Kaziord15fb522014-09-25 12:33:47 +0200307 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300308
Michal Kazior53268492014-09-25 12:33:50 +0200309 INIT_LIST_HEAD(&stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200310 INIT_LIST_HEAD(&stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200311 INIT_LIST_HEAD(&stats.peers);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300312
Michal Kazior53268492014-09-25 12:33:50 +0200313 spin_lock_bh(&ar->data_lock);
314 ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
Michal Kaziord15fb522014-09-25 12:33:47 +0200315 if (ret) {
316 ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
Raja Mani5db879a2015-07-09 14:19:43 +0530317 goto free;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300318 }
319
Michal Kazior53268492014-09-25 12:33:50 +0200320 /* Stat data may exceed htc-wmi buffer limit. In such case firmware
321 * splits the stats data and delivers it in a ping-pong fashion of
322 * request cmd-update event.
323 *
324 * However there is no explicit end-of-data. Instead start-of-data is
325 * used as an implicit one. This works as follows:
326 * a) discard stat update events until one with pdev stats is
327 * delivered - this skips session started at end of (b)
328 * b) consume stat update events until another one with pdev stats is
329 * delivered which is treated as end-of-data and is itself discarded
330 */
331
332 if (ar->debug.fw_stats_done) {
333 ath10k_warn(ar, "received unsolicited stats update event\n");
334 goto free;
335 }
336
Manikanta Pubbisettybc6f9ae2015-10-16 15:54:52 +0300337 num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers);
338 num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200339 is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
340 !list_empty(&stats.pdevs));
341 is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
342 !list_empty(&stats.pdevs));
343
344 if (is_start)
345 list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
346
347 if (is_end)
348 ar->debug.fw_stats_done = true;
349
350 is_started = !list_empty(&ar->debug.fw_stats.pdevs);
351
352 if (is_started && !is_end) {
353 if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) {
354 /* Although this is unlikely impose a sane limit to
355 * prevent firmware from DoS-ing the host.
356 */
357 ath10k_warn(ar, "dropping fw peer stats\n");
358 goto free;
359 }
360
Michal Kazior7b6b1532015-02-15 16:50:40 +0200361 if (num_vdevs >= BITS_PER_LONG) {
362 ath10k_warn(ar, "dropping fw vdev stats\n");
363 goto free;
364 }
365
Michal Kazior53268492014-09-25 12:33:50 +0200366 list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200367 list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200368 }
369
Michal Kazior60ef4012014-09-25 12:33:48 +0200370 complete(&ar->debug.fw_stats_complete);
Michal Kaziord15fb522014-09-25 12:33:47 +0200371
Michal Kazior53268492014-09-25 12:33:50 +0200372free:
373 /* In some cases lists have been spliced and cleared. Free up
374 * resources if that is not the case.
375 */
376 ath10k_debug_fw_stats_pdevs_free(&stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200377 ath10k_debug_fw_stats_vdevs_free(&stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200378 ath10k_debug_fw_stats_peers_free(&stats.peers);
379
Michal Kaziord15fb522014-09-25 12:33:47 +0200380 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300381}
382
Michal Kazior53268492014-09-25 12:33:50 +0200383static int ath10k_debug_fw_stats_request(struct ath10k *ar)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300384{
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300385 unsigned long timeout, time_left;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300386 int ret;
387
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200388 lockdep_assert_held(&ar->conf_mutex);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300389
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300390 timeout = jiffies + msecs_to_jiffies(1 * HZ);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300391
Michal Kazior53268492014-09-25 12:33:50 +0200392 ath10k_debug_fw_stats_reset(ar);
393
394 for (;;) {
395 if (time_after(jiffies, timeout))
396 return -ETIMEDOUT;
397
398 reinit_completion(&ar->debug.fw_stats_complete);
399
Yanbo Li6274cd42015-04-01 22:53:21 +0300400 ret = ath10k_wmi_request_stats(ar, ar->fw_stats_req_mask);
Michal Kazior53268492014-09-25 12:33:50 +0200401 if (ret) {
402 ath10k_warn(ar, "could not request stats (%d)\n", ret);
403 return ret;
404 }
405
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300406 time_left =
407 wait_for_completion_timeout(&ar->debug.fw_stats_complete,
408 1 * HZ);
409 if (!time_left)
Michal Kazior53268492014-09-25 12:33:50 +0200410 return -ETIMEDOUT;
411
412 spin_lock_bh(&ar->data_lock);
413 if (ar->debug.fw_stats_done) {
414 spin_unlock_bh(&ar->data_lock);
415 break;
416 }
417 spin_unlock_bh(&ar->data_lock);
418 }
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200419
420 return 0;
421}
422
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200423static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
424{
425 struct ath10k *ar = inode->i_private;
426 void *buf = NULL;
427 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300428
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200429 mutex_lock(&ar->conf_mutex);
430
431 if (ar->state != ATH10K_STATE_ON) {
432 ret = -ENETDOWN;
433 goto err_unlock;
434 }
435
436 buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);
437 if (!buf) {
438 ret = -ENOMEM;
439 goto err_unlock;
440 }
441
Michal Kazior53268492014-09-25 12:33:50 +0200442 ret = ath10k_debug_fw_stats_request(ar);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200443 if (ret) {
444 ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
445 goto err_free;
446 }
447
Manikanta Pubbisettybc6f9ae2015-10-16 15:54:52 +0300448 ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
449 if (ret) {
450 ath10k_warn(ar, "failed to fill fw stats: %d\n", ret);
451 goto err_free;
452 }
453
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200454 file->private_data = buf;
455
Kalle Valo5e3dd152013-06-12 20:52:10 +0300456 mutex_unlock(&ar->conf_mutex);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200457 return 0;
458
459err_free:
460 vfree(buf);
461
462err_unlock:
463 mutex_unlock(&ar->conf_mutex);
464 return ret;
465}
466
467static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
468{
469 vfree(file->private_data);
470
471 return 0;
472}
473
474static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
475 size_t count, loff_t *ppos)
476{
477 const char *buf = file->private_data;
478 unsigned int len = strlen(buf);
479
480 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300481}
482
483static const struct file_operations fops_fw_stats = {
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200484 .open = ath10k_fw_stats_open,
485 .release = ath10k_fw_stats_release,
Michal Kazior60ef4012014-09-25 12:33:48 +0200486 .read = ath10k_fw_stats_read,
Kalle Valo5e3dd152013-06-12 20:52:10 +0300487 .owner = THIS_MODULE,
488 .llseek = default_llseek,
489};
490
Ben Greearf51dbe72014-09-29 14:41:46 +0300491static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
492 char __user *user_buf,
493 size_t count, loff_t *ppos)
494{
495 struct ath10k *ar = file->private_data;
496 int ret, len, buf_len;
497 char *buf;
498
499 buf_len = 500;
500 buf = kmalloc(buf_len, GFP_KERNEL);
501 if (!buf)
502 return -ENOMEM;
503
504 spin_lock_bh(&ar->data_lock);
505
506 len = 0;
507 len += scnprintf(buf + len, buf_len - len,
508 "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
509 len += scnprintf(buf + len, buf_len - len,
510 "fw_warm_reset_counter\t\t%d\n",
511 ar->stats.fw_warm_reset_counter);
512 len += scnprintf(buf + len, buf_len - len,
513 "fw_cold_reset_counter\t\t%d\n",
514 ar->stats.fw_cold_reset_counter);
515
516 spin_unlock_bh(&ar->data_lock);
517
518 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
519
520 kfree(buf);
521
522 return ret;
523}
524
525static const struct file_operations fops_fw_reset_stats = {
526 .open = simple_open,
527 .read = ath10k_debug_fw_reset_stats_read,
528 .owner = THIS_MODULE,
529 .llseek = default_llseek,
530};
531
Ben Greeard5aebc72014-09-10 18:59:28 +0300532/* This is a clean assert crash in firmware. */
533static int ath10k_debug_fw_assert(struct ath10k *ar)
534{
535 struct wmi_vdev_install_key_cmd *cmd;
536 struct sk_buff *skb;
537
538 skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
539 if (!skb)
540 return -ENOMEM;
541
542 cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
543 memset(cmd, 0, sizeof(*cmd));
544
545 /* big enough number so that firmware asserts */
546 cmd->vdev_id = __cpu_to_le32(0x7ffe);
547
548 return ath10k_wmi_cmd_send(ar, skb,
549 ar->wmi.cmd->vdev_install_key_cmdid);
550}
551
Michal Kazior278c4a82013-07-22 14:08:51 +0200552static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
553 char __user *user_buf,
554 size_t count, loff_t *ppos)
555{
Kalle Valo75cb96d2014-09-14 12:50:44 +0300556 const char buf[] =
557 "To simulate firmware crash write one of the keywords to this file:\n"
558 "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
559 "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
Michal Kazior605cdba2014-10-28 10:34:37 +0100560 "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"
561 "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
Marek Puzyniak8c656992014-03-21 17:46:56 +0200562
Michal Kazior278c4a82013-07-22 14:08:51 +0200563 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
564}
565
Marek Puzyniak8c656992014-03-21 17:46:56 +0200566/* Simulate firmware crash:
567 * 'soft': Call wmi command causing firmware hang. This firmware hang is
568 * recoverable by warm firmware reset.
569 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
570 * vdev id. This is hard firmware crash because it is recoverable only by cold
571 * firmware reset.
572 */
Michal Kazior278c4a82013-07-22 14:08:51 +0200573static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
574 const char __user *user_buf,
575 size_t count, loff_t *ppos)
576{
577 struct ath10k *ar = file->private_data;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200578 char buf[32];
Michal Kazior278c4a82013-07-22 14:08:51 +0200579 int ret;
580
581 mutex_lock(&ar->conf_mutex);
582
583 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200584
585 /* make sure that buf is null terminated */
586 buf[sizeof(buf) - 1] = 0;
Michal Kazior278c4a82013-07-22 14:08:51 +0200587
588 if (ar->state != ATH10K_STATE_ON &&
589 ar->state != ATH10K_STATE_RESTARTED) {
590 ret = -ENETDOWN;
591 goto exit;
592 }
593
Marek Puzyniak8c656992014-03-21 17:46:56 +0200594 /* drop the possible '\n' from the end */
595 if (buf[count - 1] == '\n') {
596 buf[count - 1] = 0;
597 count--;
598 }
Michal Kazior278c4a82013-07-22 14:08:51 +0200599
Marek Puzyniak8c656992014-03-21 17:46:56 +0200600 if (!strcmp(buf, "soft")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200601 ath10k_info(ar, "simulating soft firmware crash\n");
Marek Puzyniak8c656992014-03-21 17:46:56 +0200602 ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
603 } else if (!strcmp(buf, "hard")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200604 ath10k_info(ar, "simulating hard firmware crash\n");
Ben Greear611b3682014-07-25 11:56:40 +0300605 /* 0x7fff is vdev id, and it is always out of range for all
606 * firmware variants in order to force a firmware crash.
607 */
608 ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
Kalle Valo5b07e072014-09-14 12:50:06 +0300609 ar->wmi.vdev_param->rts_threshold,
610 0);
Ben Greeard5aebc72014-09-10 18:59:28 +0300611 } else if (!strcmp(buf, "assert")) {
612 ath10k_info(ar, "simulating firmware assert crash\n");
613 ret = ath10k_debug_fw_assert(ar);
Michal Kazior605cdba2014-10-28 10:34:37 +0100614 } else if (!strcmp(buf, "hw-restart")) {
615 ath10k_info(ar, "user requested hw restart\n");
616 queue_work(ar->workqueue, &ar->restart_work);
617 ret = 0;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200618 } else {
619 ret = -EINVAL;
620 goto exit;
621 }
Michal Kazior278c4a82013-07-22 14:08:51 +0200622
Marek Puzyniak8c656992014-03-21 17:46:56 +0200623 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200624 ath10k_warn(ar, "failed to simulate firmware crash: %d\n", ret);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200625 goto exit;
626 }
627
628 ret = count;
Michal Kazior278c4a82013-07-22 14:08:51 +0200629
630exit:
631 mutex_unlock(&ar->conf_mutex);
632 return ret;
633}
634
635static const struct file_operations fops_simulate_fw_crash = {
636 .read = ath10k_read_simulate_fw_crash,
637 .write = ath10k_write_simulate_fw_crash,
638 .open = simple_open,
639 .owner = THIS_MODULE,
640 .llseek = default_llseek,
641};
642
Kalle Valo763b8cd2013-09-01 11:22:21 +0300643static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf,
644 size_t count, loff_t *ppos)
645{
646 struct ath10k *ar = file->private_data;
647 unsigned int len;
648 char buf[50];
649
650 len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id);
651
652 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
653}
654
655static const struct file_operations fops_chip_id = {
656 .read = ath10k_read_chip_id,
657 .open = simple_open,
658 .owner = THIS_MODULE,
659 .llseek = default_llseek,
660};
661
Ben Greear384914b2014-08-25 08:37:32 +0300662struct ath10k_fw_crash_data *
663ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
664{
665 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
666
667 lockdep_assert_held(&ar->data_lock);
668
669 crash_data->crashed_since_read = true;
670 uuid_le_gen(&crash_data->uuid);
671 getnstimeofday(&crash_data->timestamp);
672
673 return crash_data;
674}
675EXPORT_SYMBOL(ath10k_debug_get_new_fw_crash_data);
676
677static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
678{
679 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
680 struct ath10k_dump_file_data *dump_data;
681 struct ath10k_tlv_dump_data *dump_tlv;
682 int hdr_len = sizeof(*dump_data);
683 unsigned int len, sofar = 0;
684 unsigned char *buf;
685
686 len = hdr_len;
687 len += sizeof(*dump_tlv) + sizeof(crash_data->registers);
688
689 sofar += hdr_len;
690
691 /* This is going to get big when we start dumping FW RAM and such,
692 * so go ahead and use vmalloc.
693 */
694 buf = vzalloc(len);
695 if (!buf)
696 return NULL;
697
698 spin_lock_bh(&ar->data_lock);
699
700 if (!crash_data->crashed_since_read) {
701 spin_unlock_bh(&ar->data_lock);
702 vfree(buf);
703 return NULL;
704 }
705
706 dump_data = (struct ath10k_dump_file_data *)(buf);
707 strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP",
708 sizeof(dump_data->df_magic));
709 dump_data->len = cpu_to_le32(len);
710
711 dump_data->version = cpu_to_le32(ATH10K_FW_CRASH_DUMP_VERSION);
712
713 memcpy(dump_data->uuid, &crash_data->uuid, sizeof(dump_data->uuid));
714 dump_data->chip_id = cpu_to_le32(ar->chip_id);
715 dump_data->bus_type = cpu_to_le32(0);
716 dump_data->target_version = cpu_to_le32(ar->target_version);
717 dump_data->fw_version_major = cpu_to_le32(ar->fw_version_major);
718 dump_data->fw_version_minor = cpu_to_le32(ar->fw_version_minor);
719 dump_data->fw_version_release = cpu_to_le32(ar->fw_version_release);
720 dump_data->fw_version_build = cpu_to_le32(ar->fw_version_build);
721 dump_data->phy_capability = cpu_to_le32(ar->phy_capability);
722 dump_data->hw_min_tx_power = cpu_to_le32(ar->hw_min_tx_power);
723 dump_data->hw_max_tx_power = cpu_to_le32(ar->hw_max_tx_power);
724 dump_data->ht_cap_info = cpu_to_le32(ar->ht_cap_info);
725 dump_data->vht_cap_info = cpu_to_le32(ar->vht_cap_info);
726 dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains);
727
728 strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
729 sizeof(dump_data->fw_ver));
730
Johannes Berg12c27152014-11-21 18:58:49 +0200731 dump_data->kernel_ver_code = 0;
732 strlcpy(dump_data->kernel_ver, init_utsname()->release,
Ben Greear384914b2014-08-25 08:37:32 +0300733 sizeof(dump_data->kernel_ver));
734
735 dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
736 dump_data->tv_nsec = cpu_to_le64(crash_data->timestamp.tv_nsec);
737
738 /* Gather crash-dump */
739 dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
740 dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_REGISTERS);
741 dump_tlv->tlv_len = cpu_to_le32(sizeof(crash_data->registers));
742 memcpy(dump_tlv->tlv_data, &crash_data->registers,
743 sizeof(crash_data->registers));
744 sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers);
745
746 ar->debug.fw_crash_data->crashed_since_read = false;
747
748 spin_unlock_bh(&ar->data_lock);
749
750 return dump_data;
751}
752
753static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file)
754{
755 struct ath10k *ar = inode->i_private;
756 struct ath10k_dump_file_data *dump;
757
758 dump = ath10k_build_dump_file(ar);
759 if (!dump)
760 return -ENODATA;
761
762 file->private_data = dump;
763
764 return 0;
765}
766
767static ssize_t ath10k_fw_crash_dump_read(struct file *file,
768 char __user *user_buf,
769 size_t count, loff_t *ppos)
770{
771 struct ath10k_dump_file_data *dump_file = file->private_data;
772
773 return simple_read_from_buffer(user_buf, count, ppos,
774 dump_file,
775 le32_to_cpu(dump_file->len));
776}
777
778static int ath10k_fw_crash_dump_release(struct inode *inode,
779 struct file *file)
780{
781 vfree(file->private_data);
782
783 return 0;
784}
785
786static const struct file_operations fops_fw_crash_dump = {
787 .open = ath10k_fw_crash_dump_open,
788 .read = ath10k_fw_crash_dump_read,
789 .release = ath10k_fw_crash_dump_release,
790 .owner = THIS_MODULE,
791 .llseek = default_llseek,
792};
793
Yanbo Li077a3802014-11-25 12:24:33 +0200794static ssize_t ath10k_reg_addr_read(struct file *file,
795 char __user *user_buf,
796 size_t count, loff_t *ppos)
797{
798 struct ath10k *ar = file->private_data;
799 u8 buf[32];
800 unsigned int len = 0;
801 u32 reg_addr;
802
803 mutex_lock(&ar->conf_mutex);
804 reg_addr = ar->debug.reg_addr;
805 mutex_unlock(&ar->conf_mutex);
806
807 len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);
808
809 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
810}
811
812static ssize_t ath10k_reg_addr_write(struct file *file,
813 const char __user *user_buf,
814 size_t count, loff_t *ppos)
815{
816 struct ath10k *ar = file->private_data;
817 u32 reg_addr;
818 int ret;
819
820 ret = kstrtou32_from_user(user_buf, count, 0, &reg_addr);
821 if (ret)
822 return ret;
823
824 if (!IS_ALIGNED(reg_addr, 4))
825 return -EFAULT;
826
827 mutex_lock(&ar->conf_mutex);
828 ar->debug.reg_addr = reg_addr;
829 mutex_unlock(&ar->conf_mutex);
830
831 return count;
832}
833
834static const struct file_operations fops_reg_addr = {
835 .read = ath10k_reg_addr_read,
836 .write = ath10k_reg_addr_write,
837 .open = simple_open,
838 .owner = THIS_MODULE,
839 .llseek = default_llseek,
840};
841
842static ssize_t ath10k_reg_value_read(struct file *file,
843 char __user *user_buf,
844 size_t count, loff_t *ppos)
845{
846 struct ath10k *ar = file->private_data;
847 u8 buf[48];
848 unsigned int len;
849 u32 reg_addr, reg_val;
850 int ret;
851
852 mutex_lock(&ar->conf_mutex);
853
854 if (ar->state != ATH10K_STATE_ON &&
855 ar->state != ATH10K_STATE_UTF) {
856 ret = -ENETDOWN;
857 goto exit;
858 }
859
860 reg_addr = ar->debug.reg_addr;
861
862 reg_val = ath10k_hif_read32(ar, reg_addr);
863 len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);
864
865 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
866
867exit:
868 mutex_unlock(&ar->conf_mutex);
869
870 return ret;
871}
872
873static ssize_t ath10k_reg_value_write(struct file *file,
874 const char __user *user_buf,
875 size_t count, loff_t *ppos)
876{
877 struct ath10k *ar = file->private_data;
878 u32 reg_addr, reg_val;
879 int ret;
880
881 mutex_lock(&ar->conf_mutex);
882
883 if (ar->state != ATH10K_STATE_ON &&
884 ar->state != ATH10K_STATE_UTF) {
885 ret = -ENETDOWN;
886 goto exit;
887 }
888
889 reg_addr = ar->debug.reg_addr;
890
891 ret = kstrtou32_from_user(user_buf, count, 0, &reg_val);
892 if (ret)
893 goto exit;
894
895 ath10k_hif_write32(ar, reg_addr, reg_val);
896
897 ret = count;
898
899exit:
900 mutex_unlock(&ar->conf_mutex);
901
902 return ret;
903}
904
905static const struct file_operations fops_reg_value = {
906 .read = ath10k_reg_value_read,
907 .write = ath10k_reg_value_write,
908 .open = simple_open,
909 .owner = THIS_MODULE,
910 .llseek = default_llseek,
911};
912
Yanbo Li9f65ad22014-11-25 12:24:48 +0200913static ssize_t ath10k_mem_value_read(struct file *file,
914 char __user *user_buf,
915 size_t count, loff_t *ppos)
916{
917 struct ath10k *ar = file->private_data;
918 u8 *buf;
919 int ret;
920
921 if (*ppos < 0)
922 return -EINVAL;
923
924 if (!count)
925 return 0;
926
927 mutex_lock(&ar->conf_mutex);
928
929 buf = vmalloc(count);
930 if (!buf) {
931 ret = -ENOMEM;
932 goto exit;
933 }
934
935 if (ar->state != ATH10K_STATE_ON &&
936 ar->state != ATH10K_STATE_UTF) {
937 ret = -ENETDOWN;
938 goto exit;
939 }
940
941 ret = ath10k_hif_diag_read(ar, *ppos, buf, count);
942 if (ret) {
943 ath10k_warn(ar, "failed to read address 0x%08x via diagnose window fnrom debugfs: %d\n",
944 (u32)(*ppos), ret);
945 goto exit;
946 }
947
948 ret = copy_to_user(user_buf, buf, count);
949 if (ret) {
950 ret = -EFAULT;
951 goto exit;
952 }
953
954 count -= ret;
955 *ppos += count;
956 ret = count;
957
958exit:
959 vfree(buf);
960 mutex_unlock(&ar->conf_mutex);
961
962 return ret;
963}
964
965static ssize_t ath10k_mem_value_write(struct file *file,
966 const char __user *user_buf,
967 size_t count, loff_t *ppos)
968{
969 struct ath10k *ar = file->private_data;
970 u8 *buf;
971 int ret;
972
973 if (*ppos < 0)
974 return -EINVAL;
975
976 if (!count)
977 return 0;
978
979 mutex_lock(&ar->conf_mutex);
980
981 buf = vmalloc(count);
982 if (!buf) {
983 ret = -ENOMEM;
984 goto exit;
985 }
986
987 if (ar->state != ATH10K_STATE_ON &&
988 ar->state != ATH10K_STATE_UTF) {
989 ret = -ENETDOWN;
990 goto exit;
991 }
992
993 ret = copy_from_user(buf, user_buf, count);
994 if (ret) {
995 ret = -EFAULT;
996 goto exit;
997 }
998
999 ret = ath10k_hif_diag_write(ar, *ppos, buf, count);
1000 if (ret) {
1001 ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",
1002 (u32)(*ppos), ret);
1003 goto exit;
1004 }
1005
1006 *ppos += count;
1007 ret = count;
1008
1009exit:
1010 vfree(buf);
1011 mutex_unlock(&ar->conf_mutex);
1012
1013 return ret;
1014}
1015
1016static const struct file_operations fops_mem_value = {
1017 .read = ath10k_mem_value_read,
1018 .write = ath10k_mem_value_write,
1019 .open = simple_open,
1020 .owner = THIS_MODULE,
1021 .llseek = default_llseek,
1022};
1023
Kalle Valoa3d135e2013-09-03 11:44:10 +03001024static int ath10k_debug_htt_stats_req(struct ath10k *ar)
1025{
1026 u64 cookie;
1027 int ret;
1028
1029 lockdep_assert_held(&ar->conf_mutex);
1030
1031 if (ar->debug.htt_stats_mask == 0)
1032 /* htt stats are disabled */
1033 return 0;
1034
1035 if (ar->state != ATH10K_STATE_ON)
1036 return 0;
1037
1038 cookie = get_jiffies_64();
1039
1040 ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask,
1041 cookie);
1042 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001043 ath10k_warn(ar, "failed to send htt stats request: %d\n", ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001044 return ret;
1045 }
1046
1047 queue_delayed_work(ar->workqueue, &ar->debug.htt_stats_dwork,
1048 msecs_to_jiffies(ATH10K_DEBUG_HTT_STATS_INTERVAL));
1049
1050 return 0;
1051}
1052
1053static void ath10k_debug_htt_stats_dwork(struct work_struct *work)
1054{
1055 struct ath10k *ar = container_of(work, struct ath10k,
1056 debug.htt_stats_dwork.work);
1057
1058 mutex_lock(&ar->conf_mutex);
1059
1060 ath10k_debug_htt_stats_req(ar);
1061
1062 mutex_unlock(&ar->conf_mutex);
1063}
1064
1065static ssize_t ath10k_read_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001066 char __user *user_buf,
1067 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001068{
1069 struct ath10k *ar = file->private_data;
1070 char buf[32];
1071 unsigned int len;
1072
1073 len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask);
1074
1075 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1076}
1077
1078static ssize_t ath10k_write_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001079 const char __user *user_buf,
1080 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001081{
1082 struct ath10k *ar = file->private_data;
1083 unsigned long mask;
1084 int ret;
1085
1086 ret = kstrtoul_from_user(user_buf, count, 0, &mask);
1087 if (ret)
1088 return ret;
1089
1090 /* max 8 bit masks (for now) */
1091 if (mask > 0xff)
1092 return -E2BIG;
1093
1094 mutex_lock(&ar->conf_mutex);
1095
1096 ar->debug.htt_stats_mask = mask;
1097
1098 ret = ath10k_debug_htt_stats_req(ar);
1099 if (ret)
1100 goto out;
1101
1102 ret = count;
1103
1104out:
1105 mutex_unlock(&ar->conf_mutex);
1106
1107 return ret;
1108}
1109
1110static const struct file_operations fops_htt_stats_mask = {
1111 .read = ath10k_read_htt_stats_mask,
1112 .write = ath10k_write_htt_stats_mask,
1113 .open = simple_open,
1114 .owner = THIS_MODULE,
1115 .llseek = default_llseek,
1116};
1117
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001118static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
1119 char __user *user_buf,
1120 size_t count, loff_t *ppos)
1121{
1122 struct ath10k *ar = file->private_data;
1123 char buf[64];
1124 u8 amsdu = 3, ampdu = 64;
1125 unsigned int len;
1126
1127 mutex_lock(&ar->conf_mutex);
1128
David Liuccec9032015-07-24 20:25:32 +03001129 amsdu = ar->htt.max_num_amsdu;
1130 ampdu = ar->htt.max_num_ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001131 mutex_unlock(&ar->conf_mutex);
1132
1133 len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
1134
1135 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1136}
1137
1138static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
1139 const char __user *user_buf,
1140 size_t count, loff_t *ppos)
1141{
1142 struct ath10k *ar = file->private_data;
1143 int res;
1144 char buf[64];
1145 unsigned int amsdu, ampdu;
1146
1147 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
1148
1149 /* make sure that buf is null terminated */
1150 buf[sizeof(buf) - 1] = 0;
1151
1152 res = sscanf(buf, "%u %u", &amsdu, &ampdu);
1153
1154 if (res != 2)
1155 return -EINVAL;
1156
1157 mutex_lock(&ar->conf_mutex);
1158
1159 res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
1160 if (res)
1161 goto out;
1162
1163 res = count;
David Liuccec9032015-07-24 20:25:32 +03001164 ar->htt.max_num_amsdu = amsdu;
1165 ar->htt.max_num_ampdu = ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001166
1167out:
1168 mutex_unlock(&ar->conf_mutex);
1169 return res;
1170}
1171
1172static const struct file_operations fops_htt_max_amsdu_ampdu = {
1173 .read = ath10k_read_htt_max_amsdu_ampdu,
1174 .write = ath10k_write_htt_max_amsdu_ampdu,
1175 .open = simple_open,
1176 .owner = THIS_MODULE,
1177 .llseek = default_llseek,
1178};
1179
Kalle Valof118a3e2014-01-03 12:59:31 +02001180static ssize_t ath10k_read_fw_dbglog(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001181 char __user *user_buf,
1182 size_t count, loff_t *ppos)
Kalle Valof118a3e2014-01-03 12:59:31 +02001183{
1184 struct ath10k *ar = file->private_data;
1185 unsigned int len;
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301186 char buf[64];
Kalle Valof118a3e2014-01-03 12:59:31 +02001187
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301188 len = scnprintf(buf, sizeof(buf), "0x%08x %u\n",
1189 ar->debug.fw_dbglog_mask, ar->debug.fw_dbglog_level);
Kalle Valof118a3e2014-01-03 12:59:31 +02001190
1191 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1192}
1193
1194static ssize_t ath10k_write_fw_dbglog(struct file *file,
1195 const char __user *user_buf,
1196 size_t count, loff_t *ppos)
1197{
1198 struct ath10k *ar = file->private_data;
Kalle Valof118a3e2014-01-03 12:59:31 +02001199 int ret;
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301200 char buf[64];
1201 unsigned int log_level, mask;
Kalle Valof118a3e2014-01-03 12:59:31 +02001202
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301203 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
1204
1205 /* make sure that buf is null terminated */
1206 buf[sizeof(buf) - 1] = 0;
1207
1208 ret = sscanf(buf, "%x %u", &mask, &log_level);
1209
1210 if (!ret)
1211 return -EINVAL;
1212
1213 if (ret == 1)
1214 /* default if user did not specify */
1215 log_level = ATH10K_DBGLOG_LEVEL_WARN;
Kalle Valof118a3e2014-01-03 12:59:31 +02001216
1217 mutex_lock(&ar->conf_mutex);
1218
1219 ar->debug.fw_dbglog_mask = mask;
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301220 ar->debug.fw_dbglog_level = log_level;
Kalle Valof118a3e2014-01-03 12:59:31 +02001221
1222 if (ar->state == ATH10K_STATE_ON) {
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301223 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1224 ar->debug.fw_dbglog_level);
Kalle Valof118a3e2014-01-03 12:59:31 +02001225 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001226 ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n",
Kalle Valof118a3e2014-01-03 12:59:31 +02001227 ret);
1228 goto exit;
1229 }
1230 }
1231
1232 ret = count;
1233
1234exit:
1235 mutex_unlock(&ar->conf_mutex);
1236
1237 return ret;
1238}
1239
Ben Greear6cddcc72014-09-29 14:41:46 +03001240/* TODO: Would be nice to always support ethtool stats, would need to
1241 * move the stats storage out of ath10k_debug, or always have ath10k_debug
1242 * struct available..
1243 */
1244
1245/* This generally cooresponds to the debugfs fw_stats file */
1246static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
1247 "tx_pkts_nic",
1248 "tx_bytes_nic",
1249 "rx_pkts_nic",
1250 "rx_bytes_nic",
1251 "d_noise_floor",
1252 "d_cycle_count",
1253 "d_phy_error",
1254 "d_rts_bad",
1255 "d_rts_good",
1256 "d_tx_power", /* in .5 dbM I think */
1257 "d_rx_crc_err", /* fcs_bad */
1258 "d_no_beacon",
1259 "d_tx_mpdus_queued",
1260 "d_tx_msdu_queued",
1261 "d_tx_msdu_dropped",
1262 "d_local_enqued",
1263 "d_local_freed",
1264 "d_tx_ppdu_hw_queued",
1265 "d_tx_ppdu_reaped",
1266 "d_tx_fifo_underrun",
1267 "d_tx_ppdu_abort",
1268 "d_tx_mpdu_requed",
1269 "d_tx_excessive_retries",
1270 "d_tx_hw_rate",
1271 "d_tx_dropped_sw_retries",
1272 "d_tx_illegal_rate",
1273 "d_tx_continuous_xretries",
1274 "d_tx_timeout",
1275 "d_tx_mpdu_txop_limit",
1276 "d_pdev_resets",
1277 "d_rx_mid_ppdu_route_change",
1278 "d_rx_status",
1279 "d_rx_extra_frags_ring0",
1280 "d_rx_extra_frags_ring1",
1281 "d_rx_extra_frags_ring2",
1282 "d_rx_extra_frags_ring3",
1283 "d_rx_msdu_htt",
1284 "d_rx_mpdu_htt",
1285 "d_rx_msdu_stack",
1286 "d_rx_mpdu_stack",
1287 "d_rx_phy_err",
1288 "d_rx_phy_err_drops",
1289 "d_rx_mpdu_errors", /* FCS, MIC, ENC */
1290 "d_fw_crash_count",
1291 "d_fw_warm_reset_count",
1292 "d_fw_cold_reset_count",
1293};
1294
1295#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
1296
1297void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
1298 struct ieee80211_vif *vif,
1299 u32 sset, u8 *data)
1300{
1301 if (sset == ETH_SS_STATS)
1302 memcpy(data, *ath10k_gstrings_stats,
1303 sizeof(ath10k_gstrings_stats));
1304}
1305
1306int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
1307 struct ieee80211_vif *vif, int sset)
1308{
1309 if (sset == ETH_SS_STATS)
1310 return ATH10K_SSTATS_LEN;
1311
1312 return 0;
1313}
1314
1315void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
1316 struct ieee80211_vif *vif,
1317 struct ethtool_stats *stats, u64 *data)
1318{
1319 struct ath10k *ar = hw->priv;
1320 static const struct ath10k_fw_stats_pdev zero_stats = {};
1321 const struct ath10k_fw_stats_pdev *pdev_stats;
1322 int i = 0, ret;
1323
1324 mutex_lock(&ar->conf_mutex);
1325
1326 if (ar->state == ATH10K_STATE_ON) {
1327 ret = ath10k_debug_fw_stats_request(ar);
1328 if (ret) {
1329 /* just print a warning and try to use older results */
1330 ath10k_warn(ar,
1331 "failed to get fw stats for ethtool: %d\n",
1332 ret);
1333 }
1334 }
1335
1336 pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,
1337 struct ath10k_fw_stats_pdev,
1338 list);
1339 if (!pdev_stats) {
1340 /* no results available so just return zeroes */
1341 pdev_stats = &zero_stats;
1342 }
1343
1344 spin_lock_bh(&ar->data_lock);
1345
1346 data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
1347 data[i++] = 0; /* tx bytes */
1348 data[i++] = pdev_stats->htt_mpdus;
1349 data[i++] = 0; /* rx bytes */
1350 data[i++] = pdev_stats->ch_noise_floor;
1351 data[i++] = pdev_stats->cycle_count;
1352 data[i++] = pdev_stats->phy_err_count;
1353 data[i++] = pdev_stats->rts_bad;
1354 data[i++] = pdev_stats->rts_good;
1355 data[i++] = pdev_stats->chan_tx_power;
1356 data[i++] = pdev_stats->fcs_bad;
1357 data[i++] = pdev_stats->no_beacons;
1358 data[i++] = pdev_stats->mpdu_enqued;
1359 data[i++] = pdev_stats->msdu_enqued;
1360 data[i++] = pdev_stats->wmm_drop;
1361 data[i++] = pdev_stats->local_enqued;
1362 data[i++] = pdev_stats->local_freed;
1363 data[i++] = pdev_stats->hw_queued;
1364 data[i++] = pdev_stats->hw_reaped;
1365 data[i++] = pdev_stats->underrun;
1366 data[i++] = pdev_stats->tx_abort;
1367 data[i++] = pdev_stats->mpdus_requed;
1368 data[i++] = pdev_stats->tx_ko;
1369 data[i++] = pdev_stats->data_rc;
1370 data[i++] = pdev_stats->sw_retry_failure;
1371 data[i++] = pdev_stats->illgl_rate_phy_err;
1372 data[i++] = pdev_stats->pdev_cont_xretry;
1373 data[i++] = pdev_stats->pdev_tx_timeout;
1374 data[i++] = pdev_stats->txop_ovf;
1375 data[i++] = pdev_stats->pdev_resets;
1376 data[i++] = pdev_stats->mid_ppdu_route_change;
1377 data[i++] = pdev_stats->status_rcvd;
1378 data[i++] = pdev_stats->r0_frags;
1379 data[i++] = pdev_stats->r1_frags;
1380 data[i++] = pdev_stats->r2_frags;
1381 data[i++] = pdev_stats->r3_frags;
1382 data[i++] = pdev_stats->htt_msdus;
1383 data[i++] = pdev_stats->htt_mpdus;
1384 data[i++] = pdev_stats->loc_msdus;
1385 data[i++] = pdev_stats->loc_mpdus;
1386 data[i++] = pdev_stats->phy_errs;
1387 data[i++] = pdev_stats->phy_err_drop;
1388 data[i++] = pdev_stats->mpdu_errs;
1389 data[i++] = ar->stats.fw_crash_counter;
1390 data[i++] = ar->stats.fw_warm_reset_counter;
1391 data[i++] = ar->stats.fw_cold_reset_counter;
1392
1393 spin_unlock_bh(&ar->data_lock);
1394
1395 mutex_unlock(&ar->conf_mutex);
1396
1397 WARN_ON(i != ATH10K_SSTATS_LEN);
1398}
1399
Kalle Valof118a3e2014-01-03 12:59:31 +02001400static const struct file_operations fops_fw_dbglog = {
1401 .read = ath10k_read_fw_dbglog,
1402 .write = ath10k_write_fw_dbglog,
1403 .open = simple_open,
1404 .owner = THIS_MODULE,
1405 .llseek = default_llseek,
1406};
1407
Kalle Valo7869b4f2014-09-24 14:16:58 +03001408static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
1409{
1410 struct ath10k *ar = inode->i_private;
1411 void *buf;
1412 u32 hi_addr;
1413 __le32 addr;
1414 int ret;
1415
1416 mutex_lock(&ar->conf_mutex);
1417
1418 if (ar->state != ATH10K_STATE_ON &&
1419 ar->state != ATH10K_STATE_UTF) {
1420 ret = -ENETDOWN;
1421 goto err;
1422 }
1423
1424 buf = vmalloc(QCA988X_CAL_DATA_LEN);
1425 if (!buf) {
1426 ret = -ENOMEM;
1427 goto err;
1428 }
1429
1430 hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
1431
1432 ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
1433 if (ret) {
1434 ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret);
1435 goto err_vfree;
1436 }
1437
1438 ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
1439 QCA988X_CAL_DATA_LEN);
1440 if (ret) {
1441 ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
1442 goto err_vfree;
1443 }
1444
1445 file->private_data = buf;
1446
1447 mutex_unlock(&ar->conf_mutex);
1448
1449 return 0;
1450
1451err_vfree:
1452 vfree(buf);
1453
1454err:
1455 mutex_unlock(&ar->conf_mutex);
1456
1457 return ret;
1458}
1459
1460static ssize_t ath10k_debug_cal_data_read(struct file *file,
1461 char __user *user_buf,
1462 size_t count, loff_t *ppos)
1463{
1464 void *buf = file->private_data;
1465
1466 return simple_read_from_buffer(user_buf, count, ppos,
1467 buf, QCA988X_CAL_DATA_LEN);
1468}
1469
1470static int ath10k_debug_cal_data_release(struct inode *inode,
1471 struct file *file)
1472{
1473 vfree(file->private_data);
1474
1475 return 0;
1476}
1477
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05301478static ssize_t ath10k_write_ani_enable(struct file *file,
1479 const char __user *user_buf,
1480 size_t count, loff_t *ppos)
1481{
1482 struct ath10k *ar = file->private_data;
1483 int ret;
1484 u8 enable;
1485
1486 if (kstrtou8_from_user(user_buf, count, 0, &enable))
1487 return -EINVAL;
1488
1489 mutex_lock(&ar->conf_mutex);
1490
1491 if (ar->ani_enabled == enable) {
1492 ret = count;
1493 goto exit;
1494 }
1495
1496 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->ani_enable,
1497 enable);
1498 if (ret) {
1499 ath10k_warn(ar, "ani_enable failed from debugfs: %d\n", ret);
1500 goto exit;
1501 }
1502 ar->ani_enabled = enable;
1503
1504 ret = count;
1505
1506exit:
1507 mutex_unlock(&ar->conf_mutex);
1508
1509 return ret;
1510}
1511
1512static ssize_t ath10k_read_ani_enable(struct file *file, char __user *user_buf,
1513 size_t count, loff_t *ppos)
1514{
1515 struct ath10k *ar = file->private_data;
1516 int len = 0;
1517 char buf[32];
1518
1519 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
1520 ar->ani_enabled);
1521
1522 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1523}
1524
1525static const struct file_operations fops_ani_enable = {
1526 .read = ath10k_read_ani_enable,
1527 .write = ath10k_write_ani_enable,
1528 .open = simple_open,
1529 .owner = THIS_MODULE,
1530 .llseek = default_llseek,
1531};
1532
Kalle Valo7869b4f2014-09-24 14:16:58 +03001533static const struct file_operations fops_cal_data = {
1534 .open = ath10k_debug_cal_data_open,
1535 .read = ath10k_debug_cal_data_read,
1536 .release = ath10k_debug_cal_data_release,
1537 .owner = THIS_MODULE,
1538 .llseek = default_llseek,
1539};
1540
Peter Oha7bd3e92014-12-02 13:07:14 +02001541static ssize_t ath10k_read_nf_cal_period(struct file *file,
1542 char __user *user_buf,
1543 size_t count, loff_t *ppos)
1544{
1545 struct ath10k *ar = file->private_data;
1546 unsigned int len;
1547 char buf[32];
1548
1549 len = scnprintf(buf, sizeof(buf), "%d\n",
1550 ar->debug.nf_cal_period);
1551
1552 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1553}
1554
1555static ssize_t ath10k_write_nf_cal_period(struct file *file,
1556 const char __user *user_buf,
1557 size_t count, loff_t *ppos)
1558{
1559 struct ath10k *ar = file->private_data;
1560 unsigned long period;
1561 int ret;
1562
1563 ret = kstrtoul_from_user(user_buf, count, 0, &period);
1564 if (ret)
1565 return ret;
1566
1567 if (period > WMI_PDEV_PARAM_CAL_PERIOD_MAX)
1568 return -EINVAL;
1569
1570 /* there's no way to switch back to the firmware default */
1571 if (period == 0)
1572 return -EINVAL;
1573
1574 mutex_lock(&ar->conf_mutex);
1575
1576 ar->debug.nf_cal_period = period;
1577
1578 if (ar->state != ATH10K_STATE_ON) {
1579 /* firmware is not running, nothing else to do */
1580 ret = count;
1581 goto exit;
1582 }
1583
1584 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->cal_period,
1585 ar->debug.nf_cal_period);
1586 if (ret) {
1587 ath10k_warn(ar, "cal period cfg failed from debugfs: %d\n",
1588 ret);
1589 goto exit;
1590 }
1591
1592 ret = count;
1593
1594exit:
1595 mutex_unlock(&ar->conf_mutex);
1596
1597 return ret;
1598}
1599
1600static const struct file_operations fops_nf_cal_period = {
1601 .read = ath10k_read_nf_cal_period,
1602 .write = ath10k_write_nf_cal_period,
1603 .open = simple_open,
1604 .owner = THIS_MODULE,
1605 .llseek = default_llseek,
1606};
1607
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001608#define ATH10K_TPC_CONFIG_BUF_SIZE (1024 * 1024)
1609
1610static int ath10k_debug_tpc_stats_request(struct ath10k *ar)
1611{
1612 int ret;
1613 unsigned long time_left;
1614
1615 lockdep_assert_held(&ar->conf_mutex);
1616
1617 reinit_completion(&ar->debug.tpc_complete);
1618
1619 ret = ath10k_wmi_pdev_get_tpc_config(ar, WMI_TPC_CONFIG_PARAM);
1620 if (ret) {
1621 ath10k_warn(ar, "failed to request tpc config: %d\n", ret);
1622 return ret;
1623 }
1624
1625 time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
1626 1 * HZ);
1627 if (time_left == 0)
1628 return -ETIMEDOUT;
1629
1630 return 0;
1631}
1632
1633void ath10k_debug_tpc_stats_process(struct ath10k *ar,
1634 struct ath10k_tpc_stats *tpc_stats)
1635{
1636 spin_lock_bh(&ar->data_lock);
1637
1638 kfree(ar->debug.tpc_stats);
1639 ar->debug.tpc_stats = tpc_stats;
1640 complete(&ar->debug.tpc_complete);
1641
1642 spin_unlock_bh(&ar->data_lock);
1643}
1644
1645static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
1646 unsigned int j, char *buf, unsigned int *len)
1647{
1648 unsigned int i, buf_len;
1649 static const char table_str[][5] = { "CDD",
1650 "STBC",
1651 "TXBF" };
1652 static const char pream_str[][6] = { "CCK",
1653 "OFDM",
1654 "HT20",
1655 "HT40",
1656 "VHT20",
1657 "VHT40",
1658 "VHT80",
1659 "HTCUP" };
1660
1661 buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1662 *len += scnprintf(buf + *len, buf_len - *len,
1663 "********************************\n");
1664 *len += scnprintf(buf + *len, buf_len - *len,
1665 "******************* %s POWER TABLE ****************\n",
1666 table_str[j]);
1667 *len += scnprintf(buf + *len, buf_len - *len,
1668 "********************************\n");
1669 *len += scnprintf(buf + *len, buf_len - *len,
1670 "No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3\n");
1671
1672 for (i = 0; i < tpc_stats->rate_max; i++) {
1673 *len += scnprintf(buf + *len, buf_len - *len,
1674 "%8d %s 0x%2x %s\n", i,
1675 pream_str[tpc_stats->tpc_table[j].pream_idx[i]],
1676 tpc_stats->tpc_table[j].rate_code[i],
1677 tpc_stats->tpc_table[j].tpc_value[i]);
1678 }
1679
1680 *len += scnprintf(buf + *len, buf_len - *len,
1681 "***********************************\n");
1682}
1683
1684static void ath10k_tpc_stats_fill(struct ath10k *ar,
1685 struct ath10k_tpc_stats *tpc_stats,
1686 char *buf)
1687{
1688 unsigned int len, j, buf_len;
1689
1690 len = 0;
1691 buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1692
1693 spin_lock_bh(&ar->data_lock);
1694
1695 if (!tpc_stats) {
1696 ath10k_warn(ar, "failed to get tpc stats\n");
1697 goto unlock;
1698 }
1699
1700 len += scnprintf(buf + len, buf_len - len, "\n");
1701 len += scnprintf(buf + len, buf_len - len,
1702 "*************************************\n");
1703 len += scnprintf(buf + len, buf_len - len,
1704 "TPC config for channel %4d mode %d\n",
1705 tpc_stats->chan_freq,
1706 tpc_stats->phy_mode);
1707 len += scnprintf(buf + len, buf_len - len,
1708 "*************************************\n");
1709 len += scnprintf(buf + len, buf_len - len,
1710 "CTL = 0x%2x Reg. Domain = %2d\n",
1711 tpc_stats->ctl,
1712 tpc_stats->reg_domain);
1713 len += scnprintf(buf + len, buf_len - len,
1714 "Antenna Gain = %2d Reg. Max Antenna Gain = %2d\n",
1715 tpc_stats->twice_antenna_gain,
1716 tpc_stats->twice_antenna_reduction);
1717 len += scnprintf(buf + len, buf_len - len,
1718 "Power Limit = %2d Reg. Max Power = %2d\n",
1719 tpc_stats->power_limit,
1720 tpc_stats->twice_max_rd_power / 2);
1721 len += scnprintf(buf + len, buf_len - len,
1722 "Num tx chains = %2d Num supported rates = %2d\n",
1723 tpc_stats->num_tx_chain,
1724 tpc_stats->rate_max);
1725
1726 for (j = 0; j < tpc_stats->num_tx_chain ; j++) {
1727 switch (j) {
1728 case WMI_TPC_TABLE_TYPE_CDD:
1729 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1730 len += scnprintf(buf + len, buf_len - len,
1731 "CDD not supported\n");
1732 break;
1733 }
1734
1735 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1736 break;
1737 case WMI_TPC_TABLE_TYPE_STBC:
1738 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1739 len += scnprintf(buf + len, buf_len - len,
1740 "STBC not supported\n");
1741 break;
1742 }
1743
1744 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1745 break;
1746 case WMI_TPC_TABLE_TYPE_TXBF:
1747 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1748 len += scnprintf(buf + len, buf_len - len,
1749 "TXBF not supported\n***************************\n");
1750 break;
1751 }
1752
1753 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1754 break;
1755 default:
1756 len += scnprintf(buf + len, buf_len - len,
1757 "Invalid Type\n");
1758 break;
1759 }
1760 }
1761
1762unlock:
1763 spin_unlock_bh(&ar->data_lock);
1764
1765 if (len >= buf_len)
1766 buf[len - 1] = 0;
1767 else
1768 buf[len] = 0;
1769}
1770
1771static int ath10k_tpc_stats_open(struct inode *inode, struct file *file)
1772{
1773 struct ath10k *ar = inode->i_private;
1774 void *buf = NULL;
1775 int ret;
1776
1777 mutex_lock(&ar->conf_mutex);
1778
1779 if (ar->state != ATH10K_STATE_ON) {
1780 ret = -ENETDOWN;
1781 goto err_unlock;
1782 }
1783
1784 buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
1785 if (!buf) {
1786 ret = -ENOMEM;
1787 goto err_unlock;
1788 }
1789
1790 ret = ath10k_debug_tpc_stats_request(ar);
1791 if (ret) {
1792 ath10k_warn(ar, "failed to request tpc config stats: %d\n",
1793 ret);
1794 goto err_free;
1795 }
1796
1797 ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
1798 file->private_data = buf;
1799
1800 mutex_unlock(&ar->conf_mutex);
1801 return 0;
1802
1803err_free:
1804 vfree(buf);
1805
1806err_unlock:
1807 mutex_unlock(&ar->conf_mutex);
1808 return ret;
1809}
1810
1811static int ath10k_tpc_stats_release(struct inode *inode, struct file *file)
1812{
1813 vfree(file->private_data);
1814
1815 return 0;
1816}
1817
1818static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf,
1819 size_t count, loff_t *ppos)
1820{
1821 const char *buf = file->private_data;
1822 unsigned int len = strlen(buf);
1823
1824 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1825}
1826
1827static const struct file_operations fops_tpc_stats = {
1828 .open = ath10k_tpc_stats_open,
1829 .release = ath10k_tpc_stats_release,
1830 .read = ath10k_tpc_stats_read,
1831 .owner = THIS_MODULE,
1832 .llseek = default_llseek,
1833};
1834
Kalle Valodb66ea02013-09-03 11:44:03 +03001835int ath10k_debug_start(struct ath10k *ar)
1836{
Kalle Valoa3d135e2013-09-03 11:44:10 +03001837 int ret;
1838
Kalle Valo60631c52013-10-08 21:45:25 +03001839 lockdep_assert_held(&ar->conf_mutex);
1840
Kalle Valoa3d135e2013-09-03 11:44:10 +03001841 ret = ath10k_debug_htt_stats_req(ar);
1842 if (ret)
1843 /* continue normally anyway, this isn't serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001844 ath10k_warn(ar, "failed to start htt stats workqueue: %d\n",
1845 ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001846
Kalle Valof118a3e2014-01-03 12:59:31 +02001847 if (ar->debug.fw_dbglog_mask) {
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301848 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1849 ATH10K_DBGLOG_LEVEL_WARN);
Kalle Valof118a3e2014-01-03 12:59:31 +02001850 if (ret)
1851 /* not serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001852 ath10k_warn(ar, "failed to enable dbglog during start: %d",
Kalle Valof118a3e2014-01-03 12:59:31 +02001853 ret);
1854 }
1855
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001856 if (ar->debug.pktlog_filter) {
1857 ret = ath10k_wmi_pdev_pktlog_enable(ar,
1858 ar->debug.pktlog_filter);
1859 if (ret)
1860 /* not serious */
1861 ath10k_warn(ar,
1862 "failed to enable pktlog filter %x: %d\n",
1863 ar->debug.pktlog_filter, ret);
1864 } else {
1865 ret = ath10k_wmi_pdev_pktlog_disable(ar);
1866 if (ret)
1867 /* not serious */
1868 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
1869 }
1870
Peter Oha7bd3e92014-12-02 13:07:14 +02001871 if (ar->debug.nf_cal_period) {
1872 ret = ath10k_wmi_pdev_set_param(ar,
1873 ar->wmi.pdev_param->cal_period,
1874 ar->debug.nf_cal_period);
1875 if (ret)
1876 /* not serious */
1877 ath10k_warn(ar, "cal period cfg failed from debug start: %d\n",
1878 ret);
1879 }
1880
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001881 return ret;
Kalle Valodb66ea02013-09-03 11:44:03 +03001882}
1883
1884void ath10k_debug_stop(struct ath10k *ar)
1885{
Kalle Valo60631c52013-10-08 21:45:25 +03001886 lockdep_assert_held(&ar->conf_mutex);
1887
1888 /* Must not use _sync to avoid deadlock, we do that in
1889 * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid
1890 * warning from del_timer(). */
1891 if (ar->debug.htt_stats_mask != 0)
1892 cancel_delayed_work(&ar->debug.htt_stats_dwork);
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001893
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001894 ath10k_wmi_pdev_pktlog_disable(ar);
Kalle Valodb66ea02013-09-03 11:44:03 +03001895}
1896
Janusz Dziedzic9702c682013-11-20 09:59:41 +02001897static ssize_t ath10k_write_simulate_radar(struct file *file,
1898 const char __user *user_buf,
1899 size_t count, loff_t *ppos)
1900{
1901 struct ath10k *ar = file->private_data;
1902
1903 ieee80211_radar_detected(ar->hw);
1904
1905 return count;
1906}
1907
1908static const struct file_operations fops_simulate_radar = {
1909 .write = ath10k_write_simulate_radar,
1910 .open = simple_open,
1911 .owner = THIS_MODULE,
1912 .llseek = default_llseek,
1913};
1914
1915#define ATH10K_DFS_STAT(s, p) (\
1916 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
1917 ar->debug.dfs_stats.p))
1918
1919#define ATH10K_DFS_POOL_STAT(s, p) (\
1920 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
1921 ar->debug.dfs_pool_stats.p))
1922
1923static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf,
1924 size_t count, loff_t *ppos)
1925{
1926 int retval = 0, len = 0;
1927 const int size = 8000;
1928 struct ath10k *ar = file->private_data;
1929 char *buf;
1930
1931 buf = kzalloc(size, GFP_KERNEL);
1932 if (buf == NULL)
1933 return -ENOMEM;
1934
1935 if (!ar->dfs_detector) {
1936 len += scnprintf(buf + len, size - len, "DFS not enabled\n");
1937 goto exit;
1938 }
1939
1940 ar->debug.dfs_pool_stats =
1941 ar->dfs_detector->get_stats(ar->dfs_detector);
1942
1943 len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");
1944
1945 ATH10K_DFS_STAT("reported phy errors", phy_errors);
1946 ATH10K_DFS_STAT("pulse events reported", pulses_total);
1947 ATH10K_DFS_STAT("DFS pulses detected", pulses_detected);
1948 ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded);
1949 ATH10K_DFS_STAT("Radars detected", radar_detected);
1950
1951 len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");
1952 ATH10K_DFS_POOL_STAT("Pool references", pool_reference);
1953 ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated);
1954 ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error);
1955 ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used);
1956 ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated);
1957 ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error);
1958 ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used);
1959
1960exit:
1961 if (len > size)
1962 len = size;
1963
1964 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1965 kfree(buf);
1966
1967 return retval;
1968}
1969
1970static const struct file_operations fops_dfs_stats = {
1971 .read = ath10k_read_dfs_stats,
1972 .open = simple_open,
1973 .owner = THIS_MODULE,
1974 .llseek = default_llseek,
1975};
1976
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001977static ssize_t ath10k_write_pktlog_filter(struct file *file,
1978 const char __user *ubuf,
1979 size_t count, loff_t *ppos)
1980{
1981 struct ath10k *ar = file->private_data;
1982 u32 filter;
1983 int ret;
1984
1985 if (kstrtouint_from_user(ubuf, count, 0, &filter))
1986 return -EINVAL;
1987
1988 mutex_lock(&ar->conf_mutex);
1989
1990 if (ar->state != ATH10K_STATE_ON) {
1991 ar->debug.pktlog_filter = filter;
1992 ret = count;
1993 goto out;
1994 }
1995
1996 if (filter && (filter != ar->debug.pktlog_filter)) {
1997 ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
1998 if (ret) {
1999 ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
2000 ar->debug.pktlog_filter, ret);
2001 goto out;
2002 }
2003 } else {
2004 ret = ath10k_wmi_pdev_pktlog_disable(ar);
2005 if (ret) {
2006 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
2007 goto out;
2008 }
2009 }
2010
2011 ar->debug.pktlog_filter = filter;
2012 ret = count;
2013
2014out:
2015 mutex_unlock(&ar->conf_mutex);
2016 return ret;
2017}
2018
2019static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf,
2020 size_t count, loff_t *ppos)
2021{
2022 char buf[32];
2023 struct ath10k *ar = file->private_data;
2024 int len = 0;
2025
2026 mutex_lock(&ar->conf_mutex);
2027 len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
2028 ar->debug.pktlog_filter);
2029 mutex_unlock(&ar->conf_mutex);
2030
2031 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2032}
2033
2034static const struct file_operations fops_pktlog_filter = {
2035 .read = ath10k_read_pktlog_filter,
2036 .write = ath10k_write_pktlog_filter,
2037 .open = simple_open
2038};
2039
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302040static ssize_t ath10k_write_quiet_period(struct file *file,
2041 const char __user *ubuf,
2042 size_t count, loff_t *ppos)
2043{
2044 struct ath10k *ar = file->private_data;
2045 u32 period;
2046
2047 if (kstrtouint_from_user(ubuf, count, 0, &period))
2048 return -EINVAL;
2049
2050 if (period < ATH10K_QUIET_PERIOD_MIN) {
2051 ath10k_warn(ar, "Quiet period %u can not be lesser than 25ms\n",
2052 period);
2053 return -EINVAL;
2054 }
2055 mutex_lock(&ar->conf_mutex);
2056 ar->thermal.quiet_period = period;
Rajkumar Manoharan8515b5c2015-03-15 20:36:22 +05302057 ath10k_thermal_set_throttling(ar);
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302058 mutex_unlock(&ar->conf_mutex);
2059
2060 return count;
2061}
2062
2063static ssize_t ath10k_read_quiet_period(struct file *file, char __user *ubuf,
2064 size_t count, loff_t *ppos)
2065{
2066 char buf[32];
2067 struct ath10k *ar = file->private_data;
2068 int len = 0;
2069
2070 mutex_lock(&ar->conf_mutex);
2071 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2072 ar->thermal.quiet_period);
2073 mutex_unlock(&ar->conf_mutex);
2074
2075 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2076}
2077
2078static const struct file_operations fops_quiet_period = {
2079 .read = ath10k_read_quiet_period,
2080 .write = ath10k_write_quiet_period,
2081 .open = simple_open
2082};
2083
Yanbo Li844fa572015-10-31 11:07:21 +02002084static ssize_t ath10k_write_btcoex(struct file *file,
2085 const char __user *ubuf,
2086 size_t count, loff_t *ppos)
2087{
2088 struct ath10k *ar = file->private_data;
2089 char buf[32];
2090 size_t buf_size;
2091 bool val;
2092
2093 buf_size = min(count, (sizeof(buf) - 1));
2094 if (copy_from_user(buf, ubuf, buf_size))
2095 return -EFAULT;
2096
2097 buf[buf_size] = '\0';
2098
2099 if (strtobool(buf, &val) != 0)
2100 return -EINVAL;
2101
2102 mutex_lock(&ar->conf_mutex);
2103
2104 if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val))
2105 goto exit;
2106
2107 if (val)
2108 set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
2109 else
2110 clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
2111
2112 if (ar->state != ATH10K_STATE_ON)
2113 goto exit;
2114
2115 ath10k_info(ar, "restarting firmware due to btcoex change");
2116
2117 queue_work(ar->workqueue, &ar->restart_work);
2118
2119exit:
2120 mutex_unlock(&ar->conf_mutex);
2121
2122 return count;
2123}
2124
2125static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
2126 size_t count, loff_t *ppos)
2127{
2128 char buf[32];
2129 struct ath10k *ar = file->private_data;
2130 int len = 0;
2131
2132 mutex_lock(&ar->conf_mutex);
2133 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2134 test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));
2135 mutex_unlock(&ar->conf_mutex);
2136
2137 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2138}
2139
2140static const struct file_operations fops_btcoex = {
2141 .read = ath10k_read_btcoex,
2142 .write = ath10k_write_btcoex,
2143 .open = simple_open
2144};
2145
Kalle Valo5e3dd152013-06-12 20:52:10 +03002146int ath10k_debug_create(struct ath10k *ar)
2147{
Ben Greear384914b2014-08-25 08:37:32 +03002148 ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002149 if (!ar->debug.fw_crash_data)
2150 return -ENOMEM;
Ben Greear384914b2014-08-25 08:37:32 +03002151
Michal Kazior53268492014-09-25 12:33:50 +02002152 INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +02002153 INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +02002154 INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
2155
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002156 return 0;
2157}
2158
2159void ath10k_debug_destroy(struct ath10k *ar)
2160{
2161 vfree(ar->debug.fw_crash_data);
2162 ar->debug.fw_crash_data = NULL;
Michal Kazior53268492014-09-25 12:33:50 +02002163
2164 ath10k_debug_fw_stats_reset(ar);
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002165
2166 kfree(ar->debug.tpc_stats);
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002167}
2168
2169int ath10k_debug_register(struct ath10k *ar)
2170{
Kalle Valo5e3dd152013-06-12 20:52:10 +03002171 ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
2172 ar->hw->wiphy->debugfsdir);
Michal Kazioradb43b22014-09-04 12:36:45 +02002173 if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
2174 if (IS_ERR(ar->debug.debugfs_phy))
2175 return PTR_ERR(ar->debug.debugfs_phy);
Kalle Valod8bb26b2014-09-14 12:50:33 +03002176
2177 return -ENOMEM;
Michal Kazioradb43b22014-09-04 12:36:45 +02002178 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03002179
Kalle Valoa3d135e2013-09-03 11:44:10 +03002180 INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
2181 ath10k_debug_htt_stats_dwork);
2182
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002183 init_completion(&ar->debug.tpc_complete);
Michal Kazior60ef4012014-09-25 12:33:48 +02002184 init_completion(&ar->debug.fw_stats_complete);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002185
2186 debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
2187 &fops_fw_stats);
2188
Ben Greearf51dbe72014-09-29 14:41:46 +03002189 debugfs_create_file("fw_reset_stats", S_IRUSR, ar->debug.debugfs_phy,
2190 ar, &fops_fw_reset_stats);
2191
Kalle Valo5e3dd152013-06-12 20:52:10 +03002192 debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
2193 &fops_wmi_services);
2194
Mohammed Shafi Shajakhan8bf1ba12015-11-24 22:26:37 +05302195 debugfs_create_file("simulate_fw_crash", S_IRUSR | S_IWUSR,
2196 ar->debug.debugfs_phy, ar, &fops_simulate_fw_crash);
Michal Kazior278c4a82013-07-22 14:08:51 +02002197
Ben Greear384914b2014-08-25 08:37:32 +03002198 debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
2199 ar, &fops_fw_crash_dump);
2200
Yanbo Li077a3802014-11-25 12:24:33 +02002201 debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR,
2202 ar->debug.debugfs_phy, ar, &fops_reg_addr);
2203
2204 debugfs_create_file("reg_value", S_IRUSR | S_IWUSR,
2205 ar->debug.debugfs_phy, ar, &fops_reg_value);
2206
Yanbo Li9f65ad22014-11-25 12:24:48 +02002207 debugfs_create_file("mem_value", S_IRUSR | S_IWUSR,
2208 ar->debug.debugfs_phy, ar, &fops_mem_value);
2209
Kalle Valo763b8cd2013-09-01 11:22:21 +03002210 debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
2211 ar, &fops_chip_id);
2212
Mohammed Shafi Shajakhan8bf1ba12015-11-24 22:26:37 +05302213 debugfs_create_file("htt_stats_mask", S_IRUSR | S_IWUSR,
2214 ar->debug.debugfs_phy, ar, &fops_htt_stats_mask);
Kalle Valoa3d135e2013-09-03 11:44:10 +03002215
Janusz Dziedzicd3856232014-06-02 21:19:46 +03002216 debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
2217 ar->debug.debugfs_phy, ar,
2218 &fops_htt_max_amsdu_ampdu);
2219
Mohammed Shafi Shajakhan8bf1ba12015-11-24 22:26:37 +05302220 debugfs_create_file("fw_dbglog", S_IRUSR | S_IWUSR,
2221 ar->debug.debugfs_phy, ar, &fops_fw_dbglog);
Kalle Valof118a3e2014-01-03 12:59:31 +02002222
Kalle Valo7869b4f2014-09-24 14:16:58 +03002223 debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
2224 ar, &fops_cal_data);
2225
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05302226 debugfs_create_file("ani_enable", S_IRUSR | S_IWUSR,
2227 ar->debug.debugfs_phy, ar, &fops_ani_enable);
2228
Peter Oha7bd3e92014-12-02 13:07:14 +02002229 debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR,
2230 ar->debug.debugfs_phy, ar, &fops_nf_cal_period);
2231
Janusz Dziedzic9702c682013-11-20 09:59:41 +02002232 if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
2233 debugfs_create_file("dfs_simulate_radar", S_IWUSR,
2234 ar->debug.debugfs_phy, ar,
2235 &fops_simulate_radar);
2236
Marek Puzyniak7d9b40b2013-11-20 10:00:28 +02002237 debugfs_create_bool("dfs_block_radar_events", S_IWUSR,
2238 ar->debug.debugfs_phy,
2239 &ar->dfs_block_radar_events);
2240
Janusz Dziedzic9702c682013-11-20 09:59:41 +02002241 debugfs_create_file("dfs_stats", S_IRUSR,
2242 ar->debug.debugfs_phy, ar,
2243 &fops_dfs_stats);
2244 }
2245
Rajkumar Manoharan90174452014-10-03 08:02:33 +03002246 debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR,
2247 ar->debug.debugfs_phy, ar, &fops_pktlog_filter);
2248
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302249 debugfs_create_file("quiet_period", S_IRUGO | S_IWUSR,
2250 ar->debug.debugfs_phy, ar, &fops_quiet_period);
2251
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002252 debugfs_create_file("tpc_stats", S_IRUSR,
2253 ar->debug.debugfs_phy, ar, &fops_tpc_stats);
2254
Yanbo Li844fa572015-10-31 11:07:21 +02002255 if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
2256 debugfs_create_file("btcoex", S_IRUGO | S_IWUSR,
2257 ar->debug.debugfs_phy, ar, &fops_btcoex);
2258
Kalle Valo5e3dd152013-06-12 20:52:10 +03002259 return 0;
2260}
Kalle Valodb66ea02013-09-03 11:44:03 +03002261
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002262void ath10k_debug_unregister(struct ath10k *ar)
Kalle Valo60631c52013-10-08 21:45:25 +03002263{
2264 cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
2265}
2266
Kalle Valo5e3dd152013-06-12 20:52:10 +03002267#endif /* CONFIG_ATH10K_DEBUGFS */
2268
2269#ifdef CONFIG_ATH10K_DEBUG
Michal Kazior7aa7a722014-08-25 12:09:38 +02002270void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
2271 const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +03002272{
2273 struct va_format vaf;
2274 va_list args;
2275
2276 va_start(args, fmt);
2277
2278 vaf.fmt = fmt;
2279 vaf.va = &args;
2280
2281 if (ath10k_debug_mask & mask)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002282 dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002283
Michal Kaziord35a6c12014-09-02 11:00:21 +03002284 trace_ath10k_log_dbg(ar, mask, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002285
2286 va_end(args);
2287}
2288EXPORT_SYMBOL(ath10k_dbg);
2289
Michal Kazior7aa7a722014-08-25 12:09:38 +02002290void ath10k_dbg_dump(struct ath10k *ar,
2291 enum ath10k_debug_mask mask,
Kalle Valo5e3dd152013-06-12 20:52:10 +03002292 const char *msg, const char *prefix,
2293 const void *buf, size_t len)
2294{
Michal Kazior45724a82014-09-23 10:22:53 +02002295 char linebuf[256];
2296 unsigned int linebuflen;
2297 const void *ptr;
2298
Kalle Valo5e3dd152013-06-12 20:52:10 +03002299 if (ath10k_debug_mask & mask) {
2300 if (msg)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002301 ath10k_dbg(ar, mask, "%s\n", msg);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002302
Michal Kazior45724a82014-09-23 10:22:53 +02002303 for (ptr = buf; (ptr - buf) < len; ptr += 16) {
2304 linebuflen = 0;
2305 linebuflen += scnprintf(linebuf + linebuflen,
2306 sizeof(linebuf) - linebuflen,
2307 "%s%08x: ",
2308 (prefix ? prefix : ""),
2309 (unsigned int)(ptr - buf));
2310 hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
2311 linebuf + linebuflen,
2312 sizeof(linebuf) - linebuflen, true);
2313 dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
2314 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03002315 }
2316
2317 /* tracing code doesn't like null strings :/ */
Michal Kaziord35a6c12014-09-02 11:00:21 +03002318 trace_ath10k_log_dbg_dump(ar, msg ? msg : "", prefix ? prefix : "",
Kalle Valo5e3dd152013-06-12 20:52:10 +03002319 buf, len);
2320}
2321EXPORT_SYMBOL(ath10k_dbg_dump);
2322
2323#endif /* CONFIG_ATH10K_DEBUG */