Skip to content

Commit 6218499

Browse files
author
CKI KWF Bot
committed
Merge: cpufreq: intel_pstate: Updates to 6.17
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1581 Description: updates for cpufreq: intel_pstate JIRA: https://issues.redhat.com/browse/RHEL-110833 Build Info: 69100436 Tested: Successful platform test results on Intel (intel-bartlett-lake-01) system. Signed-off-by: Steve Best <sbest@redhat.com> Approved-by: Tony Camuso <tcamuso@redhat.com> Approved-by: Lenny Szubowicz <lszubowi@redhat.com> Approved-by: Baoquan He <5820488-baoquan_he@users.noreply.gitlab.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Approved-by: Rafael Aquini <raquini@redhat.com> Approved-by: Aristeu Rozanski <arozansk@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents f5bae92 + c89f09b commit 6218499

File tree

7 files changed

+319
-141
lines changed

7 files changed

+319
-141
lines changed

drivers/base/arch_topology.c

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,6 @@ void topology_set_freq_scale(const struct cpumask *cpus, unsigned long cur_freq,
154154
per_cpu(arch_freq_scale, i) = scale;
155155
}
156156

157-
DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
158-
EXPORT_PER_CPU_SYMBOL_GPL(cpu_scale);
159-
160-
void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity)
161-
{
162-
per_cpu(cpu_scale, cpu) = capacity;
163-
}
164-
165157
DEFINE_PER_CPU(unsigned long, hw_pressure);
166158

