b9409eeadfab1024860b406908f30dd6c5a47851
[openwrt/staging/chunkeey.git] / package / mac80211 / src / 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 #define IEEE80211_IF_FMT(name, field, format_string) \
43 static ssize_t ieee80211_if_fmt_##name( \
44 const struct ieee80211_sub_if_data *sdata, char *buf, \
45 int buflen) \
46 { \
47 return scnprintf(buf, buflen, format_string, sdata->field); \
48 }
49 #define IEEE80211_IF_FMT_DEC(name, field) \
50 IEEE80211_IF_FMT(name, field, "%d\n")
51 #define IEEE80211_IF_FMT_HEX(name, field) \
52 IEEE80211_IF_FMT(name, field, "%#x\n")
53 #define IEEE80211_IF_FMT_SIZE(name, field) \
54 IEEE80211_IF_FMT(name, field, "%zd\n")
55
56 #define IEEE80211_IF_FMT_ATOMIC(name, field) \
57 static ssize_t ieee80211_if_fmt_##name( \
58 const struct ieee80211_sub_if_data *sdata, \
59 char *buf, int buflen) \
60 { \
61 return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\
62 }
63
64 #define IEEE80211_IF_FMT_MAC(name, field) \
65 static ssize_t ieee80211_if_fmt_##name( \
66 const struct ieee80211_sub_if_data *sdata, char *buf, \
67 int buflen) \
68 { \
69 return scnprintf(buf, buflen, MAC_FMT "\n", MAC_ARG(sdata->field));\
70 }
71
72 #define __IEEE80211_IF_FILE(name) \
73 static ssize_t ieee80211_if_read_##name(struct file *file, \
74 char __user *userbuf, \
75 size_t count, loff_t *ppos) \
76 { \
77 return ieee80211_if_read(file->private_data, \
78 userbuf, count, ppos, \
79 ieee80211_if_fmt_##name); \
80 } \
81 static const struct file_operations name##_ops = { \
82 .read = ieee80211_if_read_##name, \
83 .open = mac80211_open_file_generic, \
84 }
85
86 #define IEEE80211_IF_FILE(name, field, format) \
87 IEEE80211_IF_FMT_##format(name, field) \
88 __IEEE80211_IF_FILE(name)
89
90 static struct ieee80211_elem_tspec _tspec = {
91 .nominal_msdu_size = 200,
92 .inactivity_interval = 40,
93 .mean_data_rate = 40000,
94 .min_phy_rate = 6000000,
95 .surplus_band_allow = 8192,
96 .medium_time = 30,
97 };
98 static u8 _dls_mac[ETH_ALEN];
99
100 #define DEBUGFS_QOS_FILE(name, f) \
101 static ssize_t qos_ ##name## _write(struct file *file, \
102 const char __user *userbuf, \
103 size_t count, loff_t *ppos) \
104 { \
105 struct ieee80211_sub_if_data *sdata = file->private_data; \
106 \
107 f(sdata->dev, &sdata->u.sta, &_tspec); \
108 \
109 return count; \
110 } \
111 \
112 static const struct file_operations qos_ ##name## _ops = { \
113 .write = qos_ ##name## _write, \
114 .open = mac80211_open_file_generic, \
115 };
116
117 #define DEBUGFS_QOS_ADD(name) \
118 sdata->debugfs.sta.qos.name = debugfs_create_file(#name, 0444, qosd,\
119 sdata, &qos_ ##name## _ops);
120
121 #define DEBUGFS_QOS_DEL(name) \
122 do { \
123 debugfs_remove(sdata->debugfs.sta.qos.name); \
124 sdata->debugfs.sta.qos.name = NULL; \
125 } while (0)
126
127 DEBUGFS_QOS_FILE(addts_11e, ieee80211_send_addts);
128 DEBUGFS_QOS_FILE(addts_wmm, wmm_send_addts);
129 DEBUGFS_QOS_FILE(delts_11e, ieee80211_send_delts);
130 DEBUGFS_QOS_FILE(delts_wmm, wmm_send_delts);
131
132 static ssize_t qos_if_dls_mac(const struct ieee80211_sub_if_data *sdata,
133 char *buf, int buflen)
134 {
135 return scnprintf(buf, buflen, MAC_FMT "\n", MAC_ARG(_dls_mac));
136 }
137
138 static ssize_t qos_dls_mac_read(struct file *file,
139 char __user *userbuf,
140 size_t count, loff_t *ppos)
141 {
142 return ieee80211_if_read(file->private_data,
143 userbuf, count, ppos,
144 qos_if_dls_mac);
145 }
146
147 static ssize_t qos_dls_mac_write(struct file *file, const char __user *userbuf,
148 size_t count, loff_t *ppos)
149 {
150 struct ieee80211_sub_if_data *sdata = file->private_data;
151 char buf[20];
152 size_t size;
153 u8 m[ETH_ALEN];
154
155 size = min(sizeof(buf) - 1, count);
156 buf[size] = '\0';
157 if (copy_from_user(buf, userbuf, size))
158 return -EFAULT;
159
160 if (sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
161 &((u8*)(m))[0], &((u8*)(m))[1], &((u8*)(m))[2],
162 &((u8*)(m))[3], &((u8*)(m))[4], &((u8*)(m))[5]) != ETH_ALEN){
163 printk(KERN_ERR "%s: sscanf input error\n", sdata->dev->name);
164 return -EINVAL;
165 }
166 memcpy(_dls_mac, m, ETH_ALEN);
167 return count;
168 }
169
170 static const struct file_operations qos_dls_mac_ops = {
171 .read = qos_dls_mac_read,
172 .write = qos_dls_mac_write,
173 .open = mac80211_open_file_generic,
174 };
175
176 static ssize_t qos_if_dls_op(const struct ieee80211_sub_if_data *sdata,
177 char *buf, int buflen)
178 {
179 return scnprintf(buf, buflen,
180 "DLS Operation: Setup = 1; Teardown = 2\n");
181 }
182
183 static ssize_t qos_dls_op_read(struct file *file, char __user *userbuf,
184 size_t count, loff_t *ppos)
185 {
186 return ieee80211_if_read(file->private_data,
187 userbuf, count, ppos,
188 qos_if_dls_op);
189 }
190
191 static ssize_t qos_dls_op_write(struct file *file, const char __user *userbuf,
192 size_t count, loff_t *ppos)
193 {
194 struct ieee80211_sub_if_data *sdata = file->private_data;
195 char buf[20];
196 size_t size;
197 unsigned int opt;
198
199 size = min(sizeof(buf) - 1, count);
200 buf[size] = '\0';
201 if (copy_from_user(buf, userbuf, size))
202 return -EFAULT;
203
204 if (sscanf(buf, "%u", &opt) != 1) {
205 printk(KERN_ERR "%s: sscanf input error\n", sdata->dev->name);
206 return -EINVAL;
207 }
208 switch (opt) {
209 case 1:
210 ieee80211_send_dls_req(sdata->dev, &sdata->u.sta, _dls_mac, 0);
211 break;
212 case 2:
213 ieee80211_send_dls_teardown(sdata->dev, &sdata->u.sta, _dls_mac,
214 WLAN_REASON_QSTA_NOT_USE);
215 break;
216 default:
217 printk(KERN_ERR "Unknown DLS Operation: %d\n", opt);
218 break;
219 }
220 return count;
221 }
222
223 static const struct file_operations qos_dls_op_ops = {
224 .read = qos_dls_op_read,
225 .write = qos_dls_op_write,
226 .open = mac80211_open_file_generic,
227 };
228
229 #define DEBUGFS_TSINFO_FILE(_name, min_val, max_val) \
230 static ssize_t tsinfo_ ##_name## _read(struct file *file, \
231 char __user *userbuf, \
232 size_t count, loff_t *ppos) \
233 { \
234 char buf[20]; \
235 int res = scnprintf(buf, count, "%u\n", \
236 IEEE80211_TSINFO_## _name (_tspec.ts_info)); \
237 return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
238 } \
239 \
240 static ssize_t tsinfo_ ##_name## _write(struct file *file, \
241 const char __user *userbuf, \
242 size_t count, loff_t *ppos) \
243 { \
244 char buf[20]; \
245 size_t size; \
246 int val; \
247 \
248 size = min(sizeof(buf) - 1, count); \
249 buf[size] = '\0'; \
250 if (copy_from_user(buf, userbuf, size)) \
251 return -EFAULT; \
252 \
253 val = simple_strtoul(buf, NULL, 0); \
254 if ((val < min_val) || (val > max_val)) { \
255 struct ieee80211_sub_if_data *sdata = file->private_data;\
256 printk(KERN_ERR "%s: set value (%u) out of range " \
257 "[%u, %u]\n",sdata->dev->name,val,min_val,max_val);\
258 return -EINVAL; \
259 } \
260 SET_TSINFO_ ##_name (_tspec.ts_info, val); \
261 return count; \
262 } \
263 \
264 static const struct file_operations tsinfo_ ##_name## _ops = { \
265 .read = tsinfo_ ##_name## _read, \
266 .write = tsinfo_ ##_name## _write, \
267 .open = mac80211_open_file_generic, \
268 };
269
270 #define DEBUGFS_TSINFO_ADD_TSID \
271 sdata->debugfs.sta.tsinfo.tsid = \
272 debugfs_create_file("tsid", 0444, tsinfod, \
273 sdata, &tsinfo_TSID_ops);
274
275 #define DEBUGFS_TSINFO_ADD_DIR \
276 sdata->debugfs.sta.tsinfo.direction = \
277 debugfs_create_file("direction", 0444, tsinfod, \
278 sdata, &tsinfo_DIR_ops);
279
280 #define DEBUGFS_TSINFO_ADD_UP \
281 sdata->debugfs.sta.tsinfo.up = \
282 debugfs_create_file("up", 0444, tsinfod, \
283 sdata, &tsinfo_UP_ops);
284
285 #define DEBUGFS_TSINFO_DEL(name) \
286 do { \
287 debugfs_remove(sdata->debugfs.sta.tsinfo.name); \
288 sdata->debugfs.sta.tsinfo.name = NULL; \
289 } while (0)
290
291 DEBUGFS_TSINFO_FILE(TSID, 8, 15);
292 DEBUGFS_TSINFO_FILE(DIR, 0, 3);
293 DEBUGFS_TSINFO_FILE(UP, 0, 7);
294
295 #define DEBUGFS_TSPEC_FILE(name) \
296 static ssize_t tspec_ ##name## _read(struct file *file, \
297 char __user *userbuf, \
298 size_t count, loff_t *ppos) \
299 { \
300 char buf[20]; \
301 int res = scnprintf(buf, count, "%u\n", _tspec.name); \
302 return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
303 } \
304 \
305 static ssize_t tspec_ ##name## _write(struct file *file, \
306 const char __user *userbuf, \
307 size_t count, loff_t *ppos) \
308 { \
309 char buf[20]; \
310 size_t size; \
311 \
312 size = min(sizeof(buf) - 1, count); \
313 buf[size] = '\0'; \
314 if (copy_from_user(buf, userbuf, size)) \
315 return -EFAULT; \
316 \
317 _tspec.name = simple_strtoul(buf, NULL, 0); \
318 return count; \
319 } \
320 \
321 static const struct file_operations tspec_ ##name## _ops = { \
322 .read = tspec_ ##name## _read, \
323 .write = tspec_ ##name## _write, \
324 .open = mac80211_open_file_generic, \
325 };
326
327 #define DEBUGFS_TSPEC_ADD(name) \
328 sdata->debugfs.sta.tspec.name = debugfs_create_file(#name, \
329 0444, tspecd, sdata, &tspec_ ##name## _ops);
330
331 #define DEBUGFS_TSPEC_DEL(name) \
332 do { \
333 debugfs_remove(sdata->debugfs.sta.tspec.name); \
334 sdata->debugfs.sta.tspec.name = NULL; \
335 } while (0)
336
337 DEBUGFS_TSPEC_FILE(nominal_msdu_size);
338 DEBUGFS_TSPEC_FILE(max_msdu_size);
339 DEBUGFS_TSPEC_FILE(min_service_interval);
340 DEBUGFS_TSPEC_FILE(max_service_interval);
341 DEBUGFS_TSPEC_FILE(inactivity_interval);
342 DEBUGFS_TSPEC_FILE(suspension_interval);
343 DEBUGFS_TSPEC_FILE(service_start_time);
344 DEBUGFS_TSPEC_FILE(min_data_rate);
345 DEBUGFS_TSPEC_FILE(mean_data_rate);
346 DEBUGFS_TSPEC_FILE(peak_data_rate);
347 DEBUGFS_TSPEC_FILE(burst_size);
348 DEBUGFS_TSPEC_FILE(delay_bound);
349 DEBUGFS_TSPEC_FILE(min_phy_rate);
350 DEBUGFS_TSPEC_FILE(surplus_band_allow);
351 DEBUGFS_TSPEC_FILE(medium_time);
352
353
354 /* common attributes */
355 IEEE80211_IF_FILE(channel_use, channel_use, DEC);
356 IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
357 IEEE80211_IF_FILE(eapol, eapol, DEC);
358 IEEE80211_IF_FILE(ieee8021_x, ieee802_1x, DEC);
359
360 /* STA/IBSS attributes */
361 IEEE80211_IF_FILE(state, u.sta.state, DEC);
362 IEEE80211_IF_FILE(bssid, u.sta.bssid, MAC);
363 IEEE80211_IF_FILE(prev_bssid, u.sta.prev_bssid, MAC);
364 IEEE80211_IF_FILE(ssid_len, u.sta.ssid_len, SIZE);
365 IEEE80211_IF_FILE(aid, u.sta.aid, DEC);
366 IEEE80211_IF_FILE(ap_capab, u.sta.ap_capab, HEX);
367 IEEE80211_IF_FILE(capab, u.sta.capab, HEX);
368 IEEE80211_IF_FILE(extra_ie_len, u.sta.extra_ie_len, SIZE);
369 IEEE80211_IF_FILE(auth_tries, u.sta.auth_tries, DEC);
370 IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC);
371 IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
372 IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
373 IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
374
375 static ssize_t ieee80211_if_fmt_flags(
376 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
377 {
378 return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n",
379 sdata->u.sta.ssid_set ? "SSID\n" : "",
380 sdata->u.sta.bssid_set ? "BSSID\n" : "",
381 sdata->u.sta.prev_bssid_set ? "prev BSSID\n" : "",
382 sdata->u.sta.authenticated ? "AUTH\n" : "",
383 sdata->u.sta.associated ? "ASSOC\n" : "",
384 sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "",
385 sdata->u.sta.use_protection ? "CTS prot\n" : "");
386 }
387 __IEEE80211_IF_FILE(flags);
388
389 /* AP attributes */
390 IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
391 IEEE80211_IF_FILE(dtim_period, u.ap.dtim_period, DEC);
392 IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
393 IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC);
394 IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC);
395 IEEE80211_IF_FILE(max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx, DEC);
396
397 static ssize_t ieee80211_if_fmt_num_buffered_multicast(
398 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
399 {
400 return scnprintf(buf, buflen, "%u\n",
401 skb_queue_len(&sdata->u.ap.ps_bc_buf));
402 }
403 __IEEE80211_IF_FILE(num_buffered_multicast);
404
405 static ssize_t ieee80211_if_fmt_beacon_head_len(
406 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
407 {
408 if (sdata->u.ap.beacon_head)
409 return scnprintf(buf, buflen, "%d\n",
410 sdata->u.ap.beacon_head_len);
411 return scnprintf(buf, buflen, "\n");
412 }
413 __IEEE80211_IF_FILE(beacon_head_len);
414
415 static ssize_t ieee80211_if_fmt_beacon_tail_len(
416 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
417 {
418 if (sdata->u.ap.beacon_tail)
419 return scnprintf(buf, buflen, "%d\n",
420 sdata->u.ap.beacon_tail_len);
421 return scnprintf(buf, buflen, "\n");
422 }
423 __IEEE80211_IF_FILE(beacon_tail_len);
424
425 /* WDS attributes */
426 IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
427
428 /* VLAN attributes */
429 IEEE80211_IF_FILE(vlan_id, u.vlan.id, DEC);
430
431 /* MONITOR attributes */
432 static ssize_t ieee80211_if_fmt_mode(
433 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
434 {
435 struct ieee80211_local *local = sdata->local;
436
437 return scnprintf(buf, buflen, "%s\n",
438 ((local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) ||
439 local->open_count == local->monitors) ?
440 "hard" : "soft");
441 }
442 __IEEE80211_IF_FILE(mode);
443
444
445 #define DEBUGFS_ADD(name, type)\
446 sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\
447 sdata->debugfsdir, sdata, &name##_ops);
448
449 static void add_sta_files(struct ieee80211_sub_if_data *sdata)
450 {
451 struct dentry *qosd;
452 struct dentry *tsinfod;
453 struct dentry *tspecd;
454
455 DEBUGFS_ADD(channel_use, sta);
456 DEBUGFS_ADD(drop_unencrypted, sta);
457 DEBUGFS_ADD(eapol, sta);
458 DEBUGFS_ADD(ieee8021_x, sta);
459 DEBUGFS_ADD(state, sta);
460 DEBUGFS_ADD(bssid, sta);
461 DEBUGFS_ADD(prev_bssid, sta);
462 DEBUGFS_ADD(ssid_len, sta);
463 DEBUGFS_ADD(aid, sta);
464 DEBUGFS_ADD(ap_capab, sta);
465 DEBUGFS_ADD(capab, sta);
466 DEBUGFS_ADD(extra_ie_len, sta);
467 DEBUGFS_ADD(auth_tries, sta);
468 DEBUGFS_ADD(assoc_tries, sta);
469 DEBUGFS_ADD(auth_algs, sta);
470 DEBUGFS_ADD(auth_alg, sta);
471 DEBUGFS_ADD(auth_transaction, sta);
472 DEBUGFS_ADD(flags, sta);
473
474 qosd = debugfs_create_dir("qos", sdata->debugfsdir);
475 sdata->debugfs.sta.qos_dir = qosd;
476
477 DEBUGFS_QOS_ADD(addts_11e);
478 DEBUGFS_QOS_ADD(addts_wmm);
479 DEBUGFS_QOS_ADD(delts_11e);
480 DEBUGFS_QOS_ADD(delts_wmm);
481 DEBUGFS_QOS_ADD(dls_mac);
482 DEBUGFS_QOS_ADD(dls_op);
483
484 tsinfod = debugfs_create_dir("ts_info", qosd);
485 sdata->debugfs.sta.tsinfo_dir = tsinfod;
486
487 DEBUGFS_TSINFO_ADD_TSID;
488 DEBUGFS_TSINFO_ADD_DIR;
489 DEBUGFS_TSINFO_ADD_UP;
490
491 tspecd = debugfs_create_dir("tspec", qosd);
492 sdata->debugfs.sta.tspec_dir = tspecd;
493
494 DEBUGFS_TSPEC_ADD(nominal_msdu_size);
495 DEBUGFS_TSPEC_ADD(max_msdu_size);
496 DEBUGFS_TSPEC_ADD(min_service_interval);
497 DEBUGFS_TSPEC_ADD(max_service_interval);
498 DEBUGFS_TSPEC_ADD(inactivity_interval);
499 DEBUGFS_TSPEC_ADD(suspension_interval);
500 DEBUGFS_TSPEC_ADD(service_start_time);
501 DEBUGFS_TSPEC_ADD(min_data_rate);
502 DEBUGFS_TSPEC_ADD(mean_data_rate);
503 DEBUGFS_TSPEC_ADD(peak_data_rate);
504 DEBUGFS_TSPEC_ADD(burst_size);
505 DEBUGFS_TSPEC_ADD(delay_bound);
506 DEBUGFS_TSPEC_ADD(min_phy_rate);
507 DEBUGFS_TSPEC_ADD(surplus_band_allow);
508 DEBUGFS_TSPEC_ADD(medium_time);
509 }
510
511 static void add_ap_files(struct ieee80211_sub_if_data *sdata)
512 {
513 DEBUGFS_ADD(channel_use, ap);
514 DEBUGFS_ADD(drop_unencrypted, ap);
515 DEBUGFS_ADD(eapol, ap);
516 DEBUGFS_ADD(ieee8021_x, ap);
517 DEBUGFS_ADD(num_sta_ps, ap);
518 DEBUGFS_ADD(dtim_period, ap);
519 DEBUGFS_ADD(dtim_count, ap);
520 DEBUGFS_ADD(num_beacons, ap);
521 DEBUGFS_ADD(force_unicast_rateidx, ap);
522 DEBUGFS_ADD(max_ratectrl_rateidx, ap);
523 DEBUGFS_ADD(num_buffered_multicast, ap);
524 DEBUGFS_ADD(beacon_head_len, ap);
525 DEBUGFS_ADD(beacon_tail_len, ap);
526 }
527
528 static void add_wds_files(struct ieee80211_sub_if_data *sdata)
529 {
530 DEBUGFS_ADD(channel_use, wds);
531 DEBUGFS_ADD(drop_unencrypted, wds);
532 DEBUGFS_ADD(eapol, wds);
533 DEBUGFS_ADD(ieee8021_x, wds);
534 DEBUGFS_ADD(peer, wds);
535 }
536
537 static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
538 {
539 DEBUGFS_ADD(channel_use, vlan);
540 DEBUGFS_ADD(drop_unencrypted, vlan);
541 DEBUGFS_ADD(eapol, vlan);
542 DEBUGFS_ADD(ieee8021_x, vlan);
543 DEBUGFS_ADD(vlan_id, vlan);
544 }
545
546 static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
547 {
548 DEBUGFS_ADD(mode, monitor);
549 }
550
551 static void add_files(struct ieee80211_sub_if_data *sdata)
552 {
553 if (!sdata->debugfsdir)
554 return;
555
556 switch (sdata->type) {
557 case IEEE80211_IF_TYPE_STA:
558 case IEEE80211_IF_TYPE_IBSS:
559 add_sta_files(sdata);
560 break;
561 case IEEE80211_IF_TYPE_AP:
562 add_ap_files(sdata);
563 break;
564 case IEEE80211_IF_TYPE_WDS:
565 add_wds_files(sdata);
566 break;
567 case IEEE80211_IF_TYPE_MNTR:
568 add_monitor_files(sdata);
569 break;
570 case IEEE80211_IF_TYPE_VLAN:
571 add_vlan_files(sdata);
572 break;
573 default:
574 break;
575 }
576 }
577
578 #define DEBUGFS_DEL(name, type) \
579 do { \
580 debugfs_remove(sdata->debugfs.type.name); \
581 sdata->debugfs.type.name = NULL; \
582 } while (0)
583
584 static void del_sta_files(struct ieee80211_sub_if_data *sdata)
585 {
586 DEBUGFS_DEL(channel_use, sta);
587 DEBUGFS_DEL(drop_unencrypted, sta);
588 DEBUGFS_DEL(eapol, sta);
589 DEBUGFS_DEL(ieee8021_x, sta);
590 DEBUGFS_DEL(state, sta);
591 DEBUGFS_DEL(bssid, sta);
592 DEBUGFS_DEL(prev_bssid, sta);
593 DEBUGFS_DEL(ssid_len, sta);
594 DEBUGFS_DEL(aid, sta);
595 DEBUGFS_DEL(ap_capab, sta);
596 DEBUGFS_DEL(capab, sta);
597 DEBUGFS_DEL(extra_ie_len, sta);
598 DEBUGFS_DEL(auth_tries, sta);
599 DEBUGFS_DEL(assoc_tries, sta);
600 DEBUGFS_DEL(auth_algs, sta);
601 DEBUGFS_DEL(auth_alg, sta);
602 DEBUGFS_DEL(auth_transaction, sta);
603 DEBUGFS_DEL(flags, sta);
604
605 DEBUGFS_TSINFO_DEL(tsid);
606 DEBUGFS_TSINFO_DEL(direction);
607 DEBUGFS_TSINFO_DEL(up);
608
609 DEBUGFS_TSPEC_DEL(nominal_msdu_size);
610 DEBUGFS_TSPEC_DEL(max_msdu_size);
611 DEBUGFS_TSPEC_DEL(min_service_interval);
612 DEBUGFS_TSPEC_DEL(max_service_interval);
613 DEBUGFS_TSPEC_DEL(inactivity_interval);
614 DEBUGFS_TSPEC_DEL(suspension_interval);
615 DEBUGFS_TSPEC_DEL(service_start_time);
616 DEBUGFS_TSPEC_DEL(min_data_rate);
617 DEBUGFS_TSPEC_DEL(mean_data_rate);
618 DEBUGFS_TSPEC_DEL(peak_data_rate);
619 DEBUGFS_TSPEC_DEL(burst_size);
620 DEBUGFS_TSPEC_DEL(delay_bound);
621 DEBUGFS_TSPEC_DEL(min_phy_rate);
622 DEBUGFS_TSPEC_DEL(surplus_band_allow);
623 DEBUGFS_TSPEC_DEL(medium_time);
624
625 DEBUGFS_QOS_DEL(addts_11e);
626 DEBUGFS_QOS_DEL(addts_wmm);
627 DEBUGFS_QOS_DEL(delts_11e);
628 DEBUGFS_QOS_DEL(delts_wmm);
629 DEBUGFS_QOS_DEL(dls_mac);
630 DEBUGFS_QOS_DEL(dls_op);
631
632 debugfs_remove(sdata->debugfs.sta.tspec_dir);
633 sdata->debugfs.sta.tspec_dir = NULL;
634 debugfs_remove(sdata->debugfs.sta.tsinfo_dir);
635 sdata->debugfs.sta.tsinfo_dir = NULL;
636 debugfs_remove(sdata->debugfs.sta.qos_dir);
637 sdata->debugfs.sta.qos_dir = NULL;
638 }
639
640 static void del_ap_files(struct ieee80211_sub_if_data *sdata)
641 {
642 DEBUGFS_DEL(channel_use, ap);
643 DEBUGFS_DEL(drop_unencrypted, ap);
644 DEBUGFS_DEL(eapol, ap);
645 DEBUGFS_DEL(ieee8021_x, ap);
646 DEBUGFS_DEL(num_sta_ps, ap);
647 DEBUGFS_DEL(dtim_period, ap);
648 DEBUGFS_DEL(dtim_count, ap);
649 DEBUGFS_DEL(num_beacons, ap);
650 DEBUGFS_DEL(force_unicast_rateidx, ap);
651 DEBUGFS_DEL(max_ratectrl_rateidx, ap);
652 DEBUGFS_DEL(num_buffered_multicast, ap);
653 DEBUGFS_DEL(beacon_head_len, ap);
654 DEBUGFS_DEL(beacon_tail_len, ap);
655 }
656
657 static void del_wds_files(struct ieee80211_sub_if_data *sdata)
658 {
659 DEBUGFS_DEL(channel_use, wds);
660 DEBUGFS_DEL(drop_unencrypted, wds);
661 DEBUGFS_DEL(eapol, wds);
662 DEBUGFS_DEL(ieee8021_x, wds);
663 DEBUGFS_DEL(peer, wds);
664 }
665
666 static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
667 {
668 DEBUGFS_DEL(channel_use, vlan);
669 DEBUGFS_DEL(drop_unencrypted, vlan);
670 DEBUGFS_DEL(eapol, vlan);
671 DEBUGFS_DEL(ieee8021_x, vlan);
672 DEBUGFS_DEL(vlan_id, vlan);
673 }
674
675 static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
676 {
677 DEBUGFS_DEL(mode, monitor);
678 }
679
680 static void del_files(struct ieee80211_sub_if_data *sdata, int type)
681 {
682 if (!sdata->debugfsdir)
683 return;
684
685 switch (type) {
686 case IEEE80211_IF_TYPE_STA:
687 case IEEE80211_IF_TYPE_IBSS:
688 del_sta_files(sdata);
689 break;
690 case IEEE80211_IF_TYPE_AP:
691 del_ap_files(sdata);
692 break;
693 case IEEE80211_IF_TYPE_WDS:
694 del_wds_files(sdata);
695 break;
696 case IEEE80211_IF_TYPE_MNTR:
697 del_monitor_files(sdata);
698 break;
699 case IEEE80211_IF_TYPE_VLAN:
700 del_vlan_files(sdata);
701 break;
702 default:
703 break;
704 }
705 }
706
707 static int notif_registered;
708
709 void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
710 {
711 char buf[10+IFNAMSIZ];
712
713 if (!notif_registered)
714 return;
715
716 sprintf(buf, "netdev:%s", sdata->dev->name);
717 sdata->debugfsdir = debugfs_create_dir(buf,
718 sdata->local->hw.wiphy->debugfsdir);
719 }
720
721 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
722 {
723 del_files(sdata, sdata->type);
724 debugfs_remove(sdata->debugfsdir);
725 sdata->debugfsdir = NULL;
726 }
727
728 void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
729 int oldtype)
730 {
731 del_files(sdata, oldtype);
732 add_files(sdata);
733 }
734
735 static int netdev_notify(struct notifier_block * nb,
736 unsigned long state,
737 void *ndev)
738 {
739 struct net_device *dev = ndev;
740 char buf[10+IFNAMSIZ];
741
742 if (state != NETDEV_CHANGENAME)
743 return 0;
744
745 if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
746 return 0;
747
748 if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
749 return 0;
750
751 /* TODO
752 sprintf(buf, "netdev:%s", dev->name);
753 debugfs_rename(IEEE80211_DEV_TO_SUB_IF(dev)->debugfsdir, buf);
754 */
755
756 return 0;
757 }
758
759 static struct notifier_block mac80211_debugfs_netdev_notifier = {
760 .notifier_call = netdev_notify,
761 };
762
763 void ieee80211_debugfs_netdev_init(void)
764 {
765 int err;
766
767 err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
768 if (err) {
769 printk(KERN_ERR
770 "mac80211: failed to install netdev notifier,"
771 " disabling per-netdev debugfs!\n");
772 } else
773 notif_registered = 1;
774 }
775
776 void ieee80211_debugfs_netdev_exit(void)
777 {
778 unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
779 notif_registered = 0;
780 }