Skip to content

Commit 6f9baa9

Browse files
committed
Merge tag 'pm-6.13-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull more power management updates from Rafael Wysocki: "These mostly are updates of cpufreq drivers used on ARM platforms plus one new DT-based cpufreq driver for virtualized guests and two cpuidle changes that should not make any difference on systems currently in the field, but will be needed for future development: - Add virtual cpufreq driver for guest kernels (David Dai) - Minor cleanup to various cpufreq drivers (Andy Shevchenko, Dhruva Gole, Jie Zhan, Jinjie Ruan, Shuosheng Huang, Sibi Sankar, and Yuan Can) - Revert "cpufreq: brcmstb-avs-cpufreq: Fix initial command check" (Colin Ian King) - Improve DT bindings for qcom-hw driver (Dmitry Baryshkov, Konrad Dybcio, and Nikunj Kela) - Make cpuidle_play_dead() try all idle states with :enter_dead() callbacks and change their return type to void (Rafael Wysocki)" * tag 'pm-6.13-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (22 commits) cpuidle: Change :enter_dead() driver callback return type to void cpuidle: Do not return from cpuidle_play_dead() on callback failures arm64: dts: qcom: sc8180x: Add a SoC-specific compatible to cpufreq-hw dt-bindings: cpufreq: cpufreq-qcom-hw: Add SC8180X compatible cpufreq: sun50i: add a100 cpufreq support cpufreq: mediatek-hw: Fix wrong return value in mtk_cpufreq_get_cpu_power() cpufreq: CPPC: Fix wrong return value in cppc_get_cpu_power() cpufreq: CPPC: Fix wrong return value in cppc_get_cpu_cost() cpufreq: loongson3: Check for error code from devm_mutex_init() call cpufreq: scmi: Fix cleanup path when boost enablement fails cpufreq: CPPC: Fix possible null-ptr-deref for cppc_get_cpu_cost() cpufreq: CPPC: Fix possible null-ptr-deref for cpufreq_cpu_get_raw() Revert "cpufreq: brcmstb-avs-cpufreq: Fix initial command check" dt-bindings: cpufreq: cpufreq-qcom-hw: Add SAR2130P compatible cpufreq: add virtual-cpufreq driver dt-bindings: cpufreq: add virtual cpufreq device cpufreq: loongson2: Unregister platform_driver on failure cpufreq: ti-cpufreq: Remove revision offsets in AM62 family cpufreq: ti-cpufreq: Allow backward compatibility for efuse syscon cppc_cpufreq: Remove HiSilicon CPPC workaround ...
2 parents 619d996 + f3e66e7 commit 6f9baa9

19 files changed

+517
-103
lines changed

Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ properties:
2323
- enum:
2424
- qcom,qcm2290-cpufreq-hw
2525
- qcom,sc7180-cpufreq-hw
26+
- qcom,sc8180x-cpufreq-hw
2627
- qcom,sdm670-cpufreq-hw
2728
- qcom,sdm845-cpufreq-hw
2829
- qcom,sm6115-cpufreq-hw
@@ -34,7 +35,9 @@ properties:
3435
items:
3536
- enum:
3637
- qcom,qdu1000-cpufreq-epss
38+
- qcom,sa8255p-cpufreq-epss
3739
- qcom,sa8775p-cpufreq-epss
40+
- qcom,sar2130p-cpufreq-epss
3841
- qcom,sc7280-cpufreq-epss
3942
- qcom,sc8280xp-cpufreq-epss
4043
- qcom,sdx75-cpufreq-epss
@@ -107,6 +110,7 @@ allOf:
107110
contains:
108111
enum:
109112
- qcom,qcm2290-cpufreq-hw
113+
- qcom,sar2130p-cpufreq-epss
110114
then:
111115
properties:
112116
reg:
@@ -130,7 +134,9 @@ allOf:
130134
contains:
131135
enum:
132136
- qcom,qdu1000-cpufreq-epss
137+
- qcom,sa8255p-cpufreq-epss
133138
- qcom,sc7180-cpufreq-hw
139+
- qcom,sc8180x-cpufreq-hw
134140
- qcom,sc8280xp-cpufreq-epss
135141
- qcom,sdm670-cpufreq-hw
136142
- qcom,sdm845-cpufreq-hw
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/cpufreq/qemu,virtual-cpufreq.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: Virtual CPUFreq
8+
9+
maintainers:
10+
- David Dai <[email protected]>
11+
- Saravana Kannan <[email protected]>
12+
13+
description:
14+
Virtual CPUFreq is a virtualized driver in guest kernels that sends performance
15+
selection of its vCPUs as a hint to the host through MMIO regions. Each vCPU
16+
is associated with a performance domain which can be shared with other vCPUs.
17+
Each performance domain has its own set of registers for performance controls.
18+
19+
properties:
20+
compatible:
21+
const: qemu,virtual-cpufreq
22+
23+
reg:
24+
maxItems: 1
25+
description:
26+
Address and size of region containing performance controls for each of the
27+
performance domains. Regions for each performance domain is placed
28+
contiguously and contain registers for controlling DVFS(Dynamic Frequency
29+
and Voltage) characteristics. The size of the region is proportional to
30+
total number of performance domains.
31+
32+
required:
33+
- compatible
34+
- reg
35+
36+
additionalProperties: false
37+
38+
examples:
39+
- |
40+
soc {
41+
#address-cells = <1>;
42+
#size-cells = <1>;
43+
44+
cpufreq@1040000 {
45+
compatible = "qemu,virtual-cpufreq";
46+
reg = <0x1040000 0x2000>;
47+
};
48+
};

