2.6.18-git9 wireless fixes break ipw2200 association to AP with WPA

From: Alessandro Suardi
Date: Fri Sep 29 2006 - 15:26:16 EST


Dell Latitude D610, FC5-latest, ipw2200 configured to associate
with a D-Link DSL-G604T (combo of router/ADSL modem/802.11g AP).

2.6.18-git8 (plus semaphore.h) is ok
-git9, -git10, -git11 fail to associate
-git11 with reverted wireless changes is ok

Attaching diff of what I reverted in -git11 to make it work again.

wpa_supplicant log of failing session available upon request.

Thanks, ciao,

--alessandro

"Well a man has two reasons for things that he does
the first one is pride and the second one is love
all understandings must come by this way"

(Husker Du, 'She Floated Away') diff -urN linux-2.6.18-git11/drivers/net/wireless/ipw2200.c linux-2.6.18-git11-oldwifi/drivers/net/wireless/ipw2200.c
--- linux-2.6.18-git11/drivers/net/wireless/ipw2200.c 2006-09-29 21:11:19.000000000 +0200
+++ linux-2.6.18-git11-oldwifi/drivers/net/wireless/ipw2200.c 2006-09-29 20:24:33.000000000 +0200
@@ -8875,6 +8875,8 @@
}

length = min((int)wrqu->essid.length, IW_ESSID_MAX_SIZE);
+ if (!extra[length - 1])
+ length--;

priv->config |= CFG_STATIC_ESSID;

@@ -8951,7 +8953,7 @@
struct ipw_priv *priv = ieee80211_priv(dev);
IPW_DEBUG_WX("Getting nick\n");
mutex_lock(&priv->mutex);
- wrqu->data.length = strlen(priv->nick);
+ wrqu->data.length = strlen(priv->nick) + 1;
memcpy(extra, priv->nick, wrqu->data.length);
wrqu->data.flags = 1; /* active */
mutex_unlock(&priv->mutex);
@@ -9274,9 +9276,9 @@
return -EINVAL;

mutex_lock(&priv->mutex);
- if (wrqu->retry.flags & IW_RETRY_SHORT)
+ if (wrqu->retry.flags & IW_RETRY_MIN)
priv->short_retry_limit = (u8) wrqu->retry.value;
- else if (wrqu->retry.flags & IW_RETRY_LONG)
+ else if (wrqu->retry.flags & IW_RETRY_MAX)
priv->long_retry_limit = (u8) wrqu->retry.value;
else {
priv->short_retry_limit = (u8) wrqu->retry.value;
@@ -9305,11 +9307,11 @@
return -EINVAL;
}

- if (wrqu->retry.flags & IW_RETRY_LONG) {
- wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
+ if (wrqu->retry.flags & IW_RETRY_MAX) {
+ wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
wrqu->retry.value = priv->long_retry_limit;
- } else if (wrqu->retry.flags & IW_RETRY_SHORT) {
- wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
+ } else if (wrqu->retry.flags & IW_RETRY_MIN) {
+ wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
wrqu->retry.value = priv->short_retry_limit;
} else {
wrqu->retry.flags = IW_RETRY_LIMIT;
diff -urN linux-2.6.18-git11/include/linux/netdevice.h linux-2.6.18-git11-oldwifi/include/linux/netdevice.h
--- linux-2.6.18-git11/include/linux/netdevice.h 2006-09-29 21:11:30.000000000 +0200
+++ linux-2.6.18-git11-oldwifi/include/linux/netdevice.h 2006-09-29 20:27:49.000000000 +0200
@@ -334,6 +334,7 @@


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 <net/iw_handler.h> for details. Jean II */
diff -urN linux-2.6.18-git11/net/core/net-sysfs.c linux-2.6.18-git11-oldwifi/net/core/net-sysfs.c
--- linux-2.6.18-git11/net/core/net-sysfs.c 2006-09-29 21:11:31.000000000 +0200
+++ linux-2.6.18-git11-oldwifi/net/core/net-sysfs.c 2006-09-29 20:24:34.000000000 +0200
@@ -344,6 +344,8 @@
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);
}
@@ -463,7 +465,8 @@
*groups++ = &netstat_group;

