Skip to content

Commit aef4226

Browse files
committed
Merge tag 'pm-5.14-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull more power management updates from Rafael Wysocki: "These include cpufreq core simplifications and fixes, cpufreq driver updates, cpuidle driver update, a generic power domains (genpd) locking fix and a debug-related simplification of the PM core. Specifics: - Drop the ->stop_cpu() (not really useful) and ->resolve_freq() (unused) cpufreq driver callbacks and modify the users of the former accordingly (Viresh Kumar, Rafael Wysocki). - Add frequency invariance support to the ACPI CPPC cpufreq driver again along with the related fixes and cleanups (Viresh Kumar). - Update the Meditak, qcom and SCMI ARM cpufreq drivers (Fabien Parent, Seiya Wang, Sibi Sankar, Christophe JAILLET). - Rename black/white-lists in the DT cpufreq driver (Viresh Kumar). - Add generic performance domains support to the dvfs DT bindings (Sudeep Holla). - Refine locking in the generic power domains (genpd) support code to avoid lock dependency issues (Stephen Boyd). - Update the MSM and qcom ARM cpuidle drivers (Bartosz Dudziak). - Simplify the PM core debug code by using ktime_us_delta() to compute time interval lengths (Mark-PK Tsai)" * tag 'pm-5.14-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (21 commits) PM: domains: Shrink locking area of the gpd_list_lock PM: sleep: Use ktime_us_delta() in initcall_debug_report() cpufreq: CPPC: Add support for frequency invariance arch_topology: Avoid use-after-free for scale_freq_data cpufreq: CPPC: Pass structure instance by reference cpufreq: CPPC: Fix potential memleak in cppc_cpufreq_cpu_init cpufreq: Remove ->resolve_freq() cpufreq: Reuse cpufreq_driver_resolve_freq() in __cpufreq_driver_target() cpufreq: Remove the ->stop_cpu() driver callback cpufreq: powernv: Migrate to ->exit() callback instead of ->stop_cpu() cpufreq: CPPC: Migrate to ->exit() callback instead of ->stop_cpu() cpufreq: intel_pstate: Combine ->stop_cpu() and ->offline() cpuidle: qcom: Add SPM register data for MSM8226 dt-bindings: arm: msm: Add SAW2 for MSM8226 dt-bindings: cpufreq: update cpu type and clock name for MT8173 SoC clk: mediatek: remove deprecated CLK_INFRA_CA57SEL for MT8173 SoC cpufreq: dt: Rename black/white-lists cpufreq: scmi: Fix an error message cpufreq: mediatek: add support for mt8365 dt-bindings: dvfs: Add support for generic performance domains ...
2 parents c6e8c51 + 843372d commit aef4226

File tree

22 files changed

+474
-149
lines changed

22 files changed

+474
-149
lines changed

Documentation/cpu-freq/cpu-drivers.rst

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,6 @@ And optionally
5858

5959
.driver_data - cpufreq driver specific data.
6060

61-
.resolve_freq - Returns the most appropriate frequency for a target
62-
frequency. Doesn't change the frequency though.
63-
6461
.get_intermediate and target_intermediate - Used to switch to stable
6562
frequency while changing CPU frequency.
6663

@@ -71,9 +68,6 @@ And optionally
7168
.exit - A pointer to a per-policy cleanup function called during
7269
CPU_POST_DEAD phase of cpu hotplug process.
7370

74-
.stop_cpu - A pointer to a per-policy stop function called during
75-
CPU_DOWN_PREPARE phase of cpu hotplug process.
76-
7771
.suspend - A pointer to a per-policy suspend function which is called
7872
with interrupts disabled and _after_ the governor is stopped for the
7973
policy.

Documentation/devicetree/bindings/arm/cpus.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,13 @@ properties:
257257

258258
where voltage is in V, frequency is in MHz.
259259

260+
performance-domains:
261+
maxItems: 1
262+
description:
263+
List of phandles and performance domain specifiers, as defined by
264+
bindings of the performance domain provider. See also
265+
dvfs/performance-domain.yaml.
266+
260267
power-domains:
261268
description:
262269
List of phandles and PM domain specifiers, as defined by bindings of the

Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ PROPERTIES
2525
"qcom,saw2"
2626
A more specific value could be one of:
2727
"qcom,apq8064-saw2-v1.1-cpu"
28+
"qcom,msm8226-saw2-v2.1-cpu"
2829
"qcom,msm8974-saw2-v2.1-cpu"
2930
"qcom,apq8084-saw2-v2.1-cpu"
3031

Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,23 +202,23 @@ Example 2 (MT8173 SoC):
202202

