2 * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
9 #include <linux/kernel.h>
10 #include <linux/device.h>
12 #include <linux/interrupt.h>
13 #include <linux/netdevice.h>
14 #include <linux/rtnetlink.h>
15 #include <net/d80211.h>
16 #include "ieee80211_i.h"
17 #include "ieee80211_rate.h"
19 #define to_ieee80211_local(class) \
20 container_of(class, struct ieee80211_local, class_dev)
21 #define to_net_dev(class) \
22 container_of(class, struct net_device, class_dev)
24 static inline int rtnl_lock_local(struct ieee80211_local
*local
)
27 if (unlikely(local
->reg_state
!= IEEE80211_DEV_REGISTERED
)) {
34 static const char *ieee80211_mode_str_short(int mode
)
43 case MODE_ATHEROS_TURBO
:
44 return "AtherosTurbo";
50 static const char *ieee80211_mode_str(int mode
)
54 return "IEEE 802.11a";
56 return "IEEE 802.11b";
58 return "IEEE 802.11g";
59 case MODE_ATHEROS_TURBO
:
60 return "Atheros Turbo (5 GHz)";
66 /* attributes in /sys/class/ieee80211/phyX/ */
68 static ssize_t
store_add_iface(struct class_device
*dev
,
69 const char *buf
, size_t len
)
71 struct ieee80211_local
*local
= to_ieee80211_local(dev
);
72 struct net_device
*new_dev
;
75 if (!capable(CAP_NET_ADMIN
))
79 res
= rtnl_lock_local(local
);
82 res
= ieee80211_if_add(local
->mdev
, buf
, 0, &new_dev
);
84 ieee80211_if_set_type(new_dev
, IEEE80211_IF_TYPE_STA
);
86 return res
< 0 ? res
: len
;
89 static ssize_t
store_remove_iface(struct class_device
*dev
,
90 const char *buf
, size_t len
)
92 struct ieee80211_local
*local
= to_ieee80211_local(dev
);
95 if (!capable(CAP_NET_ADMIN
))
99 res
= rtnl_lock_local(local
);
102 res
= ieee80211_if_remove(local
->mdev
, buf
, -1);
104 return res
< 0 ? res
: len
;
107 static ssize_t
store_rate_ctrl_alg(struct class_device
*dev
,
108 const char *buf
, size_t len
)
110 struct ieee80211_local
*local
= to_ieee80211_local(dev
);
113 if (!capable(CAP_NET_ADMIN
))
115 res
= rtnl_lock_local(local
);
118 res
= ieee80211_init_rate_ctrl_alg(local
, buf
);
120 return res
< 0 ? res
: len
;
123 static ssize_t
ieee80211_local_show(struct class_device
*dev
, char *buf
,
124 ssize_t (*format
)(struct ieee80211_local
*, char *))
126 struct ieee80211_local
*local
= to_ieee80211_local(dev
);
127 ssize_t ret
= -EINVAL
;
129 if (local
->reg_state
== IEEE80211_DEV_REGISTERED
)
130 ret
= (*format
)(local
, buf
);
134 #define IEEE80211_LOCAL_FMT(name, field, format_string) \
135 static ssize_t ieee80211_local_fmt_##name(struct ieee80211_local *local,\
138 return sprintf(buf, format_string, local->field); \
141 #define __IEEE80211_LOCAL_SHOW(name) \
142 static ssize_t ieee80211_local_show_##name(struct class_device *cd, \
145 return ieee80211_local_show(cd, buf, \
146 ieee80211_local_fmt_##name); \
149 #define IEEE80211_LOCAL_SHOW(name, field, format) \
150 IEEE80211_LOCAL_FMT(name, field, format "\n") \
151 __IEEE80211_LOCAL_SHOW(name)
153 IEEE80211_LOCAL_SHOW(channel
, hw
.conf
.channel
, "%d");
154 IEEE80211_LOCAL_SHOW(frequency
, hw
.conf
.freq
, "%d");
155 IEEE80211_LOCAL_SHOW(radar_detect
, hw
.conf
.radar_detect
, "%d");
156 IEEE80211_LOCAL_SHOW(antenna_sel
, hw
.conf
.antenna_sel
, "%d");
157 IEEE80211_LOCAL_SHOW(bridge_packets
, bridge_packets
, "%d");
158 IEEE80211_LOCAL_SHOW(key_tx_rx_threshold
, key_tx_rx_threshold
, "%d");
159 IEEE80211_LOCAL_SHOW(rts_threshold
, rts_threshold
, "%d");
160 IEEE80211_LOCAL_SHOW(fragmentation_threshold
, fragmentation_threshold
, "%d");
161 IEEE80211_LOCAL_SHOW(short_retry_limit
, short_retry_limit
, "%d");
162 IEEE80211_LOCAL_SHOW(long_retry_limit
, long_retry_limit
, "%d");
163 IEEE80211_LOCAL_SHOW(total_ps_buffered
, total_ps_buffered
, "%d");
165 static ssize_t
ieee80211_local_fmt_mode(struct ieee80211_local
*local
,
168 return sprintf(buf
, "%s\n", ieee80211_mode_str(local
->hw
.conf
.phymode
));
170 __IEEE80211_LOCAL_SHOW(mode
);
172 static ssize_t
ieee80211_local_fmt_wep_iv(struct ieee80211_local
*local
,
175 return sprintf(buf
, "%#06x\n", local
->wep_iv
& 0xffffff);
177 __IEEE80211_LOCAL_SHOW(wep_iv
);
179 static ssize_t
ieee80211_local_fmt_tx_power_reduction(struct ieee80211_local
182 short tx_power_reduction
= local
->hw
.conf
.tx_power_reduction
;
184 return sprintf(buf
, "%d.%d dBm\n", tx_power_reduction
/ 10,
185 tx_power_reduction
% 10);
187 __IEEE80211_LOCAL_SHOW(tx_power_reduction
);
189 static ssize_t
ieee80211_local_fmt_modes(struct ieee80211_local
*local
,
193 struct ieee80211_hw_modes
*mode
;
196 /* FIXME: locking against ieee80211_update_hw? */
197 for (i
= 0; i
< local
->hw
.num_modes
; i
++) {
198 mode
= &local
->hw
.modes
[i
];
199 p
+= sprintf(p
, "%s\n", ieee80211_mode_str_short(mode
->mode
));
203 __IEEE80211_LOCAL_SHOW(modes
);
205 static ssize_t
ieee80211_local_fmt_rate_ctrl_alg(struct ieee80211_local
*local
,
208 struct rate_control_ref
*ref
= local
->rate_ctrl
;
210 return sprintf(buf
, "%s\n", ref
->ops
->name
);
213 __IEEE80211_LOCAL_SHOW(rate_ctrl_alg
);
215 static struct class_device_attribute ieee80211_class_dev_attrs
[] = {
216 __ATTR(add_iface
, S_IWUGO
, NULL
, store_add_iface
),
217 __ATTR(remove_iface
, S_IWUGO
, NULL
, store_remove_iface
),
218 __ATTR(channel
, S_IRUGO
, ieee80211_local_show_channel
, NULL
),
219 __ATTR(frequency
, S_IRUGO
, ieee80211_local_show_frequency
, NULL
),
220 __ATTR(radar_detect
, S_IRUGO
, ieee80211_local_show_radar_detect
, NULL
),
221 __ATTR(antenna_sel
, S_IRUGO
, ieee80211_local_show_antenna_sel
, NULL
),
222 __ATTR(bridge_packets
, S_IRUGO
, ieee80211_local_show_bridge_packets
, NULL
),
223 __ATTR(key_tx_rx_threshold
, S_IRUGO
, ieee80211_local_show_key_tx_rx_threshold
, NULL
),
224 __ATTR(rts_threshold
, S_IRUGO
, ieee80211_local_show_rts_threshold
, NULL
),
225 __ATTR(fragmentation_threshold
, S_IRUGO
, ieee80211_local_show_fragmentation_threshold
, NULL
),
226 __ATTR(short_retry_limit
, S_IRUGO
, ieee80211_local_show_short_retry_limit
, NULL
),
227 __ATTR(long_retry_limit
, S_IRUGO
, ieee80211_local_show_long_retry_limit
, NULL
),
228 __ATTR(total_ps_buffered
, S_IRUGO
, ieee80211_local_show_total_ps_buffered
, NULL
),
229 __ATTR(mode
, S_IRUGO
, ieee80211_local_show_mode
, NULL
),
230 __ATTR(wep_iv
, S_IRUGO
, ieee80211_local_show_wep_iv
, NULL
),
231 __ATTR(tx_power_reduction
, S_IRUGO
, ieee80211_local_show_tx_power_reduction
, NULL
),
232 __ATTR(modes
, S_IRUGO
, ieee80211_local_show_modes
, NULL
),
233 __ATTR(rate_ctrl_alg
, S_IRUGO
| S_IWUGO
, ieee80211_local_show_rate_ctrl_alg
, store_rate_ctrl_alg
),
237 /* attributes in /sys/class/ieee80211/phyX/statistics/ */
239 #define IEEE80211_LOCAL_ATTR(name, field, format) \
240 IEEE80211_LOCAL_SHOW(name, field, format) \
241 static CLASS_DEVICE_ATTR(name, S_IRUGO, ieee80211_local_show_##name, NULL);
243 IEEE80211_LOCAL_ATTR(transmitted_fragment_count
, dot11TransmittedFragmentCount
, "%u");
244 IEEE80211_LOCAL_ATTR(multicast_transmitted_frame_count
, dot11MulticastTransmittedFrameCount
, "%u");
245 IEEE80211_LOCAL_ATTR(failed_count
, dot11FailedCount
, "%u");
246 IEEE80211_LOCAL_ATTR(retry_count
, dot11RetryCount
, "%u");
247 IEEE80211_LOCAL_ATTR(multiple_retry_count
, dot11MultipleRetryCount
, "%u");
248 IEEE80211_LOCAL_ATTR(frame_duplicate_count
, dot11FrameDuplicateCount
, "%u");
249 IEEE80211_LOCAL_ATTR(received_fragment_count
, dot11ReceivedFragmentCount
, "%u");
250 IEEE80211_LOCAL_ATTR(multicast_received_frame_count
, dot11MulticastReceivedFrameCount
, "%u");
251 IEEE80211_LOCAL_ATTR(transmitted_frame_count
, dot11TransmittedFrameCount
, "%u");
252 IEEE80211_LOCAL_ATTR(wep_undecryptable_count
, dot11WEPUndecryptableCount
, "%u");
253 IEEE80211_LOCAL_ATTR(num_scans
, scan
.num_scans
, "%u");
255 #ifdef CONFIG_D80211_DEBUG_COUNTERS
256 IEEE80211_LOCAL_ATTR(tx_handlers_drop
, tx_handlers_drop
, "%u");
257 IEEE80211_LOCAL_ATTR(tx_handlers_queued
, tx_handlers_queued
, "%u");
258 IEEE80211_LOCAL_ATTR(tx_handlers_drop_unencrypted
, tx_handlers_drop_unencrypted
, "%u");
259 IEEE80211_LOCAL_ATTR(tx_handlers_drop_fragment
, tx_handlers_drop_fragment
, "%u");
260 IEEE80211_LOCAL_ATTR(tx_handlers_drop_wep
, tx_handlers_drop_wep
, "%u");
261 IEEE80211_LOCAL_ATTR(tx_handlers_drop_not_assoc
, tx_handlers_drop_not_assoc
, "%u");
262 IEEE80211_LOCAL_ATTR(tx_handlers_drop_unauth_port
, tx_handlers_drop_unauth_port
, "%u");
263 IEEE80211_LOCAL_ATTR(rx_handlers_drop
, rx_handlers_drop
, "%u");
264 IEEE80211_LOCAL_ATTR(rx_handlers_queued
, rx_handlers_queued
, "%u");
265 IEEE80211_LOCAL_ATTR(rx_handlers_drop_nullfunc
, rx_handlers_drop_nullfunc
, "%u");
266 IEEE80211_LOCAL_ATTR(rx_handlers_drop_defrag
, rx_handlers_drop_defrag
, "%u");
267 IEEE80211_LOCAL_ATTR(rx_handlers_drop_short
, rx_handlers_drop_short
, "%u");
268 IEEE80211_LOCAL_ATTR(rx_handlers_drop_passive_scan
, rx_handlers_drop_passive_scan
, "%u");
269 IEEE80211_LOCAL_ATTR(tx_expand_skb_head
, tx_expand_skb_head
, "%u");
270 IEEE80211_LOCAL_ATTR(tx_expand_skb_head_cloned
, tx_expand_skb_head_cloned
, "%u");
271 IEEE80211_LOCAL_ATTR(rx_expand_skb_head
, rx_expand_skb_head
, "%u");
272 IEEE80211_LOCAL_ATTR(rx_expand_skb_head2
, rx_expand_skb_head2
, "%u");
273 IEEE80211_LOCAL_ATTR(rx_handlers_fragments
, rx_handlers_fragments
, "%u");
274 IEEE80211_LOCAL_ATTR(tx_status_drop
, tx_status_drop
, "%u");
276 static ssize_t
ieee80211_local_fmt_wme_rx_queue(struct ieee80211_local
*local
,
282 for (i
= 0; i
< NUM_RX_DATA_QUEUES
; i
++)
283 p
+= sprintf(p
, "%u\n", local
->wme_rx_queue
[i
]);
286 __IEEE80211_LOCAL_SHOW(wme_rx_queue
);
287 static CLASS_DEVICE_ATTR(wme_rx_queue
, S_IRUGO
,
288 ieee80211_local_show_wme_rx_queue
, NULL
);
290 static ssize_t
ieee80211_local_fmt_wme_tx_queue(struct ieee80211_local
*local
,
296 for (i
= 0; i
< NUM_RX_DATA_QUEUES
; i
++)
297 p
+= sprintf(p
, "%u\n", local
->wme_tx_queue
[i
]);
300 __IEEE80211_LOCAL_SHOW(wme_tx_queue
);
301 static CLASS_DEVICE_ATTR(wme_tx_queue
, S_IRUGO
,
302 ieee80211_local_show_wme_tx_queue
, NULL
);
305 static ssize_t
ieee80211_stats_show(struct class_device
*dev
, char *buf
,
306 ssize_t (*format
)(struct ieee80211_low_level_stats
*, char *))
308 struct ieee80211_local
*local
= to_ieee80211_local(dev
);
309 struct ieee80211_low_level_stats stats
;
310 ssize_t ret
= -EINVAL
;
312 if (!local
->ops
->get_stats
)
314 ret
= rtnl_lock_local(local
);
317 ret
= local
->ops
->get_stats(local_to_hw(local
), &stats
);
320 ret
= (*format
)(&stats
, buf
);
324 #define IEEE80211_STATS_FMT(name, field, format_string) \
325 static ssize_t ieee80211_stats_fmt_##name(struct ieee80211_low_level_stats \
328 return sprintf(buf, format_string, stats->field); \
331 #define __IEEE80211_STATS_SHOW(name) \
332 static ssize_t ieee80211_stats_show_##name(struct class_device *cd, \
335 return ieee80211_stats_show(cd, buf, \
336 ieee80211_stats_fmt_##name); \
339 #define IEEE80211_STATS_ATTR(name, field, format) \
340 IEEE80211_STATS_FMT(name, field, format "\n") \
341 __IEEE80211_STATS_SHOW(name) \
342 static CLASS_DEVICE_ATTR(name, S_IRUGO, ieee80211_stats_show_##name, NULL);
344 IEEE80211_STATS_ATTR(ack_failure_count
, dot11ACKFailureCount
, "%u");
345 IEEE80211_STATS_ATTR(rts_failure_count
, dot11RTSFailureCount
, "%u");
346 IEEE80211_STATS_ATTR(fcs_error_count
, dot11FCSErrorCount
, "%u");
347 IEEE80211_STATS_ATTR(rts_success_count
, dot11RTSSuccessCount
, "%u");
349 static struct attribute
*ieee80211_stats_attrs
[] = {
350 &class_device_attr_transmitted_fragment_count
.attr
,
351 &class_device_attr_multicast_transmitted_frame_count
.attr
,
352 &class_device_attr_failed_count
.attr
,
353 &class_device_attr_retry_count
.attr
,
354 &class_device_attr_multiple_retry_count
.attr
,
355 &class_device_attr_frame_duplicate_count
.attr
,
356 &class_device_attr_received_fragment_count
.attr
,
357 &class_device_attr_multicast_received_frame_count
.attr
,
358 &class_device_attr_transmitted_frame_count
.attr
,
359 &class_device_attr_wep_undecryptable_count
.attr
,
360 &class_device_attr_ack_failure_count
.attr
,
361 &class_device_attr_rts_failure_count
.attr
,
362 &class_device_attr_fcs_error_count
.attr
,
363 &class_device_attr_rts_success_count
.attr
,
364 &class_device_attr_num_scans
.attr
,
365 #ifdef CONFIG_D80211_DEBUG_COUNTERS
366 &class_device_attr_tx_handlers_drop
.attr
,
367 &class_device_attr_tx_handlers_queued
.attr
,
368 &class_device_attr_tx_handlers_drop_unencrypted
.attr
,
369 &class_device_attr_tx_handlers_drop_fragment
.attr
,
370 &class_device_attr_tx_handlers_drop_wep
.attr
,
371 &class_device_attr_tx_handlers_drop_not_assoc
.attr
,
372 &class_device_attr_tx_handlers_drop_unauth_port
.attr
,
373 &class_device_attr_rx_handlers_drop
.attr
,
374 &class_device_attr_rx_handlers_queued
.attr
,
375 &class_device_attr_rx_handlers_drop_nullfunc
.attr
,
376 &class_device_attr_rx_handlers_drop_defrag
.attr
,
377 &class_device_attr_rx_handlers_drop_short
.attr
,
378 &class_device_attr_rx_handlers_drop_passive_scan
.attr
,
379 &class_device_attr_tx_expand_skb_head
.attr
,
380 &class_device_attr_tx_expand_skb_head_cloned
.attr
,
381 &class_device_attr_rx_expand_skb_head
.attr
,
382 &class_device_attr_rx_expand_skb_head2
.attr
,
383 &class_device_attr_rx_handlers_fragments
.attr
,
384 &class_device_attr_tx_status_drop
.attr
,
385 &class_device_attr_wme_rx_queue
.attr
,
386 &class_device_attr_wme_tx_queue
.attr
,
391 static struct attribute_group ieee80211_stats_group
= {
392 .name
= "statistics",
393 .attrs
= ieee80211_stats_attrs
,
396 /* attributes in /sys/class/net/X/ */
398 static ssize_t
ieee80211_if_show(struct class_device
*cd
, char *buf
,
399 ssize_t (*format
)(const struct ieee80211_sub_if_data
*,
402 struct net_device
*dev
= to_net_dev(cd
);
403 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
404 ssize_t ret
= -EINVAL
;
406 read_lock(&dev_base_lock
);
407 if (dev
->reg_state
== NETREG_REGISTERED
) {
408 ret
= (*format
)(sdata
, buf
);
410 read_unlock(&dev_base_lock
);
414 #define IEEE80211_IF_FMT(name, field, format_string) \
415 static ssize_t ieee80211_if_fmt_##name(const struct \
416 ieee80211_sub_if_data *sdata, char *buf) \
418 return sprintf(buf, format_string, sdata->field); \
420 #define IEEE80211_IF_FMT_DEC(name, field) \
421 IEEE80211_IF_FMT(name, field, "%d\n")
422 #define IEEE80211_IF_FMT_HEX(name, field) \
423 IEEE80211_IF_FMT(name, field, "%#x\n")
424 #define IEEE80211_IF_FMT_SIZE(name, field) \
425 IEEE80211_IF_FMT(name, field, "%zd\n")
427 #define IEEE80211_IF_FMT_ATOMIC(name, field) \
428 static ssize_t ieee80211_if_fmt_##name(const struct \
429 ieee80211_sub_if_data *sdata, char *buf) \
431 return sprintf(buf, "%d\n", atomic_read(&sdata->field)); \
434 #define IEEE80211_IF_FMT_MAC(name, field) \
435 static ssize_t ieee80211_if_fmt_##name(const struct \
436 ieee80211_sub_if_data *sdata, char *buf) \
438 return sprintf(buf, MAC_FMT "\n", MAC_ARG(sdata->field)); \
441 #define __IEEE80211_IF_SHOW(name) \
442 static ssize_t ieee80211_if_show_##name(struct class_device *cd, \
445 return ieee80211_if_show(cd, buf, ieee80211_if_fmt_##name); \
447 static CLASS_DEVICE_ATTR(name, S_IRUGO, ieee80211_if_show_##name, NULL);
449 #define IEEE80211_IF_SHOW(name, field, format) \
450 IEEE80211_IF_FMT_##format(name, field) \
451 __IEEE80211_IF_SHOW(name)
453 /* common attributes */
454 IEEE80211_IF_SHOW(channel_use
, channel_use
, DEC
);
455 IEEE80211_IF_SHOW(drop_unencrypted
, drop_unencrypted
, DEC
);
456 IEEE80211_IF_SHOW(eapol
, eapol
, DEC
);
457 IEEE80211_IF_SHOW(ieee8021_x
, ieee802_1x
, DEC
);
459 /* STA/IBSS attributes */
460 IEEE80211_IF_SHOW(state
, u
.sta
.state
, DEC
);
461 IEEE80211_IF_SHOW(bssid
, u
.sta
.bssid
, MAC
);
462 IEEE80211_IF_SHOW(prev_bssid
, u
.sta
.prev_bssid
, MAC
);
463 IEEE80211_IF_SHOW(ssid_len
, u
.sta
.ssid_len
, SIZE
);
464 IEEE80211_IF_SHOW(aid
, u
.sta
.aid
, DEC
);
465 IEEE80211_IF_SHOW(ap_capab
, u
.sta
.ap_capab
, HEX
);
466 IEEE80211_IF_SHOW(capab
, u
.sta
.capab
, HEX
);
467 IEEE80211_IF_SHOW(extra_ie_len
, u
.sta
.extra_ie_len
, SIZE
);
468 IEEE80211_IF_SHOW(auth_tries
, u
.sta
.auth_tries
, DEC
);
469 IEEE80211_IF_SHOW(assoc_tries
, u
.sta
.assoc_tries
, DEC
);
470 IEEE80211_IF_SHOW(auth_algs
, u
.sta
.auth_algs
, HEX
);
471 IEEE80211_IF_SHOW(auth_alg
, u
.sta
.auth_alg
, DEC
);
472 IEEE80211_IF_SHOW(auth_transaction
, u
.sta
.auth_transaction
, DEC
);
474 static ssize_t
ieee80211_if_fmt_flags(const struct
475 ieee80211_sub_if_data
*sdata
, char *buf
)
477 return sprintf(buf
, "%s%s%s%s%s%s%s\n",
478 sdata
->u
.sta
.ssid_set
? "SSID\n" : "",
479 sdata
->u
.sta
.bssid_set
? "BSSID\n" : "",
480 sdata
->u
.sta
.prev_bssid_set
? "prev BSSID\n" : "",
481 sdata
->u
.sta
.authenticated
? "AUTH\n" : "",
482 sdata
->u
.sta
.associated
? "ASSOC\n" : "",
483 sdata
->u
.sta
.probereq_poll
? "PROBEREQ POLL\n" : "",
484 sdata
->u
.sta
.use_protection
? "CTS prot\n" : "");
486 __IEEE80211_IF_SHOW(flags
);
489 IEEE80211_IF_SHOW(num_sta_ps
, u
.ap
.num_sta_ps
, ATOMIC
);
490 IEEE80211_IF_SHOW(dtim_period
, u
.ap
.dtim_period
, DEC
);
491 IEEE80211_IF_SHOW(dtim_count
, u
.ap
.dtim_count
, DEC
);
492 IEEE80211_IF_SHOW(num_beacons
, u
.ap
.num_beacons
, DEC
);
493 IEEE80211_IF_SHOW(force_unicast_rateidx
, u
.ap
.force_unicast_rateidx
, DEC
);
494 IEEE80211_IF_SHOW(max_ratectrl_rateidx
, u
.ap
.max_ratectrl_rateidx
, DEC
);
496 static ssize_t
ieee80211_if_fmt_num_buffered_multicast(const struct
497 ieee80211_sub_if_data
*sdata
, char *buf
)
499 return sprintf(buf
, "%u\n", skb_queue_len(&sdata
->u
.ap
.ps_bc_buf
));
501 __IEEE80211_IF_SHOW(num_buffered_multicast
);
503 static ssize_t
ieee80211_if_fmt_beacon_head_len(const struct
504 ieee80211_sub_if_data
*sdata
, char *buf
)
506 if (sdata
->u
.ap
.beacon_head
)
507 return sprintf(buf
, "%d\n", sdata
->u
.ap
.beacon_head_len
);
508 return sprintf(buf
, "\n");
510 __IEEE80211_IF_SHOW(beacon_head_len
);
512 static ssize_t
ieee80211_if_fmt_beacon_tail_len(const struct
513 ieee80211_sub_if_data
*sdata
, char *buf
)
515 if (sdata
->u
.ap
.beacon_tail
)
516 return sprintf(buf
, "%d\n", sdata
->u
.ap
.beacon_tail_len
);
517 return sprintf(buf
, "\n");
519 __IEEE80211_IF_SHOW(beacon_tail_len
);
522 IEEE80211_IF_SHOW(peer
, u
.wds
.remote_addr
, MAC
);
524 /* VLAN attributes */
525 IEEE80211_IF_SHOW(vlan_id
, u
.vlan
.id
, DEC
);
527 /* MONITOR attributes */
528 static ssize_t
ieee80211_if_fmt_mode(const struct
529 ieee80211_sub_if_data
*sdata
, char *buf
)
531 struct ieee80211_local
*local
= sdata
->local
;
533 return sprintf(buf
, "%s\n",
534 ((local
->hw
.flags
& IEEE80211_HW_MONITOR_DURING_OPER
) ||
535 local
->open_count
== local
->monitors
) ?
538 __IEEE80211_IF_SHOW(mode
);
540 static struct attribute
*ieee80211_sta_attrs
[] = {
541 &class_device_attr_channel_use
.attr
,
542 &class_device_attr_drop_unencrypted
.attr
,
543 &class_device_attr_eapol
.attr
,
544 &class_device_attr_ieee8021_x
.attr
,
545 &class_device_attr_state
.attr
,
546 &class_device_attr_bssid
.attr
,
547 &class_device_attr_prev_bssid
.attr
,
548 &class_device_attr_ssid_len
.attr
,
549 &class_device_attr_aid
.attr
,
550 &class_device_attr_ap_capab
.attr
,
551 &class_device_attr_capab
.attr
,
552 &class_device_attr_extra_ie_len
.attr
,
553 &class_device_attr_auth_tries
.attr
,
554 &class_device_attr_assoc_tries
.attr
,
555 &class_device_attr_auth_algs
.attr
,
556 &class_device_attr_auth_alg
.attr
,
557 &class_device_attr_auth_transaction
.attr
,
558 &class_device_attr_flags
.attr
,
562 static struct attribute
*ieee80211_ap_attrs
[] = {
563 &class_device_attr_channel_use
.attr
,
564 &class_device_attr_drop_unencrypted
.attr
,
565 &class_device_attr_eapol
.attr
,
566 &class_device_attr_ieee8021_x
.attr
,
567 &class_device_attr_num_sta_ps
.attr
,
568 &class_device_attr_dtim_period
.attr
,
569 &class_device_attr_dtim_count
.attr
,
570 &class_device_attr_num_beacons
.attr
,
571 &class_device_attr_force_unicast_rateidx
.attr
,
572 &class_device_attr_max_ratectrl_rateidx
.attr
,
573 &class_device_attr_num_buffered_multicast
.attr
,
574 &class_device_attr_beacon_head_len
.attr
,
575 &class_device_attr_beacon_tail_len
.attr
,
579 static struct attribute
*ieee80211_wds_attrs
[] = {
580 &class_device_attr_channel_use
.attr
,
581 &class_device_attr_drop_unencrypted
.attr
,
582 &class_device_attr_eapol
.attr
,
583 &class_device_attr_ieee8021_x
.attr
,
584 &class_device_attr_peer
.attr
,
588 static struct attribute
*ieee80211_vlan_attrs
[] = {
589 &class_device_attr_channel_use
.attr
,
590 &class_device_attr_drop_unencrypted
.attr
,
591 &class_device_attr_eapol
.attr
,
592 &class_device_attr_ieee8021_x
.attr
,
593 &class_device_attr_vlan_id
.attr
,
597 static struct attribute
*ieee80211_monitor_attrs
[] = {
598 &class_device_attr_mode
.attr
,
602 static struct attribute_group ieee80211_sta_group
= {
604 .attrs
= ieee80211_sta_attrs
,
607 static struct attribute_group ieee80211_ap_group
= {
609 .attrs
= ieee80211_ap_attrs
,
612 static struct attribute_group ieee80211_wds_group
= {
614 .attrs
= ieee80211_wds_attrs
,
617 static struct attribute_group ieee80211_vlan_group
= {
619 .attrs
= ieee80211_vlan_attrs
,
622 static struct attribute_group ieee80211_monitor_group
= {
624 .attrs
= ieee80211_monitor_attrs
,
627 /* /sys/class/ieee80211/phyX functions */
629 static void ieee80211_class_dev_release(struct class_device
*dev
)
631 ieee80211_release_hw(to_ieee80211_local(dev
));
634 #ifdef CONFIG_HOTPLUG
635 static int ieee80211_uevent(struct class_device
*cd
, char **envp
,
636 int num_envp
, char *buf
, int size
)
638 struct ieee80211_local
*local
= to_ieee80211_local(cd
);
643 if (snprintf(buf
, size
, "IEEE80211_DEV=phy%d",
644 local
->hw
.index
) + 1 >= size
)
651 static struct class ieee80211_class
= {
653 .class_dev_attrs
= ieee80211_class_dev_attrs
,
654 .release
= ieee80211_class_dev_release
,
655 #ifdef CONFIG_HOTPLUG
656 .uevent
= ieee80211_uevent
,
660 void ieee80211_dev_sysfs_init(struct ieee80211_local
*local
)
662 local
->class_dev
.class = &ieee80211_class
;
663 local
->class_dev
.class_data
= local
;
664 class_device_initialize(&local
->class_dev
);
667 void ieee80211_dev_sysfs_put(struct ieee80211_local
*local
)
669 class_device_put(&local
->class_dev
);
672 int ieee80211_dev_sysfs_add(struct ieee80211_local
*local
)
676 snprintf(local
->class_dev
.class_id
, BUS_ID_SIZE
,
677 "phy%d", local
->hw
.index
);
678 res
= class_device_add(&local
->class_dev
);
681 res
= sysfs_create_group(&local
->class_dev
.kobj
,
682 &ieee80211_stats_group
);
684 class_device_del(&local
->class_dev
);
688 void ieee80211_dev_sysfs_del(struct ieee80211_local
*local
)
690 sysfs_remove_group(&local
->class_dev
.kobj
, &ieee80211_stats_group
);
691 class_device_del(&local
->class_dev
);
694 /* /sys/class/net/X functions */
696 static void __ieee80211_remove_if_group(struct kobject
*kobj
,
697 struct ieee80211_sub_if_data
*sdata
)
699 if (sdata
->sysfs_group
) {
700 sysfs_remove_group(kobj
, sdata
->sysfs_group
);
701 sdata
->sysfs_group
= NULL
;
705 static inline void ieee80211_remove_if_group(struct kobject
*kobj
,
706 struct net_device
*dev
)
708 __ieee80211_remove_if_group(kobj
, IEEE80211_DEV_TO_SUB_IF(dev
));
711 static int ieee80211_add_if_group(struct kobject
*kobj
,
712 struct net_device
*dev
)
714 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
717 __ieee80211_remove_if_group(kobj
, sdata
);
718 switch (sdata
->type
) {
719 case IEEE80211_IF_TYPE_STA
:
720 sdata
->sysfs_group
= &ieee80211_sta_group
;
722 case IEEE80211_IF_TYPE_AP
:
723 sdata
->sysfs_group
= &ieee80211_ap_group
;
725 case IEEE80211_IF_TYPE_WDS
:
726 sdata
->sysfs_group
= &ieee80211_wds_group
;
728 case IEEE80211_IF_TYPE_VLAN
:
729 sdata
->sysfs_group
= &ieee80211_vlan_group
;
731 case IEEE80211_IF_TYPE_MNTR
:
732 sdata
->sysfs_group
= &ieee80211_monitor_group
;
737 res
= sysfs_create_group(kobj
, sdata
->sysfs_group
);
739 sdata
->sysfs_group
= NULL
;
744 int ieee80211_sysfs_change_if_type(struct net_device
*dev
)
746 return ieee80211_add_if_group(&dev
->class_dev
.kobj
, dev
);
749 int ieee80211_sysfs_add_netdevice(struct net_device
*dev
)
751 struct ieee80211_local
*local
= dev
->ieee80211_ptr
;
754 res
= sysfs_create_link(&dev
->class_dev
.kobj
, &local
->class_dev
.kobj
,
758 res
= ieee80211_add_if_group(&dev
->class_dev
.kobj
, dev
);
761 res
= ieee80211_key_kset_sysfs_register(IEEE80211_DEV_TO_SUB_IF(dev
));
765 sysfs_remove_link(&dev
->class_dev
.kobj
, "hw");
770 void ieee80211_sysfs_remove_netdevice(struct net_device
*dev
)
772 ieee80211_key_kset_sysfs_unregister(IEEE80211_DEV_TO_SUB_IF(dev
));
773 ieee80211_remove_if_group(&dev
->class_dev
.kobj
, dev
);
774 sysfs_remove_link(&dev
->class_dev
.kobj
, "hw");
777 /* general module functions */
779 int ieee80211_sysfs_init(void)
781 return class_register(&ieee80211_class
);
784 void ieee80211_sysfs_deinit(void)
786 class_unregister(&ieee80211_class
);