Merge branches 'pm-core' and 'pm-domains'

* pm-core:
  PM / sleep: Drop unused `info' variable
  PM / Runtime: Move ignore_children flag under CONFIG_PM
  PM / Runtime: Fix error path in pm_runtime_force_resume()

* pm-domains:
  PM / Domains: Drop unnecessary wakeup code from pm_genpd_prepare()
  PM / Domains: Remove redundant pm_runtime_get|put*() in pm_genpd_prepare()
  PM / Domains: Remove ->save|restore_state() callbacks
  PM / Domains: Rename pm_genpd_runtime_suspend|resume()
  PM / Domains: Rename stop_ok to suspend_ok for the genpd governor
This commit is contained in:
Rafael J. Wysocki 2016-05-16 14:31:29 +02:00
commit aa24781b1c
9 changed files with 91 additions and 121 deletions

View file

@ -229,17 +229,6 @@ static int genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth)
return ret; return ret;
} }
static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
{
return GENPD_DEV_CALLBACK(genpd, int, save_state, dev);
}
static int genpd_restore_dev(struct generic_pm_domain *genpd,
struct device *dev)
{
return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev);
}
static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
unsigned long val, void *ptr) unsigned long val, void *ptr)
{ {
@ -372,17 +361,63 @@ static void genpd_power_off_work_fn(struct work_struct *work)
} }
/** /**
* pm_genpd_runtime_suspend - Suspend a device belonging to I/O PM domain. * __genpd_runtime_suspend - walk the hierarchy of ->runtime_suspend() callbacks
* @dev: Device to handle.
*/
static int __genpd_runtime_suspend(struct device *dev)
{
int (*cb)(struct device *__dev);
if (dev->type && dev->type->pm)
cb = dev->type->pm->runtime_suspend;
else if (dev->class && dev->class->pm)
cb = dev->class->pm->runtime_suspend;
else if (dev->bus && dev->bus->pm)
cb = dev->bus->pm->runtime_suspend;
else
cb = NULL;
if (!cb && dev->driver && dev->driver->pm)
cb = dev->driver->pm->runtime_suspend;
return cb ? cb(dev) : 0;
}
/**
* __genpd_runtime_resume - walk the hierarchy of ->runtime_resume() callbacks
* @dev: Device to handle.
*/
static int __genpd_runtime_resume(struct device *dev)
{
int (*cb)(struct device *__dev);
if (dev->type && dev->type->pm)
cb = dev->type->pm->runtime_resume;
else if (dev->class && dev->class->pm)
cb = dev->class->pm->runtime_resume;
else if (dev->bus && dev->bus->pm)
cb = dev->bus->pm->runtime_resume;
else
cb = NULL;
if (!cb && dev->driver && dev->driver->pm)
cb = dev->driver->pm->runtime_resume;
return cb ? cb(dev) : 0;
}
/**
* genpd_runtime_suspend - Suspend a device belonging to I/O PM domain.
* @dev: Device to suspend. * @dev: Device to suspend.
* *
* Carry out a runtime suspend of a device under the assumption that its * Carry out a runtime suspend of a device under the assumption that its
* pm_domain field points to the domain member of an object of type * pm_domain field points to the domain member of an object of type
* struct generic_pm_domain representing a PM domain consisting of I/O devices. * struct generic_pm_domain representing a PM domain consisting of I/O devices.
*/ */
static int pm_genpd_runtime_suspend(struct device *dev) static int genpd_runtime_suspend(struct device *dev)
{ {
struct generic_pm_domain *genpd; struct generic_pm_domain *genpd;
bool (*stop_ok)(struct device *__dev); bool (*suspend_ok)(struct device *__dev);
struct gpd_timing_data *td = &dev_gpd_data(dev)->td; struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
bool runtime_pm = pm_runtime_enabled(dev); bool runtime_pm = pm_runtime_enabled(dev);
ktime_t time_start; ktime_t time_start;
@ -401,21 +436,21 @@ static int pm_genpd_runtime_suspend(struct device *dev)
* runtime PM is disabled. Under these circumstances, we shall skip * runtime PM is disabled. Under these circumstances, we shall skip
* validating/measuring the PM QoS latency. * validating/measuring the PM QoS latency.
*/ */
stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL; suspend_ok = genpd->gov ? genpd->gov->suspend_ok : NULL;
if (runtime_pm && stop_ok && !stop_ok(dev)) if (runtime_pm && suspend_ok && !suspend_ok(dev))
return -EBUSY; return -EBUSY;
/* Measure suspend latency. */ /* Measure suspend latency. */
if (runtime_pm) if (runtime_pm)
time_start = ktime_get(); time_start = ktime_get();
ret = genpd_save_dev(genpd, dev); ret = __genpd_runtime_suspend(dev);
if (ret) if (ret)
return ret; return ret;
ret = genpd_stop_dev(genpd, dev); ret = genpd_stop_dev(genpd, dev);
if (ret) { if (ret) {
genpd_restore_dev(genpd, dev); __genpd_runtime_resume(dev);
return ret; return ret;
} }
@ -446,14 +481,14 @@ static int pm_genpd_runtime_suspend(struct device *dev)
} }
/** /**
* pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain. * genpd_runtime_resume - Resume a device belonging to I/O PM domain.
* @dev: Device to resume. * @dev: Device to resume.
* *
* Carry out a runtime resume of a device under the assumption that its * Carry out a runtime resume of a device under the assumption that its
* pm_domain field points to the domain member of an object of type * pm_domain field points to the domain member of an object of type
* struct generic_pm_domain representing a PM domain consisting of I/O devices. * struct generic_pm_domain representing a PM domain consisting of I/O devices.
*/ */
static int pm_genpd_runtime_resume(struct device *dev) static int genpd_runtime_resume(struct device *dev)
{ {
struct generic_pm_domain *genpd; struct generic_pm_domain *genpd;
struct gpd_timing_data *td = &dev_gpd_data(dev)->td; struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
@ -491,7 +526,7 @@ static int pm_genpd_runtime_resume(struct device *dev)
if (ret) if (ret)
goto err_poweroff; goto err_poweroff;
ret = genpd_restore_dev(genpd, dev); ret = __genpd_runtime_resume(dev);
if (ret) if (ret)
goto err_stop; goto err_stop;
@ -695,15 +730,6 @@ static int pm_genpd_prepare(struct device *dev)
* at this point and a system wakeup event should be reported if it's * at this point and a system wakeup event should be reported if it's
* set up to wake up the system from sleep states. * set up to wake up the system from sleep states.
*/ */
pm_runtime_get_noresume(dev);
if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
pm_wakeup_event(dev, 0);
if (pm_wakeup_pending()) {
pm_runtime_put(dev);
return -EBUSY;
}
if (resume_needed(dev, genpd)) if (resume_needed(dev, genpd))
pm_runtime_resume(dev); pm_runtime_resume(dev);
@ -716,10 +742,8 @@ static int pm_genpd_prepare(struct device *dev)
mutex_unlock(&genpd->lock); mutex_unlock(&genpd->lock);
if (genpd->suspend_power_off) { if (genpd->suspend_power_off)
pm_runtime_put_noidle(dev);
return 0; return 0;
}
/* /*
* The PM domain must be in the GPD_STATE_ACTIVE state at this point, * The PM domain must be in the GPD_STATE_ACTIVE state at this point,
@ -741,7 +765,6 @@ static int pm_genpd_prepare(struct device *dev)
pm_runtime_enable(dev); pm_runtime_enable(dev);
} }
pm_runtime_put(dev);
return ret; return ret;
} }
@ -1427,54 +1450,6 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
} }
EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain);
/* Default device callbacks for generic PM domains. */
/**
* pm_genpd_default_save_state - Default "save device state" for PM domains.
* @dev: Device to handle.
*/
static int pm_genpd_default_save_state(struct device *dev)
{
int (*cb)(struct device *__dev);
if (dev->type && dev->type->pm)
cb = dev->type->pm->runtime_suspend;
else if (dev->class && dev->class->pm)
cb = dev->class->pm->runtime_suspend;
else if (dev->bus && dev->bus->pm)
cb = dev->bus->pm->runtime_suspend;
else
cb = NULL;
if (!cb && dev->driver && dev->driver->pm)
cb = dev->driver->pm->runtime_suspend;
return cb ? cb(dev) : 0;
}
/**
* pm_genpd_default_restore_state - Default PM domains "restore device state".
* @dev: Device to handle.
*/
static int pm_genpd_default_restore_state(struct device *dev)
{
int (*cb)(struct device *__dev);
if (dev->type && dev->type->pm)
cb = dev->type->pm->runtime_resume;
else if (dev->class && dev->class->pm)
cb = dev->class->pm->runtime_resume;
else if (dev->bus && dev->bus->pm)
cb = dev->bus->pm->runtime_resume;
else
cb = NULL;
if (!cb && dev->driver && dev->driver->pm)
cb = dev->driver->pm->runtime_resume;
return cb ? cb(dev) : 0;
}
/** /**
* pm_genpd_init - Initialize a generic I/O PM domain object. * pm_genpd_init - Initialize a generic I/O PM domain object.
* @genpd: PM domain object to initialize. * @genpd: PM domain object to initialize.
@ -1498,8 +1473,8 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
genpd->device_count = 0; genpd->device_count = 0;
genpd->max_off_time_ns = -1; genpd->max_off_time_ns = -1;
genpd->max_off_time_changed = true; genpd->max_off_time_changed = true;
genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend; genpd->domain.ops.runtime_suspend = genpd_runtime_suspend;
genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume; genpd->domain.ops.runtime_resume = genpd_runtime_resume;
genpd->domain.ops.prepare = pm_genpd_prepare; genpd->domain.ops.prepare = pm_genpd_prepare;
genpd->domain.ops.suspend = pm_genpd_suspend; genpd->domain.ops.suspend = pm_genpd_suspend;
genpd->domain.ops.suspend_late = pm_genpd_suspend_late; genpd->domain.ops.suspend_late = pm_genpd_suspend_late;
@ -1520,8 +1495,6 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
genpd->domain.ops.restore_early = pm_genpd_resume_early; genpd->domain.ops.restore_early = pm_genpd_resume_early;
genpd->domain.ops.restore = pm_genpd_resume; genpd->domain.ops.restore = pm_genpd_resume;
genpd->domain.ops.complete = pm_genpd_complete; genpd->domain.ops.complete = pm_genpd_complete;
genpd->dev_ops.save_state = pm_genpd_default_save_state;
genpd->dev_ops.restore_state = pm_genpd_default_restore_state;
if (genpd->flags & GENPD_FLAG_PM_CLK) { if (genpd->flags & GENPD_FLAG_PM_CLK) {
genpd->dev_ops.stop = pm_clk_suspend; genpd->dev_ops.stop = pm_clk_suspend;

View file

@ -37,10 +37,10 @@ static int dev_update_qos_constraint(struct device *dev, void *data)
} }
/** /**
* default_stop_ok - Default PM domain governor routine for stopping devices. * default_suspend_ok - Default PM domain governor routine to suspend devices.
* @dev: Device to check. * @dev: Device to check.
*/ */
static bool default_stop_ok(struct device *dev) static bool default_suspend_ok(struct device *dev)
{ {
struct gpd_timing_data *td = &dev_gpd_data(dev)->td; struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
unsigned long flags; unsigned long flags;
@ -51,13 +51,13 @@ static bool default_stop_ok(struct device *dev)
spin_lock_irqsave(&dev->power.lock, flags); spin_lock_irqsave(&dev->power.lock, flags);
if (!td->constraint_changed) { if (!td->constraint_changed) {
bool ret = td->cached_stop_ok; bool ret = td->cached_suspend_ok;
spin_unlock_irqrestore(&dev->power.lock, flags); spin_unlock_irqrestore(&dev->power.lock, flags);
return ret; return ret;
} }
td->constraint_changed = false; td->constraint_changed = false;
td->cached_stop_ok = false; td->cached_suspend_ok = false;
td->effective_constraint_ns = -1; td->effective_constraint_ns = -1;
constraint_ns = __dev_pm_qos_read_value(dev); constraint_ns = __dev_pm_qos_read_value(dev);
@ -83,13 +83,13 @@ static bool default_stop_ok(struct device *dev)
return false; return false;
} }
td->effective_constraint_ns = constraint_ns; td->effective_constraint_ns = constraint_ns;
td->cached_stop_ok = constraint_ns >= 0; td->cached_suspend_ok = constraint_ns >= 0;
/* /*
* The children have been suspended already, so we don't need to take * The children have been suspended already, so we don't need to take
* their stop latencies into account here. * their suspend latencies into account here.
*/ */
return td->cached_stop_ok; return td->cached_suspend_ok;
} }
/** /**
@ -150,7 +150,7 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd,
*/ */
td = &to_gpd_data(pdd)->td; td = &to_gpd_data(pdd)->td;
constraint_ns = td->effective_constraint_ns; constraint_ns = td->effective_constraint_ns;
/* default_stop_ok() need not be called before us. */ /* default_suspend_ok() need not be called before us. */
if (constraint_ns < 0) { if (constraint_ns < 0) {
constraint_ns = dev_pm_qos_read_value(pdd->dev); constraint_ns = dev_pm_qos_read_value(pdd->dev);
constraint_ns *= NSEC_PER_USEC; constraint_ns *= NSEC_PER_USEC;
@ -227,7 +227,7 @@ static bool always_on_power_down_ok(struct dev_pm_domain *domain)
} }
struct dev_power_governor simple_qos_governor = { struct dev_power_governor simple_qos_governor = {
.stop_ok = default_stop_ok, .suspend_ok = default_suspend_ok,
.power_down_ok = default_power_down_ok, .power_down_ok = default_power_down_ok,
}; };
@ -236,5 +236,5 @@ struct dev_power_governor simple_qos_governor = {
*/ */
struct dev_power_governor pm_domain_always_on_gov = { struct dev_power_governor pm_domain_always_on_gov = {
.power_down_ok = always_on_power_down_ok, .power_down_ok = always_on_power_down_ok,
.stop_ok = default_stop_ok, .suspend_ok = default_suspend_ok,
}; };

View file

@ -1556,7 +1556,6 @@ int dpm_suspend(pm_message_t state)
static int device_prepare(struct device *dev, pm_message_t state) static int device_prepare(struct device *dev, pm_message_t state)
{ {
int (*callback)(struct device *) = NULL; int (*callback)(struct device *) = NULL;
char *info = NULL;
int ret = 0; int ret = 0;
if (dev->power.syscore) if (dev->power.syscore)
@ -1579,24 +1578,17 @@ static int device_prepare(struct device *dev, pm_message_t state)
goto unlock; goto unlock;
} }
if (dev->pm_domain) { if (dev->pm_domain)
info = "preparing power domain ";
callback = dev->pm_domain->ops.prepare; callback = dev->pm_domain->ops.prepare;
} else if (dev->type && dev->type->pm) { else if (dev->type && dev->type->pm)
info = "preparing type ";
callback = dev->type->pm->prepare; callback = dev->type->pm->prepare;
} else if (dev->class && dev->class->pm) { else if (dev->class && dev->class->pm)
info = "preparing class ";
callback = dev->class->pm->prepare; callback = dev->class->pm->prepare;
} else if (dev->bus && dev->bus->pm) { else if (dev->bus && dev->bus->pm)
info = "preparing bus ";
callback = dev->bus->pm->prepare; callback = dev->bus->pm->prepare;
}
if (!callback && dev->driver && dev->driver->pm) { if (!callback && dev->driver && dev->driver->pm)
info = "preparing driver ";
callback = dev->driver->pm->prepare; callback = dev->driver->pm->prepare;
}
if (callback) if (callback)
ret = callback(dev); ret = callback(dev);

View file

@ -1506,11 +1506,16 @@ int pm_runtime_force_resume(struct device *dev)
goto out; goto out;
} }
ret = callback(dev); ret = pm_runtime_set_active(dev);
if (ret) if (ret)
goto out; goto out;
pm_runtime_set_active(dev); ret = callback(dev);
if (ret) {
pm_runtime_set_suspended(dev);
goto out;
}
pm_runtime_mark_last_busy(dev); pm_runtime_mark_last_busy(dev);
out: out:
pm_runtime_enable(dev); pm_runtime_enable(dev);

View file

@ -21,6 +21,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/mmc.h> #include <linux/mmc/mmc.h>

View file

@ -956,11 +956,6 @@ static inline bool device_async_suspend_enabled(struct device *dev)
return !!dev->power.async_suspend; return !!dev->power.async_suspend;
} }
static inline void pm_suspend_ignore_children(struct device *dev, bool enable)
{
dev->power.ignore_children = enable;
}
static inline void dev_pm_syscore_device(struct device *dev, bool val) static inline void dev_pm_syscore_device(struct device *dev, bool val)
{ {
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP

View file

@ -563,7 +563,6 @@ struct dev_pm_info {
bool is_suspended:1; /* Ditto */ bool is_suspended:1; /* Ditto */
bool is_noirq_suspended:1; bool is_noirq_suspended:1;
bool is_late_suspended:1; bool is_late_suspended:1;
bool ignore_children:1;
bool early_init:1; /* Owned by the PM core */ bool early_init:1; /* Owned by the PM core */
bool direct_complete:1; /* Owned by the PM core */ bool direct_complete:1; /* Owned by the PM core */
spinlock_t lock; spinlock_t lock;
@ -591,6 +590,7 @@ struct dev_pm_info {
unsigned int deferred_resume:1; unsigned int deferred_resume:1;
unsigned int run_wake:1; unsigned int run_wake:1;
unsigned int runtime_auto:1; unsigned int runtime_auto:1;
bool ignore_children:1;
unsigned int no_callbacks:1; unsigned int no_callbacks:1;
unsigned int irq_safe:1; unsigned int irq_safe:1;
unsigned int use_autosuspend:1; unsigned int use_autosuspend:1;

View file

@ -28,14 +28,12 @@ enum gpd_status {
struct dev_power_governor { struct dev_power_governor {
bool (*power_down_ok)(struct dev_pm_domain *domain); bool (*power_down_ok)(struct dev_pm_domain *domain);
bool (*stop_ok)(struct device *dev); bool (*suspend_ok)(struct device *dev);
}; };
struct gpd_dev_ops { struct gpd_dev_ops {
int (*start)(struct device *dev); int (*start)(struct device *dev);
int (*stop)(struct device *dev); int (*stop)(struct device *dev);
int (*save_state)(struct device *dev);
int (*restore_state)(struct device *dev);
bool (*active_wakeup)(struct device *dev); bool (*active_wakeup)(struct device *dev);
}; };
@ -94,7 +92,7 @@ struct gpd_timing_data {
s64 resume_latency_ns; s64 resume_latency_ns;
s64 effective_constraint_ns; s64 effective_constraint_ns;
bool constraint_changed; bool constraint_changed;
bool cached_stop_ok; bool cached_suspend_ok;
}; };
struct pm_domain_data { struct pm_domain_data {

View file

@ -56,6 +56,11 @@ extern void pm_runtime_update_max_time_suspended(struct device *dev,
s64 delta_ns); s64 delta_ns);
extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable); extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable);
static inline void pm_suspend_ignore_children(struct device *dev, bool enable)
{
dev->power.ignore_children = enable;
}
static inline bool pm_children_suspended(struct device *dev) static inline bool pm_children_suspended(struct device *dev)
{ {
return dev->power.ignore_children return dev->power.ignore_children
@ -156,6 +161,7 @@ static inline void __pm_runtime_disable(struct device *dev, bool c) {}
static inline void pm_runtime_allow(struct device *dev) {} static inline void pm_runtime_allow(struct device *dev) {}
static inline void pm_runtime_forbid(struct device *dev) {} static inline void pm_runtime_forbid(struct device *dev) {}
static inline void pm_suspend_ignore_children(struct device *dev, bool enable) {}
static inline bool pm_children_suspended(struct device *dev) { return false; } static inline bool pm_children_suspended(struct device *dev) { return false; }
static inline void pm_runtime_get_noresume(struct device *dev) {} static inline void pm_runtime_get_noresume(struct device *dev) {}
static inline void pm_runtime_put_noidle(struct device *dev) {} static inline void pm_runtime_put_noidle(struct device *dev) {}