[PATCH] pcmcia: unify detach, REMOVAL_EVENT handlers into one remove callback

Unify the "detach" and REMOVAL_EVENT handlers to one "remove" function.
Old functionality is preserved, for the moment.

Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>

diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index 5c822f5..45c25c7 100644
--- a/Documentation/pcmcia/driver-changes.txt
+++ b/Documentation/pcmcia/driver-changes.txt
@@ -1,5 +1,8 @@
 This file details changes in 2.6 which affect PCMCIA card driver authors:
 
+* Unify detach and REMOVAL event code (as of 2.6.16)
+        void (*remove)          (struct pcmcia_device *dev);
+
 * Move suspend, resume and reset out of event handler (as of 2.6.16)
        int (*suspend)          (struct pcmcia_device *dev);
        int (*resume)           (struct pcmcia_device *dev);
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 5b24131..f5088cb 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -92,7 +92,7 @@
 static dev_info_t dev_info = "bluecard_cs";
 
 static dev_link_t *bluecard_attach(void);
-static void bluecard_detach(dev_link_t *);
+static void bluecard_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list = NULL;
 
@@ -899,7 +899,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != CS_SUCCESS) {
 		cs_error(link->handle, RegisterClient, ret);
-		bluecard_detach(link);
+		bluecard_detach(link->handle);
 		return NULL;
 	}
 
@@ -907,11 +907,11 @@
 }
 
 
-static void bluecard_detach(dev_link_t *link)
+static void bluecard_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	bluecard_info_t *info = link->priv;
 	dev_link_t **linkp;
-	int ret;
 
 	/* Locate device structure */
 	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
@@ -924,12 +924,6 @@
 	if (link->state & DEV_CONFIG)
 		bluecard_release(link);
 
-	if (link->handle) {
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
-	}
-
 	/* Unlink device structure, free bits */
 	*linkp = link->next;
 
@@ -1070,16 +1064,8 @@
 static int bluecard_event(event_t event, int priority, event_callback_args_t *args)
 {
 	dev_link_t *link = args->client_data;
-	bluecard_info_t *info = link->priv;
 
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			bluecard_close(info);
-			bluecard_release(link);
-		}
-		break;
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		bluecard_config(link);
@@ -1104,7 +1090,7 @@
 	},
 	.attach		= bluecard_attach,
 	.event		= bluecard_event,
-	.detach		= bluecard_detach,
+	.remove		= bluecard_detach,
 	.id_table	= bluecard_ids,
 	.suspend	= bluecard_suspend,
 	.resume		= bluecard_resume,
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 1d524ba..02ce38e 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -95,7 +95,7 @@
 static dev_info_t dev_info = "bt3c_cs";
 
 static dev_link_t *bt3c_attach(void);
-static void bt3c_detach(dev_link_t *);
+static void bt3c_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list = NULL;
 
@@ -700,7 +700,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != CS_SUCCESS) {
 		cs_error(link->handle, RegisterClient, ret);
-		bt3c_detach(link);
+		bt3c_detach(link->handle);
 		return NULL;
 	}
 
@@ -708,11 +708,11 @@
 }
 
 
-static void bt3c_detach(dev_link_t *link)
+static void bt3c_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	bt3c_info_t *info = link->priv;
 	dev_link_t **linkp;
-	int ret;
 
 	/* Locate device structure */
 	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
@@ -725,12 +725,6 @@
 	if (link->state & DEV_CONFIG)
 		bt3c_release(link);
 
-	if (link->handle) {
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
-	}
-
 	/* Unlink device structure, free bits */
 	*linkp = link->next;
 
@@ -916,16 +910,8 @@
 static int bt3c_event(event_t event, int priority, event_callback_args_t *args)
 {
 	dev_link_t *link = args->client_data;
-	bt3c_info_t *info = link->priv;
 
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			bt3c_close(info);
-			bt3c_release(link);
-		}
-		break;
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		bt3c_config(link);
@@ -948,7 +934,7 @@
 	},
 	.attach		= bt3c_attach,
 	.event		= bt3c_event,
-	.detach		= bt3c_detach,
+	.remove		= bt3c_detach,
 	.id_table	= bt3c_ids,
 	.suspend	= bt3c_suspend,
 	.resume		= bt3c_resume,
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 1828ba6..63221d3 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -91,7 +91,7 @@
 static dev_info_t dev_info = "btuart_cs";
 
 static dev_link_t *btuart_attach(void);
-static void btuart_detach(dev_link_t *);
+static void btuart_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list = NULL;
 
@@ -619,7 +619,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != CS_SUCCESS) {
 		cs_error(link->handle, RegisterClient, ret);
-		btuart_detach(link);
+		btuart_detach(link->handle);
 		return NULL;
 	}
 
@@ -627,11 +627,11 @@
 }
 
 
-static void btuart_detach(dev_link_t *link)
+static void btuart_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	btuart_info_t *info = link->priv;
 	dev_link_t **linkp;
-	int ret;
 
 	/* Locate device structure */
 	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
@@ -644,12 +644,6 @@
 	if (link->state & DEV_CONFIG)
 		btuart_release(link);
 
-	if (link->handle) {
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
-	}
-
 	/* Unlink device structure, free bits */
 	*linkp = link->next;
 
@@ -837,16 +831,8 @@
 static int btuart_event(event_t event, int priority, event_callback_args_t *args)
 {
 	dev_link_t *link = args->client_data;
-	btuart_info_t *info = link->priv;
 
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			btuart_close(info);
-			btuart_release(link);
-		}
-		break;
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		btuart_config(link);
@@ -869,7 +855,7 @@
 	},
 	.attach		= btuart_attach,
 	.event		= btuart_event,
-	.detach		= btuart_detach,
+	.remove		= btuart_detach,
 	.id_table	= btuart_ids,
 	.suspend	= btuart_suspend,
 	.resume		= btuart_resume,
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 9f9d3f9..2874d87 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -94,7 +94,7 @@
 static dev_info_t dev_info = "dtl1_cs";
 
 static dev_link_t *dtl1_attach(void);
-static void dtl1_detach(dev_link_t *);
+static void dtl1_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list = NULL;
 
@@ -598,7 +598,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != CS_SUCCESS) {
 		cs_error(link->handle, RegisterClient, ret);
-		dtl1_detach(link);
+		dtl1_detach(link->handle);
 		return NULL;
 	}
 
@@ -606,11 +606,11 @@
 }
 
 
-static void dtl1_detach(dev_link_t *link)
+static void dtl1_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	dtl1_info_t *info = link->priv;
 	dev_link_t **linkp;
-	int ret;
 
 	/* Locate device structure */
 	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
@@ -623,12 +623,6 @@
 	if (link->state & DEV_CONFIG)
 		dtl1_release(link);
 
-	if (link->handle) {
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
-	}
-
 	/* Unlink device structure, free bits */
 	*linkp = link->next;
 
@@ -788,16 +782,8 @@
 static int dtl1_event(event_t event, int priority, event_callback_args_t *args)
 {
 	dev_link_t *link = args->client_data;
-	dtl1_info_t *info = link->priv;
 
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			dtl1_close(info);
-			dtl1_release(link);
-		}
-		break;
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		dtl1_config(link);
@@ -821,7 +807,7 @@
 	},
 	.attach		= dtl1_attach,
 	.event		= dtl1_event,
-	.detach		= dtl1_detach,
+	.remove		= dtl1_detach,
 	.id_table	= dtl1_ids,
 	.suspend	= dtl1_suspend,
 	.resume		= dtl1_resume,
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 05e9305..8a064f2 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -66,7 +66,7 @@
 #define	T_100MSEC	msecs_to_jiffies(100)
 #define	T_500MSEC	msecs_to_jiffies(500)
 
-static void cm4000_detach(dev_link_t *link);
+static void cm4000_detach(struct pcmcia_device *p_dev);
 static void cm4000_release(dev_link_t *link);
 
 static int major;		/* major number we get from the kernel */
@@ -1888,11 +1888,6 @@
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		cm4000_config(link, devno);
 		break;
-	case CS_EVENT_CARD_REMOVAL:
-		DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n");
-		link->state &= ~DEV_PRESENT;
-		stop_monitor(dev);
-		break;
 	default:
 		DEBUGP(5, dev, "unknown event %.2x\n", event);
 		break;
@@ -1978,7 +1973,7 @@
 	i = pcmcia_register_client(&link->handle, &client_reg);
 	if (i) {
 		cs_error(link->handle, RegisterClient, i);
-		cm4000_detach(link);
+		cm4000_detach(link->handle);
 		return NULL;
 	}
 
@@ -1990,39 +1985,28 @@
 	return link;
 }
 
-static void cm4000_detach_by_devno(int devno, dev_link_t * link)
+static void cm4000_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct cm4000_dev *dev = link->priv;
-
-	DEBUGP(3, dev, "-> detach_by_devno(devno=%d)\n", devno);
-
-	if (link->state & DEV_CONFIG) {
-		DEBUGP(5, dev, "device still configured (try to release it)\n");
-		cm4000_release(link);
-	}
-
-	if (link->handle) {
-		pcmcia_deregister_client(link->handle);
-	}
-
-	dev_table[devno] = NULL;
-	kfree(dev);
-	return;
-}
-
-static void cm4000_detach(dev_link_t * link)
-{
-	int i;
+	int devno;
 
 	/* find device */
-	for (i = 0; i < CM4000_MAX_DEV; i++)
-		if (dev_table[i] == link)
+	for (devno = 0; devno < CM4000_MAX_DEV; devno++)
+		if (dev_table[devno] == link)
 			break;
-
-	if (i == CM4000_MAX_DEV)
+	if (devno == CM4000_MAX_DEV)
 		return;
 
-	cm4000_detach_by_devno(i, link);
+	link->state &= ~DEV_PRESENT;
+	stop_monitor(dev);
+
+	if (link->state & DEV_CONFIG)
+ 		cm4000_release(link);
+
+	dev_table[devno] = NULL;
+ 	kfree(dev);
+
 	return;
 }
 
@@ -2048,7 +2032,7 @@
 		.name = "cm4000_cs",
 		},
 	.attach   = cm4000_attach,
-	.detach   = cm4000_detach,
+	.remove   = cm4000_detach,
 	.suspend  = cm4000_suspend,
 	.resume   = cm4000_resume,
 	.event	  = cm4000_event,
@@ -2071,13 +2055,8 @@
 
 static void __exit cmm_exit(void)
 {
-	int i;
-
 	printk(KERN_INFO MODULE_NAME ": unloading\n");
 	pcmcia_unregister_driver(&cm4000_driver);
-	for (i = 0; i < CM4000_MAX_DEV; i++)
-		if (dev_table[i])
-			cm4000_detach_by_devno(i, dev_table[i]);
 	unregister_chrdev(major, DEVICE_NAME);
 };
 
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 3622fd3..e08ab94 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -65,7 +65,7 @@
 #define POLL_PERIOD 				msecs_to_jiffies(10)
 
 static void reader_release(dev_link_t *link);
