diff options
| author | Andrew Morton <akpm@digeo.com> | 2002-10-29 23:23:34 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@penguin.transmeta.com> | 2002-10-29 23:23:34 -0800 |
| commit | 706489d8a6f1187875ebdb86a751b6d77d1911e4 (patch) | |
| tree | 97879c4cdcbc8bd68c4f4345d3c918c1a1a7ce98 /kernel | |
| parent | c51fcfae69efd3af4df2f87c37409521ae69b3db (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.c | 20 | ||||
| -rw-r--r-- | kernel/softirq.c | 3 |
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 }; |