167159
/**
@@ -207,53 +199,9 @@ void topology_update_hw_pressure(const struct cpumask *cpus,
207199
}
208200
EXPORT_SYMBOL_GPL(topology_update_hw_pressure);
209201

210-
static ssize_t cpu_capacity_show(struct device *dev,
211-
struct device_attribute *attr,
212-
char *buf)
213-
{
214-
struct cpu *cpu = container_of(dev, struct cpu, dev);
215-
216-
return sysfs_emit(buf, "%lu\n", topology_get_cpu_scale(cpu->dev.id));
217-
}
218-
219202
static void update_topology_flags_workfn(struct work_struct *work);
220203
static DECLARE_WORK(update_topology_flags_work, update_topology_flags_workfn);
221204

222-
static DEVICE_ATTR_RO(cpu_capacity);
223-
224-
static int cpu_capacity_sysctl_add(unsigned int cpu)
225-
{
226-
struct device *cpu_dev = get_cpu_device(cpu);
227-
228-
if (!cpu_dev)
229-
return -ENOENT;
230-
231-
device_create_file(cpu_dev, &dev_attr_cpu_capacity);
232-
233-
return 0;
234-
}
235-
236-
static int cpu_capacity_sysctl_remove(unsigned int cpu)
237-
{
238-
struct device *cpu_dev = get_cpu_device(cpu);
239-
240-
if (!cpu_dev)
241-
return -ENOENT;
242-
243-
device_remove_file(cpu_dev, &dev_attr_cpu_capacity);
244-
245-
return 0;
246-
}
247-
248-
static int register_cpu_capacity_sysctl(void)
249-
{
250-
cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "topology/cpu-capacity",
251-
cpu_capacity_sysctl_add, cpu_capacity_sysctl_remove);
252-
253-
return 0;
254-
}
255-
subsys_initcall(register_cpu_capacity_sysctl);
256-
257205
static int update_topology;
258206

259207
int topology_update_cpu_topology(void)

drivers/base/topology.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,55 @@ static int __init topology_sysfs_init(void)
208208
}
209209

210210
device_initcall(topology_sysfs_init);
211+
212+
DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
213+
EXPORT_PER_CPU_SYMBOL_GPL(cpu_scale);
214+
215+
void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity)
216+
{
217+
per_cpu(cpu_scale, cpu) = capacity;
218+
}
219+
220+
static ssize_t cpu_capacity_show(struct device *dev,
221+
struct device_attribute *attr,
222+
char *buf)
223+
{
224+
struct cpu *cpu = container_of(dev, struct cpu, dev);
225+
226+
return sysfs_emit(buf, "%lu\n", topology_get_cpu_scale(cpu->dev.id));
227+
}
228+
229+
static DEVICE_ATTR_RO(cpu_capacity);
230+
231+
static int cpu_capacity_sysctl_add(unsigned int cpu)
232+
{
233+
struct device *cpu_dev = get_cpu_device(cpu);
234+
235+
if (!cpu_dev)
236+
return -ENOENT;
237+
238+
device_create_file(cpu_dev, &dev_attr_cpu_capacity);
239+
240+
return 0;
241+
}
242+
243+
static int cpu_capacity_sysctl_remove(unsigned int cpu)
244+
{
245+
struct device *cpu_dev = get_cpu_device(cpu);
246+
247+
if (!cpu_dev)
248+
return -ENOENT;
249+
250+
device_remove_file(cpu_dev, &dev_attr_cpu_capacity);
251+
252+
return 0;
253+
}
254+
255+
static int register_cpu_capacity_sysctl(void)
256+
{
257+
cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "topology/cpu-capacity",
258+
cpu_capacity_sysctl_add, cpu_capacity_sysctl_remove);
259+
260+
return 0;
261+
}
262+
subsys_initcall(register_cpu_capacity_sysctl);

drivers/cpufreq/intel_pstate.c

Lines changed: 137 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ struct global_params {
221221
* @sched_flags: Store scheduler flags for possible cross CPU update
222222
* @hwp_boost_min: Last HWP boosted min performance
223223
* @suspended: Whether or not the driver has been suspended.
224+
* @pd_registered: Set when a perf domain is registered for this CPU.
224225
* @hwp_notify_work: workqueue for HWP notifications.
225226
*
226227
* This structure stores per CPU instance data for all CPUs.
@@ -260,6 +261,9 @@ struct cpudata {
260261
unsigned int sched_flags;
261262
u32 hwp_boost_min;
262263
bool suspended;
264+
#ifdef CONFIG_ENERGY_MODEL
265+
bool pd_registered;
266+
#endif
263267
struct delayed_work hwp_notify_work;
264268
};
265269

@@ -303,6 +307,7 @@ static bool hwp_is_hybrid;
303307

304308
static struct cpufreq_driver *intel_pstate_driver __read_mostly;
305309

310+
#define INTEL_PSTATE_CORE_SCALING 100000
306311
#define HYBRID_SCALING_FACTOR_ADL 78741
307312
#define HYBRID_SCALING_FACTOR_MTL 80000
308313
#define HYBRID_SCALING_FACTOR_LNL 86957
@@ -311,7 +316,7 @@ static int hybrid_scaling_factor;
311316

312317
static inline int core_get_scaling(void)
313318
{
314-
return 100000;
319+
return INTEL_PSTATE_CORE_SCALING;
315320
}
316321

317322
#ifdef CONFIG_ACPI
@@ -948,12 +953,124 @@ static struct cpudata *hybrid_max_perf_cpu __read_mostly;
948953
*/
949954
static DEFINE_MUTEX(hybrid_capacity_lock);
950955

