Skip to content

Commit 2a8d69f

Browse files
committed
Merge branches 'pm-cpufreq' and 'pm-domains'
* pm-cpufreq: 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 * pm-domains: soc: imx: gpc: Use GENPD_FLAG_RPM_ALWAYS_ON for ERR009619 PM / Domains: Add GENPD_FLAG_RPM_ALWAYS_ON flag
3 parents 9ed0985 + 32345f4 + 8d5d766 commit 2a8d69f

File tree

10 files changed

+162
-104
lines changed

10 files changed

+162
-104
lines changed

MAINTAINERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4073,7 +4073,9 @@ F: Documentation/admin-guide/pm/intel_pstate.rst
40734073
F: Documentation/cpu-freq/
40744074
F: Documentation/devicetree/bindings/cpufreq/
40754075
F: drivers/cpufreq/
4076+
F: kernel/sched/cpufreq*.c
40764077
F: include/linux/cpufreq.h
4078+
F: include/linux/sched/cpufreq.h
40774079
F: tools/testing/selftests/cpufreq/
40784080

40794081
CPU FREQUENCY DRIVERS - ARM BIG LITTLE

arch/arm/kernel/smp.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -754,15 +754,20 @@ static int cpufreq_callback(struct notifier_block *nb,
754754
unsigned long val, void *data)
755755
{
756756
struct cpufreq_freqs *freq = data;
757-
int cpu = freq->cpu;
757+
struct cpumask *cpus = freq->policy->cpus;
758+
int cpu, first = cpumask_first(cpus);
759+
unsigned int lpj;
758760

759761
if (freq->flags & CPUFREQ_CONST_LOOPS)
760762
return NOTIFY_OK;
761763

762-
if (!per_cpu(l_p_j_ref, cpu)) {
763-
per_cpu(l_p_j_ref, cpu) =
764-
per_cpu(cpu_data, cpu).loops_per_jiffy;
765-
per_cpu(l_p_j_ref_freq, cpu) = freq->old;
764+
if (!per_cpu(l_p_j_ref, first)) {
765+
for_each_cpu(cpu, cpus) {
766+
per_cpu(l_p_j_ref, cpu) =
767+
per_cpu(cpu_data, cpu).loops_per_jiffy;
768+
per_cpu(l_p_j_ref_freq, cpu) = freq->old;
769+
}
770+
766771
if (!global_l_p_j_ref) {
767772
global_l_p_j_ref = loops_per_jiffy;
768773
global_l_p_j_ref_freq = freq->old;
@@ -774,10 +779,11 @@ static int cpufreq_callback(struct notifier_block *nb,
774779
loops_per_jiffy = cpufreq_scale(global_l_p_j_ref,
775780
global_l_p_j_ref_freq,
776781
freq->new);
777-
per_cpu(cpu_data, cpu).loops_per_jiffy =
778-
cpufreq_scale(per_cpu(l_p_j_ref, cpu),
779-
per_cpu(l_p_j_ref_freq, cpu),
780-
freq->new);
782+
783+
lpj = cpufreq_scale(per_cpu(l_p_j_ref, first),
784+
per_cpu(l_p_j_ref_freq, first), freq->new);
785+
for_each_cpu(cpu, cpus)
786+
per_cpu(cpu_data, cpu).loops_per_jiffy = lpj;
781787
}
782788
return NOTIFY_OK;
783789
}

arch/sparc/kernel/time_64.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -653,19 +653,23 @@ static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val
653653
void *data)
654654
{
655655
struct cpufreq_freqs *freq = data;
656-
unsigned int cpu = freq->cpu;
657-
struct freq_table *ft = &per_cpu(sparc64_freq_table, cpu);
656+
unsigned int cpu;
657+
struct freq_table *ft;
658658

659-
if (!ft->ref_freq) {
660-
ft->ref_freq = freq->old;
661-
ft->clock_tick_ref = cpu_data(cpu).clock_tick;
662-
}
663-
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
664-
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
665-
cpu_data(cpu).clock_tick =
666-
cpufreq_scale(ft->clock_tick_ref,
667-
ft->ref_freq,
668-
freq->new);
659+
for_each_cpu(cpu, freq->policy->cpus) {
660+
ft = &per_cpu(sparc64_freq_table, cpu);
661+
662+
if (!ft->ref_freq) {
663+
ft->ref_freq = freq->old;
664+
ft->clock_tick_ref = cpu_data(cpu).clock_tick;
665+
}
666+
667+
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
668+
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
669+
cpu_data(cpu).clock_tick =
670+
cpufreq_scale(ft->clock_tick_ref, ft->ref_freq,
671+
freq->new);
672+
}
669673
}
670674

671675
return 0;

arch/x86/kernel/tsc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
979979
if (!(freq->flags & CPUFREQ_CONST_LOOPS))
980980
mark_tsc_unstable("cpufreq changes");
981981

982-
set_cyc2ns_scale(tsc_khz, freq->cpu, rdtsc());
982+
set_cyc2ns_scale(tsc_khz, freq->policy->cpu, rdtsc());
983983
}
984984

985985
return 0;

arch/x86/kvm/x86.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6698,10 +6698,8 @@ static void kvm_hyperv_tsc_notifier(void)
66986698
}
66996699
#endif
67006700