-static void reader_detach(dev_link_t *link);
+static void reader_detach(struct pcmcia_device *p_dev);
 
 static int major;
 
@@ -652,10 +652,6 @@
 			link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 			reader_config(link, devno);
 			break;
-		case CS_EVENT_CARD_REMOVAL:
-			DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n");
-			link->state &= ~DEV_PRESENT;
-			break;
 
 		default:
 			DEBUGP(5, dev, "reader_event: unknown event %.2x\n",
@@ -734,7 +730,7 @@
 	i = pcmcia_register_client(&link->handle, &client_reg);
 	if (i) {
 		cs_error(link->handle, RegisterClient, i);
-		reader_detach(link);
+		reader_detach(link->handle);
 		return NULL;
 	}
 	init_waitqueue_head(&dev->devq);
@@ -747,36 +743,28 @@
 	return link;
 }
 
-static void reader_detach_by_devno(int devno, dev_link_t *link)
+static void reader_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct reader_dev *dev = link->priv;
-
-	if (link->state & DEV_CONFIG) {
-		DEBUGP(5, dev, "device still configured (try to release it)\n");
-		reader_release(link);
-	}
-
-	pcmcia_deregister_client(link->handle);
-	dev_table[devno] = NULL;
-	DEBUGP(5, dev, "freeing dev=%p\n", dev);
-	cm4040_stop_poll(dev);
-	kfree(dev);
-	return;
-}
-
-static void reader_detach(dev_link_t *link)
-{
-	int i;
+	int devno;
 
 	/* find device */
-	for (i = 0; i < CM_MAX_DEV; i++) {
-		if (dev_table[i] == link)
+	for (devno = 0; devno < CM_MAX_DEV; devno++) {
+		if (dev_table[devno] == link)
 			break;
 	}
-	if (i == CM_MAX_DEV)
+	if (devno == CM_MAX_DEV)
 		return;
 
-	reader_detach_by_devno(i, link);
+	link->state &= ~DEV_PRESENT;
+
+	if (link->state & DEV_CONFIG)
+		reader_release(link);
+
+	dev_table[devno] = NULL;
+	kfree(dev);
+
 	return;
 }
 
@@ -803,7 +791,7 @@
 		.name	= "cm4040_cs",
 	},
 	.attach		= reader_attach,
-	.detach		= reader_detach,
+	.remove		= reader_detach,
 	.suspend	= reader_suspend,
 	.resume		= reader_resume,
 	.event		= reader_event,
@@ -825,14 +813,8 @@
 
 static void __exit cm4040_exit(void)
 {
-	int i;
-
 	printk(KERN_INFO MODULE_NAME ": unloading\n");
 	pcmcia_unregister_driver(&reader_driver);
-	for (i = 0; i < CM_MAX_DEV; i++) {
-		if (dev_table[i])
-			reader_detach_by_devno(i, dev_table[i]);
-	}
 	unregister_chrdev(major, DEVICE_NAME);
 }
 
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 776103e..3459714 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -489,7 +489,7 @@
 static int  mgslpc_event(event_t event, int priority,
 			 event_callback_args_t *args);
 static dev_link_t *mgslpc_attach(void);
-static void mgslpc_detach(dev_link_t *);
+static void mgslpc_detach(struct pcmcia_device *p_dev);
 
 static dev_info_t dev_info = "synclink_cs";
 static dev_link_t *dev_list = NULL;
@@ -598,7 +598,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
 	    cs_error(link->handle, RegisterClient, ret);
-	    mgslpc_detach(link);
+	    mgslpc_detach(link->handle);
 	    return NULL;
     }
 
@@ -736,17 +736,16 @@
 	    pcmcia_release_io(link->handle, &link->io);
     if (link->irq.AssignedIRQ)
 	    pcmcia_release_irq(link->handle, &link->irq);
-    if (link->state & DEV_STALE_LINK)
-	    mgslpc_detach(link);
 }
 
-static void mgslpc_detach(dev_link_t *link)
+static void mgslpc_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
 
     if (debug_level >= DEBUG_LEVEL_INFO)
 	    printk("mgslpc_detach(0x%p)\n", link);
-    
+
     /* find device */
     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
 	    if (*linkp == link) break;
@@ -754,20 +753,10 @@
 	    return;
 
     if (link->state & DEV_CONFIG) {
-	    /* device is configured/active, mark it so when
-	     * release() is called a proper detach() occurs.
-	     */
-	    if (debug_level >= DEBUG_LEVEL_INFO)
-		    printk(KERN_DEBUG "synclinkpc: detach postponed, '%s' "
-			   "still locked\n", link->dev->dev_name);
-	    link->state |= DEV_STALE_LINK;
-	    return;
+	    ((MGSLPC_INFO *)link->priv)->stop = 1;
+	    mgslpc_release((u_long)link);
     }
 
-    /* Break the link with Card Services */
-    if (link->handle)
-	    pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, and free it */
     *linkp = link->next;
     mgslpc_remove_device((MGSLPC_INFO *)link->priv);
@@ -809,13 +798,6 @@
 	    printk("mgslpc_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	    link->state &= ~DEV_PRESENT;
-	    if (link->state & DEV_CONFIG) {
-		    ((MGSLPC_INFO *)link->priv)->stop = 1;
-		    mgslpc_release((u_long)link);
-	    }
-	    break;
     case CS_EVENT_CARD_INSERTION:
 	    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	    mgslpc_config(link);
@@ -3102,7 +3084,7 @@
 	},
 	.attach		= mgslpc_attach,
 	.event		= mgslpc_event,
-	.detach		= mgslpc_detach,
+	.remove		= mgslpc_detach,
 	.id_table	= mgslpc_ids,
 	.suspend	= mgslpc_suspend,
 	.resume		= mgslpc_resume,
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 982b74a..1fb8976 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -94,7 +94,7 @@
 static dev_info_t dev_info = "ide-cs";
 
 static dev_link_t *ide_attach(void);
-static void ide_detach(dev_link_t *);
+static void ide_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list = NULL;
 
@@ -138,7 +138,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
 	cs_error(link->handle, RegisterClient, ret);
-	ide_detach(link);
+	ide_detach(link->handle);
 	return NULL;
     }
     
@@ -154,10 +154,10 @@
 
 ======================================================================*/
 
-static void ide_detach(dev_link_t *link)
+static void ide_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
-    int ret;
 
     DEBUG(0, "ide_detach(0x%p)\n", link);
     
@@ -170,12 +170,6 @@
     if (link->state & DEV_CONFIG)
 	ide_release(link);
     
-    if (link->handle) {
-	ret = pcmcia_deregister_client(link->handle);
-	if (ret != CS_SUCCESS)
-	    cs_error(link->handle, DeregisterClient, ret);
-    }
-    
     /* Unlink, free device structure */
     *linkp = link->next;
     kfree(link->priv);
@@ -445,11 +439,6 @@
     DEBUG(1, "ide_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-		ide_release(link);
-	break;
     case CS_EVENT_CARD_INSERTION:
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	ide_config(link);
@@ -504,7 +493,7 @@
 	},
 	.attach		= ide_attach,
 	.event		= ide_event,
-	.detach		= ide_detach,
+	.remove		= ide_detach,
 	.id_table       = ide_ids,
 	.suspend	= ide_suspend,
 	.resume		= ide_resume,
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 6d9816e..2d898d3 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -63,7 +63,7 @@
 */
 
 static dev_link_t *avmcs_attach(void);
-static void avmcs_detach(dev_link_t *);
+static void avmcs_detach(struct pcmcia_device *p_dev);
 
 /*
    The dev_info variable is the "key" that is used to match up this
@@ -165,7 +165,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
 	cs_error(link->handle, RegisterClient, ret);
-	avmcs_detach(link);
+	avmcs_detach(link->handle);
 	goto err;
     }
     return link;
@@ -185,8 +185,9 @@
 
 ======================================================================*/
 
-static void avmcs_detach(dev_link_t *link)
+static void avmcs_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
 
     /* Locate device structure */
@@ -195,21 +196,9 @@
     if (*linkp == NULL)
 	return;
 
-    /*
-       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().
-    */
-    if (link->state & DEV_CONFIG) {
-	link->state |= DEV_STALE_LINK;
-	return;
-    }
+    if (link->state & DEV_CONFIG)
+	avmcs_release(link);
 
-    /* Break the link with Card Services */
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, free pieces */
     *linkp = link->next;
     kfree(link->priv);
@@ -424,10 +413,6 @@
     pcmcia_release_io(link->handle, &link->io);
     pcmcia_release_irq(link->handle, &link->irq);
     link->state &= ~DEV_CONFIG;
-    
-    if (link->state & DEV_STALE_LINK)
-	avmcs_detach(link);
-    
 } /* avmcs_release */
 
 static int avmcs_suspend(struct pcmcia_device *dev)
@@ -472,11 +457,6 @@
     dev_link_t *link = args->client_data;
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-		avmcs_release(link);
-	break;
     case CS_EVENT_CARD_INSERTION:
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	avmcs_config(link);
@@ -500,7 +480,7 @@
 	},
 	.attach	= avmcs_attach,
 	.event	= avmcs_event,
-	.detach	= avmcs_detach,
+	.remove	= avmcs_detach,
 	.id_table = avmcs_ids,
 	.suspend= avmcs_suspend,
 	.resume = avmcs_resume,
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 433cec4..6b322e8 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -79,7 +79,7 @@
 */
 
 static dev_link_t *avma1cs_attach(void);
-static void avma1cs_detach(dev_link_t *);
+static void avma1cs_detach(struct pcmcia_device *p_dev);
 
 /*
    The dev_info variable is the "key" that is used to match up this
@@ -187,7 +187,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
 	cs_error(link->handle, RegisterClient, ret);
-	avma1cs_detach(link);
+	avma1cs_detach(link->handle);
 	return NULL;
     }
 
@@ -203,42 +203,26 @@
 
 ======================================================================*/
 
-static void avma1cs_detach(dev_link_t *link)
+static void avma1cs_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
 
     DEBUG(0, "avma1cs_detach(0x%p)\n", link);
-    
+
     /* Locate device structure */
     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
 	if (*linkp == link) break;
     if (*linkp == NULL)
 	return;
 
-    /*
-       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().
-    */
-    if (link->state & DEV_CONFIG) {
-#ifdef PCMCIA_DEBUG
-	printk(KERN_DEBUG "avma1_cs: detach postponed, '%s' "
-	       "still locked\n", link->dev->dev_name);
-#endif
-	link->state |= DEV_STALE_LINK;
-	return;
-    }
+    if (link->state & DEV_CONFIG)
+	    avma1cs_release(link);
 
-    /* Break the link with Card Services */
-    if (link->handle)
-    	pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, free pieces */
     *linkp = link->next;
     kfree(link->priv);
     kfree(link);
-    
 } /* avma1cs_detach */
 
 /*======================================================================
@@ -440,9 +424,6 @@
     pcmcia_release_io(link->handle, &link->io);
     pcmcia_release_irq(link->handle, &link->irq);
     link->state &= ~DEV_CONFIG;
-    
-    if (link->state & DEV_STALE_LINK)
-	avma1cs_detach(link);
 } /* avma1cs_release */
 
 static int avma1cs_suspend(struct pcmcia_device *dev)
