diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index bd68e1b7f29f34552b9e4decd2c430a6d3916c43..df0ef7ec5b5b691d53cf01d1b9e7faa8cb8dadbf 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -100,6 +100,11 @@ static inline u32 get_acpi_id_for_cpu(unsigned int cpu) static inline void arch_fix_phys_package_id(int num, u32 slot) { } void __init acpi_init_cpus(void); int apei_claim_sea(struct pt_regs *regs); +void acpi_pptt_find_min_physid_cpu_node(struct acpi_table_header *table_hdr, + struct acpi_pptt_processor *cpu_node, + phys_cpuid_t *min_physid, + struct acpi_pptt_processor **min_cpu_node); + #else static inline void acpi_init_cpus(void) { } static inline int apei_claim_sea(struct pt_regs *regs) { return -ENOENT; } diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index afa7ddfdf10d6acacac846693d48b71bfb0e883b..8eddddc5afcc50567e10219b8f08667b416f45b8 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -430,6 +430,61 @@ static struct acpi_pptt_cache *acpi_find_cache_node(struct acpi_table_header *ta return found; } +/** + * acpi_pptt_min_physid_from_cpu_node() - Recursivly find @min_physid for all + * leaf CPUs below @cpu_node. + * @table_hdr: Pointer to the head of the PPTT table + * @cpu_node: The point in the toplogy to start the walk + * @min_physid: The min_physid to update with leaf CPUs. + * @min_cpu_node: The min_cpu_node to update with leaf CPUs. + */ +void acpi_pptt_find_min_physid_cpu_node(struct acpi_table_header *table_hdr, + struct acpi_pptt_processor *cpu_node, + phys_cpuid_t *min_physid, + struct acpi_pptt_processor **min_cpu_node) +{ + bool leaf = true; + u32 acpi_processor_id; + phys_cpuid_t cpu_node_phys_id; + struct acpi_subtable_header *iter; + struct acpi_pptt_processor *iter_node = NULL; + u32 target_node = ACPI_PTR_DIFF(cpu_node, table_hdr); + u32 proc_sz = sizeof(struct acpi_pptt_processor *); + unsigned long table_end = (unsigned long)table_hdr + table_hdr->length; + + /* + * Walk the PPTT, looking for nodes that reference cpu_node + * as parent. + */ + iter = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr, + sizeof(struct acpi_table_pptt)); + + while ((unsigned long)iter + proc_sz < table_end) { + iter_node = (struct acpi_pptt_processor *)iter; + + if (iter->type == ACPI_PPTT_TYPE_PROCESSOR && + iter_node->parent == target_node) { + leaf = false; + acpi_pptt_find_min_physid_cpu_node(table_hdr, iter_node, + min_physid, min_cpu_node); + } + + if (iter->length == 0) + return; + iter = ACPI_ADD_PTR(struct acpi_subtable_header, iter, + iter->length); + } + + acpi_processor_id = cpu_node->acpi_processor_id; + cpu_node_phys_id = acpi_id_to_phys_cpuid(acpi_processor_id); + if (!invalid_phys_cpuid(cpu_node_phys_id) && + *min_physid > cpu_node_phys_id && + leaf == true) { + *min_physid = cpu_node_phys_id; + *min_cpu_node = cpu_node; + } +} + /** * update_cache_properties() - Update cacheinfo for the given processor * @this_leaf: Kernel cache info structure being updated