xref: /linux/drivers/net/wireless/ath/ath11k/debugfs.c (revision 27605c8c0f69e319df156b471974e4e223035378)
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", &param, &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 		     &params.peer_macaddr[0],
1576 		     &params.peer_macaddr[1],
1577 		     &params.peer_macaddr[2],
1578 		     &params.peer_macaddr[3],
1579 		     &params.peer_macaddr[4],
1580 		     &params.peer_macaddr[5],
1581 		     &params.dialog_id,
1582 		     &params.wake_intvl_us,
1583 		     &params.wake_intvl_mantis,
1584 		     &params.wake_dura_us,
1585 		     &params.sp_offset_us,
1586 		     &params.twt_cmd,
1587 		     &params.flag_bcast,
1588 		     &params.flag_trigger,
1589 		     &params.flag_flow_type,
1590 		     &params.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, &params);
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 		     &params.peer_macaddr[0],
1651 		     &params.peer_macaddr[1],
1652 		     &params.peer_macaddr[2],
1653 		     &params.peer_macaddr[3],
1654 		     &params.peer_macaddr[4],
1655 		     &params.peer_macaddr[5],
1656 		     &params.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, &params);
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 		     &params.peer_macaddr[0],
1696 		     &params.peer_macaddr[1],
1697 		     &params.peer_macaddr[2],
1698 		     &params.peer_macaddr[3],
1699 		     &params.peer_macaddr[4],
1700 		     &params.peer_macaddr[5],
1701 		     &params.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, &params);
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 		     &params.peer_macaddr[0],
1735 		     &params.peer_macaddr[1],
1736 		     &params.peer_macaddr[2],
1737 		     &params.peer_macaddr[3],
1738 		     &params.peer_macaddr[4],
1739 		     &params.peer_macaddr[5],
1740 		     &params.dialog_id,
1741 		     &params.sp_offset_us,
1742 		     &params.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, &params);
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