From bda3bdc9afce46302810e12ca1790ce08b9c40ce Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:41 +0000 Subject: m32r: Remove pointless function prototypes Already declared in include/linux/smp.h Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Cc: Hirokazu Takata Link: http://lkml.kernel.org/r/20120420124556.899547554@linutronix.de --- arch/m32r/kernel/smpboot.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c index cfdbe5d15002..31541c9b7eb6 100644 --- a/arch/m32r/kernel/smpboot.c +++ b/arch/m32r/kernel/smpboot.c @@ -109,12 +109,8 @@ static unsigned int calibration_result; /* Function Prototypes */ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ -void smp_prepare_boot_cpu(void); -void smp_prepare_cpus(unsigned int); static void init_ipi_lock(void); static void do_boot_cpu(int); -int __cpu_up(unsigned int); -void smp_cpus_done(unsigned int); int start_secondary(void *); static void smp_callin(void); -- cgit v1.2.3 From 8239c25f47d2b318156993b15f33900a86ea5e17 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:42 +0000 Subject: smp: Add task_struct argument to __cpu_up() Preparatory patch to make the idle thread allocation for secondary cpus generic. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Cc: Matt Turner Cc: Russell King Cc: Mike Frysinger Cc: Jesper Nilsson Cc: Richard Kuo Cc: Tony Luck Cc: Hirokazu Takata Cc: Ralf Baechle Cc: David Howells Cc: James E.J. Bottomley Cc: Benjamin Herrenschmidt Cc: Martin Schwidefsky Cc: Paul Mundt Cc: David S. Miller Cc: Chris Metcalf Cc: Richard Weinberger Cc: x86@kernel.org Link: http://lkml.kernel.org/r/20120420124556.964170564@linutronix.de --- arch/alpha/kernel/smp.c | 2 +- arch/arm/kernel/smp.c | 2 +- arch/blackfin/mach-common/smp.c | 2 +- arch/cris/arch-v32/kernel/smp.c | 2 +- arch/hexagon/kernel/smp.c | 2 +- arch/ia64/kernel/smpboot.c | 2 +- arch/m32r/kernel/smpboot.c | 2 +- arch/mips/kernel/smp.c | 2 +- arch/mn10300/kernel/smp.c | 2 +- arch/parisc/kernel/smp.c | 2 +- arch/powerpc/kernel/smp.c | 2 +- arch/s390/include/asm/smp.h | 2 +- arch/s390/kernel/smp.c | 2 +- arch/sh/kernel/smp.c | 2 +- arch/sparc/kernel/smp_32.c | 2 +- arch/sparc/kernel/smp_64.c | 2 +- arch/tile/kernel/smpboot.c | 2 +- arch/um/kernel/smp.c | 2 +- arch/x86/include/asm/smp.h | 4 +++- include/linux/smp.h | 2 +- kernel/cpu.c | 2 +- 21 files changed, 23 insertions(+), 21 deletions(-) diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 50d438db1f6b..68d39470fb52 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -487,7 +487,7 @@ smp_prepare_boot_cpu(void) } int __cpuinit -__cpu_up(unsigned int cpu) +__cpu_up(unsigned int cpu, struct task_struct *tidle) { smp_boot_one_cpu(cpu); diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index addbbe8028c2..f0e2cbbd837d 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -60,7 +60,7 @@ enum ipi_msg_type { static DECLARE_COMPLETION(cpu_running); -int __cpuinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu); struct task_struct *idle = ci->idle; diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index ac8f8a43158c..d0cddd95b0dd 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -340,7 +340,7 @@ void smp_send_stop(void) return; } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { int ret; struct blackfin_cpudata *ci = &per_cpu(cpu_data, cpu); diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index 0b99df72d2a4..125ee2d7bc87 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -207,7 +207,7 @@ int setup_profiling_timer(unsigned int multiplier) */ unsigned long cache_decay_ticks = 1; -int __cpuinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { smp_boot_one_cpu(cpu); return cpu_online(cpu) ? 0 : -ENOSYS; diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c index 1298141874a3..93e77e2b17a8 100644 --- a/arch/hexagon/kernel/smp.c +++ b/arch/hexagon/kernel/smp.c @@ -196,7 +196,7 @@ void __cpuinit start_secondary(void) * maintains control until "cpu_online(cpu)" is set. */ -int __cpuinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { struct task_struct *idle; struct thread_info *thread; diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 796f6a5b966a..03e4ef3893c9 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -793,7 +793,7 @@ set_cpu_sibling_map(int cpu) } int __cpuinit -__cpu_up (unsigned int cpu) +__cpu_up(unsigned int cpu, struct task_struct *tidle) { int ret; int sapicid; diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c index 31541c9b7eb6..a2cfc0abb05c 100644 --- a/arch/m32r/kernel/smpboot.c +++ b/arch/m32r/kernel/smpboot.c @@ -343,7 +343,7 @@ static void __init do_boot_cpu(int phys_id) } } -int __cpuinit __cpu_up(unsigned int cpu_id) +int __cpuinit __cpu_up(unsigned int cpu_id, struct task_struct *tidle) { int timeout; diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index ba9376bf52a1..41079b256092 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -209,7 +209,7 @@ static void __cpuinit do_fork_idle(struct work_struct *work) complete(&c_idle->done); } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { struct task_struct *idle; diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c index 910dddf65e44..c6b40dad0d0b 100644 --- a/arch/mn10300/kernel/smp.c +++ b/arch/mn10300/kernel/smp.c @@ -921,7 +921,7 @@ void initialize_secondary(void) * __cpu_up - Set smp_commenced_mask for the nominated CPU * @cpu: The target CPU. */ -int __devinit __cpu_up(unsigned int cpu) +int __devinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { int timeout; diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 0bb1d63907f8..eae8cd808f07 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -449,7 +449,7 @@ void smp_cpus_done(unsigned int cpu_max) } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { if (cpu != 0 && cpu < parisc_max_cpus) smp_boot_one_cpu(cpu); diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index d9f94410fd7f..d38030fb3471 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -482,7 +482,7 @@ static int __cpuinit create_idle(unsigned int cpu) return 0; } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { int rc, c; diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index c77c6de6f6c0..0b6f586c1383 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h @@ -16,7 +16,7 @@ extern struct mutex smp_cpu_state_mutex; extern struct save_area *zfcpdump_save_areas[NR_CPUS + 1]; -extern int __cpu_up(unsigned int cpu); +extern int __cpu_up(unsigned int cpu, struct task_struct *tidle); extern void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 1f77227669e8..fc827aa8f9ca 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -738,7 +738,7 @@ static void __cpuinit smp_fork_idle(struct work_struct *work) } /* Upping and downing of CPUs */ -int __cpuinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { struct create_idle c_idle; struct pcpu *pcpu; diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index eaebdf6a5c77..ebb76e2a748b 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -220,7 +220,7 @@ extern struct { void *thread_info; } stack_start; -int __cpuinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { struct task_struct *tsk; unsigned long timeout; diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index f671e7fd6ddc..1f397ae11028 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c @@ -411,7 +411,7 @@ void __init smp_prepare_boot_cpu(void) set_cpu_possible(cpuid, true); } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { extern int __cpuinit smp4m_boot_one_cpu(int); extern int __cpuinit smp4d_boot_one_cpu(int); diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 3b1bd7c50164..2f9948c4107c 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -1227,7 +1227,7 @@ void __devinit smp_fill_in_sib_core_maps(void) } } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { int ret = smp_boot_one_cpu(cpu); diff --git a/arch/tile/kernel/smpboot.c b/arch/tile/kernel/smpboot.c index 172aef7d3159..84873fbe8f27 100644 --- a/arch/tile/kernel/smpboot.c +++ b/arch/tile/kernel/smpboot.c @@ -222,7 +222,7 @@ void __cpuinit online_secondary(void) cpu_idle(); } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { /* Wait 5s total for all CPUs for them to come online */ static int timeout; diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index 6f588e160fb0..a02b7e9e6b94 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c @@ -140,7 +140,7 @@ void smp_prepare_boot_cpu(void) set_cpu_online(smp_processor_id(), true); } -int __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu, struct task_struct *tidle) { cpu_set(cpu, smp_commenced_mask); while (!cpu_online(cpu)) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 0434c400287c..4eb3a74bc4b0 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -62,6 +62,8 @@ DECLARE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid); /* Static state in head.S used to set up a CPU */ extern unsigned long stack_start; /* Initial stack pointer address */ +struct task_struct; + struct smp_ops { void (*smp_prepare_boot_cpu)(void); void (*smp_prepare_cpus)(unsigned max_cpus); @@ -113,7 +115,7 @@ static inline void smp_cpus_done(unsigned int max_cpus) smp_ops.smp_cpus_done(max_cpus); } -static inline int __cpu_up(unsigned int cpu) +static inline int __cpu_up(unsigned int cpu, struct task_struct *tidle) { return smp_ops.cpu_up(cpu); } diff --git a/include/linux/smp.h b/include/linux/smp.h index 10530d92c04b..24360de6c968 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -61,7 +61,7 @@ extern void smp_prepare_cpus(unsigned int max_cpus); /* * Bring a CPU up */ -extern int __cpu_up(unsigned int cpunum); +extern int __cpu_up(unsigned int cpunum, struct task_struct *tidle); /* * Final polishing of CPUs diff --git a/kernel/cpu.c b/kernel/cpu.c index 2060c6e57027..e711aef0fb3c 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -309,7 +309,7 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) } /* Arch-specific enabling code. */ - ret = __cpu_up(cpu); + ret = __cpu_up(cpu, NULL); if (ret != 0) goto out_notify; BUG_ON(!cpu_online(cpu)); -- cgit v1.2.3 From 38498a67aa2cf8c80754b8d304bfacc10bc582b5 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:44 +0000 Subject: smp: Add generic smpboot facility Start a new file, which will hold SMP and CPU hotplug related generic infrastructure. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Cc: Matt Turner Cc: Russell King Cc: Mike Frysinger Cc: Jesper Nilsson Cc: Richard Kuo Cc: Tony Luck Cc: Hirokazu Takata Cc: Ralf Baechle Cc: David Howells Cc: James E.J. Bottomley Cc: Benjamin Herrenschmidt Cc: Martin Schwidefsky Cc: Paul Mundt Cc: David S. Miller Cc: Chris Metcalf Cc: Richard Weinberger Cc: x86@kernel.org Link: http://lkml.kernel.org/r/20120420124557.035417523@linutronix.de --- kernel/Makefile | 1 + kernel/cpu.c | 8 ++++++++ kernel/smpboot.c | 14 ++++++++++++++ kernel/smpboot.h | 6 ++++++ 4 files changed, 29 insertions(+) create mode 100644 kernel/smpboot.c create mode 100644 kernel/smpboot.h diff --git a/kernel/Makefile b/kernel/Makefile index cb41b9547c9f..6c07f30fa9b7 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_DEBUG_RT_MUTEXES) += rtmutex-debug.o obj-$(CONFIG_RT_MUTEX_TESTER) += rtmutex-tester.o obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_SMP) += smpboot.o ifneq ($(CONFIG_SMP),y) obj-y += up.o endif diff --git a/kernel/cpu.c b/kernel/cpu.c index e711aef0fb3c..e58b99ada3d8 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -17,6 +17,8 @@ #include #include +#include "smpboot.h" + #ifdef CONFIG_SMP /* Serializes the updates to cpu_online_mask, cpu_present_mask */ static DEFINE_MUTEX(cpu_add_remove_lock); @@ -300,6 +302,11 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) return -EINVAL; cpu_hotplug_begin(); + + ret = smpboot_prepare(cpu); + if (ret) + goto out; + ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls); if (ret) { nr_calls--; @@ -320,6 +327,7 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) out_notify: if (ret != 0) __cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL); +out: cpu_hotplug_done(); return ret; diff --git a/kernel/smpboot.c b/kernel/smpboot.c new file mode 100644 index 000000000000..6dae6a3d2d59 --- /dev/null +++ b/kernel/smpboot.c @@ -0,0 +1,14 @@ +/* + * Common SMP CPU bringup/teardown functions + */ +#include + +#include "smpboot.h" + +/** + * smpboot_prepare - generic smpboot preparation + */ +int __cpuinit smpboot_prepare(unsigned int cpu) +{ + return 0; +} diff --git a/kernel/smpboot.h b/kernel/smpboot.h new file mode 100644 index 000000000000..d88e77165086 --- /dev/null +++ b/kernel/smpboot.h @@ -0,0 +1,6 @@ +#ifndef SMPBOOT_H +#define SMPBOOT_H + +int smpboot_prepare(unsigned int cpu); + +#endif -- cgit v1.2.3 From 29d5e0476e1c4a513859e7858845ad172f560389 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:45 +0000 Subject: smp: Provide generic idle thread allocation All SMP architectures have magic to fork the idle task and to store it for reusage when cpu hotplug is enabled. Provide a generic infrastructure for it. Create/reinit the idle thread for the cpu which is brought up in the generic code and hand the thread pointer to the architecture code via __cpu_up(). Note, that fork_idle() is called via a workqueue, because this guarantees that the idle thread does not get a reference to a user space VM. This can happen when the boot process did not bring up all possible cpus and a later cpu_up() is initiated via the sysfs interface. In that case fork_idle() would be called in the context of the user space task and take a reference on the user space VM. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Cc: Matt Turner Cc: Russell King Cc: Mike Frysinger Cc: Jesper Nilsson Cc: Richard Kuo Cc: Tony Luck Cc: Hirokazu Takata Cc: Ralf Baechle Cc: David Howells Cc: James E.J. Bottomley Cc: Benjamin Herrenschmidt Cc: Martin Schwidefsky Cc: Paul Mundt Cc: David S. Miller Cc: Chris Metcalf Cc: Richard Weinberger Cc: x86@kernel.org Acked-by: Venkatesh Pallipadi Link: http://lkml.kernel.org/r/20120420124557.102478630@linutronix.de --- arch/Kconfig | 3 ++ kernel/cpu.c | 2 +- kernel/sched/core.c | 2 ++ kernel/smpboot.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++- kernel/smpboot.h | 10 +++++++ 5 files changed, 99 insertions(+), 2 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 684eb5af439d..4f0d0f7c8313 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -145,6 +145,9 @@ config HAVE_DMA_ATTRS config USE_GENERIC_SMP_HELPERS bool +config GENERIC_SMP_IDLE_THREAD + bool + config HAVE_REGS_AND_STACK_ACCESS_API bool help diff --git a/kernel/cpu.c b/kernel/cpu.c index e58b99ada3d8..05c46bae5e55 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -316,7 +316,7 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) } /* Arch-specific enabling code. */ - ret = __cpu_up(cpu, NULL); + ret = __cpu_up(cpu, idle_thread_get(cpu)); if (ret != 0) goto out_notify; BUG_ON(!cpu_online(cpu)); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 4603b9d8f30a..6a63cde23d03 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -83,6 +83,7 @@ #include "sched.h" #include "../workqueue_sched.h" +#include "../smpboot.h" #define CREATE_TRACE_POINTS #include @@ -7049,6 +7050,7 @@ void __init sched_init(void) /* May be allocated at isolcpus cmdline parse time */ if (cpu_isolated_map == NULL) zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT); + idle_thread_set_boot_cpu(); #endif init_sched_fair_class(); diff --git a/kernel/smpboot.c b/kernel/smpboot.c index 6dae6a3d2d59..ed1576981801 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -1,14 +1,96 @@ /* * Common SMP CPU bringup/teardown functions */ +#include +#include #include +#include +#include +#include #include "smpboot.h" +#ifdef CONFIG_GENERIC_SMP_IDLE_THREAD +struct create_idle { + struct work_struct work; + struct task_struct *idle; + struct completion done; + unsigned int cpu; +}; + +static void __cpuinit do_fork_idle(struct work_struct *work) +{ + struct create_idle *c = container_of(work, struct create_idle, work); + + c->idle = fork_idle(c->cpu); + complete(&c->done); +} + +static struct task_struct * __cpuinit idle_thread_create(unsigned int cpu) +{ + struct create_idle c_idle = { + .cpu = cpu, + .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), + }; + + INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle); + schedule_work(&c_idle.work); + wait_for_completion(&c_idle.done); + destroy_work_on_stack(&c_idle.work); + return c_idle.idle; +} + +/* + * For the hotplug case we keep the task structs around and reuse + * them. + */ +static DEFINE_PER_CPU(struct task_struct *, idle_threads); + +static inline struct task_struct *get_idle_for_cpu(unsigned int cpu) +{ + struct task_struct *tsk = per_cpu(idle_threads, cpu); + + if (!tsk) + return idle_thread_create(cpu); + init_idle(tsk, cpu); + return tsk; +} + +struct task_struct * __cpuinit idle_thread_get(unsigned int cpu) +{ + return per_cpu(idle_threads, cpu); +} + +void __init idle_thread_set_boot_cpu(void) +{ + per_cpu(idle_threads, smp_processor_id()) = current; +} + +/** + * idle_thread_init - Initialize the idle thread for a cpu + * @cpu: The cpu for which the idle thread should be initialized + * + * Creates the thread if it does not exist. + */ +static int __cpuinit idle_thread_init(unsigned int cpu) +{ + struct task_struct *idle = get_idle_for_cpu(cpu); + + if (IS_ERR(idle)) { + printk(KERN_ERR "failed fork for CPU %u\n", cpu); + return PTR_ERR(idle); + } + per_cpu(idle_threads, cpu) = idle; + return 0; +} +#else +static inline int idle_thread_init(unsigned int cpu) { return 0; } +#endif + /** * smpboot_prepare - generic smpboot preparation */ int __cpuinit smpboot_prepare(unsigned int cpu) { - return 0; + return idle_thread_init(cpu); } diff --git a/kernel/smpboot.h b/kernel/smpboot.h index d88e77165086..7943bbbab917 100644 --- a/kernel/smpboot.h +++ b/kernel/smpboot.h @@ -1,6 +1,16 @@ #ifndef SMPBOOT_H #define SMPBOOT_H +struct task_struct; + int smpboot_prepare(unsigned int cpu); +#ifdef CONFIG_GENERIC_SMP_IDLE_THREAD +struct task_struct *idle_thread_get(unsigned int cpu); +void idle_thread_set_boot_cpu(void); +#else +static inline struct task_struct *idle_thread_get(unsigned int cpu) { return NULL; } +static inline void idle_thread_set_boot_cpu(void) { } +#endif + #endif -- cgit v1.2.3 From 5cdaf1834f43b0edc4a3aa683aa4ec98f6bfe8a7 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:47 +0000 Subject: x86: Add task_struct argument to smp_ops.cpu_up Preparatory patch to use the generic idle thread allocation. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Cc: Jeremy Fitzhardinge Cc: x86@kernel.org Link: http://lkml.kernel.org/r/20120420124557.176604405@linutronix.de --- arch/x86/include/asm/smp.h | 6 +++--- arch/x86/kernel/smpboot.c | 2 +- arch/x86/xen/smp.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 4eb3a74bc4b0..f3ed33811c23 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -72,7 +72,7 @@ struct smp_ops { void (*stop_other_cpus)(int wait); void (*smp_send_reschedule)(int cpu); - int (*cpu_up)(unsigned cpu); + int (*cpu_up)(unsigned cpu, struct task_struct *tidle); int (*cpu_disable)(void); void (*cpu_die)(unsigned int cpu); void (*play_dead)(void); @@ -117,7 +117,7 @@ static inline void smp_cpus_done(unsigned int max_cpus) static inline int __cpu_up(unsigned int cpu, struct task_struct *tidle) { - return smp_ops.cpu_up(cpu); + return smp_ops.cpu_up(cpu, tidle); } static inline int __cpu_disable(void) @@ -154,7 +154,7 @@ void cpu_disable_common(void); void native_smp_prepare_boot_cpu(void); void native_smp_prepare_cpus(unsigned int max_cpus); void native_smp_cpus_done(unsigned int max_cpus); -int native_cpu_up(unsigned int cpunum); +int native_cpu_up(unsigned int cpunum, struct task_struct *tidle); int native_cpu_disable(void); void native_cpu_die(unsigned int cpu); void native_play_dead(void); diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 6e1e406038c2..def235bf7594 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -818,7 +818,7 @@ do_rest: return boot_error; } -int __cpuinit native_cpu_up(unsigned int cpu) +int __cpuinit native_cpu_up(unsigned int cpu, struct task_struct *tidle) { int apicid = apic->cpu_present_to_apicid(cpu); unsigned long flags; diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 5fac6919b957..64d3bbce0b36 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -331,7 +331,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) return 0; } -static int __cpuinit xen_cpu_up(unsigned int cpu) +static int __cpuinit xen_cpu_up(unsigned int cpu, struct task_struct *tidle) { struct task_struct *idle = idle_task(cpu); int rc; @@ -547,10 +547,10 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus) xen_init_lock_cpu(0); } -static int __cpuinit xen_hvm_cpu_up(unsigned int cpu) +static int __cpuinit xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle) { int rc; - rc = native_cpu_up(cpu); + rc = native_cpu_up(cpu, tidle); WARN_ON (xen_smp_intr_init(cpu)); return rc; } -- cgit v1.2.3 From 7eb43a6d232bfa46464b501cd1987ec2d705d8cf Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:48 +0000 Subject: x86: Use generic idle thread allocation Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Cc: Jeremy Fitzhardinge Cc: x86@kernel.org Link: http://lkml.kernel.org/r/20120420124557.246929343@linutronix.de --- arch/x86/Kconfig | 1 + arch/x86/include/asm/smp.h | 1 + arch/x86/kernel/smpboot.c | 81 ++++++---------------------------------------- arch/x86/xen/smp.c | 15 ++------- 4 files changed, 14 insertions(+), 84 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 1d14cc6b79ad..046bf4bd2510 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -82,6 +82,7 @@ config X86 select ARCH_HAVE_NMI_SAFE_CMPXCHG select GENERIC_IOMAP select DCACHE_WORD_ACCESS if !DEBUG_PAGEALLOC + select GENERIC_SMP_IDLE_THREAD config INSTRUCTION_DECODER def_bool (KPROBES || PERF_EVENTS) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index f3ed33811c23..f8cbc6f20e31 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -164,6 +164,7 @@ int wbinvd_on_all_cpus(void); void native_send_call_func_ipi(const struct cpumask *mask); void native_send_call_func_single_ipi(int cpu); +void x86_idle_thread_init(unsigned int cpu, struct task_struct *idle); void smp_store_cpu_info(int id); #define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index def235bf7594..3acaf51dfddb 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -76,19 +76,7 @@ /* State of each CPU */ DEFINE_PER_CPU(int, cpu_state) = { 0 }; -/* Store all idle threads, this can be reused instead of creating -* a new thread. Also avoids complicated thread destroy functionality -* for idle threads. -*/ #ifdef CONFIG_HOTPLUG_CPU -/* - * Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is - * removed after init for !CONFIG_HOTPLUG_CPU. - */ -static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); -#define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x)) -#define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p)) - /* * We need this for trampoline_base protection from concurrent accesses when * off- and onlining cores wildly. @@ -97,20 +85,16 @@ static DEFINE_MUTEX(x86_cpu_hotplug_driver_mutex); void cpu_hotplug_driver_lock(void) { - mutex_lock(&x86_cpu_hotplug_driver_mutex); + mutex_lock(&x86_cpu_hotplug_driver_mutex); } void cpu_hotplug_driver_unlock(void) { - mutex_unlock(&x86_cpu_hotplug_driver_mutex); + mutex_unlock(&x86_cpu_hotplug_driver_mutex); } ssize_t arch_cpu_probe(const char *buf, size_t count) { return -1; } ssize_t arch_cpu_release(const char *buf, size_t count) { return -1; } -#else -static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; -#define get_idle_for_cpu(x) (idle_thread_array[(x)]) -#define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p)) #endif /* Number of siblings per CPU package */ @@ -618,22 +602,6 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) return (send_status | accept_status); } -struct create_idle { - struct work_struct work; - struct task_struct *idle; - struct completion done; - int cpu; -}; - -static void __cpuinit do_fork_idle(struct work_struct *work) -{ - struct create_idle *c_idle = - container_of(work, struct create_idle, work); - - c_idle->idle = fork_idle(c_idle->cpu); - complete(&c_idle->done); -} - /* reduce the number of lines printed when booting a large cpu count system */ static void __cpuinit announce_cpu(int cpu, int apicid) { @@ -660,58 +628,31 @@ static void __cpuinit announce_cpu(int cpu, int apicid) * Returns zero if CPU booted OK, else error code from * ->wakeup_secondary_cpu. */ -static int __cpuinit do_boot_cpu(int apicid, int cpu) +static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) { unsigned long boot_error = 0; unsigned long start_ip; int timeout; - struct create_idle c_idle = { - .cpu = cpu, - .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), - }; - - INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle); alternatives_smp_switch(1); - c_idle.idle = get_idle_for_cpu(cpu); - - /* - * We can't use kernel_thread since we must avoid to - * reschedule the child. - */ - if (c_idle.idle) { - c_idle.idle->thread.sp = (unsigned long) (((struct pt_regs *) - (THREAD_SIZE + task_stack_page(c_idle.idle))) - 1); - init_idle(c_idle.idle, cpu); - goto do_rest; - } + idle->thread.sp = (unsigned long) (((struct pt_regs *) + (THREAD_SIZE + task_stack_page(idle))) - 1); + per_cpu(current_task, cpu) = idle; - schedule_work(&c_idle.work); - wait_for_completion(&c_idle.done); - - if (IS_ERR(c_idle.idle)) { - printk("failed fork for CPU %d\n", cpu); - destroy_work_on_stack(&c_idle.work); - return PTR_ERR(c_idle.idle); - } - - set_idle_for_cpu(cpu, c_idle.idle); -do_rest: - per_cpu(current_task, cpu) = c_idle.idle; #ifdef CONFIG_X86_32 /* Stack for startup_32 can be just as for start_secondary onwards */ irq_ctx_init(cpu); #else - clear_tsk_thread_flag(c_idle.idle, TIF_FORK); + clear_tsk_thread_flag(idle, TIF_FORK); initial_gs = per_cpu_offset(cpu); per_cpu(kernel_stack, cpu) = - (unsigned long)task_stack_page(c_idle.idle) - + (unsigned long)task_stack_page(idle) - KERNEL_STACK_OFFSET + THREAD_SIZE; #endif early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); initial_code = (unsigned long)start_secondary; - stack_start = c_idle.idle->thread.sp; + stack_start = idle->thread.sp; /* start_ip had better be page-aligned! */ start_ip = trampoline_address(); @@ -813,8 +754,6 @@ do_rest: */ smpboot_restore_warm_reset_vector(); } - - destroy_work_on_stack(&c_idle.work); return boot_error; } @@ -851,7 +790,7 @@ int __cpuinit native_cpu_up(unsigned int cpu, struct task_struct *tidle) per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; - err = do_boot_cpu(apicid, cpu); + err = do_boot_cpu(apicid, cpu, tidle); if (err) { pr_debug("do_boot_cpu failed %d\n", err); return -EIO; diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 64d3bbce0b36..8f44cc1a9291 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -250,18 +250,8 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus) set_cpu_possible(cpu, false); } - for_each_possible_cpu (cpu) { - struct task_struct *idle; - - if (cpu == 0) - continue; - - idle = fork_idle(cpu); - if (IS_ERR(idle)) - panic("failed fork for CPU %d", cpu); - + for_each_possible_cpu(cpu) set_cpu_present(cpu, true); - } } static int __cpuinit @@ -331,9 +321,8 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) return 0; } -static int __cpuinit xen_cpu_up(unsigned int cpu, struct task_struct *tidle) +static int __cpuinit xen_cpu_up(unsigned int cpu, struct task_struct *idle) { - struct task_struct *idle = idle_task(cpu); int rc; per_cpu(current_task, cpu) = idle; -- cgit v1.2.3 From 17e32eacc3543c25a4377bb7ce54026e38db7d20 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:48 +0000 Subject: powerpc: Use generic idle thread allocation Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Cc: Benjamin Herrenschmidt Link: http://lkml.kernel.org/r/20120420124557.311212868@linutronix.de --- arch/powerpc/Kconfig | 1 + arch/powerpc/kernel/smp.c | 74 ++++------------------------------------------- 2 files changed, 6 insertions(+), 69 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index feab3bad6d0f..c81553508366 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -144,6 +144,7 @@ config PPC select HAVE_BPF_JIT if (PPC64 && NET) select HAVE_ARCH_JUMP_LABEL select ARCH_HAVE_NMI_SAFE_CMPXCHG + select GENERIC_SMP_IDLE_THREAD config EARLY_PRINTK bool diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index d38030fb3471..e4cb34322de4 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -57,27 +57,9 @@ #define DBG(fmt...) #endif - -/* Store all idle threads, this can be reused instead of creating -* a new thread. Also avoids complicated thread destroy functionality -* for idle threads. -*/ #ifdef CONFIG_HOTPLUG_CPU -/* - * Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is - * removed after init for !CONFIG_HOTPLUG_CPU. - */ -static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); -#define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x)) -#define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p)) - /* State of each CPU during hotplug phases */ static DEFINE_PER_CPU(int, cpu_state) = { 0 }; - -#else -static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; -#define get_idle_for_cpu(x) (idle_thread_array[(x)]) -#define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p)) #endif struct thread_info *secondary_ti; @@ -429,57 +411,16 @@ int generic_check_cpu_restart(unsigned int cpu) } #endif -struct create_idle { - struct work_struct work; - struct task_struct *idle; - struct completion done; - int cpu; -}; - -static void __cpuinit do_fork_idle(struct work_struct *work) +static void cpu_idle_thread_init(unsigned int cpu, struct task_struct *idle) { - struct create_idle *c_idle = - container_of(work, struct create_idle, work); - - c_idle->idle = fork_idle(c_idle->cpu); - complete(&c_idle->done); -} - -static int __cpuinit create_idle(unsigned int cpu) -{ - struct thread_info *ti; - struct create_idle c_idle = { - .cpu = cpu, - .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), - }; - INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle); - - c_idle.idle = get_idle_for_cpu(cpu); - - /* We can't use kernel_thread since we must avoid to - * reschedule the child. We use a workqueue because - * we want to fork from a kernel thread, not whatever - * userspace process happens to be trying to online us. - */ - if (!c_idle.idle) { - schedule_work(&c_idle.work); - wait_for_completion(&c_idle.done); - } else - init_idle(c_idle.idle, cpu); - if (IS_ERR(c_idle.idle)) { - pr_err("Failed fork for CPU %u: %li", cpu, PTR_ERR(c_idle.idle)); - return PTR_ERR(c_idle.idle); - } - ti = task_thread_info(c_idle.idle); + struct thread_info *ti = task_thread_info(idle); #ifdef CONFIG_PPC64 - paca[cpu].__current = c_idle.idle; + paca[cpu].__current = idle; paca[cpu].kstack = (unsigned long)ti + THREAD_SIZE - STACK_FRAME_OVERHEAD; #endif ti->cpu = cpu; - current_set[cpu] = ti; - - return 0; + secondary_ti = current_set[cpu] = ti; } int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) @@ -490,12 +431,7 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))) return -EINVAL; - /* Make sure we have an idle thread */ - rc = create_idle(cpu); - if (rc) - return rc; - - secondary_ti = current_set[cpu]; + cpu_idle_thread_init(cpu, tidle); /* Make sure callin-map entry is 0 (can be leftover a CPU * hotplug -- cgit v1.2.3 From 13583bf15eb1e890e03d46b6f2753e4b64af21c9 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:49 +0000 Subject: ia64: Use generic idle thread allocation Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Cc: Tony Luck Link: http://lkml.kernel.org/r/20120420124557.380965133@linutronix.de --- arch/ia64/Kconfig | 1 + arch/ia64/kernel/smpboot.c | 61 +++------------------------------------------- 2 files changed, 4 insertions(+), 58 deletions(-) diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index bd7266903bf8..11975475516a 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -33,6 +33,7 @@ config IA64 select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_HAVE_NMI_SAFE_CMPXCHG select GENERIC_IOMAP + select GENERIC_SMP_IDLE_THREAD default y help The Itanium Processor Family is Intel's 64-bit successor to diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 03e4ef3893c9..1113b8aba07f 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -74,13 +74,6 @@ #define bsp_remove_ok 0 #endif -/* - * Store all idle threads, this can be reused instead of creating - * a new thread. Also avoids complicated thread destroy functionality - * for idle threads. - */ -struct task_struct *idle_thread_array[NR_CPUS]; - /* * Global array allocated for NR_CPUS at boot time */ @@ -94,13 +87,7 @@ struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0]; #define set_brendez_area(x) (sal_state_for_booting_cpu = &sal_boot_rendez_state[(x)]); -#define get_idle_for_cpu(x) (idle_thread_array[(x)]) -#define set_idle_for_cpu(x,p) (idle_thread_array[(x)] = (p)) - #else - -#define get_idle_for_cpu(x) (NULL) -#define set_idle_for_cpu(x,p) #define set_brendez_area(x) #endif @@ -480,54 +467,12 @@ struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) return NULL; } -struct create_idle { - struct work_struct work; - struct task_struct *idle; - struct completion done; - int cpu; -}; - -void __cpuinit -do_fork_idle(struct work_struct *work) -{ - struct create_idle *c_idle = - container_of(work, struct create_idle, work); - - c_idle->idle = fork_idle(c_idle->cpu); - complete(&c_idle->done); -} - static int __cpuinit -do_boot_cpu (int sapicid, int cpu) +do_boot_cpu (int sapicid, int cpu, struct task_struct *idle) { int timeout; - struct create_idle c_idle = { - .work = __WORK_INITIALIZER(c_idle.work, do_fork_idle), - .cpu = cpu, - .done = COMPLETION_INITIALIZER(c_idle.done), - }; - - /* - * We can't use kernel_thread since we must avoid to - * reschedule the child. - */ - c_idle.idle = get_idle_for_cpu(cpu); - if (c_idle.idle) { - init_idle(c_idle.idle, cpu); - goto do_rest; - } - - schedule_work(&c_idle.work); - wait_for_completion(&c_idle.done); - - if (IS_ERR(c_idle.idle)) - panic("failed fork for CPU %d", cpu); - - set_idle_for_cpu(cpu, c_idle.idle); - -do_rest: - task_for_booting_cpu = c_idle.idle; + task_for_booting_cpu = idle; Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); set_brendez_area(cpu); @@ -811,7 +756,7 @@ __cpu_up(unsigned int cpu, struct task_struct *tidle) per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; /* Processor goes to start_secondary(), sets online flag */ - ret = do_boot_cpu(sapicid, cpu); + ret = do_boot_cpu(sapicid, cpu, tidle); if (ret < 0) return ret; -- cgit v1.2.3 From 84ec6d5796e095e2f8698bd2b5d33849ed26d9e2 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:50 +0000 Subject: arm: Use generic idle thread allocation Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Cc: Russell King Tested-by: Frank Rowand Link: http://lkml.kernel.org/r/20120420124557.448826362@linutronix.de --- arch/arm/Kconfig | 1 + arch/arm/include/asm/cpu.h | 1 - arch/arm/kernel/smp.c | 26 +------------------------- 3 files changed, 2 insertions(+), 26 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index cf006d40342c..cb253ce218a0 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -34,6 +34,7 @@ config ARM select CPU_PM if (SUSPEND || CPU_IDLE) select GENERIC_PCI_IOMAP select HAVE_BPF_JIT if NET + select GENERIC_SMP_IDLE_THREAD help The ARM series is a line of low-power-consumption RISC chip designs licensed by ARM Ltd and targeted at embedded applications and diff --git a/arch/arm/include/asm/cpu.h b/arch/arm/include/asm/cpu.h index 793968173bef..d797223b39d5 100644 --- a/arch/arm/include/asm/cpu.h +++ b/arch/arm/include/asm/cpu.h @@ -16,7 +16,6 @@ struct cpuinfo_arm { struct cpu cpu; #ifdef CONFIG_SMP - struct task_struct *idle; unsigned int loops_per_jiffy; #endif }; diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index f0e2cbbd837d..5e86f7c47824 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -60,31 +60,10 @@ enum ipi_msg_type { static DECLARE_COMPLETION(cpu_running); -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) { - struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu); - struct task_struct *idle = ci->idle; int ret; - /* - * Spawn a new process manually, if not already done. - * Grab a pointer to its task struct so we can mess with it - */ - if (!idle) { - idle = fork_idle(cpu); - if (IS_ERR(idle)) { - printk(KERN_ERR "CPU%u: fork() failed\n", cpu); - return PTR_ERR(idle); - } - ci->idle = idle; - } else { - /* - * Since this idle thread is being re-used, call - * init_idle() to reinitialize the thread structure. - */ - init_idle(idle, cpu); - } - /* * We need to tell the secondary core where to find * its stack and the page tables. @@ -318,9 +297,6 @@ void __init smp_cpus_done(unsigned int max_cpus) void __init smp_prepare_boot_cpu(void) { - unsigned int cpu = smp_processor_id(); - - per_cpu(cpu_data, cpu).idle = current; } void __init smp_prepare_cpus(unsigned int max_cpus) -- cgit v1.2.3 From 360014a36170464ebd9935514f0e0e3d558b0e56 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:51 +0000 Subject: mips: Use generic idle thread allocation Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Cc: Ralf Baechle Link: http://lkml.kernel.org/r/20120420124557.512158271@linutronix.de --- arch/mips/Kconfig | 1 + arch/mips/kernel/smp.c | 54 +------------------------------------------------- 2 files changed, 2 insertions(+), 53 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index ce30e2f91d77..186fc8cf9ee0 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -29,6 +29,7 @@ config MIPS select HAVE_MEMBLOCK select HAVE_MEMBLOCK_NODE_MAP select ARCH_DISCARD_MEMBLOCK + select GENERIC_SMP_IDLE_THREAD menu "Machine selection" diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 41079b256092..71a95f55a649 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -186,61 +186,9 @@ void __devinit smp_prepare_boot_cpu(void) cpu_set(0, cpu_callin_map); } -/* - * Called once for each "cpu_possible(cpu)". Needs to spin up the cpu - * and keep control until "cpu_online(cpu)" is set. Note: cpu is - * physical, not logical. - */ -static struct task_struct *cpu_idle_thread[NR_CPUS]; - -struct create_idle { - struct work_struct work; - struct task_struct *idle; - struct completion done; - int cpu; -}; - -static void __cpuinit do_fork_idle(struct work_struct *work) -{ - struct create_idle *c_idle = - container_of(work, struct create_idle, work); - - c_idle->idle = fork_idle(c_idle->cpu); - complete(&c_idle->done); -} - int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { - struct task_struct *idle; - - /* - * Processor goes to start_secondary(), sets online flag - * The following code is purely to make sure - * Linux can schedule processes on this slave. - */ - if (!cpu_idle_thread[cpu]) { - /* - * Schedule work item to avoid forking user task - * Ported from arch/x86/kernel/smpboot.c - */ - struct create_idle c_idle = { - .cpu = cpu, - .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), - }; - - INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle); - schedule_work(&c_idle.work); - wait_for_completion(&c_idle.done); - idle = cpu_idle_thread[cpu] = c_idle.idle; - - if (IS_ERR(idle)) - panic(KERN_ERR "Fork failed for CPU %d", cpu); - } else { - idle = cpu_idle_thread[cpu]; - init_idle(idle, cpu); - } - - mp_ops->boot_secondary(cpu, idle); + mp_ops->boot_secondary(cpu, tidle); /* * Trust is futile. We should really have timeouts ... -- cgit v1.2.3 From 3b0132ce4fff68b30abdfcb74cffc283af711076 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:51 +0000 Subject: hexagon: Use generic idle thread allocation Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Acked-and-tested-by: Richard Kuo Link: http://lkml.kernel.org/r/20120420124557.581762105@linutronix.de --- arch/hexagon/Kconfig | 1 + arch/hexagon/kernel/smp.c | 11 ++--------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig index 9059e3905887..d2e4a3330336 100644 --- a/arch/hexagon/Kconfig +++ b/arch/hexagon/Kconfig @@ -27,6 +27,7 @@ config HEXAGON select HAVE_ARCH_TRACEHOOK select NO_IOPORT select GENERIC_IOMAP + select GENERIC_SMP_IDLE_THREAD # mostly generic routines, with some accelerated ones ---help--- Qualcomm Hexagon is a processor architecture designed for high diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c index 93e77e2b17a8..f7264621e58d 100644 --- a/arch/hexagon/kernel/smp.c +++ b/arch/hexagon/kernel/smp.c @@ -196,18 +196,11 @@ void __cpuinit start_secondary(void) * maintains control until "cpu_online(cpu)" is set. */ -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) { - struct task_struct *idle; - struct thread_info *thread; + struct thread_info *thread = (struct thread_info *)idle->stack; void *stack_start; - /* Create new init task for the CPU */ - idle = fork_idle(cpu); - if (IS_ERR(idle)) - panic(KERN_ERR "fork_idle failed\n"); - - thread = (struct thread_info *)idle->stack; thread->cpu = cpu; /* Boot to the head. */ -- cgit v1.2.3 From e80e7813cd772cf30597024b371e73df9736de8d Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:52 +0000 Subject: s390: Use generic idle thread allocation Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Acked-by: Martin Schwidefsky Link: http://lkml.kernel.org/r/20120420124557.652574928@linutronix.de --- arch/s390/Kconfig | 1 + arch/s390/kernel/smp.c | 33 ++------------------------------- 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 9015060919a0..15cab3ee44e8 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -122,6 +122,7 @@ config S390 select ARCH_INLINE_WRITE_UNLOCK_BH select ARCH_INLINE_WRITE_UNLOCK_IRQ select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE + select GENERIC_SMP_IDLE_THREAD config SCHED_OMIT_FRAME_POINTER def_bool y diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index fc827aa8f9ca..992b7b93a574 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -85,7 +85,6 @@ enum { struct pcpu { struct cpu cpu; - struct task_struct *idle; /* idle process for the cpu */ struct _lowcore *lowcore; /* lowcore page(s) for the cpu */ unsigned long async_stack; /* async stack for the cpu */ unsigned long panic_stack; /* panic stack for the cpu */ @@ -721,26 +720,9 @@ static void __cpuinit smp_start_secondary(void *cpuvoid) cpu_idle(); } -struct create_idle { - struct work_struct work; - struct task_struct *idle; - struct completion done; - int cpu; -}; - -static void __cpuinit smp_fork_idle(struct work_struct *work) -{ - struct create_idle *c_idle; - - c_idle = container_of(work, struct create_idle, work); - c_idle->idle = fork_idle(c_idle->cpu); - complete(&c_idle->done); -} - /* Upping and downing of CPUs */ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { - struct create_idle c_idle; struct pcpu *pcpu; int rc; @@ -750,22 +732,12 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) if (pcpu_sigp_retry(pcpu, sigp_initial_cpu_reset, 0) != sigp_order_code_accepted) return -EIO; - if (!pcpu->idle) { - c_idle.done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done); - INIT_WORK_ONSTACK(&c_idle.work, smp_fork_idle); - c_idle.cpu = cpu; - schedule_work(&c_idle.work); - wait_for_completion(&c_idle.done); - if (IS_ERR(c_idle.idle)) - return PTR_ERR(c_idle.idle); - pcpu->idle = c_idle.idle; - } - init_idle(pcpu->idle, cpu); + rc = pcpu_alloc_lowcore(pcpu, cpu); if (rc) return rc; pcpu_prepare_secondary(pcpu, cpu); - pcpu_attach_task(pcpu, pcpu->idle); + pcpu_attach_task(pcpu, tidle); pcpu_start_fn(pcpu, smp_start_secondary, NULL); while (!cpu_online(cpu)) cpu_relax(); @@ -852,7 +824,6 @@ void __init smp_prepare_boot_cpu(void) struct pcpu *pcpu = pcpu_devices; boot_cpu_address = stap(); - pcpu->idle = current; pcpu->state = CPU_STATE_CONFIGURED; pcpu->address = boot_cpu_address; pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix(); -- cgit v1.2.3 From a4cfc31da34eacafd9f6b16e149448bf0ef6d0b2 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:53 +0000 Subject: cris: Use generic idle thread allocation Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Acked-by: Jesper Nilsson Link: http://lkml.kernel.org/r/20120420124557.789657793@linutronix.de --- arch/cris/Kconfig | 1 + arch/cris/arch-v32/kernel/smp.c | 12 ++---------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index b3abfb08aa5c..2995035812ec 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -49,6 +49,7 @@ config CRIS select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW select GENERIC_IOMAP + select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32 config HZ int diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index 125ee2d7bc87..ebe2cb30bd11 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -108,17 +108,12 @@ void __init smp_cpus_done(unsigned int max_cpus) /* Bring one cpu online.*/ static int __init -smp_boot_one_cpu(int cpuid) +smp_boot_one_cpu(int cpuid, struct task_struct idle) { unsigned timeout; - struct task_struct *idle; cpumask_t cpu_mask; cpumask_clear(&cpu_mask); - idle = fork_idle(cpuid); - if (IS_ERR(idle)) - panic("SMP: fork failed for CPU:%d", cpuid); - task_thread_info(idle)->cpu = cpuid; /* Information to the CPU that is about to boot */ @@ -142,9 +137,6 @@ smp_boot_one_cpu(int cpuid) barrier(); } - put_task_struct(idle); - idle = NULL; - printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid); return -1; } @@ -209,7 +201,7 @@ unsigned long cache_decay_ticks = 1; int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { - smp_boot_one_cpu(cpu); + smp_boot_one_cpu(cpu, tidle); return cpu_online(cpu) ? 0 : -ENOSYS; } -- cgit v1.2.3 From 6bba2682c62e432eaf7b82f8ca182e8c73256e74 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:53 +0000 Subject: blackfin: Use generic idle thread allocation Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Cc: Mike Frysinger Link: http://lkml.kernel.org/r/20120420124557.717064871@linutronix.de --- arch/blackfin/Kconfig | 1 + arch/blackfin/mach-common/smp.c | 19 +------------------ 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 373a6902d8fa..779b9c846fd7 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -37,6 +37,7 @@ config BLACKFIN select GENERIC_IRQ_PROBE select IRQ_PER_CPU if SMP select HAVE_NMI_WATCHDOG if NMI_WATCHDOG + select GENERIC_SMP_IDLE_THREAD config GENERIC_CSUM def_bool y diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index d0cddd95b0dd..00bbe672b3b3 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -340,27 +340,10 @@ void smp_send_stop(void) return; } -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) { int ret; - struct blackfin_cpudata *ci = &per_cpu(cpu_data, cpu); - struct task_struct *idle = ci->idle; - if (idle) { - free_task(idle); - idle = NULL; - } - - if (!idle) { - idle = fork_idle(cpu); - if (IS_ERR(idle)) { - printk(KERN_ERR "CPU%u: fork() failed\n", cpu); - return PTR_ERR(idle); - } - ci->idle = idle; - } else { - init_idle(idle, cpu); - } secondary_stack = task_stack_page(idle) + THREAD_SIZE; ret = platform_boot_secondary(cpu, idle); -- cgit v1.2.3 From ea0588cb6b201c38b0120c4ad38bc548d5dde29a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:54 +0000 Subject: sh: Use generic idle thread allocation Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Acked-by: Paul Mundt Link: http://lkml.kernel.org/r/20120420124557.855203626@linutronix.de --- arch/sh/Kconfig | 1 + arch/sh/include/asm/processor.h | 4 ---- arch/sh/kernel/smp.c | 14 +------------- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ff9e033ce626..244cfd0dbb7b 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -28,6 +28,7 @@ config SUPERH select RTC_LIB select GENERIC_ATOMIC64 select GENERIC_IRQ_SHOW + select GENERIC_SMP_IDLE_THREAD help The SuperH is a RISC processor targeted for use in embedded systems and consumer electronics; it was also used in the Sega Dreamcast diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h index a229c393826a..6d87912415a7 100644 --- a/arch/sh/include/asm/processor.h +++ b/arch/sh/include/asm/processor.h @@ -85,10 +85,6 @@ struct sh_cpuinfo { struct tlb_info itlb; struct tlb_info dtlb; -#ifdef CONFIG_SMP - struct task_struct *idle; -#endif - unsigned int phys_bits; unsigned long flags; } __attribute__ ((aligned(L1_CACHE_BYTES))); diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index ebb76e2a748b..b86e9ca79455 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -220,22 +220,10 @@ extern struct { void *thread_info; } stack_start; -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) +int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tsk) { - struct task_struct *tsk; unsigned long timeout; - tsk = cpu_data[cpu].idle; - if (!tsk) { - tsk = fork_idle(cpu); - if (IS_ERR(tsk)) { - pr_err("Failed forking idle task for cpu %d\n", cpu); - return PTR_ERR(tsk); - } - - cpu_data[cpu].idle = tsk; - } - per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; /* Fill in data in head.S for secondary cpus */ -- cgit v1.2.3 From 2ec9415c71a1ddad969602e690a9c848b81256b3 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:55 +0000 Subject: alpha: Use generic idle thread allocation Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Cc: Matt Turner Link: http://lkml.kernel.org/r/20120420124557.914631081@linutronix.de --- arch/alpha/Kconfig | 1 + arch/alpha/kernel/smp.c | 18 ++---------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 56a4df952fb0..991b8bbff4ff 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -15,6 +15,7 @@ config ALPHA select GENERIC_IRQ_SHOW select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_HAVE_NMI_SAFE_CMPXCHG + select GENERIC_SMP_IDLE_THREAD help The Alpha is a 64-bit general-purpose processor designed and marketed by the Digital Equipment Corporation of blessed memory, diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 68d39470fb52..35ddc02bfa4a 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -357,24 +357,10 @@ secondary_cpu_start(int cpuid, struct task_struct *idle) * Bring one cpu online. */ static int __cpuinit -smp_boot_one_cpu(int cpuid) +smp_boot_one_cpu(int cpuid, struct task_struct *idle) { - struct task_struct *idle; unsigned long timeout; - /* Cook up an idler for this guy. Note that the address we - give to kernel_thread is irrelevant -- it's going to start - where HWRPB.CPU_restart says to start. But this gets all - the other task-y sort of data structures set up like we - wish. We can't use kernel_thread since we must avoid - rescheduling the child. */ - idle = fork_idle(cpuid); - if (IS_ERR(idle)) - panic("failed fork for CPU %d", cpuid); - - DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n", - cpuid, idle->state, idle->flags)); - /* Signal the secondary to wait a moment. */ smp_secondary_alive = -1; @@ -489,7 +475,7 @@ smp_prepare_boot_cpu(void) int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { - smp_boot_one_cpu(cpu); + smp_boot_one_cpu(cpu, tidle); return cpu_online(cpu) ? 0 : -ENOSYS; } -- cgit v1.2.3 From f0a2bc7e54bb51f64d4c2cd5942ba6018a13d762 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Apr 2012 13:05:56 +0000 Subject: sparc: Use generic idle thread allocation Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Tested-by: David S. Miller Link: http://lkml.kernel.org/r/20120420124558.055198736@linutronix.de --- arch/sparc/Kconfig | 1 + arch/sparc/include/asm/leon.h | 5 +++-- arch/sparc/kernel/leon_smp.c | 9 ++------- arch/sparc/kernel/smp_32.c | 10 +++++----- arch/sparc/kernel/smp_64.c | 10 +++------- arch/sparc/kernel/sun4d_smp.c | 8 ++------ arch/sparc/kernel/sun4m_smp.c | 7 ++----- 7 files changed, 18 insertions(+), 32 deletions(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 6c0683d3fcba..e417f35d5912 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -30,6 +30,7 @@ config SPARC select USE_GENERIC_SMP_HELPERS if SMP select GENERIC_PCI_IOMAP select HAVE_NMI_WATCHDOG if SPARC64 + select GENERIC_SMP_IDLE_THREAD config SPARC32 def_bool !64BIT diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h index a4e457f003ed..6a1585b52c49 100644 --- a/arch/sparc/include/asm/leon.h +++ b/arch/sparc/include/asm/leon.h @@ -315,6 +315,7 @@ struct leon2_cacheregs { #include struct device_node; +struct task_struct; extern unsigned int leon_build_device_irq(unsigned int real_irq, irq_flow_handler_t flow_handler, const char *name, int do_ack); @@ -344,7 +345,7 @@ extern int leon_smp_nrcpus(void); extern void leon_clear_profile_irq(int cpu); extern void leon_smp_done(void); extern void leon_boot_cpus(void); -extern int leon_boot_one_cpu(int i); +extern int leon_boot_one_cpu(int i, struct task_struct *); void leon_init_smp(void); extern void cpu_idle(void); extern void init_IRQ(void); @@ -380,7 +381,7 @@ extern int leon_ipi_irq; #define init_leon() do {} while (0) #define leon_smp_done() do {} while (0) #define leon_boot_cpus() do {} while (0) -#define leon_boot_one_cpu(i) 1 +#define leon_boot_one_cpu(i, t) 1 #define leon_init_smp() do {} while (0) #endif /* !defined(CONFIG_SPARC_LEON) */ diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 160cac9c4036..b34c93c351b6 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c @@ -204,16 +204,11 @@ void __init leon_boot_cpus(void) } -int __cpuinit leon_boot_one_cpu(int i) +int __cpuinit leon_boot_one_cpu(int i, struct task_struct *idle) { - - struct task_struct *p; int timeout; - /* Cook up an idler for this guy. */ - p = fork_idle(i); - - current_set[i] = task_thread_info(p); + current_set[i] = task_thread_info(idle); /* See trampoline.S:leon_smp_cpu_startup for details... * Initialize the contexts table diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index 1f397ae11028..9028566b3cd6 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c @@ -413,8 +413,8 @@ void __init smp_prepare_boot_cpu(void) int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) { - extern int __cpuinit smp4m_boot_one_cpu(int); - extern int __cpuinit smp4d_boot_one_cpu(int); + extern int __cpuinit smp4m_boot_one_cpu(int, struct task_struct *); + extern int __cpuinit smp4d_boot_one_cpu(int, struct task_struct *); int ret=0; switch(sparc_cpu_model) { @@ -427,13 +427,13 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) BUG(); break; case sun4m: - ret = smp4m_boot_one_cpu(cpu); + ret = smp4m_boot_one_cpu(cpu, tidle); break; case sun4d: - ret = smp4d_boot_one_cpu(cpu); + ret = smp4d_boot_one_cpu(cpu, tidle); break; case sparc_leon: - ret = leon_boot_one_cpu(cpu); + ret = leon_boot_one_cpu(cpu, tidle); break; case sun4e: printk("SUN4E\n"); diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/ke