1 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
2 /*
3 * Copyright (C) 2024-2025 Intel Corporation
4 */
5 #include "iface.h"
6 #include "sta.h"
7
8 #define MLD_DEBUGFS_OPEN_WRAPPER(name, buflen, argtype) \
9 struct dbgfs_##name##_data { \
10 argtype *arg; \
11 bool read_done; \
12 ssize_t rlen; \
13 char buf[buflen]; \
14 }; \
15 static int _iwl_dbgfs_##name##_open(struct inode *inode, \
16 struct file *file) \
17 { \
18 struct dbgfs_##name##_data *data; \
19 \
20 if ((file->f_flags & O_ACCMODE) == O_RDWR) \
21 return -EOPNOTSUPP; \
22 \
23 data = kzalloc(sizeof(*data), GFP_KERNEL); \
24 if (!data) \
25 return -ENOMEM; \
26 \
27 data->read_done = false; \
28 data->arg = inode->i_private; \
29 file->private_data = data; \
30 \
31 return 0; \
32 }
33
34 #define MLD_DEBUGFS_READ_WRAPPER(name) \
35 static ssize_t _iwl_dbgfs_##name##_read(struct file *file, \
36 char __user *user_buf, \
37 size_t count, loff_t *ppos) \
38 { \
39 struct dbgfs_##name##_data *data = file->private_data; \
40 \
41 if (!data->read_done) { \
42 data->read_done = true; \
43 data->rlen = iwl_dbgfs_##name##_read(data->arg, \
44 sizeof(data->buf),\
45 data->buf); \
46 } \
47 \
48 if (data->rlen < 0) \
49 return data->rlen; \
50 return simple_read_from_buffer(user_buf, count, ppos, \
51 data->buf, data->rlen); \
52 }
53
_iwl_dbgfs_release(struct inode * inode,struct file * file)54 static int _iwl_dbgfs_release(struct inode *inode, struct file *file)
55 {
56 kfree(file->private_data);
57 return 0;
58 }
59
60 #define _MLD_DEBUGFS_READ_FILE_OPS(name, buflen, argtype) \
61 MLD_DEBUGFS_OPEN_WRAPPER(name, buflen, argtype) \
62 MLD_DEBUGFS_READ_WRAPPER(name) \
63 static const struct file_operations iwl_dbgfs_##name##_ops = { \
64 .read = _iwl_dbgfs_##name##_read, \
65 .open = _iwl_dbgfs_##name##_open, \
66 .llseek = generic_file_llseek, \
67 .release = _iwl_dbgfs_release, \
68 }
69
70 #define WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER(name) \
71 static ssize_t iwl_dbgfs_##name##_write_handler(struct wiphy *wiphy, \
72 struct file *file, char *buf, \
73 size_t count, void *data) \
74 { \
75 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); \
76 struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); \
77 return iwl_dbgfs_##name##_write(mld, buf, count, data); \
78 }
79
80 static inline struct iwl_mld *
iwl_mld_from_link_sta(struct ieee80211_link_sta * link_sta)81 iwl_mld_from_link_sta(struct ieee80211_link_sta *link_sta)
82 {
83 struct ieee80211_vif *vif =
84 iwl_mld_sta_from_mac80211(link_sta->sta)->vif;
85 return iwl_mld_vif_from_mac80211(vif)->mld;
86 }
87
88 static inline struct iwl_mld *
iwl_mld_from_bss_conf(struct ieee80211_bss_conf * link)89 iwl_mld_from_bss_conf(struct ieee80211_bss_conf *link)
90 {
91 return iwl_mld_vif_from_mac80211(link->vif)->mld;
92 }
93
iwl_mld_from_vif(struct ieee80211_vif * vif)94 static inline struct iwl_mld *iwl_mld_from_vif(struct ieee80211_vif *vif)
95 {
96 return iwl_mld_vif_from_mac80211(vif)->mld;
97 }
98
99 #define WIPHY_DEBUGFS_WRITE_WRAPPER(name, bufsz, objtype) \
100 WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER(name) \
101 static ssize_t __iwl_dbgfs_##name##_write(struct file *file, \
102 const char __user *user_buf, \
103 size_t count, loff_t *ppos) \
104 { \
105 struct ieee80211_##objtype *arg = file->private_data; \
106 struct iwl_mld *mld = iwl_mld_from_##objtype(arg); \
107 char buf[bufsz] = {}; \
108 \
109 return wiphy_locked_debugfs_write(mld->wiphy, file, \
110 buf, sizeof(buf), \
111 user_buf, count, \
112 iwl_dbgfs_##name##_write_handler, \
113 arg); \
114 }
115
116 #define WIPHY_DEBUGFS_WRITE_FILE_OPS(name, bufsz, objtype) \
117 WIPHY_DEBUGFS_WRITE_WRAPPER(name, bufsz, objtype) \
118 static const struct file_operations iwl_dbgfs_##name##_ops = { \
119 .write = __iwl_dbgfs_##name##_write, \
120 .open = simple_open, \
121 .llseek = generic_file_llseek, \
122 }
123
124 #define WIPHY_DEBUGFS_READ_HANDLER_WRAPPER_MLD(name) \
125 static ssize_t iwl_dbgfs_##name##_read_handler(struct wiphy *wiphy, \
126 struct file *file, char *buf, \
127 size_t count, void *data) \
128 { \
129 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); \
130 struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); \
131 return iwl_dbgfs_##name##_read(mld, buf, count); \
132 }
133
134 #define WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER_MLD(name) \
135 static ssize_t iwl_dbgfs_##name##_write_handler(struct wiphy *wiphy, \
136 struct file *file, char *buf, \
137 size_t count, void *data) \
138 { \
139 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); \
140 struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); \
141 return iwl_dbgfs_##name##_write(mld, buf, count); \
142 }
143
144 #define WIPHY_DEBUGFS_WRITE_WRAPPER_MLD(name) \
145 WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER_MLD(name) \
146 static ssize_t __iwl_dbgfs_##name##_write(struct file *file, \
147 const char __user *user_buf, \
148 size_t count, loff_t *ppos) \
149 { \
150 struct dbgfs_##name##_data *data = file->private_data; \
151 struct iwl_mld *mld = data->arg; \
152 \
153 return wiphy_locked_debugfs_write(mld->wiphy, file, \
154 data->buf, sizeof(data->buf), \
155 user_buf, count, \
156 iwl_dbgfs_##name##_write_handler, \
157 NULL); \
158 }
159
160 #define WIPHY_DEBUGFS_READ_WRAPPER_MLD(name) \
161 WIPHY_DEBUGFS_READ_HANDLER_WRAPPER_MLD(name) \
162 static ssize_t __iwl_dbgfs_##name##_read(struct file *file, \
163 char __user *user_buf, \
164 size_t count, loff_t *ppos) \
165 { \
166 struct dbgfs_##name##_data *data = file->private_data; \
167 struct iwl_mld *mld = data->arg; \
168 \
169 if (!data->read_done) { \
170 data->read_done = true; \
171 data->rlen = wiphy_locked_debugfs_read(mld->wiphy, \
172 file, data->buf, sizeof(data->buf), \
173 user_buf, count, ppos, \
174 iwl_dbgfs_##name##_read_handler, NULL); \
175 return data->rlen; \
176 } \
177 \
178 if (data->rlen < 0) \
179 return data->rlen; \
180 return simple_read_from_buffer(user_buf, count, ppos, \
181 data->buf, data->rlen); \
182 }
183
184 #define WIPHY_DEBUGFS_READ_FILE_OPS_MLD(name, bufsz) \
185 MLD_DEBUGFS_OPEN_WRAPPER(name, bufsz, struct iwl_mld) \
186 WIPHY_DEBUGFS_READ_WRAPPER_MLD(name) \
187 static const struct file_operations iwl_dbgfs_##name##_ops = { \
188 .read = __iwl_dbgfs_##name##_read, \
189 .open = _iwl_dbgfs_##name##_open, \
190 .llseek = generic_file_llseek, \
191 .release = _iwl_dbgfs_release, \
192 }
193
194 #define WIPHY_DEBUGFS_WRITE_FILE_OPS_MLD(name, bufsz) \
195 MLD_DEBUGFS_OPEN_WRAPPER(name, bufsz, struct iwl_mld) \
196 WIPHY_DEBUGFS_WRITE_WRAPPER_MLD(name) \
197 static const struct file_operations iwl_dbgfs_##name##_ops = { \
198 .write = __iwl_dbgfs_##name##_write, \
199 .open = _iwl_dbgfs_##name##_open, \
200 .llseek = generic_file_llseek, \
201 .release = _iwl_dbgfs_release, \
202 }
203
204 #define WIPHY_DEBUGFS_READ_WRITE_FILE_OPS_MLD(name, bufsz) \
205 MLD_DEBUGFS_OPEN_WRAPPER(name, bufsz, struct iwl_mld) \
206 WIPHY_DEBUGFS_WRITE_WRAPPER_MLD(name) \
207 WIPHY_DEBUGFS_READ_WRAPPER_MLD(name) \
208 static const struct file_operations iwl_dbgfs_##name##_ops = { \
209 .write = __iwl_dbgfs_##name##_write, \
210 .read = __iwl_dbgfs_##name##_read, \
211 .open = _iwl_dbgfs_##name##_open, \
212 .llseek = generic_file_llseek, \
213 .release = _iwl_dbgfs_release, \
214 }
215
216 #define WIPHY_DEBUGFS_WRITE_WRAPPER_IEEE80211(name, bufsz, objtype) \
217 WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER(name) \
218 static ssize_t _iwl_dbgfs_##name##_write(struct file *file, \
219 const char __user *user_buf, \
220 size_t count, loff_t *ppos) \
221 { \
222 struct dbgfs_##name##_data *data = file->private_data; \
223 struct ieee80211_##objtype *arg = data->arg; \
224 struct iwl_mld *mld = iwl_mld_from_##objtype(arg); \
225 char buf[bufsz] = {}; \
226 \
227 return wiphy_locked_debugfs_write(mld->wiphy, file, \
228 buf, sizeof(buf), \
229 user_buf, count, \
230 iwl_dbgfs_##name##_write_handler, \
231 arg); \
232 }
233
234 #define IEEE80211_WIPHY_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, objtype) \
235 MLD_DEBUGFS_OPEN_WRAPPER(name, bufsz, struct ieee80211_##objtype) \
236 WIPHY_DEBUGFS_WRITE_WRAPPER_IEEE80211(name, bufsz, objtype) \
237 MLD_DEBUGFS_READ_WRAPPER(name) \
238 static const struct file_operations iwl_dbgfs_##name##_ops = { \
239 .write = _iwl_dbgfs_##name##_write, \
240 .read = _iwl_dbgfs_##name##_read, \
241 .open = _iwl_dbgfs_##name##_open, \
242 .llseek = generic_file_llseek, \
243 .release = _iwl_dbgfs_release, \
244 }
245