blob: b6e29ffbb70d16d3907cb43fac29daf104a27855 [file] [log] [blame]
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001/*
2 * drivers/base/power/domain.c - Common code related to device power domains.
3 *
4 * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
5 *
6 * This file is released under the GPLv2.
7 */
8
9#include <linux/init.h>
10#include <linux/kernel.h>
11#include <linux/io.h>
12#include <linux/pm_runtime.h>
13#include <linux/pm_domain.h>
14#include <linux/slab.h>
15#include <linux/err.h>
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +020016#include <linux/sched.h>
17#include <linux/suspend.h>
Rafael J. Wysockif7218892011-07-01 22:12:45 +020018
Rafael J. Wysocki52480512011-07-01 22:13:10 +020019#ifdef CONFIG_PM
20
21static struct generic_pm_domain *dev_to_genpd(struct device *dev)
22{
23 if (IS_ERR_OR_NULL(dev->pm_domain))
24 return ERR_PTR(-EINVAL);
25
Rafael J. Wysocki596ba342011-07-01 22:13:19 +020026 return pd_to_genpd(dev->pm_domain);
Rafael J. Wysocki52480512011-07-01 22:13:10 +020027}
Rafael J. Wysockif7218892011-07-01 22:12:45 +020028
29static void genpd_sd_counter_dec(struct generic_pm_domain *genpd)
30{
31 if (!WARN_ON(genpd->sd_count == 0))
32 genpd->sd_count--;
33}
34
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +020035static void genpd_acquire_lock(struct generic_pm_domain *genpd)
36{
37 DEFINE_WAIT(wait);
38
39 mutex_lock(&genpd->lock);
40 /*
41 * Wait for the domain to transition into either the active,
42 * or the power off state.
43 */
44 for (;;) {
45 prepare_to_wait(&genpd->status_wait_queue, &wait,
46 TASK_UNINTERRUPTIBLE);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +020047 if (genpd->status == GPD_STATE_ACTIVE
48 || genpd->status == GPD_STATE_POWER_OFF)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +020049 break;
50 mutex_unlock(&genpd->lock);
51
52 schedule();
53
54 mutex_lock(&genpd->lock);
55 }
56 finish_wait(&genpd->status_wait_queue, &wait);
57}
58
59static void genpd_release_lock(struct generic_pm_domain *genpd)
60{
61 mutex_unlock(&genpd->lock);
62}
63
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +020064static void genpd_set_active(struct generic_pm_domain *genpd)
65{
66 if (genpd->resume_count == 0)
67 genpd->status = GPD_STATE_ACTIVE;
68}
69
Rafael J. Wysockif7218892011-07-01 22:12:45 +020070/**
Rafael J. Wysocki52480512011-07-01 22:13:10 +020071 * pm_genpd_poweron - Restore power to a given PM domain and its parents.
72 * @genpd: PM domain to power up.
73 *
74 * Restore power to @genpd and all of its parents so that it is possible to
75 * resume a device belonging to it.
76 */
Magnus Damm18b4f3f2011-07-10 10:39:14 +020077int pm_genpd_poweron(struct generic_pm_domain *genpd)
Rafael J. Wysocki52480512011-07-01 22:13:10 +020078{
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +020079 struct generic_pm_domain *parent = genpd->parent;
80 DEFINE_WAIT(wait);
Rafael J. Wysocki52480512011-07-01 22:13:10 +020081 int ret = 0;
82
83 start:
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +020084 if (parent) {
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +020085 genpd_acquire_lock(parent);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +020086 mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
87 } else {
88 mutex_lock(&genpd->lock);
89 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +020090
91 if (genpd->status == GPD_STATE_ACTIVE
Rafael J. Wysocki596ba342011-07-01 22:13:19 +020092 || (genpd->prepared_count > 0 && genpd->suspend_power_off))
Rafael J. Wysocki52480512011-07-01 22:13:10 +020093 goto out;
94
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +020095 if (genpd->status != GPD_STATE_POWER_OFF) {
96 genpd_set_active(genpd);
97 goto out;
98 }
99
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200100 if (parent && parent->status != GPD_STATE_ACTIVE) {
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200101 mutex_unlock(&genpd->lock);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200102 genpd_release_lock(parent);
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200103
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200104 ret = pm_genpd_poweron(parent);
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200105 if (ret)
106 return ret;
107
108 goto start;
109 }
110
111 if (genpd->power_on) {
112 int ret = genpd->power_on(genpd);
113 if (ret)
114 goto out;
115 }
116
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200117 genpd_set_active(genpd);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200118 if (parent)
119 parent->sd_count++;
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200120
121 out:
122 mutex_unlock(&genpd->lock);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200123 if (parent)
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200124 genpd_release_lock(parent);
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200125
126 return ret;
127}
128
129#endif /* CONFIG_PM */
130
131#ifdef CONFIG_PM_RUNTIME
132
133/**
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200134 * __pm_genpd_save_device - Save the pre-suspend state of a device.
135 * @dle: Device list entry of the device to save the state of.
136 * @genpd: PM domain the device belongs to.
137 */
138static int __pm_genpd_save_device(struct dev_list_entry *dle,
139 struct generic_pm_domain *genpd)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200140 __releases(&genpd->lock) __acquires(&genpd->lock)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200141{
142 struct device *dev = dle->dev;
143 struct device_driver *drv = dev->driver;
144 int ret = 0;
145
146 if (dle->need_restore)
147 return 0;
148
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200149 mutex_unlock(&genpd->lock);
150
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200151 if (drv && drv->pm && drv->pm->runtime_suspend) {
152 if (genpd->start_device)
153 genpd->start_device(dev);
154
155 ret = drv->pm->runtime_suspend(dev);
156
157 if (genpd->stop_device)
158 genpd->stop_device(dev);
159 }
160
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200161 mutex_lock(&genpd->lock);
162
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200163 if (!ret)
164 dle->need_restore = true;
165
166 return ret;
167}
168
169/**
170 * __pm_genpd_restore_device - Restore the pre-suspend state of a device.
171 * @dle: Device list entry of the device to restore the state of.
172 * @genpd: PM domain the device belongs to.
173 */
174static void __pm_genpd_restore_device(struct dev_list_entry *dle,
175 struct generic_pm_domain *genpd)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200176 __releases(&genpd->lock) __acquires(&genpd->lock)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200177{
178 struct device *dev = dle->dev;
179 struct device_driver *drv = dev->driver;
180
181 if (!dle->need_restore)
182 return;
183
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200184 mutex_unlock(&genpd->lock);
185
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200186 if (drv && drv->pm && drv->pm->runtime_resume) {
187 if (genpd->start_device)
188 genpd->start_device(dev);
189
190 drv->pm->runtime_resume(dev);
191
192 if (genpd->stop_device)
193 genpd->stop_device(dev);
194 }
195
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200196 mutex_lock(&genpd->lock);
197
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200198 dle->need_restore = false;
199}
200
201/**
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200202 * genpd_abort_poweroff - Check if a PM domain power off should be aborted.
203 * @genpd: PM domain to check.
204 *
205 * Return true if a PM domain's status changed to GPD_STATE_ACTIVE during
206 * a "power off" operation, which means that a "power on" has occured in the
207 * meantime, or if its resume_count field is different from zero, which means
208 * that one of its devices has been resumed in the meantime.
209 */
210static bool genpd_abort_poweroff(struct generic_pm_domain *genpd)
211{
212 return genpd->status == GPD_STATE_ACTIVE || genpd->resume_count > 0;
213}
214
215/**
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200216 * pm_genpd_poweroff - Remove power from a given PM domain.
217 * @genpd: PM domain to power down.
218 *
219 * If all of the @genpd's devices have been suspended and all of its subdomains
220 * have been powered down, run the runtime suspend callbacks provided by all of
221 * the @genpd's devices' drivers and remove power from @genpd.
222 */
223static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200224 __releases(&genpd->lock) __acquires(&genpd->lock)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200225{
226 struct generic_pm_domain *parent;
227 struct dev_list_entry *dle;
228 unsigned int not_suspended;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200229 int ret = 0;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200230
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200231 start:
232 /*
233 * Do not try to power off the domain in the following situations:
234 * (1) The domain is already in the "power off" state.
235 * (2) System suspend is in progress.
236 * (3) One of the domain's devices is being resumed right now.
237 */
238 if (genpd->status == GPD_STATE_POWER_OFF || genpd->prepared_count > 0
239 || genpd->resume_count > 0)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200240 return 0;
241
242 if (genpd->sd_count > 0)
243 return -EBUSY;
244
245 not_suspended = 0;
246 list_for_each_entry(dle, &genpd->dev_list, node)
247 if (dle->dev->driver && !pm_runtime_suspended(dle->dev))
248 not_suspended++;
249
250 if (not_suspended > genpd->in_progress)
251 return -EBUSY;
252
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200253 if (genpd->poweroff_task) {
254 /*
255 * Another instance of pm_genpd_poweroff() is executing
256 * callbacks, so tell it to start over and return.
257 */
258 genpd->status = GPD_STATE_REPEAT;
259 return 0;
260 }
261
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200262 if (genpd->gov && genpd->gov->power_down_ok) {
263 if (!genpd->gov->power_down_ok(&genpd->domain))
264 return -EAGAIN;
265 }
266
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200267 genpd->status = GPD_STATE_BUSY;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200268 genpd->poweroff_task = current;
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200269
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200270 list_for_each_entry_reverse(dle, &genpd->dev_list, node) {
271 ret = __pm_genpd_save_device(dle, genpd);
Rafael J. Wysocki697a7f32011-07-12 00:39:48 +0200272 if (ret) {
273 genpd_set_active(genpd);
274 goto out;
275 }
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200276
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200277 if (genpd_abort_poweroff(genpd))
278 goto out;
279
280 if (genpd->status == GPD_STATE_REPEAT) {
281 genpd->poweroff_task = NULL;
282 goto start;
283 }
284 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200285
286 parent = genpd->parent;
287 if (parent) {
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200288 mutex_unlock(&genpd->lock);
289
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200290 genpd_acquire_lock(parent);
291 mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200292
293 if (genpd_abort_poweroff(genpd)) {
294 genpd_release_lock(parent);
295 goto out;
296 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200297 }
298
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200299 if (genpd->power_off)
300 genpd->power_off(genpd);
301
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200302 genpd->status = GPD_STATE_POWER_OFF;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200303
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200304 if (parent) {
305 genpd_sd_counter_dec(parent);
306 if (parent->sd_count == 0)
307 queue_work(pm_wq, &parent->power_off_work);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200308
309 genpd_release_lock(parent);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200310 }
311
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200312 out:
313 genpd->poweroff_task = NULL;
314 wake_up_all(&genpd->status_wait_queue);
315 return ret;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200316}
317
318/**
319 * genpd_power_off_work_fn - Power off PM domain whose subdomain count is 0.
320 * @work: Work structure used for scheduling the execution of this function.
321 */
322static void genpd_power_off_work_fn(struct work_struct *work)
323{
324 struct generic_pm_domain *genpd;
325
326 genpd = container_of(work, struct generic_pm_domain, power_off_work);
327
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200328 genpd_acquire_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200329 pm_genpd_poweroff(genpd);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200330 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200331}
332
333/**
334 * pm_genpd_runtime_suspend - Suspend a device belonging to I/O PM domain.
335 * @dev: Device to suspend.
336 *
337 * Carry out a runtime suspend of a device under the assumption that its
338 * pm_domain field points to the domain member of an object of type
339 * struct generic_pm_domain representing a PM domain consisting of I/O devices.
340 */
341static int pm_genpd_runtime_suspend(struct device *dev)
342{
343 struct generic_pm_domain *genpd;
344
345 dev_dbg(dev, "%s()\n", __func__);
346
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200347 genpd = dev_to_genpd(dev);
348 if (IS_ERR(genpd))
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200349 return -EINVAL;
350
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200351 if (genpd->stop_device) {
352 int ret = genpd->stop_device(dev);
353 if (ret)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200354 return ret;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200355 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200356
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200357 mutex_lock(&genpd->lock);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200358 genpd->in_progress++;
359 pm_genpd_poweroff(genpd);
360 genpd->in_progress--;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200361 mutex_unlock(&genpd->lock);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200362
363 return 0;
364}
365
366/**
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200367 * __pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
368 * @dev: Device to resume.
369 * @genpd: PM domain the device belongs to.
370 */
371static void __pm_genpd_runtime_resume(struct device *dev,
372 struct generic_pm_domain *genpd)
373{
374 struct dev_list_entry *dle;
375
376 list_for_each_entry(dle, &genpd->dev_list, node) {
377 if (dle->dev == dev) {
378 __pm_genpd_restore_device(dle, genpd);
379 break;
380 }
381 }
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200382}
383
384/**
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200385 * pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
386 * @dev: Device to resume.
387 *
388 * Carry out a runtime resume of a device under the assumption that its
389 * pm_domain field points to the domain member of an object of type
390 * struct generic_pm_domain representing a PM domain consisting of I/O devices.
391 */
392static int pm_genpd_runtime_resume(struct device *dev)
393{
394 struct generic_pm_domain *genpd;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200395 DEFINE_WAIT(wait);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200396 int ret;
397
398 dev_dbg(dev, "%s()\n", __func__);
399
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200400 genpd = dev_to_genpd(dev);
401 if (IS_ERR(genpd))
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200402 return -EINVAL;
403
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200404 ret = pm_genpd_poweron(genpd);
405 if (ret)
406 return ret;
407
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200408 mutex_lock(&genpd->lock);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200409 genpd->status = GPD_STATE_BUSY;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200410 genpd->resume_count++;
411 for (;;) {
412 prepare_to_wait(&genpd->status_wait_queue, &wait,
413 TASK_UNINTERRUPTIBLE);
414 /*
415 * If current is the powering off task, we have been called
416 * reentrantly from one of the device callbacks, so we should
417 * not wait.
418 */
419 if (!genpd->poweroff_task || genpd->poweroff_task == current)
420 break;
421 mutex_unlock(&genpd->lock);
422
423 schedule();
424
425 mutex_lock(&genpd->lock);
426 }
427 finish_wait(&genpd->status_wait_queue, &wait);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200428 __pm_genpd_runtime_resume(dev, genpd);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200429 genpd->resume_count--;
430 genpd_set_active(genpd);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200431 wake_up_all(&genpd->status_wait_queue);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200432 mutex_unlock(&genpd->lock);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200433
434 if (genpd->start_device)
435 genpd->start_device(dev);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200436
437 return 0;
438}
439
440#else
441
442static inline void genpd_power_off_work_fn(struct work_struct *work) {}
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200443static inline void __pm_genpd_runtime_resume(struct device *dev,
444 struct generic_pm_domain *genpd) {}
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200445
446#define pm_genpd_runtime_suspend NULL
447#define pm_genpd_runtime_resume NULL
448
449#endif /* CONFIG_PM_RUNTIME */
450
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200451#ifdef CONFIG_PM_SLEEP
452
453/**
454 * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its parents.
455 * @genpd: PM domain to power off, if possible.
456 *
457 * Check if the given PM domain can be powered off (during system suspend or
458 * hibernation) and do that if so. Also, in that case propagate to its parent.
459 *
460 * This function is only called in "noirq" stages of system power transitions,
461 * so it need not acquire locks (all of the "noirq" callbacks are executed
462 * sequentially, so it is guaranteed that it will never run twice in parallel).
463 */
464static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
465{
466 struct generic_pm_domain *parent = genpd->parent;
467
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200468 if (genpd->status == GPD_STATE_POWER_OFF)
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200469 return;
470
471 if (genpd->suspended_count != genpd->device_count || genpd->sd_count > 0)
472 return;
473
474 if (genpd->power_off)
475 genpd->power_off(genpd);
476
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200477 genpd->status = GPD_STATE_POWER_OFF;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200478 if (parent) {
479 genpd_sd_counter_dec(parent);
480 pm_genpd_sync_poweroff(parent);
481 }
482}
483
484/**
Rafael J. Wysocki4ecd6e62011-07-12 00:39:57 +0200485 * resume_needed - Check whether to resume a device before system suspend.
486 * @dev: Device to check.
487 * @genpd: PM domain the device belongs to.
488 *
489 * There are two cases in which a device that can wake up the system from sleep
490 * states should be resumed by pm_genpd_prepare(): (1) if the device is enabled
491 * to wake up the system and it has to remain active for this purpose while the
492 * system is in the sleep state and (2) if the device is not enabled to wake up
493 * the system from sleep states and it generally doesn't generate wakeup signals
494 * by itself (those signals are generated on its behalf by other parts of the
495 * system). In the latter case it may be necessary to reconfigure the device's
496 * wakeup settings during system suspend, because it may have been set up to
497 * signal remote wakeup from the system's working state as needed by runtime PM.
498 * Return 'true' in either of the above cases.
499 */
500static bool resume_needed(struct device *dev, struct generic_pm_domain *genpd)
501{
502 bool active_wakeup;
503
504 if (!device_can_wakeup(dev))
505 return false;
506
507 active_wakeup = genpd->active_wakeup && genpd->active_wakeup(dev);
508 return device_may_wakeup(dev) ? active_wakeup : !active_wakeup;
509}
510
511/**
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200512 * pm_genpd_prepare - Start power transition of a device in a PM domain.
513 * @dev: Device to start the transition of.
514 *
515 * Start a power transition of a device (during a system-wide power transition)
516 * under the assumption that its pm_domain field points to the domain member of
517 * an object of type struct generic_pm_domain representing a PM domain
518 * consisting of I/O devices.
519 */
520static int pm_genpd_prepare(struct device *dev)
521{
522 struct generic_pm_domain *genpd;
Rafael J. Wysockib6c10c82011-07-12 00:39:21 +0200523 int ret;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200524
525 dev_dbg(dev, "%s()\n", __func__);
526
527 genpd = dev_to_genpd(dev);
528 if (IS_ERR(genpd))
529 return -EINVAL;
530
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200531 /*
532 * If a wakeup request is pending for the device, it should be woken up
533 * at this point and a system wakeup event should be reported if it's
534 * set up to wake up the system from sleep states.
535 */
536 pm_runtime_get_noresume(dev);
537 if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
538 pm_wakeup_event(dev, 0);
539
540 if (pm_wakeup_pending()) {
541 pm_runtime_put_sync(dev);
542 return -EBUSY;
543 }
544
Rafael J. Wysocki4ecd6e62011-07-12 00:39:57 +0200545 if (resume_needed(dev, genpd))
546 pm_runtime_resume(dev);
547
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200548 genpd_acquire_lock(genpd);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200549
550 if (genpd->prepared_count++ == 0)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200551 genpd->suspend_power_off = genpd->status == GPD_STATE_POWER_OFF;
552
553 genpd_release_lock(genpd);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200554
555 if (genpd->suspend_power_off) {
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200556 pm_runtime_put_noidle(dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200557 return 0;
558 }
559
560 /*
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200561 * The PM domain must be in the GPD_STATE_ACTIVE state at this point,
562 * so pm_genpd_poweron() will return immediately, but if the device
563 * is suspended (e.g. it's been stopped by .stop_device()), we need
564 * to make it operational.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200565 */
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200566 pm_runtime_resume(dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200567 __pm_runtime_disable(dev, false);
568
Rafael J. Wysockib6c10c82011-07-12 00:39:21 +0200569 ret = pm_generic_prepare(dev);
570 if (ret) {
571 mutex_lock(&genpd->lock);
572
573 if (--genpd->prepared_count == 0)
574 genpd->suspend_power_off = false;
575
576 mutex_unlock(&genpd->lock);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200577 pm_runtime_enable(dev);
Rafael J. Wysockib6c10c82011-07-12 00:39:21 +0200578 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200579
580 pm_runtime_put_sync(dev);
Rafael J. Wysockib6c10c82011-07-12 00:39:21 +0200581 return ret;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200582}
583
584/**
585 * pm_genpd_suspend - Suspend a device belonging to an I/O PM domain.
586 * @dev: Device to suspend.
587 *
588 * Suspend a device under the assumption that its pm_domain field points to the
589 * domain member of an object of type struct generic_pm_domain representing
590 * a PM domain consisting of I/O devices.
591 */
592static int pm_genpd_suspend(struct device *dev)
593{
594 struct generic_pm_domain *genpd;
595
596 dev_dbg(dev, "%s()\n", __func__);
597
598 genpd = dev_to_genpd(dev);
599 if (IS_ERR(genpd))
600 return -EINVAL;
601
602 return genpd->suspend_power_off ? 0 : pm_generic_suspend(dev);
603}
604
605/**
606 * pm_genpd_suspend_noirq - Late suspend of a device from an I/O PM domain.
607 * @dev: Device to suspend.
608 *
609 * Carry out a late suspend of a device under the assumption that its
610 * pm_domain field points to the domain member of an object of type
611 * struct generic_pm_domain representing a PM domain consisting of I/O devices.
612 */
613static int pm_genpd_suspend_noirq(struct device *dev)
614{
615 struct generic_pm_domain *genpd;
616 int ret;
617
618 dev_dbg(dev, "%s()\n", __func__);
619
620 genpd = dev_to_genpd(dev);
621 if (IS_ERR(genpd))
622 return -EINVAL;
623
624 if (genpd->suspend_power_off)
625 return 0;
626
627 ret = pm_generic_suspend_noirq(dev);
628 if (ret)
629 return ret;
630
Rafael J. Wysockid4f2d872011-07-01 22:13:29 +0200631 if (device_may_wakeup(dev)
632 && genpd->active_wakeup && genpd->active_wakeup(dev))
633 return 0;
634
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200635 if (genpd->stop_device)
636 genpd->stop_device(dev);
637
638 /*
639 * Since all of the "noirq" callbacks are executed sequentially, it is
640 * guaranteed that this function will never run twice in parallel for
641 * the same PM domain, so it is not necessary to use locking here.
642 */
643 genpd->suspended_count++;
644 pm_genpd_sync_poweroff(genpd);
645
646 return 0;
647}
648
649/**
650 * pm_genpd_resume_noirq - Early resume of a device from an I/O power domain.
651 * @dev: Device to resume.
652 *
653 * Carry out an early resume of a device under the assumption that its
654 * pm_domain field points to the domain member of an object of type
655 * struct generic_pm_domain representing a power domain consisting of I/O
656 * devices.
657 */
658static int pm_genpd_resume_noirq(struct device *dev)
659{
660 struct generic_pm_domain *genpd;
661
662 dev_dbg(dev, "%s()\n", __func__);
663
664 genpd = dev_to_genpd(dev);
665 if (IS_ERR(genpd))
666 return -EINVAL;
667
668 if (genpd->suspend_power_off)
669 return 0;
670
671 /*
672 * Since all of the "noirq" callbacks are executed sequentially, it is
673 * guaranteed that this function will never run twice in parallel for
674 * the same PM domain, so it is not necessary to use locking here.
675 */
676 pm_genpd_poweron(genpd);
677 genpd->suspended_count--;
678 if (genpd->start_device)
679 genpd->start_device(dev);
680
681 return pm_generic_resume_noirq(dev);
682}
683
684/**
685 * pm_genpd_resume - Resume a device belonging to an I/O power domain.
686 * @dev: Device to resume.
687 *
688 * Resume a device under the assumption that its pm_domain field points to the
689 * domain member of an object of type struct generic_pm_domain representing
690 * a power domain consisting of I/O devices.
691 */
692static int pm_genpd_resume(struct device *dev)
693{
694 struct generic_pm_domain *genpd;
695
696 dev_dbg(dev, "%s()\n", __func__);
697
698 genpd = dev_to_genpd(dev);
699 if (IS_ERR(genpd))
700 return -EINVAL;
701
702 return genpd->suspend_power_off ? 0 : pm_generic_resume(dev);
703}
704
705/**
706 * pm_genpd_freeze - Freeze a device belonging to an I/O power domain.
707 * @dev: Device to freeze.
708 *
709 * Freeze a device under the assumption that its pm_domain field points to the
710 * domain member of an object of type struct generic_pm_domain representing
711 * a power domain consisting of I/O devices.
712 */
713static int pm_genpd_freeze(struct device *dev)
714{
715 struct generic_pm_domain *genpd;
716
717 dev_dbg(dev, "%s()\n", __func__);
718
719 genpd = dev_to_genpd(dev);
720 if (IS_ERR(genpd))
721 return -EINVAL;
722
723 return genpd->suspend_power_off ? 0 : pm_generic_freeze(dev);
724}
725
726/**
727 * pm_genpd_freeze_noirq - Late freeze of a device from an I/O power domain.
728 * @dev: Device to freeze.
729 *
730 * Carry out a late freeze of a device under the assumption that its
731 * pm_domain field points to the domain member of an object of type
732 * struct generic_pm_domain representing a power domain consisting of I/O
733 * devices.
734 */
735static int pm_genpd_freeze_noirq(struct device *dev)
736{
737 struct generic_pm_domain *genpd;
738 int ret;
739
740 dev_dbg(dev, "%s()\n", __func__);
741
742 genpd = dev_to_genpd(dev);
743 if (IS_ERR(genpd))
744 return -EINVAL;
745
746 if (genpd->suspend_power_off)
747 return 0;
748
749 ret = pm_generic_freeze_noirq(dev);
750 if (ret)
751 return ret;
752
753 if (genpd->stop_device)
754 genpd->stop_device(dev);
755
756 return 0;
757}
758
759/**
760 * pm_genpd_thaw_noirq - Early thaw of a device from an I/O power domain.
761 * @dev: Device to thaw.
762 *
763 * Carry out an early thaw of a device under the assumption that its
764 * pm_domain field points to the domain member of an object of type
765 * struct generic_pm_domain representing a power domain consisting of I/O
766 * devices.
767 */
768static int pm_genpd_thaw_noirq(struct device *dev)
769{
770 struct generic_pm_domain *genpd;
771
772 dev_dbg(dev, "%s()\n", __func__);
773
774 genpd = dev_to_genpd(dev);
775 if (IS_ERR(genpd))
776 return -EINVAL;
777
778 if (genpd->suspend_power_off)
779 return 0;
780
781 if (genpd->start_device)
782 genpd->start_device(dev);
783
784 return pm_generic_thaw_noirq(dev);
785}
786
787/**
788 * pm_genpd_thaw - Thaw a device belonging to an I/O power domain.
789 * @dev: Device to thaw.
790 *
791 * Thaw a device under the assumption that its pm_domain field points to the
792 * domain member of an object of type struct generic_pm_domain representing
793 * a power domain consisting of I/O devices.
794 */
795static int pm_genpd_thaw(struct device *dev)
796{
797 struct generic_pm_domain *genpd;
798
799 dev_dbg(dev, "%s()\n", __func__);
800
801 genpd = dev_to_genpd(dev);
802 if (IS_ERR(genpd))
803 return -EINVAL;
804
805 return genpd->suspend_power_off ? 0 : pm_generic_thaw(dev);
806}
807
808/**
809 * pm_genpd_dev_poweroff - Power off a device belonging to an I/O PM domain.
810 * @dev: Device to suspend.
811 *
812 * Power off a device under the assumption that its pm_domain field points to
813 * the domain member of an object of type struct generic_pm_domain representing
814 * a PM domain consisting of I/O devices.
815 */
816static int pm_genpd_dev_poweroff(struct device *dev)
817{
818 struct generic_pm_domain *genpd;
819
820 dev_dbg(dev, "%s()\n", __func__);
821
822 genpd = dev_to_genpd(dev);
823 if (IS_ERR(genpd))
824 return -EINVAL;
825
826 return genpd->suspend_power_off ? 0 : pm_generic_poweroff(dev);
827}
828
829/**
830 * pm_genpd_dev_poweroff_noirq - Late power off of a device from a PM domain.
831 * @dev: Device to suspend.
832 *
833 * Carry out a late powering off of a device under the assumption that its
834 * pm_domain field points to the domain member of an object of type
835 * struct generic_pm_domain representing a PM domain consisting of I/O devices.
836 */
837static int pm_genpd_dev_poweroff_noirq(struct device *dev)
838{
839 struct generic_pm_domain *genpd;
840 int ret;
841
842 dev_dbg(dev, "%s()\n", __func__);
843
844 genpd = dev_to_genpd(dev);
845 if (IS_ERR(genpd))
846 return -EINVAL;
847
848 if (genpd->suspend_power_off)
849 return 0;
850
851 ret = pm_generic_poweroff_noirq(dev);
852 if (ret)
853 return ret;
854
Rafael J. Wysockid4f2d872011-07-01 22:13:29 +0200855 if (device_may_wakeup(dev)
856 && genpd->active_wakeup && genpd->active_wakeup(dev))
857 return 0;
858
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200859 if (genpd->stop_device)
860 genpd->stop_device(dev);
861
862 /*
863 * Since all of the "noirq" callbacks are executed sequentially, it is
864 * guaranteed that this function will never run twice in parallel for
865 * the same PM domain, so it is not necessary to use locking here.
866 */
867 genpd->suspended_count++;
868 pm_genpd_sync_poweroff(genpd);
869
870 return 0;
871}
872
873/**
874 * pm_genpd_restore_noirq - Early restore of a device from an I/O power domain.
875 * @dev: Device to resume.
876 *
877 * Carry out an early restore of a device under the assumption that its
878 * pm_domain field points to the domain member of an object of type
879 * struct generic_pm_domain representing a power domain consisting of I/O
880 * devices.
881 */
882static int pm_genpd_restore_noirq(struct device *dev)
883{
884 struct generic_pm_domain *genpd;
885
886 dev_dbg(dev, "%s()\n", __func__);
887
888 genpd = dev_to_genpd(dev);
889 if (IS_ERR(genpd))
890 return -EINVAL;
891
892 /*
893 * Since all of the "noirq" callbacks are executed sequentially, it is
894 * guaranteed that this function will never run twice in parallel for
895 * the same PM domain, so it is not necessary to use locking here.
896 */
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200897 genpd->status = GPD_STATE_POWER_OFF;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200898 if (genpd->suspend_power_off) {
899 /*
900 * The boot kernel might put the domain into the power on state,
901 * so make sure it really is powered off.
902 */
903 if (genpd->power_off)
904 genpd->power_off(genpd);
905 return 0;
906 }
907
908 pm_genpd_poweron(genpd);
909 genpd->suspended_count--;
910 if (genpd->start_device)
911 genpd->start_device(dev);
912
913 return pm_generic_restore_noirq(dev);
914}
915
916/**
917 * pm_genpd_restore - Restore a device belonging to an I/O power domain.
918 * @dev: Device to resume.
919 *
920 * Restore a device under the assumption that its pm_domain field points to the
921 * domain member of an object of type struct generic_pm_domain representing
922 * a power domain consisting of I/O devices.
923 */
924static int pm_genpd_restore(struct device *dev)
925{
926 struct generic_pm_domain *genpd;
927
928 dev_dbg(dev, "%s()\n", __func__);
929
930 genpd = dev_to_genpd(dev);
931 if (IS_ERR(genpd))
932 return -EINVAL;
933
934 return genpd->suspend_power_off ? 0 : pm_generic_restore(dev);
935}
936
937/**
938 * pm_genpd_complete - Complete power transition of a device in a power domain.
939 * @dev: Device to complete the transition of.
940 *
941 * Complete a power transition of a device (during a system-wide power
942 * transition) under the assumption that its pm_domain field points to the
943 * domain member of an object of type struct generic_pm_domain representing
944 * a power domain consisting of I/O devices.
945 */
946static void pm_genpd_complete(struct device *dev)
947{
948 struct generic_pm_domain *genpd;
949 bool run_complete;
950
951 dev_dbg(dev, "%s()\n", __func__);
952
953 genpd = dev_to_genpd(dev);
954 if (IS_ERR(genpd))
955 return;
956
957 mutex_lock(&genpd->lock);
958
959 run_complete = !genpd->suspend_power_off;
960 if (--genpd->prepared_count == 0)
961 genpd->suspend_power_off = false;
962
963 mutex_unlock(&genpd->lock);
964
965 if (run_complete) {
966 pm_generic_complete(dev);
Rafael J. Wysocki6f00ff72011-07-12 00:39:10 +0200967 pm_runtime_set_active(dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200968 pm_runtime_enable(dev);
Rafael J. Wysocki6f00ff72011-07-12 00:39:10 +0200969 pm_runtime_idle(dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200970 }
971}
972
973#else
974
975#define pm_genpd_prepare NULL
976#define pm_genpd_suspend NULL
977#define pm_genpd_suspend_noirq NULL
978#define pm_genpd_resume_noirq NULL
979#define pm_genpd_resume NULL
980#define pm_genpd_freeze NULL
981#define pm_genpd_freeze_noirq NULL
982#define pm_genpd_thaw_noirq NULL
983#define pm_genpd_thaw NULL
984#define pm_genpd_dev_poweroff_noirq NULL
985#define pm_genpd_dev_poweroff NULL
986#define pm_genpd_restore_noirq NULL
987#define pm_genpd_restore NULL
988#define pm_genpd_complete NULL
989
990#endif /* CONFIG_PM_SLEEP */
991
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200992/**
993 * pm_genpd_add_device - Add a device to an I/O PM domain.
994 * @genpd: PM domain to add the device to.
995 * @dev: Device to be added.
996 */
997int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev)
998{
999 struct dev_list_entry *dle;
1000 int ret = 0;
1001
1002 dev_dbg(dev, "%s()\n", __func__);
1003
1004 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
1005 return -EINVAL;
1006
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001007 genpd_acquire_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001008
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001009 if (genpd->status == GPD_STATE_POWER_OFF) {
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001010 ret = -EINVAL;
1011 goto out;
1012 }
1013
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001014 if (genpd->prepared_count > 0) {
1015 ret = -EAGAIN;
1016 goto out;
1017 }
1018
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001019 list_for_each_entry(dle, &genpd->dev_list, node)
1020 if (dle->dev == dev) {
1021 ret = -EINVAL;
1022 goto out;
1023 }
1024
1025 dle = kzalloc(sizeof(*dle), GFP_KERNEL);
1026 if (!dle) {
1027 ret = -ENOMEM;
1028 goto out;
1029 }
1030
1031 dle->dev = dev;
1032 dle->need_restore = false;
1033 list_add_tail(&dle->node, &genpd->dev_list);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001034 genpd->device_count++;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001035
1036 spin_lock_irq(&dev->power.lock);
1037 dev->pm_domain = &genpd->domain;
1038 spin_unlock_irq(&dev->power.lock);
1039
1040 out:
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001041 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001042
1043 return ret;
1044}
1045
1046/**
1047 * pm_genpd_remove_device - Remove a device from an I/O PM domain.
1048 * @genpd: PM domain to remove the device from.
1049 * @dev: Device to be removed.
1050 */
1051int pm_genpd_remove_device(struct generic_pm_domain *genpd,
1052 struct device *dev)
1053{
1054 struct dev_list_entry *dle;
1055 int ret = -EINVAL;
1056
1057 dev_dbg(dev, "%s()\n", __func__);
1058
1059 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
1060 return -EINVAL;
1061
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001062 genpd_acquire_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001063
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001064 if (genpd->prepared_count > 0) {
1065 ret = -EAGAIN;
1066 goto out;
1067 }
1068
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001069 list_for_each_entry(dle, &genpd->dev_list, node) {
1070 if (dle->dev != dev)
1071 continue;
1072
1073 spin_lock_irq(&dev->power.lock);
1074 dev->pm_domain = NULL;
1075 spin_unlock_irq(&dev->power.lock);
1076
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001077 genpd->device_count--;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001078 list_del(&dle->node);
1079 kfree(dle);
1080
1081 ret = 0;
1082 break;
1083 }
1084
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001085 out:
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001086 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001087
1088 return ret;
1089}
1090
1091/**
1092 * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
1093 * @genpd: Master PM domain to add the subdomain to.
1094 * @new_subdomain: Subdomain to be added.
1095 */
1096int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
1097 struct generic_pm_domain *new_subdomain)
1098{
1099 struct generic_pm_domain *subdomain;
1100 int ret = 0;
1101
1102 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(new_subdomain))
1103 return -EINVAL;
1104
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001105 start:
1106 genpd_acquire_lock(genpd);
1107 mutex_lock_nested(&new_subdomain->lock, SINGLE_DEPTH_NESTING);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001108
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001109 if (new_subdomain->status != GPD_STATE_POWER_OFF
1110 && new_subdomain->status != GPD_STATE_ACTIVE) {
1111 mutex_unlock(&new_subdomain->lock);
1112 genpd_release_lock(genpd);
1113 goto start;
1114 }
1115
1116 if (genpd->status == GPD_STATE_POWER_OFF
1117 && new_subdomain->status != GPD_STATE_POWER_OFF) {
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001118 ret = -EINVAL;
1119 goto out;
1120 }
1121
1122 list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
1123 if (subdomain == new_subdomain) {
1124 ret = -EINVAL;
1125 goto out;
1126 }
1127 }
1128
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001129 list_add_tail(&new_subdomain->sd_node, &genpd->sd_list);
1130 new_subdomain->parent = genpd;
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001131 if (subdomain->status != GPD_STATE_POWER_OFF)
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001132 genpd->sd_count++;
1133
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001134 out:
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001135 mutex_unlock(&new_subdomain->lock);
1136 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001137
1138 return ret;
1139}
1140
1141/**
1142 * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
1143 * @genpd: Master PM domain to remove the subdomain from.
1144 * @target: Subdomain to be removed.
1145 */
1146int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
1147 struct generic_pm_domain *target)
1148{
1149 struct generic_pm_domain *subdomain;
1150 int ret = -EINVAL;
1151
1152 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(target))
1153 return -EINVAL;
1154
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001155 start:
1156 genpd_acquire_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001157
1158 list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
1159 if (subdomain != target)
1160 continue;
1161
1162 mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
1163
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001164 if (subdomain->status != GPD_STATE_POWER_OFF
1165 && subdomain->status != GPD_STATE_ACTIVE) {
1166 mutex_unlock(&subdomain->lock);
1167 genpd_release_lock(genpd);
1168 goto start;
1169 }
1170
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001171 list_del(&subdomain->sd_node);
1172 subdomain->parent = NULL;
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001173 if (subdomain->status != GPD_STATE_POWER_OFF)
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001174 genpd_sd_counter_dec(genpd);
1175
1176 mutex_unlock(&subdomain->lock);
1177
1178 ret = 0;
1179 break;
1180 }
1181
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001182 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001183
1184 return ret;
1185}
1186
1187/**
1188 * pm_genpd_init - Initialize a generic I/O PM domain object.
1189 * @genpd: PM domain object to initialize.
1190 * @gov: PM domain governor to associate with the domain (may be NULL).
1191 * @is_off: Initial value of the domain's power_is_off field.
1192 */
1193void pm_genpd_init(struct generic_pm_domain *genpd,
1194 struct dev_power_governor *gov, bool is_off)
1195{
1196 if (IS_ERR_OR_NULL(genpd))
1197 return;
1198
1199 INIT_LIST_HEAD(&genpd->sd_node);
1200 genpd->parent = NULL;
1201 INIT_LIST_HEAD(&genpd->dev_list);
1202 INIT_LIST_HEAD(&genpd->sd_list);
1203 mutex_init(&genpd->lock);
1204 genpd->gov = gov;
1205 INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
1206 genpd->in_progress = 0;
1207 genpd->sd_count = 0;
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001208 genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE;
1209 init_waitqueue_head(&genpd->status_wait_queue);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +02001210 genpd->poweroff_task = NULL;
1211 genpd->resume_count = 0;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001212 genpd->device_count = 0;
1213 genpd->suspended_count = 0;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001214 genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
1215 genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
1216 genpd->domain.ops.runtime_idle = pm_generic_runtime_idle;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001217 genpd->domain.ops.prepare = pm_genpd_prepare;
1218 genpd->domain.ops.suspend = pm_genpd_suspend;
1219 genpd->domain.ops.suspend_noirq = pm_genpd_suspend_noirq;
1220 genpd->domain.ops.resume_noirq = pm_genpd_resume_noirq;
1221 genpd->domain.ops.resume = pm_genpd_resume;
1222 genpd->domain.ops.freeze = pm_genpd_freeze;
1223 genpd->domain.ops.freeze_noirq = pm_genpd_freeze_noirq;
1224 genpd->domain.ops.thaw_noirq = pm_genpd_thaw_noirq;
1225 genpd->domain.ops.thaw = pm_genpd_thaw;
1226 genpd->domain.ops.poweroff = pm_genpd_dev_poweroff;
1227 genpd->domain.ops.poweroff_noirq = pm_genpd_dev_poweroff_noirq;
1228 genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq;
1229 genpd->domain.ops.restore = pm_genpd_restore;
1230 genpd->domain.ops.complete = pm_genpd_complete;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001231}