blob: 6ca24427e18487b9e609d4a7f9209742183e7ebe [file] [log] [blame]
Kalle Valo5e3dd152013-06-12 20:52:10 +03001/*
2 * Copyright (c) 2005-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <linux/module.h>
19#include <linux/debugfs.h>
Ben Greear384914b2014-08-25 08:37:32 +030020#include <linux/vmalloc.h>
Johannes Berg12c27152014-11-21 18:58:49 +020021#include <linux/utsname.h>
Kalle Valo5e3dd152013-06-12 20:52:10 +030022
23#include "core.h"
24#include "debug.h"
Kalle Valo7869b4f2014-09-24 14:16:58 +030025#include "hif.h"
Michal Kaziord7579d12014-12-03 10:10:54 +020026#include "wmi-ops.h"
Kalle Valo5e3dd152013-06-12 20:52:10 +030027
Kalle Valoa3d135e2013-09-03 11:44:10 +030028/* ms */
29#define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
30
Ben Greear384914b2014-08-25 08:37:32 +030031#define ATH10K_FW_CRASH_DUMP_VERSION 1
32
33/**
34 * enum ath10k_fw_crash_dump_type - types of data in the dump file
35 * @ATH10K_FW_CRASH_DUMP_REGDUMP: Register crash dump in binary format
36 */
37enum ath10k_fw_crash_dump_type {
38 ATH10K_FW_CRASH_DUMP_REGISTERS = 0,
39
40 ATH10K_FW_CRASH_DUMP_MAX,
41};
42
43struct ath10k_tlv_dump_data {
44 /* see ath10k_fw_crash_dump_type above */
45 __le32 type;
46
47 /* in bytes */
48 __le32 tlv_len;
49
50 /* pad to 32-bit boundaries as needed */
51 u8 tlv_data[];
52} __packed;
53
54struct ath10k_dump_file_data {
55 /* dump file information */
56
57 /* "ATH10K-FW-DUMP" */
58 char df_magic[16];
59
60 __le32 len;
61
62 /* file dump version */
63 __le32 version;
64
65 /* some info we can get from ath10k struct that might help */
66
67 u8 uuid[16];
68
69 __le32 chip_id;
70
71 /* 0 for now, in place for later hardware */
72 __le32 bus_type;
73
74 __le32 target_version;
75 __le32 fw_version_major;
76 __le32 fw_version_minor;
77 __le32 fw_version_release;
78 __le32 fw_version_build;
79 __le32 phy_capability;
80 __le32 hw_min_tx_power;
81 __le32 hw_max_tx_power;
82 __le32 ht_cap_info;
83 __le32 vht_cap_info;
84 __le32 num_rf_chains;
85
86 /* firmware version string */
87 char fw_ver[ETHTOOL_FWVERS_LEN];
88
89 /* Kernel related information */
90
91 /* time-of-day stamp */
92 __le64 tv_sec;
93
94 /* time-of-day stamp, nano-seconds */
95 __le64 tv_nsec;
96
97 /* LINUX_VERSION_CODE */
98 __le32 kernel_ver_code;
99
100 /* VERMAGIC_STRING */
101 char kernel_ver[64];
102
103 /* room for growth w/out changing binary format */
104 u8 unused[128];
105
106 /* struct ath10k_tlv_dump_data + more */
107 u8 data[0];
108} __packed;
109
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700110void ath10k_info(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300111{
112 struct va_format vaf = {
113 .fmt = fmt,
114 };
115 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300116
117 va_start(args, fmt);
118 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700119 dev_info(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300120 trace_ath10k_log_info(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300121 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300122}
123EXPORT_SYMBOL(ath10k_info);
124
Kalle Valo8a0c7972014-08-25 08:37:45 +0300125void ath10k_print_driver_info(struct ath10k *ar)
126{
Kalle Valoffdd0752014-12-17 12:21:03 +0200127 ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d cal %s max_sta %d\n",
Kalle Valo8a0c7972014-08-25 08:37:45 +0300128 ar->hw_params.name,
129 ar->target_version,
130 ar->chip_id,
131 ar->hw->wiphy->fw_version,
132 ar->fw_api,
133 ar->htt.target_version_major,
Michal Kazior34b28b62014-09-23 10:22:52 +0200134 ar->htt.target_version_minor,
Kalle Valoffdd0752014-12-17 12:21:03 +0200135 ar->wmi.op_version,
Michal Kaziorcfd10612014-11-25 15:16:05 +0100136 ath10k_cal_mode_str(ar->cal_mode),
137 ar->max_num_stations);
Kalle Valo43d2a302014-09-10 18:23:30 +0300138 ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
Kalle Valo8a0c7972014-08-25 08:37:45 +0300139 config_enabled(CONFIG_ATH10K_DEBUG),
140 config_enabled(CONFIG_ATH10K_DEBUGFS),
141 config_enabled(CONFIG_ATH10K_TRACING),
Kalle Valo43d2a302014-09-10 18:23:30 +0300142 config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
143 config_enabled(CONFIG_NL80211_TESTMODE));
Kalle Valo8a0c7972014-08-25 08:37:45 +0300144}
145EXPORT_SYMBOL(ath10k_print_driver_info);
146
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700147void ath10k_err(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300148{
149 struct va_format vaf = {
150 .fmt = fmt,
151 };
152 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300153
154 va_start(args, fmt);
155 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700156 dev_err(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300157 trace_ath10k_log_err(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300158 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300159}
160EXPORT_SYMBOL(ath10k_err);
161
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700162void ath10k_warn(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300163{
164 struct va_format vaf = {
165 .fmt = fmt,
166 };
167 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300168
169 va_start(args, fmt);
170 vaf.va = &args;
Michal Kazior7aa7a722014-08-25 12:09:38 +0200171 dev_warn_ratelimited(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300172 trace_ath10k_log_warn(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300173
174 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300175}
176EXPORT_SYMBOL(ath10k_warn);
177
178#ifdef CONFIG_ATH10K_DEBUGFS
179
Kalle Valo5e3dd152013-06-12 20:52:10 +0300180static ssize_t ath10k_read_wmi_services(struct file *file,
181 char __user *user_buf,
182 size_t count, loff_t *ppos)
183{
184 struct ath10k *ar = file->private_data;
185 char *buf;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300186 unsigned int len = 0, buf_len = 4096;
187 const char *name;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300188 ssize_t ret_cnt;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300189 bool enabled;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300190 int i;
191
192 buf = kzalloc(buf_len, GFP_KERNEL);
193 if (!buf)
194 return -ENOMEM;
195
196 mutex_lock(&ar->conf_mutex);
197
198 if (len > buf_len)
199 len = buf_len;
200
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100201 spin_lock_bh(&ar->data_lock);
Michal Kaziorc4f8c832014-09-04 10:18:32 +0200202 for (i = 0; i < WMI_SERVICE_MAX; i++) {
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100203 enabled = test_bit(i, ar->wmi.svc_map);
Michal Kaziorcff990c2014-08-04 09:18:33 +0300204 name = wmi_service_name(i);
205
206 if (!name) {
207 if (enabled)
208 len += scnprintf(buf + len, buf_len - len,
209 "%-40s %s (bit %d)\n",
210 "unknown", "enabled", i);
211
212 continue;
213 }
Kalle Valo5e3dd152013-06-12 20:52:10 +0300214
215 len += scnprintf(buf + len, buf_len - len,
Michal Kaziorcff990c2014-08-04 09:18:33 +0300216 "%-40s %s\n",
217 name, enabled ? "enabled" : "-");
Kalle Valo5e3dd152013-06-12 20:52:10 +0300218 }
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100219 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300220
221 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
222
223 mutex_unlock(&ar->conf_mutex);
224
225 kfree(buf);
226 return ret_cnt;
227}
228
229static const struct file_operations fops_wmi_services = {
230 .read = ath10k_read_wmi_services,
231 .open = simple_open,
232 .owner = THIS_MODULE,
233 .llseek = default_llseek,
234};
235
Michal Kazior53268492014-09-25 12:33:50 +0200236static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
237{
238 struct ath10k_fw_stats_pdev *i, *tmp;
239
240 list_for_each_entry_safe(i, tmp, head, list) {
241 list_del(&i->list);
242 kfree(i);
243 }
244}
245
246static void ath10k_debug_fw_stats_peers_free(struct list_head *head)
247{
248 struct ath10k_fw_stats_peer *i, *tmp;
249
250 list_for_each_entry_safe(i, tmp, head, list) {
251 list_del(&i->list);
252 kfree(i);
253 }
254}
255
256static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
257{
258 spin_lock_bh(&ar->data_lock);
259 ar->debug.fw_stats_done = false;
260 ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
261 ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers);
262 spin_unlock_bh(&ar->data_lock);
263}
264
265static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head)
266{
267 struct ath10k_fw_stats_peer *i;
268 size_t num = 0;
269
270 list_for_each_entry(i, head, list)
271 ++num;
272
273 return num;
274}
275
Michal Kazior60ef4012014-09-25 12:33:48 +0200276void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300277{
Michal Kazior53268492014-09-25 12:33:50 +0200278 struct ath10k_fw_stats stats = {};
279 bool is_start, is_started, is_end;
280 size_t num_peers;
Michal Kaziord15fb522014-09-25 12:33:47 +0200281 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300282
Michal Kazior53268492014-09-25 12:33:50 +0200283 INIT_LIST_HEAD(&stats.pdevs);
284 INIT_LIST_HEAD(&stats.peers);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300285
Michal Kazior53268492014-09-25 12:33:50 +0200286 spin_lock_bh(&ar->data_lock);
287 ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
Michal Kaziord15fb522014-09-25 12:33:47 +0200288 if (ret) {
289 ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
290 goto unlock;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300291 }
292
Michal Kazior53268492014-09-25 12:33:50 +0200293 /* Stat data may exceed htc-wmi buffer limit. In such case firmware
294 * splits the stats data and delivers it in a ping-pong fashion of
295 * request cmd-update event.
296 *
297 * However there is no explicit end-of-data. Instead start-of-data is
298 * used as an implicit one. This works as follows:
299 * a) discard stat update events until one with pdev stats is
300 * delivered - this skips session started at end of (b)
301 * b) consume stat update events until another one with pdev stats is
302 * delivered which is treated as end-of-data and is itself discarded
303 */
304
305 if (ar->debug.fw_stats_done) {
306 ath10k_warn(ar, "received unsolicited stats update event\n");
307 goto free;
308 }
309
310 num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers);
311 is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
312 !list_empty(&stats.pdevs));
313 is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
314 !list_empty(&stats.pdevs));
315
316 if (is_start)
317 list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
318
319 if (is_end)
320 ar->debug.fw_stats_done = true;
321
322 is_started = !list_empty(&ar->debug.fw_stats.pdevs);
323
324 if (is_started && !is_end) {
325 if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) {
326 /* Although this is unlikely impose a sane limit to
327 * prevent firmware from DoS-ing the host.
328 */
329 ath10k_warn(ar, "dropping fw peer stats\n");
330 goto free;
331 }
332
333 list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
334 }
335
Michal Kazior60ef4012014-09-25 12:33:48 +0200336 complete(&ar->debug.fw_stats_complete);
Michal Kaziord15fb522014-09-25 12:33:47 +0200337
Michal Kazior53268492014-09-25 12:33:50 +0200338free:
339 /* In some cases lists have been spliced and cleared. Free up
340 * resources if that is not the case.
341 */
342 ath10k_debug_fw_stats_pdevs_free(&stats.pdevs);
343 ath10k_debug_fw_stats_peers_free(&stats.peers);
344
Michal Kaziord15fb522014-09-25 12:33:47 +0200345unlock:
346 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300347}
348
Michal Kazior53268492014-09-25 12:33:50 +0200349static int ath10k_debug_fw_stats_request(struct ath10k *ar)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300350{
Michal Kazior53268492014-09-25 12:33:50 +0200351 unsigned long timeout;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300352 int ret;
353
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200354 lockdep_assert_held(&ar->conf_mutex);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300355
Michal Kazior53268492014-09-25 12:33:50 +0200356 timeout = jiffies + msecs_to_jiffies(1*HZ);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300357
Michal Kazior53268492014-09-25 12:33:50 +0200358 ath10k_debug_fw_stats_reset(ar);
359
360 for (;;) {
361 if (time_after(jiffies, timeout))
362 return -ETIMEDOUT;
363
364 reinit_completion(&ar->debug.fw_stats_complete);
365
366 ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
367 if (ret) {
368 ath10k_warn(ar, "could not request stats (%d)\n", ret);
369 return ret;
370 }
371
372 ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete,
373 1*HZ);
374 if (ret <= 0)
375 return -ETIMEDOUT;
376
377 spin_lock_bh(&ar->data_lock);
378 if (ar->debug.fw_stats_done) {
379 spin_unlock_bh(&ar->data_lock);
380 break;
381 }
382 spin_unlock_bh(&ar->data_lock);
383 }
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200384
385 return 0;
386}
387
388/* FIXME: How to calculate the buffer size sanely? */
389#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
390
391static void ath10k_fw_stats_fill(struct ath10k *ar,
392 struct ath10k_fw_stats *fw_stats,
393 char *buf)
394{
395 unsigned int len = 0;
396 unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
Michal Kazior53268492014-09-25 12:33:50 +0200397 const struct ath10k_fw_stats_pdev *pdev;
398 const struct ath10k_fw_stats_peer *peer;
399 size_t num_peers;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300400
Michal Kazior87571bf2013-07-16 09:38:59 +0200401 spin_lock_bh(&ar->data_lock);
Michal Kazior53268492014-09-25 12:33:50 +0200402
403 pdev = list_first_entry_or_null(&fw_stats->pdevs,
404 struct ath10k_fw_stats_pdev, list);
405 if (!pdev) {
406 ath10k_warn(ar, "failed to get pdev stats\n");
407 goto unlock;
408 }
409
410 num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers);
411
Kalle Valo5e3dd152013-06-12 20:52:10 +0300412 len += scnprintf(buf + len, buf_len - len, "\n");
413 len += scnprintf(buf + len, buf_len - len, "%30s\n",
414 "ath10k PDEV stats");
415 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
416 "=================");
417
418 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200419 "Channel noise floor", pdev->ch_noise_floor);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300420 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200421 "Channel TX power", pdev->chan_tx_power);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300422 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200423 "TX frame count", pdev->tx_frame_count);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300424 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200425 "RX frame count", pdev->rx_frame_count);
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 "RX clear count", pdev->rx_clear_count);
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 "Cycle count", pdev->cycle_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 "PHY error count", pdev->phy_err_count);
Chun-Yeow Yeoh52e346d2014-03-28 14:35:16 +0200432 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200433 "RTS bad count", pdev->rts_bad);
Chun-Yeow Yeoh52e346d2014-03-28 14:35:16 +0200434 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200435 "RTS good count", pdev->rts_good);
Chun-Yeow Yeoh52e346d2014-03-28 14:35:16 +0200436 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200437 "FCS bad count", pdev->fcs_bad);
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 "No beacon count", pdev->no_beacons);
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 "MIB int count", pdev->mib_int_count);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300442
443 len += scnprintf(buf + len, buf_len - len, "\n");
444 len += scnprintf(buf + len, buf_len - len, "%30s\n",
445 "ath10k PDEV TX stats");
446 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
447 "=================");
448
449 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200450 "HTT cookies queued", pdev->comp_queued);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300451 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200452 "HTT cookies disp.", pdev->comp_delivered);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300453 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200454 "MSDU queued", pdev->msdu_enqued);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300455 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200456 "MPDU queued", pdev->mpdu_enqued);
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 "MSDUs dropped", pdev->wmm_drop);
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 "Local enqued", pdev->local_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 "Local freed", pdev->local_freed);
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 "HW queued", pdev->hw_queued);
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 "PPDUs reaped", pdev->hw_reaped);
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 "Num underruns", pdev->underrun);
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 "PPDUs cleaned", pdev->tx_abort);
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 "MPDUs requed", pdev->mpdus_requed);
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 "Excessive retries", pdev->tx_ko);
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 "HW rate", pdev->data_rc);
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 "Sched self tiggers", pdev->self_triggers);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300479 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
480 "Dropped due to SW retries",
Michal Kazior53268492014-09-25 12:33:50 +0200481 pdev->sw_retry_failure);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300482 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
483 "Illegal rate phy errors",
Michal Kazior53268492014-09-25 12:33:50 +0200484 pdev->illgl_rate_phy_err);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300485 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200486 "Pdev continous xretry", pdev->pdev_cont_xretry);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300487 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200488 "TX timeout", pdev->pdev_tx_timeout);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300489 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200490 "PDEV resets", pdev->pdev_resets);
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 "PHY underrun", pdev->phy_underrun);
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 "MPDU is more than txop limit", pdev->txop_ovf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300495
496 len += scnprintf(buf + len, buf_len - len, "\n");
497 len += scnprintf(buf + len, buf_len - len, "%30s\n",
498 "ath10k PDEV RX stats");
499 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
500 "=================");
501
502 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
503 "Mid PPDU route change",
Michal Kazior53268492014-09-25 12:33:50 +0200504 pdev->mid_ppdu_route_change);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300505 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200506 "Tot. number of statuses", pdev->status_rcvd);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300507 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200508 "Extra frags on rings 0", pdev->r0_frags);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300509 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
Michal Kazior53268492014-09-25 12:33:50 +0200510 "Extra frags on rings 1", pdev->r1_frags);
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 "Extra frags on rings 2", pdev->r2_frags);
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 3", pdev->r3_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 "MSDUs delivered to HTT", pdev->htt_msdus);
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 "MPDUs delivered to HTT", pdev->htt_mpdus);
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 "MSDUs delivered to stack", pdev->loc_msdus);
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 "MPDUs delivered to stack", pdev->loc_mpdus);
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 "Oversized AMSUs", pdev->oversize_amsdu);
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 "PHY errors", pdev->phy_errs);
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 "PHY errors drops", pdev->phy_err_drop);
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 "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300531
532 len += scnprintf(buf + len, buf_len - len, "\n");
Michal Kazior53268492014-09-25 12:33:50 +0200533 len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
534 "ath10k PEER stats", num_peers);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300535 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
536 "=================");
537
Michal Kazior53268492014-09-25 12:33:50 +0200538 list_for_each_entry(peer, &fw_stats->peers, list) {
Kalle Valo5e3dd152013-06-12 20:52:10 +0300539 len += scnprintf(buf + len, buf_len - len, "%30s %pM\n",
Michal Kazior53268492014-09-25 12:33:50 +0200540 "Peer MAC address", peer->peer_macaddr);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300541 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200542 "Peer RSSI", peer->peer_rssi);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300543 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200544 "Peer TX rate", peer->peer_tx_rate);
Ben Greear23c3aae2014-03-28 14:35:15 +0200545 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
Michal Kazior53268492014-09-25 12:33:50 +0200546 "Peer RX rate", peer->peer_rx_rate);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300547 len += scnprintf(buf + len, buf_len - len, "\n");
548 }
Michal Kazior53268492014-09-25 12:33:50 +0200549
550unlock:
Michal Kazior87571bf2013-07-16 09:38:59 +0200551 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300552
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200553 if (len >= buf_len)
554 buf[len - 1] = 0;
555 else
556 buf[len] = 0;
557}
Kalle Valo5e3dd152013-06-12 20:52:10 +0300558
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200559static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
560{
561 struct ath10k *ar = inode->i_private;
562 void *buf = NULL;
563 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300564
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200565 mutex_lock(&ar->conf_mutex);
566
567 if (ar->state != ATH10K_STATE_ON) {
568 ret = -ENETDOWN;
569 goto err_unlock;
570 }
571
572 buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);
573 if (!buf) {
574 ret = -ENOMEM;
575 goto err_unlock;
576 }
577
Michal Kazior53268492014-09-25 12:33:50 +0200578 ret = ath10k_debug_fw_stats_request(ar);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200579 if (ret) {
580 ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
581 goto err_free;
582 }
583
584 ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
585 file->private_data = buf;
586
Kalle Valo5e3dd152013-06-12 20:52:10 +0300587 mutex_unlock(&ar->conf_mutex);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200588 return 0;
589
590err_free:
591 vfree(buf);
592
593err_unlock:
594 mutex_unlock(&ar->conf_mutex);
595 return ret;
596}
597
598static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
599{
600 vfree(file->private_data);
601
602 return 0;
603}
604
605static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
606 size_t count, loff_t *ppos)
607{
608 const char *buf = file->private_data;
609 unsigned int len = strlen(buf);
610
611 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300612}
613
614static const struct file_operations fops_fw_stats = {
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200615 .open = ath10k_fw_stats_open,
616 .release = ath10k_fw_stats_release,
Michal Kazior60ef4012014-09-25 12:33:48 +0200617 .read = ath10k_fw_stats_read,
Kalle Valo5e3dd152013-06-12 20:52:10 +0300618 .owner = THIS_MODULE,
619 .llseek = default_llseek,
620};
621
Ben Greearf51dbe72014-09-29 14:41:46 +0300622static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
623 char __user *user_buf,
624 size_t count, loff_t *ppos)
625{
626 struct ath10k *ar = file->private_data;
627 int ret, len, buf_len;
628 char *buf;
629
630 buf_len = 500;
631 buf = kmalloc(buf_len, GFP_KERNEL);
632 if (!buf)
633 return -ENOMEM;
634
635 spin_lock_bh(&ar->data_lock);
636
637 len = 0;
638 len += scnprintf(buf + len, buf_len - len,
639 "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
640 len += scnprintf(buf + len, buf_len - len,
641 "fw_warm_reset_counter\t\t%d\n",
642 ar->stats.fw_warm_reset_counter);
643 len += scnprintf(buf + len, buf_len - len,
644 "fw_cold_reset_counter\t\t%d\n",
645 ar->stats.fw_cold_reset_counter);
646
647 spin_unlock_bh(&ar->data_lock);
648
649 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
650
651 kfree(buf);
652
653 return ret;
654}
655
656static const struct file_operations fops_fw_reset_stats = {
657 .open = simple_open,
658 .read = ath10k_debug_fw_reset_stats_read,
659 .owner = THIS_MODULE,
660 .llseek = default_llseek,
661};
662
Ben Greeard5aebc72014-09-10 18:59:28 +0300663/* This is a clean assert crash in firmware. */
664static int ath10k_debug_fw_assert(struct ath10k *ar)
665{
666 struct wmi_vdev_install_key_cmd *cmd;
667 struct sk_buff *skb;
668
669 skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
670 if (!skb)
671 return -ENOMEM;
672
673 cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
674 memset(cmd, 0, sizeof(*cmd));
675
676 /* big enough number so that firmware asserts */
677 cmd->vdev_id = __cpu_to_le32(0x7ffe);
678
679 return ath10k_wmi_cmd_send(ar, skb,
680 ar->wmi.cmd->vdev_install_key_cmdid);
681}
682
Michal Kazior278c4a82013-07-22 14:08:51 +0200683static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
684 char __user *user_buf,
685 size_t count, loff_t *ppos)
686{
Kalle Valo75cb96d2014-09-14 12:50:44 +0300687 const char buf[] =
688 "To simulate firmware crash write one of the keywords to this file:\n"
689 "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
690 "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
Michal Kazior605cdba2014-10-28 10:34:37 +0100691 "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"
692 "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
Marek Puzyniak8c656992014-03-21 17:46:56 +0200693
Michal Kazior278c4a82013-07-22 14:08:51 +0200694 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
695}
696
Marek Puzyniak8c656992014-03-21 17:46:56 +0200697/* Simulate firmware crash:
698 * 'soft': Call wmi command causing firmware hang. This firmware hang is
699 * recoverable by warm firmware reset.
700 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
701 * vdev id. This is hard firmware crash because it is recoverable only by cold
702 * firmware reset.
703 */
Michal Kazior278c4a82013-07-22 14:08:51 +0200704static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
705 const char __user *user_buf,
706 size_t count, loff_t *ppos)
707{
708 struct ath10k *ar = file->private_data;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200709 char buf[32];
Michal Kazior278c4a82013-07-22 14:08:51 +0200710 int ret;
711
712 mutex_lock(&ar->conf_mutex);
713
714 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200715
716 /* make sure that buf is null terminated */
717 buf[sizeof(buf) - 1] = 0;
Michal Kazior278c4a82013-07-22 14:08:51 +0200718
719 if (ar->state != ATH10K_STATE_ON &&
720 ar->state != ATH10K_STATE_RESTARTED) {
721 ret = -ENETDOWN;
722 goto exit;
723 }
724
Marek Puzyniak8c656992014-03-21 17:46:56 +0200725 /* drop the possible '\n' from the end */
726 if (buf[count - 1] == '\n') {
727 buf[count - 1] = 0;
728 count--;
729 }
Michal Kazior278c4a82013-07-22 14:08:51 +0200730
Marek Puzyniak8c656992014-03-21 17:46:56 +0200731 if (!strcmp(buf, "soft")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200732 ath10k_info(ar, "simulating soft firmware crash\n");
Marek Puzyniak8c656992014-03-21 17:46:56 +0200733 ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
734 } else if (!strcmp(buf, "hard")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200735 ath10k_info(ar, "simulating hard firmware crash\n");
Ben Greear611b3682014-07-25 11:56:40 +0300736 /* 0x7fff is vdev id, and it is always out of range for all
737 * firmware variants in order to force a firmware crash.
738 */
739 ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
Kalle Valo5b07e072014-09-14 12:50:06 +0300740 ar->wmi.vdev_param->rts_threshold,
741 0);
Ben Greeard5aebc72014-09-10 18:59:28 +0300742 } else if (!strcmp(buf, "assert")) {
743 ath10k_info(ar, "simulating firmware assert crash\n");
744 ret = ath10k_debug_fw_assert(ar);
Michal Kazior605cdba2014-10-28 10:34:37 +0100745 } else if (!strcmp(buf, "hw-restart")) {
746 ath10k_info(ar, "user requested hw restart\n");
747 queue_work(ar->workqueue, &ar->restart_work);
748 ret = 0;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200749 } else {
750 ret = -EINVAL;
751 goto exit;
752 }
Michal Kazior278c4a82013-07-22 14:08:51 +0200753
Marek Puzyniak8c656992014-03-21 17:46:56 +0200754 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200755 ath10k_warn(ar, "failed to simulate firmware crash: %d\n", ret);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200756 goto exit;
757 }
758
759 ret = count;
Michal Kazior278c4a82013-07-22 14:08:51 +0200760
761exit:
762 mutex_unlock(&ar->conf_mutex);
763 return ret;
764}
765
766static const struct file_operations fops_simulate_fw_crash = {
767 .read = ath10k_read_simulate_fw_crash,
768 .write = ath10k_write_simulate_fw_crash,
769 .open = simple_open,
770 .owner = THIS_MODULE,
771 .llseek = default_llseek,
772};
773
Kalle Valo763b8cd2013-09-01 11:22:21 +0300774static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf,
775 size_t count, loff_t *ppos)
776{
777 struct ath10k *ar = file->private_data;
778 unsigned int len;
779 char buf[50];
780
781 len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id);
782
783 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
784}
785
786static const struct file_operations fops_chip_id = {
787 .read = ath10k_read_chip_id,
788 .open = simple_open,
789 .owner = THIS_MODULE,
790 .llseek = default_llseek,
791};
792
Ben Greear384914b2014-08-25 08:37:32 +0300793struct ath10k_fw_crash_data *
794ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
795{
796 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
797
798 lockdep_assert_held(&ar->data_lock);
799
800 crash_data->crashed_since_read = true;
801 uuid_le_gen(&crash_data->uuid);
802 getnstimeofday(&crash_data->timestamp);
803
804 return crash_data;
805}
806EXPORT_SYMBOL(ath10k_debug_get_new_fw_crash_data);
807
808static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
809{
810 struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
811 struct ath10k_dump_file_data *dump_data;
812 struct ath10k_tlv_dump_data *dump_tlv;
813 int hdr_len = sizeof(*dump_data);
814 unsigned int len, sofar = 0;
815 unsigned char *buf;
816
817 len = hdr_len;
818 len += sizeof(*dump_tlv) + sizeof(crash_data->registers);
819
820 sofar += hdr_len;
821
822 /* This is going to get big when we start dumping FW RAM and such,
823 * so go ahead and use vmalloc.
824 */
825 buf = vzalloc(len);
826 if (!buf)
827 return NULL;
828
829 spin_lock_bh(&ar->data_lock);
830
831 if (!crash_data->crashed_since_read) {
832 spin_unlock_bh(&ar->data_lock);
833 vfree(buf);
834 return NULL;
835 }
836
837 dump_data = (struct ath10k_dump_file_data *)(buf);
838 strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP",
839 sizeof(dump_data->df_magic));
840 dump_data->len = cpu_to_le32(len);
841
842 dump_data->version = cpu_to_le32(ATH10K_FW_CRASH_DUMP_VERSION);
843
844 memcpy(dump_data->uuid, &crash_data->uuid, sizeof(dump_data->uuid));
845 dump_data->chip_id = cpu_to_le32(ar->chip_id);
846 dump_data->bus_type = cpu_to_le32(0);
847 dump_data->target_version = cpu_to_le32(ar->target_version);
848 dump_data->fw_version_major = cpu_to_le32(ar->fw_version_major);
849 dump_data->fw_version_minor = cpu_to_le32(ar->fw_version_minor);
850 dump_data->fw_version_release = cpu_to_le32(ar->fw_version_release);
851 dump_data->fw_version_build = cpu_to_le32(ar->fw_version_build);
852 dump_data->phy_capability = cpu_to_le32(ar->phy_capability);
853 dump_data->hw_min_tx_power = cpu_to_le32(ar->hw_min_tx_power);
854 dump_data->hw_max_tx_power = cpu_to_le32(ar->hw_max_tx_power);
855 dump_data->ht_cap_info = cpu_to_le32(ar->ht_cap_info);
856 dump_data->vht_cap_info = cpu_to_le32(ar->vht_cap_info);
857 dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains);
858
859 strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
860 sizeof(dump_data->fw_ver));
861
Johannes Berg12c27152014-11-21 18:58:49 +0200862 dump_data->kernel_ver_code = 0;
863 strlcpy(dump_data->kernel_ver, init_utsname()->release,
Ben Greear384914b2014-08-25 08:37:32 +0300864 sizeof(dump_data->kernel_ver));
865
866 dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
867 dump_data->tv_nsec = cpu_to_le64(crash_data->timestamp.tv_nsec);
868
869 /* Gather crash-dump */
870 dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
871 dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_REGISTERS);
872 dump_tlv->tlv_len = cpu_to_le32(sizeof(crash_data->registers));
873 memcpy(dump_tlv->tlv_data, &crash_data->registers,
874 sizeof(crash_data->registers));
875 sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers);
876
877 ar->debug.fw_crash_data->crashed_since_read = false;
878
879 spin_unlock_bh(&ar->data_lock);
880
881 return dump_data;
882}
883
884static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file)
885{
886 struct ath10k *ar = inode->i_private;
887 struct ath10k_dump_file_data *dump;
888
889 dump = ath10k_build_dump_file(ar);
890 if (!dump)
891 return -ENODATA;
892
893 file->private_data = dump;
894
895 return 0;
896}
897
898static ssize_t ath10k_fw_crash_dump_read(struct file *file,
899 char __user *user_buf,
900 size_t count, loff_t *ppos)
901{
902 struct ath10k_dump_file_data *dump_file = file->private_data;
903
904 return simple_read_from_buffer(user_buf, count, ppos,
905 dump_file,
906 le32_to_cpu(dump_file->len));
907}
908
909static int ath10k_fw_crash_dump_release(struct inode *inode,
910 struct file *file)
911{
912 vfree(file->private_data);
913
914 return 0;
915}
916
917static const struct file_operations fops_fw_crash_dump = {
918 .open = ath10k_fw_crash_dump_open,
919 .read = ath10k_fw_crash_dump_read,
920 .release = ath10k_fw_crash_dump_release,
921 .owner = THIS_MODULE,
922 .llseek = default_llseek,
923};
924
Yanbo Li077a3802014-11-25 12:24:33 +0200925static ssize_t ath10k_reg_addr_read(struct file *file,
926 char __user *user_buf,
927 size_t count, loff_t *ppos)
928{
929 struct ath10k *ar = file->private_data;
930 u8 buf[32];
931 unsigned int len = 0;
932 u32 reg_addr;
933
934 mutex_lock(&ar->conf_mutex);
935 reg_addr = ar->debug.reg_addr;
936 mutex_unlock(&ar->conf_mutex);
937
938 len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);
939
940 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
941}
942
943static ssize_t ath10k_reg_addr_write(struct file *file,
944 const char __user *user_buf,
945 size_t count, loff_t *ppos)
946{
947 struct ath10k *ar = file->private_data;
948 u32 reg_addr;
949 int ret;
950
951 ret = kstrtou32_from_user(user_buf, count, 0, &reg_addr);
952 if (ret)
953 return ret;
954
955 if (!IS_ALIGNED(reg_addr, 4))
956 return -EFAULT;
957
958 mutex_lock(&ar->conf_mutex);
959 ar->debug.reg_addr = reg_addr;
960 mutex_unlock(&ar->conf_mutex);
961
962 return count;
963}
964
965static const struct file_operations fops_reg_addr = {
966 .read = ath10k_reg_addr_read,
967 .write = ath10k_reg_addr_write,
968 .open = simple_open,
969 .owner = THIS_MODULE,
970 .llseek = default_llseek,
971};
972
973static ssize_t ath10k_reg_value_read(struct file *file,
974 char __user *user_buf,
975 size_t count, loff_t *ppos)
976{
977 struct ath10k *ar = file->private_data;
978 u8 buf[48];
979 unsigned int len;
980 u32 reg_addr, reg_val;
981 int ret;
982
983 mutex_lock(&ar->conf_mutex);
984
985 if (ar->state != ATH10K_STATE_ON &&
986 ar->state != ATH10K_STATE_UTF) {
987 ret = -ENETDOWN;
988 goto exit;
989 }
990
991 reg_addr = ar->debug.reg_addr;
992
993 reg_val = ath10k_hif_read32(ar, reg_addr);
994 len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);
995
996 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
997
998exit:
999 mutex_unlock(&ar->conf_mutex);
1000
1001 return ret;
1002}
1003
1004static ssize_t ath10k_reg_value_write(struct file *file,
1005 const char __user *user_buf,
1006 size_t count, loff_t *ppos)
1007{
1008 struct ath10k *ar = file->private_data;
1009 u32 reg_addr, reg_val;
1010 int ret;
1011
1012 mutex_lock(&ar->conf_mutex);
1013
1014 if (ar->state != ATH10K_STATE_ON &&
1015 ar->state != ATH10K_STATE_UTF) {
1016 ret = -ENETDOWN;
1017 goto exit;
1018 }
1019
1020 reg_addr = ar->debug.reg_addr;
1021
1022 ret = kstrtou32_from_user(user_buf, count, 0, &reg_val);
1023 if (ret)
1024 goto exit;
1025
1026 ath10k_hif_write32(ar, reg_addr, reg_val);
1027
1028 ret = count;
1029
1030exit:
1031 mutex_unlock(&ar->conf_mutex);
1032
1033 return ret;
1034}
1035
1036static const struct file_operations fops_reg_value = {
1037 .read = ath10k_reg_value_read,
1038 .write = ath10k_reg_value_write,
1039 .open = simple_open,
1040 .owner = THIS_MODULE,
1041 .llseek = default_llseek,
1042};
1043
Yanbo Li9f65ad22014-11-25 12:24:48 +02001044static ssize_t ath10k_mem_value_read(struct file *file,
1045 char __user *user_buf,
1046 size_t count, loff_t *ppos)
1047{
1048 struct ath10k *ar = file->private_data;
1049 u8 *buf;
1050 int ret;
1051
1052 if (*ppos < 0)
1053 return -EINVAL;
1054
1055 if (!count)
1056 return 0;
1057
1058 mutex_lock(&ar->conf_mutex);
1059
1060 buf = vmalloc(count);
1061 if (!buf) {
1062 ret = -ENOMEM;
1063 goto exit;
1064 }
1065
1066 if (ar->state != ATH10K_STATE_ON &&
1067 ar->state != ATH10K_STATE_UTF) {
1068 ret = -ENETDOWN;
1069 goto exit;
1070 }
1071
1072 ret = ath10k_hif_diag_read(ar, *ppos, buf, count);
1073 if (ret) {
1074 ath10k_warn(ar, "failed to read address 0x%08x via diagnose window fnrom debugfs: %d\n",
1075 (u32)(*ppos), ret);
1076 goto exit;
1077 }
1078
1079 ret = copy_to_user(user_buf, buf, count);
1080 if (ret) {
1081 ret = -EFAULT;
1082 goto exit;
1083 }
1084
1085 count -= ret;
1086 *ppos += count;
1087 ret = count;
1088
1089exit:
1090 vfree(buf);
1091 mutex_unlock(&ar->conf_mutex);
1092
1093 return ret;
1094}
1095
1096static ssize_t ath10k_mem_value_write(struct file *file,
1097 const char __user *user_buf,
1098 size_t count, loff_t *ppos)
1099{
1100 struct ath10k *ar = file->private_data;
1101 u8 *buf;
1102 int ret;
1103
1104 if (*ppos < 0)
1105 return -EINVAL;
1106
1107 if (!count)
1108 return 0;
1109
1110 mutex_lock(&ar->conf_mutex);
1111
1112 buf = vmalloc(count);
1113 if (!buf) {
1114 ret = -ENOMEM;
1115 goto exit;
1116 }
1117
1118 if (ar->state != ATH10K_STATE_ON &&
1119 ar->state != ATH10K_STATE_UTF) {
1120 ret = -ENETDOWN;
1121 goto exit;
1122 }
1123
1124 ret = copy_from_user(buf, user_buf, count);
1125 if (ret) {
1126 ret = -EFAULT;
1127 goto exit;
1128 }
1129
1130 ret = ath10k_hif_diag_write(ar, *ppos, buf, count);
1131 if (ret) {
1132 ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",
1133 (u32)(*ppos), ret);
1134 goto exit;
1135 }
1136
1137 *ppos += count;
1138 ret = count;
1139
1140exit:
1141 vfree(buf);
1142 mutex_unlock(&ar->conf_mutex);
1143
1144 return ret;
1145}
1146
1147static const struct file_operations fops_mem_value = {
1148 .read = ath10k_mem_value_read,
1149 .write = ath10k_mem_value_write,
1150 .open = simple_open,
1151 .owner = THIS_MODULE,
1152 .llseek = default_llseek,
1153};
1154
Kalle Valoa3d135e2013-09-03 11:44:10 +03001155static int ath10k_debug_htt_stats_req(struct ath10k *ar)
1156{
1157 u64 cookie;
1158 int ret;
1159
1160 lockdep_assert_held(&ar->conf_mutex);
1161
1162 if (ar->debug.htt_stats_mask == 0)
1163 /* htt stats are disabled */
1164 return 0;
1165
1166 if (ar->state != ATH10K_STATE_ON)
1167 return 0;
1168
1169 cookie = get_jiffies_64();
1170
1171 ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask,
1172 cookie);
1173 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001174 ath10k_warn(ar, "failed to send htt stats request: %d\n", ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001175 return ret;
1176 }
1177
1178 queue_delayed_work(ar->workqueue, &ar->debug.htt_stats_dwork,
1179 msecs_to_jiffies(ATH10K_DEBUG_HTT_STATS_INTERVAL));
1180
1181 return 0;
1182}
1183
1184static void ath10k_debug_htt_stats_dwork(struct work_struct *work)
1185{
1186 struct ath10k *ar = container_of(work, struct ath10k,
1187 debug.htt_stats_dwork.work);
1188
1189 mutex_lock(&ar->conf_mutex);
1190
1191 ath10k_debug_htt_stats_req(ar);
1192
1193 mutex_unlock(&ar->conf_mutex);
1194}
1195
1196static ssize_t ath10k_read_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001197 char __user *user_buf,
1198 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001199{
1200 struct ath10k *ar = file->private_data;
1201 char buf[32];
1202 unsigned int len;
1203
1204 len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask);
1205
1206 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1207}
1208
1209static ssize_t ath10k_write_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001210 const char __user *user_buf,
1211 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +03001212{
1213 struct ath10k *ar = file->private_data;
1214 unsigned long mask;
1215 int ret;
1216
1217 ret = kstrtoul_from_user(user_buf, count, 0, &mask);
1218 if (ret)
1219 return ret;
1220
1221 /* max 8 bit masks (for now) */
1222 if (mask > 0xff)
1223 return -E2BIG;
1224
1225 mutex_lock(&ar->conf_mutex);
1226
1227 ar->debug.htt_stats_mask = mask;
1228
1229 ret = ath10k_debug_htt_stats_req(ar);
1230 if (ret)
1231 goto out;
1232
1233 ret = count;
1234
1235out:
1236 mutex_unlock(&ar->conf_mutex);
1237
1238 return ret;
1239}
1240
1241static const struct file_operations fops_htt_stats_mask = {
1242 .read = ath10k_read_htt_stats_mask,
1243 .write = ath10k_write_htt_stats_mask,
1244 .open = simple_open,
1245 .owner = THIS_MODULE,
1246 .llseek = default_llseek,
1247};
1248
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001249static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
1250 char __user *user_buf,
1251 size_t count, loff_t *ppos)
1252{
1253 struct ath10k *ar = file->private_data;
1254 char buf[64];
1255 u8 amsdu = 3, ampdu = 64;
1256 unsigned int len;
1257
1258 mutex_lock(&ar->conf_mutex);
1259
1260 if (ar->debug.htt_max_amsdu)
1261 amsdu = ar->debug.htt_max_amsdu;
1262
1263 if (ar->debug.htt_max_ampdu)
1264 ampdu = ar->debug.htt_max_ampdu;
1265
1266 mutex_unlock(&ar->conf_mutex);
1267
1268 len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
1269
1270 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1271}
1272
1273static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
1274 const char __user *user_buf,
1275 size_t count, loff_t *ppos)
1276{
1277 struct ath10k *ar = file->private_data;
1278 int res;
1279 char buf[64];
1280 unsigned int amsdu, ampdu;
1281
1282 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
1283
1284 /* make sure that buf is null terminated */
1285 buf[sizeof(buf) - 1] = 0;
1286
1287 res = sscanf(buf, "%u %u", &amsdu, &ampdu);
1288
1289 if (res != 2)
1290 return -EINVAL;
1291
1292 mutex_lock(&ar->conf_mutex);
1293
1294 res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
1295 if (res)
1296 goto out;
1297
1298 res = count;
1299 ar->debug.htt_max_amsdu = amsdu;
1300 ar->debug.htt_max_ampdu = ampdu;
1301
1302out:
1303 mutex_unlock(&ar->conf_mutex);
1304 return res;
1305}
1306
1307static const struct file_operations fops_htt_max_amsdu_ampdu = {
1308 .read = ath10k_read_htt_max_amsdu_ampdu,
1309 .write = ath10k_write_htt_max_amsdu_ampdu,
1310 .open = simple_open,
1311 .owner = THIS_MODULE,
1312 .llseek = default_llseek,
1313};
1314
Kalle Valof118a3e2014-01-03 12:59:31 +02001315static ssize_t ath10k_read_fw_dbglog(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001316 char __user *user_buf,
1317 size_t count, loff_t *ppos)
Kalle Valof118a3e2014-01-03 12:59:31 +02001318{
1319 struct ath10k *ar = file->private_data;
1320 unsigned int len;
1321 char buf[32];
1322
1323 len = scnprintf(buf, sizeof(buf), "0x%08x\n",
1324 ar->debug.fw_dbglog_mask);
1325
1326 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1327}
1328
1329static ssize_t ath10k_write_fw_dbglog(struct file *file,
1330 const char __user *user_buf,
1331 size_t count, loff_t *ppos)
1332{
1333 struct ath10k *ar = file->private_data;
1334 unsigned long mask;
1335 int ret;
1336
1337 ret = kstrtoul_from_user(user_buf, count, 0, &mask);
1338 if (ret)
1339 return ret;
1340
1341 mutex_lock(&ar->conf_mutex);
1342
1343 ar->debug.fw_dbglog_mask = mask;
1344
1345 if (ar->state == ATH10K_STATE_ON) {
1346 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask);
1347 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001348 ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n",
Kalle Valof118a3e2014-01-03 12:59:31 +02001349 ret);
1350 goto exit;
1351 }
1352 }
1353
1354 ret = count;
1355
1356exit:
1357 mutex_unlock(&ar->conf_mutex);
1358
1359 return ret;
1360}
1361
Ben Greear6cddcc72014-09-29 14:41:46 +03001362/* TODO: Would be nice to always support ethtool stats, would need to
1363 * move the stats storage out of ath10k_debug, or always have ath10k_debug
1364 * struct available..
1365 */
1366
1367/* This generally cooresponds to the debugfs fw_stats file */
1368static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
1369 "tx_pkts_nic",
1370 "tx_bytes_nic",
1371 "rx_pkts_nic",
1372 "rx_bytes_nic",
1373 "d_noise_floor",
1374 "d_cycle_count",
1375 "d_phy_error",
1376 "d_rts_bad",
1377 "d_rts_good",
1378 "d_tx_power", /* in .5 dbM I think */
1379 "d_rx_crc_err", /* fcs_bad */
1380 "d_no_beacon",
1381 "d_tx_mpdus_queued",
1382 "d_tx_msdu_queued",
1383 "d_tx_msdu_dropped",
1384 "d_local_enqued",
1385 "d_local_freed",
1386 "d_tx_ppdu_hw_queued",
1387 "d_tx_ppdu_reaped",
1388 "d_tx_fifo_underrun",
1389 "d_tx_ppdu_abort",
1390 "d_tx_mpdu_requed",
1391 "d_tx_excessive_retries",
1392 "d_tx_hw_rate",
1393 "d_tx_dropped_sw_retries",
1394 "d_tx_illegal_rate",
1395 "d_tx_continuous_xretries",
1396 "d_tx_timeout",
1397 "d_tx_mpdu_txop_limit",
1398 "d_pdev_resets",
1399 "d_rx_mid_ppdu_route_change",
1400 "d_rx_status",
1401 "d_rx_extra_frags_ring0",
1402 "d_rx_extra_frags_ring1",
1403 "d_rx_extra_frags_ring2",
1404 "d_rx_extra_frags_ring3",
1405 "d_rx_msdu_htt",
1406 "d_rx_mpdu_htt",
1407 "d_rx_msdu_stack",
1408 "d_rx_mpdu_stack",
1409 "d_rx_phy_err",
1410 "d_rx_phy_err_drops",
1411 "d_rx_mpdu_errors", /* FCS, MIC, ENC */
1412 "d_fw_crash_count",
1413 "d_fw_warm_reset_count",
1414 "d_fw_cold_reset_count",
1415};
1416
1417#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
1418
1419void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
1420 struct ieee80211_vif *vif,
1421 u32 sset, u8 *data)
1422{
1423 if (sset == ETH_SS_STATS)
1424 memcpy(data, *ath10k_gstrings_stats,
1425 sizeof(ath10k_gstrings_stats));
1426}
1427
1428int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
1429 struct ieee80211_vif *vif, int sset)
1430{
1431 if (sset == ETH_SS_STATS)
1432 return ATH10K_SSTATS_LEN;
1433
1434 return 0;
1435}
1436
1437void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
1438 struct ieee80211_vif *vif,
1439 struct ethtool_stats *stats, u64 *data)
1440{
1441 struct ath10k *ar = hw->priv;
1442 static const struct ath10k_fw_stats_pdev zero_stats = {};
1443 const struct ath10k_fw_stats_pdev *pdev_stats;
1444 int i = 0, ret;
1445
1446 mutex_lock(&ar->conf_mutex);
1447
1448 if (ar->state == ATH10K_STATE_ON) {
1449 ret = ath10k_debug_fw_stats_request(ar);
1450 if (ret) {
1451 /* just print a warning and try to use older results */
1452 ath10k_warn(ar,
1453 "failed to get fw stats for ethtool: %d\n",
1454 ret);
1455 }
1456 }
1457
1458 pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,
1459 struct ath10k_fw_stats_pdev,
1460 list);
1461 if (!pdev_stats) {
1462 /* no results available so just return zeroes */
1463 pdev_stats = &zero_stats;
1464 }
1465
1466 spin_lock_bh(&ar->data_lock);
1467
1468 data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
1469 data[i++] = 0; /* tx bytes */
1470 data[i++] = pdev_stats->htt_mpdus;
1471 data[i++] = 0; /* rx bytes */
1472 data[i++] = pdev_stats->ch_noise_floor;
1473 data[i++] = pdev_stats->cycle_count;
1474 data[i++] = pdev_stats->phy_err_count;
1475 data[i++] = pdev_stats->rts_bad;
1476 data[i++] = pdev_stats->rts_good;
1477 data[i++] = pdev_stats->chan_tx_power;
1478 data[i++] = pdev_stats->fcs_bad;
1479 data[i++] = pdev_stats->no_beacons;
1480 data[i++] = pdev_stats->mpdu_enqued;
1481 data[i++] = pdev_stats->msdu_enqued;
1482 data[i++] = pdev_stats->wmm_drop;
1483 data[i++] = pdev_stats->local_enqued;
1484 data[i++] = pdev_stats->local_freed;
1485 data[i++] = pdev_stats->hw_queued;
1486 data[i++] = pdev_stats->hw_reaped;
1487 data[i++] = pdev_stats->underrun;
1488 data[i++] = pdev_stats->tx_abort;
1489 data[i++] = pdev_stats->mpdus_requed;
1490 data[i++] = pdev_stats->tx_ko;
1491 data[i++] = pdev_stats->data_rc;
1492 data[i++] = pdev_stats->sw_retry_failure;
1493 data[i++] = pdev_stats->illgl_rate_phy_err;
1494 data[i++] = pdev_stats->pdev_cont_xretry;
1495 data[i++] = pdev_stats->pdev_tx_timeout;
1496 data[i++] = pdev_stats->txop_ovf;
1497 data[i++] = pdev_stats->pdev_resets;
1498 data[i++] = pdev_stats->mid_ppdu_route_change;
1499 data[i++] = pdev_stats->status_rcvd;
1500 data[i++] = pdev_stats->r0_frags;
1501 data[i++] = pdev_stats->r1_frags;
1502 data[i++] = pdev_stats->r2_frags;
1503 data[i++] = pdev_stats->r3_frags;
1504 data[i++] = pdev_stats->htt_msdus;
1505 data[i++] = pdev_stats->htt_mpdus;
1506 data[i++] = pdev_stats->loc_msdus;
1507 data[i++] = pdev_stats->loc_mpdus;
1508 data[i++] = pdev_stats->phy_errs;
1509 data[i++] = pdev_stats->phy_err_drop;
1510 data[i++] = pdev_stats->mpdu_errs;
1511 data[i++] = ar->stats.fw_crash_counter;
1512 data[i++] = ar->stats.fw_warm_reset_counter;
1513 data[i++] = ar->stats.fw_cold_reset_counter;
1514
1515 spin_unlock_bh(&ar->data_lock);
1516
1517 mutex_unlock(&ar->conf_mutex);
1518
1519 WARN_ON(i != ATH10K_SSTATS_LEN);
1520}
1521
Kalle Valof118a3e2014-01-03 12:59:31 +02001522static const struct file_operations fops_fw_dbglog = {
1523 .read = ath10k_read_fw_dbglog,
1524 .write = ath10k_write_fw_dbglog,
1525 .open = simple_open,
1526 .owner = THIS_MODULE,
1527 .llseek = default_llseek,
1528};
1529
Kalle Valo7869b4f2014-09-24 14:16:58 +03001530static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
1531{
1532 struct ath10k *ar = inode->i_private;
1533 void *buf;
1534 u32 hi_addr;
1535 __le32 addr;
1536 int ret;
1537
1538 mutex_lock(&ar->conf_mutex);
1539
1540 if (ar->state != ATH10K_STATE_ON &&
1541 ar->state != ATH10K_STATE_UTF) {
1542 ret = -ENETDOWN;
1543 goto err;
1544 }
1545
1546 buf = vmalloc(QCA988X_CAL_DATA_LEN);
1547 if (!buf) {
1548 ret = -ENOMEM;
1549 goto err;
1550 }
1551
1552 hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
1553
1554 ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
1555 if (ret) {
1556 ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret);
1557 goto err_vfree;
1558 }
1559
1560 ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
1561 QCA988X_CAL_DATA_LEN);
1562 if (ret) {
1563 ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
1564 goto err_vfree;
1565 }
1566
1567 file->private_data = buf;
1568
1569 mutex_unlock(&ar->conf_mutex);
1570
1571 return 0;
1572
1573err_vfree:
1574 vfree(buf);
1575
1576err:
1577 mutex_unlock(&ar->conf_mutex);
1578
1579 return ret;
1580}
1581
1582static ssize_t ath10k_debug_cal_data_read(struct file *file,
1583 char __user *user_buf,
1584 size_t count, loff_t *ppos)
1585{
1586 void *buf = file->private_data;
1587
1588 return simple_read_from_buffer(user_buf, count, ppos,
1589 buf, QCA988X_CAL_DATA_LEN);
1590}
1591
1592static int ath10k_debug_cal_data_release(struct inode *inode,
1593 struct file *file)
1594{
1595 vfree(file->private_data);
1596
1597 return 0;
1598}
1599
1600static const struct file_operations fops_cal_data = {
1601 .open = ath10k_debug_cal_data_open,
1602 .read = ath10k_debug_cal_data_read,
1603 .release = ath10k_debug_cal_data_release,
1604 .owner = THIS_MODULE,
1605 .llseek = default_llseek,
1606};
1607
Peter Oha7bd3e92014-12-02 13:07:14 +02001608static ssize_t ath10k_read_nf_cal_period(struct file *file,
1609 char __user *user_buf,
1610 size_t count, loff_t *ppos)
1611{
1612 struct ath10k *ar = file->private_data;
1613 unsigned int len;
1614 char buf[32];
1615
1616 len = scnprintf(buf, sizeof(buf), "%d\n",
1617 ar->debug.nf_cal_period);
1618
1619 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1620}
1621
1622static ssize_t ath10k_write_nf_cal_period(struct file *file,
1623 const char __user *user_buf,
1624 size_t count, loff_t *ppos)
1625{
1626 struct ath10k *ar = file->private_data;
1627 unsigned long period;
1628 int ret;
1629
1630 ret = kstrtoul_from_user(user_buf, count, 0, &period);
1631 if (ret)
1632 return ret;
1633
1634 if (period > WMI_PDEV_PARAM_CAL_PERIOD_MAX)
1635 return -EINVAL;
1636
1637 /* there's no way to switch back to the firmware default */
1638 if (period == 0)
1639 return -EINVAL;
1640
1641 mutex_lock(&ar->conf_mutex);
1642
1643 ar->debug.nf_cal_period = period;
1644
1645 if (ar->state != ATH10K_STATE_ON) {
1646 /* firmware is not running, nothing else to do */
1647 ret = count;
1648 goto exit;
1649 }
1650
1651 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->cal_period,
1652 ar->debug.nf_cal_period);
1653 if (ret) {
1654 ath10k_warn(ar, "cal period cfg failed from debugfs: %d\n",
1655 ret);
1656 goto exit;
1657 }
1658
1659 ret = count;
1660
1661exit:
1662 mutex_unlock(&ar->conf_mutex);
1663
1664 return ret;
1665}
1666
1667static const struct file_operations fops_nf_cal_period = {
1668 .read = ath10k_read_nf_cal_period,
1669 .write = ath10k_write_nf_cal_period,
1670 .open = simple_open,
1671 .owner = THIS_MODULE,
1672 .llseek = default_llseek,
1673};
1674
Kalle Valodb66ea02013-09-03 11:44:03 +03001675int ath10k_debug_start(struct ath10k *ar)
1676{
Kalle Valoa3d135e2013-09-03 11:44:10 +03001677 int ret;
1678
Kalle Valo60631c52013-10-08 21:45:25 +03001679 lockdep_assert_held(&ar->conf_mutex);
1680
Kalle Valoa3d135e2013-09-03 11:44:10 +03001681 ret = ath10k_debug_htt_stats_req(ar);
1682 if (ret)
1683 /* continue normally anyway, this isn't serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001684 ath10k_warn(ar, "failed to start htt stats workqueue: %d\n",
1685 ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001686
Kalle Valof118a3e2014-01-03 12:59:31 +02001687 if (ar->debug.fw_dbglog_mask) {
1688 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask);
1689 if (ret)
1690 /* not serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001691 ath10k_warn(ar, "failed to enable dbglog during start: %d",
Kalle Valof118a3e2014-01-03 12:59:31 +02001692 ret);
1693 }
1694
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001695 if (ar->debug.pktlog_filter) {
1696 ret = ath10k_wmi_pdev_pktlog_enable(ar,
1697 ar->debug.pktlog_filter);
1698 if (ret)
1699 /* not serious */
1700 ath10k_warn(ar,
1701 "failed to enable pktlog filter %x: %d\n",
1702 ar->debug.pktlog_filter, ret);
1703 } else {
1704 ret = ath10k_wmi_pdev_pktlog_disable(ar);
1705 if (ret)
1706 /* not serious */
1707 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
1708 }
1709
Peter Oha7bd3e92014-12-02 13:07:14 +02001710 if (ar->debug.nf_cal_period) {
1711 ret = ath10k_wmi_pdev_set_param(ar,
1712 ar->wmi.pdev_param->cal_period,
1713 ar->debug.nf_cal_period);
1714 if (ret)
1715 /* not serious */
1716 ath10k_warn(ar, "cal period cfg failed from debug start: %d\n",
1717 ret);
1718 }
1719
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001720 return ret;
Kalle Valodb66ea02013-09-03 11:44:03 +03001721}
1722
1723void ath10k_debug_stop(struct ath10k *ar)
1724{
Kalle Valo60631c52013-10-08 21:45:25 +03001725 lockdep_assert_held(&ar->conf_mutex);
1726
1727 /* Must not use _sync to avoid deadlock, we do that in
1728 * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid
1729 * warning from del_timer(). */
1730 if (ar->debug.htt_stats_mask != 0)
1731 cancel_delayed_work(&ar->debug.htt_stats_dwork);
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001732
1733 ar->debug.htt_max_amsdu = 0;
1734 ar->debug.htt_max_ampdu = 0;
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001735
1736 ath10k_wmi_pdev_pktlog_disable(ar);
Kalle Valodb66ea02013-09-03 11:44:03 +03001737}
1738
Janusz Dziedzic9702c682013-11-20 09:59:41 +02001739static ssize_t ath10k_write_simulate_radar(struct file *file,
1740 const char __user *user_buf,
1741 size_t count, loff_t *ppos)
1742{
1743 struct ath10k *ar = file->private_data;
1744
1745 ieee80211_radar_detected(ar->hw);
1746
1747 return count;
1748}
1749
1750static const struct file_operations fops_simulate_radar = {
1751 .write = ath10k_write_simulate_radar,
1752 .open = simple_open,
1753 .owner = THIS_MODULE,
1754 .llseek = default_llseek,
1755};
1756
1757#define ATH10K_DFS_STAT(s, p) (\
1758 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
1759 ar->debug.dfs_stats.p))
1760
1761#define ATH10K_DFS_POOL_STAT(s, p) (\
1762 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
1763 ar->debug.dfs_pool_stats.p))
1764
1765static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf,
1766 size_t count, loff_t *ppos)
1767{
1768 int retval = 0, len = 0;
1769 const int size = 8000;
1770 struct ath10k *ar = file->private_data;
1771 char *buf;
1772
1773 buf = kzalloc(size, GFP_KERNEL);
1774 if (buf == NULL)
1775 return -ENOMEM;
1776
1777 if (!ar->dfs_detector) {
1778 len += scnprintf(buf + len, size - len, "DFS not enabled\n");
1779 goto exit;
1780 }
1781
1782 ar->debug.dfs_pool_stats =
1783 ar->dfs_detector->get_stats(ar->dfs_detector);
1784
1785 len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");
1786
1787 ATH10K_DFS_STAT("reported phy errors", phy_errors);
1788 ATH10K_DFS_STAT("pulse events reported", pulses_total);
1789 ATH10K_DFS_STAT("DFS pulses detected", pulses_detected);
1790 ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded);
1791 ATH10K_DFS_STAT("Radars detected", radar_detected);
1792
1793 len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");
1794 ATH10K_DFS_POOL_STAT("Pool references", pool_reference);
1795 ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated);
1796 ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error);
1797 ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used);
1798 ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated);
1799 ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error);
1800 ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used);
1801
1802exit:
1803 if (len > size)
1804 len = size;
1805
1806 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1807 kfree(buf);
1808
1809 return retval;
1810}
1811
1812static const struct file_operations fops_dfs_stats = {
1813 .read = ath10k_read_dfs_stats,
1814 .open = simple_open,
1815 .owner = THIS_MODULE,
1816 .llseek = default_llseek,
1817};
1818
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001819static ssize_t ath10k_write_pktlog_filter(struct file *file,
1820 const char __user *ubuf,
1821 size_t count, loff_t *ppos)
1822{
1823 struct ath10k *ar = file->private_data;
1824 u32 filter;
1825 int ret;
1826
1827 if (kstrtouint_from_user(ubuf, count, 0, &filter))
1828 return -EINVAL;
1829
1830 mutex_lock(&ar->conf_mutex);
1831
1832 if (ar->state != ATH10K_STATE_ON) {
1833 ar->debug.pktlog_filter = filter;
1834 ret = count;
1835 goto out;
1836 }
1837
1838 if (filter && (filter != ar->debug.pktlog_filter)) {
1839 ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
1840 if (ret) {
1841 ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
1842 ar->debug.pktlog_filter, ret);
1843 goto out;
1844 }
1845 } else {
1846 ret = ath10k_wmi_pdev_pktlog_disable(ar);
1847 if (ret) {
1848 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
1849 goto out;
1850 }
1851 }
1852
1853 ar->debug.pktlog_filter = filter;
1854 ret = count;
1855
1856out:
1857 mutex_unlock(&ar->conf_mutex);
1858 return ret;
1859}
1860
1861static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf,
1862 size_t count, loff_t *ppos)
1863{
1864 char buf[32];
1865 struct ath10k *ar = file->private_data;
1866 int len = 0;
1867
1868 mutex_lock(&ar->conf_mutex);
1869 len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
1870 ar->debug.pktlog_filter);
1871 mutex_unlock(&ar->conf_mutex);
1872
1873 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1874}
1875
1876static const struct file_operations fops_pktlog_filter = {
1877 .read = ath10k_read_pktlog_filter,
1878 .write = ath10k_write_pktlog_filter,
1879 .open = simple_open
1880};
1881
Kalle Valo5e3dd152013-06-12 20:52:10 +03001882int ath10k_debug_create(struct ath10k *ar)
1883{
Ben Greear384914b2014-08-25 08:37:32 +03001884 ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
Michal Kaziore13cf7a2014-09-04 09:13:08 +02001885 if (!ar->debug.fw_crash_data)
1886 return -ENOMEM;
Ben Greear384914b2014-08-25 08:37:32 +03001887
Michal Kazior53268492014-09-25 12:33:50 +02001888 INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
1889 INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
1890
Michal Kaziore13cf7a2014-09-04 09:13:08 +02001891 return 0;
1892}
1893
1894void ath10k_debug_destroy(struct ath10k *ar)
1895{
1896 vfree(ar->debug.fw_crash_data);
1897 ar->debug.fw_crash_data = NULL;
Michal Kazior53268492014-09-25 12:33:50 +02001898
1899 ath10k_debug_fw_stats_reset(ar);
Michal Kaziore13cf7a2014-09-04 09:13:08 +02001900}
1901
1902int ath10k_debug_register(struct ath10k *ar)
1903{
Kalle Valo5e3dd152013-06-12 20:52:10 +03001904 ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
1905 ar->hw->wiphy->debugfsdir);
Michal Kazioradb43b22014-09-04 12:36:45 +02001906 if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
1907 if (IS_ERR(ar->debug.debugfs_phy))
1908 return PTR_ERR(ar->debug.debugfs_phy);
Kalle Valod8bb26b2014-09-14 12:50:33 +03001909
1910 return -ENOMEM;
Michal Kazioradb43b22014-09-04 12:36:45 +02001911 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03001912
Kalle Valoa3d135e2013-09-03 11:44:10 +03001913 INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
1914 ath10k_debug_htt_stats_dwork);
1915
Michal Kazior60ef4012014-09-25 12:33:48 +02001916 init_completion(&ar->debug.fw_stats_complete);
Kalle Valo5e3dd152013-06-12 20:52:10 +03001917
1918 debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
1919 &fops_fw_stats);
1920
Ben Greearf51dbe72014-09-29 14:41:46 +03001921 debugfs_create_file("fw_reset_stats", S_IRUSR, ar->debug.debugfs_phy,
1922 ar, &fops_fw_reset_stats);
1923
Kalle Valo5e3dd152013-06-12 20:52:10 +03001924 debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
1925 &fops_wmi_services);
1926
Michal Kazior278c4a82013-07-22 14:08:51 +02001927 debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
1928 ar, &fops_simulate_fw_crash);
1929
Ben Greear384914b2014-08-25 08:37:32 +03001930 debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
1931 ar, &fops_fw_crash_dump);
1932
Yanbo Li077a3802014-11-25 12:24:33 +02001933 debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR,
1934 ar->debug.debugfs_phy, ar, &fops_reg_addr);
1935
1936 debugfs_create_file("reg_value", S_IRUSR | S_IWUSR,
1937 ar->debug.debugfs_phy, ar, &fops_reg_value);
1938
Yanbo Li9f65ad22014-11-25 12:24:48 +02001939 debugfs_create_file("mem_value", S_IRUSR | S_IWUSR,
1940 ar->debug.debugfs_phy, ar, &fops_mem_value);
1941
Kalle Valo763b8cd2013-09-01 11:22:21 +03001942 debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
1943 ar, &fops_chip_id);
1944
Kalle Valoa3d135e2013-09-03 11:44:10 +03001945 debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
1946 ar, &fops_htt_stats_mask);
1947
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001948 debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
1949 ar->debug.debugfs_phy, ar,
1950 &fops_htt_max_amsdu_ampdu);
1951
Kalle Valof118a3e2014-01-03 12:59:31 +02001952 debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
1953 ar, &fops_fw_dbglog);
1954
Kalle Valo7869b4f2014-09-24 14:16:58 +03001955 debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
1956 ar, &fops_cal_data);
1957
Peter Oha7bd3e92014-12-02 13:07:14 +02001958 debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR,
1959 ar->debug.debugfs_phy, ar, &fops_nf_cal_period);
1960
Janusz Dziedzic9702c682013-11-20 09:59:41 +02001961 if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
1962 debugfs_create_file("dfs_simulate_radar", S_IWUSR,
1963 ar->debug.debugfs_phy, ar,
1964 &fops_simulate_radar);
1965
Marek Puzyniak7d9b40b2013-11-20 10:00:28 +02001966 debugfs_create_bool("dfs_block_radar_events", S_IWUSR,
1967 ar->debug.debugfs_phy,
1968 &ar->dfs_block_radar_events);
1969
Janusz Dziedzic9702c682013-11-20 09:59:41 +02001970 debugfs_create_file("dfs_stats", S_IRUSR,
1971 ar->debug.debugfs_phy, ar,
1972 &fops_dfs_stats);
1973 }
1974
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001975 debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR,
1976 ar->debug.debugfs_phy, ar, &fops_pktlog_filter);
1977
Kalle Valo5e3dd152013-06-12 20:52:10 +03001978 return 0;
1979}
Kalle Valodb66ea02013-09-03 11:44:03 +03001980
Michal Kaziore13cf7a2014-09-04 09:13:08 +02001981void ath10k_debug_unregister(struct ath10k *ar)
Kalle Valo60631c52013-10-08 21:45:25 +03001982{
1983 cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
1984}
1985
Kalle Valo5e3dd152013-06-12 20:52:10 +03001986#endif /* CONFIG_ATH10K_DEBUGFS */
1987
1988#ifdef CONFIG_ATH10K_DEBUG
Michal Kazior7aa7a722014-08-25 12:09:38 +02001989void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
1990 const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +03001991{
1992 struct va_format vaf;
1993 va_list args;
1994
1995 va_start(args, fmt);
1996
1997 vaf.fmt = fmt;
1998 vaf.va = &args;
1999
2000 if (ath10k_debug_mask & mask)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002001 dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002002
Michal Kaziord35a6c12014-09-02 11:00:21 +03002003 trace_ath10k_log_dbg(ar, mask, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002004
2005 va_end(args);
2006}
2007EXPORT_SYMBOL(ath10k_dbg);
2008
Michal Kazior7aa7a722014-08-25 12:09:38 +02002009void ath10k_dbg_dump(struct ath10k *ar,
2010 enum ath10k_debug_mask mask,
Kalle Valo5e3dd152013-06-12 20:52:10 +03002011 const char *msg, const char *prefix,
2012 const void *buf, size_t len)
2013{
Michal Kazior45724a82014-09-23 10:22:53 +02002014 char linebuf[256];
2015 unsigned int linebuflen;
2016 const void *ptr;
2017
Kalle Valo5e3dd152013-06-12 20:52:10 +03002018 if (ath10k_debug_mask & mask) {
2019 if (msg)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002020 ath10k_dbg(ar, mask, "%s\n", msg);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002021
Michal Kazior45724a82014-09-23 10:22:53 +02002022 for (ptr = buf; (ptr - buf) < len; ptr += 16) {
2023 linebuflen = 0;
2024 linebuflen += scnprintf(linebuf + linebuflen,
2025 sizeof(linebuf) - linebuflen,
2026 "%s%08x: ",
2027 (prefix ? prefix : ""),
2028 (unsigned int)(ptr - buf));
2029 hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
2030 linebuf + linebuflen,
2031 sizeof(linebuf) - linebuflen, true);
2032 dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
2033 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03002034 }
2035
2036 /* tracing code doesn't like null strings :/ */
Michal Kaziord35a6c12014-09-02 11:00:21 +03002037 trace_ath10k_log_dbg_dump(ar, msg ? msg : "", prefix ? prefix : "",
Kalle Valo5e3dd152013-06-12 20:52:10 +03002038 buf, len);
2039}
2040EXPORT_SYMBOL(ath10k_dbg_dump);
2041
2042#endif /* CONFIG_ATH10K_DEBUG */