1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3 * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
4 * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
5 */
6
7 #include <linux/vmalloc.h>
8
9 #include "debugfs.h"
10
11 #include "core.h"
12 #include "debug.h"
13 #include "wmi.h"
14 #include "hal_rx.h"
15 #include "dp_tx.h"
16 #include "debugfs_htt_stats.h"
17 #include "peer.h"
18 #include "hif.h"
19
20 static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
21 "REO2SW1_RING",
22 "REO2SW2_RING",
23 "REO2SW3_RING",
24 "REO2SW4_RING",
25 "WBM2REO_LINK_RING",
26 "REO2TCL_RING",
27 "REO2FW_RING",
28 "RELEASE_RING",
29 "PPE_RELEASE_RING",
30 "TCL2TQM_RING",
31 "TQM_RELEASE_RING",
32 "REO_RELEASE_RING",
33 "WBM2SW0_RELEASE_RING",
34 "WBM2SW1_RELEASE_RING",
35 "WBM2SW2_RELEASE_RING",
36 "WBM2SW3_RELEASE_RING",
37 "REO_CMD_RING",
38 "REO_STATUS_RING",
39 };
40
41 static const char *htt_bp_lmac_ring[HTT_SW_LMAC_RING_IDX_MAX] = {
42 "FW2RXDMA_BUF_RING",
43 "FW2RXDMA_STATUS_RING",
44 "FW2RXDMA_LINK_RING",
45 "SW2RXDMA_BUF_RING",
46 "WBM2RXDMA_LINK_RING",
47 "RXDMA2FW_RING",
48 "RXDMA2SW_RING",
49 "RXDMA2RELEASE_RING",
50 "RXDMA2REO_RING",
51 "MONITOR_STATUS_RING",
52 "MONITOR_BUF_RING",
53 "MONITOR_DESC_RING",
54 "MONITOR_DEST_RING",
55 };
56
ath11k_debugfs_add_dbring_entry(struct ath11k * ar,enum wmi_direct_buffer_module id,enum ath11k_dbg_dbr_event event,struct hal_srng * srng)57 void ath11k_debugfs_add_dbring_entry(struct ath11k *ar,
58 enum wmi_direct_buffer_module id,
59 enum ath11k_dbg_dbr_event event,
60 struct hal_srng *srng)
61 {
62 struct ath11k_debug_dbr *dbr_debug;
63 struct ath11k_dbg_dbr_data *dbr_data;
64 struct ath11k_dbg_dbr_entry *entry;
65
66 if (id >= WMI_DIRECT_BUF_MAX || event >= ATH11K_DBG_DBR_EVENT_MAX)
67 return;
68
69 dbr_debug = ar->debug.dbr_debug[id];
70 if (!dbr_debug)
71 return;
72
73 if (!dbr_debug->dbr_debug_enabled)
74 return;
75
76 dbr_data = &dbr_debug->dbr_dbg_data;
77
78 spin_lock_bh(&dbr_data->lock);
79
80 if (dbr_data->entries) {
81 entry = &dbr_data->entries[dbr_data->dbr_debug_idx];
82 entry->hp = srng->u.src_ring.hp;
83 entry->tp = *srng->u.src_ring.tp_addr;
84 entry->timestamp = jiffies;
85 entry->event = event;
86
87 dbr_data->dbr_debug_idx++;
88 if (dbr_data->dbr_debug_idx ==
89 dbr_data->num_ring_debug_entries)
90 dbr_data->dbr_debug_idx = 0;
91 }
92
93 spin_unlock_bh(&dbr_data->lock);
94 }
95
ath11k_debugfs_fw_stats_reset(struct ath11k * ar)96 static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar)
97 {
98 spin_lock_bh(&ar->data_lock);
99 ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
100 ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs);
101 ar->fw_stats.num_vdev_recvd = 0;
102 ar->fw_stats.num_bcn_recvd = 0;
103 spin_unlock_bh(&ar->data_lock);
104 }
105
ath11k_debugfs_fw_stats_process(struct ath11k * ar,struct ath11k_fw_stats * stats)106 void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats)
107 {
108 struct ath11k_base *ab = ar->ab;
109 struct ath11k_pdev *pdev;
110 bool is_end = true;
111 size_t total_vdevs_started = 0;
112 int i;
113
114 /* WMI_REQUEST_PDEV_STAT request has been already processed */
115
116 if (stats->stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
117 complete(&ar->fw_stats_done);
118 return;
119 }
120
121 if (stats->stats_id == WMI_REQUEST_VDEV_STAT) {
122 if (list_empty(&stats->vdevs)) {
123 ath11k_warn(ab, "empty vdev stats");
124 return;
125 }
126 /* FW sends all the active VDEV stats irrespective of PDEV,
127 * hence limit until the count of all VDEVs started
128 */
129 for (i = 0; i < ab->num_radios; i++) {
130 pdev = rcu_dereference(ab->pdevs_active[i]);
131 if (pdev && pdev->ar)
132 total_vdevs_started += ar->num_started_vdevs;
133 }
134
135 if (total_vdevs_started)
136 is_end = ((++ar->fw_stats.num_vdev_recvd) ==
137 total_vdevs_started);
138
139 list_splice_tail_init(&stats->vdevs,
140 &ar->fw_stats.vdevs);
141
142 if (is_end)
143 complete(&ar->fw_stats_done);
144
145 return;
146 }
147
148 if (stats->stats_id == WMI_REQUEST_BCN_STAT) {
149 if (list_empty(&stats->bcn)) {
150 ath11k_warn(ab, "empty bcn stats");
151 return;
152 }
153 /* Mark end until we reached the count of all started VDEVs
154 * within the PDEV
155 */
156 if (ar->num_started_vdevs)
157 is_end = ((++ar->fw_stats.num_bcn_recvd) ==
158 ar->num_started_vdevs);
159
160 list_splice_tail_init(&stats->bcn,
161 &ar->fw_stats.bcn);
162
163 if (is_end)
164 complete(&ar->fw_stats_done);
165 }
166 }
167
ath11k_debugfs_fw_stats_request(struct ath11k * ar,struct stats_request_params * req_param)168 static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
169 struct stats_request_params *req_param)
170 {
171 struct ath11k_base *ab = ar->ab;
172 unsigned long time_left;
173 int ret;
174
175 lockdep_assert_held(&ar->conf_mutex);
176
177 ath11k_debugfs_fw_stats_reset(ar);
178
179 reinit_completion(&ar->fw_stats_complete);
180 reinit_completion(&ar->fw_stats_done);
181
182 ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
183
184 if (ret) {
185 ath11k_warn(ab, "could not request fw stats (%d)\n",
186 ret);
187 return ret;
188 }
189
190 time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ);
191 if (!time_left)
192 return -ETIMEDOUT;
193
194 /* FW stats can get split when exceeding the stats data buffer limit.
195 * In that case, since there is no end marking for the back-to-back
196 * received 'update stats' event, we keep a 3 seconds timeout in case,
197 * fw_stats_done is not marked yet
198 */
199 time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ);
200 if (!time_left)
201 return -ETIMEDOUT;
202
203 return 0;
204 }
205
ath11k_debugfs_get_fw_stats(struct ath11k * ar,u32 pdev_id,u32 vdev_id,u32 stats_id)206 int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
207 u32 vdev_id, u32 stats_id)
208 {
209 struct ath11k_base *ab = ar->ab;
210 struct stats_request_params req_param;
211 int ret;
212
213 mutex_lock(&ar->conf_mutex);
214
215 if (ar->state != ATH11K_STATE_ON) {
216 ret = -ENETDOWN;
217 goto err_unlock;
218 }
219
220 req_param.pdev_id = pdev_id;
221 req_param.vdev_id = vdev_id;
222 req_param.stats_id = stats_id;
223
224 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
225 if (ret)
226 ath11k_warn(ab, "failed to request fw stats: %d\n", ret);
227
228 ath11k_dbg(ab, ATH11K_DBG_WMI,
229 "debug get fw stat pdev id %d vdev id %d stats id 0x%x\n",
230 pdev_id, vdev_id, stats_id);
231
232 err_unlock:
233 mutex_unlock(&ar->conf_mutex);
234
235 return ret;
236 }
237
ath11k_open_pdev_stats(struct inode * inode,struct file * file)238 static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
239 {
240 struct ath11k *ar = inode->i_private;
241 struct ath11k_base *ab = ar->ab;
242 struct stats_request_params req_param;
243 void *buf = NULL;
244 int ret;
245
246 mutex_lock(&ar->conf_mutex);
247
248 if (ar->state != ATH11K_STATE_ON) {
249 ret = -ENETDOWN;
250 goto err_unlock;
251 }
252
253 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
254 if (!buf) {
255 ret = -ENOMEM;
256 goto err_unlock;
257 }
258
259 req_param.pdev_id = ar->pdev->pdev_id;
260 req_param.vdev_id = 0;
261 req_param.stats_id = WMI_REQUEST_PDEV_STAT;
262
263 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
264 if (ret) {
265 ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
266 goto err_free;
267 }
268
269 ath11k_wmi_fw_stats_fill(ar, &ar->fw_stats, req_param.stats_id, buf);
270
271 file->private_data = buf;
272
273 mutex_unlock(&ar->conf_mutex);
274 return 0;
275
276 err_free:
277 vfree(buf);
278
279 err_unlock:
280 mutex_unlock(&ar->conf_mutex);
281 return ret;
282 }
283
ath11k_release_pdev_stats(struct inode * inode,struct file * file)284 static int ath11k_release_pdev_stats(struct inode *inode, struct file *file)
285 {
286 vfree(file->private_data);
287
288 return 0;
289 }
290
ath11k_read_pdev_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)291 static ssize_t ath11k_read_pdev_stats(struct file *file,
292 char __user *user_buf,
293 size_t count, loff_t *ppos)
294 {
295 const char *buf = file->private_data;
296 size_t len = strlen(buf);
297
298 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
299 }
300
301 static const struct file_operations fops_pdev_stats = {
302 .open = ath11k_open_pdev_stats,
303 .release = ath11k_release_pdev_stats,
304 .read = ath11k_read_pdev_stats,
305 .owner = THIS_MODULE,
306 .llseek = default_llseek,
307 };
308
ath11k_open_vdev_stats(struct inode * inode,struct file * file)309 static int ath11k_open_vdev_stats(struct inode *inode, struct file *file)
310 {
311 struct ath11k *ar = inode->i_private;
312 struct stats_request_params req_param;
313 void *buf = NULL;
314 int ret;
315
316 mutex_lock(&ar->conf_mutex);
317
318 if (ar->state != ATH11K_STATE_ON) {
319 ret = -ENETDOWN;
320 goto err_unlock;
321 }
322
323 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
324 if (!buf) {
325 ret = -ENOMEM;
326 goto err_unlock;
327 }
328
329 req_param.pdev_id = ar->pdev->pdev_id;
330 /* VDEV stats is always sent for all active VDEVs from FW */
331 req_param.vdev_id = 0;
332 req_param.stats_id = WMI_REQUEST_VDEV_STAT;
333
334 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
335 if (ret) {
336 ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
337 goto err_free;
338 }
339
340 ath11k_wmi_fw_stats_fill(ar, &ar->fw_stats, req_param.stats_id, buf);
341
342 file->private_data = buf;
343
344 mutex_unlock(&ar->conf_mutex);
345 return 0;
346
347 err_free:
348 vfree(buf);
349
350 err_unlock:
351 mutex_unlock(&ar->conf_mutex);
352 return ret;
353 }
354
ath11k_release_vdev_stats(struct inode * inode,struct file * file)355 static int ath11k_release_vdev_stats(struct inode *inode, struct file *file)
356 {
357 vfree(file->private_data);
358
359 return 0;
360 }
361
ath11k_read_vdev_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)362 static ssize_t ath11k_read_vdev_stats(struct file *file,
363 char __user *user_buf,
364 size_t count, loff_t *ppos)
365 {
366 const char *buf = file->private_data;
367 size_t len = strlen(buf);
368
369 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
370 }
371
372 static const struct file_operations fops_vdev_stats = {
373 .open = ath11k_open_vdev_stats,
374 .release = ath11k_release_vdev_stats,
375 .read = ath11k_read_vdev_stats,
376 .owner = THIS_MODULE,
377 .llseek = default_llseek,
378 };
379
ath11k_open_bcn_stats(struct inode * inode,struct file * file)380 static int ath11k_open_bcn_stats(struct inode *inode, struct file *file)
381 {
382 struct ath11k *ar = inode->i_private;
383 struct ath11k_vif *arvif;
384 struct stats_request_params req_param;
385 void *buf = NULL;
386 int ret;
387
388 mutex_lock(&ar->conf_mutex);
389
390 if (ar->state != ATH11K_STATE_ON) {
391 ret = -ENETDOWN;
392 goto err_unlock;
393 }
394
395 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
396 if (!buf) {
397 ret = -ENOMEM;
398 goto err_unlock;
399 }
400
401 req_param.stats_id = WMI_REQUEST_BCN_STAT;
402 req_param.pdev_id = ar->pdev->pdev_id;
403
404 /* loop all active VDEVs for bcn stats */
405 list_for_each_entry(arvif, &ar->arvifs, list) {
406 if (!arvif->is_up)
407 continue;
408
409 req_param.vdev_id = arvif->vdev_id;
410 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
411 if (ret) {
412 ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
413 goto err_free;
414 }
415 }
416
417 ath11k_wmi_fw_stats_fill(ar, &ar->fw_stats, req_param.stats_id, buf);
418
419 /* since beacon stats request is looped for all active VDEVs, saved fw
420 * stats is not freed for each request until done for all active VDEVs
421 */
422 spin_lock_bh(&ar->data_lock);
423 ath11k_fw_stats_bcn_free(&ar->fw_stats.bcn);
424 spin_unlock_bh(&ar->data_lock);
425
426 file->private_data = buf;
427
428 mutex_unlock(&ar->conf_mutex);
429 return 0;
430
431 err_free:
432 vfree(buf);
433
434 err_unlock:
435 mutex_unlock(&ar->conf_mutex);
436 return ret;
437 }
438
ath11k_release_bcn_stats(struct inode * inode,struct file * file)439 static int ath11k_release_bcn_stats(struct inode *inode, struct file *file)
440 {
441 vfree(file->private_data);
442
443 return 0;
444 }
445
ath11k_read_bcn_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)446 static ssize_t ath11k_read_bcn_stats(struct file *file,
447 char __user *user_buf,
448 size_t count, loff_t *ppos)
449 {
450 const char *buf = file->private_data;
451 size_t len = strlen(buf);
452
453 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
454 }
455
456 static const struct file_operations fops_bcn_stats = {
457 .open = ath11k_open_bcn_stats,
458 .release = ath11k_release_bcn_stats,
459 .read = ath11k_read_bcn_stats,
460 .owner = THIS_MODULE,
461 .llseek = default_llseek,
462 };
463
ath11k_read_simulate_fw_crash(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)464 static ssize_t ath11k_read_simulate_fw_crash(struct file *file,
465 char __user *user_buf,
466 size_t count, loff_t *ppos)
467 {
468 const char buf[] =
469 "To simulate firmware crash write one of the keywords to this file:\n"
470 "`assert` - this will send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n"
471 "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
472
473 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
474 }
475
476 /* Simulate firmware crash:
477 * 'soft': Call wmi command causing firmware hang. This firmware hang is
478 * recoverable by warm firmware reset.
479 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
480 * vdev id. This is hard firmware crash because it is recoverable only by cold
481 * firmware reset.
482 */
ath11k_write_simulate_fw_crash(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)483 static ssize_t ath11k_write_simulate_fw_crash(struct file *file,
484 const char __user *user_buf,
485 size_t count, loff_t *ppos)
486 {
487 struct ath11k_base *ab = file->private_data;
488 struct ath11k_pdev *pdev;
489 struct ath11k *ar = ab->pdevs[0].ar;
490 char buf[32] = {0};
491 ssize_t rc;
492 int i, ret, radioup = 0;
493
494 for (i = 0; i < ab->num_radios; i++) {
495 pdev = &ab->pdevs[i];
496 ar = pdev->ar;
497 if (ar && ar->state == ATH11K_STATE_ON) {
498 radioup = 1;
499 break;
500 }
501 }
502 /* filter partial writes and invalid commands */
503 if (*ppos != 0 || count >= sizeof(buf) || count == 0)
504 return -EINVAL;
505
506 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
507 if (rc < 0)
508 return rc;
509
510 /* drop the possible '\n' from the end */
511 if (buf[*ppos - 1] == '\n')
512 buf[*ppos - 1] = '\0';
513
514 if (radioup == 0) {
515 ret = -ENETDOWN;
516 goto exit;
517 }
518
519 if (!strcmp(buf, "assert")) {
520 ath11k_info(ab, "simulating firmware assert crash\n");
521 ret = ath11k_wmi_force_fw_hang_cmd(ar,
522 ATH11K_WMI_FW_HANG_ASSERT_TYPE,
523 ATH11K_WMI_FW_HANG_DELAY);
524 } else if (!strcmp(buf, "hw-restart")) {
525 ath11k_info(ab, "user requested hw restart\n");
526 queue_work(ab->workqueue_aux, &ab->reset_work);
527 ret = 0;
528 } else {
529 ret = -EINVAL;
530 goto exit;
531 }
532
533 if (ret) {
534 ath11k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
535 goto exit;
536 }
537
538 ret = count;
539
540 exit:
541 return ret;
542 }
543
544 static const struct file_operations fops_simulate_fw_crash = {
545 .read = ath11k_read_simulate_fw_crash,
546 .write = ath11k_write_simulate_fw_crash,
547 .open = simple_open,
548 .owner = THIS_MODULE,
549 .llseek = default_llseek,
550 };
551
ath11k_write_enable_extd_tx_stats(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)552 static ssize_t ath11k_write_enable_extd_tx_stats(struct file *file,
553 const char __user *ubuf,
554 size_t count, loff_t *ppos)
555 {
556 struct ath11k *ar = file->private_data;
557 u32 filter;
558 int ret;
559
560 if (kstrtouint_from_user(ubuf, count, 0, &filter))
561 return -EINVAL;
562
563 mutex_lock(&ar->conf_mutex);
564
565 if (ar->state != ATH11K_STATE_ON) {
566 ret = -ENETDOWN;
567 goto out;
568 }
569
570 if (filter == ar->debug.extd_tx_stats) {
571 ret = count;
572 goto out;
573 }
574
575 ar->debug.extd_tx_stats = filter;
576 ret = count;
577
578 out:
579 mutex_unlock(&ar->conf_mutex);
580 return ret;
581 }
582
ath11k_read_enable_extd_tx_stats(struct file * file,char __user * ubuf,size_t count,loff_t * ppos)583 static ssize_t ath11k_read_enable_extd_tx_stats(struct file *file,
584 char __user *ubuf,
585 size_t count, loff_t *ppos)
586
587 {
588 char buf[32] = {0};
589 struct ath11k *ar = file->private_data;
590 int len = 0;
591
592 mutex_lock(&ar->conf_mutex);
593 len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
594 ar->debug.extd_tx_stats);
595 mutex_unlock(&ar->conf_mutex);
596
597 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
598 }
599
600 static const struct file_operations fops_extd_tx_stats = {
601 .read = ath11k_read_enable_extd_tx_stats,
602 .write = ath11k_write_enable_extd_tx_stats,
603 .open = simple_open
604 };
605
ath11k_write_extd_rx_stats(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)606 static ssize_t ath11k_write_extd_rx_stats(struct file *file,
607 const char __user *ubuf,
608 size_t count, loff_t *ppos)
609 {
610 struct ath11k *ar = file->private_data;
611 struct ath11k_base *ab = ar->ab;
612 struct htt_rx_ring_tlv_filter tlv_filter = {0};
613 u32 enable, rx_filter = 0, ring_id;
614 int i;
615 int ret;
616
617 if (kstrtouint_from_user(ubuf, count, 0, &enable))
618 return -EINVAL;
619
620 mutex_lock(&ar->conf_mutex);
621
622 if (ar->state != ATH11K_STATE_ON) {
623 ret = -ENETDOWN;
624 goto exit;
625 }
626
627 if (enable > 1) {
628 ret = -EINVAL;
629 goto exit;
630 }
631
632 if (enable == ar->debug.extd_rx_stats) {
633 ret = count;
634 goto exit;
635 }
636
637 if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags)) {
638 ar->debug.extd_rx_stats = enable;
639 ret = count;
640 goto exit;
641 }
642
643 if (enable) {
644 rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
645 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
646 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END;
647 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS;
648 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT;
649 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE;
650
651 tlv_filter.rx_filter = rx_filter;
652 tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
653 tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
654 tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
655 tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
656 HTT_RX_FP_DATA_FILTER_FLASG3;
657 } else {
658 tlv_filter = ath11k_mac_mon_status_filter_default;
659 }
660
661 ar->debug.rx_filter = tlv_filter.rx_filter;
662
663 for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
664 ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
665 ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
666 HAL_RXDMA_MONITOR_STATUS,
667 DP_RX_BUFFER_SIZE, &tlv_filter);
668
669 if (ret) {
670 ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
671 goto exit;
672 }
673 }
674
675 ar->debug.extd_rx_stats = enable;
676 ret = count;
677 exit:
678 mutex_unlock(&ar->conf_mutex);
679 return ret;
680 }
681
ath11k_read_extd_rx_stats(struct file * file,char __user * ubuf,size_t count,loff_t * ppos)682 static ssize_t ath11k_read_extd_rx_stats(struct file *file,
683 char __user *ubuf,
684 size_t count, loff_t *ppos)
685 {
686 struct ath11k *ar = file->private_data;
687 char buf[32];
688 int len = 0;
689
690 mutex_lock(&ar->conf_mutex);
691 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
692 ar->debug.extd_rx_stats);
693 mutex_unlock(&ar->conf_mutex);
694
695 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
696 }
697
698 static const struct file_operations fops_extd_rx_stats = {
699 .read = ath11k_read_extd_rx_stats,
700 .write = ath11k_write_extd_rx_stats,
701 .open = simple_open,
702 };
703
ath11k_fill_bp_stats(struct ath11k_base * ab,struct ath11k_bp_stats * bp_stats,char * buf,int len,int size)704 static int ath11k_fill_bp_stats(struct ath11k_base *ab,
705 struct ath11k_bp_stats *bp_stats,
706 char *buf, int len, int size)
707 {
708 lockdep_assert_held(&ab->base_lock);
709
710 len += scnprintf(buf + len, size - len, "count: %u\n",
711 bp_stats->count);
712 len += scnprintf(buf + len, size - len, "hp: %u\n",
713 bp_stats->hp);
714 len += scnprintf(buf + len, size - len, "tp: %u\n",
715 bp_stats->tp);
716 len += scnprintf(buf + len, size - len, "seen before: %ums\n\n",
717 jiffies_to_msecs(jiffies - bp_stats->jiffies));
718 return len;
719 }
720
ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base * ab,char * buf,int size)721 static ssize_t ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base *ab,
722 char *buf, int size)
723 {
724 struct ath11k_bp_stats *bp_stats;
725 bool stats_rxd = false;
726 u8 i, pdev_idx;
727 int len = 0;
728
729 len += scnprintf(buf + len, size - len, "\nBackpressure Stats\n");
730 len += scnprintf(buf + len, size - len, "==================\n");
731
732 spin_lock_bh(&ab->base_lock);
733 for (i = 0; i < HTT_SW_UMAC_RING_IDX_MAX; i++) {
734 bp_stats = &ab->soc_stats.bp_stats.umac_ring_bp_stats[i];
735
736 if (!bp_stats->count)
737 continue;
738
739 len += scnprintf(buf + len, size - len, "Ring: %s\n",
740 htt_bp_umac_ring[i]);
741 len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
742 stats_rxd = true;
743 }
744
745 for (i = 0; i < HTT_SW_LMAC_RING_IDX_MAX; i++) {
746 for (pdev_idx = 0; pdev_idx < MAX_RADIOS; pdev_idx++) {
747 bp_stats =
748 &ab->soc_stats.bp_stats.lmac_ring_bp_stats[i][pdev_idx];
749
750 if (!bp_stats->count)
751 continue;
752
753 len += scnprintf(buf + len, size - len, "Ring: %s\n",
754 htt_bp_lmac_ring[i]);
755 len += scnprintf(buf + len, size - len, "pdev: %d\n",
756 pdev_idx);
757 len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
758 stats_rxd = true;
759 }
760 }
761 spin_unlock_bh(&ab->base_lock);
762
763 if (!stats_rxd)
764 len += scnprintf(buf + len, size - len,
765 "No Ring Backpressure stats received\n\n");
766
767 return len;
768 }
769
ath11k_debugfs_dump_soc_dp_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)770 static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
771 char __user *user_buf,
772 size_t count, loff_t *ppos)
773 {
774 struct ath11k_base *ab = file->private_data;
775 struct ath11k_soc_dp_stats *soc_stats = &ab->soc_stats;
776 int len = 0, i, retval;
777 const int size = 4096;
778 static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
779 "Overflow", "MPDU len", "FCS", "Decrypt", "TKIP MIC",
780 "Unencrypt", "MSDU len", "MSDU limit", "WiFi parse",
781 "AMSDU parse", "SA timeout", "DA timeout",
782 "Flow timeout", "Flush req"};
783 static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
784 "Desc addr zero", "Desc inval", "AMPDU in non BA",
785 "Non BA dup", "BA dup", "Frame 2k jump", "BAR 2k jump",
786 "Frame OOR", "BAR OOR", "No BA session",
787 "Frame SN equal SSN", "PN check fail", "2k err",
788 "PN err", "Desc blocked"};
789
790 char *buf;
791
792 buf = kzalloc(size, GFP_KERNEL);
793 if (!buf)
794 return -ENOMEM;
795
796 len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n");
797 len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
798 soc_stats->err_ring_pkts);
799 len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
800 soc_stats->invalid_rbm);
801 len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
802 for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
803 len += scnprintf(buf + len, size - len, "%s: %u\n",
804 rxdma_err[i], soc_stats->rxdma_error[i]);
805
806 len += scnprintf(buf + len, size - len, "\nREO errors:\n");
807 for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
808 len += scnprintf(buf + len, size - len, "%s: %u\n",
809 reo_err[i], soc_stats->reo_error[i]);
810
811 len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
812 len += scnprintf(buf + len, size - len,
813 "ring0: %u\nring1: %u\nring2: %u\nring3: %u\n",
814 soc_stats->hal_reo_error[0],
815 soc_stats->hal_reo_error[1],
816 soc_stats->hal_reo_error[2],
817 soc_stats->hal_reo_error[3]);
818
819 len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
820 len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
821
822 for (i = 0; i < ab->hw_params.max_tx_ring; i++)
823 len += scnprintf(buf + len, size - len, "ring%d: %u\n",
824 i, soc_stats->tx_err.desc_na[i]);
825
826 len += scnprintf(buf + len, size - len,
827 "\nMisc Transmit Failures: %d\n",
828 atomic_read(&soc_stats->tx_err.misc_fail));
829
830 len += ath11k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len);
831
832 if (len > size)
833 len = size;
834 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
835 kfree(buf);
836
837 return retval;
838 }
839
840 static const struct file_operations fops_soc_dp_stats = {
841 .read = ath11k_debugfs_dump_soc_dp_stats,
842 .open = simple_open,
843 .owner = THIS_MODULE,
844 .llseek = default_llseek,
845 };
846
ath11k_write_fw_dbglog(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)847 static ssize_t ath11k_write_fw_dbglog(struct file *file,
848 const char __user *user_buf,
849 size_t count, loff_t *ppos)
850 {
851 struct ath11k *ar = file->private_data;
852 char buf[128] = {0};
853 struct ath11k_fw_dbglog dbglog;
854 unsigned int param, mod_id_index, is_end;
855 u64 value;
856 int ret, num;
857
858 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
859 user_buf, count);
860 if (ret <= 0)
861 return ret;
862
863 num = sscanf(buf, "%u %llx %u %u", ¶m, &value, &mod_id_index, &is_end);
864
865 if (num < 2)
866 return -EINVAL;
867
868 mutex_lock(&ar->conf_mutex);
869 if (param == WMI_DEBUG_LOG_PARAM_MOD_ENABLE_BITMAP ||
870 param == WMI_DEBUG_LOG_PARAM_WOW_MOD_ENABLE_BITMAP) {
871 if (num != 4 || mod_id_index > (MAX_MODULE_ID_BITMAP_WORDS - 1)) {
872 ret = -EINVAL;
873 goto out;
874 }
875 ar->debug.module_id_bitmap[mod_id_index] = upper_32_bits(value);
876 if (!is_end) {
877 ret = count;
878 goto out;
879 }
880 } else {
881 if (num != 2) {
882 ret = -EINVAL;
883 goto out;
884 }
885 }
886
887 dbglog.param = param;
888 dbglog.value = lower_32_bits(value);
889 ret = ath11k_wmi_fw_dbglog_cfg(ar, ar->debug.module_id_bitmap, &dbglog);
890 if (ret) {
891 ath11k_warn(ar->ab, "fw dbglog config failed from debugfs: %d\n",
892 ret);
893 goto out;
894 }
895
896 ret = count;
897
898 out:
899 mutex_unlock(&ar->conf_mutex);
900 return ret;
901 }
902
903 static const struct file_operations fops_fw_dbglog = {
904 .write = ath11k_write_fw_dbglog,
905 .open = simple_open,
906 .owner = THIS_MODULE,
907 .llseek = default_llseek,
908 };
909
ath11k_open_sram_dump(struct inode * inode,struct file * file)910 static int ath11k_open_sram_dump(struct inode *inode, struct file *file)
911 {
912 struct ath11k_base *ab = inode->i_private;
913 u8 *buf;
914 u32 start, end;
915 int ret;
916
917 start = ab->hw_params.sram_dump.start;
918 end = ab->hw_params.sram_dump.end;
919
920 buf = vmalloc(end - start + 1);
921 if (!buf)
922 return -ENOMEM;
923
924 ret = ath11k_hif_read(ab, buf, start, end);
925 if (ret) {
926 ath11k_warn(ab, "failed to dump sram: %d\n", ret);
927 vfree(buf);
928 return ret;
929 }
930
931 file->private_data = buf;
932 return 0;
933 }
934
ath11k_read_sram_dump(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)935 static ssize_t ath11k_read_sram_dump(struct file *file,
936 char __user *user_buf,
937 size_t count, loff_t *ppos)
938 {
939 struct ath11k_base *ab = file->f_inode->i_private;
940 const char *buf = file->private_data;
941 int len;
942 u32 start, end;
943
944 start = ab->hw_params.sram_dump.start;
945 end = ab->hw_params.sram_dump.end;
946 len = end - start + 1;
947
948 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
949 }
950
ath11k_release_sram_dump(struct inode * inode,struct file * file)951 static int ath11k_release_sram_dump(struct inode *inode, struct file *file)
952 {
953 vfree(file->private_data);
954 file->private_data = NULL;
955
956 return 0;
957 }
958
959 static const struct file_operations fops_sram_dump = {
960 .open = ath11k_open_sram_dump,
961 .read = ath11k_read_sram_dump,
962 .release = ath11k_release_sram_dump,
963 .owner = THIS_MODULE,
964 .llseek = default_llseek,
965 };
966
ath11k_debugfs_pdev_create(struct ath11k_base * ab)967 int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
968 {
969 if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
970 return 0;
971
972 debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
973 &fops_simulate_fw_crash);
974
975 debugfs_create_file("soc_dp_stats", 0400, ab->debugfs_soc, ab,
976 &fops_soc_dp_stats);
977
978 if (ab->hw_params.sram_dump.start != 0)
979 debugfs_create_file("sram", 0400, ab->debugfs_soc, ab,
980 &fops_sram_dump);
981
982 return 0;
983 }
984
ath11k_debugfs_pdev_destroy(struct ath11k_base * ab)985 void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab)
986 {
987 debugfs_remove_recursive(ab->debugfs_soc);
988 ab->debugfs_soc = NULL;
989 }
990
ath11k_debugfs_soc_create(struct ath11k_base * ab)991 int ath11k_debugfs_soc_create(struct ath11k_base *ab)
992 {
993 struct dentry *root;
994 bool dput_needed;
995 char name[64];
996 int ret;
997
998 root = debugfs_lookup("ath11k", NULL);
999 if (!root) {
1000 root = debugfs_create_dir("ath11k", NULL);
1001 if (IS_ERR_OR_NULL(root))
1002 return PTR_ERR(root);
1003
1004 dput_needed = false;
1005 } else {
1006 /* a dentry from lookup() needs dput() after we don't use it */
1007 dput_needed = true;
1008 }
1009
1010 scnprintf(name, sizeof(name), "%s-%s", ath11k_bus_str(ab->hif.bus),
1011 dev_name(ab->dev));
1012
1013 ab->debugfs_soc = debugfs_create_dir(name, root);
1014 if (IS_ERR_OR_NULL(ab->debugfs_soc)) {
1015 ret = PTR_ERR(ab->debugfs_soc);
1016 goto out;
1017 }
1018
1019 ret = 0;
1020
1021 out:
1022 if (dput_needed)
1023 dput(root);
1024
1025 return ret;
1026 }
1027
ath11k_debugfs_soc_destroy(struct ath11k_base * ab)1028 void ath11k_debugfs_soc_destroy(struct ath11k_base *ab)
1029 {
1030 debugfs_remove_recursive(ab->debugfs_soc);
1031 ab->debugfs_soc = NULL;
1032
1033 /* We are not removing ath11k directory on purpose, even if it
1034 * would be empty. This simplifies the directory handling and it's
1035 * a minor cosmetic issue to leave an empty ath11k directory to
1036 * debugfs.
1037 */
1038 }
1039 EXPORT_SYMBOL(ath11k_debugfs_soc_destroy);
1040
ath11k_debugfs_fw_stats_init(struct ath11k * ar)1041 void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
1042 {
1043 struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
1044 ar->debug.debugfs_pdev);
1045
1046 ar->fw_stats.debugfs_fwstats = fwstats_dir;
1047
1048 /* all stats debugfs files created are under "fw_stats" directory
1049 * created per PDEV
1050 */
1051 debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
1052 &fops_pdev_stats);
1053 debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar,
1054 &fops_vdev_stats);
1055 debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
1056 &fops_bcn_stats);
1057 }
1058
ath11k_write_pktlog_filter(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)1059 static ssize_t ath11k_write_pktlog_filter(struct file *file,
1060 const char __user *ubuf,
1061 size_t count, loff_t *ppos)
1062 {
1063 struct ath11k *ar = file->private_data;
1064 struct ath11k_base *ab = ar->ab;
1065 struct htt_rx_ring_tlv_filter tlv_filter = {0};
1066 u32 rx_filter = 0, ring_id, filter, mode;
1067 u8 buf[128] = {0};
1068 int i, ret, rx_buf_sz = 0;
1069 ssize_t rc;
1070
1071 mutex_lock(&ar->conf_mutex);
1072 if (ar->state != ATH11K_STATE_ON) {
1073 ret = -ENETDOWN;
1074 goto out;
1075 }
1076
1077 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1078 if (rc < 0) {
1079 ret = rc;
1080 goto out;
1081 }
1082 buf[rc] = '\0';
1083
1084 ret = sscanf(buf, "0x%x %u", &filter, &mode);
1085 if (ret != 2) {
1086 ret = -EINVAL;
1087 goto out;
1088 }
1089
1090 if (filter) {
1091 ret = ath11k_wmi_pdev_pktlog_enable(ar, filter);
1092 if (ret) {
1093 ath11k_warn(ar->ab,
1094 "failed to enable pktlog filter %x: %d\n",
1095 ar->debug.pktlog_filter, ret);
1096 goto out;
1097 }
1098 } else {
1099 ret = ath11k_wmi_pdev_pktlog_disable(ar);
1100 if (ret) {
1101 ath11k_warn(ar->ab, "failed to disable pktlog: %d\n", ret);
1102 goto out;
1103 }
1104 }
1105
1106 /* Clear rx filter set for monitor mode and rx status */
1107 for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
1108 ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
1109 ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
1110 HAL_RXDMA_MONITOR_STATUS,
1111 rx_buf_sz, &tlv_filter);
1112 if (ret) {
1113 ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
1114 goto out;
1115 }
1116 }
1117 #define HTT_RX_FILTER_TLV_LITE_MODE \
1118 (HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
1119 HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
1120 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
1121 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
1122 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE | \
1123 HTT_RX_FILTER_TLV_FLAGS_MPDU_START)
1124
1125 if (mode == ATH11K_PKTLOG_MODE_FULL) {
1126 rx_filter = HTT_RX_FILTER_TLV_LITE_MODE |
1127 HTT_RX_FILTER_TLV_FLAGS_MSDU_START |
1128 HTT_RX_FILTER_TLV_FLAGS_MSDU_END |
1129 HTT_RX_FILTER_TLV_FLAGS_MPDU_END |
1130 HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER |
1131 HTT_RX_FILTER_TLV_FLAGS_ATTENTION;
1132 rx_buf_sz = DP_RX_BUFFER_SIZE;
1133 } else if (mode == ATH11K_PKTLOG_MODE_LITE) {
1134 ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
1135 HTT_PPDU_STATS_TAG_PKTLOG);
1136 if (ret) {
1137 ath11k_err(ar->ab, "failed to enable pktlog lite: %d\n", ret);
1138 goto out;
1139 }
1140
1141 rx_filter = HTT_RX_FILTER_TLV_LITE_MODE;
1142 rx_buf_sz = DP_RX_BUFFER_SIZE_LITE;
1143 } else {
1144 rx_buf_sz = DP_RX_BUFFER_SIZE;
1145 tlv_filter = ath11k_mac_mon_status_filter_default;
1146 rx_filter = tlv_filter.rx_filter;
1147
1148 ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
1149 HTT_PPDU_STATS_TAG_DEFAULT);
1150 if (ret) {
1151 ath11k_err(ar->ab, "failed to send htt ppdu stats req: %d\n",
1152 ret);
1153 goto out;
1154 }
1155 }
1156
1157 tlv_filter.rx_filter = rx_filter;
1158 if (rx_filter) {
1159 tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
1160 tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
1161 tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
1162 tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
1163 HTT_RX_FP_DATA_FILTER_FLASG3;
1164 }
1165
1166 for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
1167 ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
1168 ret = ath11k_dp_tx_htt_rx_filter_setup(ab, ring_id,
1169 ar->dp.mac_id + i,
1170 HAL_RXDMA_MONITOR_STATUS,
1171 rx_buf_sz, &tlv_filter);
1172
1173 if (ret) {
1174 ath11k_warn(ab, "failed to set rx filter for monitor status ring\n");
1175 goto out;
1176 }
1177 }
1178
1179 ath11k_info(ab, "pktlog mode %s\n",
1180 ((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite"));
1181
1182 ar->debug.pktlog_filter = filter;
1183 ar->debug.pktlog_mode = mode;
1184 ret = count;
1185
1186 out:
1187 mutex_unlock(&ar->conf_mutex);
1188 return ret;
1189 }
1190
ath11k_read_pktlog_filter(struct file * file,char __user * ubuf,size_t count,loff_t * ppos)1191 static ssize_t ath11k_read_pktlog_filter(struct file *file,
1192 char __user *ubuf,
1193 size_t count, loff_t *ppos)
1194
1195 {
1196 char buf[32] = {0};
1197 struct ath11k *ar = file->private_data;
1198 int len = 0;
1199
1200 mutex_lock(&ar->conf_mutex);
1201 len = scnprintf(buf, sizeof(buf) - len, "%08x %08x\n",
1202 ar->debug.pktlog_filter,
1203 ar->debug.pktlog_mode);
1204 mutex_unlock(&ar->conf_mutex);
1205
1206 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1207 }
1208
1209 static const struct file_operations fops_pktlog_filter = {
1210 .read = ath11k_read_pktlog_filter,
1211 .write = ath11k_write_pktlog_filter,
1212 .open = simple_open
1213 };
1214
ath11k_write_simulate_radar(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1215 static ssize_t ath11k_write_simulate_radar(struct file *file,
1216 const char __user *user_buf,
1217 size_t count, loff_t *ppos)
1218 {
1219 struct ath11k *ar = file->private_data;
1220 int ret;
1221
1222 ret = ath11k_wmi_simulate_radar(ar);
1223 if (ret)
1224 return ret;
1225
1226 return count;
1227 }
1228
1229 static const struct file_operations fops_simulate_radar = {
1230 .write = ath11k_write_simulate_radar,
1231 .open = simple_open
1232 };
1233
ath11k_debug_dump_dbr_entries(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1234 static ssize_t ath11k_debug_dump_dbr_entries(struct file *file,
1235 char __user *user_buf,
1236 size_t count, loff_t *ppos)
1237 {
1238 struct ath11k_dbg_dbr_data *dbr_dbg_data = file->private_data;
1239 static const char * const event_id_to_string[] = {"empty", "Rx", "Replenish"};
1240 int size = ATH11K_DEBUG_DBR_ENTRIES_MAX * 100;
1241 char *buf;
1242 int i, ret;
1243 int len = 0;
1244
1245 buf = kzalloc(size, GFP_KERNEL);
1246 if (!buf)
1247 return -ENOMEM;
1248
1249 len += scnprintf(buf + len, size - len,
1250 "-----------------------------------------\n");
1251 len += scnprintf(buf + len, size - len,
1252 "| idx | hp | tp | timestamp | event |\n");
1253 len += scnprintf(buf + len, size - len,
1254 "-----------------------------------------\n");
1255
1256 spin_lock_bh(&dbr_dbg_data->lock);
1257
1258 for (i = 0; i < dbr_dbg_data->num_ring_debug_entries; i++) {
1259 len += scnprintf(buf + len, size - len,
1260 "|%4u|%8u|%8u|%11llu|%8s|\n", i,
1261 dbr_dbg_data->entries[i].hp,
1262 dbr_dbg_data->entries[i].tp,
1263 dbr_dbg_data->entries[i].timestamp,
1264 event_id_to_string[dbr_dbg_data->entries[i].event]);
1265 }
1266
1267 spin_unlock_bh(&dbr_dbg_data->lock);
1268
1269 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1270 kfree(buf);
1271
1272 return ret;
1273 }
1274
1275 static const struct file_operations fops_debug_dump_dbr_entries = {
1276 .read = ath11k_debug_dump_dbr_entries,
1277 .open = simple_open,
1278 .owner = THIS_MODULE,
1279 .llseek = default_llseek,
1280 };
1281
ath11k_debugfs_dbr_dbg_destroy(struct ath11k * ar,int dbr_id)1282 static void ath11k_debugfs_dbr_dbg_destroy(struct ath11k *ar, int dbr_id)
1283 {
1284 struct ath11k_debug_dbr *dbr_debug;
1285 struct ath11k_dbg_dbr_data *dbr_dbg_data;
1286
1287 if (!ar->debug.dbr_debug[dbr_id])
1288 return;
1289
1290 dbr_debug = ar->debug.dbr_debug[dbr_id];
1291 dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1292
1293 debugfs_remove_recursive(dbr_debug->dbr_debugfs);
1294 kfree(dbr_dbg_data->entries);
1295 kfree(dbr_debug);
1296 ar->debug.dbr_debug[dbr_id] = NULL;
1297 }
1298
ath11k_debugfs_dbr_dbg_init(struct ath11k * ar,int dbr_id)1299 static int ath11k_debugfs_dbr_dbg_init(struct ath11k *ar, int dbr_id)
1300 {
1301 struct ath11k_debug_dbr *dbr_debug;
1302 struct ath11k_dbg_dbr_data *dbr_dbg_data;
1303 static const char * const dbr_id_to_str[] = {"spectral", "CFR"};
1304
1305 if (ar->debug.dbr_debug[dbr_id])
1306 return 0;
1307
1308 ar->debug.dbr_debug[dbr_id] = kzalloc(sizeof(*dbr_debug),
1309 GFP_KERNEL);
1310
1311 if (!ar->debug.dbr_debug[dbr_id])
1312 return -ENOMEM;
1313
1314 dbr_debug = ar->debug.dbr_debug[dbr_id];
1315 dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1316
1317 if (dbr_debug->dbr_debugfs)
1318 return 0;
1319
1320 dbr_debug->dbr_debugfs = debugfs_create_dir(dbr_id_to_str[dbr_id],
1321 ar->debug.debugfs_pdev);
1322 if (IS_ERR_OR_NULL(dbr_debug->dbr_debugfs)) {
1323 if (IS_ERR(dbr_debug->dbr_debugfs))
1324 return PTR_ERR(dbr_debug->dbr_debugfs);
1325 return -ENOMEM;
1326 }
1327
1328 dbr_debug->dbr_debug_enabled = true;
1329 dbr_dbg_data->num_ring_debug_entries = ATH11K_DEBUG_DBR_ENTRIES_MAX;
1330 dbr_dbg_data->dbr_debug_idx = 0;
1331 dbr_dbg_data->entries = kcalloc(ATH11K_DEBUG_DBR_ENTRIES_MAX,
1332 sizeof(struct ath11k_dbg_dbr_entry),
1333 GFP_KERNEL);
1334 if (!dbr_dbg_data->entries)
1335 return -ENOMEM;
1336
1337 spin_lock_init(&dbr_dbg_data->lock);
1338
1339 debugfs_create_file("dump_dbr_debug", 0444, dbr_debug->dbr_debugfs,
1340 dbr_dbg_data, &fops_debug_dump_dbr_entries);
1341
1342 return 0;
1343 }
1344
ath11k_debugfs_write_enable_dbr_dbg(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)1345 static ssize_t ath11k_debugfs_write_enable_dbr_dbg(struct file *file,
1346 const char __user *ubuf,
1347 size_t count, loff_t *ppos)
1348 {
1349 struct ath11k *ar = file->private_data;
1350 char buf[32] = {0};
1351 u32 dbr_id, enable;
1352 int ret;
1353
1354 mutex_lock(&ar->conf_mutex);
1355
1356 if (ar->state != ATH11K_STATE_ON) {
1357 ret = -ENETDOWN;
1358 goto out;
1359 }
1360
1361 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1362 if (ret < 0)
1363 goto out;
1364
1365 buf[ret] = '\0';
1366 ret = sscanf(buf, "%u %u", &dbr_id, &enable);
1367 if (ret != 2 || dbr_id > 1 || enable > 1) {
1368 ret = -EINVAL;
1369 ath11k_warn(ar->ab, "usage: echo <dbr_id> <val> dbr_id:0-Spectral 1-CFR val:0-disable 1-enable\n");
1370 goto out;
1371 }
1372
1373 if (enable) {
1374 ret = ath11k_debugfs_dbr_dbg_init(ar, dbr_id);
1375 if (ret) {
1376 ath11k_warn(ar->ab, "db ring module debugfs init failed: %d\n",
1377 ret);
1378 goto out;
1379 }
1380 } else {
1381 ath11k_debugfs_dbr_dbg_destroy(ar, dbr_id);
1382 }
1383
1384 ret = count;
1385 out:
1386 mutex_unlock(&ar->conf_mutex);
1387 return ret;
1388 }
1389
1390 static const struct file_operations fops_dbr_debug = {
1391 .write = ath11k_debugfs_write_enable_dbr_dbg,
1392 .open = simple_open,
1393 .owner = THIS_MODULE,
1394 .llseek = default_llseek,
1395 };
1396
ath11k_write_ps_timekeeper_enable(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1397 static ssize_t ath11k_write_ps_timekeeper_enable(struct file *file,
1398 const char __user *user_buf,
1399 size_t count, loff_t *ppos)
1400 {
1401 struct ath11k *ar = file->private_data;
1402 ssize_t ret;
1403 u8 ps_timekeeper_enable;
1404
1405 if (kstrtou8_from_user(user_buf, count, 0, &ps_timekeeper_enable))
1406 return -EINVAL;
1407
1408 mutex_lock(&ar->conf_mutex);
1409
1410 if (ar->state != ATH11K_STATE_ON) {
1411 ret = -ENETDOWN;
1412 goto exit;
1413 }
1414
1415 if (!ar->ps_state_enable) {
1416 ret = -EINVAL;
1417 goto exit;
1418 }
1419
1420 ar->ps_timekeeper_enable = !!ps_timekeeper_enable;
1421 ret = count;
1422 exit:
1423 mutex_unlock(&ar->conf_mutex);
1424
1425 return ret;
1426 }
1427
ath11k_read_ps_timekeeper_enable(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1428 static ssize_t ath11k_read_ps_timekeeper_enable(struct file *file,
1429 char __user *user_buf,
1430 size_t count, loff_t *ppos)
1431 {
1432 struct ath11k *ar = file->private_data;
1433 char buf[32];
1434 int len;
1435
1436 mutex_lock(&ar->conf_mutex);
1437 len = scnprintf(buf, sizeof(buf), "%d\n", ar->ps_timekeeper_enable);
1438 mutex_unlock(&ar->conf_mutex);
1439
1440 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1441 }
1442
1443 static const struct file_operations fops_ps_timekeeper_enable = {
1444 .read = ath11k_read_ps_timekeeper_enable,
1445 .write = ath11k_write_ps_timekeeper_enable,
1446 .open = simple_open,
1447 .owner = THIS_MODULE,
1448 .llseek = default_llseek,
1449 };
1450
ath11k_reset_peer_ps_duration(void * data,struct ieee80211_sta * sta)1451 static void ath11k_reset_peer_ps_duration(void *data,
1452 struct ieee80211_sta *sta)
1453 {
1454 struct ath11k *ar = data;
1455 struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
1456
1457 spin_lock_bh(&ar->data_lock);
1458 arsta->ps_total_duration = 0;
1459 spin_unlock_bh(&ar->data_lock);
1460 }
1461
ath11k_write_reset_ps_duration(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1462 static ssize_t ath11k_write_reset_ps_duration(struct file *file,
1463 const char __user *user_buf,
1464 size_t count, loff_t *ppos)
1465 {
1466 struct ath11k *ar = file->private_data;
1467 int ret;
1468 u8 reset_ps_duration;
1469
1470 if (kstrtou8_from_user(user_buf, count, 0, &reset_ps_duration))
1471 return -EINVAL;
1472
1473 mutex_lock(&ar->conf_mutex);
1474
1475 if (ar->state != ATH11K_STATE_ON) {
1476 ret = -ENETDOWN;
1477 goto exit;
1478 }
1479
1480 if (!ar->ps_state_enable) {
1481 ret = -EINVAL;
1482 goto exit;
1483 }
1484
1485 ieee80211_iterate_stations_atomic(ar->hw,
1486 ath11k_reset_peer_ps_duration,
1487 ar);
1488
1489 ret = count;
1490 exit:
1491 mutex_unlock(&ar->conf_mutex);
1492 return ret;
1493 }
1494
1495 static const struct file_operations fops_reset_ps_duration = {
1496 .write = ath11k_write_reset_ps_duration,
1497 .open = simple_open,
1498 .owner = THIS_MODULE,
1499 .llseek = default_llseek,
1500 };
1501
ath11k_peer_ps_state_disable(void * data,struct ieee80211_sta * sta)1502 static void ath11k_peer_ps_state_disable(void *data,
1503 struct ieee80211_sta *sta)
1504 {
1505 struct ath11k *ar = data;
1506 struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
1507
1508 spin_lock_bh(&ar->data_lock);
1509 arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
1510 arsta->ps_start_time = 0;
1511 arsta->ps_total_duration = 0;
1512 spin_unlock_bh(&ar->data_lock);
1513 }
1514
ath11k_write_ps_state_enable(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1515 static ssize_t ath11k_write_ps_state_enable(struct file *file,
1516 const char __user *user_buf,
1517 size_t count, loff_t *ppos)
1518 {
1519 struct ath11k *ar = file->private_data;
1520 struct ath11k_pdev *pdev = ar->pdev;
1521 int ret;
1522 u32 param;
1523 u8 ps_state_enable;
1524
1525 if (kstrtou8_from_user(user_buf, count, 0, &ps_state_enable))
1526 return -EINVAL;
1527
1528 mutex_lock(&ar->conf_mutex);
1529
1530 ps_state_enable = !!ps_state_enable;
1531
1532 if (ar->ps_state_enable == ps_state_enable) {
1533 ret = count;
1534 goto exit;
1535 }
1536
1537 param = WMI_PDEV_PEER_STA_PS_STATECHG_ENABLE;
1538 ret = ath11k_wmi_pdev_set_param(ar, param, ps_state_enable, pdev->pdev_id);
1539 if (ret) {
1540 ath11k_warn(ar->ab, "failed to enable ps_state_enable: %d\n",
1541 ret);
1542 goto exit;
1543 }
1544 ar->ps_state_enable = ps_state_enable;
1545
1546 if (!ar->ps_state_enable) {
1547 ar->ps_timekeeper_enable = false;
1548 ieee80211_iterate_stations_atomic(ar->hw,
1549 ath11k_peer_ps_state_disable,
1550 ar);
1551 }
1552
1553 ret = count;
1554
1555 exit:
1556 mutex_unlock(&ar->conf_mutex);
1557
1558 return ret;
1559 }
1560
ath11k_read_ps_state_enable(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1561 static ssize_t ath11k_read_ps_state_enable(struct file *file,
1562 char __user *user_buf,
1563 size_t count, loff_t *ppos)
1564 {
1565 struct ath11k *ar = file->private_data;
1566 char buf[32];
1567 int len;
1568
1569 mutex_lock(&ar->conf_mutex);
1570 len = scnprintf(buf, sizeof(buf), "%d\n", ar->ps_state_enable);
1571 mutex_unlock(&ar->conf_mutex);
1572
1573 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1574 }
1575
1576 static const struct file_operations fops_ps_state_enable = {
1577 .read = ath11k_read_ps_state_enable,
1578 .write = ath11k_write_ps_state_enable,
1579 .open = simple_open,
1580 .owner = THIS_MODULE,
1581 .llseek = default_llseek,
1582 };
1583
ath11k_debugfs_register(struct ath11k * ar)1584 int ath11k_debugfs_register(struct ath11k *ar)
1585 {
1586 struct ath11k_base *ab = ar->ab;
1587 char pdev_name[5];
1588 char buf[100] = {0};
1589
1590 snprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
1591
1592 ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
1593 if (IS_ERR(ar->debug.debugfs_pdev))
1594 return PTR_ERR(ar->debug.debugfs_pdev);
1595
1596 /* Create a symlink under ieee80211/phy* */
1597 snprintf(buf, 100, "../../ath11k/%pd2", ar->debug.debugfs_pdev);
1598 debugfs_create_symlink("ath11k", ar->hw->wiphy->debugfsdir, buf);
1599
1600 ath11k_debugfs_htt_stats_init(ar);
1601
1602 ath11k_debugfs_fw_stats_init(ar);
1603
1604 debugfs_create_file("ext_tx_stats", 0644,
1605 ar->debug.debugfs_pdev, ar,
1606 &fops_extd_tx_stats);
1607 debugfs_create_file("ext_rx_stats", 0644,
1608 ar->debug.debugfs_pdev, ar,
1609 &fops_extd_rx_stats);
1610 debugfs_create_file("pktlog_filter", 0644,
1611 ar->debug.debugfs_pdev, ar,
1612 &fops_pktlog_filter);
1613 debugfs_create_file("fw_dbglog_config", 0600,
1614 ar->debug.debugfs_pdev, ar,
1615 &fops_fw_dbglog);
1616
1617 if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
1618 debugfs_create_file("dfs_simulate_radar", 0200,
1619 ar->debug.debugfs_pdev, ar,
1620 &fops_simulate_radar);
1621 debugfs_create_bool("dfs_block_radar_events", 0200,
1622 ar->debug.debugfs_pdev,
1623 &ar->dfs_block_radar_events);
1624 }
1625
1626 if (ab->hw_params.dbr_debug_support)
1627 debugfs_create_file("enable_dbr_debug", 0200, ar->debug.debugfs_pdev,
1628 ar, &fops_dbr_debug);
1629
1630 debugfs_create_file("ps_state_enable", 0600, ar->debug.debugfs_pdev, ar,
1631 &fops_ps_state_enable);
1632
1633 if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
1634 ar->ab->wmi_ab.svc_map)) {
1635 debugfs_create_file("ps_timekeeper_enable", 0600,
1636 ar->debug.debugfs_pdev, ar,
1637 &fops_ps_timekeeper_enable);
1638
1639 debugfs_create_file("reset_ps_duration", 0200,
1640 ar->debug.debugfs_pdev, ar,
1641 &fops_reset_ps_duration);
1642 }
1643
1644 return 0;
1645 }
1646
ath11k_debugfs_unregister(struct ath11k * ar)1647 void ath11k_debugfs_unregister(struct ath11k *ar)
1648 {
1649 struct ath11k_debug_dbr *dbr_debug;
1650 struct ath11k_dbg_dbr_data *dbr_dbg_data;
1651 int i;
1652
1653 for (i = 0; i < WMI_DIRECT_BUF_MAX; i++) {
1654 dbr_debug = ar->debug.dbr_debug[i];
1655 if (!dbr_debug)
1656 continue;
1657
1658 dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1659 kfree(dbr_dbg_data->entries);
1660 debugfs_remove_recursive(dbr_debug->dbr_debugfs);
1661 kfree(dbr_debug);
1662 ar->debug.dbr_debug[i] = NULL;
1663 }
1664 }
1665
ath11k_write_twt_add_dialog(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)1666 static ssize_t ath11k_write_twt_add_dialog(struct file *file,
1667 const char __user *ubuf,
1668 size_t count, loff_t *ppos)
1669 {
1670 struct ath11k_vif *arvif = file->private_data;
1671 struct wmi_twt_add_dialog_params params = { 0 };
1672 struct wmi_twt_enable_params twt_params = {0};
1673 struct ath11k *ar = arvif->ar;
1674 u8 buf[128] = {0};
1675 int ret;
1676
1677 if (ar->twt_enabled == 0) {
1678 ath11k_err(ar->ab, "twt support is not enabled\n");
1679 return -EOPNOTSUPP;
1680 }
1681
1682 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1683 if (ret < 0)
1684 return ret;
1685
1686 buf[ret] = '\0';
1687 ret = sscanf(buf,
1688 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u %u %u %hhu %hhu %hhu %hhu %hhu",
1689 ¶ms.peer_macaddr[0],
1690 ¶ms.peer_macaddr[1],
1691 ¶ms.peer_macaddr[2],
1692 ¶ms.peer_macaddr[3],
1693 ¶ms.peer_macaddr[4],
1694 ¶ms.peer_macaddr[5],
1695 ¶ms.dialog_id,
1696 ¶ms.wake_intvl_us,
1697 ¶ms.wake_intvl_mantis,
1698 ¶ms.wake_dura_us,
1699 ¶ms.sp_offset_us,
1700 ¶ms.twt_cmd,
1701 ¶ms.flag_bcast,
1702 ¶ms.flag_trigger,
1703 ¶ms.flag_flow_type,
1704 ¶ms.flag_protection);
1705 if (ret != 16)
1706 return -EINVAL;
1707
1708 /* In the case of station vif, TWT is entirely handled by
1709 * the firmware based on the input parameters in the TWT enable
1710 * WMI command that is sent to the target during assoc.
1711 * For manually testing the TWT feature, we need to first disable
1712 * TWT and send enable command again with TWT input parameter
1713 * sta_cong_timer_ms set to 0.
1714 */
1715 if (arvif->vif->type == NL80211_IFTYPE_STATION) {
1716 ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
1717
1718 ath11k_wmi_fill_default_twt_params(&twt_params);
1719 twt_params.sta_cong_timer_ms = 0;
1720
1721 ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id, &twt_params);
1722 }
1723
1724 params.vdev_id = arvif->vdev_id;
1725
1726 ret = ath11k_wmi_send_twt_add_dialog_cmd(arvif->ar, ¶ms);
1727 if (ret)
1728 goto err_twt_add_dialog;
1729
1730 return count;
1731
1732 err_twt_add_dialog:
1733 if (arvif->vif->type == NL80211_IFTYPE_STATION) {
1734 ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
1735 ath11k_wmi_fill_default_twt_params(&twt_params);
1736 ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id, &twt_params);
1737 }
1738
1739 return ret;
1740 }
1741
ath11k_write_twt_del_dialog(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)1742 static ssize_t ath11k_write_twt_del_dialog(struct file *file,
1743 const char __user *ubuf,
1744 size_t count, loff_t *ppos)
1745 {
1746 struct ath11k_vif *arvif = file->private_data;
1747 struct wmi_twt_del_dialog_params params = { 0 };
1748 struct wmi_twt_enable_params twt_params = {0};
1749 struct ath11k *ar = arvif->ar;
1750 u8 buf[64] = {0};
1751 int ret;
1752
1753 if (ar->twt_enabled == 0) {
1754 ath11k_err(ar->ab, "twt support is not enabled\n");
1755 return -EOPNOTSUPP;
1756 }
1757
1758 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1759 if (ret < 0)
1760 return ret;
1761
1762 buf[ret] = '\0';
1763 ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u",
1764 ¶ms.peer_macaddr[0],
1765 ¶ms.peer_macaddr[1],
1766 ¶ms.peer_macaddr[2],
1767 ¶ms.peer_macaddr[3],
1768 ¶ms.peer_macaddr[4],
1769 ¶ms.peer_macaddr[5],
1770 ¶ms.dialog_id);
1771 if (ret != 7)
1772 return -EINVAL;
1773
1774 params.vdev_id = arvif->vdev_id;
1775
1776 ret = ath11k_wmi_send_twt_del_dialog_cmd(arvif->ar, ¶ms);
1777 if (ret)
1778 return ret;
1779
1780 if (arvif->vif->type == NL80211_IFTYPE_STATION) {
1781 ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
1782 ath11k_wmi_fill_default_twt_params(&twt_params);
1783 ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id, &twt_params);
1784 }
1785
1786 return count;
1787 }
1788
ath11k_write_twt_pause_dialog(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)1789 static ssize_t ath11k_write_twt_pause_dialog(struct file *file,
1790 const char __user *ubuf,
1791 size_t count, loff_t *ppos)
1792 {
1793 struct ath11k_vif *arvif = file->private_data;
1794 struct wmi_twt_pause_dialog_params params = { 0 };
1795 u8 buf[64] = {0};
1796 int ret;
1797
1798 if (arvif->ar->twt_enabled == 0) {
1799 ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1800 return -EOPNOTSUPP;
1801 }
1802
1803 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1804 if (ret < 0)
1805 return ret;
1806
1807 buf[ret] = '\0';
1808 ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u",
1809 ¶ms.peer_macaddr[0],
1810 ¶ms.peer_macaddr[1],
1811 ¶ms.peer_macaddr[2],
1812 ¶ms.peer_macaddr[3],
1813 ¶ms.peer_macaddr[4],
1814 ¶ms.peer_macaddr[5],
1815 ¶ms.dialog_id);
1816 if (ret != 7)
1817 return -EINVAL;
1818
1819 params.vdev_id = arvif->vdev_id;
1820
1821 ret = ath11k_wmi_send_twt_pause_dialog_cmd(arvif->ar, ¶ms);
1822 if (ret)
1823 return ret;
1824
1825 return count;
1826 }
1827
ath11k_write_twt_resume_dialog(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)1828 static ssize_t ath11k_write_twt_resume_dialog(struct file *file,
1829 const char __user *ubuf,
1830 size_t count, loff_t *ppos)
1831 {
1832 struct ath11k_vif *arvif = file->private_data;
1833 struct wmi_twt_resume_dialog_params params = { 0 };
1834 u8 buf[64] = {0};
1835 int ret;
1836
1837 if (arvif->ar->twt_enabled == 0) {
1838 ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1839 return -EOPNOTSUPP;
1840 }
1841
1842 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1843 if (ret < 0)
1844 return ret;
1845
1846 buf[ret] = '\0';
1847 ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u",
1848 ¶ms.peer_macaddr[0],
1849 ¶ms.peer_macaddr[1],
1850 ¶ms.peer_macaddr[2],
1851 ¶ms.peer_macaddr[3],
1852 ¶ms.peer_macaddr[4],
1853 ¶ms.peer_macaddr[5],
1854 ¶ms.dialog_id,
1855 ¶ms.sp_offset_us,
1856 ¶ms.next_twt_size);
1857 if (ret != 9)
1858 return -EINVAL;
1859
1860 params.vdev_id = arvif->vdev_id;
1861
1862 ret = ath11k_wmi_send_twt_resume_dialog_cmd(arvif->ar, ¶ms);
1863 if (ret)
1864 return ret;
1865
1866 return count;
1867 }
1868
1869 static const struct file_operations ath11k_fops_twt_add_dialog = {
1870 .write = ath11k_write_twt_add_dialog,
1871 .open = simple_open
1872 };
1873
1874 static const struct file_operations ath11k_fops_twt_del_dialog = {
1875 .write = ath11k_write_twt_del_dialog,
1876 .open = simple_open
1877 };
1878
1879 static const struct file_operations ath11k_fops_twt_pause_dialog = {
1880 .write = ath11k_write_twt_pause_dialog,
1881 .open = simple_open
1882 };
1883
1884 static const struct file_operations ath11k_fops_twt_resume_dialog = {
1885 .write = ath11k_write_twt_resume_dialog,
1886 .open = simple_open
1887 };
1888
ath11k_debugfs_add_interface(struct ath11k_vif * arvif)1889 void ath11k_debugfs_add_interface(struct ath11k_vif *arvif)
1890 {
1891 struct ath11k_base *ab = arvif->ar->ab;
1892
1893 if (arvif->vif->type != NL80211_IFTYPE_AP &&
1894 !(arvif->vif->type == NL80211_IFTYPE_STATION &&
1895 test_bit(WMI_TLV_SERVICE_STA_TWT, ab->wmi_ab.svc_map)))
1896 return;
1897
1898 arvif->debugfs_twt = debugfs_create_dir("twt",
1899 arvif->vif->debugfs_dir);
1900 debugfs_create_file("add_dialog", 0200, arvif->debugfs_twt,
1901 arvif, &ath11k_fops_twt_add_dialog);
1902
1903 debugfs_create_file("del_dialog", 0200, arvif->debugfs_twt,
1904 arvif, &ath11k_fops_twt_del_dialog);
1905
1906 debugfs_create_file("pause_dialog", 0200, arvif->debugfs_twt,
1907 arvif, &ath11k_fops_twt_pause_dialog);
1908
1909 debugfs_create_file("resume_dialog", 0200, arvif->debugfs_twt,
1910 arvif, &ath11k_fops_twt_resume_dialog);
1911 }
1912
ath11k_debugfs_remove_interface(struct ath11k_vif * arvif)1913 void ath11k_debugfs_remove_interface(struct ath11k_vif *arvif)
1914 {
1915 if (!arvif->debugfs_twt)
1916 return;
1917
1918 debugfs_remove_recursive(arvif->debugfs_twt);
1919 arvif->debugfs_twt = NULL;
1920 }
1921