@@ -489,10 +470,6 @@
     DEBUG(1, "avma1cs_event(0x%06x)\n", event);
     
     switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-	    if (link->state & DEV_CONFIG)
-		avma1cs_release(link);
-	    break;
 	case CS_EVENT_CARD_INSERTION:
 	    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	    avma1cs_config(link);
@@ -515,7 +492,7 @@
 	},
 	.attach		= avma1cs_attach,
 	.event		= avma1cs_event,
-	.detach		= avma1cs_detach,
+	.remove		= avma1cs_detach,
 	.id_table	= avma1cs_ids,
 	.suspend	= avma1cs_suspend,
 	.resume		= avma1cs_resume,
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 0cbe045..48cc677 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -106,7 +106,7 @@
 */
 
 static dev_link_t *elsa_cs_attach(void);
-static void elsa_cs_detach(dev_link_t *);
+static void elsa_cs_detach(struct pcmcia_device *p_dev);
 
 /*
    The dev_info variable is the "key" that is used to match up this
@@ -216,7 +216,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
         cs_error(link->handle, RegisterClient, ret);
-        elsa_cs_detach(link);
+        elsa_cs_detach(link->handle);
         return NULL;
     }
 
@@ -232,11 +232,11 @@
 
 ======================================================================*/
 
-static void elsa_cs_detach(dev_link_t *link)
+static void elsa_cs_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
     local_info_t *info = link->priv;
-    int ret;
 
     DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
 
@@ -246,14 +246,9 @@
     if (*linkp == NULL)
         return;
 
-    if (link->state & DEV_CONFIG)
+    if (link->state & DEV_CONFIG) {
+        ((local_info_t*)link->priv)->busy = 1;
         elsa_cs_release(link);
-
-    /* Break the link with Card Services */
-    if (link->handle) {
-        ret = pcmcia_deregister_client(link->handle);
-	if (ret != CS_SUCCESS)
-	    cs_error(link->handle, DeregisterClient, ret);
     }
 
     /* Unlink device structure and free it */
@@ -495,13 +490,6 @@
     DEBUG(1, "elsa_cs_event(%d)\n", event);
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        if (link->state & DEV_CONFIG) {
-            ((local_info_t*)link->priv)->busy = 1;
-	    elsa_cs_release(link);
-        }
-        break;
     case CS_EVENT_CARD_INSERTION:
         link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
         elsa_cs_config(link);
@@ -524,7 +512,7 @@
 	},
 	.attach		= elsa_cs_attach,
 	.event		= elsa_cs_event,
-	.detach		= elsa_cs_detach,
+	.remove		= elsa_cs_detach,
 	.id_table	= elsa_ids,
 	.suspend	= elsa_suspend,
 	.resume		= elsa_resume,
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 27dce7c..d2386f6 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -107,7 +107,7 @@
 */
 
 static dev_link_t *sedlbauer_attach(void);
-static void sedlbauer_detach(dev_link_t *);
+static void sedlbauer_detach(struct pcmcia_device *p_dev);
 
 /*
    You'll also need to prototype all the functions that will actually
@@ -230,7 +230,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
 	cs_error(link->handle, RegisterClient, ret);
-	sedlbauer_detach(link);
+	sedlbauer_detach(link->handle);
 	return NULL;
     }
 
@@ -246,8 +246,9 @@
 
 ======================================================================*/
 
-static void sedlbauer_detach(dev_link_t *link)
+static void sedlbauer_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
 
     DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
@@ -258,25 +259,11 @@
     if (*linkp == NULL)
 	return;
 
-    /*
-       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().
-    */
     if (link->state & DEV_CONFIG) {
-#ifdef PCMCIA_DEBUG
-	printk(KERN_DEBUG "sedlbauer_cs: detach postponed, '%s' "
-	       "still locked\n", link->dev->dev_name);
-#endif
-	link->state |= DEV_STALE_LINK;
-	return;
+	((local_info_t *)link->priv)->stop = 1;
+	sedlbauer_release(link);
     }
 
-    /* Break the link with Card Services */
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, and free it */
     *linkp = link->next;
     /* This points to the parent local_info_t struct */
@@ -547,10 +534,6 @@
     if (link->irq.AssignedIRQ)
 	pcmcia_release_irq(link->handle, &link->irq);
     link->state &= ~DEV_CONFIG;
-    
-    if (link->state & DEV_STALE_LINK)
-	sedlbauer_detach(link);
-    
 } /* sedlbauer_release */
 
 static int sedlbauer_suspend(struct pcmcia_device *p_dev)
@@ -599,13 +582,6 @@
     DEBUG(1, "sedlbauer_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG) {
-	    ((local_info_t *)link->priv)->stop = 1;
-	    sedlbauer_release(link);
-	}
-	break;
     case CS_EVENT_CARD_INSERTION:
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	sedlbauer_config(link);
@@ -633,7 +609,7 @@
 	},
 	.attach		= sedlbauer_attach,
 	.event		= sedlbauer_event,
-	.detach		= sedlbauer_detach,
+	.remove		= sedlbauer_detach,
 	.id_table	= sedlbauer_ids,
 	.suspend	= sedlbauer_suspend,
 	.resume		= sedlbauer_resume,
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 70213bc..cd0f86f 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -87,7 +87,7 @@
 */
 
 static dev_link_t *teles_attach(void);
-static void teles_detach(dev_link_t *);
+static void teles_detach(struct pcmcia_device *p_dev);
 
 /*
    The dev_info variable is the "key" that is used to match up this
@@ -197,7 +197,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
         cs_error(link->handle, RegisterClient, ret);
-        teles_detach(link);
+        teles_detach(link->handle);
         return NULL;
     }
 
@@ -213,11 +213,11 @@
 
 ======================================================================*/
 
-static void teles_detach(dev_link_t *link)
+static void teles_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
     local_info_t *info = link->priv;
-    int ret;
 
     DEBUG(0, "teles_detach(0x%p)\n", link);
 
@@ -227,14 +227,9 @@
     if (*linkp == NULL)
         return;
 
-    if (link->state & DEV_CONFIG)
+    if (link->state & DEV_CONFIG) {
+        info->busy = 1;
         teles_cs_release(link);
-
-    /* Break the link with Card Services */
-    if (link->handle) {
-        ret = pcmcia_deregister_client(link->handle);
-	if (ret != CS_SUCCESS)
-	    cs_error(link->handle, DeregisterClient, ret);
     }
 
     /* Unlink device structure and free it */
@@ -476,13 +471,6 @@
     DEBUG(1, "teles_cs_event(%d)\n", event);
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        if (link->state & DEV_CONFIG) {
-            ((local_info_t*)link->priv)->busy = 1;
-	    teles_cs_release(link);
-        }
-        break;
     case CS_EVENT_CARD_INSERTION:
         link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
         teles_cs_config(link);
@@ -504,7 +492,7 @@
 	},
 	.attach		= teles_attach,
 	.event		= teles_cs_event,
-	.detach		= teles_detach,
+	.remove		= teles_detach,
 	.id_table       = teles_ids,
 	.suspend	= teles_suspend,
 	.resume		= teles_resume,
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 86443cf..3ddcb1b 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -722,18 +722,6 @@
 
 	DEBUG(1, "event=0x%06x", event);
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		DEBUG(2, "EVENT_CARD_REMOVAL");
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			struct pcmciamtd_dev *dev = link->priv;
-			if(dev->mtd_info) {
-				del_mtd_device(dev->mtd_info);
-				info("mtd%d: Removed", dev->mtd_info->index);
-			}
-			pcmciamtd_release(link);
-		}
-		break;
 	case CS_EVENT_CARD_INSERTION:
 		DEBUG(2, "EVENT_CARD_INSERTION");
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
@@ -752,23 +740,21 @@
  * when the device is released.
  */
 
-static void pcmciamtd_detach(dev_link_t *link)
+static void pcmciamtd_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
+
 	DEBUG(3, "link=0x%p", link);
 
 	if(link->state & DEV_CONFIG) {
+		struct pcmciamtd_dev *dev = link->priv;
+		if(dev->mtd_info) {
+			del_mtd_device(dev->mtd_info);
+			info("mtd%d: Removed", dev->mtd_info->index);
+		}
+
 		pcmciamtd_release(link);
 	}
-
-	if (link->handle) {
-		int ret;
-		DEBUG(2, "Deregistering with card services");
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
-	}
-
-	link->state |= DEV_STALE_LINK;
 }
 
 
@@ -807,7 +793,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != 0) {
 		cs_error(link->handle, RegisterClient, ret);
-		pcmciamtd_detach(link);
+		pcmciamtd_detach(link->handle);
 		return NULL;
 	}
 	DEBUG(2, "link = %p", link);
@@ -847,7 +833,7 @@
 	},
 	.attach		= pcmciamtd_attach,
 	.event		= pcmciamtd_event,
-	.detach		= pcmciamtd_detach,
+	.remove		= pcmciamtd_detach,
 	.owner		= THIS_MODULE,
 	.id_table	= pcmciamtd_ids,
 	.suspend	= pcmciamtd_suspend,
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 80414a7..60a3bc2 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -253,7 +253,7 @@
 static dev_info_t dev_info = "3c574_cs";
 
 static dev_link_t *tc574_attach(void);
-static void tc574_detach(dev_link_t *);
+static void tc574_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list;
 
@@ -316,7 +316,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != 0) {
 		cs_error(link->handle, RegisterClient, ret);
-		tc574_detach(link);
+		tc574_detach(link->handle);
 		return NULL;
 	}
 
@@ -332,8 +332,9 @@
 
 */
 
-static void tc574_detach(dev_link_t *link)
+static void tc574_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 	dev_link_t **linkp;
 
@@ -351,9 +352,6 @@
 	if (link->state & DEV_CONFIG)
 		tc574_release(link);
 
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
-
 	/* Unlink device structure, free bits */
 	*linkp = link->next;
 	free_netdev(dev);
@@ -590,16 +588,10 @@
 					   event_callback_args_t *args)
 {
 	dev_link_t *link = args->client_data;
-	struct net_device *dev = link->priv;
 
 	DEBUG(1, "3c574_event(0x%06x)\n", event);
 
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG)
-			netif_device_detach(dev);
-		break;
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		tc574_config(link);
@@ -1304,7 +1296,7 @@
 	},
 	.attach		= tc574_attach,
 	.event		= tc574_event,
-	.detach		= tc574_detach,
+	.remove		= tc574_detach,
 	.id_table       = tc574_ids,
 	.suspend	= tc574_suspend,
 	.resume		= tc574_resume,
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index bbda681..09b96c7 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -164,7 +164,7 @@
 static dev_info_t dev_info = "3c589_cs";
 
 static dev_link_t *tc589_attach(void);
-static void tc589_detach(dev_link_t *);
+static void tc589_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list;
 
