]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/base/power/sysfs.c
PM: Add facility for advanced testing of async suspend/resume
[net-next-2.6.git] / drivers / base / power / sysfs.c
index c011ff15632c8fe5eeb41d26be83ebd52809a5d9..86fd9373447e4761fe6b0a8f8c81110b99febc54 100644 (file)
  *     wakeup events internally (unless they are disabled), keeping
  *     their hardware in low power modes whenever they're unused.  This
  *     saves runtime power, without requiring system-wide sleep states.
+ *
+ *     async - Report/change current async suspend setting for the device
+ *
+ *     Asynchronous suspend and resume of the device during system-wide power
+ *     state transitions can be enabled by writing "enabled" to this file.
+ *     Analogously, if "disabled" is written to this file, the device will be
+ *     suspended and resumed synchronously.
+ *
+ *     All devices have one of the following two values for power/async:
+ *
+ *      + "enabled\n" to permit the asynchronous suspend/resume of the device;
+ *      + "disabled\n" to forbid it;
+ *
+ *     NOTE: It generally is unsafe to permit the asynchronous suspend/resume
+ *     of a device unless it is certain that all of the PM dependencies of the
+ *     device are known to the PM core.  However, for some devices this
+ *     attribute is set to "enabled" by bus type code or device drivers and in
+ *     that cases it should be safe to leave the default value.
  */
 
 static const char enabled[] = "enabled";
@@ -125,12 +143,43 @@ wake_store(struct device * dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
 
+#ifdef CONFIG_PM_SLEEP_ADVANCED_DEBUG
+static ssize_t async_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       return sprintf(buf, "%s\n",
+                       device_async_suspend_enabled(dev) ? enabled : disabled);
+}
+
+static ssize_t async_store(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t n)
+{
+       char *cp;
+       int len = n;
+
+       cp = memchr(buf, '\n', n);
+       if (cp)
+               len = cp - buf;
+       if (len == sizeof enabled - 1 && strncmp(buf, enabled, len) == 0)
+               device_enable_async_suspend(dev);
+       else if (len == sizeof disabled - 1 && strncmp(buf, disabled, len) == 0)
+               device_disable_async_suspend(dev);
+       else
+               return -EINVAL;
+       return n;
+}
+
+static DEVICE_ATTR(async, 0644, async_show, async_store);
+#endif /* CONFIG_PM_SLEEP_ADVANCED_DEBUG */
 
 static struct attribute * power_attrs[] = {
 #ifdef CONFIG_PM_RUNTIME
        &dev_attr_control.attr,
 #endif
        &dev_attr_wakeup.attr,
+#ifdef CONFIG_PM_SLEEP_ADVANCED_DEBUG
+       &dev_attr_async.attr,
+#endif
        NULL,
 };
 static struct attribute_group pm_attr_group = {