203203
cpu2: cpu@100 {
204204
device_type = "cpu";
205-
compatible = "arm,cortex-a57";
205+
compatible = "arm,cortex-a72";
206206
reg = <0x100>;
207207
enable-method = "psci";
208208
cpu-idle-states = <&CPU_SLEEP_0>;
209-
clocks = <&infracfg CLK_INFRA_CA57SEL>,
209+
clocks = <&infracfg CLK_INFRA_CA72SEL>,
210210
<&apmixedsys CLK_APMIXED_MAINPLL>;
211211
clock-names = "cpu", "intermediate";
212212
operating-points-v2 = <&cpu_opp_table_b>;
213213
};
214214

215215
cpu3: cpu@101 {
216216
device_type = "cpu";
217-
compatible = "arm,cortex-a57";
217+
compatible = "arm,cortex-a72";
218218
reg = <0x101>;
219219
enable-method = "psci";
220220
cpu-idle-states = <&CPU_SLEEP_0>;
221-
clocks = <&infracfg CLK_INFRA_CA57SEL>,
221+
clocks = <&infracfg CLK_INFRA_CA72SEL>,
222222
<&apmixedsys CLK_APMIXED_MAINPLL>;
223223
clock-names = "cpu", "intermediate";
224224
operating-points-v2 = <&cpu_opp_table_b>;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/dvfs/performance-domain.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: Generic performance domains
8+
9+
maintainers:
10+
- Sudeep Holla <[email protected]>
11+
12+
description: |+
13+
This binding is intended for performance management of groups of devices or
14+
CPUs that run in the same performance domain. Performance domains must not
15+
be confused with power domains. A performance domain is defined by a set
16+
of devices that always have to run at the same performance level. For a given
17+
performance domain, there is a single point of control that affects all the
18+
devices in the domain, making it impossible to set the performance level of
19+
an individual device in the domain independently from other devices in
20+
that domain. For example, a set of CPUs that share a voltage domain, and
21+
have a common frequency control, is said to be in the same performance
22+
domain.
23+
24+
This device tree binding can be used to bind performance domain consumer
25+
devices with their performance domains provided by performance domain
26+
providers. A performance domain provider can be represented by any node in
27+
the device tree and can provide one or more performance domains. A consumer
28+
node can refer to the provider by a phandle and a set of phandle arguments
29+
(so called performance domain specifiers) of length specified by the
30+
\#performance-domain-cells property in the performance domain provider node.
31+
32+
select: true
33+
34+
properties:
35+
"#performance-domain-cells":
36+
description:
37+
Number of cells in a performance domain specifier. Typically 0 for nodes
38+
representing a single performance domain and 1 for nodes providing
39+
multiple performance domains (e.g. performance controllers), but can be
40+
any value as specified by device tree binding documentation of particular
41+
provider.
42+
enum: [ 0, 1 ]
43+
44+
performance-domains:
45+
$ref: '/schemas/types.yaml#/definitions/phandle-array'
46+
maxItems: 1
47+
description:
48+
A phandle and performance domain specifier as defined by bindings of the
49+
performance controller/provider specified by phandle.
50+
51+
additionalProperties: true
52+
53+
examples:
54+
- |
55+
performance: performance-controller@12340000 {
56+
compatible = "qcom,cpufreq-hw";
57+
reg = <0x12340000 0x1000>;
58+
#performance-domain-cells = <1>;
59+
};
60+
61+
// The node above defines a performance controller that is a performance
62+
// domain provider and expects one cell as its phandle argument.
63+
64+
cpus {
65+
#address-cells = <2>;
66+
#size-cells = <0>;
67+
68+
cpu@0 {
69+
device_type = "cpu";
70+
compatible = "arm,cortex-a57";
71+
reg = <0x0 0x0>;
72+
performance-domains = <&performance 1>;
73+
};
74+
};

Documentation/translations/zh_CN/cpu-freq/cpu-drivers.rst

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ CPUfreq核心层注册一个cpufreq_driver结构体。
6464

6565
.driver_data - cpufreq驱动程序的特定数据。
6666

67-
.resolve_freq - 返回最适合目标频率的频率。不过并不能改变频率。
68-
6967
.get_intermediate 和 target_intermediate - 用于在改变CPU频率时切换到稳定
7068
的频率。
7169

@@ -76,9 +74,6 @@ CPUfreq核心层注册一个cpufreq_driver结构体。
7674
.exit - 一个指向per-policy清理函数的指针,该函数在cpu热插拔过程的CPU_POST_DEAD
7775
阶段被调用。
7876

79-
.stop_cpu - 一个指向per-policy停止函数的指针,该函数在cpu热插拔过程的CPU_DOWN_PREPARE
80-
阶段被调用。
81-
8277
.suspend - 一个指向per-policy暂停函数的指针,该函数在关中断且在该策略的调节器停止
8378
后被调用。
8479

drivers/base/arch_topology.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818
#include <linux/cpumask.h>
1919
#include <linux/init.h>
2020
#include <linux/percpu.h>
21+
#include <linux/rcupdate.h>
2122
#include <linux/sched.h>
2223
#include <linux/smp.h>
2324

24-
static DEFINE_PER_CPU(struct scale_freq_data *, sft_data);
25+
static DEFINE_PER_CPU(struct scale_freq_data __rcu *, sft_data);
2526
static struct cpumask scale_freq_counters_mask;
2627
static bool scale_freq_invariant;
2728

@@ -66,16 +67,20 @@ void topology_set_scale_freq_source(struct scale_freq_data *data,
6667
if (cpumask_empty(&scale_freq_counters_mask))
6768
scale_freq_invariant = topology_scale_freq_invariant();
6869

70+
rcu_read_lock();
71+
6972
for_each_cpu(cpu, cpus) {
70-
sfd = per_cpu(sft_data, cpu);
73+
sfd = rcu_dereference(*per_cpu_ptr(&sft_data, cpu));
7174

7275
/* Use ARCH provided counters whenever possible */
7376
if (!sfd || sfd->source != SCALE_FREQ_SOURCE_ARCH) {
74-
per_cpu(sft_data, cpu) = data;
77+
rcu_assign_pointer(per_cpu(sft_data, cpu), data);
7578
cpumask_set_cpu(cpu, &scale_freq_counters_mask);
7679
}
7780
}
7881

82+
rcu_read_unlock();
83+
7984
update_scale_freq_invariant(true);
8085
}
8186
EXPORT_SYMBOL_GPL(topology_set_scale_freq_source);
@@ -86,22 +91,32 @@ void topology_clear_scale_freq_source(enum scale_freq_source source,
8691
struct scale_freq_data *sfd;
8792
int cpu;
8893

94+
rcu_read_lock();
95+
8996
for_each_cpu(cpu, cpus) {
90-
sfd = per_cpu(sft_data, cpu);
97+
sfd = rcu_dereference(*per_cpu_ptr(&sft_data, cpu));
9198

9299
if (sfd && sfd->source == source) {
93-
per_cpu(sft_data, cpu) = NULL;
100+
rcu_assign_pointer(per_cpu(sft_data, cpu), NULL);
94101
cpumask_clear_cpu(cpu, &scale_freq_counters_mask);
95102
}
96103
}
97104

105+
rcu_read_unlock();
106+
107+
/*
108+
* Make sure all references to previous sft_data are dropped to avoid
109+
* use-after-free races.
110+
*/
111+
synchronize_rcu();
112+
98113
update_scale_freq_invariant(false);
99114
}
100115
EXPORT_SYMBOL_GPL(topology_clear_scale_freq_source);
101116

102117
void topology_scale_freq_tick(void)
103118
{
104-
struct scale_freq_data *sfd = *this_cpu_ptr(&sft_data);
119+
struct scale_freq_data *sfd = rcu_dereference_sched(*this_cpu_ptr(&sft_data));
105120

106121
if (sfd)
107122
sfd->set_freq_scale();

drivers/base/power/domain.c

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,8 +2018,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
20182018

20192019
mutex_lock(&gpd_list_lock);
20202020
list_add(&genpd->gpd_list_node, &gpd_list);
2021-
genpd_debug_add(genpd);
20222021
mutex_unlock(&gpd_list_lock);
2022+
genpd_debug_add(genpd);
20232023

20242024
return 0;
20252025
}
@@ -2206,12 +2206,19 @@ static int genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
22062206

22072207
static bool genpd_present(const struct generic_pm_domain *genpd)
22082208
{
2209+
bool ret = false;
22092210
const struct generic_pm_domain *gpd;
22102211

2211-
list_for_each_entry(gpd, &gpd_list, gpd_list_node)
2212-
if (gpd == genpd)
2213-
return true;
2214-
return false;
2212+
mutex_lock(&gpd_list_lock);
2213+
list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
2214+
if (gpd == genpd) {
2215+
ret = true;
2216+
break;
2217+
}
2218+
}
2219+
mutex_unlock(&gpd_list_lock);
2220+
2221+
return ret;
22152222
}
22162223