@@ -230,7 +230,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
 	cs_error(link->handle, RegisterClient, ret);
-	tc589_detach(link);
+	tc589_detach(link->handle);
 	return NULL;
     }
     
@@ -246,8 +246,9 @@
 
 ======================================================================*/
 
-static void tc589_detach(dev_link_t *link)
+static void tc589_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
     
@@ -264,10 +265,7 @@
 
     if (link->state & DEV_CONFIG)
 	tc589_release(link);
-    
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
+
     /* Unlink device structure, free bits */
     *linkp = link->next;
     free_netdev(dev);
@@ -466,16 +464,10 @@
 		       event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
     
     DEBUG(1, "3c589_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    netif_device_detach(dev);
-	break;
     case CS_EVENT_CARD_INSERTION:
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	tc589_config(link);
@@ -1079,7 +1071,7 @@
 	},
 	.attach		= tc589_attach,
 	.event		= tc589_event,
-	.detach		= tc589_detach,
+	.remove		= tc589_detach,
         .id_table       = tc589_ids,
 	.suspend	= tc589_suspend,
 	.resume		= tc589_resume,
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 6c6b252..11f701a 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -108,7 +108,7 @@
 			 const u_char *buf, const int start_page);
 
 static dev_link_t *axnet_attach(void);
-static void axnet_detach(dev_link_t *);
+static void axnet_detach(struct pcmcia_device *p_dev);
 
 static dev_info_t dev_info = "axnet_cs";
 static dev_link_t *dev_list;
@@ -185,7 +185,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
 	cs_error(link->handle, RegisterClient, ret);
-	axnet_detach(link);
+	axnet_detach(link->handle);
 	return NULL;
     }
 
@@ -201,8 +201,9 @@
 
 ======================================================================*/
 
-static void axnet_detach(dev_link_t *link)
+static void axnet_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
 
@@ -220,9 +221,6 @@
     if (link->state & DEV_CONFIG)
 	axnet_release(link);
 
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-
     /* Unlink device structure, free bits */
     *linkp = link->next;
     free_netdev(dev);
@@ -537,16 +535,10 @@
 		       event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
 
     DEBUG(2, "axnet_event(0x%06x)\n", event);
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    netif_device_detach(dev);
-	break;
     case CS_EVENT_CARD_INSERTION:
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	axnet_config(link);
@@ -890,7 +882,7 @@
 	},
 	.attach		= axnet_attach,
 	.event		= axnet_event,
-	.detach		= axnet_detach,
+	.remove		= axnet_detach,
 	.id_table       = axnet_ids,
 	.suspend	= axnet_suspend,
 	.resume		= axnet_resume,
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 6861222..6970888 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -126,7 +126,7 @@
 static dev_info_t dev_info = "com20020_cs";
 
 static dev_link_t *com20020_attach(void);
-static void com20020_detach(dev_link_t *);
+static void com20020_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list;
 
@@ -204,7 +204,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
         cs_error(link->handle, RegisterClient, ret);
-        com20020_detach(link);
+        com20020_detach(link->handle);
         return NULL;
     }
 
@@ -226,8 +226,9 @@
 
 ======================================================================*/
 
-static void com20020_detach(dev_link_t *link)
+static void com20020_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct com20020_dev_t *info = link->priv;
     dev_link_t **linkp;
     struct net_device *dev; 
@@ -260,9 +261,6 @@
     if (link->state & DEV_CONFIG)
         com20020_release(link);
 
-    if (link->handle)
-        pcmcia_deregister_client(link->handle);
-
     /* Unlink device structure, free bits */
     DEBUG(1,"unlinking...\n");
     *linkp = link->next;
@@ -470,17 +468,10 @@
 			  event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    com20020_dev_t *info = link->priv;
-    struct net_device *dev = info->dev;
 
     DEBUG(1, "com20020_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        if (link->state & DEV_CONFIG)
-            netif_device_detach(dev);
-        break;
     case CS_EVENT_CARD_INSERTION:
         link->state |= DEV_PRESENT;
 	com20020_config(link); 
@@ -502,7 +493,7 @@
 	},
 	.attach		= com20020_attach,
 	.event		= com20020_event,
-	.detach		= com20020_detach,
+	.remove		= com20020_detach,
 	.id_table	= com20020_ids,
 	.suspend	= com20020_suspend,
 	.resume		= com20020_resume,
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 388ecad..560d4ee 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -91,7 +91,7 @@
 static int fmvj18x_event(event_t event, int priority,
 			  event_callback_args_t *args);
 static dev_link_t *fmvj18x_attach(void);
-static void fmvj18x_detach(dev_link_t *);
+static void fmvj18x_detach(struct pcmcia_device *p_dev);
 
 /*
     LAN controller(MBH86960A) specific routines
@@ -291,7 +291,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
 	cs_error(link->handle, RegisterClient, ret);
-	fmvj18x_detach(link);
+	fmvj18x_detach(link->handle);
 	return NULL;
     }
 
@@ -300,8 +300,9 @@
 
 /*====================================================================*/
 
-static void fmvj18x_detach(dev_link_t *link)
+static void fmvj18x_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
     
@@ -319,10 +320,6 @@
     if (link->state & DEV_CONFIG)
 	fmvj18x_release(link);
 
-    /* Break the link with Card Services */
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, free pieces */
     *linkp = link->next;
     free_netdev(dev);
@@ -752,16 +749,10 @@
 			  event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
 
     DEBUG(1, "fmvj18x_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    netif_device_detach(dev);
-	break;
     case CS_EVENT_CARD_INSERTION:
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	fmvj18x_config(link);
@@ -802,7 +793,7 @@
 	},
 	.attach		= fmvj18x_attach,
 	.event		= fmvj18x_event,
-	.detach		= fmvj18x_detach,
+	.remove		= fmvj18x_detach,
 	.id_table       = fmvj18x_ids,
 	.suspend	= fmvj18x_suspend,
 	.resume		= fmvj18x_resume,
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index 3a7218e..9612949 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -114,7 +114,7 @@
 static dev_info_t dev_info = "ibmtr_cs";
 
 static dev_link_t *ibmtr_attach(void);
-static void ibmtr_detach(dev_link_t *);
+static void ibmtr_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list;
 
@@ -201,7 +201,7 @@
     return link;
 
 out_detach:
-    ibmtr_detach(link);
+    ibmtr_detach(link->handle);
     link = NULL;
     goto out;
 } /* ibmtr_attach */
@@ -215,8 +215,9 @@
 
 ======================================================================*/
 
-static void ibmtr_detach(dev_link_t *link)
+static void ibmtr_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct ibmtr_dev_t *info = link->priv;
     dev_link_t **linkp;
     struct net_device *dev;
@@ -241,9 +242,6 @@
     if (link->state & DEV_CONFIG)
         ibmtr_release(link);
 
-    if (link->handle)
-        pcmcia_deregister_client(link->handle);
-
     /* Unlink device structure, free bits */
     *linkp = link->next;
     free_netdev(dev);
@@ -449,21 +447,10 @@
                        event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    ibmtr_dev_t *info = link->priv;
-    struct net_device *dev = info->dev;
 
     DEBUG(1, "ibmtr_event(0x%06x)\n", event);
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        if (link->state & DEV_CONFIG) {
-	    /* set flag to bypass normal interrupt code */
-	    struct tok_info *priv = netdev_priv(dev);
-	    priv->sram_phys |= 1;
-	    netif_device_detach(dev);
-        }
-        break;
     case CS_EVENT_CARD_INSERTION:
         link->state |= DEV_PRESENT;
 	ibmtr_config(link);
@@ -529,7 +516,7 @@
 	},
 	.attach		= ibmtr_attach,
 	.event		= ibmtr_event,
-	.detach		= ibmtr_detach,
+	.remove		= ibmtr_detach,
 	.id_table       = ibmtr_ids,
 	.suspend	= ibmtr_suspend,
 	.resume		= ibmtr_resume,
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index fa4921f..011ceb0 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -440,7 +440,7 @@
 
 
 static dev_link_t *nmclan_attach(void);
-static void nmclan_detach(dev_link_t *);
+static void nmclan_detach(struct pcmcia_device *p_dev);
 
 /* ----------------------------------------------------------------------------
 nmclan_attach
@@ -506,7 +506,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
 	cs_error(link->handle, RegisterClient, ret);
-	nmclan_detach(link);
+	nmclan_detach(link->handle);
 	return NULL;
     }
 
@@ -521,8 +521,9 @@
 	when the device is released.
 ---------------------------------------------------------------------------- */
 
-static void nmclan_detach(dev_link_t *link)
+static void nmclan_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
 
@@ -540,9 +541,6 @@
     if (link->state & DEV_CONFIG)
 	nmclan_release(link);
 
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-
     /* Unlink device structure, free bits */
     *linkp = link->next;
     free_netdev(dev);
@@ -845,16 +843,10 @@
 		       event_callback_args_t *args)
 {
   dev_link_t *link = args->client_data;
-  struct net_device *dev = link->priv;
 
   DEBUG(1, "nmclan_event(0x%06x)\n", event);
 
   switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-      link->state &= ~DEV_PRESENT;
-      if (link->state & DEV_CONFIG)
-	netif_device_detach(dev);
-      break;
     case CS_EVENT_CARD_INSERTION:
       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
       nmclan_config(link);
@@ -1694,7 +1686,7 @@
 	},
 	.attach		= nmclan_attach,
 	.event		= nmclan_event,
-	.detach		= nmclan_detach,
+	.remove		= nmclan_detach,
 	.id_table       = nmclan_ids,
 	.suspend	= nmclan_suspend,
 	.resume		= nmclan_resume,
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 7db4d6f..fb3e411 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -121,7 +121,7 @@
 			    int stop_pg);
 
 static dev_link_t *pcnet_attach(void);
-static void pcnet_detach(dev_link_t *);
+static void pcnet_detach(struct pcmcia_device *p_dev);
 
 static dev_info_t dev_info = "pcnet_cs";
 static dev_link_t *dev_list;
@@ -280,7 +280,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
 	cs_error(link->handle, RegisterClient, ret);
-	pcnet_detach(link);
+	pcnet_detach(link->handle);
 	return NULL;
     }
 
@@ -296,31 +296,29 @@
 
 ======================================================================*/
 
