diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2015-07-16 06:58:44 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2015-07-29 18:51:47 -0400 |
commit | b23d8e527815954768861bb20d2b224009fff7cd (patch) | |
tree | 14b48e9112c7aa94ee8e26a9c28a4147716d81c1 | |
parent | c149e4cd08ba01f4d2d0104f469d5f5419294e06 (diff) |
x86/apic: Migrate apic timer to new set_state interface
Migrate apic driver to the new 'set-state' interface provided by
clockevents core, the earlier 'set-mode' interface is marked obsolete
now.
This also enables us to implement callbacks for new states of clockevent
devices, for example: ONESHOT_STOPPED.
We weren't doing anything while switching to resume mode and so that
callback isn't implemented.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Cc: linaro-kernel@lists.linaro.org
Cc: Jiang Liu <jiang.liu@linux.intel.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Bandan Das <bsd@redhat.com>
Link: http://lkml.kernel.org/r/1896ac5989d27f2ac37f4786af9bd537e1921b83.1437042675.git.viresh.kumar@linaro.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 86 |
1 files changed, 51 insertions, 35 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index dcb52850a28f..ecd6705c9f4b 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -462,40 +462,53 @@ static int lapic_next_deadline(unsigned long delta, | |||
462 | return 0; | 462 | return 0; |
463 | } | 463 | } |
464 | 464 | ||
465 | /* | 465 | static int lapic_timer_shutdown(struct clock_event_device *evt) |
466 | * Setup the lapic timer in periodic or oneshot mode | ||
467 | */ | ||
468 | static void lapic_timer_setup(enum clock_event_mode mode, | ||
469 | struct clock_event_device *evt) | ||
470 | { | 466 | { |
471 | unsigned long flags; | 467 | unsigned long flags; |
472 | unsigned int v; | 468 | unsigned int v; |
473 | 469 | ||
474 | /* Lapic used as dummy for broadcast ? */ | 470 | /* Lapic used as dummy for broadcast ? */ |
475 | if (evt->features & CLOCK_EVT_FEAT_DUMMY) | 471 | if (evt->features & CLOCK_EVT_FEAT_DUMMY) |
476 | return; | 472 | return 0; |
477 | 473 | ||
478 | local_irq_save(flags); | 474 | local_irq_save(flags); |
479 | 475 | ||
480 | switch (mode) { | 476 | v = apic_read(APIC_LVTT); |
481 | case CLOCK_EVT_MODE_PERIODIC: | 477 | v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); |
482 | case CLOCK_EVT_MODE_ONESHOT: | 478 | apic_write(APIC_LVTT, v); |
483 | __setup_APIC_LVTT(lapic_timer_frequency, | 479 | apic_write(APIC_TMICT, 0); |
484 | mode != CLOCK_EVT_MODE_PERIODIC, 1); | 480 | |
485 | break; | 481 | local_irq_restore(flags); |
486 | case CLOCK_EVT_MODE_UNUSED: | 482 | |
487 | case CLOCK_EVT_MODE_SHUTDOWN: | 483 | return 0; |
488 | v = apic_read(APIC_LVTT); | 484 | } |
489 | v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); | 485 | |
490 | apic_write(APIC_LVTT, v); | 486 | static inline int |
491 | apic_write(APIC_TMICT, 0); | 487 | lapic_timer_set_periodic_oneshot(struct clock_event_device *evt, bool oneshot) |
492 | break; | 488 | { |
493 | case CLOCK_EVT_MODE_RESUME: | 489 | unsigned long flags; |
494 | /* Nothing to do here */ | 490 | |
495 | break; | 491 | /* Lapic used as dummy for broadcast ? */ |
496 | } | 492 | if (evt->features & CLOCK_EVT_FEAT_DUMMY) |
493 | return 0; | ||
494 | |||
495 | local_irq_save(flags); | ||
496 | |||
497 | __setup_APIC_LVTT(lapic_timer_frequency, oneshot, 1); | ||
497 | 498 | ||
498 | local_irq_restore(flags); | 499 | local_irq_restore(flags); |
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | static int lapic_timer_set_periodic(struct clock_event_device *evt) | ||
505 | { | ||
506 | return lapic_timer_set_periodic_oneshot(evt, false); | ||
507 | } | ||
508 | |||
509 | static int lapic_timer_set_oneshot(struct clock_event_device *evt) | ||
510 | { | ||
511 | return lapic_timer_set_periodic_oneshot(evt, true); | ||
499 | } | 512 | } |
500 | 513 | ||
501 | /* | 514 | /* |
@@ -513,15 +526,18 @@ static void lapic_timer_broadcast(const struct cpumask *mask) | |||
513 | * The local apic timer can be used for any function which is CPU local. | 526 | * The local apic timer can be used for any function which is CPU local. |
514 | */ | 527 | */ |
515 | static struct clock_event_device lapic_clockevent = { | 528 | static struct clock_event_device lapic_clockevent = { |
516 | .name = "lapic", | 529 | .name = "lapic", |
517 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | 530 | .features = CLOCK_EVT_FEAT_PERIODIC | |
518 | | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY, | 531 | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP |
519 | .shift = 32, | 532 | | CLOCK_EVT_FEAT_DUMMY, |
520 | .set_mode = lapic_timer_setup, | 533 | .shift = 32, |
521 | .set_next_event = lapic_next_event, | 534 | .set_state_shutdown = lapic_timer_shutdown, |
522 | .broadcast = lapic_timer_broadcast, | 535 | .set_state_periodic = lapic_timer_set_periodic, |
523 | .rating = 100, | 536 | .set_state_oneshot = lapic_timer_set_oneshot, |
524 | .irq = -1, | 537 | .set_next_event = lapic_next_event, |
538 | .broadcast = lapic_timer_broadcast, | ||
539 | .rating = 100, | ||
540 | .irq = -1, | ||
525 | }; | 541 | }; |
526 | static DEFINE_PER_CPU(struct clock_event_device, lapic_events); | 542 | static DEFINE_PER_CPU(struct clock_event_device, lapic_events); |
527 | 543 | ||
@@ -778,7 +794,7 @@ static int __init calibrate_APIC_clock(void) | |||
778 | * Setup the apic timer manually | 794 | * Setup the apic timer manually |
779 | */ | 795 | */ |
780 | levt->event_handler = lapic_cal_handler; | 796 | levt->event_handler = lapic_cal_handler; |
781 | lapic_timer_setup(CLOCK_EVT_MODE_PERIODIC, levt); | 797 | lapic_timer_set_periodic(levt); |
782 | lapic_cal_loops = -1; | 798 | lapic_cal_loops = -1; |
783 | 799 | ||
784 | /* Let the interrupts run */ | 800 | /* Let the interrupts run */ |
@@ -788,7 +804,7 @@ static int __init calibrate_APIC_clock(void) | |||
788 | cpu_relax(); | 804 | cpu_relax(); |
789 | 805 | ||
790 | /* Stop the lapic timer */ | 806 | /* Stop the lapic timer */ |
791 | lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, levt); | 807 | lapic_timer_shutdown(levt); |
792 | 808 | ||
793 | /* Jiffies delta */ | 809 | /* Jiffies delta */ |
794 | deltaj = lapic_cal_j2 - lapic_cal_j1; | 810 | deltaj = lapic_cal_j2 - lapic_cal_j1; |
@@ -878,7 +894,7 @@ static void local_apic_timer_interrupt(void) | |||
878 | if (!evt->event_handler) { | 894 | if (!evt->event_handler) { |
879 | pr_warning("Spurious LAPIC timer interrupt on cpu %d\n", cpu); | 895 | pr_warning("Spurious LAPIC timer interrupt on cpu %d\n", cpu); |
880 | /* Switch it off */ | 896 | /* Switch it off */ |
881 | lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt); | 897 | lapic_timer_shutdown(evt); |
882 | return; | 898 | return; |
883 | } | 899 | } |
884 | 900 | ||