22172224
/**
@@ -2222,15 +2229,13 @@ static bool genpd_present(const struct generic_pm_domain *genpd)
22222229
int of_genpd_add_provider_simple(struct device_node *np,
22232230
struct generic_pm_domain *genpd)
22242231
{
2225-
int ret = -EINVAL;
2232+
int ret;
22262233

22272234
if (!np || !genpd)
22282235
return -EINVAL;
22292236

2230-
mutex_lock(&gpd_list_lock);
2231-
22322237
if (!genpd_present(genpd))
2233-
goto unlock;
2238+
return -EINVAL;
22342239

22352240
genpd->dev.of_node = np;
22362241

@@ -2241,7 +2246,7 @@ int of_genpd_add_provider_simple(struct device_node *np,
22412246
if (ret != -EPROBE_DEFER)
22422247
dev_err(&genpd->dev, "Failed to add OPP table: %d\n",
22432248
ret);
2244-
goto unlock;
2249+
return ret;
22452250
}
22462251

22472252
/*
@@ -2259,16 +2264,13 @@ int of_genpd_add_provider_simple(struct device_node *np,
22592264
dev_pm_opp_of_remove_table(&genpd->dev);
22602265
}
22612266

2262-
goto unlock;
2267+
return ret;
22632268
}
22642269

22652270
genpd->provider = &np->fwnode;
22662271
genpd->has_provider = true;
22672272

2268-
unlock:
2269-
mutex_unlock(&gpd_list_lock);
2270-
2271-
return ret;
2273+
return 0;
22722274
}
22732275
EXPORT_SYMBOL_GPL(of_genpd_add_provider_simple);
22742276

@@ -2287,8 +2289,6 @@ int of_genpd_add_provider_onecell(struct device_node *np,
22872289
if (!np || !data)
22882290
return -EINVAL;
22892291

2290-
mutex_lock(&gpd_list_lock);
2291-
22922292
if (!data->xlate)
22932293
data->xlate = genpd_xlate_onecell;
22942294

@@ -2328,8 +2328,6 @@ int of_genpd_add_provider_onecell(struct device_node *np,
23282328
if (ret < 0)
23292329
goto error;
23302330

2331-
mutex_unlock(&gpd_list_lock);
2332-
23332331
return 0;
23342332

23352333
error:
@@ -2348,8 +2346,6 @@ int of_genpd_add_provider_onecell(struct device_node *np,
23482346
}
23492347
}
23502348

2351-
mutex_unlock(&gpd_list_lock);
2352-
23532349
return ret;
23542350
}
23552351
EXPORT_SYMBOL_GPL(of_genpd_add_provider_onecell);

drivers/base/power/main.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,16 +220,13 @@ static void initcall_debug_report(struct device *dev, ktime_t calltime,
220220
void *cb, int error)
221221
{
222222
ktime_t rettime;
223-
s64 nsecs;
224223

225224
if (!pm_print_times_enabled)
226225
return;
227226

228227
rettime = ktime_get();
229-
nsecs = (s64) ktime_to_ns(ktime_sub(rettime, calltime));
230-
231228
dev_info(dev, "%pS returned %d after %Ld usecs\n", cb, error,
232-
(unsigned long long)nsecs >> 10);
229+
(unsigned long long)ktime_us_delta(rettime, calltime));
233230
}
234231

235232
/**

drivers/cpufreq/Kconfig.arm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ config ACPI_CPPC_CPUFREQ
1919

2020
If in doubt, say N.
2121

22+
config ACPI_CPPC_CPUFREQ_FIE
23+
bool "Frequency Invariance support for CPPC cpufreq driver"
24+
depends on ACPI_CPPC_CPUFREQ && GENERIC_ARCH_TOPOLOGY
25+
default y
26+
help
27+
This extends frequency invariance support in the CPPC cpufreq driver,
28+
by using CPPC delivered and reference performance counters.
29+
30+
If in doubt, say N.
31+
2232
config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM
2333
tristate "Allwinner nvmem based SUN50I CPUFreq driver"
2434
depends on ARCH_SUNXI

0 commit comments

Comments
 (0)