[PATCH] libertas: tweak association debug output
[safe/jmp/linux-2.6] / drivers / net / wireless / airo.c
index 16befbc..2d3a180 100644 (file)
 
 ======================================================================*/
 
+#include <linux/err.h>
 #include <linux/init.h>
 
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
 
 #include <linux/sched.h>
 #include <linux/ptrace.h>
@@ -47,6 +47,8 @@
 #include <linux/pci.h>
 #include <asm/uaccess.h>
 #include <net/ieee80211.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
 
 #include "airo.h"
 
@@ -1118,8 +1120,7 @@ static void mpi_receive_802_3(struct airo_info *ai);
 static void mpi_receive_802_11(struct airo_info *ai);
 static int waitbusy (struct airo_info *ai);
 
-static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs
-                           *regs);
+static irqreturn_t airo_interrupt( int irq, void* dev_id);
 static int airo_thread(void *data);
 static void timer_func( struct net_device *dev );
 static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -1143,6 +1144,7 @@ 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
@@ -1187,11 +1189,10 @@ struct airo_info {
                        int whichbap);
        unsigned short *flash;
        tdsRssiEntry *rssi;
-       struct task_struct *task;
+       struct task_struct *list_bss_task;
+       struct task_struct *airo_thread_task;
        struct semaphore sem;
-       pid_t thr_pid;
        wait_queue_head_t thr_wait;
-       struct completion thr_exited;
        unsigned long expires;
        struct {
                struct sk_buff *skb;
@@ -1203,7 +1204,7 @@ struct airo_info {
        struct iw_spy_data      spy_data;
        struct iw_public_data   wireless_data;
        /* MIC stuff */
-       struct crypto_tfm       *tfm;
+       struct crypto_cipher    *tfm;
        mic_module              mod[2];
        mic_statistics          micstats;
        HostRxDesc rxfids[MPI_MAX_FIDS]; // rx/tx/config MPI350 descriptors
@@ -1271,7 +1272,8 @@ static int flashrestart(struct airo_info *ai,struct net_device *dev);
 
 static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq);
 static void MoveWindow(miccntx *context, u32 micSeq);
-static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *);
+static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen,
+                          struct crypto_cipher *tfm);
 static void emmh32_init(emmh32_context *context);
 static void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
 static void emmh32_final(emmh32_context *context, u8 digest[4]);
