Skip to content

Commit b8fe128

Browse files
JeffyCNgregkh
authored andcommitted
arch_topology: Adjust initial CPU capacities with current freq
The CPU freqs are not supposed to change before cpufreq policies properly registered, meaning that they should be used to calculate the initial CPU capacities. Doing this helps choosing the best CPU during early boot, especially for the initramfs decompressing. There's no functional changes for non-clk CPU DVFS mechanism. Signed-off-by: Jeffy Chen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 847e338 commit b8fe128

File tree

1 file changed

+28
-12
lines changed

1 file changed

+28
-12
lines changed

drivers/base/arch_topology.c

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ static void update_topology_flags_workfn(struct work_struct *work)
9494
update_topology = 0;
9595
}
9696

97-
static u32 capacity_scale;
97+
static DEFINE_PER_CPU(u32, freq_factor) = 1;
9898
static u32 *raw_capacity;
9999

100100
static int free_raw_capacity(void)
@@ -108,17 +108,23 @@ static int free_raw_capacity(void)
108108
void topology_normalize_cpu_scale(void)
109109
{
110110
u64 capacity;
111+
u64 capacity_scale;
111112
int cpu;
112113

113114
if (!raw_capacity)
114115
return;
115116

116-
pr_debug("cpu_capacity: capacity_scale=%u\n", capacity_scale);
117+
capacity_scale = 1;
117118
for_each_possible_cpu(cpu) {
118-
pr_debug("cpu_capacity: cpu=%d raw_capacity=%u\n",
119-
cpu, raw_capacity[cpu]);
120-
capacity = (raw_capacity[cpu] << SCHED_CAPACITY_SHIFT)
121-
/ capacity_scale;
119+
capacity = raw_capacity[cpu] * per_cpu(freq_factor, cpu);
120+
capacity_scale = max(capacity, capacity_scale);
121+
}
122+
123+
pr_debug("cpu_capacity: capacity_scale=%llu\n", capacity_scale);
124+
for_each_possible_cpu(cpu) {
125+
capacity = raw_capacity[cpu] * per_cpu(freq_factor, cpu);
126+
capacity = div64_u64(capacity << SCHED_CAPACITY_SHIFT,
127+
capacity_scale);
122128
topology_set_cpu_scale(cpu, capacity);
123129
pr_debug("cpu_capacity: CPU%d cpu_capacity=%lu\n",
124130
cpu, topology_get_cpu_scale(cpu));
@@ -127,6 +133,7 @@ void topology_normalize_cpu_scale(void)
127133

128134
bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
129135
{
136+
struct clk *cpu_clk;
130137
static bool cap_parsing_failed;
131138
int ret;
132139
u32 cpu_capacity;
@@ -146,10 +153,22 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
146153
return false;
147154
}
148155
}
149-
capacity_scale = max(cpu_capacity, capacity_scale);
150156
raw_capacity[cpu] = cpu_capacity;
151157
pr_debug("cpu_capacity: %pOF cpu_capacity=%u (raw)\n",
152158
cpu_node, raw_capacity[cpu]);
159+
160+
/*
161+
* Update freq_factor for calculating early boot cpu capacities.
162+
* For non-clk CPU DVFS mechanism, there's no way to get the
163+
* frequency value now, assuming they are running at the same
164+
* frequency (by keeping the initial freq_factor value).
165+
*/
166+
cpu_clk = of_clk_get(cpu_node, 0);
167+
if (!PTR_ERR_OR_ZERO(cpu_clk))
168+
per_cpu(freq_factor, cpu) =
169+
clk_get_rate(cpu_clk) / 1000;
170+
171+
clk_put(cpu_clk);
153172
} else {
154173
if (raw_capacity) {
155174
pr_err("cpu_capacity: missing %pOF raw capacity\n",
@@ -188,11 +207,8 @@ init_cpu_capacity_callback(struct notifier_block *nb,
188207

189208
cpumask_andnot(cpus_to_visit, cpus_to_visit, policy->related_cpus);
190209

191-
for_each_cpu(cpu, policy->related_cpus) {
192-
raw_capacity[cpu] = topology_get_cpu_scale(cpu) *
193-
policy->cpuinfo.max_freq / 1000UL;
194-
capacity_scale = max(raw_capacity[cpu], capacity_scale);
195-
}
210+
for_each_cpu(cpu, policy->related_cpus)
211+
per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq / 1000;
196212

197213
if (cpumask_empty(cpus_to_visit)) {
198214
topology_normalize_cpu_scale();

0 commit comments

Comments
 (0)