Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag '3.10-rc2-psci-ops-11-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/sstabellini/xen into devel-stable

Pull psci_smp_ops support from Stefano Stabellini:
It contains the generic PSCI patch and the smp_init patch that we
discussed so much about. I think it would be helpful for other
people if you could create a stable branch with these patches so
that SoC devs can base their work on it.

+113 -60
+5
arch/arm/include/asm/mach/arch.h
··· 8 8 * published by the Free Software Foundation. 9 9 */ 10 10 11 + #include <linux/types.h> 12 + 11 13 #ifndef __ASSEMBLY__ 12 14 13 15 struct tag; ··· 18 16 struct smp_operations; 19 17 #ifdef CONFIG_SMP 20 18 #define smp_ops(ops) (&(ops)) 19 + #define smp_init_ops(ops) (&(ops)) 21 20 #else 22 21 #define smp_ops(ops) (struct smp_operations *)NULL 22 + #define smp_init_ops(ops) (bool (*)(void))NULL 23 23 #endif 24 24 25 25 struct machine_desc { ··· 45 41 unsigned char reserve_lp2 :1; /* never has lp2 */ 46 42 char restart_mode; /* default restart mode */ 47 43 struct smp_operations *smp; /* SMP operations */ 44 + bool (*smp_init)(void); 48 45 void (*fixup)(struct tag *, char **, 49 46 struct meminfo *); 50 47 void (*reserve)(void);/* reserve mem blocks */
+9
arch/arm/include/asm/psci.h
··· 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 */
+4 -1
arch/arm/kernel/Makefile
··· 88 88 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 89 89 90 90 obj-$(CONFIG_ARM_VIRT_EXT) += hyp-stub.o 91 - obj-$(CONFIG_ARM_PSCI) += psci.o 91 + ifeq ($(CONFIG_ARM_PSCI),y) 92 + obj-y += psci.o 93 + obj-$(CONFIG_SMP) += psci_smp.o 94 + endif 92 95 93 96 extra-y := $(head-y) vmlinux.lds
+3 -4
arch/arm/kernel/psci.c
··· 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 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 ··· 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);
+84
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 + };
+8 -1
arch/arm/kernel/setup.c
··· 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> ··· 810 809 unflatten_device_tree(); 811 810 812 811 arm_dt_init_cpu_maps(); 812 + psci_init(); 813 813 #ifdef CONFIG_SMP 814 814 if (is_smp()) { 815 - smp_set_ops(mdesc->smp); 815 + if (!mdesc->smp_init || !mdesc->smp_init()) { 816 + if (psci_smp_available()) 817 + smp_set_ops(&psci_smp_ops); 818 + else if (mdesc->smp) 819 + smp_set_ops(mdesc->smp); 820 + } 816 821 smp_init_cpus(); 817 822 } 818 823 #endif
-1
arch/arm/mach-virt/Makefile
··· 3 3 # 4 4 5 5 obj-y := virt.o 6 - obj-$(CONFIG_SMP) += platsmp.o
-50
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 - };
-3
arch/arm/mach-virt/virt.c
··· 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