@@ -1339,10 +1341,11 @@ static int micsetup(struct airo_info *ai) {
        int i;
 
        if (ai->tfm == NULL)
-               ai->tfm = crypto_alloc_tfm("aes", CRYPTO_TFM_REQ_MAY_SLEEP);
+               ai->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
 
-        if (ai->tfm == NULL) {
+        if (IS_ERR(ai->tfm)) {
                 airo_print_err(ai->dev->name, "failed to load transform for AES");
+                ai->tfm = NULL;
                 return ERROR;
         }
 
@@ -1608,7 +1611,8 @@ static void MoveWindow(miccntx *context, u32 micSeq)
 static unsigned char aes_counter[16];
 
 /* expand the key to fill the MMH coefficient array */
-static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *tfm)
+static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen,
+                          struct crypto_cipher *tfm)
 {
   /* take the keying material, expand if necessary, truncate at 16-bytes */
   /* run through AES counter mode to generate context->coeff[] */
@@ -1616,21 +1620,19 @@ static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct
        int i,j;
        u32 counter;
        u8 *cipher, plain[16];
-       struct scatterlist sg[1];
 
        crypto_cipher_setkey(tfm, pkey, 16);
        counter = 0;
-       for (i = 0; i < (sizeof(context->coeff)/sizeof(context->coeff[0])); ) {
+       for (i = 0; i < ARRAY_SIZE(context->coeff); ) {
                aes_counter[15] = (u8)(counter >> 0);
                aes_counter[14] = (u8)(counter >> 8);
                aes_counter[13] = (u8)(counter >> 16);
                aes_counter[12] = (u8)(counter >> 24);
                counter++;
                memcpy (plain, aes_counter, 16);
-               sg_set_buf(sg, plain, 16);
-               crypto_cipher_encrypt(tfm, sg, sg, 16);
-               cipher = kmap(sg->page) + sg->offset;
-               for (j=0; (j<16) && (i< (sizeof(context->coeff)/sizeof(context->coeff[0]))); ) {
+               crypto_cipher_encrypt_one(tfm, plain, plain);
+               cipher = plain;
+               for (j = 0; (j < 16) && (i < ARRAY_SIZE(context->coeff)); ) {
                        context->coeff[i++] = ntohl(*(u32 *)&cipher[j]);
                        j += 4;
                }
@@ -1733,12 +1735,12 @@ static int readBSSListRid(struct airo_info *ai, int first,
                cmd.cmd=CMD_LISTBSS;
                if (down_interruptible(&ai->sem))
                        return -ERESTARTSYS;
+               ai->list_bss_task = current;
                issuecommand(ai, &cmd, &rsp);
                up(&ai->sem);
                /* Let the command take effect */
-               ai->task = current;
-               ssleep(3);
-               ai->task = NULL;
+               schedule_timeout_uninterruptible(3 * HZ);
+               ai->list_bss_task = NULL;
        }
        rc = PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext,
                            list, ai->bssListRidLen, 1);
@@ -2358,6 +2360,21 @@ static int airo_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
+static LIST_HEAD(airo_devices);
+
+static void add_airo_dev(struct airo_info *ai)
+{
+       /* Upper layers already keep track of PCI devices,
+        * so we only need to remember our non-PCI cards. */
+       if (!ai->pci)
+               list_add_tail(&ai->dev_list, &airo_devices);
+}
+
+static void del_airo_dev(struct airo_info *ai)
+{
+       if (!ai->pci)
+               list_del(&ai->dev_list);
+}
 
 static int airo_close(struct net_device *dev) {
        struct airo_info *ai = dev->priv;
@@ -2379,8 +2396,6 @@ static int airo_close(struct net_device *dev) {
        return 0;
 }
 
-static void del_airo_dev( struct net_device *dev );
-
 void stop_airo_card( struct net_device *dev, int freeres )
 {
        struct airo_info *ai = dev->priv;
@@ -2400,8 +2415,7 @@ void stop_airo_card( struct net_device *dev, int freeres )
                clear_bit(FLAG_REGISTERED, &ai->flags);
        }
        set_bit(JOB_DIE, &ai->jobs);
-       kill_proc(ai->thr_pid, SIGTERM, 1);
-       wait_for_completion(&ai->thr_exited);
+       kthread_stop(ai->airo_thread_task);
 
        /*
         * Clean out tx queue
@@ -2432,18 +2446,16 @@ void stop_airo_card( struct net_device *dev, int freeres )
                                ai->shared, ai->shared_dma);
                }
         }
-       crypto_free_tfm(ai->tfm);
-       del_airo_dev( dev );
+       crypto_free_cipher(ai->tfm);
+       del_airo_dev(ai);
        free_netdev( dev );
 }
 
 EXPORT_SYMBOL(stop_airo_card);
 
-static int add_airo_dev( struct net_device *dev );
-
 static int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
 {
-       memcpy(haddr, skb->mac.raw + 10, ETH_ALEN);
+       memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN);
        return ETH_ALEN;
 }
 
@@ -2739,8 +2751,6 @@ static int airo_networks_allocate(struct airo_info *ai)
 
 static void airo_networks_free(struct airo_info *ai)
 {
-       if (!ai->networks)
-               return;
        kfree(ai->networks);
        ai->networks = NULL;
 }
@@ -2811,17 +2821,14 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        ai->config.len = 0;
        ai->pci = pci;
        init_waitqueue_head (&ai->thr_wait);
-       init_completion (&ai->thr_exited);
-       ai->thr_pid = kernel_thread(airo_thread, dev, CLONE_FS | CLONE_FILES);
-       if (ai->thr_pid < 0)
+       ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name);
+       if (IS_ERR(ai->airo_thread_task))
                goto err_out_free;
        ai->tfm = NULL;
-       rc = add_airo_dev( dev );
-       if (rc)
-               goto err_out_thr;
+       add_airo_dev(ai);
 
        if (airo_networks_allocate (ai))
-               goto err_out_unlink;
+               goto err_out_thr;
        airo_networks_initialize (ai);
 
        /* The Airo-specific entries in the device structure. */
@@ -2852,7 +2859,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        if (rc) {
                airo_print_err(dev->name, "register interrupt %d failed, rc %d",
                                irq, rc);
-               goto err_out_unlink;
+               goto err_out_nets;
        }
        if (!is_pcmcia) {
                if (!request_region( dev->base_addr, 64, dev->name )) {
@@ -2898,6 +2905,8 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
                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 %x:%x:%x:%x:%x:%x",
@@ -2909,11 +2918,18 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
                for( i = 0; i < MAX_FIDS; i++ )
                        ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
 
-       setup_proc_entry( dev, dev->priv ); /* XXX check for failure */
+       if (setup_proc_entry(dev, dev->priv) < 0)
+               goto err_out_wifi;
+
        netif_start_queue(dev);
        SET_MODULE_OWNER(dev);
        return dev;
 
+err_out_wifi:
+       unregister_netdev(ai->wifidev);
+       free_netdev(ai->wifidev);
+err_out_reg:
+       unregister_netdev(dev);
 err_out_map:
        if (test_bit(FLAG_MPI,&ai->flags) && pci) {
                pci_free_consistent(pci, PCI_SHARED_LEN, ai->shared, ai->shared_dma);
@@ -2926,12 +2942,12 @@ err_out_res:
                release_region( dev->base_addr, 64 );
 err_out_irq:
        free_irq(dev->irq, dev);
-err_out_unlink:
-       del_airo_dev(dev);
+err_out_nets:
+       airo_networks_free(ai);
 err_out_thr:
+       del_airo_dev(ai);
        set_bit(JOB_DIE, &ai->jobs);
-       kill_proc(ai->thr_pid, SIGTERM, 1);
-       wait_for_completion(&ai->thr_exited);
+       kthread_stop(ai->airo_thread_task);
 err_out_free:
        free_netdev(dev);
        return NULL;
@@ -3063,13 +3079,7 @@ static int airo_thread(void *data) {
        struct airo_info *ai = dev->priv;
        int locked;
        
-       daemonize("%s", dev->name);
-       allow_signal(SIGTERM);
-
        while(1) {
-               if (signal_pending(current))
-                       flush_signals(current);
-
                /* make swsusp happy with our thread */
                try_to_freeze();
 
@@ -3097,7 +3107,8 @@ static int airo_thread(void *data) {
                                                set_bit(JOB_AUTOWEP, &ai->jobs);
                                                break;
                                        }
-                                       if (!signal_pending(current)) {
+                                       if (!kthread_should_stop() &&
+                                           !freezing(current)) {
                                                unsigned long wake_at;
                                                if (!ai->expires || !ai->scan_timeout) {
                                                        wake_at = max(ai->expires,
@@ -3109,7 +3120,8 @@ static int airo_thread(void *data) {
                                                schedule_timeout(wake_at - jiffies);
                                                continue;
                                        }
-                               } else if (!signal_pending(current)) {
+                               } else if (!kthread_should_stop() &&
+                                          !freezing(current)) {
                                        schedule();
                                        continue;
                                }
@@ -3154,10 +3166,11 @@ static int airo_thread(void *data) {
                else  /* Shouldn't get here, but we make sure to unlock */
                        up(&ai->sem);
        }
-       complete_and_exit (&ai->thr_exited, 0);
+
+       return 0;
 }
 
-static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) {
+static irqreturn_t airo_interrupt ( int irq, void* dev_id) {
        struct net_device *dev = (struct net_device *)dev_id;
        u16 status;
        u16 fid;
@@ -3235,8 +3248,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
                        if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
                                if (auto_wep)
                                        apriv->expires = 0;
-                               if (apriv->task)
-                                       wake_up_process (apriv->task);
+                               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);
 
@@ -3404,14 +3417,12 @@ badrx:
                        OUT4500( apriv, EVACK, EV_RX);
 
                        if (test_bit(FLAG_802_11, &apriv->flags)) {
-                               skb->mac.raw = skb->data;
+                               skb_reset_mac_header(skb);
                                skb->pkt_type = PACKET_OTHERHOST;
                                skb->dev = apriv->wifidev;
                                skb->protocol = htons(ETH_P_802_2);
-                       } else {
-                               skb->dev = dev;
+                       } else
                                skb->protocol = eth_type_trans(skb,dev);
-                       }
                        skb->dev->last_rx = jiffies;
                        skb->ip_summed = CHECKSUM_NONE;
 
@@ -3634,7 +3645,6 @@ badmic:
                }
 #endif /* WIRELESS_SPY */
 
-               skb->dev = ai->dev;
                skb->ip_summed = CHECKSUM_NONE;
                skb->protocol = eth_type_trans(skb, ai->dev);
                skb->dev->last_rx = jiffies;
@@ -3742,7 +3752,7 @@ void mpi_receive_802_11 (struct airo_info *ai)
                wireless_spy_update(ai->dev, sa, &wstats);
        }
 #endif /* IW_WIRELESS_SPY */
-       skb->mac.raw = skb->data;
+       skb_reset_mac_header(skb);
        skb->pkt_type = PACKET_OTHERHOST;
        skb->dev = ai->wifidev;
        skb->protocol = htons(ETH_P_802_2);
@@ -4425,53 +4435,53 @@ static int proc_BSSList_open( struct inode *inode, struct file *file );
 static int proc_config_open( struct inode *inode, struct file *file );
 static int proc_wepkey_open( struct inode *inode, struct file *file );
 
-static struct file_operations proc_statsdelta_ops = {
+static const struct file_operations proc_statsdelta_ops = {
        .read           = proc_read,
        .open           = proc_statsdelta_open,
        .release        = proc_close
 };
 
-static struct file_operations proc_stats_ops = {
+static const struct file_operations proc_stats_ops = {
        .read           = proc_read,
        .open           = proc_stats_open,
        .release        = proc_close
 };
 
-static struct file_operations proc_status_ops = {
+static const struct file_operations proc_status_ops = {
        .read           = proc_read,
        .open           = proc_status_open,
        .release        = proc_close
 };
 
-static struct file_operations proc_SSID_ops = {
+static const struct file_operations proc_SSID_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_SSID_open,
        .release        = proc_close
 };
 
-static struct file_operations proc_BSSList_ops = {
+static const struct file_operations proc_BSSList_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_BSSList_open,
        .release        = proc_close
 };
 
-static struct file_operations proc_APList_ops = {
+static const struct file_operations proc_APList_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_APList_open,
        .release        = proc_close
 };
 
-static struct file_operations proc_config_ops = {
+static const struct file_operations proc_config_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_config_open,
        .release        = proc_close
 };
 
-static struct file_operations proc_wepkey_ops = {
+static const struct file_operations proc_wepkey_ops = {
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_wepkey_open,
@@ -4502,91 +4512,128 @@ static int setup_proc_entry( struct net_device *dev,
        apriv->proc_entry = create_proc_entry(apriv->proc_name,
                                              S_IFDIR|airo_perm,
                                              airo_entry);
-        apriv->proc_entry->uid = proc_uid;
-        apriv->proc_entry->gid = proc_gid;
-        apriv->proc_entry->owner = THIS_MODULE;
+       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 = create_proc_entry("StatsDelta",
                                  S_IFREG | (S_IRUGO&proc_perm),
                                  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+       if (!entry)
+               goto fail_stats_delta;
+       entry->uid = proc_uid;
+       entry->gid = proc_gid;
        entry->data = dev;
-        entry->owner = THIS_MODULE;
+       entry->owner = THIS_MODULE;
        SETPROC_OPS(entry, proc_statsdelta_ops);
 
        /* Setup the Stats */
        entry = create_proc_entry("Stats",
                                  S_IFREG | (S_IRUGO&proc_perm),
                                  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+       if (!entry)
+               goto fail_stats;
+       entry->uid = proc_uid;
+       entry->gid = proc_gid;
        entry->data = dev;
-        entry->owner = THIS_MODULE;
+       entry->owner = THIS_MODULE;
        SETPROC_OPS(entry, proc_stats_ops);
 
        /* Setup the Status */
        entry = create_proc_entry("Status",
                                  S_IFREG | (S_IRUGO&proc_perm),
                                  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+       if (!entry)
+               goto fail_status;
+       entry->uid = proc_uid;
+       entry->gid = proc_gid;
        entry->data = dev;
-        entry->owner = THIS_MODULE;
+       entry->owner = THIS_MODULE;
        SETPROC_OPS(entry, proc_status_ops);
 
        /* Setup the Config */
        entry = create_proc_entry("Config",
                                  S_IFREG | proc_perm,
                                  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+       if (!entry)
+               goto fail_config;
+       entry->uid = proc_uid;
+       entry->gid = proc_gid;
        entry->data = dev;
-        entry->owner = THIS_MODULE;
+       entry->owner = THIS_MODULE;
        SETPROC_OPS(entry, proc_config_ops);
 
        /* Setup the SSID */
        entry = create_proc_entry("SSID",
                                  S_IFREG | proc_perm,
                                  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+       if (!entry)
+               goto fail_ssid;
+       entry->uid = proc_uid;
+       entry->gid = proc_gid;
        entry->data = dev;
-        entry->owner = THIS_MODULE;
+       entry->owner = THIS_MODULE;
        SETPROC_OPS(entry, proc_SSID_ops);
 
        /* Setup the APList */
        entry = create_proc_entry("APList",
                                  S_IFREG | proc_perm,
                                  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+       if (!entry)
+               goto fail_aplist;
+       entry->uid = proc_uid;
+       entry->gid = proc_gid;
        entry->data = dev;
-        entry->owner = THIS_MODULE;
+       entry->owner = THIS_MODULE;
        SETPROC_OPS(entry, proc_APList_ops);
 
        /* Setup the BSSList */
        entry = create_proc_entry("BSSList",
                                  S_IFREG | proc_perm,
                                  apriv->proc_entry);
+       if (!entry)
+               goto fail_bsslist;
        entry->uid = proc_uid;
        entry->gid = proc_gid;
        entry->data = dev;
-        entry->owner = THIS_MODULE;
+       entry->owner = THIS_MODULE;
        SETPROC_OPS(entry, proc_BSSList_ops);
 
        /* Setup the WepKey */
        entry = create_proc_entry("WepKey",
                                  S_IFREG | proc_perm,
                                  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+       if (!entry)
+               goto fail_wepkey;
+       entry->uid = proc_uid;
+       entry->gid = proc_gid;
        entry->data = dev;
-        entry->owner = THIS_MODULE;
+       entry->owner = THIS_MODULE;
        SETPROC_OPS(entry, proc_wepkey_ops);
 
        return 0;
+
+fail_wepkey:
+       remove_proc_entry("BSSList", apriv->proc_entry);
+fail_bsslist:
+       remove_proc_entry("APList", apriv->proc_entry);
+fail_aplist:
+       remove_proc_entry("SSID", apriv->proc_entry);
+fail_ssid:
+       remove_proc_entry("Config", apriv->proc_entry);
+fail_config:
+       remove_proc_entry("Status", apriv->proc_entry);
+fail_status:
+       remove_proc_entry("Stats", apriv->proc_entry);
+fail_stats:
+       remove_proc_entry("StatsDelta", apriv->proc_entry);
+fail_stats_delta:
+       remove_proc_entry(apriv->proc_name, airo_entry);
+fail:
+       return -ENOMEM;
 }
 
 static int takedown_proc_entry( struct net_device *dev,
@@ -5494,11 +5541,6 @@ static int proc_close( struct inode *inode, struct file *file )
        return 0;
 }
 
-static struct net_device_list {
-       struct net_device *dev;
-       struct net_device_list *next;
-} *airo_devices;
-
 /* Since the card doesn't automatically switch to the right WEP mode,
    we will make it do it.  If the card isn't associated, every secs we
    will switch WEP modes to see if that will help.  If the card is
@@ -5541,26 +5583,6 @@ static void timer_func( struct net_device *dev ) {
        apriv->expires = RUN_AT(HZ*3);
 }
 
-static int add_airo_dev( struct net_device *dev ) {
-       struct net_device_list *node = kmalloc( sizeof( *node ), GFP_KERNEL );
-       if ( !node )
-               return -ENOMEM;
-
-       node->dev = dev;
-       node->next = airo_devices;
-       airo_devices = node;
-
-       return 0;
-}
-
-static void del_airo_dev( struct net_device *dev ) {
-       struct net_device_list **p = &airo_devices;
-       while( *p && ( (*p)->dev != dev ) )
-               p = &(*p)->next;
-       if ( *p && (*p)->dev == dev )
-               *p = (*p)->next;
-}
-
 #ifdef CONFIG_PCI
 static int __devinit airo_pci_probe(struct pci_dev *pdev,
                                    const struct pci_device_id *pent)
@@ -5584,6 +5606,10 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev,
 
 static void __devexit airo_pci_remove(struct pci_dev *pdev)
 {
+       struct net_device *dev = pci_get_drvdata(pdev);
+
+       airo_print_info(dev->name, "Unregistering...");
+       stop_airo_card(dev, 1);
 }
 
 static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -5665,25 +5691,40 @@ static int airo_pci_resume(struct pci_dev *pdev)
 
 static int __init airo_init_module( void )
 {
-       int i, have_isa_dev = 0;
+       int i;
+#if 0
+       int have_isa_dev = 0;
+#endif
 
        airo_entry = create_proc_entry("aironet",
                                       S_IFDIR | airo_perm,
                                       proc_root_driver);
-        airo_entry->uid = proc_uid;
-        airo_entry->gid = proc_gid;
+
+       if (airo_entry) {
+               airo_entry->uid = proc_uid;
+               airo_entry->gid = proc_gid;
+       }
 
        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
        airo_print_info("", "Probing for PCI adapters");
-       pci_register_driver(&airo_driver);
+       i = pci_register_driver(&airo_driver);
        airo_print_info("", "Finished probing for PCI adapters");
+
+       if (i) {
+               remove_proc_entry("aironet", proc_root_driver);
+               return i;
+       }
 #endif
 
        /* Always exit with success, as we are a library module
@@ -5694,9 +5735,11 @@ static int __init airo_init_module( void )
 
 static void __exit airo_cleanup_module( void )
 {
-       while( airo_devices ) {
-               airo_print_info(airo_devices->dev->name, "Unregistering...\n");
-               stop_airo_card( airo_devices->dev, 1 );
+       struct airo_info *ai;
+       while(!list_empty(&airo_devices)) {
+               ai = list_entry(airo_devices.next, struct airo_info, dev_list);
+               airo_print_info(ai->dev->name, "Unregistering...");
+               stop_airo_card(ai->dev, 1);
        }
 #ifdef CONFIG_PCI
        pci_unregister_driver(&airo_driver);
@@ -5874,7 +5917,7 @@ static int airo_set_essid(struct net_device *dev,
                int     index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 
                /* Check the size of the string */
-               if(dwrq->length > IW_ESSID_MAX_SIZE+1) {
+               if(dwrq->length > IW_ESSID_MAX_SIZE) {
                        return -E2BIG ;
                }
                /* Check if index is valid */
@@ -5886,7 +5929,7 @@ static int airo_set_essid(struct net_device *dev,
                memset(SSID_rid.ssids[index].ssid, 0,
                       sizeof(SSID_rid.ssids[index].ssid));
                memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length);
-               SSID_rid.ssids[index].len = dwrq->length - 1;
+               SSID_rid.ssids[index].len = dwrq->length;
        }
        SSID_rid.len = sizeof(SSID_rid);
        /* Write it to the card */
@@ -5916,7 +5959,6 @@ static int airo_get_essid(struct net_device *dev,
 
        /* Get the current SSID */
        memcpy(extra, status_rid.SSID, status_rid.SSIDlen);
-       extra[status_rid.SSIDlen] = '\0';
        /* If none, we may want to get the one that was set */
 
        /* Push it out ! */
@@ -5996,7 +6038,7 @@ static int airo_set_nick(struct net_device *dev,
        struct airo_info *local = dev->priv;
 
        /* Check the size of the string */
-       if(dwrq->length > 16 + 1) {
+       if(dwrq->length > 16) {
                return -E2BIG;
        }
        readConfigRid(local, 1);
@@ -6021,7 +6063,7 @@ static int airo_get_nick(struct net_device *dev,
        readConfigRid(local, 1);
        strncpy(extra, local->config.nodeName, 16);
        extra[16] = '\0';
-       dwrq->length = strlen(extra) + 1;
+       dwrq->length = strlen(extra);
 
        return 0;
 }
@@ -6773,9 +6815,9 @@ static int airo_set_retry(struct net_device *dev,
        }
        readConfigRid(local, 1);
        if(vwrq->flags & IW_RETRY_LIMIT) {
-               if(vwrq->flags & IW_RETRY_MAX)
+               if(vwrq->flags & IW_RETRY_LONG)
                        local->config.longRetryLimit = vwrq->value;
-               else if (vwrq->flags & IW_RETRY_MIN)
+               else if (vwrq->flags & IW_RETRY_SHORT)
                        local->config.shortRetryLimit = vwrq->value;
                else {
                        /* No modifier : set both */
@@ -6811,14 +6853,14 @@ static int airo_get_retry(struct net_device *dev,
        if((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
                vwrq->flags = IW_RETRY_LIFETIME;
                vwrq->value = (int)local->config.txLifetime * 1024;
-       } else if((vwrq->flags & IW_RETRY_MAX)) {
-               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+       } else if((vwrq->flags & IW_RETRY_LONG)) {
+               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                vwrq->value = (int)local->config.longRetryLimit;
        } else {
                vwrq->flags = IW_RETRY_LIMIT;
                vwrq->value = (int)local->config.shortRetryLimit;
                if((int)local->config.shortRetryLimit != (int)local->config.longRetryLimit)
-                       vwrq->flags |= IW_RETRY_MIN;
+                       vwrq->flags |= IW_RETRY_SHORT;
        }
 
        return 0;
@@ -6996,6 +7038,7 @@ static int airo_set_power(struct net_device *dev,
                        local->config.rmode |= RXMODE_BC_MC_ADDR;
                        set_bit (FLAG_COMMIT, &local->flags);
                case IW_POWER_ON:
+                       /* This is broken, fixme ;-) */
                        break;
                default:
                        return -EINVAL;