Merge tag 'pm-5.2-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull more power management updates from Rafael Wysocki:
 "These fix a recent regression causing kernels built with CONFIG_PM
  unset to crash on systems that support the Performance and Energy Bias
  Hint (EPB), clean up the cpufreq core and some users of transition
  notifiers and introduce a new power domain flag into the generic power
  domains framework (genpd).

  Specifics:

   - Fix recent regression causing kernels built with CONFIG_PM unset to
     crash on systems that support the Performance and Energy Bias Hint
     (EPB) by avoiding to compile the EPB-related code depending on
     CONFIG_PM when it is unset (Rafael Wysocki).

   - Clean up the transition notifier invocation code in the cpufreq
     core and change some users of cpufreq transition notifiers
     accordingly (Viresh Kumar).

   - Change MAINTAINERS to cover the schedutil governor as part of
     cpufreq (Viresh Kumar).

   - Simplify cpufreq_init_policy() to avoid redundant computations (Yue
     Hu).

   - Add explanatory comment to the cpufreq core (Rafael Wysocki).

   - Introduce a new flag, GENPD_FLAG_RPM_ALWAYS_ON, to the generic
     power domains (genpd) framework along with the first user of it
     (Leonard Crestez)"

* tag 'pm-5.2-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  soc: imx: gpc: Use GENPD_FLAG_RPM_ALWAYS_ON for ERR009619
  PM / Domains: Add GENPD_FLAG_RPM_ALWAYS_ON flag
  cpufreq: Update MAINTAINERS to include schedutil governor
  cpufreq: Don't find governor for setpolicy drivers in cpufreq_init_policy()
  cpufreq: Explain the kobject_put() in cpufreq_policy_alloc()
  cpufreq: Call transition notifier only once for each policy
  x86: intel_epb: Take CONFIG_PM into account
Этот коммит содержится в:
Linus Torvalds
2019-05-15 08:46:44 -07:00
родитель 88f76bc31b 2a8d69f613
Коммит bfbfbf7368
11 изменённых файлов: 184 добавлений и 106 удалений

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

@@ -340,11 +340,14 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
struct cpufreq_freqs *freqs,
unsigned int state)
{
int cpu;
BUG_ON(irqs_disabled());
if (cpufreq_disabled())
return;
freqs->policy = policy;
freqs->flags = cpufreq_driver->flags;
pr_debug("notification %u of frequency transition to %u kHz\n",
state, freqs->new);
@@ -364,10 +367,8 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
}
}
for_each_cpu(freqs->cpu, policy->cpus) {
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
CPUFREQ_PRECHANGE, freqs);
}
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
CPUFREQ_PRECHANGE, freqs);
adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
break;
@@ -377,11 +378,11 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
pr_debug("FREQ: %u - CPUs: %*pbl\n", freqs->new,
cpumask_pr_args(policy->cpus));
for_each_cpu(freqs->cpu, policy->cpus) {
trace_cpu_frequency(freqs->new, freqs->cpu);
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
CPUFREQ_POSTCHANGE, freqs);
}
for_each_cpu(cpu, policy->cpus)
trace_cpu_frequency(freqs->new, cpu);
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
CPUFREQ_POSTCHANGE, freqs);
cpufreq_stats_record_transition(policy, freqs->new);
policy->cur = freqs->new;
@@ -618,50 +619,52 @@ static struct cpufreq_governor *find_governor(const char *str_governor)
return NULL;
}
static int cpufreq_parse_policy(char *str_governor,
struct cpufreq_policy *policy)
{
if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
return 0;
}
if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
policy->policy = CPUFREQ_POLICY_POWERSAVE;
return 0;
}
return -EINVAL;
}
/**
* cpufreq_parse_governor - parse a governor string
* cpufreq_parse_governor - parse a governor string only for !setpolicy
*/
static int cpufreq_parse_governor(char *str_governor,
struct cpufreq_policy *policy)
{
if (cpufreq_driver->setpolicy) {
if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
return 0;
}
struct cpufreq_governor *t;
if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
policy->policy = CPUFREQ_POLICY_POWERSAVE;
return 0;
}
} else {
struct cpufreq_governor *t;
mutex_lock(&cpufreq_governor_mutex);
t = find_governor(str_governor);
if (!t) {
int ret;
mutex_unlock(&cpufreq_governor_mutex);
ret = request_module("cpufreq_%s", str_governor);
if (ret)
return -EINVAL;
mutex_lock(&cpufreq_governor_mutex);
t = find_governor(str_governor);
if (!t) {
int ret;
}
if (t && !try_module_get(t->owner))
t = NULL;
mutex_unlock(&cpufreq_governor_mutex);
mutex_unlock(&cpufreq_governor_mutex);
ret = request_module("cpufreq_%s", str_governor);
if (ret)
return -EINVAL;
mutex_lock(&cpufreq_governor_mutex);
t = find_governor(str_governor);
}
if (t && !try_module_get(t->owner))
t = NULL;
mutex_unlock(&cpufreq_governor_mutex);
if (t) {
policy->governor = t;
return 0;
}
if (t) {
policy->governor = t;
return 0;
}
return -EINVAL;
@@ -783,8 +786,13 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
if (ret != 1)
return -EINVAL;
if (cpufreq_parse_governor(str_governor, &new_policy))
return -EINVAL;
if (cpufreq_driver->setpolicy) {
if (cpufreq_parse_policy(str_governor, &new_policy))
return -EINVAL;
} else {
if (cpufreq_parse_governor(str_governor, &new_policy))
return -EINVAL;
}
ret = cpufreq_set_policy(policy, &new_policy);
@@ -1050,32 +1058,39 @@ __weak struct cpufreq_governor *cpufreq_default_governor(void)
static int cpufreq_init_policy(struct cpufreq_policy *policy)
{
struct cpufreq_governor *gov = NULL;
struct cpufreq_governor *gov = NULL, *def_gov = NULL;
struct cpufreq_policy new_policy;
memcpy(&new_policy, policy, sizeof(*policy));
/* Update governor of new_policy to the governor used before hotplug */
gov = find_governor(policy->last_governor);
if (gov) {
pr_debug("Restoring governor %s for cpu %d\n",
def_gov = cpufreq_default_governor();
if (has_target()) {
/*
* Update governor of new_policy to the governor used before
* hotplug
*/
gov = find_governor(policy->last_governor);
if (gov) {
pr_debug("Restoring governor %s for cpu %d\n",
policy->governor->name, policy->cpu);
} else {
if (!def_gov)
return -ENODATA;
gov = def_gov;
}
new_policy.governor = gov;
} else {
gov = cpufreq_default_governor();
if (!gov)
return -ENODATA;
}
new_policy.governor = gov;
/* Use the default policy if there is no last_policy. */
if (cpufreq_driver->setpolicy) {
if (policy->last_policy)
/* Use the default policy if there is no last_policy. */
if (policy->last_policy) {
new_policy.policy = policy->last_policy;
else
cpufreq_parse_governor(gov->name, &new_policy);
} else {
if (!def_gov)
return -ENODATA;
cpufreq_parse_policy(def_gov->name, &new_policy);
}
}
/* set default policy */
return cpufreq_set_policy(policy, &new_policy);
}
@@ -1133,6 +1148,11 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
cpufreq_global_kobject, "policy%u", cpu);
if (ret) {
pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret);
/*
* The entire policy object will be freed below, but the extra
* memory allocated for the kobject name needs to be freed by
* releasing the kobject.
*/
kobject_put(&policy->kobj);
goto err_free_real_cpus;
}