blob: ff831ca507f704d7d2aab7832a4d66cdc31ca68f [file] [log] [blame]
Kalle Valo5e3dd152013-06-12 20:52:10 +03001/*
2 * Copyright (c) 2005-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <linux/module.h>
19#include <linux/debugfs.h>
Ben Greear384914b2014-08-25 08:37:32 +030020#include <linux/vmalloc.h>
Johannes Berg12c27152014-11-21 18:58:49 +020021#include <linux/utsname.h>
Kalle Valo5e3dd152013-06-12 20:52:10 +030022
23#include "core.h"
24#include "debug.h"
Kalle Valo7869b4f2014-09-24 14:16:58 +030025#include "hif.h"
Kalle Valo5e3dd152013-06-12 20:52:10 +030026
Kalle Valoa3d135e2013-09-03 11:44:10 +030027/* ms */
28#define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
29
Ben Greear384914b2014-08-25 08:37:32 +030030#define ATH10K_FW_CRASH_DUMP_VERSION 1
31
32/**
33 * enum ath10k_fw_crash_dump_type - types of data in the dump file
34 * @ATH10K_FW_CRASH_DUMP_REGDUMP: Register crash dump in binary format
35 */
36enum ath10k_fw_crash_dump_type {
37 ATH10K_FW_CRASH_DUMP_REGISTERS = 0,
38
39 ATH10K_FW_CRASH_DUMP_MAX,
40};
41
42struct ath10k_tlv_dump_data {
43 /* see ath10k_fw_crash_dump_type above */
44 __le32 type;
45
46 /* in bytes */
47 __le32 tlv_len;
48
49 /* pad to 32-bit boundaries as needed */
50 u8 tlv_data[];
51} __packed;
52
53struct ath10k_dump_file_data {
54 /* dump file information */
55
56 /* "ATH10K-FW-DUMP" */
57 char df_magic[16];
58
59 __le32 len;
60
61 /* file dump version */
62 __le32 version;
63
64 /* some info we can get from ath10k struct that might help */
65
66 u8 uuid[16];
67
68 __le32 chip_id;
69
70 /* 0 for now, in place for later hardware */
71 __le32 bus_type;
72
73 __le32 target_version;
74 __le32 fw_version_major;
75 __le32 fw_version_minor;
76 __le32 fw_version_release;
77 __le32 fw_version_build;
78 __le32 phy_capability;
79 __le32 hw_min_tx_power;
80 __le32 hw_max_tx_power;
81 __le32 ht_cap_info;
82 __le32 vht_cap_info;
83 __le32 num_rf_chains;
84
85 /* firmware version string */
86 char fw_ver[ETHTOOL_FWVERS_LEN];
87
88 /* Kernel related information */
89
90 /* time-of-day stamp */
91 __le64 tv_sec;
92
93 /* time-of-day stamp, nano-seconds */
94 __le64 tv_nsec;
95
96 /* LINUX_VERSION_CODE */
97 __le32 kernel_ver_code;
98
99 /* VERMAGIC_STRING */
100 char kernel_ver[64];
101
102 /* room for growth w/out changing binary format */
103 u8 unused[128];
104
105 /* struct ath10k_tlv_dump_data + more */
106 u8 data[0];
107} __packed;
108
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700109void ath10k_info(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300110{
111 struct va_format vaf = {
112 .fmt = fmt,
113 };
114 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300115
116 va_start(args, fmt);
117 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700118 dev_info(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300119 trace_ath10k_log_info(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300120 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300121}
122EXPORT_SYMBOL(ath10k_info);
123
Kalle Valo8a0c7972014-08-25 08:37:45 +0300124void ath10k_print_driver_info(struct ath10k *ar)
125{
Kalle Valoa58227e2014-10-13 09:40:59 +0300126 ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d.%d.%d.%d cal %s\n",
Kalle Valo8a0c7972014-08-25 08:37:45 +0300127 ar->hw_params.name,
128 ar->target_version,
129 ar->chip_id,
130 ar->hw->wiphy->fw_version,
131 ar->fw_api,
132 ar->htt.target_version_major,
Michal Kazior34b28b62014-09-23 10:22:52 +0200133 ar->htt.target_version_minor,
134 ar->fw_version_major,
135 ar->fw_version_minor,
136 ar->fw_version_release,
Kalle Valoa58227e2014-10-13 09:40:59 +0300137 ar->fw_version_build,
138 ath10k_cal_mode_str(ar->cal_mode));
Kalle Valo43d2a302014-09-10 18:23:30 +0300139 ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
Kalle Valo8a0c7972014-08-25 08:37:45 +0300140 config_enabled(CONFIG_ATH10K_DEBUG),
141 config_enabled(CONFIG_ATH10K_DEBUGFS),
142 config_enabled(CONFIG_ATH10K_TRACING),
Kalle Valo43d2a302014-09-10 18:23:30 +0300143 config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
144 config_enabled(CONFIG_NL80211_TESTMODE));
Kalle Valo8a0c7972014-08-25 08:37:45 +0300145}
146EXPORT_SYMBOL(ath10k_print_driver_info);
147
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700148void ath10k_err(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300149{
150 struct va_format vaf = {
151 .fmt = fmt,
152 };
153 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300154
155 va_start(args, fmt);
156 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700157 dev_err(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300158 trace_ath10k_log_err(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300159 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300160}
161EXPORT_SYMBOL(ath10k_err);
162
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700163void ath10k_warn(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300164{
165 struct va_format vaf = {
166 .fmt = fmt,
167 };
168 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300169
170 va_start(args, fmt);
171 vaf.va = &args;
Michal Kazior7aa7a722014-08-25 12:09:38 +0200172 dev_warn_ratelimited(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300173 trace_ath10k_log_warn(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300174
175 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300176}
177EXPORT_SYMBOL(ath10k_warn);
178
179#ifdef CONFIG_ATH10K_DEBUGFS
180
181void ath10k_debug_read_service_map(struct ath10k *ar,
Michal Kazior5c01aa3d2014-09-18 15:21:24 +0200182 const void *service_map,
Kalle Valo5e3dd152013-06-12 20:52:10 +0300183 size_t map_size)
184{
185 memcpy(ar->debug.wmi_service_bitmap, service_map, map_size);
186}
187
188static ssize_t ath10k_read_wmi_services(struct file *file,
189 char __user *user_buf,
190 size_t count, loff_t *ppos)
191{
192 struct ath10k *ar = file->private_data;
193 char *buf;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300194 unsigned int len = 0, buf_len = 4096;
195 const char *name;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300196 ssize_t ret_cnt;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300197 bool enabled;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300198 int i;
199
200 buf = kzalloc(buf_len, GFP_KERNEL);
201 if (!buf)
202 return -ENOMEM;
203
204 mutex_lock(&ar->conf_mutex);
205
206 if (len > buf_len)
207 len = buf_len;
208
Michal Kaziorc4f8c832014-09-04 10:18:32 +0200209 for (i = 0; i < WMI_SERVICE_MAX; i++) {
Michal Kaziorcff990c2014-08-04 09:18:33 +0300210 enabled = test_bit(i, ar->debug.wmi_service_bitmap);
211 name = wmi_service_name(i);
212
213 if (!name) {
214 if (enabled)
215 len += scnprintf(buf + len, buf_len - len,
216 "%-40s %s (bit %d)\n",
217 "unknown", "enabled", i);
218
219 continue;
220 }
Kalle Valo5e3dd152013-06-12 20:52:10 +0300221
222 len += scnprintf(buf + len, buf_len - len,
Michal Kaziorcff990c2014-08-04 09:18:33 +0300223 "%-40s %s\n",
224 name, enabled ? "enabled" : "-");
Kalle Valo5e3dd152013-06-12 20:52:10 +0300225 }
226
227 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
228
229 mutex_unlock(&ar->conf_mutex);
230
231 kfree(buf);
232 return ret_cnt;
233}
234
235static const struct file_operations fops_wmi_services = {
236 .read = ath10k_read_wmi_services,
237 .open = simple_open,
238 .owner = THIS_MODULE,
239 .llseek = default_llseek,
240};
241
Michal Kazior53268492014-09-25 12:33:50 +0200242static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
243{
244 struct ath10k_fw_stats_pdev *i, *tmp;
245
246 list_for_each_entry_safe(i, tmp, head, list) {
247 list_del(&i->list);
248 kfree(i);
249 }
250}
251
252static void ath10k_debug_fw_stats_peers_free(struct list_head *head)
253{
254 struct ath10k_fw_stats_peer *i, *tmp;
255
256 list_for_each_entry_safe(i, tmp, head, list) {
257 list_del(&i->list);
258 kfree(i);
259 }
260}
261
262static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
263{
264 spin_lock_bh(&ar->data_lock);
265 ar->debug.fw_stats_done = false;
266 ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
267 ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers);
268 spin_unlock_bh(&ar->data_lock);
269}
270
271static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head)
272{
273 struct ath10k_fw_stats_peer *i;
274 size_t num = 0;
275
276 list_for_each_entry(i, head, list)
277 ++num;
278
279 return num;
280}
281
Michal Kazior60ef4012014-09-25 12:33:48 +0200282void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300283{
Michal Kazior53268492014-09-25 12:33:50 +0200284 struct ath10k_fw_stats stats = {};
285 bool is_start, is_started, is_end;
286 size_t num_peers;
Michal Kaziord15fb522014-09-25 12:33:47 +0200287 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300288
Michal Kazior53268492014-09-25 12:33:50 +0200289 INIT_LIST_HEAD(&stats.pdevs);
290 INIT_LIST_HEAD(&stats.peers);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300291
Michal Kazior53268492014-09-25 12:33:50 +0200292 spin_lock_bh(&ar->data_lock);
293 ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
Michal Kaziord15fb522014-09-25 12:33:47 +0200294 if (ret) {
295 ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
296 goto unlock;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300297 }
298
Michal Kazior53268492014-09-25 12:33:50 +0200299 /* Stat data may exceed htc-wmi buffer limit. In such case firmware
300 * splits the stats data and delivers it in a ping-pong fashion of
301 * request cmd-update event.
302 *
303 * However there is no explicit end-of-data. Instead start-of-data is
304 * used as an implicit one. This works as follows:
305 * a) discard stat update events until one with pdev stats is
306 * delivered - this skips session started at end of (b)
307 * b) consume stat update events until another one with pdev stats is
308 * delivered which is treated as end-of-data and is itself discarded
309 */
310
311 if (ar->debug.fw_stats_done) {
312 ath10k_warn(ar, "received unsolicited stats update event\n");
313 goto free;
314 }
315
316 num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers);
317 is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
318 !list_empty(&stats.pdevs));
319 is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
320 !list_empty(&stats.pdevs));
321
322 if (is_start)
323 list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
324
325 if (is_end)
326 ar->debug.fw_stats_done = true;
327
328 is_started = !list_empty(&ar->debug.fw_stats.pdevs);
329
330 if (is_started && !is_end) {
331 if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) {
332 /* Although this is unlikely impose a sane limit to
333 * prevent firmware from DoS-ing the host.
334 */
335 ath10k_warn(ar, "dropping fw peer stats\n");
336 goto free;
337 }
338
339 list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
340 }
341
Michal Kazior60ef4012014-09-25 12:33:48 +0200342 complete(&ar->debug.fw_stats_complete);
Michal Kaziord15fb522014-09-25 12:33:47 +0200343
Michal Kazior53268492014-09-25 12:33:50 +0200344free:
345 /* In some cases lists have been spliced and cleared. Free up
346 * resources if that is not the case.
347 */
348 ath10k_debug_fw_stats_pdevs_free(&stats.pdevs);
349 ath10k_debug_fw_stats_peers_free(&stats.peers);
350
Michal Kaziord15fb522014-09-25 12:33:47 +0200351unlock:
352 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300353}
354
Michal Kazior53268492014-09-25 12:33:50 +0200355static int ath10k_debug_fw_stats_request(struct ath10k *ar)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300356{
Michal Kazior53268492014-09-25 12:33:50 +0200357 unsigned long timeout;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300358 int ret;
359
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200360 lockdep_assert_held(&ar->conf_mutex);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300361
Michal Kazior53268492014-09-25 12:33:50 +0200362 timeout = jiffies + msecs_to_jiffies(1*HZ);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300363
Michal Kazior53268492014-09-25 12:33:50 +0200364 ath10k_debug_fw_stats_reset(ar);
365
366 for (;;) {
367 if (time_after(jiffies, timeout))
368 return -ETIMEDOUT;
369
370 reinit_completion(&ar->debug.fw_stats_complete);
371
372 ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
373 if (ret) {
374 ath10k_warn(ar, "could not request stats (%d)\n", ret);
375 return ret;
376 }
377
378 ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete,
379 1*HZ);
380 if (ret <= 0)
381 return -ETIMEDOUT;
382
383 spin_lock_bh(&ar->data_lock);
384 if (ar->debug.fw_stats_done) {
385 spin_unlock_bh(&ar->data_lock);
386 break;
387 }
388 spin_unlock_bh(&ar->data_lock);
389 }
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200390
391 return 0;
392}
393
394/* FIXME: How to calculate the buffer size sanely? */
395#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
396
397static void ath10k_fw_stats_fill(struct ath10k *ar,
398 struct ath10k_fw_stats *fw_stats,
399 char *buf)
400{
401 unsigned int len = 0;
402 unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
Michal Kazior53268492014-09-25 12:33:50 +0200403 const struct ath10k_fw_stats_pdev *pdev;
404 const struct ath10k_fw_stats_peer *peer;
405 size_t num_peers;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300406
Michal Kazior87571bf2013-07-16 09:38:59 +0200407 spin_lock_bh(&ar->data_lock);
Michal Kazior53268492014-09-25 12:33:50 +0200408
409 pdev = list_first_entry_or_null(&fw_stats->pdevs,
410 struct ath10k_fw_stats_pdev, list);
411 if (!pdev) {
412 ath10k_warn(ar, "failed to get pdev stats\n");
413 goto unlock;
414 }
415
416 num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers);
417
Kalle Valo5e3dd152013-06-12 20:52:10 +0300418 len += scnprintf(buf + len, buf_len - len, "\n");
419 len += scnprintf(buf + len, buf_len - len, "%30s\n",
420 "ath10k PDEV stats");
421 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
422 "=================");
423
424 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200425 "Channel noise floor", pdev->ch_noise_floor);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300426 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200427 "Channel TX power", pdev->chan_tx_power);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300428 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200429 "TX frame count", pdev->tx_frame_count);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300430 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200431 "RX frame count", pdev->rx_frame_count);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300432 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200433 "RX clear count", pdev->rx_clear_count);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300434 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200435 "Cycle count", pdev->cycle_count);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300436 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200437 "PHY error count", pdev->phy_err_count);
Chun-Yeow Yeoh52e346d2014-03-28 14:35:16 +0200438 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200439 "RTS bad count", pdev->rts_bad);
Chun-Yeow Yeoh52e346d2014-03-28 14:35:16 +0200440 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200441 "RTS good count", pdev->rts_good);
Chun-Yeow Yeoh52e346d2014-03-28 14:35:16 +0200442 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200443 "FCS bad count", pdev->fcs_bad);
Chun-Yeow Yeoh52e346d2014-03-28 14:35:16 +0200444 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200445 "No beacon count", pdev->no_beacons);
Chun-Yeow Yeoh52e346d2014-03-28 14:35:16 +0200446 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200447 "MIB int count", pdev->mib_int_count);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300448
449 len += scnprintf(buf + len, buf_len - len, "\n");
450 len += scnprintf(buf + len, buf_len - len, "%30s\n",
451 "ath10k PDEV TX stats");
452 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
453 "=================");
454
455 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200456 "HTT cookies queued", pdev->comp_queued);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300457 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200458 "HTT cookies disp.", pdev->comp_delivered);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300459 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200460 "MSDU queued", pdev->msdu_enqued);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300461 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200462 "MPDU queued", pdev->mpdu_enqued);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300463 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200464 "MSDUs dropped", pdev->wmm_drop);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300465 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200466 "Local enqued", pdev->local_enqued);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300467 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200468 "Local freed", pdev->local_freed);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300469 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200470 "HW queued", pdev->hw_queued);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300471 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200472 "PPDUs reaped", pdev->hw_reaped);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300473 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200474 "Num underruns", pdev->underrun);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300475 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200476 "PPDUs cleaned", pdev->tx_abort);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300477 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200478 "MPDUs requed", pdev->mpdus_requed);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300479 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200480 "Excessive retries", pdev->tx_ko);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300481 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200482 "HW rate", pdev->data_rc);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300483 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200484 "Sched self tiggers", pdev->self_triggers);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300485 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
486 "Dropped due to SW retries",
Michal Kazior53268492014-09-25 12:33:50 +0200487 pdev->sw_retry_failure);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300488 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
489 "Illegal rate phy errors",
Michal Kazior53268492014-09-25 12:33:50 +0200490 pdev->illgl_rate_phy_err);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300491 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200492 "Pdev continous xretry", pdev->pdev_cont_xretry);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300493 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200494 "TX timeout", pdev->pdev_tx_timeout);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300495 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200496 "PDEV resets", pdev->pdev_resets);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300497 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200498 "PHY underrun", pdev->phy_underrun);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300499 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200500 "MPDU is more than txop limit", pdev->txop_ovf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300501
502 len += scnprintf(buf + len, buf_len - len, "\n");
503 len += scnprintf(buf + len, buf_len - len, "%30s\n",
504 "ath10k PDEV RX stats");
505 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
506 "=================");
507
508 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
509 "Mid PPDU route change",
Michal Kazior53268492014-09-25 12:33:50 +0200510 pdev->mid_ppdu_route_change);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300511 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200512 "Tot. number of statuses", pdev->status_rcvd);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300513 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200514 "Extra frags on rings 0", pdev->r0_frags);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300515 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200516 "Extra frags on rings 1", pdev->r1_frags);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300517 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200518 "Extra frags on rings 2", pdev->r2_frags);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300519 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200520 "Extra frags on rings 3", pdev->r3_frags);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300521 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200522 "MSDUs delivered to HTT", pdev->htt_msdus);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300523 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200524 "MPDUs delivered to HTT", pdev->htt_mpdus);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300525 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200526 "MSDUs delivered to stack", pdev->loc_msdus);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300527 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200528 "MPDUs delivered to stack", pdev->loc_mpdus);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300529 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200530 "Oversized AMSUs", pdev->oversize_amsdu);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300531 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200532 "PHY errors", pdev->phy_errs);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300533 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200534 "PHY errors drops", pdev->phy_err_drop);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300535 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200536 "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300537
538 len += scnprintf(buf + len, buf_len - len, "\n");
Michal Kazior53268492014-09-25 12:33:50 +0200539 len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
540 "ath10k PEER stats", num_peers);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300541 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
542 "=================");
543
Michal Kazior53268492014-09-25 12:33:50 +0200544 list_for_each_entry(peer, &fw_stats->peers, list) {
Kalle Valo5e3dd152013-06-12 20:52:10 +0300545 len += scnprintf(buf + len, buf_len - len, "%30s %pM\n",
Michal Kazior53268492014-09-25 12:33:50 +0200546 "Peer MAC address", peer->peer_macaddr);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300547 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200548 "Peer RSSI", peer->peer_rssi);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300549 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200550 "Peer TX rate", peer->peer_tx_rate);
Ben Greear23c3aae2014-03-28 14:35:15 +0200551 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200552 "Peer RX rate", peer->peer_rx_rate);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300553 len += scnprintf(buf + len, buf_len - len, "\n");
554 }
Michal Kazior53268492014-09-25 12:33:50 +0200555
556unlock:
Michal Kazior87571bf2013-07-16 09:38:59 +0200557 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300558
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200559 if (len >= buf_len)
560 buf[len - 1] = 0;
561 else
562 buf[len] = 0;
563}
Kalle Valo5e3dd152013-06-12 20:52:10 +0300564
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200565static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
566{
567 struct ath10k *ar = inode->i_private;
568 void *buf = NULL;
569 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300570
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200571 mutex_lock(&ar->conf_mutex);
572
573 if (ar->state != ATH10K_STATE_ON) {
574 ret = -ENETDOWN;
575 goto err_unlock;
576 }
577
578 buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);
579 if (!buf) {
580 ret = -ENOMEM;
581 goto err_unlock;
582 }
583
Michal Kazior53268492014-09-25 12:33:50 +0200584 ret = ath10k_debug_fw_stats_request(ar);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200585 if (ret) {
586 ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
587 goto err_free;
588 }
589
590 ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
591 file->private_data = buf;
592
Kalle Valo5e3dd152013-06-12 20:52:10 +0300593 mutex_unlock(&ar->conf_mutex);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200594 return 0;
595
596err_free:
597 vfree(buf);
598
599err_unlock:
600 mutex_unlock(&ar->conf_mutex);
601 return ret;
602}
603
604static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
605{
606 vfree(file->private_data);
607
608 return 0;
609}
610
611static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
612 size_t count, loff_t *ppos)
613{
614 const char *buf = file->private_data;
615 unsigned int len = strlen(buf);
616
617 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300618}
619
620static const struct file_operations fops_fw_stats = {
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200621 .open = ath10k_fw_stats_open,
622 .release = ath10k_fw_stats_release,
Michal Kazior60ef4012014-09-25 12:33:48 +0200623 .read = ath10k_fw_stats_read,
Kalle Valo5e3dd152013-06-12 20:52:10 +0300624 .owner = THIS_MODULE,
625 .llseek = default_llseek,
626};
627
Ben Greearf51dbe72014-09-29 14:41:46 +0300628static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
629 char __user *user_buf,
630 size_t count, loff_t *ppos)
631{
632 struct ath10k *ar = file->private_data;
633 int ret, len, buf_len;
634 char *buf;
635
636 buf_len = 500;
637 buf = kmalloc(buf_len, GFP_KERNEL);
638 if (!buf)
639 return -ENOMEM;
640
641 spin_lock_bh(&ar->data_lock);
642
643 len = 0;
644 len += scnprintf(buf + len, buf_len - len,
645 "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
646 len += scnprintf(buf + len, buf_len - len,
647 "fw_warm_reset_counter\t\t%d\n",
648 ar->stats.fw_warm_reset_counter);
649 len += scnprintf(buf + len, buf_len - len,
650 "fw_cold_reset_counter\t\t%d\n",
651 ar->stats.fw_cold_reset_counter);
652
653 spin_unlock_bh(&ar->data_lock);
654
655 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
656
657 kfree(buf);
658
659 return ret;
660}
661
662static const struct file_operations fops_fw_reset_stats = {
663 .open = simple_open,
664 .read = ath10k_debug_fw_reset_stats_read,
665 .owner = THIS_MODULE,
666 .llseek = default_llseek,
667};
668
Ben Greeard5aebc72014-09-10 18:59:28 +0300669/* This is a clean assert crash in firmware. */
670static int ath10k_debug_fw_assert(struct ath10k *ar)
671{
672 struct wmi_vdev_install_key_cmd *cmd;
673 struct sk_buff *skb;
674
675 skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
676 if (!skb)
677 return -ENOMEM;
678
679 cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
680 memset(cmd, 0, sizeof(*cmd));
681
682 /* big enough number so that firmware asserts */
683 cmd->vdev_id = __cpu_to_le32(0x7ffe);
684
685 return ath10k_wmi_cmd_send(ar, skb,
686 ar->wmi.cmd->vdev_install_key_cmdid);
687}
688
Michal Kazior278c4a82013-07-22 14:08:51 +0200689static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
690 char __user *user_buf,
691 size_t count, loff_t *ppos)
692{
Kalle Valo75cb96d2014-09-14 12:50:44 +0300693 const char buf[] =
694 "To simulate firmware crash write one of the keywords to this file:\n"
695 "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
696 "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
Michal Kazior605cdba2014-10-28 10:34:37 +0100697 "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"
698 "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
Marek Puzyniak8c656992014-03-21 17:46:56 +0200699
Michal Kazior278c4a82013-07-22 14:08:51 +0200700 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
701}
702
Marek Puzyniak8c656992014-03-21 17:46:56 +0200703/* Simulate firmware crash:
704 * 'soft': Call wmi command causing firmware hang. This firmware hang is
705 * recoverable by warm firmware reset.
706 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
707 * vdev id. This is hard firmware crash because it is recoverable only by cold
708 * firmware reset.
709 */
Michal Kazior278c4a82013-07-22 14:08:51 +0200710static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
711 const char __user *user_buf,
712 size_t count, loff_t *ppos)
713{
714 struct ath10k *ar = file->private_data;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200715 char buf[32];
Michal Kazior278c4a82013-07-22 14:08:51 +0200716 int ret;
717
718 mutex_lock(&ar->conf_mutex);
719
720 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200721
722 /* make sure that buf is null terminated */
723 buf[sizeof(buf) - 1] = 0;
Michal Kazior278c4a82013-07-22 14:08:51 +0200724
725 if (ar->state != ATH10K_STATE_ON &&
726 ar->state != ATH10K_STATE_RESTARTED) {
727 ret = -ENETDOWN;
728 goto exit;
729 }
730
Marek Puzyniak8c656992014-03-21 17:46:56 +0200731 /* drop the possible '\n' from the end */
732 if (buf[count - 1] == '\n') {
733 buf[count - 1] = 0;
734 count--;
735 }
Michal Kazior278c4a82013-07-22 14:08:51 +0200736
Marek Puzyniak8c656992014-03-21 17:46:56 +0200737 if (!strcmp(buf, "soft")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200738 ath10k_info(ar, "simulating soft firmware crash\n");
Marek Puzyniak8c656992014-03-21 17:46:56 +0200739 ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
740 } else if (!strcmp(buf, "hard")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200741 ath10k_info(ar, "simulating hard firmware crash\n");
Ben Greear611b3682014-07-25 11:56:40 +0300742 /* 0x7fff is vdev id, and it is always out of range for all
743 * firmware variants in order to force a firmware crash.
744 */
745 ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
Kalle Valo5b07e072014-09-14 12:50:06 +0300746 ar->wmi.vdev_param->rts_threshold,
747 0);
Ben Greeard5aebc72014-09-10 18:59:28 +0300748 } else if (!strcmp(buf, "assert")) {
749 ath10k_info(ar, "simulating firmware assert crash\n");
750 ret = ath10k_debug_fw_assert(ar);
Michal Kazior605cdba2014-10-28 10:34:37 +0100751 } else if (!strcmp(buf, "hw-restart")) {
752 ath10k_info(ar, "user requested hw restart\n");
753 queue_work(ar->workqueue, &ar->restart_work);
754 ret = 0;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200755 } else {
756 ret = -EINVAL;
757 goto exit;
758 }
Michal Kazior278c4a82013-07-22 14:08:51 +0200759
Marek Puzyniak8c656992014-03-21 17:46:56 +0200760 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200761 ath10k_warn(ar, "failed to simulate firmware crash: %d\n", ret);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200762 goto exit;
763 }
764
765 ret = count;
Michal Kazior278c4a82013-07-22 14:08:51 +0200766
767exit:
768 mutex_unlock(&ar->conf_mutex);
769 return ret;
770}
771
772static const struct file_operations fops_simulate_fw_crash = {
773 .read = ath10k_read_simulate_fw_crash,
774 .write = ath10k_write_simulate_fw_crash,
775 .open = simple_open,
776 .owner = THIS_MODULE,
777 .llseek = default_llseek,
778};
779
Kalle Valo763b8cd2013-09-01 11:22:21 +0300780static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf,
781 size_t count, loff_t *ppos)
782{
783 struct ath10k *ar = file->private_data;
784 unsigned int len;
785 char buf[50];
786
787 len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id);
788
789 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
790}
791
792static const struct file_operations fops_chip_id = {
793 .read = ath10k_read_chip_id,
794 .open = simple_open,
795 .owner = THIS_MODULE,
796 .llseek = default_llseek,
797};
798
Ben Greear384914b2014-08-25 08:37:32 +0300799struct ath10k_fw_crash_data *
800ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
801{
802 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
803
804 lockdep_assert_held(&ar->data_lock);
805
806 crash_data->crashed_since_read = true;
807 uuid_le_gen(&crash_data->uuid);
808 getnstimeofday(&crash_data->timestamp);
809
810 return crash_data;
811}
812EXPORT_SYMBOL(ath10k_debug_get_new_fw_crash_data);
813
814static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
815{
816 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
817 struct ath10k_dump_file_data *dump_data;
818 struct ath10k_tlv_dump_data *dump_tlv;
819 int hdr_len = sizeof(*dump_data);
820 unsigned int len, sofar = 0;
821 unsigned char *buf;
822
823 len = hdr_len;
824 len += sizeof(*dump_tlv) + sizeof(crash_data->registers);
825
826 sofar += hdr_len;
827
828 /* This is going to get big when we start dumping FW RAM and such,
829 * so go ahead and use vmalloc.
830 */
831 buf = vzalloc(len);
832 if (!buf)
833 return NULL;
834
835 spin_lock_bh(&ar->data_lock);
836
837 if (!crash_data->crashed_since_read) {
838 spin_unlock_bh(&ar->data_lock);
839 vfree(buf);
840 return NULL;
841 }
842
843 dump_data = (struct ath10k_dump_file_data *)(buf);
844 strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP",
845 sizeof(dump_data->df_magic));
846 dump_data->len = cpu_to_le32(len);
847
848 dump_data->version = cpu_to_le32(ATH10K_FW_CRASH_DUMP_VERSION);
849
850 memcpy(dump_data->uuid, &crash_data->uuid, sizeof(dump_data->uuid));
851 dump_data->chip_id = cpu_to_le32(ar->chip_id);
852 dump_data->bus_type = cpu_to_le32(0);
853 dump_data->target_version = cpu_to_le32(ar->target_version);
854 dump_data->fw_version_major = cpu_to_le32(ar->fw_version_major);
855 dump_data->fw_version_minor = cpu_to_le32(ar->fw_version_minor);
856 dump_data->fw_version_release = cpu_to_le32(ar->fw_version_release);
857 dump_data->fw_version_build = cpu_to_le32(ar->fw_version_build);
858 dump_data->phy_capability = cpu_to_le32(ar->phy_capability);
859 dump_data->hw_min_tx_power = cpu_to_le32(ar->hw_min_tx_power);
860 dump_data->hw_max_tx_power = cpu_to_le32(ar->hw_max_tx_power);
861 dump_data->ht_cap_info = cpu_to_le32(ar->ht_cap_info);
862 dump_data->vht_cap_info = cpu_to_le32(ar->vht_cap_info);
863 dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains);
864
865 strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
866 sizeof(dump_data->fw_ver));
867
Johannes Berg12c27152014-11-21 18:58:49 +0200868 dump_data->kernel_ver_code = 0;
869 strlcpy(dump_data->kernel_ver, init_utsname()->release,
Ben Greear384914b2014-08-25 08:37:32 +0300870 sizeof(dump_data->kernel_ver));
871
872 dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
873 dump_data->tv_nsec = cpu_to_le64(crash_data->timestamp.tv_nsec);
874
875 /* Gather crash-dump */
876 dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
877 dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_REGISTERS);
878 dump_tlv->tlv_len = cpu_to_le32(sizeof(crash_data->registers));
879 memcpy(dump_tlv->tlv_data, &crash_data->registers,
880 sizeof(crash_data->registers));
881 sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers);
882
883 ar->debug.fw_crash_data->crashed_since_read = false;
884
885 spin_unlock_bh(&ar->data_lock);
886
887 return dump_data;
888}
889
890static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file)
891{
892 struct ath10k *ar = inode->i_private;
893 struct ath10k_dump_file_data *dump;
894
895 dump = ath10k_build_dump_file(ar);
896 if (!dump)
897 return -ENODATA;
898
899 file->private_data = dump;
900
901 return 0;
902}
903
904static ssize_t ath10k_fw_crash_dump_read(struct file *file,
905 char __user *user_buf,
906 size_t count, loff_t *ppos)
907{
908 struct ath10k_dump_file_data *dump_file = file->private_data;
909
910 return simple_read_from_buffer(user_buf, count, ppos,
911 dump_file,
912 le32_to_cpu(dump_file->len));
913}
914
915static int ath10k_fw_crash_dump_release(struct inode *inode,
916 struct file *file)
917{
918 vfree(file->private_data);
919
920 return 0;
921}
922
923static const struct file_operations fops_fw_crash_dump = {
924 .open = ath10k_fw_crash_dump_open,
925 .read = ath10k_fw_crash_dump_read,
926 .release = ath10k_fw_crash_dump_release,
927 .owner = THIS_MODULE,
928 .llseek = default_llseek,
929};
930
Yanbo Li077a3802014-11-25 12:24:33 +0200931static ssize_t ath10k_reg_addr_read(struct file *file,
932 char __user *user_buf,
933 size_t count, loff_t *ppos)
934{
935 struct ath10k *ar = file->private_data;
936 u8 buf[32];
937 unsigned int len = 0;
938 u32 reg_addr;
939
940 mutex_lock(&ar->conf_mutex);
941 reg_addr = ar->debug.reg_addr;
942 mutex_unlock(&ar->conf_mutex);
943
944 len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);
945
946 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
947}
948
949static ssize_t ath10k_reg_addr_write(struct file *file,
950 const char __user *user_buf,
951 size_t count, loff_t *ppos)
952{
953 struct ath10k *ar = file->private_data;
954 u32 reg_addr;
955 int ret;
956
957 ret = kstrtou32_from_user(user_buf, count, 0, &reg_addr);
958 if (ret)
959 return ret;
960
961 if (!IS_ALIGNED(reg_addr, 4))
962 return -EFAULT;
963
964 mutex_lock(&ar->conf_mutex);
965 ar->debug.reg_addr = reg_addr;
966 mutex_unlock(&ar->conf_mutex);
967
968 return count;
969}
970
971static const struct file_operations fops_reg_addr = {
972 .read = ath10k_reg_addr_read,
973 .write = ath10k_reg_addr_write,
974 .open = simple_open,
975 .owner = THIS_MODULE,
976 .llseek = default_llseek,
977};
978
979static ssize_t ath10k_reg_value_read(struct file *file,
980 char __user *user_buf,
981 size_t count, loff_t *ppos)
982{
983 struct ath10k *ar = file->private_data;
984 u8 buf[48];
985 unsigned int len;
986 u32 reg_addr, reg_val;
987 int ret;
988
989 mutex_lock(&ar->conf_mutex);
990
991 if (ar->state != ATH10K_STATE_ON &&
992 ar->state != ATH10K_STATE_UTF) {
993 ret = -ENETDOWN;
994 goto exit;
995 }
996
997 reg_addr = ar->debug.reg_addr;
998
999 reg_val = ath10k_hif_read32(ar, reg_addr);
1000 len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);
1001
1002 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1003
1004exit:
1005 mutex_unlock(&ar->conf_mutex);
1006
1007 return ret;
1008}
1009
1010static ssize_t ath10k_reg_value_write(struct file *file,
1011 const char __user *user_buf,
1012 size_t count, loff_t *ppos)
1013{
1014 struct ath10k *ar = file->private_data;
1015 u32 reg_addr, reg_val;
1016 int ret;
1017
1018 mutex_lock(&ar->conf_mutex);
1019
1020 if (ar->state != ATH10K_STATE_ON &&
1021 ar->state != ATH10K_STATE_UTF) {
1022 ret = -ENETDOWN;
1023 goto exit;
1024 }
1025
1026 reg_addr = ar->debug.reg_addr;
1027
1028 ret = kstrtou32_from_user(user_buf, count, 0, &reg_val);
1029 if (ret)
1030 goto exit;
1031
1032 ath10k_hif_write32(ar, reg_addr, reg_val);
1033
1034 ret = count;
1035
1036exit:
1037 mutex_unlock(&ar->conf_mutex);
1038
1039 return ret;
1040}
1041
1042static const struct file_operations fops_reg_value = {
1043 .read = ath10k_reg_value_read,
1044 .write = ath10k_reg_value_write,
1045 .open = simple_open,
1046 .owner = THIS_MODULE,
1047 .llseek = default_llseek,
1048};
1049
Yanbo Li9f65ad22014-11-25 12:24:48 +02001050static ssize_t ath10k_mem_value_read(struct file *file,
1051 char __user *user_buf,
1052 size_t count, loff_t *ppos)
1053{
1054 struct ath10k *ar = file->private_data;
1055 u8 *buf;
1056 int ret;
1057
1058 if (*ppos < 0)
1059 return -EINVAL;
1060
1061 if (!count)
1062 return 0;
1063
1064 mutex_lock(&ar->conf_mutex);
1065
1066 buf = vmalloc(count);
1067 if (!buf) {
1068 ret = -ENOMEM;
1069 goto exit;
1070 }
1071
1072 if (ar->state != ATH10K_STATE_ON &&
1073 ar->state != ATH10K_STATE_UTF) {
1074 ret = -ENETDOWN;
1075 goto exit;
1076 }
1077
1078 ret = ath10k_hif_diag_read(ar, *ppos, buf, count);
1079 if (ret) {
1080 ath10k_warn(ar, "failed to read address 0x%08x via diagnose window fnrom debugfs: %d\n",
1081 (u32)(*ppos), ret);
1082 goto exit;
1083 }
1084
1085 ret = copy_to_user(user_buf, buf, count);
1086 if (ret) {
1087 ret = -EFAULT;
1088 goto exit;
1089 }
1090
1091 count -= ret;
1092 *ppos += count;
1093 ret = count;
1094
1095exit:
1096 vfree(buf);
1097 mutex_unlock(&ar->conf_mutex);
1098
1099 return ret;
1100}
1101
1102static ssize_t ath10k_mem_value_write(struct file *file,
1103 const char __user *user_buf,
1104 size_t count, loff_t *ppos)
1105{
1106 struct ath10k *ar = file->private_data;
1107 u8 *buf;
1108 int ret;
1109
1110 if (*ppos < 0)
1111 return -EINVAL;
1112
1113 if (!count)
1114 return 0;
1115
1116 mutex_lock(&ar->conf_mutex);
1117
1118 buf = vmalloc(count);
1119 if (!buf) {
1120 ret = -ENOMEM;
1121 goto exit;
1122 }
1123
1124 if (ar->state != ATH10K_STATE_ON &&
1125 ar->state != ATH10K_STATE_UTF) {
1126 ret = -ENETDOWN;
1127 goto exit;
1128 }
1129
1130 ret = copy_from_user(buf, user_buf, count);
1131 if (ret) {
1132 ret = -EFAULT;
1133 goto exit;
1134 }
1135
1136 ret = ath10k_hif_diag_write(ar, *ppos, buf, count);
1137 if (ret) {
1138 ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",
1139 (u32)(*ppos), ret);
1140 goto exit;
1141 }
1142
1143 *ppos += count;
1144 ret = count;
1145
1146exit:
1147 vfree(buf);
1148 mutex_unlock(&ar->conf_mutex);
1149
1150 return ret;
1151}
1152
1153static const struct file_operations fops_mem_value = {
1154 .read = ath10k_mem_value_read,
1155 .write = ath10k_mem_value_write,
1156 .open = simple_open,
1157 .owner = THIS_MODULE,
1158 .llseek = default_llseek,
1159};
1160
Kalle Valoa3d135e2013-09-03 11:44:10 +03001161static int ath10k_debug_htt_stats_req(struct ath10k *ar)
1162{
1163 u64 cookie;
1164 int ret;
1165
1166 lockdep_assert_held(&ar->conf_mutex);
1167
1168 if (ar->debug.htt_stats_mask == 0)
1169 /* htt stats are disabled */
1170 return 0;
1171
1172 if (ar->state != ATH10K_STATE_ON)
1173 return 0;
1174
1175 cookie = get_jiffies_64();
1176
1177 ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask,
1178 cookie);
1179 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001180 ath10k_warn(ar, "failed to send htt stats request: %d\n", ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001181 return ret;
1182 }
1183
1184 queue_delayed_work(ar->workqueue, &ar->debug.htt_stats_dwork,
1185 msecs_to_jiffies(ATH10K_DEBUG_HTT_STATS_INTERVAL));
1186
1187 return 0;
1188}
1189
1190static void ath10k_debug_htt_stats_dwork(struct work_struct *work)
1191{
1192 struct ath10k *ar = container_of(work, struct ath10k,
1193 debug.htt_stats_dwork.work);
1194
1195 mutex_lock(&ar->conf_mutex);
1196
1197 ath10k_debug_htt_stats_req(ar);
1198
1199 mutex_unlock(&ar->conf_mutex);
1200}
1201
1202static ssize_t ath10k_read_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001203 char __user *user_buf,
1204 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001205{
1206 struct ath10k *ar = file->private_data;
1207 char buf[32];
1208 unsigned int len;
1209
1210 len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask);
1211
1212 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1213}
1214
1215static ssize_t ath10k_write_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001216 const char __user *user_buf,
1217 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001218{
1219 struct ath10k *ar = file->private_data;
1220 unsigned long mask;
1221 int ret;
1222
1223 ret = kstrtoul_from_user(user_buf, count, 0, &mask);
1224 if (ret)
1225 return ret;
1226
1227 /* max 8 bit masks (for now) */
1228 if (mask > 0xff)
1229 return -E2BIG;
1230
1231 mutex_lock(&ar->conf_mutex);
1232
1233 ar->debug.htt_stats_mask = mask;
1234
1235 ret = ath10k_debug_htt_stats_req(ar);
1236 if (ret)
1237 goto out;
1238
1239 ret = count;
1240
1241out:
1242 mutex_unlock(&ar->conf_mutex);
1243
1244 return ret;
1245}
1246
1247static const struct file_operations fops_htt_stats_mask = {
1248 .read = ath10k_read_htt_stats_mask,
1249 .write = ath10k_write_htt_stats_mask,
1250 .open = simple_open,
1251 .owner = THIS_MODULE,
1252 .llseek = default_llseek,
1253};
1254
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001255static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
1256 char __user *user_buf,
1257 size_t count, loff_t *ppos)
1258{
1259 struct ath10k *ar = file->private_data;
1260 char buf[64];
1261 u8 amsdu = 3, ampdu = 64;
1262 unsigned int len;
1263
1264 mutex_lock(&ar->conf_mutex);
1265
1266 if (ar->debug.htt_max_amsdu)
1267 amsdu = ar->debug.htt_max_amsdu;
1268
1269 if (ar->debug.htt_max_ampdu)
1270 ampdu = ar->debug.htt_max_ampdu;
1271
1272 mutex_unlock(&ar->conf_mutex);
1273
1274 len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
1275
1276 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1277}
1278
1279static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
1280 const char __user *user_buf,
1281 size_t count, loff_t *ppos)
1282{
1283 struct ath10k *ar = file->private_data;
1284 int res;
1285 char buf[64];
1286 unsigned int amsdu, ampdu;
1287
1288 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
1293 res = sscanf(buf, "%u %u", &amsdu, &ampdu);
1294
1295 if (res != 2)
1296 return -EINVAL;
1297
1298 mutex_lock(&ar->conf_mutex);
1299
1300 res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
1301 if (res)
1302 goto out;
1303
1304 res = count;
1305 ar->debug.htt_max_amsdu = amsdu;
1306 ar->debug.htt_max_ampdu = ampdu;
1307
1308out:
1309 mutex_unlock(&ar->conf_mutex);
1310 return res;
1311}
1312
1313static const struct file_operations fops_htt_max_amsdu_ampdu = {
1314 .read = ath10k_read_htt_max_amsdu_ampdu,
1315 .write = ath10k_write_htt_max_amsdu_ampdu,
1316 .open = simple_open,
1317 .owner = THIS_MODULE,
1318 .llseek = default_llseek,
1319};
1320
Kalle Valof118a3e2014-01-03 12:59:31 +02001321static ssize_t ath10k_read_fw_dbglog(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001322 char __user *user_buf,
1323 size_t count, loff_t *ppos)
Kalle Valof118a3e2014-01-03 12:59:31 +02001324{
1325 struct ath10k *ar = file->private_data;
1326 unsigned int len;
1327 char buf[32];
1328
1329 len = scnprintf(buf, sizeof(buf), "0x%08x\n",
1330 ar->debug.fw_dbglog_mask);
1331
1332 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1333}
1334
1335static ssize_t ath10k_write_fw_dbglog(struct file *file,
1336 const char __user *user_buf,
1337 size_t count, loff_t *ppos)
1338{
1339 struct ath10k *ar = file->private_data;
1340 unsigned long mask;
1341 int ret;
1342
1343 ret = kstrtoul_from_user(user_buf, count, 0, &mask);
1344 if (ret)
1345 return ret;
1346
1347 mutex_lock(&ar->conf_mutex);
1348
1349 ar->debug.fw_dbglog_mask = mask;
1350
1351 if (ar->state == ATH10K_STATE_ON) {
1352 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask);
1353 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001354 ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n",
Kalle Valof118a3e2014-01-03 12:59:31 +02001355 ret);
1356 goto exit;
1357 }
1358 }
1359
1360 ret = count;
1361
1362exit:
1363 mutex_unlock(&ar->conf_mutex);
1364
1365 return ret;
1366}
1367
Ben Greear6cddcc72014-09-29 14:41:46 +03001368/* TODO: Would be nice to always support ethtool stats, would need to
1369 * move the stats storage out of ath10k_debug, or always have ath10k_debug
1370 * struct available..
1371 */
1372
1373/* This generally cooresponds to the debugfs fw_stats file */
1374static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
1375 "tx_pkts_nic",
1376 "tx_bytes_nic",
1377 "rx_pkts_nic",
1378 "rx_bytes_nic",
1379 "d_noise_floor",
1380 "d_cycle_count",
1381 "d_phy_error",
1382 "d_rts_bad",
1383 "d_rts_good",
1384 "d_tx_power", /* in .5 dbM I think */
1385 "d_rx_crc_err", /* fcs_bad */
1386 "d_no_beacon",
1387 "d_tx_mpdus_queued",
1388 "d_tx_msdu_queued",
1389 "d_tx_msdu_dropped",
1390 "d_local_enqued",
1391 "d_local_freed",
1392 "d_tx_ppdu_hw_queued",
1393 "d_tx_ppdu_reaped",
1394 "d_tx_fifo_underrun",
1395 "d_tx_ppdu_abort",
1396 "d_tx_mpdu_requed",
1397 "d_tx_excessive_retries",
1398 "d_tx_hw_rate",
1399 "d_tx_dropped_sw_retries",
1400 "d_tx_illegal_rate",
1401 "d_tx_continuous_xretries",
1402 "d_tx_timeout",
1403 "d_tx_mpdu_txop_limit",
1404 "d_pdev_resets",
1405 "d_rx_mid_ppdu_route_change",
1406 "d_rx_status",
1407 "d_rx_extra_frags_ring0",
1408 "d_rx_extra_frags_ring1",
1409 "d_rx_extra_frags_ring2",
1410 "d_rx_extra_frags_ring3",
1411 "d_rx_msdu_htt",
1412 "d_rx_mpdu_htt",
1413 "d_rx_msdu_stack",
1414 "d_rx_mpdu_stack",
1415 "d_rx_phy_err",
1416 "d_rx_phy_err_drops",
1417 "d_rx_mpdu_errors", /* FCS, MIC, ENC */
1418 "d_fw_crash_count",
1419 "d_fw_warm_reset_count",
1420 "d_fw_cold_reset_count",
1421};
1422
1423#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
1424
1425void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
1426 struct ieee80211_vif *vif,
1427 u32 sset, u8 *data)
1428{
1429 if (sset == ETH_SS_STATS)
1430 memcpy(data, *ath10k_gstrings_stats,
1431 sizeof(ath10k_gstrings_stats));
1432}
1433
1434int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
1435 struct ieee80211_vif *vif, int sset)
1436{
1437 if (sset == ETH_SS_STATS)
1438 return ATH10K_SSTATS_LEN;
1439
1440 return 0;
1441}
1442
1443void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
1444 struct ieee80211_vif *vif,
1445 struct ethtool_stats *stats, u64 *data)
1446{
1447 struct ath10k *ar = hw->priv;
1448 static const struct ath10k_fw_stats_pdev zero_stats = {};
1449 const struct ath10k_fw_stats_pdev *pdev_stats;
1450 int i = 0, ret;
1451
1452 mutex_lock(&ar->conf_mutex);
1453
1454 if (ar->state == ATH10K_STATE_ON) {
1455 ret = ath10k_debug_fw_stats_request(ar);
1456 if (ret) {
1457 /* just print a warning and try to use older results */
1458 ath10k_warn(ar,
1459 "failed to get fw stats for ethtool: %d\n",
1460 ret);
1461 }
1462 }
1463
1464 pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,
1465 struct ath10k_fw_stats_pdev,
1466 list);
1467 if (!pdev_stats) {
1468 /* no results available so just return zeroes */
1469 pdev_stats = &zero_stats;
1470 }
1471
1472 spin_lock_bh(&ar->data_lock);
1473
1474 data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
1475 data[i++] = 0; /* tx bytes */
1476 data[i++] = pdev_stats->htt_mpdus;
1477 data[i++] = 0; /* rx bytes */
1478 data[i++] = pdev_stats->ch_noise_floor;
1479 data[i++] = pdev_stats->cycle_count;
1480 data[i++] = pdev_stats->phy_err_count;
1481 data[i++] = pdev_stats->rts_bad;
1482 data[i++] = pdev_stats->rts_good;
1483 data[i++] = pdev_stats->chan_tx_power;
1484 data[i++] = pdev_stats->fcs_bad;
1485 data[i++] = pdev_stats->no_beacons;
1486 data[i++] = pdev_stats->mpdu_enqued;
1487 data[i++] = pdev_stats->msdu_enqued;
1488 data[i++] = pdev_stats->wmm_drop;
1489 data[i++] = pdev_stats->local_enqued;
1490 data[i++] = pdev_stats->local_freed;
1491 data[i++] = pdev_stats->hw_queued;
1492 data[i++] = pdev_stats->hw_reaped;
1493 data[i++] = pdev_stats->underrun;
1494 data[i++] = pdev_stats->tx_abort;
1495 data[i++] = pdev_stats->mpdus_requed;
1496 data[i++] = pdev_stats->tx_ko;
1497 data[i++] = pdev_stats->data_rc;
1498 data[i++] = pdev_stats->sw_retry_failure;
1499 data[i++] = pdev_stats->illgl_rate_phy_err;
1500 data[i++] = pdev_stats->pdev_cont_xretry;
1501 data[i++] = pdev_stats->pdev_tx_timeout;
1502 data[i++] = pdev_stats->txop_ovf;
1503 data[i++] = pdev_stats->pdev_resets;
1504 data[i++] = pdev_stats->mid_ppdu_route_change;
1505 data[i++] = pdev_stats->status_rcvd;
1506 data[i++] = pdev_stats->r0_frags;
1507 data[i++] = pdev_stats->r1_frags;
1508 data[i++] = pdev_stats->r2_frags;
1509 data[i++] = pdev_stats->r3_frags;
1510 data[i++] = pdev_stats->htt_msdus;
1511 data[i++] = pdev_stats->htt_mpdus;
1512 data[i++] = pdev_stats->loc_msdus;
1513 data[i++] = pdev_stats->loc_mpdus;
1514 data[i++] = pdev_stats->phy_errs;
1515 data[i++] = pdev_stats->phy_err_drop;
1516 data[i++] = pdev_stats->mpdu_errs;
1517 data[i++] = ar->stats.fw_crash_counter;
1518 data[i++] = ar->stats.fw_warm_reset_counter;
1519 data[i++] = ar->stats.fw_cold_reset_counter;
1520
1521 spin_unlock_bh(&ar->data_lock);
1522
1523 mutex_unlock(&ar->conf_mutex);
1524
1525 WARN_ON(i != ATH10K_SSTATS_LEN);
1526}
1527
Kalle Valof118a3e2014-01-03 12:59:31 +02001528static const struct file_operations fops_fw_dbglog = {
1529 .read = ath10k_read_fw_dbglog,
1530 .write = ath10k_write_fw_dbglog,
1531 .open = simple_open,
1532 .owner = THIS_MODULE,
1533 .llseek = default_llseek,
1534};
1535
Kalle Valo7869b4f2014-09-24 14:16:58 +03001536static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
1537{
1538 struct ath10k *ar = inode->i_private;
1539 void *buf;
1540 u32 hi_addr;
1541 __le32 addr;
1542 int ret;
1543
1544 mutex_lock(&ar->conf_mutex);
1545
1546 if (ar->state != ATH10K_STATE_ON &&
1547 ar->state != ATH10K_STATE_UTF) {
1548 ret = -ENETDOWN;
1549 goto err;
1550 }
1551
1552 buf = vmalloc(QCA988X_CAL_DATA_LEN);
1553 if (!buf) {
1554 ret = -ENOMEM;
1555 goto err;
1556 }
1557
1558 hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
1559
1560 ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
1561 if (ret) {
1562 ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret);
1563 goto err_vfree;
1564 }
1565
1566 ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
1567 QCA988X_CAL_DATA_LEN);
1568 if (ret) {
1569 ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
1570 goto err_vfree;
1571 }
1572
1573 file->private_data = buf;
1574
1575 mutex_unlock(&ar->conf_mutex);
1576
1577 return 0;
1578
1579err_vfree:
1580 vfree(buf);
1581
1582err:
1583 mutex_unlock(&ar->conf_mutex);
1584
1585 return ret;
1586}
1587
1588static ssize_t ath10k_debug_cal_data_read(struct file *file,
1589 char __user *user_buf,
1590 size_t count, loff_t *ppos)
1591{
1592 void *buf = file->private_data;
1593
1594 return simple_read_from_buffer(user_buf, count, ppos,
1595 buf, QCA988X_CAL_DATA_LEN);
1596}
1597
1598static int ath10k_debug_cal_data_release(struct inode *inode,
1599 struct file *file)
1600{
1601 vfree(file->private_data);
1602
1603 return 0;
1604}
1605
1606static const struct file_operations fops_cal_data = {
1607 .open = ath10k_debug_cal_data_open,
1608 .read = ath10k_debug_cal_data_read,
1609 .release = ath10k_debug_cal_data_release,
1610 .owner = THIS_MODULE,
1611 .llseek = default_llseek,
1612};
1613
Kalle Valodb66ea02013-09-03 11:44:03 +03001614int ath10k_debug_start(struct ath10k *ar)
1615{
Kalle Valoa3d135e2013-09-03 11:44:10 +03001616 int ret;
1617
Kalle Valo60631c52013-10-08 21:45:25 +03001618 lockdep_assert_held(&ar->conf_mutex);
1619
Kalle Valoa3d135e2013-09-03 11:44:10 +03001620 ret = ath10k_debug_htt_stats_req(ar);
1621 if (ret)
1622 /* continue normally anyway, this isn't serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001623 ath10k_warn(ar, "failed to start htt stats workqueue: %d\n",
1624 ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001625
Kalle Valof118a3e2014-01-03 12:59:31 +02001626 if (ar->debug.fw_dbglog_mask) {
1627 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask);
1628 if (ret)
1629 /* not serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001630 ath10k_warn(ar, "failed to enable dbglog during start: %d",
Kalle Valof118a3e2014-01-03 12:59:31 +02001631 ret);
1632 }
1633
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001634 if (ar->debug.pktlog_filter) {
1635 ret = ath10k_wmi_pdev_pktlog_enable(ar,
1636 ar->debug.pktlog_filter);
1637 if (ret)
1638 /* not serious */
1639 ath10k_warn(ar,
1640 "failed to enable pktlog filter %x: %d\n",
1641 ar->debug.pktlog_filter, ret);
1642 } else {
1643 ret = ath10k_wmi_pdev_pktlog_disable(ar);
1644 if (ret)
1645 /* not serious */
1646 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
1647 }
1648
1649 return ret;
Kalle Valodb66ea02013-09-03 11:44:03 +03001650}
1651
1652void ath10k_debug_stop(struct ath10k *ar)
1653{
Kalle Valo60631c52013-10-08 21:45:25 +03001654 lockdep_assert_held(&ar->conf_mutex);
1655
1656 /* Must not use _sync to avoid deadlock, we do that in
1657 * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid
1658 * warning from del_timer(). */
1659 if (ar->debug.htt_stats_mask != 0)
1660 cancel_delayed_work(&ar->debug.htt_stats_dwork);
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001661
1662 ar->debug.htt_max_amsdu = 0;
1663 ar->debug.htt_max_ampdu = 0;
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001664
1665 ath10k_wmi_pdev_pktlog_disable(ar);
Kalle Valodb66ea02013-09-03 11:44:03 +03001666}
1667
Janusz Dziedzic9702c682013-11-20 09:59:41 +02001668static ssize_t ath10k_write_simulate_radar(struct file *file,
1669 const char __user *user_buf,
1670 size_t count, loff_t *ppos)
1671{
1672 struct ath10k *ar = file->private_data;
1673
1674 ieee80211_radar_detected(ar->hw);
1675
1676 return count;
1677}
1678
1679static const struct file_operations fops_simulate_radar = {
1680 .write = ath10k_write_simulate_radar,
1681 .open = simple_open,
1682 .owner = THIS_MODULE,
1683 .llseek = default_llseek,
1684};
1685
1686#define ATH10K_DFS_STAT(s, p) (\
1687 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
1688 ar->debug.dfs_stats.p))
1689
1690#define ATH10K_DFS_POOL_STAT(s, p) (\
1691 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
1692 ar->debug.dfs_pool_stats.p))
1693
1694static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf,
1695 size_t count, loff_t *ppos)
1696{
1697 int retval = 0, len = 0;
1698 const int size = 8000;
1699 struct ath10k *ar = file->private_data;
1700 char *buf;
1701
1702 buf = kzalloc(size, GFP_KERNEL);
1703 if (buf == NULL)
1704 return -ENOMEM;
1705
1706 if (!ar->dfs_detector) {
1707 len += scnprintf(buf + len, size - len, "DFS not enabled\n");
1708 goto exit;
1709 }
1710
1711 ar->debug.dfs_pool_stats =
1712 ar->dfs_detector->get_stats(ar->dfs_detector);
1713
1714 len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");
1715
1716 ATH10K_DFS_STAT("reported phy errors", phy_errors);
1717 ATH10K_DFS_STAT("pulse events reported", pulses_total);
1718 ATH10K_DFS_STAT("DFS pulses detected", pulses_detected);
1719 ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded);
1720 ATH10K_DFS_STAT("Radars detected", radar_detected);
1721
1722 len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");
1723 ATH10K_DFS_POOL_STAT("Pool references", pool_reference);
1724 ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated);
1725 ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error);
1726 ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used);
1727 ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated);
1728 ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error);
1729 ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used);
1730
1731exit:
1732 if (len > size)
1733 len = size;
1734
1735 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1736 kfree(buf);
1737
1738 return retval;
1739}
1740
1741static const struct file_operations fops_dfs_stats = {
1742 .read = ath10k_read_dfs_stats,
1743 .open = simple_open,
1744 .owner = THIS_MODULE,
1745 .llseek = default_llseek,
1746};
1747
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001748static ssize_t ath10k_write_pktlog_filter(struct file *file,
1749 const char __user *ubuf,
1750 size_t count, loff_t *ppos)
1751{
1752 struct ath10k *ar = file->private_data;
1753 u32 filter;
1754 int ret;
1755
1756 if (kstrtouint_from_user(ubuf, count, 0, &filter))
1757 return -EINVAL;
1758
1759 mutex_lock(&ar->conf_mutex);
1760
1761 if (ar->state != ATH10K_STATE_ON) {
1762 ar->debug.pktlog_filter = filter;
1763 ret = count;
1764 goto out;
1765 }
1766
1767 if (filter && (filter != ar->debug.pktlog_filter)) {
1768 ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
1769 if (ret) {
1770 ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
1771 ar->debug.pktlog_filter, ret);
1772 goto out;
1773 }
1774 } else {
1775 ret = ath10k_wmi_pdev_pktlog_disable(ar);
1776 if (ret) {
1777 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
1778 goto out;
1779 }
1780 }
1781
1782 ar->debug.pktlog_filter = filter;
1783 ret = count;
1784
1785out:
1786 mutex_unlock(&ar->conf_mutex);
1787 return ret;
1788}
1789
1790static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf,
1791 size_t count, loff_t *ppos)
1792{
1793 char buf[32];
1794 struct ath10k *ar = file->private_data;
1795 int len = 0;
1796
1797 mutex_lock(&ar->conf_mutex);
1798 len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
1799 ar->debug.pktlog_filter);
1800 mutex_unlock(&ar->conf_mutex);
1801
1802 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1803}
1804
1805static const struct file_operations fops_pktlog_filter = {
1806 .read = ath10k_read_pktlog_filter,
1807 .write = ath10k_write_pktlog_filter,
1808 .open = simple_open
1809};
1810
Kalle Valo5e3dd152013-06-12 20:52:10 +03001811int ath10k_debug_create(struct ath10k *ar)
1812{
Ben Greear384914b2014-08-25 08:37:32 +03001813 ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
Michal Kaziore13cf7a2014-09-04 09:13:08 +02001814 if (!ar->debug.fw_crash_data)
1815 return -ENOMEM;
Ben Greear384914b2014-08-25 08:37:32 +03001816
Michal Kazior53268492014-09-25 12:33:50 +02001817 INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
1818 INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
1819
Michal Kaziore13cf7a2014-09-04 09:13:08 +02001820 return 0;
1821}
1822
1823void ath10k_debug_destroy(struct ath10k *ar)
1824{
1825 vfree(ar->debug.fw_crash_data);
1826 ar->debug.fw_crash_data = NULL;
Michal Kazior53268492014-09-25 12:33:50 +02001827
1828 ath10k_debug_fw_stats_reset(ar);
Michal Kaziore13cf7a2014-09-04 09:13:08 +02001829}
1830
1831int ath10k_debug_register(struct ath10k *ar)
1832{
Kalle Valo5e3dd152013-06-12 20:52:10 +03001833 ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
1834 ar->hw->wiphy->debugfsdir);
Michal Kazioradb43b22014-09-04 12:36:45 +02001835 if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
1836 if (IS_ERR(ar->debug.debugfs_phy))
1837 return PTR_ERR(ar->debug.debugfs_phy);
Kalle Valod8bb26b2014-09-14 12:50:33 +03001838
1839 return -ENOMEM;
Michal Kazioradb43b22014-09-04 12:36:45 +02001840 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03001841
Kalle Valoa3d135e2013-09-03 11:44:10 +03001842 INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
1843 ath10k_debug_htt_stats_dwork);
1844
Michal Kazior60ef4012014-09-25 12:33:48 +02001845 init_completion(&ar->debug.fw_stats_complete);
Kalle Valo5e3dd152013-06-12 20:52:10 +03001846
1847 debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
1848 &fops_fw_stats);
1849
Ben Greearf51dbe72014-09-29 14:41:46 +03001850 debugfs_create_file("fw_reset_stats", S_IRUSR, ar->debug.debugfs_phy,
1851 ar, &fops_fw_reset_stats);
1852
Kalle Valo5e3dd152013-06-12 20:52:10 +03001853 debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
1854 &fops_wmi_services);
1855
Michal Kazior278c4a82013-07-22 14:08:51 +02001856 debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
1857 ar, &fops_simulate_fw_crash);
1858
Ben Greear384914b2014-08-25 08:37:32 +03001859 debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
1860 ar, &fops_fw_crash_dump);
1861
Yanbo Li077a3802014-11-25 12:24:33 +02001862 debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR,
1863 ar->debug.debugfs_phy, ar, &fops_reg_addr);
1864
1865 debugfs_create_file("reg_value", S_IRUSR | S_IWUSR,
1866 ar->debug.debugfs_phy, ar, &fops_reg_value);
1867
Yanbo Li9f65ad22014-11-25 12:24:48 +02001868 debugfs_create_file("mem_value", S_IRUSR | S_IWUSR,
1869 ar->debug.debugfs_phy, ar, &fops_mem_value);
1870
Kalle Valo763b8cd2013-09-01 11:22:21 +03001871 debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
1872 ar, &fops_chip_id);
1873
Kalle Valoa3d135e2013-09-03 11:44:10 +03001874 debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
1875 ar, &fops_htt_stats_mask);
1876
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001877 debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
1878 ar->debug.debugfs_phy, ar,
1879 &fops_htt_max_amsdu_ampdu);
1880
Kalle Valof118a3e2014-01-03 12:59:31 +02001881 debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
1882 ar, &fops_fw_dbglog);
1883
Kalle Valo7869b4f2014-09-24 14:16:58 +03001884 debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
1885 ar, &fops_cal_data);
1886
Janusz Dziedzic9702c682013-11-20 09:59:41 +02001887 if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
1888 debugfs_create_file("dfs_simulate_radar", S_IWUSR,
1889 ar->debug.debugfs_phy, ar,
1890 &fops_simulate_radar);
1891
Marek Puzyniak7d9b40b2013-11-20 10:00:28 +02001892 debugfs_create_bool("dfs_block_radar_events", S_IWUSR,
1893 ar->debug.debugfs_phy,
1894 &ar->dfs_block_radar_events);
1895
Janusz Dziedzic9702c682013-11-20 09:59:41 +02001896 debugfs_create_file("dfs_stats", S_IRUSR,
1897 ar->debug.debugfs_phy, ar,
1898 &fops_dfs_stats);
1899 }
1900
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001901 debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR,
1902 ar->debug.debugfs_phy, ar, &fops_pktlog_filter);
1903
Kalle Valo5e3dd152013-06-12 20:52:10 +03001904 return 0;
1905}
Kalle Valodb66ea02013-09-03 11:44:03 +03001906
Michal Kaziore13cf7a2014-09-04 09:13:08 +02001907void ath10k_debug_unregister(struct ath10k *ar)
Kalle Valo60631c52013-10-08 21:45:25 +03001908{
1909 cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
1910}
1911
Kalle Valo5e3dd152013-06-12 20:52:10 +03001912#endif /* CONFIG_ATH10K_DEBUGFS */
1913
1914#ifdef CONFIG_ATH10K_DEBUG
Michal Kazior7aa7a722014-08-25 12:09:38 +02001915void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
1916 const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +03001917{
1918 struct va_format vaf;
1919 va_list args;
1920
1921 va_start(args, fmt);
1922
1923 vaf.fmt = fmt;
1924 vaf.va = &args;
1925
1926 if (ath10k_debug_mask & mask)
Michal Kazior7aa7a722014-08-25 12:09:38 +02001927 dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03001928
Michal Kaziord35a6c12014-09-02 11:00:21 +03001929 trace_ath10k_log_dbg(ar, mask, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03001930
1931 va_end(args);
1932}
1933EXPORT_SYMBOL(ath10k_dbg);
1934
Michal Kazior7aa7a722014-08-25 12:09:38 +02001935void ath10k_dbg_dump(struct ath10k *ar,
1936 enum ath10k_debug_mask mask,
Kalle Valo5e3dd152013-06-12 20:52:10 +03001937 const char *msg, const char *prefix,
1938 const void *buf, size_t len)
1939{
Michal Kazior45724a82014-09-23 10:22:53 +02001940 char linebuf[256];
1941 unsigned int linebuflen;
1942 const void *ptr;
1943
Kalle Valo5e3dd152013-06-12 20:52:10 +03001944 if (ath10k_debug_mask & mask) {
1945 if (msg)
Michal Kazior7aa7a722014-08-25 12:09:38 +02001946 ath10k_dbg(ar, mask, "%s\n", msg);
Kalle Valo5e3dd152013-06-12 20:52:10 +03001947
Michal Kazior45724a82014-09-23 10:22:53 +02001948 for (ptr = buf; (ptr - buf) < len; ptr += 16) {
1949 linebuflen = 0;
1950 linebuflen += scnprintf(linebuf + linebuflen,
1951 sizeof(linebuf) - linebuflen,
1952 "%s%08x: ",
1953 (prefix ? prefix : ""),
1954 (unsigned int)(ptr - buf));
1955 hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
1956 linebuf + linebuflen,
1957 sizeof(linebuf) - linebuflen, true);
1958 dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
1959 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03001960 }
1961
1962 /* tracing code doesn't like null strings :/ */
Michal Kaziord35a6c12014-09-02 11:00:21 +03001963 trace_ath10k_log_dbg_dump(ar, msg ? msg : "", prefix ? prefix : "",
Kalle Valo5e3dd152013-06-12 20:52:10 +03001964 buf, len);
1965}
1966EXPORT_SYMBOL(ath10k_dbg_dump);
1967
1968#endif /* CONFIG_ATH10K_DEBUG */