Loading arch/arm64/include/asm/acpi.h +4 −0 Original line number Diff line number Diff line Loading @@ -93,4 +93,8 @@ static inline bool acpi_psci_use_hvc(void) { return false; } static inline void acpi_init_cpus(void) { } #endif /* CONFIG_ACPI */ static inline const char *acpi_get_enable_method(int cpu) { return acpi_psci_present() ? "psci" : NULL; } #endif /*_ASM_ACPI_H*/ arch/arm64/include/asm/cpu_ops.h +15 −12 Original line number Diff line number Diff line Loading @@ -19,15 +19,15 @@ #include <linux/init.h> #include <linux/threads.h> struct device_node; /** * struct cpu_operations - Callback operations for hotplugging CPUs. * * @name: Name of the property as appears in a devicetree cpu node's * enable-method property. * @cpu_init: Reads any data necessary for a specific enable-method from the * devicetree, for a given cpu node and proposed logical id. * enable-method property. On systems booting with ACPI, @name * identifies the struct cpu_operations entry corresponding to * the boot protocol specified in the ACPI MADT table. * @cpu_init: Reads any data necessary for a specific enable-method for a * proposed logical id. * @cpu_prepare: Early one-time preparation step for a cpu. If there is a * mechanism for doing so, tests whether it is possible to boot * the given CPU. Loading @@ -40,15 +40,15 @@ struct device_node; * @cpu_die: Makes a cpu leave the kernel. Must not fail. Called from the * cpu being killed. * @cpu_kill: Ensures a cpu has left the kernel. Called from another cpu. * @cpu_init_idle: Reads any data necessary to initialize CPU idle states from * devicetree, for a given cpu node and proposed logical id. * @cpu_init_idle: Reads any data necessary to initialize CPU idle states for * a proposed logical id. * @cpu_suspend: Suspends a cpu and saves the required context. May fail owing * to wrong parameters or error conditions. Called from the * CPU being suspended. Must be called with IRQs disabled. */ struct cpu_operations { const char *name; int (*cpu_init)(struct device_node *, unsigned int); int (*cpu_init)(unsigned int); int (*cpu_prepare)(unsigned int); int (*cpu_boot)(unsigned int); void (*cpu_postboot)(void); Loading @@ -58,14 +58,17 @@ struct cpu_operations { int (*cpu_kill)(unsigned int cpu); #endif #ifdef CONFIG_CPU_IDLE int (*cpu_init_idle)(struct device_node *, unsigned int); int (*cpu_init_idle)(unsigned int); int (*cpu_suspend)(unsigned long); #endif }; extern const struct cpu_operations *cpu_ops[NR_CPUS]; int __init cpu_read_ops(struct device_node *dn, int cpu); void __init cpu_read_bootcpu_ops(void); const struct cpu_operations *cpu_get_ops(const char *name); int __init cpu_read_ops(int cpu); static inline void __init cpu_read_bootcpu_ops(void) { cpu_read_ops(0); } #endif /* ifndef __ASM_CPU_OPS_H */ arch/arm64/include/asm/smp.h +1 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ extern void handle_IPI(int ipinr, struct pt_regs *regs); * Discover the set of possible CPUs and determine their * SMP operations. */ extern void of_smp_init_cpus(void); extern void smp_init_cpus(void); /* * Provide a function to raise an IPI cross call on CPUs in callmap. Loading arch/arm64/kernel/acpi.c +0 −124 Original line number Diff line number Diff line Loading @@ -36,12 +36,6 @@ EXPORT_SYMBOL(acpi_disabled); int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ EXPORT_SYMBOL(acpi_pci_disabled); /* Processors with enabled flag and sane MPIDR */ static int enabled_cpus; /* Boot CPU is valid or not in MADT */ static bool bootcpu_valid __initdata; static bool param_acpi_off __initdata; static bool param_acpi_force __initdata; Loading Loading @@ -95,124 +89,6 @@ void __init __acpi_unmap_table(char *map, unsigned long size) early_memunmap(map, size); } /** * acpi_map_gic_cpu_interface - generates a logical cpu number * and map to MPIDR represented by GICC structure */ static void __init acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor) { int i; u64 mpidr = processor->arm_mpidr & MPIDR_HWID_BITMASK; bool enabled = !!(processor->flags & ACPI_MADT_ENABLED); if (mpidr == INVALID_HWID) { pr_info("Skip MADT cpu entry with invalid MPIDR\n"); return; } total_cpus++; if (!enabled) return; if (enabled_cpus >= NR_CPUS) { pr_warn("NR_CPUS limit of %d reached, Processor %d/0x%llx ignored.\n", NR_CPUS, total_cpus, mpidr); return; } /* Check if GICC structure of boot CPU is available in the MADT */ if (cpu_logical_map(0) == mpidr) { if (bootcpu_valid) { pr_err("Firmware bug, duplicate CPU MPIDR: 0x%llx in MADT\n", mpidr); return; } bootcpu_valid = true; } /* * Duplicate MPIDRs are a recipe for disaster. Scan * all initialized entries and check for * duplicates. If any is found just ignore the CPU. */ for (i = 1; i < enabled_cpus; i++) { if (cpu_logical_map(i) == mpidr) { pr_err("Firmware bug, duplicate CPU MPIDR: 0x%llx in MADT\n", mpidr); return; } } if (!acpi_psci_present()) return; cpu_ops[enabled_cpus] = cpu_get_ops("psci"); /* CPU 0 was already initialized */ if (enabled_cpus) { if (!cpu_ops[enabled_cpus]) return; if (cpu_ops[enabled_cpus]->cpu_init(NULL, enabled_cpus)) return; /* map the logical cpu id to cpu MPIDR */ cpu_logical_map(enabled_cpus) = mpidr; } enabled_cpus++; } static int __init acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header, const unsigned long end) { struct acpi_madt_generic_interrupt *processor; processor = (struct acpi_madt_generic_interrupt *)header; if (BAD_MADT_ENTRY(processor, end)) return -EINVAL; acpi_table_print_madt_entry(header); acpi_map_gic_cpu_interface(processor); return 0; } /* Parse GIC cpu interface entries in MADT for SMP init */ void __init acpi_init_cpus(void) { int count, i; /* * do a partial walk of MADT to determine how many CPUs * we have including disabled CPUs, and get information * we need for SMP init */ count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, acpi_parse_gic_cpu_interface, 0); if (!count) { pr_err("No GIC CPU interface entries present\n"); return; } else if (count < 0) { pr_err("Error parsing GIC CPU interface entry\n"); return; } if (!bootcpu_valid) { pr_err("MADT missing boot CPU MPIDR, not enabling secondaries\n"); return; } for (i = 0; i < enabled_cpus; i++) set_cpu_possible(i, true); /* Make boot-up look pretty */ pr_info("%d CPUs enabled, %d CPUs total\n", enabled_cpus, total_cpus); } /* * acpi_fadt_sanity_check() - Check FADT presence and carry out sanity * checks on it Loading arch/arm64/kernel/cpu_ops.c +44 −28 Original line number Diff line number Diff line Loading @@ -16,11 +16,13 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <asm/cpu_ops.h> #include <asm/smp_plat.h> #include <linux/acpi.h> #include <linux/errno.h> #include <linux/of.h> #include <linux/string.h> #include <asm/acpi.h> #include <asm/cpu_ops.h> #include <asm/smp_plat.h> extern const struct cpu_operations smp_spin_table_ops; extern const struct cpu_operations cpu_psci_ops; Loading @@ -35,7 +37,7 @@ static const struct cpu_operations *supported_cpu_ops[] __initconst = { NULL, }; const struct cpu_operations * __init cpu_get_ops(const char *name) static const struct cpu_operations * __init cpu_get_ops(const char *name) { const struct cpu_operations **ops = supported_cpu_ops; Loading @@ -49,39 +51,53 @@ const struct cpu_operations * __init cpu_get_ops(const char *name) return NULL; } /* * Read a cpu's enable method from the device tree and record it in cpu_ops. */ int __init cpu_read_ops(struct device_node *dn, int cpu) static const char *__init cpu_read_enable_method(int cpu) { const char *enable_method = of_get_property(dn, "enable-method", NULL); const char *enable_method; if (acpi_disabled) { struct device_node *dn = of_get_cpu_node(cpu, NULL); if (!dn) { if (!cpu) pr_err("Failed to find device node for boot cpu\n"); return NULL; } enable_method = of_get_property(dn, "enable-method", NULL); if (!enable_method) { /* * The boot CPU may not have an enable method (e.g. when * spin-table is used for secondaries). Don't warn spuriously. * The boot CPU may not have an enable method (e.g. * when spin-table is used for secondaries). * Don't warn spuriously. */ if (cpu != 0) pr_err("%s: missing enable-method property\n", dn->full_name); return -ENOENT; } } else { enable_method = acpi_get_enable_method(cpu); if (!enable_method) pr_err("Unsupported ACPI enable-method\n"); } return enable_method; } /* * Read a cpu's enable method and record it in cpu_ops. */ int __init cpu_read_ops(int cpu) { const char *enable_method = cpu_read_enable_method(cpu); if (!enable_method) return -ENODEV; cpu_ops[cpu] = cpu_get_ops(enable_method); if (!cpu_ops[cpu]) { pr_warn("%s: unsupported enable-method property: %s\n", dn->full_name, enable_method); pr_warn("Unsupported enable-method: %s\n", enable_method); return -EOPNOTSUPP; } return 0; } void __init cpu_read_bootcpu_ops(void) { struct device_node *dn = of_get_cpu_node(0, NULL); if (!dn) { pr_err("Failed to find device node for boot cpu\n"); return; } cpu_read_ops(dn, 0); } Loading
arch/arm64/include/asm/acpi.h +4 −0 Original line number Diff line number Diff line Loading @@ -93,4 +93,8 @@ static inline bool acpi_psci_use_hvc(void) { return false; } static inline void acpi_init_cpus(void) { } #endif /* CONFIG_ACPI */ static inline const char *acpi_get_enable_method(int cpu) { return acpi_psci_present() ? "psci" : NULL; } #endif /*_ASM_ACPI_H*/
arch/arm64/include/asm/cpu_ops.h +15 −12 Original line number Diff line number Diff line Loading @@ -19,15 +19,15 @@ #include <linux/init.h> #include <linux/threads.h> struct device_node; /** * struct cpu_operations - Callback operations for hotplugging CPUs. * * @name: Name of the property as appears in a devicetree cpu node's * enable-method property. * @cpu_init: Reads any data necessary for a specific enable-method from the * devicetree, for a given cpu node and proposed logical id. * enable-method property. On systems booting with ACPI, @name * identifies the struct cpu_operations entry corresponding to * the boot protocol specified in the ACPI MADT table. * @cpu_init: Reads any data necessary for a specific enable-method for a * proposed logical id. * @cpu_prepare: Early one-time preparation step for a cpu. If there is a * mechanism for doing so, tests whether it is possible to boot * the given CPU. Loading @@ -40,15 +40,15 @@ struct device_node; * @cpu_die: Makes a cpu leave the kernel. Must not fail. Called from the * cpu being killed. * @cpu_kill: Ensures a cpu has left the kernel. Called from another cpu. * @cpu_init_idle: Reads any data necessary to initialize CPU idle states from * devicetree, for a given cpu node and proposed logical id. * @cpu_init_idle: Reads any data necessary to initialize CPU idle states for * a proposed logical id. * @cpu_suspend: Suspends a cpu and saves the required context. May fail owing * to wrong parameters or error conditions. Called from the * CPU being suspended. Must be called with IRQs disabled. */ struct cpu_operations { const char *name; int (*cpu_init)(struct device_node *, unsigned int); int (*cpu_init)(unsigned int); int (*cpu_prepare)(unsigned int); int (*cpu_boot)(unsigned int); void (*cpu_postboot)(void); Loading @@ -58,14 +58,17 @@ struct cpu_operations { int (*cpu_kill)(unsigned int cpu); #endif #ifdef CONFIG_CPU_IDLE int (*cpu_init_idle)(struct device_node *, unsigned int); int (*cpu_init_idle)(unsigned int); int (*cpu_suspend)(unsigned long); #endif }; extern const struct cpu_operations *cpu_ops[NR_CPUS]; int __init cpu_read_ops(struct device_node *dn, int cpu); void __init cpu_read_bootcpu_ops(void); const struct cpu_operations *cpu_get_ops(const char *name); int __init cpu_read_ops(int cpu); static inline void __init cpu_read_bootcpu_ops(void) { cpu_read_ops(0); } #endif /* ifndef __ASM_CPU_OPS_H */
arch/arm64/include/asm/smp.h +1 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ extern void handle_IPI(int ipinr, struct pt_regs *regs); * Discover the set of possible CPUs and determine their * SMP operations. */ extern void of_smp_init_cpus(void); extern void smp_init_cpus(void); /* * Provide a function to raise an IPI cross call on CPUs in callmap. Loading
arch/arm64/kernel/acpi.c +0 −124 Original line number Diff line number Diff line Loading @@ -36,12 +36,6 @@ EXPORT_SYMBOL(acpi_disabled); int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ EXPORT_SYMBOL(acpi_pci_disabled); /* Processors with enabled flag and sane MPIDR */ static int enabled_cpus; /* Boot CPU is valid or not in MADT */ static bool bootcpu_valid __initdata; static bool param_acpi_off __initdata; static bool param_acpi_force __initdata; Loading Loading @@ -95,124 +89,6 @@ void __init __acpi_unmap_table(char *map, unsigned long size) early_memunmap(map, size); } /** * acpi_map_gic_cpu_interface - generates a logical cpu number * and map to MPIDR represented by GICC structure */ static void __init acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor) { int i; u64 mpidr = processor->arm_mpidr & MPIDR_HWID_BITMASK; bool enabled = !!(processor->flags & ACPI_MADT_ENABLED); if (mpidr == INVALID_HWID) { pr_info("Skip MADT cpu entry with invalid MPIDR\n"); return; } total_cpus++; if (!enabled) return; if (enabled_cpus >= NR_CPUS) { pr_warn("NR_CPUS limit of %d reached, Processor %d/0x%llx ignored.\n", NR_CPUS, total_cpus, mpidr); return; } /* Check if GICC structure of boot CPU is available in the MADT */ if (cpu_logical_map(0) == mpidr) { if (bootcpu_valid) { pr_err("Firmware bug, duplicate CPU MPIDR: 0x%llx in MADT\n", mpidr); return; } bootcpu_valid = true; } /* * Duplicate MPIDRs are a recipe for disaster. Scan * all initialized entries and check for * duplicates. If any is found just ignore the CPU. */ for (i = 1; i < enabled_cpus; i++) { if (cpu_logical_map(i) == mpidr) { pr_err("Firmware bug, duplicate CPU MPIDR: 0x%llx in MADT\n", mpidr); return; } } if (!acpi_psci_present()) return; cpu_ops[enabled_cpus] = cpu_get_ops("psci"); /* CPU 0 was already initialized */ if (enabled_cpus) { if (!cpu_ops[enabled_cpus]) return; if (cpu_ops[enabled_cpus]->cpu_init(NULL, enabled_cpus)) return; /* map the logical cpu id to cpu MPIDR */ cpu_logical_map(enabled_cpus) = mpidr; } enabled_cpus++; } static int __init acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header, const unsigned long end) { struct acpi_madt_generic_interrupt *processor; processor = (struct acpi_madt_generic_interrupt *)header; if (BAD_MADT_ENTRY(processor, end)) return -EINVAL; acpi_table_print_madt_entry(header); acpi_map_gic_cpu_interface(processor); return 0; } /* Parse GIC cpu interface entries in MADT for SMP init */ void __init acpi_init_cpus(void) { int count, i; /* * do a partial walk of MADT to determine how many CPUs * we have including disabled CPUs, and get information * we need for SMP init */ count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, acpi_parse_gic_cpu_interface, 0); if (!count) { pr_err("No GIC CPU interface entries present\n"); return; } else if (count < 0) { pr_err("Error parsing GIC CPU interface entry\n"); return; } if (!bootcpu_valid) { pr_err("MADT missing boot CPU MPIDR, not enabling secondaries\n"); return; } for (i = 0; i < enabled_cpus; i++) set_cpu_possible(i, true); /* Make boot-up look pretty */ pr_info("%d CPUs enabled, %d CPUs total\n", enabled_cpus, total_cpus); } /* * acpi_fadt_sanity_check() - Check FADT presence and carry out sanity * checks on it Loading
arch/arm64/kernel/cpu_ops.c +44 −28 Original line number Diff line number Diff line Loading @@ -16,11 +16,13 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <asm/cpu_ops.h> #include <asm/smp_plat.h> #include <linux/acpi.h> #include <linux/errno.h> #include <linux/of.h> #include <linux/string.h> #include <asm/acpi.h> #include <asm/cpu_ops.h> #include <asm/smp_plat.h> extern const struct cpu_operations smp_spin_table_ops; extern const struct cpu_operations cpu_psci_ops; Loading @@ -35,7 +37,7 @@ static const struct cpu_operations *supported_cpu_ops[] __initconst = { NULL, }; const struct cpu_operations * __init cpu_get_ops(const char *name) static const struct cpu_operations * __init cpu_get_ops(const char *name) { const struct cpu_operations **ops = supported_cpu_ops; Loading @@ -49,39 +51,53 @@ const struct cpu_operations * __init cpu_get_ops(const char *name) return NULL; } /* * Read a cpu's enable method from the device tree and record it in cpu_ops. */ int __init cpu_read_ops(struct device_node *dn, int cpu) static const char *__init cpu_read_enable_method(int cpu) { const char *enable_method = of_get_property(dn, "enable-method", NULL); const char *enable_method; if (acpi_disabled) { struct device_node *dn = of_get_cpu_node(cpu, NULL); if (!dn) { if (!cpu) pr_err("Failed to find device node for boot cpu\n"); return NULL; } enable_method = of_get_property(dn, "enable-method", NULL); if (!enable_method) { /* * The boot CPU may not have an enable method (e.g. when * spin-table is used for secondaries). Don't warn spuriously. * The boot CPU may not have an enable method (e.g. * when spin-table is used for secondaries). * Don't warn spuriously. */ if (cpu != 0) pr_err("%s: missing enable-method property\n", dn->full_name); return -ENOENT; } } else { enable_method = acpi_get_enable_method(cpu); if (!enable_method) pr_err("Unsupported ACPI enable-method\n"); } return enable_method; } /* * Read a cpu's enable method and record it in cpu_ops. */ int __init cpu_read_ops(int cpu) { const char *enable_method = cpu_read_enable_method(cpu); if (!enable_method) return -ENODEV; cpu_ops[cpu] = cpu_get_ops(enable_method); if (!cpu_ops[cpu]) { pr_warn("%s: unsupported enable-method property: %s\n", dn->full_name, enable_method); pr_warn("Unsupported enable-method: %s\n", enable_method); return -EOPNOTSUPP; } return 0; } void __init cpu_read_bootcpu_ops(void) { struct device_node *dn = of_get_cpu_node(0, NULL); if (!dn) { pr_err("Failed to find device node for boot cpu\n"); return; } cpu_read_ops(dn, 0); }