Merge branches 'pm-cpuidle', 'pm-cpufreq' and 'pm-sleep'

* pm-cpuidle:
  doc: trace: fix reference to cpuidle documentation file
  cpuidle / Documentation: Update cpuidle MAINTAINERS entry

* pm-cpufreq:
  cpufreq: scmi: Fix frequency invariance in slow path
  cpufreq: check if policy is inactive early in __cpufreq_get()
  cpufreq: scpi/scmi: Fix freeing of dynamic OPPs
  cpufreq / Documentation: Update cpufreq MAINTAINERS entry

* pm-sleep:
  PM: sleep: call devfreq suspend/resume
This commit is contained in:
Rafael J. Wysocki 2019-01-11 10:09:51 +01:00
Коммит 343e60e52a
8 изменённых файлов: 82 добавлений и 22 удалений

Просмотреть файл

@ -165,7 +165,7 @@ Do some work...
The same can also be done from an application program. The same can also be done from an application program.
Disable specific CPU's specific idle state from cpuidle sysfs (see Disable specific CPU's specific idle state from cpuidle sysfs (see
Documentation/cpuidle/sysfs.txt): Documentation/admin-guide/pm/cpuidle.rst):
# echo 1 > /sys/devices/system/cpu/cpu$cpu/cpuidle/state$state/disable # echo 1 > /sys/devices/system/cpu/cpu$cpu/cpuidle/state$state/disable

Просмотреть файл