-static void pcnet_detach(dev_link_t *link)
+static void pcnet_detach(struct pcmcia_device *p_dev)
 {
-    struct net_device *dev = link->priv;
-    dev_link_t **linkp;
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+	dev_link_t **linkp;
 
-    DEBUG(0, "pcnet_detach(0x%p)\n", link);
+	DEBUG(0, "pcnet_detach(0x%p)\n", link);
 
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
+	/* Locate device structure */
+	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+		if (*linkp == link) break;
+	if (*linkp == NULL)
+		return;
 
-    if (link->dev)
-	unregister_netdev(dev);
+	if (link->dev)
+		unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-	pcnet_release(link);
+	if (link->state & DEV_CONFIG)
+		pcnet_release(link);
 
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-
-    /* Unlink device structure, free bits */
-    *linkp = link->next;
-    free_netdev(dev);
+	/* Unlink device structure, free bits */
+	*linkp = link->next;
+	free_netdev(dev);
 } /* pcnet_detach */
 
 /*======================================================================
@@ -817,16 +815,10 @@
 		       event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
 
     DEBUG(2, "pcnet_event(0x%06x)\n", event);
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    netif_device_detach(dev);
-	break;
     case CS_EVENT_CARD_INSERTION:
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	pcnet_config(link);
@@ -1856,7 +1848,7 @@
 	},
 	.attach		= pcnet_attach,
 	.event		= pcnet_event,
-	.detach		= pcnet_detach,
+	.remove		= pcnet_detach,
 	.owner		= THIS_MODULE,
 	.id_table	= pcnet_ids,
 	.suspend	= pcnet_suspend,
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 7c61ec9..6cb5198 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -282,7 +282,7 @@
 /*====================================================================*/
 
 static dev_link_t *smc91c92_attach(void);
-static void smc91c92_detach(dev_link_t *);
+static void smc91c92_detach(struct pcmcia_device *p_dev);
 static void smc91c92_config(dev_link_t *link);
 static void smc91c92_release(dev_link_t *link);
 static int smc91c92_event(event_t event, int priority,
@@ -375,7 +375,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
 	cs_error(link->handle, RegisterClient, ret);
-	smc91c92_detach(link);
+	smc91c92_detach(link->handle);
 	return NULL;
     }
 
@@ -391,8 +391,9 @@
 
 ======================================================================*/
 
-static void smc91c92_detach(dev_link_t *link)
+static void smc91c92_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
 
@@ -410,9 +411,6 @@
     if (link->state & DEV_CONFIG)
 	smc91c92_release(link);
 
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-
     /* Unlink device structure, free bits */
     *linkp = link->next;
     free_netdev(dev);
@@ -1237,16 +1235,10 @@
 			  event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
 
     DEBUG(1, "smc91c92_event(0x%06x)\n", event);
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    netif_device_detach(dev);
-	break;
     case CS_EVENT_CARD_INSERTION:
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	smc91c92_config(link);
@@ -2371,7 +2363,7 @@
 	},
 	.attach		= smc91c92_attach,
 	.event		= smc91c92_event,
-	.detach		= smc91c92_detach,
+	.remove		= smc91c92_detach,
 	.id_table       = smc91c92_ids,
 	.suspend	= smc91c92_suspend,
 	.resume		= smc91c92_resume,
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 917e50a..804e567 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -302,7 +302,7 @@
  */
 
 static dev_link_t *xirc2ps_attach(void);
-static void xirc2ps_detach(dev_link_t *);
+static void xirc2ps_detach(struct pcmcia_device *p_dev);
 
 /****************
  * You'll also need to prototype all the functions that will actually
@@ -622,7 +622,7 @@
     client_reg.event_callback_args.client_data = link;
     if ((err = pcmcia_register_client(&link->handle, &client_reg))) {
 	cs_error(link->handle, RegisterClient, err);
-	xirc2ps_detach(link);
+	xirc2ps_detach(link->handle);
 	return NULL;
     }
 
@@ -637,8 +637,9 @@
  */
 
 static void
-xirc2ps_detach(dev_link_t * link)
+xirc2ps_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
 
@@ -656,19 +657,9 @@
     if (link->dev)
 	unregister_netdev(dev);
 
-    /*
-     * 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().
-     */
     if (link->state & DEV_CONFIG)
 	xirc2ps_release(link);
 
-    /* Break the link with Card Services */
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-
     /* Unlink device structure, free it */
     *linkp = link->next;
     free_netdev(dev);
@@ -1209,19 +1200,10 @@
 	      event_callback_args_t * args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
 
     DEBUG(0, "event(%d)\n", (int)event);
 
     switch (event) {
-    case CS_EVENT_REGISTRATION_COMPLETE:
-	DEBUG(0, "registration complete\n");
-	break;
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    netif_device_detach(dev);
-	break;
     case CS_EVENT_CARD_INSERTION:
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	xirc2ps_config(link);
@@ -2022,7 +2004,7 @@
 	},
 	.attach		= xirc2ps_attach,
 	.event		= xirc2ps_event,
-	.detach		= xirc2ps_detach,
+	.remove		= xirc2ps_detach,
 	.id_table       = xirc2ps_ids,
 	.suspend	= xirc2ps_suspend,
 	.resume		= xirc2ps_resume,
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index 80c9de7..7a28139 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -92,7 +92,7 @@
 */
 
 static dev_link_t *airo_attach(void);
-static void airo_detach(dev_link_t *);
+static void airo_detach(struct pcmcia_device *p_dev);
 
 /*
    You'll also need to prototype all the functions that will actually
@@ -210,7 +210,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != 0) {
 		cs_error(link->handle, RegisterClient, ret);
-		airo_detach(link);
+		airo_detach(link->handle);
 		return NULL;
 	}
 	
@@ -226,8 +226,9 @@
   
   ======================================================================*/
 
-static void airo_detach(dev_link_t *link)
+static void airo_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	dev_link_t **linkp;
 	
 	DEBUG(0, "airo_detach(0x%p)\n", link);
@@ -244,14 +245,8 @@
 	if ( ((local_info_t*)link->priv)->eth_dev ) {
 		stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 );
 	}
-	((local_info_t*)link->priv)->eth_dev = NULL;   
-	
-	/* Break the link with Card Services */
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
-	
-	
-	
+	((local_info_t*)link->priv)->eth_dev = NULL;
+
 	/* Unlink device structure, free pieces */
 	*linkp = link->next;
 	kfree(link->priv);
@@ -537,18 +532,10 @@
 		      event_callback_args_t *args)
 {
 	dev_link_t *link = args->client_data;
-	local_info_t *local = link->priv;
-	
+
 	DEBUG(1, "airo_event(0x%06x)\n", event);
-	
+
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			netif_device_detach(local->eth_dev);
-			airo_release(link);
-		}
-		break;
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		airo_config(link);
@@ -573,7 +560,7 @@
 	},
 	.attach		= airo_attach,
 	.event		= airo_event,
-	.detach		= airo_detach,
+	.remove		= airo_detach,
 	.id_table       = airo_ids,
 	.suspend	= airo_suspend,
 	.resume		= airo_resume,
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 598a9cd..3ab33dd 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -103,7 +103,7 @@
 */
 
 static dev_link_t *atmel_attach(void);
-static void atmel_detach(dev_link_t *);
+static void atmel_detach(struct pcmcia_device *p_dev);
 
 /*
    You'll also need to prototype all the functions that will actually
@@ -221,7 +221,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != 0) {
 		cs_error(link->handle, RegisterClient, ret);
-		atmel_detach(link);
+		atmel_detach(link->handle);
 		return NULL;
 	}
 	
@@ -237,8 +237,9 @@
   
   ======================================================================*/
 
-static void atmel_detach(dev_link_t *link)
+static void atmel_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	dev_link_t **linkp;
 	
 	DEBUG(0, "atmel_detach(0x%p)\n", link);
@@ -252,10 +253,6 @@
 	if (link->state & DEV_CONFIG)
 		atmel_release(link);
 		
-	/* Break the link with Card Services */
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
-
 	/* Unlink device structure, free pieces */
 	*linkp = link->next;
 	kfree(link->priv);
@@ -522,18 +519,10 @@
 		      event_callback_args_t *args)
 {
 	dev_link_t *link = args->client_data;
-	local_info_t *local = link->priv;
-	
+
 	DEBUG(1, "atmel_event(0x%06x)\n", event);
-	
+
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			netif_device_detach(local->eth_dev);
-			atmel_release(link);
-		}
-		break;
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		atmel_config(link);
@@ -593,7 +582,7 @@
         },
 	.attach         = atmel_attach,
 	.event		= atmel_event,
-	.detach		= atmel_detach,
+	.remove		= atmel_detach,
 	.id_table	= atmel_ids,
 	.suspend	= atmel_suspend,
 	.resume		= atmel_resume,
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index ba4a7da..866142a 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -203,7 +203,7 @@
 
 
 
-static void prism2_detach(dev_link_t *link);
+static void prism2_detach(struct pcmcia_device *p_dev);
 static void prism2_release(u_long arg);
 static int prism2_event(event_t event, int priority,
 			event_callback_args_t *args);
@@ -528,15 +528,16 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != CS_SUCCESS) {
 		cs_error(link->handle, RegisterClient, ret);
-		prism2_detach(link);
+		prism2_detach(link->handle);
 		return NULL;
 	}
 	return link;
 }
 
 
-static void prism2_detach(dev_link_t *link)
+static void prism2_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	dev_link_t **linkp;
 
 	PDEBUG(DEBUG_FLOW, "prism2_detach\n");
@@ -554,14 +555,6 @@
 		prism2_release((u_long)link);
 	}
 
-	if (link->handle) {
-		int res = pcmcia_deregister_client(link->handle);
-		if (res) {
-			printk("CardService(DeregisterClient) => %d\n", res);
-			cs_error(link->handle, DeregisterClient, res);
-		}
-	}
-
 	*linkp = link->next;
 	/* release net devices */
 	if (link->priv) {
@@ -902,7 +895,6 @@
 			event_callback_args_t *args)
 {
 	dev_link_t *link = args->client_data;
-	struct net_device *dev = (struct net_device *) link->priv;
 
 	switch (event) {
 	case CS_EVENT_CARD_INSERTION:
@@ -913,16 +905,6 @@
 		}
 		break;
 
-	case CS_EVENT_CARD_REMOVAL:
-		PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_REMOVAL\n", dev_info);
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			netif_stop_queue(dev);
-			netif_device_detach(dev);
-			prism2_release((u_long) link);
-		}
-		break;
-
 	default:
 		PDEBUG(DEBUG_EXTRA, "%s: prism2_event() - unknown event %d\n",
 		       dev_info, event);
@@ -991,7 +973,7 @@
 		.name	= "hostap_cs",
 	},
 	.attach		= prism2_attach,
-	.detach		= prism2_detach,
+	.remove		= prism2_detach,
 	.owner		= THIS_MODULE,
 	.event		= prism2_event,
 	.id_table	= hostap_cs_ids,
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 7ab2d70..1770677 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -200,7 +200,7 @@
 static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card 
 													   insertion */
 static dev_link_t *netwave_attach(void);     /* Create instance */
-static void netwave_detach(dev_link_t *);    /* Destroy instance */
+static void netwave_detach(struct pcmcia_device *p_dev);    /* Destroy instance */
 
 /* Hardware configuration */
 static void netwave_doreset(kio_addr_t iobase, u_char __iomem *ramBase);
@@ -459,7 +459,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
 	cs_error(link->handle, RegisterClient, ret);
-	netwave_detach(link);
+	netwave_detach(link->handle);
 	return NULL;
     }
 
@@ -474,8 +474,9 @@
  *    structures are freed.  Otherwise, the structures will be freed
  *    when the device is released.
  */
