[PATCH] pcmcia: new suspend core

Move the suspend and resume methods out of the event handler, and into
special functions. Also use these functions for pre- and post-reset, as
almost all drivers already do, and the remaining ones can easily be
converted.

Bugfix to include/pcmcia/ds.c
Signed-off-by: Andrew Morton <akpm@osdl.org>

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

diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index e328547..80c9de7 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -492,6 +492,35 @@
 	link->state &= ~DEV_CONFIG;
 }
 
+static int airo_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	local_info_t *local = link->priv;
+
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		netif_device_detach(local->eth_dev);
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
+
+static int airo_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	local_info_t *local = link->priv;
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		pcmcia_request_configuration(link->handle, &link->conf);
+		reset_airo_card(local->eth_dev);
+		netif_device_attach(local->eth_dev);
+	}
+
+	return 0;
+}
+
 /*======================================================================
   
   The card status event handler.  Mostly, this schedules other
@@ -524,25 +553,6 @@
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		airo_config(link);
 		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG) {
-			netif_device_detach(local->eth_dev);
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			pcmcia_request_configuration(link->handle, &link->conf);
-			reset_airo_card(local->eth_dev);
-			netif_device_attach(local->eth_dev);
-		}
-		break;
 	}
 	return 0;
 } /* airo_event */
@@ -565,6 +575,8 @@
 	.event		= airo_event,
 	.detach		= airo_detach,
 	.id_table       = airo_ids,
+	.suspend	= airo_suspend,
+	.resume		= airo_resume,
 };
 
 static int airo_cs_init(void)
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 17d1fd9..598a9cd 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -477,6 +477,35 @@
 	link->state &= ~DEV_CONFIG;
 }
 
+static int atmel_suspend(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+	local_info_t *local = link->priv;
+
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		netif_device_detach(local->eth_dev);
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
+
+static int atmel_resume(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+	local_info_t *local = link->priv;
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		pcmcia_request_configuration(link->handle, &link->conf);
+		atmel_open(local->eth_dev);
+		netif_device_attach(local->eth_dev);
+	}
+
+	return 0;
+}
+
 /*======================================================================
   
   The card status event handler.  Mostly, this schedules other
@@ -509,25 +538,6 @@
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		atmel_config(link);
 		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG) {
-			netif_device_detach(local->eth_dev);
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			pcmcia_request_configuration(link->handle, &link->conf);
-			atmel_open(local->eth_dev);
-			netif_device_attach(local->eth_dev);
-		}
-		break;
 	}
 	return 0;
 } /* atmel_event */
@@ -585,6 +595,8 @@
 	.event		= atmel_event,
 	.detach		= atmel_detach,
 	.id_table	= atmel_ids,
+	.suspend	= atmel_suspend,
+	.resume		= atmel_resume,
 };
 
 static int atmel_cs_init(void)
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 2643976..ba4a7da 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -846,19 +846,63 @@
 	PDEBUG(DEBUG_FLOW, "release - done\n");
 }
 
