summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/smp.c
diff options
context:
space:
mode:
authorNathan Lynch2008-07-27 07:24:52 +0200
committerBenjamin Herrenschmidt2008-07-28 08:30:49 +0200
commite2075f79a99b45a6cc10de021c93f07212098a84 (patch)
tree8c3ccb423f706336741734d0758219028d765396 /arch/powerpc/kernel/smp.c
parentpowerpc: register_cpu_online should be __cpuinit (diff)
downloadkernel-qcow2-linux-e2075f79a99b45a6cc10de021c93f07212098a84.tar.gz
kernel-qcow2-linux-e2075f79a99b45a6cc10de021c93f07212098a84.tar.xz
kernel-qcow2-linux-e2075f79a99b45a6cc10de021c93f07212098a84.zip
powerpc: Update cpu_sibling_maps dynamically
Rather doing one initialization pass over all the per-cpu cpu_sibling_maps at boot, update the maps at cpu online/offline time. This is a behavior change -- the thread_siblings attribute now reflects only online siblings, whereas it would display offline siblings before. The new behavior matches that of x86, and is arguably more useful. Signed-off-by: Nathan Lynch <ntl@pobox.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/smp.c')
-rw-r--r--arch/powerpc/kernel/smp.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index f5ae9fa222ea..3c4d07e5e06a 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -41,6 +41,7 @@
#include <asm/smp.h>
#include <asm/time.h>
#include <asm/machdep.h>
+#include <asm/cputhreads.h>
#include <asm/cputable.h>
#include <asm/system.h>
#include <asm/mpic.h>
@@ -228,6 +229,7 @@ void __devinit smp_prepare_boot_cpu(void)
BUG_ON(smp_processor_id() != boot_cpuid);
cpu_set(boot_cpuid, cpu_online_map);
+ cpu_set(boot_cpuid, per_cpu(cpu_sibling_map, boot_cpuid));
#ifdef CONFIG_PPC64
paca[boot_cpuid].__current = current;
#endif
@@ -380,6 +382,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
int __devinit start_secondary(void *unused)
{
unsigned int cpu = smp_processor_id();
+ int i, base;
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
@@ -400,6 +403,14 @@ int __devinit start_secondary(void *unused)
ipi_call_lock();
cpu_set(cpu, cpu_online_map);
+ /* Update sibling maps */
+ base = cpu_first_thread_in_core(cpu);
+ for (i = 0; i < threads_per_core; i++) {
+ if (cpu_is_offline(base + i))
+ continue;
+ cpu_set(cpu, per_cpu(cpu_sibling_map, base + i));
+ cpu_set(base + i, per_cpu(cpu_sibling_map, cpu));
+ }
ipi_call_unlock();
local_irq_enable();
@@ -437,10 +448,25 @@ void __init smp_cpus_done(unsigned int max_cpus)
#ifdef CONFIG_HOTPLUG_CPU
int __cpu_disable(void)
{
- if (smp_ops->cpu_disable)
- return smp_ops->cpu_disable();
+ int cpu = smp_processor_id();
+ int base, i;
+ int err;
- return -ENOSYS;
+ if (!smp_ops->cpu_disable)
+ return -ENOSYS;
+
+ err = smp_ops->cpu_disable();
+ if (err)
+ return err;
+
+ /* Update sibling maps */
+ base = cpu_first_thread_in_core(cpu);
+ for (i = 0; i < threads_per_core; i++) {
+ cpu_clear(cpu, per_cpu(cpu_sibling_map, base + i));
+ cpu_clear(base + i, per_cpu(cpu_sibling_map, cpu));
+ }
+
+ return 0;
}
void __cpu_die(unsigned int cpu)