[PATCH 3/3] firmware: qcom: scm: drop the __scm global

From: Albert Esteve

Date: Mon Sep 14 2026 - 08:53:04 EST


Stop publishing a driver-wide singleton. Mark the instance
ready with scm->available, look it up from the platform driver
for module-parameter stores, and use platform_get_drvdata() on
shutdown.

Signed-off-by: Albert Esteve <aesteve@xxxxxxxxxx>
---
drivers/firmware/qcom/qcom_scm.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index 73e9752e3cca..68cd8dc622c6 100644
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -63,6 +63,9 @@ struct qcom_scm {

struct qcom_tzmem_pool *mempool;
unsigned int wq_cnt;
+
+ /* Published with smp_store_release() once the SCM API is usable. */
+ int available;
};

struct qcom_scm_current_perm_info {
@@ -174,8 +177,6 @@ static const char * const download_mode_name[] = {
[QCOM_DLOAD_BOTHDUMP] = "full,mini",
};

-static struct qcom_scm *__scm;
-
static int qcom_scm_clk_enable(struct qcom_scm *scm)
{
int ret;
@@ -1962,7 +1963,7 @@ EXPORT_SYMBOL_GPL(qcom_scm_lmh_dcvsh_available);
* This is only supposed to be called once by the TZMem module. It takes the
* SCM struct device as argument and uses it to pass the call as at the time
* the SHM Bridge is enabled, the SCM is not yet fully set up and doesn't
- * accept global user calls. Don't try to use the __scm pointer here.
+ * accept global user calls.
*/
int qcom_scm_shm_bridge_enable(struct device *scm_dev)
{
@@ -2657,7 +2658,7 @@ static void qcom_scm_qtee_init(struct qcom_scm *scm)
bool qcom_scm_is_available(struct qcom_scm *scm)
{
/* Paired with smp_store_release() in qcom_scm_probe */
- return scm && scm == smp_load_acquire(&__scm);
+ return scm && smp_load_acquire(&scm->available);
}
EXPORT_SYMBOL_GPL(qcom_scm_is_available);

@@ -2817,7 +2818,7 @@ static int set_download_mode(const char *val, const struct kernel_param *kp)

download_mode = ret;
/* Pairs with smp_store_release() in qcom_scm_probe(). */
- scm = smp_load_acquire(&__scm);
+ scm = qcom_scm_get();
if (scm)
qcom_scm_set_download_mode(scm, download_mode);

@@ -2858,7 +2859,7 @@ static int set_minidump_dest(const char *val, const struct kernel_param *kp)
minidump_dest = minidump_dest_map[i].val;

/* Pairs with smp_store_release() in qcom_scm_probe(). */
- scm = smp_load_acquire(&__scm);
+ scm = qcom_scm_get();
if (scm && scm->minidump_sram && (download_mode & QCOM_DLOAD_MINIDUMP))
writel_relaxed(minidump_dest, scm->minidump_sram);

@@ -2983,7 +2984,7 @@ static int qcom_scm_probe(struct platform_device *pdev)
* be called after the TrustZone memory pool is initialized and the
* waitqueue interrupt requested.
*/
- smp_store_release(&__scm, scm);
+ smp_store_release(&scm->available, 1);

__get_convention(scm->dev);

@@ -3033,8 +3034,10 @@ static int qcom_scm_probe(struct platform_device *pdev)

static void qcom_scm_shutdown(struct platform_device *pdev)
{
+ struct qcom_scm *scm = platform_get_drvdata(pdev);
+
/* Clean shutdown, disable download mode to allow normal restart */
- qcom_scm_set_download_mode(__scm, QCOM_DLOAD_NODUMP);
+ qcom_scm_set_download_mode(scm, QCOM_DLOAD_NODUMP);
qcom_pas_ops_unregister();
}


--
2.55.0