[PATCH v2 3/8] ACPI: CPPC: Refactor resource cleanup into free_reg_resource()
Lifeng Zheng <[email protected]> Tue, 4 Aug 2026 16:50:37 +0800
| Newsgroups | gmane.linux.acpi.devel,gmane.linux.kernel,gmane.linux.power-management.general |
|---|---|
| Message-ID | <[email protected]> |
Both the error path of acpi_cppc_processor_probe() and the normal cleanup in acpi_cppc_processor_exit() iterate over the cpc_regs[] array and iounmap() any SystemMemory virtual addresses that were set up during probe. CPPC v4 adds Package-type entries that own dynamically allocated sub-elements which also need to be freed. Inlining this recursive cleanup at every call-site would be error-prone and repetitive. Extract the per-register cleanup logic into free_reg_resource(), which releases any iomapped address and, for Package-type entries, recursively frees all child elements and the elements array itself. Convert both the probe error path and _exit() to use the new helper. No functional change for existing Integer / Buffer entries. Signed-off-by: Lifeng Zheng <[email protected]> --- drivers/acpi/cppc_acpi.c | 41 ++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index c4f9fed66fa0..da8399efc6a6 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -753,6 +753,30 @@ static int parse_cpc_element(union acpi_object *cpc_obj, return 0; } +/** + * free_reg_resource - Free resources held by a CPC register resource. + * @cpc_reg: Pointer to the CPC register resource to clean up. + * + * Releases any iomapped SystemMemory address and, for Package-type + * resources, recursively frees all nested elements before freeing the + * elements array itself. + */ +static void free_reg_resource(struct cpc_register_resource *cpc_reg) +{ + void __iomem *addr = cpc_reg->sys_mem_vaddr; + int i; + + if (addr) + iounmap(addr); + + if (cpc_reg->type == ACPI_TYPE_PACKAGE) { + for (i = 0; i < cpc_reg->cpc_entry.package.count; i++) + free_reg_resource(&cpc_reg->cpc_entry.package.elements[i]); + + kfree(cpc_reg->cpc_entry.package.elements); + } +} + /* * An example CPC table looks like the following. * @@ -965,12 +989,9 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) out_free: /* Free all the mapped sys mem areas for this CPU */ - for (i = 2; i < cpc_ptr->num_entries; i++) { - void __iomem *addr = cpc_ptr->cpc_regs[i-2].sys_mem_vaddr; + for (i = 2; i < cpc_ptr->num_entries; i++) + free_reg_resource(&cpc_ptr->cpc_regs[i-2]); - if (addr) - iounmap(addr); - } kfree(cpc_ptr); out_buf_free: @@ -989,7 +1010,6 @@ void acpi_cppc_processor_exit(struct acpi_processor *pr) { struct cpc_desc *cpc_ptr; unsigned int i; - void __iomem *addr; int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, pr->id); if (pcc_ss_id >= 0 && pcc_data[pcc_ss_id]) { @@ -1007,12 +1027,9 @@ void acpi_cppc_processor_exit(struct acpi_processor *pr) if (!cpc_ptr) return; - /* Free all the mapped sys mem areas for this CPU */ - for (i = 2; i < cpc_ptr->num_entries; i++) { - addr = cpc_ptr->cpc_regs[i-2].sys_mem_vaddr; - if (addr) - iounmap(addr); - } + /* Free all the mapped sys mem areas and nested package resources for this CPU */ + for (i = 2; i < cpc_ptr->num_entries; i++) + free_reg_resource(&cpc_ptr->cpc_regs[i-2]); kobject_put(&cpc_ptr->kobj); kfree(cpc_ptr); -- 2.33.0