Merge branch 'sched/for-linus' into tracing/for-linus
[linux-2.6] / 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 "power.h"
8
9 int (*platform_enable_wakeup)(struct device *dev, int is_on);
10
11
12 /*
13  *      wakeup - Report/change current wakeup option for device
14  *
15  *      Some devices support "wakeup" events, which are hardware signals
16  *      used to activate devices from suspended or low power states.  Such
17  *      devices have one of three values for the sysfs power/wakeup file:
18  *
19  *       + "enabled\n" to issue the events;
20  *       + "disabled\n" not to do so; or
21  *       + "\n" for temporary or permanent inability to issue wakeup.
22  *
23  *      (For example, unconfigured USB devices can't issue wakeups.)
24  *
25  *      Familiar examples of devices that can issue wakeup events include
26  *      keyboards and mice (both PS2 and USB styles), power buttons, modems,
27  *      "Wake-On-LAN" Ethernet links, GPIO lines, and more.  Some events
28  *      will wake the entire system from a suspend state; others may just
29  *      wake up the device (if the system as a whole is already active).
30  *      Some wakeup events use normal IRQ lines; other use special out
31  *      of band signaling.
32  *
33  *      It is the responsibility of device drivers to enable (or disable)
34  *      wakeup signaling as part of changing device power states, respecting
35  *      the policy choices provided through the driver model.
36  *
37  *      Devices may not be able to generate wakeup events from all power
38  *      states.  Also, the events may be ignored in some configurations;
39  *      for example, they might need help from other devices that aren't
40  *      active, or which may have wakeup disabled.  Some drivers rely on
41  *      wakeup events internally (unless they are disabled), keeping
42  *      their hardware in low power modes whenever they're unused.  This
43  *      saves runtime power, without requiring system-wide sleep states.
44  */
45
46 static const char enabled[] = "enabled";
47 static const char disabled[] = "disabled";
48
49 static ssize_t
50 wake_show(struct device * dev, struct device_attribute *attr, char * buf)
51 {
52         return sprintf(buf, "%s\n", device_can_wakeup(dev)
53                 ? (device_may_wakeup(dev) ? enabled : disabled)
54                 : "");
55 }
56
57 static ssize_t
58 wake_store(struct device * dev, struct device_attribute *attr,
59         const char * buf, size_t n)
60 {
61         char *cp;
62         int len = n;
63
64         if (!device_can_wakeup(dev))
65                 return -EINVAL;
66
67         cp = memchr(buf, '\n', n);
68         if (cp)
69                 len = cp - buf;
70         if (len == sizeof enabled - 1
71                         && strncmp(buf, enabled, sizeof enabled - 1) == 0)
72                 device_set_wakeup_enable(dev, 1);
73         else if (len == sizeof disabled - 1
74                         && strncmp(buf, disabled, sizeof disabled - 1) == 0)
75                 device_set_wakeup_enable(dev, 0);
76         else
77                 return -EINVAL;
78         return n;
79 }
80
81 static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
82
83
84 static struct attribute * power_attrs[] = {
85         &dev_attr_wakeup.attr,
86         NULL,
87 };
88 static struct attribute_group pm_attr_group = {
89         .name   = "power",
90         .attrs  = power_attrs,
91 };
92
93 int dpm_sysfs_add(struct device * dev)
94 {
95         return sysfs_create_group(&dev->kobj, &pm_attr_group);
96 }
97
98 void dpm_sysfs_remove(struct device * dev)
99 {
100         sysfs_remove_group(&dev->kobj, &pm_attr_group);
101 }