arch/arm64/boot/dts/qcom/sc8180x.dtsi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3889,7 +3889,7 @@
38893889
};
38903890

38913891
cpufreq_hw: cpufreq@18323000 {
3892-
compatible = "qcom,cpufreq-hw";
3892+
compatible = "qcom,sc8180x-cpufreq-hw", "qcom,cpufreq-hw";
38933893
reg = <0 0x18323000 0 0x1400>, <0 0x18325800 0 0x1400>;
38943894
reg-names = "freq-domain0", "freq-domain1";
38953895

drivers/acpi/processor_idle.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ static void __cpuidle acpi_idle_do_entry(struct acpi_processor_cx *cx)
578578
* @dev: the target CPU
579579
* @index: the index of suggested state
580580
*/
581-
static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
581+
static void acpi_idle_play_dead(struct cpuidle_device *dev, int index)
582582
{
583583
struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
584584

@@ -591,11 +591,8 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
591591
else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) {
592592
io_idle(cx->address);
593593
} else
594-
return -ENODEV;
594+
return;
595595
}
596-
597-
/* Never reached */
598-
return 0;
599596
}
600597

601598
static __always_inline bool acpi_idle_fallback_to_c1(struct acpi_processor *pr)

drivers/cpufreq/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,20 @@ config CPUFREQ_DT
217217

218218
If in doubt, say N.
219219

220+
config CPUFREQ_VIRT
221+
tristate "Virtual cpufreq driver"
222+
depends on GENERIC_ARCH_TOPOLOGY
223+
help
224+
This adds a virtualized cpufreq driver for guest kernels that
225+
read/writes to a MMIO region for a virtualized cpufreq device to
226+
communicate with the host. It sends performance requests to the host
227+
which gets used as a hint to schedule vCPU threads and select CPU
228+
frequency. If a VM does not support a virtualized FIE such as AMUs,
229+
it updates the frequency scaling factor by polling host CPU frequency
230+
to enable accurate Per-Entity Load Tracking for tasks running in the guest.
231+
232+
If in doubt, say N.
233+
220234
config CPUFREQ_DT_PLATDEV
221235
tristate "Generic DT based cpufreq platdev driver"
222236
depends on OF

drivers/cpufreq/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o
1616

1717
obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o
1818
obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o
19+
obj-$(CONFIG_CPUFREQ_VIRT) += virtual-cpufreq.o
1920

2021
# Traces
2122
CFLAGS_amd-pstate-trace.o := -I$(src)

drivers/cpufreq/brcmstb-avs-cpufreq.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,8 +474,8 @@ static bool brcm_avs_is_firmware_loaded(struct private_data *priv)
474474
rc = brcm_avs_get_pmap(priv, NULL);
475475
magic = readl(priv->base + AVS_MBOX_MAGIC);
476476

477-
return (magic == AVS_FIRMWARE_MAGIC) && ((rc != -ENOTSUPP) ||
478-
(rc != -EINVAL));
477+
return (magic == AVS_FIRMWARE_MAGIC) && (rc != -ENOTSUPP) &&
478+
(rc != -EINVAL);
479479
}
480480

481481
static unsigned int brcm_avs_cpufreq_get(unsigned int cpu)

drivers/cpufreq/cppc_cpufreq.c

Lines changed: 53 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -36,33 +36,15 @@ static LIST_HEAD(cpu_data_list);
3636

3737
static bool boost_supported;
3838