-static void netwave_detach(dev_link_t *link)
+static void netwave_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
 
@@ -489,11 +490,7 @@
 	*/
     if (link->state & DEV_CONFIG)
 	netwave_release(link);
-	
-    /* Break the link with Card Services */
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
+
     /* Locate device structure */
     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
 	if (*linkp == link) break;
@@ -986,22 +983,10 @@
 			 event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
-	
-    DEBUG(1, "netwave_event(0x%06x)\n", event);
-  
-    switch (event) {
-    case CS_EVENT_REGISTRATION_COMPLETE:
-	DEBUG(0, "netwave_cs: registration complete\n");
-	break;
 
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG) {
-	    netif_device_detach(dev);
-	    netwave_release(link);
-	}
-	break;
+    DEBUG(1, "netwave_event(0x%06x)\n", event);
+
+    switch (event) {
     case CS_EVENT_CARD_INSERTION:
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	netwave_pcmcia_config( link);
@@ -1504,7 +1489,7 @@
 	},
 	.attach		= netwave_attach,
 	.event		= netwave_event,
-	.detach		= netwave_detach,
+	.remove		= netwave_detach,
 	.id_table       = netwave_ids,
 	.suspend	= netwave_suspend,
 	.resume		= netwave_resume,
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index 1d66050..00679b6 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -81,7 +81,7 @@
 /********************************************************************/
 
 static void orinoco_cs_release(dev_link_t *link);
-static void orinoco_cs_detach(dev_link_t *link);
+static void orinoco_cs_detach(struct pcmcia_device *p_dev);
 
 /********************************************************************/
 /* Device methods     						    */
@@ -165,7 +165,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != CS_SUCCESS) {
 		cs_error(link->handle, RegisterClient, ret);
-		orinoco_cs_detach(link);
+		orinoco_cs_detach(link->handle);
 		return NULL;
 	}
 
@@ -178,8 +178,9 @@
  * are freed.  Otherwise, the structures will be freed when the device
  * is released.
  */
-static void orinoco_cs_detach(dev_link_t *link)
+static void orinoco_cs_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	dev_link_t **linkp;
 	struct net_device *dev = link->priv;
 
@@ -193,10 +194,6 @@
 	if (link->state & DEV_CONFIG)
 		orinoco_cs_release(link);
 
-	/* Break the link with Card Services */
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
-
 	/* Unlink device structure, and free it */
 	*linkp = link->next;
 	DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
@@ -551,30 +548,15 @@
 		       event_callback_args_t * args)
 {
 	dev_link_t *link = args->client_data;
-	struct net_device *dev = link->priv;
-	struct orinoco_private *priv = netdev_priv(dev);
-	int err = 0;
 
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			unsigned long flags;
-
-			spin_lock_irqsave(&priv->lock, flags);
-			netif_device_detach(dev);
-			priv->hw_unavailable++;
-			spin_unlock_irqrestore(&priv->lock, flags);
-		}
-		break;
-
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		orinoco_cs_config(link);
 		break;
 	}
 
-	return err;
+	return 0;
 }				/* orinoco_cs_event */
 
 /********************************************************************/
@@ -677,7 +659,7 @@
 		.name	= DRIVER_NAME,
 	},
 	.attach		= orinoco_cs_attach,
-	.detach		= orinoco_cs_detach,
+	.remove		= orinoco_cs_detach,
 	.event		= orinoco_cs_event,
 	.id_table       = orinoco_cs_ids,
 	.suspend	= orinoco_cs_suspend,
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index c2cb6c8..33a89e2 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -94,7 +94,7 @@
 static void ray_release(dev_link_t *link);
 static int ray_event(event_t event, int priority, event_callback_args_t *args);
 static dev_link_t *ray_attach(void);
-static void ray_detach(dev_link_t *);
+static void ray_detach(struct pcmcia_device *p_dev);
 
 /***** Prototypes indicated by device structure ******************************/
 static int ray_dev_close(struct net_device *dev);
@@ -402,7 +402,7 @@
     if (ret != 0) {
         printk("ray_cs ray_attach RegisterClient unhappy - detaching\n");
         cs_error(link->handle, RegisterClient, ret);
-        ray_detach(link);
+        ray_detach(link->handle);
         return NULL;
     }
     DEBUG(2,"ray_cs ray_attach ending\n");
@@ -418,9 +418,12 @@
     structures are freed.  Otherwise, the structures will be freed
     when the device is released.
 =============================================================================*/
-static void ray_detach(dev_link_t *link)
+static void ray_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
+    struct net_device *dev;
+    ray_dev_t *local;
 
     DEBUG(1, "ray_detach(0x%p)\n", link);
     
@@ -430,22 +433,18 @@
     if (*linkp == NULL)
         return;
 
-    /* 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().
-    */
-    if (link->state & DEV_CONFIG)
-        ray_release(link);
+    dev = link->priv;
 
-    /* Break the link with Card Services */
-    if (link->handle)
-        pcmcia_deregister_client(link->handle);
-    
+    if (link->state & DEV_CONFIG) {
+	    ray_release(link);
+
+	    local = (ray_dev_t *)dev->priv;
+            del_timer(&local->timer);
+    }
+
     /* Unlink device structure, free pieces */
     *linkp = link->next;
     if (link->priv) {
-        struct net_device *dev = link->priv;
 	if (link->dev) unregister_netdev(dev);
         free_netdev(dev);
     }
@@ -940,19 +939,9 @@
                      event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
-    ray_dev_t *local = (ray_dev_t *)dev->priv;
     DEBUG(1, "ray_event(0x%06x)\n", event);
-    
+
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        netif_device_detach(dev);
-        if (link->state & DEV_CONFIG) {
-	    ray_release(link);
-            del_timer(&local->timer);
-        }
-        break;
     case CS_EVENT_CARD_INSERTION:
         link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
         ray_config(link);
@@ -2958,7 +2947,7 @@
 	},
 	.attach		= ray_attach,
 	.event		= ray_event,
-	.detach		= ray_detach,
+	.remove		= ray_detach,
 	.id_table       = ray_ids,
 	.suspend	= ray_suspend,
 	.resume		= ray_resume,
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index 3938a57..a2dcab7 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -90,7 +90,7 @@
 /********************************************************************/
 
 static void spectrum_cs_release(dev_link_t *link);
-static void spectrum_cs_detach(dev_link_t *link);
+static void spectrum_cs_detach(struct pcmcia_device *p_dev);
 
 /********************************************************************/
 /* Firmware downloader						    */
@@ -647,7 +647,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != CS_SUCCESS) {
 		cs_error(link->handle, RegisterClient, ret);
-		spectrum_cs_detach(link);
+		spectrum_cs_detach(link->handle);
 		return NULL;
 	}
 
@@ -660,27 +660,14 @@
  * are freed.  Otherwise, the structures will be freed when the device
  * is released.
  */
-static void spectrum_cs_detach(dev_link_t *link)
+static void spectrum_cs_detach(struct pcmcia_device *p_dev)
 {
-	dev_link_t **linkp;
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-
-	BUG_ON(*linkp == NULL);
-
 	if (link->state & DEV_CONFIG)
 		spectrum_cs_release(link);
 
-	/* Break the link with Card Services */
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
-
-	/* Unlink device structure, and free it */
-	*linkp = link->next;
 	DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
 	if (link->dev) {
 		DEBUG(0, PFX "About to unregister net device %p\n",
@@ -1007,22 +994,8 @@
 		       event_callback_args_t * args)
 {
 	dev_link_t *link = args->client_data;
-	struct net_device *dev = link->priv;
-	struct orinoco_private *priv = netdev_priv(dev);
 
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			unsigned long flags;
-
-			spin_lock_irqsave(&priv->lock, flags);
-			netif_device_detach(dev);
-			priv->hw_unavailable++;
-			spin_unlock_irqrestore(&priv->lock, flags);
-		}
-		break;
-
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		spectrum_cs_config(link);
@@ -1057,7 +1030,7 @@
 		.name	= DRIVER_NAME,
 	},
 	.attach		= spectrum_cs_attach,
-	.detach		= spectrum_cs_detach,
+	.remove		= spectrum_cs_detach,
 	.suspend	= spectrum_cs_suspend,
 	.resume		= spectrum_cs_resume,
 	.event		= spectrum_cs_event,
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 3e35328..255952d 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -4692,7 +4692,7 @@
   if(ret != 0)
     {
       cs_error(link->handle, RegisterClient, ret);
-      wavelan_detach(link);
+      wavelan_detach(link->handle);
       return NULL;
     }
 
@@ -4711,8 +4711,10 @@
  * is released.
  */
 static void
-wavelan_detach(dev_link_t *	link)
+wavelan_detach(struct pcmcia_device *p_dev)
 {
+   dev_link_t *link = dev_to_instance(p_dev);
+
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link);
 #endif
@@ -4729,10 +4731,6 @@
       wv_pcmcia_release(link);
     }
 
-  /* Break the link with Card Services */
-  if(link->handle)
-    pcmcia_deregister_client(link->handle);
-    
   /* Remove the interface data from the linked list */
   if(dev_list == link)
     dev_list = link->next;
@@ -4854,25 +4852,6 @@
 
     switch(event)
       {
-      case CS_EVENT_REGISTRATION_COMPLETE:
-#ifdef DEBUG_CONFIG_INFO
-	printk(KERN_DEBUG "wavelan_cs: registration complete\n");
-#endif
-	break;
-
-      case CS_EVENT_CARD_REMOVAL:
-	/* Oups ! The card is no more there */
-	link->state &= ~DEV_PRESENT;
-	if(link->state & DEV_CONFIG)
-	  {
-	    /* Accept no more transmissions */
-	    netif_device_detach(dev);
-
-	    /* Release the card */
-	    wv_pcmcia_release(link);
-	  }
-	break;
-
       case CS_EVENT_CARD_INSERTION:
 	/* Reset and configure the card */
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
@@ -4906,7 +4885,7 @@
 	},
 	.attach		= wavelan_attach,
 	.event		= wavelan_event,
-	.detach		= wavelan_detach,
+	.remove		= wavelan_detach,
 	.id_table       = wavelan_ids,
 	.suspend	= wavelan_suspend,
 	.resume		= wavelan_resume,
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index 724a715..3cb3481 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -757,7 +757,7 @@
 static dev_link_t *
 	wavelan_attach(void);		/* Create a new device */
 static void
-	wavelan_detach(dev_link_t *);	/* Destroy a removed device */
+	wavelan_detach(struct pcmcia_device *p_dev);	/* Destroy a removed device */
 static int
 	wavelan_event(event_t,		/* Manage pcmcia events */
 		      int,
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 7511431..21e498f 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1498,9 +1498,11 @@
  * Services. If it has been released, all local data structures are freed.
  * Otherwise, the structures will be freed when the device is released.
  */
-static void wl3501_detach(dev_link_t *link)
+static void wl3501_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	dev_link_t **linkp;
+	struct net_device *dev = link->priv;
 
 	/* Locate device structure */
 	for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next)
