[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20260116113322.29427-1-fido_max@inbox.ru>
Date: Fri, 16 Jan 2026 14:33:22 +0300
From: Maxim Kochetkov <fido_max@...ox.ru>
To: arm-scmi@...r.kernel.org
Cc: linux-arm-kernel@...ts.infradead.org,
linux-kernel@...r.kernel.org,
Jonathan.Cameron@...wei.com,
cristian.marussi@....com,
sudeep.holla@....com,
Maxim Kochetkov <fido_max@...ox.ru>
Subject: [PATCH 1/1] firmware: arm_scmi: move scmi_channels_setup() after SCMI stack init
scmi_channels_setup() makes channels enabled and ready to receive
messages immediately. In some cases channel may receive message from
firmware here (i.e. notification). This message will be passed to
SCMI RX path scmi_rx_callback(). Then in scmi_handle_notification()
scmi_xfer_get() is called to get message buffer to unpack.
scmi_xfer_get() uses xfer_lock spinlock. But xfer_lock init is
located in scmi_xfer_info_init() which is called after
scmi_channels_setup() in scmi_probe().
So here we have trying to access to uninitialized spinlok:
[ 9.978360] BUG: spinlock bad magic on CPU#0, irq/16-1e200000/123
[ 9.979236] lock: 0xffffffd6035500c8, .magic: 00000000, .owner: <none>/-1, .owner_cpu: 0
[ 9.980633] CPU: 0 UID: 0 PID: 123 Comm: irq/16-1e200000 Not tainted 6.12.0-01250-g7fb379e5f78e-dirty #2
[ 9.983157] Call Trace:
[ 9.983422] [<ffffffff80007ab4>] dump_backtrace+0x1c/0x24
[ 9.983972] [<ffffffff80b5d380>] show_stack+0x2e/0x38
[ 9.984523] [<ffffffff80b6e58e>] dump_stack_lvl+0x52/0x74
[ 9.985336] [<ffffffff80b6e5c4>] dump_stack+0x14/0x1c
[ 9.985556] [<ffffffff80b5dfa8>] spin_dump+0x62/0x6e
[ 9.985942] [<ffffffff8007df7a>] do_raw_spin_lock+0xd2/0x12c
[ 9.986213] [<ffffffff80b78f16>] _raw_spin_lock_irqsave+0x22/0x2e
[ 9.986585] [<ffffffff80823442>] scmi_rx_callback+0x158/0x7ca
So move scmi_channels_setup() after full SCMI stack init to make
sure we are ready to receive messages before enabling channels.
Fixes: 4ebd8f6dea81 ("firmware: arm_scmi: Add receive buffer support for notifications")
Signed-off-by: Maxim Kochetkov <fido_max@...ox.ru>
---
drivers/firmware/arm_scmi/driver.c | 27 +++++++++++++--------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 3e76a3204ba4..0c46a9dfaf80 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -3225,17 +3225,10 @@ static int scmi_probe(struct platform_device *pdev)
handle->devm_protocol_put = scmi_devm_protocol_put;
handle->is_transport_atomic = scmi_is_transport_atomic;
- /* Setup all channels described in the DT at first */
- ret = scmi_channels_setup(info);
- if (ret) {
- err_str = "failed to setup channels\n";
- goto clear_ida;
- }
-
ret = bus_register_notifier(&scmi_bus_type, &info->bus_nb);
if (ret) {
err_str = "failed to register bus notifier\n";
- goto clear_txrx_setup;
+ goto clear_ida;
}
ret = blocking_notifier_chain_register(&scmi_requested_devices_nh,
@@ -3279,6 +3272,12 @@ static int scmi_probe(struct platform_device *pdev)
dev_err(dev,
"Transport is not polling capable. Atomic mode not supported.\n");
+ ret = scmi_channels_setup(info);
+ if (ret) {
+ err_str = "failed to setup channels\n";
+ goto notification_exit;
+ }
+
/*
* Trigger SCMI Base protocol initialization.
* It's mandatory and won't be ever released/deinit until the
@@ -3291,7 +3290,7 @@ static int scmi_probe(struct platform_device *pdev)
dev_err(dev, "%s", err_str);
return 0;
}
- goto notification_exit;
+ goto clear_txrx_setup;
}
mutex_lock(&scmi_list_mutex);
@@ -3333,6 +3332,8 @@ static int scmi_probe(struct platform_device *pdev)
return 0;
+clear_txrx_setup:
+ scmi_cleanup_txrx_channels(info);
notification_exit:
if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT))
scmi_raw_mode_cleanup(info->raw);
@@ -3342,8 +3343,6 @@ static int scmi_probe(struct platform_device *pdev)
&info->dev_req_nb);
clear_bus_notifier:
bus_unregister_notifier(&scmi_bus_type, &info->bus_nb);
-clear_txrx_setup:
- scmi_cleanup_txrx_channels(info);
clear_ida:
ida_free(&scmi_id, info->id);
@@ -3367,6 +3366,9 @@ static void scmi_remove(struct platform_device *pdev)
list_del(&info->node);
mutex_unlock(&scmi_list_mutex);
+ /* Safe to free channels since no more users */
+ scmi_cleanup_txrx_channels(info);
+
scmi_notification_exit(&info->handle);
mutex_lock(&info->protocols_mtx);
@@ -3381,9 +3383,6 @@ static void scmi_remove(struct platform_device *pdev)
&info->dev_req_nb);
bus_unregister_notifier(&scmi_bus_type, &info->bus_nb);
- /* Safe to free channels since no more users */
- scmi_cleanup_txrx_channels(info);
-
ida_free(&scmi_id, info->id);
}
--
2.51.0
Powered by blists - more mailing lists