summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAndrew Morton <akpm@digeo.com>2002-10-29 23:23:34 -0800
committerLinus Torvalds <torvalds@penguin.transmeta.com>2002-10-29 23:23:34 -0800
commit706489d8a6f1187875ebdb86a751b6d77d1911e4 (patch)
tree97879c4cdcbc8bd68c4f4345d3c918c1a1a7ce98 /kernel
parentc51fcfae69efd3af4df2f87c37409521ae69b3db (diff)
[PATCH] slab: extended cpu notifiers
Patch from Dipankar Sarma <dipankar@in.ibm.com> This is Manfred's patch which provides a CPU_UP_PREPARE cpu notifier to allow initialization of per_cpu data just before the cpu becomes fully functional. It also provides a facility for the CPU_UP_PREPARE handler to return NOTIFY_BAD to signify that the CPU is not permitted to come up. If that happens, a CPU_UP_CANCELLED message is passed to all the handlers. The patch also fixes a bogus NOFITY_BAD return from the softirq setup code. Patch has been acked by Rusty. We need this mechanism in slab for starting per-cpu timers and for allocating the per-cpu slab hgead arrays *before* the CPU has come up and started using slab.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cpu.c20
-rw-r--r--kernel/softirq.c3
2 files changed, 17 insertions, 6 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c
index a155998dbe3e..4c0ada2b99ae 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -29,26 +29,38 @@ void unregister_cpu_notifier(struct notifier_block *nb)
int __devinit cpu_up(unsigned int cpu)
{
int ret;
+ void *hcpu = (void *)(long)cpu;
- if ((ret = down_interruptible(&cpucontrol)) != 0)
+ if ((ret = down_interruptible(&cpucontrol)) != 0)
return ret;
if (cpu_online(cpu)) {
ret = -EINVAL;
goto out;
}
+ ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
+ if (ret == NOTIFY_BAD) {
+ printk("%s: attempt to bring up CPU %u failed\n",
+ __FUNCTION__, cpu);
+ ret = -EINVAL;
+ goto out_notify;
+ }
/* Arch-specific enabling code. */
ret = __cpu_up(cpu);
- if (ret != 0) goto out;
+ if (ret != 0)
+ goto out_notify;
if (!cpu_online(cpu))
BUG();
/* Now call notifier in preparation. */
printk("CPU %u IS NOW UP!\n", cpu);
- notifier_call_chain(&cpu_chain, CPU_ONLINE, (void *)(long)cpu);
+ notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);
- out:
+out_notify:
+ if (ret != 0)
+ notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu);
+out:
up(&cpucontrol);
return ret;
}
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 45e8712f9f70..1c0f1c4e39e0 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -316,9 +316,8 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
while (!ksoftirqd_task(hotcpu))
yield();
- return NOTIFY_OK;
}
- return NOTIFY_BAD;
+ return NOTIFY_OK;
}
static struct notifier_block cpu_nfb = { &cpu_callback, NULL, 0 };