diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index d93e400940a31b28aa90139e6958cae49abdd703..4d2d03fd2dc23dad21a2e1f27c1b512411cb469c 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -387,10 +387,16 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, return; } +static bool acpi_processor_vendor_amd(void) +{ + return boot_cpu_data.x86_vendor == X86_VENDOR_AMD; +} + static int acpi_processor_power_verify(struct acpi_processor *pr) { unsigned int i; unsigned int working = 0; + u32 latency2, latency3; pr->power.timer_broadcast_on_state = INT_MAX; @@ -406,9 +412,11 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) if (!cx->address) break; cx->valid = 1; + latency2 = cx->latency; break; case ACPI_STATE_C3: + latency3 = cx->latency; acpi_processor_power_verify_c3(pr, cx); break; } @@ -420,6 +428,15 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) working++; } + /* Some AMD BIOSes mistakenly have higher C2 latencies than C3 latencies. + * In order to properly support S0ix, the platform needs to not skip C states. + * Correct the latencies here. + */ + if (acpi_processor_vendor_amd() && (latency2 >= latency3)) { + pr->power.states[2].latency = 18; + pr->power.states[3].latency = 350; + } + lapic_timer_propagate_broadcast(pr); return (working);