diff options
Diffstat (limited to 'drivers/acpi/processor_idle.c')
-rw-r--r-- | drivers/acpi/processor_idle.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 2235f4e02d26..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); |
@@ -534,6 +555,7 @@ static void acpi_processor_idle(void) | |||
534 | break; | 555 | break; |
535 | 556 | ||
536 | case ACPI_STATE_C3: | 557 | case ACPI_STATE_C3: |
558 | acpi_unlazy_tlb(smp_processor_id()); | ||
537 | /* | 559 | /* |
538 | * Must be done before busmaster disable as we might | 560 | * Must be done before busmaster disable as we might |
539 | * need to access HPET ! | 561 | * need to access HPET ! |
@@ -579,7 +601,8 @@ static void acpi_processor_idle(void) | |||
579 | 601 | ||
580 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 602 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
581 | /* TSC halts in C3, so notify users */ | 603 | /* TSC halts in C3, so notify users */ |
582 | mark_tsc_unstable("TSC halts in C3"); | 604 | if (tsc_halts_in_c(ACPI_STATE_C3)) |
605 | mark_tsc_unstable("TSC halts in C3"); | ||
583 | #endif | 606 | #endif |
584 | /* Compute time (ticks) that we were actually asleep */ | 607 | /* Compute time (ticks) that we were actually asleep */ |
585 | sleep_ticks = ticks_elapsed(t1, t2); | 608 | sleep_ticks = ticks_elapsed(t1, t2); |
@@ -1423,6 +1446,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
1423 | return 0; | 1446 | return 0; |
1424 | } | 1447 | } |
1425 | 1448 | ||
1449 | acpi_unlazy_tlb(smp_processor_id()); | ||
1426 | /* | 1450 | /* |
1427 | * Must be done before busmaster disable as we might need to | 1451 | * Must be done before busmaster disable as we might need to |
1428 | * access HPET ! | 1452 | * access HPET ! |
@@ -1443,7 +1467,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
1443 | 1467 | ||
1444 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 1468 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
1445 | /* TSC could halt in idle, so notify users */ | 1469 | /* TSC could halt in idle, so notify users */ |
1446 | mark_tsc_unstable("TSC halts in idle");; | 1470 | if (tsc_halts_in_c(cx->type)) |
1471 | mark_tsc_unstable("TSC halts in idle");; | ||
1447 | #endif | 1472 | #endif |
1448 | sleep_ticks = ticks_elapsed(t1, t2); | 1473 | sleep_ticks = ticks_elapsed(t1, t2); |
1449 | 1474 | ||
@@ -1554,7 +1579,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1554 | 1579 | ||
1555 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) | 1580 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |
1556 | /* TSC could halt in idle, so notify users */ | 1581 | /* TSC could halt in idle, so notify users */ |
1557 | mark_tsc_unstable("TSC halts in idle"); | 1582 | if (tsc_halts_in_c(ACPI_STATE_C3)) |
1583 | mark_tsc_unstable("TSC halts in idle"); | ||
1558 | #endif | 1584 | #endif |
1559 | sleep_ticks = ticks_elapsed(t1, t2); | 1585 | sleep_ticks = ticks_elapsed(t1, t2); |
1560 | /* Tell the scheduler how much we idled: */ | 1586 | /* Tell the scheduler how much we idled: */ |