Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/athk/ath10k/debug.c
48375 views
1
// SPDX-License-Identifier: ISC
2
/*
3
* Copyright (c) 2005-2011 Atheros Communications Inc.
4
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
5
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
6
*/
7
8
#include <linux/module.h>
9
#include <linux/debugfs.h>
10
#include <linux/vmalloc.h>
11
#include <linux/crc32.h>
12
#include <linux/firmware.h>
13
#include <linux/kstrtox.h>
14
15
#if defined(__FreeBSD__)
16
#ifdef CONFIG_ATH10K_DEBUG
17
#include <sys/sbuf.h>
18
#endif
19
#endif
20
21
#include "core.h"
22
#include "debug.h"
23
#include "hif.h"
24
#include "wmi-ops.h"
25
26
/* ms */
27
#define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
28
29
#define ATH10K_DEBUG_CAL_DATA_LEN 12064
30
31
void ath10k_info(struct ath10k *ar, const char *fmt, ...)
32
{
33
struct va_format vaf = {
34
.fmt = fmt,
35
};
36
va_list args;
37
38
va_start(args, fmt);
39
vaf.va = &args;
40
#if defined(__linux__)
41
dev_info(ar->dev, "%pV", &vaf);
42
#elif defined(__FreeBSD__)
43
{
44
char *str;
45
vasprintf(&str, M_KMALLOC, fmt, args);
46
dev_printk(KERN_DEBUG, ar->dev, "%s", str);
47
free(str, M_KMALLOC);
48
}
49
#endif
50
trace_ath10k_log_info(ar, &vaf);
51
va_end(args);
52
}
53
EXPORT_SYMBOL(ath10k_info);
54
55
void ath10k_debug_print_hwfw_info(struct ath10k *ar)
56
{
57
const struct firmware *firmware;
58
char fw_features[128] = {};
59
u32 crc = 0;
60
61
ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
62
63
#if defined(__linux__)
64
ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x",
65
#elif defined(__FreeBSD__)
66
ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x\n",
67
#endif
68
ar->hw_params.name,
69
ar->target_version,
70
ar->bus_param.chip_id,
71
ar->id.subsystem_vendor, ar->id.subsystem_device);
72
73
ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n",
74
IS_ENABLED(CONFIG_ATH10K_DEBUG),
75
IS_ENABLED(CONFIG_ATH10K_DEBUGFS),
76
IS_ENABLED(CONFIG_ATH10K_TRACING),
77
IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED),
78
IS_ENABLED(CONFIG_NL80211_TESTMODE));
79
80
firmware = ar->normal_mode_fw.fw_file.firmware;
81
if (firmware)
82
crc = crc32_le(0, firmware->data, firmware->size);
83
84
ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",
85
ar->hw->wiphy->fw_version,
86
ar->fw_api,
87
fw_features,
88
crc);
89
}
90
91
void ath10k_debug_print_board_info(struct ath10k *ar)
92
{
93
char boardinfo[100];
94
const struct firmware *board;
95
u32 crc;
96
97
if (ar->id.bmi_ids_valid)
98
scnprintf(boardinfo, sizeof(boardinfo), "%d:%d",
99
ar->id.bmi_chip_id, ar->id.bmi_board_id);
100
else
101
scnprintf(boardinfo, sizeof(boardinfo), "N/A");
102
103
board = ar->normal_mode_fw.board;
104
if (!IS_ERR_OR_NULL(board))
105
crc = crc32_le(0, board->data, board->size);
106
else
107
crc = 0;
108
109
#if defined(__linux__)
110
ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x",
111
#elif defined(__FreeBSD__)
112
ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x\n",
113
#endif
114
ar->bd_api,
115
boardinfo,
116
crc);
117
}
118
119
void ath10k_debug_print_boot_info(struct ath10k *ar)
120
{
121
ath10k_info(ar, "htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d\n",
122
ar->htt.target_version_major,
123
ar->htt.target_version_minor,
124
ar->normal_mode_fw.fw_file.wmi_op_version,
125
ar->normal_mode_fw.fw_file.htt_op_version,
126
ath10k_cal_mode_str(ar->cal_mode),
127
ar->max_num_stations,
128
test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
129
!test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags));
130
}
131
132
void ath10k_print_driver_info(struct ath10k *ar)
133
{
134
ath10k_debug_print_hwfw_info(ar);
135
ath10k_debug_print_board_info(ar);
136
ath10k_debug_print_boot_info(ar);
137
}
138
EXPORT_SYMBOL(ath10k_print_driver_info);
139
140
void ath10k_err(struct ath10k *ar, const char *fmt, ...)
141
{
142
struct va_format vaf = {
143
.fmt = fmt,
144
};
145
va_list args;
146
147
va_start(args, fmt);
148
vaf.va = &args;
149
#if defined(__linux__)
150
dev_err(ar->dev, "%pV", &vaf);
151
#elif defined(__FreeBSD__)
152
{
153
char *str;
154
vasprintf(&str, M_KMALLOC, fmt, args);
155
dev_err(ar->dev, "%s", str);
156
free(str, M_KMALLOC);
157
}
158
#endif
159
trace_ath10k_log_err(ar, &vaf);
160
va_end(args);
161
}
162
EXPORT_SYMBOL(ath10k_err);
163
164
void ath10k_warn(struct ath10k *ar, const char *fmt, ...)
165
{
166
struct va_format vaf = {
167
.fmt = fmt,
168
};
169
va_list args;
170
171
va_start(args, fmt);
172
vaf.va = &args;
173
#if defined(__linux__)
174
dev_warn_ratelimited(ar->dev, "%pV", &vaf);
175
#elif defined(__FreeBSD__)
176
{
177
char *str;
178
vasprintf(&str, M_KMALLOC, fmt, args);
179
dev_warn_ratelimited(ar->dev, "%s", str);
180
free(str, M_KMALLOC);
181
}
182
#endif
183
trace_ath10k_log_warn(ar, &vaf);
184
185
va_end(args);
186
}
187
EXPORT_SYMBOL(ath10k_warn);
188
189
#ifdef CONFIG_ATH10K_DEBUGFS
190
191
static ssize_t ath10k_read_wmi_services(struct file *file,
192
char __user *user_buf,
193
size_t count, loff_t *ppos)
194
{
195
struct ath10k *ar = file->private_data;
196
char *buf;
197
size_t len = 0, buf_len = 8192;
198
const char *name;
199
ssize_t ret_cnt;
200
bool enabled;
201
int i;
202
203
buf = kzalloc(buf_len, GFP_KERNEL);
204
if (!buf)
205
return -ENOMEM;
206
207
mutex_lock(&ar->conf_mutex);
208
209
spin_lock_bh(&ar->data_lock);
210
for (i = 0; i < WMI_SERVICE_MAX; i++) {
211
enabled = test_bit(i, ar->wmi.svc_map);
212
name = wmi_service_name(i);
213
214
if (!name) {
215
if (enabled)
216
len += scnprintf(buf + len, buf_len - len,
217
"%-40s %s (bit %d)\n",
218
"unknown", "enabled", i);
219
220
continue;
221
}
222
223
len += scnprintf(buf + len, buf_len - len,
224
"%-40s %s\n",
225
name, enabled ? "enabled" : "-");
226
}
227
spin_unlock_bh(&ar->data_lock);
228
229
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
230
231
mutex_unlock(&ar->conf_mutex);
232
233
kfree(buf);
234
return ret_cnt;
235
}
236
237
static const struct file_operations fops_wmi_services = {
238
.read = ath10k_read_wmi_services,
239
.open = simple_open,
240
.owner = THIS_MODULE,
241
.llseek = default_llseek,
242
};
243
244
static void ath10k_fw_stats_pdevs_free(struct list_head *head)
245
{
246
struct ath10k_fw_stats_pdev *i, *tmp;
247
248
list_for_each_entry_safe(i, tmp, head, list) {
249
list_del(&i->list);
250
kfree(i);
251
}
252
}
253
254
static void ath10k_fw_stats_vdevs_free(struct list_head *head)
255
{
256
struct ath10k_fw_stats_vdev *i, *tmp;
257
258
list_for_each_entry_safe(i, tmp, head, list) {
259
list_del(&i->list);
260
kfree(i);
261
}
262
}
263
264
static void ath10k_fw_stats_peers_free(struct list_head *head)
265
{
266
struct ath10k_fw_stats_peer *i, *tmp;
267
268
list_for_each_entry_safe(i, tmp, head, list) {
269
list_del(&i->list);
270
kfree(i);
271
}
272
}
273
274
static void ath10k_fw_extd_stats_peers_free(struct list_head *head)
275
{
276
struct ath10k_fw_extd_stats_peer *i, *tmp;
277
278
list_for_each_entry_safe(i, tmp, head, list) {
279
list_del(&i->list);
280
kfree(i);
281
}
282
}
283
284
static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
285
{
286
spin_lock_bh(&ar->data_lock);
287
ar->debug.fw_stats_done = false;
288
ar->debug.fw_stats.extended = false;
289
ath10k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
290
ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
291
ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
292
ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);
293
spin_unlock_bh(&ar->data_lock);
294
}
295
296
void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
297
{
298
struct ath10k_fw_stats stats = {};
299
bool is_start, is_started, is_end;
300
size_t num_peers;
301
size_t num_vdevs;
302
int ret;
303
304
INIT_LIST_HEAD(&stats.pdevs);
305
INIT_LIST_HEAD(&stats.vdevs);
306
INIT_LIST_HEAD(&stats.peers);
307
INIT_LIST_HEAD(&stats.peers_extd);
308
309
spin_lock_bh(&ar->data_lock);
310
ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
311
if (ret) {
312
ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
313
goto free;
314
}
315
316
/* Stat data may exceed htc-wmi buffer limit. In such case firmware
317
* splits the stats data and delivers it in a ping-pong fashion of
318
* request cmd-update event.
319
*
320
* However there is no explicit end-of-data. Instead start-of-data is
321
* used as an implicit one. This works as follows:
322
* a) discard stat update events until one with pdev stats is
323
* delivered - this skips session started at end of (b)
324
* b) consume stat update events until another one with pdev stats is
325
* delivered which is treated as end-of-data and is itself discarded
326
*/
327
if (ath10k_peer_stats_enabled(ar))
328
ath10k_sta_update_rx_duration(ar, &stats);
329
330
if (ar->debug.fw_stats_done) {
331
if (!ath10k_peer_stats_enabled(ar))
332
ath10k_warn(ar, "received unsolicited stats update event\n");
333
334
goto free;
335
}
336
337
num_peers = list_count_nodes(&ar->debug.fw_stats.peers);
338
num_vdevs = list_count_nodes(&ar->debug.fw_stats.vdevs);
339
is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
340
!list_empty(&stats.pdevs));
341
is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
342
!list_empty(&stats.pdevs));
343
344
if (is_start)
345
list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
346
347
if (is_end)
348
ar->debug.fw_stats_done = true;
349
350
if (stats.extended)
351
ar->debug.fw_stats.extended = true;
352
353
is_started = !list_empty(&ar->debug.fw_stats.pdevs);
354
355
if (is_started && !is_end) {
356
if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) {
357
/* Although this is unlikely impose a sane limit to
358
* prevent firmware from DoS-ing the host.
359
*/
360
ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
361
ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);
362
ath10k_warn(ar, "dropping fw peer stats\n");
363
goto free;
364
}
365
366
if (num_vdevs >= BITS_PER_LONG) {
367
ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
368
ath10k_warn(ar, "dropping fw vdev stats\n");
369
goto free;
370
}
371
372
if (!list_empty(&stats.peers))
373
list_splice_tail_init(&stats.peers_extd,
374
&ar->debug.fw_stats.peers_extd);
375
376
list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
377
list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
378
}
379
380
complete(&ar->debug.fw_stats_complete);
381
382
free:
383
/* In some cases lists have been spliced and cleared. Free up
384
* resources if that is not the case.
385
*/
386
ath10k_fw_stats_pdevs_free(&stats.pdevs);
387
ath10k_fw_stats_vdevs_free(&stats.vdevs);
388
ath10k_fw_stats_peers_free(&stats.peers);
389
ath10k_fw_extd_stats_peers_free(&stats.peers_extd);
390
391
spin_unlock_bh(&ar->data_lock);
392
}
393
394
int ath10k_debug_fw_stats_request(struct ath10k *ar)
395
{
396
unsigned long timeout, time_left;
397
int ret;
398
399
lockdep_assert_held(&ar->conf_mutex);
400
401
timeout = jiffies + msecs_to_jiffies(1 * HZ);
402
403
ath10k_debug_fw_stats_reset(ar);
404
405
for (;;) {
406
if (time_after(jiffies, timeout))
407
return -ETIMEDOUT;
408
409
reinit_completion(&ar->debug.fw_stats_complete);
410
411
ret = ath10k_wmi_request_stats(ar, ar->fw_stats_req_mask);
412
if (ret) {
413
ath10k_warn(ar, "could not request stats (%d)\n", ret);
414
return ret;
415
}
416
417
time_left =
418
wait_for_completion_timeout(&ar->debug.fw_stats_complete,
419
1 * HZ);
420
if (!time_left)
421
return -ETIMEDOUT;
422
423
spin_lock_bh(&ar->data_lock);
424
if (ar->debug.fw_stats_done) {
425
spin_unlock_bh(&ar->data_lock);
426
break;
427
}
428
spin_unlock_bh(&ar->data_lock);
429
}
430
431
return 0;
432
}
433
434
static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
435
{
436
struct ath10k *ar = inode->i_private;
437
void *buf = NULL;
438
int ret;
439
440
mutex_lock(&ar->conf_mutex);
441
442
if (ar->state != ATH10K_STATE_ON) {
443
ret = -ENETDOWN;
444
goto err_unlock;
445
}
446
447
buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);
448
if (!buf) {
449
ret = -ENOMEM;
450
goto err_unlock;
451
}
452
453
ret = ath10k_debug_fw_stats_request(ar);
454
if (ret) {
455
ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
456
goto err_free;
457
}
458
459
ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
460
if (ret) {
461
ath10k_warn(ar, "failed to fill fw stats: %d\n", ret);
462
goto err_free;
463
}
464
465
file->private_data = buf;
466
467
mutex_unlock(&ar->conf_mutex);
468
return 0;
469
470
err_free:
471
vfree(buf);
472
473
err_unlock:
474
mutex_unlock(&ar->conf_mutex);
475
return ret;
476
}
477
478
static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
479
{
480
vfree(file->private_data);
481
482
return 0;
483
}
484
485
static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
486
size_t count, loff_t *ppos)
487
{
488
const char *buf = file->private_data;
489
size_t len = strlen(buf);
490
491
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
492
}
493
494
static const struct file_operations fops_fw_stats = {
495
.open = ath10k_fw_stats_open,
496
.release = ath10k_fw_stats_release,
497
.read = ath10k_fw_stats_read,
498
.owner = THIS_MODULE,
499
.llseek = default_llseek,
500
};
501
502
static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
503
char __user *user_buf,
504
size_t count, loff_t *ppos)
505
{
506
struct ath10k *ar = file->private_data;
507
int ret;
508
size_t len = 0, buf_len = 500;
509
char *buf;
510
511
buf = kmalloc(buf_len, GFP_KERNEL);
512
if (!buf)
513
return -ENOMEM;
514
515
spin_lock_bh(&ar->data_lock);
516
517
len += scnprintf(buf + len, buf_len - len,
518
"fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
519
len += scnprintf(buf + len, buf_len - len,
520
"fw_warm_reset_counter\t\t%d\n",
521
ar->stats.fw_warm_reset_counter);
522
len += scnprintf(buf + len, buf_len - len,
523
"fw_cold_reset_counter\t\t%d\n",
524
ar->stats.fw_cold_reset_counter);
525
526
spin_unlock_bh(&ar->data_lock);
527
528
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
529
530
kfree(buf);
531
532
return ret;
533
}
534
535
static const struct file_operations fops_fw_reset_stats = {
536
.open = simple_open,
537
.read = ath10k_debug_fw_reset_stats_read,
538
.owner = THIS_MODULE,
539
.llseek = default_llseek,
540
};
541
542
/* This is a clean assert crash in firmware. */
543
static int ath10k_debug_fw_assert(struct ath10k *ar)
544
{
545
struct wmi_vdev_install_key_cmd *cmd;
546
struct sk_buff *skb;
547
548
skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
549
if (!skb)
550
return -ENOMEM;
551
552
cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
553
memset(cmd, 0, sizeof(*cmd));
554
555
/* big enough number so that firmware asserts */
556
cmd->vdev_id = __cpu_to_le32(0x7ffe);
557
558
return ath10k_wmi_cmd_send(ar, skb,
559
ar->wmi.cmd->vdev_install_key_cmdid);
560
}
561
562
static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
563
char __user *user_buf,
564
size_t count, loff_t *ppos)
565
{
566
const char buf[] =
567
"To simulate firmware crash write one of the keywords to this file:\n"
568
"`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
569
"`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
570
"`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"
571
"`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
572
573
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
574
}
575
576
/* Simulate firmware crash:
577
* 'soft': Call wmi command causing firmware hang. This firmware hang is
578
* recoverable by warm firmware reset.
579
* 'hard': Force firmware crash by setting any vdev parameter for not allowed
580
* vdev id. This is hard firmware crash because it is recoverable only by cold
581
* firmware reset.
582
*/
583
static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
584
const char __user *user_buf,
585
size_t count, loff_t *ppos)
586
{
587
struct ath10k *ar = file->private_data;
588
char buf[32] = {0};
589
ssize_t rc;
590
int ret;
591
592
/* filter partial writes and invalid commands */
593
if (*ppos != 0 || count >= sizeof(buf) || count == 0)
594
return -EINVAL;
595
596
rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
597
if (rc < 0)
598
return rc;
599
600
/* drop the possible '\n' from the end */
601
if (buf[*ppos - 1] == '\n')
602
buf[*ppos - 1] = '\0';
603
604
mutex_lock(&ar->conf_mutex);
605
606
if (ar->state != ATH10K_STATE_ON &&
607
ar->state != ATH10K_STATE_RESTARTED) {
608
ret = -ENETDOWN;
609
goto exit;
610
}
611
612
if (!strcmp(buf, "soft")) {
613
ath10k_info(ar, "simulating soft firmware crash\n");
614
ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
615
} else if (!strcmp(buf, "hard")) {
616
ath10k_info(ar, "simulating hard firmware crash\n");
617
/* 0x7fff is vdev id, and it is always out of range for all
618
* firmware variants in order to force a firmware crash.
619
*/
620
ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
621
ar->wmi.vdev_param->rts_threshold,
622
0);
623
} else if (!strcmp(buf, "assert")) {
624
ath10k_info(ar, "simulating firmware assert crash\n");
625
ret = ath10k_debug_fw_assert(ar);
626
} else if (!strcmp(buf, "hw-restart")) {
627
ath10k_info(ar, "user requested hw restart\n");
628
ath10k_core_start_recovery(ar);
629
ret = 0;
630
} else {
631
ret = -EINVAL;
632
goto exit;
633
}
634
635
if (ret) {
636
ath10k_warn(ar, "failed to simulate firmware crash: %d\n", ret);
637
goto exit;
638
}
639
640
ret = count;
641
642
exit:
643
mutex_unlock(&ar->conf_mutex);
644
return ret;
645
}
646
647
static const struct file_operations fops_simulate_fw_crash = {
648
.read = ath10k_read_simulate_fw_crash,
649
.write = ath10k_write_simulate_fw_crash,
650
.open = simple_open,
651
.owner = THIS_MODULE,
652
.llseek = default_llseek,
653
};
654
655
static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf,
656
size_t count, loff_t *ppos)
657
{
658
struct ath10k *ar = file->private_data;
659
size_t len;
660
char buf[50];
661
662
len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->bus_param.chip_id);
663
664
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
665
}
666
667
static const struct file_operations fops_chip_id = {
668
.read = ath10k_read_chip_id,
669
.open = simple_open,
670
.owner = THIS_MODULE,
671
.llseek = default_llseek,
672
};
673
674
static ssize_t ath10k_reg_addr_read(struct file *file,
675
char __user *user_buf,
676
size_t count, loff_t *ppos)
677
{
678
struct ath10k *ar = file->private_data;
679
u8 buf[32];
680
size_t len = 0;
681
u32 reg_addr;
682
683
mutex_lock(&ar->conf_mutex);
684
reg_addr = ar->debug.reg_addr;
685
mutex_unlock(&ar->conf_mutex);
686
687
len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);
688
689
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
690
}
691
692
static ssize_t ath10k_reg_addr_write(struct file *file,
693
const char __user *user_buf,
694
size_t count, loff_t *ppos)
695
{
696
struct ath10k *ar = file->private_data;
697
u32 reg_addr;
698
int ret;
699
700
ret = kstrtou32_from_user(user_buf, count, 0, &reg_addr);
701
if (ret)
702
return ret;
703
704
if (!IS_ALIGNED(reg_addr, 4))
705
return -EFAULT;
706
707
mutex_lock(&ar->conf_mutex);
708
ar->debug.reg_addr = reg_addr;
709
mutex_unlock(&ar->conf_mutex);
710
711
return count;
712
}
713
714
static const struct file_operations fops_reg_addr = {
715
.read = ath10k_reg_addr_read,
716
.write = ath10k_reg_addr_write,
717
.open = simple_open,
718
.owner = THIS_MODULE,
719
.llseek = default_llseek,
720
};
721
722
static ssize_t ath10k_reg_value_read(struct file *file,
723
char __user *user_buf,
724
size_t count, loff_t *ppos)
725
{
726
struct ath10k *ar = file->private_data;
727
u8 buf[48];
728
size_t len;
729
u32 reg_addr, reg_val;
730
int ret;
731
732
mutex_lock(&ar->conf_mutex);
733
734
if (ar->state != ATH10K_STATE_ON &&
735
ar->state != ATH10K_STATE_UTF) {
736
ret = -ENETDOWN;
737
goto exit;
738
}
739
740
reg_addr = ar->debug.reg_addr;
741
742
reg_val = ath10k_hif_read32(ar, reg_addr);
743
len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);
744
745
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
746
747
exit:
748
mutex_unlock(&ar->conf_mutex);
749
750
return ret;
751
}
752
753
static ssize_t ath10k_reg_value_write(struct file *file,
754
const char __user *user_buf,
755
size_t count, loff_t *ppos)
756
{
757
struct ath10k *ar = file->private_data;
758
u32 reg_addr, reg_val;
759
int ret;
760
761
mutex_lock(&ar->conf_mutex);
762
763
if (ar->state != ATH10K_STATE_ON &&
764
ar->state != ATH10K_STATE_UTF) {
765
ret = -ENETDOWN;
766
goto exit;
767
}
768
769
reg_addr = ar->debug.reg_addr;
770
771
ret = kstrtou32_from_user(user_buf, count, 0, &reg_val);
772
if (ret)
773
goto exit;
774
775
ath10k_hif_write32(ar, reg_addr, reg_val);
776
777
ret = count;
778
779
exit:
780
mutex_unlock(&ar->conf_mutex);
781
782
return ret;
783
}
784
785
static const struct file_operations fops_reg_value = {
786
.read = ath10k_reg_value_read,
787
.write = ath10k_reg_value_write,
788
.open = simple_open,
789
.owner = THIS_MODULE,
790
.llseek = default_llseek,
791
};
792
793
static ssize_t ath10k_mem_value_read(struct file *file,
794
char __user *user_buf,
795
size_t count, loff_t *ppos)
796
{
797
struct ath10k *ar = file->private_data;
798
u8 *buf;
799
int ret;
800
801
if (*ppos < 0)
802
return -EINVAL;
803
804
if (!count)
805
return 0;
806
807
mutex_lock(&ar->conf_mutex);
808
809
buf = vmalloc(count);
810
if (!buf) {
811
ret = -ENOMEM;
812
goto exit;
813
}
814
815
if (ar->state != ATH10K_STATE_ON &&
816
ar->state != ATH10K_STATE_UTF) {
817
ret = -ENETDOWN;
818
goto exit;
819
}
820
821
ret = ath10k_hif_diag_read(ar, *ppos, buf, count);
822
if (ret) {
823
ath10k_warn(ar, "failed to read address 0x%08x via diagnose window from debugfs: %d\n",
824
(u32)(*ppos), ret);
825
goto exit;
826
}
827
828
ret = copy_to_user(user_buf, buf, count);
829
if (ret) {
830
ret = -EFAULT;
831
goto exit;
832
}
833
834
count -= ret;
835
*ppos += count;
836
ret = count;
837
838
exit:
839
vfree(buf);
840
mutex_unlock(&ar->conf_mutex);
841
842
return ret;
843
}
844
845
static ssize_t ath10k_mem_value_write(struct file *file,
846
const char __user *user_buf,
847
size_t count, loff_t *ppos)
848
{
849
struct ath10k *ar = file->private_data;
850
u8 *buf;
851
int ret;
852
853
if (*ppos < 0)
854
return -EINVAL;
855
856
if (!count)
857
return 0;
858
859
mutex_lock(&ar->conf_mutex);
860
861
buf = vmalloc(count);
862
if (!buf) {
863
ret = -ENOMEM;
864
goto exit;
865
}
866
867
if (ar->state != ATH10K_STATE_ON &&
868
ar->state != ATH10K_STATE_UTF) {
869
ret = -ENETDOWN;
870
goto exit;
871
}
872
873
ret = copy_from_user(buf, user_buf, count);
874
if (ret) {
875
ret = -EFAULT;
876
goto exit;
877
}
878
879
ret = ath10k_hif_diag_write(ar, *ppos, buf, count);
880
if (ret) {
881
ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",
882
(u32)(*ppos), ret);
883
goto exit;
884
}
885
886
*ppos += count;
887
ret = count;
888
889
exit:
890
vfree(buf);
891
mutex_unlock(&ar->conf_mutex);
892
893
return ret;
894
}
895
896
static const struct file_operations fops_mem_value = {
897
.read = ath10k_mem_value_read,
898
.write = ath10k_mem_value_write,
899
.open = simple_open,
900
.owner = THIS_MODULE,
901
.llseek = default_llseek,
902
};
903
904
static int ath10k_debug_htt_stats_req(struct ath10k *ar)
905
{
906
u64 cookie;
907
int ret;
908
909
lockdep_assert_held(&ar->conf_mutex);
910
911
if (ar->debug.htt_stats_mask == 0)
912
/* htt stats are disabled */
913
return 0;
914
915
if (ar->state != ATH10K_STATE_ON)
916
return 0;
917
918
cookie = get_jiffies_64();
919
920
ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask,
921
ar->debug.reset_htt_stats, cookie);
922
if (ret) {
923
ath10k_warn(ar, "failed to send htt stats request: %d\n", ret);
924
return ret;
925
}
926
927
queue_delayed_work(ar->workqueue, &ar->debug.htt_stats_dwork,
928
msecs_to_jiffies(ATH10K_DEBUG_HTT_STATS_INTERVAL));
929
930
return 0;
931
}
932
933
static void ath10k_debug_htt_stats_dwork(struct work_struct *work)
934
{
935
struct ath10k *ar = container_of(work, struct ath10k,
936
debug.htt_stats_dwork.work);
937
938
mutex_lock(&ar->conf_mutex);
939
940
ath10k_debug_htt_stats_req(ar);
941
942
mutex_unlock(&ar->conf_mutex);
943
}
944
945
static ssize_t ath10k_read_htt_stats_mask(struct file *file,
946
char __user *user_buf,
947
size_t count, loff_t *ppos)
948
{
949
struct ath10k *ar = file->private_data;
950
char buf[32];
951
size_t len;
952
953
len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask);
954
955
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
956
}
957
958
static ssize_t ath10k_write_htt_stats_mask(struct file *file,
959
const char __user *user_buf,
960
size_t count, loff_t *ppos)
961
{
962
struct ath10k *ar = file->private_data;
963
unsigned long mask;
964
int ret;
965
966
ret = kstrtoul_from_user(user_buf, count, 0, &mask);
967
if (ret)
968
return ret;
969
970
/* max 17 bit masks (for now) */
971
if (mask > HTT_STATS_BIT_MASK)
972
return -E2BIG;
973
974
mutex_lock(&ar->conf_mutex);
975
976
ar->debug.htt_stats_mask = mask;
977
978
ret = ath10k_debug_htt_stats_req(ar);
979
if (ret)
980
goto out;
981
982
ret = count;
983
984
out:
985
mutex_unlock(&ar->conf_mutex);
986
987
return ret;
988
}
989
990
static const struct file_operations fops_htt_stats_mask = {
991
.read = ath10k_read_htt_stats_mask,
992
.write = ath10k_write_htt_stats_mask,
993
.open = simple_open,
994
.owner = THIS_MODULE,
995
.llseek = default_llseek,
996
};
997
998
static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
999
char __user *user_buf,
1000
size_t count, loff_t *ppos)
1001
{
1002
struct ath10k *ar = file->private_data;
1003
char buf[64];
1004
u8 amsdu, ampdu;
1005
size_t len;
1006
1007
mutex_lock(&ar->conf_mutex);
1008
1009
amsdu = ar->htt.max_num_amsdu;
1010
ampdu = ar->htt.max_num_ampdu;
1011
mutex_unlock(&ar->conf_mutex);
1012
1013
len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
1014
1015
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1016
}
1017
1018
static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
1019
const char __user *user_buf,
1020
size_t count, loff_t *ppos)
1021
{
1022
struct ath10k *ar = file->private_data;
1023
int res;
1024
char buf[64] = {0};
1025
unsigned int amsdu, ampdu;
1026
1027
res = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
1028
user_buf, count);
1029
if (res <= 0)
1030
return res;
1031
1032
res = sscanf(buf, "%u %u", &amsdu, &ampdu);
1033
1034
if (res != 2)
1035
return -EINVAL;
1036
1037
mutex_lock(&ar->conf_mutex);
1038
1039
res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
1040
if (res)
1041
goto out;
1042
1043
res = count;
1044
ar->htt.max_num_amsdu = amsdu;
1045
ar->htt.max_num_ampdu = ampdu;
1046
1047
out:
1048
mutex_unlock(&ar->conf_mutex);
1049
return res;
1050
}
1051
1052
static const struct file_operations fops_htt_max_amsdu_ampdu = {
1053
.read = ath10k_read_htt_max_amsdu_ampdu,
1054
.write = ath10k_write_htt_max_amsdu_ampdu,
1055
.open = simple_open,
1056
.owner = THIS_MODULE,
1057
.llseek = default_llseek,
1058
};
1059
1060
static ssize_t ath10k_read_fw_dbglog(struct file *file,
1061
char __user *user_buf,
1062
size_t count, loff_t *ppos)
1063
{
1064
struct ath10k *ar = file->private_data;
1065
size_t len;
1066
char buf[96];
1067
1068
len = scnprintf(buf, sizeof(buf), "0x%16llx %u\n",
1069
ar->debug.fw_dbglog_mask, ar->debug.fw_dbglog_level);
1070
1071
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1072
}
1073
1074
static ssize_t ath10k_write_fw_dbglog(struct file *file,
1075
const char __user *user_buf,
1076
size_t count, loff_t *ppos)
1077
{
1078
struct ath10k *ar = file->private_data;
1079
int ret;
1080
char buf[96] = {0};
1081
unsigned int log_level;
1082
u64 mask;
1083
1084
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
1085
user_buf, count);
1086
if (ret <= 0)
1087
return ret;
1088
1089
ret = sscanf(buf, "%llx %u", &mask, &log_level);
1090
1091
if (!ret)
1092
return -EINVAL;
1093
1094
if (ret == 1)
1095
/* default if user did not specify */
1096
log_level = ATH10K_DBGLOG_LEVEL_WARN;
1097
1098
mutex_lock(&ar->conf_mutex);
1099
1100
ar->debug.fw_dbglog_mask = mask;
1101
ar->debug.fw_dbglog_level = log_level;
1102
1103
if (ar->state == ATH10K_STATE_ON) {
1104
ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1105
ar->debug.fw_dbglog_level);
1106
if (ret) {
1107
ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n",
1108
ret);
1109
goto exit;
1110
}
1111
}
1112
1113
ret = count;
1114
1115
exit:
1116
mutex_unlock(&ar->conf_mutex);
1117
1118
return ret;
1119
}
1120
1121
/* TODO: Would be nice to always support ethtool stats, would need to
1122
* move the stats storage out of ath10k_debug, or always have ath10k_debug
1123
* struct available..
1124
*/
1125
1126
/* This generally corresponds to the debugfs fw_stats file */
1127
static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
1128
"tx_pkts_nic",
1129
"tx_bytes_nic",
1130
"rx_pkts_nic",
1131
"rx_bytes_nic",
1132
"d_noise_floor",
1133
"d_cycle_count",
1134
"d_phy_error",
1135
"d_rts_bad",
1136
"d_rts_good",
1137
"d_tx_power", /* in .5 dbM I think */
1138
"d_rx_crc_err", /* fcs_bad */
1139
"d_rx_crc_err_drop", /* frame with FCS error, dropped late in kernel */
1140
"d_no_beacon",
1141
"d_tx_mpdus_queued",
1142
"d_tx_msdu_queued",
1143
"d_tx_msdu_dropped",
1144
"d_local_enqued",
1145
"d_local_freed",
1146
"d_tx_ppdu_hw_queued",
1147
"d_tx_ppdu_reaped",
1148
"d_tx_fifo_underrun",
1149
"d_tx_ppdu_abort",
1150
"d_tx_mpdu_requeued",
1151
"d_tx_excessive_retries",
1152
"d_tx_hw_rate",
1153
"d_tx_dropped_sw_retries",
1154
"d_tx_illegal_rate",
1155
"d_tx_continuous_xretries",
1156
"d_tx_timeout",
1157
"d_tx_mpdu_txop_limit",
1158
"d_pdev_resets",
1159
"d_rx_mid_ppdu_route_change",
1160
"d_rx_status",
1161
"d_rx_extra_frags_ring0",
1162
"d_rx_extra_frags_ring1",
1163
"d_rx_extra_frags_ring2",
1164
"d_rx_extra_frags_ring3",
1165
"d_rx_msdu_htt",
1166
"d_rx_mpdu_htt",
1167
"d_rx_msdu_stack",
1168
"d_rx_mpdu_stack",
1169
"d_rx_phy_err",
1170
"d_rx_phy_err_drops",
1171
"d_rx_mpdu_errors", /* FCS, MIC, ENC */
1172
"d_fw_crash_count",
1173
"d_fw_warm_reset_count",
1174
"d_fw_cold_reset_count",
1175
};
1176
1177
#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
1178
1179
void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
1180
struct ieee80211_vif *vif,
1181
u32 sset, u8 *data)
1182
{
1183
if (sset == ETH_SS_STATS)
1184
memcpy(data, *ath10k_gstrings_stats,
1185
sizeof(ath10k_gstrings_stats));
1186
}
1187
1188
int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
1189
struct ieee80211_vif *vif, int sset)
1190
{
1191
if (sset == ETH_SS_STATS)
1192
return ATH10K_SSTATS_LEN;
1193
1194
return 0;
1195
}
1196
1197
void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
1198
struct ieee80211_vif *vif,
1199
struct ethtool_stats *stats, u64 *data)
1200
{
1201
struct ath10k *ar = hw->priv;
1202
static const struct ath10k_fw_stats_pdev zero_stats = {};
1203
const struct ath10k_fw_stats_pdev *pdev_stats;
1204
int i = 0, ret;
1205
1206
mutex_lock(&ar->conf_mutex);
1207
1208
if (ar->state == ATH10K_STATE_ON) {
1209
ret = ath10k_debug_fw_stats_request(ar);
1210
if (ret) {
1211
/* just print a warning and try to use older results */
1212
ath10k_warn(ar,
1213
"failed to get fw stats for ethtool: %d\n",
1214
ret);
1215
}
1216
}
1217
1218
pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,
1219
struct ath10k_fw_stats_pdev,
1220
list);
1221
if (!pdev_stats) {
1222
/* no results available so just return zeroes */
1223
pdev_stats = &zero_stats;
1224
}
1225
1226
spin_lock_bh(&ar->data_lock);
1227
1228
data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
1229
data[i++] = 0; /* tx bytes */
1230
data[i++] = pdev_stats->htt_mpdus;
1231
data[i++] = 0; /* rx bytes */
1232
data[i++] = pdev_stats->ch_noise_floor;
1233
data[i++] = pdev_stats->cycle_count;
1234
data[i++] = pdev_stats->phy_err_count;
1235
data[i++] = pdev_stats->rts_bad;
1236
data[i++] = pdev_stats->rts_good;
1237
data[i++] = pdev_stats->chan_tx_power;
1238
data[i++] = pdev_stats->fcs_bad;
1239
data[i++] = ar->stats.rx_crc_err_drop;
1240
data[i++] = pdev_stats->no_beacons;
1241
data[i++] = pdev_stats->mpdu_enqued;
1242
data[i++] = pdev_stats->msdu_enqued;
1243
data[i++] = pdev_stats->wmm_drop;
1244
data[i++] = pdev_stats->local_enqued;
1245
data[i++] = pdev_stats->local_freed;
1246
data[i++] = pdev_stats->hw_queued;
1247
data[i++] = pdev_stats->hw_reaped;
1248
data[i++] = pdev_stats->underrun;
1249
data[i++] = pdev_stats->tx_abort;
1250
data[i++] = pdev_stats->mpdus_requeued;
1251
data[i++] = pdev_stats->tx_ko;
1252
data[i++] = pdev_stats->data_rc;
1253
data[i++] = pdev_stats->sw_retry_failure;
1254
data[i++] = pdev_stats->illgl_rate_phy_err;
1255
data[i++] = pdev_stats->pdev_cont_xretry;
1256
data[i++] = pdev_stats->pdev_tx_timeout;
1257
data[i++] = pdev_stats->txop_ovf;
1258
data[i++] = pdev_stats->pdev_resets;
1259
data[i++] = pdev_stats->mid_ppdu_route_change;
1260
data[i++] = pdev_stats->status_rcvd;
1261
data[i++] = pdev_stats->r0_frags;
1262
data[i++] = pdev_stats->r1_frags;
1263
data[i++] = pdev_stats->r2_frags;
1264
data[i++] = pdev_stats->r3_frags;
1265
data[i++] = pdev_stats->htt_msdus;
1266
data[i++] = pdev_stats->htt_mpdus;
1267
data[i++] = pdev_stats->loc_msdus;
1268
data[i++] = pdev_stats->loc_mpdus;
1269
data[i++] = pdev_stats->phy_errs;
1270
data[i++] = pdev_stats->phy_err_drop;
1271
data[i++] = pdev_stats->mpdu_errs;
1272
data[i++] = ar->stats.fw_crash_counter;
1273
data[i++] = ar->stats.fw_warm_reset_counter;
1274
data[i++] = ar->stats.fw_cold_reset_counter;
1275
1276
spin_unlock_bh(&ar->data_lock);
1277
1278
mutex_unlock(&ar->conf_mutex);
1279
1280
WARN_ON(i != ATH10K_SSTATS_LEN);
1281
}
1282
1283
static const struct file_operations fops_fw_dbglog = {
1284
.read = ath10k_read_fw_dbglog,
1285
.write = ath10k_write_fw_dbglog,
1286
.open = simple_open,
1287
.owner = THIS_MODULE,
1288
.llseek = default_llseek,
1289
};
1290
1291
static int ath10k_debug_cal_data_fetch(struct ath10k *ar)
1292
{
1293
u32 hi_addr;
1294
__le32 addr;
1295
int ret;
1296
1297
lockdep_assert_held(&ar->conf_mutex);
1298
1299
if (WARN_ON(ar->hw_params.cal_data_len > ATH10K_DEBUG_CAL_DATA_LEN))
1300
return -EINVAL;
1301
1302
if (ar->hw_params.cal_data_len == 0)
1303
return -EOPNOTSUPP;
1304
1305
hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
1306
1307
ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
1308
if (ret) {
1309
ath10k_warn(ar, "failed to read hi_board_data address: %d\n",
1310
ret);
1311
return ret;
1312
}
1313
1314
ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), ar->debug.cal_data,
1315
ar->hw_params.cal_data_len);
1316
if (ret) {
1317
ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
1318
return ret;
1319
}
1320
1321
return 0;
1322
}
1323
1324
static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
1325
{
1326
struct ath10k *ar = inode->i_private;
1327
1328
mutex_lock(&ar->conf_mutex);
1329
1330
if (ar->state == ATH10K_STATE_ON ||
1331
ar->state == ATH10K_STATE_UTF) {
1332
ath10k_debug_cal_data_fetch(ar);
1333
}
1334
1335
file->private_data = ar;
1336
mutex_unlock(&ar->conf_mutex);
1337
1338
return 0;
1339
}
1340
1341
static ssize_t ath10k_debug_cal_data_read(struct file *file,
1342
char __user *user_buf,
1343
size_t count, loff_t *ppos)
1344
{
1345
struct ath10k *ar = file->private_data;
1346
1347
mutex_lock(&ar->conf_mutex);
1348
1349
count = simple_read_from_buffer(user_buf, count, ppos,
1350
ar->debug.cal_data,
1351
ar->hw_params.cal_data_len);
1352
1353
mutex_unlock(&ar->conf_mutex);
1354
1355
return count;
1356
}
1357
1358
static ssize_t ath10k_write_ani_enable(struct file *file,
1359
const char __user *user_buf,
1360
size_t count, loff_t *ppos)
1361
{
1362
struct ath10k *ar = file->private_data;
1363
int ret;
1364
u8 enable;
1365
1366
if (kstrtou8_from_user(user_buf, count, 0, &enable))
1367
return -EINVAL;
1368
1369
mutex_lock(&ar->conf_mutex);
1370
1371
if (ar->ani_enabled == enable) {
1372
ret = count;
1373
goto exit;
1374
}
1375
1376
ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->ani_enable,
1377
enable);
1378
if (ret) {
1379
ath10k_warn(ar, "ani_enable failed from debugfs: %d\n", ret);
1380
goto exit;
1381
}
1382
ar->ani_enabled = enable;
1383
1384
ret = count;
1385
1386
exit:
1387
mutex_unlock(&ar->conf_mutex);
1388
1389
return ret;
1390
}
1391
1392
static ssize_t ath10k_read_ani_enable(struct file *file, char __user *user_buf,
1393
size_t count, loff_t *ppos)
1394
{
1395
struct ath10k *ar = file->private_data;
1396
size_t len;
1397
char buf[32];
1398
1399
len = scnprintf(buf, sizeof(buf), "%d\n", ar->ani_enabled);
1400
1401
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1402
}
1403
1404
static const struct file_operations fops_ani_enable = {
1405
.read = ath10k_read_ani_enable,
1406
.write = ath10k_write_ani_enable,
1407
.open = simple_open,
1408
.owner = THIS_MODULE,
1409
.llseek = default_llseek,
1410
};
1411
1412
static const struct file_operations fops_cal_data = {
1413
.open = ath10k_debug_cal_data_open,
1414
.read = ath10k_debug_cal_data_read,
1415
.owner = THIS_MODULE,
1416
.llseek = default_llseek,
1417
};
1418
1419
static ssize_t ath10k_read_nf_cal_period(struct file *file,
1420
char __user *user_buf,
1421
size_t count, loff_t *ppos)
1422
{
1423
struct ath10k *ar = file->private_data;
1424
size_t len;
1425
char buf[32];
1426
1427
len = scnprintf(buf, sizeof(buf), "%d\n", ar->debug.nf_cal_period);
1428
1429
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1430
}
1431
1432
static ssize_t ath10k_write_nf_cal_period(struct file *file,
1433
const char __user *user_buf,
1434
size_t count, loff_t *ppos)
1435
{
1436
struct ath10k *ar = file->private_data;
1437
unsigned long period;
1438
int ret;
1439
1440
ret = kstrtoul_from_user(user_buf, count, 0, &period);
1441
if (ret)
1442
return ret;
1443
1444
if (period > WMI_PDEV_PARAM_CAL_PERIOD_MAX)
1445
return -EINVAL;
1446
1447
/* there's no way to switch back to the firmware default */
1448
if (period == 0)
1449
return -EINVAL;
1450
1451
mutex_lock(&ar->conf_mutex);
1452
1453
ar->debug.nf_cal_period = period;
1454
1455
if (ar->state != ATH10K_STATE_ON) {
1456
/* firmware is not running, nothing else to do */
1457
ret = count;
1458
goto exit;
1459
}
1460
1461
ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->cal_period,
1462
ar->debug.nf_cal_period);
1463
if (ret) {
1464
ath10k_warn(ar, "cal period cfg failed from debugfs: %d\n",
1465
ret);
1466
goto exit;
1467
}
1468
1469
ret = count;
1470
1471
exit:
1472
mutex_unlock(&ar->conf_mutex);
1473
1474
return ret;
1475
}
1476
1477
static const struct file_operations fops_nf_cal_period = {
1478
.read = ath10k_read_nf_cal_period,
1479
.write = ath10k_write_nf_cal_period,
1480
.open = simple_open,
1481
.owner = THIS_MODULE,
1482
.llseek = default_llseek,
1483
};
1484
1485
#define ATH10K_TPC_CONFIG_BUF_SIZE (1024 * 1024)
1486
1487
static int ath10k_debug_tpc_stats_request(struct ath10k *ar)
1488
{
1489
int ret;
1490
unsigned long time_left;
1491
1492
lockdep_assert_held(&ar->conf_mutex);
1493
1494
reinit_completion(&ar->debug.tpc_complete);
1495
1496
ret = ath10k_wmi_pdev_get_tpc_config(ar, WMI_TPC_CONFIG_PARAM);
1497
if (ret) {
1498
ath10k_warn(ar, "failed to request tpc config: %d\n", ret);
1499
return ret;
1500
}
1501
1502
time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
1503
1 * HZ);
1504
if (time_left == 0)
1505
return -ETIMEDOUT;
1506
1507
return 0;
1508
}
1509
1510
void ath10k_debug_tpc_stats_process(struct ath10k *ar,
1511
struct ath10k_tpc_stats *tpc_stats)
1512
{
1513
spin_lock_bh(&ar->data_lock);
1514
1515
kfree(ar->debug.tpc_stats);
1516
ar->debug.tpc_stats = tpc_stats;
1517
complete(&ar->debug.tpc_complete);
1518
1519
spin_unlock_bh(&ar->data_lock);
1520
}
1521
1522
void
1523
ath10k_debug_tpc_stats_final_process(struct ath10k *ar,
1524
struct ath10k_tpc_stats_final *tpc_stats)
1525
{
1526
spin_lock_bh(&ar->data_lock);
1527
1528
kfree(ar->debug.tpc_stats_final);
1529
ar->debug.tpc_stats_final = tpc_stats;
1530
complete(&ar->debug.tpc_complete);
1531
1532
spin_unlock_bh(&ar->data_lock);
1533
}
1534
1535
static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
1536
unsigned int j, char *buf, size_t *len)
1537
{
1538
int i;
1539
size_t buf_len;
1540
static const char table_str[][5] = { "CDD",
1541
"STBC",
1542
"TXBF" };
1543
static const char pream_str[][6] = { "CCK",
1544
"OFDM",
1545
"HT20",
1546
"HT40",
1547
"VHT20",
1548
"VHT40",
1549
"VHT80",
1550
"HTCUP" };
1551
1552
buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1553
*len += scnprintf(buf + *len, buf_len - *len,
1554
"********************************\n");
1555
*len += scnprintf(buf + *len, buf_len - *len,
1556
"******************* %s POWER TABLE ****************\n",
1557
table_str[j]);
1558
*len += scnprintf(buf + *len, buf_len - *len,
1559
"********************************\n");
1560
*len += scnprintf(buf + *len, buf_len - *len,
1561
"No. Preamble Rate_code ");
1562
1563
for (i = 0; i < tpc_stats->num_tx_chain; i++)
1564
*len += scnprintf(buf + *len, buf_len - *len,
1565
"tpc_value%d ", i);
1566
1567
*len += scnprintf(buf + *len, buf_len - *len, "\n");
1568
1569
for (i = 0; i < tpc_stats->rate_max; i++) {
1570
*len += scnprintf(buf + *len, buf_len - *len,
1571
"%8d %s 0x%2x %s\n", i,
1572
pream_str[tpc_stats->tpc_table[j].pream_idx[i]],
1573
tpc_stats->tpc_table[j].rate_code[i],
1574
tpc_stats->tpc_table[j].tpc_value[i]);
1575
}
1576
1577
*len += scnprintf(buf + *len, buf_len - *len,
1578
"***********************************\n");
1579
}
1580
1581
static void ath10k_tpc_stats_fill(struct ath10k *ar,
1582
struct ath10k_tpc_stats *tpc_stats,
1583
char *buf)
1584
{
1585
int j;
1586
size_t len, buf_len;
1587
1588
len = 0;
1589
buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1590
1591
spin_lock_bh(&ar->data_lock);
1592
1593
if (!tpc_stats) {
1594
ath10k_warn(ar, "failed to get tpc stats\n");
1595
goto unlock;
1596
}
1597
1598
len += scnprintf(buf + len, buf_len - len, "\n");
1599
len += scnprintf(buf + len, buf_len - len,
1600
"*************************************\n");
1601
len += scnprintf(buf + len, buf_len - len,
1602
"TPC config for channel %4d mode %d\n",
1603
tpc_stats->chan_freq,
1604
tpc_stats->phy_mode);
1605
len += scnprintf(buf + len, buf_len - len,
1606
"*************************************\n");
1607
len += scnprintf(buf + len, buf_len - len,
1608
"CTL = 0x%2x Reg. Domain = %2d\n",
1609
tpc_stats->ctl,
1610
tpc_stats->reg_domain);
1611
len += scnprintf(buf + len, buf_len - len,
1612
"Antenna Gain = %2d Reg. Max Antenna Gain = %2d\n",
1613
tpc_stats->twice_antenna_gain,
1614
tpc_stats->twice_antenna_reduction);
1615
len += scnprintf(buf + len, buf_len - len,
1616
"Power Limit = %2d Reg. Max Power = %2d\n",
1617
tpc_stats->power_limit,
1618
tpc_stats->twice_max_rd_power / 2);
1619
len += scnprintf(buf + len, buf_len - len,
1620
"Num tx chains = %2d Num supported rates = %2d\n",
1621
tpc_stats->num_tx_chain,
1622
tpc_stats->rate_max);
1623
1624
for (j = 0; j < WMI_TPC_FLAG; j++) {
1625
switch (j) {
1626
case WMI_TPC_TABLE_TYPE_CDD:
1627
if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1628
len += scnprintf(buf + len, buf_len - len,
1629
"CDD not supported\n");
1630
break;
1631
}
1632
1633
ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1634
break;
1635
case WMI_TPC_TABLE_TYPE_STBC:
1636
if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1637
len += scnprintf(buf + len, buf_len - len,
1638
"STBC not supported\n");
1639
break;
1640
}
1641
1642
ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1643
break;
1644
case WMI_TPC_TABLE_TYPE_TXBF:
1645
if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1646
len += scnprintf(buf + len, buf_len - len,
1647
"TXBF not supported\n***************************\n");
1648
break;
1649
}
1650
1651
ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1652
break;
1653
default:
1654
len += scnprintf(buf + len, buf_len - len,
1655
"Invalid Type\n");
1656
break;
1657
}
1658
}
1659
1660
unlock:
1661
spin_unlock_bh(&ar->data_lock);
1662
1663
if (len >= buf_len)
1664
buf[len - 1] = 0;
1665
else
1666
buf[len] = 0;
1667
}
1668
1669
static int ath10k_tpc_stats_open(struct inode *inode, struct file *file)
1670
{
1671
struct ath10k *ar = inode->i_private;
1672
void *buf = NULL;
1673
int ret;
1674
1675
mutex_lock(&ar->conf_mutex);
1676
1677
if (ar->state != ATH10K_STATE_ON) {
1678
ret = -ENETDOWN;
1679
goto err_unlock;
1680
}
1681
1682
buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
1683
if (!buf) {
1684
ret = -ENOMEM;
1685
goto err_unlock;
1686
}
1687
1688
ret = ath10k_debug_tpc_stats_request(ar);
1689
if (ret) {
1690
ath10k_warn(ar, "failed to request tpc config stats: %d\n",
1691
ret);
1692
goto err_free;
1693
}
1694
1695
ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
1696
file->private_data = buf;
1697
1698
mutex_unlock(&ar->conf_mutex);
1699
return 0;
1700
1701
err_free:
1702
vfree(buf);
1703
1704
err_unlock:
1705
mutex_unlock(&ar->conf_mutex);
1706
return ret;
1707
}
1708
1709
static int ath10k_tpc_stats_release(struct inode *inode, struct file *file)
1710
{
1711
vfree(file->private_data);
1712
1713
return 0;
1714
}
1715
1716
static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf,
1717
size_t count, loff_t *ppos)
1718
{
1719
const char *buf = file->private_data;
1720
size_t len = strlen(buf);
1721
1722
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1723
}
1724
1725
static const struct file_operations fops_tpc_stats = {
1726
.open = ath10k_tpc_stats_open,
1727
.release = ath10k_tpc_stats_release,
1728
.read = ath10k_tpc_stats_read,
1729
.owner = THIS_MODULE,
1730
.llseek = default_llseek,
1731
};
1732
1733
int ath10k_debug_start(struct ath10k *ar)
1734
{
1735
int ret;
1736
1737
lockdep_assert_held(&ar->conf_mutex);
1738
1739
ret = ath10k_debug_htt_stats_req(ar);
1740
if (ret)
1741
/* continue normally anyway, this isn't serious */
1742
ath10k_warn(ar, "failed to start htt stats workqueue: %d\n",
1743
ret);
1744
1745
if (ar->debug.fw_dbglog_mask) {
1746
ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1747
ATH10K_DBGLOG_LEVEL_WARN);
1748
if (ret)
1749
/* not serious */
1750
ath10k_warn(ar, "failed to enable dbglog during start: %d",
1751
ret);
1752
}
1753
1754
if (ar->pktlog_filter) {
1755
ret = ath10k_wmi_pdev_pktlog_enable(ar,
1756
ar->pktlog_filter);
1757
if (ret)
1758
/* not serious */
1759
ath10k_warn(ar,
1760
"failed to enable pktlog filter %x: %d\n",
1761
ar->pktlog_filter, ret);
1762
} else {
1763
ret = ath10k_wmi_pdev_pktlog_disable(ar);
1764
if (ret)
1765
/* not serious */
1766
ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
1767
}
1768
1769
if (ar->debug.nf_cal_period &&
1770
!test_bit(ATH10K_FW_FEATURE_NON_BMI,
1771
ar->normal_mode_fw.fw_file.fw_features)) {
1772
ret = ath10k_wmi_pdev_set_param(ar,
1773
ar->wmi.pdev_param->cal_period,
1774
ar->debug.nf_cal_period);
1775
if (ret)
1776
/* not serious */
1777
ath10k_warn(ar, "cal period cfg failed from debug start: %d\n",
1778
ret);
1779
}
1780
1781
return ret;
1782
}
1783
1784
void ath10k_debug_stop(struct ath10k *ar)
1785
{
1786
lockdep_assert_held(&ar->conf_mutex);
1787
1788
if (!test_bit(ATH10K_FW_FEATURE_NON_BMI,
1789
ar->normal_mode_fw.fw_file.fw_features))
1790
ath10k_debug_cal_data_fetch(ar);
1791
1792
/* Must not use _sync to avoid deadlock, we do that in
1793
* ath10k_debug_destroy(). The check for htt_stats_mask is to avoid
1794
* warning from del_timer().
1795
*/
1796
if (ar->debug.htt_stats_mask != 0)
1797
cancel_delayed_work(&ar->debug.htt_stats_dwork);
1798
1799
ath10k_wmi_pdev_pktlog_disable(ar);
1800
}
1801
1802
static ssize_t ath10k_write_simulate_radar(struct file *file,
1803
const char __user *user_buf,
1804
size_t count, loff_t *ppos)
1805
{
1806
struct ath10k *ar = file->private_data;
1807
struct ath10k_vif *arvif;
1808
1809
/* Just check for the first vif alone, as all the vifs will be
1810
* sharing the same channel and if the channel is disabled, all the
1811
* vifs will share the same 'is_started' state.
1812
*/
1813
arvif = list_first_entry(&ar->arvifs, typeof(*arvif), list);
1814
if (!arvif->is_started)
1815
return -EINVAL;
1816
1817
ieee80211_radar_detected(ar->hw);
1818
1819
return count;
1820
}
1821
1822
static const struct file_operations fops_simulate_radar = {
1823
.write = ath10k_write_simulate_radar,
1824
.open = simple_open,
1825
.owner = THIS_MODULE,
1826
.llseek = default_llseek,
1827
};
1828
1829
#define ATH10K_DFS_STAT(s, p) (\
1830
len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
1831
ar->debug.dfs_stats.p))
1832
1833
#define ATH10K_DFS_POOL_STAT(s, p) (\
1834
len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
1835
ar->debug.dfs_pool_stats.p))
1836
1837
static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf,
1838
size_t count, loff_t *ppos)
1839
{
1840
int retval = 0, len = 0;
1841
const int size = 8000;
1842
struct ath10k *ar = file->private_data;
1843
char *buf;
1844
1845
buf = kzalloc(size, GFP_KERNEL);
1846
if (buf == NULL)
1847
return -ENOMEM;
1848
1849
if (!ar->dfs_detector) {
1850
len += scnprintf(buf + len, size - len, "DFS not enabled\n");
1851
goto exit;
1852
}
1853
1854
ar->debug.dfs_pool_stats =
1855
ar->dfs_detector->get_stats(ar->dfs_detector);
1856
1857
len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");
1858
1859
ATH10K_DFS_STAT("reported phy errors", phy_errors);
1860
ATH10K_DFS_STAT("pulse events reported", pulses_total);
1861
ATH10K_DFS_STAT("DFS pulses detected", pulses_detected);
1862
ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded);
1863
ATH10K_DFS_STAT("Radars detected", radar_detected);
1864
1865
len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");
1866
ATH10K_DFS_POOL_STAT("Pool references", pool_reference);
1867
ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated);
1868
ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error);
1869
ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used);
1870
ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated);
1871
ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error);
1872
ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used);
1873
1874
exit:
1875
if (len > size)
1876
len = size;
1877
1878
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1879
kfree(buf);
1880
1881
return retval;
1882
}
1883
1884
static const struct file_operations fops_dfs_stats = {
1885
.read = ath10k_read_dfs_stats,
1886
.open = simple_open,
1887
.owner = THIS_MODULE,
1888
.llseek = default_llseek,
1889
};
1890
1891
static ssize_t ath10k_write_pktlog_filter(struct file *file,
1892
const char __user *ubuf,
1893
size_t count, loff_t *ppos)
1894
{
1895
struct ath10k *ar = file->private_data;
1896
u32 filter;
1897
int ret;
1898
1899
if (kstrtouint_from_user(ubuf, count, 0, &filter))
1900
return -EINVAL;
1901
1902
mutex_lock(&ar->conf_mutex);
1903
1904
if (ar->state != ATH10K_STATE_ON) {
1905
ar->pktlog_filter = filter;
1906
ret = count;
1907
goto out;
1908
}
1909
1910
if (filter == ar->pktlog_filter) {
1911
ret = count;
1912
goto out;
1913
}
1914
1915
if (filter) {
1916
ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
1917
if (ret) {
1918
ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
1919
ar->pktlog_filter, ret);
1920
goto out;
1921
}
1922
} else {
1923
ret = ath10k_wmi_pdev_pktlog_disable(ar);
1924
if (ret) {
1925
ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
1926
goto out;
1927
}
1928
}
1929
1930
ar->pktlog_filter = filter;
1931
ret = count;
1932
1933
out:
1934
mutex_unlock(&ar->conf_mutex);
1935
return ret;
1936
}
1937
1938
static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf,
1939
size_t count, loff_t *ppos)
1940
{
1941
char buf[32];
1942
struct ath10k *ar = file->private_data;
1943
int len = 0;
1944
1945
mutex_lock(&ar->conf_mutex);
1946
len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
1947
ar->pktlog_filter);
1948
mutex_unlock(&ar->conf_mutex);
1949
1950
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1951
}
1952
1953
static const struct file_operations fops_pktlog_filter = {
1954
.read = ath10k_read_pktlog_filter,
1955
.write = ath10k_write_pktlog_filter,
1956
.open = simple_open
1957
};
1958
1959
static ssize_t ath10k_write_quiet_period(struct file *file,
1960
const char __user *ubuf,
1961
size_t count, loff_t *ppos)
1962
{
1963
struct ath10k *ar = file->private_data;
1964
u32 period;
1965
1966
if (kstrtouint_from_user(ubuf, count, 0, &period))
1967
return -EINVAL;
1968
1969
if (period < ATH10K_QUIET_PERIOD_MIN) {
1970
ath10k_warn(ar, "Quiet period %u can not be lesser than 25ms\n",
1971
period);
1972
return -EINVAL;
1973
}
1974
mutex_lock(&ar->conf_mutex);
1975
ar->thermal.quiet_period = period;
1976
ath10k_thermal_set_throttling(ar);
1977
mutex_unlock(&ar->conf_mutex);
1978
1979
return count;
1980
}
1981
1982
static ssize_t ath10k_read_quiet_period(struct file *file, char __user *ubuf,
1983
size_t count, loff_t *ppos)
1984
{
1985
char buf[32];
1986
struct ath10k *ar = file->private_data;
1987
int len = 0;
1988
1989
mutex_lock(&ar->conf_mutex);
1990
len = scnprintf(buf, sizeof(buf) - len, "%d\n",
1991
ar->thermal.quiet_period);
1992
mutex_unlock(&ar->conf_mutex);
1993
1994
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1995
}
1996
1997
static const struct file_operations fops_quiet_period = {
1998
.read = ath10k_read_quiet_period,
1999
.write = ath10k_write_quiet_period,
2000
.open = simple_open
2001
};
2002
2003
static ssize_t ath10k_write_btcoex(struct file *file,
2004
const char __user *ubuf,
2005
size_t count, loff_t *ppos)
2006
{
2007
struct ath10k *ar = file->private_data;
2008
char buf[32];
2009
size_t buf_size;
2010
int ret;
2011
bool val;
2012
u32 pdev_param;
2013
2014
buf_size = min(count, (sizeof(buf) - 1));
2015
if (copy_from_user(buf, ubuf, buf_size))
2016
return -EFAULT;
2017
2018
buf[buf_size] = '\0';
2019
2020
if (kstrtobool(buf, &val) != 0)
2021
return -EINVAL;
2022
2023
if (!ar->coex_support)
2024
return -EOPNOTSUPP;
2025
2026
mutex_lock(&ar->conf_mutex);
2027
2028
if (ar->state != ATH10K_STATE_ON &&
2029
ar->state != ATH10K_STATE_RESTARTED) {
2030
ret = -ENETDOWN;
2031
goto exit;
2032
}
2033
2034
if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) {
2035
ret = count;
2036
goto exit;
2037
}
2038
2039
pdev_param = ar->wmi.pdev_param->enable_btcoex;
2040
if (test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM,
2041
ar->running_fw->fw_file.fw_features)) {
2042
ret = ath10k_wmi_pdev_set_param(ar, pdev_param, val);
2043
if (ret) {
2044
ath10k_warn(ar, "failed to enable btcoex: %d\n", ret);
2045
ret = count;
2046
goto exit;
2047
}
2048
} else {
2049
ath10k_info(ar, "restarting firmware due to btcoex change");
2050
ath10k_core_start_recovery(ar);
2051
}
2052
2053
if (val)
2054
set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
2055
else
2056
clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
2057
2058
ret = count;
2059
2060
exit:
2061
mutex_unlock(&ar->conf_mutex);
2062
2063
return ret;
2064
}
2065
2066
static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
2067
size_t count, loff_t *ppos)
2068
{
2069
char buf[32];
2070
struct ath10k *ar = file->private_data;
2071
int len = 0;
2072
2073
mutex_lock(&ar->conf_mutex);
2074
len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2075
test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));
2076
mutex_unlock(&ar->conf_mutex);
2077
2078
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2079
}
2080
2081
static const struct file_operations fops_btcoex = {
2082
.read = ath10k_read_btcoex,
2083
.write = ath10k_write_btcoex,
2084
.open = simple_open
2085
};
2086
2087
static ssize_t ath10k_write_enable_extd_tx_stats(struct file *file,
2088
const char __user *ubuf,
2089
size_t count, loff_t *ppos)
2090
{
2091
struct ath10k *ar = file->private_data;
2092
u32 filter;
2093
int ret;
2094
2095
if (kstrtouint_from_user(ubuf, count, 0, &filter))
2096
return -EINVAL;
2097
2098
mutex_lock(&ar->conf_mutex);
2099
2100
if (ar->state != ATH10K_STATE_ON) {
2101
ar->debug.enable_extd_tx_stats = filter;
2102
ret = count;
2103
goto out;
2104
}
2105
2106
if (filter == ar->debug.enable_extd_tx_stats) {
2107
ret = count;
2108
goto out;
2109
}
2110
2111
ar->debug.enable_extd_tx_stats = filter;
2112
ret = count;
2113
2114
out:
2115
mutex_unlock(&ar->conf_mutex);
2116
return ret;
2117
}
2118
2119
static ssize_t ath10k_read_enable_extd_tx_stats(struct file *file,
2120
char __user *ubuf,
2121
size_t count, loff_t *ppos)
2122
2123
{
2124
char buf[32];
2125
struct ath10k *ar = file->private_data;
2126
int len = 0;
2127
2128
mutex_lock(&ar->conf_mutex);
2129
len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
2130
ar->debug.enable_extd_tx_stats);
2131
mutex_unlock(&ar->conf_mutex);
2132
2133
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2134
}
2135
2136
static const struct file_operations fops_enable_extd_tx_stats = {
2137
.read = ath10k_read_enable_extd_tx_stats,
2138
.write = ath10k_write_enable_extd_tx_stats,
2139
.open = simple_open
2140
};
2141
2142
static ssize_t ath10k_write_peer_stats(struct file *file,
2143
const char __user *ubuf,
2144
size_t count, loff_t *ppos)
2145
{
2146
struct ath10k *ar = file->private_data;
2147
char buf[32];
2148
size_t buf_size;
2149
int ret;
2150
bool val;
2151
2152
buf_size = min(count, (sizeof(buf) - 1));
2153
if (copy_from_user(buf, ubuf, buf_size))
2154
return -EFAULT;
2155
2156
buf[buf_size] = '\0';
2157
2158
if (kstrtobool(buf, &val) != 0)
2159
return -EINVAL;
2160
2161
mutex_lock(&ar->conf_mutex);
2162
2163
if (ar->state != ATH10K_STATE_ON &&
2164
ar->state != ATH10K_STATE_RESTARTED) {
2165
ret = -ENETDOWN;
2166
goto exit;
2167
}
2168
2169
if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val)) {
2170
ret = count;
2171
goto exit;
2172
}
2173
2174
if (val)
2175
set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
2176
else
2177
clear_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
2178
2179
ath10k_info(ar, "restarting firmware due to Peer stats change");
2180
2181
ath10k_core_start_recovery(ar);
2182
ret = count;
2183
2184
exit:
2185
mutex_unlock(&ar->conf_mutex);
2186
return ret;
2187
}
2188
2189
static ssize_t ath10k_read_peer_stats(struct file *file, char __user *ubuf,
2190
size_t count, loff_t *ppos)
2191
2192
{
2193
char buf[32];
2194
struct ath10k *ar = file->private_data;
2195
int len = 0;
2196
2197
mutex_lock(&ar->conf_mutex);
2198
len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2199
test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags));
2200
mutex_unlock(&ar->conf_mutex);
2201
2202
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2203
}
2204
2205
static const struct file_operations fops_peer_stats = {
2206
.read = ath10k_read_peer_stats,
2207
.write = ath10k_write_peer_stats,
2208
.open = simple_open
2209
};
2210
2211
static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
2212
char __user *user_buf,
2213
size_t count, loff_t *ppos)
2214
{
2215
struct ath10k *ar = file->private_data;
2216
size_t len = 0, buf_len = 4096;
2217
ssize_t ret_cnt;
2218
char *buf;
2219
2220
buf = kzalloc(buf_len, GFP_KERNEL);
2221
if (!buf)
2222
return -ENOMEM;
2223
2224
mutex_lock(&ar->conf_mutex);
2225
2226
len += scnprintf(buf + len, buf_len - len,
2227
"firmware-N.bin\t\t%08x\n",
2228
crc32_le(0, ar->normal_mode_fw.fw_file.firmware->data,
2229
ar->normal_mode_fw.fw_file.firmware->size));
2230
len += scnprintf(buf + len, buf_len - len,
2231
"athwlan\t\t\t%08x\n",
2232
crc32_le(0, ar->normal_mode_fw.fw_file.firmware_data,
2233
ar->normal_mode_fw.fw_file.firmware_len));
2234
len += scnprintf(buf + len, buf_len - len,
2235
"otp\t\t\t%08x\n",
2236
crc32_le(0, ar->normal_mode_fw.fw_file.otp_data,
2237
ar->normal_mode_fw.fw_file.otp_len));
2238
len += scnprintf(buf + len, buf_len - len,
2239
"codeswap\t\t%08x\n",
2240
crc32_le(0, ar->normal_mode_fw.fw_file.codeswap_data,
2241
ar->normal_mode_fw.fw_file.codeswap_len));
2242
len += scnprintf(buf + len, buf_len - len,
2243
"board-N.bin\t\t%08x\n",
2244
crc32_le(0, ar->normal_mode_fw.board->data,
2245
ar->normal_mode_fw.board->size));
2246
len += scnprintf(buf + len, buf_len - len,
2247
"board\t\t\t%08x\n",
2248
crc32_le(0, ar->normal_mode_fw.board_data,
2249
ar->normal_mode_fw.board_len));
2250
2251
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
2252
2253
mutex_unlock(&ar->conf_mutex);
2254
2255
kfree(buf);
2256
return ret_cnt;
2257
}
2258
2259
static const struct file_operations fops_fw_checksums = {
2260
.read = ath10k_debug_fw_checksums_read,
2261
.open = simple_open,
2262
.owner = THIS_MODULE,
2263
.llseek = default_llseek,
2264
};
2265
2266
static ssize_t ath10k_sta_tid_stats_mask_read(struct file *file,
2267
char __user *user_buf,
2268
size_t count, loff_t *ppos)
2269
{
2270
struct ath10k *ar = file->private_data;
2271
char buf[32];
2272
size_t len;
2273
2274
len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->sta_tid_stats_mask);
2275
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
2276
}
2277
2278
static ssize_t ath10k_sta_tid_stats_mask_write(struct file *file,
2279
const char __user *user_buf,
2280
size_t count, loff_t *ppos)
2281
{
2282
struct ath10k *ar = file->private_data;
2283
char buf[32];
2284
ssize_t len;
2285
u32 mask;
2286
2287
len = min(count, sizeof(buf) - 1);
2288
if (copy_from_user(buf, user_buf, len))
2289
return -EFAULT;
2290
2291
buf[len] = '\0';
2292
if (kstrtoint(buf, 0, &mask))
2293
return -EINVAL;
2294
2295
ar->sta_tid_stats_mask = mask;
2296
2297
return len;
2298
}
2299
2300
static const struct file_operations fops_sta_tid_stats_mask = {
2301
.read = ath10k_sta_tid_stats_mask_read,
2302
.write = ath10k_sta_tid_stats_mask_write,
2303
.open = simple_open,
2304
.owner = THIS_MODULE,
2305
.llseek = default_llseek,
2306
};
2307
2308
static int ath10k_debug_tpc_stats_final_request(struct ath10k *ar)
2309
{
2310
int ret;
2311
unsigned long time_left;
2312
2313
lockdep_assert_held(&ar->conf_mutex);
2314
2315
reinit_completion(&ar->debug.tpc_complete);
2316
2317
ret = ath10k_wmi_pdev_get_tpc_table_cmdid(ar, WMI_TPC_CONFIG_PARAM);
2318
if (ret) {
2319
ath10k_warn(ar, "failed to request tpc table cmdid: %d\n", ret);
2320
return ret;
2321
}
2322
2323
time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
2324
1 * HZ);
2325
if (time_left == 0)
2326
return -ETIMEDOUT;
2327
2328
return 0;
2329
}
2330
2331
static int ath10k_tpc_stats_final_open(struct inode *inode, struct file *file)
2332
{
2333
struct ath10k *ar = inode->i_private;
2334
void *buf;
2335
int ret;
2336
2337
mutex_lock(&ar->conf_mutex);
2338
2339
if (ar->state != ATH10K_STATE_ON) {
2340
ret = -ENETDOWN;
2341
goto err_unlock;
2342
}
2343
2344
buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
2345
if (!buf) {
2346
ret = -ENOMEM;
2347
goto err_unlock;
2348
}
2349
2350
ret = ath10k_debug_tpc_stats_final_request(ar);
2351
if (ret) {
2352
ath10k_warn(ar, "failed to request tpc stats final: %d\n",
2353
ret);
2354
goto err_free;
2355
}
2356
2357
ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
2358
file->private_data = buf;
2359
2360
mutex_unlock(&ar->conf_mutex);
2361
return 0;
2362
2363
err_free:
2364
vfree(buf);
2365
2366
err_unlock:
2367
mutex_unlock(&ar->conf_mutex);
2368
return ret;
2369
}
2370
2371
static int ath10k_tpc_stats_final_release(struct inode *inode,
2372
struct file *file)
2373
{
2374
vfree(file->private_data);
2375
2376
return 0;
2377
}
2378
2379
static ssize_t ath10k_tpc_stats_final_read(struct file *file,
2380
char __user *user_buf,
2381
size_t count, loff_t *ppos)
2382
{
2383
const char *buf = file->private_data;
2384
unsigned int len = strlen(buf);
2385
2386
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
2387
}
2388
2389
static const struct file_operations fops_tpc_stats_final = {
2390
.open = ath10k_tpc_stats_final_open,
2391
.release = ath10k_tpc_stats_final_release,
2392
.read = ath10k_tpc_stats_final_read,
2393
.owner = THIS_MODULE,
2394
.llseek = default_llseek,
2395
};
2396
2397
static ssize_t ath10k_write_warm_hw_reset(struct file *file,
2398
const char __user *user_buf,
2399
size_t count, loff_t *ppos)
2400
{
2401
struct ath10k *ar = file->private_data;
2402
int ret;
2403
bool val;
2404
2405
if (kstrtobool_from_user(user_buf, count, &val))
2406
return -EFAULT;
2407
2408
if (!val)
2409
return -EINVAL;
2410
2411
mutex_lock(&ar->conf_mutex);
2412
2413
if (ar->state != ATH10K_STATE_ON) {
2414
ret = -ENETDOWN;
2415
goto exit;
2416
}
2417
2418
ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pdev_reset,
2419
WMI_RST_MODE_WARM_RESET);
2420
2421
if (ret) {
2422
ath10k_warn(ar, "failed to enable warm hw reset: %d\n", ret);
2423
goto exit;
2424
}
2425
2426
ret = count;
2427
2428
exit:
2429
mutex_unlock(&ar->conf_mutex);
2430
return ret;
2431
}
2432
2433
static const struct file_operations fops_warm_hw_reset = {
2434
.write = ath10k_write_warm_hw_reset,
2435
.open = simple_open,
2436
.owner = THIS_MODULE,
2437
.llseek = default_llseek,
2438
};
2439
2440
static void ath10k_peer_ps_state_disable(void *data,
2441
struct ieee80211_sta *sta)
2442
{
2443
struct ath10k *ar = data;
2444
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
2445
2446
spin_lock_bh(&ar->data_lock);
2447
arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
2448
spin_unlock_bh(&ar->data_lock);
2449
}
2450
2451
static ssize_t ath10k_write_ps_state_enable(struct file *file,
2452
const char __user *user_buf,
2453
size_t count, loff_t *ppos)
2454
{
2455
struct ath10k *ar = file->private_data;
2456
int ret;
2457
u32 param;
2458
u8 ps_state_enable;
2459
2460
if (kstrtou8_from_user(user_buf, count, 0, &ps_state_enable))
2461
return -EINVAL;
2462
2463
if (ps_state_enable > 1)
2464
return -EINVAL;
2465
2466
mutex_lock(&ar->conf_mutex);
2467
2468
if (ar->ps_state_enable == ps_state_enable) {
2469
ret = count;
2470
goto exit;
2471
}
2472
2473
param = ar->wmi.pdev_param->peer_sta_ps_statechg_enable;
2474
ret = ath10k_wmi_pdev_set_param(ar, param, ps_state_enable);
2475
if (ret) {
2476
ath10k_warn(ar, "failed to enable ps_state_enable: %d\n",
2477
ret);
2478
goto exit;
2479
}
2480
ar->ps_state_enable = ps_state_enable;
2481
2482
if (!ar->ps_state_enable)
2483
ieee80211_iterate_stations_atomic(ar->hw,
2484
ath10k_peer_ps_state_disable,
2485
ar);
2486
2487
ret = count;
2488
2489
exit:
2490
mutex_unlock(&ar->conf_mutex);
2491
2492
return ret;
2493
}
2494
2495
static ssize_t ath10k_read_ps_state_enable(struct file *file,
2496
char __user *user_buf,
2497
size_t count, loff_t *ppos)
2498
{
2499
struct ath10k *ar = file->private_data;
2500
int len = 0;
2501
char buf[32];
2502
2503
mutex_lock(&ar->conf_mutex);
2504
len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2505
ar->ps_state_enable);
2506
mutex_unlock(&ar->conf_mutex);
2507
2508
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
2509
}
2510
2511
static const struct file_operations fops_ps_state_enable = {
2512
.read = ath10k_read_ps_state_enable,
2513
.write = ath10k_write_ps_state_enable,
2514
.open = simple_open,
2515
.owner = THIS_MODULE,
2516
.llseek = default_llseek,
2517
};
2518
2519
static ssize_t ath10k_write_reset_htt_stats(struct file *file,
2520
const char __user *user_buf,
2521
size_t count, loff_t *ppos)
2522
{
2523
struct ath10k *ar = file->private_data;
2524
unsigned long reset;
2525
int ret;
2526
2527
ret = kstrtoul_from_user(user_buf, count, 0, &reset);
2528
if (ret)
2529
return ret;
2530
2531
if (reset == 0 || reset > 0x1ffff)
2532
return -EINVAL;
2533
2534
mutex_lock(&ar->conf_mutex);
2535
2536
ar->debug.reset_htt_stats = reset;
2537
2538
ret = ath10k_debug_htt_stats_req(ar);
2539
if (ret)
2540
goto out;
2541
2542
ar->debug.reset_htt_stats = 0;
2543
ret = count;
2544
2545
out:
2546
mutex_unlock(&ar->conf_mutex);
2547
return ret;
2548
}
2549
2550
static const struct file_operations fops_reset_htt_stats = {
2551
.write = ath10k_write_reset_htt_stats,
2552
.owner = THIS_MODULE,
2553
.open = simple_open,
2554
.llseek = default_llseek,
2555
};
2556
2557
int ath10k_debug_create(struct ath10k *ar)
2558
{
2559
ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
2560
if (!ar->debug.cal_data)
2561
return -ENOMEM;
2562
2563
INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
2564
INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
2565
INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
2566
INIT_LIST_HEAD(&ar->debug.fw_stats.peers_extd);
2567
2568
return 0;
2569
}
2570
2571
void ath10k_debug_destroy(struct ath10k *ar)
2572
{
2573
vfree(ar->debug.cal_data);
2574
ar->debug.cal_data = NULL;
2575
2576
ath10k_debug_fw_stats_reset(ar);
2577
2578
kfree(ar->debug.tpc_stats);
2579
kfree(ar->debug.tpc_stats_final);
2580
}
2581
2582
int ath10k_debug_register(struct ath10k *ar)
2583
{
2584
ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
2585
ar->hw->wiphy->debugfsdir);
2586
if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
2587
if (IS_ERR(ar->debug.debugfs_phy))
2588
return PTR_ERR(ar->debug.debugfs_phy);
2589
2590
return -ENOMEM;
2591
}
2592
2593
INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
2594
ath10k_debug_htt_stats_dwork);
2595
2596
init_completion(&ar->debug.tpc_complete);
2597
init_completion(&ar->debug.fw_stats_complete);
2598
2599
debugfs_create_file("fw_stats", 0400, ar->debug.debugfs_phy, ar,
2600
&fops_fw_stats);
2601
2602
debugfs_create_file("fw_reset_stats", 0400, ar->debug.debugfs_phy, ar,
2603
&fops_fw_reset_stats);
2604
2605
debugfs_create_file("wmi_services", 0400, ar->debug.debugfs_phy, ar,
2606
&fops_wmi_services);
2607
2608
debugfs_create_file("simulate_fw_crash", 0600, ar->debug.debugfs_phy, ar,
2609
&fops_simulate_fw_crash);
2610
2611
debugfs_create_file("reg_addr", 0600, ar->debug.debugfs_phy, ar,
2612
&fops_reg_addr);
2613
2614
debugfs_create_file("reg_value", 0600, ar->debug.debugfs_phy, ar,
2615
&fops_reg_value);
2616
2617
debugfs_create_file("mem_value", 0600, ar->debug.debugfs_phy, ar,
2618
&fops_mem_value);
2619
2620
debugfs_create_file("chip_id", 0400, ar->debug.debugfs_phy, ar,
2621
&fops_chip_id);
2622
2623
debugfs_create_file("htt_stats_mask", 0600, ar->debug.debugfs_phy, ar,
2624
&fops_htt_stats_mask);
2625
2626
debugfs_create_file("htt_max_amsdu_ampdu", 0600, ar->debug.debugfs_phy, ar,
2627
&fops_htt_max_amsdu_ampdu);
2628
2629
debugfs_create_file("fw_dbglog", 0600, ar->debug.debugfs_phy, ar,
2630
&fops_fw_dbglog);
2631
2632
if (!test_bit(ATH10K_FW_FEATURE_NON_BMI,
2633
ar->normal_mode_fw.fw_file.fw_features)) {
2634
debugfs_create_file("cal_data", 0400, ar->debug.debugfs_phy, ar,
2635
&fops_cal_data);
2636
2637
debugfs_create_file("nf_cal_period", 0600, ar->debug.debugfs_phy, ar,
2638
&fops_nf_cal_period);
2639
}
2640
2641
debugfs_create_file("ani_enable", 0600, ar->debug.debugfs_phy, ar,
2642
&fops_ani_enable);
2643
2644
if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {
2645
debugfs_create_file("dfs_simulate_radar", 0200, ar->debug.debugfs_phy,
2646
ar, &fops_simulate_radar);
2647
2648
debugfs_create_bool("dfs_block_radar_events", 0200,
2649
ar->debug.debugfs_phy,
2650
&ar->dfs_block_radar_events);
2651
2652
debugfs_create_file("dfs_stats", 0400, ar->debug.debugfs_phy, ar,
2653
&fops_dfs_stats);
2654
}
2655
2656
debugfs_create_file("pktlog_filter", 0644, ar->debug.debugfs_phy, ar,
2657
&fops_pktlog_filter);
2658
2659
if (test_bit(WMI_SERVICE_THERM_THROT, ar->wmi.svc_map))
2660
debugfs_create_file("quiet_period", 0644, ar->debug.debugfs_phy, ar,
2661
&fops_quiet_period);
2662
2663
debugfs_create_file("tpc_stats", 0400, ar->debug.debugfs_phy, ar,
2664
&fops_tpc_stats);
2665
2666
if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
2667
debugfs_create_file("btcoex", 0644, ar->debug.debugfs_phy, ar,
2668
&fops_btcoex);
2669
2670
if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) {
2671
debugfs_create_file("peer_stats", 0644, ar->debug.debugfs_phy, ar,
2672
&fops_peer_stats);
2673
2674
debugfs_create_file("enable_extd_tx_stats", 0644,
2675
ar->debug.debugfs_phy, ar,
2676
&fops_enable_extd_tx_stats);
2677
}
2678
2679
debugfs_create_file("fw_checksums", 0400, ar->debug.debugfs_phy, ar,
2680
&fops_fw_checksums);
2681
2682
if (IS_ENABLED(CONFIG_MAC80211_DEBUGFS))
2683
debugfs_create_file("sta_tid_stats_mask", 0600,
2684
ar->debug.debugfs_phy,
2685
ar, &fops_sta_tid_stats_mask);
2686
2687
if (test_bit(WMI_SERVICE_TPC_STATS_FINAL, ar->wmi.svc_map))
2688
debugfs_create_file("tpc_stats_final", 0400,
2689
ar->debug.debugfs_phy, ar,
2690
&fops_tpc_stats_final);
2691
2692
if (test_bit(WMI_SERVICE_RESET_CHIP, ar->wmi.svc_map))
2693
debugfs_create_file("warm_hw_reset", 0600,
2694
ar->debug.debugfs_phy, ar,
2695
&fops_warm_hw_reset);
2696
2697
debugfs_create_file("ps_state_enable", 0600, ar->debug.debugfs_phy, ar,
2698
&fops_ps_state_enable);
2699
2700
debugfs_create_file("reset_htt_stats", 0200, ar->debug.debugfs_phy, ar,
2701
&fops_reset_htt_stats);
2702
2703
return 0;
2704
}
2705
2706
void ath10k_debug_unregister(struct ath10k *ar)
2707
{
2708
cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
2709
}
2710
2711
#endif /* CONFIG_ATH10K_DEBUGFS */
2712
2713
#ifdef CONFIG_ATH10K_DEBUG
2714
void __ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
2715
const char *fmt, ...)
2716
{
2717
struct va_format vaf;
2718
va_list args;
2719
2720
va_start(args, fmt);
2721
2722
vaf.fmt = fmt;
2723
vaf.va = &args;
2724
2725
if (ath10k_debug_mask & mask)
2726
#if defined(__linux__)
2727
dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);
2728
#elif defined(__FreeBSD__)
2729
{
2730
char *str;
2731
vasprintf(&str, M_KMALLOC, fmt, args);
2732
dev_printk(KERN_DEBUG, ar->dev, "%s", str);
2733
free(str, M_KMALLOC);
2734
}
2735
#endif
2736
2737
trace_ath10k_log_dbg(ar, mask, &vaf);
2738
2739
va_end(args);
2740
}
2741
EXPORT_SYMBOL(__ath10k_dbg);
2742
2743
void ath10k_dbg_dump(struct ath10k *ar,
2744
enum ath10k_debug_mask mask,
2745
const char *msg, const char *prefix,
2746
const void *buf, size_t len)
2747
{
2748
#if defined(__linux__)
2749
char linebuf[256];
2750
size_t linebuflen;
2751
const void *ptr;
2752
#elif defined(__FreeBSD__)
2753
struct sbuf *sb;
2754
int rc;
2755
#endif
2756
2757
if (ath10k_debug_mask & mask) {
2758
if (msg)
2759
__ath10k_dbg(ar, mask, "%s\n", msg);
2760
2761
#if defined(__linux__)
2762
for (ptr = buf; (ptr - buf) < len; ptr += 16) {
2763
linebuflen = 0;
2764
linebuflen += scnprintf(linebuf + linebuflen,
2765
sizeof(linebuf) - linebuflen,
2766
"%s%08x: ",
2767
(prefix ? prefix : ""),
2768
(unsigned int)(ptr - buf));
2769
hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
2770
linebuf + linebuflen,
2771
sizeof(linebuf) - linebuflen, true);
2772
dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
2773
}
2774
#elif defined(__FreeBSD__)
2775
sb = sbuf_new_auto();
2776
if (sb == NULL)
2777
goto trace;
2778
2779
sbuf_hexdump(sb, buf, len, prefix, 0);
2780
sbuf_trim(sb);
2781
rc = sbuf_finish(sb);
2782
if (rc == 0)
2783
dev_printk(KERN_DEBUG, ar->dev, "%s\n", sbuf_data(sb));
2784
sbuf_delete(sb);
2785
trace: ;
2786
#endif
2787
}
2788
2789
/* tracing code doesn't like null strings :/ */
2790
trace_ath10k_log_dbg_dump(ar, msg ? msg : "", prefix ? prefix : "",
2791
buf, len);
2792
}
2793
EXPORT_SYMBOL(ath10k_dbg_dump);
2794
2795
#endif /* CONFIG_ATH10K_DEBUG */
2796
2797