[PATCH RFC 1/2] ACPI/PPTT: Add acpi_pptt_get_package_info() API

From: John Garry
Date: Tue Jan 28 2020 - 06:20:38 EST


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