956+
#ifdef CONFIG_ENERGY_MODEL
957+
#define HYBRID_EM_STATE_COUNT 4
958+
959+
static int hybrid_active_power(struct device *dev, unsigned long *power,
960+
unsigned long *freq)
961+
{
962+
/*
963+
* Create "utilization bins" of 0-40%, 40%-60%, 60%-80%, and 80%-100%
964+
* of the maximum capacity such that two CPUs of the same type will be
965+
* regarded as equally attractive if the utilization of each of them
966+
* falls into the same bin, which should prevent tasks from being
967+
* migrated between them too often.
968+
*
969+
* For this purpose, return the "frequency" of 2 for the first
970+
* performance level and otherwise leave the value set by the caller.
971+
*/
972+
if (!*freq)
973+
*freq = 2;
974+
975+
/* No power information. */
976+
*power = EM_MAX_POWER;
977+
978+
return 0;
979+
}
980+
981+
static int hybrid_get_cost(struct device *dev, unsigned long freq,
982+
unsigned long *cost)
983+
{
984+
struct pstate_data *pstate = &all_cpu_data[dev->id]->pstate;
985+
struct cpu_cacheinfo *cacheinfo = get_cpu_cacheinfo(dev->id);
986+
987+
/*
988+
* The smaller the perf-to-frequency scaling factor, the larger the IPC
989+
* ratio between the given CPU and the least capable CPU in the system.
990+
* Regard that IPC ratio as the primary cost component and assume that
991+
* the scaling factors for different CPU types will differ by at least
992+
* 5% and they will not be above INTEL_PSTATE_CORE_SCALING.
993+
*
994+
* Add the freq value to the cost, so that the cost of running on CPUs
995+
* of the same type in different "utilization bins" is different.
996+
*/
997+
*cost = div_u64(100ULL * INTEL_PSTATE_CORE_SCALING, pstate->scaling) + freq;
998+
/*
999+
* Increase the cost slightly for CPUs able to access L3 to avoid
1000+
* touching it in case some other CPUs of the same type can do the work
1001+
* without it.
1002+
*/
1003+
if (cacheinfo) {
1004+
unsigned int i;
1005+
1006+
/* Check if L3 cache is there. */
1007+
for (i = 0; i < cacheinfo->num_leaves; i++) {
1008+
if (cacheinfo->info_list[i].level == 3) {
1009+
*cost += 2;
1010+
break;
1011+
}
1012+
}
1013+
}
1014+
1015+
return 0;
1016+
}
1017+
1018+
static bool hybrid_register_perf_domain(unsigned int cpu)
1019+
{
1020+
static const struct em_data_callback cb
1021+
= EM_ADV_DATA_CB(hybrid_active_power, hybrid_get_cost);
1022+
struct cpudata *cpudata = all_cpu_data[cpu];
1023+
struct device *cpu_dev;
1024+
1025+
/*
1026+
* Registering EM perf domains without enabling asymmetric CPU capacity
1027+
* support is not really useful and one domain should not be registered
1028+
* more than once.
1029+
*/
1030+
if (!hybrid_max_perf_cpu || cpudata->pd_registered)
1031+
return false;
1032+
1033+
cpu_dev = get_cpu_device(cpu);
1034+
if (!cpu_dev)
1035+
return false;
1036+
1037+
if (em_dev_register_pd_no_update(cpu_dev, HYBRID_EM_STATE_COUNT, &cb,
1038+
cpumask_of(cpu), false))
1039+
return false;
1040+
1041+
cpudata->pd_registered = true;
1042+
1043+
return true;
1044+
}
1045+
1046+
static void hybrid_register_all_perf_domains(void)
1047+
{
1048+
unsigned int cpu;
1049+
1050+
for_each_online_cpu(cpu)
1051+
hybrid_register_perf_domain(cpu);
1052+
}
1053+
1054+
static void hybrid_update_perf_domain(struct cpudata *cpu)
1055+
{
1056+
if (cpu->pd_registered)
1057+
em_adjust_cpu_capacity(cpu->cpu);
1058+
}
1059+
#else /* !CONFIG_ENERGY_MODEL */
1060+
static inline bool hybrid_register_perf_domain(unsigned int cpu) { return false; }
1061+
static inline void hybrid_register_all_perf_domains(void) {}
1062+
static inline void hybrid_update_perf_domain(struct cpudata *cpu) {}
1063+
#endif /* CONFIG_ENERGY_MODEL */
1064+
9511065
static void hybrid_set_cpu_capacity(struct cpudata *cpu)
9521066
{
9531067
arch_set_cpu_capacity(cpu->cpu, cpu->capacity_perf,
9541068
hybrid_max_perf_cpu->capacity_perf,
9551069
cpu->capacity_perf,
9561070
cpu->pstate.max_pstate_physical);
1071+
hybrid_update_perf_domain(cpu);
1072+
1073+
topology_set_cpu_scale(cpu->cpu, arch_scale_cpu_capacity(cpu->cpu));
9571074

9581075
pr_debug("CPU%d: perf = %u, max. perf = %u, base perf = %d\n", cpu->cpu,
9591076
cpu->capacity_perf, hybrid_max_perf_cpu->capacity_perf,
@@ -1042,6 +1159,11 @@ static void hybrid_refresh_cpu_capacity_scaling(void)
10421159
guard(mutex)(&hybrid_capacity_lock);
10431160

10441161
__hybrid_refresh_cpu_capacity_scaling();
1162+
/*
1163+
* Perf domains are not registered before setting hybrid_max_perf_cpu,
1164+
* so register them all after setting up CPU capacity scaling.
1165+
*/
1166+
hybrid_register_all_perf_domains();
10451167
}
10461168

10471169
static void hybrid_init_cpu_capacity_scaling(bool refresh)
@@ -1069,7 +1191,7 @@ static void hybrid_init_cpu_capacity_scaling(bool refresh)
10691191
hybrid_refresh_cpu_capacity_scaling();
10701192
/*
10711193
* Disabling ITMT causes sched domains to be rebuilt to disable asym
1072-
* packing and enable asym capacity.
1194+
* packing and enable asym capacity and EAS.
10731195
*/
10741196
sched_clear_itmt_support();
10751197
}
@@ -1147,6 +1269,14 @@ static void hybrid_update_capacity(struct cpudata *cpu)
11471269
}
11481270