6701-
static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
6702-
void *data)
6701+
static void __kvmclock_cpufreq_notifier(struct cpufreq_freqs *freq, int cpu)
67036702
{
6704-
struct cpufreq_freqs *freq = data;
67056703
struct kvm *kvm;
67066704
struct kvm_vcpu *vcpu;
67076705
int i, send_ipi = 0;
@@ -6745,17 +6743,12 @@ static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long va
67456743
*
67466744
*/
67476745

6748-
if (val == CPUFREQ_PRECHANGE && freq->old > freq->new)
6749-
return 0;
6750-
if (val == CPUFREQ_POSTCHANGE && freq->old < freq->new)
6751-
return 0;
6752-
6753-
smp_call_function_single(freq->cpu, tsc_khz_changed, freq, 1);
6746+
smp_call_function_single(cpu, tsc_khz_changed, freq, 1);
67546747

67556748
spin_lock(&kvm_lock);
67566749
list_for_each_entry(kvm, &vm_list, vm_list) {
67576750
kvm_for_each_vcpu(i, vcpu, kvm) {
6758-
if (vcpu->cpu != freq->cpu)
6751+
if (vcpu->cpu != cpu)
67596752
continue;
67606753
kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
67616754
if (vcpu->cpu != smp_processor_id())
@@ -6777,8 +6770,24 @@ static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long va
67776770
* guest context is entered kvmclock will be updated,
67786771
* so the guest will not see stale values.
67796772
*/
6780-
smp_call_function_single(freq->cpu, tsc_khz_changed, freq, 1);
6773+
smp_call_function_single(cpu, tsc_khz_changed, freq, 1);
67816774
}
6775+
}
6776+
6777+
static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
6778+
void *data)
6779+
{
6780+
struct cpufreq_freqs *freq = data;
6781+
int cpu;
6782+
6783+
if (val == CPUFREQ_PRECHANGE && freq->old > freq->new)
6784+
return 0;
6785+
if (val == CPUFREQ_POSTCHANGE && freq->old < freq->new)
6786+
return 0;
6787+
6788+
for_each_cpu(cpu, freq->policy->cpus)
6789+
__kvmclock_cpufreq_notifier(freq, cpu);
6790+
67826791
return 0;
67836792
}
67846793

drivers/base/power/domain.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ static const struct genpd_lock_ops genpd_spin_ops = {
130130
#define genpd_is_always_on(genpd) (genpd->flags & GENPD_FLAG_ALWAYS_ON)
131131
#define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP)
132132
#define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN)
133+
#define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON)
133134

134135
static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev,
135136
const struct generic_pm_domain *genpd)
@@ -517,7 +518,9 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
517518
* (1) The domain is configured as always on.
518519
* (2) When the domain has a subdomain being powered on.
519520
*/
520-
if (genpd_is_always_on(genpd) || atomic_read(&genpd->sd_count) > 0)
521+
if (genpd_is_always_on(genpd) ||
522+
genpd_is_rpm_always_on(genpd) ||
523+
atomic_read(&genpd->sd_count) > 0)
521524
return -EBUSY;
522525

