[S390] pm: ccwgroup bus power management callbacks
authorSebastian Ott <sebott@linux.vnet.ibm.com>
Tue, 16 Jun 2009 08:30:21 +0000 (10:30 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 16 Jun 2009 08:31:08 +0000 (10:31 +0200)
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/ccwgroup.h
drivers/s390/cio/ccwgroup.c

index a27f68985a791d7c5317a8574c0605ef1c54064c..c79c1e787b86fc67903c0823d9637b94a784ac93 100644 (file)
@@ -38,6 +38,11 @@ struct ccwgroup_device {
  * @set_online: function called when device is set online
  * @set_offline: function called when device is set offline
  * @shutdown: function called when device is shut down
+ * @prepare: prepare for pm state transition
+ * @complete: undo work done in @prepare
+ * @freeze: callback for freezing during hibernation snapshotting
+ * @thaw: undo work done in @freeze
+ * @restore: callback for restoring after hibernation
  * @driver: embedded driver structure
  */
 struct ccwgroup_driver {
@@ -51,6 +56,11 @@ struct ccwgroup_driver {
        int (*set_online) (struct ccwgroup_device *);
        int (*set_offline) (struct ccwgroup_device *);
        void (*shutdown)(struct ccwgroup_device *);
+       int (*prepare) (struct ccwgroup_device *);
+       void (*complete) (struct ccwgroup_device *);
+       int (*freeze)(struct ccwgroup_device *);
+       int (*thaw) (struct ccwgroup_device *);
+       int (*restore)(struct ccwgroup_device *);
 
        struct device_driver driver;
 };
index 22ce765d537e9f0bccbca4c769131c07b3c03574..a5a62f1f7747c66107c71ea62be654473765541f 100644 (file)
@@ -1,11 +1,10 @@
 /*
- *  drivers/s390/cio/ccwgroup.c
  *  bus driver for ccwgroup
  *
- *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
- *                       IBM Corporation
- *    Author(s): Arnd Bergmann (arndb@de.ibm.com)
- *               Cornelia Huck (cornelia.huck@de.ibm.com)
+ *  Copyright IBM Corp. 2002, 2009
+ *
+ *  Author(s): Arnd Bergmann (arndb@de.ibm.com)
+ *            Cornelia Huck (cornelia.huck@de.ibm.com)
  */
 #include <linux/module.h>
 #include <linux/errno.h>
@@ -501,6 +500,74 @@ static void ccwgroup_shutdown(struct device *dev)
                gdrv->shutdown(gdev);
 }
 
+static int ccwgroup_pm_prepare(struct device *dev)
+{
+       struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+       struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
+
+       /* Fail while device is being set online/offline. */
+       if (atomic_read(&gdev->onoff))
+               return -EAGAIN;
+
+       if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE)
+               return 0;
+
+       return gdrv->prepare ? gdrv->prepare(gdev) : 0;
+}
+
+static void ccwgroup_pm_complete(struct device *dev)
+{
+       struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+       struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
+
+       if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE)
+               return;
+
+       if (gdrv->complete)
+               gdrv->complete(gdev);
+}
+
+static int ccwgroup_pm_freeze(struct device *dev)
+{
+       struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+       struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
+
+       if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE)
+               return 0;
+
+       return gdrv->freeze ? gdrv->freeze(gdev) : 0;
+}
+
+static int ccwgroup_pm_thaw(struct device *dev)
+{
+       struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+       struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
+
+       if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE)
+               return 0;
+
+       return gdrv->thaw ? gdrv->thaw(gdev) : 0;
+}
+
+static int ccwgroup_pm_restore(struct device *dev)
+{
+       struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+       struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
+
+       if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE)
+               return 0;
+
+       return gdrv->restore ? gdrv->restore(gdev) : 0;
+}
+
+static struct dev_pm_ops ccwgroup_pm_ops = {
+       .prepare = ccwgroup_pm_prepare,
+       .complete = ccwgroup_pm_complete,
+       .freeze = ccwgroup_pm_freeze,
+       .thaw = ccwgroup_pm_thaw,
+       .restore = ccwgroup_pm_restore,
+};
+
 static struct bus_type ccwgroup_bus_type = {
        .name   = "ccwgroup",
        .match  = ccwgroup_bus_match,
@@ -508,6 +575,7 @@ static struct bus_type ccwgroup_bus_type = {
        .probe  = ccwgroup_probe,
        .remove = ccwgroup_remove,
        .shutdown = ccwgroup_shutdown,
+       .pm = &ccwgroup_pm_ops,
 };