aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/wireless.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/wireless.c')
-rw-r--r--net/core/wireless.c79
1 files changed, 58 insertions, 21 deletions
diff --git a/net/core/wireless.c b/net/core/wireless.c
index d2bc72d318f7..ffff0da46c6e 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -68,11 +68,18 @@
68 * 68 *
69 * v8 - 17.02.06 - Jean II 69 * v8 - 17.02.06 - Jean II
70 * o RtNetlink requests support (SET/GET) 70 * o RtNetlink requests support (SET/GET)
71 *
72 * v8b - 03.08.06 - Herbert Xu
73 * o Fix Wireless Event locking issues.
74 *
75 * v9 - 14.3.06 - Jean II
76 * o Change length in ESSID and NICK to strlen() instead of strlen()+1
77 * o Make standard_ioctl_num and standard_event_num unsigned
78 * o Remove (struct net_device *)->get_wireless_stats()
71 */ 79 */
72 80
73/***************************** INCLUDES *****************************/ 81/***************************** INCLUDES *****************************/
74 82
75#include <linux/config.h> /* Not needed ??? */
76#include <linux/module.h> 83#include <linux/module.h>
77#include <linux/types.h> /* off_t */ 84#include <linux/types.h> /* off_t */
78#include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */ 85#include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */
@@ -82,9 +89,11 @@
82#include <linux/init.h> /* for __init */ 89#include <linux/init.h> /* for __init */
83#include <linux/if_arp.h> /* ARPHRD_ETHER */ 90#include <linux/if_arp.h> /* ARPHRD_ETHER */
84#include <linux/etherdevice.h> /* compare_ether_addr */ 91#include <linux/etherdevice.h> /* compare_ether_addr */
92#include <linux/interrupt.h>
85 93
86#include <linux/wireless.h> /* Pretty obvious */ 94#include <linux/wireless.h> /* Pretty obvious */
87#include <net/iw_handler.h> /* New driver API */ 95#include <net/iw_handler.h> /* New driver API */
96#include <net/netlink.h>
88 97
89#include <asm/uaccess.h> /* copy_to_user() */ 98#include <asm/uaccess.h> /* copy_to_user() */
90 99
@@ -233,24 +242,24 @@ static const struct iw_ioctl_description standard_ioctl[] = {
233 [SIOCSIWESSID - SIOCIWFIRST] = { 242 [SIOCSIWESSID - SIOCIWFIRST] = {
234 .header_type = IW_HEADER_TYPE_POINT, 243 .header_type = IW_HEADER_TYPE_POINT,
235 .token_size = 1, 244 .token_size = 1,
236 .max_tokens = IW_ESSID_MAX_SIZE + 1, 245 .max_tokens = IW_ESSID_MAX_SIZE,
237 .flags = IW_DESCR_FLAG_EVENT, 246 .flags = IW_DESCR_FLAG_EVENT,
238 }, 247 },
239 [SIOCGIWESSID - SIOCIWFIRST] = { 248 [SIOCGIWESSID - SIOCIWFIRST] = {
240 .header_type = IW_HEADER_TYPE_POINT, 249 .header_type = IW_HEADER_TYPE_POINT,
241 .token_size = 1, 250 .token_size = 1,
242 .max_tokens = IW_ESSID_MAX_SIZE + 1, 251 .max_tokens = IW_ESSID_MAX_SIZE,
243 .flags = IW_DESCR_FLAG_DUMP, 252 .flags = IW_DESCR_FLAG_DUMP,
244 }, 253 },
245 [SIOCSIWNICKN - SIOCIWFIRST] = { 254 [SIOCSIWNICKN - SIOCIWFIRST] = {
246 .header_type = IW_HEADER_TYPE_POINT, 255 .header_type = IW_HEADER_TYPE_POINT,
247 .token_size = 1, 256 .token_size = 1,
248 .max_tokens = IW_ESSID_MAX_SIZE + 1, 257 .max_tokens = IW_ESSID_MAX_SIZE,
249 }, 258 },
250 [SIOCGIWNICKN - SIOCIWFIRST] = { 259 [SIOCGIWNICKN - SIOCIWFIRST] = {
251 .header_type = IW_HEADER_TYPE_POINT, 260 .header_type = IW_HEADER_TYPE_POINT,
252 .token_size = 1, 261 .token_size = 1,
253 .max_tokens = IW_ESSID_MAX_SIZE + 1, 262 .max_tokens = IW_ESSID_MAX_SIZE,
254 }, 263 },
255 [SIOCSIWRATE - SIOCIWFIRST] = { 264 [SIOCSIWRATE - SIOCIWFIRST] = {
256 .header_type = IW_HEADER_TYPE_PARAM, 265 .header_type = IW_HEADER_TYPE_PARAM,
@@ -337,8 +346,8 @@ static const struct iw_ioctl_description standard_ioctl[] = {
337 .max_tokens = sizeof(struct iw_pmksa), 346 .max_tokens = sizeof(struct iw_pmksa),
338 }, 347 },
339}; 348};
340static const int standard_ioctl_num = (sizeof(standard_ioctl) / 349static const unsigned standard_ioctl_num = (sizeof(standard_ioctl) /
341 sizeof(struct iw_ioctl_description)); 350 sizeof(struct iw_ioctl_description));
342 351
343/* 352/*
344 * Meta-data about all the additional standard Wireless Extension events 353 * Meta-data about all the additional standard Wireless Extension events
@@ -388,8 +397,8 @@ static const struct iw_ioctl_description standard_event[] = {
388 .max_tokens = sizeof(struct iw_pmkid_cand), 397 .max_tokens = sizeof(struct iw_pmkid_cand),
389 }, 398 },
390}; 399};
391static const int standard_event_num = (sizeof(standard_event) / 400static const unsigned standard_event_num = (sizeof(standard_event) /
392 sizeof(struct iw_ioctl_description)); 401 sizeof(struct iw_ioctl_description));
393 402
394/* Size (in bytes) of the various private data types */ 403/* Size (in bytes) of the various private data types */
395static const char iw_priv_type_size[] = { 404static const char iw_priv_type_size[] = {
@@ -464,17 +473,6 @@ static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
464 (dev->wireless_handlers->get_wireless_stats != NULL)) 473 (dev->wireless_handlers->get_wireless_stats != NULL))
465 return dev->wireless_handlers->get_wireless_stats(dev); 474 return dev->wireless_handlers->get_wireless_stats(dev);
466 475
467 /* Old location, field to be removed in next WE */
468 if(dev->get_wireless_stats) {
469 static int printed_message;
470
471 if (!printed_message++)
472 printk(KERN_DEBUG "%s (WE) : Driver using old /proc/net/wireless support, please fix driver !\n",
473 dev->name);
474
475 return dev->get_wireless_stats(dev);
476 }
477
478 /* Not found */ 476 /* Not found */
479 return (struct iw_statistics *) NULL; 477 return (struct iw_statistics *) NULL;
480} 478}
@@ -1844,6 +1842,43 @@ int wireless_rtnetlink_set(struct net_device * dev,
1844#ifdef WE_EVENT_RTNETLINK 1842#ifdef WE_EVENT_RTNETLINK
1845/* ---------------------------------------------------------------- */ 1843/* ---------------------------------------------------------------- */
1846/* 1844/*
1845 * Locking...
1846 * ----------
1847 *
1848 * Thanks to Herbert Xu <herbert@gondor.apana.org.au> for fixing
1849 * the locking issue in here and implementing this code !
1850 *
1851 * The issue : wireless_send_event() is often called in interrupt context,
1852 * while the Netlink layer can never be called in interrupt context.
1853 * The fully formed RtNetlink events are queued, and then a tasklet is run
1854 * to feed those to Netlink.
1855 * The skb_queue is interrupt safe, and its lock is not held while calling
1856 * Netlink, so there is no possibility of dealock.
1857 * Jean II
1858 */
1859
1860static struct sk_buff_head wireless_nlevent_queue;
1861
1862static int __init wireless_nlevent_init(void)
1863{
1864 skb_queue_head_init(&wireless_nlevent_queue);
1865 return 0;
1866}
1867
1868subsys_initcall(wireless_nlevent_init);
1869
1870static void wireless_nlevent_process(unsigned long data)
1871{
1872 struct sk_buff *skb;
1873
1874 while ((skb = skb_dequeue(&wireless_nlevent_queue)))
1875 rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
1876}
1877
1878static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0);
1879
1880/* ---------------------------------------------------------------- */
1881/*
1847 * Fill a rtnetlink message with our event data. 1882 * Fill a rtnetlink message with our event data.
1848 * Note that we propage only the specified event and don't dump the 1883 * Note that we propage only the specified event and don't dump the
1849 * current wireless config. Dumping the wireless config is far too 1884 * current wireless config. Dumping the wireless config is far too
@@ -1904,8 +1939,10 @@ static inline void rtmsg_iwinfo(struct net_device * dev,
1904 return; 1939 return;
1905 } 1940 }
1906 NETLINK_CB(skb).dst_group = RTNLGRP_LINK; 1941 NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
1907 netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); 1942 skb_queue_tail(&wireless_nlevent_queue, skb);
1943 tasklet_schedule(&wireless_nlevent_tasklet);
1908} 1944}
1945
1909#endif /* WE_EVENT_RTNETLINK */ 1946#endif /* WE_EVENT_RTNETLINK */
1910 1947
1911/* ---------------------------------------------------------------- */ 1948/* ---------------------------------------------------------------- */