ath9k: move ar9100 version checking macros into a more appropriate place
[safe/jmp/linux-2.6] / drivers / net / wireless / rndis_wlan.c
index c281c0b..82af21e 100644 (file)
 #include <linux/usb.h>
 #include <linux/usb/cdc.h>
 #include <linux/wireless.h>
+#include <linux/ieee80211.h>
 #include <linux/if_arp.h>
 #include <linux/ctype.h>
 #include <linux/spinlock.h>
 #include <net/iw_handler.h>
-#include <net/ieee80211.h>
 #include <linux/usb/usbnet.h>
 #include <linux/usb/rndis_host.h>
 
@@ -90,44 +90,44 @@ MODULE_PARM_DESC(workaround_interval,
 
 
 /* various RNDIS OID defs */
-#define OID_GEN_LINK_SPEED                     ccpu2(0x00010107)
-#define OID_GEN_RNDIS_CONFIG_PARAMETER         ccpu2(0x0001021b)
-
-#define OID_GEN_XMIT_OK                                ccpu2(0x00020101)
-#define OID_GEN_RCV_OK                         ccpu2(0x00020102)
-#define OID_GEN_XMIT_ERROR                     ccpu2(0x00020103)
-#define OID_GEN_RCV_ERROR                      ccpu2(0x00020104)
-#define OID_GEN_RCV_NO_BUFFER                  ccpu2(0x00020105)
-
-#define OID_802_3_PERMANENT_ADDRESS            ccpu2(0x01010101)
-#define OID_802_3_CURRENT_ADDRESS              ccpu2(0x01010102)
-#define OID_802_3_MULTICAST_LIST               ccpu2(0x01010103)
-#define OID_802_3_MAXIMUM_LIST_SIZE            ccpu2(0x01010104)
-
-#define OID_802_11_BSSID                       ccpu2(0x0d010101)
-#define OID_802_11_SSID                                ccpu2(0x0d010102)
-#define OID_802_11_INFRASTRUCTURE_MODE         ccpu2(0x0d010108)
-#define OID_802_11_ADD_WEP                     ccpu2(0x0d010113)
-#define OID_802_11_REMOVE_WEP                  ccpu2(0x0d010114)
-#define OID_802_11_DISASSOCIATE                        ccpu2(0x0d010115)
-#define OID_802_11_AUTHENTICATION_MODE         ccpu2(0x0d010118)
-#define OID_802_11_PRIVACY_FILTER              ccpu2(0x0d010119)
-#define OID_802_11_BSSID_LIST_SCAN             ccpu2(0x0d01011a)
-#define OID_802_11_ENCRYPTION_STATUS           ccpu2(0x0d01011b)
-#define OID_802_11_ADD_KEY                     ccpu2(0x0d01011d)
-#define OID_802_11_REMOVE_KEY                  ccpu2(0x0d01011e)
-#define OID_802_11_ASSOCIATION_INFORMATION     ccpu2(0x0d01011f)
-#define OID_802_11_PMKID                       ccpu2(0x0d010123)
-#define OID_802_11_NETWORK_TYPES_SUPPORTED     ccpu2(0x0d010203)
-#define OID_802_11_NETWORK_TYPE_IN_USE         ccpu2(0x0d010204)
-#define OID_802_11_TX_POWER_LEVEL              ccpu2(0x0d010205)
-#define OID_802_11_RSSI                                ccpu2(0x0d010206)
-#define OID_802_11_RSSI_TRIGGER                        ccpu2(0x0d010207)
-#define OID_802_11_FRAGMENTATION_THRESHOLD     ccpu2(0x0d010209)
-#define OID_802_11_RTS_THRESHOLD               ccpu2(0x0d01020a)
-#define OID_802_11_SUPPORTED_RATES             ccpu2(0x0d01020e)
-#define OID_802_11_CONFIGURATION               ccpu2(0x0d010211)
-#define OID_802_11_BSSID_LIST                  ccpu2(0x0d010217)
+#define OID_GEN_LINK_SPEED                     cpu_to_le32(0x00010107)
+#define OID_GEN_RNDIS_CONFIG_PARAMETER         cpu_to_le32(0x0001021b)
+
+#define OID_GEN_XMIT_OK                                cpu_to_le32(0x00020101)
+#define OID_GEN_RCV_OK                         cpu_to_le32(0x00020102)
+#define OID_GEN_XMIT_ERROR                     cpu_to_le32(0x00020103)
+#define OID_GEN_RCV_ERROR                      cpu_to_le32(0x00020104)
+#define OID_GEN_RCV_NO_BUFFER                  cpu_to_le32(0x00020105)
+
+#define OID_802_3_PERMANENT_ADDRESS            cpu_to_le32(0x01010101)
+#define OID_802_3_CURRENT_ADDRESS              cpu_to_le32(0x01010102)
+#define OID_802_3_MULTICAST_LIST               cpu_to_le32(0x01010103)
+#define OID_802_3_MAXIMUM_LIST_SIZE            cpu_to_le32(0x01010104)
+
+#define OID_802_11_BSSID                       cpu_to_le32(0x0d010101)
+#define OID_802_11_SSID                                cpu_to_le32(0x0d010102)
+#define OID_802_11_INFRASTRUCTURE_MODE         cpu_to_le32(0x0d010108)
+#define OID_802_11_ADD_WEP                     cpu_to_le32(0x0d010113)
+#define OID_802_11_REMOVE_WEP                  cpu_to_le32(0x0d010114)
+#define OID_802_11_DISASSOCIATE                        cpu_to_le32(0x0d010115)
+#define OID_802_11_AUTHENTICATION_MODE         cpu_to_le32(0x0d010118)
+#define OID_802_11_PRIVACY_FILTER              cpu_to_le32(0x0d010119)
+#define OID_802_11_BSSID_LIST_SCAN             cpu_to_le32(0x0d01011a)
+#define OID_802_11_ENCRYPTION_STATUS           cpu_to_le32(0x0d01011b)
+#define OID_802_11_ADD_KEY                     cpu_to_le32(0x0d01011d)
+#define OID_802_11_REMOVE_KEY                  cpu_to_le32(0x0d01011e)
+#define OID_802_11_ASSOCIATION_INFORMATION     cpu_to_le32(0x0d01011f)
+#define OID_802_11_PMKID                       cpu_to_le32(0x0d010123)
+#define OID_802_11_NETWORK_TYPES_SUPPORTED     cpu_to_le32(0x0d010203)
+#define OID_802_11_NETWORK_TYPE_IN_USE         cpu_to_le32(0x0d010204)
+#define OID_802_11_TX_POWER_LEVEL              cpu_to_le32(0x0d010205)
+#define OID_802_11_RSSI                                cpu_to_le32(0x0d010206)
+#define OID_802_11_RSSI_TRIGGER                        cpu_to_le32(0x0d010207)
+#define OID_802_11_FRAGMENTATION_THRESHOLD     cpu_to_le32(0x0d010209)
+#define OID_802_11_RTS_THRESHOLD               cpu_to_le32(0x0d01020a)
+#define OID_802_11_SUPPORTED_RATES             cpu_to_le32(0x0d01020e)
+#define OID_802_11_CONFIGURATION               cpu_to_le32(0x0d010211)
+#define OID_802_11_BSSID_LIST                  cpu_to_le32(0x0d010217)
 
 
 /* Typical noise/maximum signal level values taken from ndiswrapper iw_ndis.h */
@@ -144,8 +144,8 @@ MODULE_PARM_DESC(workaround_interval,
 
 
 /* codes for "status" field of completion messages */
-#define RNDIS_STATUS_ADAPTER_NOT_READY         ccpu2(0xc0010011)
-#define RNDIS_STATUS_ADAPTER_NOT_OPEN          ccpu2(0xc0010012)
+#define RNDIS_STATUS_ADAPTER_NOT_READY         cpu_to_le32(0xc0010011)
+#define RNDIS_STATUS_ADAPTER_NOT_OPEN          cpu_to_le32(0xc0010012)
 
 
 /* NDIS data structures. Taken from wpa_supplicant driver_ndis.c
@@ -314,6 +314,8 @@ enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
 #define WORK_LINK_DOWN         (1<<1)
 #define WORK_SET_MULTICAST_LIST        (1<<2)
 
+#define COMMAND_BUFFER_SIZE    (CONTROL_BUFFER_SIZE + sizeof(struct rndis_set))
+
 /* RNDIS device private data */
 struct rndis_wext_private {
        char name[32];
@@ -362,11 +364,10 @@ struct rndis_wext_private {
        u8  *wpa_ie;
        int  wpa_cipher_pair;
        int  wpa_cipher_group;
-};
 
+       u8 command_buffer[COMMAND_BUFFER_SIZE];
+};
 
-static const int freq_chan[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
-                               2447, 2452, 2457, 2462, 2467, 2472, 2484 };
 
 static const int rates_80211g[8] = { 6, 9, 12, 18, 24, 36, 48, 54 };
 
@@ -428,18 +429,23 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
        buflen = *len + sizeof(*u.get);
        if (buflen < CONTROL_BUFFER_SIZE)
                buflen = CONTROL_BUFFER_SIZE;
-       u.buf = kmalloc(buflen, GFP_KERNEL);
-       if (!u.buf)
-               return -ENOMEM;
+
+       if (buflen > COMMAND_BUFFER_SIZE) {
+               u.buf = kmalloc(buflen, GFP_KERNEL);
+               if (!u.buf)
+                       return -ENOMEM;
+       } else {
+               u.buf = priv->command_buffer;
+       }
+
+       mutex_lock(&priv->command_lock);
+
        memset(u.get, 0, sizeof *u.get);
        u.get->msg_type = RNDIS_MSG_QUERY;
-       u.get->msg_len = ccpu2(sizeof *u.get);
+       u.get->msg_len = cpu_to_le32(sizeof *u.get);
        u.get->oid = oid;
 
-       mutex_lock(&priv->command_lock);
-       ret = rndis_command(dev, u.header);
-       mutex_unlock(&priv->command_lock);
-
+       ret = rndis_command(dev, u.header, buflen);
        if (ret == 0) {
                ret = le32_to_cpu(u.get_c->len);
                *len = (*len > ret) ? ret : *len;
@@ -447,7 +453,10 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
                ret = rndis_error_status(u.get_c->status);
        }
 
-       kfree(u.buf);
+       mutex_unlock(&priv->command_lock);
+
+       if (u.buf != priv->command_buffer)
+               kfree(u.buf);
        return ret;
 }
 
@@ -466,27 +475,34 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
        buflen = len + sizeof(*u.set);
        if (buflen < CONTROL_BUFFER_SIZE)
                buflen = CONTROL_BUFFER_SIZE;
-       u.buf = kmalloc(buflen, GFP_KERNEL);
-       if (!u.buf)
-               return -ENOMEM;
+
+       if (buflen > COMMAND_BUFFER_SIZE) {
+               u.buf = kmalloc(buflen, GFP_KERNEL);
+               if (!u.buf)
+                       return -ENOMEM;
+       } else {
+               u.buf = priv->command_buffer;
+       }
+
+       mutex_lock(&priv->command_lock);
 
        memset(u.set, 0, sizeof *u.set);
        u.set->msg_type = RNDIS_MSG_SET;
        u.set->msg_len = cpu_to_le32(sizeof(*u.set) + len);
        u.set->oid = oid;
        u.set->len = cpu_to_le32(len);
-       u.set->offset = ccpu2(sizeof(*u.set) - 8);
-       u.set->handle = ccpu2(0);
+       u.set->offset = cpu_to_le32(sizeof(*u.set) - 8);
+       u.set->handle = cpu_to_le32(0);
        memcpy(u.buf + sizeof(*u.set), data, len);
 
-       mutex_lock(&priv->command_lock);
-       ret = rndis_command(dev, u.header);
-       mutex_unlock(&priv->command_lock);
-
+       ret = rndis_command(dev, u.header, buflen);
        if (ret == 0)
                ret = rndis_error_status(u.set_c->status);
 
-       kfree(u.buf);
+       mutex_unlock(&priv->command_lock);
+
+       if (u.buf != priv->command_buffer)
+               kfree(u.buf);
        return ret;
 }
 
