patch-2.4.0-test8 linux/drivers/net/pcmcia/ray_cs.c

Next file: linux/drivers/net/pcmcia/smc91c92_cs.c
Previous file: linux/drivers/net/pcmcia/pcnet_cs.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test7/linux/drivers/net/pcmcia/ray_cs.c linux/drivers/net/pcmcia/ray_cs.c
@@ -318,6 +318,23 @@
     error_info_t err = { func, ret };
     pcmcia_report_error(handle, &err);
 }
+/*======================================================================
+
+    This bit of code is used to avoid unregistering network devices
+    at inappropriate times.  2.2 and later kernels are fairly picky
+    about when this can happen.
+    
+======================================================================*/
+
+static void flush_stale_links(void)
+{
+    dev_link_t *link, *next;
+    for (link = dev_list; link; link = next) {
+	next = link->next;
+	if (link->state & DEV_STALE_LINK)
+	    ray_detach(link);
+    }
+}
 
 /*=============================================================================
     ray_attach() creates an "instance" of the driver, allocating
@@ -336,6 +353,7 @@
     struct net_device *dev;
     
     DEBUG(1, "ray_attach()\n");
+    flush_stale_links();
 
     /* Initialize the dev_link_t structure */
     link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
@@ -384,7 +402,6 @@
     
     dev->priv = local;
     local->finder = link;
-    link->dev = &local->node;
     local->card_status = CARD_INSERTED;
     local->authentication_state = UNAUTHENTICATED;
     local->num_multi = 0;
@@ -451,8 +468,6 @@
 static void ray_detach(dev_link_t *link)
 {
     dev_link_t **linkp;
-    struct net_device *dev;
-    long flags;
 
     DEBUG(1, "ray_detach(0x%p)\n", link);
     
@@ -462,19 +477,12 @@
     if (*linkp == NULL)
         return;
 
-    save_flags(flags);
-    cli();
-    if (link->state & DEV_RELEASE_PENDING) {
-        del_timer(&link->release);
-        link->state &= ~DEV_RELEASE_PENDING;
-    }
-    restore_flags(flags);
-
     /* If the device is currently configured and active, we won't
       actually delete it yet.  Instead, it is marked so that when
       the release() function is called, that will trigger a proper
       detach().
     */
+    del_timer(&link->release);
     if (link->state & DEV_CONFIG) {
         ray_release((u_long)link);
         if(link->state & DEV_STALE_CONFIG) {
@@ -490,10 +498,10 @@
     /* Unlink device structure, free pieces */
     *linkp = link->next;
     if (link->priv) {
-        dev = link->priv;
+        struct net_device *dev = link->priv;
+	if (link->dev) unregister_netdev(dev);
         if (dev->priv)
             kfree(dev->priv);
-
         kfree(link->priv);
     }
     kfree(link);
@@ -606,6 +614,7 @@
     }
 
     strcpy(local->node.dev_name, dev->name);
+    link->dev = &local->node;
 
     link->state &= ~DEV_CONFIG_PENDING;
     printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ",
@@ -907,9 +916,7 @@
         return;
     }
     del_timer(&local->timer);
-    if (link->dev != '\0') unregister_netdev(dev);
-    /* Unlink the device chain */
-    link->dev = NULL;
+    link->state &= ~DEV_CONFIG;
 
     iounmap(local->sram);
     iounmap(local->rmem);
@@ -926,8 +933,6 @@
     i = pcmcia_release_irq(link->handle, &link->irq);
     if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i);
 
-    link->state &= ~DEV_CONFIG;
-    if (link->state & DEV_STALE_LINK) ray_detach(link);
     DEBUG(2,"ray_release ending\n");
 } /* ray_release */
 /*=============================================================================
@@ -954,8 +959,7 @@
         link->state &= ~DEV_PRESENT;
         netif_device_detach(dev);
         if (link->state & DEV_CONFIG) {
-            link->release.expires = jiffies + HZ/20;
-            add_timer(&link->release);
+            mod_timer(&link->release, jiffies + HZ/20);
             del_timer(&local->timer);
         }
         break;
@@ -1006,7 +1010,7 @@
     if ( (i = dl_startup_params(dev)) < 0)
     {
         printk(KERN_INFO "ray_dev_init dl_startup_params failed - "
-           "returns 0x%x/n",i);
+           "returns 0x%x\n",i);
         return -1;
     }
     
@@ -1554,11 +1558,8 @@
 
     link->open--;
     netif_stop_queue(dev);
-    if (link->state & DEV_STALE_CONFIG) {
-        link->release.expires = jiffies + HZ/20;
-        link->state |= DEV_RELEASE_PENDING;
-        add_timer(&link->release);
-    }
+    if (link->state & DEV_STALE_CONFIG)
+	mod_timer(&link->release, jiffies + HZ/20);
 
     MOD_DEC_USE_COUNT;
 
@@ -2773,10 +2774,9 @@
 #endif
 
     unregister_pcmcia_driver(&dev_info);
-    while (dev_list != NULL) {
-        if (dev_list->state & DEV_CONFIG) ray_release((u_long)dev_list);
+    while (dev_list != NULL)
         ray_detach(dev_list);
-    }
+
 #ifdef CONFIG_PROC_FS
     remove_proc_entry("driver/ray_cs/ray_cs", NULL);
     remove_proc_entry("driver/ray_cs/essid", NULL);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)