@@ -1514,16 +1516,12 @@
 	 * function is called, that will trigger a proper detach(). */
 
 	if (link->state & DEV_CONFIG) {
-#ifdef PCMCIA_DEBUG
-		printk(KERN_DEBUG "wl3501_cs: detach postponed, '%s' "
-		       "still locked\n", link->dev->dev_name);
-#endif
-		goto out;
-	}
+		while (link->open > 0)
+			wl3501_close(dev);
 
-	/* Break the link with Card Services */
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
+		netif_device_detach(dev);
+		wl3501_release(link);
+	}
 
 	/* Unlink device structure, free pieces */
 	*linkp = link->next;
@@ -2012,7 +2010,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret) {
 		cs_error(link->handle, RegisterClient, ret);
-		wl3501_detach(link);
+		wl3501_detach(link->handle);
 		link = NULL;
 	}
 out:
@@ -2225,18 +2223,8 @@
 static int wl3501_event(event_t event, int pri, event_callback_args_t *args)
 {
 	dev_link_t *link = args->client_data;
-	struct net_device *dev = link->priv;
 
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			while (link->open > 0)
-				wl3501_close(dev);
-			netif_device_detach(dev);
-			wl3501_release(link);
-		}
-		break;
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		wl3501_config(link);
@@ -2258,7 +2246,7 @@
 	},
 	.attach		= wl3501_attach,
 	.event		= wl3501_event,
-	.detach		= wl3501_detach,
+	.remove		= wl3501_detach,
 	.id_table	= wl3501_ids,
 	.suspend	= wl3501_suspend,
 	.resume		= wl3501_resume,
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 4c89853..063d22d 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -88,7 +88,7 @@
 } parport_info_t;
 
 static dev_link_t *parport_attach(void);
-static void parport_detach(dev_link_t *);
+static void parport_detach(struct pcmcia_device *p_dev);
 static void parport_config(dev_link_t *link);
 static void parport_cs_release(dev_link_t *);
 static int parport_event(event_t event, int priority,
@@ -137,7 +137,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
 	cs_error(link->handle, RegisterClient, ret);
-	parport_detach(link);
+	parport_detach(link->handle);
 	return NULL;
     }
     
@@ -153,13 +153,13 @@
 
 ======================================================================*/
 
-static void parport_detach(dev_link_t *link)
+static void parport_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
-    int ret;
 
     DEBUG(0, "parport_detach(0x%p)\n", link);
-    
+
     /* Locate device structure */
     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
 	if (*linkp == link) break;
@@ -168,17 +168,10 @@
 
     if (link->state & DEV_CONFIG)
 	parport_cs_release(link);
-    
-    if (link->handle) {
-	ret = pcmcia_deregister_client(link->handle);
-	if (ret != CS_SUCCESS)
-	    cs_error(link->handle, DeregisterClient, ret);
-    }
-    
+
     /* Unlink, free device structure */
     *linkp = link->next;
     kfree(link->priv);
-    
 } /* parport_detach */
 
 /*======================================================================
@@ -362,11 +355,6 @@
     DEBUG(1, "parport_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-		parport_cs_release(link);
-	break;
     case CS_EVENT_CARD_INSERTION:
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	parport_config(link);
@@ -389,7 +377,7 @@
 	},
 	.attach		= parport_attach,
 	.event		= parport_event,
-	.detach		= parport_detach,
+	.remove		= parport_detach,
 	.id_table	= parport_ids,
 	.suspend	= parport_suspend,
 	.resume		= parport_resume,
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 5223395..32b4d6b 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -57,8 +57,6 @@
 
 spinlock_t pcmcia_dev_list_lock;
 
-static int unbind_request(struct pcmcia_socket *s);
-
 /*====================================================================*/
 
 /* code which was in cs.c before */
@@ -205,7 +203,7 @@
 	unsigned int i;
 	u32 hash;
 
-	if (!p_drv->attach || !p_drv->event || !p_drv->detach)
+	if (!p_drv->attach || !p_drv->event || !p_drv->remove)
 		printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback "
 		       "function\n", p_drv->drv.name);
 
@@ -399,13 +397,42 @@
 {
 	struct pcmcia_device *p_dev;
 	struct pcmcia_driver *p_drv;
+	int i;
 
 	/* detach the "instance" */
 	p_dev = to_pcmcia_dev(dev);
 	p_drv = to_pcmcia_drv(dev->driver);
 
+	/* the likely, new path */
+	if (p_drv && p_drv->remove) {
+	       	p_drv->remove(p_dev);
+
+		/* check for proper unloading */
+		if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
+			printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
+			       p_drv->drv.name);
+
+		for (i = 0; i < MAX_WIN; i++)
+			if (p_dev->state & CLIENT_WIN_REQ(i))
+				printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
+				       p_drv->drv.name);
+
+		/* undo pcmcia_register_client */
+		p_dev->state = CLIENT_UNBOUND;
+		pcmcia_put_dev(p_dev);
+
+		/* references from pcmcia_probe_device */
+		pcmcia_put_dev(p_dev);
+		module_put(p_drv->owner);
+
+		return 0;
+	}
+
+	/* old path */
 	if (p_drv) {
 		if ((p_drv->detach) && (p_dev->instance)) {
+			printk(KERN_INFO "pcmcia: using deprecated detach mechanism. Fix the driver!\n");
+
 			p_drv->detach(p_dev->instance);
 			/* from pcmcia_probe_device */
 			put_device(&p_dev->dev);
@@ -417,6 +444,36 @@
 }
 
 
+/*
+ * Removes a PCMCIA card from the device tree and socket list.
+ */
+static void pcmcia_card_remove(struct pcmcia_socket *s)
+{
+	struct pcmcia_device	*p_dev;
+	unsigned long		flags;
+
+	ds_dbg(2, "unbind_request(%d)\n", s->sock);
+
+	s->device_count = 0;
+
+	for (;;) {
+		/* unregister all pcmcia_devices registered with this socket*/
+		spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+		if (list_empty(&s->devices_list)) {
+			spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ 			return;
+		}
+		p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
+		list_del(&p_dev->socket_device_list);
+		p_dev->state |= CLIENT_STALE;
+		spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+		device_unregister(&p_dev->dev);
+	}
+
+	return;
+} /* unbind_request */
+
 
 /*
  * pcmcia_device_query -- determine information about a pcmcia device
@@ -1059,8 +1116,8 @@
 
 	case CS_EVENT_CARD_REMOVAL:
 		s->pcmcia_state.present = 0;
-	    	send_event(skt, event, priority);
-		unbind_request(skt);
+		send_event(skt, event, priority);
+		pcmcia_card_remove(skt);
 		handle_event(skt, event);
 		break;
 	
@@ -1177,36 +1234,6 @@
 EXPORT_SYMBOL(pcmcia_register_client);
 
 
-/* unbind _all_ devices attached to a given pcmcia_bus_socket. The
- * drivers have been called with EVENT_CARD_REMOVAL before.
- */
-static int unbind_request(struct pcmcia_socket *s)
-{
-	struct pcmcia_device	*p_dev;
-	unsigned long		flags;
-
-	ds_dbg(2, "unbind_request(%d)\n", s->sock);
-
-	s->device_count = 0;
-
-	for (;;) {
-		/* unregister all pcmcia_devices registered with this socket*/
-		spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
-		if (list_empty(&s->devices_list)) {
-			spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- 			return 0;
-		}
-		p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
-		list_del(&p_dev->socket_device_list);
-		p_dev->state |= CLIENT_STALE;
-		spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-
-		device_unregister(&p_dev->dev);
-	}
-
-	return 0;
-} /* unbind_request */
-
 int pcmcia_deregister_client(struct pcmcia_device *p_dev)
 {
 	struct pcmcia_socket *s;
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 82988a3..3128ba8 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -99,7 +99,7 @@
 			 event_callback_args_t *args);
 
 static dev_link_t *aha152x_attach(void);
-static void aha152x_detach(dev_link_t *);
+static void aha152x_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list;
 static dev_info_t dev_info = "aha152x_cs";
@@ -138,7 +138,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
 	cs_error(link->handle, RegisterClient, ret);
-	aha152x_detach(link);
+	aha152x_detach(link->handle);
 	return NULL;
     }
     
@@ -147,8 +147,9 @@
 
 /*====================================================================*/
 
-static void aha152x_detach(dev_link_t *link)
+static void aha152x_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
 
     DEBUG(0, "aha152x_detach(0x%p)\n", link);
@@ -162,9 +163,6 @@
     if (link->state & DEV_CONFIG)
 	aha152x_release_cs(link);
 
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, free bits */
     *linkp = link->next;
     kfree(link->priv);
@@ -307,11 +305,6 @@
     DEBUG(0, "aha152x_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    aha152x_release_cs(link);
-	break;
     case CS_EVENT_CARD_INSERTION:
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	aha152x_config_cs(link);
@@ -337,7 +330,7 @@
 	},
 	.attach		= aha152x_attach,
 	.event		= aha152x_event,
-	.detach		= aha152x_detach,
+	.remove		= aha152x_detach,
 	.id_table       = aha152x_ids,
 	.suspend	= aha152x_suspend,
 	.resume		= aha152x_resume,
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 9e1d68c..5842c93 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -84,7 +84,7 @@
 			event_callback_args_t *args);
 
 static dev_link_t *fdomain_attach(void);
-static void fdomain_detach(dev_link_t *);
+static void fdomain_detach(struct pcmcia_device *p_dev);
 
 
 static dev_link_t *dev_list = NULL;
@@ -124,7 +124,7 @@
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
 	cs_error(link->handle, RegisterClient, ret);
-	fdomain_detach(link);
+	fdomain_detach(link->handle);
 	return NULL;
     }
     
@@ -133,8 +133,9 @@
 
 /*====================================================================*/
 
-static void fdomain_detach(dev_link_t *link)
+static void fdomain_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
 
     DEBUG(0, "fdomain_detach(0x%p)\n", link);
@@ -148,9 +149,6 @@
     if (link->state & DEV_CONFIG)
 	fdomain_release(link);
 
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, free bits */
     *linkp = link->next;
     kfree(link->priv);
@@ -288,11 +286,6 @@
     DEBUG(1, "fdomain_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    fdomain_release(link);
-	break;
     case CS_EVENT_CARD_INSERTION:
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	fdomain_config(link);
@@ -317,7 +310,7 @@
 	},
 	.attach		= fdomain_attach,
 	.event		= fdomain_event,
-	.detach		= fdomain_detach,
+	.remove		= fdomain_detach,
 	.id_table       = fdomain_ids,
 	.suspend	= fdomain_suspend,
 	.resume		= fdomain_resume,
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 870e871..e40a8c2 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1646,7 +1646,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != CS_SUCCESS) {
 		cs_error(link->handle, RegisterClient, ret);
-		nsp_cs_detach(link);
+		nsp_cs_detach(link->handle);
 		return NULL;
 	}
 
@@ -1662,8 +1662,9 @@
     structures are freed.  Otherwise, the structures will be freed
     when the device is released.
 ======================================================================*/
