diff mbox series

[1/2] x86/cpu/amd: Clarify amd_get_highest_perf()

Message ID 20240626042043.2410-2-mario.limonciello@amd.com (mailing list archive)
State New
Delegated to: Mario Limonciello
Headers show
Series Fixes for wrong performance levels in acpi-cpufreq | expand

Commit Message

Mario Limonciello June 26, 2024, 4:20 a.m. UTC
Rather than parsing through families and models as an if/else, use
cpu_feature_enabled() and switch/case.

Add definitions aligned with the amd-pstate definition for performance
levels. No intended functional changes.

Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
 arch/x86/kernel/cpu/amd.c | 30 +++++++++++++++++++++++-------
 1 file changed, 23 insertions(+), 7 deletions(-)

Comments

Borislav Petkov June 26, 2024, 5:14 p.m. UTC | #1
On Tue, Jun 25, 2024 at 11:20:42PM -0500, Mario Limonciello wrote:
>  static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
>  {
>  	u32 gprs[8] = { 0 };
> @@ -1194,15 +1198,27 @@ u32 amd_get_highest_perf(void)
>  {
>  	struct cpuinfo_x86 *c = &boot_cpu_data;
>  
> -	if (c->x86 == 0x17 && ((c->x86_model >= 0x30 && c->x86_model < 0x40) ||
> -			       (c->x86_model >= 0x70 && c->x86_model < 0x80)))
> -		return 166;
> +	if (cpu_feature_enabled(X86_FEATURE_ZEN2)) {
> +		switch (c->x86_model) {
> +		case 0x30 ... 0x40:
> +		case 0x70 ... 0x80:

Well, it was < 0x40 and < 0x80

You're making it <=.

> +			return CPPC_HIGHEST_PERF_DEFAULT;
> +		default:
> +			return CPPC_HIGHEST_PERF_MAX;
> +		}
> +	}
>  
> -	if (c->x86 == 0x19 && ((c->x86_model >= 0x20 && c->x86_model < 0x30) ||
> -			       (c->x86_model >= 0x40 && c->x86_model < 0x70)))
> -		return 166;
> +	if (cpu_feature_enabled(X86_FEATURE_ZEN3)) {
> +		switch (c->x86_model) {
> +		case 0x20 ... 0x30:
> +		case 0x40 ... 0x70:

Ditto.

Also, ontop:

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 73559db78433..5d496de4e141 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -1204,7 +1204,7 @@ u32 amd_get_highest_perf(void)
 		case 0x70 ... 0x80:
 			return CPPC_HIGHEST_PERF_DEFAULT;
 		default:
-			return CPPC_HIGHEST_PERF_MAX;
+			break;
 		}
 	}
 
@@ -1214,7 +1214,7 @@ u32 amd_get_highest_perf(void)
 		case 0x40 ... 0x70:
 			return CPPC_HIGHEST_PERF_DEFAULT;
 		default:
-			return CPPC_HIGHEST_PERF_MAX;
+			break;
 		}
 	}
 
