xref: /openbmc/linux/net/mac80211/debugfs_netdev.c (revision 384740dc)
1 /*
2  * Copyright (c) 2006	Jiri Benc <jbenc@suse.cz>
3  * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9 
10 #include <linux/kernel.h>
11 #include <linux/device.h>
12 #include <linux/if.h>
13 #include <linux/interrupt.h>
14 #include <linux/netdevice.h>
15 #include <linux/rtnetlink.h>
16 #include <linux/notifier.h>
17 #include <net/mac80211.h>
18 #include <net/cfg80211.h>
19 #include "ieee80211_i.h"
20 #include "rate.h"
21 #include "debugfs.h"
22 #include "debugfs_netdev.h"
23 
24 static ssize_t ieee80211_if_read(
25 	struct ieee80211_sub_if_data *sdata,
26 	char __user *userbuf,
27 	size_t count, loff_t *ppos,
28 	ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int))
29 {
30 	char buf[70];
31 	ssize_t ret = -EINVAL;
32 
33 	read_lock(&dev_base_lock);
34 	if (sdata->dev->reg_state == NETREG_REGISTERED)
35 		ret = (*format)(sdata, buf, sizeof(buf));
36 	read_unlock(&dev_base_lock);
37 
38 	if (ret != -EINVAL)
39 		ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
40 
41 	return ret;
42 }
43 
44 #ifdef CONFIG_MAC80211_MESH
45 static ssize_t ieee80211_if_write(
46 	struct ieee80211_sub_if_data *sdata,
47 	char const __user *userbuf,
48 	size_t count, loff_t *ppos,
49 	int (*format)(struct ieee80211_sub_if_data *, char *))
50 {
51 	char buf[10];
52 	int buf_size;
53 
54 	memset(buf, 0x00, sizeof(buf));
55 	buf_size = min(count, (sizeof(buf)-1));
56 	if (copy_from_user(buf, userbuf, buf_size))
57 		return count;
58 	read_lock(&dev_base_lock);
59 	if (sdata->dev->reg_state == NETREG_REGISTERED)
60 		(*format)(sdata, buf);
61 	read_unlock(&dev_base_lock);
62 
63 	return count;
64 }
65 #endif
66 
67 #define IEEE80211_IF_FMT(name, field, format_string)			\
68 static ssize_t ieee80211_if_fmt_##name(					\
69 	const struct ieee80211_sub_if_data *sdata, char *buf,		\
70 	int buflen)							\
71 {									\
72 	return scnprintf(buf, buflen, format_string, sdata->field);	\
73 }
74 #define IEEE80211_IF_WFMT(name, field, type)				\
75 static int ieee80211_if_wfmt_##name(					\
76 	struct ieee80211_sub_if_data *sdata, char *buf)			\
77 {									\
78 	unsigned long tmp;						\
79 	char *endp;							\
80 									\
81 	tmp = simple_strtoul(buf, &endp, 0);				\
82 	if ((endp == buf) || ((type)tmp != tmp))			\
83 		return -EINVAL;						\
84 	sdata->field = tmp;						\
85 	return 0;							\
86 }
87 #define IEEE80211_IF_FMT_DEC(name, field)				\
88 		IEEE80211_IF_FMT(name, field, "%d\n")
89 #define IEEE80211_IF_FMT_HEX(name, field)				\
90 		IEEE80211_IF_FMT(name, field, "%#x\n")
91 #define IEEE80211_IF_FMT_SIZE(name, field)				\
92 		IEEE80211_IF_FMT(name, field, "%zd\n")
93 
94 #define IEEE80211_IF_FMT_ATOMIC(name, field)				\
95 static ssize_t ieee80211_if_fmt_##name(					\
96 	const struct ieee80211_sub_if_data *sdata,			\
97 	char *buf, int buflen)						\
98 {									\
99 	return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\
100 }
101 
102 #define IEEE80211_IF_FMT_MAC(name, field)				\
103 static ssize_t ieee80211_if_fmt_##name(					\
104 	const struct ieee80211_sub_if_data *sdata, char *buf,		\
105 	int buflen)							\
106 {									\
107 	DECLARE_MAC_BUF(mac);						\
108 	return scnprintf(buf, buflen, "%s\n", print_mac(mac, sdata->field));\
109 }
110 
111 #define __IEEE80211_IF_FILE(name)					\
112 static ssize_t ieee80211_if_read_##name(struct file *file,		\
113 					char __user *userbuf,		\
114 					size_t count, loff_t *ppos)	\
115 {									\
116 	return ieee80211_if_read(file->private_data,			\
117 				 userbuf, count, ppos,			\
118 				 ieee80211_if_fmt_##name);		\
119 }									\
120 static const struct file_operations name##_ops = {			\
121 	.read = ieee80211_if_read_##name,				\
122 	.open = mac80211_open_file_generic,				\
123 }
124 
125 #define IEEE80211_IF_FILE(name, field, format)				\
126 		IEEE80211_IF_FMT_##format(name, field)			\
127 		__IEEE80211_IF_FILE(name)
128 
129 #define __IEEE80211_IF_WFILE(name)					\
130 static ssize_t ieee80211_if_read_##name(struct file *file,		\
131 					char __user *userbuf,		\
132 					size_t count, loff_t *ppos)	\
133 {									\
134 	return ieee80211_if_read(file->private_data,			\
135 				 userbuf, count, ppos,			\
136 				 ieee80211_if_fmt_##name);		\
137 }									\
138 static ssize_t ieee80211_if_write_##name(struct file *file,		\
139 					const char __user *userbuf,	\
140 					size_t count, loff_t *ppos)	\
141 {									\
142 	return ieee80211_if_write(file->private_data,			\
143 				 userbuf, count, ppos,			\
144 				 ieee80211_if_wfmt_##name);		\
145 }									\
146 static const struct file_operations name##_ops = {			\
147 	.read = ieee80211_if_read_##name,				\
148 	.write = ieee80211_if_write_##name,				\
149 	.open = mac80211_open_file_generic,				\
150 }
151 
152 #define IEEE80211_IF_WFILE(name, field, format, type)			\
153 		IEEE80211_IF_FMT_##format(name, field)			\
154 		IEEE80211_IF_WFMT(name, field, type)			\
155 		__IEEE80211_IF_WFILE(name)
156 
157 /* common attributes */
158 IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
159 IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC);
160 IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC);
161 
162 /* STA/IBSS attributes */
163 IEEE80211_IF_FILE(state, u.sta.state, DEC);
164 IEEE80211_IF_FILE(bssid, u.sta.bssid, MAC);
165 IEEE80211_IF_FILE(prev_bssid, u.sta.prev_bssid, MAC);
166 IEEE80211_IF_FILE(ssid_len, u.sta.ssid_len, SIZE);
167 IEEE80211_IF_FILE(aid, u.sta.aid, DEC);
168 IEEE80211_IF_FILE(ap_capab, u.sta.ap_capab, HEX);
169 IEEE80211_IF_FILE(capab, u.sta.capab, HEX);
170 IEEE80211_IF_FILE(extra_ie_len, u.sta.extra_ie_len, SIZE);
171 IEEE80211_IF_FILE(auth_tries, u.sta.auth_tries, DEC);
172 IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC);
173 IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
174 IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
175 IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
176 IEEE80211_IF_FILE(num_beacons_sta, u.sta.num_beacons, DEC);
177 
178 static ssize_t ieee80211_if_fmt_flags(
179 	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
180 {
181 	return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n",
182 		 sdata->u.sta.flags & IEEE80211_STA_SSID_SET ? "SSID\n" : "",
183 		 sdata->u.sta.flags & IEEE80211_STA_BSSID_SET ? "BSSID\n" : "",
184 		 sdata->u.sta.flags & IEEE80211_STA_PREV_BSSID_SET ? "prev BSSID\n" : "",
185 		 sdata->u.sta.flags & IEEE80211_STA_AUTHENTICATED ? "AUTH\n" : "",
186 		 sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED ? "ASSOC\n" : "",
187 		 sdata->u.sta.flags & IEEE80211_STA_PROBEREQ_POLL ? "PROBEREQ POLL\n" : "",
188 		 sdata->bss_conf.use_cts_prot ? "CTS prot\n" : "");
189 }
190 __IEEE80211_IF_FILE(flags);
191 
192 /* AP attributes */
193 IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
194 IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
195 IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC);
196 
197 static ssize_t ieee80211_if_fmt_num_buffered_multicast(
198 	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
199 {
200 	return scnprintf(buf, buflen, "%u\n",
201 			 skb_queue_len(&sdata->u.ap.ps_bc_buf));
202 }
203 __IEEE80211_IF_FILE(num_buffered_multicast);
204 
205 /* WDS attributes */
206 IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
207 
208 #ifdef CONFIG_MAC80211_MESH
209 /* Mesh stats attributes */
210 IEEE80211_IF_FILE(fwded_frames, u.sta.mshstats.fwded_frames, DEC);
211 IEEE80211_IF_FILE(dropped_frames_ttl, u.sta.mshstats.dropped_frames_ttl, DEC);
212 IEEE80211_IF_FILE(dropped_frames_no_route,
213 		u.sta.mshstats.dropped_frames_no_route, DEC);
214 IEEE80211_IF_FILE(estab_plinks, u.sta.mshstats.estab_plinks, ATOMIC);
215 
216 /* Mesh parameters */
217 IEEE80211_IF_WFILE(dot11MeshMaxRetries,
218 		u.sta.mshcfg.dot11MeshMaxRetries, DEC, u8);
219 IEEE80211_IF_WFILE(dot11MeshRetryTimeout,
220 		u.sta.mshcfg.dot11MeshRetryTimeout, DEC, u16);
221 IEEE80211_IF_WFILE(dot11MeshConfirmTimeout,
222 		u.sta.mshcfg.dot11MeshConfirmTimeout, DEC, u16);
223 IEEE80211_IF_WFILE(dot11MeshHoldingTimeout,
224 		u.sta.mshcfg.dot11MeshHoldingTimeout, DEC, u16);
225 IEEE80211_IF_WFILE(dot11MeshTTL, u.sta.mshcfg.dot11MeshTTL, DEC, u8);
226 IEEE80211_IF_WFILE(auto_open_plinks, u.sta.mshcfg.auto_open_plinks, DEC, u8);
227 IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks,
228 		u.sta.mshcfg.dot11MeshMaxPeerLinks, DEC, u16);
229 IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout,
230 		u.sta.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32);
231 IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval,
232 		u.sta.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16);
233 IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime,
234 		u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16);
235 IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries,
236 		u.sta.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8);
237 IEEE80211_IF_WFILE(path_refresh_time,
238 		u.sta.mshcfg.path_refresh_time, DEC, u32);
239 IEEE80211_IF_WFILE(min_discovery_timeout,
240 		u.sta.mshcfg.min_discovery_timeout, DEC, u16);
241 #endif
242 
243 
244 #define DEBUGFS_ADD(name, type)\
245 	sdata->debugfs.type.name = debugfs_create_file(#name, 0400,\
246 		sdata->debugfsdir, sdata, &name##_ops);
247 
248 static void add_sta_files(struct ieee80211_sub_if_data *sdata)
249 {
250 	DEBUGFS_ADD(drop_unencrypted, sta);
251 	DEBUGFS_ADD(force_unicast_rateidx, sta);
252 	DEBUGFS_ADD(max_ratectrl_rateidx, sta);
253 
254 	DEBUGFS_ADD(state, sta);
255 	DEBUGFS_ADD(bssid, sta);
256 	DEBUGFS_ADD(prev_bssid, sta);
257 	DEBUGFS_ADD(ssid_len, sta);
258 	DEBUGFS_ADD(aid, sta);
259 	DEBUGFS_ADD(ap_capab, sta);
260 	DEBUGFS_ADD(capab, sta);
261 	DEBUGFS_ADD(extra_ie_len, sta);
262 	DEBUGFS_ADD(auth_tries, sta);
263 	DEBUGFS_ADD(assoc_tries, sta);
264 	DEBUGFS_ADD(auth_algs, sta);
265 	DEBUGFS_ADD(auth_alg, sta);
266 	DEBUGFS_ADD(auth_transaction, sta);
267 	DEBUGFS_ADD(flags, sta);
268 	DEBUGFS_ADD(num_beacons_sta, sta);
269 }
270 
271 static void add_ap_files(struct ieee80211_sub_if_data *sdata)
272 {
273 	DEBUGFS_ADD(drop_unencrypted, ap);
274 	DEBUGFS_ADD(force_unicast_rateidx, ap);
275 	DEBUGFS_ADD(max_ratectrl_rateidx, ap);
276 
277 	DEBUGFS_ADD(num_sta_ps, ap);
278 	DEBUGFS_ADD(dtim_count, ap);
279 	DEBUGFS_ADD(num_beacons, ap);
280 	DEBUGFS_ADD(num_buffered_multicast, ap);
281 }
282 
283 static void add_wds_files(struct ieee80211_sub_if_data *sdata)
284 {
285 	DEBUGFS_ADD(drop_unencrypted, wds);
286 	DEBUGFS_ADD(force_unicast_rateidx, wds);
287 	DEBUGFS_ADD(max_ratectrl_rateidx, wds);
288 
289 	DEBUGFS_ADD(peer, wds);
290 }
291 
292 static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
293 {
294 	DEBUGFS_ADD(drop_unencrypted, vlan);
295 	DEBUGFS_ADD(force_unicast_rateidx, vlan);
296 	DEBUGFS_ADD(max_ratectrl_rateidx, vlan);
297 }
298 
299 static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
300 {
301 }
302 
303 #ifdef CONFIG_MAC80211_MESH
304 #define MESHSTATS_ADD(name)\
305 	sdata->mesh_stats.name = debugfs_create_file(#name, 0400,\
306 		sdata->mesh_stats_dir, sdata, &name##_ops);
307 
308 static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
309 {
310 	sdata->mesh_stats_dir = debugfs_create_dir("mesh_stats",
311 				sdata->debugfsdir);
312 	MESHSTATS_ADD(fwded_frames);
313 	MESHSTATS_ADD(dropped_frames_ttl);
314 	MESHSTATS_ADD(dropped_frames_no_route);
315 	MESHSTATS_ADD(estab_plinks);
316 }
317 
318 #define MESHPARAMS_ADD(name)\
319 	sdata->mesh_config.name = debugfs_create_file(#name, 0600,\
320 		sdata->mesh_config_dir, sdata, &name##_ops);
321 
322 static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
323 {
324 	sdata->mesh_config_dir = debugfs_create_dir("mesh_config",
325 				sdata->debugfsdir);
326 	MESHPARAMS_ADD(dot11MeshMaxRetries);
327 	MESHPARAMS_ADD(dot11MeshRetryTimeout);
328 	MESHPARAMS_ADD(dot11MeshConfirmTimeout);
329 	MESHPARAMS_ADD(dot11MeshHoldingTimeout);
330 	MESHPARAMS_ADD(dot11MeshTTL);
331 	MESHPARAMS_ADD(auto_open_plinks);
332 	MESHPARAMS_ADD(dot11MeshMaxPeerLinks);
333 	MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout);
334 	MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval);
335 	MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime);
336 	MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries);
337 	MESHPARAMS_ADD(path_refresh_time);
338 	MESHPARAMS_ADD(min_discovery_timeout);
339 }
340 #endif
341 
342 static void add_files(struct ieee80211_sub_if_data *sdata)
343 {
344 	if (!sdata->debugfsdir)
345 		return;
346 
347 	switch (sdata->vif.type) {
348 	case IEEE80211_IF_TYPE_MESH_POINT:
349 #ifdef CONFIG_MAC80211_MESH
350 		add_mesh_stats(sdata);
351 		add_mesh_config(sdata);
352 #endif
353 		/* fall through */
354 	case IEEE80211_IF_TYPE_STA:
355 	case IEEE80211_IF_TYPE_IBSS:
356 		add_sta_files(sdata);
357 		break;
358 	case IEEE80211_IF_TYPE_AP:
359 		add_ap_files(sdata);
360 		break;
361 	case IEEE80211_IF_TYPE_WDS:
362 		add_wds_files(sdata);
363 		break;
364 	case IEEE80211_IF_TYPE_MNTR:
365 		add_monitor_files(sdata);
366 		break;
367 	case IEEE80211_IF_TYPE_VLAN:
368 		add_vlan_files(sdata);
369 		break;
370 	default:
371 		break;
372 	}
373 }
374 
375 #define DEBUGFS_DEL(name, type)					\
376 	do {							\
377 		debugfs_remove(sdata->debugfs.type.name);	\
378 		sdata->debugfs.type.name = NULL;		\
379 	} while (0)
380 
381 static void del_sta_files(struct ieee80211_sub_if_data *sdata)
382 {
383 	DEBUGFS_DEL(drop_unencrypted, sta);
384 	DEBUGFS_DEL(force_unicast_rateidx, sta);
385 	DEBUGFS_DEL(max_ratectrl_rateidx, sta);
386 
387 	DEBUGFS_DEL(state, sta);
388 	DEBUGFS_DEL(bssid, sta);
389 	DEBUGFS_DEL(prev_bssid, sta);
390 	DEBUGFS_DEL(ssid_len, sta);
391 	DEBUGFS_DEL(aid, sta);
392 	DEBUGFS_DEL(ap_capab, sta);
393 	DEBUGFS_DEL(capab, sta);
394 	DEBUGFS_DEL(extra_ie_len, sta);
395 	DEBUGFS_DEL(auth_tries, sta);
396 	DEBUGFS_DEL(assoc_tries, sta);
397 	DEBUGFS_DEL(auth_algs, sta);
398 	DEBUGFS_DEL(auth_alg, sta);
399 	DEBUGFS_DEL(auth_transaction, sta);
400 	DEBUGFS_DEL(flags, sta);
401 	DEBUGFS_DEL(num_beacons_sta, sta);
402 }
403 
404 static void del_ap_files(struct ieee80211_sub_if_data *sdata)
405 {
406 	DEBUGFS_DEL(drop_unencrypted, ap);
407 	DEBUGFS_DEL(force_unicast_rateidx, ap);
408 	DEBUGFS_DEL(max_ratectrl_rateidx, ap);
409 
410 	DEBUGFS_DEL(num_sta_ps, ap);
411 	DEBUGFS_DEL(dtim_count, ap);
412 	DEBUGFS_DEL(num_beacons, ap);
413 	DEBUGFS_DEL(num_buffered_multicast, ap);
414 }
415 
416 static void del_wds_files(struct ieee80211_sub_if_data *sdata)
417 {
418 	DEBUGFS_DEL(drop_unencrypted, wds);
419 	DEBUGFS_DEL(force_unicast_rateidx, wds);
420 	DEBUGFS_DEL(max_ratectrl_rateidx, wds);
421 
422 	DEBUGFS_DEL(peer, wds);
423 }
424 
425 static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
426 {
427 	DEBUGFS_DEL(drop_unencrypted, vlan);
428 	DEBUGFS_DEL(force_unicast_rateidx, vlan);
429 	DEBUGFS_DEL(max_ratectrl_rateidx, vlan);
430 }
431 
432 static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
433 {
434 }
435 
436 #ifdef CONFIG_MAC80211_MESH
437 #define MESHSTATS_DEL(name)			\
438 	do {						\
439 		debugfs_remove(sdata->mesh_stats.name);	\
440 		sdata->mesh_stats.name = NULL;		\
441 	} while (0)
442 
443 static void del_mesh_stats(struct ieee80211_sub_if_data *sdata)
444 {
445 	MESHSTATS_DEL(fwded_frames);
446 	MESHSTATS_DEL(dropped_frames_ttl);
447 	MESHSTATS_DEL(dropped_frames_no_route);
448 	MESHSTATS_DEL(estab_plinks);
449 	debugfs_remove(sdata->mesh_stats_dir);
450 	sdata->mesh_stats_dir = NULL;
451 }
452 
453 #define MESHPARAMS_DEL(name)			\
454 	do {						\
455 		debugfs_remove(sdata->mesh_config.name);	\
456 		sdata->mesh_config.name = NULL;		\
457 	} while (0)
458 
459 static void del_mesh_config(struct ieee80211_sub_if_data *sdata)
460 {
461 	MESHPARAMS_DEL(dot11MeshMaxRetries);
462 	MESHPARAMS_DEL(dot11MeshRetryTimeout);
463 	MESHPARAMS_DEL(dot11MeshConfirmTimeout);
464 	MESHPARAMS_DEL(dot11MeshHoldingTimeout);
465 	MESHPARAMS_DEL(dot11MeshTTL);
466 	MESHPARAMS_DEL(auto_open_plinks);
467 	MESHPARAMS_DEL(dot11MeshMaxPeerLinks);
468 	MESHPARAMS_DEL(dot11MeshHWMPactivePathTimeout);
469 	MESHPARAMS_DEL(dot11MeshHWMPpreqMinInterval);
470 	MESHPARAMS_DEL(dot11MeshHWMPnetDiameterTraversalTime);
471 	MESHPARAMS_DEL(dot11MeshHWMPmaxPREQretries);
472 	MESHPARAMS_DEL(path_refresh_time);
473 	MESHPARAMS_DEL(min_discovery_timeout);
474 	debugfs_remove(sdata->mesh_config_dir);
475 	sdata->mesh_config_dir = NULL;
476 }
477 #endif
478 
479 static void del_files(struct ieee80211_sub_if_data *sdata)
480 {
481 	if (!sdata->debugfsdir)
482 		return;
483 
484 	switch (sdata->vif.type) {
485 	case IEEE80211_IF_TYPE_MESH_POINT:
486 #ifdef CONFIG_MAC80211_MESH
487 		del_mesh_stats(sdata);
488 		del_mesh_config(sdata);
489 #endif
490 		/* fall through */
491 	case IEEE80211_IF_TYPE_STA:
492 	case IEEE80211_IF_TYPE_IBSS:
493 		del_sta_files(sdata);
494 		break;
495 	case IEEE80211_IF_TYPE_AP:
496 		del_ap_files(sdata);
497 		break;
498 	case IEEE80211_IF_TYPE_WDS:
499 		del_wds_files(sdata);
500 		break;
501 	case IEEE80211_IF_TYPE_MNTR:
502 		del_monitor_files(sdata);
503 		break;
504 	case IEEE80211_IF_TYPE_VLAN:
505 		del_vlan_files(sdata);
506 		break;
507 	default:
508 		break;
509 	}
510 }
511 
512 static int notif_registered;
513 
514 void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
515 {
516 	char buf[10+IFNAMSIZ];
517 
518 	if (!notif_registered)
519 		return;
520 
521 	sprintf(buf, "netdev:%s", sdata->dev->name);
522 	sdata->debugfsdir = debugfs_create_dir(buf,
523 		sdata->local->hw.wiphy->debugfsdir);
524 	add_files(sdata);
525 }
526 
527 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
528 {
529 	del_files(sdata);
530 	debugfs_remove(sdata->debugfsdir);
531 	sdata->debugfsdir = NULL;
532 }
533 
534 static int netdev_notify(struct notifier_block *nb,
535 			 unsigned long state,
536 			 void *ndev)
537 {
538 	struct net_device *dev = ndev;
539 	struct dentry *dir;
540 	struct ieee80211_sub_if_data *sdata;
541 	char buf[10+IFNAMSIZ];
542 
543 	if (state != NETDEV_CHANGENAME)
544 		return 0;
545 
546 	if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
547 		return 0;
548 
549 	if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
550 		return 0;
551 
552 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
553 
554 	sprintf(buf, "netdev:%s", dev->name);
555 	dir = sdata->debugfsdir;
556 	if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
557 		printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs "
558 		       "dir to %s\n", buf);
559 
560 	return 0;
561 }
562 
563 static struct notifier_block mac80211_debugfs_netdev_notifier = {
564 	.notifier_call = netdev_notify,
565 };
566 
567 void ieee80211_debugfs_netdev_init(void)
568 {
569 	int err;
570 
571 	err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
572 	if (err) {
573 		printk(KERN_ERR
574 		       "mac80211: failed to install netdev notifier,"
575 		       " disabling per-netdev debugfs!\n");
576 	} else
577 		notif_registered = 1;
578 }
579 
580 void ieee80211_debugfs_netdev_exit(void)
581 {
582 	unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
583 	notif_registered = 0;
584 }
585