diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/processor_idle.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 0721a8183c89..eb1f82f79153 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -357,6 +357,26 @@ int acpi_processor_resume(struct acpi_device * device) | |||
357 | return 0; | 357 | return 0; |
358 | } | 358 | } |
359 | 359 | ||
360 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | ||
361 | static int tsc_halts_in_c(int state) | ||
362 | { | ||
363 | switch (boot_cpu_data.x86_vendor) { | ||
364 | case X86_VENDOR_AMD: | ||
365 | /* | ||
366 | * AMD Fam10h TSC will tick in all | ||
367 | * C/P/S0/S1 states when this bit is set. | ||
368 | */ | ||
369 | if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) | ||
370 | return 0; | ||
371 | /*FALL THROUGH*/ | ||
372 | case X86_VENDOR_INTEL: | ||
373 | /* Several cases known where TSC halts in C2 too */ | ||
374 | default: | ||
375 | return state > ACPI_STATE_C1; | ||
376 | } | ||
377 | } | ||
378 | #endif | ||
379 | |||
360 | #ifndef CONFIG_CPU_IDLE | 380 | #ifndef CONFIG_CPU_IDLE |
361 | static void acpi_processor_idle(void) | 381 | static void acpi_processor_idle(void) |
362 | { | 382 | { |
@@ -516,7 +536,8 @@ static void acpi_processor_idle(void) | |||
516 | 536 | ||
517 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 537 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
518 | /* TSC halts in C2, so notify users */ | 538 | /* TSC halts in C2, so notify users */ |
519 | mark_tsc_unstable("possible TSC halt in C2"); | 539 | if (tsc_halts_in_c(ACPI_STATE_C2)) |
540 | mark_tsc_unstable("possible TSC halt in C2"); | ||
520 | #endif | 541 | #endif |
521 | /* Compute time (ticks) that we were actually asleep */ | 542 | /* Compute time (ticks) that we were actually asleep */ |
522 | sleep_ticks = ticks_elapsed(t1, t2); | 543 | sleep_ticks = ticks_elapsed(t1, t2); |
@@ -580,7 +601,8 @@ static void acpi_processor_idle(void) | |||
580 | 601 | ||
581 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 602 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
582 | /* TSC halts in C3, so notify users */ | 603 | /* TSC halts in C3, so notify users */ |
583 | mark_tsc_unstable("TSC halts in C3"); | 604 | if (tsc_halts_in_c(ACPI_STATE_C3)) |
605 | mark_tsc_unstable("TSC halts in C3"); | ||
584 | #endif | 606 | #endif |
585 | /* Compute time (ticks) that we were actually asleep */ | 607 | /* Compute time (ticks) that we were actually asleep */ |
586 | sleep_ticks = ticks_elapsed(t1, t2); | 608 | sleep_ticks = ticks_elapsed(t1, t2); |
@@ -1445,7 +1467,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
1445 | 1467 | ||
1446 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 1468 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
1447 | /* TSC could halt in idle, so notify users */ | 1469 | /* TSC could halt in idle, so notify users */ |
1448 | mark_tsc_unstable("TSC halts in idle");; | 1470 | if (tsc_halts_in_c(cx->type)) |
1471 | mark_tsc_unstable("TSC halts in idle");; | ||
1449 | #endif | 1472 | #endif |
1450 | sleep_ticks = ticks_elapsed(t1, t2); | 1473 | sleep_ticks = ticks_elapsed(t1, t2); |
1451 | 1474 | ||
@@ -1556,7 +1579,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1556 | 1579 | ||
1557 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 1580 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
1558 | /* TSC could halt in idle, so notify users */ | 1581 | /* TSC could halt in idle, so notify users */ |
1559 | mark_tsc_unstable("TSC halts in idle"); | 1582 | if (tsc_halts_in_c(ACPI_STATE_C3)) |
1583 | mark_tsc_unstable("TSC halts in idle"); | ||
1560 | #endif | 1584 | #endif |
1561 | sleep_ticks = ticks_elapsed(t1, t2); | 1585 | sleep_ticks = ticks_elapsed(t1, t2); |
1562 | /* Tell the scheduler how much we idled: */ | 1586 | /* Tell the scheduler how much we idled: */ |