aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/debugfs_netdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/debugfs_netdev.c')
-rw-r--r--net/mac80211/debugfs_netdev.c391
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
45static 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
68freebuf:
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) \
45static ssize_t ieee80211_if_fmt_##name( \ 74static 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) \
75static ssize_t ieee80211_if_read_##name(struct file *file, \ 104static 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} \
83static const struct file_operations name##_ops = { \ 112static 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) \
119static 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 */
93IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); 134IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
94IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC); 135IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ],
95IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); 136 HEX);
137IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ],
138 HEX);
96 139
97/* STA attributes */ 140/* STA attributes */
98IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); 141IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
99IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); 142IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
100IEEE80211_IF_FILE(capab, u.mgd.capab, HEX); 143
144static 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
171static 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
178static 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
189static 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 */
103IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); 209IEEE80211_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 */
115IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); 221IEEE80211_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);
150IEEE80211_IF_FILE(min_discovery_timeout, 256IEEE80211_IF_FILE(min_discovery_timeout,
151 u.mesh.mshcfg.min_discovery_timeout, DEC); 257 u.mesh.mshcfg.min_discovery_timeout, DEC);
258IEEE80211_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
159static void add_sta_files(struct ieee80211_sub_if_data *sdata) 271static 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
170static void add_ap_files(struct ieee80211_sub_if_data *sdata) 282static 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
181static void add_wds_files(struct ieee80211_sub_if_data *sdata) 293static 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
190static void add_vlan_files(struct ieee80211_sub_if_data *sdata) 302static 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
197static void add_monitor_files(struct ieee80211_sub_if_data *sdata) 309static 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
206static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) 315static 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
222static void add_mesh_config(struct ieee80211_sub_if_data *sdata) 332static 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
242static void add_files(struct ieee80211_sub_if_data *sdata) 358static 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
283static 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
294static 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
305static 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
314static 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
321static 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
332static 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
350static 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
370static 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
405static int notif_registered;
406
407void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) 393void 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
420void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) 403void 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
427static int netdev_notify(struct notifier_block *nb, 412void 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
460static struct notifier_block mac80211_debugfs_netdev_notifier = {
461 .notifier_call = netdev_notify,
462};
463
464void 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
477void ieee80211_debugfs_netdev_exit(void)
478{
479 unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
480 notif_registered = 0;
481} 426}