Commit 05774088391c7430f6a4c1d5d18196ef17bb3ba9

Authored by Stefano Stabellini
1 parent c7788792a5

arm: introduce psci_smp_ops

Rename virt_smp_ops to psci_smp_ops and move them to arch/arm/kernel/psci_smp.c.
Remove mach-virt/platsmp.c, now unused.
Compile psci_smp if CONFIG_ARM_PSCI and CONFIG_SMP.

Add a cpu_die smp_op based on psci_ops.cpu_off.

Initialize PSCI before setting smp_ops in setup_arch.

If PSCI is available on the platform, prefer psci_smp_ops over the
platform smp_ops.


Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Will Deacon <will.deacon@arm.com>
CC: arnd@arndb.de
CC: marc.zyngier@arm.com
CC: linux@arm.linux.org.uk
CC: nico@linaro.org
CC: rob.herring@calxeda.com

Showing 8 changed files with 106 additions and 60 deletions Side-by-side Diff

arch/arm/include/asm/psci.h
... ... @@ -32,6 +32,15 @@
32 32 };
33 33  
34 34 extern struct psci_operations psci_ops;
  35 +extern struct smp_operations psci_smp_ops;
  36 +
  37 +#ifdef CONFIG_ARM_PSCI
  38 +void psci_init(void);
  39 +bool psci_smp_available(void);
  40 +#else
  41 +static inline void psci_init(void) { }
  42 +static inline bool psci_smp_available(void) { return false; }
  43 +#endif
35 44  
36 45 #endif /* __ASM_ARM_PSCI_H */
arch/arm/kernel/Makefile
... ... @@ -82,7 +82,10 @@
82 82 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
83 83  
84 84 obj-$(CONFIG_ARM_VIRT_EXT) += hyp-stub.o
85   -obj-$(CONFIG_ARM_PSCI) += psci.o
  85 +ifeq ($(CONFIG_ARM_PSCI),y)
  86 +obj-y += psci.o
  87 +obj-$(CONFIG_SMP) += psci_smp.o
  88 +endif
86 89  
87 90 extra-y := $(head-y) vmlinux.lds
arch/arm/kernel/psci.c
... ... @@ -158,7 +158,7 @@
158 158 {},
159 159 };
160 160  
161   -static int __init psci_init(void)
  161 +void __init psci_init(void)
162 162 {
163 163 struct device_node *np;
164 164 const char *method;
... ... @@ -166,7 +166,7 @@
166 166  
167 167 np = of_find_matching_node(NULL, psci_of_match);
168 168 if (!np)
169   - return 0;
  169 + return;
170 170  
171 171 pr_info("probing function IDs from device-tree\n");
172 172  
173 173  
... ... @@ -206,7 +206,6 @@
206 206  
207 207 out_put_node:
208 208 of_node_put(np);
209   - return 0;
  209 + return;
210 210 }
211   -early_initcall(psci_init);
arch/arm/kernel/psci_smp.c
  1 +/*
  2 + * This program is free software; you can redistribute it and/or modify
  3 + * it under the terms of the GNU General Public License version 2 as
  4 + * published by the Free Software Foundation.
  5 + *
  6 + * This program is distributed in the hope that it will be useful,
  7 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  8 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9 + * GNU General Public License for more details.
  10 + *
  11 + * Copyright (C) 2012 ARM Limited
  12 + *
  13 + * Author: Will Deacon <will.deacon@arm.com>
  14 + */
  15 +
  16 +#include <linux/init.h>
  17 +#include <linux/irqchip/arm-gic.h>
  18 +#include <linux/smp.h>
  19 +#include <linux/of.h>
  20 +
  21 +#include <asm/psci.h>
  22 +#include <asm/smp_plat.h>
  23 +
  24 +/*
  25 + * psci_smp assumes that the following is true about PSCI:
  26 + *
  27 + * cpu_suspend Suspend the execution on a CPU
  28 + * @state we don't currently describe affinity levels, so just pass 0.
  29 + * @entry_point the first instruction to be executed on return
  30 + * returns 0 success, < 0 on failure
  31 + *
  32 + * cpu_off Power down a CPU
  33 + * @state we don't currently describe affinity levels, so just pass 0.
  34 + * no return on successful call
  35 + *
  36 + * cpu_on Power up a CPU
  37 + * @cpuid cpuid of target CPU, as from MPIDR
  38 + * @entry_point the first instruction to be executed on return
  39 + * returns 0 success, < 0 on failure
  40 + *
  41 + * migrate Migrate the context to a different CPU
  42 + * @cpuid cpuid of target CPU, as from MPIDR
  43 + * returns 0 success, < 0 on failure
  44 + *
  45 + */
  46 +
  47 +extern void secondary_startup(void);
  48 +
  49 +static int __cpuinit psci_boot_secondary(unsigned int cpu,
  50 + struct task_struct *idle)
  51 +{
  52 + if (psci_ops.cpu_on)
  53 + return psci_ops.cpu_on(cpu_logical_map(cpu),
  54 + __pa(secondary_startup));
  55 + return -ENODEV;
  56 +}
  57 +
  58 +#ifdef CONFIG_HOTPLUG_CPU
  59 +void __ref psci_cpu_die(unsigned int cpu)
  60 +{
  61 + const struct psci_power_state ps = {
  62 + .type = PSCI_POWER_STATE_TYPE_POWER_DOWN,
  63 + };
  64 +
  65 + if (psci_ops.cpu_off)
  66 + psci_ops.cpu_off(ps);
  67 +
  68 + /* We should never return */
  69 + panic("psci: cpu %d failed to shutdown\n", cpu);
  70 +}
  71 +#else
  72 +#define psci_cpu_die NULL
  73 +#endif
  74 +
  75 +bool __init psci_smp_available(void)
  76 +{
  77 + /* is cpu_on available at least? */
  78 + return (psci_ops.cpu_on != NULL);
  79 +}
  80 +
  81 +struct smp_operations __initdata psci_smp_ops = {
  82 + .smp_boot_secondary = psci_boot_secondary,
  83 + .cpu_die = psci_cpu_die,
  84 +};
