|
@@ -462,40 +462,53 @@ static int lapic_next_deadline(unsigned long delta,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Setup the lapic timer in periodic or oneshot mode
|
|
|
- */
|
|
|
-static void lapic_timer_setup(enum clock_event_mode mode,
|
|
|
- struct clock_event_device *evt)
|
|
|
+static int lapic_timer_shutdown(struct clock_event_device *evt)
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
unsigned int v;
|
|
|
|
|
|
/* Lapic used as dummy for broadcast ? */
|
|
|
if (evt->features & CLOCK_EVT_FEAT_DUMMY)
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
|
|
|
local_irq_save(flags);
|
|
|
|
|
|
- switch (mode) {
|
|
|
- case CLOCK_EVT_MODE_PERIODIC:
|
|
|
- case CLOCK_EVT_MODE_ONESHOT:
|
|
|
- __setup_APIC_LVTT(lapic_timer_frequency,
|
|
|
- mode != CLOCK_EVT_MODE_PERIODIC, 1);
|
|
|
- break;
|
|
|
- case CLOCK_EVT_MODE_UNUSED:
|
|
|
- case CLOCK_EVT_MODE_SHUTDOWN:
|
|
|
- v = apic_read(APIC_LVTT);
|
|
|
- v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
|
|
|
- apic_write(APIC_LVTT, v);
|
|
|
- apic_write(APIC_TMICT, 0);
|
|
|
- break;
|
|
|
- case CLOCK_EVT_MODE_RESUME:
|
|
|
- /* Nothing to do here */
|
|
|
- break;
|
|
|
- }
|
|
|
+ v = apic_read(APIC_LVTT);
|
|
|
+ v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
|
|
|
+ apic_write(APIC_LVTT, v);
|
|
|
+ apic_write(APIC_TMICT, 0);
|
|
|
+
|
|
|
+ local_irq_restore(flags);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static inline int
|
|
|
+lapic_timer_set_periodic_oneshot(struct clock_event_device *evt, bool oneshot)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ /* Lapic used as dummy for broadcast ? */
|
|
|
+ if (evt->features & CLOCK_EVT_FEAT_DUMMY)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ local_irq_save(flags);
|
|
|
+
|
|
|
+ __setup_APIC_LVTT(lapic_timer_frequency, oneshot, 1);
|
|
|
|
|
|
local_irq_restore(flags);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int lapic_timer_set_periodic(struct clock_event_device *evt)
|
|
|
+{
|
|
|
+ return lapic_timer_set_periodic_oneshot(evt, false);
|
|
|
+}
|
|
|
+
|
|
|
+static int lapic_timer_set_oneshot(struct clock_event_device *evt)
|
|
|
+{
|
|
|
+ return lapic_timer_set_periodic_oneshot(evt, true);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -513,15 +526,18 @@ static void lapic_timer_broadcast(const struct cpumask *mask)
|
|
|
* The local apic timer can be used for any function which is CPU local.
|
|
|
*/
|
|
|
static struct clock_event_device lapic_clockevent = {
|
|
|
- .name = "lapic",
|
|
|
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
|
|
|
- | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
|
|
|
- .shift = 32,
|
|
|
- .set_mode = lapic_timer_setup,
|
|
|
- .set_next_event = lapic_next_event,
|
|
|
- .broadcast = lapic_timer_broadcast,
|
|
|
- .rating = 100,
|
|
|
- .irq = -1,
|
|
|
+ .name = "lapic",
|
|
|
+ .features = CLOCK_EVT_FEAT_PERIODIC |
|
|
|
+ CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP
|
|
|
+ | CLOCK_EVT_FEAT_DUMMY,
|
|
|
+ .shift = 32,
|
|
|
+ .set_state_shutdown = lapic_timer_shutdown,
|
|
|
+ .set_state_periodic = lapic_timer_set_periodic,
|
|
|
+ .set_state_oneshot = lapic_timer_set_oneshot,
|
|
|
+ .set_next_event = lapic_next_event,
|
|
|
+ .broadcast = lapic_timer_broadcast,
|
|
|
+ .rating = 100,
|
|
|
+ .irq = -1,
|
|
|
};
|
|
|
static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
|
|
|
|
|
@@ -778,7 +794,7 @@ static int __init calibrate_APIC_clock(void)
|
|
|
* Setup the apic timer manually
|
|
|
*/
|
|
|
levt->event_handler = lapic_cal_handler;
|
|
|
- lapic_timer_setup(CLOCK_EVT_MODE_PERIODIC, levt);
|
|
|
+ lapic_timer_set_periodic(levt);
|
|
|
lapic_cal_loops = -1;
|
|
|
|
|
|
/* Let the interrupts run */
|
|
@@ -788,7 +804,7 @@ static int __init calibrate_APIC_clock(void)
|
|
|
cpu_relax();
|
|
|
|
|
|
/* Stop the lapic timer */
|
|
|
- lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, levt);
|
|
|
+ lapic_timer_shutdown(levt);
|
|
|
|
|
|
/* Jiffies delta */
|
|
|
deltaj = lapic_cal_j2 - lapic_cal_j1;
|
|
@@ -878,7 +894,7 @@ static void local_apic_timer_interrupt(void)
|
|
|
if (!evt->event_handler) {
|
|
|
pr_warning("Spurious LAPIC timer interrupt on cpu %d\n", cpu);
|
|
|
/* Switch it off */
|
|
|
- lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt);
|
|
|
+ lapic_timer_shutdown(evt);
|
|
|
return;
|
|
|
}
|
|
|
|