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

Commit 37ee16ae authored by Russell King's avatar Russell King Committed by Russell King
Browse files

[ARM SMP] Add core ARM support for local timers



Add infrastructure for supporting per-cpu local timers to update
the profiling information and update system time accounting.

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 3b6353fa
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -356,6 +356,16 @@ config HOTPLUG_CPU
	  Say Y here to experiment with turning CPUs off and on.  CPUs
	  can be controlled through /sys/devices/system/cpu.

config LOCAL_TIMERS
	bool "Use local timer interrupts"
	depends on SMP && n
	default y
	help
	  Enable support for local timers on SMP platforms, rather then the
	  legacy IPI broadcast method.  Local timers allows the system
	  accounting to be spread across the timer interval, preventing a
	  "thundering herd" at every timer tick.

config PREEMPT
	bool "Preemptible Kernel (EXPERIMENTAL)"
	depends on EXPERIMENTAL
+7 −0
Original line number Diff line number Diff line
@@ -47,6 +47,13 @@
	movne	r0, sp
	adrne	lr, 1b
	bne	do_IPI

#ifdef CONFIG_LOCAL_TIMERS
	test_for_ltirq r0, r6, r5, lr
	movne	r0, sp
	adrne	lr, 1b
	bne	do_local_timer
#endif
#endif

	.endm
+1 −0
Original line number Diff line number Diff line
@@ -264,6 +264,7 @@ int show_interrupts(struct seq_file *p, void *v)
#endif
#ifdef CONFIG_SMP
		show_ipi_list(p);
		show_local_irqs(p);
#endif
		seq_printf(p, "Err: %10lu\n", irq_err_count);
	}
+34 −0
Original line number Diff line number Diff line
@@ -184,6 +184,11 @@ int __cpuexit __cpu_disable(void)
	 */
	migrate_irqs();

	/*
	 * Stop the local timer for this CPU.
	 */
	local_timer_stop(cpu);

	/*
	 * Flush user cache and TLB mappings, and then remove this CPU
	 * from the vm mask set of all processes.
@@ -289,6 +294,11 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
	 */
	cpu_set(cpu, cpu_online_map);

	/*
	 * Setup local timer for this CPU.
	 */
	local_timer_setup(cpu);

	/*
	 * OK, it's off to the idle thread for us
	 */
@@ -454,6 +464,18 @@ void show_ipi_list(struct seq_file *p)
	seq_putc(p, '\n');
}

void show_local_irqs(struct seq_file *p)
{
	unsigned int cpu;

	seq_printf(p, "LOC: ");

	for_each_present_cpu(cpu)
		seq_printf(p, "%10u ", irq_stat[cpu].local_timer_irqs);

	seq_putc(p, '\n');
}

static void ipi_timer(struct pt_regs *regs)
{
	int user = user_mode(regs);
@@ -464,6 +486,18 @@ static void ipi_timer(struct pt_regs *regs)
	irq_exit();
}

#ifdef CONFIG_LOCAL_TIMERS
asmlinkage void do_local_timer(struct pt_regs *regs)
{
	int cpu = smp_processor_id();

	if (local_timer_ack()) {
		irq_stat[cpu].local_timer_irqs++;
		ipi_timer(regs);
	}
}
#endif

/*
 * ipi_call_function - handle IPI from smp_call_function()
 *
+1 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@

typedef struct {
	unsigned int __softirq_pending;
	unsigned int local_timer_irqs;
} ____cacheline_aligned irq_cpustat_t;

#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
Loading