mirror of
https://github.com/adulau/aha.git
synced 2025-01-01 05:36:24 +00:00
Merge with ARM SMP tree
This commit is contained in:
commit
72274c9e24
6 changed files with 91 additions and 0 deletions
|
@ -356,6 +356,16 @@ config HOTPLUG_CPU
|
||||||
Say Y here to experiment with turning CPUs off and on. CPUs
|
Say Y here to experiment with turning CPUs off and on. CPUs
|
||||||
can be controlled through /sys/devices/system/cpu.
|
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
|
config PREEMPT
|
||||||
bool "Preemptible Kernel (EXPERIMENTAL)"
|
bool "Preemptible Kernel (EXPERIMENTAL)"
|
||||||
depends on EXPERIMENTAL
|
depends on EXPERIMENTAL
|
||||||
|
|
|
@ -47,6 +47,13 @@
|
||||||
movne r0, sp
|
movne r0, sp
|
||||||
adrne lr, 1b
|
adrne lr, 1b
|
||||||
bne do_IPI
|
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
|
#endif
|
||||||
|
|
||||||
.endm
|
.endm
|
||||||
|
|
|
@ -264,6 +264,7 @@ unlock:
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
show_ipi_list(p);
|
show_ipi_list(p);
|
||||||
|
show_local_irqs(p);
|
||||||
#endif
|
#endif
|
||||||
seq_printf(p, "Err: %10lu\n", irq_err_count);
|
seq_printf(p, "Err: %10lu\n", irq_err_count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,6 +184,11 @@ int __cpuexit __cpu_disable(void)
|
||||||
*/
|
*/
|
||||||
migrate_irqs();
|
migrate_irqs();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stop the local timer for this CPU.
|
||||||
|
*/
|
||||||
|
local_timer_stop(cpu);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flush user cache and TLB mappings, and then remove this CPU
|
* Flush user cache and TLB mappings, and then remove this CPU
|
||||||
* from the vm mask set of all processes.
|
* 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);
|
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
|
* 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');
|
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)
|
static void ipi_timer(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int user = user_mode(regs);
|
int user = user_mode(regs);
|
||||||
|
@ -464,6 +486,18 @@ static void ipi_timer(struct pt_regs *regs)
|
||||||
irq_exit();
|
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()
|
* ipi_call_function - handle IPI from smp_call_function()
|
||||||
*
|
*
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int __softirq_pending;
|
unsigned int __softirq_pending;
|
||||||
|
unsigned int local_timer_irqs;
|
||||||
} ____cacheline_aligned irq_cpustat_t;
|
} ____cacheline_aligned irq_cpustat_t;
|
||||||
|
|
||||||
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
|
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
|
||||||
|
|
|
@ -92,4 +92,42 @@ extern void platform_cpu_die(unsigned int cpu);
|
||||||
extern int platform_cpu_kill(unsigned int cpu);
|
extern int platform_cpu_kill(unsigned int cpu);
|
||||||
extern void platform_cpu_enable(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 */
|
#endif /* ifndef __ASM_ARM_SMP_H */
|
||||||
|
|
Loading…
Reference in a new issue