523526
list_for_each_entry(pdd, &genpd->dev_list, list_node) {
@@ -1814,7 +1817,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
18141817
}
18151818

18161819
/* Always-on domains must be powered on at initialization. */
1817-
if (genpd_is_always_on(genpd) && !genpd_status_on(genpd))
1820+
if ((genpd_is_always_on(genpd) || genpd_is_rpm_always_on(genpd)) &&
1821+
!genpd_status_on(genpd))
18181822
return -EINVAL;
18191823

18201824
if (genpd_is_cpu_domain(genpd) &&

drivers/cpufreq/cpufreq.c

Lines changed: 80 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -340,11 +340,14 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
340340
struct cpufreq_freqs *freqs,
341341
unsigned int state)
342342
{
343+
int cpu;
344+
343345
BUG_ON(irqs_disabled());
344346

345347
if (cpufreq_disabled())
346348
return;
347349

350+
freqs->policy = policy;
348351
freqs->flags = cpufreq_driver->flags;
349352
pr_debug("notification %u of frequency transition to %u kHz\n",
350353
state, freqs->new);
@@ -364,10 +367,8 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
364367
}
365368
}
366369

367-
for_each_cpu(freqs->cpu, policy->cpus) {
368-
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
369-
CPUFREQ_PRECHANGE, freqs);
370-
}
370+
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
371+
CPUFREQ_PRECHANGE, freqs);
371372

372373
adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
373374
break;
@@ -377,11 +378,11 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
377378
pr_debug("FREQ: %u - CPUs: %*pbl\n", freqs->new,
378379
cpumask_pr_args(policy->cpus));
379380

380-
for_each_cpu(freqs->cpu, policy->cpus) {
381-
trace_cpu_frequency(freqs->new, freqs->cpu);
382-
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
383-
CPUFREQ_POSTCHANGE, freqs);
384-
}
381+
for_each_cpu(cpu, policy->cpus)
382+
trace_cpu_frequency(freqs->new, cpu);
383+
384+
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
385+
CPUFREQ_POSTCHANGE, freqs);
385386

386387
cpufreq_stats_record_transition(policy, freqs->new);
387388
policy->cur = freqs->new;
@@ -618,50 +619,52 @@ static struct cpufreq_governor *find_governor(const char *str_governor)
618619
return NULL;
619620
}
620621

