xref: /linux/drivers/net/wireless/ath/ath12k/debugfs.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
5  */
6 
7 #include "core.h"
8 #include "debugfs.h"
9 #include "debugfs_htt_stats.h"
10 
11 static ssize_t ath12k_write_simulate_radar(struct file *file,
12 					   const char __user *user_buf,
13 					   size_t count, loff_t *ppos)
14 {
15 	struct ath12k *ar = file->private_data;
16 	int ret;
17 
18 	wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
19 	ret = ath12k_wmi_simulate_radar(ar);
20 	if (ret)
21 		goto exit;
22 
23 	ret = count;
24 exit:
25 	wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
26 	return ret;
27 }
28 
29 static const struct file_operations fops_simulate_radar = {
30 	.write = ath12k_write_simulate_radar,
31 	.open = simple_open
32 };
33 
34 void ath12k_debugfs_soc_create(struct ath12k_base *ab)
35 {
36 	bool dput_needed;
37 	char soc_name[64] = { 0 };
38 	struct dentry *debugfs_ath12k;
39 
40 	debugfs_ath12k = debugfs_lookup("ath12k", NULL);
41 	if (debugfs_ath12k) {
42 		/* a dentry from lookup() needs dput() after we don't use it */
43 		dput_needed = true;
44 	} else {
45 		debugfs_ath12k = debugfs_create_dir("ath12k", NULL);
46 		if (IS_ERR_OR_NULL(debugfs_ath12k))
47 			return;
48 		dput_needed = false;
49 	}
50 
51 	scnprintf(soc_name, sizeof(soc_name), "%s-%s", ath12k_bus_str(ab->hif.bus),
52 		  dev_name(ab->dev));
53 
54 	ab->debugfs_soc = debugfs_create_dir(soc_name, debugfs_ath12k);
55 
56 	if (dput_needed)
57 		dput(debugfs_ath12k);
58 }
59 
60 void ath12k_debugfs_soc_destroy(struct ath12k_base *ab)
61 {
62 	debugfs_remove_recursive(ab->debugfs_soc);
63 	ab->debugfs_soc = NULL;
64 	/* We are not removing ath12k directory on purpose, even if it
65 	 * would be empty. This simplifies the directory handling and it's
66 	 * a minor cosmetic issue to leave an empty ath12k directory to
67 	 * debugfs.
68 	 */
69 }
70 
71 void ath12k_debugfs_register(struct ath12k *ar)
72 {
73 	struct ath12k_base *ab = ar->ab;
74 	struct ieee80211_hw *hw = ar->ah->hw;
75 	char pdev_name[5];
76 	char buf[100] = {0};
77 
78 	scnprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
79 
80 	ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
81 
82 	/* Create a symlink under ieee80211/phy* */
83 	scnprintf(buf, sizeof(buf), "../../ath12k/%pd2", ar->debug.debugfs_pdev);
84 	ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k",
85 								hw->wiphy->debugfsdir,
86 								buf);
87 
88 	if (ar->mac.sbands[NL80211_BAND_5GHZ].channels) {
89 		debugfs_create_file("dfs_simulate_radar", 0200,
90 				    ar->debug.debugfs_pdev, ar,
91 				    &fops_simulate_radar);
92 	}
93 
94 	ath12k_debugfs_htt_stats_register(ar);
95 }
96 
97 void ath12k_debugfs_unregister(struct ath12k *ar)
98 {
99 	if (!ar->debug.debugfs_pdev)
100 		return;
101 
102 	/* Remove symlink under ieee80211/phy* */
103 	debugfs_remove(ar->debug.debugfs_pdev_symlink);
104 	debugfs_remove_recursive(ar->debug.debugfs_pdev);
105 	ar->debug.debugfs_pdev_symlink = NULL;
106 	ar->debug.debugfs_pdev = NULL;
107 }
108