aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/processor_idle.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/processor_idle.c')
-rw-r--r--drivers/acpi/processor_idle.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 4ea6d8b20d17..8206fc1ecc58 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -39,6 +39,7 @@
39#include <linux/moduleparam.h> 39#include <linux/moduleparam.h>
40#include <linux/sched.h> /* need_resched() */ 40#include <linux/sched.h> /* need_resched() */
41#include <linux/latency.h> 41#include <linux/latency.h>
42#include <linux/clockchips.h>
42 43
43/* 44/*
44 * Include the apic definitions for x86 to have the APIC timer related defines 45 * Include the apic definitions for x86 to have the APIC timer related defines
@@ -274,12 +275,40 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr,
274 275
275static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) 276static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)
276{ 277{
278#ifdef CONFIG_GENERIC_CLOCKEVENTS
279 unsigned long reason;
280
281 reason = pr->power.timer_broadcast_on_state < INT_MAX ?
282 CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF;
283
284 clockevents_notify(reason, &pr->id);
285#else
277 cpumask_t mask = cpumask_of_cpu(pr->id); 286 cpumask_t mask = cpumask_of_cpu(pr->id);
278 287
279 if (pr->power.timer_broadcast_on_state < INT_MAX) 288 if (pr->power.timer_broadcast_on_state < INT_MAX)
280 on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1); 289 on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1);
281 else 290 else
282 on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1); 291 on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
292#endif
293}
294
295/* Power(C) State timer broadcast control */
296static void acpi_state_timer_broadcast(struct acpi_processor *pr,
297 struct acpi_processor_cx *cx,
298 int broadcast)
299{
300#ifdef CONFIG_GENERIC_CLOCKEVENTS
301
302 int state = cx - pr->power.states;
303
304 if (state >= pr->power.timer_broadcast_on_state) {
305 unsigned long reason;
306
307 reason = broadcast ? CLOCK_EVT_NOTIFY_BROADCAST_ENTER :
308 CLOCK_EVT_NOTIFY_BROADCAST_EXIT;
309 clockevents_notify(reason, &pr->id);
310 }
311#endif
283} 312}
284 313
285#else 314#else
@@ -287,6 +316,11 @@ static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)
287static void acpi_timer_check_state(int state, struct acpi_processor *pr, 316static void acpi_timer_check_state(int state, struct acpi_processor *pr,
288 struct acpi_processor_cx *cstate) { } 317 struct acpi_processor_cx *cstate) { }
289static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { } 318static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { }
319static void acpi_state_timer_broadcast(struct acpi_processor *pr,
320 struct acpi_processor_cx *cx,
321 int broadcast)
322{
323}
290 324
291#endif 325#endif
292 326
@@ -434,6 +468,7 @@ static void acpi_processor_idle(void)
434 /* Get start time (ticks) */ 468 /* Get start time (ticks) */
435 t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); 469 t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
436 /* Invoke C2 */ 470 /* Invoke C2 */
471 acpi_state_timer_broadcast(pr, cx, 1);
437 acpi_cstate_enter(cx); 472 acpi_cstate_enter(cx);
438 /* Get end time (ticks) */ 473 /* Get end time (ticks) */
439 t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); 474 t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
@@ -448,6 +483,7 @@ static void acpi_processor_idle(void)
448 /* Compute time (ticks) that we were actually asleep */ 483 /* Compute time (ticks) that we were actually asleep */
449 sleep_ticks = 484 sleep_ticks =
450 ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD; 485 ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
486 acpi_state_timer_broadcast(pr, cx, 0);
451 break; 487 break;
452 488
453 case ACPI_STATE_C3: 489 case ACPI_STATE_C3:
@@ -469,6 +505,7 @@ static void acpi_processor_idle(void)
469 /* Get start time (ticks) */ 505 /* Get start time (ticks) */
470 t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); 506 t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
471 /* Invoke C3 */ 507 /* Invoke C3 */
508 acpi_state_timer_broadcast(pr, cx, 1);
472 acpi_cstate_enter(cx); 509 acpi_cstate_enter(cx);
473 /* Get end time (ticks) */ 510 /* Get end time (ticks) */
474 t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); 511 t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
@@ -488,6 +525,7 @@ static void acpi_processor_idle(void)
488 /* Compute time (ticks) that we were actually asleep */ 525 /* Compute time (ticks) that we were actually asleep */
489 sleep_ticks = 526 sleep_ticks =
490 ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD; 527 ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD;
528 acpi_state_timer_broadcast(pr, cx, 0);
491 break; 529 break;
492 530
493 default: 531 default: