diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2007-02-16 04:28:04 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-16 11:13:59 -0500 |
commit | e9e2cdb412412326c4827fc78ba27f410d837e6e (patch) | |
tree | cd4ca03e6bdc3691619024492fb9414427b2f813 /drivers/acpi | |
parent | 79bf2bb335b85db25d27421c798595a2fa2a0e82 (diff) |
[PATCH] clockevents: i386 drivers
Add clockevent drivers for i386: lapic (local) and PIT/HPET (global). Update
the timer IRQ to call into the PIT/HPET driver's event handler and the
lapic-timer IRQ to call into the lapic clockevent driver. The assignement of
timer functionality is delegated to the core framework code and replaces the
compile and runtime evalution in do_timer_interrupt_hook()
Use the clockevents broadcast support and implement the lapic_broadcast
function for ACPI.
No changes to existing functionality.
[ kdump fix from Vivek Goyal <vgoyal@in.ibm.com> ]
[ fixes based on review feedback from Arjan van de Ven <arjan@infradead.org> ]
Cleanups-from: Adrian Bunk <bunk@stusta.de>
Build-fixes-from: Andrew Morton <akpm@osdl.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Cc: john stultz <johnstul@us.ibm.com>
Cc: Roman Zippel <zippel@linux-m68k.org>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/processor_idle.c | 38 |
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 | ||
275 | static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) | 276 | static 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 */ | ||
296 | static 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) | |||
287 | static void acpi_timer_check_state(int state, struct acpi_processor *pr, | 316 | static void acpi_timer_check_state(int state, struct acpi_processor *pr, |
288 | struct acpi_processor_cx *cstate) { } | 317 | struct acpi_processor_cx *cstate) { } |
289 | static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { } | 318 | static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { } |
319 | static 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: |