From: Rafael J. Wysocki Date: Mon, 14 Dec 2015 21:58:57 +0000 (+0100) Subject: Merge branches 'powercap', 'pm-cpufreq' and 'pm-domains' X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=f1b9fc591e437ec07626ba84e1d81be19cb00eb6;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git Merge branches 'powercap', 'pm-cpufreq' and 'pm-domains' * powercap: powercap / RAPL: fix BIOS lock check * pm-cpufreq: cpufreq: intel_pstate: Minor cleanup for FRAC_BITS cpufreq: tegra: add regulator dependency for T124 * pm-domains: PM / Domains: Allow runtime PM callbacks to be re-used during system PM --- f1b9fc591e437ec07626ba84e1d81be19cb00eb6 diff --cc drivers/base/power/domain.c index 167418e73445,16550c63d611,167418e73445,8ad59f3e6f80..65f50eccd49b --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@@@@ -389,9 -482,6 -389,9 -389,10 +389,10 @@@@@ static int pm_genpd_runtime_suspend(str { struct generic_pm_domain *genpd; bool (*stop_ok)(struct device *__dev); + struct gpd_timing_data *td = &dev_gpd_data(dev)->td; +++ bool runtime_pm = pm_runtime_enabled(dev); + ktime_t time_start; + s64 elapsed_ns; int ret; dev_dbg(dev, "%s()\n", __func__); @@@@@ -400,13 -490,10 -400,13 -401,20 +401,20 @@@@@ if (IS_ERR(genpd)) return -EINVAL; +++ /* +++ * A runtime PM centric subsystem/driver may re-use the runtime PM +++ * callbacks for other purposes than runtime PM. In those scenarios +++ * runtime PM is disabled. Under these circumstances, we shall skip +++ * validating/measuring the PM QoS latency. +++ */ stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL; --- if (stop_ok && !stop_ok(dev)) +++ if (runtime_pm && stop_ok && !stop_ok(dev)) return -EBUSY; + /* Measure suspend latency. */ - - time_start = ktime_get(); +++ if (runtime_pm) +++ time_start = ktime_get(); + ret = genpd_save_dev(genpd, dev); if (ret) return ret; @@@@@ -417,16 -504,6 -417,16 -425,18 +425,18 @@@@@ return ret; } + /* Update suspend latency value if the measured time exceeds it. */ - - elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); - - if (elapsed_ns > td->suspend_latency_ns) { - - td->suspend_latency_ns = elapsed_ns; - - dev_dbg(dev, "suspend latency exceeded, %lld ns\n", - - elapsed_ns); - - genpd->max_off_time_changed = true; - - td->constraint_changed = true; +++ if (runtime_pm) { +++ elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); +++ if (elapsed_ns > td->suspend_latency_ns) { +++ td->suspend_latency_ns = elapsed_ns; +++ dev_dbg(dev, "suspend latency exceeded, %lld ns\n", +++ elapsed_ns); +++ genpd->max_off_time_changed = true; +++ td->constraint_changed = true; +++ } + } + /* * If power.irq_safe is set, this routine will be run with interrupts * off, so it can't use mutexes. @@@@@ -452,9 -531,6 -452,9 -462,10 +462,10 @@@@@ static int pm_genpd_runtime_resume(struct device *dev) { struct generic_pm_domain *genpd; + struct gpd_timing_data *td = &dev_gpd_data(dev)->td; +++ bool runtime_pm = pm_runtime_enabled(dev); + ktime_t time_start; + s64 elapsed_ns; int ret; bool timed = true; @@@@@ -478,24 -554,8 -478,24 -489,24 +489,24 @@@@@ return ret; out: - genpd_start_dev(genpd, dev, timed); - genpd_restore_dev(genpd, dev, timed); + /* Measure resume latency. */ - - if (timed) +++ if (timed && runtime_pm) + time_start = ktime_get(); + + genpd_start_dev(genpd, dev); + genpd_restore_dev(genpd, dev); + + /* Update resume latency value if the measured time exceeds it. */ - - if (timed) { +++ if (timed && runtime_pm) { + elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); + if (elapsed_ns > td->resume_latency_ns) { + td->resume_latency_ns = elapsed_ns; + dev_dbg(dev, "resume latency exceeded, %lld ns\n", + elapsed_ns); + genpd->max_off_time_changed = true; + td->constraint_changed = true; + } + } return 0; } @@@@@ -1348,11 -1424,38 -1348,11 -1359,10 +1359,11 @@@@@ int pm_genpd_add_subdomain(struct gener out: mutex_unlock(&subdomain->lock); mutex_unlock(&genpd->lock); - + if (ret) + kfree(link); return ret; } - - /** - * pm_genpd_add_subdomain_names - Add a subdomain to an I/O PM domain. - * @master_name: Name of the master PM domain to add the subdomain to. - * @subdomain_name: Name of the subdomain to be added. - */ - int pm_genpd_add_subdomain_names(const char *master_name, - const char *subdomain_name) - { - struct generic_pm_domain *master = NULL, *subdomain = NULL, *gpd; - - if (IS_ERR_OR_NULL(master_name) || IS_ERR_OR_NULL(subdomain_name)) - return -EINVAL; - - mutex_lock(&gpd_list_lock); - list_for_each_entry(gpd, &gpd_list, gpd_list_node) { - if (!master && !strcmp(gpd->name, master_name)) - master = gpd; - - if (!subdomain && !strcmp(gpd->name, subdomain_name)) - subdomain = gpd; - - if (master && subdomain) - break; - } - mutex_unlock(&gpd_list_lock); - - return pm_genpd_add_subdomain(master, subdomain); - } + +EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain); /** * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain. @@@@@ -1400,7 -1503,124 -1400,7 -1410,6 +1411,7 @@@@@ out return ret; } - - /** - * pm_genpd_attach_cpuidle - Connect the given PM domain with cpuidle. - * @genpd: PM domain to be connected with cpuidle. - * @state: cpuidle state this domain can disable/enable. - * - * Make a PM domain behave as though it contained a CPU core, that is, instead - * of calling its power down routine it will enable the given cpuidle state so - * that the cpuidle subsystem can power it down (if possible and desirable). - */ - int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) - { - struct cpuidle_driver *cpuidle_drv; - struct gpd_cpuidle_data *cpuidle_data; - struct cpuidle_state *idle_state; - int ret = 0; - - if (IS_ERR_OR_NULL(genpd) || state < 0) - return -EINVAL; - - mutex_lock(&genpd->lock); - - if (genpd->cpuidle_data) { - ret = -EEXIST; - goto out; - } - cpuidle_data = kzalloc(sizeof(*cpuidle_data), GFP_KERNEL); - if (!cpuidle_data) { - ret = -ENOMEM; - goto out; - } - cpuidle_drv = cpuidle_driver_ref(); - if (!cpuidle_drv) { - ret = -ENODEV; - goto err_drv; - } - if (cpuidle_drv->state_count <= state) { - ret = -EINVAL; - goto err; - } - idle_state = &cpuidle_drv->states[state]; - if (!idle_state->disabled) { - ret = -EAGAIN; - goto err; - } - cpuidle_data->idle_state = idle_state; - cpuidle_data->saved_exit_latency = idle_state->exit_latency; - genpd->cpuidle_data = cpuidle_data; - genpd_recalc_cpu_exit_latency(genpd); - - out: - mutex_unlock(&genpd->lock); - return ret; - - err: - cpuidle_driver_unref(); - - err_drv: - kfree(cpuidle_data); - goto out; - } - - /** - * pm_genpd_name_attach_cpuidle - Find PM domain and connect cpuidle to it. - * @name: Name of the domain to connect to cpuidle. - * @state: cpuidle state this domain can manipulate. - */ - int pm_genpd_name_attach_cpuidle(const char *name, int state) - { - return pm_genpd_attach_cpuidle(pm_genpd_lookup_name(name), state); - } - - /** - * pm_genpd_detach_cpuidle - Remove the cpuidle connection from a PM domain. - * @genpd: PM domain to remove the cpuidle connection from. - * - * Remove the cpuidle connection set up by pm_genpd_attach_cpuidle() from the - * given PM domain. - */ - int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd) - { - struct gpd_cpuidle_data *cpuidle_data; - struct cpuidle_state *idle_state; - int ret = 0; - - if (IS_ERR_OR_NULL(genpd)) - return -EINVAL; - - mutex_lock(&genpd->lock); - - cpuidle_data = genpd->cpuidle_data; - if (!cpuidle_data) { - ret = -ENODEV; - goto out; - } - idle_state = cpuidle_data->idle_state; - if (!idle_state->disabled) { - ret = -EAGAIN; - goto out; - } - idle_state->exit_latency = cpuidle_data->saved_exit_latency; - cpuidle_driver_unref(); - genpd->cpuidle_data = NULL; - kfree(cpuidle_data); - - out: - mutex_unlock(&genpd->lock); - return ret; - } - - /** - * pm_genpd_name_detach_cpuidle - Find PM domain and disconnect cpuidle from it. - * @name: Name of the domain to disconnect cpuidle from. - */ - int pm_genpd_name_detach_cpuidle(const char *name) - { - return pm_genpd_detach_cpuidle(pm_genpd_lookup_name(name)); - } + +EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); /* Default device callbacks for generic PM domains. */