39-
struct cppc_workaround_oem_info {
40-
char oem_id[ACPI_OEM_ID_SIZE + 1];
41-
char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
42-
u32 oem_revision;
43-
};
44-
45-
static struct cppc_workaround_oem_info wa_info[] = {
46-
{
47-
.oem_id = "HISI ",
48-
.oem_table_id = "HIP07 ",
49-
.oem_revision = 0,
50-
}, {
51-
.oem_id = "HISI ",
52-
.oem_table_id = "HIP08 ",
53-
.oem_revision = 0,
54-
}
55-
};
56-
5739
static struct cpufreq_driver cppc_cpufreq_driver;
5840

41+
#ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
5942
static enum {
6043
FIE_UNSET = -1,
6144
FIE_ENABLED,
6245
FIE_DISABLED
6346
} fie_disabled = FIE_UNSET;
6447

65-
#ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
6648
module_param(fie_disabled, int, 0444);
6749
MODULE_PARM_DESC(fie_disabled, "Disable Frequency Invariance Engine (FIE)");
6850

@@ -78,7 +60,6 @@ struct cppc_freq_invariance {
7860
static DEFINE_PER_CPU(struct cppc_freq_invariance, cppc_freq_inv);
7961
static struct kthread_worker *kworker_fie;
8062

81-
static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu);
8263
static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data,
8364
struct cppc_perf_fb_ctrs *fb_ctrs_t0,
8465
struct cppc_perf_fb_ctrs *fb_ctrs_t1);
@@ -118,6 +99,9 @@ static void cppc_scale_freq_workfn(struct kthread_work *work)
11899

119100
perf = cppc_perf_from_fbctrs(cpu_data, &cppc_fi->prev_perf_fb_ctrs,
120101
&fb_ctrs);
102+
if (!perf)
103+
return;
104+
121105
cppc_fi->prev_perf_fb_ctrs = fb_ctrs;
122106

123107
perf <<= SCHED_CAPACITY_SHIFT;
@@ -420,6 +404,9 @@ static int cppc_get_cpu_power(struct device *cpu_dev,
420404
struct cppc_cpudata *cpu_data;
421405

422406
policy = cpufreq_cpu_get_raw(cpu_dev->id);
407+
if (!policy)
408+
return -EINVAL;
409+
423410
cpu_data = policy->driver_data;
424411
perf_caps = &cpu_data->perf_caps;
425412
max_cap = arch_scale_cpu_capacity(cpu_dev->id);
@@ -487,6 +474,9 @@ static int cppc_get_cpu_cost(struct device *cpu_dev, unsigned long KHz,
487474
int step;
488475

489476
policy = cpufreq_cpu_get_raw(cpu_dev->id);
477+
if (!policy)
478+
return -EINVAL;
479+
490480
cpu_data = policy->driver_data;
491481
perf_caps = &cpu_data->perf_caps;
492482
max_cap = arch_scale_cpu_capacity(cpu_dev->id);
@@ -724,13 +714,31 @@ static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data,
724714
delta_delivered = get_delta(fb_ctrs_t1->delivered,
725715
fb_ctrs_t0->delivered);
726716

727-
/* Check to avoid divide-by zero and invalid delivered_perf */
717+
/*
718+
* Avoid divide-by zero and unchanged feedback counters.
719+
* Leave it for callers to handle.
720+
*/
728721
if (!delta_reference || !delta_delivered)
729-
return cpu_data->perf_ctrls.desired_perf;
722+
return 0;
730723

731724
return (reference_perf * delta_delivered) / delta_reference;
732725
}
733726

727+
static int cppc_get_perf_ctrs_sample(int cpu,
728+
struct cppc_perf_fb_ctrs *fb_ctrs_t0,
729+
struct cppc_perf_fb_ctrs *fb_ctrs_t1)
730+
{
731+
int ret;
732+
733+
ret = cppc_get_perf_ctrs(cpu, fb_ctrs_t0);
734+
if (ret)
735+
return ret;
736+
737+
udelay(2); /* 2usec delay between sampling */
738+
739+
return cppc_get_perf_ctrs(cpu, fb_ctrs_t1);
740+
}
741+
734742
static unsigned int cppc_cpufreq_get_rate(unsigned int cpu)
735743
{
736744
struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0};
@@ -746,18 +754,32 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpu)
746754

747755
cpufreq_cpu_put(policy);
748756

749-
ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t0);
750-
if (ret)
751-
return 0;
752-
753-
udelay(2); /* 2usec delay between sampling */
754-
755-
ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t1);
756-
if (ret)
757-
return 0;
757+
ret = cppc_get_perf_ctrs_sample(cpu, &fb_ctrs_t0, &fb_ctrs_t1);
758+
if (ret) {
759+
if (ret == -EFAULT)
760+
/* Any of the associated CPPC regs is 0. */
761+
goto out_invalid_counters;
762+
else
763+
return 0;
764+
}
758765

