aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-09-22 16:09:10 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2010-10-16 19:57:43 -0400
commit074037ec79bea73edf1b1ec72fef1010e83e3cc5 (patch)
tree1876caa07f755e680da5ea102d985efe4b508d56
parent0702d9ee0f1dcb6258789032f03b3208bfafaffc (diff)
PM / Wakeup: Introduce wakeup source objects and event statistics (v3)
Introduce struct wakeup_source for representing system wakeup sources within the kernel and for collecting statistics related to them. Make the recently introduced helper functions pm_wakeup_event(), pm_stay_awake() and pm_relax() use struct wakeup_source objects internally, so that wakeup statistics associated with wakeup devices can be collected and reported in a consistent way (the definition of pm_relax() is changed, which is harmless, because this function is not called directly by anyone yet). Introduce new wakeup-related sysfs device attributes in /sys/devices/.../power for reporting the device wakeup statistics. Change the global wakeup events counters event_count and events_in_progress into atomic variables, so that it is not necessary to acquire a global spinlock in pm_wakeup_event(), pm_stay_awake() and pm_relax(), which should allow us to avoid lock contention in these functions on SMP systems with many wakeup devices. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--Documentation/ABI/testing/sysfs-devices-power70
-rw-r--r--drivers/base/power/main.c4
-rw-r--r--drivers/base/power/power.h1
-rw-r--r--drivers/base/power/runtime.c2
-rw-r--r--drivers/base/power/sysfs.c121
-rw-r--r--drivers/base/power/wakeup.c528
-rw-r--r--include/linux/pm.h16
-rw-r--r--include/linux/pm_wakeup.h127
-rw-r--r--include/linux/suspend.h4
-rw-r--r--kernel/power/main.c8
10 files changed, 756 insertions, 125 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index 6123c523bfd7..6bb2dd3c3a71 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -77,3 +77,73 @@ Description:
77 devices this attribute is set to "enabled" by bus type code or 77 devices this attribute is set to "enabled" by bus type code or
78 device drivers and in that cases it should be safe to leave the 78 device drivers and in that cases it should be safe to leave the
79 default value. 79 default value.
80
81What: /sys/devices/.../power/wakeup_count
82Date: September 2010
83Contact: Rafael J. Wysocki <rjw@sisk.pl>
84Description:
85 The /sys/devices/.../wakeup_count attribute contains the number
86 of signaled wakeup events associated with the device. This
87 attribute is read-only. If the device is not enabled to wake up
88 the system from sleep states, this attribute is empty.
89
90What: /sys/devices/.../power/wakeup_active_count
91Date: September 2010
92Contact: Rafael J. Wysocki <rjw@sisk.pl>
93Description:
94 The /sys/devices/.../wakeup_active_count attribute contains the
95 number of times the processing of wakeup events associated with
96 the device was completed (at the kernel level). This attribute
97 is read-only. If the device is not enabled to wake up the
98 system from sleep states, this attribute is empty.
99
100What: /sys/devices/.../power/wakeup_hit_count
101Date: September 2010
102Contact: Rafael J. Wysocki <rjw@sisk.pl>
103Description:
104 The /sys/devices/.../wakeup_hit_count attribute contains the
105 number of times the processing of a wakeup event associated with
106 the device might prevent the system from entering a sleep state.
107 This attribute is read-only. If the device is not enabled to
108 wake up the system from sleep states, this attribute is empty.
109
110What: /sys/devices/.../power/wakeup_active
111Date: September 2010
112Contact: Rafael J. Wysocki <rjw@sisk.pl>
113Description:
114 The /sys/devices/.../wakeup_active attribute contains either 1,
115 or 0, depending on whether or not a wakeup event associated with
116 the device is being processed (1). This attribute is read-only.
117 If the device is not enabled to wake up the system from sleep
118 states, this attribute is empty.
119
120What: /sys/devices/.../power/wakeup_total_time_ms
121Date: September 2010
122Contact: Rafael J. Wysocki <rjw@sisk.pl>
123Description:
124 The /sys/devices/.../wakeup_total_time_ms attribute contains
125 the total time of processing wakeup events associated with the
126 device, in milliseconds. This attribute is read-only. If the
127 device is not enabled to wake up the system from sleep states,
128 this attribute is empty.
129
130What: /sys/devices/.../power/wakeup_max_time_ms
131Date: September 2010
132Contact: Rafael J. Wysocki <rjw@sisk.pl>
133Description:
134 The /sys/devices/.../wakeup_max_time_ms attribute contains
135 the maximum time of processing a single wakeup event associated
136 with the device, in milliseconds. This attribute is read-only.
137 If the device is not enabled to wake up the system from sleep
138 states, this attribute is empty.
139
140What: /sys/devices/.../power/wakeup_last_time_ms
141Date: September 2010
142Contact: Rafael J. Wysocki <rjw@sisk.pl>
143Description:
144 The /sys/devices/.../wakeup_last_time_ms attribute contains
145 the value of the monotonic clock corresponding to the time of
146 signaling the last wakeup event associated with the device, in
147 milliseconds. This attribute is read-only. If the device is
148 not enabled to wake up the system from sleep states, this
149 attribute is empty.
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index db677199403c..7ae6fe414c38 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -60,7 +60,8 @@ void device_pm_init(struct device *dev)
60 dev->power.status = DPM_ON; 60 dev->power.status = DPM_ON;
61 init_completion(&dev->power.completion); 61 init_completion(&dev->power.completion);
62 complete_all(&dev->power.completion); 62 complete_all(&dev->power.completion);
63 dev->power.wakeup_count = 0; 63 dev->power.wakeup = NULL;
64 spin_lock_init(&dev->power.lock);
64 pm_runtime_init(dev); 65 pm_runtime_init(dev);
65} 66}
66 67
@@ -120,6 +121,7 @@ void device_pm_remove(struct device *dev)
120 mutex_lock(&dpm_list_mtx); 121 mutex_lock(&dpm_list_mtx);
121 list_del_init(&dev->power.entry); 122 list_del_init(&dev->power.entry);
122 mutex_unlock(&dpm_list_mtx); 123 mutex_unlock(&dpm_list_mtx);
124 device_wakeup_disable(dev);
123 pm_runtime_remove(dev); 125 pm_runtime_remove(dev);
124} 126}
125 127
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index c0bd03c83b9c..8b2745c69e2a 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -34,6 +34,7 @@ extern void device_pm_move_last(struct device *);
34 34
35static inline void device_pm_init(struct device *dev) 35static inline void device_pm_init(struct device *dev)
36{ 36{
37 spin_lock_init(&dev->power.lock);
37 pm_runtime_init(dev); 38 pm_runtime_init(dev);
38} 39}
39 40
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index b78c401ffa73..e9520ad2d716 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1099,8 +1099,6 @@ EXPORT_SYMBOL_GPL(pm_runtime_allow);
1099 */ 1099 */
1100void pm_runtime_init(struct device *dev) 1100void pm_runtime_init(struct device *dev)
1101{ 1101{
1102 spin_lock_init(&dev->power.lock);
1103
1104 dev->power.runtime_status = RPM_SUSPENDED; 1102 dev->power.runtime_status = RPM_SUSPENDED;
1105 dev->power.idle_notification = false; 1103 dev->power.idle_notification = false;
1106 1104
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index e56b4388fe61..8859780817e1 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -210,11 +210,122 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
210static ssize_t wakeup_count_show(struct device *dev, 210static ssize_t wakeup_count_show(struct device *dev,
211 struct device_attribute *attr, char *buf) 211 struct device_attribute *attr, char *buf)
212{ 212{
213 return sprintf(buf, "%lu\n", dev->power.wakeup_count); 213 unsigned long count = 0;
214 bool enabled = false;
215
216 spin_lock_irq(&dev->power.lock);
217 if (dev->power.wakeup) {
218 count = dev->power.wakeup->event_count;
219 enabled = true;
220 }
221 spin_unlock_irq(&dev->power.lock);
222 return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
214} 223}
215 224
216static DEVICE_ATTR(wakeup_count, 0444, wakeup_count_show, NULL); 225static DEVICE_ATTR(wakeup_count, 0444, wakeup_count_show, NULL);
217#endif 226
227static ssize_t wakeup_active_count_show(struct device *dev,
228 struct device_attribute *attr, char *buf)
229{
230 unsigned long count = 0;
231 bool enabled = false;
232
233 spin_lock_irq(&dev->power.lock);
234 if (dev->power.wakeup) {
235 count = dev->power.wakeup->active_count;
236 enabled = true;
237 }
238 spin_unlock_irq(&dev->power.lock);
239 return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
240}
241
242static DEVICE_ATTR(wakeup_active_count, 0444, wakeup_active_count_show, NULL);
243
244static ssize_t wakeup_hit_count_show(struct device *dev,
245 struct device_attribute *attr, char *buf)
246{
247 unsigned long count = 0;
248 bool enabled = false;
249
250 spin_lock_irq(&dev->power.lock);
251 if (dev->power.wakeup) {
252 count = dev->power.wakeup->hit_count;
253 enabled = true;
254 }
255 spin_unlock_irq(&dev->power.lock);
256 return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
257}
258
259static DEVICE_ATTR(wakeup_hit_count, 0444, wakeup_hit_count_show, NULL);
260
261static ssize_t wakeup_active_show(struct device *dev,
262 struct device_attribute *attr, char *buf)
263{
264 unsigned int active = 0;
265 bool enabled = false;
266
267 spin_lock_irq(&dev->power.lock);
268 if (dev->power.wakeup) {
269 active = dev->power.wakeup->active;
270 enabled = true;
271 }
272 spin_unlock_irq(&dev->power.lock);
273 return enabled ? sprintf(buf, "%u\n", active) : sprintf(buf, "\n");
274}
275
276static DEVICE_ATTR(wakeup_active, 0444, wakeup_active_show, NULL);
277
278static ssize_t wakeup_total_time_show(struct device *dev,
279 struct device_attribute *attr, char *buf)
280{
281 s64 msec = 0;
282 bool enabled = false;
283
284 spin_lock_irq(&dev->power.lock);
285 if (dev->power.wakeup) {
286 msec = ktime_to_ms(dev->power.wakeup->total_time);
287 enabled = true;
288 }
289 spin_unlock_irq(&dev->power.lock);
290 return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
291}
292
293static DEVICE_ATTR(wakeup_total_time_ms, 0444, wakeup_total_time_show, NULL);
294
295static ssize_t wakeup_max_time_show(struct device *dev,
296 struct device_attribute *attr, char *buf)
297{
298 s64 msec = 0;
299 bool enabled = false;
300
301 spin_lock_irq(&dev->power.lock);
302 if (dev->power.wakeup) {
303 msec = ktime_to_ms(dev->power.wakeup->max_time);
304 enabled = true;
305 }
306 spin_unlock_irq(&dev->power.lock);
307 return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
308}
309
310static DEVICE_ATTR(wakeup_max_time_ms, 0444, wakeup_max_time_show, NULL);
311
312static ssize_t wakeup_last_time_show(struct device *dev,
313 struct device_attribute *attr, char *buf)
314{
315 s64 msec = 0;
316 bool enabled = false;
317
318 spin_lock_irq(&dev->power.lock);
319 if (dev->power.wakeup) {
320 msec = ktime_to_ms(dev->power.wakeup->last_time);
321 enabled = true;
322 }
323 spin_unlock_irq(&dev->power.lock);
324 return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
325}
326
327static DEVICE_ATTR(wakeup_last_time_ms, 0444, wakeup_last_time_show, NULL);
328#endif /* CONFIG_PM_SLEEP */
218 329
219#ifdef CONFIG_PM_ADVANCED_DEBUG 330#ifdef CONFIG_PM_ADVANCED_DEBUG
220#ifdef CONFIG_PM_RUNTIME 331#ifdef CONFIG_PM_RUNTIME
@@ -288,6 +399,12 @@ static struct attribute * power_attrs[] = {
288 &dev_attr_wakeup.attr, 399 &dev_attr_wakeup.attr,
289#ifdef CONFIG_PM_SLEEP 400#ifdef CONFIG_PM_SLEEP
290 &dev_attr_wakeup_count.attr, 401 &dev_attr_wakeup_count.attr,
402 &dev_attr_wakeup_active_count.attr,
403 &dev_attr_wakeup_hit_count.attr,
404 &dev_attr_wakeup_active.attr,
405 &dev_attr_wakeup_total_time_ms.attr,
406 &dev_attr_wakeup_max_time_ms.attr,
407 &dev_attr_wakeup_last_time_ms.attr,
291#endif 408#endif
292#ifdef CONFIG_PM_ADVANCED_DEBUG 409#ifdef CONFIG_PM_ADVANCED_DEBUG
293 &dev_attr_async.attr, 410 &dev_attr_async.attr,
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index eb594facfc3f..03751a01dbad 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -11,7 +11,10 @@
11#include <linux/sched.h> 11#include <linux/sched.h>
12#include <linux/capability.h> 12#include <linux/capability.h>
13#include <linux/suspend.h> 13#include <linux/suspend.h>
14#include <linux/pm.h> 14
15#include "power.h"
16
17#define TIMEOUT 100
15 18
16/* 19/*
17 * If set, the suspend/hibernate code will abort transitions to a sleep state 20 * If set, the suspend/hibernate code will abort transitions to a sleep state
@@ -20,18 +23,244 @@
20bool events_check_enabled; 23bool events_check_enabled;
21 24
22/* The counter of registered wakeup events. */ 25/* The counter of registered wakeup events. */
23static unsigned long event_count; 26static atomic_t event_count = ATOMIC_INIT(0);
24/* A preserved old value of event_count. */ 27/* A preserved old value of event_count. */
25static unsigned long saved_event_count; 28static unsigned int saved_count;
26/* The counter of wakeup events being processed. */ 29/* The counter of wakeup events being processed. */
27static unsigned long events_in_progress; 30static atomic_t events_in_progress = ATOMIC_INIT(0);
28 31
29static DEFINE_SPINLOCK(events_lock); 32static DEFINE_SPINLOCK(events_lock);
30 33
31static void pm_wakeup_timer_fn(unsigned long data); 34static void pm_wakeup_timer_fn(unsigned long data);
32 35
33static DEFINE_TIMER(events_timer, pm_wakeup_timer_fn, 0, 0); 36static LIST_HEAD(wakeup_sources);
34static unsigned long events_timer_expires; 37
38/**
39 * wakeup_source_create - Create a struct wakeup_source object.
40 * @name: Name of the new wakeup source.
41 */
42struct wakeup_source *wakeup_source_create(const char *name)
43{
44 struct wakeup_source *ws;
45
46 ws = kzalloc(sizeof(*ws), GFP_KERNEL);
47 if (!ws)
48 return NULL;
49
50 spin_lock_init(&ws->lock);
51 if (name)
52 ws->name = kstrdup(name, GFP_KERNEL);
53
54 return ws;
55}
56EXPORT_SYMBOL_GPL(wakeup_source_create);
57
58/**
59 * wakeup_source_destroy - Destroy a struct wakeup_source object.
60 * @ws: Wakeup source to destroy.
61 */
62void wakeup_source_destroy(struct wakeup_source *ws)
63{
64 if (!ws)
65 return;
66
67 spin_lock_irq(&ws->lock);
68 while (ws->active) {
69 spin_unlock_irq(&ws->lock);
70
71 schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
72
73 spin_lock_irq(&ws->lock);
74 }
75 spin_unlock_irq(&ws->lock);
76
77 kfree(ws->name);
78 kfree(ws);
79}
80EXPORT_SYMBOL_GPL(wakeup_source_destroy);
81
82/**
83 * wakeup_source_add - Add given object to the list of wakeup sources.
84 * @ws: Wakeup source object to add to the list.
85 */
86void wakeup_source_add(struct wakeup_source *ws)
87{
88 if (WARN_ON(!ws))
89 return;
90
91 setup_timer(&ws->timer, pm_wakeup_timer_fn, (unsigned long)ws);
92 ws->active = false;
93
94 spin_lock_irq(&events_lock);
95 list_add_rcu(&ws->entry, &wakeup_sources);
96 spin_unlock_irq(&events_lock);
97 synchronize_rcu();
98}
99EXPORT_SYMBOL_GPL(wakeup_source_add);
100
101/**
102 * wakeup_source_remove - Remove given object from the wakeup sources list.
103 * @ws: Wakeup source object to remove from the list.
104 */
105void wakeup_source_remove(struct wakeup_source *ws)
106{
107 if (WARN_ON(!ws))
108 return;
109
110 spin_lock_irq(&events_lock);
111 list_del_rcu(&ws->entry);
112 spin_unlock_irq(&events_lock);
113 synchronize_rcu();
114}
115EXPORT_SYMBOL_GPL(wakeup_source_remove);
116
117/**
118 * wakeup_source_register - Create wakeup source and add it to the list.
119 * @name: Name of the wakeup source to register.
120 */
121struct wakeup_source *wakeup_source_register(const char *name)
122{
123 struct wakeup_source *ws;
124
125 ws = wakeup_source_create(name);
126 if (ws)
127 wakeup_source_add(ws);
128
129 return ws;
130}
131EXPORT_SYMBOL_GPL(wakeup_source_register);
132
133/**
134 * wakeup_source_unregister - Remove wakeup source from the list and remove it.
135 * @ws: Wakeup source object to unregister.
136 */
137void wakeup_source_unregister(struct wakeup_source *ws)
138{
139 wakeup_source_remove(ws);
140 wakeup_source_destroy(ws);
141}
142EXPORT_SYMBOL_GPL(wakeup_source_unregister);
143
144/**
145 * device_wakeup_attach - Attach a wakeup source object to a device object.
146 * @dev: Device to handle.
147 * @ws: Wakeup source object to attach to @dev.
148 *
149 * This causes @dev to be treated as a wakeup device.
150 */
151static int device_wakeup_attach(struct device *dev, struct wakeup_source *ws)
152{
153 spin_lock_irq(&dev->power.lock);
154 if (dev->power.wakeup) {
155 spin_unlock_irq(&dev->power.lock);
156 return -EEXIST;
157 }
158 dev->power.wakeup = ws;
159 spin_unlock_irq(&dev->power.lock);
160 return 0;
161}
162
163/**
164 * device_wakeup_enable - Enable given device to be a wakeup source.
165 * @dev: Device to handle.
166 *
167 * Create a wakeup source object, register it and attach it to @dev.
168 */
169int device_wakeup_enable(struct device *dev)
170{
171 struct wakeup_source *ws;
172 int ret;
173
174 if (!dev || !dev->power.can_wakeup)
175 return -EINVAL;
176
177 ws = wakeup_source_register(dev_name(dev));
178 if (!ws)
179 return -ENOMEM;
180
181 ret = device_wakeup_attach(dev, ws);
182 if (ret)
183 wakeup_source_unregister(ws);
184
185 return ret;
186}
187EXPORT_SYMBOL_GPL(device_wakeup_enable);
188
189/**
190 * device_wakeup_detach - Detach a device's wakeup source object from it.
191 * @dev: Device to detach the wakeup source object from.
192 *
193 * After it returns, @dev will not be treated as a wakeup device any more.
194 */
195static struct wakeup_source *device_wakeup_detach(struct device *dev)
196{
197 struct wakeup_source *ws;
198
199 spin_lock_irq(&dev->power.lock);
200 ws = dev->power.wakeup;
201 dev->power.wakeup = NULL;
202 spin_unlock_irq(&dev->power.lock);
203 return ws;
204}
205
206/**
207 * device_wakeup_disable - Do not regard a device as a wakeup source any more.
208 * @dev: Device to handle.
209 *
210 * Detach the @dev's wakeup source object from it, unregister this wakeup source
211 * object and destroy it.
212 */
213int device_wakeup_disable(struct device *dev)
214{
215 struct wakeup_source *ws;
216
217 if (!dev || !dev->power.can_wakeup)
218 return -EINVAL;
219
220 ws = device_wakeup_detach(dev);
221 if (ws)
222 wakeup_source_unregister(ws);
223
224 return 0;
225}
226EXPORT_SYMBOL_GPL(device_wakeup_disable);
227
228/**
229 * device_init_wakeup - Device wakeup initialization.
230 * @dev: Device to handle.
231 * @enable: Whether or not to enable @dev as a wakeup device.
232 *
233 * By default, most devices should leave wakeup disabled. The exceptions are
234 * devices that everyone expects to be wakeup sources: keyboards, power buttons,
235 * possibly network interfaces, etc.
236 */
237int device_init_wakeup(struct device *dev, bool enable)
238{
239 int ret = 0;
240
241 if (enable) {
242 device_set_wakeup_capable(dev, true);
243 ret = device_wakeup_enable(dev);
244 } else {
245 device_set_wakeup_capable(dev, false);
246 }
247
248 return ret;
249}
250EXPORT_SYMBOL_GPL(device_init_wakeup);
251
252/**
253 * device_set_wakeup_enable - Enable or disable a device to wake up the system.
254 * @dev: Device to handle.
255 */
256int device_set_wakeup_enable(struct device *dev, bool enable)
257{
258 if (!dev || !dev->power.can_wakeup)
259 return -EINVAL;
260
261 return enable ? device_wakeup_enable(dev) : device_wakeup_disable(dev);
262}
263EXPORT_SYMBOL_GPL(device_set_wakeup_enable);
35 264
36/* 265/*
37 * The functions below use the observation that each wakeup event starts a 266 * The functions below use the observation that each wakeup event starts a
@@ -55,118 +284,259 @@ static unsigned long events_timer_expires;
55 * knowledge, however, may not be available to it, so it can simply specify time 284 * knowledge, however, may not be available to it, so it can simply specify time
56 * to wait before the system can be suspended and pass it as the second 285 * to wait before the system can be suspended and pass it as the second
57 * argument of pm_wakeup_event(). 286 * argument of pm_wakeup_event().
287 *
288 * It is valid to call pm_relax() after pm_wakeup_event(), in which case the
289 * "no suspend" period will be ended either by the pm_relax(), or by the timer
290 * function executed when the timer expires, whichever comes first.
58 */ 291 */
59 292
60/** 293/**
294 * wakup_source_activate - Mark given wakeup source as active.
295 * @ws: Wakeup source to handle.
296 *
297 * Update the @ws' statistics and, if @ws has just been activated, notify the PM
298 * core of the event by incrementing the counter of of wakeup events being
299 * processed.
300 */
301static void wakeup_source_activate(struct wakeup_source *ws)
302{
303 ws->active = true;
304 ws->active_count++;
305 ws->timer_expires = jiffies;
306 ws->last_time = ktime_get();
307
308 atomic_inc(&events_in_progress);
309}
310
311/**
312 * __pm_stay_awake - Notify the PM core of a wakeup event.
313 * @ws: Wakeup source object associated with the source of the event.
314 *
315 * It is safe to call this function from interrupt context.
316 */
317void __pm_stay_awake(struct wakeup_source *ws)
318{
319 unsigned long flags;
320
321 if (!ws)
322 return;
323
324 spin_lock_irqsave(&ws->lock, flags);
325 ws->event_count++;
326 if (!ws->active)
327 wakeup_source_activate(ws);
328 spin_unlock_irqrestore(&ws->lock, flags);
329}
330EXPORT_SYMBOL_GPL(__pm_stay_awake);
331
332/**
61 * pm_stay_awake - Notify the PM core that a wakeup event is being processed. 333 * pm_stay_awake - Notify the PM core that a wakeup event is being processed.
62 * @dev: Device the wakeup event is related to. 334 * @dev: Device the wakeup event is related to.
63 * 335 *
64 * Notify the PM core of a wakeup event (signaled by @dev) by incrementing the 336 * Notify the PM core of a wakeup event (signaled by @dev) by calling
65 * counter of wakeup events being processed. If @dev is not NULL, the counter 337 * __pm_stay_awake for the @dev's wakeup source object.
66 * of wakeup events related to @dev is incremented too.
67 * 338 *
68 * Call this function after detecting of a wakeup event if pm_relax() is going 339 * Call this function after detecting of a wakeup event if pm_relax() is going
69 * to be called directly after processing the event (and possibly passing it to 340 * to be called directly after processing the event (and possibly passing it to
70 * user space for further processing). 341 * user space for further processing).
71 *
72 * It is safe to call this function from interrupt context.
73 */ 342 */
74void pm_stay_awake(struct device *dev) 343void pm_stay_awake(struct device *dev)
75{ 344{
76 unsigned long flags; 345 unsigned long flags;
77 346
78 spin_lock_irqsave(&events_lock, flags); 347 if (!dev)
79 if (dev) 348 return;
80 dev->power.wakeup_count++;
81 349
82 events_in_progress++; 350 spin_lock_irqsave(&dev->power.lock, flags);
83 spin_unlock_irqrestore(&events_lock, flags); 351 __pm_stay_awake(dev->power.wakeup);
352 spin_unlock_irqrestore(&dev->power.lock, flags);
84} 353}
354EXPORT_SYMBOL_GPL(pm_stay_awake);
85 355
86/** 356/**
87 * pm_relax - Notify the PM core that processing of a wakeup event has ended. 357 * wakup_source_deactivate - Mark given wakeup source as inactive.
358 * @ws: Wakeup source to handle.
88 * 359 *
89 * Notify the PM core that a wakeup event has been processed by decrementing 360 * Update the @ws' statistics and notify the PM core that the wakeup source has
90 * the counter of wakeup events being processed and incrementing the counter 361 * become inactive by decrementing the counter of wakeup events being processed
91 * of registered wakeup events. 362 * and incrementing the counter of registered wakeup events.
363 */
364static void wakeup_source_deactivate(struct wakeup_source *ws)
365{
366 ktime_t duration;
367 ktime_t now;
368
369 ws->relax_count++;
370 /*
371 * __pm_relax() may be called directly or from a timer function.
372 * If it is called directly right after the timer function has been
373 * started, but before the timer function calls __pm_relax(), it is
374 * possible that __pm_stay_awake() will be called in the meantime and
375 * will set ws->active. Then, ws->active may be cleared immediately
376 * by the __pm_relax() called from the timer function, but in such a
377 * case ws->relax_count will be different from ws->active_count.
378 */
379 if (ws->relax_count != ws->active_count) {
380 ws->relax_count--;
381 return;
382 }
383
384 ws->active = false;
385
386 now = ktime_get();
387 duration = ktime_sub(now, ws->last_time);
388 ws->total_time = ktime_add(ws->total_time, duration);
389 if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time))
390 ws->max_time = duration;
391
392 del_timer(&ws->timer);
393
394 /*
395 * event_count has to be incremented before events_in_progress is
396 * modified, so that the callers of pm_check_wakeup_events() and
397 * pm_save_wakeup_count() don't see the old value of event_count and
398 * events_in_progress equal to zero at the same time.
399 */
400 atomic_inc(&event_count);
401 smp_mb__before_atomic_dec();
402 atomic_dec(&events_in_progress);
403}
404
405/**
406 * __pm_relax - Notify the PM core that processing of a wakeup event has ended.
407 * @ws: Wakeup source object associated with the source of the event.
92 * 408 *
93 * Call this function for wakeup events whose processing started with calling 409 * Call this function for wakeup events whose processing started with calling
94 * pm_stay_awake(). 410 * __pm_stay_awake().
95 * 411 *
96 * It is safe to call it from interrupt context. 412 * It is safe to call it from interrupt context.
97 */ 413 */
98void pm_relax(void) 414void __pm_relax(struct wakeup_source *ws)
99{ 415{
100 unsigned long flags; 416 unsigned long flags;
101 417
102 spin_lock_irqsave(&events_lock, flags); 418 if (!ws)
103 if (events_in_progress) { 419 return;
104 events_in_progress--; 420
105 event_count++; 421 spin_lock_irqsave(&ws->lock, flags);
106 } 422 if (ws->active)
107 spin_unlock_irqrestore(&events_lock, flags); 423 wakeup_source_deactivate(ws);
424 spin_unlock_irqrestore(&ws->lock, flags);
425}
426EXPORT_SYMBOL_GPL(__pm_relax);
427
428/**
429 * pm_relax - Notify the PM core that processing of a wakeup event has ended.
430 * @dev: Device that signaled the event.
431 *
432 * Execute __pm_relax() for the @dev's wakeup source object.
433 */
434void pm_relax(struct device *dev)
435{
436 unsigned long flags;
437
438 if (!dev)
439 return;
440
441 spin_lock_irqsave(&dev->power.lock, flags);
442 __pm_relax(dev->power.wakeup);
443 spin_unlock_irqrestore(&dev->power.lock, flags);
108} 444}
445EXPORT_SYMBOL_GPL(pm_relax);
109 446
110/** 447/**
111 * pm_wakeup_timer_fn - Delayed finalization of a wakeup event. 448 * pm_wakeup_timer_fn - Delayed finalization of a wakeup event.
449 * @data: Address of the wakeup source object associated with the event source.
112 * 450 *
113 * Decrease the counter of wakeup events being processed after it was increased 451 * Call __pm_relax() for the wakeup source whose address is stored in @data.
114 * by pm_wakeup_event().
115 */ 452 */
116static void pm_wakeup_timer_fn(unsigned long data) 453static void pm_wakeup_timer_fn(unsigned long data)
117{ 454{
455 __pm_relax((struct wakeup_source *)data);
456}
457
458/**
459 * __pm_wakeup_event - Notify the PM core of a wakeup event.
460 * @ws: Wakeup source object associated with the event source.
461 * @msec: Anticipated event processing time (in milliseconds).
462 *
463 * Notify the PM core of a wakeup event whose source is @ws that will take
464 * approximately @msec milliseconds to be processed by the kernel. If @ws is
465 * not active, activate it. If @msec is nonzero, set up the @ws' timer to
466 * execute pm_wakeup_timer_fn() in future.
467 *
468 * It is safe to call this function from interrupt context.
469 */
470void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
471{
118 unsigned long flags; 472 unsigned long flags;
473 unsigned long expires;
119 474
120 spin_lock_irqsave(&events_lock, flags); 475 if (!ws)
121 if (events_timer_expires 476 return;
122 && time_before_eq(events_timer_expires, jiffies)) { 477
123 events_in_progress--; 478 spin_lock_irqsave(&ws->lock, flags);
124 events_timer_expires = 0; 479
480 ws->event_count++;
481 if (!ws->active)
482 wakeup_source_activate(ws);
483
484 if (!msec) {
485 wakeup_source_deactivate(ws);
486 goto unlock;
125 } 487 }
126 spin_unlock_irqrestore(&events_lock, flags); 488
489 expires = jiffies + msecs_to_jiffies(msec);
490 if (!expires)
491 expires = 1;
492
493 if (time_after(expires, ws->timer_expires)) {
494 mod_timer(&ws->timer, expires);
495 ws->timer_expires = expires;
496 }
497
498 unlock:
499 spin_unlock_irqrestore(&ws->lock, flags);
127} 500}
501EXPORT_SYMBOL_GPL(__pm_wakeup_event);
502
128 503
129/** 504/**
130 * pm_wakeup_event - Notify the PM core of a wakeup event. 505 * pm_wakeup_event - Notify the PM core of a wakeup event.
131 * @dev: Device the wakeup event is related to. 506 * @dev: Device the wakeup event is related to.
132 * @msec: Anticipated event processing time (in milliseconds). 507 * @msec: Anticipated event processing time (in milliseconds).
133 * 508 *
134 * Notify the PM core of a wakeup event (signaled by @dev) that will take 509 * Call __pm_wakeup_event() for the @dev's wakeup source object.
135 * approximately @msec milliseconds to be processed by the kernel. Increment
136 * the counter of registered wakeup events and (if @msec is nonzero) set up
137 * the wakeup events timer to execute pm_wakeup_timer_fn() in future (if the
138 * timer has not been set up already, increment the counter of wakeup events
139 * being processed). If @dev is not NULL, the counter of wakeup events related
140 * to @dev is incremented too.
141 *
142 * It is safe to call this function from interrupt context.
143 */ 510 */
144void pm_wakeup_event(struct device *dev, unsigned int msec) 511void pm_wakeup_event(struct device *dev, unsigned int msec)
145{ 512{
146 unsigned long flags; 513 unsigned long flags;
147 514
148 spin_lock_irqsave(&events_lock, flags); 515 if (!dev)
149 event_count++; 516 return;
150 if (dev)
151 dev->power.wakeup_count++;
152
153 if (msec) {
154 unsigned long expires;
155 517
156 expires = jiffies + msecs_to_jiffies(msec); 518 spin_lock_irqsave(&dev->power.lock, flags);
157 if (!expires) 519 __pm_wakeup_event(dev->power.wakeup, msec);
158 expires = 1; 520 spin_unlock_irqrestore(&dev->power.lock, flags);
521}
522EXPORT_SYMBOL_GPL(pm_wakeup_event);
159 523
160 if (!events_timer_expires 524/**
161 || time_after(expires, events_timer_expires)) { 525 * pm_wakeup_update_hit_counts - Update hit counts of all active wakeup sources.
162 if (!events_timer_expires) 526 */
163 events_in_progress++; 527static void pm_wakeup_update_hit_counts(void)
528{
529 unsigned long flags;
530 struct wakeup_source *ws;
164 531
165 mod_timer(&events_timer, expires); 532 rcu_read_lock();
166 events_timer_expires = expires; 533 list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
167 } 534 spin_lock_irqsave(&ws->lock, flags);
535 if (ws->active)
536 ws->hit_count++;
537 spin_unlock_irqrestore(&ws->lock, flags);
168 } 538 }
169 spin_unlock_irqrestore(&events_lock, flags); 539 rcu_read_unlock();
170} 540}
171 541
172/** 542/**
@@ -184,10 +554,13 @@ bool pm_check_wakeup_events(void)
184 554
185 spin_lock_irqsave(&events_lock, flags); 555 spin_lock_irqsave(&events_lock, flags);
186 if (events_check_enabled) { 556 if (events_check_enabled) {
187 ret = (event_count == saved_event_count) && !events_in_progress; 557 ret = ((unsigned int)atomic_read(&event_count) == saved_count)
558 && !atomic_read(&events_in_progress);
188 events_check_enabled = ret; 559 events_check_enabled = ret;
189 } 560 }
190 spin_unlock_irqrestore(&events_lock, flags); 561 spin_unlock_irqrestore(&events_lock, flags);
562 if (!ret)
563 pm_wakeup_update_hit_counts();
191 return ret; 564 return ret;
192} 565}
193 566
@@ -202,24 +575,20 @@ bool pm_check_wakeup_events(void)
202 * drop down to zero has been interrupted by a signal (and the current number 575 * drop down to zero has been interrupted by a signal (and the current number
203 * of wakeup events being processed is still nonzero). Otherwise return true. 576 * of wakeup events being processed is still nonzero). Otherwise return true.
204 */ 577 */
205bool pm_get_wakeup_count(unsigned long *count) 578bool pm_get_wakeup_count(unsigned int *count)
206{ 579{
207 bool ret; 580 bool ret;
208 581
209 spin_lock_irq(&events_lock);
210 if (capable(CAP_SYS_ADMIN)) 582 if (capable(CAP_SYS_ADMIN))
211 events_check_enabled = false; 583 events_check_enabled = false;
212 584
213 while (events_in_progress && !signal_pending(current)) { 585 while (atomic_read(&events_in_progress) && !signal_pending(current)) {
214 spin_unlock_irq(&events_lock); 586 pm_wakeup_update_hit_counts();
215 587 schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
216 schedule_timeout_interruptible(msecs_to_jiffies(100));
217
218 spin_lock_irq(&events_lock);
219 } 588 }
220 *count = event_count; 589
221 ret = !events_in_progress; 590 ret = !atomic_read(&events_in_progress);
222 spin_unlock_irq(&events_lock); 591 *count = atomic_read(&event_count);
223 return ret; 592 return ret;
224} 593}
225 594
@@ -232,16 +601,19 @@ bool pm_get_wakeup_count(unsigned long *count)
232 * old number of registered wakeup events to be used by pm_check_wakeup_events() 601 * old number of registered wakeup events to be used by pm_check_wakeup_events()
233 * and return true. Otherwise return false. 602 * and return true. Otherwise return false.
234 */ 603 */
235bool pm_save_wakeup_count(unsigned long count) 604bool pm_save_wakeup_count(unsigned int count)
236{ 605{
237 bool ret = false; 606 bool ret = false;
238 607
239 spin_lock_irq(&events_lock); 608 spin_lock_irq(&events_lock);
240 if (count == event_count && !events_in_progress) { 609 if (count == (unsigned int)atomic_read(&event_count)
241 saved_event_count = count; 610 && !atomic_read(&events_in_progress)) {
611 saved_count = count;
242 events_check_enabled = true; 612 events_check_enabled = true;
243 ret = true; 613 ret = true;
244 } 614 }
245 spin_unlock_irq(&events_lock); 615 spin_unlock_irq(&events_lock);
616 if (!ret)
617 pm_wakeup_update_hit_counts();
246 return ret; 618 return ret;
247} 619}
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 52e8c55ff314..a84118911ced 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -448,23 +448,24 @@ enum rpm_request {
448 RPM_REQ_RESUME, 448 RPM_REQ_RESUME,
449}; 449};
450 450
451struct wakeup_source;
452
451struct dev_pm_info { 453struct dev_pm_info {
452 pm_message_t power_state; 454 pm_message_t power_state;
453 unsigned int can_wakeup:1; 455 unsigned int can_wakeup:1;
454 unsigned int should_wakeup:1;
455 unsigned async_suspend:1; 456 unsigned async_suspend:1;
456 enum dpm_state status; /* Owned by the PM core */ 457 enum dpm_state status; /* Owned by the PM core */
458 spinlock_t lock;
457#ifdef CONFIG_PM_SLEEP 459#ifdef CONFIG_PM_SLEEP
458 struct list_head entry; 460 struct list_head entry;
459 struct completion completion; 461 struct completion completion;
460 unsigned long wakeup_count; 462 struct wakeup_source *wakeup;
461#endif 463#endif
462#ifdef CONFIG_PM_RUNTIME 464#ifdef CONFIG_PM_RUNTIME
463 struct timer_list suspend_timer; 465 struct timer_list suspend_timer;
464 unsigned long timer_expires; 466 unsigned long timer_expires;
465 struct work_struct work; 467 struct work_struct work;
466 wait_queue_head_t wait_queue; 468 wait_queue_head_t wait_queue;
467 spinlock_t lock;
468 atomic_t usage_count; 469 atomic_t usage_count;
469 atomic_t child_count; 470 atomic_t child_count;
470 unsigned int disable_depth:3; 471 unsigned int disable_depth:3;
@@ -559,11 +560,6 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);
559 } while (0) 560 } while (0)
560 561
561extern void device_pm_wait_for_dev(struct device *sub, struct device *dev); 562extern void device_pm_wait_for_dev(struct device *sub, struct device *dev);
562
563/* drivers/base/power/wakeup.c */
564extern void pm_wakeup_event(struct device *dev, unsigned int msec);
565extern void pm_stay_awake(struct device *dev);
566extern void pm_relax(void);
567#else /* !CONFIG_PM_SLEEP */ 563#else /* !CONFIG_PM_SLEEP */
568 564
569#define device_pm_lock() do {} while (0) 565#define device_pm_lock() do {} while (0)
@@ -577,10 +573,6 @@ static inline int dpm_suspend_start(pm_message_t state)
577#define suspend_report_result(fn, ret) do {} while (0) 573#define suspend_report_result(fn, ret) do {} while (0)
578 574
579static inline void device_pm_wait_for_dev(struct device *a, struct device *b) {} 575static inline void device_pm_wait_for_dev(struct device *a, struct device *b) {}
580
581static inline void pm_wakeup_event(struct device *dev, unsigned int msec) {}
582static inline void pm_stay_awake(struct device *dev) {}
583static inline void pm_relax(void) {}
584#endif /* !CONFIG_PM_SLEEP */ 576#endif /* !CONFIG_PM_SLEEP */
585 577
586/* How to reorder dpm_list after device_move() */ 578/* How to reorder dpm_list after device_move() */
diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h
index 76aca48722ae..9cff00dd6b63 100644
--- a/include/linux/pm_wakeup.h
+++ b/include/linux/pm_wakeup.h
@@ -2,6 +2,7 @@
2 * pm_wakeup.h - Power management wakeup interface 2 * pm_wakeup.h - Power management wakeup interface
3 * 3 *
4 * Copyright (C) 2008 Alan Stern 4 * Copyright (C) 2008 Alan Stern
5 * Copyright (C) 2010 Rafael J. Wysocki, Novell Inc.
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -27,19 +28,77 @@
27 28
28#include <linux/types.h> 29#include <linux/types.h>
29 30
30#ifdef CONFIG_PM 31/**
31 32 * struct wakeup_source - Representation of wakeup sources
32/* Changes to device_may_wakeup take effect on the next pm state change.
33 * 33 *
34 * By default, most devices should leave wakeup disabled. The exceptions 34 * @total_time: Total time this wakeup source has been active.
35 * are devices that everyone expects to be wakeup sources: keyboards, 35 * @max_time: Maximum time this wakeup source has been continuously active.
36 * power buttons, possibly network interfaces, etc. 36 * @last_time: Monotonic clock when the wakeup source's was activated last time.
37 * @event_count: Number of signaled wakeup events.
38 * @active_count: Number of times the wakeup sorce was activated.
39 * @relax_count: Number of times the wakeup sorce was deactivated.
40 * @hit_count: Number of times the wakeup sorce might abort system suspend.
41 * @active: Status of the wakeup source.
37 */ 42 */
38static inline void device_init_wakeup(struct device *dev, bool val) 43struct wakeup_source {
44 char *name;
45 struct list_head entry;
46 spinlock_t lock;
47 struct timer_list timer;
48 unsigned long timer_expires;
49 ktime_t total_time;
50 ktime_t max_time;
51 ktime_t last_time;
52 unsigned long event_count;
53 unsigned long active_count;
54 unsigned long relax_count;
55 unsigned long hit_count;
56 unsigned int active:1;
57};
58
59#ifdef CONFIG_PM_SLEEP
60
61/*
62 * Changes to device_may_wakeup take effect on the next pm state change.
63 */
64
65static inline void device_set_wakeup_capable(struct device *dev, bool capable)
66{
67 dev->power.can_wakeup = capable;
68}
69
70static inline bool device_can_wakeup(struct device *dev)
71{
72 return dev->power.can_wakeup;
73}
74
75
76
77static inline bool device_may_wakeup(struct device *dev)
39{ 78{
40 dev->power.can_wakeup = dev->power.should_wakeup = val; 79 return dev->power.can_wakeup && !!dev->power.wakeup;
41} 80}
42 81
82/* drivers/base/power/wakeup.c */
83extern struct wakeup_source *wakeup_source_create(const char *name);
84extern void wakeup_source_destroy(struct wakeup_source *ws);
85extern void wakeup_source_add(struct wakeup_source *ws);
86extern void wakeup_source_remove(struct wakeup_source *ws);
87extern struct wakeup_source *wakeup_source_register(const char *name);
88extern void wakeup_source_unregister(struct wakeup_source *ws);
89extern int device_wakeup_enable(struct device *dev);
90extern int device_wakeup_disable(struct device *dev);
91extern int device_init_wakeup(struct device *dev, bool val);
92extern int device_set_wakeup_enable(struct device *dev, bool enable);
93extern void __pm_stay_awake(struct wakeup_source *ws);
94extern void pm_stay_awake(struct device *dev);
95extern void __pm_relax(struct wakeup_source *ws);
96extern void pm_relax(struct device *dev);
97extern void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec);
98extern void pm_wakeup_event(struct device *dev, unsigned int msec);
99
100#else /* !CONFIG_PM_SLEEP */
101
43static inline void device_set_wakeup_capable(struct device *dev, bool capable) 102static inline void device_set_wakeup_capable(struct device *dev, bool capable)
44{ 103{
45 dev->power.can_wakeup = capable; 104 dev->power.can_wakeup = capable;
@@ -50,43 +109,63 @@ static inline bool device_can_wakeup(struct device *dev)
50 return dev->power.can_wakeup; 109 return dev->power.can_wakeup;
51} 110}
52 111
53static inline void device_set_wakeup_enable(struct device *dev, bool enable) 112static inline bool device_may_wakeup(struct device *dev)
54{ 113{
55 dev->power.should_wakeup = enable; 114 return false;
56} 115}
57 116
58static inline bool device_may_wakeup(struct device *dev) 117static inline struct wakeup_source *wakeup_source_create(const char *name)
59{ 118{
60 return dev->power.can_wakeup && dev->power.should_wakeup; 119 return NULL;
61} 120}
62 121
63#else /* !CONFIG_PM */ 122static inline void wakeup_source_destroy(struct wakeup_source *ws) {}
123
124static inline void wakeup_source_add(struct wakeup_source *ws) {}
64 125
65/* For some reason the following routines work even without CONFIG_PM */ 126static inline void wakeup_source_remove(struct wakeup_source *ws) {}
66static inline void device_init_wakeup(struct device *dev, bool val) 127
128static inline struct wakeup_source *wakeup_source_register(const char *name)
67{ 129{
68 dev->power.can_wakeup = val; 130 return NULL;
69} 131}
70 132
71static inline void device_set_wakeup_capable(struct device *dev, bool capable) 133static inline void wakeup_source_unregister(struct wakeup_source *ws) {}
134
135static inline int device_wakeup_enable(struct device *dev)
72{ 136{
73 dev->power.can_wakeup = capable; 137 return -EINVAL;
74} 138}
75 139
76static inline bool device_can_wakeup(struct device *dev) 140static inline int device_wakeup_disable(struct device *dev)
77{ 141{
78 return dev->power.can_wakeup; 142 return 0;
79} 143}
80 144
81static inline void device_set_wakeup_enable(struct device *dev, bool enable) 145static inline int device_init_wakeup(struct device *dev, bool val)
82{ 146{
147 dev->power.can_wakeup = val;
148 return val ? -EINVAL : 0;
83} 149}
84 150
85static inline bool device_may_wakeup(struct device *dev) 151
152static inline int device_set_wakeup_enable(struct device *dev, bool enable)
86{ 153{
87 return false; 154 return -EINVAL;
88} 155}
89 156
90#endif /* !CONFIG_PM */ 157static inline void __pm_stay_awake(struct wakeup_source *ws) {}
158
159static inline void pm_stay_awake(struct device *dev) {}
160
161static inline void __pm_relax(struct wakeup_source *ws) {}
162
163static inline void pm_relax(struct device *dev) {}
164
165static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) {}
166
167static inline void pm_wakeup_event(struct device *dev, unsigned int msec) {}
168
169#endif /* !CONFIG_PM_SLEEP */
91 170
92#endif /* _LINUX_PM_WAKEUP_H */ 171#endif /* _LINUX_PM_WAKEUP_H */
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 4af270ec2204..6b1712c51102 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -293,8 +293,8 @@ extern int unregister_pm_notifier(struct notifier_block *nb);
293extern bool events_check_enabled; 293extern bool events_check_enabled;
294 294
295extern bool pm_check_wakeup_events(void); 295extern bool pm_check_wakeup_events(void);
296extern bool pm_get_wakeup_count(unsigned long *count); 296extern bool pm_get_wakeup_count(unsigned int *count);
297extern bool pm_save_wakeup_count(unsigned long count); 297extern bool pm_save_wakeup_count(unsigned int count);
298#else /* !CONFIG_PM_SLEEP */ 298#else /* !CONFIG_PM_SLEEP */
299 299
300static inline int register_pm_notifier(struct notifier_block *nb) 300static inline int register_pm_notifier(struct notifier_block *nb)
diff --git a/kernel/power/main.c b/kernel/power/main.c
index f06ad6eff37a..6b12a0cf4d9f 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -237,18 +237,18 @@ static ssize_t wakeup_count_show(struct kobject *kobj,
237 struct kobj_attribute *attr, 237 struct kobj_attribute *attr,
238 char *buf) 238 char *buf)
239{ 239{
240 unsigned long val; 240 unsigned int val;
241 241
242 return pm_get_wakeup_count(&val) ? sprintf(buf, "%lu\n", val) : -EINTR; 242 return pm_get_wakeup_count(&val) ? sprintf(buf, "%u\n", val) : -EINTR;
243} 243}
244 244
245static ssize_t wakeup_count_store(struct kobject *kobj, 245static ssize_t wakeup_count_store(struct kobject *kobj,
246 struct kobj_attribute *attr, 246 struct kobj_attribute *attr,
247 const char *buf, size_t n) 247 const char *buf, size_t n)
248{ 248{
249 unsigned long val; 249 unsigned int val;
250 250
251 if (sscanf(buf, "%lu", &val) == 1) { 251 if (sscanf(buf, "%u", &val) == 1) {
252 if (pm_save_wakeup_count(val)) 252 if (pm_save_wakeup_count(val))
253 return n; 253 return n;
254 } 254 }