622+
static int cpufreq_parse_policy(char *str_governor,
623+
struct cpufreq_policy *policy)
624+
{
625+
if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
626+
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
627+
return 0;
628+
}
629+
if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
630+
policy->policy = CPUFREQ_POLICY_POWERSAVE;
631+
return 0;
632+
}
633+
return -EINVAL;
634+
}
635+
621636
/**
622-
* cpufreq_parse_governor - parse a governor string
637+
* cpufreq_parse_governor - parse a governor string only for !setpolicy
623638
*/
624639
static int cpufreq_parse_governor(char *str_governor,
625640
struct cpufreq_policy *policy)
626641
{
627-
if (cpufreq_driver->setpolicy) {
628-
if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
629-
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
630-
return 0;
631-
}
642+
struct cpufreq_governor *t;
632643

633-
if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
634-
policy->policy = CPUFREQ_POLICY_POWERSAVE;
635-
return 0;
636-
}
637-
} else {
638-
struct cpufreq_governor *t;
644+
mutex_lock(&cpufreq_governor_mutex);
639645

640-
mutex_lock(&cpufreq_governor_mutex);
646+
t = find_governor(str_governor);
647+
if (!t) {
648+
int ret;
641649

642-
t = find_governor(str_governor);
643-
if (!t) {
644-
int ret;
645-
646-
mutex_unlock(&cpufreq_governor_mutex);
650+
mutex_unlock(&cpufreq_governor_mutex);
647651

648-
ret = request_module("cpufreq_%s", str_governor);
649-
if (ret)
650-
return -EINVAL;
652+
ret = request_module("cpufreq_%s", str_governor);
653+
if (ret)
654+
return -EINVAL;
651655

652-
mutex_lock(&cpufreq_governor_mutex);
656+
mutex_lock(&cpufreq_governor_mutex);
653657

654-
t = find_governor(str_governor);
655-
}
656-
if (t && !try_module_get(t->owner))
657-
t = NULL;
658+
t = find_governor(str_governor);
659+
}
660+
if (t && !try_module_get(t->owner))
661+
t = NULL;
658662

659-
mutex_unlock(&cpufreq_governor_mutex);
663+
mutex_unlock(&cpufreq_governor_mutex);
660664

661-
if (t) {
662-
policy->governor = t;
663-
return 0;
664-
}
665+
if (t) {
666+
policy->governor = t;
667+
return 0;
665668
}
666669

667670
return -EINVAL;
@@ -783,8 +786,13 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
783786
if (ret != 1)
784787
return -EINVAL;
785788

786-
if (cpufreq_parse_governor(str_governor, &new_policy))
787-
return -EINVAL;
789+
if (cpufreq_driver->setpolicy) {
790+
if (cpufreq_parse_policy(str_governor, &new_policy))
791+
return -EINVAL;
792+
} else {
793+
if (cpufreq_parse_governor(str_governor, &new_policy))
794+
return -EINVAL;
795+
}
788796

789797
ret = cpufreq_set_policy(policy, &new_policy);
790798

@@ -1050,32 +1058,39 @@ __weak struct cpufreq_governor *cpufreq_default_governor(void)
10501058

10511059
static int cpufreq_init_policy(struct cpufreq_policy *policy)
10521060
{
1053-
struct cpufreq_governor *gov = NULL;
1061+
struct cpufreq_governor *gov = NULL, *def_gov = NULL;
10541062
struct cpufreq_policy new_policy;
10551063

10561064
memcpy(&new_policy, policy, sizeof(*policy));
10571065

1058-
/* Update governor of new_policy to the governor used before hotplug */
1059-
gov = find_governor(policy->last_governor);
1060-
if (gov) {
1061-
pr_debug("Restoring governor %s for cpu %d\n",
1066+
def_gov = cpufreq_default_governor();
1067+
1068+
if (has_target()) {
1069+
/*
1070+
* Update governor of new_policy to the governor used before
1071+
* hotplug
1072+
*/
1073+
gov = find_governor(policy->last_governor);
1074+
if (gov) {
1075+
pr_debug("Restoring governor %s for cpu %d\n",
10621076
policy->governor->name, policy->cpu);
1077+
} else {
1078+
if (!def_gov)
1079+
return -ENODATA;
1080+
gov = def_gov;
1081+
}
1082+
new_policy.governor = gov;
10631083
} else {
1064-
gov = cpufreq_default_governor();
1065-
if (!gov)
1066-
return -ENODATA;
1067-
}
1068-
1069-
new_policy.governor = gov;
1070-
1071-
/* Use the default policy if there is no last_policy. */
1072-
if (cpufreq_driver->setpolicy) {
1073-
if (policy->last_policy)
1084+
/* Use the default policy if there is no last_policy. */
1085+
if (policy->last_policy) {
10741086
new_policy.policy = policy->last_policy;
1075-
else
1076-
cpufreq_parse_governor(gov->name, &new_policy);
1087+
} else {
1088+
if (!def_gov)
1089+
return -ENODATA;
1090+
cpufreq_parse_policy(def_gov->name, &new_policy);
1091+
}
10771092
}
1078-
/* set default policy */
1093+
10791094
return cpufreq_set_policy(policy, &new_policy);
10801095
}
10811096

@@ -1133,6 +1148,11 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
11331148
cpufreq_global_kobject, "policy%u", cpu);
11341149
if (ret) {
11351150
pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret);
1151+
/*
1152+
* The entire policy object will be freed below, but the extra
1153+
* memory allocated for the kobject name needs to be freed by
1154+
* releasing the kobject.
1155+
*/
11361156
kobject_put(&policy->kobj);
11371157
goto err_free_real_cpus;
11381158
}

0 commit comments

Comments
 (0)