#ifdef WIRELESS_EXT
- if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
+ if (net->get_wireless_stats
+ || (net->wireless_handlers && net->wireless_handlers->get_wireless_stats))
*groups++ = &wireless_group;
#endif

diff -urN linux-2.6.18-git11/net/core/wireless.c linux-2.6.18-git11-oldwifi/net/core/wireless.c
--- linux-2.6.18-git11/net/core/wireless.c 2006-09-29 21:11:31.000000000 +0200
+++ linux-2.6.18-git11-oldwifi/net/core/wireless.c 2006-09-29 20:24:35.000000000 +0200
@@ -68,14 +68,6 @@
*
* 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 *****************************/
@@ -242,24 +234,24 @@
[SIOCSIWESSID - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
- .max_tokens = IW_ESSID_MAX_SIZE,
+ .max_tokens = IW_ESSID_MAX_SIZE + 1,
.flags = IW_DESCR_FLAG_EVENT,
},
[SIOCGIWESSID - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
- .max_tokens = IW_ESSID_MAX_SIZE,
+ .max_tokens = IW_ESSID_MAX_SIZE + 1,
.flags = IW_DESCR_FLAG_DUMP,
},
[SIOCSIWNICKN - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
- .max_tokens = IW_ESSID_MAX_SIZE,
+ .max_tokens = IW_ESSID_MAX_SIZE + 1,
},
[SIOCGIWNICKN - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
- .max_tokens = IW_ESSID_MAX_SIZE,
+ .max_tokens = IW_ESSID_MAX_SIZE + 1,
},
[SIOCSIWRATE - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
@@ -346,8 +338,8 @@
.max_tokens = sizeof(struct iw_pmksa),
},
};
-static const unsigned standard_ioctl_num = (sizeof(standard_ioctl) /
- sizeof(struct iw_ioctl_description));
+static const int standard_ioctl_num = (sizeof(standard_ioctl) /
+ sizeof(struct iw_ioctl_description));

/*
* Meta-data about all the additional standard Wireless Extension events
@@ -397,8 +389,8 @@
.max_tokens = sizeof(struct iw_pmkid_cand),
},
};
-static const unsigned standard_event_num = (sizeof(standard_event) /
- sizeof(struct iw_ioctl_description));
+static const int 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[] = {
@@ -473,6 +465,17 @@
(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;
}
@@ -1840,33 +1843,8 @@
*/

#ifdef WE_EVENT_RTNETLINK
-/* ---------------------------------------------------------------- */
-/*
- * Locking...
- * ----------
- *
- * Thanks to Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx> 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;
@@ -1943,6 +1921,13 @@
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 */

/* ---------------------------------------------------------------- */
diff -urN linux-2.6.18-git11/net/ieee80211/softmac/ieee80211softmac_wx.c linux-2.6.18-git11-oldwifi/net/ieee80211/softmac/ieee80211softmac_wx.c
--- linux-2.6.18-git11/net/ieee80211/softmac/ieee80211softmac_wx.c 2006-09-29 21:11:32.000000000 +0200
+++ linux-2.6.18-git11-oldwifi/net/ieee80211/softmac/ieee80211softmac_wx.c 2006-09-29 20:24:37.000000000 +0200
@@ -80,10 +80,10 @@
* If it's our network, ignore the change, we're already doing it!
*/
if((sm->associnfo.associating || sm->associated) &&
- (data->essid.flags && data->essid.length)) {
+ (data->essid.flags && data->essid.length && extra)) {
/* Get the associating network */
n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
- if(n && n->essid.len == data->essid.length &&
+ if(n && n->essid.len == (data->essid.length - 1) &&
!memcmp(n->essid.data, extra, n->essid.len)) {
dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n",
MAC_ARG(sm->associnfo.bssid));
@@ -109,8 +109,8 @@
sm->associnfo.static_essid = 0;
sm->associnfo.assoc_wait = 0;

- if (data->essid.flags && data->essid.length) {
- length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
+ if (data->essid.flags && data->essid.length && extra /*required?*/) {
+ length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE);
if (length) {
memcpy(sm->associnfo.req_essid.data, extra, length);
sm->associnfo.static_essid = 1;