2011-09-30 04:29:44 +08:00
|
|
|
#include <linux/pm_qos.h>
|
|
|
|
|
2012-08-06 07:44:28 +08:00
|
|
|
static inline void device_pm_init_common(struct device *dev)
|
|
|
|
{
|
2012-08-06 07:45:11 +08:00
|
|
|
if (!dev->power.early_init) {
|
|
|
|
spin_lock_init(&dev->power.lock);
|
|
|
|
dev->power.power_state = PMSG_INVALID;
|
|
|
|
dev->power.early_init = true;
|
|
|
|
}
|
2012-08-06 07:44:28 +08:00
|
|
|
}
|
|
|
|
|
2009-08-19 05:38:32 +08:00
|
|
|
#ifdef CONFIG_PM_RUNTIME
|
|
|
|
|
2012-08-06 07:45:11 +08:00
|
|
|
static inline void pm_runtime_early_init(struct device *dev)
|
|
|
|
{
|
|
|
|
dev->power.disable_depth = 1;
|
|
|
|
device_pm_init_common(dev);
|
|
|
|
}
|
|
|
|
|
2009-08-19 05:38:32 +08:00
|
|
|
extern void pm_runtime_init(struct device *dev);
|
|
|
|
extern void pm_runtime_remove(struct device *dev);
|
|
|
|
|
|
|
|
#else /* !CONFIG_PM_RUNTIME */
|
|
|
|
|
2012-08-06 07:45:11 +08:00
|
|
|
static inline void pm_runtime_early_init(struct device *dev)
|
|
|
|
{
|
|
|
|
device_pm_init_common(dev);
|
|
|
|
}
|
|
|
|
|
2009-08-19 05:38:32 +08:00
|
|
|
static inline void pm_runtime_init(struct device *dev) {}
|
|
|
|
static inline void pm_runtime_remove(struct device *dev) {}
|
|
|
|
|
|
|
|
#endif /* !CONFIG_PM_RUNTIME */
|
2008-08-08 01:06:12 +08:00
|
|
|
|
2007-07-30 05:27:18 +08:00
|
|
|
#ifdef CONFIG_PM_SLEEP
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-01-24 05:25:15 +08:00
|
|
|
/* kernel/power/main.c */
|
|
|
|
extern int pm_async_enabled;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-01-24 05:25:15 +08:00
|
|
|
/* drivers/base/power/main.c */
|
Introduce new top level suspend and hibernation callbacks
Introduce 'struct pm_ops' and 'struct pm_ext_ops' ('ext' meaning
'extended') representing suspend and hibernation operations for bus
types, device classes, device types and device drivers.
Modify the PM core to use 'struct pm_ops' and 'struct pm_ext_ops'
objects, if defined, instead of the ->suspend(), ->resume(),
->suspend_late(), and ->resume_early() callbacks (the old callbacks
will be considered as legacy and gradually phased out).
The main purpose of doing this is to separate suspend (aka S2RAM and
standby) callbacks from hibernation callbacks in such a way that the
new callbacks won't take arguments and the semantics of each of them
will be clearly specified. This has been requested for multiple
times by many people, including Linus himself, and the reason is that
within the current scheme if ->resume() is called, for example, it's
difficult to say why it's been called (ie. is it a resume from RAM or
from hibernation or a suspend/hibernation failure etc.?).
The second purpose is to make the suspend/hibernation callbacks more
flexible so that device drivers can handle more than they can within
the current scheme. For example, some drivers may need to prevent
new children of the device from being registered before their
->suspend() callbacks are executed or they may want to carry out some
operations requiring the availability of some other devices, not
directly bound via the parent-child relationship, in order to prepare
for the execution of ->suspend(), etc.
Ultimately, we'd like to stop using the freezing of tasks for suspend
and therefore the drivers' suspend/hibernation code will have to take
care of the handling of the user space during suspend/hibernation.
That, in turn, would be difficult within the current scheme, without
the new ->prepare() and ->complete() callbacks.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
2008-05-21 05:00:01 +08:00
|
|
|
extern struct list_head dpm_list; /* The active device list */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-11-22 06:55:18 +08:00
|
|
|
static inline struct device *to_device(struct list_head *entry)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2007-09-22 03:36:56 +08:00
|
|
|
return container_of(entry, struct device, power.entry);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2012-08-06 07:44:28 +08:00
|
|
|
extern void device_pm_sleep_init(struct device *dev);
|
2008-08-08 01:06:12 +08:00
|
|
|
extern void device_pm_add(struct device *);
|
2005-04-17 06:20:36 +08:00
|
|
|
extern void device_pm_remove(struct device *);
|
2009-03-04 19:44:00 +08:00
|
|
|
extern void device_pm_move_before(struct device *, struct device *);
|
|
|
|
extern void device_pm_move_after(struct device *, struct device *);
|
|
|
|
extern void device_pm_move_last(struct device *);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-08-19 05:38:32 +08:00
|
|
|
#else /* !CONFIG_PM_SLEEP */
|
|
|
|
|
2012-08-06 07:44:28 +08:00
|
|
|
static inline void device_pm_sleep_init(struct device *dev) {}
|
2009-08-19 05:38:32 +08:00
|
|
|
|
2011-09-30 04:29:44 +08:00
|
|
|
static inline void device_pm_add(struct device *dev)
|
|
|
|
{
|
|
|
|
dev_pm_qos_constraints_init(dev);
|
|
|
|
}
|
|
|
|
|
2009-08-19 05:38:32 +08:00
|
|
|
static inline void device_pm_remove(struct device *dev)
|
|
|
|
{
|
2011-09-30 04:29:44 +08:00
|
|
|
dev_pm_qos_constraints_destroy(dev);
|
2009-08-19 05:38:32 +08:00
|
|
|
pm_runtime_remove(dev);
|
|
|
|
}
|
2007-11-22 06:55:18 +08:00
|
|
|
|
2009-03-04 19:44:00 +08:00
|
|
|
static inline void device_pm_move_before(struct device *deva,
|
|
|
|
struct device *devb) {}
|
|
|
|
static inline void device_pm_move_after(struct device *deva,
|
|
|
|
struct device *devb) {}
|
|
|
|
static inline void device_pm_move_last(struct device *dev) {}
|
2008-01-13 03:40:46 +08:00
|
|
|
|
2009-08-19 05:38:32 +08:00
|
|
|
#endif /* !CONFIG_PM_SLEEP */
|
2007-11-22 06:55:18 +08:00
|
|
|
|
2012-08-06 07:44:28 +08:00
|
|
|
static inline void device_pm_init(struct device *dev)
|
|
|
|
{
|
|
|
|
device_pm_init_common(dev);
|
|
|
|
device_pm_sleep_init(dev);
|
|
|
|
pm_runtime_init(dev);
|
|
|
|
}
|
|
|
|
|
2007-11-22 06:55:18 +08:00
|
|
|
#ifdef CONFIG_PM
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* sysfs.c
|
|
|
|
*/
|
|
|
|
|
2011-02-09 06:26:02 +08:00
|
|
|
extern int dpm_sysfs_add(struct device *dev);
|
|
|
|
extern void dpm_sysfs_remove(struct device *dev);
|
|
|
|
extern void rpm_sysfs_remove(struct device *dev);
|
|
|
|
extern int wakeup_sysfs_add(struct device *dev);
|
|
|
|
extern void wakeup_sysfs_remove(struct device *dev);
|
2012-10-24 08:08:18 +08:00
|
|
|
extern int pm_qos_sysfs_add_latency(struct device *dev);
|
|
|
|
extern void pm_qos_sysfs_remove_latency(struct device *dev);
|
|
|
|
extern int pm_qos_sysfs_add_flags(struct device *dev);
|
|
|
|
extern void pm_qos_sysfs_remove_flags(struct device *dev);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-11-22 06:55:18 +08:00
|
|
|
#else /* CONFIG_PM */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-02-09 06:26:02 +08:00
|
|
|
static inline int dpm_sysfs_add(struct device *dev) { return 0; }
|
|
|
|
static inline void dpm_sysfs_remove(struct device *dev) {}
|
|
|
|
static inline void rpm_sysfs_remove(struct device *dev) {}
|
|
|
|
static inline int wakeup_sysfs_add(struct device *dev) { return 0; }
|
|
|
|
static inline void wakeup_sysfs_remove(struct device *dev) {}
|
PM / QoS: Make it possible to expose PM QoS latency constraints
A runtime suspend of a device (e.g. an MMC controller) belonging to
a power domain or, in a more complicated scenario, a runtime suspend
of another device in the same power domain, may cause power to be
removed from the entire domain. In that case, the amount of time
necessary to runtime-resume the given device (e.g. the MMC
controller) is often substantially greater than the time needed to
run its driver's runtime resume callback. That may hurt performance
in some situations, because user data may need to wait for the
device to become operational, so we should make it possible to
prevent that from happening.
For this reason, introduce a new sysfs attribute for devices,
power/pm_qos_resume_latency_us, allowing user space to specify the
upper bound of the time necessary to bring the (runtime-suspended)
device up after the resume of it has been requested. However, make
that attribute appear only for the devices whose drivers declare
support for it by calling the (new) dev_pm_qos_expose_latency_limit()
helper function with the appropriate initial value of the attribute.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
2012-03-13 08:01:39 +08:00
|
|
|
static inline int pm_qos_sysfs_add(struct device *dev) { return 0; }
|
|
|
|
static inline void pm_qos_sysfs_remove(struct device *dev) {}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
#endif
|