[PATCH v4 02/10] ARM: SoC: Add per SoC SMP and CPU hotplug operations
Kyungmin Park
kmpark at infradead.org
Tue Oct 4 06:35:19 EDT 2011
On Tue, Oct 4, 2011 at 7:30 PM, Kyungmin Park <kmpark at infradead.org> wrote:
> 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);
>> +}
One more, if (soc_smp_init_ops && ...)
>> +
>> +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