From: Christian Loehle <christian.loehle@arm.com>
To: "Rafael J . Wysocki" <rafael@kernel.org>,
Viresh Kumar <viresh.kumar@linaro.org>
Cc: linux-pm@vger.kernel.org, linux-acpi@vger.kernel.org,
linux-kernel@vger.kernel.org, Len Brown <lenb@kernel.org>,
Jie Zhan <zhanjie9@hisilicon.com>,
Lifeng Zheng <zhenglifeng1@huawei.com>,
Pierre Gondois <pierre.gondois@arm.com>,
Sumit Gupta <sumitg@nvidia.com>,
Sudeep Holla <sudeep.holla@arm.com>,
Ionela Voinescu <ionela.voinescu@arm.com>,
zhongqiu.han@oss.qualcomm.com,
Christian Loehle <christian.loehle@arm.com>
Subject: [PATCH v3 08/15] ACPI: CPPC: Release PCC data after probe failures
Date: Sun, 9 Aug 2026 07:25:42 +0100 [thread overview]
Message-ID: <20260809062549.1415955-9-christian.loehle@arm.com> (raw)
In-Reply-To: <20260809062549.1415955-1-christian.loehle@arm.com>
pcc_data_alloc() takes a per-processor reference while parsing the first
PCC register. Every later probe failure currently frees the CPC descriptor
without dropping that reference. Depending on where probe fails, this
leaks an unacquired PCC object, an acquired mailbox channel, or an extra
reference to a shared channel.
Factor the teardown into pcc_data_put() so it handles both acquired and
unacquired state, and invoke it on every failure after allocation.
Do not store the temporary pcc_data_alloc() result in the eventual probe
return value. A successful allocation must not make a later parsing failure
run cleanup and then return success.
The per-CPU PCC subspace index is zero-initialized. If probe returns before
assigning it, a later processor exit can consequently drop the reference
for subspace 0 even though this CPU never acquired one. Initialize the
index to -1 before any probe return and only release it from exit after a
CPC descriptor has been published.
Fixes: 85b1407bf6d2 ("ACPI / CPPC: Make CPPC ACPI driver aware of PCC subspace IDs")
Signed-off-by: Christian Loehle <christian.loehle@arm.com>
---
drivers/acpi/cppc_acpi.c | 61 +++++++++++++++++++++++++++-------------
1 file changed, 42 insertions(+), 19 deletions(-)
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index 826e27f61530..ef1f716860b3 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -807,6 +807,24 @@ static int pcc_data_alloc(int pcc_ss_id)
return 0;
}
+static void pcc_data_put(int pcc_ss_id)
+{
+ struct cppc_pcc_data *data;
+
+ if (pcc_ss_id < 0 || pcc_ss_id >= MAX_PCC_SUBSPACES)
+ return;
+
+ data = pcc_data[pcc_ss_id];
+ if (!data || --data->refcount)
+ return;
+
+ if (data->pcc_channel_acquired)
+ pcc_mbox_free_channel(data->pcc_channel);
+
+ kfree(data);
+ pcc_data[pcc_ss_id] = NULL;
+}
+
/*
* An example CPC table looks like the following.
*
@@ -852,8 +870,12 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
acpi_handle handle = pr->handle;
unsigned int num_ent, i, cpc_rev;
int pcc_subspace_id = -1;
+ bool pcc_data_ref = false;
acpi_status status;
int ret = -ENODATA;
+ int err;
+
+ per_cpu(cpu_pcc_subspace_idx, pr->id) = -1;
if (!osc_sb_cppc2_support_acked) {
pr_debug("CPPC v2 _OSC not acked\n");
@@ -986,8 +1008,12 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
if (gas_t->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
if (pcc_subspace_id < 0) {
pcc_subspace_id = gas_t->access_width;
- if (pcc_data_alloc(pcc_subspace_id))
+ err = pcc_data_alloc(pcc_subspace_id);
+ if (err) {
+ ret = err;
goto out_free;
+ }
+ pcc_data_ref = true;
} else if (pcc_subspace_id != gas_t->access_width) {
pr_debug("Mismatched PCC ids in _CPC for CPU:%d\n",
pr->id);
@@ -1140,7 +1166,7 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
if (ret) {
per_cpu(cpc_desc_ptr, pr->id) = NULL;
kobject_put(&cpc_ptr->kobj);
- goto out_buf_free;
+ goto out_pcc_put;
}
kfree(output.pointer);
@@ -1150,6 +1176,11 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
pr_err("CPU%d: failed to initialize _CPC: %d\n", pr->id, ret);
cppc_free_desc(cpc_ptr);
+out_pcc_put:
+ if (pcc_data_ref)
+ pcc_data_put(pcc_subspace_id);
+ per_cpu(cpu_pcc_subspace_idx, pr->id) = -1;
+
out_buf_free:
kfree(output.pointer);
return ret;
@@ -1165,28 +1196,20 @@ EXPORT_SYMBOL_GPL(acpi_cppc_processor_probe);
void acpi_cppc_processor_exit(struct acpi_processor *pr)
{
struct cpc_desc *cpc_ptr;
- int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, pr->id);
+ int pcc_ss_id;
cpc_ptr = per_cpu(cpc_desc_ptr, pr->id);
- if (cpc_ptr) {
- per_cpu(cpc_desc_ptr, pr->id) = NULL;
- kobject_del(&cpc_ptr->kobj);
+ if (!cpc_ptr) {
+ per_cpu(cpu_pcc_subspace_idx, pr->id) = -1;
+ return;
}
- if (pcc_ss_id >= 0 && pcc_data[pcc_ss_id]) {
- if (pcc_data[pcc_ss_id]->pcc_channel_acquired) {
- pcc_data[pcc_ss_id]->refcount--;
- if (!pcc_data[pcc_ss_id]->refcount) {
- pcc_mbox_free_channel(pcc_data[pcc_ss_id]->pcc_channel);
- kfree(pcc_data[pcc_ss_id]);
- pcc_data[pcc_ss_id] = NULL;
- }
- }
- }
- per_cpu(cpu_pcc_subspace_idx, pr->id) = -1;
+ pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, pr->id);
+ per_cpu(cpc_desc_ptr, pr->id) = NULL;
+ kobject_del(&cpc_ptr->kobj);
- if (!cpc_ptr)
- return;
+ pcc_data_put(pcc_ss_id);
+ per_cpu(cpu_pcc_subspace_idx, pr->id) = -1;
kobject_put(&cpc_ptr->kobj);
}
--
2.34.1
next prev parent reply other threads:[~2026-08-09 6:26 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-09 6:25 [PATCH v3 00/15] ACPI: CPPC: Fix register access and lifetime bugs Christian Loehle
2026-08-09 6:25 ` [PATCH v3 01/15] ACPI: CPPC: Validate the _CPC package header Christian Loehle
2026-08-09 6:25 ` [PATCH v3 02/15] ACPI: CPPC: Validate _CPC entry and control semantics Christian Loehle
2026-08-09 6:25 ` [PATCH v3 03/15] ACPI: CPPC: Propagate performance-control write errors Christian Loehle
2026-08-09 6:25 ` [PATCH v3 04/15] ACPI: CPPC: Use 64-bit masks for register fields Christian Loehle
2026-08-09 6:25 ` [PATCH v3 05/15] ACPI: CPPC: Serialize PCC single-register payload updates Christian Loehle
2026-08-09 6:25 ` [PATCH v3 06/15] ACPI: CPPC: Serialize PCC EPP " Christian Loehle
2026-08-09 6:25 ` [PATCH v3 07/15] ACPI: CPPC: Release CPC descriptors through kobject Christian Loehle
2026-08-09 6:25 ` Christian Loehle [this message]
2026-08-09 6:25 ` [PATCH v3 09/15] ACPI: CPPC: Reject unsafe cross-CPU SystemMemory RMW Christian Loehle
2026-08-09 6:25 ` [PATCH v3 10/15] ACPI: CPPC: Reject reads and RMW of write-only controls Christian Loehle
2026-08-09 6:25 ` [PATCH v3 11/15] ACPI: CPPC: Validate and access PCC register layouts Christian Loehle
2026-08-09 6:25 ` [PATCH v3 12/15] ACPI: CPPC: Validate SystemIO " Christian Loehle
2026-08-09 6:25 ` [PATCH v3 13/15] ACPI: CPPC: Validate PCC overlaps across processors Christian Loehle
2026-08-09 6:25 ` [PATCH v3 14/15] ACPI: CPPC: Validate SystemIO " Christian Loehle
2026-08-09 6:25 ` [PATCH v3 15/15] ACPI: CPPC: Clear Performance Limited without a stale read Christian Loehle
2026-08-09 7:01 ` Christian Loehle
2026-08-25 9:15 ` Sumit Gupta
2026-08-25 10:09 ` Christian Loehle
2026-08-09 7:18 ` [PATCH v3 00/15] ACPI: CPPC: Fix register access and lifetime bugs Christian Loehle
2026-08-10 5:15 ` Christian Loehle
2026-08-20 10:07 ` Christian Loehle
2026-08-20 10:31 ` Rafael J. Wysocki (Intel)
2026-08-21 14:39 ` Rafael J. Wysocki (Intel)
2026-08-25 6:58 ` Sumit Gupta
2026-08-25 8:25 ` Christian Loehle
2026-08-25 11:48 ` Rafael J. Wysocki (Intel)
2026-08-25 20:53 ` Sumit Gupta
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260809062549.1415955-9-christian.loehle@arm.com \
--to=christian.loehle@arm.com \
--cc=ionela.voinescu@arm.com \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=pierre.gondois@arm.com \
--cc=rafael@kernel.org \
--cc=sudeep.holla@arm.com \
--cc=sumitg@nvidia.com \
--cc=viresh.kumar@linaro.org \
--cc=zhanjie9@hisilicon.com \
--cc=zhenglifeng1@huawei.com \
--cc=zhongqiu.han@oss.qualcomm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox