diff options
Diffstat (limited to 'drivers/base/power')
-rw-r--r-- | drivers/base/power/common.c | 20 | ||||
-rw-r--r-- | drivers/base/power/domain.c | 40 | ||||
-rw-r--r-- | drivers/base/power/power.h | 30 | ||||
-rw-r--r-- | drivers/base/power/qos.c | 70 | ||||
-rw-r--r-- | drivers/base/power/wakeirq.c | 4 |
5 files changed, 56 insertions, 108 deletions
diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c index 8db98a1f83dc..bbddb267c2e6 100644 --- a/drivers/base/power/common.c +++ b/drivers/base/power/common.c @@ -188,6 +188,26 @@ void dev_pm_domain_detach(struct device *dev, bool power_off) EXPORT_SYMBOL_GPL(dev_pm_domain_detach); /** + * dev_pm_domain_start - Start the device through its PM domain. + * @dev: Device to start. + * + * This function should typically be called during probe by a subsystem/driver, + * when it needs to start its device from the PM domain's perspective. Note + * that, it's assumed that the PM domain is already powered on when this + * function is called. + * + * Returns 0 on success and negative error values on failures. + */ +int dev_pm_domain_start(struct device *dev) +{ + if (dev->pm_domain && dev->pm_domain->start) + return dev->pm_domain->start(dev); + + return 0; +} +EXPORT_SYMBOL_GPL(dev_pm_domain_start); + +/** * dev_pm_domain_set - Set PM domain of a device. * @dev: Device whose PM domain is to be set. * @pd: PM domain to be set, or NULL. diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index cc85e87eaf05..8e5725b11ee8 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -634,6 +634,13 @@ static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth) return ret; } +static int genpd_dev_pm_start(struct device *dev) +{ + struct generic_pm_domain *genpd = dev_to_genpd(dev); + + return genpd_start_dev(genpd, dev); +} + static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, unsigned long val, void *ptr) { @@ -922,24 +929,6 @@ static int __init genpd_power_off_unused(void) } late_initcall(genpd_power_off_unused); -#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_GENERIC_DOMAINS_OF) - -static bool genpd_present(const struct generic_pm_domain *genpd) -{ - const struct generic_pm_domain *gpd; - - if (IS_ERR_OR_NULL(genpd)) - return false; - - list_for_each_entry(gpd, &gpd_list, gpd_list_node) - if (gpd == genpd) - return true; - - return false; -} - -#endif - #ifdef CONFIG_PM_SLEEP /** @@ -1354,8 +1343,8 @@ static void genpd_syscore_switch(struct device *dev, bool suspend) { struct generic_pm_domain *genpd; - genpd = dev_to_genpd(dev); - if (!genpd_present(genpd)) + genpd = dev_to_genpd_safe(dev); + if (!genpd) return; if (suspend) { @@ -1805,6 +1794,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd, genpd->domain.ops.poweroff_noirq = genpd_poweroff_noirq; genpd->domain.ops.restore_noirq = genpd_restore_noirq; genpd->domain.ops.complete = genpd_complete; + genpd->domain.start = genpd_dev_pm_start; if (genpd->flags & GENPD_FLAG_PM_CLK) { genpd->dev_ops.stop = pm_clk_suspend; @@ -2020,6 +2010,16 @@ static int genpd_add_provider(struct device_node *np, genpd_xlate_t xlate, return 0; } +static bool genpd_present(const struct generic_pm_domain *genpd) +{ + const struct generic_pm_domain *gpd; + + list_for_each_entry(gpd, &gpd_list, gpd_list_node) + if (gpd == genpd) + return true; + return false; +} + /** * of_genpd_add_provider_simple() - Register a simple PM domain provider * @np: Device node pointer associated with the PM domain provider. diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 39a06a0cfdaa..444f5c169a0b 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -117,6 +117,13 @@ static inline bool device_pm_initialized(struct device *dev) return dev->power.in_dpm_list; } +/* drivers/base/power/wakeup_stats.c */ +extern int wakeup_source_sysfs_add(struct device *parent, + struct wakeup_source *ws); +extern void wakeup_source_sysfs_remove(struct wakeup_source *ws); + +extern int pm_wakeup_source_sysfs_add(struct device *parent); + #else /* !CONFIG_PM_SLEEP */ static inline void device_pm_sleep_init(struct device *dev) {} @@ -141,6 +148,11 @@ static inline bool device_pm_initialized(struct device *dev) return device_is_registered(dev); } +static inline int pm_wakeup_source_sysfs_add(struct device *parent) +{ + return 0; +} + #endif /* !CONFIG_PM_SLEEP */ static inline void device_pm_init(struct device *dev) @@ -149,21 +161,3 @@ static inline void device_pm_init(struct device *dev) device_pm_sleep_init(dev); pm_runtime_init(dev); } - -#ifdef CONFIG_PM_SLEEP - -/* drivers/base/power/wakeup_stats.c */ -extern int wakeup_source_sysfs_add(struct device *parent, - struct wakeup_source *ws); -extern void wakeup_source_sysfs_remove(struct wakeup_source *ws); - -extern int pm_wakeup_source_sysfs_add(struct device *parent); - -#else /* !CONFIG_PM_SLEEP */ - -static inline int pm_wakeup_source_sysfs_add(struct device *parent) -{ - return 0; -} - -#endif /* CONFIG_PM_SLEEP */ diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 6c90fd7e2ff8..350dcafd751f 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -115,20 +115,10 @@ s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type) spin_lock_irqsave(&dev->power.lock, flags); - switch (type) { - case DEV_PM_QOS_RESUME_LATENCY: + if (type == DEV_PM_QOS_RESUME_LATENCY) { ret = IS_ERR_OR_NULL(qos) ? PM_QOS_RESUME_LATENCY_NO_CONSTRAINT : pm_qos_read_value(&qos->resume_latency); - break; - case DEV_PM_QOS_MIN_FREQUENCY: - ret = IS_ERR_OR_NULL(qos) ? PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE - : pm_qos_read_value(&qos->min_frequency); - break; - case DEV_PM_QOS_MAX_FREQUENCY: - ret = IS_ERR_OR_NULL(qos) ? PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE - : pm_qos_read_value(&qos->max_frequency); - break; - default: + } else { WARN_ON(1); ret = 0; } @@ -169,14 +159,6 @@ static int apply_constraint(struct dev_pm_qos_request *req, req->dev->power.set_latency_tolerance(req->dev, value); } break; - case DEV_PM_QOS_MIN_FREQUENCY: - ret = pm_qos_update_target(&qos->min_frequency, - &req->data.pnode, action, value); - break; - case DEV_PM_QOS_MAX_FREQUENCY: - ret = pm_qos_update_target(&qos->max_frequency, - &req->data.pnode, action, value); - break; case DEV_PM_QOS_FLAGS: ret = pm_qos_update_flags(&qos->flags, &req->data.flr, action, value); @@ -227,24 +209,6 @@ static int dev_pm_qos_constraints_allocate(struct device *dev) c->no_constraint_value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT; c->type = PM_QOS_MIN; - c = &qos->min_frequency; - plist_head_init(&c->list); - c->target_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE; - c->default_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE; - c->no_constraint_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE; - c->type = PM_QOS_MAX; - c->notifiers = ++n; - BLOCKING_INIT_NOTIFIER_HEAD(n); - - c = &qos->max_frequency; - plist_head_init(&c->list); - c->target_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE; - c->default_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE; - c->no_constraint_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE; - c->type = PM_QOS_MIN; - c->notifiers = ++n; - BLOCKING_INIT_NOTIFIER_HEAD(n); - INIT_LIST_HEAD(&qos->flags.list); spin_lock_irq(&dev->power.lock); @@ -305,18 +269,6 @@ void dev_pm_qos_constraints_destroy(struct device *dev) memset(req, 0, sizeof(*req)); } - c = &qos->min_frequency; - plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) { - apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE); - memset(req, 0, sizeof(*req)); - } - - c = &qos->max_frequency; - plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) { - apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE); - memset(req, 0, sizeof(*req)); - } - f = &qos->flags; list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) { apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); @@ -428,8 +380,6 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req, switch(req->type) { case DEV_PM_QOS_RESUME_LATENCY: case DEV_PM_QOS_LATENCY_TOLERANCE: - case DEV_PM_QOS_MIN_FREQUENCY: - case DEV_PM_QOS_MAX_FREQUENCY: curr_value = req->data.pnode.prio; break; case DEV_PM_QOS_FLAGS: @@ -557,14 +507,6 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier, ret = blocking_notifier_chain_register(dev->power.qos->resume_latency.notifiers, notifier); break; - case DEV_PM_QOS_MIN_FREQUENCY: - ret = blocking_notifier_chain_register(dev->power.qos->min_frequency.notifiers, - notifier); - break; - case DEV_PM_QOS_MAX_FREQUENCY: - ret = blocking_notifier_chain_register(dev->power.qos->max_frequency.notifiers, - notifier); - break; default: WARN_ON(1); ret = -EINVAL; @@ -604,14 +546,6 @@ int dev_pm_qos_remove_notifier(struct device *dev, ret = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers, notifier); break; - case DEV_PM_QOS_MIN_FREQUENCY: - ret = blocking_notifier_chain_unregister(dev->power.qos->min_frequency.notifiers, - notifier); - break; - case DEV_PM_QOS_MAX_FREQUENCY: - ret = blocking_notifier_chain_unregister(dev->power.qos->max_frequency.notifiers, - notifier); - break; default: WARN_ON(1); ret = -EINVAL; diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c index 5ce77d1ef9fc..8e021082dba8 100644 --- a/drivers/base/power/wakeirq.c +++ b/drivers/base/power/wakeirq.c @@ -272,7 +272,7 @@ void dev_pm_enable_wake_irq_check(struct device *dev, { struct wake_irq *wirq = dev->power.wakeirq; - if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK))) + if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK)) return; if (likely(wirq->status & WAKE_IRQ_DEDICATED_MANAGED)) { @@ -299,7 +299,7 @@ void dev_pm_disable_wake_irq_check(struct device *dev) { struct wake_irq *wirq = dev->power.wakeirq; - if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK))) + if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK)) return; if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) |