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

Commit 10034aab authored by Russell King's avatar Russell King
Browse files

ARM: localtimer: clean up local timer on hot unplug



When a CPU is hot unplugged, the generic tick code cleans up the
clock event device, but fails to call down to the device's set_mode
function to actually shut the device down.

To work around this, we've historically had a local_timer_stop()
callback out of the hotplug code.  However, this adds needless
complexity when we have the clock event device itself available.

Explicitly call the clock event device's set_mode function with
CLOCK_EVT_MODE_UNUSED, so that the hardware can be cleanly shutdown
without any special external callbacks.  When/if the generic code
is fixed, percpu_timer_stop() can be killed off.

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent e3d9c625
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ asmlinkage void do_local_timer(struct pt_regs *);
#include "smp_twd.h"

#define local_timer_ack()	twd_timer_ack()
#define local_timer_stop()	twd_timer_stop()

#else

@@ -40,11 +39,6 @@ asmlinkage void do_local_timer(struct pt_regs *);
 */
int local_timer_ack(void);

/*
 * Stop a local timer interrupt.
 */
void local_timer_stop(void);

#endif

/*
@@ -52,12 +46,6 @@ void local_timer_stop(void);
 */
void local_timer_setup(struct clock_event_device *);

#else

static inline void local_timer_stop(void)
{
}

#endif

#endif
+0 −1
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ struct clock_event_device;

extern void __iomem *twd_base;

void twd_timer_stop(void);
int twd_timer_ack(void);
void twd_timer_setup(struct clock_event_device *);

+18 −1
Original line number Diff line number Diff line
@@ -189,6 +189,8 @@ int __cpuinit __cpu_up(unsigned int cpu)
}

#ifdef CONFIG_HOTPLUG_CPU
static void percpu_timer_stop(void);

/*
 * __cpu_disable runs on the processor to be shutdown.
 */
@@ -216,7 +218,7 @@ int __cpu_disable(void)
	/*
	 * Stop the local timer for this CPU.
	 */
	local_timer_stop();
	percpu_timer_stop();

	/*
	 * Flush user cache and TLB mappings, and then remove this CPU
@@ -539,6 +541,21 @@ void __cpuinit percpu_timer_setup(void)
	local_timer_setup(evt);
}

#ifdef CONFIG_HOTPLUG_CPU
/*
 * The generic clock events code purposely does not stop the local timer
 * on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it
 * manually here.
 */
static void percpu_timer_stop(void)
{
	unsigned int cpu = smp_processor_id();
	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);

	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
}
#endif

static DEFINE_SPINLOCK(stop_lock);

/*
+0 −10
Original line number Diff line number Diff line
@@ -150,13 +150,3 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)

	clockevents_register_device(clk);
}

#ifdef CONFIG_HOTPLUG_CPU
/*
 * take a local timer down
 */
void twd_timer_stop(void)
{
	__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
}
#endif