+static int hostap_cs_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = (struct net_device *) link->priv;
+	int dev_open = 0;
+
+	PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
+
+	link->state |= DEV_SUSPEND;
+
+	if (link->state & DEV_CONFIG) {
+		struct hostap_interface *iface = netdev_priv(dev);
+		if (iface && iface->local)
+			dev_open = iface->local->num_dev_open > 0;
+		if (dev_open) {
+			netif_stop_queue(dev);
+			netif_device_detach(dev);
+		}
+		prism2_suspend(dev);
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
+
+static int hostap_cs_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = (struct net_device *) link->priv;
+	int dev_open = 0;
+
+	PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		struct hostap_interface *iface = netdev_priv(dev);
+		if (iface && iface->local)
+			dev_open = iface->local->num_dev_open > 0;
+
+		pcmcia_request_configuration(link->handle, &link->conf);
+
+		prism2_hw_shutdown(dev, 1);
+		prism2_hw_config(dev, dev_open ? 0 : 1);
+		if (dev_open) {
+			netif_device_attach(dev);
+			netif_start_queue(dev);
+		}
+	}
+
+	return 0;
+}
 
 static int prism2_event(event_t event, int priority,
 			event_callback_args_t *args)
 {
 	dev_link_t *link = args->client_data;
 	struct net_device *dev = (struct net_device *) link->priv;
-	int dev_open = 0;
-
-	if (link->state & DEV_CONFIG) {
-		struct hostap_interface *iface = netdev_priv(dev);
-		if (iface && iface->local)
-			dev_open = iface->local->num_dev_open > 0;
-	}
 
 	switch (event) {
 	case CS_EVENT_CARD_INSERTION:
@@ -879,42 +923,6 @@
 		}
 		break;
 
-	case CS_EVENT_PM_SUSPEND:
-		PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
-		link->state |= DEV_SUSPEND;
-		/* fall through */
-
-	case CS_EVENT_RESET_PHYSICAL:
-		PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info);
-		if (link->state & DEV_CONFIG) {
-			if (dev_open) {
-				netif_stop_queue(dev);
-				netif_device_detach(dev);
-			}
-			prism2_suspend(dev);
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
-
-	case CS_EVENT_PM_RESUME:
-		PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
-		link->state &= ~DEV_SUSPEND;
-		/* fall through */
-
-	case CS_EVENT_CARD_RESET:
-		PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_RESET\n", dev_info);
-		if (link->state & DEV_CONFIG) {
-			pcmcia_request_configuration(link->handle,
-						     &link->conf);
-			prism2_hw_shutdown(dev, 1);
-			prism2_hw_config(dev, dev_open ? 0 : 1);
-			if (dev_open) {
-				netif_device_attach(dev);
-				netif_start_queue(dev);
-			}
-		}
-		break;
-
 	default:
 		PDEBUG(DEBUG_EXTRA, "%s: prism2_event() - unknown event %d\n",
 		       dev_info, event);
@@ -987,6 +995,8 @@
 	.owner		= THIS_MODULE,
 	.event		= prism2_event,
 	.id_table	= hostap_cs_ids,
+	.suspend	= hostap_cs_suspend,
+	.resume		= hostap_cs_resume,
 };
 
 static int __init init_prism2_pccard(void)
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 92793b9..7ab2d70 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -935,6 +935,39 @@
     link->state &= ~DEV_CONFIG;
 }
 
+static int netwave_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		if (link->open)
+			netif_device_detach(dev);
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
+
+static int netwave_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			netwave_reset(dev);
+			netif_device_attach(dev);
+		}
+	}
+
+	return 0;
+}
+
+
 /*
  * Function netwave_event (event, priority, args)
  *
@@ -973,28 +1006,6 @@
 	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 	netwave_pcmcia_config( link);
 	break;
-    case CS_EVENT_PM_SUSPEND:
-	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
-	if (link->state & DEV_CONFIG) {
-	    if (link->open)
-		netif_device_detach(dev);
-	    pcmcia_release_configuration(link->handle);
-	}
-	break;
-    case CS_EVENT_PM_RESUME:
-	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
-	if (link->state & DEV_CONFIG) {
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	    if (link->open) {
-		netwave_reset(dev);
-		netif_device_attach(dev);
-	    }
-	}
-	break;
     }
     return 0;
 } /* netwave_event */
@@ -1495,6 +1506,8 @@
 	.event		= netwave_event,
 	.detach		= netwave_detach,
 	.id_table       = netwave_ids,
+	.suspend	= netwave_suspend,
+	.resume		= netwave_resume,
 };
 
 static int __init init_netwave_cs(void)
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index dc1128a..1d66050 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -465,6 +465,83 @@
 		ioport_unmap(priv->hw.iobase);
 }				/* orinoco_cs_release */
 
