aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-01-23 16:02:51 -0500
committerRafael J. Wysocki <rjw@sisk.pl>2010-02-26 14:39:08 -0500
commit53823639173cc9e9a261f68f4abefe62364b86c6 (patch)
treea4af3a12edea5cf24d23ddece703ec85bacffb42 /drivers/base
parent68c6b859846bd078b37c6ca5f3882032f129e72d (diff)
PM / Runtime: Add sysfs switch for disabling device run-time PM
Add new device sysfs attribute, power/control, allowing the user space to block the run-time power management of the devices. If this attribute is set to "on", the driver of the device won't be able to power manage it at run time (without breaking the rules) and the device will always be in the full power state (except when the entire system goes into a sleep state). Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Alan Stern <stern@rowland.harvard.edu>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/runtime.c45
-rw-r--r--drivers/base/power/sysfs.c51
2 files changed, 96 insertions, 0 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index f8b044e8aef7..626dd147b75f 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1011,6 +1011,50 @@ void pm_runtime_enable(struct device *dev)
1011EXPORT_SYMBOL_GPL(pm_runtime_enable); 1011EXPORT_SYMBOL_GPL(pm_runtime_enable);
1012 1012
1013/** 1013/**
1014 * pm_runtime_forbid - Block run-time PM of a device.
1015 * @dev: Device to handle.
1016 *
1017 * Increase the device's usage count and clear its power.runtime_auto flag,
1018 * so that it cannot be suspended at run time until pm_runtime_allow() is called
1019 * for it.
1020 */
1021void pm_runtime_forbid(struct device *dev)
1022{
1023 spin_lock_irq(&dev->power.lock);
1024 if (!dev->power.runtime_auto)
1025 goto out;
1026
1027 dev->power.runtime_auto = false;
1028 atomic_inc(&dev->power.usage_count);
1029 __pm_runtime_resume(dev, false);
1030
1031 out:
1032 spin_unlock_irq(&dev->power.lock);
1033}
1034EXPORT_SYMBOL_GPL(pm_runtime_forbid);
1035
1036/**
1037 * pm_runtime_allow - Unblock run-time PM of a device.
1038 * @dev: Device to handle.
1039 *
1040 * Decrease the device's usage count and set its power.runtime_auto flag.
1041 */
1042void pm_runtime_allow(struct device *dev)
1043{
1044 spin_lock_irq(&dev->power.lock);
1045 if (dev->power.runtime_auto)
1046 goto out;
1047
1048 dev->power.runtime_auto = true;
1049 if (atomic_dec_and_test(&dev->power.usage_count))
1050 __pm_runtime_idle(dev);
1051
1052 out:
1053 spin_unlock_irq(&dev->power.lock);
1054}
1055EXPORT_SYMBOL_GPL(pm_runtime_allow);
1056
1057/**
1014 * pm_runtime_init - Initialize run-time PM fields in given device object. 1058 * pm_runtime_init - Initialize run-time PM fields in given device object.
1015 * @dev: Device object to initialize. 1059 * @dev: Device object to initialize.
1016 */ 1060 */
@@ -1028,6 +1072,7 @@ void pm_runtime_init(struct device *dev)
1028 1072
1029 atomic_set(&dev->power.child_count, 0); 1073 atomic_set(&dev->power.child_count, 0);
1030 pm_suspend_ignore_children(dev, false); 1074 pm_suspend_ignore_children(dev, false);
1075 dev->power.runtime_auto = true;
1031 1076
1032 dev->power.request_pending = false; 1077 dev->power.request_pending = false;
1033 dev->power.request = RPM_REQ_NONE; 1078 dev->power.request = RPM_REQ_NONE;
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 596aeecfdffe..c011ff15632c 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -4,9 +4,25 @@
4 4
5#include <linux/device.h> 5#include <linux/device.h>
6#include <linux/string.h> 6#include <linux/string.h>
7#include <linux/pm_runtime.h>
7#include "power.h" 8#include "power.h"
8 9
9/* 10/*
11 * control - Report/change current runtime PM setting of the device
12 *
13 * Runtime power management of a device can be blocked with the help of
14 * this attribute. All devices have one of the following two values for
15 * the power/control file:
16 *
17 * + "auto\n" to allow the device to be power managed at run time;
18 * + "on\n" to prevent the device from being power managed at run time;
19 *
20 * The default for all devices is "auto", which means that devices may be
21 * subject to automatic power management, depending on their drivers.
22 * Changing this attribute to "on" prevents the driver from power managing
23 * the device at run time. Doing that while the device is suspended causes
24 * it to be woken up.
25 *
10 * wakeup - Report/change current wakeup option for device 26 * wakeup - Report/change current wakeup option for device
11 * 27 *
12 * Some devices support "wakeup" events, which are hardware signals 28 * Some devices support "wakeup" events, which are hardware signals
@@ -43,6 +59,38 @@
43static const char enabled[] = "enabled"; 59static const char enabled[] = "enabled";
44static const char disabled[] = "disabled"; 60static const char disabled[] = "disabled";
45 61
62#ifdef CONFIG_PM_RUNTIME
63static const char ctrl_auto[] = "auto";
64static const char ctrl_on[] = "on";
65
66static ssize_t control_show(struct device *dev, struct device_attribute *attr,
67 char *buf)
68{
69 return sprintf(buf, "%s\n",
70 dev->power.runtime_auto ? ctrl_auto : ctrl_on);
71}
72
73static ssize_t control_store(struct device * dev, struct device_attribute *attr,
74 const char * buf, size_t n)
75{
76 char *cp;
77 int len = n;
78
79 cp = memchr(buf, '\n', n);
80 if (cp)
81 len = cp - buf;
82 if (len == sizeof ctrl_auto - 1 && strncmp(buf, ctrl_auto, len) == 0)
83 pm_runtime_allow(dev);
84 else if (len == sizeof ctrl_on - 1 && strncmp(buf, ctrl_on, len) == 0)
85 pm_runtime_forbid(dev);
86 else
87 return -EINVAL;
88 return n;
89}
90
91static DEVICE_ATTR(control, 0644, control_show, control_store);
92#endif
93
46static ssize_t 94static ssize_t
47wake_show(struct device * dev, struct device_attribute *attr, char * buf) 95wake_show(struct device * dev, struct device_attribute *attr, char * buf)
48{ 96{
@@ -79,6 +127,9 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
79 127
80 128
81static struct attribute * power_attrs[] = { 129static struct attribute * power_attrs[] = {
130#ifdef CONFIG_PM_RUNTIME
131 &dev_attr_control.attr,
132#endif
82 &dev_attr_wakeup.attr, 133 &dev_attr_wakeup.attr,
83 NULL, 134 NULL,
84}; 135};