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