@ -3951,7 +3951,7 @@ L: netdev@vger.kernel.org
S: Maintained S: Maintained
F: drivers/net/ethernet/ti/cpmac.c F: drivers/net/ethernet/ti/cpmac.c
CPU FREQUENCY DRIVERS CPU FREQUENCY SCALING FRAMEWORK
M: "Rafael J. Wysocki" <rjw@rjwysocki.net> M: "Rafael J. Wysocki" <rjw@rjwysocki.net>
M: Viresh Kumar <viresh.kumar@linaro.org> M: Viresh Kumar <viresh.kumar@linaro.org>
L: linux-pm@vger.kernel.org L: linux-pm@vger.kernel.org
@ -3959,6 +3959,8 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
T: git git://git.linaro.org/people/vireshk/linux.git (For ARM Updates) T: git git://git.linaro.org/people/vireshk/linux.git (For ARM Updates)
B: https://bugzilla.kernel.org B: https://bugzilla.kernel.org
F: Documentation/admin-guide/pm/cpufreq.rst
F: Documentation/admin-guide/pm/intel_pstate.rst
F: Documentation/cpu-freq/ F: Documentation/cpu-freq/
F: Documentation/devicetree/bindings/cpufreq/ F: Documentation/devicetree/bindings/cpufreq/
F: drivers/cpufreq/ F: drivers/cpufreq/
@ -4006,13 +4008,14 @@ S: Supported
F: drivers/cpuidle/cpuidle-exynos.c F: drivers/cpuidle/cpuidle-exynos.c
F: arch/arm/mach-exynos/pm.c F: arch/arm/mach-exynos/pm.c
CPUIDLE DRIVERS CPU IDLE TIME MANAGEMENT FRAMEWORK
M: "Rafael J. Wysocki" <rjw@rjwysocki.net> M: "Rafael J. Wysocki" <rjw@rjwysocki.net>
M: Daniel Lezcano <daniel.lezcano@linaro.org> M: Daniel Lezcano <daniel.lezcano@linaro.org>
L: linux-pm@vger.kernel.org L: linux-pm@vger.kernel.org
S: Maintained S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
B: https://bugzilla.kernel.org B: https://bugzilla.kernel.org
F: Documentation/admin-guide/pm/cpuidle.rst
F: drivers/cpuidle/* F: drivers/cpuidle/*
F: include/linux/cpuidle.h F: include/linux/cpuidle.h

Просмотреть файл

@ -32,6 +32,7 @@
#include <trace/events/power.h> #include <trace/events/power.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/cpuidle.h> #include <linux/cpuidle.h>
#include <linux/devfreq.h>
#include <linux/timer.h> #include <linux/timer.h>
#include "../base.h" #include "../base.h"
@ -1078,6 +1079,7 @@ void dpm_resume(pm_message_t state)
dpm_show_time(starttime, state, 0, NULL); dpm_show_time(starttime, state, 0, NULL);
cpufreq_resume(); cpufreq_resume();
devfreq_resume();
trace_suspend_resume(TPS("dpm_resume"), state.event, false); trace_suspend_resume(TPS("dpm_resume"), state.event, false);
} }
@ -1852,6 +1854,7 @@ int dpm_suspend(pm_message_t state)
trace_suspend_resume(TPS("dpm_suspend"), state.event, true); trace_suspend_resume(TPS("dpm_suspend"), state.event, true);
might_sleep(); might_sleep();
devfreq_suspend();
cpufreq_suspend(); cpufreq_suspend();
mutex_lock(&dpm_list_mtx); mutex_lock(&dpm_list_mtx);

Просмотреть файл

@ -1530,17 +1530,16 @@ static unsigned int __cpufreq_get(struct cpufreq_policy *policy)
{ {
unsigned int ret_freq = 0; unsigned int ret_freq = 0;
if (!cpufreq_driver->get) if (unlikely(policy_is_inactive(policy)) || !cpufreq_driver->get)
return ret_freq; return ret_freq;
ret_freq = cpufreq_driver->get(policy->cpu); ret_freq = cpufreq_driver->get(policy->cpu);
/* /*
* Updating inactive policies is invalid, so avoid doing that. Also * If fast frequency switching is used with the given policy, the check
* if fast frequency switching is used with the given policy, the check
* against policy->cur is pointless, so skip it in that case too. * against policy->cur is pointless, so skip it in that case too.
*/ */
if (unlikely(policy_is_inactive(policy)) || policy->fast_switch_enabled) if (policy->fast_switch_enabled)
return ret_freq; return ret_freq;
if (ret_freq && policy->cur && if (ret_freq && policy->cur &&
@ -1569,10 +1568,7 @@ unsigned int cpufreq_get(unsigned int cpu)
if (policy) { if (policy) {
down_read(&policy->rwsem); down_read(&policy->rwsem);
ret_freq = __cpufreq_get(policy);
if (!policy_is_inactive(policy))
ret_freq = __cpufreq_get(policy);
up_read(&policy->rwsem); up_read(&policy->rwsem);
cpufreq_cpu_put(policy); cpufreq_cpu_put(policy);

Просмотреть файл

@ -52,9 +52,9 @@ scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
int ret; int ret;
struct scmi_data *priv = policy->driver_data; struct scmi_data *priv = policy->driver_data;
struct scmi_perf_ops *perf_ops = handle->perf_ops; struct scmi_perf_ops *perf_ops = handle->perf_ops;
u64 freq = policy->freq_table[index].frequency * 1000; u64 freq = policy->freq_table[index].frequency;
ret = perf_ops->freq_set(handle, priv->domain_id, freq, false); ret = perf_ops->freq_set(handle, priv->domain_id, freq * 1000, false);
if (!ret) if (!ret)
arch_set_freq_scale(policy->related_cpus, freq, arch_set_freq_scale(policy->related_cpus, freq,
policy->cpuinfo.max_freq); policy->cpuinfo.max_freq);
@ -176,7 +176,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
out_free_priv: out_free_priv:
kfree(priv); kfree(priv);
out_free_opp: out_free_opp:
dev_pm_opp_cpumask_remove_table(policy->cpus); dev_pm_opp_remove_all_dynamic(cpu_dev);
return ret; return ret;
} }
@ -188,7 +188,7 @@ static int scmi_cpufreq_exit(struct cpufreq_policy *policy)
cpufreq_cooling_unregister(priv->cdev); cpufreq_cooling_unregister(priv->cdev);
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
kfree(priv); kfree(priv);
dev_pm_opp_cpumask_remove_table(policy->related_cpus); dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
return 0; return 0;
} }

Просмотреть файл

@ -177,7 +177,7 @@ out_free_cpufreq_table:
out_free_priv: out_free_priv:
kfree(priv); kfree(priv);
out_free_opp: out_free_opp:
dev_pm_opp_cpumask_remove_table(policy->cpus); dev_pm_opp_remove_all_dynamic(cpu_dev);
return ret; return ret;
} }
@ -190,7 +190,7 @@ static int scpi_cpufreq_exit(struct cpufreq_policy *policy)
clk_put(priv->clk); clk_put(priv->clk);
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
kfree(priv); kfree(priv);
dev_pm_opp_cpumask_remove_table(policy->related_cpus); dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
return 0; return 0;
} }

Просмотреть файл

