blob: ef25b6f99f99fa7453bb9bbb510bf520987a9c44 [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. Wysocki5125bbf2011-07-13 12:31:52 +020019static LIST_HEAD(gpd_list);
20static DEFINE_MUTEX(gpd_list_lock);
21
Rafael J. Wysocki52480512011-07-01 22:13:10 +020022#ifdef CONFIG_PM
23
24static struct generic_pm_domain *dev_to_genpd(struct device *dev)
25{
26 if (IS_ERR_OR_NULL(dev->pm_domain))
27 return ERR_PTR(-EINVAL);
28
Rafael J. Wysocki596ba342011-07-01 22:13:19 +020029 return pd_to_genpd(dev->pm_domain);
Rafael J. Wysocki52480512011-07-01 22:13:10 +020030}
Rafael J. Wysockif7218892011-07-01 22:12:45 +020031
Rafael J. Wysockic4bb3162011-08-08 23:43:04 +020032static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
Rafael J. Wysockif7218892011-07-01 22:12:45 +020033{
Rafael J. Wysockic4bb3162011-08-08 23:43:04 +020034 bool ret = false;
35
36 if (!WARN_ON(atomic_read(&genpd->sd_count) == 0))
37 ret = !!atomic_dec_and_test(&genpd->sd_count);
38
39 return ret;
40}
41
42static void genpd_sd_counter_inc(struct generic_pm_domain *genpd)
43{
44 atomic_inc(&genpd->sd_count);
45 smp_mb__after_atomic_inc();
Rafael J. Wysockif7218892011-07-01 22:12:45 +020046}
47
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +020048static void genpd_acquire_lock(struct generic_pm_domain *genpd)
49{
50 DEFINE_WAIT(wait);
51
52 mutex_lock(&genpd->lock);
53 /*
54 * Wait for the domain to transition into either the active,
55 * or the power off state.
56 */
57 for (;;) {
58 prepare_to_wait(&genpd->status_wait_queue, &wait,
59 TASK_UNINTERRUPTIBLE);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +020060 if (genpd->status == GPD_STATE_ACTIVE
61 || genpd->status == GPD_STATE_POWER_OFF)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +020062 break;
63 mutex_unlock(&genpd->lock);
64
65 schedule();
66
67 mutex_lock(&genpd->lock);
68 }
69 finish_wait(&genpd->status_wait_queue, &wait);
70}
71
72static void genpd_release_lock(struct generic_pm_domain *genpd)
73{
74 mutex_unlock(&genpd->lock);
75}
76
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +020077static void genpd_set_active(struct generic_pm_domain *genpd)
78{
79 if (genpd->resume_count == 0)
80 genpd->status = GPD_STATE_ACTIVE;
81}
82
Rafael J. Wysockif7218892011-07-01 22:12:45 +020083/**
Rafael J. Wysocki52480512011-07-01 22:13:10 +020084 * pm_genpd_poweron - Restore power to a given PM domain and its parents.
85 * @genpd: PM domain to power up.
86 *
87 * Restore power to @genpd and all of its parents so that it is possible to
88 * resume a device belonging to it.
89 */
Magnus Damm18b4f3f2011-07-10 10:39:14 +020090int pm_genpd_poweron(struct generic_pm_domain *genpd)
Rafael J. Wysocki52480512011-07-01 22:13:10 +020091{
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +020092 struct generic_pm_domain *parent = genpd->parent;
Rafael J. Wysocki52480512011-07-01 22:13:10 +020093 int ret = 0;
94
95 start:
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +020096 mutex_lock(&genpd->lock);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +020097
98 if (genpd->status == GPD_STATE_ACTIVE
Rafael J. Wysocki596ba342011-07-01 22:13:19 +020099 || (genpd->prepared_count > 0 && genpd->suspend_power_off))
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200100 goto out;
101
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200102 if (genpd->status != GPD_STATE_POWER_OFF) {
103 genpd_set_active(genpd);
104 goto out;
105 }
106
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200107 if (parent) {
108 genpd_sd_counter_inc(parent);
109
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200110 mutex_unlock(&genpd->lock);
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200111
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200112 ret = pm_genpd_poweron(parent);
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200113 if (ret) {
114 genpd_sd_counter_dec(parent);
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200115 return ret;
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200116 }
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200117
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200118 parent = NULL;
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200119 goto start;
120 }
121
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200122 if (genpd->power_on)
Rafael J. Wysockife202fd2011-08-05 21:45:11 +0200123 ret = genpd->power_on(genpd);
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200124
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200125 if (ret) {
126 if (genpd->parent)
127 genpd_sd_counter_dec(genpd->parent);
128 } else {
129 genpd_set_active(genpd);
130 }
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200131
132 out:
133 mutex_unlock(&genpd->lock);
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200134
135 return ret;
136}
137
138#endif /* CONFIG_PM */
139
140#ifdef CONFIG_PM_RUNTIME
141
142/**
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200143 * __pm_genpd_save_device - Save the pre-suspend state of a device.
144 * @dle: Device list entry of the device to save the state of.
145 * @genpd: PM domain the device belongs to.
146 */
147static int __pm_genpd_save_device(struct dev_list_entry *dle,
148 struct generic_pm_domain *genpd)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200149 __releases(&genpd->lock) __acquires(&genpd->lock)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200150{
151 struct device *dev = dle->dev;
152 struct device_driver *drv = dev->driver;
153 int ret = 0;
154
155 if (dle->need_restore)
156 return 0;
157
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200158 mutex_unlock(&genpd->lock);
159
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200160 if (drv && drv->pm && drv->pm->runtime_suspend) {
161 if (genpd->start_device)
162 genpd->start_device(dev);
163
164 ret = drv->pm->runtime_suspend(dev);
165
166 if (genpd->stop_device)
167 genpd->stop_device(dev);
168 }
169
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200170 mutex_lock(&genpd->lock);
171
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200172 if (!ret)
173 dle->need_restore = true;
174
175 return ret;
176}
177
178/**
179 * __pm_genpd_restore_device - Restore the pre-suspend state of a device.
180 * @dle: Device list entry of the device to restore the state of.
181 * @genpd: PM domain the device belongs to.
182 */
183static void __pm_genpd_restore_device(struct dev_list_entry *dle,
184 struct generic_pm_domain *genpd)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200185 __releases(&genpd->lock) __acquires(&genpd->lock)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200186{
187 struct device *dev = dle->dev;
188 struct device_driver *drv = dev->driver;
189
190 if (!dle->need_restore)
191 return;
192
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200193 mutex_unlock(&genpd->lock);
194
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200195 if (drv && drv->pm && drv->pm->runtime_resume) {
196 if (genpd->start_device)
197 genpd->start_device(dev);
198
199 drv->pm->runtime_resume(dev);
200
201 if (genpd->stop_device)
202 genpd->stop_device(dev);
203 }
204
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200205 mutex_lock(&genpd->lock);
206
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200207 dle->need_restore = false;
208}
209
210/**
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200211 * genpd_abort_poweroff - Check if a PM domain power off should be aborted.
212 * @genpd: PM domain to check.
213 *
214 * Return true if a PM domain's status changed to GPD_STATE_ACTIVE during
215 * a "power off" operation, which means that a "power on" has occured in the
216 * meantime, or if its resume_count field is different from zero, which means
217 * that one of its devices has been resumed in the meantime.
218 */
219static bool genpd_abort_poweroff(struct generic_pm_domain *genpd)
220{
221 return genpd->status == GPD_STATE_ACTIVE || genpd->resume_count > 0;
222}
223
224/**
Rafael J. Wysocki56375fd2011-07-12 00:40:03 +0200225 * genpd_queue_power_off_work - Queue up the execution of pm_genpd_poweroff().
226 * @genpd: PM domait to power off.
227 *
228 * Queue up the execution of pm_genpd_poweroff() unless it's already been done
229 * before.
230 */
Rafael J. Wysocki0bc5b2d2011-07-14 20:59:07 +0200231void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
Rafael J. Wysocki56375fd2011-07-12 00:40:03 +0200232{
233 if (!work_pending(&genpd->power_off_work))
234 queue_work(pm_wq, &genpd->power_off_work);
235}
236
237/**
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200238 * pm_genpd_poweroff - Remove power from a given PM domain.
239 * @genpd: PM domain to power down.
240 *
241 * If all of the @genpd's devices have been suspended and all of its subdomains
242 * have been powered down, run the runtime suspend callbacks provided by all of
243 * the @genpd's devices' drivers and remove power from @genpd.
244 */
245static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200246 __releases(&genpd->lock) __acquires(&genpd->lock)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200247{
248 struct generic_pm_domain *parent;
249 struct dev_list_entry *dle;
250 unsigned int not_suspended;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200251 int ret = 0;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200252
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200253 start:
254 /*
255 * Do not try to power off the domain in the following situations:
256 * (1) The domain is already in the "power off" state.
257 * (2) System suspend is in progress.
258 * (3) One of the domain's devices is being resumed right now.
259 */
260 if (genpd->status == GPD_STATE_POWER_OFF || genpd->prepared_count > 0
261 || genpd->resume_count > 0)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200262 return 0;
263
Rafael J. Wysockic4bb3162011-08-08 23:43:04 +0200264 if (atomic_read(&genpd->sd_count) > 0)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200265 return -EBUSY;
266
267 not_suspended = 0;
268 list_for_each_entry(dle, &genpd->dev_list, node)
269 if (dle->dev->driver && !pm_runtime_suspended(dle->dev))
270 not_suspended++;
271
272 if (not_suspended > genpd->in_progress)
273 return -EBUSY;
274
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200275 if (genpd->poweroff_task) {
276 /*
277 * Another instance of pm_genpd_poweroff() is executing
278 * callbacks, so tell it to start over and return.
279 */
280 genpd->status = GPD_STATE_REPEAT;
281 return 0;
282 }
283
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200284 if (genpd->gov && genpd->gov->power_down_ok) {
285 if (!genpd->gov->power_down_ok(&genpd->domain))
286 return -EAGAIN;
287 }
288
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200289 genpd->status = GPD_STATE_BUSY;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200290 genpd->poweroff_task = current;
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200291
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200292 list_for_each_entry_reverse(dle, &genpd->dev_list, node) {
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200293 ret = atomic_read(&genpd->sd_count) == 0 ?
294 __pm_genpd_save_device(dle, genpd) : -EBUSY;
Rafael J. Wysocki697a7f32011-07-12 00:39:48 +0200295 if (ret) {
296 genpd_set_active(genpd);
297 goto out;
298 }
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200299
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200300 if (genpd_abort_poweroff(genpd))
301 goto out;
302
303 if (genpd->status == GPD_STATE_REPEAT) {
304 genpd->poweroff_task = NULL;
305 goto start;
306 }
307 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200308
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200309 if (genpd->power_off) {
310 if (atomic_read(&genpd->sd_count) > 0) {
311 ret = -EBUSY;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200312 goto out;
313 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200314
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200315 /*
316 * If sd_count > 0 at this point, one of the children hasn't
317 * managed to call pm_genpd_poweron() for the parent yet after
318 * incrementing it. In that case pm_genpd_poweron() will wait
319 * for us to drop the lock, so we can call .power_off() and let
320 * the pm_genpd_poweron() restore power for us (this shouldn't
321 * happen very often).
322 */
Rafael J. Wysockid2805402011-07-14 20:59:20 +0200323 ret = genpd->power_off(genpd);
324 if (ret == -EBUSY) {
325 genpd_set_active(genpd);
Rafael J. Wysockid2805402011-07-14 20:59:20 +0200326 goto out;
327 }
328 }
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200329
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200330 genpd->status = GPD_STATE_POWER_OFF;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200331
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200332 parent = genpd->parent;
333 if (parent && genpd_sd_counter_dec(parent))
334 genpd_queue_power_off_work(parent);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200335
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200336 out:
337 genpd->poweroff_task = NULL;
338 wake_up_all(&genpd->status_wait_queue);
339 return ret;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200340}
341
342/**
343 * genpd_power_off_work_fn - Power off PM domain whose subdomain count is 0.
344 * @work: Work structure used for scheduling the execution of this function.
345 */
346static void genpd_power_off_work_fn(struct work_struct *work)
347{
348 struct generic_pm_domain *genpd;
349
350 genpd = container_of(work, struct generic_pm_domain, power_off_work);
351
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200352 genpd_acquire_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200353 pm_genpd_poweroff(genpd);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200354 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200355}
356
357/**
358 * pm_genpd_runtime_suspend - Suspend a device belonging to I/O PM domain.
359 * @dev: Device to suspend.
360 *
361 * Carry out a runtime suspend of a device under the assumption that its
362 * pm_domain field points to the domain member of an object of type
363 * struct generic_pm_domain representing a PM domain consisting of I/O devices.
364 */
365static int pm_genpd_runtime_suspend(struct device *dev)
366{
367 struct generic_pm_domain *genpd;
368
369 dev_dbg(dev, "%s()\n", __func__);
370
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200371 genpd = dev_to_genpd(dev);
372 if (IS_ERR(genpd))
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200373 return -EINVAL;
374
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200375 if (genpd->stop_device) {
376 int ret = genpd->stop_device(dev);
377 if (ret)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200378 return ret;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200379 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200380
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200381 mutex_lock(&genpd->lock);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200382 genpd->in_progress++;
383 pm_genpd_poweroff(genpd);
384 genpd->in_progress--;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200385 mutex_unlock(&genpd->lock);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200386
387 return 0;
388}
389
390/**
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200391 * __pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
392 * @dev: Device to resume.
393 * @genpd: PM domain the device belongs to.
394 */
395static void __pm_genpd_runtime_resume(struct device *dev,
396 struct generic_pm_domain *genpd)
397{
398 struct dev_list_entry *dle;
399
400 list_for_each_entry(dle, &genpd->dev_list, node) {
401 if (dle->dev == dev) {
402 __pm_genpd_restore_device(dle, genpd);
403 break;
404 }
405 }
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200406}
407
408/**
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200409 * pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
410 * @dev: Device to resume.
411 *
412 * Carry out a runtime resume of a device under the assumption that its
413 * pm_domain field points to the domain member of an object of type
414 * struct generic_pm_domain representing a PM domain consisting of I/O devices.
415 */
416static int pm_genpd_runtime_resume(struct device *dev)
417{
418 struct generic_pm_domain *genpd;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200419 DEFINE_WAIT(wait);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200420 int ret;
421
422 dev_dbg(dev, "%s()\n", __func__);
423
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200424 genpd = dev_to_genpd(dev);
425 if (IS_ERR(genpd))
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200426 return -EINVAL;
427
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200428 ret = pm_genpd_poweron(genpd);
429 if (ret)
430 return ret;
431
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200432 mutex_lock(&genpd->lock);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200433 genpd->status = GPD_STATE_BUSY;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200434 genpd->resume_count++;
435 for (;;) {
436 prepare_to_wait(&genpd->status_wait_queue, &wait,
437 TASK_UNINTERRUPTIBLE);
438 /*
439 * If current is the powering off task, we have been called
440 * reentrantly from one of the device callbacks, so we should
441 * not wait.
442 */
443 if (!genpd->poweroff_task || genpd->poweroff_task == current)
444 break;
445 mutex_unlock(&genpd->lock);
446
447 schedule();
448
449 mutex_lock(&genpd->lock);
450 }
451 finish_wait(&genpd->status_wait_queue, &wait);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200452 __pm_genpd_runtime_resume(dev, genpd);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200453 genpd->resume_count--;
454 genpd_set_active(genpd);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200455 wake_up_all(&genpd->status_wait_queue);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200456 mutex_unlock(&genpd->lock);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200457
458 if (genpd->start_device)
459 genpd->start_device(dev);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200460
461 return 0;
462}
463
Rafael J. Wysocki17f2ae72011-08-14 13:34:31 +0200464/**
465 * pm_genpd_poweroff_unused - Power off all PM domains with no devices in use.
466 */
467void pm_genpd_poweroff_unused(void)
468{
469 struct generic_pm_domain *genpd;
470
471 mutex_lock(&gpd_list_lock);
472
473 list_for_each_entry(genpd, &gpd_list, gpd_list_node)
474 genpd_queue_power_off_work(genpd);
475
476 mutex_unlock(&gpd_list_lock);
477}
478
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200479#else
480
481static inline void genpd_power_off_work_fn(struct work_struct *work) {}
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200482static inline void __pm_genpd_runtime_resume(struct device *dev,
483 struct generic_pm_domain *genpd) {}
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200484
485#define pm_genpd_runtime_suspend NULL
486#define pm_genpd_runtime_resume NULL
487
488#endif /* CONFIG_PM_RUNTIME */
489
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200490#ifdef CONFIG_PM_SLEEP
491
492/**
493 * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its parents.
494 * @genpd: PM domain to power off, if possible.
495 *
496 * Check if the given PM domain can be powered off (during system suspend or
497 * hibernation) and do that if so. Also, in that case propagate to its parent.
498 *
499 * This function is only called in "noirq" stages of system power transitions,
500 * so it need not acquire locks (all of the "noirq" callbacks are executed
501 * sequentially, so it is guaranteed that it will never run twice in parallel).
502 */
503static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
504{
505 struct generic_pm_domain *parent = genpd->parent;
506
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200507 if (genpd->status == GPD_STATE_POWER_OFF)
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200508 return;
509
Rafael J. Wysockic4bb3162011-08-08 23:43:04 +0200510 if (genpd->suspended_count != genpd->device_count
511 || atomic_read(&genpd->sd_count) > 0)
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200512 return;
513
514 if (genpd->power_off)
515 genpd->power_off(genpd);
516
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200517 genpd->status = GPD_STATE_POWER_OFF;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200518 if (parent) {
519 genpd_sd_counter_dec(parent);
520 pm_genpd_sync_poweroff(parent);
521 }
522}
523
524/**
Rafael J. Wysocki4ecd6e62011-07-12 00:39:57 +0200525 * resume_needed - Check whether to resume a device before system suspend.
526 * @dev: Device to check.
527 * @genpd: PM domain the device belongs to.
528 *
529 * There are two cases in which a device that can wake up the system from sleep
530 * states should be resumed by pm_genpd_prepare(): (1) if the device is enabled
531 * to wake up the system and it has to remain active for this purpose while the
532 * system is in the sleep state and (2) if the device is not enabled to wake up
533 * the system from sleep states and it generally doesn't generate wakeup signals
534 * by itself (those signals are generated on its behalf by other parts of the
535 * system). In the latter case it may be necessary to reconfigure the device's
536 * wakeup settings during system suspend, because it may have been set up to
537 * signal remote wakeup from the system's working state as needed by runtime PM.
538 * Return 'true' in either of the above cases.
539 */
540static bool resume_needed(struct device *dev, struct generic_pm_domain *genpd)
541{
542 bool active_wakeup;
543
544 if (!device_can_wakeup(dev))
545 return false;
546
547 active_wakeup = genpd->active_wakeup && genpd->active_wakeup(dev);
548 return device_may_wakeup(dev) ? active_wakeup : !active_wakeup;
549}
550
551/**
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200552 * pm_genpd_prepare - Start power transition of a device in a PM domain.
553 * @dev: Device to start the transition of.
554 *
555 * Start a power transition of a device (during a system-wide power transition)
556 * under the assumption that its pm_domain field points to the domain member of
557 * an object of type struct generic_pm_domain representing a PM domain
558 * consisting of I/O devices.
559 */
560static int pm_genpd_prepare(struct device *dev)
561{
562 struct generic_pm_domain *genpd;
Rafael J. Wysockib6c10c82011-07-12 00:39:21 +0200563 int ret;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200564
565 dev_dbg(dev, "%s()\n", __func__);
566
567 genpd = dev_to_genpd(dev);
568 if (IS_ERR(genpd))
569 return -EINVAL;
570
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200571 /*
572 * If a wakeup request is pending for the device, it should be woken up
573 * at this point and a system wakeup event should be reported if it's
574 * set up to wake up the system from sleep states.
575 */
576 pm_runtime_get_noresume(dev);
577 if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
578 pm_wakeup_event(dev, 0);
579
580 if (pm_wakeup_pending()) {
581 pm_runtime_put_sync(dev);
582 return -EBUSY;
583 }
584
Rafael J. Wysocki4ecd6e62011-07-12 00:39:57 +0200585 if (resume_needed(dev, genpd))
586 pm_runtime_resume(dev);
587
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200588 genpd_acquire_lock(genpd);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200589
590 if (genpd->prepared_count++ == 0)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200591 genpd->suspend_power_off = genpd->status == GPD_STATE_POWER_OFF;
592
593 genpd_release_lock(genpd);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200594
595 if (genpd->suspend_power_off) {
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200596 pm_runtime_put_noidle(dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200597 return 0;
598 }
599
600 /*
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200601 * The PM domain must be in the GPD_STATE_ACTIVE state at this point,
602 * so pm_genpd_poweron() will return immediately, but if the device
603 * is suspended (e.g. it's been stopped by .stop_device()), we need
604 * to make it operational.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200605 */
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200606 pm_runtime_resume(dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200607 __pm_runtime_disable(dev, false);
608
Rafael J. Wysockib6c10c82011-07-12 00:39:21 +0200609 ret = pm_generic_prepare(dev);
610 if (ret) {
611 mutex_lock(&genpd->lock);
612
613 if (--genpd->prepared_count == 0)
614 genpd->suspend_power_off = false;
615
616 mutex_unlock(&genpd->lock);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200617 pm_runtime_enable(dev);
Rafael J. Wysockib6c10c82011-07-12 00:39:21 +0200618 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200619
620 pm_runtime_put_sync(dev);
Rafael J. Wysockib6c10c82011-07-12 00:39:21 +0200621 return ret;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200622}
623
624/**
625 * pm_genpd_suspend - Suspend a device belonging to an I/O PM domain.
626 * @dev: Device to suspend.
627 *
628 * Suspend a device under the assumption that its pm_domain field points to the
629 * domain member of an object of type struct generic_pm_domain representing
630 * a PM domain consisting of I/O devices.
631 */
632static int pm_genpd_suspend(struct device *dev)
633{
634 struct generic_pm_domain *genpd;
635
636 dev_dbg(dev, "%s()\n", __func__);
637
638 genpd = dev_to_genpd(dev);
639 if (IS_ERR(genpd))
640 return -EINVAL;
641
642 return genpd->suspend_power_off ? 0 : pm_generic_suspend(dev);
643}
644
645/**
646 * pm_genpd_suspend_noirq - Late suspend of a device from an I/O PM domain.
647 * @dev: Device to suspend.
648 *
649 * Carry out a late suspend of a device under the assumption that its
650 * pm_domain field points to the domain member of an object of type
651 * struct generic_pm_domain representing a PM domain consisting of I/O devices.
652 */
653static int pm_genpd_suspend_noirq(struct device *dev)
654{
655 struct generic_pm_domain *genpd;
656 int ret;
657
658 dev_dbg(dev, "%s()\n", __func__);
659
660 genpd = dev_to_genpd(dev);
661 if (IS_ERR(genpd))
662 return -EINVAL;
663
664 if (genpd->suspend_power_off)
665 return 0;
666
667 ret = pm_generic_suspend_noirq(dev);
668 if (ret)
669 return ret;
670
Rafael J. Wysockid4f2d872011-07-01 22:13:29 +0200671 if (device_may_wakeup(dev)
672 && genpd->active_wakeup && genpd->active_wakeup(dev))
673 return 0;
674
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200675 if (genpd->stop_device)
676 genpd->stop_device(dev);
677
678 /*
679 * Since all of the "noirq" callbacks are executed sequentially, it is
680 * guaranteed that this function will never run twice in parallel for
681 * the same PM domain, so it is not necessary to use locking here.
682 */
683 genpd->suspended_count++;
684 pm_genpd_sync_poweroff(genpd);
685
686 return 0;
687}
688
689/**
690 * pm_genpd_resume_noirq - Early resume of a device from an I/O power domain.
691 * @dev: Device to resume.
692 *
693 * Carry out an early resume of a device under the assumption that its
694 * pm_domain field points to the domain member of an object of type
695 * struct generic_pm_domain representing a power domain consisting of I/O
696 * devices.
697 */
698static int pm_genpd_resume_noirq(struct device *dev)
699{
700 struct generic_pm_domain *genpd;
701
702 dev_dbg(dev, "%s()\n", __func__);
703
704 genpd = dev_to_genpd(dev);
705 if (IS_ERR(genpd))
706 return -EINVAL;
707
708 if (genpd->suspend_power_off)
709 return 0;
710
711 /*
712 * Since all of the "noirq" callbacks are executed sequentially, it is
713 * guaranteed that this function will never run twice in parallel for
714 * the same PM domain, so it is not necessary to use locking here.
715 */
716 pm_genpd_poweron(genpd);
717 genpd->suspended_count--;
718 if (genpd->start_device)
719 genpd->start_device(dev);
720
721 return pm_generic_resume_noirq(dev);
722}
723
724/**
725 * pm_genpd_resume - Resume a device belonging to an I/O power domain.
726 * @dev: Device to resume.
727 *
728 * Resume a device under the assumption that its pm_domain field points to the
729 * domain member of an object of type struct generic_pm_domain representing
730 * a power domain consisting of I/O devices.
731 */
732static int pm_genpd_resume(struct device *dev)
733{
734 struct generic_pm_domain *genpd;
735
736 dev_dbg(dev, "%s()\n", __func__);
737
738 genpd = dev_to_genpd(dev);
739 if (IS_ERR(genpd))
740 return -EINVAL;
741
742 return genpd->suspend_power_off ? 0 : pm_generic_resume(dev);
743}
744
745/**
746 * pm_genpd_freeze - Freeze a device belonging to an I/O power domain.
747 * @dev: Device to freeze.
748 *
749 * Freeze a device under the assumption that its pm_domain field points to the
750 * domain member of an object of type struct generic_pm_domain representing
751 * a power domain consisting of I/O devices.
752 */
753static int pm_genpd_freeze(struct device *dev)
754{
755 struct generic_pm_domain *genpd;
756
757 dev_dbg(dev, "%s()\n", __func__);
758
759 genpd = dev_to_genpd(dev);
760 if (IS_ERR(genpd))
761 return -EINVAL;
762
763 return genpd->suspend_power_off ? 0 : pm_generic_freeze(dev);
764}
765
766/**
767 * pm_genpd_freeze_noirq - Late freeze of a device from an I/O power domain.
768 * @dev: Device to freeze.
769 *
770 * Carry out a late freeze of a device under the assumption that its
771 * pm_domain field points to the domain member of an object of type
772 * struct generic_pm_domain representing a power domain consisting of I/O
773 * devices.
774 */
775static int pm_genpd_freeze_noirq(struct device *dev)
776{
777 struct generic_pm_domain *genpd;
778 int ret;
779
780 dev_dbg(dev, "%s()\n", __func__);
781
782 genpd = dev_to_genpd(dev);
783 if (IS_ERR(genpd))
784 return -EINVAL;
785
786 if (genpd->suspend_power_off)
787 return 0;
788
789 ret = pm_generic_freeze_noirq(dev);
790 if (ret)
791 return ret;
792
793 if (genpd->stop_device)
794 genpd->stop_device(dev);
795
796 return 0;
797}
798
799/**
800 * pm_genpd_thaw_noirq - Early thaw of a device from an I/O power domain.
801 * @dev: Device to thaw.
802 *
803 * Carry out an early thaw of a device under the assumption that its
804 * pm_domain field points to the domain member of an object of type
805 * struct generic_pm_domain representing a power domain consisting of I/O
806 * devices.
807 */
808static int pm_genpd_thaw_noirq(struct device *dev)
809{
810 struct generic_pm_domain *genpd;
811
812 dev_dbg(dev, "%s()\n", __func__);
813
814 genpd = dev_to_genpd(dev);
815 if (IS_ERR(genpd))
816 return -EINVAL;
817
818 if (genpd->suspend_power_off)
819 return 0;
820
821 if (genpd->start_device)
822 genpd->start_device(dev);
823
824 return pm_generic_thaw_noirq(dev);
825}
826
827/**
828 * pm_genpd_thaw - Thaw a device belonging to an I/O power domain.
829 * @dev: Device to thaw.
830 *
831 * Thaw a device under the assumption that its pm_domain field points to the
832 * domain member of an object of type struct generic_pm_domain representing
833 * a power domain consisting of I/O devices.
834 */
835static int pm_genpd_thaw(struct device *dev)
836{
837 struct generic_pm_domain *genpd;
838
839 dev_dbg(dev, "%s()\n", __func__);
840
841 genpd = dev_to_genpd(dev);
842 if (IS_ERR(genpd))
843 return -EINVAL;
844
845 return genpd->suspend_power_off ? 0 : pm_generic_thaw(dev);
846}
847
848/**
849 * pm_genpd_dev_poweroff - Power off a device belonging to an I/O PM domain.
850 * @dev: Device to suspend.
851 *
852 * Power off a device under the assumption that its pm_domain field points to
853 * the domain member of an object of type struct generic_pm_domain representing
854 * a PM domain consisting of I/O devices.
855 */
856static int pm_genpd_dev_poweroff(struct device *dev)
857{
858 struct generic_pm_domain *genpd;
859
860 dev_dbg(dev, "%s()\n", __func__);
861
862 genpd = dev_to_genpd(dev);
863 if (IS_ERR(genpd))
864 return -EINVAL;
865
866 return genpd->suspend_power_off ? 0 : pm_generic_poweroff(dev);
867}
868
869/**
870 * pm_genpd_dev_poweroff_noirq - Late power off of a device from a PM domain.
871 * @dev: Device to suspend.
872 *
873 * Carry out a late powering off of a device under the assumption that its
874 * pm_domain field points to the domain member of an object of type
875 * struct generic_pm_domain representing a PM domain consisting of I/O devices.
876 */
877static int pm_genpd_dev_poweroff_noirq(struct device *dev)
878{
879 struct generic_pm_domain *genpd;
880 int ret;
881
882 dev_dbg(dev, "%s()\n", __func__);
883
884 genpd = dev_to_genpd(dev);
885 if (IS_ERR(genpd))
886 return -EINVAL;
887
888 if (genpd->suspend_power_off)
889 return 0;
890
891 ret = pm_generic_poweroff_noirq(dev);
892 if (ret)
893 return ret;
894
Rafael J. Wysockid4f2d872011-07-01 22:13:29 +0200895 if (device_may_wakeup(dev)
896 && genpd->active_wakeup && genpd->active_wakeup(dev))
897 return 0;
898
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200899 if (genpd->stop_device)
900 genpd->stop_device(dev);
901
902 /*
903 * Since all of the "noirq" callbacks are executed sequentially, it is
904 * guaranteed that this function will never run twice in parallel for
905 * the same PM domain, so it is not necessary to use locking here.
906 */
907 genpd->suspended_count++;
908 pm_genpd_sync_poweroff(genpd);
909
910 return 0;
911}
912
913/**
914 * pm_genpd_restore_noirq - Early restore of a device from an I/O power domain.
915 * @dev: Device to resume.
916 *
917 * Carry out an early restore of a device under the assumption that its
918 * pm_domain field points to the domain member of an object of type
919 * struct generic_pm_domain representing a power domain consisting of I/O
920 * devices.
921 */
922static int pm_genpd_restore_noirq(struct device *dev)
923{
924 struct generic_pm_domain *genpd;
925
926 dev_dbg(dev, "%s()\n", __func__);
927
928 genpd = dev_to_genpd(dev);
929 if (IS_ERR(genpd))
930 return -EINVAL;
931
932 /*
933 * Since all of the "noirq" callbacks are executed sequentially, it is
934 * guaranteed that this function will never run twice in parallel for
935 * the same PM domain, so it is not necessary to use locking here.
936 */
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200937 genpd->status = GPD_STATE_POWER_OFF;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200938 if (genpd->suspend_power_off) {
939 /*
940 * The boot kernel might put the domain into the power on state,
941 * so make sure it really is powered off.
942 */
943 if (genpd->power_off)
944 genpd->power_off(genpd);
945 return 0;
946 }
947
948 pm_genpd_poweron(genpd);
949 genpd->suspended_count--;
950 if (genpd->start_device)
951 genpd->start_device(dev);
952
953 return pm_generic_restore_noirq(dev);
954}
955
956/**
957 * pm_genpd_restore - Restore a device belonging to an I/O power domain.
958 * @dev: Device to resume.
959 *
960 * Restore a device under the assumption that its pm_domain field points to the
961 * domain member of an object of type struct generic_pm_domain representing
962 * a power domain consisting of I/O devices.
963 */
964static int pm_genpd_restore(struct device *dev)
965{
966 struct generic_pm_domain *genpd;
967
968 dev_dbg(dev, "%s()\n", __func__);
969
970 genpd = dev_to_genpd(dev);
971 if (IS_ERR(genpd))
972 return -EINVAL;
973
974 return genpd->suspend_power_off ? 0 : pm_generic_restore(dev);
975}
976
977/**
978 * pm_genpd_complete - Complete power transition of a device in a power domain.
979 * @dev: Device to complete the transition of.
980 *
981 * Complete a power transition of a device (during a system-wide power
982 * transition) under the assumption that its pm_domain field points to the
983 * domain member of an object of type struct generic_pm_domain representing
984 * a power domain consisting of I/O devices.
985 */
986static void pm_genpd_complete(struct device *dev)
987{
988 struct generic_pm_domain *genpd;
989 bool run_complete;
990
991 dev_dbg(dev, "%s()\n", __func__);
992
993 genpd = dev_to_genpd(dev);
994 if (IS_ERR(genpd))
995 return;
996
997 mutex_lock(&genpd->lock);
998
999 run_complete = !genpd->suspend_power_off;
1000 if (--genpd->prepared_count == 0)
1001 genpd->suspend_power_off = false;
1002
1003 mutex_unlock(&genpd->lock);
1004
1005 if (run_complete) {
1006 pm_generic_complete(dev);
Rafael J. Wysocki6f00ff72011-07-12 00:39:10 +02001007 pm_runtime_set_active(dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001008 pm_runtime_enable(dev);
Rafael J. Wysocki6f00ff72011-07-12 00:39:10 +02001009 pm_runtime_idle(dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001010 }
1011}
1012
1013#else
1014
1015#define pm_genpd_prepare NULL
1016#define pm_genpd_suspend NULL
1017#define pm_genpd_suspend_noirq NULL
1018#define pm_genpd_resume_noirq NULL
1019#define pm_genpd_resume NULL
1020#define pm_genpd_freeze NULL
1021#define pm_genpd_freeze_noirq NULL
1022#define pm_genpd_thaw_noirq NULL
1023#define pm_genpd_thaw NULL
1024#define pm_genpd_dev_poweroff_noirq NULL
1025#define pm_genpd_dev_poweroff NULL
1026#define pm_genpd_restore_noirq NULL
1027#define pm_genpd_restore NULL
1028#define pm_genpd_complete NULL
1029
1030#endif /* CONFIG_PM_SLEEP */
1031
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001032/**
1033 * pm_genpd_add_device - Add a device to an I/O PM domain.
1034 * @genpd: PM domain to add the device to.
1035 * @dev: Device to be added.
1036 */
1037int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev)
1038{
1039 struct dev_list_entry *dle;
1040 int ret = 0;
1041
1042 dev_dbg(dev, "%s()\n", __func__);
1043
1044 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
1045 return -EINVAL;
1046
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001047 genpd_acquire_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001048
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001049 if (genpd->status == GPD_STATE_POWER_OFF) {
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001050 ret = -EINVAL;
1051 goto out;
1052 }
1053
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001054 if (genpd->prepared_count > 0) {
1055 ret = -EAGAIN;
1056 goto out;
1057 }
1058
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001059 list_for_each_entry(dle, &genpd->dev_list, node)
1060 if (dle->dev == dev) {
1061 ret = -EINVAL;
1062 goto out;
1063 }
1064
1065 dle = kzalloc(sizeof(*dle), GFP_KERNEL);
1066 if (!dle) {
1067 ret = -ENOMEM;
1068 goto out;
1069 }
1070
1071 dle->dev = dev;
1072 dle->need_restore = false;
1073 list_add_tail(&dle->node, &genpd->dev_list);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001074 genpd->device_count++;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001075
1076 spin_lock_irq(&dev->power.lock);
1077 dev->pm_domain = &genpd->domain;
1078 spin_unlock_irq(&dev->power.lock);
1079
1080 out:
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001081 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001082
1083 return ret;
1084}
1085
1086/**
1087 * pm_genpd_remove_device - Remove a device from an I/O PM domain.
1088 * @genpd: PM domain to remove the device from.
1089 * @dev: Device to be removed.
1090 */
1091int pm_genpd_remove_device(struct generic_pm_domain *genpd,
1092 struct device *dev)
1093{
1094 struct dev_list_entry *dle;
1095 int ret = -EINVAL;
1096
1097 dev_dbg(dev, "%s()\n", __func__);
1098
1099 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
1100 return -EINVAL;
1101
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001102 genpd_acquire_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001103
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001104 if (genpd->prepared_count > 0) {
1105 ret = -EAGAIN;
1106 goto out;
1107 }
1108
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001109 list_for_each_entry(dle, &genpd->dev_list, node) {
1110 if (dle->dev != dev)
1111 continue;
1112
1113 spin_lock_irq(&dev->power.lock);
1114 dev->pm_domain = NULL;
1115 spin_unlock_irq(&dev->power.lock);
1116
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001117 genpd->device_count--;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001118 list_del(&dle->node);
1119 kfree(dle);
1120
1121 ret = 0;
1122 break;
1123 }
1124
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001125 out:
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001126 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001127
1128 return ret;
1129}
1130
1131/**
1132 * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
1133 * @genpd: Master PM domain to add the subdomain to.
1134 * @new_subdomain: Subdomain to be added.
1135 */
1136int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
1137 struct generic_pm_domain *new_subdomain)
1138{
1139 struct generic_pm_domain *subdomain;
1140 int ret = 0;
1141
1142 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(new_subdomain))
1143 return -EINVAL;
1144
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001145 start:
1146 genpd_acquire_lock(genpd);
1147 mutex_lock_nested(&new_subdomain->lock, SINGLE_DEPTH_NESTING);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001148
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001149 if (new_subdomain->status != GPD_STATE_POWER_OFF
1150 && new_subdomain->status != GPD_STATE_ACTIVE) {
1151 mutex_unlock(&new_subdomain->lock);
1152 genpd_release_lock(genpd);
1153 goto start;
1154 }
1155
1156 if (genpd->status == GPD_STATE_POWER_OFF
1157 && new_subdomain->status != GPD_STATE_POWER_OFF) {
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001158 ret = -EINVAL;
1159 goto out;
1160 }
1161
1162 list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
1163 if (subdomain == new_subdomain) {
1164 ret = -EINVAL;
1165 goto out;
1166 }
1167 }
1168
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001169 list_add_tail(&new_subdomain->sd_node, &genpd->sd_list);
1170 new_subdomain->parent = genpd;
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001171 if (subdomain->status != GPD_STATE_POWER_OFF)
Rafael J. Wysockic4bb3162011-08-08 23:43:04 +02001172 genpd_sd_counter_inc(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001173
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001174 out:
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001175 mutex_unlock(&new_subdomain->lock);
1176 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001177
1178 return ret;
1179}
1180
1181/**
1182 * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
1183 * @genpd: Master PM domain to remove the subdomain from.
1184 * @target: Subdomain to be removed.
1185 */
1186int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
1187 struct generic_pm_domain *target)
1188{
1189 struct generic_pm_domain *subdomain;
1190 int ret = -EINVAL;
1191
1192 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(target))
1193 return -EINVAL;
1194
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001195 start:
1196 genpd_acquire_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001197
1198 list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
1199 if (subdomain != target)
1200 continue;
1201
1202 mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
1203
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001204 if (subdomain->status != GPD_STATE_POWER_OFF
1205 && subdomain->status != GPD_STATE_ACTIVE) {
1206 mutex_unlock(&subdomain->lock);
1207 genpd_release_lock(genpd);
1208 goto start;
1209 }
1210
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001211 list_del(&subdomain->sd_node);
1212 subdomain->parent = NULL;
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001213 if (subdomain->status != GPD_STATE_POWER_OFF)
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001214 genpd_sd_counter_dec(genpd);
1215
1216 mutex_unlock(&subdomain->lock);
1217
1218 ret = 0;
1219 break;
1220 }
1221
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001222 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001223
1224 return ret;
1225}
1226
1227/**
1228 * pm_genpd_init - Initialize a generic I/O PM domain object.
1229 * @genpd: PM domain object to initialize.
1230 * @gov: PM domain governor to associate with the domain (may be NULL).
1231 * @is_off: Initial value of the domain's power_is_off field.
1232 */
1233void pm_genpd_init(struct generic_pm_domain *genpd,
1234 struct dev_power_governor *gov, bool is_off)
1235{
1236 if (IS_ERR_OR_NULL(genpd))
1237 return;
1238
1239 INIT_LIST_HEAD(&genpd->sd_node);
1240 genpd->parent = NULL;
1241 INIT_LIST_HEAD(&genpd->dev_list);
1242 INIT_LIST_HEAD(&genpd->sd_list);
1243 mutex_init(&genpd->lock);
1244 genpd->gov = gov;
1245 INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
1246 genpd->in_progress = 0;
Rafael J. Wysockic4bb3162011-08-08 23:43:04 +02001247 atomic_set(&genpd->sd_count, 0);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001248 genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE;
1249 init_waitqueue_head(&genpd->status_wait_queue);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +02001250 genpd->poweroff_task = NULL;
1251 genpd->resume_count = 0;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001252 genpd->device_count = 0;
1253 genpd->suspended_count = 0;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001254 genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
1255 genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
1256 genpd->domain.ops.runtime_idle = pm_generic_runtime_idle;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001257 genpd->domain.ops.prepare = pm_genpd_prepare;
1258 genpd->domain.ops.suspend = pm_genpd_suspend;
1259 genpd->domain.ops.suspend_noirq = pm_genpd_suspend_noirq;
1260 genpd->domain.ops.resume_noirq = pm_genpd_resume_noirq;
1261 genpd->domain.ops.resume = pm_genpd_resume;
1262 genpd->domain.ops.freeze = pm_genpd_freeze;
1263 genpd->domain.ops.freeze_noirq = pm_genpd_freeze_noirq;
1264 genpd->domain.ops.thaw_noirq = pm_genpd_thaw_noirq;
1265 genpd->domain.ops.thaw = pm_genpd_thaw;
1266 genpd->domain.ops.poweroff = pm_genpd_dev_poweroff;
1267 genpd->domain.ops.poweroff_noirq = pm_genpd_dev_poweroff_noirq;
1268 genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq;
1269 genpd->domain.ops.restore = pm_genpd_restore;
1270 genpd->domain.ops.complete = pm_genpd_complete;
Rafael J. Wysocki5125bbf2011-07-13 12:31:52 +02001271 mutex_lock(&gpd_list_lock);
1272 list_add(&genpd->gpd_list_node, &gpd_list);
1273 mutex_unlock(&gpd_list_lock);
1274}