For cpus sharing one cpufreq domain, cpufreq_driver.init() is only invoked on the firstcpu, so current per-CPU hwp driver data struct hwp_drv_data{} actually fails to be allocated for cpus other than the first one. There is no need to make it per-CPU. We embed struct hwp_drv_data{} into struct cpufreq_policy{}, then cpus could share the hwp driver data allocated for the firstcpu, like the way they share struct cpufreq_policy{}. We also make it a union, with "hwp", and later "amd-cppc" as a sub-struct.
Suggested-by: Jan Beulich <jbeul...@suse.com> Signed-off-by: Penny Zheng <penny.zh...@amd.com> --- v8 -> v9: - new commit --- xen/arch/x86/acpi/cpufreq/hwp.c | 32 +++++++++++++----------------- xen/include/acpi/cpufreq/cpufreq.h | 6 ++++++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/xen/arch/x86/acpi/cpufreq/hwp.c b/xen/arch/x86/acpi/cpufreq/hwp.c index 240491c96a..5c98f3eb3e 100644 --- a/xen/arch/x86/acpi/cpufreq/hwp.c +++ b/xen/arch/x86/acpi/cpufreq/hwp.c @@ -67,7 +67,6 @@ struct hwp_drv_data uint8_t desired; uint8_t energy_perf; }; -static DEFINE_PER_CPU_READ_MOSTLY(struct hwp_drv_data *, hwp_drv_data); #define hwp_err(cpu, fmt, args...) \ printk(XENLOG_ERR "HWP: CPU%u error: " fmt, cpu, ## args) @@ -224,7 +223,7 @@ static bool __init hwp_available(void) static int cf_check hwp_cpufreq_verify(struct cpufreq_policy *policy) { - struct hwp_drv_data *data = per_cpu(hwp_drv_data, policy->cpu); + struct hwp_drv_data *data = policy->u.hwp; if ( !feature_hwp_activity_window && data->activity_window ) { @@ -239,7 +238,7 @@ static int cf_check hwp_cpufreq_verify(struct cpufreq_policy *policy) static void cf_check hwp_write_request(void *info) { const struct cpufreq_policy *policy = info; - struct hwp_drv_data *data = this_cpu(hwp_drv_data); + struct hwp_drv_data *data = policy->u.hwp; union hwp_request hwp_req = data->curr_req; data->ret = 0; @@ -259,7 +258,7 @@ static int cf_check hwp_cpufreq_target(struct cpufreq_policy *policy, unsigned int relation) { unsigned int cpu = policy->cpu; - struct hwp_drv_data *data = per_cpu(hwp_drv_data, cpu); + struct hwp_drv_data *data = policy->u.hwp; /* Zero everything to ensure reserved bits are zero... */ union hwp_request hwp_req = { .raw = 0 }; @@ -350,7 +349,7 @@ static void hwp_get_cpu_speeds(struct cpufreq_policy *policy) static void cf_check hwp_init_msrs(void *info) { struct cpufreq_policy *policy = info; - struct hwp_drv_data *data = this_cpu(hwp_drv_data); + struct hwp_drv_data *data = policy->u.hwp; uint64_t val; /* @@ -426,15 +425,14 @@ static int cf_check hwp_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->governor = &cpufreq_gov_hwp; - per_cpu(hwp_drv_data, cpu) = data; + policy->u.hwp = data; on_selected_cpus(cpumask_of(cpu), hwp_init_msrs, policy, 1); if ( data->curr_req.raw == -1 ) { hwp_err(cpu, "Could not initialize HWP properly\n"); - per_cpu(hwp_drv_data, cpu) = NULL; - xfree(data); + XFREE(policy->u.hwp); return -ENODEV; } @@ -462,10 +460,8 @@ static int cf_check hwp_cpufreq_cpu_init(struct cpufreq_policy *policy) static int cf_check hwp_cpufreq_cpu_exit(struct cpufreq_policy *policy) { - struct hwp_drv_data *data = per_cpu(hwp_drv_data, policy->cpu); - - per_cpu(hwp_drv_data, policy->cpu) = NULL; - xfree(data); + if ( policy->u.hwp ) + XFREE(policy->u.hwp); return 0; } @@ -480,7 +476,7 @@ static int cf_check hwp_cpufreq_cpu_exit(struct cpufreq_policy *policy) static void cf_check hwp_set_misc_turbo(void *info) { const struct cpufreq_policy *policy = info; - struct hwp_drv_data *data = per_cpu(hwp_drv_data, policy->cpu); + struct hwp_drv_data *data = policy->u.hwp; uint64_t msr; data->ret = 0; @@ -511,7 +507,7 @@ static int cf_check hwp_cpufreq_update(unsigned int cpu, struct cpufreq_policy * { on_selected_cpus(cpumask_of(cpu), hwp_set_misc_turbo, policy, 1); - return per_cpu(hwp_drv_data, cpu)->ret; + return policy->u.hwp->ret; } #endif /* CONFIG_PM_OP */ @@ -531,9 +527,10 @@ hwp_cpufreq_driver = { int get_hwp_para(unsigned int cpu, struct xen_get_cppc_para *cppc_para) { - const struct hwp_drv_data *data = per_cpu(hwp_drv_data, cpu); + const struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_policy, cpu); + const struct hwp_drv_data *data; - if ( data == NULL ) + if ( !policy || !(data = policy->u.hwp) ) return -ENODATA; cppc_para->features = @@ -554,8 +551,7 @@ int get_hwp_para(unsigned int cpu, int set_hwp_para(struct cpufreq_policy *policy, struct xen_set_cppc_para *set_cppc) { - unsigned int cpu = policy->cpu; - struct hwp_drv_data *data = per_cpu(hwp_drv_data, cpu); + struct hwp_drv_data *data = policy->u.hwp; bool cleared_act_window = false; if ( data == NULL ) diff --git a/xen/include/acpi/cpufreq/cpufreq.h b/xen/include/acpi/cpufreq/cpufreq.h index 5d4881eea8..c0ecd690c5 100644 --- a/xen/include/acpi/cpufreq/cpufreq.h +++ b/xen/include/acpi/cpufreq/cpufreq.h @@ -62,6 +62,7 @@ struct perf_limits { uint32_t min_policy_pct; }; +struct hwp_drv_data; struct cpufreq_policy { cpumask_var_t cpus; /* affected CPUs */ unsigned int shared_type; /* ANY or ALL affected CPUs @@ -81,6 +82,11 @@ struct cpufreq_policy { int8_t turbo; /* tristate flag: 0 for unsupported * -1 for disable, 1 for enabled * See CPUFREQ_TURBO_* below for defines */ + union { +#ifdef CONFIG_INTEL + struct hwp_drv_data *hwp; /* Driver data for Intel HWP */ +#endif + } u; }; DECLARE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_policy); -- 2.34.1