1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3 * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
4 */
5
6 #include "debugfs.h"
7
8 #include "core.h"
9 #include "debug.h"
10 #include "wmi.h"
11 #include "hal_rx.h"
12 #include "dp_tx.h"
13 #include "debugfs_htt_stats.h"
14 #include "peer.h"
15
16 static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
17 "REO2SW1_RING",
18 "REO2SW2_RING",
19 "REO2SW3_RING",
20 "REO2SW4_RING",
21 "WBM2REO_LINK_RING",
22 "REO2TCL_RING",
23 "REO2FW_RING",
24 "RELEASE_RING",
25 "PPE_RELEASE_RING",
26 "TCL2TQM_RING",
27 "TQM_RELEASE_RING",
28 "REO_RELEASE_RING",
29 "WBM2SW0_RELEASE_RING",
30 "WBM2SW1_RELEASE_RING",
31 "WBM2SW2_RELEASE_RING",
32 "WBM2SW3_RELEASE_RING",
33 "REO_CMD_RING",
34 "REO_STATUS_RING",
35 };
36
37 static const char *htt_bp_lmac_ring[HTT_SW_LMAC_RING_IDX_MAX] = {
38 "FW2RXDMA_BUF_RING",
39 "FW2RXDMA_STATUS_RING",
40 "FW2RXDMA_LINK_RING",
41 "SW2RXDMA_BUF_RING",
42 "WBM2RXDMA_LINK_RING",
43 "RXDMA2FW_RING",
44 "RXDMA2SW_RING",
45 "RXDMA2RELEASE_RING",
46 "RXDMA2REO_RING",
47 "MONITOR_STATUS_RING",
48 "MONITOR_BUF_RING",
49 "MONITOR_DESC_RING",
50 "MONITOR_DEST_RING",
51 };
52
ath11k_fw_stats_pdevs_free(struct list_head * head)53 static void ath11k_fw_stats_pdevs_free(struct list_head *head)
54 {
55 struct ath11k_fw_stats_pdev *i, *tmp;
56
57 list_for_each_entry_safe(i, tmp, head, list) {
58 list_del(&i->list);
59 kfree(i);
60 }
61 }
62
ath11k_fw_stats_vdevs_free(struct list_head * head)63 static void ath11k_fw_stats_vdevs_free(struct list_head *head)
64 {
65 struct ath11k_fw_stats_vdev *i, *tmp;
66
67 list_for_each_entry_safe(i, tmp, head, list) {
68 list_del(&i->list);
69 kfree(i);
70 }
71 }
72
ath11k_fw_stats_bcn_free(struct list_head * head)73 static void ath11k_fw_stats_bcn_free(struct list_head *head)
74 {
75 struct ath11k_fw_stats_bcn *i, *tmp;
76
77 list_for_each_entry_safe(i, tmp, head, list) {
78 list_del(&i->list);
79 kfree(i);
80 }
81 }
82
ath11k_debugfs_fw_stats_reset(struct ath11k * ar)83 static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar)
84 {
85 spin_lock_bh(&ar->data_lock);
86 ar->debug.fw_stats_done = false;
87 ath11k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
88 ath11k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
89 spin_unlock_bh(&ar->data_lock);
90 }
91
ath11k_debugfs_fw_stats_process(struct ath11k_base * ab,struct sk_buff * skb)92 void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb)
93 {
94 struct ath11k_fw_stats stats = {};
95 struct ath11k *ar;
96 struct ath11k_pdev *pdev;
97 bool is_end;
98 static unsigned int num_vdev, num_bcn;
99 size_t total_vdevs_started = 0;
100 int i, ret;
101
102 INIT_LIST_HEAD(&stats.pdevs);
103 INIT_LIST_HEAD(&stats.vdevs);
104 INIT_LIST_HEAD(&stats.bcn);
105
106 ret = ath11k_wmi_pull_fw_stats(ab, skb, &stats);
107 if (ret) {
108 ath11k_warn(ab, "failed to pull fw stats: %d\n", ret);
109 goto free;
110 }
111
112 rcu_read_lock();
113 ar = ath11k_mac_get_ar_by_pdev_id(ab, stats.pdev_id);
114 if (!ar) {
115 rcu_read_unlock();
116 ath11k_warn(ab, "failed to get ar for pdev_id %d: %d\n",
117 stats.pdev_id, ret);
118 goto free;
119 }
120
121 spin_lock_bh(&ar->data_lock);
122
123 if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
124 list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
125 ar->debug.fw_stats_done = true;
126 goto complete;
127 }
128
129 if (stats.stats_id == WMI_REQUEST_VDEV_STAT) {
130 if (list_empty(&stats.vdevs)) {
131 ath11k_warn(ab, "empty vdev stats");
132 goto complete;
133 }
134 /* FW sends all the active VDEV stats irrespective of PDEV,
135 * hence limit until the count of all VDEVs started
136 */
137 for (i = 0; i < ab->num_radios; i++) {
138 pdev = rcu_dereference(ab->pdevs_active[i]);
139 if (pdev && pdev->ar)
140 total_vdevs_started += ar->num_started_vdevs;
141 }
142
143 is_end = ((++num_vdev) == total_vdevs_started);
144
145 list_splice_tail_init(&stats.vdevs,
146 &ar->debug.fw_stats.vdevs);
147
148 if (is_end) {
149 ar->debug.fw_stats_done = true;
150 num_vdev = 0;
151 }
152 goto complete;
153 }
154
155 if (stats.stats_id == WMI_REQUEST_BCN_STAT) {
156 if (list_empty(&stats.bcn)) {
157 ath11k_warn(ab, "empty bcn stats");
158 goto complete;
159 }
160 /* Mark end until we reached the count of all started VDEVs
161 * within the PDEV
162 */
163 is_end = ((++num_bcn) == ar->num_started_vdevs);
164
165 list_splice_tail_init(&stats.bcn,
166 &ar->debug.fw_stats.bcn);
167
168 if (is_end) {
169 ar->debug.fw_stats_done = true;
170 num_bcn = 0;
171 }
172 }
173 complete:
174 complete(&ar->debug.fw_stats_complete);
175 rcu_read_unlock();
176 spin_unlock_bh(&ar->data_lock);
177
178 free:
179 ath11k_fw_stats_pdevs_free(&stats.pdevs);
180 ath11k_fw_stats_vdevs_free(&stats.vdevs);
181 ath11k_fw_stats_bcn_free(&stats.bcn);
182 }
183
ath11k_debugfs_fw_stats_request(struct ath11k * ar,struct stats_request_params * req_param)184 static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
185 struct stats_request_params *req_param)
186 {
187 struct ath11k_base *ab = ar->ab;
188 unsigned long timeout, time_left;
189 int ret;
190
191 lockdep_assert_held(&ar->conf_mutex);
192
193 /* FW stats can get split when exceeding the stats data buffer limit.
194 * In that case, since there is no end marking for the back-to-back
195 * received 'update stats' event, we keep a 3 seconds timeout in case,
196 * fw_stats_done is not marked yet
197 */
198 timeout = jiffies + msecs_to_jiffies(3 * HZ);
199
200 ath11k_debugfs_fw_stats_reset(ar);
201
202 reinit_completion(&ar->debug.fw_stats_complete);
203
204 ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
205
206 if (ret) {
207 ath11k_warn(ab, "could not request fw stats (%d)\n",
208 ret);
209 return ret;
210 }
211
212 time_left =
213 wait_for_completion_timeout(&ar->debug.fw_stats_complete,
214 1 * HZ);
215 if (!time_left)
216 return -ETIMEDOUT;
217
218 for (;;) {
219 if (time_after(jiffies, timeout))
220 break;
221
222 spin_lock_bh(&ar->data_lock);
223 if (ar->debug.fw_stats_done) {
224 spin_unlock_bh(&ar->data_lock);
225 break;
226 }
227 spin_unlock_bh(&ar->data_lock);
228 }
229 return 0;
230 }
231
ath11k_open_pdev_stats(struct inode * inode,struct file * file)232 static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
233 {
234 struct ath11k *ar = inode->i_private;
235 struct ath11k_base *ab = ar->ab;
236 struct stats_request_params req_param;
237 void *buf = NULL;
238 int ret;
239
240 mutex_lock(&ar->conf_mutex);
241
242 if (ar->state != ATH11K_STATE_ON) {
243 ret = -ENETDOWN;
244 goto err_unlock;
245 }
246
247 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
248 if (!buf) {
249 ret = -ENOMEM;
250 goto err_unlock;
251 }
252
253 req_param.pdev_id = ar->pdev->pdev_id;
254 req_param.vdev_id = 0;
255 req_param.stats_id = WMI_REQUEST_PDEV_STAT;
256
257 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
258 if (ret) {
259 ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
260 goto err_free;
261 }
262
263 ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
264 buf);
265
266 file->private_data = buf;
267
268 mutex_unlock(&ar->conf_mutex);
269 return 0;
270
271 err_free:
272 vfree(buf);
273
274 err_unlock:
275 mutex_unlock(&ar->conf_mutex);
276 return ret;
277 }
278
ath11k_release_pdev_stats(struct inode * inode,struct file * file)279 static int ath11k_release_pdev_stats(struct inode *inode, struct file *file)
280 {
281 vfree(file->private_data);
282
283 return 0;
284 }
285
ath11k_read_pdev_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)286 static ssize_t ath11k_read_pdev_stats(struct file *file,
287 char __user *user_buf,
288 size_t count, loff_t *ppos)
289 {
290 const char *buf = file->private_data;
291 size_t len = strlen(buf);
292
293 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
294 }
295
296 static const struct file_operations fops_pdev_stats = {
297 .open = ath11k_open_pdev_stats,
298 .release = ath11k_release_pdev_stats,
299 .read = ath11k_read_pdev_stats,
300 .owner = THIS_MODULE,
301 .llseek = default_llseek,
302 };
303
ath11k_open_vdev_stats(struct inode * inode,struct file * file)304 static int ath11k_open_vdev_stats(struct inode *inode, struct file *file)
305 {
306 struct ath11k *ar = inode->i_private;
307 struct stats_request_params req_param;
308 void *buf = NULL;
309 int ret;
310
311 mutex_lock(&ar->conf_mutex);
312
313 if (ar->state != ATH11K_STATE_ON) {
314 ret = -ENETDOWN;
315 goto err_unlock;
316 }
317
318 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
319 if (!buf) {
320 ret = -ENOMEM;
321 goto err_unlock;
322 }
323
324 req_param.pdev_id = ar->pdev->pdev_id;
325 /* VDEV stats is always sent for all active VDEVs from FW */
326 req_param.vdev_id = 0;
327 req_param.stats_id = WMI_REQUEST_VDEV_STAT;
328
329 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
330 if (ret) {
331 ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
332 goto err_free;
333 }
334
335 ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
336 buf);
337
338 file->private_data = buf;
339
340 mutex_unlock(&ar->conf_mutex);
341 return 0;
342
343 err_free:
344 vfree(buf);
345
346 err_unlock:
347 mutex_unlock(&ar->conf_mutex);
348 return ret;
349 }
350
ath11k_release_vdev_stats(struct inode * inode,struct file * file)351 static int ath11k_release_vdev_stats(struct inode *inode, struct file *file)
352 {
353 vfree(file->private_data);
354
355 return 0;
356 }
357
ath11k_read_vdev_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)358 static ssize_t ath11k_read_vdev_stats(struct file *file,
359 char __user *user_buf,
360 size_t count, loff_t *ppos)
361 {
362 const char *buf = file->private_data;
363 size_t len = strlen(buf);
364
365 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
366 }
367
368 static const struct file_operations fops_vdev_stats = {
369 .open = ath11k_open_vdev_stats,
370 .release = ath11k_release_vdev_stats,
371 .read = ath11k_read_vdev_stats,
372 .owner = THIS_MODULE,
373 .llseek = default_llseek,
374 };
375
ath11k_open_bcn_stats(struct inode * inode,struct file * file)376 static int ath11k_open_bcn_stats(struct inode *inode, struct file *file)
377 {
378 struct ath11k *ar = inode->i_private;
379 struct ath11k_vif *arvif;
380 struct stats_request_params req_param;
381 void *buf = NULL;
382 int ret;
383
384 mutex_lock(&ar->conf_mutex);
385
386 if (ar->state != ATH11K_STATE_ON) {
387 ret = -ENETDOWN;
388 goto err_unlock;
389 }
390
391 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
392 if (!buf) {
393 ret = -ENOMEM;
394 goto err_unlock;
395 }
396
397 req_param.stats_id = WMI_REQUEST_BCN_STAT;
398 req_param.pdev_id = ar->pdev->pdev_id;
399
400 /* loop all active VDEVs for bcn stats */
401 list_for_each_entry(arvif, &ar->arvifs, list) {
402 if (!arvif->is_up)
403 continue;
404
405 req_param.vdev_id = arvif->vdev_id;
406 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
407 if (ret) {
408 ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
409 goto err_free;
410 }
411 }
412
413 ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
414 buf);
415
416 /* since beacon stats request is looped for all active VDEVs, saved fw
417 * stats is not freed for each request until done for all active VDEVs
418 */
419 spin_lock_bh(&ar->data_lock);
420 ath11k_fw_stats_bcn_free(&ar->debug.fw_stats.bcn);
421 spin_unlock_bh(&ar->data_lock);
422
423 file->private_data = buf;
424
425 mutex_unlock(&ar->conf_mutex);
426 return 0;
427
428 err_free:
429 vfree(buf);
430
431 err_unlock:
432 mutex_unlock(&ar->conf_mutex);
433 return ret;
434 }
435
ath11k_release_bcn_stats(struct inode * inode,struct file * file)436 static int ath11k_release_bcn_stats(struct inode *inode, struct file *file)
437 {
438 vfree(file->private_data);
439
440 return 0;
441 }
442
ath11k_read_bcn_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)443 static ssize_t ath11k_read_bcn_stats(struct file *file,
444 char __user *user_buf,
445 size_t count, loff_t *ppos)
446 {
447 const char *buf = file->private_data;
448 size_t len = strlen(buf);
449
450 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
451 }
452
453 static const struct file_operations fops_bcn_stats = {
454 .open = ath11k_open_bcn_stats,
455 .release = ath11k_release_bcn_stats,
456 .read = ath11k_read_bcn_stats,
457 .owner = THIS_MODULE,
458 .llseek = default_llseek,
459 };
460
ath11k_read_simulate_fw_crash(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)461 static ssize_t ath11k_read_simulate_fw_crash(struct file *file,
462 char __user *user_buf,
463 size_t count, loff_t *ppos)
464 {
465 const char buf[] =
466 "To simulate firmware crash write one of the keywords to this file:\n"
467 "`assert` - this will send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n"
468 "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
469
470 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
471 }
472
473 /* Simulate firmware crash:
474 * 'soft': Call wmi command causing firmware hang. This firmware hang is
475 * recoverable by warm firmware reset.
476 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
477 * vdev id. This is hard firmware crash because it is recoverable only by cold
478 * firmware reset.
479 */
ath11k_write_simulate_fw_crash(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)480 static ssize_t ath11k_write_simulate_fw_crash(struct file *file,
481 const char __user *user_buf,
482 size_t count, loff_t *ppos)
483 {
484 struct ath11k_base *ab = file->private_data;
485 struct ath11k_pdev *pdev;
486 struct ath11k *ar = ab->pdevs[0].ar;
487 char buf[32] = {0};
488 ssize_t rc;
489 int i, ret, radioup = 0;
490
491 for (i = 0; i < ab->num_radios; i++) {
492 pdev = &ab->pdevs[i];
493 ar = pdev->ar;
494 if (ar && ar->state == ATH11K_STATE_ON) {
495 radioup = 1;
496 break;
497 }
498 }
499 /* filter partial writes and invalid commands */
500 if (*ppos != 0 || count >= sizeof(buf) || count == 0)
501 return -EINVAL;
502
503 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
504 if (rc < 0)
505 return rc;
506
507 /* drop the possible '\n' from the end */
508 if (buf[*ppos - 1] == '\n')
509 buf[*ppos - 1] = '\0';
510
511 if (radioup == 0) {
512 ret = -ENETDOWN;
513 goto exit;
514 }
515
516 if (!strcmp(buf, "assert")) {
517 ath11k_info(ab, "simulating firmware assert crash\n");
518 ret = ath11k_wmi_force_fw_hang_cmd(ar,
519 ATH11K_WMI_FW_HANG_ASSERT_TYPE,
520 ATH11K_WMI_FW_HANG_DELAY);
521 } else {
522 ret = -EINVAL;
523 goto exit;
524 }
525
526 if (ret) {
527 ath11k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
528 goto exit;
529 }
530
531 ret = count;
532
533 exit:
534 return ret;
535 }
536
537 static const struct file_operations fops_simulate_fw_crash = {
538 .read = ath11k_read_simulate_fw_crash,
539 .write = ath11k_write_simulate_fw_crash,
540 .open = simple_open,
541 .owner = THIS_MODULE,
542 .llseek = default_llseek,
543 };
544
ath11k_write_enable_extd_tx_stats(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)545 static ssize_t ath11k_write_enable_extd_tx_stats(struct file *file,
546 const char __user *ubuf,
547 size_t count, loff_t *ppos)
548 {
549 struct ath11k *ar = file->private_data;
550 u32 filter;
551 int ret;
552
553 if (kstrtouint_from_user(ubuf, count, 0, &filter))
554 return -EINVAL;
555
556 mutex_lock(&ar->conf_mutex);
557
558 if (ar->state != ATH11K_STATE_ON) {
559 ret = -ENETDOWN;
560 goto out;
561 }
562
563 if (filter == ar->debug.extd_tx_stats) {
564 ret = count;
565 goto out;
566 }
567
568 ar->debug.extd_tx_stats = filter;
569 ret = count;
570
571 out:
572 mutex_unlock(&ar->conf_mutex);
573 return ret;
574 }
575
ath11k_read_enable_extd_tx_stats(struct file * file,char __user * ubuf,size_t count,loff_t * ppos)576 static ssize_t ath11k_read_enable_extd_tx_stats(struct file *file,
577 char __user *ubuf,
578 size_t count, loff_t *ppos)
579
580 {
581 char buf[32] = {0};
582 struct ath11k *ar = file->private_data;
583 int len = 0;
584
585 mutex_lock(&ar->conf_mutex);
586 len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
587 ar->debug.extd_tx_stats);
588 mutex_unlock(&ar->conf_mutex);
589
590 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
591 }
592
593 static const struct file_operations fops_extd_tx_stats = {
594 .read = ath11k_read_enable_extd_tx_stats,
595 .write = ath11k_write_enable_extd_tx_stats,
596 .open = simple_open
597 };
598
ath11k_write_extd_rx_stats(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)599 static ssize_t ath11k_write_extd_rx_stats(struct file *file,
600 const char __user *ubuf,
601 size_t count, loff_t *ppos)
602 {
603 struct ath11k *ar = file->private_data;
604 struct ath11k_base *ab = ar->ab;
605 struct htt_rx_ring_tlv_filter tlv_filter = {0};
606 u32 enable, rx_filter = 0, ring_id;
607 int i;
608 int ret;
609
610 if (kstrtouint_from_user(ubuf, count, 0, &enable))
611 return -EINVAL;
612
613 mutex_lock(&ar->conf_mutex);
614
615 if (ar->state != ATH11K_STATE_ON) {
616 ret = -ENETDOWN;
617 goto exit;
618 }
619
620 if (enable > 1) {
621 ret = -EINVAL;
622 goto exit;
623 }
624
625 if (enable == ar->debug.extd_rx_stats) {
626 ret = count;
627 goto exit;
628 }
629
630 if (enable) {
631 rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
632 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
633 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END;
634 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS;
635 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT;
636 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE;
637
638 tlv_filter.rx_filter = rx_filter;
639 tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
640 tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
641 tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
642 tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
643 HTT_RX_FP_DATA_FILTER_FLASG3;
644 } else {
645 tlv_filter = ath11k_mac_mon_status_filter_default;
646 }
647
648 ar->debug.rx_filter = tlv_filter.rx_filter;
649
650 for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
651 ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
652 ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
653 HAL_RXDMA_MONITOR_STATUS,
654 DP_RX_BUFFER_SIZE, &tlv_filter);
655
656 if (ret) {
657 ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
658 goto exit;
659 }
660 }
661
662 ar->debug.extd_rx_stats = enable;
663 ret = count;
664 exit:
665 mutex_unlock(&ar->conf_mutex);
666 return ret;
667 }
668
ath11k_read_extd_rx_stats(struct file * file,char __user * ubuf,size_t count,loff_t * ppos)669 static ssize_t ath11k_read_extd_rx_stats(struct file *file,
670 char __user *ubuf,
671 size_t count, loff_t *ppos)
672 {
673 struct ath11k *ar = file->private_data;
674 char buf[32];
675 int len = 0;
676
677 mutex_lock(&ar->conf_mutex);
678 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
679 ar->debug.extd_rx_stats);
680 mutex_unlock(&ar->conf_mutex);
681
682 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
683 }
684
685 static const struct file_operations fops_extd_rx_stats = {
686 .read = ath11k_read_extd_rx_stats,
687 .write = ath11k_write_extd_rx_stats,
688 .open = simple_open,
689 };
690
ath11k_fill_bp_stats(struct ath11k_base * ab,struct ath11k_bp_stats * bp_stats,char * buf,int len,int size)691 static int ath11k_fill_bp_stats(struct ath11k_base *ab,
692 struct ath11k_bp_stats *bp_stats,
693 char *buf, int len, int size)
694 {
695 lockdep_assert_held(&ab->base_lock);
696
697 len += scnprintf(buf + len, size - len, "count: %u\n",
698 bp_stats->count);
699 len += scnprintf(buf + len, size - len, "hp: %u\n",
700 bp_stats->hp);
701 len += scnprintf(buf + len, size - len, "tp: %u\n",
702 bp_stats->tp);
703 len += scnprintf(buf + len, size - len, "seen before: %ums\n\n",
704 jiffies_to_msecs(jiffies - bp_stats->jiffies));
705 return len;
706 }
707
ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base * ab,char * buf,int size)708 static ssize_t ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base *ab,
709 char *buf, int size)
710 {
711 struct ath11k_bp_stats *bp_stats;
712 bool stats_rxd = false;
713 u8 i, pdev_idx;
714 int len = 0;
715
716 len += scnprintf(buf + len, size - len, "\nBackpressure Stats\n");
717 len += scnprintf(buf + len, size - len, "==================\n");
718
719 spin_lock_bh(&ab->base_lock);
720 for (i = 0; i < HTT_SW_UMAC_RING_IDX_MAX; i++) {
721 bp_stats = &ab->soc_stats.bp_stats.umac_ring_bp_stats[i];
722
723 if (!bp_stats->count)
724 continue;
725
726 len += scnprintf(buf + len, size - len, "Ring: %s\n",
727 htt_bp_umac_ring[i]);
728 len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
729 stats_rxd = true;
730 }
731
732 for (i = 0; i < HTT_SW_LMAC_RING_IDX_MAX; i++) {
733 for (pdev_idx = 0; pdev_idx < MAX_RADIOS; pdev_idx++) {
734 bp_stats =
735 &ab->soc_stats.bp_stats.lmac_ring_bp_stats[i][pdev_idx];
736
737 if (!bp_stats->count)
738 continue;
739
740 len += scnprintf(buf + len, size - len, "Ring: %s\n",
741 htt_bp_lmac_ring[i]);
742 len += scnprintf(buf + len, size - len, "pdev: %d\n",
743 pdev_idx);
744 len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
745 stats_rxd = true;
746 }
747 }
748 spin_unlock_bh(&ab->base_lock);
749
750 if (!stats_rxd)
751 len += scnprintf(buf + len, size - len,
752 "No Ring Backpressure stats received\n\n");
753
754 return len;
755 }
756
ath11k_debugfs_dump_soc_dp_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)757 static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
758 char __user *user_buf,
759 size_t count, loff_t *ppos)
760 {
761 struct ath11k_base *ab = file->private_data;
762 struct ath11k_soc_dp_stats *soc_stats = &ab->soc_stats;
763 int len = 0, i, retval;
764 const int size = 4096;
765 static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
766 "Overflow", "MPDU len", "FCS", "Decrypt", "TKIP MIC",
767 "Unencrypt", "MSDU len", "MSDU limit", "WiFi parse",
768 "AMSDU parse", "SA timeout", "DA timeout",
769 "Flow timeout", "Flush req"};
770 static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
771 "Desc addr zero", "Desc inval", "AMPDU in non BA",
772 "Non BA dup", "BA dup", "Frame 2k jump", "BAR 2k jump",
773 "Frame OOR", "BAR OOR", "No BA session",
774 "Frame SN equal SSN", "PN check fail", "2k err",
775 "PN err", "Desc blocked"};
776
777 char *buf;
778
779 buf = kzalloc(size, GFP_KERNEL);
780 if (!buf)
781 return -ENOMEM;
782
783 len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n");
784 len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
785 soc_stats->err_ring_pkts);
786 len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
787 soc_stats->invalid_rbm);
788 len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
789 for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
790 len += scnprintf(buf + len, size - len, "%s: %u\n",
791 rxdma_err[i], soc_stats->rxdma_error[i]);
792
793 len += scnprintf(buf + len, size - len, "\nREO errors:\n");
794 for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
795 len += scnprintf(buf + len, size - len, "%s: %u\n",
796 reo_err[i], soc_stats->reo_error[i]);
797
798 len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
799 len += scnprintf(buf + len, size - len,
800 "ring0: %u\nring1: %u\nring2: %u\nring3: %u\n",
801 soc_stats->hal_reo_error[0],
802 soc_stats->hal_reo_error[1],
803 soc_stats->hal_reo_error[2],
804 soc_stats->hal_reo_error[3]);
805
806 len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
807 len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
808
809 for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
810 len += scnprintf(buf + len, size - len, "ring%d: %u\n",
811 i, soc_stats->tx_err.desc_na[i]);
812
813 len += scnprintf(buf + len, size - len,
814 "\nMisc Transmit Failures: %d\n",
815 atomic_read(&soc_stats->tx_err.misc_fail));
816
817 len += ath11k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len);
818
819 if (len > size)
820 len = size;
821 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
822 kfree(buf);
823
824 return retval;
825 }
826
827 static const struct file_operations fops_soc_dp_stats = {
828 .read = ath11k_debugfs_dump_soc_dp_stats,
829 .open = simple_open,
830 .owner = THIS_MODULE,
831 .llseek = default_llseek,
832 };
833
ath11k_debugfs_pdev_create(struct ath11k_base * ab)834 int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
835 {
836 if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
837 return 0;
838
839 debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
840 &fops_simulate_fw_crash);
841
842 debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
843 &fops_soc_dp_stats);
844
845 return 0;
846 }
847
ath11k_debugfs_pdev_destroy(struct ath11k_base * ab)848 void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab)
849 {
850 debugfs_remove_recursive(ab->debugfs_soc);
851 ab->debugfs_soc = NULL;
852 }
853
ath11k_debugfs_soc_create(struct ath11k_base * ab)854 int ath11k_debugfs_soc_create(struct ath11k_base *ab)
855 {
856 struct dentry *root;
857 bool dput_needed;
858 char name[64];
859 int ret;
860
861 root = debugfs_lookup("ath11k", NULL);
862 if (!root) {
863 root = debugfs_create_dir("ath11k", NULL);
864 if (IS_ERR_OR_NULL(root))
865 return PTR_ERR(root);
866
867 dput_needed = false;
868 } else {
869 /* a dentry from lookup() needs dput() after we don't use it */
870 dput_needed = true;
871 }
872
873 scnprintf(name, sizeof(name), "%s-%s", ath11k_bus_str(ab->hif.bus),
874 dev_name(ab->dev));
875
876 ab->debugfs_soc = debugfs_create_dir(name, root);
877 if (IS_ERR_OR_NULL(ab->debugfs_soc)) {
878 ret = PTR_ERR(ab->debugfs_soc);
879 goto out;
880 }
881
882 ret = 0;
883
884 out:
885 if (dput_needed)
886 dput(root);
887
888 return ret;
889 }
890
ath11k_debugfs_soc_destroy(struct ath11k_base * ab)891 void ath11k_debugfs_soc_destroy(struct ath11k_base *ab)
892 {
893 debugfs_remove_recursive(ab->debugfs_soc);
894 ab->debugfs_soc = NULL;
895
896 /* We are not removing ath11k directory on purpose, even if it
897 * would be empty. This simplifies the directory handling and it's
898 * a minor cosmetic issue to leave an empty ath11k directory to
899 * debugfs.
900 */
901 }
902 EXPORT_SYMBOL(ath11k_debugfs_soc_destroy);
903
ath11k_debugfs_fw_stats_init(struct ath11k * ar)904 void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
905 {
906 struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
907 ar->debug.debugfs_pdev);
908
909 ar->debug.fw_stats.debugfs_fwstats = fwstats_dir;
910
911 /* all stats debugfs files created are under "fw_stats" directory
912 * created per PDEV
913 */
914 debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
915 &fops_pdev_stats);
916 debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar,
917 &fops_vdev_stats);
918 debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
919 &fops_bcn_stats);
920
921 INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
922 INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
923 INIT_LIST_HEAD(&ar->debug.fw_stats.bcn);
924
925 init_completion(&ar->debug.fw_stats_complete);
926 }
927
ath11k_write_pktlog_filter(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)928 static ssize_t ath11k_write_pktlog_filter(struct file *file,
929 const char __user *ubuf,
930 size_t count, loff_t *ppos)
931 {
932 struct ath11k *ar = file->private_data;
933 struct ath11k_base *ab = ar->ab;
934 struct htt_rx_ring_tlv_filter tlv_filter = {0};
935 u32 rx_filter = 0, ring_id, filter, mode;
936 u8 buf[128] = {0};
937 int i, ret;
938 ssize_t rc;
939
940 mutex_lock(&ar->conf_mutex);
941 if (ar->state != ATH11K_STATE_ON) {
942 ret = -ENETDOWN;
943 goto out;
944 }
945
946 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
947 if (rc < 0) {
948 ret = rc;
949 goto out;
950 }
951 buf[rc] = '\0';
952
953 ret = sscanf(buf, "0x%x %u", &filter, &mode);
954 if (ret != 2) {
955 ret = -EINVAL;
956 goto out;
957 }
958
959 if (filter) {
960 ret = ath11k_wmi_pdev_pktlog_enable(ar, filter);
961 if (ret) {
962 ath11k_warn(ar->ab,
963 "failed to enable pktlog filter %x: %d\n",
964 ar->debug.pktlog_filter, ret);
965 goto out;
966 }
967 } else {
968 ret = ath11k_wmi_pdev_pktlog_disable(ar);
969 if (ret) {
970 ath11k_warn(ar->ab, "failed to disable pktlog: %d\n", ret);
971 goto out;
972 }
973 }
974
975 #define HTT_RX_FILTER_TLV_LITE_MODE \
976 (HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
977 HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
978 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
979 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
980 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE | \
981 HTT_RX_FILTER_TLV_FLAGS_MPDU_START)
982
983 if (mode == ATH11K_PKTLOG_MODE_FULL) {
984 rx_filter = HTT_RX_FILTER_TLV_LITE_MODE |
985 HTT_RX_FILTER_TLV_FLAGS_MSDU_START |
986 HTT_RX_FILTER_TLV_FLAGS_MSDU_END |
987 HTT_RX_FILTER_TLV_FLAGS_MPDU_END |
988 HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER |
989 HTT_RX_FILTER_TLV_FLAGS_ATTENTION;
990 } else if (mode == ATH11K_PKTLOG_MODE_LITE) {
991 ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
992 HTT_PPDU_STATS_TAG_PKTLOG);
993 if (ret) {
994 ath11k_err(ar->ab, "failed to enable pktlog lite: %d\n", ret);
995 goto out;
996 }
997
998 rx_filter = HTT_RX_FILTER_TLV_LITE_MODE;
999 } else {
1000 ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
1001 HTT_PPDU_STATS_TAG_DEFAULT);
1002 if (ret) {
1003 ath11k_err(ar->ab, "failed to send htt ppdu stats req: %d\n",
1004 ret);
1005 goto out;
1006 }
1007 }
1008
1009 tlv_filter.rx_filter = rx_filter;
1010 if (rx_filter) {
1011 tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
1012 tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
1013 tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
1014 tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
1015 HTT_RX_FP_DATA_FILTER_FLASG3;
1016 }
1017
1018 for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
1019 ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
1020 ret = ath11k_dp_tx_htt_rx_filter_setup(ab, ring_id,
1021 ar->dp.mac_id + i,
1022 HAL_RXDMA_MONITOR_STATUS,
1023 DP_RX_BUFFER_SIZE, &tlv_filter);
1024
1025 if (ret) {
1026 ath11k_warn(ab, "failed to set rx filter for monitor status ring\n");
1027 goto out;
1028 }
1029 }
1030
1031 ath11k_dbg(ab, ATH11K_DBG_WMI, "pktlog filter %d mode %s\n",
1032 filter, ((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite"));
1033
1034 ar->debug.pktlog_filter = filter;
1035 ar->debug.pktlog_mode = mode;
1036 ret = count;
1037
1038 out:
1039 mutex_unlock(&ar->conf_mutex);
1040 return ret;
1041 }
1042
ath11k_read_pktlog_filter(struct file * file,char __user * ubuf,size_t count,loff_t * ppos)1043 static ssize_t ath11k_read_pktlog_filter(struct file *file,
1044 char __user *ubuf,
1045 size_t count, loff_t *ppos)
1046
1047 {
1048 char buf[32] = {0};
1049 struct ath11k *ar = file->private_data;
1050 int len = 0;
1051
1052 mutex_lock(&ar->conf_mutex);
1053 len = scnprintf(buf, sizeof(buf) - len, "%08x %08x\n",
1054 ar->debug.pktlog_filter,
1055 ar->debug.pktlog_mode);
1056 mutex_unlock(&ar->conf_mutex);
1057
1058 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1059 }
1060
1061 static const struct file_operations fops_pktlog_filter = {
1062 .read = ath11k_read_pktlog_filter,
1063 .write = ath11k_write_pktlog_filter,
1064 .open = simple_open
1065 };
1066
ath11k_write_simulate_radar(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1067 static ssize_t ath11k_write_simulate_radar(struct file *file,
1068 const char __user *user_buf,
1069 size_t count, loff_t *ppos)
1070 {
1071 struct ath11k *ar = file->private_data;
1072 int ret;
1073
1074 ret = ath11k_wmi_simulate_radar(ar);
1075 if (ret)
1076 return ret;
1077
1078 return count;
1079 }
1080
1081 static const struct file_operations fops_simulate_radar = {
1082 .write = ath11k_write_simulate_radar,
1083 .open = simple_open
1084 };
1085
ath11k_debugfs_register(struct ath11k * ar)1086 int ath11k_debugfs_register(struct ath11k *ar)
1087 {
1088 struct ath11k_base *ab = ar->ab;
1089 char pdev_name[5];
1090 char buf[100] = {0};
1091
1092 snprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
1093
1094 ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
1095 if (IS_ERR(ar->debug.debugfs_pdev))
1096 return PTR_ERR(ar->debug.debugfs_pdev);
1097
1098 /* Create a symlink under ieee80211/phy* */
1099 snprintf(buf, 100, "../../ath11k/%pd2", ar->debug.debugfs_pdev);
1100 debugfs_create_symlink("ath11k", ar->hw->wiphy->debugfsdir, buf);
1101
1102 ath11k_debugfs_htt_stats_init(ar);
1103
1104 ath11k_debugfs_fw_stats_init(ar);
1105
1106 debugfs_create_file("ext_tx_stats", 0644,
1107 ar->debug.debugfs_pdev, ar,
1108 &fops_extd_tx_stats);
1109 debugfs_create_file("ext_rx_stats", 0644,
1110 ar->debug.debugfs_pdev, ar,
1111 &fops_extd_rx_stats);
1112 debugfs_create_file("pktlog_filter", 0644,
1113 ar->debug.debugfs_pdev, ar,
1114 &fops_pktlog_filter);
1115
1116 if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
1117 debugfs_create_file("dfs_simulate_radar", 0200,
1118 ar->debug.debugfs_pdev, ar,
1119 &fops_simulate_radar);
1120 debugfs_create_bool("dfs_block_radar_events", 0200,
1121 ar->debug.debugfs_pdev,
1122 &ar->dfs_block_radar_events);
1123 }
1124
1125 return 0;
1126 }
1127
ath11k_debugfs_unregister(struct ath11k * ar)1128 void ath11k_debugfs_unregister(struct ath11k *ar)
1129 {
1130 }
1131