759766
delivered_perf = cppc_perf_from_fbctrs(cpu_data, &fb_ctrs_t0,
760767
&fb_ctrs_t1);
768+
if (!delivered_perf)
769+
goto out_invalid_counters;
770+
771+
return cppc_perf_to_khz(&cpu_data->perf_caps, delivered_perf);
772+
773+
out_invalid_counters:
774+
/*
775+
* Feedback counters could be unchanged or 0 when a cpu enters a
776+
* low-power idle state, e.g. clock-gated or power-gated.
777+
* Use desired perf for reflecting frequency. Get the latest register
778+
* value first as some platforms may update the actual delivered perf
779+
* there; if failed, resort to the cached desired perf.
780+
*/
781+
if (cppc_get_desired_perf(cpu, &delivered_perf))
782+
delivered_perf = cpu_data->perf_ctrls.desired_perf;
761783

762784
return cppc_perf_to_khz(&cpu_data->perf_caps, delivered_perf);
763785
}
@@ -812,65 +834,13 @@ static struct cpufreq_driver cppc_cpufreq_driver = {
812834
.name = "cppc_cpufreq",
813835
};
814836

815-
/*
816-
* HISI platform does not support delivered performance counter and
817-
* reference performance counter. It can calculate the performance using the
818-
* platform specific mechanism. We reuse the desired performance register to
819-
* store the real performance calculated by the platform.
820-
*/
821-
static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu)
822-
{
823-
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
824-
struct cppc_cpudata *cpu_data;
825-
u64 desired_perf;
826-
int ret;
827-
828-
if (!policy)
829-
return -ENODEV;
830-
831-
cpu_data = policy->driver_data;
832-
833-
cpufreq_cpu_put(policy);
834-
835-
ret = cppc_get_desired_perf(cpu, &desired_perf);
836-
if (ret < 0)
837-
return -EIO;
838-
839-
return cppc_perf_to_khz(&cpu_data->perf_caps, desired_perf);
840-
}
841-
842-
static void cppc_check_hisi_workaround(void)
843-
{
844-
struct acpi_table_header *tbl;
845-
acpi_status status = AE_OK;
846-
int i;
847-
848-
status = acpi_get_table(ACPI_SIG_PCCT, 0, &tbl);
849-
if (ACPI_FAILURE(status) || !tbl)
850-
return;
851-
852-
for (i = 0; i < ARRAY_SIZE(wa_info); i++) {
853-
if (!memcmp(wa_info[i].oem_id, tbl->oem_id, ACPI_OEM_ID_SIZE) &&
854-
!memcmp(wa_info[i].oem_table_id, tbl->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
855-
wa_info[i].oem_revision == tbl->oem_revision) {
856-
/* Overwrite the get() callback */
857-
cppc_cpufreq_driver.get = hisi_cppc_cpufreq_get_rate;
858-
fie_disabled = FIE_DISABLED;
859-
break;
860-
}
861-
}
862-
863-
acpi_put_table(tbl);
864-
}
865-
866837
static int __init cppc_cpufreq_init(void)
867838
{
868839
int ret;
869840

870841
if (!acpi_cpc_valid())
871842
return -ENODEV;
872843

873-
cppc_check_hisi_workaround();
874844
cppc_freq_invariance_init();
875845
populate_efficiency_class();
876846

drivers/cpufreq/cpufreq-dt-platdev.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ static const struct of_device_id allowlist[] __initconst = {
103103
* platforms using "operating-points-v2" property.
104104
*/
105105
static const struct of_device_id blocklist[] __initconst = {
106+
{ .compatible = "allwinner,sun50i-a100" },
106107
{ .compatible = "allwinner,sun50i-h6", },
107108
{ .compatible = "allwinner,sun50i-h616", },
108109
{ .compatible = "allwinner,sun50i-h618", },

drivers/cpufreq/loongson2_cpufreq.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,9 @@ static int __init cpufreq_init(void)
148148

149149
ret = cpufreq_register_driver(&loongson2_cpufreq_driver);
150150

151-
if (!ret && !nowait) {
151+
if (ret) {
152+
platform_driver_unregister(&platform_driver);
153+
} else if (!nowait) {
152154
saved_cpu_wait = cpu_wait;
153155
cpu_wait = loongson2_cpu_wait;
154156
}

0 commit comments

Comments
 (0)