[PATCH RFC v3 08/11] ACPI: PPTT: Add acpi_pptt_get_cache_size_from_id helper
Drew Fustini <[email protected]>
| Newsgroups | dev.linux.lists.acpica-devel,org.infradead.lists.linux-riscv,org.kernel.vger.linux-acpi,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Add helper to look up a cache's size from its cache ID in the PPTT table. This is needed by the RISC-V RQSC parser to determine the cache size for CBQRI capacity controllers. The implementation follows the pattern established by find_acpi_cache_level_from_id() and acpi_pptt_get_cpumask_from_cache_id(): uses acpi_get_pptt(), upgrade_pptt_cache(), checks all three cache types, and uses the do/while empty-detection loop. Signed-off-by: Drew Fustini <[email protected]> --- drivers/acpi/pptt.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 8 +++++++ 2 files changed, 71 insertions(+) diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index de5f8c018333..36e375551b43 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -1063,3 +1063,66 @@ int acpi_pptt_get_cpumask_from_cache_id(u32 cache_id, cpumask_t *cpus) return 0; } + +/** + * acpi_pptt_get_cache_size_from_id() - Get the size of the specified cache + * @cache_id: The id field of the cache + * @size: Where to store the cache size in bytes + * + * Determine the size of the cache identified by cache_id. This allows the + * property to be found even if the CPUs are offline. + * + * The PPTT table must be rev 3 or later. + * + * Return: -ENOENT if the PPTT doesn't exist, the revision isn't supported or + * the cache cannot be found. Otherwise returns 0 and sets *size. + */ +int acpi_pptt_get_cache_size_from_id(u32 cache_id, u32 *size) +{ + int cpu; + struct acpi_table_header *table; + + table = acpi_get_pptt(); + if (!table) + return -ENOENT; + + if (table->revision < 3) + return -ENOENT; + + for_each_possible_cpu(cpu) { + bool empty; + int level = 1; + u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu); + struct acpi_pptt_processor *cpu_node; + + cpu_node = acpi_find_processor_node(table, acpi_cpu_id); + if (!cpu_node) + continue; + + do { + int cache_type[] = {CACHE_TYPE_INST, CACHE_TYPE_DATA, CACHE_TYPE_UNIFIED}; + + empty = true; + for (int i = 0; i < ARRAY_SIZE(cache_type); i++) { + struct acpi_pptt_cache *cache; + struct acpi_pptt_cache_v1_full *cache_v1; + + cache = acpi_find_cache_node(table, acpi_cpu_id, cache_type[i], + level, &cpu_node); + if (!cache) + continue; + + empty = false; + + cache_v1 = upgrade_pptt_cache(cache); + if (cache_v1 && cache_v1->cache_id == cache_id) { + *size = cache->size; + return 0; + } + } + level++; + } while (!empty); + } + + return -ENOENT; +} diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 4d2f0bed7a06..0596ec18f522 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -1547,6 +1547,7 @@ 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); +int acpi_pptt_get_cache_size_from_id(u32 cache_id, u32 *size); int acpi_pptt_get_cpumask_from_cache_id(u32 cache_id, cpumask_t *cpus); #else static inline int acpi_pptt_cpu_is_thread(unsigned int cpu) @@ -1571,10 +1572,17 @@ 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 -ENOENT; } + +static inline int acpi_pptt_get_cache_size_from_id(u32 cache_id, u32 *size) +{ + return -ENOENT; +} + static inline int acpi_pptt_get_cpumask_from_cache_id(u32 cache_id, cpumask_t *cpus) { -- 2.43.0