blob: e1a70dffc52a80a351eb45a04c0e576333a3769e [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);
Michal Kazior53268492014-09-25 12:33:50 +0200403 ath10k_warn(ar, "dropping fw peer stats\n");
404 goto free;
405 }
406
Michal Kazior7b6b1532015-02-15 16:50:40 +0200407 if (num_vdevs >= BITS_PER_LONG) {
Mohammed Shafi Shajakhand57e7f22016-01-13 21:16:32 +0530408 ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200409 ath10k_warn(ar, "dropping fw vdev stats\n");
410 goto free;
411 }
412
Michal Kazior53268492014-09-25 12:33:50 +0200413 list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200414 list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300415 list_splice_tail_init(&stats.peers_extd,
416 &ar->debug.fw_stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +0200417 }
418
Michal Kazior60ef4012014-09-25 12:33:48 +0200419 complete(&ar->debug.fw_stats_complete);
Michal Kaziord15fb522014-09-25 12:33:47 +0200420
Michal Kazior53268492014-09-25 12:33:50 +0200421free:
422 /* In some cases lists have been spliced and cleared. Free up
423 * resources if that is not the case.
424 */
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530425 ath10k_fw_stats_pdevs_free(&stats.pdevs);
426 ath10k_fw_stats_vdevs_free(&stats.vdevs);
427 ath10k_fw_stats_peers_free(&stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300428 ath10k_fw_extd_stats_peers_free(&stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +0200429
Michal Kaziord15fb522014-09-25 12:33:47 +0200430 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300431}
432
Michal Kazior53268492014-09-25 12:33:50 +0200433static int ath10k_debug_fw_stats_request(struct ath10k *ar)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300434{
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300435 unsigned long timeout, time_left;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300436 int ret;
437
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200438 lockdep_assert_held(&ar->conf_mutex);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300439
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300440 timeout = jiffies + msecs_to_jiffies(1 * HZ);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300441
Michal Kazior53268492014-09-25 12:33:50 +0200442 ath10k_debug_fw_stats_reset(ar);
443
444 for (;;) {
445 if (time_after(jiffies, timeout))
446 return -ETIMEDOUT;
447
448 reinit_completion(&ar->debug.fw_stats_complete);
449
Yanbo Li6274cd42015-04-01 22:53:21 +0300450 ret = ath10k_wmi_request_stats(ar, ar->fw_stats_req_mask);
Michal Kazior53268492014-09-25 12:33:50 +0200451 if (ret) {
452 ath10k_warn(ar, "could not request stats (%d)\n", ret);
453 return ret;
454 }
455
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300456 time_left =
457 wait_for_completion_timeout(&ar->debug.fw_stats_complete,
458 1 * HZ);
459 if (!time_left)
Michal Kazior53268492014-09-25 12:33:50 +0200460 return -ETIMEDOUT;
461
462 spin_lock_bh(&ar->data_lock);
463 if (ar->debug.fw_stats_done) {
464 spin_unlock_bh(&ar->data_lock);
465 break;
466 }
467 spin_unlock_bh(&ar->data_lock);
468 }
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200469
470 return 0;
471}
472
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200473static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
474{
475 struct ath10k *ar = inode->i_private;
476 void *buf = NULL;
477 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300478
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200479 mutex_lock(&ar->conf_mutex);
480
481 if (ar->state != ATH10K_STATE_ON) {
482 ret = -ENETDOWN;
483 goto err_unlock;
484 }
485
486 buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);
487 if (!buf) {
488 ret = -ENOMEM;
489 goto err_unlock;
490 }
491
Michal Kazior53268492014-09-25 12:33:50 +0200492 ret = ath10k_debug_fw_stats_request(ar);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200493 if (ret) {
494 ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
495 goto err_free;
496 }
497
Manikanta Pubbisettybc6f9ae2015-10-16 15:54:52 +0300498 ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
499 if (ret) {
500 ath10k_warn(ar, "failed to fill fw stats: %d\n", ret);
501 goto err_free;
502 }
503
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200504 file->private_data = buf;
505
Kalle Valo5e3dd152013-06-12 20:52:10 +0300506 mutex_unlock(&ar->conf_mutex);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200507 return 0;
508
509err_free:
510 vfree(buf);
511
512err_unlock:
513 mutex_unlock(&ar->conf_mutex);
514 return ret;
515}
516
517static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
518{
519 vfree(file->private_data);
520
521 return 0;
522}
523
524static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
525 size_t count, loff_t *ppos)
526{
527 const char *buf = file->private_data;
528 unsigned int len = strlen(buf);
529
530 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300531}
532
533static const struct file_operations fops_fw_stats = {
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200534 .open = ath10k_fw_stats_open,
535 .release = ath10k_fw_stats_release,
Michal Kazior60ef4012014-09-25 12:33:48 +0200536 .read = ath10k_fw_stats_read,
Kalle Valo5e3dd152013-06-12 20:52:10 +0300537 .owner = THIS_MODULE,
538 .llseek = default_llseek,
539};
540
Ben Greearf51dbe72014-09-29 14:41:46 +0300541static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
542 char __user *user_buf,
543 size_t count, loff_t *ppos)
544{
545 struct ath10k *ar = file->private_data;
546 int ret, len, buf_len;
547 char *buf;
548
549 buf_len = 500;
550 buf = kmalloc(buf_len, GFP_KERNEL);
551 if (!buf)
552 return -ENOMEM;
553
554 spin_lock_bh(&ar->data_lock);
555
556 len = 0;
557 len += scnprintf(buf + len, buf_len - len,
558 "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
559 len += scnprintf(buf + len, buf_len - len,
560 "fw_warm_reset_counter\t\t%d\n",
561 ar->stats.fw_warm_reset_counter);
562 len += scnprintf(buf + len, buf_len - len,
563 "fw_cold_reset_counter\t\t%d\n",
564 ar->stats.fw_cold_reset_counter);
565
566 spin_unlock_bh(&ar->data_lock);
567
568 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
569
570 kfree(buf);
571
572 return ret;
573}
574
575static const struct file_operations fops_fw_reset_stats = {
576 .open = simple_open,
577 .read = ath10k_debug_fw_reset_stats_read,
578 .owner = THIS_MODULE,
579 .llseek = default_llseek,
580};
581
Ben Greeard5aebc72014-09-10 18:59:28 +0300582/* This is a clean assert crash in firmware. */
583static int ath10k_debug_fw_assert(struct ath10k *ar)
584{
585 struct wmi_vdev_install_key_cmd *cmd;
586 struct sk_buff *skb;
587
588 skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
589 if (!skb)
590 return -ENOMEM;
591
592 cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
593 memset(cmd, 0, sizeof(*cmd));
594
595 /* big enough number so that firmware asserts */
596 cmd->vdev_id = __cpu_to_le32(0x7ffe);
597
598 return ath10k_wmi_cmd_send(ar, skb,
599 ar->wmi.cmd->vdev_install_key_cmdid);
600}
601
Michal Kazior278c4a82013-07-22 14:08:51 +0200602static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
603 char __user *user_buf,
604 size_t count, loff_t *ppos)
605{
Kalle Valo75cb96d2014-09-14 12:50:44 +0300606 const char buf[] =
607 "To simulate firmware crash write one of the keywords to this file:\n"
608 "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
609 "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
Michal Kazior605cdba2014-10-28 10:34:37 +0100610 "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"
611 "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
Marek Puzyniak8c656992014-03-21 17:46:56 +0200612
Michal Kazior278c4a82013-07-22 14:08:51 +0200613 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
614}
615
Marek Puzyniak8c656992014-03-21 17:46:56 +0200616/* Simulate firmware crash:
617 * 'soft': Call wmi command causing firmware hang. This firmware hang is
618 * recoverable by warm firmware reset.
619 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
620 * vdev id. This is hard firmware crash because it is recoverable only by cold
621 * firmware reset.
622 */
Michal Kazior278c4a82013-07-22 14:08:51 +0200623static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
624 const char __user *user_buf,
625 size_t count, loff_t *ppos)
626{
627 struct ath10k *ar = file->private_data;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200628 char buf[32];
Michal Kazior278c4a82013-07-22 14:08:51 +0200629 int ret;
630
Michal Kazior278c4a82013-07-22 14:08:51 +0200631 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200632
633 /* make sure that buf is null terminated */
634 buf[sizeof(buf) - 1] = 0;
Michal Kazior278c4a82013-07-22 14:08:51 +0200635
Mohammed Shafi Shajakhanf5e30752016-05-28 11:25:41 +0300636 /* drop the possible '\n' from the end */
637 if (buf[count - 1] == '\n')
638 buf[count - 1] = 0;
639
640 mutex_lock(&ar->conf_mutex);
641
Michal Kazior278c4a82013-07-22 14:08:51 +0200642 if (ar->state != ATH10K_STATE_ON &&
643 ar->state != ATH10K_STATE_RESTARTED) {
644 ret = -ENETDOWN;
645 goto exit;
646 }
647
Marek Puzyniak8c656992014-03-21 17:46:56 +0200648 if (!strcmp(buf, "soft")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200649 ath10k_info(ar, "simulating soft firmware crash\n");
Marek Puzyniak8c656992014-03-21 17:46:56 +0200650 ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
651 } else if (!strcmp(buf, "hard")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200652 ath10k_info(ar, "simulating hard firmware crash\n");
Ben Greear611b3682014-07-25 11:56:40 +0300653 /* 0x7fff is vdev id, and it is always out of range for all
654 * firmware variants in order to force a firmware crash.
655 */
656 ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
Kalle Valo5b07e072014-09-14 12:50:06 +0300657 ar->wmi.vdev_param->rts_threshold,
658 0);
Ben Greeard5aebc72014-09-10 18:59:28 +0300659 } else if (!strcmp(buf, "assert")) {
660 ath10k_info(ar, "simulating firmware assert crash\n");
661 ret = ath10k_debug_fw_assert(ar);
Michal Kazior605cdba2014-10-28 10:34:37 +0100662 } else if (!strcmp(buf, "hw-restart")) {
663 ath10k_info(ar, "user requested hw restart\n");
664 queue_work(ar->workqueue, &ar->restart_work);
665 ret = 0;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200666 } else {
667 ret = -EINVAL;
668 goto exit;
669 }
Michal Kazior278c4a82013-07-22 14:08:51 +0200670
Marek Puzyniak8c656992014-03-21 17:46:56 +0200671 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200672 ath10k_warn(ar, "failed to simulate firmware crash: %d\n", ret);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200673 goto exit;
674 }
675
676 ret = count;
Michal Kazior278c4a82013-07-22 14:08:51 +0200677
678exit:
679 mutex_unlock(&ar->conf_mutex);
680 return ret;
681}
682
683static const struct file_operations fops_simulate_fw_crash = {
684 .read = ath10k_read_simulate_fw_crash,
685 .write = ath10k_write_simulate_fw_crash,
686 .open = simple_open,
687 .owner = THIS_MODULE,
688 .llseek = default_llseek,
689};
690
Kalle Valo763b8cd2013-09-01 11:22:21 +0300691static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf,
692 size_t count, loff_t *ppos)
693{
694 struct ath10k *ar = file->private_data;
695 unsigned int len;
696 char buf[50];
697
698 len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id);
699
700 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
701}
702
703static const struct file_operations fops_chip_id = {
704 .read = ath10k_read_chip_id,
705 .open = simple_open,
706 .owner = THIS_MODULE,
707 .llseek = default_llseek,
708};
709
Ben Greear384914b2014-08-25 08:37:32 +0300710struct ath10k_fw_crash_data *
711ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
712{
713 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
714
715 lockdep_assert_held(&ar->data_lock);
716
717 crash_data->crashed_since_read = true;
718 uuid_le_gen(&crash_data->uuid);
719 getnstimeofday(&crash_data->timestamp);
720
721 return crash_data;
722}
723EXPORT_SYMBOL(ath10k_debug_get_new_fw_crash_data);
724
Arun Khandavalli727000e2016-12-21 14:19:21 +0200725static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar,
726 bool mark_read)
Ben Greear384914b2014-08-25 08:37:32 +0300727{
728 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
729 struct ath10k_dump_file_data *dump_data;
730 struct ath10k_tlv_dump_data *dump_tlv;
731 int hdr_len = sizeof(*dump_data);
732 unsigned int len, sofar = 0;
733 unsigned char *buf;
734
735 len = hdr_len;
736 len += sizeof(*dump_tlv) + sizeof(crash_data->registers);
737
738 sofar += hdr_len;
739
740 /* This is going to get big when we start dumping FW RAM and such,
741 * so go ahead and use vmalloc.
742 */
743 buf = vzalloc(len);
744 if (!buf)
745 return NULL;
746
747 spin_lock_bh(&ar->data_lock);
748
749 if (!crash_data->crashed_since_read) {
750 spin_unlock_bh(&ar->data_lock);
751 vfree(buf);
752 return NULL;
753 }
754
755 dump_data = (struct ath10k_dump_file_data *)(buf);
756 strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP",
757 sizeof(dump_data->df_magic));
758 dump_data->len = cpu_to_le32(len);
759
760 dump_data->version = cpu_to_le32(ATH10K_FW_CRASH_DUMP_VERSION);
761
762 memcpy(dump_data->uuid, &crash_data->uuid, sizeof(dump_data->uuid));
763 dump_data->chip_id = cpu_to_le32(ar->chip_id);
764 dump_data->bus_type = cpu_to_le32(0);
765 dump_data->target_version = cpu_to_le32(ar->target_version);
766 dump_data->fw_version_major = cpu_to_le32(ar->fw_version_major);
767 dump_data->fw_version_minor = cpu_to_le32(ar->fw_version_minor);
768 dump_data->fw_version_release = cpu_to_le32(ar->fw_version_release);
769 dump_data->fw_version_build = cpu_to_le32(ar->fw_version_build);
770 dump_data->phy_capability = cpu_to_le32(ar->phy_capability);
771 dump_data->hw_min_tx_power = cpu_to_le32(ar->hw_min_tx_power);
772 dump_data->hw_max_tx_power = cpu_to_le32(ar->hw_max_tx_power);
773 dump_data->ht_cap_info = cpu_to_le32(ar->ht_cap_info);
774 dump_data->vht_cap_info = cpu_to_le32(ar->vht_cap_info);
775 dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains);
776
777 strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
778 sizeof(dump_data->fw_ver));
779
Johannes Berg12c27152014-11-21 18:58:49 +0200780 dump_data->kernel_ver_code = 0;
781 strlcpy(dump_data->kernel_ver, init_utsname()->release,
Ben Greear384914b2014-08-25 08:37:32 +0300782 sizeof(dump_data->kernel_ver));
783
784 dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
785 dump_data->tv_nsec = cpu_to_le64(crash_data->timestamp.tv_nsec);
786
787 /* Gather crash-dump */
788 dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
789 dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_REGISTERS);
790 dump_tlv->tlv_len = cpu_to_le32(sizeof(crash_data->registers));
791 memcpy(dump_tlv->tlv_data, &crash_data->registers,
792 sizeof(crash_data->registers));
793 sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers);
794
Arun Khandavalli727000e2016-12-21 14:19:21 +0200795 ar->debug.fw_crash_data->crashed_since_read = !mark_read;
Ben Greear384914b2014-08-25 08:37:32 +0300796
797 spin_unlock_bh(&ar->data_lock);
798
799 return dump_data;
800}
801
Arun Khandavalli727000e2016-12-21 14:19:21 +0200802int ath10k_debug_fw_devcoredump(struct ath10k *ar)
803{
804 struct ath10k_dump_file_data *dump;
805 void *dump_ptr;
806 u32 dump_len;
807
808 /* To keep the dump file available also for debugfs don't mark the
809 * file read, only debugfs should do that.
810 */
811 dump = ath10k_build_dump_file(ar, false);
812 if (!dump) {
813 ath10k_warn(ar, "no crash dump data found for devcoredump");
814 return -ENODATA;
815 }
816
817 /* Make a copy of the dump file for dev_coredumpv() as during the
818 * transition period we need to own the original file. Once
819 * fw_crash_dump debugfs file is removed no need to have a copy
820 * anymore.
821 */
822 dump_len = le32_to_cpu(dump->len);
823 dump_ptr = vzalloc(dump_len);
824
825 if (!dump_ptr)
826 return -ENOMEM;
827
828 memcpy(dump_ptr, dump, dump_len);
829
830 dev_coredumpv(ar->dev, dump_ptr, dump_len, GFP_KERNEL);
831
832 return 0;
833}
834
Ben Greear384914b2014-08-25 08:37:32 +0300835static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file)
836{
837 struct ath10k *ar = inode->i_private;
838 struct ath10k_dump_file_data *dump;
839
Arun Khandavalli727000e2016-12-21 14:19:21 +0200840 ath10k_warn(ar, "fw_crash_dump debugfs file is deprecated, please use /sys/class/devcoredump instead.");
841
842 dump = ath10k_build_dump_file(ar, true);
Ben Greear384914b2014-08-25 08:37:32 +0300843 if (!dump)
844 return -ENODATA;
845
846 file->private_data = dump;
847
848 return 0;
849}
850
851static ssize_t ath10k_fw_crash_dump_read(struct file *file,
852 char __user *user_buf,
853 size_t count, loff_t *ppos)
854{
855 struct ath10k_dump_file_data *dump_file = file->private_data;
856
857 return simple_read_from_buffer(user_buf, count, ppos,
858 dump_file,
859 le32_to_cpu(dump_file->len));
860}
861
862static int ath10k_fw_crash_dump_release(struct inode *inode,
863 struct file *file)
864{
865 vfree(file->private_data);
866
867 return 0;
868}
869
870static const struct file_operations fops_fw_crash_dump = {
871 .open = ath10k_fw_crash_dump_open,
872 .read = ath10k_fw_crash_dump_read,
873 .release = ath10k_fw_crash_dump_release,
874 .owner = THIS_MODULE,
875 .llseek = default_llseek,
876};
877
Yanbo Li077a3802014-11-25 12:24:33 +0200878static ssize_t ath10k_reg_addr_read(struct file *file,
879 char __user *user_buf,
880 size_t count, loff_t *ppos)
881{
882 struct ath10k *ar = file->private_data;
883 u8 buf[32];
884 unsigned int len = 0;
885 u32 reg_addr;
886
887 mutex_lock(&ar->conf_mutex);
888 reg_addr = ar->debug.reg_addr;
889 mutex_unlock(&ar->conf_mutex);
890
891 len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);
892
893 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
894}
895
896static ssize_t ath10k_reg_addr_write(struct file *file,
897 const char __user *user_buf,
898 size_t count, loff_t *ppos)
899{
900 struct ath10k *ar = file->private_data;
901 u32 reg_addr;
902 int ret;
903
904 ret = kstrtou32_from_user(user_buf, count, 0, &reg_addr);
905 if (ret)
906 return ret;
907
908 if (!IS_ALIGNED(reg_addr, 4))
909 return -EFAULT;
910
911 mutex_lock(&ar->conf_mutex);
912 ar->debug.reg_addr = reg_addr;
913 mutex_unlock(&ar->conf_mutex);
914
915 return count;
916}
917
918static const struct file_operations fops_reg_addr = {
919 .read = ath10k_reg_addr_read,
920 .write = ath10k_reg_addr_write,
921 .open = simple_open,
922 .owner = THIS_MODULE,
923 .llseek = default_llseek,
924};
925
926static ssize_t ath10k_reg_value_read(struct file *file,
927 char __user *user_buf,
928 size_t count, loff_t *ppos)
929{
930 struct ath10k *ar = file->private_data;
931 u8 buf[48];
932 unsigned int len;
933 u32 reg_addr, reg_val;
934 int ret;
935
936 mutex_lock(&ar->conf_mutex);
937
938 if (ar->state != ATH10K_STATE_ON &&
939 ar->state != ATH10K_STATE_UTF) {
940 ret = -ENETDOWN;
941 goto exit;
942 }
943
944 reg_addr = ar->debug.reg_addr;
945
946 reg_val = ath10k_hif_read32(ar, reg_addr);
947 len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);
948
949 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
950
951exit:
952 mutex_unlock(&ar->conf_mutex);
953
954 return ret;
955}
956
957static ssize_t ath10k_reg_value_write(struct file *file,
958 const char __user *user_buf,
959 size_t count, loff_t *ppos)
960{
961 struct ath10k *ar = file->private_data;
962 u32 reg_addr, reg_val;
963 int ret;
964
965 mutex_lock(&ar->conf_mutex);
966
967 if (ar->state != ATH10K_STATE_ON &&
968 ar->state != ATH10K_STATE_UTF) {
969 ret = -ENETDOWN;
970 goto exit;
971 }
972
973 reg_addr = ar->debug.reg_addr;
974
975 ret = kstrtou32_from_user(user_buf, count, 0, &reg_val);
976 if (ret)
977 goto exit;
978
979 ath10k_hif_write32(ar, reg_addr, reg_val);
980
981 ret = count;
982
983exit:
984 mutex_unlock(&ar->conf_mutex);
985
986 return ret;
987}
988
989static const struct file_operations fops_reg_value = {
990 .read = ath10k_reg_value_read,
991 .write = ath10k_reg_value_write,
992 .open = simple_open,
993 .owner = THIS_MODULE,
994 .llseek = default_llseek,
995};
996
Yanbo Li9f65ad22014-11-25 12:24:48 +0200997static ssize_t ath10k_mem_value_read(struct file *file,
998 char __user *user_buf,
999 size_t count, loff_t *ppos)
1000{
1001 struct ath10k *ar = file->private_data;
1002 u8 *buf;
1003 int ret;
1004
1005 if (*ppos < 0)
1006 return -EINVAL;
1007
1008 if (!count)
1009 return 0;
1010
1011 mutex_lock(&ar->conf_mutex);
1012
1013 buf = vmalloc(count);
1014 if (!buf) {
1015 ret = -ENOMEM;
1016 goto exit;
1017 }
1018
1019 if (ar->state != ATH10K_STATE_ON &&
1020 ar->state != ATH10K_STATE_UTF) {
1021 ret = -ENETDOWN;
1022 goto exit;
1023 }
1024
1025 ret = ath10k_hif_diag_read(ar, *ppos, buf, count);
1026 if (ret) {
1027 ath10k_warn(ar, "failed to read address 0x%08x via diagnose window fnrom debugfs: %d\n",
1028 (u32)(*ppos), ret);
1029 goto exit;
1030 }
1031
1032 ret = copy_to_user(user_buf, buf, count);
1033 if (ret) {
1034 ret = -EFAULT;
1035 goto exit;
1036 }
1037
1038 count -= ret;
1039 *ppos += count;
1040 ret = count;
1041
1042exit:
1043 vfree(buf);
1044 mutex_unlock(&ar->conf_mutex);
1045
1046 return ret;
1047}
1048
1049static ssize_t ath10k_mem_value_write(struct file *file,
1050 const char __user *user_buf,
1051 size_t count, loff_t *ppos)
1052{
1053 struct ath10k *ar = file->private_data;
1054 u8 *buf;
1055 int ret;
1056
1057 if (*ppos < 0)
1058 return -EINVAL;
1059
1060 if (!count)
1061 return 0;
1062
1063 mutex_lock(&ar->conf_mutex);
1064
1065 buf = vmalloc(count);
1066 if (!buf) {
1067 ret = -ENOMEM;
1068 goto exit;
1069 }
1070
1071 if (ar->state != ATH10K_STATE_ON &&
1072 ar->state != ATH10K_STATE_UTF) {
1073 ret = -ENETDOWN;
1074 goto exit;
1075 }
1076
1077 ret = copy_from_user(buf, user_buf, count);
1078 if (ret) {
1079 ret = -EFAULT;
1080 goto exit;
1081 }
1082
1083 ret = ath10k_hif_diag_write(ar, *ppos, buf, count);
1084 if (ret) {
1085 ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",
1086 (u32)(*ppos), ret);
1087 goto exit;
1088 }
1089
1090 *ppos += count;
1091 ret = count;
1092
1093exit:
1094 vfree(buf);
1095 mutex_unlock(&ar->conf_mutex);
1096
1097 return ret;
1098}
1099
1100static const struct file_operations fops_mem_value = {
1101 .read = ath10k_mem_value_read,
1102 .write = ath10k_mem_value_write,
1103 .open = simple_open,
1104 .owner = THIS_MODULE,
1105 .llseek = default_llseek,
1106};
1107
Kalle Valoa3d135e2013-09-03 11:44:10 +03001108static int ath10k_debug_htt_stats_req(struct ath10k *ar)
1109{
1110 u64 cookie;
1111 int ret;
1112
1113 lockdep_assert_held(&ar->conf_mutex);
1114
1115 if (ar->debug.htt_stats_mask == 0)
1116 /* htt stats are disabled */
1117 return 0;
1118
1119 if (ar->state != ATH10K_STATE_ON)
1120 return 0;
1121
1122 cookie = get_jiffies_64();
1123
1124 ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask,
1125 cookie);
1126 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001127 ath10k_warn(ar, "failed to send htt stats request: %d\n", ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001128 return ret;
1129 }
1130
1131 queue_delayed_work(ar->workqueue, &ar->debug.htt_stats_dwork,
1132 msecs_to_jiffies(ATH10K_DEBUG_HTT_STATS_INTERVAL));
1133
1134 return 0;
1135}
1136
1137static void ath10k_debug_htt_stats_dwork(struct work_struct *work)
1138{
1139 struct ath10k *ar = container_of(work, struct ath10k,
1140 debug.htt_stats_dwork.work);
1141
1142 mutex_lock(&ar->conf_mutex);
1143
1144 ath10k_debug_htt_stats_req(ar);
1145
1146 mutex_unlock(&ar->conf_mutex);
1147}
1148
1149static ssize_t ath10k_read_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001150 char __user *user_buf,
1151 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001152{
1153 struct ath10k *ar = file->private_data;
1154 char buf[32];
1155 unsigned int len;
1156
1157 len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask);
1158
1159 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1160}
1161
1162static ssize_t ath10k_write_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001163 const char __user *user_buf,
1164 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001165{
1166 struct ath10k *ar = file->private_data;
1167 unsigned long mask;
1168 int ret;
1169
1170 ret = kstrtoul_from_user(user_buf, count, 0, &mask);
1171 if (ret)
1172 return ret;
1173
1174 /* max 8 bit masks (for now) */
1175 if (mask > 0xff)
1176 return -E2BIG;
1177
1178 mutex_lock(&ar->conf_mutex);
1179
1180 ar->debug.htt_stats_mask = mask;
1181
1182 ret = ath10k_debug_htt_stats_req(ar);
1183 if (ret)
1184 goto out;
1185
1186 ret = count;
1187
1188out:
1189 mutex_unlock(&ar->conf_mutex);
1190
1191 return ret;
1192}
1193
1194static const struct file_operations fops_htt_stats_mask = {
1195 .read = ath10k_read_htt_stats_mask,
1196 .write = ath10k_write_htt_stats_mask,
1197 .open = simple_open,
1198 .owner = THIS_MODULE,
1199 .llseek = default_llseek,
1200};
1201
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001202static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
1203 char __user *user_buf,
1204 size_t count, loff_t *ppos)
1205{
1206 struct ath10k *ar = file->private_data;
1207 char buf[64];
Mohammed Shafi Shajakhan81ec3c02015-11-30 22:29:39 +05301208 u8 amsdu, ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001209 unsigned int len;
1210
1211 mutex_lock(&ar->conf_mutex);
1212
David Liuccec9032015-07-24 20:25:32 +03001213 amsdu = ar->htt.max_num_amsdu;
1214 ampdu = ar->htt.max_num_ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001215 mutex_unlock(&ar->conf_mutex);
1216
1217 len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
1218
1219 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1220}
1221
1222static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
1223 const char __user *user_buf,
1224 size_t count, loff_t *ppos)
1225{
1226 struct ath10k *ar = file->private_data;
1227 int res;
1228 char buf[64];
1229 unsigned int amsdu, ampdu;
1230
1231 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
1232
1233 /* make sure that buf is null terminated */
1234 buf[sizeof(buf) - 1] = 0;
1235
1236 res = sscanf(buf, "%u %u", &amsdu, &ampdu);
1237
1238 if (res != 2)
1239 return -EINVAL;
1240
1241 mutex_lock(&ar->conf_mutex);
1242
1243 res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
1244 if (res)
1245 goto out;
1246
1247 res = count;
David Liuccec9032015-07-24 20:25:32 +03001248 ar->htt.max_num_amsdu = amsdu;
1249 ar->htt.max_num_ampdu = ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001250
1251out:
1252 mutex_unlock(&ar->conf_mutex);
1253 return res;
1254}
1255
1256static const struct file_operations fops_htt_max_amsdu_ampdu = {
1257 .read = ath10k_read_htt_max_amsdu_ampdu,
1258 .write = ath10k_write_htt_max_amsdu_ampdu,
1259 .open = simple_open,
1260 .owner = THIS_MODULE,
1261 .llseek = default_llseek,
1262};
1263
Kalle Valof118a3e2014-01-03 12:59:31 +02001264static ssize_t ath10k_read_fw_dbglog(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001265 char __user *user_buf,
1266 size_t count, loff_t *ppos)
Kalle Valof118a3e2014-01-03 12:59:31 +02001267{
1268 struct ath10k *ar = file->private_data;
1269 unsigned int len;
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301270 char buf[96];
Kalle Valof118a3e2014-01-03 12:59:31 +02001271
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301272 len = scnprintf(buf, sizeof(buf), "0x%16llx %u\n",
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301273 ar->debug.fw_dbglog_mask, ar->debug.fw_dbglog_level);
Kalle Valof118a3e2014-01-03 12:59:31 +02001274
1275 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1276}
1277
1278static ssize_t ath10k_write_fw_dbglog(struct file *file,
1279 const char __user *user_buf,
1280 size_t count, loff_t *ppos)
1281{
1282 struct ath10k *ar = file->private_data;
Kalle Valof118a3e2014-01-03 12:59:31 +02001283 int ret;
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301284 char buf[96];
1285 unsigned int log_level;
1286 u64 mask;
Kalle Valof118a3e2014-01-03 12:59:31 +02001287
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301288 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
1289
1290 /* make sure that buf is null terminated */
1291 buf[sizeof(buf) - 1] = 0;
1292
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301293 ret = sscanf(buf, "%llx %u", &mask, &log_level);
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301294
1295 if (!ret)
1296 return -EINVAL;
1297
1298 if (ret == 1)
1299 /* default if user did not specify */
1300 log_level = ATH10K_DBGLOG_LEVEL_WARN;
Kalle Valof118a3e2014-01-03 12:59:31 +02001301
1302 mutex_lock(&ar->conf_mutex);
1303
1304 ar->debug.fw_dbglog_mask = mask;
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301305 ar->debug.fw_dbglog_level = log_level;
Kalle Valof118a3e2014-01-03 12:59:31 +02001306
1307 if (ar->state == ATH10K_STATE_ON) {
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301308 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1309 ar->debug.fw_dbglog_level);
Kalle Valof118a3e2014-01-03 12:59:31 +02001310 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001311 ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n",
Kalle Valof118a3e2014-01-03 12:59:31 +02001312 ret);
1313 goto exit;
1314 }
1315 }
1316
1317 ret = count;
1318
1319exit:
1320 mutex_unlock(&ar->conf_mutex);
1321
1322 return ret;
1323}
1324
Ben Greear6cddcc72014-09-29 14:41:46 +03001325/* TODO: Would be nice to always support ethtool stats, would need to
1326 * move the stats storage out of ath10k_debug, or always have ath10k_debug
1327 * struct available..
1328 */
1329
1330/* This generally cooresponds to the debugfs fw_stats file */
1331static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
1332 "tx_pkts_nic",
1333 "tx_bytes_nic",
1334 "rx_pkts_nic",
1335 "rx_bytes_nic",
1336 "d_noise_floor",
1337 "d_cycle_count",
1338 "d_phy_error",
1339 "d_rts_bad",
1340 "d_rts_good",
1341 "d_tx_power", /* in .5 dbM I think */
1342 "d_rx_crc_err", /* fcs_bad */
1343 "d_no_beacon",
1344 "d_tx_mpdus_queued",
1345 "d_tx_msdu_queued",
1346 "d_tx_msdu_dropped",
1347 "d_local_enqued",
1348 "d_local_freed",
1349 "d_tx_ppdu_hw_queued",
1350 "d_tx_ppdu_reaped",
1351 "d_tx_fifo_underrun",
1352 "d_tx_ppdu_abort",
1353 "d_tx_mpdu_requed",
1354 "d_tx_excessive_retries",
1355 "d_tx_hw_rate",
1356 "d_tx_dropped_sw_retries",
1357 "d_tx_illegal_rate",
1358 "d_tx_continuous_xretries",
1359 "d_tx_timeout",
1360 "d_tx_mpdu_txop_limit",
1361 "d_pdev_resets",
1362 "d_rx_mid_ppdu_route_change",
1363 "d_rx_status",
1364 "d_rx_extra_frags_ring0",
1365 "d_rx_extra_frags_ring1",
1366 "d_rx_extra_frags_ring2",
1367 "d_rx_extra_frags_ring3",
1368 "d_rx_msdu_htt",
1369 "d_rx_mpdu_htt",
1370 "d_rx_msdu_stack",
1371 "d_rx_mpdu_stack",
1372 "d_rx_phy_err",
1373 "d_rx_phy_err_drops",
1374 "d_rx_mpdu_errors", /* FCS, MIC, ENC */
1375 "d_fw_crash_count",
1376 "d_fw_warm_reset_count",
1377 "d_fw_cold_reset_count",
1378};
1379
1380#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
1381
1382void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
1383 struct ieee80211_vif *vif,
1384 u32 sset, u8 *data)
1385{
1386 if (sset == ETH_SS_STATS)
1387 memcpy(data, *ath10k_gstrings_stats,
1388 sizeof(ath10k_gstrings_stats));
1389}
1390
1391int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
1392 struct ieee80211_vif *vif, int sset)
1393{
1394 if (sset == ETH_SS_STATS)
1395 return ATH10K_SSTATS_LEN;
1396
1397 return 0;
1398}
1399
1400void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
1401 struct ieee80211_vif *vif,
1402 struct ethtool_stats *stats, u64 *data)
1403{
1404 struct ath10k *ar = hw->priv;
1405 static const struct ath10k_fw_stats_pdev zero_stats = {};
1406 const struct ath10k_fw_stats_pdev *pdev_stats;
1407 int i = 0, ret;
1408
1409 mutex_lock(&ar->conf_mutex);
1410
1411 if (ar->state == ATH10K_STATE_ON) {
1412 ret = ath10k_debug_fw_stats_request(ar);
1413 if (ret) {
1414 /* just print a warning and try to use older results */
1415 ath10k_warn(ar,
1416 "failed to get fw stats for ethtool: %d\n",
1417 ret);
1418 }
1419 }
1420
1421 pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,
1422 struct ath10k_fw_stats_pdev,
1423 list);
1424 if (!pdev_stats) {
1425 /* no results available so just return zeroes */
1426 pdev_stats = &zero_stats;
1427 }
1428
1429 spin_lock_bh(&ar->data_lock);
1430
1431 data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
1432 data[i++] = 0; /* tx bytes */
1433 data[i++] = pdev_stats->htt_mpdus;
1434 data[i++] = 0; /* rx bytes */
1435 data[i++] = pdev_stats->ch_noise_floor;
1436 data[i++] = pdev_stats->cycle_count;
1437 data[i++] = pdev_stats->phy_err_count;
1438 data[i++] = pdev_stats->rts_bad;
1439 data[i++] = pdev_stats->rts_good;
1440 data[i++] = pdev_stats->chan_tx_power;
1441 data[i++] = pdev_stats->fcs_bad;
1442 data[i++] = pdev_stats->no_beacons;
1443 data[i++] = pdev_stats->mpdu_enqued;
1444 data[i++] = pdev_stats->msdu_enqued;
1445 data[i++] = pdev_stats->wmm_drop;
1446 data[i++] = pdev_stats->local_enqued;
1447 data[i++] = pdev_stats->local_freed;
1448 data[i++] = pdev_stats->hw_queued;
1449 data[i++] = pdev_stats->hw_reaped;
1450 data[i++] = pdev_stats->underrun;
1451 data[i++] = pdev_stats->tx_abort;
1452 data[i++] = pdev_stats->mpdus_requed;
1453 data[i++] = pdev_stats->tx_ko;
1454 data[i++] = pdev_stats->data_rc;
1455 data[i++] = pdev_stats->sw_retry_failure;
1456 data[i++] = pdev_stats->illgl_rate_phy_err;
1457 data[i++] = pdev_stats->pdev_cont_xretry;
1458 data[i++] = pdev_stats->pdev_tx_timeout;
1459 data[i++] = pdev_stats->txop_ovf;
1460 data[i++] = pdev_stats->pdev_resets;
1461 data[i++] = pdev_stats->mid_ppdu_route_change;
1462 data[i++] = pdev_stats->status_rcvd;
1463 data[i++] = pdev_stats->r0_frags;
1464 data[i++] = pdev_stats->r1_frags;
1465 data[i++] = pdev_stats->r2_frags;
1466 data[i++] = pdev_stats->r3_frags;
1467 data[i++] = pdev_stats->htt_msdus;
1468 data[i++] = pdev_stats->htt_mpdus;
1469 data[i++] = pdev_stats->loc_msdus;
1470 data[i++] = pdev_stats->loc_mpdus;
1471 data[i++] = pdev_stats->phy_errs;
1472 data[i++] = pdev_stats->phy_err_drop;
1473 data[i++] = pdev_stats->mpdu_errs;
1474 data[i++] = ar->stats.fw_crash_counter;
1475 data[i++] = ar->stats.fw_warm_reset_counter;
1476 data[i++] = ar->stats.fw_cold_reset_counter;
1477
1478 spin_unlock_bh(&ar->data_lock);
1479
1480 mutex_unlock(&ar->conf_mutex);
1481
1482 WARN_ON(i != ATH10K_SSTATS_LEN);
1483}
1484
Kalle Valof118a3e2014-01-03 12:59:31 +02001485static const struct file_operations fops_fw_dbglog = {
1486 .read = ath10k_read_fw_dbglog,
1487 .write = ath10k_write_fw_dbglog,
1488 .open = simple_open,
1489 .owner = THIS_MODULE,
1490 .llseek = default_llseek,
1491};
1492
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001493static int ath10k_debug_cal_data_fetch(struct ath10k *ar)
Kalle Valo7869b4f2014-09-24 14:16:58 +03001494{
Kalle Valo7869b4f2014-09-24 14:16:58 +03001495 u32 hi_addr;
1496 __le32 addr;
1497 int ret;
1498
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001499 lockdep_assert_held(&ar->conf_mutex);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001500
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001501 if (WARN_ON(ar->hw_params.cal_data_len > ATH10K_DEBUG_CAL_DATA_LEN))
1502 return -EINVAL;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001503
1504 hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
1505
1506 ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
1507 if (ret) {
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001508 ath10k_warn(ar, "failed to read hi_board_data address: %d\n",
1509 ret);
1510 return ret;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001511 }
1512
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001513 ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), ar->debug.cal_data,
Raja Mani0b8e3c42016-03-18 11:44:22 +02001514 ar->hw_params.cal_data_len);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001515 if (ret) {
1516 ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001517 return ret;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001518 }
1519
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001520 return 0;
1521}
Kalle Valo7869b4f2014-09-24 14:16:58 +03001522
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001523static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
1524{
1525 struct ath10k *ar = inode->i_private;
1526
1527 mutex_lock(&ar->conf_mutex);
1528
1529 if (ar->state == ATH10K_STATE_ON ||
1530 ar->state == ATH10K_STATE_UTF) {
1531 ath10k_debug_cal_data_fetch(ar);
1532 }
1533
1534 file->private_data = ar;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001535 mutex_unlock(&ar->conf_mutex);
1536
1537 return 0;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001538}
1539
1540static ssize_t ath10k_debug_cal_data_read(struct file *file,
1541 char __user *user_buf,
1542 size_t count, loff_t *ppos)
1543{
Raja Mani0b8e3c42016-03-18 11:44:22 +02001544 struct ath10k *ar = file->private_data;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001545
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001546 mutex_lock(&ar->conf_mutex);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001547
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001548 count = simple_read_from_buffer(user_buf, count, ppos,
1549 ar->debug.cal_data,
1550 ar->hw_params.cal_data_len);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001551
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001552 mutex_unlock(&ar->conf_mutex);
1553
1554 return count;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001555}
1556
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05301557static ssize_t ath10k_write_ani_enable(struct file *file,
1558 const char __user *user_buf,
1559 size_t count, loff_t *ppos)
1560{
1561 struct ath10k *ar = file->private_data;
1562 int ret;
1563 u8 enable;
1564
1565 if (kstrtou8_from_user(user_buf, count, 0, &enable))
1566 return -EINVAL;
1567
1568 mutex_lock(&ar->conf_mutex);
1569
1570 if (ar->ani_enabled == enable) {
1571 ret = count;
1572 goto exit;
1573 }
1574
1575 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->ani_enable,
1576 enable);
1577 if (ret) {
1578 ath10k_warn(ar, "ani_enable failed from debugfs: %d\n", ret);
1579 goto exit;
1580 }
1581 ar->ani_enabled = enable;
1582
1583 ret = count;
1584
1585exit:
1586 mutex_unlock(&ar->conf_mutex);
1587
1588 return ret;
1589}
1590
1591static ssize_t ath10k_read_ani_enable(struct file *file, char __user *user_buf,
1592 size_t count, loff_t *ppos)
1593{
1594 struct ath10k *ar = file->private_data;
1595 int len = 0;
1596 char buf[32];
1597
1598 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
1599 ar->ani_enabled);
1600
1601 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1602}
1603
1604static const struct file_operations fops_ani_enable = {
1605 .read = ath10k_read_ani_enable,
1606 .write = ath10k_write_ani_enable,
1607 .open = simple_open,
1608 .owner = THIS_MODULE,
1609 .llseek = default_llseek,
1610};
1611
Kalle Valo7869b4f2014-09-24 14:16:58 +03001612static const struct file_operations fops_cal_data = {
1613 .open = ath10k_debug_cal_data_open,
1614 .read = ath10k_debug_cal_data_read,
Kalle Valo7869b4f2014-09-24 14:16:58 +03001615 .owner = THIS_MODULE,
1616 .llseek = default_llseek,
1617};
1618
Peter Oha7bd3e92014-12-02 13:07:14 +02001619static ssize_t ath10k_read_nf_cal_period(struct file *file,
1620 char __user *user_buf,
1621 size_t count, loff_t *ppos)
1622{
1623 struct ath10k *ar = file->private_data;
1624 unsigned int len;
1625 char buf[32];
1626
1627 len = scnprintf(buf, sizeof(buf), "%d\n",
1628 ar->debug.nf_cal_period);
1629
1630 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1631}
1632
1633static ssize_t ath10k_write_nf_cal_period(struct file *file,
1634 const char __user *user_buf,
1635 size_t count, loff_t *ppos)
1636{
1637 struct ath10k *ar = file->private_data;
1638 unsigned long period;
1639 int ret;
1640
1641 ret = kstrtoul_from_user(user_buf, count, 0, &period);
1642 if (ret)
1643 return ret;
1644
1645 if (period > WMI_PDEV_PARAM_CAL_PERIOD_MAX)
1646 return -EINVAL;
1647
1648 /* there's no way to switch back to the firmware default */
1649 if (period == 0)
1650 return -EINVAL;
1651
1652 mutex_lock(&ar->conf_mutex);
1653
1654 ar->debug.nf_cal_period = period;
1655
1656 if (ar->state != ATH10K_STATE_ON) {
1657 /* firmware is not running, nothing else to do */
1658 ret = count;
1659 goto exit;
1660 }
1661
1662 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->cal_period,
1663 ar->debug.nf_cal_period);
1664 if (ret) {
1665 ath10k_warn(ar, "cal period cfg failed from debugfs: %d\n",
1666 ret);
1667 goto exit;
1668 }
1669
1670 ret = count;
1671
1672exit:
1673 mutex_unlock(&ar->conf_mutex);
1674
1675 return ret;
1676}
1677
1678static const struct file_operations fops_nf_cal_period = {
1679 .read = ath10k_read_nf_cal_period,
1680 .write = ath10k_write_nf_cal_period,
1681 .open = simple_open,
1682 .owner = THIS_MODULE,
1683 .llseek = default_llseek,
1684};
1685
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001686#define ATH10K_TPC_CONFIG_BUF_SIZE (1024 * 1024)
1687
1688static int ath10k_debug_tpc_stats_request(struct ath10k *ar)
1689{
1690 int ret;
1691 unsigned long time_left;
1692
1693 lockdep_assert_held(&ar->conf_mutex);
1694
1695 reinit_completion(&ar->debug.tpc_complete);
1696
1697 ret = ath10k_wmi_pdev_get_tpc_config(ar, WMI_TPC_CONFIG_PARAM);
1698 if (ret) {
1699 ath10k_warn(ar, "failed to request tpc config: %d\n", ret);
1700 return ret;
1701 }
1702
1703 time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
1704 1 * HZ);
1705 if (time_left == 0)
1706 return -ETIMEDOUT;
1707
1708 return 0;
1709}
1710
1711void ath10k_debug_tpc_stats_process(struct ath10k *ar,
1712 struct ath10k_tpc_stats *tpc_stats)
1713{
1714 spin_lock_bh(&ar->data_lock);
1715
1716 kfree(ar->debug.tpc_stats);
1717 ar->debug.tpc_stats = tpc_stats;
1718 complete(&ar->debug.tpc_complete);
1719
1720 spin_unlock_bh(&ar->data_lock);
1721}
1722
1723static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
1724 unsigned int j, char *buf, unsigned int *len)
1725{
1726 unsigned int i, buf_len;
1727 static const char table_str[][5] = { "CDD",
1728 "STBC",
1729 "TXBF" };
1730 static const char pream_str[][6] = { "CCK",
1731 "OFDM",
1732 "HT20",
1733 "HT40",
1734 "VHT20",
1735 "VHT40",
1736 "VHT80",
1737 "HTCUP" };
1738
1739 buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1740 *len += scnprintf(buf + *len, buf_len - *len,
1741 "********************************\n");
1742 *len += scnprintf(buf + *len, buf_len - *len,
1743 "******************* %s POWER TABLE ****************\n",
1744 table_str[j]);
1745 *len += scnprintf(buf + *len, buf_len - *len,
1746 "********************************\n");
1747 *len += scnprintf(buf + *len, buf_len - *len,
1748 "No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3\n");
1749
1750 for (i = 0; i < tpc_stats->rate_max; i++) {
1751 *len += scnprintf(buf + *len, buf_len - *len,
1752 "%8d %s 0x%2x %s\n", i,
1753 pream_str[tpc_stats->tpc_table[j].pream_idx[i]],
1754 tpc_stats->tpc_table[j].rate_code[i],
1755 tpc_stats->tpc_table[j].tpc_value[i]);
1756 }
1757
1758 *len += scnprintf(buf + *len, buf_len - *len,
1759 "***********************************\n");
1760}
1761
1762static void ath10k_tpc_stats_fill(struct ath10k *ar,
1763 struct ath10k_tpc_stats *tpc_stats,
1764 char *buf)
1765{
1766 unsigned int len, j, buf_len;
1767
1768 len = 0;
1769 buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1770
1771 spin_lock_bh(&ar->data_lock);
1772
1773 if (!tpc_stats) {
1774 ath10k_warn(ar, "failed to get tpc stats\n");
1775 goto unlock;
1776 }
1777
1778 len += scnprintf(buf + len, buf_len - len, "\n");
1779 len += scnprintf(buf + len, buf_len - len,
1780 "*************************************\n");
1781 len += scnprintf(buf + len, buf_len - len,
1782 "TPC config for channel %4d mode %d\n",
1783 tpc_stats->chan_freq,
1784 tpc_stats->phy_mode);
1785 len += scnprintf(buf + len, buf_len - len,
1786 "*************************************\n");
1787 len += scnprintf(buf + len, buf_len - len,
1788 "CTL = 0x%2x Reg. Domain = %2d\n",
1789 tpc_stats->ctl,
1790 tpc_stats->reg_domain);
1791 len += scnprintf(buf + len, buf_len - len,
1792 "Antenna Gain = %2d Reg. Max Antenna Gain = %2d\n",
1793 tpc_stats->twice_antenna_gain,
1794 tpc_stats->twice_antenna_reduction);
1795 len += scnprintf(buf + len, buf_len - len,
1796 "Power Limit = %2d Reg. Max Power = %2d\n",
1797 tpc_stats->power_limit,
1798 tpc_stats->twice_max_rd_power / 2);
1799 len += scnprintf(buf + len, buf_len - len,
1800 "Num tx chains = %2d Num supported rates = %2d\n",
1801 tpc_stats->num_tx_chain,
1802 tpc_stats->rate_max);
1803
1804 for (j = 0; j < tpc_stats->num_tx_chain ; j++) {
1805 switch (j) {
1806 case WMI_TPC_TABLE_TYPE_CDD:
1807 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1808 len += scnprintf(buf + len, buf_len - len,
1809 "CDD not supported\n");
1810 break;
1811 }
1812
1813 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1814 break;
1815 case WMI_TPC_TABLE_TYPE_STBC:
1816 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1817 len += scnprintf(buf + len, buf_len - len,
1818 "STBC not supported\n");
1819 break;
1820 }
1821
1822 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1823 break;
1824 case WMI_TPC_TABLE_TYPE_TXBF:
1825 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1826 len += scnprintf(buf + len, buf_len - len,
1827 "TXBF not supported\n***************************\n");
1828 break;
1829 }
1830
1831 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1832 break;
1833 default:
1834 len += scnprintf(buf + len, buf_len - len,
1835 "Invalid Type\n");
1836 break;
1837 }
1838 }
1839
1840unlock:
1841 spin_unlock_bh(&ar->data_lock);
1842
1843 if (len >= buf_len)
1844 buf[len - 1] = 0;
1845 else
1846 buf[len] = 0;
1847}
1848
1849static int ath10k_tpc_stats_open(struct inode *inode, struct file *file)
1850{
1851 struct ath10k *ar = inode->i_private;
1852 void *buf = NULL;
1853 int ret;
1854
1855 mutex_lock(&ar->conf_mutex);
1856
1857 if (ar->state != ATH10K_STATE_ON) {
1858 ret = -ENETDOWN;
1859 goto err_unlock;
1860 }
1861
1862 buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
1863 if (!buf) {
1864 ret = -ENOMEM;
1865 goto err_unlock;
1866 }
1867
1868 ret = ath10k_debug_tpc_stats_request(ar);
1869 if (ret) {
1870 ath10k_warn(ar, "failed to request tpc config stats: %d\n",
1871 ret);
1872 goto err_free;
1873 }
1874
1875 ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
1876 file->private_data = buf;
1877
1878 mutex_unlock(&ar->conf_mutex);
1879 return 0;
1880
1881err_free:
1882 vfree(buf);
1883
1884err_unlock:
1885 mutex_unlock(&ar->conf_mutex);
1886 return ret;
1887}
1888
1889static int ath10k_tpc_stats_release(struct inode *inode, struct file *file)
1890{
1891 vfree(file->private_data);
1892
1893 return 0;
1894}
1895
1896static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf,
1897 size_t count, loff_t *ppos)
1898{
1899 const char *buf = file->private_data;
1900 unsigned int len = strlen(buf);
1901
1902 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1903}
1904
1905static const struct file_operations fops_tpc_stats = {
1906 .open = ath10k_tpc_stats_open,
1907 .release = ath10k_tpc_stats_release,
1908 .read = ath10k_tpc_stats_read,
1909 .owner = THIS_MODULE,
1910 .llseek = default_llseek,
1911};
1912
Kalle Valodb66ea02013-09-03 11:44:03 +03001913int ath10k_debug_start(struct ath10k *ar)
1914{
Kalle Valoa3d135e2013-09-03 11:44:10 +03001915 int ret;
1916
Kalle Valo60631c52013-10-08 21:45:25 +03001917 lockdep_assert_held(&ar->conf_mutex);
1918
Kalle Valoa3d135e2013-09-03 11:44:10 +03001919 ret = ath10k_debug_htt_stats_req(ar);
1920 if (ret)
1921 /* continue normally anyway, this isn't serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001922 ath10k_warn(ar, "failed to start htt stats workqueue: %d\n",
1923 ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001924
Kalle Valof118a3e2014-01-03 12:59:31 +02001925 if (ar->debug.fw_dbglog_mask) {
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301926 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1927 ATH10K_DBGLOG_LEVEL_WARN);
Kalle Valof118a3e2014-01-03 12:59:31 +02001928 if (ret)
1929 /* not serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001930 ath10k_warn(ar, "failed to enable dbglog during start: %d",
Kalle Valof118a3e2014-01-03 12:59:31 +02001931 ret);
1932 }
1933
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001934 if (ar->debug.pktlog_filter) {
1935 ret = ath10k_wmi_pdev_pktlog_enable(ar,
1936 ar->debug.pktlog_filter);
1937 if (ret)
1938 /* not serious */
1939 ath10k_warn(ar,
1940 "failed to enable pktlog filter %x: %d\n",
1941 ar->debug.pktlog_filter, ret);
1942 } else {
1943 ret = ath10k_wmi_pdev_pktlog_disable(ar);
1944 if (ret)
1945 /* not serious */
1946 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
1947 }
1948
Peter Oha7bd3e92014-12-02 13:07:14 +02001949 if (ar->debug.nf_cal_period) {
1950 ret = ath10k_wmi_pdev_set_param(ar,
1951 ar->wmi.pdev_param->cal_period,
1952 ar->debug.nf_cal_period);
1953 if (ret)
1954 /* not serious */
1955 ath10k_warn(ar, "cal period cfg failed from debug start: %d\n",
1956 ret);
1957 }
1958
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001959 return ret;
Kalle Valodb66ea02013-09-03 11:44:03 +03001960}
1961
1962void ath10k_debug_stop(struct ath10k *ar)
1963{
Kalle Valo60631c52013-10-08 21:45:25 +03001964 lockdep_assert_held(&ar->conf_mutex);
1965
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001966 ath10k_debug_cal_data_fetch(ar);
1967
Kalle Valo60631c52013-10-08 21:45:25 +03001968 /* Must not use _sync to avoid deadlock, we do that in
1969 * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid
1970 * warning from del_timer(). */
1971 if (ar->debug.htt_stats_mask != 0)
1972 cancel_delayed_work(&ar->debug.htt_stats_dwork);
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001973
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001974 ath10k_wmi_pdev_pktlog_disable(ar);
Kalle Valodb66ea02013-09-03 11:44:03 +03001975}
1976
Janusz Dziedzic9702c682013-11-20 09:59:41 +02001977static ssize_t ath10k_write_simulate_radar(struct file *file,
1978 const char __user *user_buf,
1979 size_t count, loff_t *ppos)
1980{
1981 struct ath10k *ar = file->private_data;
1982
1983 ieee80211_radar_detected(ar->hw);
1984
1985 return count;
1986}
1987
1988static const struct file_operations fops_simulate_radar = {
1989 .write = ath10k_write_simulate_radar,
1990 .open = simple_open,
1991 .owner = THIS_MODULE,
1992 .llseek = default_llseek,
1993};
1994
1995#define ATH10K_DFS_STAT(s, p) (\
1996 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
1997 ar->debug.dfs_stats.p))
1998
1999#define ATH10K_DFS_POOL_STAT(s, p) (\
2000 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
2001 ar->debug.dfs_pool_stats.p))
2002
2003static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf,
2004 size_t count, loff_t *ppos)
2005{
2006 int retval = 0, len = 0;
2007 const int size = 8000;
2008 struct ath10k *ar = file->private_data;
2009 char *buf;
2010
2011 buf = kzalloc(size, GFP_KERNEL);
2012 if (buf == NULL)
2013 return -ENOMEM;
2014
2015 if (!ar->dfs_detector) {
2016 len += scnprintf(buf + len, size - len, "DFS not enabled\n");
2017 goto exit;
2018 }
2019
2020 ar->debug.dfs_pool_stats =
2021 ar->dfs_detector->get_stats(ar->dfs_detector);
2022
2023 len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");
2024
2025 ATH10K_DFS_STAT("reported phy errors", phy_errors);
2026 ATH10K_DFS_STAT("pulse events reported", pulses_total);
2027 ATH10K_DFS_STAT("DFS pulses detected", pulses_detected);
2028 ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded);
2029 ATH10K_DFS_STAT("Radars detected", radar_detected);
2030
2031 len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");
2032 ATH10K_DFS_POOL_STAT("Pool references", pool_reference);
2033 ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated);
2034 ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error);
2035 ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used);
2036 ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated);
2037 ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error);
2038 ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used);
2039
2040exit:
2041 if (len > size)
2042 len = size;
2043
2044 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
2045 kfree(buf);
2046
2047 return retval;
2048}
2049
2050static const struct file_operations fops_dfs_stats = {
2051 .read = ath10k_read_dfs_stats,
2052 .open = simple_open,
2053 .owner = THIS_MODULE,
2054 .llseek = default_llseek,
2055};
2056
Rajkumar Manoharan90174452014-10-03 08:02:33 +03002057static ssize_t ath10k_write_pktlog_filter(struct file *file,
2058 const char __user *ubuf,
2059 size_t count, loff_t *ppos)
2060{
2061 struct ath10k *ar = file->private_data;
2062 u32 filter;
2063 int ret;
2064
2065 if (kstrtouint_from_user(ubuf, count, 0, &filter))
2066 return -EINVAL;
2067
2068 mutex_lock(&ar->conf_mutex);
2069
2070 if (ar->state != ATH10K_STATE_ON) {
2071 ar->debug.pktlog_filter = filter;
2072 ret = count;
2073 goto out;
2074 }
2075
Anilkumar Kolli9ddc4862016-03-11 11:46:39 +05302076 if (filter == ar->debug.pktlog_filter) {
2077 ret = count;
2078 goto out;
2079 }
2080
2081 if (filter) {
Rajkumar Manoharan90174452014-10-03 08:02:33 +03002082 ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
2083 if (ret) {
2084 ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
2085 ar->debug.pktlog_filter, ret);
2086 goto out;
2087 }
2088 } else {
2089 ret = ath10k_wmi_pdev_pktlog_disable(ar);
2090 if (ret) {
2091 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
2092 goto out;
2093 }
2094 }
2095
2096 ar->debug.pktlog_filter = filter;
2097 ret = count;
2098
2099out:
2100 mutex_unlock(&ar->conf_mutex);
2101 return ret;
2102}
2103
2104static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf,
2105 size_t count, loff_t *ppos)
2106{
2107 char buf[32];
2108 struct ath10k *ar = file->private_data;
2109 int len = 0;
2110
2111 mutex_lock(&ar->conf_mutex);
2112 len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
2113 ar->debug.pktlog_filter);
2114 mutex_unlock(&ar->conf_mutex);
2115
2116 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2117}
2118
2119static const struct file_operations fops_pktlog_filter = {
2120 .read = ath10k_read_pktlog_filter,
2121 .write = ath10k_write_pktlog_filter,
2122 .open = simple_open
2123};
2124
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302125static ssize_t ath10k_write_quiet_period(struct file *file,
2126 const char __user *ubuf,
2127 size_t count, loff_t *ppos)
2128{
2129 struct ath10k *ar = file->private_data;
2130 u32 period;
2131
2132 if (kstrtouint_from_user(ubuf, count, 0, &period))
2133 return -EINVAL;
2134
2135 if (period < ATH10K_QUIET_PERIOD_MIN) {
2136 ath10k_warn(ar, "Quiet period %u can not be lesser than 25ms\n",
2137 period);
2138 return -EINVAL;
2139 }
2140 mutex_lock(&ar->conf_mutex);
2141 ar->thermal.quiet_period = period;
Rajkumar Manoharan8515b5c2015-03-15 20:36:22 +05302142 ath10k_thermal_set_throttling(ar);
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302143 mutex_unlock(&ar->conf_mutex);
2144
2145 return count;
2146}
2147
2148static ssize_t ath10k_read_quiet_period(struct file *file, char __user *ubuf,
2149 size_t count, loff_t *ppos)
2150{
2151 char buf[32];
2152 struct ath10k *ar = file->private_data;
2153 int len = 0;
2154
2155 mutex_lock(&ar->conf_mutex);
2156 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2157 ar->thermal.quiet_period);
2158 mutex_unlock(&ar->conf_mutex);
2159
2160 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2161}
2162
2163static const struct file_operations fops_quiet_period = {
2164 .read = ath10k_read_quiet_period,
2165 .write = ath10k_write_quiet_period,
2166 .open = simple_open
2167};
2168
Yanbo Li844fa572015-10-31 11:07:21 +02002169static ssize_t ath10k_write_btcoex(struct file *file,
2170 const char __user *ubuf,
2171 size_t count, loff_t *ppos)
2172{
2173 struct ath10k *ar = file->private_data;
2174 char buf[32];
2175 size_t buf_size;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302176 int ret;
Yanbo Li844fa572015-10-31 11:07:21 +02002177 bool val;
Rajkumar Manoharan39136242016-05-27 20:15:59 +05302178 u32 pdev_param;
Yanbo Li844fa572015-10-31 11:07:21 +02002179
2180 buf_size = min(count, (sizeof(buf) - 1));
2181 if (copy_from_user(buf, ubuf, buf_size))
2182 return -EFAULT;
2183
2184 buf[buf_size] = '\0';
2185
2186 if (strtobool(buf, &val) != 0)
2187 return -EINVAL;
2188
2189 mutex_lock(&ar->conf_mutex);
2190
Mohammed Shafi Shajakhanc28e6f02016-02-23 12:58:36 +05302191 if (ar->state != ATH10K_STATE_ON &&
2192 ar->state != ATH10K_STATE_RESTARTED) {
2193 ret = -ENETDOWN;
2194 goto exit;
2195 }
2196
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302197 if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) {
2198 ret = count;
Yanbo Li844fa572015-10-31 11:07:21 +02002199 goto exit;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302200 }
Yanbo Li844fa572015-10-31 11:07:21 +02002201
Rajkumar Manoharan39136242016-05-27 20:15:59 +05302202 pdev_param = ar->wmi.pdev_param->enable_btcoex;
2203 if (test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM,
2204 ar->running_fw->fw_file.fw_features)) {
2205 ret = ath10k_wmi_pdev_set_param(ar, pdev_param, val);
2206 if (ret) {
2207 ath10k_warn(ar, "failed to enable btcoex: %d\n", ret);
2208 ret = count;
2209 goto exit;
2210 }
2211 } else {
2212 ath10k_info(ar, "restarting firmware due to btcoex change");
2213 queue_work(ar->workqueue, &ar->restart_work);
2214 }
2215
Yanbo Li844fa572015-10-31 11:07:21 +02002216 if (val)
2217 set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
2218 else
2219 clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
2220
Mohammed Shafi Shajakhanc28e6f02016-02-23 12:58:36 +05302221 ret = count;
Yanbo Li844fa572015-10-31 11:07:21 +02002222
2223exit:
2224 mutex_unlock(&ar->conf_mutex);
2225
Mohammed Shafi Shajakhanc28e6f02016-02-23 12:58:36 +05302226 return ret;
Yanbo Li844fa572015-10-31 11:07:21 +02002227}
2228
2229static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
2230 size_t count, loff_t *ppos)
2231{
2232 char buf[32];
2233 struct ath10k *ar = file->private_data;
2234 int len = 0;
2235
2236 mutex_lock(&ar->conf_mutex);
2237 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2238 test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));
2239 mutex_unlock(&ar->conf_mutex);
2240
2241 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2242}
2243
2244static const struct file_operations fops_btcoex = {
2245 .read = ath10k_read_btcoex,
2246 .write = ath10k_write_btcoex,
2247 .open = simple_open
2248};
2249
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302250static ssize_t ath10k_write_peer_stats(struct file *file,
2251 const char __user *ubuf,
2252 size_t count, loff_t *ppos)
2253{
2254 struct ath10k *ar = file->private_data;
2255 char buf[32];
2256 size_t buf_size;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302257 int ret;
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302258 bool val;
2259
2260 buf_size = min(count, (sizeof(buf) - 1));
2261 if (copy_from_user(buf, ubuf, buf_size))
2262 return -EFAULT;
2263
2264 buf[buf_size] = '\0';
2265
2266 if (strtobool(buf, &val) != 0)
2267 return -EINVAL;
2268
2269 mutex_lock(&ar->conf_mutex);
2270
2271 if (ar->state != ATH10K_STATE_ON &&
2272 ar->state != ATH10K_STATE_RESTARTED) {
2273 ret = -ENETDOWN;
2274 goto exit;
2275 }
2276
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302277 if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val)) {
2278 ret = count;
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302279 goto exit;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302280 }
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302281
2282 if (val)
2283 set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
2284 else
2285 clear_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
2286
2287 ath10k_info(ar, "restarting firmware due to Peer stats change");
2288
2289 queue_work(ar->workqueue, &ar->restart_work);
2290 ret = count;
2291
2292exit:
2293 mutex_unlock(&ar->conf_mutex);
2294 return ret;
2295}
2296
2297static ssize_t ath10k_read_peer_stats(struct file *file, char __user *ubuf,
2298 size_t count, loff_t *ppos)
2299
2300{
2301 char buf[32];
2302 struct ath10k *ar = file->private_data;
2303 int len = 0;
2304
2305 mutex_lock(&ar->conf_mutex);
2306 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2307 test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags));
2308 mutex_unlock(&ar->conf_mutex);
2309
2310 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2311}
2312
2313static const struct file_operations fops_peer_stats = {
2314 .read = ath10k_read_peer_stats,
2315 .write = ath10k_write_peer_stats,
2316 .open = simple_open
2317};
2318
Kalle Valo9e100c42015-11-25 15:38:41 +02002319static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
2320 char __user *user_buf,
2321 size_t count, loff_t *ppos)
2322{
2323 struct ath10k *ar = file->private_data;
2324 unsigned int len = 0, buf_len = 4096;
2325 ssize_t ret_cnt;
2326 char *buf;
2327
2328 buf = kzalloc(buf_len, GFP_KERNEL);
2329 if (!buf)
2330 return -ENOMEM;
2331
2332 mutex_lock(&ar->conf_mutex);
2333
Kalle Valo9e100c42015-11-25 15:38:41 +02002334 len += scnprintf(buf + len, buf_len - len,
2335 "firmware-N.bin\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002336 crc32_le(0, ar->normal_mode_fw.fw_file.firmware->data,
2337 ar->normal_mode_fw.fw_file.firmware->size));
Kalle Valo9e100c42015-11-25 15:38:41 +02002338 len += scnprintf(buf + len, buf_len - len,
2339 "athwlan\t\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002340 crc32_le(0, ar->normal_mode_fw.fw_file.firmware_data,
2341 ar->normal_mode_fw.fw_file.firmware_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002342 len += scnprintf(buf + len, buf_len - len,
2343 "otp\t\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002344 crc32_le(0, ar->normal_mode_fw.fw_file.otp_data,
2345 ar->normal_mode_fw.fw_file.otp_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002346 len += scnprintf(buf + len, buf_len - len,
2347 "codeswap\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002348 crc32_le(0, ar->normal_mode_fw.fw_file.codeswap_data,
2349 ar->normal_mode_fw.fw_file.codeswap_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002350 len += scnprintf(buf + len, buf_len - len,
2351 "board-N.bin\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002352 crc32_le(0, ar->normal_mode_fw.board->data,
2353 ar->normal_mode_fw.board->size));
Kalle Valo9e100c42015-11-25 15:38:41 +02002354 len += scnprintf(buf + len, buf_len - len,
2355 "board\t\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002356 crc32_le(0, ar->normal_mode_fw.board_data,
2357 ar->normal_mode_fw.board_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002358
2359 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
2360
2361 mutex_unlock(&ar->conf_mutex);
2362
2363 kfree(buf);
2364 return ret_cnt;
2365}
2366
2367static const struct file_operations fops_fw_checksums = {
2368 .read = ath10k_debug_fw_checksums_read,
2369 .open = simple_open,
2370 .owner = THIS_MODULE,
2371 .llseek = default_llseek,
2372};
2373
Kalle Valo5e3dd152013-06-12 20:52:10 +03002374int ath10k_debug_create(struct ath10k *ar)
2375{
Ben Greear384914b2014-08-25 08:37:32 +03002376 ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002377 if (!ar->debug.fw_crash_data)
2378 return -ENOMEM;
Ben Greear384914b2014-08-25 08:37:32 +03002379
Marty Faltesekf67b107d2016-10-10 19:00:04 +03002380 ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
2381 if (!ar->debug.cal_data)
2382 return -ENOMEM;
2383
Michal Kazior53268492014-09-25 12:33:50 +02002384 INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +02002385 INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +02002386 INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +03002387 INIT_LIST_HEAD(&ar->debug.fw_stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +02002388
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002389 return 0;
2390}
2391
2392void ath10k_debug_destroy(struct ath10k *ar)
2393{
2394 vfree(ar->debug.fw_crash_data);
2395 ar->debug.fw_crash_data = NULL;
Michal Kazior53268492014-09-25 12:33:50 +02002396
Marty Faltesekf67b107d2016-10-10 19:00:04 +03002397 vfree(ar->debug.cal_data);
2398 ar->debug.cal_data = NULL;
2399
Michal Kazior53268492014-09-25 12:33:50 +02002400 ath10k_debug_fw_stats_reset(ar);
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002401
2402 kfree(ar->debug.tpc_stats);
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002403}
2404
2405int ath10k_debug_register(struct ath10k *ar)
2406{
Kalle Valo5e3dd152013-06-12 20:52:10 +03002407 ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
2408 ar->hw->wiphy->debugfsdir);
Michal Kazioradb43b22014-09-04 12:36:45 +02002409 if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
2410 if (IS_ERR(ar->debug.debugfs_phy))
2411 return PTR_ERR(ar->debug.debugfs_phy);
Kalle Valod8bb26b2014-09-14 12:50:33 +03002412
2413 return -ENOMEM;
Michal Kazioradb43b22014-09-04 12:36:45 +02002414 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03002415
Kalle Valoa3d135e2013-09-03 11:44:10 +03002416 INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
2417 ath10k_debug_htt_stats_dwork);
2418
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002419 init_completion(&ar->debug.tpc_complete);
Michal Kazior60ef4012014-09-25 12:33:48 +02002420 init_completion(&ar->debug.fw_stats_complete);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002421
2422 debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
2423 &fops_fw_stats);
2424
Ben Greearf51dbe72014-09-29 14:41:46 +03002425 debugfs_create_file("fw_reset_stats", S_IRUSR, ar->debug.debugfs_phy,
2426 ar, &fops_fw_reset_stats);
2427
Kalle Valo5e3dd152013-06-12 20:52:10 +03002428 debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
2429 &fops_wmi_services);
2430
Mohammed Shafi Shajakhan8bf1ba12015-11-24 22:26:37 +05302431 debugfs_create_file("simulate_fw_crash", S_IRUSR | S_IWUSR,
2432 ar->debug.debugfs_phy, ar, &fops_simulate_fw_crash);
Michal Kazior278c4a82013-07-22 14:08:51 +02002433
Ben Greear384914b2014-08-25 08:37:32 +03002434 debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
2435 ar, &fops_fw_crash_dump);
2436
Yanbo Li077a3802014-11-25 12:24:33 +02002437 debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR,
2438 ar->debug.debugfs_phy, ar, &fops_reg_addr);
2439
2440 debugfs_create_file("reg_value", S_IRUSR | S_IWUSR,
2441 ar->debug.debugfs_phy, ar, &fops_reg_value);
2442
Yanbo Li9f65ad22014-11-25 12:24:48 +02002443 debugfs_create_file("mem_value", S_IRUSR | S_IWUSR,
2444 ar->debug.debugfs_phy, ar, &fops_mem_value);
2445
Kalle Valo763b8cd2013-09-01 11:22:21 +03002446 debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
2447 ar, &fops_chip_id);
2448
Mohammed Shafi Shajakhan8bf1ba12015-11-24 22:26:37 +05302449 debugfs_create_file("htt_stats_mask", S_IRUSR | S_IWUSR,
2450 ar->debug.debugfs_phy, ar, &fops_htt_stats_mask);
Kalle Valoa3d135e2013-09-03 11:44:10 +03002451
Janusz Dziedzicd3856232014-06-02 21:19:46 +03002452 debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
2453 ar->debug.debugfs_phy, ar,
2454 &fops_htt_max_amsdu_ampdu);
2455
Mohammed Shafi Shajakhan8bf1ba12015-11-24 22:26:37 +05302456 debugfs_create_file("fw_dbglog", S_IRUSR | S_IWUSR,
2457 ar->debug.debugfs_phy, ar, &fops_fw_dbglog);
Kalle Valof118a3e2014-01-03 12:59:31 +02002458
Kalle Valo7869b4f2014-09-24 14:16:58 +03002459 debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
2460 ar, &fops_cal_data);
2461
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05302462 debugfs_create_file("ani_enable", S_IRUSR | S_IWUSR,
2463 ar->debug.debugfs_phy, ar, &fops_ani_enable);
2464
Peter Oha7bd3e92014-12-02 13:07:14 +02002465 debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR,
2466 ar->debug.debugfs_phy, ar, &fops_nf_cal_period);
2467
Masahiro Yamada97f26452016-08-03 13:45:50 -07002468 if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {
Janusz Dziedzic9702c682013-11-20 09:59:41 +02002469 debugfs_create_file("dfs_simulate_radar", S_IWUSR,
2470 ar->debug.debugfs_phy, ar,
2471 &fops_simulate_radar);
2472
Marek Puzyniak7d9b40b2013-11-20 10:00:28 +02002473 debugfs_create_bool("dfs_block_radar_events", S_IWUSR,
2474 ar->debug.debugfs_phy,
2475 &ar->dfs_block_radar_events);
2476
Janusz Dziedzic9702c682013-11-20 09:59:41 +02002477 debugfs_create_file("dfs_stats", S_IRUSR,
2478 ar->debug.debugfs_phy, ar,
2479 &fops_dfs_stats);
2480 }
2481
Rajkumar Manoharan90174452014-10-03 08:02:33 +03002482 debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR,
2483 ar->debug.debugfs_phy, ar, &fops_pktlog_filter);
2484
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302485 debugfs_create_file("quiet_period", S_IRUGO | S_IWUSR,
2486 ar->debug.debugfs_phy, ar, &fops_quiet_period);
2487
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002488 debugfs_create_file("tpc_stats", S_IRUSR,
2489 ar->debug.debugfs_phy, ar, &fops_tpc_stats);
2490
Yanbo Li844fa572015-10-31 11:07:21 +02002491 if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
2492 debugfs_create_file("btcoex", S_IRUGO | S_IWUSR,
2493 ar->debug.debugfs_phy, ar, &fops_btcoex);
2494
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302495 if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
2496 debugfs_create_file("peer_stats", S_IRUGO | S_IWUSR,
2497 ar->debug.debugfs_phy, ar,
2498 &fops_peer_stats);
2499
Kalle Valo9e100c42015-11-25 15:38:41 +02002500 debugfs_create_file("fw_checksums", S_IRUSR,
2501 ar->debug.debugfs_phy, ar, &fops_fw_checksums);
2502
Kalle Valo5e3dd152013-06-12 20:52:10 +03002503 return 0;
2504}
Kalle Valodb66ea02013-09-03 11:44:03 +03002505
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002506void ath10k_debug_unregister(struct ath10k *ar)
Kalle Valo60631c52013-10-08 21:45:25 +03002507{
2508 cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
2509}
2510
Kalle Valo5e3dd152013-06-12 20:52:10 +03002511#endif /* CONFIG_ATH10K_DEBUGFS */
2512
2513#ifdef CONFIG_ATH10K_DEBUG
Michal Kazior7aa7a722014-08-25 12:09:38 +02002514void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
2515 const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +03002516{
2517 struct va_format vaf;
2518 va_list args;
2519
2520 va_start(args, fmt);
2521
2522 vaf.fmt = fmt;
2523 vaf.va = &args;
2524
2525 if (ath10k_debug_mask & mask)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002526 dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002527
Michal Kaziord35a6c12014-09-02 11:00:21 +03002528 trace_ath10k_log_dbg(ar, mask, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002529
2530 va_end(args);
2531}
2532EXPORT_SYMBOL(ath10k_dbg);
2533
Michal Kazior7aa7a722014-08-25 12:09:38 +02002534void ath10k_dbg_dump(struct ath10k *ar,
2535 enum ath10k_debug_mask mask,
Kalle Valo5e3dd152013-06-12 20:52:10 +03002536 const char *msg, const char *prefix,
2537 const void *buf, size_t len)
2538{
Michal Kazior45724a82014-09-23 10:22:53 +02002539 char linebuf[256];
2540 unsigned int linebuflen;
2541 const void *ptr;
2542
Kalle Valo5e3dd152013-06-12 20:52:10 +03002543 if (ath10k_debug_mask & mask) {
2544 if (msg)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002545 ath10k_dbg(ar, mask, "%s\n", msg);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002546
Michal Kazior45724a82014-09-23 10:22:53 +02002547 for (ptr = buf; (ptr - buf) < len; ptr += 16) {
2548 linebuflen = 0;
2549 linebuflen += scnprintf(linebuf + linebuflen,
2550 sizeof(linebuf) - linebuflen,
2551 "%s%08x: ",
2552 (prefix ? prefix : ""),
2553 (unsigned int)(ptr - buf));
2554 hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
2555 linebuf + linebuflen,
2556 sizeof(linebuf) - linebuflen, true);
2557 dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
2558 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03002559 }
2560
2561 /* tracing code doesn't like null strings :/ */
Michal Kaziord35a6c12014-09-02 11:00:21 +03002562 trace_ath10k_log_dbg_dump(ar, msg ? msg : "", prefix ? prefix : "",
Kalle Valo5e3dd152013-06-12 20:52:10 +03002563 buf, len);
2564}
2565EXPORT_SYMBOL(ath10k_dbg_dump);
2566
2567#endif /* CONFIG_ATH10K_DEBUG */