Skip to content

Commit 1e76b54

Browse files
krzkandersson
authored andcommitted
firmware: qcom: scm: Cleanup global '__scm' on probe failures
If SCM driver fails the probe, it should not leave global '__scm' variable assigned, because external users of this driver will assume the probe finished successfully. For example TZMEM parts ('__scm->mempool') are initialized later in the probe, but users of it (__scm_smc_call()) rely on the '__scm' variable. This fixes theoretical NULL pointer exception, triggered via introducing probe deferral in SCM driver with call trace: qcom_tzmem_alloc+0x70/0x1ac (P) qcom_tzmem_alloc+0x64/0x1ac (L) qcom_scm_assign_mem+0x78/0x194 qcom_rmtfs_mem_probe+0x2d4/0x38c platform_probe+0x68/0xc8 Fixes: 40289e3 ("firmware: qcom: scm: enable the TZ mem allocator") Signed-off-by: Krzysztof Kozlowski <[email protected]> Link: https://lore.kernel.org/r/20241209-qcom-scm-missing-barriers-and-all-sort-of-srap-v2-4-9061013c8d92@linaro.org Signed-off-by: Bjorn Andersson <[email protected]>
1 parent b628510 commit 1e76b54

File tree

1 file changed

+29
-13
lines changed

1 file changed

+29
-13
lines changed

drivers/firmware/qcom/qcom_scm.c

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2038,13 +2038,17 @@ static int qcom_scm_probe(struct platform_device *pdev)
20382038

20392039
irq = platform_get_irq_optional(pdev, 0);
20402040
if (irq < 0) {
2041-
if (irq != -ENXIO)
2042-
return irq;
2041+
if (irq != -ENXIO) {
2042+
ret = irq;
2043+
goto err;
2044+
}
20432045
} else {
20442046
ret = devm_request_threaded_irq(__scm->dev, irq, NULL, qcom_scm_irq_handler,
20452047
IRQF_ONESHOT, "qcom-scm", __scm);
2046-
if (ret < 0)
2047-
return dev_err_probe(scm->dev, ret, "Failed to request qcom-scm irq\n");
2048+
if (ret < 0) {
2049+
dev_err_probe(scm->dev, ret, "Failed to request qcom-scm irq\n");
2050+
goto err;
2051+
}
20482052
}
20492053

20502054
__get_convention();
@@ -2063,24 +2067,30 @@ static int qcom_scm_probe(struct platform_device *pdev)
20632067
qcom_scm_disable_sdi();
20642068

20652069
ret = of_reserved_mem_device_init(__scm->dev);
2066-
if (ret && ret != -ENODEV)
2067-
return dev_err_probe(__scm->dev, ret,
2068-
"Failed to setup the reserved memory region for TZ mem\n");
2070+
if (ret && ret != -ENODEV) {
2071+
dev_err_probe(__scm->dev, ret,
2072+
"Failed to setup the reserved memory region for TZ mem\n");
2073+
goto err;
2074+
}
20692075

20702076
ret = qcom_tzmem_enable(__scm->dev);
2071-
if (ret)
2072-
return dev_err_probe(__scm->dev, ret,
2073-
"Failed to enable the TrustZone memory allocator\n");
2077+
if (ret) {
2078+
dev_err_probe(__scm->dev, ret,
2079+
"Failed to enable the TrustZone memory allocator\n");
2080+
goto err;
2081+
}
20742082

20752083
memset(&pool_config, 0, sizeof(pool_config));
20762084
pool_config.initial_size = 0;
20772085
pool_config.policy = QCOM_TZMEM_POLICY_ON_DEMAND;
20782086
pool_config.max_size = SZ_256K;
20792087

20802088
__scm->mempool = devm_qcom_tzmem_pool_new(__scm->dev, &pool_config);
2081-
if (IS_ERR(__scm->mempool))
2082-
return dev_err_probe(__scm->dev, PTR_ERR(__scm->mempool),
2083-
"Failed to create the SCM memory pool\n");
2089+
if (IS_ERR(__scm->mempool)) {
2090+
dev_err_probe(__scm->dev, PTR_ERR(__scm->mempool),
2091+
"Failed to create the SCM memory pool\n");
2092+
goto err;
2093+
}
20842094

20852095
/*
20862096
* Initialize the QSEECOM interface.
@@ -2096,6 +2106,12 @@ static int qcom_scm_probe(struct platform_device *pdev)
20962106
WARN(ret < 0, "failed to initialize qseecom: %d\n", ret);
20972107

20982108
return 0;
2109+
2110+
err:
2111+
/* Paired with smp_load_acquire() in qcom_scm_is_available(). */
2112+
smp_store_release(&__scm, NULL);
2113+
2114+
return ret;
20992115
}
21002116

21012117
static void qcom_scm_shutdown(struct platform_device *pdev)

0 commit comments

Comments
 (0)