From baef186519c69b11cf7e48c26e75feb1e6173baa Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 8 Sep 2006 16:04:05 -0400 Subject: [PATCH] WE-21 support (core API) This is version 21 of the Wireless Extensions. Changelog : o finishes migrating the ESSID API (remove the +1) o netdev->get_wireless_stats is no more o long/short retry This is a redacted version of a patch originally submitted by Jean Tourrilhes. I removed most of the additions, in order to minimize future support requirements for nl80211 (or other WE successor). CC: Jean Tourrilhes Signed-off-by: John W. Linville --- include/linux/netdevice.h | 1 - include/linux/wireless.h | 24 ++++++++++++++--- net/core/net-sysfs.c | 5 +--- net/core/wireless.c | 67 +++++++++++++++++++++++++++++------------------ 4 files changed, 62 insertions(+), 35 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 43289127b45834..ac4f50213bc3c4 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -334,7 +334,6 @@ struct net_device struct net_device_stats* (*get_stats)(struct net_device *dev); - struct iw_statistics* (*get_wireless_stats)(struct net_device *dev); /* List of functions to handle Wireless Extensions (instead of ioctl). * See for details. Jean II */ diff --git a/include/linux/wireless.h b/include/linux/wireless.h index 13588564b42b04..a50a0130fd9eb0 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h @@ -1,7 +1,7 @@ /* * This file define a set of standard wireless extensions * - * Version : 20 17.2.06 + * Version : 21 14.3.06 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved. @@ -69,9 +69,14 @@ /***************************** INCLUDES *****************************/ +/* This header is used in user-space, therefore need to be sanitised + * for that purpose. Those includes are usually not compatible with glibc. + * To know which includes to use in user-space, check iwlib.h. */ +#ifdef __KERNEL__ #include /* for "caddr_t" et al */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ +#endif /* __KERNEL__ */ /***************************** VERSION *****************************/ /* @@ -80,7 +85,7 @@ * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ -#define WIRELESS_EXT 20 +#define WIRELESS_EXT 21 /* * Changes : @@ -208,6 +213,14 @@ * V19 to V20 * ---------- * - RtNetlink requests support (SET/GET) + * + * V20 to V21 + * ---------- + * - Remove (struct net_device *)->get_wireless_stats() + * - Change length in ESSID and NICK to strlen() instead of strlen()+1 + * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers + * - Power/Retry relative values no longer * 100000 + * - Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI */ /**************************** CONSTANTS ****************************/ @@ -448,6 +461,7 @@ #define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ #define IW_QUAL_LEVEL_INVALID 0x20 #define IW_QUAL_NOISE_INVALID 0x40 +#define IW_QUAL_RCPI 0x80 /* Level + Noise are 802.11k RCPI */ #define IW_QUAL_ALL_INVALID 0x70 /* Frequency flags */ @@ -500,10 +514,12 @@ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ -#define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ +#define IW_RETRY_MODIFIER 0x00FF /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ +#define IW_RETRY_SHORT 0x0010 /* Value is for short packets */ +#define IW_RETRY_LONG 0x0020 /* Value is for long packets */ /* Scanning request flags */ #define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ @@ -1017,7 +1033,7 @@ struct iw_range /* Note : this frequency list doesn't need to fit channel numbers, * because each entry contain its channel index */ - __u32 enc_capa; /* IW_ENC_CAPA_* bit field */ + __u32 enc_capa; /* IW_ENC_CAPA_* bit field */ }; /* diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 13472762b18b4c..f47f319bb7dc2a 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -344,8 +344,6 @@ static ssize_t wireless_show(struct class_device *cd, char *buf, if(dev->wireless_handlers && dev->wireless_handlers->get_wireless_stats) iw = dev->wireless_handlers->get_wireless_stats(dev); - else if (dev->get_wireless_stats) - iw = dev->get_wireless_stats(dev); if (iw != NULL) ret = (*format)(iw, buf); } @@ -465,8 +463,7 @@ int netdev_register_sysfs(struct net_device *net) *groups++ = &netstat_group; #ifdef WIRELESS_EXT - if (net->get_wireless_stats - || (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)) + if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats) *groups++ = &wireless_group; #endif diff --git a/net/core/wireless.c b/net/core/wireless.c index 3168fca312f7c4..ffff0da46c6ee2 100644 --- a/net/core/wireless.c +++ b/net/core/wireless.c @@ -68,6 +68,14 @@ * * v8 - 17.02.06 - Jean II * o RtNetlink requests support (SET/GET) + * + * v8b - 03.08.06 - Herbert Xu + * o Fix Wireless Event locking issues. + * + * v9 - 14.3.06 - Jean II + * o Change length in ESSID and NICK to strlen() instead of strlen()+1 + * o Make standard_ioctl_num and standard_event_num unsigned + * o Remove (struct net_device *)->get_wireless_stats() */ /***************************** INCLUDES *****************************/ @@ -234,24 +242,24 @@ static const struct iw_ioctl_description standard_ioctl[] = { [SIOCSIWESSID - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, - .max_tokens = IW_ESSID_MAX_SIZE + 1, + .max_tokens = IW_ESSID_MAX_SIZE, .flags = IW_DESCR_FLAG_EVENT, }, [SIOCGIWESSID - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, - .max_tokens = IW_ESSID_MAX_SIZE + 1, + .max_tokens = IW_ESSID_MAX_SIZE, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWNICKN - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, - .max_tokens = IW_ESSID_MAX_SIZE + 1, + .max_tokens = IW_ESSID_MAX_SIZE, }, [SIOCGIWNICKN - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, - .max_tokens = IW_ESSID_MAX_SIZE + 1, + .max_tokens = IW_ESSID_MAX_SIZE, }, [SIOCSIWRATE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, @@ -338,8 +346,8 @@ static const struct iw_ioctl_description standard_ioctl[] = { .max_tokens = sizeof(struct iw_pmksa), }, }; -static const int standard_ioctl_num = (sizeof(standard_ioctl) / - sizeof(struct iw_ioctl_description)); +static const unsigned standard_ioctl_num = (sizeof(standard_ioctl) / + sizeof(struct iw_ioctl_description)); /* * Meta-data about all the additional standard Wireless Extension events @@ -389,8 +397,8 @@ static const struct iw_ioctl_description standard_event[] = { .max_tokens = sizeof(struct iw_pmkid_cand), }, }; -static const int standard_event_num = (sizeof(standard_event) / - sizeof(struct iw_ioctl_description)); +static const unsigned standard_event_num = (sizeof(standard_event) / + sizeof(struct iw_ioctl_description)); /* Size (in bytes) of the various private data types */ static const char iw_priv_type_size[] = { @@ -465,17 +473,6 @@ static inline struct iw_statistics *get_wireless_stats(struct net_device *dev) (dev->wireless_handlers->get_wireless_stats != NULL)) return dev->wireless_handlers->get_wireless_stats(dev); - /* Old location, field to be removed in next WE */ - if(dev->get_wireless_stats) { - static int printed_message; - - if (!printed_message++) - printk(KERN_DEBUG "%s (WE) : Driver using old /proc/net/wireless support, please fix driver !\n", - dev->name); - - return dev->get_wireless_stats(dev); - } - /* Not found */ return (struct iw_statistics *) NULL; } @@ -1843,8 +1840,33 @@ int wireless_rtnetlink_set(struct net_device * dev, */ #ifdef WE_EVENT_RTNETLINK +/* ---------------------------------------------------------------- */ +/* + * Locking... + * ---------- + * + * Thanks to Herbert Xu for fixing + * the locking issue in here and implementing this code ! + * + * The issue : wireless_send_event() is often called in interrupt context, + * while the Netlink layer can never be called in interrupt context. + * The fully formed RtNetlink events are queued, and then a tasklet is run + * to feed those to Netlink. + * The skb_queue is interrupt safe, and its lock is not held while calling + * Netlink, so there is no possibility of dealock. + * Jean II + */ + static struct sk_buff_head wireless_nlevent_queue; +static int __init wireless_nlevent_init(void) +{ + skb_queue_head_init(&wireless_nlevent_queue); + return 0; +} + +subsys_initcall(wireless_nlevent_init); + static void wireless_nlevent_process(unsigned long data) { struct sk_buff *skb; @@ -1921,13 +1943,6 @@ static inline void rtmsg_iwinfo(struct net_device * dev, tasklet_schedule(&wireless_nlevent_tasklet); } -static int __init wireless_nlevent_init(void) -{ - skb_queue_head_init(&wireless_nlevent_queue); - return 0; -} - -subsys_initcall(wireless_nlevent_init); #endif /* WE_EVENT_RTNETLINK */ /* ---------------------------------------------------------------- */ -- cgit 1.2.3-korg