]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
[SCSI] convert to the new PM framework
authorAlan Stern <stern@rowland.harvard.edu>
Thu, 17 Jun 2010 14:36:49 +0000 (10:36 -0400)
committerJames Bottomley <James.Bottomley@suse.de>
Wed, 28 Jul 2010 14:07:49 +0000 (09:07 -0500)
This patch (as1397b) converts the SCSI midlayer to use the new PM
callbacks (struct dev_pm_ops).  A new source file, scsi_pm.c, is
created to hold the new callback routines, and the existing
suspend/resume code is moved there.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/Makefile
drivers/scsi/scsi_pm.c [new file with mode: 0644]
drivers/scsi/scsi_priv.h
drivers/scsi/scsi_sysfs.c

index 1c7ac49be649087b3b9962a1bd8e1096132ec2d0..2a3fca2eca6ae00d8ec9f4a084610daf47a60ece 100644 (file)
@@ -163,6 +163,7 @@ scsi_mod-$(CONFIG_SCSI_NETLINK)     += scsi_netlink.o
 scsi_mod-$(CONFIG_SYSCTL)      += scsi_sysctl.o
 scsi_mod-$(CONFIG_SCSI_PROC_FS)        += scsi_proc.o
 scsi_mod-y                     += scsi_trace.o
+scsi_mod-$(CONFIG_PM_OPS)      += scsi_pm.o
 
 scsi_tgt-y                     += scsi_tgt_lib.o scsi_tgt_if.o
 
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
new file mode 100644 (file)
index 0000000..cd83758
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *     scsi_pm.c       Copyright (C) 2010 Alan Stern
+ *
+ *     SCSI dynamic Power Management
+ *             Initial version: Alan Stern <stern@rowland.harvard.edu>
+ */
+
+#include <linux/pm_runtime.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_host.h>
+
+#include "scsi_priv.h"
+
+static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg)
+{
+       struct device_driver *drv;
+       int err;
+
+       err = scsi_device_quiesce(to_scsi_device(dev));
+       if (err == 0) {
+               drv = dev->driver;
+               if (drv && drv->suspend)
+                       err = drv->suspend(dev, msg);
+       }
+       dev_dbg(dev, "scsi suspend: %d\n", err);
+       return err;
+}
+
+static int scsi_dev_type_resume(struct device *dev)
+{
+       struct device_driver *drv;
+       int err = 0;
+
+       drv = dev->driver;
+       if (drv && drv->resume)
+               err = drv->resume(dev);
+       scsi_device_resume(to_scsi_device(dev));
+       dev_dbg(dev, "scsi resume: %d\n", err);
+       return err;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg)
+{
+       int err = 0;
+
+       if (scsi_is_sdev_device(dev))
+               err = scsi_dev_type_suspend(dev, msg);
+       return err;
+}
+
+static int scsi_bus_resume_common(struct device *dev)
+{
+       int err = 0;
+
+       if (scsi_is_sdev_device(dev))
+               err = scsi_dev_type_resume(dev);
+       return err;
+}
+
+static int scsi_bus_suspend(struct device *dev)
+{
+       return scsi_bus_suspend_common(dev, PMSG_SUSPEND);
+}
+
+static int scsi_bus_freeze(struct device *dev)
+{
+       return scsi_bus_suspend_common(dev, PMSG_FREEZE);
+}
+
+static int scsi_bus_poweroff(struct device *dev)
+{
+       return scsi_bus_suspend_common(dev, PMSG_HIBERNATE);
+}
+
+#else /* CONFIG_PM_SLEEP */
+
+#define scsi_bus_resume_common         NULL
+#define scsi_bus_suspend               NULL
+#define scsi_bus_freeze                        NULL
+#define scsi_bus_poweroff              NULL
+
+#endif /* CONFIG_PM_SLEEP */
+
+const struct dev_pm_ops scsi_bus_pm_ops = {
+       .suspend =              scsi_bus_suspend,
+       .resume =               scsi_bus_resume_common,
+       .freeze =               scsi_bus_freeze,
+       .thaw =                 scsi_bus_resume_common,
+       .poweroff =             scsi_bus_poweroff,
+       .restore =              scsi_bus_resume_common,
+};
index 1fbf7c78bba0ab80947e9c46207b70bf2f04c75f..dddacc7325502fd24e12bc1de7209d6910adb101 100644 (file)
@@ -144,6 +144,13 @@ static inline void scsi_netlink_init(void) {}
 static inline void scsi_netlink_exit(void) {}
 #endif
 
+/* scsi_pm.c */
+#ifdef CONFIG_PM_OPS
+extern const struct dev_pm_ops scsi_bus_pm_ops;
+#else
+#define scsi_bus_pm_ops                (*NULL)
+#endif
+
 /* 
  * internal scsi timeout functions: for use by mid-layer and transport
  * classes.
index c23ab978c3ba8e15b728a070869db6ec0466c9d2..5f85f8e831f30c710809c197ad67b7409e8bc1b5 100644 (file)
@@ -376,57 +376,11 @@ static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
        return 0;
 }
 
-static int scsi_bus_suspend(struct device * dev, pm_message_t state)
-{
-       struct device_driver *drv;
-       struct scsi_device *sdev;
-       int err;
-
-       if (dev->type != &scsi_dev_type)
-               return 0;
-
-       drv = dev->driver;
-       sdev = to_scsi_device(dev);
-
-       err = scsi_device_quiesce(sdev);
-       if (err)
-               return err;
-
-       if (drv && drv->suspend) {
-               err = drv->suspend(dev, state);
-               if (err)
-                       return err;
-       }
-
-       return 0;
-}
-
-static int scsi_bus_resume(struct device * dev)
-{
-       struct device_driver *drv;
-       struct scsi_device *sdev;
-       int err = 0;
-
-       if (dev->type != &scsi_dev_type)
-               return 0;
-
-       drv = dev->driver;
-       sdev = to_scsi_device(dev);
-
-       if (drv && drv->resume)
-               err = drv->resume(dev);
-
-       scsi_device_resume(sdev);
-
-       return err;
-}
-
 struct bus_type scsi_bus_type = {
         .name          = "scsi",
         .match         = scsi_bus_match,
        .uevent         = scsi_bus_uevent,
-       .suspend        = scsi_bus_suspend,
-       .resume         = scsi_bus_resume,
+       .pm             = &scsi_bus_pm_ops,
 };
 EXPORT_SYMBOL_GPL(scsi_bus_type);