-static void nsp_cs_detach(dev_link_t *link)
+static void nsp_cs_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	dev_link_t **linkp;
 
 	nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
@@ -1678,12 +1679,9 @@
 		return;
 	}
 
-	if (link->state & DEV_CONFIG)
+	if (link->state & DEV_CONFIG) {
+		((scsi_info_t *)link->priv)->stop = 1;
 		nsp_cs_release(link);
-
-	/* Break the link with Card Services */
-	if (link->handle) {
-		pcmcia_deregister_client(link->handle);
 	}
 
 	/* Unlink device structure, free bits */
@@ -2096,15 +2094,6 @@
 	nsp_dbg(NSP_DEBUG_INIT, "in, event=0x%08x", event);
 
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		nsp_dbg(NSP_DEBUG_INIT, "event: remove");
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			((scsi_info_t *)link->priv)->stop = 1;
-			nsp_cs_release(link);
-		}
-		break;
-
 	case CS_EVENT_CARD_INSERTION:
 		nsp_dbg(NSP_DEBUG_INIT, "event: insert");
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
@@ -2144,7 +2133,7 @@
 	},
 	.attach		= nsp_cs_attach,
 	.event		= nsp_cs_event,
-	.detach		= nsp_cs_detach,
+	.remove		= nsp_cs_detach,
 	.id_table	= nsp_cs_ids,
 	.suspend	= nsp_cs_suspend,
 	.resume		= nsp_cs_resume,
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index f8b9430..d276c46 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -297,7 +297,7 @@
 
 /* Card service functions */
 static dev_link_t *nsp_cs_attach (void);
-static void        nsp_cs_detach (dev_link_t *link);
+static void        nsp_cs_detach (struct pcmcia_device *p_dev);
 static void        nsp_cs_release(dev_link_t *link);
 static void        nsp_cs_config (dev_link_t *link);
 static int         nsp_cs_event  (event_t event, int priority, event_callback_args_t *args);
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 2541a99..8351dc2 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -101,7 +101,7 @@
 static int qlogic_event(event_t event, int priority, event_callback_args_t * args);
 
 static dev_link_t *qlogic_attach(void);
-static void qlogic_detach(dev_link_t *);
+static void qlogic_detach(struct pcmcia_device *p_dev);
 
 
 static dev_link_t *dev_list = NULL;
@@ -198,7 +198,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != 0) {
 		cs_error(link->handle, RegisterClient, ret);
-		qlogic_detach(link);
+		qlogic_detach(link->handle);
 		return NULL;
 	}
 
@@ -207,8 +207,9 @@
 
 /*====================================================================*/
 
-static void qlogic_detach(dev_link_t * link)
+static void qlogic_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	dev_link_t **linkp;
 
 	DEBUG(0, "qlogic_detach(0x%p)\n", link);
@@ -223,9 +224,6 @@
 	if (link->state & DEV_CONFIG)
 		qlogic_release(link);
 
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
-
 	/* Unlink device structure, free bits */
 	*linkp = link->next;
 	kfree(link->priv);
@@ -390,11 +388,6 @@
 	DEBUG(1, "qlogic_event(0x%06x)\n", event);
 
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG)
-			qlogic_release(link);
-		break;
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		qlogic_config(link);
@@ -432,7 +425,7 @@
 	},
 	.attach		= qlogic_attach,
 	.event		= qlogic_event,
-	.detach		= qlogic_detach,
+	.remove		= qlogic_detach,
 	.id_table       = qlogic_ids,
 	.suspend	= qlogic_suspend,
 	.resume		= qlogic_resume,
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index c4e3e22..a0f8e269 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -918,11 +918,6 @@
 	DEBUG(1, "SYM53C500_event(0x%06x)\n", event);
 
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG)
-			SYM53C500_release(link);
-		break;
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		SYM53C500_config(link);
@@ -932,8 +927,9 @@
 } /* SYM53C500_event */
 
 static void
-SYM53C500_detach(dev_link_t *link)
+SYM53C500_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	dev_link_t **linkp;
 
 	DEBUG(0, "SYM53C500_detach(0x%p)\n", link);
@@ -948,9 +944,6 @@
 	if (link->state & DEV_CONFIG)
 		SYM53C500_release(link);
 
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
-
 	/* Unlink device structure, free bits. */
 	*linkp = link->next;
 	kfree(link->priv);
@@ -993,7 +986,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != 0) {
 		cs_error(link->handle, RegisterClient, ret);
-		SYM53C500_detach(link);
+		SYM53C500_detach(link->handle);
 		return NULL;
 	}
 
@@ -1019,7 +1012,7 @@
 	},
 	.attach		= SYM53C500_attach,
 	.event		= SYM53C500_event,
-	.detach		= SYM53C500_detach,
+	.remove		= SYM53C500_detach,
 	.id_table       = sym53c500_ids,
 	.suspend	= sym53c500_suspend,
 	.resume		= sym53c500_resume,
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 3487ee9..a953663 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -120,7 +120,7 @@
 static dev_info_t dev_info = "serial_cs";
 
 static dev_link_t *serial_attach(void);
-static void serial_detach(dev_link_t *);
+static void serial_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list = NULL;
 
@@ -242,7 +242,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != CS_SUCCESS) {
 		cs_error(link->handle, RegisterClient, ret);
-		serial_detach(link);
+		serial_detach(link->handle);
 		return NULL;
 	}
 
@@ -258,11 +258,11 @@
 
 ======================================================================*/
 
-static void serial_detach(dev_link_t * link)
+static void serial_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct serial_info *info = link->priv;
 	dev_link_t **linkp;
-	int ret;
 
 	DEBUG(0, "serial_detach(0x%p)\n", link);
 
@@ -283,12 +283,6 @@
 	 */
 	serial_remove(link);
 
-	if (link->handle) {
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
-	}
-
 	/* Unlink device structure, free bits */
 	*linkp = link->next;
 	kfree(info);
@@ -741,9 +735,6 @@
 	DEBUG(1, "serial_event(0x%06x)\n", event);
 
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		serial_remove(link);
-		break;
 
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
@@ -866,7 +857,7 @@
 	},
 	.attach		= serial_attach,
 	.event		= serial_event,
-	.detach		= serial_detach,
+	.remove		= serial_detach,
 	.id_table	= serial_ids,
 	.suspend	= serial_suspend,
 	.resume		= serial_resume,
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index 7cca46b..c58140d 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -35,7 +35,7 @@
 } ixj_info_t;
 
 static dev_link_t *ixj_attach(void);
-static void ixj_detach(dev_link_t *);
+static void ixj_detach(struct pcmcia_device *p_dev);
 static void ixj_config(dev_link_t * link);
 static void ixj_cs_release(dev_link_t * link);
 static int ixj_event(event_t event, int priority, event_callback_args_t * args);
@@ -73,16 +73,17 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != CS_SUCCESS) {
 		cs_error(link->handle, RegisterClient, ret);
-		ixj_detach(link);
+		ixj_detach(link->handle);
 		return NULL;
 	}
 	return link;
 }
 
-static void ixj_detach(dev_link_t * link)
+static void ixj_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	dev_link_t **linkp;
-	int ret;
+
 	DEBUG(0, "ixj_detach(0x%p)\n", link);
 	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
 		if (*linkp == link)
@@ -92,11 +93,7 @@
 	link->state &= ~DEV_RELEASE_PENDING;
 	if (link->state & DEV_CONFIG)
 		ixj_cs_release(link);
-	if (link->handle) {
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
-	}
+
 	/* Unlink device structure, free bits */
 	*linkp = link->next;
         kfree(link->priv);
@@ -282,13 +279,6 @@
 	dev_link_t *link = args->client_data;
 	DEBUG(1, "ixj_event(0x%06x)\n", event);
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			link->state |= DEV_RELEASE_PENDING;
-			ixj_cs_release(link);
-		}
-		break;
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		ixj_config(link);
@@ -310,7 +300,7 @@
 	},
 	.attach		= ixj_attach,
 	.event		= ixj_event,
-	.detach		= ixj_detach,
+	.remove		= ixj_detach,
 	.id_table	= ixj_ids,
 	.suspend	= ixj_suspend,
 	.resume		= ixj_resume,
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index cb8c2bd..ed3e701 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -73,6 +73,8 @@
 	dev_node_t		node;
 } local_info_t;
 
+static void sl811_cs_release(dev_link_t * link);
+
 /*====================================================================*/
 
 static void release_platform_dev(struct device * dev)
@@ -138,8 +140,9 @@
 
 /*====================================================================*/
 
-static void sl811_cs_detach(dev_link_t *link)
+static void sl811_cs_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	dev_link_t **linkp;
 
 	DBG(0, "sl811_cs_detach(0x%p)\n", link);
@@ -152,9 +155,9 @@
 	if (*linkp == NULL)
 		return;
 
-	/* Break the link with Card Services */
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
+	link->state &= ~DEV_PRESENT;
+	if (link->state & DEV_CONFIG)
+		sl811_cs_release(link);
 
 	/* Unlink device structure, and free it */
 	*linkp = link->next;
@@ -167,13 +170,6 @@
 
 	DBG(0, "sl811_cs_release(0x%p)\n", link);
 
-	if (link->open) {
-		DBG(1, "sl811_cs: release postponed, '%s' still open\n",
-		    link->dev->dev_name);
-		link->state |= DEV_STALE_CONFIG;
-		return;
-	}
-
 	/* Unlink the device chain */
 	link->dev = NULL;
 
@@ -184,9 +180,6 @@
 	if (link->irq.AssignedIRQ)
 		pcmcia_release_irq(link->handle, &link->irq);
 	link->state &= ~DEV_CONFIG;
-
-	if (link->state & DEV_STALE_LINK)
-		sl811_cs_detach(link);
 }
 
 static void sl811_cs_config(dev_link_t *link)
@@ -353,12 +346,6 @@
 	DBG(1, "sl811_cs_event(0x%06x)\n", event);
 
 	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG)
-			sl811_cs_release(link);
-		break;
-
 	case CS_EVENT_CARD_INSERTION:
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		sl811_cs_config(link);
@@ -400,7 +387,7 @@
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != CS_SUCCESS) {
 		cs_error(link->handle, RegisterClient, ret);
-		sl811_cs_detach(link);
+		sl811_cs_detach(link->handle);
 		return NULL;
 	}
 
@@ -420,7 +407,7 @@
 	},
 	.attach		= sl811_cs_attach,
 	.event		= sl811_cs_event,
-	.detach		= sl811_cs_detach,
+	.remove		= sl811_cs_detach,
 	.id_table	= sl811_ids,
 	.suspend	= sl811_suspend,
 	.resume		= sl811_resume,
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 0200551..2869283 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -138,6 +138,8 @@
 				 event_callback_args_t *);
 	void			(*detach)(dev_link_t *);
 
+	void (*remove)		(struct pcmcia_device *dev);
+
 	int (*suspend)		(struct pcmcia_device *dev);
 	int (*resume)		(struct pcmcia_device *dev);