iwlagn: use sku capabilities information from EEPROM
[linux-2.6.git] / drivers / net / wireless / airo.c
index efb7444..55cf71f 100644 (file)
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <asm/uaccess.h>
-#include <net/ieee80211.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
+#include <linux/ieee80211.h>
+#include <net/iw_handler.h>
+
 #include "airo.h"
 
 #define DRV_NAME "airo"
 
 #ifdef CONFIG_PCI
-static struct pci_device_id card_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(card_ids) = {
        { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
        { 0x14b9, 0x4500, PCI_ANY_ID, PCI_ANY_ID },
        { 0x14b9, 0x4800, PCI_ANY_ID, PCI_ANY_ID, },
@@ -85,10 +87,10 @@ static struct pci_driver airo_driver = {
 
 /* Include Wireless Extension definition and check version - Jean II */
 #include <linux/wireless.h>
-#define WIRELESS_SPY           // enable iwspy support
-#include <net/iw_handler.h>    // New driver API
+#define WIRELESS_SPY           /* enable iwspy support */
+#include <net/iw_handler.h>    /* New driver API */
 
-#define CISCO_EXT              // enable Cisco extensions
+#define CISCO_EXT              /* enable Cisco extensions */
 #ifdef CISCO_EXT
 #include <linux/delay.h>
 #endif
@@ -103,7 +105,7 @@ static struct pci_driver airo_driver = {
    of statistics in the /proc filesystem */
 
 #define IGNLABEL(comment) NULL
-static char *statsLabels[] = {
+static const char *statsLabels[] = {
        "RxOverrun",
        IGNLABEL("RxPlcpCrcErr"),
        IGNLABEL("RxPlcpFormatErr"),
@@ -215,7 +217,6 @@ static char *statsLabels[] = {
    (no spaces) list of rates (up to 8). */
 
 static int rates[8];
-static int basic_rate;
 static char *ssids[3];
 
 static int io[4];
@@ -241,29 +242,29 @@ static int airo_perm = 0555;
 static int proc_perm = 0644;
 
 MODULE_AUTHOR("Benjamin Reed");
-MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \
-cards.  Direct support for ISA/PCI/MPI cards and support \
-for PCMCIA when used with airo_cs.");
+MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet cards.  "
+                  "Direct support for ISA/PCI/MPI cards and support for PCMCIA when used with airo_cs.");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340/350");
 module_param_array(io, int, NULL, 0);
 module_param_array(irq, int, NULL, 0);
-module_param(basic_rate, int, 0);
 module_param_array(rates, int, NULL, 0);
 module_param_array(ssids, charp, NULL, 0);
 module_param(auto_wep, int, 0);
-MODULE_PARM_DESC(auto_wep, "If non-zero, the driver will keep looping through \
-the authentication options until an association is made.  The value of \
-auto_wep is number of the wep keys to check.  A value of 2 will try using \
-the key at index 0 and index 1.");
+MODULE_PARM_DESC(auto_wep,
+                "If non-zero, the driver will keep looping through the authentication options until an association is made.  "
+                "The value of auto_wep is number of the wep keys to check.  "
+                "A value of 2 will try using the key at index 0 and index 1.");
 module_param(aux_bap, int, 0);
-MODULE_PARM_DESC(aux_bap, "If non-zero, the driver will switch into a mode \
-than seems to work better for older cards with some older buses.  Before \
-switching it checks that the switch is needed.");
+MODULE_PARM_DESC(aux_bap,
+                "If non-zero, the driver will switch into a mode that seems to work better for older cards with some older buses.  "
+                "Before switching it checks that the switch is needed.");
 module_param(maxencrypt, int, 0);
-MODULE_PARM_DESC(maxencrypt, "The maximum speed that the card can do \
-encryption.  Units are in 512kbs.  Zero (default) means there is no limit. \
-Older cards used to be limited to 2mbs (4).");
+MODULE_PARM_DESC(maxencrypt,
+                "The maximum speed that the card can do encryption.  "
+                "Units are in 512kbs.  "
+                "Zero (default) means there is no limit.  "
+                "Older cards used to be limited to 2mbs (4).");
 module_param(adhoc, int, 0);
 MODULE_PARM_DESC(adhoc, "If non-zero, the card will start in adhoc mode.");
 module_param(probe, int, 0);
@@ -281,7 +282,7 @@ MODULE_PARM_DESC(proc_perm, "The permission bits of the files in /proc");
 /* This is a kind of sloppy hack to get this information to OUT4500 and
    IN4500.  I would be extremely interested in the situation where this
    doesn't work though!!! */
-static int do8bitIO = 0;
+static int do8bitIO /* = 0 */;
 
 /* Return codes */
 #define SUCCESS 0
@@ -398,8 +399,8 @@ static int do8bitIO = 0;
 #define MAXTXQ 64
 
 /* BAP selectors */
-#define BAP0 0 // Used for receiving packets
-#define BAP1 2 // Used for xmiting packets and working with RIDS
+#define BAP0 0 /* Used for receiving packets */
+#define BAP1 2 /* Used for xmiting packets and working with RIDS */
 
 /* Flags */
 #define COMMAND_BUSY 0x8000
@@ -495,39 +496,41 @@ typedef struct {
  * so all rid access should use the read/writeXXXRid routines.
  */
 
-/* This is redundant for x86 archs, but it seems necessary for ARM */
-#pragma pack(1)
-
 /* This structure came from an email sent to me from an engineer at
    aironet for inclusion into this driver */
-typedef struct {
+typedef struct WepKeyRid WepKeyRid;
+struct WepKeyRid {
        __le16 len;
        __le16 kindex;
        u8 mac[ETH_ALEN];
        __le16 klen;
        u8 key[16];
-} WepKeyRid;
+} __packed;
 
 /* These structures are from the Aironet's PC4500 Developers Manual */
-typedef struct {
+typedef struct Ssid Ssid;
+struct Ssid {
        __le16 len;
        u8 ssid[32];
-} Ssid;
+} __packed;
 
-typedef struct {
+typedef struct SsidRid SsidRid;
+struct SsidRid {
        __le16 len;
        Ssid ssids[3];
-} SsidRid;
+} __packed;
 
-typedef struct {
+typedef struct ModulationRid ModulationRid;
+struct ModulationRid {
         __le16 len;
         __le16 modulation;
 #define MOD_DEFAULT cpu_to_le16(0)
 #define MOD_CCK cpu_to_le16(1)
 #define MOD_MOK cpu_to_le16(2)
-} ModulationRid;
+} __packed;
 
-typedef struct {
+typedef struct ConfigRid ConfigRid;
+struct ConfigRid {
        __le16 len; /* sizeof(ConfigRid) */
        __le16 opmode; /* operating mode */
 #define MODE_STA_IBSS cpu_to_le16(0)
@@ -648,9 +651,10 @@ typedef struct {
 #define MAGIC_STAY_IN_CAM (1<<10)
        u8 magicControl;
        __le16 autoWake;
-} ConfigRid;
+} __packed;
 
-typedef struct {
+typedef struct StatusRid StatusRid;
+struct StatusRid {
        __le16 len;
        u8 mac[ETH_ALEN];
        __le16 mode;
@@ -706,21 +710,23 @@ typedef struct {
 #define STAT_LEAPFAILED 91
 #define STAT_LEAPTIMEDOUT 92
 #define STAT_LEAPCOMPLETE 93
-} StatusRid;
+} __packed;
 
-typedef struct {
+typedef struct StatsRid StatsRid;
+struct StatsRid {
        __le16 len;
        __le16 spacer;
        __le32 vals[100];
-} StatsRid;
-
+} __packed;
 
-typedef struct {
+typedef struct APListRid APListRid;
+struct APListRid {
        __le16 len;
        u8 ap[4][ETH_ALEN];
-} APListRid;
+} __packed;
 
-typedef struct {
+typedef struct CapabilityRid CapabilityRid;
+struct CapabilityRid {
        __le16 len;
        char oui[3];
        char zero;
@@ -747,17 +753,18 @@ typedef struct {
        __le16 bootBlockVer;
        __le16 requiredHard;
        __le16 extSoftCap;
-} CapabilityRid;
-
+} __packed;
 
 /* Only present on firmware >= 5.30.17 */
-typedef struct {
+typedef struct BSSListRidExtra BSSListRidExtra;
+struct BSSListRidExtra {
   __le16 unknown[4];
   u8 fixed[12]; /* WLAN management frame */
   u8 iep[624];
-} BSSListRidExtra;
+} __packed;
 
-typedef struct {
+typedef struct BSSListRid BSSListRid;
+struct BSSListRid {
   __le16 len;
   __le16 index; /* First is 0 and 0xffff means end of list */
 #define RADIO_FH 1 /* Frequency hopping radio type */
@@ -788,33 +795,37 @@ typedef struct {
 
   /* Only present on firmware >= 5.30.17 */
   BSSListRidExtra extra;
-} BSSListRid;
+} __packed;
 
 typedef struct {
   BSSListRid bss;
   struct list_head list;
 } BSSListElement;
 
-typedef struct {
+typedef struct tdsRssiEntry tdsRssiEntry;
+struct tdsRssiEntry {
   u8 rssipct;
   u8 rssidBm;
-} tdsRssiEntry;
+} __packed;
 
-typedef struct {
+typedef struct tdsRssiRid tdsRssiRid;
+struct tdsRssiRid {
   u16 len;
   tdsRssiEntry x[256];
-} tdsRssiRid;
+} __packed;
 
-typedef struct {
-       u16 len;
-       u16 state;
-       u16 multicastValid;
+typedef struct MICRid MICRid;
+struct MICRid {
+       __le16 len;
+       __le16 state;
+       __le16 multicastValid;
        u8  multicast[16];
-       u16 unicastValid;
+       __le16 unicastValid;
        u8  unicast[16];
-} MICRid;
+} __packed;
 
-typedef struct {
+typedef struct MICBuffer MICBuffer;
+struct MICBuffer {
        __be16 typelen;
 
        union {
@@ -829,15 +840,13 @@ typedef struct {
        } u;
        __be32 mic;
        __be32 seq;
-} MICBuffer;
+} __packed;
 
 typedef struct {
        u8 da[ETH_ALEN];
        u8 sa[ETH_ALEN];
 } etherHead;
 
-#pragma pack()
-
 #define TXCTL_TXOK (1<<1) /* report if tx is ok */
 #define TXCTL_TXEX (1<<2) /* report if tx fails */
 #define TXCTL_802_3 (0<<3) /* 802.3 packet */
@@ -922,7 +931,7 @@ typedef struct aironet_ioctl {
        unsigned char __user *data;     // d-data
 } aironet_ioctl;
 
-static char swversion[] = "2.1";
+static const char swversion[] = "2.1";
 #endif /* CISCO_EXT */
 
 #define NUM_MODULES       2
@@ -980,6 +989,14 @@ typedef struct {
        dma_addr_t host_addr;
 } TxFid;
 
+struct rx_hdr {
+       __le16 status, len;
+       u8 rssi[2];
+       u8 rate;
+       u8 freq;
+       __le16 tmp[4];
+} __packed;
+
 typedef struct {
        unsigned int  ctl: 15;
        unsigned int  rdy: 1;
@@ -1069,10 +1086,6 @@ static WifiCtlHdr wifictlhdr8023 = {
        }
 };
 
-// Frequency list (map channels to frequencies)
-static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
-                               2447, 2452, 2457, 2462, 2467, 2472, 2484 };
-
 // A few details needed for WEP (Wireless Equivalent Privacy)
 #define MAX_KEY_SIZE 13                        // 128 (?) bits
 #define MIN_KEY_SIZE  5                        // 40 bits RC4 - WEP
@@ -1081,12 +1094,6 @@ typedef struct wep_key_t {
        u8      key[16];        /* 40-bit and 104-bit keys */
 } wep_key_t;
 
-/* Backward compatibility */
-#ifndef IW_ENCODE_NOKEY
-#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
-#define IW_ENCODE_MODE  (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN)
-#endif /* IW_ENCODE_NOKEY */
-
 /* List of Wireless Handlers (new API) */
 static const struct iw_handler_def     airo_handler_def;
 
@@ -1148,14 +1155,13 @@ static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm);
 static void airo_networks_free(struct airo_info *ai);
 
 struct airo_info {
-       struct net_device_stats stats;
        struct net_device             *dev;
        struct list_head              dev_list;
        /* Note, we can have MAX_FIDS outstanding.  FIDs are 16-bits, so we
           use the high bit to mark whether it is in use. */
 #define MAX_FIDS 6
 #define MPI_MAX_FIDS 1
-       int                           fids[MAX_FIDS];
+       u32                           fids[MAX_FIDS];
        ConfigRid config;
        char keyindex; // Used with auto wep
        char defindex; // Used with auto wep
@@ -1229,6 +1235,9 @@ struct airo_info {
 #define        PCI_SHARED_LEN          2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
        char                    proc_name[IFNAMSIZ];
 
+       int                     wep_capable;
+       int                     max_wep_idx;
+
        /* WPA-related stuff */
        unsigned int bssListFirst;
        unsigned int bssListNext;
@@ -1271,6 +1280,7 @@ static int flashrestart(struct airo_info *ai,struct net_device *dev);
 #define airo_print_err(name, fmt, args...) \
        airo_print(KERN_ERR, name, fmt, ##args)
 
+#define AIRO_FLASH(dev) (((struct airo_info *)dev->ml_priv)->flash)
 
 /***********************************************************************
  *                              MIC ROUTINES                           *
@@ -1286,6 +1296,29 @@ static void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
 static void emmh32_final(emmh32_context *context, u8 digest[4]);
 static int flashpchar(struct airo_info *ai,int byte,int dwelltime);
 
+static void age_mic_context(miccntx *cur, miccntx *old, u8 *key, int key_len,
+                           struct crypto_cipher *tfm)
+{
+       /* If the current MIC context is valid and its key is the same as
+        * the MIC register, there's nothing to do.
+        */
+       if (cur->valid && (memcmp(cur->key, key, key_len) == 0))
+               return;
+
+       /* Age current mic Context */
+       memcpy(old, cur, sizeof(*cur));
+
+       /* Initialize new context */
+       memcpy(cur->key, key, key_len);
+       cur->window  = 33; /* Window always points to the middle */
+       cur->rx      = 0;  /* Rx Sequence numbers */
+       cur->tx      = 0;  /* Tx sequence numbers */
+       cur->valid   = 1;  /* Key is now valid */
+
+       /* Give key to mic seed */
+       emmh32_setseed(&cur->seed, key, key_len, tfm);
+}
+
 /* micinit - Initialize mic seed */
 
 static void micinit(struct airo_info *ai)
@@ -1296,49 +1329,26 @@ static void micinit(struct airo_info *ai)
        PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0);
        up(&ai->sem);
 
-       ai->micstats.enabled = (mic_rid.state & 0x00FF) ? 1 : 0;
-
-       if (ai->micstats.enabled) {
-               /* Key must be valid and different */
-               if (mic_rid.multicastValid && (!ai->mod[0].mCtx.valid ||
-                   (memcmp (ai->mod[0].mCtx.key, mic_rid.multicast,
-                            sizeof(ai->mod[0].mCtx.key)) != 0))) {
-                       /* Age current mic Context */
-                       memcpy(&ai->mod[1].mCtx,&ai->mod[0].mCtx,sizeof(miccntx));
-                       /* Initialize new context */
-                       memcpy(&ai->mod[0].mCtx.key,mic_rid.multicast,sizeof(mic_rid.multicast));
-                       ai->mod[0].mCtx.window  = 33; //Window always points to the middle
-                       ai->mod[0].mCtx.rx      = 0;  //Rx Sequence numbers
-                       ai->mod[0].mCtx.tx      = 0;  //Tx sequence numbers
-                       ai->mod[0].mCtx.valid   = 1;  //Key is now valid
-  
-                       /* Give key to mic seed */
-                       emmh32_setseed(&ai->mod[0].mCtx.seed,mic_rid.multicast,sizeof(mic_rid.multicast), ai->tfm);
-               }
-
-               /* Key must be valid and different */
-               if (mic_rid.unicastValid && (!ai->mod[0].uCtx.valid || 
-                   (memcmp(ai->mod[0].uCtx.key, mic_rid.unicast,
-                           sizeof(ai->mod[0].uCtx.key)) != 0))) {
-                       /* Age current mic Context */
-                       memcpy(&ai->mod[1].uCtx,&ai->mod[0].uCtx,sizeof(miccntx));
-                       /* Initialize new context */
-                       memcpy(&ai->mod[0].uCtx.key,mic_rid.unicast,sizeof(mic_rid.unicast));
-       
-                       ai->mod[0].uCtx.window  = 33; //Window always points to the middle
-                       ai->mod[0].uCtx.rx      = 0;  //Rx Sequence numbers
-                       ai->mod[0].uCtx.tx      = 0;  //Tx sequence numbers
-                       ai->mod[0].uCtx.valid   = 1;  //Key is now valid
-       
-                       //Give key to mic seed
-                       emmh32_setseed(&ai->mod[0].uCtx.seed, mic_rid.unicast, sizeof(mic_rid.unicast), ai->tfm);
-               }
-       } else {
-      /* So next time we have a valid key and mic is enabled, we will update
-       * the sequence number if the key is the same as before.
-       */
+       ai->micstats.enabled = (le16_to_cpu(mic_rid.state) & 0x00FF) ? 1 : 0;
+       if (!ai->micstats.enabled) {
+               /* So next time we have a valid key and mic is enabled, we will
+                * update the sequence number if the key is the same as before.
+                */
                ai->mod[0].uCtx.valid = 0;
                ai->mod[0].mCtx.valid = 0;
+               return;
+       }
+
+       if (mic_rid.multicastValid) {
+               age_mic_context(&ai->mod[0].mCtx, &ai->mod[1].mCtx,
+                               mic_rid.multicast, sizeof(mic_rid.multicast),
+                               ai->tfm);
+       }
+
+       if (mic_rid.unicastValid) {
+               age_mic_context(&ai->mod[0].uCtx, &ai->mod[1].uCtx,
+                               mic_rid.unicast, sizeof(mic_rid.unicast),
+                               ai->tfm);
        }
 }
 
@@ -1363,7 +1373,7 @@ static int micsetup(struct airo_info *ai) {
        return SUCCESS;
 }
 
-static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
+static const u8 micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
 
 /*===========================================================================
  * Description: Mic a packet
@@ -1866,7 +1876,7 @@ static void try_auto_wep(struct airo_info *ai)
 }
 
 static int airo_open(struct net_device *dev) {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        int rc = 0;
 
        if (test_bit(FLAG_FLASHING, &ai->flags))
@@ -1875,7 +1885,7 @@ static int airo_open(struct net_device *dev) {
        /* Make sure the card is configured.
         * Wireless Extensions may postpone config changes until the card
         * is open (to pipeline changes and speed-up card setup). If
-        * those changes are not yet commited, do it now - Jean II */
+        * those changes are not yet committed, do it now - Jean II */
        if (test_bit(FLAG_COMMIT, &ai->flags)) {
                disable_MAC(ai, 1);
                writeConfigRid(ai, 1);
@@ -1910,25 +1920,27 @@ static int airo_open(struct net_device *dev) {
        return 0;
 }
 
-static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
+static netdev_tx_t mpi_start_xmit(struct sk_buff *skb,
+                                       struct net_device *dev)
+{
        int npacks, pending;
        unsigned long flags;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
 
        if (!skb) {
-               airo_print_err(dev->name, "%s: skb == NULL!",__FUNCTION__);
-               return 0;
+               airo_print_err(dev->name, "%s: skb == NULL!",__func__);
+               return NETDEV_TX_OK;
        }
        npacks = skb_queue_len (&ai->txq);
 
        if (npacks >= MAXTXQ - 1) {
                netif_stop_queue (dev);
                if (npacks > MAXTXQ) {
-                       ai->stats.tx_fifo_errors++;
-                       return 1;
+                       dev->stats.tx_fifo_errors++;
+                       return NETDEV_TX_BUSY;
                }
                skb_queue_tail (&ai->txq, skb);
-               return 0;
+               return NETDEV_TX_OK;
        }
 
        spin_lock_irqsave(&ai->aux_lock, flags);
@@ -1941,7 +1953,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
                set_bit(FLAG_PENDING_XMIT, &ai->flags);
                mpi_send_packet (dev);
        }
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 /*
@@ -1957,7 +1969,7 @@ static int mpi_send_packet (struct net_device *dev)
        unsigned char *buffer;
        s16 len;
        __le16 *payloadLen;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        u8 *sendbuf;
 
        /* get a packet to send */
@@ -1965,7 +1977,7 @@ static int mpi_send_packet (struct net_device *dev)
        if ((skb = skb_dequeue(&ai->txq)) == NULL) {
                airo_print_err(dev->name,
                        "%s: Dequeue'd zero in send_packet()",
-                       __FUNCTION__);
+                       __func__);
                return 0;
        }
 
@@ -1981,7 +1993,7 @@ static int mpi_send_packet (struct net_device *dev)
 /*
  * Magic, the cards firmware needs a length count (2 bytes) in the host buffer
  * right after  TXFID_HDR.The TXFID_HDR contains the status short so payloadlen
- * is immediatly after it. ------------------------------------------------
+ * is immediately after it. ------------------------------------------------
  *                         |TXFIDHDR+STATUS|PAYLOADLEN|802.3HDR|PACKETDATA|
  *                         ------------------------------------------------
  */
@@ -1995,7 +2007,7 @@ static int mpi_send_packet (struct net_device *dev)
                sizeof(wifictlhdr8023) + 2 ;
 
        /*
-        * Firmware automaticly puts 802 header on so
+        * Firmware automatically puts 802 header on so
         * we don't need to account for it in the length
         */
        if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
@@ -2044,13 +2056,13 @@ static void get_tx_error(struct airo_info *ai, s32 fid)
                bap_read(ai, &status, 2, BAP0);
        }
        if (le16_to_cpu(status) & 2) /* Too many retries */
-               ai->stats.tx_aborted_errors++;
+               ai->dev->stats.tx_aborted_errors++;
        if (le16_to_cpu(status) & 4) /* Transmit lifetime exceeded */
-               ai->stats.tx_heartbeat_errors++;
+               ai->dev->stats.tx_heartbeat_errors++;
        if (le16_to_cpu(status) & 8) /* Aid fail */
                { }
        if (le16_to_cpu(status) & 0x10) /* MAC disabled */
-               ai->stats.tx_carrier_errors++;
+               ai->dev->stats.tx_carrier_errors++;
        if (le16_to_cpu(status) & 0x20) /* Association lost */
                { }
        /* We produce a TXDROP event only for retry or lifetime
@@ -2086,7 +2098,7 @@ static void get_tx_error(struct airo_info *ai, s32 fid)
 static void airo_end_xmit(struct net_device *dev) {
        u16 status;
        int i;
-       struct airo_info *priv = dev->priv;
+       struct airo_info *priv = dev->ml_priv;
        struct sk_buff *skb = priv->xmit.skb;
        int fid = priv->xmit.fid;
        u32 *fids = priv->fids;
@@ -2102,22 +2114,24 @@ static void airo_end_xmit(struct net_device *dev) {
                for (; i < MAX_FIDS / 2 && (priv->fids[i] & 0xffff0000); i++);
        } else {
                priv->fids[fid] &= 0xffff;
-               priv->stats.tx_window_errors++;
+               dev->stats.tx_window_errors++;
        }
        if (i < MAX_FIDS / 2)
                netif_wake_queue(dev);
        dev_kfree_skb(skb);
 }
 
-static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
+static netdev_tx_t airo_start_xmit(struct sk_buff *skb,
+                                        struct net_device *dev)
+{
        s16 len;
        int i, j;
-       struct airo_info *priv = dev->priv;
+       struct airo_info *priv = dev->ml_priv;
        u32 *fids = priv->fids;
 
        if ( skb == NULL ) {
-               airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
-               return 0;
+               airo_print_err(dev->name, "%s: skb == NULL!", __func__);
+               return NETDEV_TX_OK;
        }
 
        /* Find a vacant FID */
@@ -2128,8 +2142,8 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
                netif_stop_queue(dev);
 
                if (i == MAX_FIDS / 2) {
-                       priv->stats.tx_fifo_errors++;
-                       return 1;
+                       dev->stats.tx_fifo_errors++;
+                       return NETDEV_TX_BUSY;
                }
        }
        /* check min length*/
@@ -2145,13 +2159,13 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
                wake_up_interruptible(&priv->thr_wait);
        } else
                airo_end_xmit(dev);
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 static void airo_end_xmit11(struct net_device *dev) {
        u16 status;
        int i;
-       struct airo_info *priv = dev->priv;
+       struct airo_info *priv = dev->ml_priv;
        struct sk_buff *skb = priv->xmit11.skb;
        int fid = priv->xmit11.fid;
        u32 *fids = priv->fids;
@@ -2167,28 +2181,31 @@ static void airo_end_xmit11(struct net_device *dev) {
                for (; i < MAX_FIDS && (priv->fids[i] & 0xffff0000); i++);
        } else {
                priv->fids[fid] &= 0xffff;
-               priv->stats.tx_window_errors++;
+               dev->stats.tx_window_errors++;
        }
        if (i < MAX_FIDS)
                netif_wake_queue(dev);
        dev_kfree_skb(skb);
 }
 
-static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
+static netdev_tx_t airo_start_xmit11(struct sk_buff *skb,
+                                          struct net_device *dev)
+{
        s16 len;
        int i, j;
-       struct airo_info *priv = dev->priv;
+       struct airo_info *priv = dev->ml_priv;
        u32 *fids = priv->fids;
 
        if (test_bit(FLAG_MPI, &priv->flags)) {
                /* Not implemented yet for MPI350 */
                netif_stop_queue(dev);
-               return -ENETDOWN;
+               dev_kfree_skb_any(skb);
+               return NETDEV_TX_OK;
        }
 
        if ( skb == NULL ) {
-               airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
-               return 0;
+               airo_print_err(dev->name, "%s: skb == NULL!", __func__);
+               return NETDEV_TX_OK;
        }
 
        /* Find a vacant FID */
@@ -2199,8 +2216,8 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
                netif_stop_queue(dev);
 
                if (i == MAX_FIDS) {
-                       priv->stats.tx_fifo_errors++;
-                       return 1;
+                       dev->stats.tx_fifo_errors++;
+                       return NETDEV_TX_BUSY;
                }
        }
        /* check min length*/
@@ -2216,11 +2233,12 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
                wake_up_interruptible(&priv->thr_wait);
        } else
                airo_end_xmit11(dev);
-       return 0;
+       return NETDEV_TX_OK;
 }
 
-static void airo_read_stats(struct airo_info *ai)
+static void airo_read_stats(struct net_device *dev)
 {
+       struct airo_info *ai = dev->ml_priv;
        StatsRid stats_rid;
        __le32 *vals = stats_rid.vals;
 
@@ -2232,28 +2250,29 @@ static void airo_read_stats(struct airo_info *ai)
        readStatsRid(ai, &stats_rid, RID_STATS, 0);
        up(&ai->sem);
 
-       ai->stats.rx_packets = le32_to_cpu(vals[43]) + le32_to_cpu(vals[44]) +
+       dev->stats.rx_packets = le32_to_cpu(vals[43]) + le32_to_cpu(vals[44]) +
                               le32_to_cpu(vals[45]);
-       ai->stats.tx_packets = le32_to_cpu(vals[39]) + le32_to_cpu(vals[40]) +
+       dev->stats.tx_packets = le32_to_cpu(vals[39]) + le32_to_cpu(vals[40]) +
                               le32_to_cpu(vals[41]);
-       ai->stats.rx_bytes = le32_to_cpu(vals[92]);
-       ai->stats.tx_bytes = le32_to_cpu(vals[91]);
-       ai->stats.rx_errors = le32_to_cpu(vals[0]) + le32_to_cpu(vals[2]) +
+       dev->stats.rx_bytes = le32_to_cpu(vals[92]);
+       dev->stats.tx_bytes = le32_to_cpu(vals[91]);
+       dev->stats.rx_errors = le32_to_cpu(vals[0]) + le32_to_cpu(vals[2]) +
                              le32_to_cpu(vals[3]) + le32_to_cpu(vals[4]);
-       ai->stats.tx_errors = le32_to_cpu(vals[42]) + ai->stats.tx_fifo_errors;
-       ai->stats.multicast = le32_to_cpu(vals[43]);
-       ai->stats.collisions = le32_to_cpu(vals[89]);
+       dev->stats.tx_errors = le32_to_cpu(vals[42]) +
+                             dev->stats.tx_fifo_errors;
+       dev->stats.multicast = le32_to_cpu(vals[43]);
+       dev->stats.collisions = le32_to_cpu(vals[89]);
 
        /* detailed rx_errors: */
-       ai->stats.rx_length_errors = le32_to_cpu(vals[3]);
-       ai->stats.rx_crc_errors = le32_to_cpu(vals[4]);
-       ai->stats.rx_frame_errors = le32_to_cpu(vals[2]);
-       ai->stats.rx_fifo_errors = le32_to_cpu(vals[0]);
+       dev->stats.rx_length_errors = le32_to_cpu(vals[3]);
+       dev->stats.rx_crc_errors = le32_to_cpu(vals[4]);
+       dev->stats.rx_frame_errors = le32_to_cpu(vals[2]);
+       dev->stats.rx_fifo_errors = le32_to_cpu(vals[0]);
 }
 
 static struct net_device_stats *airo_get_stats(struct net_device *dev)
 {
-       struct airo_info *local =  dev->priv;
+       struct airo_info *local =  dev->ml_priv;
 
        if (!test_bit(JOB_STATS, &local->jobs)) {
                /* Get stats out of the card if available */
@@ -2261,10 +2280,10 @@ static struct net_device_stats *airo_get_stats(struct net_device *dev)
                        set_bit(JOB_STATS, &local->jobs);
                        wake_up_interruptible(&local->thr_wait);
                } else
-                       airo_read_stats(local);
+                       airo_read_stats(dev);
        }
 
-       return &local->stats;
+       return &dev->stats;
 }
 
 static void airo_set_promisc(struct airo_info *ai) {
@@ -2280,7 +2299,7 @@ static void airo_set_promisc(struct airo_info *ai) {
 }
 
 static void airo_set_multicast_list(struct net_device *dev) {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
 
        if ((dev->flags ^ ai->flags) & IFF_PROMISC) {
                change_bit(FLAG_PROMISC, &ai->flags);
@@ -2291,14 +2310,14 @@ static void airo_set_multicast_list(struct net_device *dev) {
                        airo_set_promisc(ai);
        }
 
-       if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) {
+       if ((dev->flags&IFF_ALLMULTI) || !netdev_mc_empty(dev)) {
                /* Turn on multicast.  (Should be already setup...) */
        }
 }
 
 static int airo_set_mac_address(struct net_device *dev, void *p)
 {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        struct sockaddr *addr = p;
 
        readConfigRid(ai, 1);
@@ -2338,7 +2357,7 @@ static void del_airo_dev(struct airo_info *ai)
 }
 
 static int airo_close(struct net_device *dev) {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
 
        netif_stop_queue(dev);
 
@@ -2364,7 +2383,7 @@ static int airo_close(struct net_device *dev) {
 
 void stop_airo_card( struct net_device *dev, int freeres )
 {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
 
        set_bit(FLAG_RADIO_DOWN, &ai->flags);
        disable_MAC(ai, 1);
@@ -2513,7 +2532,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
 /*
  * We are setting up three things here:
  * 1) Map AUX memory for descriptors: Rid, TxFid, or RxFid.
- * 2) Map PCI memory for issueing commands.
+ * 2) Map PCI memory for issuing commands.
  * 3) Allocate memory (shared) to send and receive ethernet frames.
  */
 static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci)
@@ -2634,17 +2653,21 @@ static const struct header_ops airo_header_ops = {
        .parse = wll_header_parse,
 };
 
+static const struct net_device_ops airo11_netdev_ops = {
+       .ndo_open               = airo_open,
+       .ndo_stop               = airo_close,
+       .ndo_start_xmit         = airo_start_xmit11,
+       .ndo_get_stats          = airo_get_stats,
+       .ndo_set_mac_address    = airo_set_mac_address,
+       .ndo_do_ioctl           = airo_ioctl,
+       .ndo_change_mtu         = airo_change_mtu,
+};
+
 static void wifi_setup(struct net_device *dev)
 {
+       dev->netdev_ops = &airo11_netdev_ops;
        dev->header_ops = &airo_header_ops;
-       dev->hard_start_xmit = &airo_start_xmit11;
-       dev->get_stats = &airo_get_stats;
-       dev->set_mac_address = &airo_set_mac_address;
-       dev->do_ioctl = &airo_ioctl;
        dev->wireless_handlers = &airo_handler_def;
-       dev->change_mtu = &airo_change_mtu;
-       dev->open = &airo_open;
-       dev->stop = &airo_close;
 
        dev->type               = ARPHRD_IEEE80211;
        dev->hard_header_len    = ETH_HLEN;
@@ -2664,10 +2687,11 @@ static struct net_device *init_wifidev(struct airo_info *ai,
        struct net_device *dev = alloc_netdev(0, "wifi%d", wifi_setup);
        if (!dev)
                return NULL;
-       dev->priv = ethdev->priv;
+       dev->ml_priv = ethdev->ml_priv;
        dev->irq = ethdev->irq;
        dev->base_addr = ethdev->base_addr;
        dev->wireless_data = ethdev->wireless_data;
+       SET_NETDEV_DEV(dev, ethdev->dev.parent);
        memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
        err = register_netdev(dev);
        if (err<0) {
@@ -2678,7 +2702,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
 }
 
 static int reset_card( struct net_device *dev , int lock) {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
 
        if (lock && down_interruptible(&ai->sem))
                return -1;
@@ -2698,9 +2722,8 @@ static int airo_networks_allocate(struct airo_info *ai)
        if (ai->networks)
                return 0;
 
-       ai->networks =
-           kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement),
-                   GFP_KERNEL);
+       ai->networks = kcalloc(AIRO_MAX_NETWORK_COUNT, sizeof(BSSListElement),
+                              GFP_KERNEL);
        if (!ai->networks) {
                airo_print_warn("", "Out of memory allocating beacons");
                return -ENOMEM;
@@ -2726,27 +2749,30 @@ static void airo_networks_initialize(struct airo_info *ai)
                              &ai->network_free_list);
 }
 
-static int airo_test_wpa_capable(struct airo_info *ai)
-{
-       int status;
-       CapabilityRid cap_rid;
-
-       status = readCapabilityRid(ai, &cap_rid, 1);
-       if (status != SUCCESS) return 0;
+static const struct net_device_ops airo_netdev_ops = {
+       .ndo_open               = airo_open,
+       .ndo_stop               = airo_close,
+       .ndo_start_xmit         = airo_start_xmit,
+       .ndo_get_stats          = airo_get_stats,
+       .ndo_set_multicast_list = airo_set_multicast_list,
+       .ndo_set_mac_address    = airo_set_mac_address,
+       .ndo_do_ioctl           = airo_ioctl,
+       .ndo_change_mtu         = airo_change_mtu,
+       .ndo_validate_addr      = eth_validate_addr,
+};
 
-       /* Only firmware versions 5.30.17 or better can do WPA */
-       if (le16_to_cpu(cap_rid.softVer) > 0x530
-         || (le16_to_cpu(cap_rid.softVer) == 0x530
-             && le16_to_cpu(cap_rid.softSubVer) >= 17)) {
-               airo_print_info("", "WPA is supported.");
-               return 1;
-       }
+static const struct net_device_ops mpi_netdev_ops = {
+       .ndo_open               = airo_open,
+       .ndo_stop               = airo_close,
+       .ndo_start_xmit         = mpi_start_xmit,
+       .ndo_get_stats          = airo_get_stats,
+       .ndo_set_multicast_list = airo_set_multicast_list,
+       .ndo_set_mac_address    = airo_set_mac_address,
+       .ndo_do_ioctl           = airo_ioctl,
+       .ndo_change_mtu         = airo_change_mtu,
+       .ndo_validate_addr      = eth_validate_addr,
+};
 
-       /* No WPA support */
-       airo_print_info("", "WPA unsupported (only firmware versions 5.30.17"
-               " and greater support WPA.  Detected %s)", cap_rid.prodVer);
-       return 0;
-}
 
 static struct net_device *_init_airo_card( unsigned short irq, int port,
                                           int is_pcmcia, struct pci_dev *pci,
@@ -2755,7 +2781,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        struct net_device *dev;
        struct airo_info *ai;
        int i, rc;
-       DECLARE_MAC_BUF(mac);
+       CapabilityRid cap_rid;
 
        /* Create the network device object. */
        dev = alloc_netdev(sizeof(*ai), "", ether_setup);
@@ -2764,7 +2790,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
                return NULL;
        }
 
-       ai = dev->priv;
+       ai = dev->ml_priv = netdev_priv(dev);
        ai->wifidev = NULL;
        ai->flags = 1 << FLAG_RADIO_DOWN;
        ai->jobs = 0;
@@ -2785,22 +2811,16 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
                goto err_out_free;
        airo_networks_initialize (ai);
 
+       skb_queue_head_init (&ai->txq);
+
        /* The Airo-specific entries in the device structure. */
-       if (test_bit(FLAG_MPI,&ai->flags)) {
-               skb_queue_head_init (&ai->txq);
-               dev->hard_start_xmit = &mpi_start_xmit;
-       } else
-               dev->hard_start_xmit = &airo_start_xmit;
-       dev->get_stats = &airo_get_stats;
-       dev->set_multicast_list = &airo_set_multicast_list;
-       dev->set_mac_address = &airo_set_mac_address;
-       dev->do_ioctl = &airo_ioctl;
+       if (test_bit(FLAG_MPI,&ai->flags))
+               dev->netdev_ops = &mpi_netdev_ops;
+       else
+               dev->netdev_ops = &airo_netdev_ops;
        dev->wireless_handlers = &airo_handler_def;
        ai->wireless_data.spy_data = &ai->spy_data;
        dev->wireless_data = &ai->wireless_data;
-       dev->change_mtu = &airo_change_mtu;
-       dev->open = &airo_open;
-       dev->stop = &airo_close;
        dev->irq = irq;
        dev->base_addr = port;
 
@@ -2825,7 +2845,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        }
 
        if (probe) {
-               if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) {
+               if (setup_card(ai, dev->dev_addr, 1) != SUCCESS) {
                        airo_print_err(dev->name, "MAC could not be enabled" );
                        rc = -EIO;
                        goto err_out_map;
@@ -2835,38 +2855,59 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
                set_bit(FLAG_FLASHING, &ai->flags);
        }
 
+       strcpy(dev->name, "eth%d");
+       rc = register_netdev(dev);
+       if (rc) {
+               airo_print_err(dev->name, "Couldn't register_netdev");
+               goto err_out_map;
+       }
+       ai->wifidev = init_wifidev(ai, dev);
+       if (!ai->wifidev)
+               goto err_out_reg;
+
+       rc = readCapabilityRid(ai, &cap_rid, 1);
+       if (rc != SUCCESS) {
+               rc = -EIO;
+               goto err_out_wifi;
+       }
+       /* WEP capability discovery */
+       ai->wep_capable = (cap_rid.softCap & cpu_to_le16(0x02)) ? 1 : 0;
+       ai->max_wep_idx = (cap_rid.softCap & cpu_to_le16(0x80)) ? 3 : 0;
+
+       airo_print_info(dev->name, "Firmware version %x.%x.%02d",
+                       ((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF),
+                       (le16_to_cpu(cap_rid.softVer) & 0xFF),
+                       le16_to_cpu(cap_rid.softSubVer));
+
        /* Test for WPA support */
-       if (airo_test_wpa_capable(ai)) {
+       /* Only firmware versions 5.30.17 or better can do WPA */
+       if (le16_to_cpu(cap_rid.softVer) > 0x530
+        || (le16_to_cpu(cap_rid.softVer) == 0x530
+             && le16_to_cpu(cap_rid.softSubVer) >= 17)) {
+               airo_print_info(ai->dev->name, "WPA supported.");
+
                set_bit(FLAG_WPA_CAPABLE, &ai->flags);
                ai->bssListFirst = RID_WPA_BSSLISTFIRST;
                ai->bssListNext = RID_WPA_BSSLISTNEXT;
                ai->bssListRidLen = sizeof(BSSListRid);
        } else {
+               airo_print_info(ai->dev->name, "WPA unsupported with firmware "
+                       "versions older than 5.30.17.");
+
                ai->bssListFirst = RID_BSSLISTFIRST;
                ai->bssListNext = RID_BSSLISTNEXT;
                ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra);
        }
 
-       strcpy(dev->name, "eth%d");
-       rc = register_netdev(dev);
-       if (rc) {
-               airo_print_err(dev->name, "Couldn't register_netdev");
-               goto err_out_map;
-       }
-       ai->wifidev = init_wifidev(ai, dev);
-       if (!ai->wifidev)
-               goto err_out_reg;
-
        set_bit(FLAG_REGISTERED,&ai->flags);
-       airo_print_info(dev->name, "MAC enabled %s",
-                       print_mac(mac, dev->dev_addr));
+       airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr);
 
        /* Allocate the transmit buffers */
        if (probe && !test_bit(FLAG_MPI,&ai->flags))
                for( i = 0; i < MAX_FIDS; i++ )
                        ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
 
-       if (setup_proc_entry(dev, dev->priv) < 0)
+       if (setup_proc_entry(dev, dev->ml_priv) < 0)
                goto err_out_wifi;
 
        return dev;
@@ -2888,8 +2929,8 @@ err_out_res:
                release_region( dev->base_addr, 64 );
 err_out_nets:
        airo_networks_free(ai);
-       del_airo_dev(ai);
 err_out_free:
+       del_airo_dev(ai);
        free_netdev(dev);
        return NULL;
 }
@@ -2904,7 +2945,7 @@ EXPORT_SYMBOL(init_airo_card);
 
 static int waitbusy (struct airo_info *ai) {
        int delay = 0;
-       while ((IN4500 (ai, COMMAND) & COMMAND_BUSY) && (delay < 10000)) {
+       while ((IN4500(ai, COMMAND) & COMMAND_BUSY) && (delay < 10000)) {
                udelay (10);
                if ((++delay % 20) == 0)
                        OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
@@ -2915,8 +2956,7 @@ static int waitbusy (struct airo_info *ai) {
 int reset_airo_card( struct net_device *dev )
 {
        int i;
-       struct airo_info *ai = dev->priv;
-       DECLARE_MAC_BUF(mac);
+       struct airo_info *ai = dev->ml_priv;
 
        if (reset_card (dev, 1))
                return -1;
@@ -2925,8 +2965,7 @@ int reset_airo_card( struct net_device *dev )
                airo_print_err(dev->name, "MAC could not be enabled");
                return -1;
        }
-       airo_print_info(dev->name, "MAC enabled %s",
-                       print_mac(mac, dev->dev_addr));
+       airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr);
        /* Allocate the transmit buffers if needed */
        if (!test_bit(FLAG_MPI,&ai->flags))
                for( i = 0; i < MAX_FIDS; i++ )
@@ -2940,7 +2979,7 @@ int reset_airo_card( struct net_device *dev )
 EXPORT_SYMBOL(reset_airo_card);
 
 static void airo_send_event(struct net_device *dev) {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        union iwreq_data wrqu;
        StatusRid status_rid;
 
@@ -3017,7 +3056,7 @@ out:
 
 static int airo_thread(void *data) {
        struct net_device *dev = data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        int locked;
 
        set_freezable();
@@ -3092,7 +3131,7 @@ static int airo_thread(void *data) {
                else if (test_bit(JOB_XMIT11, &ai->jobs))
                        airo_end_xmit11(dev);
                else if (test_bit(JOB_STATS, &ai->jobs))
-                       airo_read_stats(ai);
+                       airo_read_stats(dev);
                else if (test_bit(JOB_WSTATS, &ai->jobs))
                        airo_read_wireless_stats(ai);
                else if (test_bit(JOB_PROMISC, &ai->jobs))
@@ -3127,315 +3166,365 @@ static int header_len(__le16 ctl)
        return 24;
 }
 
-static irqreturn_t airo_interrupt(int irq, void *dev_id)
+static void airo_handle_cisco_mic(struct airo_info *ai)
 {
-       struct net_device *dev = dev_id;
+       if (test_bit(FLAG_MIC_CAPABLE, &ai->flags)) {
+               set_bit(JOB_MIC, &ai->jobs);
+               wake_up_interruptible(&ai->thr_wait);
+       }
+}
+
+/* Airo Status codes */
+#define STAT_NOBEACON  0x8000 /* Loss of sync - missed beacons */
+#define STAT_MAXRETRIES        0x8001 /* Loss of sync - max retries */
+#define STAT_MAXARL    0x8002 /* Loss of sync - average retry level exceeded*/
+#define STAT_FORCELOSS 0x8003 /* Loss of sync - host request */
+#define STAT_TSFSYNC   0x8004 /* Loss of sync - TSF synchronization */
+#define STAT_DEAUTH    0x8100 /* low byte is 802.11 reason code */
+#define STAT_DISASSOC  0x8200 /* low byte is 802.11 reason code */
+#define STAT_ASSOC_FAIL        0x8400 /* low byte is 802.11 reason code */
+#define STAT_AUTH_FAIL 0x0300 /* low byte is 802.11 reason code */
+#define STAT_ASSOC     0x0400 /* Associated */
+#define STAT_REASSOC    0x0600 /* Reassociated?  Only on firmware >= 5.30.17 */
+
+static void airo_print_status(const char *devname, u16 status)
+{
+       u8 reason = status & 0xFF;
+
+       switch (status & 0xFF00) {
+       case STAT_NOBEACON:
+               switch (status) {
+               case STAT_NOBEACON:
+                       airo_print_dbg(devname, "link lost (missed beacons)");
+                       break;
+               case STAT_MAXRETRIES:
+               case STAT_MAXARL:
+                       airo_print_dbg(devname, "link lost (max retries)");
+                       break;
+               case STAT_FORCELOSS:
+                       airo_print_dbg(devname, "link lost (local choice)");
+                       break;
+               case STAT_TSFSYNC:
+                       airo_print_dbg(devname, "link lost (TSF sync lost)");
+                       break;
+               default:
+                       airo_print_dbg(devname, "unknow status %x\n", status);
+                       break;
+               }
+               break;
+       case STAT_DEAUTH:
+               airo_print_dbg(devname, "deauthenticated (reason: %d)", reason);
+               break;
+       case STAT_DISASSOC:
+               airo_print_dbg(devname, "disassociated (reason: %d)", reason);
+               break;
+       case STAT_ASSOC_FAIL:
+               airo_print_dbg(devname, "association failed (reason: %d)",
+                              reason);
+               break;
+       case STAT_AUTH_FAIL:
+               airo_print_dbg(devname, "authentication failed (reason: %d)",
+                              reason);
+               break;
+       case STAT_ASSOC:
+       case STAT_REASSOC:
+               break;
+       default:
+               airo_print_dbg(devname, "unknow status %x\n", status);
+               break;
+       }
+}
+
+static void airo_handle_link(struct airo_info *ai)
+{
+       union iwreq_data wrqu;
+       int scan_forceloss = 0;
        u16 status;
-       u16 fid;
-       struct airo_info *apriv = dev->priv;
-       u16 savedInterrupts = 0;
-       int handled = 0;
 
-       if (!netif_device_present(dev))
-               return IRQ_NONE;
+       /* Get new status and acknowledge the link change */
+       status = le16_to_cpu(IN4500(ai, LINKSTAT));
+       OUT4500(ai, EVACK, EV_LINK);
 
-       for (;;) {
-               status = IN4500( apriv, EVSTAT );
-               if ( !(status & STATUS_INTS) || status == 0xffff ) break;
+       if ((status == STAT_FORCELOSS) && (ai->scan_timeout > 0))
+               scan_forceloss = 1;
 
-               handled = 1;
+       airo_print_status(ai->dev->name, status);
 
-               if ( status & EV_AWAKE ) {
-                       OUT4500( apriv, EVACK, EV_AWAKE );
-                       OUT4500( apriv, EVACK, EV_AWAKE );
-               }
+       if ((status == STAT_ASSOC) || (status == STAT_REASSOC)) {
+               if (auto_wep)
+                       ai->expires = 0;
+               if (ai->list_bss_task)
+                       wake_up_process(ai->list_bss_task);
+               set_bit(FLAG_UPDATE_UNI, &ai->flags);
+               set_bit(FLAG_UPDATE_MULTI, &ai->flags);
 
-               if (!savedInterrupts) {
-                       savedInterrupts = IN4500( apriv, EVINTEN );
-                       OUT4500( apriv, EVINTEN, 0 );
+               if (down_trylock(&ai->sem) != 0) {
+                       set_bit(JOB_EVENT, &ai->jobs);
+                       wake_up_interruptible(&ai->thr_wait);
+               } else
+                       airo_send_event(ai->dev);
+       } else if (!scan_forceloss) {
+               if (auto_wep && !ai->expires) {
+                       ai->expires = RUN_AT(3*HZ);
+                       wake_up_interruptible(&ai->thr_wait);
                }
 
-               if ( status & EV_MIC ) {
-                       OUT4500( apriv, EVACK, EV_MIC );
-                       if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) {
-                               set_bit(JOB_MIC, &apriv->jobs);
-                               wake_up_interruptible(&apriv->thr_wait);
-                       }
-               }
-               if ( status & EV_LINK ) {
-                       union iwreq_data        wrqu;
-                       int scan_forceloss = 0;
-                       /* The link status has changed, if you want to put a
-                          monitor hook in, do it here.  (Remember that
-                          interrupts are still disabled!)
-                       */
-                       u16 newStatus = IN4500(apriv, LINKSTAT);
-                       OUT4500( apriv, EVACK, EV_LINK);
-                       /* Here is what newStatus means: */
-#define NOBEACON 0x8000 /* Loss of sync - missed beacons */
-#define MAXRETRIES 0x8001 /* Loss of sync - max retries */
-#define MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/
-#define FORCELOSS 0x8003 /* Loss of sync - host request */
-#define TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */
-#define DEAUTH 0x8100 /* Deauthentication (low byte is reason code) */
-#define DISASS 0x8200 /* Disassociation (low byte is reason code) */
-#define ASSFAIL 0x8400 /* Association failure (low byte is reason
-                         code) */
-#define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason
-                          code) */
-#define ASSOCIATED 0x0400 /* Associated */
-#define REASSOCIATED 0x0600 /* Reassociated?  Only on firmware >= 5.30.17 */
-#define RC_RESERVED 0 /* Reserved return code */
-#define RC_NOREASON 1 /* Unspecified reason */
-#define RC_AUTHINV 2 /* Previous authentication invalid */
-#define RC_DEAUTH 3 /* Deauthenticated because sending station is
-                      leaving */
-#define RC_NOACT 4 /* Disassociated due to inactivity */
-#define RC_MAXLOAD 5 /* Disassociated because AP is unable to handle
-                       all currently associated stations */
-#define RC_BADCLASS2 6 /* Class 2 frame received from
-                         non-Authenticated station */
-#define RC_BADCLASS3 7 /* Class 3 frame received from
-                         non-Associated station */
-#define RC_STATLEAVE 8 /* Disassociated because sending station is
-                         leaving BSS */
-#define RC_NOAUTH 9 /* Station requesting (Re)Association is not
-                      Authenticated with the responding station */
-                       if (newStatus == FORCELOSS && apriv->scan_timeout > 0)
-                               scan_forceloss = 1;
-                       if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
-                               if (auto_wep)
-                                       apriv->expires = 0;
-                               if (apriv->list_bss_task)
-                                       wake_up_process(apriv->list_bss_task);
-                               set_bit(FLAG_UPDATE_UNI, &apriv->flags);
-                               set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
-
-                               if (down_trylock(&apriv->sem) != 0) {
-                                       set_bit(JOB_EVENT, &apriv->jobs);
-                                       wake_up_interruptible(&apriv->thr_wait);
-                               } else
-                                       airo_send_event(dev);
-                       } else if (!scan_forceloss) {
-                               if (auto_wep && !apriv->expires) {
-                                       apriv->expires = RUN_AT(3*HZ);
-                                       wake_up_interruptible(&apriv->thr_wait);
-                               }
+               /* Send event to user space */
+               memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
+               wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+               wireless_send_event(ai->dev, SIOCGIWAP, &wrqu, NULL);
+       }
+}
 
-                               /* Send event to user space */
-                               memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
-                               wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-                               wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL);
-                       }
-               }
+static void airo_handle_rx(struct airo_info *ai)
+{
+       struct sk_buff *skb = NULL;
+       __le16 fc, v, *buffer, tmpbuf[4];
+       u16 len, hdrlen = 0, gap, fid;
+       struct rx_hdr hdr;
+       int success = 0;
 
-               /* Check to see if there is something to receive */
-               if ( status & EV_RX  ) {
-                       struct sk_buff *skb = NULL;
-                       __le16 fc, v;
-                       u16 len, hdrlen = 0;
-#pragma pack(1)
-                       struct {
-                               __le16 status, len;
-                               u8 rssi[2];
-                               u8 rate;
-                               u8 freq;
-                               __le16 tmp[4];
-                       } hdr;
-#pragma pack()
-                       u16 gap;
-                       __le16 tmpbuf[4];
-                       __le16 *buffer;
-
-                       if (test_bit(FLAG_MPI,&apriv->flags)) {
-                               if (test_bit(FLAG_802_11, &apriv->flags))
-                                       mpi_receive_802_11(apriv);
-                               else
-                                       mpi_receive_802_3(apriv);
-                               OUT4500(apriv, EVACK, EV_RX);
-                               goto exitrx;
-                       }
+       if (test_bit(FLAG_MPI, &ai->flags)) {
+               if (test_bit(FLAG_802_11, &ai->flags))
+                       mpi_receive_802_11(ai);
+               else
+                       mpi_receive_802_3(ai);
+               OUT4500(ai, EVACK, EV_RX);
+               return;
+       }
 
-                       fid = IN4500( apriv, RXFID );
-
-                       /* Get the packet length */
-                       if (test_bit(FLAG_802_11, &apriv->flags)) {
-                               bap_setup (apriv, fid, 4, BAP0);
-                               bap_read (apriv, (__le16*)&hdr, sizeof(hdr), BAP0);
-                               /* Bad CRC. Ignore packet */
-                               if (le16_to_cpu(hdr.status) & 2)
-                                       hdr.len = 0;
-                               if (apriv->wifidev == NULL)
-                                       hdr.len = 0;
-                       } else {
-                               bap_setup (apriv, fid, 0x36, BAP0);
-                               bap_read (apriv, &hdr.len, 2, BAP0);
-                       }
-                       len = le16_to_cpu(hdr.len);
+       fid = IN4500(ai, RXFID);
 
-                       if (len > AIRO_DEF_MTU) {
-                               airo_print_err(apriv->dev->name, "Bad size %d", len);
-                               goto badrx;
-                       }
-                       if (len == 0)
-                               goto badrx;
+       /* Get the packet length */
+       if (test_bit(FLAG_802_11, &ai->flags)) {
+               bap_setup (ai, fid, 4, BAP0);
+               bap_read (ai, (__le16*)&hdr, sizeof(hdr), BAP0);
+               /* Bad CRC. Ignore packet */
+               if (le16_to_cpu(hdr.status) & 2)
+                       hdr.len = 0;
+               if (ai->wifidev == NULL)
+                       hdr.len = 0;
+       } else {
+               bap_setup(ai, fid, 0x36, BAP0);
+               bap_read(ai, &hdr.len, 2, BAP0);
+       }
+       len = le16_to_cpu(hdr.len);
 
-                       if (test_bit(FLAG_802_11, &apriv->flags)) {
-                               bap_read (apriv, &fc, sizeof(fc), BAP0);
-                               hdrlen = header_len(fc);
-                       } else
-                               hdrlen = ETH_ALEN * 2;
+       if (len > AIRO_DEF_MTU) {
+               airo_print_err(ai->dev->name, "Bad size %d", len);
+               goto done;
+       }
+       if (len == 0)
+               goto done;
 
-                       skb = dev_alloc_skb( len + hdrlen + 2 + 2 );
-                       if ( !skb ) {
-                               apriv->stats.rx_dropped++;
-                               goto badrx;
-                       }
-                       skb_reserve(skb, 2); /* This way the IP header is aligned */
-                       buffer = (__le16*)skb_put (skb, len + hdrlen);
-                       if (test_bit(FLAG_802_11, &apriv->flags)) {
-                               buffer[0] = fc;
-                               bap_read (apriv, buffer + 1, hdrlen - 2, BAP0);
-                               if (hdrlen == 24)
-                                       bap_read (apriv, tmpbuf, 6, BAP0);
-
-                               bap_read (apriv, &v, sizeof(v), BAP0);
-                               gap = le16_to_cpu(v);
-                               if (gap) {
-                                       if (gap <= 8) {
-                                               bap_read (apriv, tmpbuf, gap, BAP0);
-                                       } else {
-                                               airo_print_err(apriv->dev->name, "gaplen too "
-                                                       "big. Problems will follow...");
-                                       }
-                               }
-                               bap_read (apriv, buffer + hdrlen/2, len, BAP0);
+       if (test_bit(FLAG_802_11, &ai->flags)) {
+               bap_read(ai, &fc, sizeof (fc), BAP0);
+               hdrlen = header_len(fc);
+       } else
+               hdrlen = ETH_ALEN * 2;
+
+       skb = dev_alloc_skb(len + hdrlen + 2 + 2);
+       if (!skb) {
+               ai->dev->stats.rx_dropped++;
+               goto done;
+       }
+
+       skb_reserve(skb, 2); /* This way the IP header is aligned */
+       buffer = (__le16 *) skb_put(skb, len + hdrlen);
+       if (test_bit(FLAG_802_11, &ai->flags)) {
+               buffer[0] = fc;
+               bap_read(ai, buffer + 1, hdrlen - 2, BAP0);
+               if (hdrlen == 24)
+                       bap_read(ai, tmpbuf, 6, BAP0);
+
+               bap_read(ai, &v, sizeof(v), BAP0);
+               gap = le16_to_cpu(v);
+               if (gap) {
+                       if (gap <= 8) {
+                               bap_read(ai, tmpbuf, gap, BAP0);
                        } else {
-                               MICBuffer micbuf;
-                               bap_read (apriv, buffer, ETH_ALEN*2, BAP0);
-                               if (apriv->micstats.enabled) {
-                                       bap_read (apriv,(__le16*)&micbuf,sizeof(micbuf),BAP0);
-                                       if (ntohs(micbuf.typelen) > 0x05DC)
-                                               bap_setup (apriv, fid, 0x44, BAP0);
-                                       else {
-                                               if (len <= sizeof(micbuf))
-                                                       goto badmic;
-
-                                               len -= sizeof(micbuf);
-                                               skb_trim (skb, len + hdrlen);
-                                       }
-                               }
-                               bap_read(apriv,buffer+ETH_ALEN,len,BAP0);
-                               if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) {
-badmic:
-                                       dev_kfree_skb_irq (skb);
-badrx:
-                                       OUT4500( apriv, EVACK, EV_RX);
-                                       goto exitrx;
+                               airo_print_err(ai->dev->name, "gaplen too "
+                                       "big. Problems will follow...");
+                       }
+               }
+               bap_read(ai, buffer + hdrlen/2, len, BAP0);
+       } else {
+               MICBuffer micbuf;
+
+               bap_read(ai, buffer, ETH_ALEN * 2, BAP0);
+               if (ai->micstats.enabled) {
+                       bap_read(ai, (__le16 *) &micbuf, sizeof (micbuf), BAP0);
+                       if (ntohs(micbuf.typelen) > 0x05DC)
+                               bap_setup(ai, fid, 0x44, BAP0);
+                       else {
+                               if (len <= sizeof (micbuf)) {
+                                       dev_kfree_skb_irq(skb);
+                                       goto done;
                                }
+
+                               len -= sizeof(micbuf);
+                               skb_trim(skb, len + hdrlen);
                        }
+               }
+
+               bap_read(ai, buffer + ETH_ALEN, len, BAP0);
+               if (decapsulate(ai, &micbuf, (etherHead*) buffer, len))
+                       dev_kfree_skb_irq (skb);
+               else
+                       success = 1;
+       }
+
 #ifdef WIRELESS_SPY
-                       if (apriv->spy_data.spy_number > 0) {
-                               char *sa;
-                               struct iw_quality wstats;
-                               /* Prepare spy data : addr + qual */
-                               if (!test_bit(FLAG_802_11, &apriv->flags)) {
-                                       sa = (char*)buffer + 6;
-                                       bap_setup (apriv, fid, 8, BAP0);
-                                       bap_read (apriv, (__le16*)hdr.rssi, 2, BAP0);
-                               } else
-                                       sa = (char*)buffer + 10;
-                               wstats.qual = hdr.rssi[0];
-                               if (apriv->rssi)
-                                       wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;
-                               else
-                                       wstats.level = (hdr.rssi[1] + 321) / 2;
-                               wstats.noise = apriv->wstats.qual.noise;
-                               wstats.updated = IW_QUAL_LEVEL_UPDATED
-                                       | IW_QUAL_QUAL_UPDATED
-                                       | IW_QUAL_DBM;
-                               /* Update spy records */
-                               wireless_spy_update(dev, sa, &wstats);
-                       }
+       if (success && (ai->spy_data.spy_number > 0)) {
+               char *sa;
+               struct iw_quality wstats;
+
+               /* Prepare spy data : addr + qual */
+               if (!test_bit(FLAG_802_11, &ai->flags)) {
+                       sa = (char *) buffer + 6;
+                       bap_setup(ai, fid, 8, BAP0);
+                       bap_read(ai, (__le16 *) hdr.rssi, 2, BAP0);
+               } else
+                       sa = (char *) buffer + 10;
+               wstats.qual = hdr.rssi[0];
+               if (ai->rssi)
+                       wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm;
+               else
+                       wstats.level = (hdr.rssi[1] + 321) / 2;
+               wstats.noise = ai->wstats.qual.noise;
+               wstats.updated =  IW_QUAL_LEVEL_UPDATED
+                               | IW_QUAL_QUAL_UPDATED
+                               | IW_QUAL_DBM;
+               /* Update spy records */
+               wireless_spy_update(ai->dev, sa, &wstats);
+       }
 #endif /* WIRELESS_SPY */
-                       OUT4500( apriv, EVACK, EV_RX);
 
-                       if (test_bit(FLAG_802_11, &apriv->flags)) {
-                               skb_reset_mac_header(skb);
-                               skb->pkt_type = PACKET_OTHERHOST;
-                               skb->dev = apriv->wifidev;
-                               skb->protocol = htons(ETH_P_802_2);
-                       } else
-                               skb->protocol = eth_type_trans(skb,dev);
-                       skb->dev->last_rx = jiffies;
-                       skb->ip_summed = CHECKSUM_NONE;
+done:
+       OUT4500(ai, EVACK, EV_RX);
+
+       if (success) {
+               if (test_bit(FLAG_802_11, &ai->flags)) {
+                       skb_reset_mac_header(skb);
+                       skb->pkt_type = PACKET_OTHERHOST;
+                       skb->dev = ai->wifidev;
+                       skb->protocol = htons(ETH_P_802_2);
+               } else
+                       skb->protocol = eth_type_trans(skb, ai->dev);
+               skb->ip_summed = CHECKSUM_NONE;
+
+               netif_rx(skb);
+       }
+}
+
+static void airo_handle_tx(struct airo_info *ai, u16 status)
+{
+       int i, len = 0, index = -1;
+       u16 fid;
+
+       if (test_bit(FLAG_MPI, &ai->flags)) {
+               unsigned long flags;
 
-                       netif_rx( skb );
+               if (status & EV_TXEXC)
+                       get_tx_error(ai, -1);
+
+               spin_lock_irqsave(&ai->aux_lock, flags);
+               if (!skb_queue_empty(&ai->txq)) {
+                       spin_unlock_irqrestore(&ai->aux_lock,flags);
+                       mpi_send_packet(ai->dev);
+               } else {
+                       clear_bit(FLAG_PENDING_XMIT, &ai->flags);
+                       spin_unlock_irqrestore(&ai->aux_lock,flags);
+                       netif_wake_queue(ai->dev);
                }
-exitrx:
+               OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
+               return;
+       }
 
-               /* Check to see if a packet has been transmitted */
-               if (  status & ( EV_TX|EV_TXCPY|EV_TXEXC ) ) {
-                       int i;
-                       int len = 0;
-                       int index = -1;
-
-                       if (test_bit(FLAG_MPI,&apriv->flags)) {
-                               unsigned long flags;
-
-                               if (status & EV_TXEXC)
-                                       get_tx_error(apriv, -1);
-                               spin_lock_irqsave(&apriv->aux_lock, flags);
-                               if (!skb_queue_empty(&apriv->txq)) {
-                                       spin_unlock_irqrestore(&apriv->aux_lock,flags);
-                                       mpi_send_packet (dev);
-                               } else {
-                                       clear_bit(FLAG_PENDING_XMIT, &apriv->flags);
-                                       spin_unlock_irqrestore(&apriv->aux_lock,flags);
-                                       netif_wake_queue (dev);
-                               }
-                               OUT4500( apriv, EVACK,
-                                       status & (EV_TX|EV_TXCPY|EV_TXEXC));
-                               goto exittx;
-                       }
+       fid = IN4500(ai, TXCOMPLFID);
+
+       for(i = 0; i < MAX_FIDS; i++) {
+               if ((ai->fids[i] & 0xffff) == fid) {
+                       len = ai->fids[i] >> 16;
+                       index = i;
+               }
+       }
 
-                       fid = IN4500(apriv, TXCOMPLFID);
+       if (index != -1) {
+               if (status & EV_TXEXC)
+                       get_tx_error(ai, index);
 
-                       for( i = 0; i < MAX_FIDS; i++ ) {
-                               if ( ( apriv->fids[i] & 0xffff ) == fid ) {
-                                       len = apriv->fids[i] >> 16;
-                                       index = i;
-                               }
-                       }
-                       if (index != -1) {
-                               if (status & EV_TXEXC)
-                                       get_tx_error(apriv, index);
-                               OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC));
-                               /* Set up to be used again */
-                               apriv->fids[index] &= 0xffff;
-                               if (index < MAX_FIDS / 2) {
-                                       if (!test_bit(FLAG_PENDING_XMIT, &apriv->flags))
-                                               netif_wake_queue(dev);
-                               } else {
-                                       if (!test_bit(FLAG_PENDING_XMIT11, &apriv->flags))
-                                               netif_wake_queue(apriv->wifidev);
-                               }
-                       } else {
-                               OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
-                               airo_print_err(apriv->dev->name, "Unallocated FID was "
-                                       "used to xmit" );
-                       }
+               OUT4500(ai, EVACK, status & (EV_TX | EV_TXEXC));
+
+               /* Set up to be used again */
+               ai->fids[index] &= 0xffff;
+               if (index < MAX_FIDS / 2) {
+                       if (!test_bit(FLAG_PENDING_XMIT, &ai->flags))
+                               netif_wake_queue(ai->dev);
+               } else {
+                       if (!test_bit(FLAG_PENDING_XMIT11, &ai->flags))
+                               netif_wake_queue(ai->wifidev);
                }
-exittx:
-               if ( status & ~STATUS_INTS & ~IGNORE_INTS )
-                       airo_print_warn(apriv->dev->name, "Got weird status %x",
+       } else {
+               OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
+               airo_print_err(ai->dev->name, "Unallocated FID was used to xmit");
+       }
+}
+
+static irqreturn_t airo_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       u16 status, savedInterrupts = 0;
+       struct airo_info *ai = dev->ml_priv;
+       int handled = 0;
+
+       if (!netif_device_present(dev))
+               return IRQ_NONE;
+
+       for (;;) {
+               status = IN4500(ai, EVSTAT);
+               if (!(status & STATUS_INTS) || (status == 0xffff))
+                       break;
+
+               handled = 1;
+
+               if (status & EV_AWAKE) {
+                       OUT4500(ai, EVACK, EV_AWAKE);
+                       OUT4500(ai, EVACK, EV_AWAKE);
+               }
+
+               if (!savedInterrupts) {
+                       savedInterrupts = IN4500(ai, EVINTEN);
+                       OUT4500(ai, EVINTEN, 0);
+               }
+
+               if (status & EV_MIC) {
+                       OUT4500(ai, EVACK, EV_MIC);
+                       airo_handle_cisco_mic(ai);
+               }
+
+               if (status & EV_LINK) {
+                       /* Link status changed */
+                       airo_handle_link(ai);
+               }
+
+               /* Check to see if there is something to receive */
+               if (status & EV_RX)
+                       airo_handle_rx(ai);
+
+               /* Check to see if a packet has been transmitted */
+               if (status & (EV_TX | EV_TXCPY | EV_TXEXC))
+                       airo_handle_tx(ai, status);
+
+               if ( status & ~STATUS_INTS & ~IGNORE_INTS ) {
+                       airo_print_warn(ai->dev->name, "Got weird status %x",
                                status & ~STATUS_INTS & ~IGNORE_INTS );
+               }
        }
 
        if (savedInterrupts)
-               OUT4500( apriv, EVINTEN, savedInterrupts );
+               OUT4500(ai, EVINTEN, savedInterrupts);
 
-       /* done.. */
        return IRQ_RETVAL(handled);
 }
 
@@ -3556,7 +3645,7 @@ static void mpi_receive_802_3(struct airo_info *ai)
 
                skb = dev_alloc_skb(len);
                if (!skb) {
-                       ai->stats.rx_dropped++;
+                       ai->dev->stats.rx_dropped++;
                        goto badrx;
                }
                buffer = skb_put(skb,len);
@@ -3597,7 +3686,6 @@ badmic:
 
                skb->ip_summed = CHECKSUM_NONE;
                skb->protocol = eth_type_trans(skb, ai->dev);
-               skb->dev->last_rx = jiffies;
                netif_rx(skb);
        }
 badrx:
@@ -3609,24 +3697,16 @@ badrx:
        }
 }
 
-void mpi_receive_802_11 (struct airo_info *ai)
+static void mpi_receive_802_11(struct airo_info *ai)
 {
        RxFid rxd;
        struct sk_buff *skb = NULL;
        u16 len, hdrlen = 0;
        __le16 fc;
-#pragma pack(1)
-       struct {
-               __le16 status, len;
-               u8 rssi[2];
-               u8 rate;
-               u8 freq;
-               __le16 tmp[4];
-       } hdr;
-#pragma pack()
+       struct rx_hdr hdr;
        u16 gap;
        u16 *buffer;
-       char *ptr = ai->rxfids[0].virtual_host_addr+4;
+       char *ptr = ai->rxfids[0].virtual_host_addr + 4;
 
        memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
        memcpy ((char *)&hdr, ptr, sizeof(hdr));
@@ -3649,7 +3729,7 @@ void mpi_receive_802_11 (struct airo_info *ai)
 
        skb = dev_alloc_skb( len + hdrlen + 2 );
        if ( !skb ) {
-               ai->stats.rx_dropped++;
+               ai->dev->stats.rx_dropped++;
                goto badrx;
        }
        buffer = (u16*)skb_put (skb, len + hdrlen);
@@ -3691,9 +3771,9 @@ void mpi_receive_802_11 (struct airo_info *ai)
        skb->pkt_type = PACKET_OTHERHOST;
        skb->dev = ai->wifidev;
        skb->protocol = htons(ETH_P_802_2);
-       skb->dev->last_rx = jiffies;
        skb->ip_summed = CHECKSUM_NONE;
        netif_rx( skb );
+
 badrx:
        if (rxd.valid == 0) {
                rxd.valid = 1;
@@ -3708,7 +3788,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
        Cmd cmd;
        Resp rsp;
        int status;
-       int i;
        SsidRid mySsid;
        __le16 lastindex;
        WepKeyRid wkr;
@@ -3750,6 +3829,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
        if (lock)
                up(&ai->sem);
        if (ai->config.len == 0) {
+               int i;
                tdsRssiRid rssi_rid;
                CapabilityRid cap_rid;
 
@@ -3797,22 +3877,11 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
                /* Check to see if there are any insmod configured
                   rates to add */
                if ( rates[0] ) {
-                       int i = 0;
                        memset(ai->config.rates,0,sizeof(ai->config.rates));
                        for( i = 0; i < 8 && rates[i]; i++ ) {
                                ai->config.rates[i] = rates[i];
                        }
                }
-               if ( basic_rate > 0 ) {
-                       int i;
-                       for( i = 0; i < 8; i++ ) {
-                               if ( ai->config.rates[i] == basic_rate ||
-                                    !ai->config.rates ) {
-                                       ai->config.rates[i] = basic_rate | 0x80;
-                                       break;
-                               }
-                       }
-               }
                set_bit (FLAG_COMMIT, &ai->flags);
        }
 
@@ -3879,7 +3948,7 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
 
        if ( max_tries == -1 ) {
                airo_print_err(ai->dev->name,
-                       "Max tries exceeded when issueing command");
+                       "Max tries exceeded when issuing command");
                if (IN4500(ai, COMMAND) & COMMAND_BUSY)
                        OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
                return ERROR;
@@ -4105,7 +4174,7 @@ done:
 }
 
 /*  Note, that we are using BAP1 which is also used by transmit, so
- *  make sure this isnt called when a transmit is happening */
+ *  make sure this isn't called when a transmit is happening */
 static int PC4500_writerid(struct airo_info *ai, u16 rid,
                           const void *pBuf, int len, int lock)
 {
@@ -4125,7 +4194,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
                if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid))
                        airo_print_err(ai->dev->name,
                                "%s: MAC should be disabled (rid=%04x)",
-                               __FUNCTION__, rid);
+                               __func__, rid);
                memset(&cmd, 0, sizeof(cmd));
                memset(&rsp, 0, sizeof(rsp));
 
@@ -4140,7 +4209,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
                        &ai->config_desc.rid_desc, sizeof(Rid));
 
                if (len < 4 || len > 2047) {
-                       airo_print_err(ai->dev->name, "%s: len=%d", __FUNCTION__, len);
+                       airo_print_err(ai->dev->name, "%s: len=%d", __func__, len);
                        rc = -1;
                } else {
                        memcpy((char *)ai->config_desc.virtual_host_addr,
@@ -4149,9 +4218,9 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
                        rc = issuecommand(ai, &cmd, &rsp);
                        if ((rc & 0xff00) != 0) {
                                airo_print_err(ai->dev->name, "%s: Write rid Error %d",
-                                               __FUNCTION__, rc);
+                                               __func__, rc);
                                airo_print_err(ai->dev->name, "%s: Cmd=%04x",
-                                               __FUNCTION__, cmd.cmd);
+                                               __func__, cmd.cmd);
                        }
 
                        if ((rsp.status & 0x7f00))
@@ -4350,21 +4419,24 @@ static const struct file_operations proc_statsdelta_ops = {
        .owner          = THIS_MODULE,
        .read           = proc_read,
        .open           = proc_statsdelta_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_stats_ops = {
        .owner          = THIS_MODULE,
        .read           = proc_read,
        .open           = proc_stats_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_status_ops = {
        .owner          = THIS_MODULE,
        .read           = proc_read,
        .open           = proc_status_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_SSID_ops = {
@@ -4372,7 +4444,8 @@ static const struct file_operations proc_SSID_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_SSID_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_BSSList_ops = {
@@ -4380,7 +4453,8 @@ static const struct file_operations proc_BSSList_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_BSSList_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_APList_ops = {
@@ -4388,7 +4462,8 @@ static const struct file_operations proc_APList_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_APList_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_config_ops = {
@@ -4396,7 +4471,8 @@ static const struct file_operations proc_config_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_config_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations proc_wepkey_ops = {
@@ -4404,7 +4480,8 @@ static const struct file_operations proc_wepkey_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_wepkey_open,
-       .release        = proc_close
+       .release        = proc_close,
+       .llseek         = default_llseek,
 };
 
 static struct proc_dir_entry *airo_entry;
@@ -4424,18 +4501,15 @@ static int setup_proc_entry( struct net_device *dev,
        struct proc_dir_entry *entry;
        /* First setup the device directory */
        strcpy(apriv->proc_name,dev->name);
-       apriv->proc_entry = create_proc_entry(apriv->proc_name,
-                                             S_IFDIR|airo_perm,
-                                             airo_entry);
+       apriv->proc_entry = proc_mkdir_mode(apriv->proc_name, airo_perm,
+                                           airo_entry);
        if (!apriv->proc_entry)
                goto fail;
        apriv->proc_entry->uid = proc_uid;
        apriv->proc_entry->gid = proc_gid;
-       apriv->proc_entry->owner = THIS_MODULE;
 
        /* Setup the StatsDelta */
-       entry = proc_create_data("StatsDelta",
-                                S_IFREG | (S_IRUGO&proc_perm),
+       entry = proc_create_data("StatsDelta", S_IRUGO & proc_perm,
                                 apriv->proc_entry, &proc_statsdelta_ops, dev);
        if (!entry)
                goto fail_stats_delta;
@@ -4443,8 +4517,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the Stats */
-       entry = proc_create_data("Stats",
-                                S_IFREG | (S_IRUGO&proc_perm),
+       entry = proc_create_data("Stats", S_IRUGO & proc_perm,
                                 apriv->proc_entry, &proc_stats_ops, dev);
        if (!entry)
                goto fail_stats;
@@ -4452,8 +4525,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the Status */
-       entry = proc_create_data("Status",
-                                S_IFREG | (S_IRUGO&proc_perm),
+       entry = proc_create_data("Status", S_IRUGO & proc_perm,
                                 apriv->proc_entry, &proc_status_ops, dev);
        if (!entry)
                goto fail_status;
@@ -4461,8 +4533,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the Config */
-       entry = proc_create_data("Config",
-                                S_IFREG | proc_perm,
+       entry = proc_create_data("Config", proc_perm,
                                 apriv->proc_entry, &proc_config_ops, dev);
        if (!entry)
                goto fail_config;
@@ -4470,8 +4541,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the SSID */
-       entry = proc_create_data("SSID",
-                                S_IFREG | proc_perm,
+       entry = proc_create_data("SSID", proc_perm,
                                 apriv->proc_entry, &proc_SSID_ops, dev);
        if (!entry)
                goto fail_ssid;
@@ -4479,8 +4549,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the APList */
-       entry = proc_create_data("APList",
-                                S_IFREG | proc_perm,
+       entry = proc_create_data("APList", proc_perm,
                                 apriv->proc_entry, &proc_APList_ops, dev);
        if (!entry)
                goto fail_aplist;
@@ -4488,8 +4557,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the BSSList */
-       entry = proc_create_data("BSSList",
-                                S_IFREG | proc_perm,
+       entry = proc_create_data("BSSList", proc_perm,
                                 apriv->proc_entry, &proc_BSSList_ops, dev);
        if (!entry)
                goto fail_bsslist;
@@ -4497,8 +4565,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the WepKey */
-       entry = proc_create_data("WepKey",
-                                S_IFREG | proc_perm,
+       entry = proc_create_data("WepKey", proc_perm,
                                 apriv->proc_entry, &proc_wepkey_ops, dev);
        if (!entry)
                goto fail_wepkey;
@@ -4559,22 +4626,13 @@ static ssize_t proc_read( struct file *file,
                          size_t len,
                          loff_t *offset )
 {
-       loff_t pos = *offset;
-       struct proc_data *priv = (struct proc_data*)file->private_data;
+       struct proc_data *priv = file->private_data;
 
        if (!priv->rbuffer)
                return -EINVAL;
 
-       if (pos < 0)
-               return -EINVAL;
-       if (pos >= priv->readlen)
-               return 0;
-       if (len > priv->readlen - pos)
-               len = priv->readlen - pos;
-       if (copy_to_user(buffer, priv->rbuffer + pos, len))
-               return -EFAULT;
-       *offset = pos + len;
-       return len;
+       return simple_read_from_buffer(buffer, len, offset, priv->rbuffer,
+                                       priv->readlen);
 }
 
 /*
@@ -4586,24 +4644,18 @@ static ssize_t proc_write( struct file *file,
                           size_t len,
                           loff_t *offset )
 {
-       loff_t pos = *offset;
-       struct proc_data *priv = (struct proc_data*)file->private_data;
+       ssize_t ret;
+       struct proc_data *priv = file->private_data;
 
        if (!priv->wbuffer)
                return -EINVAL;
 
-       if (pos < 0)
-               return -EINVAL;
-       if (pos >= priv->maxwritelen)
-               return 0;
-       if (len > priv->maxwritelen - pos)
-               len = priv->maxwritelen - pos;
-       if (copy_from_user(priv->wbuffer + pos, buffer, len))
-               return -EFAULT;
-       if ( pos + len > priv->writelen )
-               priv->writelen = len + file->f_pos;
-       *offset = pos + len;
-       return len;
+       ret = simple_write_to_buffer(priv->wbuffer, priv->maxwritelen, offset,
+                                       buffer, len);
+       if (ret > 0)
+               priv->writelen = max_t(int, priv->writelen, *offset);
+
+       return ret;
 }
 
 static int proc_status_open(struct inode *inode, struct file *file)
@@ -4611,7 +4663,7 @@ static int proc_status_open(struct inode *inode, struct file *file)
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *apriv = dev->priv;
+       struct airo_info *apriv = dev->ml_priv;
        CapabilityRid cap_rid;
        StatusRid status_rid;
        u16 mode;
@@ -4619,7 +4671,7 @@ static int proc_status_open(struct inode *inode, struct file *file)
 
        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
-       data = (struct proc_data *)file->private_data;
+       data = file->private_data;
        if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
                return -ENOMEM;
@@ -4694,28 +4746,29 @@ static int proc_stats_rid_open( struct inode *inode,
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *apriv = dev->priv;
+       struct airo_info *apriv = dev->ml_priv;
        StatsRid stats;
        int i, j;
        __le32 *vals = stats.vals;
-       int len = le16_to_cpu(stats.len);
+       int len;
 
        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
-       data = (struct proc_data *)file->private_data;
+       data = file->private_data;
        if ((data->rbuffer = kmalloc( 4096, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
                return -ENOMEM;
        }
 
        readStatsRid(apriv, &stats, rid, 1);
+       len = le16_to_cpu(stats.len);
 
         j = 0;
        for(i=0; statsLabels[i]!=(char *)-1 && i*4<len; i++) {
                if (!statsLabels[i]) continue;
                if (j+strlen(statsLabels[i])+16>4096) {
                        airo_print_warn(apriv->dev->name,
-                              "Potentially disasterous buffer overflow averted!");
+                              "Potentially disastrous buffer overflow averted!");
                        break;
                }
                j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i],
@@ -4731,9 +4784,8 @@ static int proc_stats_rid_open( struct inode *inode,
 static int get_dec_u16( char *buffer, int *start, int limit ) {
        u16 value;
        int valid = 0;
-       for( value = 0; buffer[*start] >= '0' &&
-                    buffer[*start] <= '9' &&
-                    *start < limit; (*start)++ ) {
+       for (value = 0; *start < limit && buffer[*start] >= '0' &&
+                       buffer[*start] <= '9'; (*start)++) {
                valid = 1;
                value *= 10;
                value += buffer[*start] - '0';
@@ -4748,7 +4800,7 @@ static int airo_config_commit(struct net_device *dev,
 
 static inline int sniffing_mode(struct airo_info *ai)
 {
-       return le16_to_cpu(ai->config.rmode & RXMODE_MASK) >=
+       return (le16_to_cpu(ai->config.rmode) & le16_to_cpu(RXMODE_MASK)) >=
                le16_to_cpu(RXMODE_RFMON);
 }
 
@@ -4757,7 +4809,7 @@ static void proc_config_on_close(struct inode *inode, struct file *file)
        struct proc_data *data = file->private_data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        char *line;
 
        if ( !data->writelen ) return;
@@ -4954,7 +5006,7 @@ static void proc_config_on_close(struct inode *inode, struct file *file)
        airo_config_commit(dev, NULL, NULL, NULL);
 }
 
-static char *get_rmode(__le16 mode)
+static const char *get_rmode(__le16 mode)
 {
         switch(mode & RXMODE_MASK) {
         case RXMODE_RFMON:  return "rfmon";
@@ -4969,13 +5021,13 @@ static int proc_config_open(struct inode *inode, struct file *file)
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        int i;
        __le16 mode;
 
        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
-       data = (struct proc_data *)file->private_data;
+       data = file->private_data;
        if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
                return -ENOMEM;
@@ -5057,10 +5109,10 @@ static int proc_config_open(struct inode *inode, struct file *file)
 
 static void proc_SSID_on_close(struct inode *inode, struct file *file)
 {
-       struct proc_data *data = (struct proc_data *)file->private_data;
+       struct proc_data *data = file->private_data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        SsidRid SSID_rid;
        int i;
        char *p = data->wbuffer;
@@ -5092,18 +5144,11 @@ static void proc_SSID_on_close(struct inode *inode, struct file *file)
        enable_MAC(ai, 1);
 }
 
-static inline u8 hexVal(char c) {
-       if (c>='0' && c<='9') return c -= '0';
-       if (c>='a' && c<='f') return c -= 'a'-10;
-       if (c>='A' && c<='F') return c -= 'A'-10;
-       return 0;
-}
-
 static void proc_APList_on_close( struct inode *inode, struct file *file ) {
-       struct proc_data *data = (struct proc_data *)file->private_data;
+       struct proc_data *data = file->private_data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        APListRid APList_rid;
        int i;
 
@@ -5118,11 +5163,11 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
                        switch(j%3) {
                        case 0:
                                APList_rid.ap[i][j/3]=
-                                       hexVal(data->wbuffer[j+i*6*3])<<4;
+                                       hex_to_bin(data->wbuffer[j+i*6*3])<<4;
                                break;
                        case 1:
                                APList_rid.ap[i][j/3]|=
-                                       hexVal(data->wbuffer[j+i*6*3]);
+                                       hex_to_bin(data->wbuffer[j+i*6*3]);
                                break;
                        }
                }
@@ -5143,77 +5188,122 @@ static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
        return rc;
 }
 
-/* Returns the length of the key at the index.  If index == 0xffff
- * the index of the transmit key is returned.  If the key doesn't exist,
- * -1 will be returned.
+/* Returns the WEP key at the specified index, or -1 if that key does
+ * not exist.  The buffer is assumed to be at least 16 bytes in length.
  */
-static int get_wep_key(struct airo_info *ai, u16 index) {
+static int get_wep_key(struct airo_info *ai, u16 index, char *buf, u16 buflen)
+{
        WepKeyRid wkr;
        int rc;
        __le16 lastindex;
 
        rc = readWepKeyRid(ai, &wkr, 1, 1);
-       if (rc == SUCCESS) do {
+       if (rc != SUCCESS)
+               return -1;
+       do {
                lastindex = wkr.kindex;
-               if (wkr.kindex == cpu_to_le16(index)) {
-                       if (index == 0xffff) {
-                               return wkr.mac[0];
-                       }
-                       return le16_to_cpu(wkr.klen);
+               if (le16_to_cpu(wkr.kindex) == index) {
+                       int klen = min_t(int, buflen, le16_to_cpu(wkr.klen));
+                       memcpy(buf, wkr.key, klen);
+                       return klen;
                }
-               readWepKeyRid(ai, &wkr, 0, 1);
+               rc = readWepKeyRid(ai, &wkr, 0, 1);
+               if (rc != SUCCESS)
+                       return -1;
+       } while (lastindex != wkr.kindex);
+       return -1;
+}
+
+static int get_wep_tx_idx(struct airo_info *ai)
+{
+       WepKeyRid wkr;
+       int rc;
+       __le16 lastindex;
+
+       rc = readWepKeyRid(ai, &wkr, 1, 1);
+       if (rc != SUCCESS)
+               return -1;
+       do {
+               lastindex = wkr.kindex;
+               if (wkr.kindex == cpu_to_le16(0xffff))
+                       return wkr.mac[0];
+               rc = readWepKeyRid(ai, &wkr, 0, 1);
+               if (rc != SUCCESS)
+                       return -1;
        } while (lastindex != wkr.kindex);
        return -1;
 }
 
-static int set_wep_key(struct airo_info *ai, u16 index,
-                      const char *key, u16 keylen, int perm, int lock )
+static int set_wep_key(struct airo_info *ai, u16 index, const char *key,
+                      u16 keylen, int perm, int lock)
 {
        static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
        WepKeyRid wkr;
+       int rc;
+
+       if (WARN_ON(keylen == 0))
+               return -1;
 
        memset(&wkr, 0, sizeof(wkr));
-       if (keylen == 0) {
-// We are selecting which key to use
-               wkr.len = cpu_to_le16(sizeof(wkr));
-               wkr.kindex = cpu_to_le16(0xffff);
-               wkr.mac[0] = (char)index;
-               if (perm) ai->defindex = (char)index;
-       } else {
-// We are actually setting the key
-               wkr.len = cpu_to_le16(sizeof(wkr));
-               wkr.kindex = cpu_to_le16(index);
-               wkr.klen = cpu_to_le16(keylen);
-               memcpy( wkr.key, key, keylen );
-               memcpy( wkr.mac, macaddr, ETH_ALEN );
-       }
+       wkr.len = cpu_to_le16(sizeof(wkr));
+       wkr.kindex = cpu_to_le16(index);
+       wkr.klen = cpu_to_le16(keylen);
+       memcpy(wkr.key, key, keylen);
+       memcpy(wkr.mac, macaddr, ETH_ALEN);
 
        if (perm) disable_MAC(ai, lock);
-       writeWepKeyRid(ai, &wkr, perm, lock);
+       rc = writeWepKeyRid(ai, &wkr, perm, lock);
        if (perm) enable_MAC(ai, lock);
-       return 0;
+       return rc;
+}
+
+static int set_wep_tx_idx(struct airo_info *ai, u16 index, int perm, int lock)
+{
+       WepKeyRid wkr;
+       int rc;
+
+       memset(&wkr, 0, sizeof(wkr));
+       wkr.len = cpu_to_le16(sizeof(wkr));
+       wkr.kindex = cpu_to_le16(0xffff);
+       wkr.mac[0] = (char)index;
+
+       if (perm) {
+               ai->defindex = (char)index;
+               disable_MAC(ai, lock);
+       }
+
+       rc = writeWepKeyRid(ai, &wkr, perm, lock);
+
+       if (perm)
+               enable_MAC(ai, lock);
+       return rc;
 }
 
 static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
-       int i;
+       struct airo_info *ai = dev->ml_priv;
+       int i, rc;
        char key[16];
        u16 index = 0;
        int j = 0;
 
        memset(key, 0, sizeof(key));
 
-       data = (struct proc_data *)file->private_data;
+       data = file->private_data;
        if ( !data->writelen ) return;
 
        if (data->wbuffer[0] >= '0' && data->wbuffer[0] <= '3' &&
            (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) {
                index = data->wbuffer[0] - '0';
                if (data->wbuffer[1] == '\n') {
-                       set_wep_key(ai, index, NULL, 0, 1, 1);
+                       rc = set_wep_tx_idx(ai, index, 1, 1);
+                       if (rc < 0) {
+                               airo_print_err(ai->dev->name, "failed to set "
+                                              "WEP transmit index to %d: %d.",
+                                              index, rc);
+                       }
                        return;
                }
                j = 2;
@@ -5225,14 +5315,19 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
        for( i = 0; i < 16*3 && data->wbuffer[i+j]; i++ ) {
                switch(i%3) {
                case 0:
-                       key[i/3] = hexVal(data->wbuffer[i+j])<<4;
+                       key[i/3] = hex_to_bin(data->wbuffer[i+j])<<4;
                        break;
                case 1:
-                       key[i/3] |= hexVal(data->wbuffer[i+j]);
+                       key[i/3] |= hex_to_bin(data->wbuffer[i+j]);
                        break;
                }
        }
-       set_wep_key(ai, index, key, i/3, 1, 1);
+
+       rc = set_wep_key(ai, index, key, i/3, 1, 1);
+       if (rc < 0) {
+               airo_print_err(ai->dev->name, "failed to set WEP key at index "
+                              "%d: %d.", index, rc);
+       }
 }
 
 static int proc_wepkey_open( struct inode *inode, struct file *file )
@@ -5240,7 +5335,7 @@ static int proc_wepkey_open( struct inode *inode, struct file *file )
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        char *ptr;
        WepKeyRid wkr;
        __le16 lastindex;
@@ -5250,7 +5345,7 @@ static int proc_wepkey_open( struct inode *inode, struct file *file )
        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
        memset(&wkr, 0, sizeof(wkr));
-       data = (struct proc_data *)file->private_data;
+       data = file->private_data;
        if ((data->rbuffer = kzalloc( 180, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
                return -ENOMEM;
@@ -5289,14 +5384,14 @@ static int proc_SSID_open(struct inode *inode, struct file *file)
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        int i;
        char *ptr;
        SsidRid SSID_rid;
 
        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
-       data = (struct proc_data *)file->private_data;
+       data = file->private_data;
        if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
                return -ENOMEM;
@@ -5333,15 +5428,14 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        int i;
        char *ptr;
        APListRid APList_rid;
-       DECLARE_MAC_BUF(mac);
 
        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
-       data = (struct proc_data *)file->private_data;
+       data = file->private_data;
        if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
                return -ENOMEM;
@@ -5361,8 +5455,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
 // We end when we find a zero MAC
                if ( !*(int*)APList_rid.ap[i] &&
                     !*(int*)&APList_rid.ap[i][2]) break;
-               ptr += sprintf(ptr, "%s\n",
-                              print_mac(mac, APList_rid.ap[i]));
+               ptr += sprintf(ptr, "%pM\n", APList_rid.ap[i]);
        }
        if (i==0) ptr += sprintf(ptr, "Not using specific APs\n");
 
@@ -5375,17 +5468,16 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        char *ptr;
        BSSListRid BSSList_rid;
        int rc;
        /* If doLoseSync is not 1, we won't do a Lose Sync */
        int doLoseSync = -1;
-       DECLARE_MAC_BUF(mac);
 
        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
-       data = (struct proc_data *)file->private_data;
+       data = file->private_data;
        if ((data->rbuffer = kmalloc( 1024, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
                return -ENOMEM;
@@ -5418,8 +5510,8 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
            we have to add a spin lock... */
        rc = readBSSListRid(ai, doLoseSync, &BSSList_rid);
        while(rc == 0 && BSSList_rid.index != cpu_to_le16(0xffff)) {
-               ptr += sprintf(ptr, "%s %*s rssi = %d",
-                              print_mac(mac, BSSList_rid.bssid),
+               ptr += sprintf(ptr, "%pM %*s rssi = %d",
+                              BSSList_rid.bssid,
                                (int)BSSList_rid.ssidLen,
                                BSSList_rid.ssid,
                                le16_to_cpu(BSSList_rid.dBm));
@@ -5454,7 +5546,7 @@ static int proc_close( struct inode *inode, struct file *file )
    associated we will check every minute to see if anything has
    changed. */
 static void timer_func( struct net_device *dev ) {
-       struct airo_info *apriv = dev->priv;
+       struct airo_info *apriv = dev->ml_priv;
 
 /* We don't have a link so try changing the authtype */
        readConfigRid(apriv, 0);
@@ -5466,13 +5558,13 @@ static void timer_func( struct net_device *dev ) {
                        break;
                case AUTH_SHAREDKEY:
                        if (apriv->keyindex < auto_wep) {
-                               set_wep_key(apriv, apriv->keyindex, NULL, 0, 0, 0);
+                               set_wep_tx_idx(apriv, apriv->keyindex, 0, 0);
                                apriv->config.authType = AUTH_SHAREDKEY;
                                apriv->keyindex++;
                        } else {
                                /* Drop to ENCRYPT */
                                apriv->keyindex = 0;
-                               set_wep_key(apriv, apriv->defindex, NULL, 0, 0, 0);
+                               set_wep_tx_idx(apriv, apriv->defindex, 0, 0);
                                apriv->config.authType = AUTH_ENCRYPT;
                        }
                        break;
@@ -5525,15 +5617,17 @@ static void __devexit airo_pci_remove(struct pci_dev *pdev)
 static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        Cmd cmd;
        Resp rsp;
 
-       if ((ai->APList == NULL) &&
-               (ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL)) == NULL)
+       if (!ai->APList)
+               ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL);
+       if (!ai->APList)
                return -ENOMEM;
-       if ((ai->SSID == NULL) &&
-               (ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL)) == NULL)
+       if (!ai->SSID)
+               ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL);
+       if (!ai->SSID)
                return -ENOMEM;
        readAPListRid(ai, ai->APList);
        readSsidRid(ai, ai->SSID);
@@ -5544,18 +5638,19 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
        disable_MAC(ai, 0);
        netif_device_detach(dev);
        ai->power = state;
-       cmd.cmd=HOSTSLEEP;
+       cmd.cmd = HOSTSLEEP;
        issuecommand(ai, &cmd, &rsp);
 
        pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
        pci_save_state(pdev);
-       return pci_set_power_state(pdev, pci_choose_state(pdev, state));
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+       return 0;
 }
 
 static int airo_pci_resume(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        pci_power_t prev_state = pdev->current_state;
 
        pci_set_power_state(pdev, PCI_D0);
@@ -5574,7 +5669,7 @@ static int airo_pci_resume(struct pci_dev *pdev)
                msleep(100);
        }
 
-       set_bit (FLAG_COMMIT, &ai->flags);
+       set_bit(FLAG_COMMIT, &ai->flags);
        disable_MAC(ai, 0);
         msleep(200);
        if (ai->SSID) {
@@ -5601,28 +5696,19 @@ static int airo_pci_resume(struct pci_dev *pdev)
 static int __init airo_init_module( void )
 {
        int i;
-#if 0
-       int have_isa_dev = 0;
-#endif
 
-       airo_entry = create_proc_entry("driver/aironet",
-                                      S_IFDIR | airo_perm,
-                                      NULL);
+       airo_entry = proc_mkdir_mode("driver/aironet", airo_perm, NULL);
 
        if (airo_entry) {
                airo_entry->uid = proc_uid;
                airo_entry->gid = proc_gid;
        }
 
-       for( i = 0; i < 4 && io[i] && irq[i]; i++ ) {
+       for (i = 0; i < 4 && io[i] && irq[i]; i++) {
                airo_print_info("", "Trying to configure ISA adapter at irq=%d "
                        "io=0x%x", irq[i], io[i] );
                if (init_airo_card( irq[i], io[i], 0, NULL ))
-#if 0
-                       have_isa_dev = 1;
-#else
                        /* do nothing */ ;
-#endif
        }
 
 #ifdef CONFIG_PCI
@@ -5668,7 +5754,7 @@ static void __exit airo_cleanup_module( void )
 
 static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi)
 {
-       if( !rssi_rid )
+       if (!rssi_rid)
                return 0;
 
        return (0x100 - rssi_rid[rssi].rssidBm);
@@ -5678,10 +5764,10 @@ static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm)
 {
        int i;
 
-       if( !rssi_rid )
+       if (!rssi_rid)
                return 0;
 
-       for( i = 0; i < 256; i++ )
+       for (i = 0; i < 256; i++)
                if (rssi_rid[i].rssidBm == dbm)
                        return rssi_rid[i].rssipct;
 
@@ -5741,20 +5827,16 @@ static int airo_set_freq(struct net_device *dev,
                         struct iw_freq *fwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        int rc = -EINPROGRESS;          /* Call commit handler */
 
        /* If setting by frequency, convert to a channel */
-       if((fwrq->e == 1) &&
-          (fwrq->m >= (int) 2.412e8) &&
-          (fwrq->m <= (int) 2.487e8)) {
+       if(fwrq->e == 1) {
                int f = fwrq->m / 100000;
-               int c = 0;
-               while((c < 14) && (f != frequency_list[c]))
-                       c++;
+
                /* Hack to fall through... */
                fwrq->e = 0;
-               fwrq->m = c + 1;
+               fwrq->m = ieee80211_freq_to_dsss_chan(f);
        }
        /* Setting by channel number */
        if((fwrq->m > 1000) || (fwrq->e > 0))
@@ -5786,7 +5868,7 @@ static int airo_get_freq(struct net_device *dev,
                         struct iw_freq *fwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        StatusRid status_rid;           /* Card status info */
        int ch;
 
@@ -5798,7 +5880,7 @@ static int airo_get_freq(struct net_device *dev,
 
        ch = le16_to_cpu(status_rid.channel);
        if((ch > 0) && (ch < 15)) {
-               fwrq->m = frequency_list[ch - 1] * 100000;
+               fwrq->m = ieee80211_dsss_chan_to_freq(ch) * 100000;
                fwrq->e = 1;
        } else {
                fwrq->m = ch;
@@ -5817,27 +5899,26 @@ static int airo_set_essid(struct net_device *dev,
                          struct iw_point *dwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        SsidRid SSID_rid;               /* SSIDs */
 
        /* Reload the list of current SSID */
        readSsidRid(local, &SSID_rid);
 
        /* Check if we asked for `any' */
-       if(dwrq->flags == 0) {
+       if (dwrq->flags == 0) {
                /* Just send an empty SSID list */
                memset(&SSID_rid, 0, sizeof(SSID_rid));
        } else {
-               int     index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+               unsigned index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 
                /* Check the size of the string */
-               if(dwrq->length > IW_ESSID_MAX_SIZE) {
+               if (dwrq->length > IW_ESSID_MAX_SIZE)
                        return -E2BIG ;
-               }
+
                /* Check if index is valid */
-               if((index < 0) || (index >= 4)) {
+               if (index >= ARRAY_SIZE(SSID_rid.ssids))
                        return -EINVAL;
-               }
 
                /* Set the SSID */
                memset(SSID_rid.ssids[index].ssid, 0,
@@ -5863,7 +5944,7 @@ static int airo_get_essid(struct net_device *dev,
                          struct iw_point *dwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        StatusRid status_rid;           /* Card status info */
 
        readStatusRid(local, &status_rid, 1);
@@ -5891,7 +5972,7 @@ static int airo_set_wap(struct net_device *dev,
                        struct sockaddr *awrq,
                        char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        Cmd cmd;
        Resp rsp;
        APListRid APList_rid;
@@ -5928,7 +6009,7 @@ static int airo_get_wap(struct net_device *dev,
                        struct sockaddr *awrq,
                        char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        StatusRid status_rid;           /* Card status info */
 
        readStatusRid(local, &status_rid, 1);
@@ -5949,7 +6030,7 @@ static int airo_set_nick(struct net_device *dev,
                         struct iw_point *dwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        /* Check the size of the string */
        if(dwrq->length > 16) {
@@ -5972,7 +6053,7 @@ static int airo_get_nick(struct net_device *dev,
                         struct iw_point *dwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        strncpy(extra, local->config.nodeName, 16);
@@ -5991,7 +6072,7 @@ static int airo_set_rate(struct net_device *dev,
                         struct iw_param *vwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        CapabilityRid cap_rid;          /* Card capability info */
        u8      brate = 0;
        int     i;
@@ -6061,7 +6142,7 @@ static int airo_get_rate(struct net_device *dev,
                         struct iw_param *vwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        StatusRid status_rid;           /* Card status info */
 
        readStatusRid(local, &status_rid, 1);
@@ -6083,7 +6164,7 @@ static int airo_set_rts(struct net_device *dev,
                        struct iw_param *vwrq,
                        char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        int rthr = vwrq->value;
 
        if(vwrq->disabled)
@@ -6107,7 +6188,7 @@ static int airo_get_rts(struct net_device *dev,
                        struct iw_param *vwrq,
                        char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        vwrq->value = le16_to_cpu(local->config.rtsThres);
@@ -6126,7 +6207,7 @@ static int airo_set_frag(struct net_device *dev,
                         struct iw_param *vwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        int fthr = vwrq->value;
 
        if(vwrq->disabled)
@@ -6151,7 +6232,7 @@ static int airo_get_frag(struct net_device *dev,
                         struct iw_param *vwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        vwrq->value = le16_to_cpu(local->config.fragThresh);
@@ -6170,7 +6251,7 @@ static int airo_set_mode(struct net_device *dev,
                         __u32 *uwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        int reset = 0;
 
        readConfigRid(local, 1);
@@ -6233,7 +6314,7 @@ static int airo_get_mode(struct net_device *dev,
                         __u32 *uwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        /* If not managed, assume it's ad-hoc */
@@ -6254,11 +6335,9 @@ static int airo_get_mode(struct net_device *dev,
        return 0;
 }
 
-static inline int valid_index(CapabilityRid *p, int index)
+static inline int valid_index(struct airo_info *ai, int index)
 {
-       if (index < 0)
-               return 0;
-       return index < (p->softCap & cpu_to_le16(0x80) ? 4 : 1);
+       return (index >= 0) && (index <= ai->max_wep_idx);
 }
 
 /*------------------------------------------------------------------*/
@@ -6270,17 +6349,14 @@ static int airo_set_encode(struct net_device *dev,
                           struct iw_point *dwrq,
                           char *extra)
 {
-       struct airo_info *local = dev->priv;
-       CapabilityRid cap_rid;          /* Card capability info */
-       int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 );
+       struct airo_info *local = dev->ml_priv;
+       int perm = (dwrq->flags & IW_ENCODE_TEMP ? 0 : 1);
        __le16 currentAuthType = local->config.authType;
+       int rc = 0;
 
-       /* Is WEP supported ? */
-       readCapabilityRid(local, &cap_rid, 1);
-       /* Older firmware doesn't support this...
-       if(!(cap_rid.softCap & cpu_to_le16(2))) {
+       if (!local->wep_capable)
                return -EOPNOTSUPP;
-       } */
+
        readConfigRid(local, 1);
 
        /* Basic checking: do we have a key to set ?
@@ -6292,23 +6368,26 @@ static int airo_set_encode(struct net_device *dev,
        if (dwrq->length > 0) {
                wep_key_t key;
                int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-               int current_index = get_wep_key(local, 0xffff);
+               int current_index;
+
                /* Check the size of the key */
                if (dwrq->length > MAX_KEY_SIZE) {
                        return -EINVAL;
                }
+
+               current_index = get_wep_tx_idx(local);
+               if (current_index < 0)
+                       current_index = 0;
+
                /* Check the index (none -> use current) */
-               if (!valid_index(&cap_rid, index))
+               if (!valid_index(local, index))
                        index = current_index;
+
                /* Set the length */
                if (dwrq->length > MIN_KEY_SIZE)
                        key.len = MAX_KEY_SIZE;
                else
-                       if (dwrq->length > 0)
-                               key.len = MIN_KEY_SIZE;
-                       else
-                               /* Disable the key */
-                               key.len = 0;
+                       key.len = MIN_KEY_SIZE;
                /* Check if the key is not marked as invalid */
                if(!(dwrq->flags & IW_ENCODE_NOKEY)) {
                        /* Cleanup */
@@ -6316,7 +6395,13 @@ static int airo_set_encode(struct net_device *dev,
                        /* Copy the key in the driver */
                        memcpy(key.key, extra, dwrq->length);
                        /* Send the key to the card */
-                       set_wep_key(local, index, key.key, key.len, perm, 1);
+                       rc = set_wep_key(local, index, key.key, key.len, perm, 1);
+                       if (rc < 0) {
+                               airo_print_err(local->dev->name, "failed to set"
+                                              " WEP key at index %d: %d.",
+                                              index, rc);
+                               return rc;
+                       }
                }
                /* WE specify that if a valid key is set, encryption
                 * should be enabled (user may turn it off later)
@@ -6328,12 +6413,19 @@ static int airo_set_encode(struct net_device *dev,
        } else {
                /* Do we want to just set the transmit key index ? */
                int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-               if (valid_index(&cap_rid, index)) {
-                       set_wep_key(local, index, NULL, 0, perm, 1);
-               } else
+               if (valid_index(local, index)) {
+                       rc = set_wep_tx_idx(local, index, perm, 1);
+                       if (rc < 0) {
+                               airo_print_err(local->dev->name, "failed to set"
+                                              " WEP transmit index to %d: %d.",
+                                              index, rc);
+                               return rc;
+                       }
+               } else {
                        /* Don't complain if only change the mode */
                        if (!(dwrq->flags & IW_ENCODE_MODE))
                                return -EINVAL;
+               }
        }
        /* Read the flags */
        if(dwrq->flags & IW_ENCODE_DISABLED)
@@ -6357,16 +6449,16 @@ static int airo_get_encode(struct net_device *dev,
                           struct iw_point *dwrq,
                           char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-       CapabilityRid cap_rid;          /* Card capability info */
+       int wep_key_len;
+       u8 buf[16];
 
-       /* Is it supported ? */
-       readCapabilityRid(local, &cap_rid, 1);
-       if(!(cap_rid.softCap & cpu_to_le16(2))) {
+       if (!local->wep_capable)
                return -EOPNOTSUPP;
-       }
+
        readConfigRid(local, 1);
+
        /* Check encryption mode */
        switch(local->config.authType)  {
                case AUTH_ENCRYPT:
@@ -6385,14 +6477,22 @@ static int airo_get_encode(struct net_device *dev,
        memset(extra, 0, 16);
 
        /* Which key do we want ? -1 -> tx index */
-       if (!valid_index(&cap_rid, index))
-               index = get_wep_key(local, 0xffff);
+       if (!valid_index(local, index)) {
+               index = get_wep_tx_idx(local);
+               if (index < 0)
+                       index = 0;
+       }
        dwrq->flags |= index + 1;
+
        /* Copy the key to the user buffer */
-       dwrq->length = get_wep_key(local, index);
-       if (dwrq->length > 16) {
-               dwrq->length=0;
+       wep_key_len = get_wep_key(local, index, &buf[0], sizeof(buf));
+       if (wep_key_len < 0) {
+               dwrq->length = 0;
+       } else {
+               dwrq->length = wep_key_len;
+               memcpy(extra, buf, dwrq->length);
        }
+
        return 0;
 }
 
@@ -6405,31 +6505,30 @@ static int airo_set_encodeext(struct net_device *dev,
                            union iwreq_data *wrqu,
                            char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        struct iw_point *encoding = &wrqu->encoding;
        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
-       CapabilityRid cap_rid;          /* Card capability info */
        int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 );
        __le16 currentAuthType = local->config.authType;
-       int idx, key_len, alg = ext->alg, set_key = 1;
+       int idx, key_len, alg = ext->alg, set_key = 1, rc;
        wep_key_t key;
 
-       /* Is WEP supported ? */
-       readCapabilityRid(local, &cap_rid, 1);
-       /* Older firmware doesn't support this...
-       if(!(cap_rid.softCap & cpu_to_le16(2))) {
+       if (!local->wep_capable)
                return -EOPNOTSUPP;
-       } */
+
        readConfigRid(local, 1);
 
        /* Determine and validate the key index */
        idx = encoding->flags & IW_ENCODE_INDEX;
        if (idx) {
-               if (!valid_index(&cap_rid, idx - 1))
+               if (!valid_index(local, idx - 1))
                        return -EINVAL;
                idx--;
-       } else
-               idx = get_wep_key(local, 0xffff);
+       } else {
+               idx = get_wep_tx_idx(local);
+               if (idx < 0)
+                       idx = 0;
+       }
 
        if (encoding->flags & IW_ENCODE_DISABLED)
                alg = IW_ENCODE_ALG_NONE;
@@ -6438,7 +6537,13 @@ static int airo_set_encodeext(struct net_device *dev,
                /* Only set transmit key index here, actual
                 * key is set below if needed.
                 */
-               set_wep_key(local, idx, NULL, 0, perm, 1);
+               rc = set_wep_tx_idx(local, idx, perm, 1);
+               if (rc < 0) {
+                       airo_print_err(local->dev->name, "failed to set "
+                                      "WEP transmit index to %d: %d.",
+                                      idx, rc);
+                       return rc;
+               }
                set_key = ext->key_len > 0 ? 1 : 0;
        }
 
@@ -6463,8 +6568,23 @@ static int airo_set_encodeext(struct net_device *dev,
                default:
                        return -EINVAL;
                }
-               /* Send the key to the card */
-               set_wep_key(local, idx, key.key, key.len, perm, 1);
+               if (key.len == 0) {
+                       rc = set_wep_tx_idx(local, idx, perm, 1);
+                       if (rc < 0) {
+                               airo_print_err(local->dev->name,
+                                              "failed to set WEP transmit index to %d: %d.",
+                                              idx, rc);
+                               return rc;
+                       }
+               } else {
+                       rc = set_wep_key(local, idx, key.key, key.len, perm, 1);
+                       if (rc < 0) {
+                               airo_print_err(local->dev->name,
+                                              "failed to set WEP key at index %d: %d.",
+                                              idx, rc);
+                               return rc;
+                       }
+               }
        }
 
        /* Read the flags */
@@ -6491,17 +6611,15 @@ static int airo_get_encodeext(struct net_device *dev,
                            union iwreq_data *wrqu,
                            char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        struct iw_point *encoding = &wrqu->encoding;
        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
-       CapabilityRid cap_rid;          /* Card capability info */
-       int idx, max_key_len;
+       int idx, max_key_len, wep_key_len;
+       u8 buf[16];
 
-       /* Is it supported ? */
-       readCapabilityRid(local, &cap_rid, 1);
-       if(!(cap_rid.softCap & cpu_to_le16(2))) {
+       if (!local->wep_capable)
                return -EOPNOTSUPP;
-       }
+
        readConfigRid(local, 1);
 
        max_key_len = encoding->length - sizeof(*ext);
@@ -6510,11 +6628,14 @@ static int airo_get_encodeext(struct net_device *dev,
 
        idx = encoding->flags & IW_ENCODE_INDEX;
        if (idx) {
-               if (!valid_index(&cap_rid, idx - 1))
+               if (!valid_index(local, idx - 1))
                        return -EINVAL;
                idx--;
-       } else
-               idx = get_wep_key(local, 0xffff);
+       } else {
+               idx = get_wep_tx_idx(local);
+               if (idx < 0)
+                       idx = 0;
+       }
 
        encoding->flags = idx + 1;
        memset(ext, 0, sizeof(*ext));
@@ -6537,9 +6658,12 @@ static int airo_get_encodeext(struct net_device *dev,
        memset(extra, 0, 16);
        
        /* Copy the key to the user buffer */
-       ext->key_len = get_wep_key(local, idx);
-       if (ext->key_len > 16) {
-               ext->key_len=0;
+       wep_key_len = get_wep_key(local, idx, &buf[0], sizeof(buf));
+       if (wep_key_len < 0) {
+               ext->key_len = 0;
+       } else {
+               ext->key_len = wep_key_len;
+               memcpy(extra, buf, ext->key_len);
        }
 
        return 0;
@@ -6554,7 +6678,7 @@ static int airo_set_auth(struct net_device *dev,
                               struct iw_request_info *info,
                               union iwreq_data *wrqu, char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        struct iw_param *param = &wrqu->param;
        __le16 currentAuthType = local->config.authType;
 
@@ -6594,11 +6718,11 @@ static int airo_set_auth(struct net_device *dev,
                                local->config.authType = AUTH_ENCRYPT;
                        } else
                                return -EINVAL;
-                       break;
 
                        /* Commit the changes to flags if needed */
                        if (local->config.authType != currentAuthType)
                                set_bit (FLAG_COMMIT, &local->flags);
+                       break;
                }
 
        case IW_AUTH_WPA_ENABLED:
@@ -6622,7 +6746,7 @@ static int airo_get_auth(struct net_device *dev,
                               struct iw_request_info *info,
                               union iwreq_data *wrqu, char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        struct iw_param *param = &wrqu->param;
        __le16 currentAuthType = local->config.authType;
 
@@ -6671,7 +6795,7 @@ static int airo_set_txpow(struct net_device *dev,
                          struct iw_param *vwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        CapabilityRid cap_rid;          /* Card capability info */
        int i;
        int rc = -EINVAL;
@@ -6688,7 +6812,7 @@ static int airo_set_txpow(struct net_device *dev,
                return -EINVAL;
        }
        clear_bit (FLAG_RADIO_OFF, &local->flags);
-       for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++)
+       for (i = 0; i < 8 && cap_rid.txPowerLevels[i]; i++)
                if (v == cap_rid.txPowerLevels[i]) {
                        readConfigRid(local, 1);
                        local->config.txPower = v;
@@ -6708,7 +6832,7 @@ static int airo_get_txpow(struct net_device *dev,
                          struct iw_param *vwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        vwrq->value = le16_to_cpu(local->config.txPower);
@@ -6728,7 +6852,7 @@ static int airo_set_retry(struct net_device *dev,
                          struct iw_param *vwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        int rc = -EINVAL;
 
        if(vwrq->disabled) {
@@ -6766,7 +6890,7 @@ static int airo_get_retry(struct net_device *dev,
                          struct iw_param *vwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        vwrq->disabled = 0;      /* Can't be disabled */
 
@@ -6797,7 +6921,7 @@ static int airo_get_range(struct net_device *dev,
                          struct iw_point *dwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        struct iw_range *range = (struct iw_range *) extra;
        CapabilityRid cap_rid;          /* Card capability info */
        int             i;
@@ -6815,8 +6939,8 @@ static int airo_get_range(struct net_device *dev,
        k = 0;
        for(i = 0; i < 14; i++) {
                range->freq[k].i = i + 1; /* List index */
-               range->freq[k].m = frequency_list[i] * 100000;
-               range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */
+               range->freq[k].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000;
+               range->freq[k++].e = 1; /* Values in MHz -> * 10^5 * 10 */
        }
        range->num_frequency = k;
 
@@ -6922,7 +7046,7 @@ static int airo_set_power(struct net_device *dev,
                          struct iw_param *vwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        if (vwrq->disabled) {
@@ -6979,7 +7103,7 @@ static int airo_get_power(struct net_device *dev,
                          struct iw_param *vwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        __le16 mode;
 
        readConfigRid(local, 1);
@@ -7010,7 +7134,7 @@ static int airo_set_sens(struct net_device *dev,
                         struct iw_param *vwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        local->config.rssiThreshold =
@@ -7029,7 +7153,7 @@ static int airo_get_sens(struct net_device *dev,
                         struct iw_param *vwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        vwrq->value = le16_to_cpu(local->config.rssiThreshold);
@@ -7049,13 +7173,17 @@ static int airo_get_aplist(struct net_device *dev,
                           struct iw_point *dwrq,
                           char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        struct sockaddr *address = (struct sockaddr *) extra;
-       struct iw_quality qual[IW_MAX_AP];
+       struct iw_quality *qual;
        BSSListRid BSSList;
        int i;
        int loseSync = capable(CAP_NET_ADMIN) ? 1: -1;
 
+       qual = kmalloc(IW_MAX_AP * sizeof(*qual), GFP_KERNEL);
+       if (!qual)
+               return -ENOMEM;
+
        for (i = 0; i < IW_MAX_AP; i++) {
                u16 dBm;
                if (readBSSListRid(local, loseSync, &BSSList))
@@ -7110,6 +7238,7 @@ static int airo_get_aplist(struct net_device *dev,
        }
        dwrq->length = i;
 
+       kfree(qual);
        return 0;
 }
 
@@ -7119,10 +7248,10 @@ static int airo_get_aplist(struct net_device *dev,
  */
 static int airo_set_scan(struct net_device *dev,
                         struct iw_request_info *info,
-                        struct iw_param *vwrq,
+                        struct iw_point *dwrq,
                         char *extra)
 {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        Cmd cmd;
        Resp rsp;
        int wake = 0;
@@ -7163,11 +7292,12 @@ out:
  * format that the Wireless Tools will understand - Jean II
  */
 static inline char *airo_translate_scan(struct net_device *dev,
+                                       struct iw_request_info *info,
                                        char *current_ev,
                                        char *end_buf,
                                        BSSListRid *bss)
 {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        struct iw_event         iwe;            /* Temporary buffer */
        __le16                  capabilities;
        char *                  current_val;    /* For rates */
@@ -7179,7 +7309,8 @@ static inline char *airo_translate_scan(struct net_device *dev,
        iwe.cmd = SIOCGIWAP;
        iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
        memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
-       current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
+       current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+                                         &iwe, IW_EV_ADDR_LEN);
 
        /* Other entries will be displayed in the order we give them */
 
@@ -7189,7 +7320,8 @@ static inline char *airo_translate_scan(struct net_device *dev,
                iwe.u.data.length = 32;
        iwe.cmd = SIOCGIWESSID;
        iwe.u.data.flags = 1;
-       current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid);
+       current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+                                         &iwe, bss->ssid);
 
        /* Add mode */
        iwe.cmd = SIOCGIWMODE;
@@ -7199,18 +7331,17 @@ static inline char *airo_translate_scan(struct net_device *dev,
                        iwe.u.mode = IW_MODE_MASTER;
                else
                        iwe.u.mode = IW_MODE_ADHOC;
-               current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
+               current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+                                                 &iwe, IW_EV_UINT_LEN);
        }
 
        /* Add frequency */
        iwe.cmd = SIOCGIWFREQ;
        iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
-       /* iwe.u.freq.m containt the channel (starting 1), our 
-        * frequency_list array start at index 0...
-        */
-       iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000;
+       iwe.u.freq.m = ieee80211_dsss_chan_to_freq(iwe.u.freq.m) * 100000;
        iwe.u.freq.e = 1;
-       current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
+       current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+                                         &iwe, IW_EV_FREQ_LEN);
 
        dBm = le16_to_cpu(bss->dBm);
 
@@ -7230,7 +7361,8 @@ static inline char *airo_translate_scan(struct net_device *dev,
                                | IW_QUAL_DBM;
        }
        iwe.u.qual.noise = ai->wstats.qual.noise;
-       current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+       current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+                                         &iwe, IW_EV_QUAL_LEN);
 
        /* Add encryption capability */
        iwe.cmd = SIOCGIWENCODE;
@@ -7239,11 +7371,12 @@ static inline char *airo_translate_scan(struct net_device *dev,
        else
                iwe.u.data.flags = IW_ENCODE_DISABLED;
        iwe.u.data.length = 0;
-       current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid);
+       current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+                                         &iwe, bss->ssid);
 
        /* Rate : stuffing multiple values in a single event require a bit
         * more of magic - Jean II */
-       current_val = current_ev + IW_EV_LCP_LEN;
+       current_val = current_ev + iwe_stream_lcp_len(info);
 
        iwe.cmd = SIOCGIWRATE;
        /* Those two flags are ignored... */
@@ -7256,10 +7389,12 @@ static inline char *airo_translate_scan(struct net_device *dev,
                /* Bit rate given in 500 kb/s units (+ 0x80) */
                iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000);
                /* Add new value to event */
-               current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
+               current_val = iwe_stream_add_value(info, current_ev,
+                                                  current_val, end_buf,
+                                                  &iwe, IW_EV_PARAM_LEN);
        }
        /* Check if we added any event */
-       if((current_val - current_ev) > IW_EV_LCP_LEN)
+       if ((current_val - current_ev) > iwe_stream_lcp_len(info))
                current_ev = current_val;
 
        /* Beacon interval */
@@ -7268,7 +7403,8 @@ static inline char *airo_translate_scan(struct net_device *dev,
                iwe.cmd = IWEVCUSTOM;
                sprintf(buf, "bcn_int=%d", bss->beaconInterval);
                iwe.u.data.length = strlen(buf);
-               current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf);
+               current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+                                                 &iwe, buf);
                kfree(buf);
        }
 
@@ -7276,53 +7412,53 @@ static inline char *airo_translate_scan(struct net_device *dev,
        if (test_bit(FLAG_WPA_CAPABLE, &ai->flags)) {
                unsigned int num_null_ies = 0;
                u16 length = sizeof (bss->extra.iep);
-               struct ieee80211_info_element *info_element =
-                       (struct ieee80211_info_element *) &bss->extra.iep;
+               u8 *ie = (void *)&bss->extra.iep;
 
-               while ((length >= sizeof(*info_element)) && (num_null_ies < 2)) {
-                       if (sizeof(*info_element) + info_element->len > length) {
+               while ((length >= 2) && (num_null_ies < 2)) {
+                       if (2 + ie[1] > length) {
                                /* Invalid element, don't continue parsing IE */
                                break;
                        }
 
-                       switch (info_element->id) {
-                       case MFIE_TYPE_SSID:
+                       switch (ie[0]) {
+                       case WLAN_EID_SSID:
                                /* Two zero-length SSID elements
                                 * mean we're done parsing elements */
-                               if (!info_element->len)
+                               if (!ie[1])
                                        num_null_ies++;
                                break;
 
-                       case MFIE_TYPE_GENERIC:
-                               if (info_element->len >= 4 &&
-                                   info_element->data[0] == 0x00 &&
-                                   info_element->data[1] == 0x50 &&
-                                   info_element->data[2] == 0xf2 &&
-                                   info_element->data[3] == 0x01) {
+                       case WLAN_EID_GENERIC:
+                               if (ie[1] >= 4 &&
+                                   ie[2] == 0x00 &&
+                                   ie[3] == 0x50 &&
+                                   ie[4] == 0xf2 &&
+                                   ie[5] == 0x01) {
                                        iwe.cmd = IWEVGENIE;
-                                       iwe.u.data.length = min(info_element->len + 2,
-                                                                 MAX_WPA_IE_LEN);
-                                       current_ev = iwe_stream_add_point(current_ev, end_buf,
-                                                       &iwe, (char *) info_element);
+                                       /* 64 is an arbitrary cut-off */
+                                       iwe.u.data.length = min(ie[1] + 2,
+                                                               64);
+                                       current_ev = iwe_stream_add_point(
+                                                       info, current_ev,
+                                                       end_buf, &iwe, ie);
                                }
                                break;
 
-                       case MFIE_TYPE_RSN:
+                       case WLAN_EID_RSN:
                                iwe.cmd = IWEVGENIE;
-                               iwe.u.data.length = min(info_element->len + 2,
-                                                         MAX_WPA_IE_LEN);
-                               current_ev = iwe_stream_add_point(current_ev, end_buf,
-                                               &iwe, (char *) info_element);
+                               /* 64 is an arbitrary cut-off */
+                               iwe.u.data.length = min(ie[1] + 2, 64);
+                               current_ev = iwe_stream_add_point(
+                                       info, current_ev, end_buf,
+                                       &iwe, ie);
                                break;
 
                        default:
                                break;
                        }
 
-                       length -= sizeof(*info_element) + info_element->len;
-                       info_element =
-                           (struct ieee80211_info_element *)&info_element->
-                           data[info_element->len];
+                       length -= 2 + ie[1];
+                       ie += 2 + ie[1];
                }
        }
        return current_ev;
@@ -7337,7 +7473,7 @@ static int airo_get_scan(struct net_device *dev,
                         struct iw_point *dwrq,
                         char *extra)
 {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        BSSListElement *net;
        int err = 0;
        char *current_ev = extra;
@@ -7351,7 +7487,7 @@ static int airo_get_scan(struct net_device *dev,
 
        list_for_each_entry (net, &ai->network_list, list) {
                /* Translate to WE format this entry */
-               current_ev = airo_translate_scan(dev, current_ev,
+               current_ev = airo_translate_scan(dev, info, current_ev,
                                                 extra + dwrq->length,
                                                 &net->bss);
 
@@ -7381,7 +7517,7 @@ static int airo_config_commit(struct net_device *dev,
                              void *zwrq,                       /* NULL */
                              char *extra)                      /* NULL */
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        if (!test_bit (FLAG_COMMIT, &local->flags))
                return 0;
@@ -7526,7 +7662,7 @@ static const struct iw_handler_def        airo_handler_def =
 static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        int rc = 0;
-       struct airo_info *ai = (struct airo_info *)dev->priv;
+       struct airo_info *ai = dev->ml_priv;
 
        if (ai->power.event)
                return 0;
@@ -7654,7 +7790,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
 
 static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
 {
-       struct airo_info *local =  dev->priv;
+       struct airo_info *local =  dev->ml_priv;
 
        if (!test_bit(JOB_WSTATS, &local->jobs)) {
                /* Get stats out of the card if available */
@@ -7679,7 +7815,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
        unsigned short ridcode;
        unsigned char *iobuf;
        int len;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
 
        if (test_bit(FLAG_FLASHING, &ai->flags))
                return -EIO;
@@ -7745,7 +7881,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
  */
 
 static int writerids(struct net_device *dev, aironet_ioctl *comp) {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        int  ridcode;
         int  enabled;
        static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
@@ -7868,41 +8004,41 @@ static int flashcard(struct net_device *dev, aironet_ioctl *comp) {
        switch(comp->command)
        {
        case AIROFLSHRST:
-               return cmdreset((struct airo_info *)dev->priv);
+               return cmdreset((struct airo_info *)dev->ml_priv);
 
        case AIROFLSHSTFL:
-               if (!((struct airo_info *)dev->priv)->flash &&
-                       (((struct airo_info *)dev->priv)->flash = kmalloc (FLASHSIZE, GFP_KERNEL)) == NULL)
+               if (!AIRO_FLASH(dev) &&
+                   (AIRO_FLASH(dev) = kmalloc(FLASHSIZE, GFP_KERNEL)) == NULL)
                        return -ENOMEM;
-               return setflashmode((struct airo_info *)dev->priv);
+               return setflashmode((struct airo_info *)dev->ml_priv);
 
        case AIROFLSHGCHR: /* Get char from aux */
                if(comp->len != sizeof(int))
                        return -EINVAL;
                if (copy_from_user(&z,comp->data,comp->len))
                        return -EFAULT;
-               return flashgchar((struct airo_info *)dev->priv,z,8000);
+               return flashgchar((struct airo_info *)dev->ml_priv, z, 8000);
 
        case AIROFLSHPCHR: /* Send char to card. */
                if(comp->len != sizeof(int))
                        return -EINVAL;
                if (copy_from_user(&z,comp->data,comp->len))
                        return -EFAULT;
-               return flashpchar((struct airo_info *)dev->priv,z,8000);
+               return flashpchar((struct airo_info *)dev->ml_priv, z, 8000);
 
        case AIROFLPUTBUF: /* Send 32k to card */
-               if (!((struct airo_info *)dev->priv)->flash)
+               if (!AIRO_FLASH(dev))
                        return -ENOMEM;
                if(comp->len > FLASHSIZE)
                        return -EINVAL;
-               if(copy_from_user(((struct airo_info *)dev->priv)->flash,comp->data,comp->len))
+               if (copy_from_user(AIRO_FLASH(dev), comp->data, comp->len))
                        return -EFAULT;
 
-               flashputbuf((struct airo_info *)dev->priv);
+               flashputbuf((struct airo_info *)dev->ml_priv);
                return 0;
 
        case AIRORESTART:
-               if(flashrestart((struct airo_info *)dev->priv,dev))
+               if (flashrestart((struct airo_info *)dev->ml_priv, dev))
                        return -EIO;
                return 0;
        }