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