aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2015-07-16 06:58:44 -0400
committerThomas Gleixner <tglx@linutronix.de>2015-07-29 18:51:47 -0400
commitb23d8e527815954768861bb20d2b224009fff7cd (patch)
tree14b48e9112c7aa94ee8e26a9c28a4147716d81c1
parentc149e4cd08ba01f4d2d0104f469d5f5419294e06 (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.c86
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/* 465static int lapic_timer_shutdown(struct clock_event_device *evt)
466 * Setup the lapic timer in periodic or oneshot mode
467 */
468static 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); 486static inline int
491 apic_write(APIC_TMICT, 0); 487lapic_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
504static int lapic_timer_set_periodic(struct clock_event_device *evt)
505{
506 return lapic_timer_set_periodic_oneshot(evt, false);
507}
508
509static 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 */
515static struct clock_event_device lapic_clockevent = { 528static 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};
526static DEFINE_PER_CPU(struct clock_event_device, lapic_events); 542static 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