[PATCH v4 02/10] ARM: SoC: Add per SoC SMP and CPU hotplug operations
Kyungmin Park
kmpark at infradead.org
Tue Oct 4 06:30:48 EDT 2011
On Tue, Oct 4, 2011 at 2:35 AM, Marc Zyngier <marc.zyngier at arm.com> wrote:
> Populate the SoC descriptor structure with the SMP and CPU hotplug
> operations. To allow the kernel to continue building, the platform
> hooks are defined as weak symbols which are overrided by the
> platform code. Once all platforms are converted, the "weak" attribute
> will be removed and the function made static.
>
> Cc: Arnd Bergmann <arnd at arndb.de>
> Cc: Nicolas Pitre <nico at fluxnic.net>
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
> arch/arm/include/asm/soc.h | 48 ++++++++++++++++++++++++++++++++++++++++++-
> arch/arm/kernel/setup.c | 29 ++++++++++++++++++++++---
> arch/arm/kernel/smp.c | 47 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 118 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/include/asm/soc.h b/arch/arm/include/asm/soc.h
> index ce92784..f1dd657 100644
> --- a/arch/arm/include/asm/soc.h
> +++ b/arch/arm/include/asm/soc.h
> @@ -12,10 +12,54 @@
> #ifndef __ASM_ARM_SOC_H
> #define __ASM_ARM_SOC_H
>
> +struct task_struct;
> +
> +struct arm_soc_smp_init_ops {
> + /*
> + * Setup the set of possible CPUs (via set_cpu_possible)
> + */
> + void (*smp_init_cpus)(void);
> + /*
> + * Initialize cpu_possible map, and enable coherency
> + */
> + void (*smp_prepare_cpus)(unsigned int max_cpus);
> +};
> +
> +struct arm_soc_smp_ops {
> + /*
> + * Perform platform specific initialisation of the specified CPU.
> + */
> + void (*smp_secondary_init)(unsigned int cpu);
> + /*
> + * Boot a secondary CPU, and assign it the specified idle task.
> + * This also gives us the initial stack to use for this CPU.
> + */
> + int (*smp_boot_secondary)(unsigned int cpu, struct task_struct *idle);
> +#ifdef CONFIG_HOTPLUG_CPU
> + int (*cpu_kill)(unsigned int cpu);
> + void (*cpu_die)(unsigned int cpu);
> + int (*cpu_disable)(unsigned int cpu);
> +#endif
> +};
> +
> struct arm_soc_desc {
> - const char *name;
> + const char *name;
> +#ifdef CONFIG_SMP
> + struct arm_soc_smp_init_ops *smp_init_ops;
> + struct arm_soc_smp_ops *smp_ops;
> +#endif
> };
>
> -extern const struct arm_soc_desc *soc_desc;
> +#ifdef CONFIG_SMP
> +#define soc_smp_init_ops(ops) .smp_init_ops = &(ops),
> +#define soc_smp_ops(ops) .smp_ops = &(ops),
> +#else
> +#define soc_smp_init_ops(ops) /* empty */
> +#define soc_smp_ops(ops) /* empty */
> +#endif
> +
> +extern const struct arm_soc_desc *soc_desc;
> +extern const struct arm_soc_smp_init_ops *soc_smp_init_ops;
> +extern const struct arm_soc_smp_ops *soc_smp_ops;
>
> #endif /* __ASM_ARM_SOC_H */
> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
> index 34ffb2e..351ae18 100644
> --- a/arch/arm/kernel/setup.c
> +++ b/arch/arm/kernel/setup.c
> @@ -141,8 +141,12 @@ static const char *cpu_name;
> static const char *machine_name;
> static char __initdata cmd_line[COMMAND_LINE_SIZE];
> struct machine_desc *machine_desc __initdata;
> -const struct arm_soc_desc *soc_desc;
> -static struct arm_soc_desc __soc_desc __read_mostly;
> +const struct arm_soc_desc *soc_desc __initdata;
> +#ifdef CONFIG_SMP
> +const struct arm_soc_smp_init_ops *soc_smp_init_ops __initdata;
> +const struct arm_soc_smp_ops *soc_smp_ops __cpuinitdata;
> +static struct arm_soc_smp_ops __soc_smp_ops __cpuinitdata;
> +#endif
>
> static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
> static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
> @@ -917,11 +921,28 @@ void __init setup_arch(char **cmdline_p)
> machine_desc = mdesc;
> machine_name = mdesc->name;
> if (mdesc->soc) {
> - __soc_desc = *mdesc->soc;
> - soc_desc = &__soc_desc;
> + soc_desc = mdesc->soc;
> pr_info("SoC: %s\n", soc_desc->name);
> } else
> soc_desc = NULL;
> +#ifdef CONFIG_SMP
> + if (soc_desc && soc_desc->smp_init_ops)
> + soc_smp_init_ops = soc_desc->smp_init_ops;
> + else
> + soc_smp_ops = NULL;
It should be "soc_smp_init_ops = NULL;"
Thank you,
Kyungmin Park
> +
> + /*
> + * Warning: we're copying an __initdata structure into a
> + * __cpuinitdata structure. We *know* it is valid because only
> + * __cpuinit (or more persistant) functions should be pointed
> + * to by soc_smp_ops. Still, this is borderline ugly.
> + */
> + if (soc_desc && soc_desc->smp_ops) {
> + __soc_smp_ops = *soc_desc->smp_ops;
> + soc_smp_ops = &__soc_smp_ops;
> + } else
> + soc_smp_ops = NULL;
> +#endif
>
> if (mdesc->soft_reboot)
> reboot_setup("s");
> diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
> index 8bb30c2..e08d2e8 100644
> --- a/arch/arm/kernel/smp.c
> +++ b/arch/arm/kernel/smp.c
> @@ -28,6 +28,7 @@
> #include <linux/completion.h>
>
> #include <linux/atomic.h>
> +#include <asm/soc.h>
> #include <asm/cacheflush.h>
> #include <asm/cpu.h>
> #include <asm/cputype.h>
> @@ -155,9 +156,55 @@ int __cpuinit __cpu_up(unsigned int cpu)
> return ret;
> }
>
> +/* SoC helpers */
> +void __attribute__((weak)) __init smp_init_cpus(void)
> +{
> + if (soc_smp_init_ops && soc_smp_init_ops->smp_init_cpus)
> + soc_smp_init_ops->smp_init_cpus();
> +}
> +
> +void __attribute__((weak)) __init platform_smp_prepare_cpus(unsigned int max_cpus)
> +{
> + if (soc_smp_ops && soc_smp_init_ops->smp_prepare_cpus)
> + soc_smp_init_ops->smp_prepare_cpus(max_cpus);
> +}
> +
> +void __attribute__((weak)) __cpuinit platform_secondary_init(unsigned int cpu)
> +{
> + if (soc_smp_ops && soc_smp_ops->smp_secondary_init)
> + soc_smp_ops->smp_secondary_init(cpu);
> +}
> +
> +int __attribute__((weak)) __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
> +{
> + if (soc_smp_ops && soc_smp_ops->smp_boot_secondary)
> + return soc_smp_ops->smp_boot_secondary(cpu, idle);
> + return -ENOSYS;
> +}
> +
> #ifdef CONFIG_HOTPLUG_CPU
> static void percpu_timer_stop(void);
>
> +int __attribute__((weak)) __cpuinit platform_cpu_kill(unsigned int cpu)
> +{
> + if (soc_smp_ops && soc_smp_ops->cpu_kill)
> + return soc_smp_ops->cpu_kill(cpu);
> + return 0;
> +}
> +
> +void __attribute__((weak)) __cpuinit platform_cpu_die(unsigned int cpu)
> +{
> + if (soc_smp_ops && soc_smp_ops->cpu_die)
> + soc_smp_ops->cpu_die(cpu);
> +}
> +
> +int __attribute__((weak)) __cpuinit platform_cpu_disable(unsigned int cpu)
> +{
> + if (soc_smp_ops && soc_smp_ops->cpu_disable)
> + return soc_smp_ops->cpu_disable(cpu);
> + return -EPERM;
> +}
> +
> /*
> * __cpu_disable runs on the processor to be shutdown.
> */
> --
> 1.7.0.4
>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
More information about the linux-arm-kernel
mailing list