so that you don't have so many redundant returns in the function.
Mario Limonciello June 26, 2024, 6:18 p.m. UTC | #2
On 6/26/2024 12:14, Borislav Petkov wrote:
> On Tue, Jun 25, 2024 at 11:20:42PM -0500, Mario Limonciello wrote:
>>   static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
>>   {
>>   	u32 gprs[8] = { 0 };
>> @@ -1194,15 +1198,27 @@ u32 amd_get_highest_perf(void)
>>   {
>>   	struct cpuinfo_x86 *c = &boot_cpu_data;
>>   
>> -	if (c->x86 == 0x17 && ((c->x86_model >= 0x30 && c->x86_model < 0x40) ||
>> -			       (c->x86_model >= 0x70 && c->x86_model < 0x80)))
>> -		return 166;
>> +	if (cpu_feature_enabled(X86_FEATURE_ZEN2)) {
>> +		switch (c->x86_model) {
>> +		case 0x30 ... 0x40:
>> +		case 0x70 ... 0x80:
> 
> Well, it was < 0x40 and < 0x80
> 
> You're making it <=.
> 

Good catch, I'll adjust to 0x3f and 0x7f.

>> +			return CPPC_HIGHEST_PERF_DEFAULT;
>> +		default:
>> +			return CPPC_HIGHEST_PERF_MAX;
>> +		}
>> +	}
>>   
>> -	if (c->x86 == 0x19 && ((c->x86_model >= 0x20 && c->x86_model < 0x30) ||
>> -			       (c->x86_model >= 0x40 && c->x86_model < 0x70)))
>> -		return 166;
>> +	if (cpu_feature_enabled(X86_FEATURE_ZEN3)) {
>> +		switch (c->x86_model) {
>> +		case 0x20 ... 0x30:
>> +		case 0x40 ... 0x70:
> 
> Ditto.
> 
> Also, ontop:
> 
> diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
> index 73559db78433..5d496de4e141 100644
> --- a/arch/x86/kernel/cpu/amd.c
> +++ b/arch/x86/kernel/cpu/amd.c
> @@ -1204,7 +1204,7 @@ u32 amd_get_highest_perf(void)
>   		case 0x70 ... 0x80:
>   			return CPPC_HIGHEST_PERF_DEFAULT;
>   		default:
> -			return CPPC_HIGHEST_PERF_MAX;
> +			break;
>   		}
>   	}
>   
> @@ -1214,7 +1214,7 @@ u32 amd_get_highest_perf(void)
>   		case 0x40 ... 0x70:
>   			return CPPC_HIGHEST_PERF_DEFAULT;
>   		default:
> -			return CPPC_HIGHEST_PERF_MAX;
> +			break;
>   		}
>   	}
>   
> so that you don't have so many redundant returns in the function.
> 

This uncovers a case that I'm not really sure what to do about.

Right now acpi-cpufreq uses this function and if the CPU isn't special 
cased you'll get the value as 255.  This is totally wrong for newer SoCs 
though.  That's what prompted this series in the first place that I saw 
different behavior in amd-pstate and acpi-cpufreq.

So I think we need to have something that is:

switch (zen1) {
case ...
default)
	return 255;
}
switch (zen2) {
case ...
default)
	return 255;
}
switch (zen3) {
case ...
default)
	break;
}
switch (zen4) {
case ...
default)
	break;
}

return 255;

(This is no functional changes)

And then patch 2 or patch 3 change the "default" return to 166 and if 
there is functional issues then they need to be special cased.
Borislav Petkov June 27, 2024, 3 a.m. UTC | #3
On Wed, Jun 26, 2024 at 01:18:17PM -0500, Mario Limonciello wrote:
> And then patch 2 or patch 3 change the "default" return to 166 and if there
> is functional issues then they need to be special cased.

Sounds ok to me. Keep the whole logic in one place. Sure.
diff mbox series

Patch

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 44df3f11e731..8b730193d79e 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -29,6 +29,10 @@ 
 
 #include "cpu.h"
 
+#define CPPC_HIGHEST_PERF_MAX		255
+#define CPPC_HIGHEST_PERF_PERFORMANCE	196
+#define CPPC_HIGHEST_PERF_DEFAULT	166
+
 static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
 {
 	u32 gprs[8] = { 0 };
@@ -1194,15 +1198,27 @@  u32 amd_get_highest_perf(void)
 {
 	struct cpuinfo_x86 *c = &boot_cpu_data;
 
-	if (c->x86 == 0x17 && ((c->x86_model >= 0x30 && c->x86_model < 0x40) ||
-			       (c->x86_model >= 0x70 && c->x86_model < 0x80)))
-		return 166;
+	if (cpu_feature_enabled(X86_FEATURE_ZEN2)) {
+		switch (c->x86_model) {
+		case 0x30 ... 0x40:
+		case 0x70 ... 0x80:
+			return CPPC_HIGHEST_PERF_DEFAULT;
+		default:
+			return CPPC_HIGHEST_PERF_MAX;
+		}
+	}
 
-	if (c->x86 == 0x19 && ((c->x86_model >= 0x20 && c->x86_model < 0x30) ||
-			       (c->x86_model >= 0x40 && c->x86_model < 0x70)))
-		return 166;
+	if (cpu_feature_enabled(X86_FEATURE_ZEN3)) {
+		switch (c->x86_model) {
+		case 0x20 ... 0x30:
+		case 0x40 ... 0x70:
+			return CPPC_HIGHEST_PERF_DEFAULT;
+		default:
+			return CPPC_HIGHEST_PERF_MAX;
+		}
+	}
 
-	return 255;
+	return CPPC_HIGHEST_PERF_MAX;
 }
 EXPORT_SYMBOL_GPL(amd_get_highest_perf);