Skip to content

Commit

Permalink
Merge with ARM SMP tree
Browse files Browse the repository at this point in the history
  • Loading branch information
Russell King authored and Russell King committed Nov 8, 2005
2 parents 5285eb5 + 37ee16a commit 72274c9
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 0 deletions.
10 changes: 10 additions & 0 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions arch/arm/kernel/entry-armv.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions arch/arm/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
34 changes: 34 additions & 0 deletions arch/arm/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
*/
Expand Down Expand Up @@ -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);
Expand All @@ -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()
*
Expand Down
1 change: 1 addition & 0 deletions include/asm-arm/hardirq.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
38 changes: 38 additions & 0 deletions include/asm-arm/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,42 @@ extern void platform_cpu_die(unsigned int cpu);
extern int platform_cpu_kill(unsigned int cpu);
extern void platform_cpu_enable(unsigned int cpu);

#ifdef CONFIG_LOCAL_TIMERS
/*
* Setup a local timer interrupt for a CPU.
*/
extern void local_timer_setup(unsigned int cpu);

/*
* Stop a local timer interrupt.
*/
extern void local_timer_stop(unsigned int cpu);

/*
* Platform provides this to acknowledge a local timer IRQ
*/
extern int local_timer_ack(void);

#else

static inline void local_timer_setup(unsigned int cpu)
{
}

static inline void local_timer_stop(unsigned int cpu)
{
}

#endif

/*
* show local interrupt info
*/
extern void show_local_irqs(struct seq_file *);

/*
* Called from assembly, this is the local timer IRQ handler
*/
asmlinkage void do_local_timer(struct pt_regs *);

#endif /* ifndef __ASM_ARM_SMP_H */

0 comments on commit 72274c9

Please sign in to comment.