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