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