From 826681043d7184b4d650cab5b007b9a86b628eb5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 May 2009 16:20:18 +0100 Subject: [ARM] smp: fix cpumask usage in ARM SMP code The ARM SMP code wasn't properly updated for the cpumask changes, which results in smp_timer_broadcast() broadcasting ticks to non-online CPUs. Signed-off-by: Russell King --- arch/arm/common/gic.c | 4 +-- arch/arm/include/asm/hardware/gic.h | 2 +- arch/arm/include/asm/smp.h | 12 +++----- arch/arm/kernel/smp.c | 46 +++++++++++-------------------- arch/arm/mach-realview/include/mach/smp.h | 6 ++-- arch/arm/mach-realview/platsmp.c | 4 +-- 6 files changed, 28 insertions(+), 46 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index c6884ba1d5e..3e1714c6523 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -253,9 +253,9 @@ void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base) } #ifdef CONFIG_SMP -void gic_raise_softirq(cpumask_t cpumask, unsigned int irq) +void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { - unsigned long map = *cpus_addr(cpumask); + unsigned long map = *cpus_addr(*mask); /* this always happens on GIC0 */ writel(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT); diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h index 4924914af18..7f34333bb54 100644 --- a/arch/arm/include/asm/hardware/gic.h +++ b/arch/arm/include/asm/hardware/gic.h @@ -36,7 +36,7 @@ void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start); void gic_cpu_init(unsigned int gic_nr, void __iomem *base); void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); -void gic_raise_softirq(cpumask_t cpumask, unsigned int irq); +void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); #endif #endif diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index fad70da5911..5995935338e 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -53,17 +53,12 @@ extern void smp_store_cpu_info(unsigned int cpuid); /* * Raise an IPI cross call on CPUs in callmap. */ -extern void smp_cross_call(cpumask_t callmap); - -/* - * Broadcast a timer interrupt to the other CPUs. - */ -extern void smp_send_timer(void); +extern void smp_cross_call(const struct cpumask *mask); /* * Broadcast a clock event to other CPUs. */ -extern void smp_timer_broadcast(cpumask_t mask); +extern void smp_timer_broadcast(const struct cpumask *mask); /* * Boot a secondary CPU, and assign it the specified idle task. @@ -102,7 +97,8 @@ extern int platform_cpu_kill(unsigned int cpu); extern void platform_cpu_enable(unsigned int cpu); extern void arch_send_call_function_single_ipi(int cpu); -extern void arch_send_call_function_ipi(cpumask_t mask); +extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); +#define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask /* * Local timer interrupt handling function (can be IPI'ed). diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 7801aac3c04..6014dfd22af 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -326,14 +326,14 @@ void __init smp_prepare_boot_cpu(void) per_cpu(cpu_data, cpu).idle = current; } -static void send_ipi_message(cpumask_t callmap, enum ipi_msg_type msg) +static void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg) { unsigned long flags; unsigned int cpu; local_irq_save(flags); - for_each_cpu_mask(cpu, callmap) { + for_each_cpu(cpu, mask) { struct ipi_data *ipi = &per_cpu(ipi_data, cpu); spin_lock(&ipi->lock); @@ -344,19 +344,19 @@ static void send_ipi_message(cpumask_t callmap, enum ipi_msg_type msg) /* * Call the platform specific cross-CPU call function. */ - smp_cross_call(callmap); + smp_cross_call(mask); local_irq_restore(flags); } -void arch_send_call_function_ipi(cpumask_t mask) +void arch_send_call_function_ipi_mask(const struct cpumask *mask) { send_ipi_message(mask, IPI_CALL_FUNC); } void arch_send_call_function_single_ipi(int cpu) { - send_ipi_message(cpumask_of_cpu(cpu), IPI_CALL_FUNC_SINGLE); + send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); } void show_ipi_list(struct seq_file *p) @@ -498,17 +498,10 @@ asmlinkage void __exception do_IPI(struct pt_regs *regs) void smp_send_reschedule(int cpu) { - send_ipi_message(cpumask_of_cpu(cpu), IPI_RESCHEDULE); + send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); } -void smp_send_timer(void) -{ - cpumask_t mask = cpu_online_map; - cpu_clear(smp_processor_id(), mask); - send_ipi_message(mask, IPI_TIMER); -} - -void smp_timer_broadcast(cpumask_t mask) +void smp_timer_broadcast(const struct cpumask *mask) { send_ipi_message(mask, IPI_TIMER); } @@ -517,7 +510,7 @@ void smp_send_stop(void) { cpumask_t mask = cpu_online_map; cpu_clear(smp_processor_id(), mask); - send_ipi_message(mask, IPI_CPU_STOP); + send_ipi_message(&mask, IPI_CPU_STOP); } /* @@ -528,20 +521,17 @@ int setup_profiling_timer(unsigned int multiplier) return -EINVAL; } -static int -on_each_cpu_mask(void (*func)(void *), void *info, int wait, cpumask_t mask) +static void +on_each_cpu_mask(void (*func)(void *), void *info, int wait, + const struct cpumask *mask) { - int ret = 0; - preempt_disable(); - ret = smp_call_function_mask(mask, func, info, wait); - if (cpu_isset(smp_processor_id(), mask)) + smp_call_function_many(mask, func, info, wait); + if (cpumask_test_cpu(smp_processor_id(), mask)) func(info); preempt_enable(); - - return ret; } /**********************************************************************/ @@ -602,20 +592,17 @@ void flush_tlb_all(void) void flush_tlb_mm(struct mm_struct *mm) { - cpumask_t mask = mm->cpu_vm_mask; - - on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mask); + on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, &mm->cpu_vm_mask); } void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) { - cpumask_t mask = vma->vm_mm->cpu_vm_mask; struct tlb_args ta; ta.ta_vma = vma; ta.ta_start = uaddr; - on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mask); + on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, &vma->vm_mm->cpu_vm_mask); } void flush_tlb_kernel_page(unsigned long kaddr) @@ -630,14 +617,13 @@ void flush_tlb_kernel_page(unsigned long kaddr) void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - cpumask_t mask = vma->vm_mm->cpu_vm_mask; struct tlb_args ta; ta.ta_vma = vma; ta.ta_start = start; ta.ta_end = end; - on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mask); + on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, &vma->vm_mm->cpu_vm_mask); } void flush_tlb_kernel_range(unsigned long start, unsigned long end) diff --git a/arch/arm/mach-realview/include/mach/smp.h b/arch/arm/mach-realview/include/mach/smp.h index 515819efd04..e2ff53402f8 100644 --- a/arch/arm/mach-realview/include/mach/smp.h +++ b/arch/arm/mach-realview/include/mach/smp.h @@ -15,15 +15,15 @@ /* * We use IRQ1 as the IPI */ -static inline void smp_cross_call(cpumask_t callmap) +static inline void smp_cross_call(const struct cpumask *mask) { - gic_raise_softirq(callmap, 1); + gic_raise_softirq(mask, 1); } /* * Do nothing on MPcore. */ -static inline void smp_cross_call_done(cpumask_t callmap) +static inline void smp_cross_call_done(const struct cpumask *mask) { } diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index ea3c75595fa..a5730466dff 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -82,7 +82,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) * to get this processor out of WFI in the BootMonitor - make * sure that we are no longer being sent this soft interrupt */ - smp_cross_call_done(cpumask_of_cpu(cpu)); + smp_cross_call_done(cpumask_of(cpu)); /* * if any interrupts are already enabled for the primary @@ -136,7 +136,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) * Use smp_cross_call() for this, since there's little * point duplicating the code here */ - smp_cross_call(cpumask_of_cpu(cpu)); + smp_cross_call(cpumask_of(cpu)); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { -- cgit v1.2.3 From 78d236c2b30d4712c1fd8c9768b163c94b39e77d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 May 2009 16:23:45 +0100 Subject: [ARM] realview: remove useless smp_cross_call_done() smp_cross_call_done() is a no-op for MPCore, and since it's only used by platform code, there's no point in having it unless it's doing something. Signed-off-by: Russell King --- arch/arm/mach-realview/include/mach/smp.h | 7 ------- arch/arm/mach-realview/platsmp.c | 7 ------- 2 files changed, 14 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-realview/include/mach/smp.h b/arch/arm/mach-realview/include/mach/smp.h index e2ff53402f8..dd53892d44a 100644 --- a/arch/arm/mach-realview/include/mach/smp.h +++ b/arch/arm/mach-realview/include/mach/smp.h @@ -20,11 +20,4 @@ static inline void smp_cross_call(const struct cpumask *mask) gic_raise_softirq(mask, 1); } -/* - * Do nothing on MPcore. - */ -static inline void smp_cross_call_done(const struct cpumask *mask) -{ -} - #endif diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index a5730466dff..b037fd6c82d 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -77,13 +77,6 @@ void __cpuinit platform_secondary_init(unsigned int cpu) { trace_hardirqs_off(); - /* - * the primary core may have used a "cross call" soft interrupt - * to get this processor out of WFI in the BootMonitor - make - * sure that we are no longer being sent this soft interrupt - */ - smp_cross_call_done(cpumask_of(cpu)); - /* * if any interrupts are already enabled for the primary * core (e.g. timer irq), then they will not have been enabled -- cgit v1.2.3 From ee348d5a1d810bc9958cabb7c27302aab235d36e Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 May 2009 17:00:47 +0100 Subject: [ARM] realview: fix broadcast tick support Having discussed broadcast tick support with Thomas Glexiner, the broadcast tick devices should be registered with a higher rating than the global tick device, and it should have the ONESHOT and PERIODIC feature flags set. Signed-off-by: Russell King Acked-by: Thomas Glexiner --- arch/arm/mach-realview/core.c | 8 -------- arch/arm/mach-realview/localtimer.c | 6 ++++-- arch/arm/mach-realview/platsmp.c | 6 ++---- 3 files changed, 6 insertions(+), 14 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 942e1a7eb9b..076acbc5070 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -750,14 +750,6 @@ void __init realview_timer_init(unsigned int timer_irq) { u32 val; -#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST - /* - * The dummy clock device has to be registered before the main device - * so that the latter will broadcast the clock events - */ - local_timer_setup(); -#endif - /* * set clock frequency: * REALVIEW_REFCLK is 32KHz diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c index d0d39adf640..1c01d13460f 100644 --- a/arch/arm/mach-realview/localtimer.c +++ b/arch/arm/mach-realview/localtimer.c @@ -189,8 +189,10 @@ void __cpuinit local_timer_setup(void) struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); clk->name = "dummy_timer"; - clk->features = CLOCK_EVT_FEAT_DUMMY; - clk->rating = 200; + clk->features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_DUMMY; + clk->rating = 400; clk->mult = 1; clk->set_mode = dummy_timer_set_mode; clk->broadcast = smp_timer_broadcast; diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index b037fd6c82d..30a9c68591f 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -217,11 +217,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus) if (max_cpus > ncores) max_cpus = ncores; -#ifdef CONFIG_LOCAL_TIMERS +#if defined(CONFIG_LOCAL_TIMERS) || defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) /* - * Enable the local timer for primary CPU. If the device is - * dummy (!CONFIG_LOCAL_TIMERS), it was already registers in - * realview_timer_init + * Enable the local timer or broadcast device for the boot CPU. */ local_timer_setup(); #endif -- cgit v1.2.3