+static int orinoco_cs_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct orinoco_pccard *card = priv->card;
+	int err = 0;
+	unsigned long flags;
+
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		/* This is probably racy, but I can't think of
+		   a better way, short of rewriting the PCMCIA
+		   layer to not suck :-( */
+		if (! test_bit(0, &card->hard_reset_in_progress)) {
+			spin_lock_irqsave(&priv->lock, flags);
+
+			err = __orinoco_down(dev);
+			if (err)
+				printk(KERN_WARNING "%s: Error %d downing interface\n",
+				       dev->name, err);
+
+			netif_device_detach(dev);
+			priv->hw_unavailable++;
+
+			spin_unlock_irqrestore(&priv->lock, flags);
+		}
+
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
+
+static int orinoco_cs_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct orinoco_pccard *card = priv->card;
+	int err = 0;
+	unsigned long flags;
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		/* FIXME: should we double check that this is
+		 * the same card as we had before */
+		pcmcia_request_configuration(link->handle, &link->conf);
+
+		if (! test_bit(0, &card->hard_reset_in_progress)) {
+			err = orinoco_reinit_firmware(dev);
+			if (err) {
+				printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
+				       dev->name, err);
+				return -EIO;
+			}
+
+			spin_lock_irqsave(&priv->lock, flags);
+
+			netif_device_attach(dev);
+			priv->hw_unavailable--;
+
+			if (priv->open && ! priv->hw_unavailable) {
+				err = __orinoco_up(dev);
+				if (err)
+					printk(KERN_ERR "%s: Error %d restarting card\n",
+					       dev->name, err);
+			}
+
+			spin_unlock_irqrestore(&priv->lock, flags);
+		}
+	}
+
+	return 0;
+}
+
+
 /*
  * The card status event handler.  Mostly, this schedules other stuff
  * to run after an event is received.
@@ -476,9 +553,7 @@
 	dev_link_t *link = args->client_data;
 	struct net_device *dev = link->priv;
 	struct orinoco_private *priv = netdev_priv(dev);
-	struct orinoco_pccard *card = priv->card;
 	int err = 0;
-	unsigned long flags;
 
 	switch (event) {
 	case CS_EVENT_CARD_REMOVAL:
@@ -497,70 +572,6 @@
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		orinoco_cs_config(link);
 		break;
-
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		/* Mark the device as stopped, to block IO until later */
-		if (link->state & DEV_CONFIG) {
-			/* This is probably racy, but I can't think of
-                           a better way, short of rewriting the PCMCIA
-                           layer to not suck :-( */
-			if (! test_bit(0, &card->hard_reset_in_progress)) {
-				spin_lock_irqsave(&priv->lock, flags);
-
-				err = __orinoco_down(dev);
-				if (err)
-					printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
-					       dev->name,
-					       event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
-					       err);
-				
-				netif_device_detach(dev);
-				priv->hw_unavailable++;
-
-				spin_unlock_irqrestore(&priv->lock, flags);
-			}
-
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
-
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			/* FIXME: should we double check that this is
-			 * the same card as we had before */
-			pcmcia_request_configuration(link->handle, &link->conf);
-
-			if (! test_bit(0, &card->hard_reset_in_progress)) {
-				err = orinoco_reinit_firmware(dev);
-				if (err) {
-					printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
-					       dev->name, err);
-					break;
-				}
-				
-				spin_lock_irqsave(&priv->lock, flags);
-				
-				netif_device_attach(dev);
-				priv->hw_unavailable--;
-				
-				if (priv->open && ! priv->hw_unavailable) {
-					err = __orinoco_up(dev);
-					if (err)
-						printk(KERN_ERR "%s: Error %d restarting card\n",
-						       dev->name, err);
-					
-				}
-
-				spin_unlock_irqrestore(&priv->lock, flags);
-			}
-		}
-		break;
 	}
 
 	return err;
@@ -669,6 +680,8 @@
 	.detach		= orinoco_cs_detach,
 	.event		= orinoco_cs_event,
 	.id_table       = orinoco_cs_ids,
+	.suspend	= orinoco_cs_suspend,
+	.resume		= orinoco_cs_resume,
 };
 
 static int __init
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 70fd6fd..c2cb6c8 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -891,6 +891,40 @@
     DEBUG(2,"ray_release ending\n");
 }
 
