From b1cffebf1029c87e1f1984d48463ee21093a6bc7 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 26 Nov 2012 15:05:48 -0600 Subject: ARM: GIC: remove direct use of gic_raise_softirq In preparation of moving gic code to drivers/irqchip, remove the direct platform dependencies on gic_raise_softirq. Move the setup of smp_cross_call into the gic code and use arch_send_wakeup_ipi_mask function to trigger wake-up IPIs. Signed-off-by: Rob Herring Cc: Russell King Cc: Kukjin Kim Cc: Sascha Hauer Cc: David Brown Cc: Daniel Walker Cc: Bryan Huntsman Acked-by: Tony Lindgren Acked-by: Santosh Shilimkar Cc: Paul Mundt Cc: Magnus Damm Acked-by: Viresh Kumar Cc: Shiraz Hashim Acked-by: Stephen Warren Cc: Srinidhi Kasagar Cc: Linus Walleij Acked-by: Olof Johansson --- arch/arm/kernel/smp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/arm/kernel/smp.c') diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 84f4cbf652e5..3fc96db2a4b6 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -416,7 +416,8 @@ static void (*smp_cross_call)(const struct cpumask *, unsigned int); void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int)) { - smp_cross_call = fn; + if (!smp_cross_call) + smp_cross_call = fn; } void arch_send_call_function_ipi_mask(const struct cpumask *mask) -- cgit v1.2.3 From 0a301110b7bd33ef10164c184fe2c1d8c4c3ab6b Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 14 Jan 2013 15:54:28 +0000 Subject: ARM: smp: remove wrapper functions Remove some silly wrapper functions which aren't really required: platform_smp_prepare_cpus platform_secondary_init platform_cpu_die This simplifies the code. Signed-off-by: Russell King --- arch/arm/kernel/smp.c | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) (limited to 'arch/arm/kernel/smp.c') diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 84f4cbf652e5..365c8d92e2eb 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -125,18 +125,6 @@ void __init smp_init_cpus(void) smp_ops.smp_init_cpus(); } -static void __init platform_smp_prepare_cpus(unsigned int max_cpus) -{ - if (smp_ops.smp_prepare_cpus) - smp_ops.smp_prepare_cpus(max_cpus); -} - -static void __cpuinit platform_secondary_init(unsigned int cpu) -{ - if (smp_ops.smp_secondary_init) - smp_ops.smp_secondary_init(cpu); -} - int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) { if (smp_ops.smp_boot_secondary) @@ -154,12 +142,6 @@ static int platform_cpu_kill(unsigned int cpu) return 1; } -static void platform_cpu_die(unsigned int cpu) -{ - if (smp_ops.cpu_die) - smp_ops.cpu_die(cpu); -} - static int platform_cpu_disable(unsigned int cpu) { if (smp_ops.cpu_disable) @@ -257,7 +239,8 @@ void __ref cpu_die(void) * actual CPU shutdown procedure is at least platform (if not * CPU) specific. */ - platform_cpu_die(cpu); + if (smp_ops.cpu_die) + smp_ops.cpu_die(cpu); /* * Do not return to the idle loop - jump back to the secondary @@ -324,7 +307,8 @@ asmlinkage void __cpuinit secondary_start_kernel(void) /* * Give the platform a chance to do its own initialisation. */ - platform_secondary_init(cpu); + if (smp_ops.smp_secondary_init) + smp_ops.smp_secondary_init(cpu); notify_cpu_starting(cpu); @@ -399,8 +383,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) /* * Initialise the present map, which describes the set of CPUs * actually populated at the present time. A platform should - * re-initialize the map in platform_smp_prepare_cpus() if - * present != possible (e.g. physical hotplug). + * re-initialize the map in the platforms smp_prepare_cpus() + * if present != possible (e.g. physical hotplug). */ init_cpu_present(cpu_possible_mask); @@ -408,7 +392,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) * Initialise the SCU if there are more than one CPU * and let them know where to start. */ - platform_smp_prepare_cpus(max_cpus); + if (smp_ops.smp_prepare_cpus) + smp_ops.smp_prepare_cpus(max_cpus); } } -- cgit v1.2.3 From e2c501190c7d4bf9d7febb9e1f1094cbde59ed89 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Tue, 30 Oct 2012 11:17:01 +0000 Subject: arm: Use generic timer broadcast receiver Currently, the ARM backend must maintain a redundant list of timers for the purpose of centralising timer broadcast functionality. This prevents sharing timer drivers across architectures. This patch moves the pain of dealing with timer broadcasts to the core clockevents tick broadcast code, which already maintains its own list of timers. Signed-off-by: Mark Rutland Reviewed-by: Santosh Shilimkar Tested-by: Santosh Shilimkar Reviewed-by: Stephen Boyd --- arch/arm/kernel/smp.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'arch/arm/kernel/smp.c') diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 84f4cbf652e5..930851912b37 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -475,12 +475,6 @@ u64 smp_irq_stat_cpu(unsigned int cpu) */ static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent); -static void ipi_timer(void) -{ - struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent); - evt->event_handler(evt); -} - #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST static void smp_timer_broadcast(const struct cpumask *mask) { @@ -596,11 +590,13 @@ void handle_IPI(int ipinr, struct pt_regs *regs) case IPI_WAKEUP: break; +#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST case IPI_TIMER: irq_enter(); - ipi_timer(); + tick_receive_broadcast(); irq_exit(); break; +#endif case IPI_RESCHEDULE: scheduler_ipi(); -- cgit v1.2.3 From 3d06770eef43eaad606e77246bfcc7e82b1d9fb4 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Tue, 30 Oct 2012 12:13:42 +0000 Subject: arm: Add generic timer broadcast support Implement timer_broadcast for the arm architecture, allowing for the use of clock_event_device_drivers decoupled from the timer tick broadcast mechanism. Signed-off-by: Mark Rutland Reviewed-by: Santosh Shilimkar Tested-by: Santosh Shilimkar Reviewed-by: Stephen Boyd --- arch/arm/Kconfig | 1 + arch/arm/kernel/smp.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/kernel/smp.c') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 67874b82a4ed..65ae7375c6c1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -4,6 +4,7 @@ config ARM select ARCH_BINFMT_ELF_RANDOMIZE_PIE select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select ARCH_HAVE_CUSTOM_GPIO_H + select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_WANT_IPC_PARSE_VERSION select BUILDTIME_EXTABLE_SORT if MMU select CPU_PM if (SUSPEND || CPU_IDLE) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 930851912b37..b7e3b506219b 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -476,7 +476,7 @@ u64 smp_irq_stat_cpu(unsigned int cpu) static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent); #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST -static void smp_timer_broadcast(const struct cpumask *mask) +void tick_broadcast(const struct cpumask *mask) { smp_cross_call(mask, IPI_TIMER); } @@ -524,7 +524,6 @@ static void __cpuinit percpu_timer_setup(void) struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); evt->cpumask = cpumask_of(cpu); - evt->broadcast = smp_timer_broadcast; if (!lt_ops || lt_ops->setup(evt)) broadcast_timer_setup(evt); -- cgit v1.2.3 From 9664ffe6a16676fa4d6a238ad3d9bb6cc24825a1 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Tue, 12 Feb 2013 18:22:14 +0100 Subject: ARM: 7651/1: remove unused smp_timer_broadcast #define The assignment of clock_event_device::broadcast can be done by timer core as of 12ad100046: "clockevents: Add generic timer broadcast function", and the arm code moved over to this as of 3d06770eef: "arm: Add generic timer broadcast support", but left a dangling #define when !CONFIG_GENERIC_TIMER_BROADCAST. This patch removes the now unused #define. Signed-off-by: Mark Rutland Signed-off-by: Russell King --- arch/arm/kernel/smp.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/arm/kernel/smp.c') diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index b7e3b506219b..ab9458d62cbb 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -480,8 +480,6 @@ void tick_broadcast(const struct cpumask *mask) { smp_cross_call(mask, IPI_TIMER); } -#else -#define smp_timer_broadcast NULL #endif static void broadcast_timer_set_mode(enum clock_event_mode mode, -- cgit v1.2.3 From 70264367a243a68b1d5636ffb570183449803cbe Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 18 Feb 2013 16:36:13 +0100 Subject: ARM: 7653/2: do not scale loops_per_jiffy when using a constant delay clock When udelay() is implemented using an architected timer, it is wrong to scale loops_per_jiffy when changing the CPU clock frequency since the timer clock remains constant. The lpj should probably become an implementation detail relevant to the CPU loop based delay routine only and more confined to it. In the mean time this is the minimal fix needed to have expected delays with the timer based implementation when cpufreq is also in use. Reported-by: Viresh Kumar Signed-off-by: Nicolas Pitre Tested-by: Viresh Kumar Acked-by: Liviu Dudau Cc: stable@vger.kernel.org Signed-off-by: Russell King --- arch/arm/include/asm/delay.h | 1 + arch/arm/kernel/smp.c | 3 +++ arch/arm/lib/delay.c | 1 + 3 files changed, 5 insertions(+) (limited to 'arch/arm/kernel/smp.c') diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h index ab98fdd083bd..720799fd3a81 100644 --- a/arch/arm/include/asm/delay.h +++ b/arch/arm/include/asm/delay.h @@ -24,6 +24,7 @@ extern struct arm_delay_ops { void (*delay)(unsigned long); void (*const_udelay)(unsigned long); void (*udelay)(unsigned long); + bool const_clock; } arm_delay_ops; #define __delay(n) arm_delay_ops.delay(n) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 84f4cbf652e5..58af91c2a2f7 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -693,6 +693,9 @@ static int cpufreq_callback(struct notifier_block *nb, if (freq->flags & CPUFREQ_CONST_LOOPS) return NOTIFY_OK; + if (arm_delay_ops.const_clock) + return NOTIFY_OK; + if (!per_cpu(l_p_j_ref, cpu)) { per_cpu(l_p_j_ref, cpu) = per_cpu(cpu_data, cpu).loops_per_jiffy; diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c index 0dc53854a5d8..6b93f6a1a3c7 100644 --- a/arch/arm/lib/delay.c +++ b/arch/arm/lib/delay.c @@ -77,6 +77,7 @@ void __init register_current_timer_delay(const struct delay_timer *timer) arm_delay_ops.delay = __timer_delay; arm_delay_ops.const_udelay = __timer_const_udelay; arm_delay_ops.udelay = __timer_udelay; + arm_delay_ops.const_clock = true; delay_calibrated = true; } else { pr_info("Ignoring duplicate/late registration of read_current_timer delay\n"); -- cgit v1.2.3 From 89c7e4b8bbb3d4fa52df5746a8ad38e610143651 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 28 Feb 2013 17:48:40 +0100 Subject: ARM: 7661/1: mm: perform explicit branch predictor maintenance when required The ARM ARM requires branch predictor maintenance if, for a given ASID, the instructions at a specific virtual address appear to change. From the kernel's point of view, that means: - Changing the kernel's view of memory (e.g. switching to the identity map) - ASID rollover (since ASIDs will be re-allocated to new tasks) This patch adds explicit branch predictor maintenance when either of the two conditions above are met. Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/smp.c | 1 + arch/arm/kernel/suspend.c | 1 + arch/arm/mm/context.c | 4 +++- arch/arm/mm/idmap.c | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) (limited to 'arch/arm/kernel/smp.c') diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 1bdfd87c8e41..31644f1978d5 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -285,6 +285,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) * switch away from it before attempting any exclusive accesses. */ cpu_switch_mm(mm->pgd, mm); + local_flush_bp_all(); enter_lazy_tlb(mm, current); local_flush_tlb_all(); diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c index 358bca3a995e..c59c97ea8268 100644 --- a/arch/arm/kernel/suspend.c +++ b/arch/arm/kernel/suspend.c @@ -68,6 +68,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) ret = __cpu_suspend(arg, fn); if (ret == 0) { cpu_switch_mm(mm->pgd, mm); + local_flush_bp_all(); local_flush_tlb_all(); } diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 44d4ee52f3e2..a5a4b2bc42ba 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -212,8 +212,10 @@ void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk) atomic64_set(&mm->context.id, asid); } - if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending)) + if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending)) { + local_flush_bp_all(); local_flush_tlb_all(); + } atomic64_set(&per_cpu(active_asids, cpu), asid); cpumask_set_cpu(cpu, mm_cpumask(mm)); diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 2dffc010cc41..5ee505c937d1 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c @@ -141,6 +141,7 @@ void setup_mm_for_reboot(void) { /* Switch to the identity mapping. */ cpu_switch_mm(idmap_pgd, &init_mm); + local_flush_bp_all(); #ifdef CONFIG_CPU_HAS_ASID /* -- cgit v1.2.3