ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW);
                if (ret == 0) {
                        send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
-                       if (socket_reset(skt) == CS_SUCCESS)
+                       if (skt->callback)
+                               skt->callback->suspend(skt);
+                       if (socket_reset(skt) == CS_SUCCESS) {
                                send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
+                               if (skt->callback)
+                                       skt->callback->resume(skt);
+                       }
                }
 
                ret = CS_SUCCESS;
                        ret = CS_UNSUPPORTED_FUNCTION;
                        break;
                }
+               if (skt->callback) {
+                       ret = skt->callback->suspend(skt);
+                       if (ret)
+                               break;
+               }
                ret = socket_suspend(skt);
        } while (0);
        up(&skt->skt_sem);
                        break;
                }
                ret = socket_resume(skt);
+               if (!ret && skt->callback)
+                       skt->callback->resume(skt);
        } while (0);
        up(&skt->skt_sem);
 
 
        __ATTR_NULL,
 };
 
+/* PM support, also needed for reset */
+
+static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
+{
+       struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+       struct pcmcia_driver *p_drv = NULL;
+
+       if (dev->driver)
+               p_drv = to_pcmcia_drv(dev->driver);
+
+       if (p_drv && p_drv->suspend)
+               return p_drv->suspend(p_dev);
+
+       return 0;
+}
+
+
+static int pcmcia_dev_resume(struct device * dev)
+{
+       struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+        struct pcmcia_driver *p_drv = NULL;
+
+       if (dev->driver)
+               p_drv = to_pcmcia_drv(dev->driver);
+
+       if (p_drv && p_drv->resume)
+               return p_drv->resume(p_dev);
+
+       return 0;
+}
+
+
+static int pcmcia_bus_suspend_callback(struct device *dev, void * _data)
+{
+       struct pcmcia_socket *skt = _data;
+       struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+
+       if (p_dev->socket != skt)
+               return 0;
+
+       return dpm_runtime_suspend(dev, PMSG_SUSPEND);
+}
+
+static int pcmcia_bus_resume_callback(struct device *dev, void * _data)
+{
+       struct pcmcia_socket *skt = _data;
+       struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+
+       if (p_dev->socket != skt)
+               return 0;
+
+       dpm_runtime_resume(dev);
+
+       return 0;
+}
+
+static int pcmcia_bus_resume(struct pcmcia_socket *skt)
+{
+       bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback);
+       return 0;
+}
+
+static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
+{
+       if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt,
+                            pcmcia_bus_suspend_callback)) {
+               pcmcia_bus_resume(skt);
+               return -EIO;
+       }
+       return 0;
+}
+
 
 /*======================================================================
 
        if (p_dev->state & (CLIENT_UNBOUND|CLIENT_STALE))
                return 0;
 
-       if ((data->event == CS_EVENT_PM_SUSPEND) ||
-           (data->event == CS_EVENT_RESET_PHYSICAL)) {
-               if (p_drv->suspend)
-                       return p_drv->suspend(p_dev);
-       } else if ((data->event == CS_EVENT_PM_RESUME) ||
-                  (data->event == CS_EVENT_CARD_RESET)) {
-               if (p_drv->resume)
-                       return p_drv->resume(p_dev);
-       }
-
        if (p_drv->event)
                return p_drv->event(data->event, data->priority,
                                    &p_dev->event_callback_args);
                ret = send_event(skt, event, priority);
                break;
 
+       case CS_EVENT_PM_SUSPEND:
+       case CS_EVENT_PM_RESUME:
+       case CS_EVENT_RESET_PHYSICAL:
+       case CS_EVENT_CARD_RESET:
+               handle_event(skt, event);
+               break;
+
        default:
                handle_event(skt, event);
                send_event(skt, event, priority);
 } /* deregister_client */
 EXPORT_SYMBOL(pcmcia_deregister_client);
 
+
 static struct pcmcia_callback pcmcia_bus_callback = {
        .owner = THIS_MODULE,
        .event = ds_event,
        .requery = pcmcia_bus_rescan,
+       .suspend = pcmcia_bus_suspend,
+       .resume = pcmcia_bus_resume,
 };
 
 static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev,
        .uevent = pcmcia_bus_uevent,
        .match = pcmcia_bus_match,
        .dev_attrs = pcmcia_dev_attrs,
+       .suspend = pcmcia_dev_suspend,
+       .resume = pcmcia_dev_resume,
 };