+static int ray_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
+	link->state |= DEV_SUSPEND;
+        if (link->state & DEV_CONFIG) {
+		if (link->open)
+			netif_device_detach(dev);
+
+		pcmcia_release_configuration(link->handle);
+        }
+
+
+	return 0;
+}
+
+static int ray_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
+	link->state &= ~DEV_SUSPEND;
+        if (link->state & DEV_CONFIG) {
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			ray_reset(dev);
+			netif_device_attach(dev);
+		}
+        }
+
+	return 0;
+}
+
 /*=============================================================================
     The card status event handler.  Mostly, this schedules other
     stuff to run after an event is received.  A CARD_REMOVAL event
@@ -923,29 +957,6 @@
         link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
         ray_config(link);
         break;
-    case CS_EVENT_PM_SUSPEND:
-        link->state |= DEV_SUSPEND;
-        /* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
-        if (link->state & DEV_CONFIG) {
-            if (link->open)
-            	netif_device_detach(dev);
-
-            pcmcia_release_configuration(link->handle);
-        }
-        break;
-    case CS_EVENT_PM_RESUME:
-        link->state &= ~DEV_SUSPEND;
-        /* Fall through... */
-    case CS_EVENT_CARD_RESET:
-        if (link->state & DEV_CONFIG) {
-            pcmcia_request_configuration(link->handle, &link->conf);
-            if (link->open) {
-                ray_reset(dev);
-		netif_device_attach(dev);
-            }
-        }
-        break;
     }
     return 0;
     DEBUG(2,"ray_event ending\n");
@@ -2949,6 +2960,8 @@
 	.event		= ray_event,
 	.detach		= ray_detach,
 	.id_table       = ray_ids,
+	.suspend	= ray_suspend,
+	.resume		= ray_resume,
 };
 
 static int __init init_ray_cs(void)
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index b1bbc8e..3938a57 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -948,6 +948,56 @@
 		ioport_unmap(priv->hw.iobase);
 }				/* spectrum_cs_release */
 
+
+static int
+spectrum_cs_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
+	unsigned long flags;
+	int err = 0;
+
+	link->state |= DEV_SUSPEND;
+	/* Mark the device as stopped, to block IO until later */
+	if (link->state & DEV_CONFIG) {
+		spin_lock_irqsave(&priv->lock, flags);
+
+		err = __orinoco_down(dev);
+		if (err)
+			printk(KERN_WARNING "%s: Error %d downing interface\n",
+			       dev->name, err);
+
+		netif_device_detach(dev);
+		priv->hw_unavailable++;
+
+		spin_unlock_irqrestore(&priv->lock, flags);
+
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
+
+static int
+spectrum_cs_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		/* FIXME: should we double check that this is
+		 * the same card as we had before */
+		pcmcia_request_configuration(link->handle, &link->conf);
+		netif_device_attach(dev);
+		priv->hw_unavailable--;
+		schedule_work(&priv->reset_work);
+	}
+	return 0;
+}
+
 /*
  * The card status event handler.  Mostly, this schedules other stuff
  * to run after an event is received.
@@ -959,8 +1009,6 @@
 	dev_link_t *link = args->client_data;
 	struct net_device *dev = link->priv;
 	struct orinoco_private *priv = netdev_priv(dev);
-	int err = 0;
-	unsigned long flags;
 
 	switch (event) {
 	case CS_EVENT_CARD_REMOVAL:
@@ -980,49 +1028,9 @@
 		spectrum_cs_config(link);
 		break;
 
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		/* Mark the device as stopped, to block IO until later */
-		if (link->state & DEV_CONFIG) {
-			/* This is probably racy, but I can't think of
-                           a better way, short of rewriting the PCMCIA
-                           layer to not suck :-( */
-			spin_lock_irqsave(&priv->lock, flags);
-
-			err = __orinoco_down(dev);
-			if (err)
-				printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
-				       dev->name,
-				       event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
-				       err);
-
-			netif_device_detach(dev);
-			priv->hw_unavailable++;
-
-			spin_unlock_irqrestore(&priv->lock, flags);
-
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
-
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			/* FIXME: should we double check that this is
-			 * the same card as we had before */
-			pcmcia_request_configuration(link->handle, &link->conf);
-			netif_device_attach(dev);
-			priv->hw_unavailable--;
-			schedule_work(&priv->reset_work);
-		}
-		break;
 	}
 
-	return err;
+	return 0;
 }				/* spectrum_cs_event */
 
 /********************************************************************/
@@ -1050,6 +1058,8 @@
 	},
 	.attach		= spectrum_cs_attach,
 	.detach		= spectrum_cs_detach,
+	.suspend	= spectrum_cs_suspend,
+	.resume		= spectrum_cs_resume,
 	.event		= spectrum_cs_event,
 	.id_table       = spectrum_cs_ids,
 };
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index c822cad..3e35328 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -4775,6 +4775,56 @@
 #endif
 }
 
