diff options
Diffstat (limited to 'net/mac80211/debugfs_netdev.c')
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 391 |
1 files changed, 168 insertions, 223 deletions
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 61234e79022b..83d4289d954b 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/netdevice.h> | 14 | #include <linux/netdevice.h> |
15 | #include <linux/rtnetlink.h> | 15 | #include <linux/rtnetlink.h> |
16 | #include <linux/slab.h> | ||
16 | #include <linux/notifier.h> | 17 | #include <linux/notifier.h> |
17 | #include <net/mac80211.h> | 18 | #include <net/mac80211.h> |
18 | #include <net/cfg80211.h> | 19 | #include <net/cfg80211.h> |
@@ -41,6 +42,34 @@ static ssize_t ieee80211_if_read( | |||
41 | return ret; | 42 | return ret; |
42 | } | 43 | } |
43 | 44 | ||
45 | static ssize_t ieee80211_if_write( | ||
46 | struct ieee80211_sub_if_data *sdata, | ||
47 | const char __user *userbuf, | ||
48 | size_t count, loff_t *ppos, | ||
49 | ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int)) | ||
50 | { | ||
51 | u8 *buf; | ||
52 | ssize_t ret; | ||
53 | |||
54 | buf = kmalloc(count, GFP_KERNEL); | ||
55 | if (!buf) | ||
56 | return -ENOMEM; | ||
57 | |||
58 | ret = -EFAULT; | ||
59 | if (copy_from_user(buf, userbuf, count)) | ||
60 | goto freebuf; | ||
61 | |||
62 | ret = -ENODEV; | ||
63 | rtnl_lock(); | ||
64 | if (sdata->dev->reg_state == NETREG_REGISTERED) | ||
65 | ret = (*write)(sdata, buf, count); | ||
66 | rtnl_unlock(); | ||
67 | |||
68 | freebuf: | ||
69 | kfree(buf); | ||
70 | return ret; | ||
71 | } | ||
72 | |||
44 | #define IEEE80211_IF_FMT(name, field, format_string) \ | 73 | #define IEEE80211_IF_FMT(name, field, format_string) \ |
45 | static ssize_t ieee80211_if_fmt_##name( \ | 74 | static ssize_t ieee80211_if_fmt_##name( \ |
46 | const struct ieee80211_sub_if_data *sdata, char *buf, \ | 75 | const struct ieee80211_sub_if_data *sdata, char *buf, \ |
@@ -71,7 +100,7 @@ static ssize_t ieee80211_if_fmt_##name( \ | |||
71 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ | 100 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ |
72 | } | 101 | } |
73 | 102 | ||
74 | #define __IEEE80211_IF_FILE(name) \ | 103 | #define __IEEE80211_IF_FILE(name, _write) \ |
75 | static ssize_t ieee80211_if_read_##name(struct file *file, \ | 104 | static ssize_t ieee80211_if_read_##name(struct file *file, \ |
76 | char __user *userbuf, \ | 105 | char __user *userbuf, \ |
77 | size_t count, loff_t *ppos) \ | 106 | size_t count, loff_t *ppos) \ |
@@ -82,22 +111,99 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \ | |||
82 | } \ | 111 | } \ |
83 | static const struct file_operations name##_ops = { \ | 112 | static const struct file_operations name##_ops = { \ |
84 | .read = ieee80211_if_read_##name, \ | 113 | .read = ieee80211_if_read_##name, \ |
114 | .write = (_write), \ | ||
85 | .open = mac80211_open_file_generic, \ | 115 | .open = mac80211_open_file_generic, \ |
86 | } | 116 | } |
87 | 117 | ||
118 | #define __IEEE80211_IF_FILE_W(name) \ | ||
119 | static ssize_t ieee80211_if_write_##name(struct file *file, \ | ||
120 | const char __user *userbuf, \ | ||
121 | size_t count, loff_t *ppos) \ | ||
122 | { \ | ||
123 | return ieee80211_if_write(file->private_data, userbuf, count, \ | ||
124 | ppos, ieee80211_if_parse_##name); \ | ||
125 | } \ | ||
126 | __IEEE80211_IF_FILE(name, ieee80211_if_write_##name) | ||
127 | |||
128 | |||
88 | #define IEEE80211_IF_FILE(name, field, format) \ | 129 | #define IEEE80211_IF_FILE(name, field, format) \ |
89 | IEEE80211_IF_FMT_##format(name, field) \ | 130 | IEEE80211_IF_FMT_##format(name, field) \ |
90 | __IEEE80211_IF_FILE(name) | 131 | __IEEE80211_IF_FILE(name, NULL) |
91 | 132 | ||
92 | /* common attributes */ | 133 | /* common attributes */ |
93 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); | 134 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); |
94 | IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC); | 135 | IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ], |
95 | IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); | 136 | HEX); |
137 | IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], | ||
138 | HEX); | ||
96 | 139 | ||
97 | /* STA attributes */ | 140 | /* STA attributes */ |
98 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 141 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
99 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); | 142 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); |
100 | IEEE80211_IF_FILE(capab, u.mgd.capab, HEX); | 143 | |
144 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, | ||
145 | enum ieee80211_smps_mode smps_mode) | ||
146 | { | ||
147 | struct ieee80211_local *local = sdata->local; | ||
148 | int err; | ||
149 | |||
150 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) && | ||
151 | smps_mode == IEEE80211_SMPS_STATIC) | ||
152 | return -EINVAL; | ||
153 | |||
154 | /* auto should be dynamic if in PS mode */ | ||
155 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) && | ||
156 | (smps_mode == IEEE80211_SMPS_DYNAMIC || | ||
157 | smps_mode == IEEE80211_SMPS_AUTOMATIC)) | ||
158 | return -EINVAL; | ||
159 | |||
160 | /* supported only on managed interfaces for now */ | ||
161 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
162 | return -EOPNOTSUPP; | ||
163 | |||
164 | mutex_lock(&local->iflist_mtx); | ||
165 | err = __ieee80211_request_smps(sdata, smps_mode); | ||
166 | mutex_unlock(&local->iflist_mtx); | ||
167 | |||
168 | return err; | ||
169 | } | ||
170 | |||
171 | static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { | ||
172 | [IEEE80211_SMPS_AUTOMATIC] = "auto", | ||
173 | [IEEE80211_SMPS_OFF] = "off", | ||
174 | [IEEE80211_SMPS_STATIC] = "static", | ||
175 | [IEEE80211_SMPS_DYNAMIC] = "dynamic", | ||
176 | }; | ||
177 | |||
178 | static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata, | ||
179 | char *buf, int buflen) | ||
180 | { | ||
181 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
182 | return -EOPNOTSUPP; | ||
183 | |||
184 | return snprintf(buf, buflen, "request: %s\nused: %s\n", | ||
185 | smps_modes[sdata->u.mgd.req_smps], | ||
186 | smps_modes[sdata->u.mgd.ap_smps]); | ||
187 | } | ||
188 | |||
189 | static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata, | ||
190 | const char *buf, int buflen) | ||
191 | { | ||
192 | enum ieee80211_smps_mode mode; | ||
193 | |||
194 | for (mode = 0; mode < IEEE80211_SMPS_NUM_MODES; mode++) { | ||
195 | if (strncmp(buf, smps_modes[mode], buflen) == 0) { | ||
196 | int err = ieee80211_set_smps(sdata, mode); | ||
197 | if (!err) | ||
198 | return buflen; | ||
199 | return err; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | return -EINVAL; | ||
204 | } | ||
205 | |||
206 | __IEEE80211_IF_FILE_W(smps); | ||
101 | 207 | ||
102 | /* AP attributes */ | 208 | /* AP attributes */ |
103 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 209 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
@@ -109,7 +215,7 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast( | |||
109 | return scnprintf(buf, buflen, "%u\n", | 215 | return scnprintf(buf, buflen, "%u\n", |
110 | skb_queue_len(&sdata->u.ap.ps_bc_buf)); | 216 | skb_queue_len(&sdata->u.ap.ps_bc_buf)); |
111 | } | 217 | } |
112 | __IEEE80211_IF_FILE(num_buffered_multicast); | 218 | __IEEE80211_IF_FILE(num_buffered_multicast, NULL); |
113 | 219 | ||
114 | /* WDS attributes */ | 220 | /* WDS attributes */ |
115 | IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); | 221 | IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); |
@@ -149,49 +255,55 @@ IEEE80211_IF_FILE(path_refresh_time, | |||
149 | u.mesh.mshcfg.path_refresh_time, DEC); | 255 | u.mesh.mshcfg.path_refresh_time, DEC); |
150 | IEEE80211_IF_FILE(min_discovery_timeout, | 256 | IEEE80211_IF_FILE(min_discovery_timeout, |
151 | u.mesh.mshcfg.min_discovery_timeout, DEC); | 257 | u.mesh.mshcfg.min_discovery_timeout, DEC); |
258 | IEEE80211_IF_FILE(dot11MeshHWMPRootMode, | ||
259 | u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC); | ||
152 | #endif | 260 | #endif |
153 | 261 | ||
154 | 262 | ||
155 | #define DEBUGFS_ADD(name, type)\ | 263 | #define DEBUGFS_ADD(name) \ |
156 | sdata->debugfs.type.name = debugfs_create_file(#name, 0400,\ | 264 | debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ |
157 | sdata->debugfsdir, sdata, &name##_ops); | 265 | sdata, &name##_ops); |
266 | |||
267 | #define DEBUGFS_ADD_MODE(name, mode) \ | ||
268 | debugfs_create_file(#name, mode, sdata->debugfs.dir, \ | ||
269 | sdata, &name##_ops); | ||
158 | 270 | ||
159 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | 271 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) |
160 | { | 272 | { |
161 | DEBUGFS_ADD(drop_unencrypted, sta); | 273 | DEBUGFS_ADD(drop_unencrypted); |
162 | DEBUGFS_ADD(force_unicast_rateidx, sta); | 274 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
163 | DEBUGFS_ADD(max_ratectrl_rateidx, sta); | 275 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
164 | 276 | ||
165 | DEBUGFS_ADD(bssid, sta); | 277 | DEBUGFS_ADD(bssid); |
166 | DEBUGFS_ADD(aid, sta); | 278 | DEBUGFS_ADD(aid); |
167 | DEBUGFS_ADD(capab, sta); | 279 | DEBUGFS_ADD_MODE(smps, 0600); |
168 | } | 280 | } |
169 | 281 | ||
170 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 282 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
171 | { | 283 | { |
172 | DEBUGFS_ADD(drop_unencrypted, ap); | 284 | DEBUGFS_ADD(drop_unencrypted); |
173 | DEBUGFS_ADD(force_unicast_rateidx, ap); | 285 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
174 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | 286 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
175 | 287 | ||
176 | DEBUGFS_ADD(num_sta_ps, ap); | 288 | DEBUGFS_ADD(num_sta_ps); |
177 | DEBUGFS_ADD(dtim_count, ap); | 289 | DEBUGFS_ADD(dtim_count); |
178 | DEBUGFS_ADD(num_buffered_multicast, ap); | 290 | DEBUGFS_ADD(num_buffered_multicast); |
179 | } | 291 | } |
180 | 292 | ||
181 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 293 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) |
182 | { | 294 | { |
183 | DEBUGFS_ADD(drop_unencrypted, wds); | 295 | DEBUGFS_ADD(drop_unencrypted); |
184 | DEBUGFS_ADD(force_unicast_rateidx, wds); | 296 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
185 | DEBUGFS_ADD(max_ratectrl_rateidx, wds); | 297 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
186 | 298 | ||
187 | DEBUGFS_ADD(peer, wds); | 299 | DEBUGFS_ADD(peer); |
188 | } | 300 | } |
189 | 301 | ||
190 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | 302 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) |
191 | { | 303 | { |
192 | DEBUGFS_ADD(drop_unencrypted, vlan); | 304 | DEBUGFS_ADD(drop_unencrypted); |
193 | DEBUGFS_ADD(force_unicast_rateidx, vlan); | 305 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
194 | DEBUGFS_ADD(max_ratectrl_rateidx, vlan); | 306 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
195 | } | 307 | } |
196 | 308 | ||
197 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 309 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) |
@@ -199,30 +311,32 @@ static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | |||
199 | } | 311 | } |
200 | 312 | ||
201 | #ifdef CONFIG_MAC80211_MESH | 313 | #ifdef CONFIG_MAC80211_MESH |
202 | #define MESHSTATS_ADD(name)\ | ||
203 | sdata->mesh_stats.name = debugfs_create_file(#name, 0400,\ | ||
204 | sdata->mesh_stats_dir, sdata, &name##_ops); | ||
205 | 314 | ||
206 | static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) | 315 | static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) |
207 | { | 316 | { |
208 | sdata->mesh_stats_dir = debugfs_create_dir("mesh_stats", | 317 | struct dentry *dir = debugfs_create_dir("mesh_stats", |
209 | sdata->debugfsdir); | 318 | sdata->debugfs.dir); |
319 | |||
320 | #define MESHSTATS_ADD(name)\ | ||
321 | debugfs_create_file(#name, 0400, dir, sdata, &name##_ops); | ||
322 | |||
210 | MESHSTATS_ADD(fwded_mcast); | 323 | MESHSTATS_ADD(fwded_mcast); |
211 | MESHSTATS_ADD(fwded_unicast); | 324 | MESHSTATS_ADD(fwded_unicast); |
212 | MESHSTATS_ADD(fwded_frames); | 325 | MESHSTATS_ADD(fwded_frames); |
213 | MESHSTATS_ADD(dropped_frames_ttl); | 326 | MESHSTATS_ADD(dropped_frames_ttl); |
214 | MESHSTATS_ADD(dropped_frames_no_route); | 327 | MESHSTATS_ADD(dropped_frames_no_route); |
215 | MESHSTATS_ADD(estab_plinks); | 328 | MESHSTATS_ADD(estab_plinks); |
329 | #undef MESHSTATS_ADD | ||
216 | } | 330 | } |
217 | 331 | ||
218 | #define MESHPARAMS_ADD(name)\ | ||
219 | sdata->mesh_config.name = debugfs_create_file(#name, 0600,\ | ||
220 | sdata->mesh_config_dir, sdata, &name##_ops); | ||
221 | |||
222 | static void add_mesh_config(struct ieee80211_sub_if_data *sdata) | 332 | static void add_mesh_config(struct ieee80211_sub_if_data *sdata) |
223 | { | 333 | { |
224 | sdata->mesh_config_dir = debugfs_create_dir("mesh_config", | 334 | struct dentry *dir = debugfs_create_dir("mesh_config", |
225 | sdata->debugfsdir); | 335 | sdata->debugfs.dir); |
336 | |||
337 | #define MESHPARAMS_ADD(name) \ | ||
338 | debugfs_create_file(#name, 0600, dir, sdata, &name##_ops); | ||
339 | |||
226 | MESHPARAMS_ADD(dot11MeshMaxRetries); | 340 | MESHPARAMS_ADD(dot11MeshMaxRetries); |
227 | MESHPARAMS_ADD(dot11MeshRetryTimeout); | 341 | MESHPARAMS_ADD(dot11MeshRetryTimeout); |
228 | MESHPARAMS_ADD(dot11MeshConfirmTimeout); | 342 | MESHPARAMS_ADD(dot11MeshConfirmTimeout); |
@@ -236,12 +350,14 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) | |||
236 | MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries); | 350 | MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries); |
237 | MESHPARAMS_ADD(path_refresh_time); | 351 | MESHPARAMS_ADD(path_refresh_time); |
238 | MESHPARAMS_ADD(min_discovery_timeout); | 352 | MESHPARAMS_ADD(min_discovery_timeout); |
353 | |||
354 | #undef MESHPARAMS_ADD | ||
239 | } | 355 | } |
240 | #endif | 356 | #endif |
241 | 357 | ||
242 | static void add_files(struct ieee80211_sub_if_data *sdata) | 358 | static void add_files(struct ieee80211_sub_if_data *sdata) |
243 | { | 359 | { |
244 | if (!sdata->debugfsdir) | 360 | if (!sdata->debugfs.dir) |
245 | return; | 361 | return; |
246 | 362 | ||
247 | switch (sdata->vif.type) { | 363 | switch (sdata->vif.type) { |
@@ -274,208 +390,37 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
274 | } | 390 | } |
275 | } | 391 | } |
276 | 392 | ||
277 | #define DEBUGFS_DEL(name, type) \ | ||
278 | do { \ | ||
279 | debugfs_remove(sdata->debugfs.type.name); \ | ||
280 | sdata->debugfs.type.name = NULL; \ | ||
281 | } while (0) | ||
282 | |||
283 | static void del_sta_files(struct ieee80211_sub_if_data *sdata) | ||
284 | { | ||
285 | DEBUGFS_DEL(drop_unencrypted, sta); | ||
286 | DEBUGFS_DEL(force_unicast_rateidx, sta); | ||
287 | DEBUGFS_DEL(max_ratectrl_rateidx, sta); | ||
288 | |||
289 | DEBUGFS_DEL(bssid, sta); | ||
290 | DEBUGFS_DEL(aid, sta); | ||
291 | DEBUGFS_DEL(capab, sta); | ||
292 | } | ||
293 | |||
294 | static void del_ap_files(struct ieee80211_sub_if_data *sdata) | ||
295 | { | ||
296 | DEBUGFS_DEL(drop_unencrypted, ap); | ||
297 | DEBUGFS_DEL(force_unicast_rateidx, ap); | ||
298 | DEBUGFS_DEL(max_ratectrl_rateidx, ap); | ||
299 | |||
300 | DEBUGFS_DEL(num_sta_ps, ap); | ||
301 | DEBUGFS_DEL(dtim_count, ap); | ||
302 | DEBUGFS_DEL(num_buffered_multicast, ap); | ||
303 | } | ||
304 | |||
305 | static void del_wds_files(struct ieee80211_sub_if_data *sdata) | ||
306 | { | ||
307 | DEBUGFS_DEL(drop_unencrypted, wds); | ||
308 | DEBUGFS_DEL(force_unicast_rateidx, wds); | ||
309 | DEBUGFS_DEL(max_ratectrl_rateidx, wds); | ||
310 | |||
311 | DEBUGFS_DEL(peer, wds); | ||
312 | } | ||
313 | |||
314 | static void del_vlan_files(struct ieee80211_sub_if_data *sdata) | ||
315 | { | ||
316 | DEBUGFS_DEL(drop_unencrypted, vlan); | ||
317 | DEBUGFS_DEL(force_unicast_rateidx, vlan); | ||
318 | DEBUGFS_DEL(max_ratectrl_rateidx, vlan); | ||
319 | } | ||
320 | |||
321 | static void del_monitor_files(struct ieee80211_sub_if_data *sdata) | ||
322 | { | ||
323 | } | ||
324 | |||
325 | #ifdef CONFIG_MAC80211_MESH | ||
326 | #define MESHSTATS_DEL(name) \ | ||
327 | do { \ | ||
328 | debugfs_remove(sdata->mesh_stats.name); \ | ||
329 | sdata->mesh_stats.name = NULL; \ | ||
330 | } while (0) | ||
331 | |||
332 | static void del_mesh_stats(struct ieee80211_sub_if_data *sdata) | ||
333 | { | ||
334 | MESHSTATS_DEL(fwded_mcast); | ||
335 | MESHSTATS_DEL(fwded_unicast); | ||
336 | MESHSTATS_DEL(fwded_frames); | ||
337 | MESHSTATS_DEL(dropped_frames_ttl); | ||
338 | MESHSTATS_DEL(dropped_frames_no_route); | ||
339 | MESHSTATS_DEL(estab_plinks); | ||
340 | debugfs_remove(sdata->mesh_stats_dir); | ||
341 | sdata->mesh_stats_dir = NULL; | ||
342 | } | ||
343 | |||
344 | #define MESHPARAMS_DEL(name) \ | ||
345 | do { \ | ||
346 | debugfs_remove(sdata->mesh_config.name); \ | ||
347 | sdata->mesh_config.name = NULL; \ | ||
348 | } while (0) | ||
349 | |||
350 | static void del_mesh_config(struct ieee80211_sub_if_data *sdata) | ||
351 | { | ||
352 | MESHPARAMS_DEL(dot11MeshMaxRetries); | ||
353 | MESHPARAMS_DEL(dot11MeshRetryTimeout); | ||
354 | MESHPARAMS_DEL(dot11MeshConfirmTimeout); | ||
355 | MESHPARAMS_DEL(dot11MeshHoldingTimeout); | ||
356 | MESHPARAMS_DEL(dot11MeshTTL); | ||
357 | MESHPARAMS_DEL(auto_open_plinks); | ||
358 | MESHPARAMS_DEL(dot11MeshMaxPeerLinks); | ||
359 | MESHPARAMS_DEL(dot11MeshHWMPactivePathTimeout); | ||
360 | MESHPARAMS_DEL(dot11MeshHWMPpreqMinInterval); | ||
361 | MESHPARAMS_DEL(dot11MeshHWMPnetDiameterTraversalTime); | ||
362 | MESHPARAMS_DEL(dot11MeshHWMPmaxPREQretries); | ||
363 | MESHPARAMS_DEL(path_refresh_time); | ||
364 | MESHPARAMS_DEL(min_discovery_timeout); | ||
365 | debugfs_remove(sdata->mesh_config_dir); | ||
366 | sdata->mesh_config_dir = NULL; | ||
367 | } | ||
368 | #endif | ||
369 | |||
370 | static void del_files(struct ieee80211_sub_if_data *sdata) | ||
371 | { | ||
372 | if (!sdata->debugfsdir) | ||
373 | return; | ||
374 | |||
375 | switch (sdata->vif.type) { | ||
376 | case NL80211_IFTYPE_MESH_POINT: | ||
377 | #ifdef CONFIG_MAC80211_MESH | ||
378 | del_mesh_stats(sdata); | ||
379 | del_mesh_config(sdata); | ||
380 | #endif | ||
381 | break; | ||
382 | case NL80211_IFTYPE_STATION: | ||
383 | del_sta_files(sdata); | ||
384 | break; | ||
385 | case NL80211_IFTYPE_ADHOC: | ||
386 | /* XXX */ | ||
387 | break; | ||
388 | case NL80211_IFTYPE_AP: | ||
389 | del_ap_files(sdata); | ||
390 | break; | ||
391 | case NL80211_IFTYPE_WDS: | ||
392 | del_wds_files(sdata); | ||
393 | break; | ||
394 | case NL80211_IFTYPE_MONITOR: | ||
395 | del_monitor_files(sdata); | ||
396 | break; | ||
397 | case NL80211_IFTYPE_AP_VLAN: | ||
398 | del_vlan_files(sdata); | ||
399 | break; | ||
400 | default: | ||
401 | break; | ||
402 | } | ||
403 | } | ||
404 | |||
405 | static int notif_registered; | ||
406 | |||
407 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) | 393 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) |
408 | { | 394 | { |
409 | char buf[10+IFNAMSIZ]; | 395 | char buf[10+IFNAMSIZ]; |
410 | 396 | ||
411 | if (!notif_registered) | 397 | sprintf(buf, "netdev:%s", sdata->name); |
412 | return; | 398 | sdata->debugfs.dir = debugfs_create_dir(buf, |
413 | |||
414 | sprintf(buf, "netdev:%s", sdata->dev->name); | ||
415 | sdata->debugfsdir = debugfs_create_dir(buf, | ||
416 | sdata->local->hw.wiphy->debugfsdir); | 399 | sdata->local->hw.wiphy->debugfsdir); |
417 | add_files(sdata); | 400 | add_files(sdata); |
418 | } | 401 | } |
419 | 402 | ||
420 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) | 403 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) |
421 | { | 404 | { |
422 | del_files(sdata); | 405 | if (!sdata->debugfs.dir) |
423 | debugfs_remove(sdata->debugfsdir); | 406 | return; |
424 | sdata->debugfsdir = NULL; | 407 | |
408 | debugfs_remove_recursive(sdata->debugfs.dir); | ||
409 | sdata->debugfs.dir = NULL; | ||
425 | } | 410 | } |
426 | 411 | ||
427 | static int netdev_notify(struct notifier_block *nb, | 412 | void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) |
428 | unsigned long state, | ||
429 | void *ndev) | ||
430 | { | 413 | { |
431 | struct net_device *dev = ndev; | ||
432 | struct dentry *dir; | 414 | struct dentry *dir; |
433 | struct ieee80211_sub_if_data *sdata; | 415 | char buf[10 + IFNAMSIZ]; |
434 | char buf[10+IFNAMSIZ]; | ||
435 | |||
436 | if (state != NETDEV_CHANGENAME) | ||
437 | return 0; | ||
438 | 416 | ||
439 | if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) | 417 | dir = sdata->debugfs.dir; |
440 | return 0; | ||
441 | |||
442 | if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) | ||
443 | return 0; | ||
444 | |||
445 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
446 | |||
447 | dir = sdata->debugfsdir; | ||
448 | 418 | ||
449 | if (!dir) | 419 | if (!dir) |
450 | return 0; | 420 | return; |
451 | 421 | ||
452 | sprintf(buf, "netdev:%s", dev->name); | 422 | sprintf(buf, "netdev:%s", sdata->name); |
453 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) | 423 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) |
454 | printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " | 424 | printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " |
455 | "dir to %s\n", buf); | 425 | "dir to %s\n", buf); |
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static struct notifier_block mac80211_debugfs_netdev_notifier = { | ||
461 | .notifier_call = netdev_notify, | ||
462 | }; | ||
463 | |||
464 | void ieee80211_debugfs_netdev_init(void) | ||
465 | { | ||
466 | int err; | ||
467 | |||
468 | err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier); | ||
469 | if (err) { | ||
470 | printk(KERN_ERR | ||
471 | "mac80211: failed to install netdev notifier," | ||
472 | " disabling per-netdev debugfs!\n"); | ||
473 | } else | ||
474 | notif_registered = 1; | ||
475 | } | ||
476 | |||
477 | void ieee80211_debugfs_netdev_exit(void) | ||
478 | { | ||
479 | unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier); | ||
480 | notif_registered = 0; | ||
481 | } | 426 | } |