diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index 0705663ba97832f2f9864f690b55664e5a05753e..f364115ac2efecd3deb1dee7d426709201f89d90 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -113,6 +113,10 @@ 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); +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) { } diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index 867b7ce82cc7d7e8be29f77897582d842367780d..879b9155b7b4a0832ddad332c5e32b7ac6ee71ab 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -426,6 +426,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