arch/arm/kernel/setup.c
... ... @@ -37,6 +37,7 @@
37 37 #include <asm/cputype.h>
38 38 #include <asm/elf.h>
39 39 #include <asm/procinfo.h>
  40 +#include <asm/psci.h>
40 41 #include <asm/sections.h>
41 42 #include <asm/setup.h>
42 43 #include <asm/smp_plat.h>
43 44  
... ... @@ -796,9 +797,13 @@
796 797 unflatten_device_tree();
797 798  
798 799 arm_dt_init_cpu_maps();
  800 + psci_init();
799 801 #ifdef CONFIG_SMP
800 802 if (is_smp()) {
801   - smp_set_ops(mdesc->smp);
  803 + if (psci_smp_available())
  804 + smp_set_ops(&psci_smp_ops);
  805 + else if (mdesc->smp)
  806 + smp_set_ops(mdesc->smp);
802 807 smp_init_cpus();
803 808 }
804 809 #endif
arch/arm/mach-virt/Makefile
... ... @@ -3,5 +3,4 @@
3 3 #
4 4  
5 5 obj-y := virt.o
6   -obj-$(CONFIG_SMP) += platsmp.o
arch/arm/mach-virt/platsmp.c
1   -/*
2   - * Dummy Virtual Machine - does what it says on the tin.
3   - *
4   - * Copyright (C) 2012 ARM Ltd
5   - * Author: Will Deacon <will.deacon@arm.com>
6   - *
7   - * This program is free software; you can redistribute it and/or modify
8   - * it under the terms of the GNU General Public License version 2 as
9   - * published by the Free Software Foundation.
10   - *
11   - * This program is distributed in the hope that it will be useful,
12   - * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14   - * GNU General Public License for more details.
15   - *
16   - * You should have received a copy of the GNU General Public License
17   - * along with this program. If not, see <http://www.gnu.org/licenses/>.
18   - */
19   -
20   -#include <linux/init.h>
21   -#include <linux/smp.h>
22   -#include <linux/of.h>
23   -
24   -#include <asm/psci.h>
25   -#include <asm/smp_plat.h>
26   -
27   -extern void secondary_startup(void);
28   -
29   -static void __init virt_smp_init_cpus(void)
30   -{
31   -}
32   -
33   -static void __init virt_smp_prepare_cpus(unsigned int max_cpus)
34   -{
35   -}
36   -
37   -static int __cpuinit virt_boot_secondary(unsigned int cpu,
38   - struct task_struct *idle)
39   -{
40   - if (psci_ops.cpu_on)
41   - return psci_ops.cpu_on(cpu_logical_map(cpu),
42   - __pa(secondary_startup));
43   - return -ENODEV;
44   -}
45   -
46   -struct smp_operations __initdata virt_smp_ops = {
47   - .smp_init_cpus = virt_smp_init_cpus,
48   - .smp_prepare_cpus = virt_smp_prepare_cpus,
49   - .smp_boot_secondary = virt_boot_secondary,
50   -};
arch/arm/mach-virt/virt.c
... ... @@ -36,12 +36,9 @@
36 36 NULL
37 37 };
38 38  
39   -extern struct smp_operations virt_smp_ops;
40   -
41 39 DT_MACHINE_START(VIRT, "Dummy Virtual Machine")
42 40 .init_irq = irqchip_init,
43 41 .init_machine = virt_init,
44   - .smp = smp_ops(virt_smp_ops),
45 42 .dt_compat = virt_dt_match,
46 43 MACHINE_END