]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/base/power/sysfs.c
PM / Runtime: Add sysfs switch for disabling device run-time PM
[net-next-2.6.git] / drivers / base / power / sysfs.c
1 /*
2  * drivers/base/power/sysfs.c - sysfs entries for device PM
3  */
4
5 #include <linux/device.h>
6 #include <linux/string.h>
7 #include <linux/pm_runtime.h>
8 #include "power.h"
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  *
26  *      wakeup - Report/change current wakeup option for device
27  *
28  *      Some devices support "wakeup" events, which are hardware signals
29  *      used to activate devices from suspended or low power states.  Such
30  *      devices have one of three values for the sysfs power/wakeup file:
31  *
32  *       + "enabled\n" to issue the events;
33  *       + "disabled\n" not to do so; or
34  *       + "\n" for temporary or permanent inability to issue wakeup.
35  *
36  *      (For example, unconfigured USB devices can't issue wakeups.)
37  *
38  *      Familiar examples of devices that can issue wakeup events include
39  *      keyboards and mice (both PS2 and USB styles), power buttons, modems,
40  *      "Wake-On-LAN" Ethernet links, GPIO lines, and more.  Some events
41  *      will wake the entire system from a suspend state; others may just
42  *      wake up the device (if the system as a whole is already active).
43  *      Some wakeup events use normal IRQ lines; other use special out
44  *      of band signaling.
45  *
46  *      It is the responsibility of device drivers to enable (or disable)
47  *      wakeup signaling as part of changing device power states, respecting
48  *      the policy choices provided through the driver model.
49  *
50  *      Devices may not be able to generate wakeup events from all power
51  *      states.  Also, the events may be ignored in some configurations;
52  *      for example, they might need help from other devices that aren't
53  *      active, or which may have wakeup disabled.  Some drivers rely on
54  *      wakeup events internally (unless they are disabled), keeping
55  *      their hardware in low power modes whenever they're unused.  This
56  *      saves runtime power, without requiring system-wide sleep states.
57  */
58
59 static const char enabled[] = "enabled";
60 static const char disabled[] = "disabled";
61
62 #ifdef CONFIG_PM_RUNTIME
63 static const char ctrl_auto[] = "auto";
64 static const char ctrl_on[] = "on";
65
66 static 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
73 static 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
91 static DEVICE_ATTR(control, 0644, control_show, control_store);
92 #endif
93
94 static ssize_t
95 wake_show(struct device * dev, struct device_attribute *attr, char * buf)
96 {
97         return sprintf(buf, "%s\n", device_can_wakeup(dev)
98                 ? (device_may_wakeup(dev) ? enabled : disabled)
99                 : "");
100 }
101
102 static ssize_t
103 wake_store(struct device * dev, struct device_attribute *attr,
104         const char * buf, size_t n)
105 {
106         char *cp;
107         int len = n;
108
109         if (!device_can_wakeup(dev))
110                 return -EINVAL;
111
112         cp = memchr(buf, '\n', n);
113         if (cp)
114                 len = cp - buf;
115         if (len == sizeof enabled - 1
116                         && strncmp(buf, enabled, sizeof enabled - 1) == 0)
117                 device_set_wakeup_enable(dev, 1);
118         else if (len == sizeof disabled - 1
119                         && strncmp(buf, disabled, sizeof disabled - 1) == 0)
120                 device_set_wakeup_enable(dev, 0);
121         else
122                 return -EINVAL;
123         return n;
124 }
125
126 static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
127
128
129 static struct attribute * power_attrs[] = {
130 #ifdef CONFIG_PM_RUNTIME
131         &dev_attr_control.attr,
132 #endif
133         &dev_attr_wakeup.attr,
134         NULL,
135 };
136 static struct attribute_group pm_attr_group = {
137         .name   = "power",
138         .attrs  = power_attrs,
139 };
140
141 int dpm_sysfs_add(struct device * dev)
142 {
143         return sysfs_create_group(&dev->kobj, &pm_attr_group);
144 }
145
146 void dpm_sysfs_remove(struct device * dev)
147 {
148         sysfs_remove_group(&dev->kobj, &pm_attr_group);
149 }