summaryrefslogtreecommitdiff
path: root/arch/arm/kernel/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/smp.c')
-rw-r--r--arch/arm/kernel/smp.c47
1 files changed, 42 insertions, 5 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index edb5a406922f..e55ea952f7aa 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -142,7 +142,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
ret = -EIO;
}
- secondary_data.stack = 0;
+ secondary_data.stack = NULL;
secondary_data.pgdir = 0;
*pmd_offset(pgd, PHYS_OFFSET) = __pmd(0);
@@ -185,6 +185,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.
*/
@@ -251,7 +256,9 @@ void __cpuexit cpu_die(void)
asmlinkage void __cpuinit secondary_start_kernel(void)
{
struct mm_struct *mm = &init_mm;
- unsigned int cpu = smp_processor_id();
+ unsigned int cpu;
+
+ cpu = smp_processor_id();
printk("CPU%u: Booted secondary processor\n", cpu);
@@ -268,6 +275,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
local_flush_tlb_all();
cpu_init();
+ preempt_disable();
/*
* Give the platform a chance to do its own initialisation.
@@ -290,6 +298,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
*/
cpu_idle();
@@ -359,8 +372,8 @@ static void send_ipi_message(cpumask_t callmap, enum ipi_msg_type msg)
* You must not call this function with disabled interrupts, from a
* hardware interrupt handler, nor from a bottom half handler.
*/
-int smp_call_function_on_cpu(void (*func)(void *info), void *info, int retry,
- int wait, cpumask_t callmap)
+static int smp_call_function_on_cpu(void (*func)(void *info), void *info,
+ int retry, int wait, cpumask_t callmap)
{
struct smp_call_struct data;
unsigned long timeout;
@@ -454,6 +467,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 +489,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()
*
@@ -515,7 +552,7 @@ static void ipi_cpu_stop(unsigned int cpu)
*
* Bit 0 - Inter-processor function call
*/
-void do_IPI(struct pt_regs *regs)
+asmlinkage void do_IPI(struct pt_regs *regs)
{
unsigned int cpu = smp_processor_id();
struct ipi_data *ipi = &per_cpu(ipi_data, cpu);