Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b23d8e52 authored by Viresh Kumar's avatar Viresh Kumar Committed by Thomas Gleixner
Browse files

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: default avatarViresh 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: default avatarThomas Gleixner <tglx@linutronix.de>
parent c149e4cd
Loading
Loading
Loading
Loading
+51 −35
Original line number Diff line number Diff line
@@ -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;

	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);
}

/*
@@ -514,10 +527,13 @@ static void lapic_timer_broadcast(const struct cpumask *mask)
 */
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,
	.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_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,
@@ -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;
	}