The ACPI PPTT ID structure (see 6.2 spec, section 5.2.29.3) allows the vendor to provide an identifier (or vendor specific part number) for a particular processor hierarchy node structure. That may be a processor identifier for a processor node, or some chip identifier for a processor package node. In some circumstances it can be useful to learn the SoC package identifiers in the system. An example is in [0], where the userspace perf tool needs to know the SoC identifier for certain per-SoC event matching. So for this purpose, add an API to get ID structure members for a processor package node index, which may be used by some driver to expose this info to userspace. The ID structure table has a number of fields, which are left open to interpretation per implementation. However the spec does provide reference examples of how the fields could be used. As such, just provide the table fields directly in the API, which the caller may interpret (probably as per spec example). https://lore.kernel.org/linux-arm-kernel/1579876505-113251-6-git-send-email-john.garry@xxxxxxxxxx/ Signed-off-by: John Garry <john.garry@xxxxxxxxxx> --- drivers/acpi/pptt.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 13 +++++++ 2 files changed, 94 insertions(+) diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index f31544d3656e..ea4ed6300d0b 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -760,3 +760,84 @@ int find_acpi_cpu_topology_hetero_id(unsigned int cpu) return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE, ACPI_PPTT_ACPI_IDENTICAL); } + +/** + * acpi_pptt_get_package_info() - Get processor package information + * @index: Index into processor package + * @info: Pointer to structure to fill in processor package info + * + * For a particular processor package index, fill in the acpi_pptt_package_info + * structure. + * + * Return: -ENOENT if the PPTT or processor package index doesn't exist, + * -EINVAL for invalid arguments, 0 for success. + */ +int acpi_pptt_get_package_info(int index, struct acpi_pptt_package_info *info) +{ + struct acpi_subtable_header *entry; + struct acpi_table_header *table; + unsigned long table_end; + acpi_status status; + int ret, count = 0; + + if (!info) + return -EINVAL; + + status = acpi_get_table(ACPI_SIG_PPTT, 0, &table); + if (ACPI_FAILURE(status)) { + acpi_pptt_warn_missing(); + return -ENOENT; + } + + table_end = (unsigned long)table + table->length; + entry = ACPI_ADD_PTR(struct acpi_subtable_header, table, + sizeof(struct acpi_table_pptt)); + + ret = -ENOENT; + while (entry) { + struct acpi_pptt_processor *cpu_node; + + cpu_node = (struct acpi_pptt_processor *)entry; + + if (entry->type == ACPI_PPTT_TYPE_PROCESSOR && + cpu_node->flags & ACPI_PPTT_PHYSICAL_PACKAGE) { + int cnt = cpu_node->number_of_priv_resources; + int i; + + for (i = 0; i < cnt; i++) { + struct acpi_subtable_header *r; + + r = acpi_get_pptt_resource(table, cpu_node, i); + + if (r->type == ACPI_PPTT_TYPE_ID && + count == index) { + struct acpi_pptt_id *id; + + id = (struct acpi_pptt_id *)r; + info->LEVEL_2_ID = + le64_to_cpu(id->level2_id); + info->vendor_id = + le32_to_cpu(id->vendor_id); + + ret = 0; + goto out; + } + + if (r->type == ACPI_PPTT_TYPE_ID) + count++; + } + } + + entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry, + entry->length); + if ((unsigned long)entry >= table_end) + break; + } + +out: + acpi_put_table(table); + + return ret; + +} +EXPORT_SYMBOL_GPL(acpi_pptt_get_package_info); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 0f37a7d5fa77..0a911a298731 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -1268,13 +1268,26 @@ static inline int lpit_read_residency_count_address(u64 *address) } #endif +struct acpi_pptt_package_info { + u64 LEVEL_2_ID; + u32 vendor_id; +}; + #ifdef CONFIG_ACPI_PPTT int acpi_pptt_cpu_is_thread(unsigned int cpu); int find_acpi_cpu_topology(unsigned int cpu, int level); int find_acpi_cpu_topology_package(unsigned int cpu); int find_acpi_cpu_topology_hetero_id(unsigned int cpu); int find_acpi_cpu_cache_topology(unsigned int cpu, int level); +int acpi_pptt_get_package_info(int index, struct acpi_pptt_package_info *info); #else +static inline int acpi_pptt_get_package_info(int index, + struct acpi_pptt_package_info *info); +{ + return -EINVAL; + +} + static inline int acpi_pptt_cpu_is_thread(unsigned int cpu) { return -EINVAL; -- 2.17.1