11491271
hybrid_set_cpu_capacity(cpu);
1272+
/*
1273+
* If the CPU was offline to start with and it is going online for the
1274+
* first time, a perf domain needs to be registered for it if hybrid
1275+
* capacity scaling has been enabled already. In that case, sched
1276+
* domains need to be rebuilt to take the new perf domain into account.
1277+
*/
1278+
if (hybrid_register_perf_domain(cpu->cpu))
1279+
em_rebuild_sched_domains();
11501280

11511281
unlock:
11521282
mutex_unlock(&hybrid_capacity_lock);
@@ -2656,6 +2786,8 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
26562786
X86_MATCH(INTEL_TIGERLAKE, core_funcs),
26572787
X86_MATCH(INTEL_SAPPHIRERAPIDS_X, core_funcs),
26582788
X86_MATCH(INTEL_EMERALDRAPIDS_X, core_funcs),
2789+
X86_MATCH(INTEL_GRANITERAPIDS_D, core_funcs),
2790+
X86_MATCH(INTEL_GRANITERAPIDS_X, core_funcs),
26592791
{}
26602792
};
26612793
MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
@@ -2672,6 +2804,7 @@ static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] __initconst = {
26722804
X86_MATCH(INTEL_GRANITERAPIDS_X, core_funcs),
26732805
X86_MATCH(INTEL_ATOM_CRESTMONT, core_funcs),
26742806
X86_MATCH(INTEL_ATOM_CRESTMONT_X, core_funcs),
2807+
X86_MATCH(INTEL_ATOM_DARKMONT_X, core_funcs),
26752808
{}
26762809
};
26772810
#endif
@@ -3130,8 +3263,8 @@ static int intel_cpufreq_update_pstate(struct cpufreq_policy *policy,
31303263
int max_pstate = policy->strict_target ?
31313264
target_pstate : cpu->max_perf_ratio;
31323265

3133-
intel_cpufreq_hwp_update(cpu, target_pstate, max_pstate, 0,
3134-
fast_switch);
3266+
intel_cpufreq_hwp_update(cpu, target_pstate, max_pstate,
3267+
target_pstate, fast_switch);
31353268
} else if (target_pstate != old_pstate) {
31363269
intel_cpufreq_perf_ctl_update(cpu, target_pstate, fast_switch);
31373270
}

include/linux/arch_topology.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@ int topology_update_cpu_topology(void);
1414
struct device_node;
1515
bool topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu);
1616

17-
DECLARE_PER_CPU(unsigned long, cpu_scale);
18-
19-
static inline unsigned long topology_get_cpu_scale(int cpu)
20-
{
21-
return per_cpu(cpu_scale, cpu);
22-
}
23-
24-
void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity);
2517

2618
DECLARE_PER_CPU(unsigned long, capacity_freq_ref);
2719

0 commit comments

Comments
 (0)