summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/smp.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-04-19 14:23:28 +0200
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-04-19 14:23:28 +0200
commitd5aeee8cb28317ef608ecac421abc4d986d585d2 (patch)
tree70ec8ed8891f26e5c58152ffca9924ea1c58fe3a /arch/arm/kernel/smp.c
parent[media] zoran: fix integer overflow in setup_window() (diff)
parentLinux 3.4-rc3 (diff)
downloadlinux-d5aeee8cb28317ef608ecac421abc4d986d585d2.tar.xz
linux-d5aeee8cb28317ef608ecac421abc4d986d585d2.zip
Merge tag 'v3.4-rc3' into staging/for_v3.5
* tag 'v3.4-rc3': (3755 commits) Linux 3.4-rc3 x86-32: fix up strncpy_from_user() sign error ARM: 7386/1: jump_label: fixup for rename to static_key ARM: 7384/1: ThumbEE: Disable userspace TEEHBR access for !CONFIG_ARM_THUMBEE ARM: 7382/1: mm: truncate memory banks to fit in 4GB space for classic MMU ARM: 7359/2: smp_twd: Only wait for reprogramming on active cpus PCI: Fix regression in pci_restore_state(), v3 SCSI: Fix error handling when no ULD is attached ARM: OMAP: clock: cleanup CPUfreq leftovers, fix build errors ARM: dts: remove blank interrupt-parent properties ARM: EXYNOS: Fix Kconfig dependencies for device tree enabled machine files do not export kernel's NULL #define to userspace ARM: EXYNOS: Remove broken config values for touchscren for NURI board ARM: EXYNOS: set fix xusbxti clock for NURI and Universal210 boards ARM: EXYNOS: fix regulator name for NURI board ARM: SAMSUNG: make SAMSUNG_PM_DEBUG select DEBUG_LL cpufreq: OMAP: fix build errors: depends on ARCH_OMAP2PLUS sparc64: Eliminate obsolete __handle_softirq() function sparc64: Fix bootup crash on sun4v. ARM: msm: Fix section mismatches in proc_comm.c ...
Diffstat (limited to 'arch/arm/kernel/smp.c')
-rw-r--r--arch/arm/kernel/smp.c46
1 files changed, 29 insertions, 17 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index d616ed51e7a7..addbbe8028c2 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -58,6 +58,8 @@ enum ipi_msg_type {
IPI_CPU_STOP,
};
+static DECLARE_COMPLETION(cpu_running);
+
int __cpuinit __cpu_up(unsigned int cpu)
{
struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
@@ -98,20 +100,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
*/
ret = boot_secondary(cpu, idle);
if (ret == 0) {
- unsigned long timeout;
-
/*
* CPU was successfully started, wait for it
* to come online or time out.
*/
- timeout = jiffies + HZ;
- while (time_before(jiffies, timeout)) {
- if (cpu_online(cpu))
- break;
-
- udelay(10);
- barrier();
- }
+ wait_for_completion_timeout(&cpu_running,
+ msecs_to_jiffies(1000));
if (!cpu_online(cpu)) {
pr_crit("CPU%u: failed to come online\n", cpu);
@@ -246,6 +240,8 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
store_cpu_topology(cpuid);
}
+static void percpu_timer_setup(void);
+
/*
* This is the secondary CPU boot entry. We're using this CPUs
* idle thread stack, but a set of temporary page tables.
@@ -286,9 +282,10 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
/*
* OK, now it's safe to let the boot CPU continue. Wait for
* the CPU migration code to notice that the CPU is online
- * before we continue.
+ * before we continue - which happens after __cpu_up returns.
*/
set_cpu_online(cpu, true);
+ complete(&cpu_running);
/*
* Setup the percpu timer for this CPU.
@@ -352,7 +349,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
* re-initialize the map in platform_smp_prepare_cpus() if
* present != possible (e.g. physical hotplug).
*/
- init_cpu_present(&cpu_possible_map);
+ init_cpu_present(cpu_possible_mask);
/*
* Initialise the SCU if there are more than one CPU
@@ -452,7 +449,20 @@ static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt)
clockevents_register_device(evt);
}
-void __cpuinit percpu_timer_setup(void)
+static struct local_timer_ops *lt_ops;
+
+#ifdef CONFIG_LOCAL_TIMERS
+int local_timer_register(struct local_timer_ops *ops)
+{
+ if (lt_ops)
+ return -EBUSY;
+
+ lt_ops = ops;
+ return 0;
+}
+#endif
+
+static void __cpuinit percpu_timer_setup(void)
{
unsigned int cpu = smp_processor_id();
struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
@@ -460,7 +470,7 @@ void __cpuinit percpu_timer_setup(void)
evt->cpumask = cpumask_of(cpu);
evt->broadcast = smp_timer_broadcast;
- if (local_timer_setup(evt))
+ if (!lt_ops || lt_ops->setup(evt))
broadcast_timer_setup(evt);
}
@@ -475,7 +485,8 @@ static void percpu_timer_stop(void)
unsigned int cpu = smp_processor_id();
struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
- local_timer_stop(evt);
+ if (lt_ops)
+ lt_ops->stop(evt);
}
#endif
@@ -570,8 +581,9 @@ void smp_send_stop(void)
unsigned long timeout;
if (num_online_cpus() > 1) {
- cpumask_t mask = cpu_online_map;
- cpu_clear(smp_processor_id(), mask);
+ struct cpumask mask;
+ cpumask_copy(&mask, cpu_online_mask);
+ cpumask_clear_cpu(smp_processor_id(), &mask);
smp_cross_call(&mask, IPI_CPU_STOP);
}