diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-04-11 15:23:43 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-04-11 15:23:43 -0700 |
commit | 9ec7dfaf2cc0e5000dec931bde41f17c7eb203db (patch) | |
tree | cecab9759d0298ec1af3a24f8a1ef14a6e383473 | |
parent | 9e528fe13c95cee1b4ee23690aebf8b02eebac1f (diff) | |
download | ltsi-kernel-9ec7dfaf2cc0e5000dec931bde41f17c7eb203db.tar.gz |
two arm smp ops patches
-rw-r--r-- | patches.misc/arm-soc-add-per-platform-smp-operations.patch | 223 | ||||
-rw-r--r-- | patches.misc/arm-soc-convert-shmobile-smp-to-smp-operations.patch | 611 | ||||
-rw-r--r-- | series | 7 |
3 files changed, 841 insertions, 0 deletions
diff --git a/patches.misc/arm-soc-add-per-platform-smp-operations.patch b/patches.misc/arm-soc-add-per-platform-smp-operations.patch new file mode 100644 index 00000000000000..15a4615d449edb --- /dev/null +++ b/patches.misc/arm-soc-add-per-platform-smp-operations.patch @@ -0,0 +1,223 @@ +From horms@vergenet.net Tue Mar 26 21:37:55 2013 +From: Simon Horman <horms+renesas@verge.net.au> +Date: Wed, 27 Mar 2013 13:37:49 +0900 +Subject: [PATCH 1/2] ARM: SoC: add per-platform SMP operations +To: ltsi-dev@lists.linuxfoundation.org +Cc: Greg KH <gregkh@linuxfoundation.org> +Message-ID: <1364359070-7002-2-git-send-email-horms+renesas@verge.net.au> + + +From: Marc Zyngier <marc.zyngier@arm.com> + +This adds a 'struct smp_operations' to abstract the CPU initialization +and hot plugging functions on SMP systems, which otherwise conflict +in a multiplatform kernel. This also helps shmobile and potentially +others that have more than one method to do these. + +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. + +Unlike the original version from Marc, this new version from Arnd +does not use a generalized abstraction for per-soc data structures +but only tries to solve the problem for the SMP operations. This +way, we can collapse the previous four data structures into a +single struct, which is less systematic but also easier to follow +as a causal reader. + +Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> +Acked-by: Nicolas Pitre <nico@fluxnic.net> +Signed-off-by: Arnd Bergmann <arnd@arndb.de> +(cherry picked from commit abcee5fb0dfbb248d883a2f6bdb4820abe3ac524) + +Conflicts: + arch/arm/kernel/smp.c + +Signed-off-by: Simon Horman <horms+renesas@verge.net.au> +--- + arch/arm/include/asm/mach/arch.h | 7 ++++ + arch/arm/include/asm/smp.h | 33 ++++++++++++++++++++ + arch/arm/kernel/setup.c | 4 +- + arch/arm/kernel/smp.c | 62 ++++++++++++++++++++++++++++++++++++++- + 4 files changed, 104 insertions(+), 2 deletions(-) + +--- a/arch/arm/include/asm/mach/arch.h ++++ b/arch/arm/include/asm/mach/arch.h +@@ -14,6 +14,12 @@ struct tag; + struct meminfo; + struct sys_timer; + struct pt_regs; ++struct smp_operations; ++#ifdef CONFIG_SMP ++#define smp_ops(ops) (&(ops)) ++#else ++#define smp_ops(ops) (struct smp_operations *)NULL ++#endif + + struct machine_desc { + unsigned int nr; /* architecture number */ +@@ -35,6 +41,7 @@ struct machine_desc { + unsigned char reserve_lp1 :1; /* never has lp1 */ + unsigned char reserve_lp2 :1; /* never has lp2 */ + char restart_mode; /* default restart mode */ ++ struct smp_operations *smp; /* SMP operations */ + void (*fixup)(struct tag *, char **, + struct meminfo *); + void (*reserve)(void);/* reserve mem blocks */ +--- a/arch/arm/include/asm/smp.h ++++ b/arch/arm/include/asm/smp.h +@@ -93,4 +93,37 @@ extern void platform_cpu_enable(unsigned + extern void arch_send_call_function_single_ipi(int cpu); + extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); + ++struct smp_operations { ++#ifdef CONFIG_SMP ++ /* ++ * 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); ++ ++ /* ++ * 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 ++#endif ++}; ++ ++/* ++ * set platform specific SMP operations ++ */ ++extern void smp_set_ops(struct smp_operations *); ++ + #endif /* ifndef __ASM_ARM_SMP_H */ +--- a/arch/arm/kernel/setup.c ++++ b/arch/arm/kernel/setup.c +@@ -977,8 +977,10 @@ void __init setup_arch(char **cmdline_p) + unflatten_device_tree(); + + #ifdef CONFIG_SMP +- if (is_smp()) ++ if (is_smp()) { ++ smp_set_ops(mdesc->smp); + smp_init_cpus(); ++ } + #endif + reserve_crashkernel(); + +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -19,7 +19,6 @@ + #include <linux/mm.h> + #include <linux/err.h> + #include <linux/cpu.h> +-#include <linux/smp.h> + #include <linux/seq_file.h> + #include <linux/irq.h> + #include <linux/percpu.h> +@@ -27,6 +26,7 @@ + #include <linux/completion.h> + + #include <linux/atomic.h> ++#include <asm/smp.h> + #include <asm/cacheflush.h> + #include <asm/cpu.h> + #include <asm/cputype.h> +@@ -42,6 +42,7 @@ + #include <asm/ptrace.h> + #include <asm/localtimer.h> + #include <asm/smp_plat.h> ++#include <asm/mach/arch.h> + + /* + * as from 2.5, kernels no longer have an init_tasks structure +@@ -60,6 +61,14 @@ enum ipi_msg_type { + + static DECLARE_COMPLETION(cpu_running); + ++static struct smp_operations smp_ops; ++ ++void __init smp_set_ops(struct smp_operations *ops) ++{ ++ if (ops) ++ smp_ops = *ops; ++}; ++ + int __cpuinit __cpu_up(unsigned int cpu) + { + struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu); +@@ -121,9 +130,60 @@ int __cpuinit __cpu_up(unsigned int cpu) + return ret; + } + ++/* platform specific SMP operations */ ++void __attribute__((weak)) __init smp_init_cpus(void) ++{ ++ if (smp_ops.smp_init_cpus) ++ smp_ops.smp_init_cpus(); ++} ++ ++void __attribute__((weak)) __init platform_smp_prepare_cpus(unsigned int max_cpus) ++{ ++ if (smp_ops.smp_prepare_cpus) ++ smp_ops.smp_prepare_cpus(max_cpus); ++} ++ ++void __attribute__((weak)) __cpuinit platform_secondary_init(unsigned int cpu) ++{ ++ if (smp_ops.smp_secondary_init) ++ smp_ops.smp_secondary_init(cpu); ++} ++ ++int __attribute__((weak)) __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ++{ ++ if (smp_ops.smp_boot_secondary) ++ return smp_ops.smp_boot_secondary(cpu, idle); ++ return -ENOSYS; ++} ++ + #ifdef CONFIG_HOTPLUG_CPU + static void percpu_timer_stop(void); + ++int __attribute__((weak)) platform_cpu_kill(unsigned int cpu) ++{ ++ if (smp_ops.cpu_kill) ++ return smp_ops.cpu_kill(cpu); ++ return 1; ++} ++ ++void __attribute__((weak)) platform_cpu_die(unsigned int cpu) ++{ ++ if (smp_ops.cpu_die) ++ smp_ops.cpu_die(cpu); ++} ++ ++int __attribute__((weak)) platform_cpu_disable(unsigned int cpu) ++{ ++ if (smp_ops.cpu_disable) ++ return smp_ops.cpu_disable(cpu); ++ ++ /* ++ * By default, allow disabling all CPUs except the first one, ++ * since this is special on a lot of platforms, e.g. because ++ * of clock tick interrupts. ++ */ ++ return cpu == 0 ? -EPERM : 0; ++} + /* + * __cpu_disable runs on the processor to be shutdown. + */ diff --git a/patches.misc/arm-soc-convert-shmobile-smp-to-smp-operations.patch b/patches.misc/arm-soc-convert-shmobile-smp-to-smp-operations.patch new file mode 100644 index 00000000000000..c5a35dcae70a98 --- /dev/null +++ b/patches.misc/arm-soc-convert-shmobile-smp-to-smp-operations.patch @@ -0,0 +1,611 @@ +From horms@vergenet.net Tue Mar 26 21:37:56 2013 +From: Simon Horman <horms+renesas@verge.net.au> +Date: Wed, 27 Mar 2013 13:37:50 +0900 +Subject: [PATCH 2/2] ARM: SoC: convert shmobile SMP to SMP operations +To: ltsi-dev@lists.linuxfoundation.org +Cc: Greg KH <gregkh@linuxfoundation.org> +Message-ID: <1364359070-7002-3-git-send-email-horms+renesas@verge.net.au> + + +From: Marc Zyngier <marc.zyngier@arm.com> + +Convert shmobile SMP platforms to use struct smp_operations to provide +their SMP and CPU hotplug operations. + +Cc: Paul Mundt <lethal@linux-sh.org> +Cc: Magnus Damm <magnus.damm@gmail.com> +Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> +Acked-by: Nicolas Pitre <nico@linaro.org> +Signed-off-by: Arnd Bergmann <arnd@arndb.de> +--- + arch/arm/mach-shmobile/board-ag5evm.c | 1 + arch/arm/mach-shmobile/board-kota2.c | 1 + arch/arm/mach-shmobile/board-kzm9d.c | 1 + arch/arm/mach-shmobile/board-kzm9g.c | 1 + arch/arm/mach-shmobile/board-marzen.c | 1 + arch/arm/mach-shmobile/hotplug.c | 31 ++------ + arch/arm/mach-shmobile/include/mach/common.h | 24 +++--- + arch/arm/mach-shmobile/include/mach/emev2.h | 7 - + arch/arm/mach-shmobile/include/mach/r8a7779.h | 2 + arch/arm/mach-shmobile/include/mach/sh73a0.h | 2 + arch/arm/mach-shmobile/platsmp.c | 96 -------------------------- + arch/arm/mach-shmobile/setup-emev2.c | 1 + arch/arm/mach-shmobile/smp-emev2.c | 47 +++++++++++- + arch/arm/mach-shmobile/smp-r8a7779.c | 48 +++++++++++-- + arch/arm/mach-shmobile/smp-sh73a0.c | 48 +++++++++++-- + 15 files changed, 165 insertions(+), 146 deletions(-) + +--- a/arch/arm/mach-shmobile/board-ag5evm.c ++++ b/arch/arm/mach-shmobile/board-ag5evm.c +@@ -574,6 +574,7 @@ static void __init ag5evm_init(void) + } + + MACHINE_START(AG5EVM, "ag5evm") ++ .smp = smp_ops(sh73a0_smp_ops), + .map_io = sh73a0_map_io, + .init_early = sh73a0_add_early_devices, + .nr_irqs = NR_IRQS_LEGACY, +--- a/arch/arm/mach-shmobile/board-kota2.c ++++ b/arch/arm/mach-shmobile/board-kota2.c +@@ -515,6 +515,7 @@ static void __init kota2_init(void) + } + + MACHINE_START(KOTA2, "kota2") ++ .smp = smp_ops(sh73a0_smp_ops), + .map_io = sh73a0_map_io, + .init_early = sh73a0_add_early_devices, + .nr_irqs = NR_IRQS_LEGACY, +--- a/arch/arm/mach-shmobile/board-kzm9d.c ++++ b/arch/arm/mach-shmobile/board-kzm9d.c +@@ -74,6 +74,7 @@ static const char *kzm9d_boards_compat_d + }; + + DT_MACHINE_START(KZM9D_DT, "kzm9d") ++ .smp = smp_ops(emev2_smp_ops), + .map_io = emev2_map_io, + .init_early = emev2_add_early_devices, + .nr_irqs = NR_IRQS_LEGACY, +--- a/arch/arm/mach-shmobile/board-kzm9g.c ++++ b/arch/arm/mach-shmobile/board-kzm9g.c +@@ -744,6 +744,7 @@ static const char *kzm9g_boards_compat_d + }; + + DT_MACHINE_START(KZM9G_DT, "kzm9g") ++ .smp = smp_ops(sh73a0_smp_ops), + .map_io = sh73a0_map_io, + .init_early = sh73a0_add_early_devices, + .nr_irqs = NR_IRQS_LEGACY, +--- a/arch/arm/mach-shmobile/board-marzen.c ++++ b/arch/arm/mach-shmobile/board-marzen.c +@@ -102,6 +102,7 @@ static void __init marzen_init(void) + } + + MACHINE_START(MARZEN, "marzen") ++ .smp = smp_ops(r8a7779_smp_ops), + .map_io = r8a7779_map_io, + .init_early = r8a7779_add_early_devices, + .nr_irqs = NR_IRQS_LEGACY, +--- a/arch/arm/mach-shmobile/hotplug.c ++++ b/arch/arm/mach-shmobile/hotplug.c +@@ -14,30 +14,16 @@ + #include <linux/smp.h> + #include <linux/cpumask.h> + #include <linux/delay.h> ++#include <linux/of.h> + #include <mach/common.h> ++#include <mach/r8a7779.h> ++#include <mach/emev2.h> + #include <asm/cacheflush.h> ++#include <asm/mach-types.h> + + static cpumask_t dead_cpus; + +-int platform_cpu_kill(unsigned int cpu) +-{ +- int k; +- +- /* this function is running on another CPU than the offline target, +- * here we need wait for shutdown code in platform_cpu_die() to +- * finish before asking SoC-specific code to power off the CPU core. +- */ +- for (k = 0; k < 1000; k++) { +- if (cpumask_test_cpu(cpu, &dead_cpus)) +- return shmobile_platform_cpu_kill(cpu); +- +- mdelay(1); +- } +- +- return 0; +-} +- +-void platform_cpu_die(unsigned int cpu) ++void shmobile_cpu_die(unsigned int cpu) + { + /* hardware shutdown code running on the CPU that is being offlined */ + flush_cache_all(); +@@ -60,7 +46,7 @@ void platform_cpu_die(unsigned int cpu) + } + } + +-int platform_cpu_disable(unsigned int cpu) ++int shmobile_cpu_disable(unsigned int cpu) + { + cpumask_clear_cpu(cpu, &dead_cpus); + /* +@@ -69,3 +55,8 @@ int platform_cpu_disable(unsigned int cp + */ + return cpu == 0 ? -EPERM : 0; + } ++ ++int shmobile_cpu_is_dead(unsigned int cpu) ++{ ++ return cpumask_test_cpu(cpu, &dead_cpus); ++} +--- a/arch/arm/mach-shmobile/include/mach/common.h ++++ b/arch/arm/mach-shmobile/include/mach/common.h +@@ -4,11 +4,10 @@ + extern void shmobile_earlytimer_init(void); + extern struct sys_timer shmobile_timer; + extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz, +- unsigned int mult, unsigned int div); ++ unsigned int mult, unsigned int div); + struct twd_local_timer; + extern void shmobile_setup_console(void); + extern void shmobile_secondary_vector(void); +-extern int shmobile_platform_cpu_kill(unsigned int cpu); + struct clk; + extern int shmobile_clk_init(void); + extern void shmobile_handle_irq_intc(struct pt_regs *); +@@ -58,11 +57,6 @@ extern struct clk sh73a0_extal2_clk; + extern struct clk sh73a0_extcki_clk; + extern struct clk sh73a0_extalr_clk; + +-extern unsigned int sh73a0_get_core_count(void); +-extern void sh73a0_secondary_init(unsigned int cpu); +-extern int sh73a0_boot_secondary(unsigned int cpu); +-extern void sh73a0_smp_prepare_cpus(void); +- + extern void r8a7740_init_irq(void); + extern void r8a7740_map_io(void); + extern void r8a7740_add_early_devices(void); +@@ -80,11 +74,6 @@ extern void r8a7779_pinmux_init(void); + extern void r8a7779_pm_init(void); + extern void r8a7740_meram_workaround(void); + +-extern unsigned int r8a7779_get_core_count(void); +-extern int r8a7779_platform_cpu_kill(unsigned int cpu); +-extern void r8a7779_secondary_init(unsigned int cpu); +-extern int r8a7779_boot_secondary(unsigned int cpu); +-extern void r8a7779_smp_prepare_cpus(void); + extern void r8a7779_register_twd(void); + + extern void shmobile_init_late(void); +@@ -101,4 +90,15 @@ int shmobile_cpuidle_init(void); + static inline int shmobile_cpuidle_init(void) { return 0; } + #endif + ++extern void shmobile_cpu_die(unsigned int cpu); ++extern int shmobile_cpu_disable(unsigned int cpu); ++ ++#ifdef CONFIG_HOTPLUG_CPU ++extern int shmobile_cpu_is_dead(unsigned int cpu); ++#else ++static inline int shmobile_cpu_is_dead(unsigned int cpu) { return 1; } ++#endif ++ ++extern void shmobile_smp_init_cpus(unsigned int ncores); ++ + #endif /* __ARCH_MACH_COMMON_H */ +--- a/arch/arm/mach-shmobile/include/mach/emev2.h ++++ b/arch/arm/mach-shmobile/include/mach/emev2.h +@@ -7,13 +7,10 @@ extern void emev2_add_early_devices(void + extern void emev2_add_standard_devices(void); + extern void emev2_clock_init(void); + extern void emev2_set_boot_vector(unsigned long value); +-extern unsigned int emev2_get_core_count(void); +-extern int emev2_platform_cpu_kill(unsigned int cpu); +-extern void emev2_secondary_init(unsigned int cpu); +-extern int emev2_boot_secondary(unsigned int cpu); +-extern void emev2_smp_prepare_cpus(void); + + #define EMEV2_GPIO_BASE 200 + #define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n)) + ++extern struct smp_operations emev2_smp_ops; ++ + #endif /* __ASM_EMEV2_H__ */ +--- a/arch/arm/mach-shmobile/include/mach/r8a7779.h ++++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h +@@ -360,4 +360,6 @@ extern void r8a7779_add_device_to_domain + #define r8a7779_add_device_to_domain(pd, pdev) do { } while (0) + #endif /* CONFIG_PM */ + ++extern struct smp_operations r8a7779_smp_ops; ++ + #endif /* __ASM_R8A7779_H__ */ +--- a/arch/arm/mach-shmobile/include/mach/sh73a0.h ++++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h +@@ -557,4 +557,6 @@ enum { + #define SH73A0_PINT0_IRQ(irq) ((irq) + 700) + #define SH73A0_PINT1_IRQ(irq) ((irq) + 732) + ++extern struct smp_operations sh73a0_smp_ops; ++ + #endif /* __ASM_SH73A0_H__ */ +--- a/arch/arm/mach-shmobile/platsmp.c ++++ b/arch/arm/mach-shmobile/platsmp.c +@@ -11,100 +11,11 @@ + * published by the Free Software Foundation. + */ + #include <linux/init.h> +-#include <linux/errno.h> +-#include <linux/delay.h> +-#include <linux/device.h> + #include <linux/smp.h> +-#include <linux/io.h> +-#include <linux/of.h> + #include <asm/hardware/gic.h> +-#include <asm/mach-types.h> +-#include <mach/common.h> +-#include <mach/emev2.h> + +-#ifdef CONFIG_ARCH_SH73A0 +-#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || \ +- of_machine_is_compatible("renesas,sh73a0")) +-#else +-#define is_sh73a0() (0) +-#endif +- +-#define is_r8a7779() machine_is_marzen() +- +-#ifdef CONFIG_ARCH_EMEV2 +-#define is_emev2() of_machine_is_compatible("renesas,emev2") +-#else +-#define is_emev2() (0) +-#endif +- +-static unsigned int __init shmobile_smp_get_core_count(void) +-{ +- if (is_sh73a0()) +- return sh73a0_get_core_count(); +- +- if (is_r8a7779()) +- return r8a7779_get_core_count(); +- +- if (is_emev2()) +- return emev2_get_core_count(); +- +- return 1; +-} +- +-static void __init shmobile_smp_prepare_cpus(void) +-{ +- if (is_sh73a0()) +- sh73a0_smp_prepare_cpus(); +- +- if (is_r8a7779()) +- r8a7779_smp_prepare_cpus(); +- +- if (is_emev2()) +- emev2_smp_prepare_cpus(); +-} +- +-int shmobile_platform_cpu_kill(unsigned int cpu) +-{ +- if (is_r8a7779()) +- return r8a7779_platform_cpu_kill(cpu); +- +- if (is_emev2()) +- return emev2_platform_cpu_kill(cpu); +- +- return 1; +-} +- +-void __cpuinit platform_secondary_init(unsigned int cpu) ++void __init shmobile_smp_init_cpus(unsigned int ncores) + { +- trace_hardirqs_off(); +- +- if (is_sh73a0()) +- sh73a0_secondary_init(cpu); +- +- if (is_r8a7779()) +- r8a7779_secondary_init(cpu); +- +- if (is_emev2()) +- emev2_secondary_init(cpu); +-} +- +-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +-{ +- if (is_sh73a0()) +- return sh73a0_boot_secondary(cpu); +- +- if (is_r8a7779()) +- return r8a7779_boot_secondary(cpu); +- +- if (is_emev2()) +- return emev2_boot_secondary(cpu); +- +- return -ENOSYS; +-} +- +-void __init smp_init_cpus(void) +-{ +- unsigned int ncores = shmobile_smp_get_core_count(); + unsigned int i; + + if (ncores > nr_cpu_ids) { +@@ -118,8 +29,3 @@ void __init smp_init_cpus(void) + + set_smp_cross_call(gic_raise_softirq); + } +- +-void __init platform_smp_prepare_cpus(unsigned int max_cpus) +-{ +- shmobile_smp_prepare_cpus(); +-} +--- a/arch/arm/mach-shmobile/setup-emev2.c ++++ b/arch/arm/mach-shmobile/setup-emev2.c +@@ -440,6 +440,7 @@ void __init emev2_init_irq_dt(void) + } + + DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)") ++ .smp = smp_ops(emev2_smp_ops), + .init_early = emev2_init_delay, + .nr_irqs = NR_IRQS_LEGACY, + .init_irq = emev2_init_irq_dt, +--- a/arch/arm/mach-shmobile/smp-emev2.c ++++ b/arch/arm/mach-shmobile/smp-emev2.c +@@ -50,7 +50,7 @@ static void modify_scu_cpu_psr(unsigned + + } + +-unsigned int __init emev2_get_core_count(void) ++static unsigned int __init emev2_get_core_count(void) + { + if (!scu_base) { + scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE); +@@ -62,17 +62,35 @@ unsigned int __init emev2_get_core_count + return scu_base ? scu_get_core_count(scu_base) : 1; + } + +-int emev2_platform_cpu_kill(unsigned int cpu) ++static int emev2_platform_cpu_kill(unsigned int cpu) + { + return 0; /* not supported yet */ + } + +-void __cpuinit emev2_secondary_init(unsigned int cpu) ++static int __maybe_unused emev2_cpu_kill(unsigned int cpu) ++{ ++ int k; ++ ++ /* this function is running on another CPU than the offline target, ++ * here we need wait for shutdown code in platform_cpu_die() to ++ * finish before asking SoC-specific code to power off the CPU core. ++ */ ++ for (k = 0; k < 1000; k++) { ++ if (shmobile_cpu_is_dead(cpu)) ++ return emev2_platform_cpu_kill(cpu); ++ mdelay(1); ++ } ++ ++ return 0; ++} ++ ++ ++static void __cpuinit emev2_secondary_init(unsigned int cpu) + { + gic_secondary_init(0); + } + +-int __cpuinit emev2_boot_secondary(unsigned int cpu) ++static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *idle) + { + cpu = cpu_logical_map(cpu); + +@@ -86,7 +104,7 @@ int __cpuinit emev2_boot_secondary(unsig + return 0; + } + +-void __init emev2_smp_prepare_cpus(void) ++static void __init emev2_smp_prepare_cpus(unsigned int max_cpus) + { + int cpu = cpu_logical_map(0); + +@@ -95,3 +113,22 @@ void __init emev2_smp_prepare_cpus(void) + /* enable cache coherency on CPU0 */ + modify_scu_cpu_psr(0, 3 << (cpu * 8)); + } ++ ++static void __init emev2_smp_init_cpus(void) ++{ ++ unsigned int ncores = emev2_get_core_count(); ++ ++ shmobile_smp_init_cpus(ncores); ++} ++ ++struct smp_operations emev2_smp_ops __initdata = { ++ .smp_init_cpus = emev2_smp_init_cpus, ++ .smp_prepare_cpus = emev2_smp_prepare_cpus, ++ .smp_secondary_init = emev2_secondary_init, ++ .smp_boot_secondary = emev2_boot_secondary, ++#ifdef CONFIG_HOTPLUG_CPU ++ .cpu_kill = emev2_cpu_kill, ++ .cpu_die = shmobile_cpu_die, ++ .cpu_disable = shmobile_cpu_disable, ++#endif ++}; +--- a/arch/arm/mach-shmobile/smp-r8a7779.c ++++ b/arch/arm/mach-shmobile/smp-r8a7779.c +@@ -87,14 +87,14 @@ static void modify_scu_cpu_psr(unsigned + __raw_writel(tmp, scu_base + 8); + } + +-unsigned int __init r8a7779_get_core_count(void) ++static unsigned int __init r8a7779_get_core_count(void) + { + void __iomem *scu_base = scu_base_addr(); + + return scu_get_core_count(scu_base); + } + +-int r8a7779_platform_cpu_kill(unsigned int cpu) ++static int r8a7779_platform_cpu_kill(unsigned int cpu) + { + struct r8a7779_pm_ch *ch = NULL; + int ret = -EIO; +@@ -113,12 +113,31 @@ int r8a7779_platform_cpu_kill(unsigned i + return ret ? ret : 1; + } + +-void __cpuinit r8a7779_secondary_init(unsigned int cpu) ++static int __maybe_unused r8a7779_cpu_kill(unsigned int cpu) ++{ ++ int k; ++ ++ /* this function is running on another CPU than the offline target, ++ * here we need wait for shutdown code in platform_cpu_die() to ++ * finish before asking SoC-specific code to power off the CPU core. ++ */ ++ for (k = 0; k < 1000; k++) { ++ if (shmobile_cpu_is_dead(cpu)) ++ return r8a7779_platform_cpu_kill(cpu); ++ ++ mdelay(1); ++ } ++ ++ return 0; ++} ++ ++ ++static void __cpuinit r8a7779_secondary_init(unsigned int cpu) + { + gic_secondary_init(0); + } + +-int __cpuinit r8a7779_boot_secondary(unsigned int cpu) ++static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle) + { + struct r8a7779_pm_ch *ch = NULL; + int ret = -EIO; +@@ -137,7 +156,7 @@ int __cpuinit r8a7779_boot_secondary(uns + return ret; + } + +-void __init r8a7779_smp_prepare_cpus(void) ++static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus) + { + int cpu = cpu_logical_map(0); + +@@ -156,3 +175,22 @@ void __init r8a7779_smp_prepare_cpus(voi + r8a7779_platform_cpu_kill(2); + r8a7779_platform_cpu_kill(3); + } ++ ++static void __init r8a7779_smp_init_cpus(void) ++{ ++ unsigned int ncores = r8a7779_get_core_count(); ++ ++ shmobile_smp_init_cpus(ncores); ++} ++ ++struct smp_operations r8a7779_smp_ops __initdata = { ++ .smp_init_cpus = r8a7779_smp_init_cpus, ++ .smp_prepare_cpus = r8a7779_smp_prepare_cpus, ++ .smp_secondary_init = r8a7779_secondary_init, ++ .smp_boot_secondary = r8a7779_boot_secondary, ++#ifdef CONFIG_HOTPLUG_CPU ++ .cpu_kill = r8a7779_cpu_kill, ++ .cpu_die = shmobile_cpu_die, ++ .cpu_disable = shmobile_cpu_disable, ++#endif ++}; +--- a/arch/arm/mach-shmobile/smp-sh73a0.c ++++ b/arch/arm/mach-shmobile/smp-sh73a0.c +@@ -22,8 +22,10 @@ + #include <linux/smp.h> + #include <linux/spinlock.h> + #include <linux/io.h> ++#include <linux/delay.h> + #include <mach/common.h> + #include <asm/smp_plat.h> ++#include <mach/sh73a0.h> + #include <asm/smp_scu.h> + #include <asm/smp_twd.h> + #include <asm/hardware/gic.h> +@@ -64,19 +66,19 @@ static void modify_scu_cpu_psr(unsigned + __raw_writel(tmp, scu_base + 8); + } + +-unsigned int __init sh73a0_get_core_count(void) ++static unsigned int __init sh73a0_get_core_count(void) + { + void __iomem *scu_base = scu_base_addr(); + + return scu_get_core_count(scu_base); + } + +-void __cpuinit sh73a0_secondary_init(unsigned int cpu) ++static void __cpuinit sh73a0_secondary_init(unsigned int cpu) + { + gic_secondary_init(0); + } + +-int __cpuinit sh73a0_boot_secondary(unsigned int cpu) ++static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle) + { + cpu = cpu_logical_map(cpu); + +@@ -91,7 +93,7 @@ int __cpuinit sh73a0_boot_secondary(unsi + return 0; + } + +-void __init sh73a0_smp_prepare_cpus(void) ++static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus) + { + int cpu = cpu_logical_map(0); + +@@ -104,3 +106,41 @@ void __init sh73a0_smp_prepare_cpus(void + /* enable cache coherency on CPU0 */ + modify_scu_cpu_psr(0, 3 << (cpu * 8)); + } ++ ++static void __init sh73a0_smp_init_cpus(void) ++{ ++ unsigned int ncores = sh73a0_get_core_count(); ++ ++ shmobile_smp_init_cpus(ncores); ++} ++ ++static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu) ++{ ++ int k; ++ ++ /* this function is running on another CPU than the offline target, ++ * here we need wait for shutdown code in platform_cpu_die() to ++ * finish before asking SoC-specific code to power off the CPU core. ++ */ ++ for (k = 0; k < 1000; k++) { ++ if (shmobile_cpu_is_dead(cpu)) ++ return 1; ++ ++ mdelay(1); ++ } ++ ++ return 0; ++} ++ ++ ++struct smp_operations sh73a0_smp_ops __initdata = { ++ .smp_init_cpus = sh73a0_smp_init_cpus, ++ .smp_prepare_cpus = sh73a0_smp_prepare_cpus, ++ .smp_secondary_init = sh73a0_secondary_init, ++ .smp_boot_secondary = sh73a0_boot_secondary, ++#ifdef CONFIG_HOTPLUG_CPU ++ .cpu_kill = sh73a0_cpu_kill, ++ .cpu_die = shmobile_cpu_die, ++ .cpu_disable = shmobile_cpu_disable, ++#endif ++}; @@ -782,6 +782,13 @@ patches.codel/codel-refine-one-condition-to-avoid-a-nul-rec_inv_sq.patch ############################################################################# +# Misc patches that don't fit into the above categories. +# +patches.misc/arm-soc-add-per-platform-smp-operations.patch +patches.misc/arm-soc-convert-shmobile-smp-to-smp-operations.patch + + +############################################################################# # fixes that go after all of the above # patches.fixes/0001-ASoC-fsi-fixup-channels_min-max.patch |