[PATCH] firmware: arm_scpi: publish scpi_ops with release semantics
Jaidev Shastri via B4 Relay
devnull+jaidevshastri.vt.edu at kernel.org
Mon Sep 21 18:06:04 PDT 2026
From: Jaidev Shastri <jaidevshastri at vt.edu>
scpi_probe() stores scpi_info early because scpi_init_versions() sends
messages through it, and sets scpi_drvinfo->scpi_ops as its last step.
get_scpi_ops() returns scpi_info->scpi_ops, so the ops pointer is the
gate that scpi-cpufreq, scpi_pm_domain, clk-scpi and scpi-hwmon test
before they use the driver.
Both accesses to scpi_ops are plain, and a consumer that passes the gate
reads scpi_info->channels, ->commands, ->num_chans and
->protocol_version through a fresh load of scpi_info rather than through
the ops pointer. The version fields are written by scpi_init_versions()
after scpi_info was published, so a consumer on another CPU can see a
non-NULL scpi_ops together with stale versions.
Publish scpi_ops with smp_store_release() and read it with
smp_load_acquire() in get_scpi_ops().
Found with MBCheck, a static herd7-based memory consistency checker.
Signed-off-by: Jaidev Shastri <jaidevshastri at vt.edu>
---
drivers/firmware/arm_scpi.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 68a730d22..eaf8134d7 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -809,7 +809,10 @@ static struct scpi_ops scpi_ops = {
struct scpi_ops *get_scpi_ops(void)
{
- return scpi_info ? scpi_info->scpi_ops : NULL;
+ struct scpi_drvinfo *info = READ_ONCE(scpi_info);
+
+ /* Pairs with the smp_store_release() of scpi_ops in scpi_probe(). */
+ return info ? smp_load_acquire(&info->scpi_ops) : NULL;
}
EXPORT_SYMBOL_GPL(get_scpi_ops);
@@ -1029,7 +1032,13 @@ static int scpi_probe(struct platform_device *pdev)
FIELD_GET(FW_REV_PATCH_MASK,
scpi_drvinfo->firmware_version));
- scpi_drvinfo->scpi_ops = &scpi_ops;
+ /*
+ * scpi_info is already visible (scpi_init_versions() needs it), so the
+ * scpi_ops field is what get_scpi_ops() callers gate on. Publish it
+ * with release semantics so that a consumer that sees the ops also
+ * sees the channels, the command table and the version fields.
+ */
+ smp_store_release(&scpi_drvinfo->scpi_ops, &scpi_ops);
ret = devm_of_platform_populate(dev);
if (ret)
---
base-commit: 93f51579e7df248780214094418f205253383cc5
change-id: 20260921-mb-arm-scpi-904141530492
Best regards,
--
Jaidev Shastri <jaidevshastri at vt.edu>
More information about the linux-arm-kernel
mailing list