firmware: qcom: scm: Fix missing smp_load_acquire()

__scm is published in qcom_scm_probe() with smp_store_release()
but qcom_scm_set_download_mode() reads it directly without
smp_load_acquire(), creating a potential ordering violation where a
CPU could observe a stale or partially initialised __scm pointer.

Use smp_load_acquire() to acquire __scm in the
qcom_scm_set_download_mode() function.

Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260624190830.3131112-4-mukesh.ojha@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
This commit is contained in:
Mukesh Ojha
2026-06-25 00:38:14 +05:30
committed by Bjorn Andersson
parent bc3c98b776
commit d9603a7790

View File

@@ -534,23 +534,23 @@ static int qcom_scm_io_rmw(phys_addr_t addr, unsigned int mask, unsigned int val
return qcom_scm_io_writel(addr, new);
}
static void qcom_scm_set_download_mode(u32 dload_mode)
static void qcom_scm_set_download_mode(struct qcom_scm *scm, u32 dload_mode)
{
int ret = 0;
if (__scm->dload_mode_addr) {
ret = qcom_scm_io_rmw(__scm->dload_mode_addr, QCOM_DLOAD_MASK,
if (scm->dload_mode_addr) {
ret = qcom_scm_io_rmw(scm->dload_mode_addr, QCOM_DLOAD_MASK,
FIELD_PREP(QCOM_DLOAD_MASK, dload_mode));
} else if (__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_BOOT,
} else if (__qcom_scm_is_call_available(scm->dev, QCOM_SCM_SVC_BOOT,
QCOM_SCM_BOOT_SET_DLOAD_MODE)) {
ret = __qcom_scm_set_dload_mode(__scm->dev, !!dload_mode);
ret = __qcom_scm_set_dload_mode(scm->dev, !!dload_mode);
} else if (dload_mode) {
dev_err(__scm->dev,
dev_err(scm->dev,
"No available mechanism for setting download mode\n");
}
if (ret)
dev_err(__scm->dev, "failed to set download mode: %d\n", ret);
dev_err(scm->dev, "failed to set download mode: %d\n", ret);
}
struct qcom_scm_pas_context *devm_qcom_scm_pas_context_alloc(struct device *dev,
@@ -2673,6 +2673,7 @@ static int get_download_mode(char *buffer, const struct kernel_param *kp)
static int set_download_mode(const char *val, const struct kernel_param *kp)
{
struct qcom_scm *scm;
bool tmp;
int ret;
@@ -2688,8 +2689,10 @@ static int set_download_mode(const char *val, const struct kernel_param *kp)
}
download_mode = ret;
if (__scm)
qcom_scm_set_download_mode(download_mode);
/* Pairs with smp_store_release() in qcom_scm_probe(). */
scm = smp_load_acquire(&__scm);
if (scm)
qcom_scm_set_download_mode(scm, download_mode);
return 0;
}
@@ -2815,7 +2818,7 @@ static int qcom_scm_probe(struct platform_device *pdev)
* will cause the boot stages to enter download mode, unless
* disabled below by a clean shutdown/reboot.
*/
qcom_scm_set_download_mode(download_mode);
qcom_scm_set_download_mode(scm, download_mode);
/*
* Disable SDI if indicated by DT that it is enabled by default.
@@ -2848,7 +2851,7 @@ static int qcom_scm_probe(struct platform_device *pdev)
static void qcom_scm_shutdown(struct platform_device *pdev)
{
/* Clean shutdown, disable download mode to allow normal restart */
qcom_scm_set_download_mode(QCOM_DLOAD_NODUMP);
qcom_scm_set_download_mode(__scm, QCOM_DLOAD_NODUMP);
qcom_pas_ops_unregister();
}