summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMukesh Ojha <mukesh.ojha@oss.qualcomm.com>2026-07-24 15:19:38 +0530
committerBjorn Andersson <andersson@kernel.org>2026-07-30 16:31:34 -0500
commitb697b20cea4374d27e2134da4bb7b0ea39f36c8b (patch)
tree291244ae13017cabd5e434e71c75275b7a206433
parent966d23c7e68ea32679275a7e3d2383181002c868 (diff)
firmware: qcom: scm: Fix reserved memory cleanup on probe failure
of_reserved_mem_device_init() adds an entry to a global list with no devres counterpart. If qcom_scm_probe() fails after the call the assignment is never cleaned up. A probe retry would add a duplicate entry, leaking the original one permanently. Add an err_rmem label that calls of_reserved_mem_device_release() and route all error paths after of_reserved_mem_device_init() through it. of_reserved_mem_device_release() is safe to call unconditionally as it simply walks an empty list when nothing was assigned. Fixes: a33b2579c8d3 ("firmware: qcom: scm: add support for SHM bridge memory carveout") Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com> Link: https://lore.kernel.org/r/20260724094939.613844-3-mukesh.ojha@oss.qualcomm.com Signed-off-by: Bjorn Andersson <andersson@kernel.org>
-rw-r--r--drivers/firmware/qcom/qcom_scm.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index d11026c26cde..3eaa4c9ccf3c 100644
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -2850,9 +2850,11 @@ static int qcom_scm_probe(struct platform_device *pdev)
"Failed to setup the reserved memory region for TZ mem\n");
ret = qcom_tzmem_enable(scm->dev);
- if (ret)
- return dev_err_probe(scm->dev, ret,
- "Failed to enable the TrustZone memory allocator\n");
+ if (ret) {
+ ret = dev_err_probe(scm->dev, ret,
+ "Failed to enable the TrustZone memory allocator\n");
+ goto err_rmem;
+ }
memset(&pool_config, 0, sizeof(pool_config));
pool_config.initial_size = 0;
@@ -2860,9 +2862,11 @@ static int qcom_scm_probe(struct platform_device *pdev)
pool_config.max_size = SZ_256K;
scm->mempool = devm_qcom_tzmem_pool_new(scm->dev, &pool_config);
- if (IS_ERR(scm->mempool))
- return dev_err_probe(scm->dev, PTR_ERR(scm->mempool),
- "Failed to create the SCM memory pool\n");
+ if (IS_ERR(scm->mempool)) {
+ ret = dev_err_probe(scm->dev, PTR_ERR(scm->mempool),
+ "Failed to create the SCM memory pool\n");
+ goto err_rmem;
+ }
ret = qcom_scm_query_waitq_count(scm);
scm->wq_cnt = ret < 0 ? QCOM_SCM_DEFAULT_WAITQ_COUNT : ret;
@@ -2938,6 +2942,10 @@ static int qcom_scm_probe(struct platform_device *pdev)
qcom_scm_gunyah_wdt_init(scm);
return 0;
+
+err_rmem:
+ of_reserved_mem_device_release(scm->dev);
+ return ret;
}
static void qcom_scm_shutdown(struct platform_device *pdev)