blob: b882b0892dcfa7b235764c32db137a19a3f29898 [file] [log] [blame]
Kalle Valo5e3dd152013-06-12 20:52:10 +03001/*
2 * Copyright (c) 2005-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <linux/module.h>
19#include <linux/debugfs.h>
Ben Greear384914b2014-08-25 08:37:32 +030020#include <linux/vmalloc.h>
Johannes Berg12c27152014-11-21 18:58:49 +020021#include <linux/utsname.h>
Kalle Valo3e580442015-11-25 15:38:34 +020022#include <linux/crc32.h>
23#include <linux/firmware.h>
Arun Khandavalli727000e2016-12-21 14:19:21 +020024#include <linux/devcoredump.h>
Kalle Valo5e3dd152013-06-12 20:52:10 +030025
26#include "core.h"
27#include "debug.h"
Kalle Valo7869b4f2014-09-24 14:16:58 +030028#include "hif.h"
Michal Kaziord7579d12014-12-03 10:10:54 +020029#include "wmi-ops.h"
Kalle Valo5e3dd152013-06-12 20:52:10 +030030
Kalle Valoa3d135e2013-09-03 11:44:10 +030031/* ms */
32#define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
33
Marty Faltesekf67b107d2016-10-10 19:00:04 +030034#define ATH10K_DEBUG_CAL_DATA_LEN 12064
35
Ben Greear384914b2014-08-25 08:37:32 +030036#define ATH10K_FW_CRASH_DUMP_VERSION 1
37
38/**
39 * enum ath10k_fw_crash_dump_type - types of data in the dump file
40 * @ATH10K_FW_CRASH_DUMP_REGDUMP: Register crash dump in binary format
41 */
42enum ath10k_fw_crash_dump_type {
43 ATH10K_FW_CRASH_DUMP_REGISTERS = 0,
44
45 ATH10K_FW_CRASH_DUMP_MAX,
46};
47
48struct ath10k_tlv_dump_data {
49 /* see ath10k_fw_crash_dump_type above */
50 __le32 type;
51
52 /* in bytes */
53 __le32 tlv_len;
54
55 /* pad to 32-bit boundaries as needed */
56 u8 tlv_data[];
57} __packed;
58
59struct ath10k_dump_file_data {
60 /* dump file information */
61
62 /* "ATH10K-FW-DUMP" */
63 char df_magic[16];
64
65 __le32 len;
66
67 /* file dump version */
68 __le32 version;
69
70 /* some info we can get from ath10k struct that might help */
71
72 u8 uuid[16];
73
74 __le32 chip_id;
75
76 /* 0 for now, in place for later hardware */
77 __le32 bus_type;
78
79 __le32 target_version;
80 __le32 fw_version_major;
81 __le32 fw_version_minor;
82 __le32 fw_version_release;
83 __le32 fw_version_build;
84 __le32 phy_capability;
85 __le32 hw_min_tx_power;
86 __le32 hw_max_tx_power;
87 __le32 ht_cap_info;
88 __le32 vht_cap_info;
89 __le32 num_rf_chains;
90
91 /* firmware version string */
92 char fw_ver[ETHTOOL_FWVERS_LEN];
93
94 /* Kernel related information */
95
96 /* time-of-day stamp */
97 __le64 tv_sec;
98
99 /* time-of-day stamp, nano-seconds */
100 __le64 tv_nsec;
101
102 /* LINUX_VERSION_CODE */
103 __le32 kernel_ver_code;
104
105 /* VERMAGIC_STRING */
106 char kernel_ver[64];
107
108 /* room for growth w/out changing binary format */
109 u8 unused[128];
110
111 /* struct ath10k_tlv_dump_data + more */
112 u8 data[0];
113} __packed;
114
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700115void ath10k_info(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300116{
117 struct va_format vaf = {
118 .fmt = fmt,
119 };
120 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300121
122 va_start(args, fmt);
123 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700124 dev_info(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300125 trace_ath10k_log_info(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300126 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300127}
128EXPORT_SYMBOL(ath10k_info);
129
Kalle Valo23f591e2015-11-25 15:38:27 +0200130void ath10k_debug_print_hwfw_info(struct ath10k *ar)
Kalle Valo8a0c7972014-08-25 08:37:45 +0300131{
Kalle Valo7ebf7212016-04-20 19:44:51 +0300132 const struct firmware *firmware;
Michal Kazior84e3df62015-08-05 06:55:37 +0200133 char fw_features[128] = {};
Michal Kazior8866c722016-03-17 10:52:08 +0100134 u32 crc = 0;
Michal Kaziorb27bc5a2015-06-15 14:46:40 +0300135
136 ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
137
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
Kalle Valof0de90b2015-11-25 15:38:12 +0200144 ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n",
Masahiro Yamada97f26452016-08-03 13:45:50 -0700145 IS_ENABLED(CONFIG_ATH10K_DEBUG),
146 IS_ENABLED(CONFIG_ATH10K_DEBUGFS),
147 IS_ENABLED(CONFIG_ATH10K_TRACING),
148 IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED),
149 IS_ENABLED(CONFIG_NL80211_TESTMODE));
Kalle Valof0de90b2015-11-25 15:38:12 +0200150
Kalle Valo7ebf7212016-04-20 19:44:51 +0300151 firmware = ar->normal_mode_fw.fw_file.firmware;
152 if (firmware)
153 crc = crc32_le(0, firmware->data, firmware->size);
Michal Kazior8866c722016-03-17 10:52:08 +0100154
Kalle Valo3e580442015-11-25 15:38:34 +0200155 ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",
Kalle Valo23f591e2015-11-25 15:38:27 +0200156 ar->hw->wiphy->fw_version,
157 ar->fw_api,
Kalle Valo3e580442015-11-25 15:38:34 +0200158 fw_features,
Michal Kazior8866c722016-03-17 10:52:08 +0100159 crc);
Kalle Valo23f591e2015-11-25 15:38:27 +0200160}
161
162void ath10k_debug_print_board_info(struct ath10k *ar)
163{
164 char boardinfo[100];
165
166 if (ar->id.bmi_ids_valid)
167 scnprintf(boardinfo, sizeof(boardinfo), "%d:%d",
168 ar->id.bmi_chip_id, ar->id.bmi_board_id);
169 else
170 scnprintf(boardinfo, sizeof(boardinfo), "N/A");
171
Kalle Valo3e580442015-11-25 15:38:34 +0200172 ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x",
Kalle Valo23f591e2015-11-25 15:38:27 +0200173 ar->bd_api,
Kalle Valo3e580442015-11-25 15:38:34 +0200174 boardinfo,
Kalle Valo7ebf7212016-04-20 19:44:51 +0300175 crc32_le(0, ar->normal_mode_fw.board->data,
176 ar->normal_mode_fw.board->size));
Kalle Valo23f591e2015-11-25 15:38:27 +0200177}
178
179void ath10k_debug_print_boot_info(struct ath10k *ar)
180{
Kalle Valof0de90b2015-11-25 15:38:12 +0200181 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 +0300182 ar->htt.target_version_major,
Michal Kazior34b28b62014-09-23 10:22:52 +0200183 ar->htt.target_version_minor,
Kalle Valobf3c13a2016-04-20 19:45:33 +0300184 ar->normal_mode_fw.fw_file.wmi_op_version,
Kalle Valo77561f92016-04-20 19:45:47 +0300185 ar->normal_mode_fw.fw_file.htt_op_version,
Michal Kaziorcfd10612014-11-25 15:16:05 +0100186 ath10k_cal_mode_str(ar->cal_mode),
Michal Kaziorb27bc5a2015-06-15 14:46:40 +0300187 ar->max_num_stations,
David Liuccec9032015-07-24 20:25:32 +0300188 test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
Kalle Valof0de90b2015-11-25 15:38:12 +0200189 !test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags));
Kalle Valo8a0c7972014-08-25 08:37:45 +0300190}
Kalle Valo23f591e2015-11-25 15:38:27 +0200191
192void ath10k_print_driver_info(struct ath10k *ar)
193{
194 ath10k_debug_print_hwfw_info(ar);
195 ath10k_debug_print_board_info(ar);
196 ath10k_debug_print_boot_info(ar);
197}
Kalle Valo8a0c7972014-08-25 08:37:45 +0300198EXPORT_SYMBOL(ath10k_print_driver_info);
199
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700200void ath10k_err(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300201{
202 struct va_format vaf = {
203 .fmt = fmt,
204 };
205 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300206
207 va_start(args, fmt);
208 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700209 dev_err(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300210 trace_ath10k_log_err(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300211 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300212}
213EXPORT_SYMBOL(ath10k_err);
214
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700215void ath10k_warn(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300216{
217 struct va_format vaf = {
218 .fmt = fmt,
219 };
220 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300221
222 va_start(args, fmt);
223 vaf.va = &args;
Michal Kazior7aa7a722014-08-25 12:09:38 +0200224 dev_warn_ratelimited(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300225 trace_ath10k_log_warn(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300226
227 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300228}
229EXPORT_SYMBOL(ath10k_warn);
230
231#ifdef CONFIG_ATH10K_DEBUGFS
232
Kalle Valo5e3dd152013-06-12 20:52:10 +0300233static ssize_t ath10k_read_wmi_services(struct file *file,
234 char __user *user_buf,
235 size_t count, loff_t *ppos)
236{
237 struct ath10k *ar = file->private_data;
238 char *buf;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300239 unsigned int len = 0, buf_len = 4096;
240 const char *name;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300241 ssize_t ret_cnt;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300242 bool enabled;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300243 int i;
244
245 buf = kzalloc(buf_len, GFP_KERNEL);
246 if (!buf)
247 return -ENOMEM;
248
249 mutex_lock(&ar->conf_mutex);
250
251 if (len > buf_len)
252 len = buf_len;
253
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100254 spin_lock_bh(&ar->data_lock);
Michal Kaziorc4f8c832014-09-04 10:18:32 +0200255 for (i = 0; i < WMI_SERVICE_MAX; i++) {
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100256 enabled = test_bit(i, ar->wmi.svc_map);
Michal Kaziorcff990c2014-08-04 09:18:33 +0300257 name = wmi_service_name(i);
258
259 if (!name) {
260 if (enabled)
261 len += scnprintf(buf + len, buf_len - len,
262 "%-40s %s (bit %d)\n",
263 "unknown", "enabled", i);
264
265 continue;
266 }
Kalle Valo5e3dd152013-06-12 20:52:10 +0300267
268 len += scnprintf(buf + len, buf_len - len,
Michal Kaziorcff990c2014-08-04 09:18:33 +0300269 "%-40s %s\n",
270 name, enabled ? "enabled" : "-");
Kalle Valo5e3dd152013-06-12 20:52:10 +0300271 }
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100272 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300273
274 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
275
276 mutex_unlock(&ar->conf_mutex);
277
278 kfree(buf);
279 return ret_cnt;
280}
281
282static const struct file_operations fops_wmi_services = {
283 .read = ath10k_read_wmi_services,
284 .open = simple_open,
285 .owner = THIS_MODULE,
286 .llseek = default_llseek,
287};
288
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530289static void ath10k_fw_stats_pdevs_free(struct list_head *head)
Michal Kazior53268492014-09-25 12:33:50 +0200290{
291 struct ath10k_fw_stats_pdev *i, *tmp;
292
293 list_for_each_entry_safe(i, tmp, head, list) {
294 list_del(&i->list);
295 kfree(i);
296 }
297}
298
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530299static void ath10k_fw_stats_vdevs_free(struct list_head *head)
Michal Kazior7b6b1532015-02-15 16:50:40 +0200300{
301 struct ath10k_fw_stats_vdev *i, *tmp;
302
303 list_for_each_entry_safe(i, tmp, head, list) {
304 list_del(&i->list);
305 kfree(i);
306 }
307}
308
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530309static void ath10k_fw_stats_peers_free(struct list_head *head)
Michal Kazior53268492014-09-25 12:33:50 +0200310{
311 struct ath10k_fw_stats_peer *i, *tmp;
312
313 list_for_each_entry_safe(i, tmp, head, list) {
314 list_del(&i->list);
315 kfree(i);
316 }
317}
318
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300319static void ath10k_fw_extd_stats_peers_free(struct list_head *head)
320{
321 struct ath10k_fw_extd_stats_peer *i, *tmp;
322
323 list_for_each_entry_safe(i, tmp, head, list) {
324 list_del(&i->list);
325 kfree(i);
326 }
327}
328
Michal Kazior53268492014-09-25 12:33:50 +0200329static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
330{
331 spin_lock_bh(&ar->data_lock);
332 ar->debug.fw_stats_done = false;
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300333 ar->debug.fw_stats.extended = false;
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530334 ath10k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
335 ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
336 ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300337 ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +0200338 spin_unlock_bh(&ar->data_lock);
339}
340
Michal Kazior60ef4012014-09-25 12:33:48 +0200341void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300342{
Michal Kazior53268492014-09-25 12:33:50 +0200343 struct ath10k_fw_stats stats = {};
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +0530344 bool is_start, is_started, is_end;
Michal Kazior53268492014-09-25 12:33:50 +0200345 size_t num_peers;
Michal Kazior7b6b1532015-02-15 16:50:40 +0200346 size_t num_vdevs;
Michal Kaziord15fb522014-09-25 12:33:47 +0200347 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300348
Michal Kazior53268492014-09-25 12:33:50 +0200349 INIT_LIST_HEAD(&stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200350 INIT_LIST_HEAD(&stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200351 INIT_LIST_HEAD(&stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300352 INIT_LIST_HEAD(&stats.peers_extd);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300353
Michal Kazior53268492014-09-25 12:33:50 +0200354 spin_lock_bh(&ar->data_lock);
355 ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
Michal Kaziord15fb522014-09-25 12:33:47 +0200356 if (ret) {
357 ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
Raja Mani5db879a2015-07-09 14:19:43 +0530358 goto free;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300359 }
360
Michal Kazior53268492014-09-25 12:33:50 +0200361 /* Stat data may exceed htc-wmi buffer limit. In such case firmware
362 * splits the stats data and delivers it in a ping-pong fashion of
363 * request cmd-update event.
364 *
365 * However there is no explicit end-of-data. Instead start-of-data is
366 * used as an implicit one. This works as follows:
367 * a) discard stat update events until one with pdev stats is
368 * delivered - this skips session started at end of (b)
369 * b) consume stat update events until another one with pdev stats is
370 * delivered which is treated as end-of-data and is itself discarded
371 */
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +0530372 if (ath10k_peer_stats_enabled(ar))
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300373 ath10k_sta_update_rx_duration(ar, &stats);
Mohammed Shafi Shajakhan74135f52016-02-03 21:07:42 +0530374
Mohammed Shafi Shajakhane0b6ce02016-02-03 21:07:43 +0530375 if (ar->debug.fw_stats_done) {
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +0530376 if (!ath10k_peer_stats_enabled(ar))
Mohammed Shafi Shajakhane0b6ce02016-02-03 21:07:43 +0530377 ath10k_warn(ar, "received unsolicited stats update event\n");
378
Michal Kazior53268492014-09-25 12:33:50 +0200379 goto free;
380 }
381
Manikanta Pubbisettybc6f9ae2015-10-16 15:54:52 +0300382 num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers);
383 num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200384 is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
385 !list_empty(&stats.pdevs));
386 is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
387 !list_empty(&stats.pdevs));
388
389 if (is_start)
390 list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
391
392 if (is_end)
393 ar->debug.fw_stats_done = true;
394
395 is_started = !list_empty(&ar->debug.fw_stats.pdevs);
396
397 if (is_started && !is_end) {
398 if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) {
399 /* Although this is unlikely impose a sane limit to
400 * prevent firmware from DoS-ing the host.
401 */
Mohammed Shafi Shajakhand57e7f22016-01-13 21:16:32 +0530402 ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
Christian Lamparterc1e33302016-12-05 22:52:45 +0100403 ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +0200404 ath10k_warn(ar, "dropping fw peer stats\n");
405 goto free;
406 }
407
Michal Kazior7b6b1532015-02-15 16:50:40 +0200408 if (num_vdevs >= BITS_PER_LONG) {
Mohammed Shafi Shajakhand57e7f22016-01-13 21:16:32 +0530409 ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200410 ath10k_warn(ar, "dropping fw vdev stats\n");
411 goto free;
412 }
413
Christian Lamparterc1e33302016-12-05 22:52:45 +0100414 if (!list_empty(&stats.peers))
415 list_splice_tail_init(&stats.peers_extd,
416 &ar->debug.fw_stats.peers_extd);
417
Michal Kazior53268492014-09-25 12:33:50 +0200418 list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200419 list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200420 }
421
Michal Kazior60ef4012014-09-25 12:33:48 +0200422 complete(&ar->debug.fw_stats_complete);
Michal Kaziord15fb522014-09-25 12:33:47 +0200423
Michal Kazior53268492014-09-25 12:33:50 +0200424free:
425 /* In some cases lists have been spliced and cleared. Free up
426 * resources if that is not the case.
427 */
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530428 ath10k_fw_stats_pdevs_free(&stats.pdevs);
429 ath10k_fw_stats_vdevs_free(&stats.vdevs);
430 ath10k_fw_stats_peers_free(&stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300431 ath10k_fw_extd_stats_peers_free(&stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +0200432
Michal Kaziord15fb522014-09-25 12:33:47 +0200433 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300434}
435
Michal Kazior53268492014-09-25 12:33:50 +0200436static int ath10k_debug_fw_stats_request(struct ath10k *ar)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300437{
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300438 unsigned long timeout, time_left;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300439 int ret;
440
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200441 lockdep_assert_held(&ar->conf_mutex);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300442
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300443 timeout = jiffies + msecs_to_jiffies(1 * HZ);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300444
Michal Kazior53268492014-09-25 12:33:50 +0200445 ath10k_debug_fw_stats_reset(ar);
446
447 for (;;) {
448 if (time_after(jiffies, timeout))
449 return -ETIMEDOUT;
450
451 reinit_completion(&ar->debug.fw_stats_complete);
452
Yanbo Li6274cd42015-04-01 22:53:21 +0300453 ret = ath10k_wmi_request_stats(ar, ar->fw_stats_req_mask);
Michal Kazior53268492014-09-25 12:33:50 +0200454 if (ret) {
455 ath10k_warn(ar, "could not request stats (%d)\n", ret);
456 return ret;
457 }
458
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300459 time_left =
460 wait_for_completion_timeout(&ar->debug.fw_stats_complete,
461 1 * HZ);
462 if (!time_left)
Michal Kazior53268492014-09-25 12:33:50 +0200463 return -ETIMEDOUT;
464
465 spin_lock_bh(&ar->data_lock);
466 if (ar->debug.fw_stats_done) {
467 spin_unlock_bh(&ar->data_lock);
468 break;
469 }
470 spin_unlock_bh(&ar->data_lock);
471 }
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200472
473 return 0;
474}
475
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200476static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
477{
478 struct ath10k *ar = inode->i_private;
479 void *buf = NULL;
480 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300481
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200482 mutex_lock(&ar->conf_mutex);
483
484 if (ar->state != ATH10K_STATE_ON) {
485 ret = -ENETDOWN;
486 goto err_unlock;
487 }
488
489 buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);
490 if (!buf) {
491 ret = -ENOMEM;
492 goto err_unlock;
493 }
494
Michal Kazior53268492014-09-25 12:33:50 +0200495 ret = ath10k_debug_fw_stats_request(ar);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200496 if (ret) {
497 ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
498 goto err_free;
499 }
500
Manikanta Pubbisettybc6f9ae2015-10-16 15:54:52 +0300501 ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
502 if (ret) {
503 ath10k_warn(ar, "failed to fill fw stats: %d\n", ret);
504 goto err_free;
505 }
506
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200507 file->private_data = buf;
508
Kalle Valo5e3dd152013-06-12 20:52:10 +0300509 mutex_unlock(&ar->conf_mutex);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200510 return 0;
511
512err_free:
513 vfree(buf);
514
515err_unlock:
516 mutex_unlock(&ar->conf_mutex);
517 return ret;
518}
519
520static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
521{
522 vfree(file->private_data);
523
524 return 0;
525}
526
527static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
528 size_t count, loff_t *ppos)
529{
530 const char *buf = file->private_data;
531 unsigned int len = strlen(buf);
532
533 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300534}
535
536static const struct file_operations fops_fw_stats = {
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200537 .open = ath10k_fw_stats_open,
538 .release = ath10k_fw_stats_release,
Michal Kazior60ef4012014-09-25 12:33:48 +0200539 .read = ath10k_fw_stats_read,
Kalle Valo5e3dd152013-06-12 20:52:10 +0300540 .owner = THIS_MODULE,
541 .llseek = default_llseek,
542};
543
Ben Greearf51dbe72014-09-29 14:41:46 +0300544static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
545 char __user *user_buf,
546 size_t count, loff_t *ppos)
547{
548 struct ath10k *ar = file->private_data;
549 int ret, len, buf_len;
550 char *buf;
551
552 buf_len = 500;
553 buf = kmalloc(buf_len, GFP_KERNEL);
554 if (!buf)
555 return -ENOMEM;
556
557 spin_lock_bh(&ar->data_lock);
558
559 len = 0;
560 len += scnprintf(buf + len, buf_len - len,
561 "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
562 len += scnprintf(buf + len, buf_len - len,
563 "fw_warm_reset_counter\t\t%d\n",
564 ar->stats.fw_warm_reset_counter);
565 len += scnprintf(buf + len, buf_len - len,
566 "fw_cold_reset_counter\t\t%d\n",
567 ar->stats.fw_cold_reset_counter);
568
569 spin_unlock_bh(&ar->data_lock);
570
571 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
572
573 kfree(buf);
574
575 return ret;
576}
577
578static const struct file_operations fops_fw_reset_stats = {
579 .open = simple_open,
580 .read = ath10k_debug_fw_reset_stats_read,
581 .owner = THIS_MODULE,
582 .llseek = default_llseek,
583};
584
Ben Greeard5aebc72014-09-10 18:59:28 +0300585/* This is a clean assert crash in firmware. */
586static int ath10k_debug_fw_assert(struct ath10k *ar)
587{
588 struct wmi_vdev_install_key_cmd *cmd;
589 struct sk_buff *skb;
590
591 skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
592 if (!skb)
593 return -ENOMEM;
594
595 cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
596 memset(cmd, 0, sizeof(*cmd));
597
598 /* big enough number so that firmware asserts */
599 cmd->vdev_id = __cpu_to_le32(0x7ffe);
600
601 return ath10k_wmi_cmd_send(ar, skb,
602 ar->wmi.cmd->vdev_install_key_cmdid);
603}
604
Michal Kazior278c4a82013-07-22 14:08:51 +0200605static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
606 char __user *user_buf,
607 size_t count, loff_t *ppos)
608{
Kalle Valo75cb96d2014-09-14 12:50:44 +0300609 const char buf[] =
610 "To simulate firmware crash write one of the keywords to this file:\n"
611 "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
612 "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
Michal Kazior605cdba2014-10-28 10:34:37 +0100613 "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"
614 "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
Marek Puzyniak8c656992014-03-21 17:46:56 +0200615
Michal Kazior278c4a82013-07-22 14:08:51 +0200616 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
617}
618
Marek Puzyniak8c656992014-03-21 17:46:56 +0200619/* Simulate firmware crash:
620 * 'soft': Call wmi command causing firmware hang. This firmware hang is
621 * recoverable by warm firmware reset.
622 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
623 * vdev id. This is hard firmware crash because it is recoverable only by cold
624 * firmware reset.
625 */
Michal Kazior278c4a82013-07-22 14:08:51 +0200626static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
627 const char __user *user_buf,
628 size_t count, loff_t *ppos)
629{
630 struct ath10k *ar = file->private_data;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200631 char buf[32];
Michal Kazior278c4a82013-07-22 14:08:51 +0200632 int ret;
633
Michal Kazior278c4a82013-07-22 14:08:51 +0200634 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200635
636 /* make sure that buf is null terminated */
637 buf[sizeof(buf) - 1] = 0;
Michal Kazior278c4a82013-07-22 14:08:51 +0200638
Mohammed Shafi Shajakhanf5e30752016-05-28 11:25:41 +0300639 /* drop the possible '\n' from the end */
640 if (buf[count - 1] == '\n')
641 buf[count - 1] = 0;
642
643 mutex_lock(&ar->conf_mutex);
644
Michal Kazior278c4a82013-07-22 14:08:51 +0200645 if (ar->state != ATH10K_STATE_ON &&
646 ar->state != ATH10K_STATE_RESTARTED) {
647 ret = -ENETDOWN;
648 goto exit;
649 }
650
Marek Puzyniak8c656992014-03-21 17:46:56 +0200651 if (!strcmp(buf, "soft")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200652 ath10k_info(ar, "simulating soft firmware crash\n");
Marek Puzyniak8c656992014-03-21 17:46:56 +0200653 ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
654 } else if (!strcmp(buf, "hard")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200655 ath10k_info(ar, "simulating hard firmware crash\n");
Ben Greear611b3682014-07-25 11:56:40 +0300656 /* 0x7fff is vdev id, and it is always out of range for all
657 * firmware variants in order to force a firmware crash.
658 */
659 ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
Kalle Valo5b07e072014-09-14 12:50:06 +0300660 ar->wmi.vdev_param->rts_threshold,
661 0);
Ben Greeard5aebc72014-09-10 18:59:28 +0300662 } else if (!strcmp(buf, "assert")) {
663 ath10k_info(ar, "simulating firmware assert crash\n");
664 ret = ath10k_debug_fw_assert(ar);
Michal Kazior605cdba2014-10-28 10:34:37 +0100665 } else if (!strcmp(buf, "hw-restart")) {
666 ath10k_info(ar, "user requested hw restart\n");
667 queue_work(ar->workqueue, &ar->restart_work);
668 ret = 0;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200669 } else {
670 ret = -EINVAL;
671 goto exit;
672 }
Michal Kazior278c4a82013-07-22 14:08:51 +0200673
Marek Puzyniak8c656992014-03-21 17:46:56 +0200674 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200675 ath10k_warn(ar, "failed to simulate firmware crash: %d\n", ret);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200676 goto exit;
677 }
678
679 ret = count;
Michal Kazior278c4a82013-07-22 14:08:51 +0200680
681exit:
682 mutex_unlock(&ar->conf_mutex);
683 return ret;
684}
685
686static const struct file_operations fops_simulate_fw_crash = {
687 .read = ath10k_read_simulate_fw_crash,
688 .write = ath10k_write_simulate_fw_crash,
689 .open = simple_open,
690 .owner = THIS_MODULE,
691 .llseek = default_llseek,
692};
693
Kalle Valo763b8cd2013-09-01 11:22:21 +0300694static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf,
695 size_t count, loff_t *ppos)
696{
697 struct ath10k *ar = file->private_data;
698 unsigned int len;
699 char buf[50];
700
701 len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id);
702
703 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
704}
705
706static const struct file_operations fops_chip_id = {
707 .read = ath10k_read_chip_id,
708 .open = simple_open,
709 .owner = THIS_MODULE,
710 .llseek = default_llseek,
711};
712
Ben Greear384914b2014-08-25 08:37:32 +0300713struct ath10k_fw_crash_data *
714ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
715{
716 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
717
718 lockdep_assert_held(&ar->data_lock);
719
720 crash_data->crashed_since_read = true;
721 uuid_le_gen(&crash_data->uuid);
722 getnstimeofday(&crash_data->timestamp);
723
724 return crash_data;
725}
726EXPORT_SYMBOL(ath10k_debug_get_new_fw_crash_data);
727
Arun Khandavalli727000e2016-12-21 14:19:21 +0200728static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar,
729 bool mark_read)
Ben Greear384914b2014-08-25 08:37:32 +0300730{
731 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
732 struct ath10k_dump_file_data *dump_data;
733 struct ath10k_tlv_dump_data *dump_tlv;
734 int hdr_len = sizeof(*dump_data);
735 unsigned int len, sofar = 0;
736 unsigned char *buf;
737
738 len = hdr_len;
739 len += sizeof(*dump_tlv) + sizeof(crash_data->registers);
740
741 sofar += hdr_len;
742
743 /* This is going to get big when we start dumping FW RAM and such,
744 * so go ahead and use vmalloc.
745 */
746 buf = vzalloc(len);
747 if (!buf)
748 return NULL;
749
750 spin_lock_bh(&ar->data_lock);
751
752 if (!crash_data->crashed_since_read) {
753 spin_unlock_bh(&ar->data_lock);
754 vfree(buf);
755 return NULL;
756 }
757
758 dump_data = (struct ath10k_dump_file_data *)(buf);
759 strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP",
760 sizeof(dump_data->df_magic));
761 dump_data->len = cpu_to_le32(len);
762
763 dump_data->version = cpu_to_le32(ATH10K_FW_CRASH_DUMP_VERSION);
764
765 memcpy(dump_data->uuid, &crash_data->uuid, sizeof(dump_data->uuid));
766 dump_data->chip_id = cpu_to_le32(ar->chip_id);
767 dump_data->bus_type = cpu_to_le32(0);
768 dump_data->target_version = cpu_to_le32(ar->target_version);
769 dump_data->fw_version_major = cpu_to_le32(ar->fw_version_major);
770 dump_data->fw_version_minor = cpu_to_le32(ar->fw_version_minor);
771 dump_data->fw_version_release = cpu_to_le32(ar->fw_version_release);
772 dump_data->fw_version_build = cpu_to_le32(ar->fw_version_build);
773 dump_data->phy_capability = cpu_to_le32(ar->phy_capability);
774 dump_data->hw_min_tx_power = cpu_to_le32(ar->hw_min_tx_power);
775 dump_data->hw_max_tx_power = cpu_to_le32(ar->hw_max_tx_power);
776 dump_data->ht_cap_info = cpu_to_le32(ar->ht_cap_info);
777 dump_data->vht_cap_info = cpu_to_le32(ar->vht_cap_info);
778 dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains);
779
780 strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
781 sizeof(dump_data->fw_ver));
782
Johannes Berg12c27152014-11-21 18:58:49 +0200783 dump_data->kernel_ver_code = 0;
784 strlcpy(dump_data->kernel_ver, init_utsname()->release,
Ben Greear384914b2014-08-25 08:37:32 +0300785 sizeof(dump_data->kernel_ver));
786
787 dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
788 dump_data->tv_nsec = cpu_to_le64(crash_data->timestamp.tv_nsec);
789
790 /* Gather crash-dump */
791 dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
792 dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_REGISTERS);
793 dump_tlv->tlv_len = cpu_to_le32(sizeof(crash_data->registers));
794 memcpy(dump_tlv->tlv_data, &crash_data->registers,
795 sizeof(crash_data->registers));
796 sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers);
797
Arun Khandavalli727000e2016-12-21 14:19:21 +0200798 ar->debug.fw_crash_data->crashed_since_read = !mark_read;
Ben Greear384914b2014-08-25 08:37:32 +0300799
800 spin_unlock_bh(&ar->data_lock);
801
802 return dump_data;
803}
804
Arun Khandavalli727000e2016-12-21 14:19:21 +0200805int ath10k_debug_fw_devcoredump(struct ath10k *ar)
806{
807 struct ath10k_dump_file_data *dump;
808 void *dump_ptr;
809 u32 dump_len;
810
811 /* To keep the dump file available also for debugfs don't mark the
812 * file read, only debugfs should do that.
813 */
814 dump = ath10k_build_dump_file(ar, false);
815 if (!dump) {
816 ath10k_warn(ar, "no crash dump data found for devcoredump");
817 return -ENODATA;
818 }
819
820 /* Make a copy of the dump file for dev_coredumpv() as during the
821 * transition period we need to own the original file. Once
822 * fw_crash_dump debugfs file is removed no need to have a copy
823 * anymore.
824 */
825 dump_len = le32_to_cpu(dump->len);
826 dump_ptr = vzalloc(dump_len);
827
828 if (!dump_ptr)
829 return -ENOMEM;
830
831 memcpy(dump_ptr, dump, dump_len);
832
833 dev_coredumpv(ar->dev, dump_ptr, dump_len, GFP_KERNEL);
834
835 return 0;
836}
837
Ben Greear384914b2014-08-25 08:37:32 +0300838static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file)
839{
840 struct ath10k *ar = inode->i_private;
841 struct ath10k_dump_file_data *dump;
842
Arun Khandavalli727000e2016-12-21 14:19:21 +0200843 ath10k_warn(ar, "fw_crash_dump debugfs file is deprecated, please use /sys/class/devcoredump instead.");
844
845 dump = ath10k_build_dump_file(ar, true);
Ben Greear384914b2014-08-25 08:37:32 +0300846 if (!dump)
847 return -ENODATA;
848
849 file->private_data = dump;
850
851 return 0;
852}
853
854static ssize_t ath10k_fw_crash_dump_read(struct file *file,
855 char __user *user_buf,
856 size_t count, loff_t *ppos)
857{
858 struct ath10k_dump_file_data *dump_file = file->private_data;
859
860 return simple_read_from_buffer(user_buf, count, ppos,
861 dump_file,
862 le32_to_cpu(dump_file->len));
863}
864
865static int ath10k_fw_crash_dump_release(struct inode *inode,
866 struct file *file)
867{
868 vfree(file->private_data);
869
870 return 0;
871}
872
873static const struct file_operations fops_fw_crash_dump = {
874 .open = ath10k_fw_crash_dump_open,
875 .read = ath10k_fw_crash_dump_read,
876 .release = ath10k_fw_crash_dump_release,
877 .owner = THIS_MODULE,
878 .llseek = default_llseek,
879};
880
Yanbo Li077a3802014-11-25 12:24:33 +0200881static ssize_t ath10k_reg_addr_read(struct file *file,
882 char __user *user_buf,
883 size_t count, loff_t *ppos)
884{
885 struct ath10k *ar = file->private_data;
886 u8 buf[32];
887 unsigned int len = 0;
888 u32 reg_addr;
889
890 mutex_lock(&ar->conf_mutex);
891 reg_addr = ar->debug.reg_addr;
892 mutex_unlock(&ar->conf_mutex);
893
894 len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);
895
896 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
897}
898
899static ssize_t ath10k_reg_addr_write(struct file *file,
900 const char __user *user_buf,
901 size_t count, loff_t *ppos)
902{
903 struct ath10k *ar = file->private_data;
904 u32 reg_addr;
905 int ret;
906
907 ret = kstrtou32_from_user(user_buf, count, 0, &reg_addr);
908 if (ret)
909 return ret;
910
911 if (!IS_ALIGNED(reg_addr, 4))
912 return -EFAULT;
913
914 mutex_lock(&ar->conf_mutex);
915 ar->debug.reg_addr = reg_addr;
916 mutex_unlock(&ar->conf_mutex);
917
918 return count;
919}
920
921static const struct file_operations fops_reg_addr = {
922 .read = ath10k_reg_addr_read,
923 .write = ath10k_reg_addr_write,
924 .open = simple_open,
925 .owner = THIS_MODULE,
926 .llseek = default_llseek,
927};
928
929static ssize_t ath10k_reg_value_read(struct file *file,
930 char __user *user_buf,
931 size_t count, loff_t *ppos)
932{
933 struct ath10k *ar = file->private_data;
934 u8 buf[48];
935 unsigned int len;
936 u32 reg_addr, reg_val;
937 int ret;
938
939 mutex_lock(&ar->conf_mutex);
940
941 if (ar->state != ATH10K_STATE_ON &&
942 ar->state != ATH10K_STATE_UTF) {
943 ret = -ENETDOWN;
944 goto exit;
945 }
946
947 reg_addr = ar->debug.reg_addr;
948
949 reg_val = ath10k_hif_read32(ar, reg_addr);
950 len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);
951
952 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
953
954exit:
955 mutex_unlock(&ar->conf_mutex);
956
957 return ret;
958}
959
960static ssize_t ath10k_reg_value_write(struct file *file,
961 const char __user *user_buf,
962 size_t count, loff_t *ppos)
963{
964 struct ath10k *ar = file->private_data;
965 u32 reg_addr, reg_val;
966 int ret;
967
968 mutex_lock(&ar->conf_mutex);
969
970 if (ar->state != ATH10K_STATE_ON &&
971 ar->state != ATH10K_STATE_UTF) {
972 ret = -ENETDOWN;
973 goto exit;
974 }
975
976 reg_addr = ar->debug.reg_addr;
977
978 ret = kstrtou32_from_user(user_buf, count, 0, &reg_val);
979 if (ret)
980 goto exit;
981
982 ath10k_hif_write32(ar, reg_addr, reg_val);
983
984 ret = count;
985
986exit:
987 mutex_unlock(&ar->conf_mutex);
988
989 return ret;
990}
991
992static const struct file_operations fops_reg_value = {
993 .read = ath10k_reg_value_read,
994 .write = ath10k_reg_value_write,
995 .open = simple_open,
996 .owner = THIS_MODULE,
997 .llseek = default_llseek,
998};
999
Yanbo Li9f65ad22014-11-25 12:24:48 +02001000static ssize_t ath10k_mem_value_read(struct file *file,
1001 char __user *user_buf,
1002 size_t count, loff_t *ppos)
1003{
1004 struct ath10k *ar = file->private_data;
1005 u8 *buf;
1006 int ret;
1007
1008 if (*ppos < 0)
1009 return -EINVAL;
1010
1011 if (!count)
1012 return 0;
1013
1014 mutex_lock(&ar->conf_mutex);
1015
1016 buf = vmalloc(count);
1017 if (!buf) {
1018 ret = -ENOMEM;
1019 goto exit;
1020 }
1021
1022 if (ar->state != ATH10K_STATE_ON &&
1023 ar->state != ATH10K_STATE_UTF) {
1024 ret = -ENETDOWN;
1025 goto exit;
1026 }
1027
1028 ret = ath10k_hif_diag_read(ar, *ppos, buf, count);
1029 if (ret) {
1030 ath10k_warn(ar, "failed to read address 0x%08x via diagnose window fnrom debugfs: %d\n",
1031 (u32)(*ppos), ret);
1032 goto exit;
1033 }
1034
1035 ret = copy_to_user(user_buf, buf, count);
1036 if (ret) {
1037 ret = -EFAULT;
1038 goto exit;
1039 }
1040
1041 count -= ret;
1042 *ppos += count;
1043 ret = count;
1044
1045exit:
1046 vfree(buf);
1047 mutex_unlock(&ar->conf_mutex);
1048
1049 return ret;
1050}
1051
1052static ssize_t ath10k_mem_value_write(struct file *file,
1053 const char __user *user_buf,
1054 size_t count, loff_t *ppos)
1055{
1056 struct ath10k *ar = file->private_data;
1057 u8 *buf;
1058 int ret;
1059
1060 if (*ppos < 0)
1061 return -EINVAL;
1062
1063 if (!count)
1064 return 0;
1065
1066 mutex_lock(&ar->conf_mutex);
1067
1068 buf = vmalloc(count);
1069 if (!buf) {
1070 ret = -ENOMEM;
1071 goto exit;
1072 }
1073
1074 if (ar->state != ATH10K_STATE_ON &&
1075 ar->state != ATH10K_STATE_UTF) {
1076 ret = -ENETDOWN;
1077 goto exit;
1078 }
1079
1080 ret = copy_from_user(buf, user_buf, count);
1081 if (ret) {
1082 ret = -EFAULT;
1083 goto exit;
1084 }
1085
1086 ret = ath10k_hif_diag_write(ar, *ppos, buf, count);
1087 if (ret) {
1088 ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",
1089 (u32)(*ppos), ret);
1090 goto exit;
1091 }
1092
1093 *ppos += count;
1094 ret = count;
1095
1096exit:
1097 vfree(buf);
1098 mutex_unlock(&ar->conf_mutex);
1099
1100 return ret;
1101}
1102
1103static const struct file_operations fops_mem_value = {
1104 .read = ath10k_mem_value_read,
1105 .write = ath10k_mem_value_write,
1106 .open = simple_open,
1107 .owner = THIS_MODULE,
1108 .llseek = default_llseek,
1109};
1110
Kalle Valoa3d135e2013-09-03 11:44:10 +03001111static int ath10k_debug_htt_stats_req(struct ath10k *ar)
1112{
1113 u64 cookie;
1114 int ret;
1115
1116 lockdep_assert_held(&ar->conf_mutex);
1117
1118 if (ar->debug.htt_stats_mask == 0)
1119 /* htt stats are disabled */
1120 return 0;
1121
1122 if (ar->state != ATH10K_STATE_ON)
1123 return 0;
1124
1125 cookie = get_jiffies_64();
1126
1127 ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask,
1128 cookie);
1129 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001130 ath10k_warn(ar, "failed to send htt stats request: %d\n", ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001131 return ret;
1132 }
1133
1134 queue_delayed_work(ar->workqueue, &ar->debug.htt_stats_dwork,
1135 msecs_to_jiffies(ATH10K_DEBUG_HTT_STATS_INTERVAL));
1136
1137 return 0;
1138}
1139
1140static void ath10k_debug_htt_stats_dwork(struct work_struct *work)
1141{
1142 struct ath10k *ar = container_of(work, struct ath10k,
1143 debug.htt_stats_dwork.work);
1144
1145 mutex_lock(&ar->conf_mutex);
1146
1147 ath10k_debug_htt_stats_req(ar);
1148
1149 mutex_unlock(&ar->conf_mutex);
1150}
1151
1152static ssize_t ath10k_read_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001153 char __user *user_buf,
1154 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001155{
1156 struct ath10k *ar = file->private_data;
1157 char buf[32];
1158 unsigned int len;
1159
1160 len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask);
1161
1162 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1163}
1164
1165static ssize_t ath10k_write_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001166 const char __user *user_buf,
1167 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001168{
1169 struct ath10k *ar = file->private_data;
1170 unsigned long mask;
1171 int ret;
1172
1173 ret = kstrtoul_from_user(user_buf, count, 0, &mask);
1174 if (ret)
1175 return ret;
1176
1177 /* max 8 bit masks (for now) */
1178 if (mask > 0xff)
1179 return -E2BIG;
1180
1181 mutex_lock(&ar->conf_mutex);
1182
1183 ar->debug.htt_stats_mask = mask;
1184
1185 ret = ath10k_debug_htt_stats_req(ar);
1186 if (ret)
1187 goto out;
1188
1189 ret = count;
1190
1191out:
1192 mutex_unlock(&ar->conf_mutex);
1193
1194 return ret;
1195}
1196
1197static const struct file_operations fops_htt_stats_mask = {
1198 .read = ath10k_read_htt_stats_mask,
1199 .write = ath10k_write_htt_stats_mask,
1200 .open = simple_open,
1201 .owner = THIS_MODULE,
1202 .llseek = default_llseek,
1203};
1204
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001205static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
1206 char __user *user_buf,
1207 size_t count, loff_t *ppos)
1208{
1209 struct ath10k *ar = file->private_data;
1210 char buf[64];
Mohammed Shafi Shajakhan81ec3c02015-11-30 22:29:39 +05301211 u8 amsdu, ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001212 unsigned int len;
1213
1214 mutex_lock(&ar->conf_mutex);
1215
David Liuccec9032015-07-24 20:25:32 +03001216 amsdu = ar->htt.max_num_amsdu;
1217 ampdu = ar->htt.max_num_ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001218 mutex_unlock(&ar->conf_mutex);
1219
1220 len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
1221
1222 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1223}
1224
1225static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
1226 const char __user *user_buf,
1227 size_t count, loff_t *ppos)
1228{
1229 struct ath10k *ar = file->private_data;
1230 int res;
1231 char buf[64];
1232 unsigned int amsdu, ampdu;
1233
1234 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
1235
1236 /* make sure that buf is null terminated */
1237 buf[sizeof(buf) - 1] = 0;
1238
1239 res = sscanf(buf, "%u %u", &amsdu, &ampdu);
1240
1241 if (res != 2)
1242 return -EINVAL;
1243
1244 mutex_lock(&ar->conf_mutex);
1245
1246 res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
1247 if (res)
1248 goto out;
1249
1250 res = count;
David Liuccec9032015-07-24 20:25:32 +03001251 ar->htt.max_num_amsdu = amsdu;
1252 ar->htt.max_num_ampdu = ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001253
1254out:
1255 mutex_unlock(&ar->conf_mutex);
1256 return res;
1257}
1258
1259static const struct file_operations fops_htt_max_amsdu_ampdu = {
1260 .read = ath10k_read_htt_max_amsdu_ampdu,
1261 .write = ath10k_write_htt_max_amsdu_ampdu,
1262 .open = simple_open,
1263 .owner = THIS_MODULE,
1264 .llseek = default_llseek,
1265};
1266
Kalle Valof118a3e2014-01-03 12:59:31 +02001267static ssize_t ath10k_read_fw_dbglog(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001268 char __user *user_buf,
1269 size_t count, loff_t *ppos)
Kalle Valof118a3e2014-01-03 12:59:31 +02001270{
1271 struct ath10k *ar = file->private_data;
1272 unsigned int len;
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301273 char buf[96];
Kalle Valof118a3e2014-01-03 12:59:31 +02001274
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301275 len = scnprintf(buf, sizeof(buf), "0x%16llx %u\n",
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301276 ar->debug.fw_dbglog_mask, ar->debug.fw_dbglog_level);
Kalle Valof118a3e2014-01-03 12:59:31 +02001277
1278 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1279}
1280
1281static ssize_t ath10k_write_fw_dbglog(struct file *file,
1282 const char __user *user_buf,
1283 size_t count, loff_t *ppos)
1284{
1285 struct ath10k *ar = file->private_data;
Kalle Valof118a3e2014-01-03 12:59:31 +02001286 int ret;
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301287 char buf[96];
1288 unsigned int log_level;
1289 u64 mask;
Kalle Valof118a3e2014-01-03 12:59:31 +02001290
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301291 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
1292
1293 /* make sure that buf is null terminated */
1294 buf[sizeof(buf) - 1] = 0;
1295
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301296 ret = sscanf(buf, "%llx %u", &mask, &log_level);
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301297
1298 if (!ret)
1299 return -EINVAL;
1300
1301 if (ret == 1)
1302 /* default if user did not specify */
1303 log_level = ATH10K_DBGLOG_LEVEL_WARN;
Kalle Valof118a3e2014-01-03 12:59:31 +02001304
1305 mutex_lock(&ar->conf_mutex);
1306
1307 ar->debug.fw_dbglog_mask = mask;
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301308 ar->debug.fw_dbglog_level = log_level;
Kalle Valof118a3e2014-01-03 12:59:31 +02001309
1310 if (ar->state == ATH10K_STATE_ON) {
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301311 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1312 ar->debug.fw_dbglog_level);
Kalle Valof118a3e2014-01-03 12:59:31 +02001313 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001314 ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n",
Kalle Valof118a3e2014-01-03 12:59:31 +02001315 ret);
1316 goto exit;
1317 }
1318 }
1319
1320 ret = count;
1321
1322exit:
1323 mutex_unlock(&ar->conf_mutex);
1324
1325 return ret;
1326}
1327
Ben Greear6cddcc72014-09-29 14:41:46 +03001328/* TODO: Would be nice to always support ethtool stats, would need to
1329 * move the stats storage out of ath10k_debug, or always have ath10k_debug
1330 * struct available..
1331 */
1332
1333/* This generally cooresponds to the debugfs fw_stats file */
1334static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
1335 "tx_pkts_nic",
1336 "tx_bytes_nic",
1337 "rx_pkts_nic",
1338 "rx_bytes_nic",
1339 "d_noise_floor",
1340 "d_cycle_count",
1341 "d_phy_error",
1342 "d_rts_bad",
1343 "d_rts_good",
1344 "d_tx_power", /* in .5 dbM I think */
1345 "d_rx_crc_err", /* fcs_bad */
1346 "d_no_beacon",
1347 "d_tx_mpdus_queued",
1348 "d_tx_msdu_queued",
1349 "d_tx_msdu_dropped",
1350 "d_local_enqued",
1351 "d_local_freed",
1352 "d_tx_ppdu_hw_queued",
1353 "d_tx_ppdu_reaped",
1354 "d_tx_fifo_underrun",
1355 "d_tx_ppdu_abort",
1356 "d_tx_mpdu_requed",
1357 "d_tx_excessive_retries",
1358 "d_tx_hw_rate",
1359 "d_tx_dropped_sw_retries",
1360 "d_tx_illegal_rate",
1361 "d_tx_continuous_xretries",
1362 "d_tx_timeout",
1363 "d_tx_mpdu_txop_limit",
1364 "d_pdev_resets",
1365 "d_rx_mid_ppdu_route_change",
1366 "d_rx_status",
1367 "d_rx_extra_frags_ring0",
1368 "d_rx_extra_frags_ring1",
1369 "d_rx_extra_frags_ring2",
1370 "d_rx_extra_frags_ring3",
1371 "d_rx_msdu_htt",
1372 "d_rx_mpdu_htt",
1373 "d_rx_msdu_stack",
1374 "d_rx_mpdu_stack",
1375 "d_rx_phy_err",
1376 "d_rx_phy_err_drops",
1377 "d_rx_mpdu_errors", /* FCS, MIC, ENC */
1378 "d_fw_crash_count",
1379 "d_fw_warm_reset_count",
1380 "d_fw_cold_reset_count",
1381};
1382
1383#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
1384
1385void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
1386 struct ieee80211_vif *vif,
1387 u32 sset, u8 *data)
1388{
1389 if (sset == ETH_SS_STATS)
1390 memcpy(data, *ath10k_gstrings_stats,
1391 sizeof(ath10k_gstrings_stats));
1392}
1393
1394int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
1395 struct ieee80211_vif *vif, int sset)
1396{
1397 if (sset == ETH_SS_STATS)
1398 return ATH10K_SSTATS_LEN;
1399
1400 return 0;
1401}
1402
1403void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
1404 struct ieee80211_vif *vif,
1405 struct ethtool_stats *stats, u64 *data)
1406{
1407 struct ath10k *ar = hw->priv;
1408 static const struct ath10k_fw_stats_pdev zero_stats = {};
1409 const struct ath10k_fw_stats_pdev *pdev_stats;
1410 int i = 0, ret;
1411
1412 mutex_lock(&ar->conf_mutex);
1413
1414 if (ar->state == ATH10K_STATE_ON) {
1415 ret = ath10k_debug_fw_stats_request(ar);
1416 if (ret) {
1417 /* just print a warning and try to use older results */
1418 ath10k_warn(ar,
1419 "failed to get fw stats for ethtool: %d\n",
1420 ret);
1421 }
1422 }
1423
1424 pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,
1425 struct ath10k_fw_stats_pdev,
1426 list);
1427 if (!pdev_stats) {
1428 /* no results available so just return zeroes */
1429 pdev_stats = &zero_stats;
1430 }
1431
1432 spin_lock_bh(&ar->data_lock);
1433
1434 data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
1435 data[i++] = 0; /* tx bytes */
1436 data[i++] = pdev_stats->htt_mpdus;
1437 data[i++] = 0; /* rx bytes */
1438 data[i++] = pdev_stats->ch_noise_floor;
1439 data[i++] = pdev_stats->cycle_count;
1440 data[i++] = pdev_stats->phy_err_count;
1441 data[i++] = pdev_stats->rts_bad;
1442 data[i++] = pdev_stats->rts_good;
1443 data[i++] = pdev_stats->chan_tx_power;
1444 data[i++] = pdev_stats->fcs_bad;
1445 data[i++] = pdev_stats->no_beacons;
1446 data[i++] = pdev_stats->mpdu_enqued;
1447 data[i++] = pdev_stats->msdu_enqued;
1448 data[i++] = pdev_stats->wmm_drop;
1449 data[i++] = pdev_stats->local_enqued;
1450 data[i++] = pdev_stats->local_freed;
1451 data[i++] = pdev_stats->hw_queued;
1452 data[i++] = pdev_stats->hw_reaped;
1453 data[i++] = pdev_stats->underrun;
1454 data[i++] = pdev_stats->tx_abort;
1455 data[i++] = pdev_stats->mpdus_requed;
1456 data[i++] = pdev_stats->tx_ko;
1457 data[i++] = pdev_stats->data_rc;
1458 data[i++] = pdev_stats->sw_retry_failure;
1459 data[i++] = pdev_stats->illgl_rate_phy_err;
1460 data[i++] = pdev_stats->pdev_cont_xretry;
1461 data[i++] = pdev_stats->pdev_tx_timeout;
1462 data[i++] = pdev_stats->txop_ovf;
1463 data[i++] = pdev_stats->pdev_resets;
1464 data[i++] = pdev_stats->mid_ppdu_route_change;
1465 data[i++] = pdev_stats->status_rcvd;
1466 data[i++] = pdev_stats->r0_frags;
1467 data[i++] = pdev_stats->r1_frags;
1468 data[i++] = pdev_stats->r2_frags;
1469 data[i++] = pdev_stats->r3_frags;
1470 data[i++] = pdev_stats->htt_msdus;
1471 data[i++] = pdev_stats->htt_mpdus;
1472 data[i++] = pdev_stats->loc_msdus;
1473 data[i++] = pdev_stats->loc_mpdus;
1474 data[i++] = pdev_stats->phy_errs;
1475 data[i++] = pdev_stats->phy_err_drop;
1476 data[i++] = pdev_stats->mpdu_errs;
1477 data[i++] = ar->stats.fw_crash_counter;
1478 data[i++] = ar->stats.fw_warm_reset_counter;
1479 data[i++] = ar->stats.fw_cold_reset_counter;
1480
1481 spin_unlock_bh(&ar->data_lock);
1482
1483 mutex_unlock(&ar->conf_mutex);
1484
1485 WARN_ON(i != ATH10K_SSTATS_LEN);
1486}
1487
Kalle Valof118a3e2014-01-03 12:59:31 +02001488static const struct file_operations fops_fw_dbglog = {
1489 .read = ath10k_read_fw_dbglog,
1490 .write = ath10k_write_fw_dbglog,
1491 .open = simple_open,
1492 .owner = THIS_MODULE,
1493 .llseek = default_llseek,
1494};
1495
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001496static int ath10k_debug_cal_data_fetch(struct ath10k *ar)
Kalle Valo7869b4f2014-09-24 14:16:58 +03001497{
Kalle Valo7869b4f2014-09-24 14:16:58 +03001498 u32 hi_addr;
1499 __le32 addr;
1500 int ret;
1501
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001502 lockdep_assert_held(&ar->conf_mutex);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001503
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001504 if (WARN_ON(ar->hw_params.cal_data_len > ATH10K_DEBUG_CAL_DATA_LEN))
1505 return -EINVAL;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001506
1507 hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
1508
1509 ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
1510 if (ret) {
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001511 ath10k_warn(ar, "failed to read hi_board_data address: %d\n",
1512 ret);
1513 return ret;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001514 }
1515
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001516 ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), ar->debug.cal_data,
Raja Mani0b8e3c42016-03-18 11:44:22 +02001517 ar->hw_params.cal_data_len);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001518 if (ret) {
1519 ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001520 return ret;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001521 }
1522
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001523 return 0;
1524}
Kalle Valo7869b4f2014-09-24 14:16:58 +03001525
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001526static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
1527{
1528 struct ath10k *ar = inode->i_private;
1529
1530 mutex_lock(&ar->conf_mutex);
1531
1532 if (ar->state == ATH10K_STATE_ON ||
1533 ar->state == ATH10K_STATE_UTF) {
1534 ath10k_debug_cal_data_fetch(ar);
1535 }
1536
1537 file->private_data = ar;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001538 mutex_unlock(&ar->conf_mutex);
1539
1540 return 0;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001541}
1542
1543static ssize_t ath10k_debug_cal_data_read(struct file *file,
1544 char __user *user_buf,
1545 size_t count, loff_t *ppos)
1546{
Raja Mani0b8e3c42016-03-18 11:44:22 +02001547 struct ath10k *ar = file->private_data;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001548
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001549 mutex_lock(&ar->conf_mutex);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001550
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001551 count = simple_read_from_buffer(user_buf, count, ppos,
1552 ar->debug.cal_data,
1553 ar->hw_params.cal_data_len);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001554
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001555 mutex_unlock(&ar->conf_mutex);
1556
1557 return count;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001558}
1559
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05301560static ssize_t ath10k_write_ani_enable(struct file *file,
1561 const char __user *user_buf,
1562 size_t count, loff_t *ppos)
1563{
1564 struct ath10k *ar = file->private_data;
1565 int ret;
1566 u8 enable;
1567
1568 if (kstrtou8_from_user(user_buf, count, 0, &enable))
1569 return -EINVAL;
1570
1571 mutex_lock(&ar->conf_mutex);
1572
1573 if (ar->ani_enabled == enable) {
1574 ret = count;
1575 goto exit;
1576 }
1577
1578 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->ani_enable,
1579 enable);
1580 if (ret) {
1581 ath10k_warn(ar, "ani_enable failed from debugfs: %d\n", ret);
1582 goto exit;
1583 }
1584 ar->ani_enabled = enable;
1585
1586 ret = count;
1587
1588exit:
1589 mutex_unlock(&ar->conf_mutex);
1590
1591 return ret;
1592}
1593
1594static ssize_t ath10k_read_ani_enable(struct file *file, char __user *user_buf,
1595 size_t count, loff_t *ppos)
1596{
1597 struct ath10k *ar = file->private_data;
1598 int len = 0;
1599 char buf[32];
1600
1601 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
1602 ar->ani_enabled);
1603
1604 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1605}
1606
1607static const struct file_operations fops_ani_enable = {
1608 .read = ath10k_read_ani_enable,
1609 .write = ath10k_write_ani_enable,
1610 .open = simple_open,
1611 .owner = THIS_MODULE,
1612 .llseek = default_llseek,
1613};
1614
Kalle Valo7869b4f2014-09-24 14:16:58 +03001615static const struct file_operations fops_cal_data = {
1616 .open = ath10k_debug_cal_data_open,
1617 .read = ath10k_debug_cal_data_read,
Kalle Valo7869b4f2014-09-24 14:16:58 +03001618 .owner = THIS_MODULE,
1619 .llseek = default_llseek,
1620};
1621
Peter Oha7bd3e92014-12-02 13:07:14 +02001622static ssize_t ath10k_read_nf_cal_period(struct file *file,
1623 char __user *user_buf,
1624 size_t count, loff_t *ppos)
1625{
1626 struct ath10k *ar = file->private_data;
1627 unsigned int len;
1628 char buf[32];
1629
1630 len = scnprintf(buf, sizeof(buf), "%d\n",
1631 ar->debug.nf_cal_period);
1632
1633 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1634}
1635
1636static ssize_t ath10k_write_nf_cal_period(struct file *file,
1637 const char __user *user_buf,
1638 size_t count, loff_t *ppos)
1639{
1640 struct ath10k *ar = file->private_data;
1641 unsigned long period;
1642 int ret;
1643
1644 ret = kstrtoul_from_user(user_buf, count, 0, &period);
1645 if (ret)
1646 return ret;
1647
1648 if (period > WMI_PDEV_PARAM_CAL_PERIOD_MAX)
1649 return -EINVAL;
1650
1651 /* there's no way to switch back to the firmware default */
1652 if (period == 0)
1653 return -EINVAL;
1654
1655 mutex_lock(&ar->conf_mutex);
1656
1657 ar->debug.nf_cal_period = period;
1658
1659 if (ar->state != ATH10K_STATE_ON) {
1660 /* firmware is not running, nothing else to do */
1661 ret = count;
1662 goto exit;
1663 }
1664
1665 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->cal_period,
1666 ar->debug.nf_cal_period);
1667 if (ret) {
1668 ath10k_warn(ar, "cal period cfg failed from debugfs: %d\n",
1669 ret);
1670 goto exit;
1671 }
1672
1673 ret = count;
1674
1675exit:
1676 mutex_unlock(&ar->conf_mutex);
1677
1678 return ret;
1679}
1680
1681static const struct file_operations fops_nf_cal_period = {
1682 .read = ath10k_read_nf_cal_period,
1683 .write = ath10k_write_nf_cal_period,
1684 .open = simple_open,
1685 .owner = THIS_MODULE,
1686 .llseek = default_llseek,
1687};
1688
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001689#define ATH10K_TPC_CONFIG_BUF_SIZE (1024 * 1024)
1690
1691static int ath10k_debug_tpc_stats_request(struct ath10k *ar)
1692{
1693 int ret;
1694 unsigned long time_left;
1695
1696 lockdep_assert_held(&ar->conf_mutex);
1697
1698 reinit_completion(&ar->debug.tpc_complete);
1699
1700 ret = ath10k_wmi_pdev_get_tpc_config(ar, WMI_TPC_CONFIG_PARAM);
1701 if (ret) {
1702 ath10k_warn(ar, "failed to request tpc config: %d\n", ret);
1703 return ret;
1704 }
1705
1706 time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
1707 1 * HZ);
1708 if (time_left == 0)
1709 return -ETIMEDOUT;
1710
1711 return 0;
1712}
1713
1714void ath10k_debug_tpc_stats_process(struct ath10k *ar,
1715 struct ath10k_tpc_stats *tpc_stats)
1716{
1717 spin_lock_bh(&ar->data_lock);
1718
1719 kfree(ar->debug.tpc_stats);
1720 ar->debug.tpc_stats = tpc_stats;
1721 complete(&ar->debug.tpc_complete);
1722
1723 spin_unlock_bh(&ar->data_lock);
1724}
1725
1726static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
1727 unsigned int j, char *buf, unsigned int *len)
1728{
1729 unsigned int i, buf_len;
1730 static const char table_str[][5] = { "CDD",
1731 "STBC",
1732 "TXBF" };
1733 static const char pream_str[][6] = { "CCK",
1734 "OFDM",
1735 "HT20",
1736 "HT40",
1737 "VHT20",
1738 "VHT40",
1739 "VHT80",
1740 "HTCUP" };
1741
1742 buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1743 *len += scnprintf(buf + *len, buf_len - *len,
1744 "********************************\n");
1745 *len += scnprintf(buf + *len, buf_len - *len,
1746 "******************* %s POWER TABLE ****************\n",
1747 table_str[j]);
1748 *len += scnprintf(buf + *len, buf_len - *len,
1749 "********************************\n");
1750 *len += scnprintf(buf + *len, buf_len - *len,
1751 "No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3\n");
1752
1753 for (i = 0; i < tpc_stats->rate_max; i++) {
1754 *len += scnprintf(buf + *len, buf_len - *len,
1755 "%8d %s 0x%2x %s\n", i,
1756 pream_str[tpc_stats->tpc_table[j].pream_idx[i]],
1757 tpc_stats->tpc_table[j].rate_code[i],
1758 tpc_stats->tpc_table[j].tpc_value[i]);
1759 }
1760
1761 *len += scnprintf(buf + *len, buf_len - *len,
1762 "***********************************\n");
1763}
1764
1765static void ath10k_tpc_stats_fill(struct ath10k *ar,
1766 struct ath10k_tpc_stats *tpc_stats,
1767 char *buf)
1768{
1769 unsigned int len, j, buf_len;
1770
1771 len = 0;
1772 buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1773
1774 spin_lock_bh(&ar->data_lock);
1775
1776 if (!tpc_stats) {
1777 ath10k_warn(ar, "failed to get tpc stats\n");
1778 goto unlock;
1779 }
1780
1781 len += scnprintf(buf + len, buf_len - len, "\n");
1782 len += scnprintf(buf + len, buf_len - len,
1783 "*************************************\n");
1784 len += scnprintf(buf + len, buf_len - len,
1785 "TPC config for channel %4d mode %d\n",
1786 tpc_stats->chan_freq,
1787 tpc_stats->phy_mode);
1788 len += scnprintf(buf + len, buf_len - len,
1789 "*************************************\n");
1790 len += scnprintf(buf + len, buf_len - len,
1791 "CTL = 0x%2x Reg. Domain = %2d\n",
1792 tpc_stats->ctl,
1793 tpc_stats->reg_domain);
1794 len += scnprintf(buf + len, buf_len - len,
1795 "Antenna Gain = %2d Reg. Max Antenna Gain = %2d\n",
1796 tpc_stats->twice_antenna_gain,
1797 tpc_stats->twice_antenna_reduction);
1798 len += scnprintf(buf + len, buf_len - len,
1799 "Power Limit = %2d Reg. Max Power = %2d\n",
1800 tpc_stats->power_limit,
1801 tpc_stats->twice_max_rd_power / 2);
1802 len += scnprintf(buf + len, buf_len - len,
1803 "Num tx chains = %2d Num supported rates = %2d\n",
1804 tpc_stats->num_tx_chain,
1805 tpc_stats->rate_max);
1806
1807 for (j = 0; j < tpc_stats->num_tx_chain ; j++) {
1808 switch (j) {
1809 case WMI_TPC_TABLE_TYPE_CDD:
1810 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1811 len += scnprintf(buf + len, buf_len - len,
1812 "CDD not supported\n");
1813 break;
1814 }
1815
1816 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1817 break;
1818 case WMI_TPC_TABLE_TYPE_STBC:
1819 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1820 len += scnprintf(buf + len, buf_len - len,
1821 "STBC not supported\n");
1822 break;
1823 }
1824
1825 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1826 break;
1827 case WMI_TPC_TABLE_TYPE_TXBF:
1828 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1829 len += scnprintf(buf + len, buf_len - len,
1830 "TXBF not supported\n***************************\n");
1831 break;
1832 }
1833
1834 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1835 break;
1836 default:
1837 len += scnprintf(buf + len, buf_len - len,
1838 "Invalid Type\n");
1839 break;
1840 }
1841 }
1842
1843unlock:
1844 spin_unlock_bh(&ar->data_lock);
1845
1846 if (len >= buf_len)
1847 buf[len - 1] = 0;
1848 else
1849 buf[len] = 0;
1850}
1851
1852static int ath10k_tpc_stats_open(struct inode *inode, struct file *file)
1853{
1854 struct ath10k *ar = inode->i_private;
1855 void *buf = NULL;
1856 int ret;
1857
1858 mutex_lock(&ar->conf_mutex);
1859
1860 if (ar->state != ATH10K_STATE_ON) {
1861 ret = -ENETDOWN;
1862 goto err_unlock;
1863 }
1864
1865 buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
1866 if (!buf) {
1867 ret = -ENOMEM;
1868 goto err_unlock;
1869 }
1870
1871 ret = ath10k_debug_tpc_stats_request(ar);
1872 if (ret) {
1873 ath10k_warn(ar, "failed to request tpc config stats: %d\n",
1874 ret);
1875 goto err_free;
1876 }
1877
1878 ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
1879 file->private_data = buf;
1880
1881 mutex_unlock(&ar->conf_mutex);
1882 return 0;
1883
1884err_free:
1885 vfree(buf);
1886
1887err_unlock:
1888 mutex_unlock(&ar->conf_mutex);
1889 return ret;
1890}
1891
1892static int ath10k_tpc_stats_release(struct inode *inode, struct file *file)
1893{
1894 vfree(file->private_data);
1895
1896 return 0;
1897}
1898
1899static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf,
1900 size_t count, loff_t *ppos)
1901{
1902 const char *buf = file->private_data;
1903 unsigned int len = strlen(buf);
1904
1905 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1906}
1907
1908static const struct file_operations fops_tpc_stats = {
1909 .open = ath10k_tpc_stats_open,
1910 .release = ath10k_tpc_stats_release,
1911 .read = ath10k_tpc_stats_read,
1912 .owner = THIS_MODULE,
1913 .llseek = default_llseek,
1914};
1915
Kalle Valodb66ea02013-09-03 11:44:03 +03001916int ath10k_debug_start(struct ath10k *ar)
1917{
Kalle Valoa3d135e2013-09-03 11:44:10 +03001918 int ret;
1919
Kalle Valo60631c52013-10-08 21:45:25 +03001920 lockdep_assert_held(&ar->conf_mutex);
1921
Kalle Valoa3d135e2013-09-03 11:44:10 +03001922 ret = ath10k_debug_htt_stats_req(ar);
1923 if (ret)
1924 /* continue normally anyway, this isn't serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001925 ath10k_warn(ar, "failed to start htt stats workqueue: %d\n",
1926 ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001927
Kalle Valof118a3e2014-01-03 12:59:31 +02001928 if (ar->debug.fw_dbglog_mask) {
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301929 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1930 ATH10K_DBGLOG_LEVEL_WARN);
Kalle Valof118a3e2014-01-03 12:59:31 +02001931 if (ret)
1932 /* not serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001933 ath10k_warn(ar, "failed to enable dbglog during start: %d",
Kalle Valof118a3e2014-01-03 12:59:31 +02001934 ret);
1935 }
1936
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001937 if (ar->debug.pktlog_filter) {
1938 ret = ath10k_wmi_pdev_pktlog_enable(ar,
1939 ar->debug.pktlog_filter);
1940 if (ret)
1941 /* not serious */
1942 ath10k_warn(ar,
1943 "failed to enable pktlog filter %x: %d\n",
1944 ar->debug.pktlog_filter, ret);
1945 } else {
1946 ret = ath10k_wmi_pdev_pktlog_disable(ar);
1947 if (ret)
1948 /* not serious */
1949 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
1950 }
1951
Peter Oha7bd3e92014-12-02 13:07:14 +02001952 if (ar->debug.nf_cal_period) {
1953 ret = ath10k_wmi_pdev_set_param(ar,
1954 ar->wmi.pdev_param->cal_period,
1955 ar->debug.nf_cal_period);
1956 if (ret)
1957 /* not serious */
1958 ath10k_warn(ar, "cal period cfg failed from debug start: %d\n",
1959 ret);
1960 }
1961
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001962 return ret;
Kalle Valodb66ea02013-09-03 11:44:03 +03001963}
1964
1965void ath10k_debug_stop(struct ath10k *ar)
1966{
Kalle Valo60631c52013-10-08 21:45:25 +03001967 lockdep_assert_held(&ar->conf_mutex);
1968
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001969 ath10k_debug_cal_data_fetch(ar);
1970
Kalle Valo60631c52013-10-08 21:45:25 +03001971 /* Must not use _sync to avoid deadlock, we do that in
1972 * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid
1973 * warning from del_timer(). */
1974 if (ar->debug.htt_stats_mask != 0)
1975 cancel_delayed_work(&ar->debug.htt_stats_dwork);
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001976
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001977 ath10k_wmi_pdev_pktlog_disable(ar);
Kalle Valodb66ea02013-09-03 11:44:03 +03001978}
1979
Janusz Dziedzic9702c682013-11-20 09:59:41 +02001980static ssize_t ath10k_write_simulate_radar(struct file *file,
1981 const char __user *user_buf,
1982 size_t count, loff_t *ppos)
1983{
1984 struct ath10k *ar = file->private_data;
1985
1986 ieee80211_radar_detected(ar->hw);
1987
1988 return count;
1989}
1990
1991static const struct file_operations fops_simulate_radar = {
1992 .write = ath10k_write_simulate_radar,
1993 .open = simple_open,
1994 .owner = THIS_MODULE,
1995 .llseek = default_llseek,
1996};
1997
1998#define ATH10K_DFS_STAT(s, p) (\
1999 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
2000 ar->debug.dfs_stats.p))
2001
2002#define ATH10K_DFS_POOL_STAT(s, p) (\
2003 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
2004 ar->debug.dfs_pool_stats.p))
2005
2006static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf,
2007 size_t count, loff_t *ppos)
2008{
2009 int retval = 0, len = 0;
2010 const int size = 8000;
2011 struct ath10k *ar = file->private_data;
2012 char *buf;
2013
2014 buf = kzalloc(size, GFP_KERNEL);
2015 if (buf == NULL)
2016 return -ENOMEM;
2017
2018 if (!ar->dfs_detector) {
2019 len += scnprintf(buf + len, size - len, "DFS not enabled\n");
2020 goto exit;
2021 }
2022
2023 ar->debug.dfs_pool_stats =
2024 ar->dfs_detector->get_stats(ar->dfs_detector);
2025
2026 len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");
2027
2028 ATH10K_DFS_STAT("reported phy errors", phy_errors);
2029 ATH10K_DFS_STAT("pulse events reported", pulses_total);
2030 ATH10K_DFS_STAT("DFS pulses detected", pulses_detected);
2031 ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded);
2032 ATH10K_DFS_STAT("Radars detected", radar_detected);
2033
2034 len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");
2035 ATH10K_DFS_POOL_STAT("Pool references", pool_reference);
2036 ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated);
2037 ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error);
2038 ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used);
2039 ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated);
2040 ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error);
2041 ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used);
2042
2043exit:
2044 if (len > size)
2045 len = size;
2046
2047 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
2048 kfree(buf);
2049
2050 return retval;
2051}
2052
2053static const struct file_operations fops_dfs_stats = {
2054 .read = ath10k_read_dfs_stats,
2055 .open = simple_open,
2056 .owner = THIS_MODULE,
2057 .llseek = default_llseek,
2058};
2059
Rajkumar Manoharan90174452014-10-03 08:02:33 +03002060static ssize_t ath10k_write_pktlog_filter(struct file *file,
2061 const char __user *ubuf,
2062 size_t count, loff_t *ppos)
2063{
2064 struct ath10k *ar = file->private_data;
2065 u32 filter;
2066 int ret;
2067
2068 if (kstrtouint_from_user(ubuf, count, 0, &filter))
2069 return -EINVAL;
2070
2071 mutex_lock(&ar->conf_mutex);
2072
2073 if (ar->state != ATH10K_STATE_ON) {
2074 ar->debug.pktlog_filter = filter;
2075 ret = count;
2076 goto out;
2077 }
2078
Anilkumar Kolli9ddc4862016-03-11 11:46:39 +05302079 if (filter == ar->debug.pktlog_filter) {
2080 ret = count;
2081 goto out;
2082 }
2083
2084 if (filter) {
Rajkumar Manoharan90174452014-10-03 08:02:33 +03002085 ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
2086 if (ret) {
2087 ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
2088 ar->debug.pktlog_filter, ret);
2089 goto out;
2090 }
2091 } else {
2092 ret = ath10k_wmi_pdev_pktlog_disable(ar);
2093 if (ret) {
2094 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
2095 goto out;
2096 }
2097 }
2098
2099 ar->debug.pktlog_filter = filter;
2100 ret = count;
2101
2102out:
2103 mutex_unlock(&ar->conf_mutex);
2104 return ret;
2105}
2106
2107static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf,
2108 size_t count, loff_t *ppos)
2109{
2110 char buf[32];
2111 struct ath10k *ar = file->private_data;
2112 int len = 0;
2113
2114 mutex_lock(&ar->conf_mutex);
2115 len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
2116 ar->debug.pktlog_filter);
2117 mutex_unlock(&ar->conf_mutex);
2118
2119 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2120}
2121
2122static const struct file_operations fops_pktlog_filter = {
2123 .read = ath10k_read_pktlog_filter,
2124 .write = ath10k_write_pktlog_filter,
2125 .open = simple_open
2126};
2127
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302128static ssize_t ath10k_write_quiet_period(struct file *file,
2129 const char __user *ubuf,
2130 size_t count, loff_t *ppos)
2131{
2132 struct ath10k *ar = file->private_data;
2133 u32 period;
2134
2135 if (kstrtouint_from_user(ubuf, count, 0, &period))
2136 return -EINVAL;
2137
2138 if (period < ATH10K_QUIET_PERIOD_MIN) {
2139 ath10k_warn(ar, "Quiet period %u can not be lesser than 25ms\n",
2140 period);
2141 return -EINVAL;
2142 }
2143 mutex_lock(&ar->conf_mutex);
2144 ar->thermal.quiet_period = period;
Rajkumar Manoharan8515b5c2015-03-15 20:36:22 +05302145 ath10k_thermal_set_throttling(ar);
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302146 mutex_unlock(&ar->conf_mutex);
2147
2148 return count;
2149}
2150
2151static ssize_t ath10k_read_quiet_period(struct file *file, char __user *ubuf,
2152 size_t count, loff_t *ppos)
2153{
2154 char buf[32];
2155 struct ath10k *ar = file->private_data;
2156 int len = 0;
2157
2158 mutex_lock(&ar->conf_mutex);
2159 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2160 ar->thermal.quiet_period);
2161 mutex_unlock(&ar->conf_mutex);
2162
2163 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2164}
2165
2166static const struct file_operations fops_quiet_period = {
2167 .read = ath10k_read_quiet_period,
2168 .write = ath10k_write_quiet_period,
2169 .open = simple_open
2170};
2171
Yanbo Li844fa572015-10-31 11:07:21 +02002172static ssize_t ath10k_write_btcoex(struct file *file,
2173 const char __user *ubuf,
2174 size_t count, loff_t *ppos)
2175{
2176 struct ath10k *ar = file->private_data;
2177 char buf[32];
2178 size_t buf_size;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302179 int ret;
Yanbo Li844fa572015-10-31 11:07:21 +02002180 bool val;
Rajkumar Manoharan39136242016-05-27 20:15:59 +05302181 u32 pdev_param;
Yanbo Li844fa572015-10-31 11:07:21 +02002182
2183 buf_size = min(count, (sizeof(buf) - 1));
2184 if (copy_from_user(buf, ubuf, buf_size))
2185 return -EFAULT;
2186
2187 buf[buf_size] = '\0';
2188
2189 if (strtobool(buf, &val) != 0)
2190 return -EINVAL;
2191
2192 mutex_lock(&ar->conf_mutex);
2193
Mohammed Shafi Shajakhanc28e6f02016-02-23 12:58:36 +05302194 if (ar->state != ATH10K_STATE_ON &&
2195 ar->state != ATH10K_STATE_RESTARTED) {
2196 ret = -ENETDOWN;
2197 goto exit;
2198 }
2199
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302200 if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) {
2201 ret = count;
Yanbo Li844fa572015-10-31 11:07:21 +02002202 goto exit;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302203 }
Yanbo Li844fa572015-10-31 11:07:21 +02002204
Rajkumar Manoharan39136242016-05-27 20:15:59 +05302205 pdev_param = ar->wmi.pdev_param->enable_btcoex;
2206 if (test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM,
2207 ar->running_fw->fw_file.fw_features)) {
2208 ret = ath10k_wmi_pdev_set_param(ar, pdev_param, val);
2209 if (ret) {
2210 ath10k_warn(ar, "failed to enable btcoex: %d\n", ret);
2211 ret = count;
2212 goto exit;
2213 }
2214 } else {
2215 ath10k_info(ar, "restarting firmware due to btcoex change");
2216 queue_work(ar->workqueue, &ar->restart_work);
2217 }
2218
Yanbo Li844fa572015-10-31 11:07:21 +02002219 if (val)
2220 set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
2221 else
2222 clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
2223
Mohammed Shafi Shajakhanc28e6f02016-02-23 12:58:36 +05302224 ret = count;
Yanbo Li844fa572015-10-31 11:07:21 +02002225
2226exit:
2227 mutex_unlock(&ar->conf_mutex);
2228
Mohammed Shafi Shajakhanc28e6f02016-02-23 12:58:36 +05302229 return ret;
Yanbo Li844fa572015-10-31 11:07:21 +02002230}
2231
2232static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
2233 size_t count, loff_t *ppos)
2234{
2235 char buf[32];
2236 struct ath10k *ar = file->private_data;
2237 int len = 0;
2238
2239 mutex_lock(&ar->conf_mutex);
2240 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2241 test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));
2242 mutex_unlock(&ar->conf_mutex);
2243
2244 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2245}
2246
2247static const struct file_operations fops_btcoex = {
2248 .read = ath10k_read_btcoex,
2249 .write = ath10k_write_btcoex,
2250 .open = simple_open
2251};
2252
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302253static ssize_t ath10k_write_peer_stats(struct file *file,
2254 const char __user *ubuf,
2255 size_t count, loff_t *ppos)
2256{
2257 struct ath10k *ar = file->private_data;
2258 char buf[32];
2259 size_t buf_size;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302260 int ret;
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302261 bool val;
2262
2263 buf_size = min(count, (sizeof(buf) - 1));
2264 if (copy_from_user(buf, ubuf, buf_size))
2265 return -EFAULT;
2266
2267 buf[buf_size] = '\0';
2268
2269 if (strtobool(buf, &val) != 0)
2270 return -EINVAL;
2271
2272 mutex_lock(&ar->conf_mutex);
2273
2274 if (ar->state != ATH10K_STATE_ON &&
2275 ar->state != ATH10K_STATE_RESTARTED) {
2276 ret = -ENETDOWN;
2277 goto exit;
2278 }
2279
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302280 if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val)) {
2281 ret = count;
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302282 goto exit;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302283 }
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302284
2285 if (val)
2286 set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
2287 else
2288 clear_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
2289
2290 ath10k_info(ar, "restarting firmware due to Peer stats change");
2291
2292 queue_work(ar->workqueue, &ar->restart_work);
2293 ret = count;
2294
2295exit:
2296 mutex_unlock(&ar->conf_mutex);
2297 return ret;
2298}
2299
2300static ssize_t ath10k_read_peer_stats(struct file *file, char __user *ubuf,
2301 size_t count, loff_t *ppos)
2302
2303{
2304 char buf[32];
2305 struct ath10k *ar = file->private_data;
2306 int len = 0;
2307
2308 mutex_lock(&ar->conf_mutex);
2309 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2310 test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags));
2311 mutex_unlock(&ar->conf_mutex);
2312
2313 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2314}
2315
2316static const struct file_operations fops_peer_stats = {
2317 .read = ath10k_read_peer_stats,
2318 .write = ath10k_write_peer_stats,
2319 .open = simple_open
2320};
2321
Kalle Valo9e100c42015-11-25 15:38:41 +02002322static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
2323 char __user *user_buf,
2324 size_t count, loff_t *ppos)
2325{
2326 struct ath10k *ar = file->private_data;
2327 unsigned int len = 0, buf_len = 4096;
2328 ssize_t ret_cnt;
2329 char *buf;
2330
2331 buf = kzalloc(buf_len, GFP_KERNEL);
2332 if (!buf)
2333 return -ENOMEM;
2334
2335 mutex_lock(&ar->conf_mutex);
2336
Kalle Valo9e100c42015-11-25 15:38:41 +02002337 len += scnprintf(buf + len, buf_len - len,
2338 "firmware-N.bin\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002339 crc32_le(0, ar->normal_mode_fw.fw_file.firmware->data,
2340 ar->normal_mode_fw.fw_file.firmware->size));
Kalle Valo9e100c42015-11-25 15:38:41 +02002341 len += scnprintf(buf + len, buf_len - len,
2342 "athwlan\t\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002343 crc32_le(0, ar->normal_mode_fw.fw_file.firmware_data,
2344 ar->normal_mode_fw.fw_file.firmware_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002345 len += scnprintf(buf + len, buf_len - len,
2346 "otp\t\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002347 crc32_le(0, ar->normal_mode_fw.fw_file.otp_data,
2348 ar->normal_mode_fw.fw_file.otp_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002349 len += scnprintf(buf + len, buf_len - len,
2350 "codeswap\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002351 crc32_le(0, ar->normal_mode_fw.fw_file.codeswap_data,
2352 ar->normal_mode_fw.fw_file.codeswap_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002353 len += scnprintf(buf + len, buf_len - len,
2354 "board-N.bin\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002355 crc32_le(0, ar->normal_mode_fw.board->data,
2356 ar->normal_mode_fw.board->size));
Kalle Valo9e100c42015-11-25 15:38:41 +02002357 len += scnprintf(buf + len, buf_len - len,
2358 "board\t\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002359 crc32_le(0, ar->normal_mode_fw.board_data,
2360 ar->normal_mode_fw.board_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002361
2362 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
2363
2364 mutex_unlock(&ar->conf_mutex);
2365
2366 kfree(buf);
2367 return ret_cnt;
2368}
2369
2370static const struct file_operations fops_fw_checksums = {
2371 .read = ath10k_debug_fw_checksums_read,
2372 .open = simple_open,
2373 .owner = THIS_MODULE,
2374 .llseek = default_llseek,
2375};
2376
Kalle Valo5e3dd152013-06-12 20:52:10 +03002377int ath10k_debug_create(struct ath10k *ar)
2378{
Ben Greear384914b2014-08-25 08:37:32 +03002379 ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002380 if (!ar->debug.fw_crash_data)
2381 return -ENOMEM;
Ben Greear384914b2014-08-25 08:37:32 +03002382
Marty Faltesekf67b107d2016-10-10 19:00:04 +03002383 ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
2384 if (!ar->debug.cal_data)
2385 return -ENOMEM;
2386
Michal Kazior53268492014-09-25 12:33:50 +02002387 INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +02002388 INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +02002389 INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +03002390 INIT_LIST_HEAD(&ar->debug.fw_stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +02002391
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002392 return 0;
2393}
2394
2395void ath10k_debug_destroy(struct ath10k *ar)
2396{
2397 vfree(ar->debug.fw_crash_data);
2398 ar->debug.fw_crash_data = NULL;
Michal Kazior53268492014-09-25 12:33:50 +02002399
Marty Faltesekf67b107d2016-10-10 19:00:04 +03002400 vfree(ar->debug.cal_data);
2401 ar->debug.cal_data = NULL;
2402
Michal Kazior53268492014-09-25 12:33:50 +02002403 ath10k_debug_fw_stats_reset(ar);
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002404
2405 kfree(ar->debug.tpc_stats);
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002406}
2407
2408int ath10k_debug_register(struct ath10k *ar)
2409{
Kalle Valo5e3dd152013-06-12 20:52:10 +03002410 ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
2411 ar->hw->wiphy->debugfsdir);
Michal Kazioradb43b22014-09-04 12:36:45 +02002412 if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
2413 if (IS_ERR(ar->debug.debugfs_phy))
2414 return PTR_ERR(ar->debug.debugfs_phy);
Kalle Valod8bb26b2014-09-14 12:50:33 +03002415
2416 return -ENOMEM;
Michal Kazioradb43b22014-09-04 12:36:45 +02002417 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03002418
Kalle Valoa3d135e2013-09-03 11:44:10 +03002419 INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
2420 ath10k_debug_htt_stats_dwork);
2421
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002422 init_completion(&ar->debug.tpc_complete);
Michal Kazior60ef4012014-09-25 12:33:48 +02002423 init_completion(&ar->debug.fw_stats_complete);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002424
2425 debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
2426 &fops_fw_stats);
2427
Ben Greearf51dbe72014-09-29 14:41:46 +03002428 debugfs_create_file("fw_reset_stats", S_IRUSR, ar->debug.debugfs_phy,
2429 ar, &fops_fw_reset_stats);
2430
Kalle Valo5e3dd152013-06-12 20:52:10 +03002431 debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
2432 &fops_wmi_services);
2433
Mohammed Shafi Shajakhan8bf1ba12015-11-24 22:26:37 +05302434 debugfs_create_file("simulate_fw_crash", S_IRUSR | S_IWUSR,
2435 ar->debug.debugfs_phy, ar, &fops_simulate_fw_crash);
Michal Kazior278c4a82013-07-22 14:08:51 +02002436
Ben Greear384914b2014-08-25 08:37:32 +03002437 debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
2438 ar, &fops_fw_crash_dump);
2439
Yanbo Li077a3802014-11-25 12:24:33 +02002440 debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR,
2441 ar->debug.debugfs_phy, ar, &fops_reg_addr);
2442
2443 debugfs_create_file("reg_value", S_IRUSR | S_IWUSR,
2444 ar->debug.debugfs_phy, ar, &fops_reg_value);
2445
Yanbo Li9f65ad22014-11-25 12:24:48 +02002446 debugfs_create_file("mem_value", S_IRUSR | S_IWUSR,
2447 ar->debug.debugfs_phy, ar, &fops_mem_value);
2448
Kalle Valo763b8cd2013-09-01 11:22:21 +03002449 debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
2450 ar, &fops_chip_id);
2451
Mohammed Shafi Shajakhan8bf1ba12015-11-24 22:26:37 +05302452 debugfs_create_file("htt_stats_mask", S_IRUSR | S_IWUSR,
2453 ar->debug.debugfs_phy, ar, &fops_htt_stats_mask);
Kalle Valoa3d135e2013-09-03 11:44:10 +03002454
Janusz Dziedzicd3856232014-06-02 21:19:46 +03002455 debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
2456 ar->debug.debugfs_phy, ar,
2457 &fops_htt_max_amsdu_ampdu);
2458
Mohammed Shafi Shajakhan8bf1ba12015-11-24 22:26:37 +05302459 debugfs_create_file("fw_dbglog", S_IRUSR | S_IWUSR,
2460 ar->debug.debugfs_phy, ar, &fops_fw_dbglog);
Kalle Valof118a3e2014-01-03 12:59:31 +02002461
Kalle Valo7869b4f2014-09-24 14:16:58 +03002462 debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
2463 ar, &fops_cal_data);
2464
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05302465 debugfs_create_file("ani_enable", S_IRUSR | S_IWUSR,
2466 ar->debug.debugfs_phy, ar, &fops_ani_enable);
2467
Peter Oha7bd3e92014-12-02 13:07:14 +02002468 debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR,
2469 ar->debug.debugfs_phy, ar, &fops_nf_cal_period);
2470
Masahiro Yamada97f26452016-08-03 13:45:50 -07002471 if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {
Janusz Dziedzic9702c682013-11-20 09:59:41 +02002472 debugfs_create_file("dfs_simulate_radar", S_IWUSR,
2473 ar->debug.debugfs_phy, ar,
2474 &fops_simulate_radar);
2475
Marek Puzyniak7d9b40b2013-11-20 10:00:28 +02002476 debugfs_create_bool("dfs_block_radar_events", S_IWUSR,
2477 ar->debug.debugfs_phy,
2478 &ar->dfs_block_radar_events);
2479
Janusz Dziedzic9702c682013-11-20 09:59:41 +02002480 debugfs_create_file("dfs_stats", S_IRUSR,
2481 ar->debug.debugfs_phy, ar,
2482 &fops_dfs_stats);
2483 }
2484
Rajkumar Manoharan90174452014-10-03 08:02:33 +03002485 debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR,
2486 ar->debug.debugfs_phy, ar, &fops_pktlog_filter);
2487
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302488 debugfs_create_file("quiet_period", S_IRUGO | S_IWUSR,
2489 ar->debug.debugfs_phy, ar, &fops_quiet_period);
2490
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002491 debugfs_create_file("tpc_stats", S_IRUSR,
2492 ar->debug.debugfs_phy, ar, &fops_tpc_stats);
2493
Yanbo Li844fa572015-10-31 11:07:21 +02002494 if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
2495 debugfs_create_file("btcoex", S_IRUGO | S_IWUSR,
2496 ar->debug.debugfs_phy, ar, &fops_btcoex);
2497
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302498 if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
2499 debugfs_create_file("peer_stats", S_IRUGO | S_IWUSR,
2500 ar->debug.debugfs_phy, ar,
2501 &fops_peer_stats);
2502
Kalle Valo9e100c42015-11-25 15:38:41 +02002503 debugfs_create_file("fw_checksums", S_IRUSR,
2504 ar->debug.debugfs_phy, ar, &fops_fw_checksums);
2505
Kalle Valo5e3dd152013-06-12 20:52:10 +03002506 return 0;
2507}
Kalle Valodb66ea02013-09-03 11:44:03 +03002508
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002509void ath10k_debug_unregister(struct ath10k *ar)
Kalle Valo60631c52013-10-08 21:45:25 +03002510{
2511 cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
2512}
2513
Kalle Valo5e3dd152013-06-12 20:52:10 +03002514#endif /* CONFIG_ATH10K_DEBUGFS */
2515
2516#ifdef CONFIG_ATH10K_DEBUG
Michal Kazior7aa7a722014-08-25 12:09:38 +02002517void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
2518 const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +03002519{
2520 struct va_format vaf;
2521 va_list args;
2522
2523 va_start(args, fmt);
2524
2525 vaf.fmt = fmt;
2526 vaf.va = &args;
2527
2528 if (ath10k_debug_mask & mask)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002529 dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002530
Michal Kaziord35a6c12014-09-02 11:00:21 +03002531 trace_ath10k_log_dbg(ar, mask, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002532
2533 va_end(args);
2534}
2535EXPORT_SYMBOL(ath10k_dbg);
2536
Michal Kazior7aa7a722014-08-25 12:09:38 +02002537void ath10k_dbg_dump(struct ath10k *ar,
2538 enum ath10k_debug_mask mask,
Kalle Valo5e3dd152013-06-12 20:52:10 +03002539 const char *msg, const char *prefix,
2540 const void *buf, size_t len)
2541{
Michal Kazior45724a82014-09-23 10:22:53 +02002542 char linebuf[256];
2543 unsigned int linebuflen;
2544 const void *ptr;
2545
Kalle Valo5e3dd152013-06-12 20:52:10 +03002546 if (ath10k_debug_mask & mask) {
2547 if (msg)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002548 ath10k_dbg(ar, mask, "%s\n", msg);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002549
Michal Kazior45724a82014-09-23 10:22:53 +02002550 for (ptr = buf; (ptr - buf) < len; ptr += 16) {
2551 linebuflen = 0;
2552 linebuflen += scnprintf(linebuf + linebuflen,
2553 sizeof(linebuf) - linebuflen,
2554 "%s%08x: ",
2555 (prefix ? prefix : ""),
2556 (unsigned int)(ptr - buf));
2557 hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
2558 linebuf + linebuflen,
2559 sizeof(linebuf) - linebuflen, true);
2560 dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
2561 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03002562 }
2563
2564 /* tracing code doesn't like null strings :/ */
Michal Kaziord35a6c12014-09-02 11:00:21 +03002565 trace_ath10k_log_dbg_dump(ar, msg ? msg : "", prefix ? prefix : "",
Kalle Valo5e3dd152013-06-12 20:52:10 +03002566 buf, len);
2567}
2568EXPORT_SYMBOL(ath10k_dbg_dump);
2569
2570#endif /* CONFIG_ATH10K_DEBUG */