Linux Power Management development
 help / color / mirror / Atom feed
* [PATCH v2]  cpufreq: acpi-cpufreq: Add better support for amd zen
@ 2026-05-14 17:37 yoy95104
  0 siblings, 0 replies; only message in thread
From: yoy95104 @ 2026-05-14 17:37 UTC (permalink / raw)
  To: rafael, viresh.kumar; +Cc: linux-pm, yoy95104

Found some bugs in the original implementation and repeated code

Signed-off-by: yahia ahmed <yahia.a.abdrabou@gmail.com>
---
 drivers/cpufreq/acpi-cpufreq.c | 80 ++++++++++++++++++++++------------
 1 file changed, 51 insertions(+), 29 deletions(-)

diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index a488a2e2f914..29daca4ffdc6 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -65,7 +65,6 @@ struct acpi_cpufreq_data {
 	void (*cpu_freq_write)(struct acpi_pct_register *reg, u32 val);
 	u32 (*cpu_freq_read)(struct acpi_pct_register *reg);
 	int is_amd_zen;
-	int on_ac;
 };
 
 /* acpi_perf_data is a pointer to percpu data. */
@@ -773,7 +772,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		return blacklisted;
 #endif
 
-	data = kzalloc_obj(*data);
+	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -781,42 +780,65 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		result = -ENOMEM;
 		goto err_free;
 	}
-
 	perf = per_cpu_ptr(acpi_perf_data, cpu);
-	data->acpi_perf_cpu = cpu;
-	policy->driver_data = data;
+	result = acpi_processor_register_performance(perf, cpu);
+
+	if (result)
+		goto err_free_mask;
 	if (c->x86_vendor == X86_VENDOR_AMD && c->x86 >= 0x17 && c->x86_model >= 0x30) {
 		data->is_amd_zen = 1;
-		policy->cur = get_current_freq(cpu);
-		policy->shared_type = CPUFREQ_SHARED_TYPE_NONE;
-		unsigned int max_boost = get_max_freq(cpu);
-		u8 virtual_pstates = 16;
-		unsigned int max_freq = get_max_freq(policy->cpu);
-		unsigned int min_freq = perf->states[perf->state_count - 1].core_frequency * 1000;
-		unsigned int step = (max_freq - min_freq) / (virtual_pstates - 1);
-		freq_table = kcalloc(virtual_pstates + 1, sizeof(*freq_table), GFP_KERNEL);
-		for (int i = 0; i < virtual_pstates; i++) {
-			freq_table[i].driver_data = i;
-			freq_table[i].frequency = max_freq - (i * step);
-		}
-		freq_table[virtual_pstates].frequency = CPUFREQ_TABLE_END;
-		policy->freq_table = freq_table;
-		if (max_boost) {
-			policy->cpuinfo.max_freq = max_boost;
-			policy->max = max_boost;
+
+		if (perf->state_count > 0 && perf->states) {
+			policy->cur = get_current_freq(cpu);
+			policy->shared_type = CPUFREQ_SHARED_TYPE_NONE;
+			unsigned int max_boost = get_max_freq(cpu);
+			u8 virtual_pstates = 16;
+			unsigned int max_freq = get_max_freq(policy->cpu);
+			unsigned int min_freq = perf->states[perf->state_count - 1].core_frequency * 1000;
+			unsigned int step = (max_freq - min_freq) / (virtual_pstates - 1);
+			freq_table = kcalloc(virtual_pstates + 1, sizeof(*freq_table), GFP_KERNEL);
+			for (int i = 0; i < virtual_pstates; i++) {
+				freq_table[i].driver_data = i;
+				freq_table[i].frequency = max_freq - (i * step);
+			}
+			freq_table[virtual_pstates].frequency = CPUFREQ_TABLE_END;
+			policy->freq_table = freq_table;
+			if (max_boost) {
+				policy->cpuinfo.max_freq = max_boost;
+				policy->max = max_boost;
+			} else {
+				policy->cpuinfo.max_freq = perf->states[0].core_frequency * 1000;
+			}
+			return 0;
 		} else {
-			policy->cpuinfo.max_freq = perf->states[0].core_frequency * 1000;
+			pr_warn("ACPI Table didnt provide any P-States");
+			unsigned int max_freq = get_max_freq(cpu);
+
+			if (max_freq == 0)
+				max_freq = 2000000;
+			u8 virtual_pstates = 16;
+			unsigned int step = 25000;
+			freq_table = kcalloc(virtual_pstates + 1, sizeof(*freq_table), GFP_KERNEL);
+			if (!freq_table) {
+			    result = -ENOMEM;
+			    goto err_unreg;
+			}
+			for (int i = 0; i < virtual_pstates; i++) {
+			    freq_table[i].driver_data = i;
+			    freq_table[i].frequency = max_freq - (i * step);
+			}
+			freq_table[virtual_pstates].frequency = CPUFREQ_TABLE_END;
+			policy->freq_table = freq_table;
+			policy->cpuinfo.max_freq = max_freq;
+			policy->max = max_freq;
+			policy->cur = get_current_freq(cpu);
+			return 0;
 		}
 	} else {
 		policy->shared_type = CPUFREQ_SHARED_TYPE_HW;
 	}
 	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC))
 		acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
-
-	result = acpi_processor_register_performance(perf, cpu);
-	if (result)
-		goto err_free_mask;
-
 	/*
 	 * Will let policy->cpus know about dependency only when software
 	 * coordination is required.
@@ -893,7 +915,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		goto err_unreg;
 	}
 
-	freq_table = kzalloc_objs(*freq_table, perf->state_count + 1);
+	freq_table = kcalloc(17, sizeof(*freq_table), GFP_KERNEL);
 	if (!freq_table) {
 		result = -ENOMEM;
 		goto err_unreg;
-- 
2.54.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-05-14 17:37 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-14 17:37 [PATCH v2] cpufreq: acpi-cpufreq: Add better support for amd zen yoy95104

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox