[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250822153048.2287-6-james.morse@arm.com>
Date: Fri, 22 Aug 2025 15:29:46 +0000
From: James Morse <james.morse@....com>
To: linux-kernel@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org,
linux-acpi@...r.kernel.org,
devicetree@...r.kernel.org
Cc: James Morse <james.morse@....com>,
shameerali.kolothum.thodi@...wei.com,
D Scott Phillips OS <scott@...amperecomputing.com>,
carl@...amperecomputing.com,
lcherian@...vell.com,
bobo.shaobowang@...wei.com,
tan.shaopeng@...itsu.com,
baolin.wang@...ux.alibaba.com,
Jamie Iles <quic_jiles@...cinc.com>,
Xin Hao <xhao@...ux.alibaba.com>,
peternewman@...gle.com,
dfustini@...libre.com,
amitsinght@...vell.com,
David Hildenbrand <david@...hat.com>,
Rex Nie <rex.nie@...uarmicro.com>,
Dave Martin <dave.martin@....com>,
Koba Ko <kobak@...dia.com>,
Shanker Donthineni <sdonthineni@...dia.com>,
fenghuay@...dia.com,
baisheng.gao@...soc.com,
Jonathan Cameron <jonathan.cameron@...wei.com>,
Rob Herring <robh@...nel.org>,
Rohit Mathew <rohit.mathew@....com>,
Rafael Wysocki <rafael@...nel.org>,
Len Brown <lenb@...nel.org>,
Lorenzo Pieralisi <lpieralisi@...nel.org>,
Hanjun Guo <guohanjun@...wei.com>,
Sudeep Holla <sudeep.holla@....com>,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>,
Catalin Marinas <catalin.marinas@....com>,
Will Deacon <will@...nel.org>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Danilo Krummrich <dakr@...nel.org>
Subject: [PATCH 05/33] ACPI / PPTT: Find cache level by cache-id
The MPAM table identifies caches by id. The MPAM driver also wants to know
the cache level to determine if the platform is of the shape that can be
managed via resctrl. Cacheinfo has this information, but only for CPUs that
are online.
Waiting for all CPUs to come online is a problem for platforms where
CPUs are brought online late by user-space.
Add a helper that walks every possible cache, until it finds the one
identified by cache-id, then return the level.
Add a cleanup based free-ing mechanism for acpi_get_table().
CC: Jonathan Cameron <jonathan.cameron@...wei.com>
Signed-off-by: James Morse <james.morse@....com>
---
Changes since RFC:
* acpi_count_levels() now returns a value.
* Converted the table-get stuff to use Jonathan's cleanup helper.
* Dropped Sudeep's Review tag due to the cleanup change.
---
drivers/acpi/pptt.c | 64 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/acpi.h | 17 ++++++++++++
2 files changed, 81 insertions(+)
diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
index 8f9b9508acba..660457644a5b 100644
--- a/drivers/acpi/pptt.c
+++ b/drivers/acpi/pptt.c
@@ -907,3 +907,67 @@ int find_acpi_cpu_topology_hetero_id(unsigned int cpu)
return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE,
ACPI_PPTT_ACPI_IDENTICAL);
}
+
+/**
+ * find_acpi_cache_level_from_id() - Get the level of the specified cache
+ * @cache_id: The id field of the unified cache
+ *
+ * Determine the level relative to any CPU for the unified cache identified by
+ * cache_id. This allows the property to be found even if the CPUs are offline.
+ *
+ * The returned level can be used to group unified caches that are peers.
+ *
+ * The PPTT table must be rev 3 or later,
+ *
+ * If one CPUs L2 is shared with another as L3, this function will return
+ * an unpredictable value.
+ *
+ * Return: -ENOENT if the PPTT doesn't exist, or the cache cannot be found.
+ * Otherwise returns a value which represents the level of the specified cache.
+ */
+int find_acpi_cache_level_from_id(u32 cache_id)
+{
+ u32 acpi_cpu_id;
+ int level, cpu, num_levels;
+ struct acpi_pptt_cache *cache;
+ struct acpi_pptt_cache_v1 *cache_v1;
+ struct acpi_pptt_processor *cpu_node;
+ struct acpi_table_header *table __free(acpi_table) = acpi_get_table_ret(ACPI_SIG_PPTT, 0);
+
+ if (IS_ERR(table))
+ return PTR_ERR(table);
+
+ if (table->revision < 3)
+ return -ENOENT;
+
+ /*
+ * If we found the cache first, we'd still need to walk from each CPU
+ * to find the level...
+ */
+ for_each_possible_cpu(cpu) {
+ acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+ cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
+ if (!cpu_node)
+ return -ENOENT;
+ num_levels = acpi_count_levels(table, cpu_node, NULL);
+
+ /* Start at 1 for L1 */
+ for (level = 1; level <= num_levels; level++) {
+ cache = acpi_find_cache_node(table, acpi_cpu_id,
+ ACPI_PPTT_CACHE_TYPE_UNIFIED,
+ level, &cpu_node);
+ if (!cache)
+ continue;
+
+ cache_v1 = ACPI_ADD_PTR(struct acpi_pptt_cache_v1,
+ cache,
+ sizeof(struct acpi_pptt_cache));
+
+ if (cache->flags & ACPI_PPTT_CACHE_ID_VALID &&
+ cache_v1->cache_id == cache_id)
+ return level;
+ }
+ }
+
+ return -ENOENT;
+}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index f97a9ff678cc..30c10b1dcdb2 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -8,6 +8,7 @@
#ifndef _LINUX_ACPI_H
#define _LINUX_ACPI_H
+#include <linux/cleanup.h>
#include <linux/errno.h>
#include <linux/ioport.h> /* for struct resource */
#include <linux/resource_ext.h>
@@ -221,6 +222,17 @@ void acpi_reserve_initial_tables (void);
void acpi_table_init_complete (void);
int acpi_table_init (void);
+static inline struct acpi_table_header *acpi_get_table_ret(char *signature, u32 instance)
+{
+ struct acpi_table_header *table;
+ int status = acpi_get_table(signature, instance, &table);
+
+ if (ACPI_FAILURE(status))
+ return ERR_PTR(-ENOENT);
+ return table;
+}
+DEFINE_FREE(acpi_table, struct acpi_table_header *, if (!IS_ERR(_T)) acpi_put_table(_T))
+
int acpi_table_parse(char *id, acpi_tbl_table_handler handler);
int __init_or_acpilib acpi_table_parse_entries(char *id,
unsigned long table_size, int entry_id,
@@ -1542,6 +1554,7 @@ int find_acpi_cpu_topology_cluster(unsigned int cpu);
int find_acpi_cpu_topology_package(unsigned int cpu);
int find_acpi_cpu_topology_hetero_id(unsigned int cpu);
void acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id, cpumask_t *cpus);
+int find_acpi_cache_level_from_id(u32 cache_id);
#else
static inline int acpi_pptt_cpu_is_thread(unsigned int cpu)
{
@@ -1565,6 +1578,10 @@ static inline int find_acpi_cpu_topology_hetero_id(unsigned int cpu)
}
static inline void acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id,
cpumask_t *cpus) { }
+static inline int find_acpi_cache_level_from_id(u32 cache_id)
+{
+ return -EINVAL;
+}
#endif
void acpi_arch_init(void);
--
2.20.1
Powered by blists - more mailing lists