+static int wavelan_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *	dev = (struct net_device *) link->priv;
+
+	/* NB: wavelan_close will be called, but too late, so we are
+	 * obliged to close nicely the wavelan here. David, could you
+	 * close the device before suspending them ? And, by the way,
+	 * could you, on resume, add a "route add -net ..." after the
+	 * ifconfig up ? Thanks... */
+
+	/* Stop receiving new messages and wait end of transmission */
+	wv_ru_stop(dev);
+
+	/* Power down the module */
+	hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT));
+
+	/* The card is now suspended */
+	link->state |= DEV_SUSPEND;
+
+    	if(link->state & DEV_CONFIG)
+	{
+		if(link->open)
+			netif_device_detach(dev);
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
+
+static int wavelan_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *	dev = (struct net_device *) link->priv;
+
+	link->state &= ~DEV_SUSPEND;
+	if(link->state & DEV_CONFIG)
+	{
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if(link->open)	/* If RESET -> True, If RESUME -> False ? */
+		{
+			wv_hw_reset(dev);
+			netif_device_attach(dev);
+		}
+	}
+
+	return 0;
+}
+
+
 /*------------------------------------------------------------------*/
 /*
  * The card status event handler. Mostly, this schedules other stuff
@@ -4832,46 +4882,6 @@
 	else
 	  dev->irq = 0;
 	break;
-
-      case CS_EVENT_PM_SUSPEND:
-	/* NB: wavelan_close will be called, but too late, so we are
-	 * obliged to close nicely the wavelan here. David, could you
-	 * close the device before suspending them ? And, by the way,
-	 * could you, on resume, add a "route add -net ..." after the
-	 * ifconfig up ? Thanks... */
-
-	/* Stop receiving new messages and wait end of transmission */
-	wv_ru_stop(dev);
-
-	/* Power down the module */
-	hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT));
-
-	/* The card is now suspended */
-	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-      case CS_EVENT_RESET_PHYSICAL:
-    	if(link->state & DEV_CONFIG)
-	  {
-      	    if(link->open)
-	      netif_device_detach(dev);
-      	    pcmcia_release_configuration(link->handle);
-	  }
-	break;
-
-      case CS_EVENT_PM_RESUME:
-	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-      case CS_EVENT_CARD_RESET:
-	if(link->state & DEV_CONFIG)
-	  {
-      	    pcmcia_request_configuration(link->handle, &link->conf);
-      	    if(link->open)	/* If RESET -> True, If RESUME -> False ? */
-	      {
-		wv_hw_reset(dev);
-		netif_device_attach(dev);
-	      }
-	  }
-	break;
     }
 
 #ifdef DEBUG_CALLBACK_TRACE
@@ -4898,6 +4908,8 @@
 	.event		= wavelan_event,
 	.detach		= wavelan_detach,
 	.id_table       = wavelan_ids,
+	.suspend	= wavelan_suspend,
+	.resume		= wavelan_resume,
 };
 
 static int __init
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 978fdc6..7511431 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -2173,6 +2173,41 @@
 	link->state &= ~DEV_CONFIG;
 }
 
+static int wl3501_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
+	link->state |= DEV_SUSPEND;
+
+	wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
+	if (link->state & DEV_CONFIG) {
+		if (link->open)
+			netif_device_detach(dev);
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
+
+static int wl3501_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
+	wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
+	if (link->state & DEV_CONFIG) {
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			wl3501_reset(dev);
+			netif_device_attach(dev);
+		}
+	}
+
+	return 0;
+}
+
+
 /**
  * wl3501_event - The card status event handler
  * @event - event
@@ -2206,30 +2241,6 @@
 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 		wl3501_config(link);
 		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG) {
-			if (link->open)
-				netif_device_detach(dev);
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			pcmcia_request_configuration(link->handle, &link->conf);
-			if (link->open) {
-				wl3501_reset(dev);
-				netif_device_attach(dev);
-			}
-		}
-		break;
 	}
 	return 0;
 }
@@ -2249,6 +2260,8 @@
 	.event		= wl3501_event,
 	.detach		= wl3501_detach,
 	.id_table	= wl3501_ids,
+	.suspend	= wl3501_suspend,
+	.resume		= wl3501_resume,
 };
 
 static int __init wl3501_init_module(void)