@@ -621,9 +637,8 @@ static void dsconfig_to_freq(unsigned int dsconfig, struct iw_freq *freq)
 static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig)
 {
        if (freq->m < 1000 && freq->e == 0) {
-               if (freq->m >= 1 &&
-                       freq->m <= (sizeof(freq_chan) / sizeof(freq_chan[0])))
-                       *dsconfig = freq_chan[freq->m - 1] * 1000;
+               if (freq->m >= 1 && freq->m <= 14)
+                       *dsconfig = ieee80211_dsss_chan_to_freq(freq->m) * 1000;
                else
                        return -1;
        } else {
@@ -1086,7 +1101,7 @@ static int rndis_iw_get_range(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
        struct iw_range *range = (struct iw_range *)extra;
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
        int len, ret, i, j, num, has_80211g_rates;
        u8 rates[8];
@@ -1160,12 +1175,11 @@ static int rndis_iw_get_range(struct net_device *dev,
                range->throughput = 11 * 1000 * 1000 / 2;
        }
 
-       range->num_channels = (sizeof(freq_chan)/sizeof(freq_chan[0]));
+       range->num_channels = 14;
 
-       for (i = 0; i < (sizeof(freq_chan)/sizeof(freq_chan[0])) &&
-                       i < IW_MAX_FREQUENCIES; i++) {
+       for (i = 0; (i < 14) && (i < IW_MAX_FREQUENCIES); i++) {
                range->freq[i].i = i + 1;
-               range->freq[i].m = freq_chan[i] * 100000;
+               range->freq[i].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000;
                range->freq[i].e = 1;
        }
        range->num_frequency = i;
@@ -1193,7 +1207,7 @@ static int rndis_iw_get_range(struct net_device *dev,
 static int rndis_iw_get_name(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
 
        strcpy(wrqu->name, priv->name);
@@ -1206,7 +1220,7 @@ static int rndis_iw_set_essid(struct net_device *dev,
 {
        struct ndis_80211_ssid ssid;
        int length = wrqu->essid.length;
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
 
        devdbg(usbdev, "SIOCSIWESSID: [flags:%d,len:%d] '%.32s'",
                wrqu->essid.flags, wrqu->essid.length, essid);
@@ -1233,7 +1247,7 @@ static int rndis_iw_get_essid(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
 {
        struct ndis_80211_ssid ssid;
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        int ret;
 
        ret = get_essid(usbdev, &ssid);
@@ -1256,15 +1270,14 @@ static int rndis_iw_get_essid(struct net_device *dev,
 static int rndis_iw_get_bssid(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        unsigned char bssid[ETH_ALEN];
        int ret;
-       DECLARE_MAC_BUF(mac);
 
        ret = get_bssid(usbdev, bssid);
 
        if (ret == 0)
-               devdbg(usbdev, "SIOCGIWAP: %s", print_mac(mac, bssid));
+               devdbg(usbdev, "SIOCGIWAP: %pM", bssid);
        else
                devdbg(usbdev, "SIOCGIWAP: <not associated>");
 
@@ -1278,12 +1291,11 @@ static int rndis_iw_get_bssid(struct net_device *dev,
 static int rndis_iw_set_bssid(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        u8 *bssid = (u8 *)wrqu->ap_addr.sa_data;
-       DECLARE_MAC_BUF(mac);
        int ret;
 
-       devdbg(usbdev, "SIOCSIWAP: %s", print_mac(mac, bssid));
+       devdbg(usbdev, "SIOCSIWAP: %pM", bssid);
 
        ret = rndis_set_oid(usbdev, OID_802_11_BSSID, bssid, ETH_ALEN);
 
@@ -1301,7 +1313,7 @@ static int rndis_iw_set_auth(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
        struct iw_param *p = &wrqu->param;
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
        int ret = -ENOTSUPP;
 
@@ -1382,7 +1394,7 @@ static int rndis_iw_get_auth(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
        struct iw_param *p = &wrqu->param;
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
 
        switch (p->flags & IW_AUTH_INDEX) {
@@ -1414,7 +1426,7 @@ static int rndis_iw_get_mode(struct net_device *dev,
                                struct iw_request_info *info,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
 
        switch (priv->infra_mode) {
@@ -1437,7 +1449,7 @@ static int rndis_iw_get_mode(struct net_device *dev,
 static int rndis_iw_set_mode(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        int mode;
 
        devdbg(usbdev, "SIOCSIWMODE: %08x", wrqu->mode);
@@ -1462,7 +1474,7 @@ static int rndis_iw_set_mode(struct net_device *dev,
 static int rndis_iw_set_encode(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
        int ret, index, key_len;
        u8 *key;
@@ -1525,7 +1537,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
        struct ndis_80211_key ndis_key;
        int keyidx, ret;
@@ -1610,16 +1622,15 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
 static int rndis_iw_set_scan(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct iw_param *param = &wrqu->param;
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        union iwreq_data evt;
        int ret = -EINVAL;
        __le32 tmp;
 
        devdbg(usbdev, "SIOCSIWSCAN");
 
-       if (param->flags == 0) {
-               tmp = ccpu2(1);
+       if (wrqu->data.flags == 0) {
+               tmp = cpu_to_le32(1);
                ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
                                                                sizeof(tmp));
                evt.data.flags = 0;
@@ -1631,33 +1642,32 @@ static int rndis_iw_set_scan(struct net_device *dev,
 
 
 static char *rndis_translate_scan(struct net_device *dev,
-    char *cev, char *end_buf, struct ndis_80211_bssid_ex *bssid)
+                                 struct iw_request_info *info, char *cev,
+                                 char *end_buf,
+                                 struct ndis_80211_bssid_ex *bssid)
 {
-#ifdef DEBUG
-       struct usbnet *usbdev = dev->priv;
-#endif
-       struct ieee80211_info_element *ie;
+       struct usbnet *usbdev = netdev_priv(dev);
+       u8 *ie;
        char *current_val;
        int bssid_len, ie_len, i;
        u32 beacon, atim;
        struct iw_event iwe;
        unsigned char sbuf[32];
-       DECLARE_MAC_BUF(mac);
 
        bssid_len = le32_to_cpu(bssid->length);
 
-       devdbg(usbdev, "BSSID %s", print_mac(mac, bssid->mac));
+       devdbg(usbdev, "BSSID %pM", bssid->mac);
        iwe.cmd = SIOCGIWAP;
        iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
        memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN);
-       cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN);
+       cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_ADDR_LEN);
 
        devdbg(usbdev, "SSID(%d) %s", le32_to_cpu(bssid->ssid.length),
                                                bssid->ssid.essid);
        iwe.cmd = SIOCGIWESSID;
        iwe.u.essid.length = le32_to_cpu(bssid->ssid.length);
        iwe.u.essid.flags = 1;
-       cev = iwe_stream_add_point(cev, end_buf, &iwe, bssid->ssid.essid);
+       cev = iwe_stream_add_point(info, cev, end_buf, &iwe, bssid->ssid.essid);
 
        devdbg(usbdev, "MODE %d", le32_to_cpu(bssid->net_infra));
        iwe.cmd = SIOCGIWMODE;
@@ -1673,12 +1683,12 @@ static char *rndis_translate_scan(struct net_device *dev,
                iwe.u.mode = IW_MODE_AUTO;
                break;
        }
-       cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN);
+       cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_UINT_LEN);
 
        devdbg(usbdev, "FREQ %d kHz", le32_to_cpu(bssid->config.ds_config));
        iwe.cmd = SIOCGIWFREQ;
        dsconfig_to_freq(le32_to_cpu(bssid->config.ds_config), &iwe.u.freq);
-       cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN);
+       cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_FREQ_LEN);
 
        devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->rssi));
        iwe.cmd = IWEVQUAL;
@@ -1687,7 +1697,7 @@ static char *rndis_translate_scan(struct net_device *dev,
        iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
                        | IW_QUAL_LEVEL_UPDATED
                        | IW_QUAL_NOISE_INVALID;
-       cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN);
+       cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_QUAL_LEN);
 
        devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->privacy));
        iwe.cmd = SIOCGIWENCODE;
@@ -1697,10 +1707,10 @@ static char *rndis_translate_scan(struct net_device *dev,
        else
                iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
 
-       cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL);
+       cev = iwe_stream_add_point(info, cev, end_buf, &iwe, NULL);
 
        devdbg(usbdev, "RATES:");
-       current_val = cev + IW_EV_LCP_LEN;
+       current_val = cev + iwe_stream_lcp_len(info);
        iwe.cmd = SIOCGIWRATE;
        for (i = 0; i < sizeof(bssid->rates); i++) {
                if (bssid->rates[i] & 0x7f) {
@@ -1708,13 +1718,13 @@ static char *rndis_translate_scan(struct net_device *dev,
                                ((bssid->rates[i] & 0x7f) *
                                500000);
                        devdbg(usbdev, " %d", iwe.u.bitrate.value);
-                       current_val = iwe_stream_add_value(cev,
+                       current_val = iwe_stream_add_value(info, cev,
                                current_val, end_buf, &iwe,
                                IW_EV_PARAM_LEN);
                }
        }
 
-       if ((current_val - cev) > IW_EV_LCP_LEN)
+       if ((current_val - cev) > iwe_stream_lcp_len(info))
                cev = current_val;
 
        beacon = le32_to_cpu(bssid->config.beacon_period);
@@ -1722,33 +1732,33 @@ static char *rndis_translate_scan(struct net_device *dev,
        iwe.cmd = IWEVCUSTOM;
        snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon);
        iwe.u.data.length = strlen(sbuf);
-       cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf);
+       cev = iwe_stream_add_point(info, cev, end_buf, &iwe, sbuf);
 
        atim = le32_to_cpu(bssid->config.atim_window);
        devdbg(usbdev, "ATIM %d", atim);
        iwe.cmd = IWEVCUSTOM;
        snprintf(sbuf, sizeof(sbuf), "atim=%u", atim);
        iwe.u.data.length = strlen(sbuf);
-       cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf);
+       cev = iwe_stream_add_point(info, cev, end_buf, &iwe, sbuf);
 
        ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies));
        ie_len = min(bssid_len - (int)sizeof(*bssid),
                                        (int)le32_to_cpu(bssid->ie_length));
        ie_len -= sizeof(struct ndis_80211_fixed_ies);
-       while (ie_len >= sizeof(*ie) && sizeof(*ie) + ie->len <= ie_len) {
-               if ((ie->id == MFIE_TYPE_GENERIC && ie->len >= 4 &&
-                               memcmp(ie->data, "\x00\x50\xf2\x01", 4) == 0) ||
-                               ie->id == MFIE_TYPE_RSN) {
+       while (ie_len >= 2 && 2 + ie[1] <= ie_len) {
+               if ((ie[0] == WLAN_EID_GENERIC && ie[1] >= 4 &&
+                    memcmp(ie + 2, "\x00\x50\xf2\x01", 4) == 0) ||
+                   ie[0] == WLAN_EID_RSN) {
                        devdbg(usbdev, "IE: WPA%d",
-                                       (ie->id == MFIE_TYPE_RSN) ? 2 : 1);
+                                       (ie[0] == WLAN_EID_RSN) ? 2 : 1);
                        iwe.cmd = IWEVGENIE;
-                       iwe.u.data.length = min(ie->len + 2, MAX_WPA_IE_LEN);
-                       cev = iwe_stream_add_point(cev, end_buf, &iwe,
-                                                               (u8 *)ie);
+                       /* arbitrary cut-off at 64 */
+                       iwe.u.data.length = min(ie[1] + 2, 64);
+                       cev = iwe_stream_add_point(info, cev, end_buf, &iwe, ie);
                }
 
-               ie_len -= sizeof(*ie) + ie->len;
-               ie = (struct ieee80211_info_element *)&ie->data[ie->len];
+               ie_len -= 2 + ie[1];
+               ie += 2 + ie[1];
        }
 
        return cev;
@@ -1758,7 +1768,7 @@ static char *rndis_translate_scan(struct net_device *dev,
 static int rndis_iw_get_scan(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        void *buf = NULL;
        char *cev = extra;
        struct ndis_80211_bssid_list_ex *bssid_list;
@@ -1786,8 +1796,8 @@ static int rndis_iw_get_scan(struct net_device *dev,
        devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count);
 
        while (count && ((void *)bssid + bssid_len) <= (buf + len)) {
-               cev = rndis_translate_scan(dev, cev, extra + IW_SCAN_MAX_DATA,
-                                                                       bssid);
+               cev = rndis_translate_scan(dev, info, cev,
+                                          extra + IW_SCAN_MAX_DATA, bssid);
                bssid = (void *)bssid + bssid_len;
                bssid_len = le32_to_cpu(bssid->length);
                count--;
@@ -1804,7 +1814,7 @@ out:
 static int rndis_iw_set_genie(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
        int ret = 0;
 
@@ -1838,7 +1848,7 @@ static int rndis_iw_set_genie(struct net_device *dev,
 static int rndis_iw_get_genie(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
 
        devdbg(usbdev, "SIOCGIWGENIE");
@@ -1861,7 +1871,7 @@ static int rndis_iw_get_genie(struct net_device *dev,
 static int rndis_iw_set_rts(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        __le32 tmp;
        devdbg(usbdev, "SIOCSIWRTS");
 
@@ -1874,7 +1884,7 @@ static int rndis_iw_set_rts(struct net_device *dev,
 static int rndis_iw_get_rts(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        __le32 tmp;
        int len, ret;
 
@@ -1895,7 +1905,7 @@ static int rndis_iw_get_rts(struct net_device *dev,
 static int rndis_iw_set_frag(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        __le32 tmp;
 
        devdbg(usbdev, "SIOCSIWFRAG");
@@ -1909,7 +1919,7 @@ static int rndis_iw_set_frag(struct net_device *dev,
 static int rndis_iw_get_frag(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        __le32 tmp;
        int len, ret;
 
@@ -1929,7 +1939,7 @@ static int rndis_iw_get_frag(struct net_device *dev,
 static int rndis_iw_set_nick(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
 
        devdbg(usbdev, "SIOCSIWNICK");
@@ -1946,7 +1956,7 @@ static int rndis_iw_set_nick(struct net_device *dev,
 static int rndis_iw_get_nick(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
 
        wrqu->data.flags = 1;
@@ -1962,7 +1972,7 @@ static int rndis_iw_get_nick(struct net_device *dev,
 static int rndis_iw_set_freq(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct ndis_80211_conf config;
        unsigned int dsconfig;
        int len, ret;
@@ -1993,7 +2003,7 @@ static int rndis_iw_set_freq(struct net_device *dev,
 static int rndis_iw_get_freq(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct ndis_80211_conf config;
        int len, ret;
 
@@ -2010,7 +2020,7 @@ static int rndis_iw_get_freq(struct net_device *dev,
 static int rndis_iw_get_txpower(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
        __le32 tx_power;
        int ret = 0, len;
@@ -2044,7 +2054,7 @@ static int rndis_iw_get_txpower(struct net_device *dev,
 static int rndis_iw_set_txpower(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
        __le32 tx_power = 0;
        int ret = 0;
@@ -2096,7 +2106,7 @@ static int rndis_iw_set_txpower(struct net_device *dev,
 static int rndis_iw_get_rate(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        __le32 tmp;
        int ret, len;
 
@@ -2114,7 +2124,7 @@ static int rndis_iw_get_rate(struct net_device *dev,
 static int rndis_iw_set_mlme(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
        struct iw_mlme *mlme = (struct iw_mlme *)extra;
        unsigned char bssid[ETH_ALEN];
@@ -2139,7 +2149,7 @@ static int rndis_iw_set_mlme(struct net_device *dev,
 
 static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
        unsigned long flags;
 
@@ -2269,16 +2279,19 @@ get_bssid:
 
 static void rndis_wext_set_multicast_list(struct net_device *dev)
 {
-       struct usbnet *usbdev = dev->priv;
+       struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
 
+       if (test_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending))
+               return;
+
        set_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending);
        queue_work(priv->workqueue, &priv->work);
 }
 
-static void rndis_wext_link_change(struct usbnet *dev, int state)
+static void rndis_wext_link_change(struct usbnet *usbdev, int state)
 {
-       struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
+       struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
 
        /* queue work to avoid recursive calls into rndis_command */
        set_bit(state ? WORK_LINK_UP : WORK_LINK_DOWN, &priv->work_pending);
@@ -2286,7 +2299,7 @@ static void rndis_wext_link_change(struct usbnet *dev, int state)
 }
 
 
-static int rndis_wext_get_caps(struct usbnet *dev)
+static int rndis_wext_get_caps(struct usbnet *usbdev)
 {
        struct {
                __le32  num_items;
@@ -2294,18 +2307,18 @@ static int rndis_wext_get_caps(struct usbnet *dev)
        } networks_supported;
        int len, retval, i, n;
        __le32 tx_power;
-       struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
+       struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
 
        /* determine if supports setting txpower */
        len = sizeof(tx_power);
-       retval = rndis_query_oid(dev, OID_802_11_TX_POWER_LEVEL, &tx_power,
-                                                               &len);
+       retval = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL, &tx_power,
+                                                                       &len);
        if (retval == 0 && le32_to_cpu(tx_power) != 0xFF)
                priv->caps |= CAP_SUPPORT_TXPOWER;
 
        /* determine supported modes */
        len = sizeof(networks_supported);
-       retval = rndis_query_oid(dev, OID_802_11_NETWORK_TYPES_SUPPORTED,
+       retval = rndis_query_oid(usbdev, OID_802_11_NETWORK_TYPES_SUPPORTED,
                                                &networks_supported, &len);
        if (retval >= 0) {
                n = le32_to_cpu(networks_supported.num_items);
@@ -2415,7 +2428,7 @@ static void rndis_update_wireless_stats(struct work_struct *work)
                /* Send scan OID. Use of both OIDs is required to get device
                 * working.
                 */
-               tmp = ccpu2(1);
+               tmp = cpu_to_le32(1);
                rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
                                                                sizeof(tmp));
 
@@ -2444,9 +2457,9 @@ end:
 }
 
 
-static int bcm4320_early_init(struct usbnet *dev)
+static int bcm4320_early_init(struct usbnet *usbdev)
 {
-       struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
+       struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
        char buf[8];
 
        /* Early initialization settings, setting these won't have effect
@@ -2494,51 +2507,48 @@ static int bcm4320_early_init(struct usbnet *dev)
        else
                priv->param_workaround_interval = modparam_workaround_interval;
 
-       rndis_set_config_parameter_str(dev, "Country", priv->param_country);
-       rndis_set_config_parameter_str(dev, "FrameBursting",
+       rndis_set_config_parameter_str(usbdev, "Country", priv->param_country);
+       rndis_set_config_parameter_str(usbdev, "FrameBursting",
                                        priv->param_frameburst ? "1" : "0");
-       rndis_set_config_parameter_str(dev, "Afterburner",
+       rndis_set_config_parameter_str(usbdev, "Afterburner",
                                        priv->param_afterburner ? "1" : "0");
        sprintf(buf, "%d", priv->param_power_save);
-       rndis_set_config_parameter_str(dev, "PowerSaveMode", buf);
+       rndis_set_config_parameter_str(usbdev, "PowerSaveMode", buf);
        sprintf(buf, "%d", priv->param_power_output);
-       rndis_set_config_parameter_str(dev, "PwrOut", buf);
+       rndis_set_config_parameter_str(usbdev, "PwrOut", buf);
        sprintf(buf, "%d", priv->param_roamtrigger);
-       rndis_set_config_parameter_str(dev, "RoamTrigger", buf);
+       rndis_set_config_parameter_str(usbdev, "RoamTrigger", buf);
        sprintf(buf, "%d", priv->param_roamdelta);
-       rndis_set_config_parameter_str(dev, "RoamDelta", buf);
+       rndis_set_config_parameter_str(usbdev, "RoamDelta", buf);
 
        return 0;
 }
 
 
-static int rndis_wext_bind(struct usbnet *dev, struct usb_interface *intf)
+static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
 {
-       struct net_device *net = dev->net;
        struct rndis_wext_private *priv;
        int retval, len;
        __le32 tmp;
 
        /* allocate rndis private data */
-       priv = kmalloc(sizeof(struct rndis_wext_private), GFP_KERNEL);
+       priv = kzalloc(sizeof(struct rndis_wext_private), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
        /* These have to be initialized before calling generic_rndis_bind().
         * Otherwise we'll be in big trouble in rndis_wext_early_init().
         */
-       dev->driver_priv = priv;
-       memset(priv, 0, sizeof(*priv));
-       memset(priv->name, 0, sizeof(priv->name));
+       usbdev->driver_priv = priv;
        strcpy(priv->name, "IEEE802.11");
-       net->wireless_handlers = &rndis_iw_handlers;
-       priv->usbdev = dev;
+       usbdev->net->wireless_handlers = &rndis_iw_handlers;
+       priv->usbdev = usbdev;
 
        mutex_init(&priv->command_lock);
        spin_lock_init(&priv->stats_lock);
 
        /* try bind rndis_host */
-       retval = generic_rndis_bind(dev, intf, FLAG_RNDIS_PHYM_WIRELESS);
+       retval = generic_rndis_bind(usbdev, intf, FLAG_RNDIS_PHYM_WIRELESS);
        if (retval < 0)
                goto fail;
 
@@ -2549,20 +2559,21 @@ static int rndis_wext_bind(struct usbnet *dev, struct usb_interface *intf)
         * rndis_host wants to avoid all OID as much as possible
         * so do promisc/multicast handling in rndis_wext.
         */
-       dev->net->set_multicast_list = rndis_wext_set_multicast_list;
+       usbdev->net->set_multicast_list = rndis_wext_set_multicast_list;
        tmp = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST;
-       retval = rndis_set_oid(dev, OID_GEN_CURRENT_PACKET_FILTER, &tmp,
+       retval = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &tmp,
                                                                sizeof(tmp));
 
        len = sizeof(tmp);
-       retval = rndis_query_oid(dev, OID_802_3_MAXIMUM_LIST_SIZE, &tmp, &len);
+       retval = rndis_query_oid(usbdev, OID_802_3_MAXIMUM_LIST_SIZE, &tmp,
+                                                               &len);
        priv->multicast_size = le32_to_cpu(tmp);
        if (retval < 0 || priv->multicast_size < 0)
                priv->multicast_size = 0;
        if (priv->multicast_size > 0)
-               dev->net->flags |= IFF_MULTICAST;
+               usbdev->net->flags |= IFF_MULTICAST;
        else
-               dev->net->flags &= ~IFF_MULTICAST;
+               usbdev->net->flags &= ~IFF_MULTICAST;
 
        priv->iwstats.qual.qual = 0;
        priv->iwstats.qual.level = 0;
@@ -2572,13 +2583,13 @@ static int rndis_wext_bind(struct usbnet *dev, struct usb_interface *intf)
                                        | IW_QUAL_QUAL_INVALID
                                        | IW_QUAL_LEVEL_INVALID;
 
-       rndis_wext_get_caps(dev);
-       set_default_iw_params(dev);
+       rndis_wext_get_caps(usbdev);
+       set_default_iw_params(usbdev);
 
        /* turn radio on */
        priv->radio_on = 1;
-       disassociate(dev, 1);
-       netif_carrier_off(dev->net);
+       disassociate(usbdev, 1);
+       netif_carrier_off(usbdev->net);
 
        /* because rndis_command() sleeps we need to use workqueue */
        priv->workqueue = create_singlethread_workqueue("rndis_wlan");
@@ -2595,12 +2606,12 @@ fail:
 }
 
 
-static void rndis_wext_unbind(struct usbnet *dev, struct usb_interface *intf)
+static void rndis_wext_unbind(struct usbnet *usbdev, struct usb_interface *intf)
 {
-       struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
+       struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
 
        /* turn radio off */
-       disassociate(dev, 0);
+       disassociate(usbdev, 0);
 
        cancel_delayed_work_sync(&priv->stats_work);
        cancel_work_sync(&priv->work);
@@ -2611,13 +2622,13 @@ static void rndis_wext_unbind(struct usbnet *dev, struct usb_interface *intf)
                kfree(priv->wpa_ie);
        kfree(priv);
 
-       rndis_unbind(dev, intf);
+       rndis_unbind(usbdev, intf);
 }
 
 
-static int rndis_wext_reset(struct usbnet *dev)
+static int rndis_wext_reset(struct usbnet *usbdev)
 {
-       return deauthenticate(dev);
+       return deauthenticate(usbdev);
 }