aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/power')
-rw-r--r--drivers/base/power/main.c26
-rw-r--r--drivers/base/power/power.h13
-rw-r--r--drivers/base/power/runtime.c1
-rw-r--r--drivers/base/power/sysfs.c73
4 files changed, 77 insertions, 36 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 15e6a8f951f1..0d2e101e4f15 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -30,23 +30,6 @@ LIST_HEAD(dpm_off_irq);
30DECLARE_MUTEX(dpm_sem); 30DECLARE_MUTEX(dpm_sem);
31DECLARE_MUTEX(dpm_list_sem); 31DECLARE_MUTEX(dpm_list_sem);
32 32
33/*
34 * PM Reference Counting.
35 */
36
37static inline void device_pm_hold(struct device * dev)
38{
39 if (dev)
40 atomic_inc(&dev->power.pm_users);
41}
42
43static inline void device_pm_release(struct device * dev)
44{
45 if (dev)
46 atomic_dec(&dev->power.pm_users);
47}
48
49
50/** 33/**
51 * device_pm_set_parent - Specify power dependency. 34 * device_pm_set_parent - Specify power dependency.
52 * @dev: Device who needs power. 35 * @dev: Device who needs power.
@@ -62,10 +45,8 @@ static inline void device_pm_release(struct device * dev)
62 45
63void device_pm_set_parent(struct device * dev, struct device * parent) 46void device_pm_set_parent(struct device * dev, struct device * parent)
64{ 47{
65 struct device * old_parent = dev->power.pm_parent; 48 put_device(dev->power.pm_parent);
66 device_pm_release(old_parent); 49 dev->power.pm_parent = get_device(parent);
67 dev->power.pm_parent = parent;
68 device_pm_hold(parent);
69} 50}
70EXPORT_SYMBOL_GPL(device_pm_set_parent); 51EXPORT_SYMBOL_GPL(device_pm_set_parent);
71 52
@@ -75,7 +56,6 @@ int device_pm_add(struct device * dev)
75 56
76 pr_debug("PM: Adding info for %s:%s\n", 57 pr_debug("PM: Adding info for %s:%s\n",
77 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name); 58 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
78 atomic_set(&dev->power.pm_users, 0);
79 down(&dpm_list_sem); 59 down(&dpm_list_sem);
80 list_add_tail(&dev->power.entry, &dpm_active); 60 list_add_tail(&dev->power.entry, &dpm_active);
81 device_pm_set_parent(dev, dev->parent); 61 device_pm_set_parent(dev, dev->parent);
@@ -91,7 +71,7 @@ void device_pm_remove(struct device * dev)
91 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name); 71 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
92 down(&dpm_list_sem); 72 down(&dpm_list_sem);
93 dpm_sysfs_remove(dev); 73 dpm_sysfs_remove(dev);
94 device_pm_release(dev->power.pm_parent); 74 put_device(dev->power.pm_parent);
95 list_del_init(&dev->power.entry); 75 list_del_init(&dev->power.entry);
96 up(&dpm_list_sem); 76 up(&dpm_list_sem);
97} 77}
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 2e700d795cf1..fb3d35a9e101 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -67,9 +67,6 @@ extern int suspend_device(struct device *, pm_message_t);
67 * runtime.c 67 * runtime.c
68 */ 68 */
69 69
70extern int dpm_runtime_suspend(struct device *, pm_message_t);
71extern void dpm_runtime_resume(struct device *);
72
73#else /* CONFIG_PM */ 70#else /* CONFIG_PM */
74 71
75 72
@@ -82,14 +79,4 @@ static inline void device_pm_remove(struct device * dev)
82 79
83} 80}
84 81
85static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state)
86{
87 return 0;
88}
89
90static inline void dpm_runtime_resume(struct device * dev)
91{
92
93}
94
95#endif 82#endif
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index e8f0519f5dfa..adbc3148c039 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -36,6 +36,7 @@ void dpm_runtime_resume(struct device * dev)
36 runtime_resume(dev); 36 runtime_resume(dev);
37 up(&dpm_sem); 37 up(&dpm_sem);
38} 38}
39EXPORT_SYMBOL(dpm_runtime_resume);
39 40
40 41
41/** 42/**
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 8d04fb435c17..89c57875f3e5 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -48,8 +48,81 @@ static ssize_t state_store(struct device * dev, struct device_attribute *attr, c
48static DEVICE_ATTR(state, 0644, state_show, state_store); 48static DEVICE_ATTR(state, 0644, state_show, state_store);
49 49
50 50
51/*
52 * wakeup - Report/change current wakeup option for device
53 *
54 * Some devices support "wakeup" events, which are hardware signals
55 * used to activate devices from suspended or low power states. Such
56 * devices have one of three values for the sysfs power/wakeup file:
57 *
58 * + "enabled\n" to issue the events;
59 * + "disabled\n" not to do so; or
60 * + "\n" for temporary or permanent inability to issue wakeup.
61 *
62 * (For example, unconfigured USB devices can't issue wakeups.)
63 *
64 * Familiar examples of devices that can issue wakeup events include
65 * keyboards and mice (both PS2 and USB styles), power buttons, modems,
66 * "Wake-On-LAN" Ethernet links, GPIO lines, and more. Some events
67 * will wake the entire system from a suspend state; others may just
68 * wake up the device (if the system as a whole is already active).
69 * Some wakeup events use normal IRQ lines; other use special out
70 * of band signaling.
71 *
72 * It is the responsibility of device drivers to enable (or disable)
73 * wakeup signaling as part of changing device power states, respecting
74 * the policy choices provided through the driver model.
75 *
76 * Devices may not be able to generate wakeup events from all power
77 * states. Also, the events may be ignored in some configurations;
78 * for example, they might need help from other devices that aren't
79 * active, or which may have wakeup disabled. Some drivers rely on
80 * wakeup events internally (unless they are disabled), keeping
81 * their hardware in low power modes whenever they're unused. This
82 * saves runtime power, without requiring system-wide sleep states.
83 */
84
85static const char enabled[] = "enabled";
86static const char disabled[] = "disabled";
87
88static ssize_t
89wake_show(struct device * dev, struct device_attribute *attr, char * buf)
90{
91 return sprintf(buf, "%s\n", device_can_wakeup(dev)
92 ? (device_may_wakeup(dev) ? enabled : disabled)
93 : "");
94}
95
96static ssize_t
97wake_store(struct device * dev, struct device_attribute *attr,
98 const char * buf, size_t n)
99{
100 char *cp;
101 int len = n;
102
103 if (!device_can_wakeup(dev))
104 return -EINVAL;
105
106 cp = memchr(buf, '\n', n);
107 if (cp)
108 len = cp - buf;
109 if (len == sizeof enabled - 1
110 && strncmp(buf, enabled, sizeof enabled - 1) == 0)
111 device_set_wakeup_enable(dev, 1);
112 else if (len == sizeof disabled - 1
113 && strncmp(buf, disabled, sizeof disabled - 1) == 0)
114 device_set_wakeup_enable(dev, 0);
115 else
116 return -EINVAL;
117 return n;
118}
119
120static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
121
122
51static struct attribute * power_attrs[] = { 123static struct attribute * power_attrs[] = {
52 &dev_attr_state.attr, 124 &dev_attr_state.attr,
125 &dev_attr_wakeup.attr,
53 NULL, 126 NULL,
54}; 127};
55static struct attribute_group pm_attr_group = { 128static struct attribute_group pm_attr_group = {