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