@ -988,11 +988,9 @@ void _opp_free(struct dev_pm_opp *opp)
kfree(opp); kfree(opp);
} }
static void _opp_kref_release(struct kref *kref) static void _opp_kref_release(struct dev_pm_opp *opp,
struct opp_table *opp_table)
{ {
struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
struct opp_table *opp_table = opp->opp_table;
/* /*
* Notify the changes in the availability of the operable * Notify the changes in the availability of the operable
* frequency/voltage list. * frequency/voltage list.
@ -1002,7 +1000,22 @@ static void _opp_kref_release(struct kref *kref)
opp_debug_remove_one(opp); opp_debug_remove_one(opp);
list_del(&opp->node); list_del(&opp->node);
kfree(opp); kfree(opp);
}
static void _opp_kref_release_unlocked(struct kref *kref)
{
struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
struct opp_table *opp_table = opp->opp_table;
_opp_kref_release(opp, opp_table);
}
static void _opp_kref_release_locked(struct kref *kref)
{
struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
struct opp_table *opp_table = opp->opp_table;
_opp_kref_release(opp, opp_table);
mutex_unlock(&opp_table->lock); mutex_unlock(&opp_table->lock);
} }
@ -1013,10 +1026,16 @@ void dev_pm_opp_get(struct dev_pm_opp *opp)
void dev_pm_opp_put(struct dev_pm_opp *opp) void dev_pm_opp_put(struct dev_pm_opp *opp)
{ {
kref_put_mutex(&opp->kref, _opp_kref_release, &opp->opp_table->lock); kref_put_mutex(&opp->kref, _opp_kref_release_locked,
&opp->opp_table->lock);
} }
EXPORT_SYMBOL_GPL(dev_pm_opp_put); EXPORT_SYMBOL_GPL(dev_pm_opp_put);
static void dev_pm_opp_put_unlocked(struct dev_pm_opp *opp)
{
kref_put(&opp->kref, _opp_kref_release_unlocked);
}
/** /**
* dev_pm_opp_remove() - Remove an OPP from OPP table * dev_pm_opp_remove() - Remove an OPP from OPP table
* @dev: device for which we do this operation * @dev: device for which we do this operation
@ -1060,6 +1079,40 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
} }
EXPORT_SYMBOL_GPL(dev_pm_opp_remove); EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
/**
* dev_pm_opp_remove_all_dynamic() - Remove all dynamically created OPPs
* @dev: device for which we do this operation
*
* This function removes all dynamically created OPPs from the opp table.
*/
void dev_pm_opp_remove_all_dynamic(struct device *dev)
{
struct opp_table *opp_table;
struct dev_pm_opp *opp, *temp;
int count = 0;
opp_table = _find_opp_table(dev);
if (IS_ERR(opp_table))
return;
mutex_lock(&opp_table->lock);
list_for_each_entry_safe(opp, temp, &opp_table->opp_list, node) {
if (opp->dynamic) {
dev_pm_opp_put_unlocked(opp);
count++;
}
}
mutex_unlock(&opp_table->lock);
/* Drop the references taken by dev_pm_opp_add() */
while (count--)
dev_pm_opp_put_opp_table(opp_table);
/* Drop the reference taken by _find_opp_table() */
dev_pm_opp_put_opp_table(opp_table);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_remove_all_dynamic);
struct dev_pm_opp *_opp_allocate(struct opp_table *table) struct dev_pm_opp *_opp_allocate(struct opp_table *table)
{ {
struct dev_pm_opp *opp; struct dev_pm_opp *opp;

Просмотреть файл

@ -108,6 +108,7 @@ void dev_pm_opp_put(struct dev_pm_opp *opp);
int dev_pm_opp_add(struct device *dev, unsigned long freq, int dev_pm_opp_add(struct device *dev, unsigned long freq,
unsigned long u_volt); unsigned long u_volt);
void dev_pm_opp_remove(struct device *dev, unsigned long freq); void dev_pm_opp_remove(struct device *dev, unsigned long freq);
void dev_pm_opp_remove_all_dynamic(struct device *dev);
int dev_pm_opp_enable(struct device *dev, unsigned long freq); int dev_pm_opp_enable(struct device *dev, unsigned long freq);
@ -217,6 +218,10 @@ static inline void dev_pm_opp_remove(struct device *dev, unsigned long freq)
{ {
} }
static inline void dev_pm_opp_remove_all_dynamic(struct device *dev)
{
}
static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq) static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq)
{ {
return 0; return 0;