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