2011-09-30 03:29:44 +07:00
|
|
|
#include <linux/pm_qos.h>
|
|
|
|
|
2012-08-06 06:44:28 +07:00
|
|
|
static inline void device_pm_init_common(struct device *dev)
|
|
|
|
{
|
2012-08-06 06:45:11 +07:00
|
|
|
if (!dev->power.early_init) {
|
|
|
|
spin_lock_init(&dev->power.lock);
|
2013-03-04 20:22:57 +07:00
|
|
|
dev->power.qos = NULL;
|
2012-08-06 06:45:11 +07:00
|
|
|
dev->power.early_init = true;
|
|
|
|
}
|
2012-08-06 06:44:28 +07:00
|
|
|
}
|
|
|
|
|
2014-11-28 04:38:05 +07:00
|
|
|
#ifdef CONFIG_PM
|
2009-08-19 04:38:32 +07:00
|
|
|
|
2012-08-06 06:45:11 +07:00
|
|
|
static inline void pm_runtime_early_init(struct device *dev)
|
|
|
|
{
|
|
|
|
dev->power.disable_depth = 1;
|
|
|
|
device_pm_init_common(dev);
|
|
|
|
}
|
|
|
|
|
2009-08-19 04:38:32 +07:00
|
|
|
extern void pm_runtime_init(struct device *dev);
|
PM / runtime: Re-init runtime PM states at probe error and driver unbind
There are two common expectations among several subsystems/drivers that
deploys runtime PM support, but which isn't met by the driver core.
Expectation 1)
At ->probe() the subsystem/driver expects the runtime PM status of the
device to be RPM_SUSPENDED, which is the initial status being assigned at
device registration.
This expectation is especially common among some of those subsystems/
drivers that manages devices with an attached PM domain, as those requires
the ->runtime_resume() callback at the PM domain level to be invoked
during ->probe().
Moreover these subsystems/drivers entirely relies on runtime PM resources
being managed at the PM domain level, thus don't implement their own set
of runtime PM callbacks.
These are two scenarios that suffers from this unmet expectation.
i) A failed ->probe() sequence requests probe deferral:
->probe()
...
pm_runtime_enable()
pm_runtime_get_sync()
...
err:
pm_runtime_put()
pm_runtime_disable()
...
As there are no guarantees that such sequence turns the runtime PM status
of the device into RPM_SUSPENDED, the re-trying ->probe() may start with
the status in RPM_ACTIVE.
In such case the runtime PM core won't invoke the ->runtime_resume()
callback because of a pm_runtime_get_sync(), as it considers the device to
be already runtime resumed.
ii) A driver re-bind sequence:
At driver unbind, the subsystem/driver's >remove() callback invokes a
sequence of runtime PM APIs, to undo actions during ->probe() and to put
the device into low power state.
->remove()
...
pm_runtime_put()
pm_runtime_disable()
...
Similar as in the failing ->probe() case, this sequence don't guarantee
the runtime PM status of the device to turn into RPM_SUSPENDED.
Trying to re-bind the driver thus causes the same issue as when re-trying
->probe(), in the probe deferral scenario.
Expectation 2)
Drivers that invokes the pm_runtime_irq_safe() API during ->probe(),
triggers the runtime PM core to increase the usage count for the device's
parent and permanently make it runtime resumed.
The usage count is only dropped at device removal, which also allows it to
be runtime suspended again.
A re-trying ->probe() repeats the call to pm_runtime_irq_safe() and thus
once more triggers the usage count of the device's parent to be increased.
This leads to not only an imbalance issue of the usage count of the
device's parent, but also to keep it runtime resumed permanently even if
->probe() fails.
To address these issues, let's change the policy of the driver core to
meet these expectations. More precisely, at ->probe() failures and driver
unbind, restore the initial states of runtime PM.
Although to still allow subsystem's to control PM for devices that doesn't
->probe() successfully, don't restore the initial states unless runtime PM
is disabled.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Kevin Hilman <khilman@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-11-18 17:48:39 +07:00
|
|
|
extern void pm_runtime_reinit(struct device *dev);
|
2009-08-19 04:38:32 +07:00
|
|
|
extern void pm_runtime_remove(struct device *dev);
|
|
|
|
|
PM / Wakeirq: Add automated device wake IRQ handling
Turns out we can automate the handling for the device_may_wakeup()
quite a bit by using the kernel wakeup source list as suggested
by Rafael J. Wysocki <rjw@rjwysocki.net>.
And as some hardware has separate dedicated wake-up interrupt
in addition to the IO interrupt, we can automate the handling by
adding a generic threaded interrupt handler that just calls the
device PM runtime to wake up the device.
This allows dropping code from device drivers as we currently
are doing it in multiple ways, and often wrong.
For most drivers, we should be able to drop the following
boilerplate code from runtime_suspend and runtime_resume
functions:
...
device_init_wakeup(dev, true);
...
if (device_may_wakeup(dev))
enable_irq_wake(irq);
...
if (device_may_wakeup(dev))
disable_irq_wake(irq);
...
device_init_wakeup(dev, false);
...
We can replace it with just the following init and exit
time code:
...
device_init_wakeup(dev, true);
dev_pm_set_wake_irq(dev, irq);
...
dev_pm_clear_wake_irq(dev);
device_init_wakeup(dev, false);
...
And for hardware with dedicated wake-up interrupts:
...
device_init_wakeup(dev, true);
dev_pm_set_dedicated_wake_irq(dev, irq);
...
dev_pm_clear_wake_irq(dev);
device_init_wakeup(dev, false);
...
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-05-19 05:40:29 +07:00
|
|
|
struct wake_irq {
|
|
|
|
struct device *dev;
|
|
|
|
int irq;
|
|
|
|
bool dedicated_irq:1;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern void dev_pm_arm_wake_irq(struct wake_irq *wirq);
|
|
|
|
extern void dev_pm_disarm_wake_irq(struct wake_irq *wirq);
|
|
|
|
|
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
|
|
|
|
|
|
extern int device_wakeup_attach_irq(struct device *dev,
|
|
|
|
struct wake_irq *wakeirq);
|
|
|
|
extern void device_wakeup_detach_irq(struct device *dev);
|
|
|
|
extern void device_wakeup_arm_wake_irqs(void);
|
|
|
|
extern void device_wakeup_disarm_wake_irqs(void);
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
device_wakeup_attach_irq(struct device *dev,
|
|
|
|
struct wake_irq *wakeirq)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void device_wakeup_detach_irq(struct device *dev)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void device_wakeup_arm_wake_irqs(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void device_wakeup_disarm_wake_irqs(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* CONFIG_PM_SLEEP */
|
|
|
|
|
2014-11-28 04:38:05 +07:00
|
|
|
/*
|
|
|
|
* sysfs.c
|
|
|
|
*/
|
|
|
|
|
|
|
|
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);
|
|
|
|
extern int pm_qos_sysfs_add_resume_latency(struct device *dev);
|
|
|
|
extern void pm_qos_sysfs_remove_resume_latency(struct device *dev);
|
|
|
|
extern int pm_qos_sysfs_add_flags(struct device *dev);
|
|
|
|
extern void pm_qos_sysfs_remove_flags(struct device *dev);
|
2015-07-27 22:03:56 +07:00
|
|
|
extern int pm_qos_sysfs_add_latency_tolerance(struct device *dev);
|
|
|
|
extern void pm_qos_sysfs_remove_latency_tolerance(struct device *dev);
|
2014-11-28 04:38:05 +07:00
|
|
|
|
|
|
|
#else /* CONFIG_PM */
|
2009-08-19 04:38:32 +07:00
|
|
|
|
2012-08-06 06:45:11 +07:00
|
|
|
static inline void pm_runtime_early_init(struct device *dev)
|
|
|
|
{
|
|
|
|
device_pm_init_common(dev);
|
|
|
|
}
|
|
|
|
|
2009-08-19 04:38:32 +07:00
|
|
|
static inline void pm_runtime_init(struct device *dev) {}
|
PM / runtime: Re-init runtime PM states at probe error and driver unbind
There are two common expectations among several subsystems/drivers that
deploys runtime PM support, but which isn't met by the driver core.
Expectation 1)
At ->probe() the subsystem/driver expects the runtime PM status of the
device to be RPM_SUSPENDED, which is the initial status being assigned at
device registration.
This expectation is especially common among some of those subsystems/
drivers that manages devices with an attached PM domain, as those requires
the ->runtime_resume() callback at the PM domain level to be invoked
during ->probe().
Moreover these subsystems/drivers entirely relies on runtime PM resources
being managed at the PM domain level, thus don't implement their own set
of runtime PM callbacks.
These are two scenarios that suffers from this unmet expectation.
i) A failed ->probe() sequence requests probe deferral:
->probe()
...
pm_runtime_enable()
pm_runtime_get_sync()
...
err:
pm_runtime_put()
pm_runtime_disable()
...
As there are no guarantees that such sequence turns the runtime PM status
of the device into RPM_SUSPENDED, the re-trying ->probe() may start with
the status in RPM_ACTIVE.
In such case the runtime PM core won't invoke the ->runtime_resume()
callback because of a pm_runtime_get_sync(), as it considers the device to
be already runtime resumed.
ii) A driver re-bind sequence:
At driver unbind, the subsystem/driver's >remove() callback invokes a
sequence of runtime PM APIs, to undo actions during ->probe() and to put
the device into low power state.
->remove()
...
pm_runtime_put()
pm_runtime_disable()
...
Similar as in the failing ->probe() case, this sequence don't guarantee
the runtime PM status of the device to turn into RPM_SUSPENDED.
Trying to re-bind the driver thus causes the same issue as when re-trying
->probe(), in the probe deferral scenario.
Expectation 2)
Drivers that invokes the pm_runtime_irq_safe() API during ->probe(),
triggers the runtime PM core to increase the usage count for the device's
parent and permanently make it runtime resumed.
The usage count is only dropped at device removal, which also allows it to
be runtime suspended again.
A re-trying ->probe() repeats the call to pm_runtime_irq_safe() and thus
once more triggers the usage count of the device's parent to be increased.
This leads to not only an imbalance issue of the usage count of the
device's parent, but also to keep it runtime resumed permanently even if
->probe() fails.
To address these issues, let's change the policy of the driver core to
meet these expectations. More precisely, at ->probe() failures and driver
unbind, restore the initial states of runtime PM.
Although to still allow subsystem's to control PM for devices that doesn't
->probe() successfully, don't restore the initial states unless runtime PM
is disabled.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Kevin Hilman <khilman@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-11-18 17:48:39 +07:00
|
|
|
static inline void pm_runtime_reinit(struct device *dev) {}
|
2009-08-19 04:38:32 +07:00
|
|
|
static inline void pm_runtime_remove(struct device *dev) {}
|
|
|
|
|
2014-11-28 04:38:05 +07: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) {}
|
|
|
|
static inline int pm_qos_sysfs_add(struct device *dev) { return 0; }
|
|
|
|
static inline void pm_qos_sysfs_remove(struct device *dev) {}
|
|
|
|
|
PM / Wakeirq: Add automated device wake IRQ handling
Turns out we can automate the handling for the device_may_wakeup()
quite a bit by using the kernel wakeup source list as suggested
by Rafael J. Wysocki <rjw@rjwysocki.net>.
And as some hardware has separate dedicated wake-up interrupt
in addition to the IO interrupt, we can automate the handling by
adding a generic threaded interrupt handler that just calls the
device PM runtime to wake up the device.
This allows dropping code from device drivers as we currently
are doing it in multiple ways, and often wrong.
For most drivers, we should be able to drop the following
boilerplate code from runtime_suspend and runtime_resume
functions:
...
device_init_wakeup(dev, true);
...
if (device_may_wakeup(dev))
enable_irq_wake(irq);
...
if (device_may_wakeup(dev))
disable_irq_wake(irq);
...
device_init_wakeup(dev, false);
...
We can replace it with just the following init and exit
time code:
...
device_init_wakeup(dev, true);
dev_pm_set_wake_irq(dev, irq);
...
dev_pm_clear_wake_irq(dev);
device_init_wakeup(dev, false);
...
And for hardware with dedicated wake-up interrupts:
...
device_init_wakeup(dev, true);
dev_pm_set_dedicated_wake_irq(dev, irq);
...
dev_pm_clear_wake_irq(dev);
device_init_wakeup(dev, false);
...
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-05-19 05:40:29 +07:00
|
|
|
static inline void dev_pm_arm_wake_irq(struct wake_irq *wirq)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void dev_pm_disarm_wake_irq(struct wake_irq *wirq)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-11-28 04:38:05 +07:00
|
|
|
#endif
|
2008-08-08 00:06:12 +07:00
|
|
|
|
2007-07-30 04:27:18 +07:00
|
|
|
#ifdef CONFIG_PM_SLEEP
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2010-01-24 04:25:15 +07:00
|
|
|
/* kernel/power/main.c */
|
|
|
|
extern int pm_async_enabled;
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2010-01-24 04:25:15 +07: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 04:00:01 +07:00
|
|
|
extern struct list_head dpm_list; /* The active device list */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2007-11-22 05:55:18 +07:00
|
|
|
static inline struct device *to_device(struct list_head *entry)
|
2005-04-17 05:20:36 +07:00
|
|
|
{
|
2007-09-22 02:36:56 +07:00
|
|
|
return container_of(entry, struct device, power.entry);
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
|
2012-08-06 06:44:28 +07:00
|
|
|
extern void device_pm_sleep_init(struct device *dev);
|
2008-08-08 00:06:12 +07:00
|
|
|
extern void device_pm_add(struct device *);
|
2005-04-17 05:20:36 +07:00
|
|
|
extern void device_pm_remove(struct device *);
|
2009-03-04 18:44:00 +07: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 *);
|
2016-01-07 22:46:14 +07:00
|
|
|
extern void device_pm_check_callbacks(struct device *dev);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2009-08-19 04:38:32 +07:00
|
|
|
#else /* !CONFIG_PM_SLEEP */
|
|
|
|
|
2012-08-06 06:44:28 +07:00
|
|
|
static inline void device_pm_sleep_init(struct device *dev) {}
|
2009-08-19 04:38:32 +07:00
|
|
|
|
2013-03-04 20:22:57 +07:00
|
|
|
static inline void device_pm_add(struct device *dev) {}
|
2011-09-30 03:29:44 +07:00
|
|
|
|
2009-08-19 04:38:32 +07:00
|
|
|
static inline void device_pm_remove(struct device *dev)
|
|
|
|
{
|
|
|
|
pm_runtime_remove(dev);
|
|
|
|
}
|
2007-11-22 05:55:18 +07:00
|
|
|
|
2009-03-04 18:44:00 +07: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 02:40:46 +07:00
|
|
|
|
2016-01-07 22:46:14 +07:00
|
|
|
static inline void device_pm_check_callbacks(struct device *dev) {}
|
|
|
|
|
2009-08-19 04:38:32 +07:00
|
|
|
#endif /* !CONFIG_PM_SLEEP */
|
2007-11-22 05:55:18 +07:00
|
|
|
|
2012-08-06 06:44:28 +07:00
|
|
|
static inline void device_pm_init(struct device *dev)
|
|
|
|
{
|
|
|
|
device_pm_init_common(dev);
|
|
|
|
device_pm_sleep_init(dev);
|
|
|
|
pm_runtime_init(dev);
|
|
|
|
}
|