Linux kernel and device drivers for NXP i.MX platforms
 help / color / mirror / Atom feed
* [PATCH v4 0/3] firmware: arm_scmi: fix module auto-loading
@ 2026-08-26 10:27 Hans de Goede
  2026-08-26 10:27 ` [PATCH v4 1/3] module: add SCMI device table alias support Hans de Goede
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Hans de Goede @ 2026-08-26 10:27 UTC (permalink / raw)
  To: Bjorn Andersson, Cristian Marussi, Sudeep Holla
  Cc: Hans de Goede, Daniel Lezcano, arm-scmi, linux-arm-kernel,
	linux-arm-msm, imx, linux-kernel

Hi All,

Here is a patch series fixing arm_scmi module autoloading this combines:

1. Patch 1/2 from Bjorn to add support for scmi bus modaliases to modpost:
https://lore.kernel.org/all/20260618-scmi-modalias-v2-1-8c7547c1be21@oss.qualcomm.com/

2. RFC 2/2 from Cristian which pre-populates the scmi { protocol, name }
tupple list with standard protocol info to break the circular dep:
https://patch.msgid.link/20250203100154.140877-2-cristian.marussi@arm.com

1. is not enough by itself because driver module auto-loading requires
the devices to already be created for udev to get the necessary uevents
based on which udev auto-loads modules.

But SCMI devices are only created after their { protocol, name } tupples
have been registered which is done from scmi_driver_register(), creating
a circular dependency.

2. breaks the circular dependency by pre-populating the { protocol, name }
list with the standard protocols. This allows the devices to be created
before the module with the driver is loaded, after which module auto
loading works the same as it does on any other bus.

I've tested this on a T14s Snapdragon laptop with Fedora's kernel config
where scmi_cpufreq is a module. With this series scmi_cpufreq correctly
autoloads even if it is not included in the initramfs.

I've added a 3th patch extending the pre-populating to also include all
the { protocol, name } tupples for the in tree SCMI drivers for IMX
vendor protocols, so that module auto-loading will work for all in tree
drivers.

Out of tree drivers can still register new tupples as before but their
modules will need to be manually loaded (also as before).

Changes in v4:
- Drop unused driver_data member from struct scmi_device_id (Uwe)
- Drop device-id/scmi.h include from mod_devicetable.h (Uwe)
- Add device-id/scmi.h to devicetable-offsets.c and file2alias.c (Uwe)

Changes in v3:
- v3 is the first series combining Bjorn and Christian's work see above.

Regards,

Hans


Bjorn Andersson (1):
  module: add SCMI device table alias support

Cristian Marussi (1):
  firmware: arm_scmi: Pre-register protocol, name tupples for standard
    protocols

Hans de Goede (1):
  firmware: arm_scmi: Pre-register protocol, name tupples for IMX
    protocols

 MAINTAINERS                       |  1 +
 drivers/firmware/arm_scmi/bus.c   | 75 +++++++++++++++++++++++--------
 include/linux/device-id/scmi.h    | 17 +++++++
 include/linux/scmi_protocol.h     |  6 +--
 scripts/mod/devicetable-offsets.c |  5 +++
 scripts/mod/file2alias.c          | 12 +++++
 6 files changed, 93 insertions(+), 23 deletions(-)
 create mode 100644 include/linux/device-id/scmi.h

-- 
2.55.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v4 1/3] module: add SCMI device table alias support
  2026-08-26 10:27 [PATCH v4 0/3] firmware: arm_scmi: fix module auto-loading Hans de Goede
@ 2026-08-26 10:27 ` Hans de Goede
  2026-08-26 10:27 ` [PATCH v4 2/3] firmware: arm_scmi: Pre-register protocol, name tupples for standard protocols Hans de Goede
  2026-08-26 10:27 ` [PATCH v4 3/3] firmware: arm_scmi: Pre-register protocol, name tupples for IMX protocols Hans de Goede
  2 siblings, 0 replies; 6+ messages in thread
From: Hans de Goede @ 2026-08-26 10:27 UTC (permalink / raw)
  To: Bjorn Andersson, Cristian Marussi, Sudeep Holla
  Cc: Hans de Goede, Daniel Lezcano, arm-scmi, linux-arm-kernel,
	linux-arm-msm, imx, linux-kernel, Bjorn Andersson

From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>

SCMI client drivers already describe their bus match data with
MODULE_DEVICE_TABLE(scmi, ...), but modpost does not know how to consume
SCMI device tables. As a result, SCMI modules do not get generated module
aliases from their id tables.

Move struct scmi_device_id to mod_devicetable.h so it has a fixed layout
visible to modpost, add the corresponding generated offsets and teach
file2alias to emit scmi:<protocol>:<name> aliases.

Use the same stable alias format for SCMI device uevents and sysfs
modaliases. The previous string included the instance-specific device
name, which is not useful for matching modules.

Assisted-by: Codex:GPT-5.5
Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Tested-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
---
Changes in v4:
- Drop unused driver_data member from struct scmi_device_id (Uwe)
- Drop device-id/scmi.h include from mod_devicetable.h (Uwe)
- Add device-id/scmi.h to devicetable-offsets.c and file2alias.c (Uwe)

Changes in v3:
- Adjust for ad428f5811bd ("mod_devicetable.h: Split into per subsystem
  headers")
- Add '\n' to modalias_show() output, matching other subsystems' modalias

Changes in v2:
- Drop #include <linux/mod_devicetable.h> from scmi_protocol.h
- Link to v1: https://patch.msgid.link/20260616-scmi-modalias-v1-0-662b8dd52ab2@oss.qualcomm.com
---
 MAINTAINERS                       |  1 +
 drivers/firmware/arm_scmi/bus.c   | 21 ++++++++++-----------
 include/linux/device-id/scmi.h    | 17 +++++++++++++++++
 include/linux/scmi_protocol.h     |  6 +-----
 scripts/mod/devicetable-offsets.c |  5 +++++
 scripts/mod/file2alias.c          | 12 ++++++++++++
 6 files changed, 46 insertions(+), 16 deletions(-)
 create mode 100644 include/linux/device-id/scmi.h

diff --git a/MAINTAINERS b/MAINTAINERS
index fc6ca082106f..ee5beee606fc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -26334,6 +26334,7 @@ F:	drivers/pmdomain/arm/
 F:	drivers/powercap/arm_scmi_powercap.c
 F:	drivers/regulator/scmi-regulator.c
 F:	drivers/reset/reset-scmi.c
+F:	include/linux/device-id/scmi.h
 F:	include/linux/sc[mp]i_protocol.h
 F:	include/trace/events/scmi.h
 F:	include/uapi/linux/virtio_scmi.h
diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index 793be9eabaed..d12d5de15a1a 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -13,11 +13,12 @@
 #include <linux/of.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/device.h>
 
 #include "common.h"
 
-#define SCMI_UEVENT_MODALIAS_FMT	"%s:%02x:%s"
+#define SCMI_UEVENT_MODALIAS_FMT	SCMI_MODULE_PREFIX "%02x:%s"
 
 BLOCKING_NOTIFIER_HEAD(scmi_requested_devices_nh);
 EXPORT_SYMBOL_GPL(scmi_requested_devices_nh);
@@ -141,7 +142,7 @@ static int scmi_protocol_table_register(const struct scmi_device_id *id_table)
 	int ret = 0;
 	const struct scmi_device_id *entry;
 
-	for (entry = id_table; entry->name && ret == 0; entry++)
+	for (entry = id_table; entry->name[0] && ret == 0; entry++)
 		ret = scmi_protocol_device_request(entry);
 
 	return ret;
@@ -197,18 +198,18 @@ scmi_protocol_table_unregister(const struct scmi_device_id *id_table)
 {
 	const struct scmi_device_id *entry;
 
-	for (entry = id_table; entry->name; entry++)
+	for (entry = id_table; entry->name[0]; entry++)
 		scmi_protocol_device_unrequest(entry);
 }
 
 static int scmi_dev_match_by_id_table(struct scmi_device *scmi_dev,
 				      const struct scmi_device_id *id_table)
 {
-	if (!id_table || !id_table->name)
+	if (!id_table || !id_table->name[0])
 		return 0;
 
 	/* Always skip transport devices from matching */
-	for (; id_table->protocol_id && id_table->name; id_table++)
+	for (; id_table->protocol_id && id_table->name[0]; id_table++)
 		if (id_table->protocol_id == scmi_dev->protocol_id &&
 		    strncmp(scmi_dev->name, "__scmi_transport_device", 23) &&
 		    !strcmp(id_table->name, scmi_dev->name))
@@ -245,7 +246,7 @@ static struct scmi_device *scmi_child_dev_find(struct device *parent,
 	struct device *dev;
 
 	id_table[0].protocol_id = prot_id;
-	id_table[0].name = name;
+	strscpy(id_table[0].name, name, sizeof(id_table[0].name));
 
 	dev = device_find_child(parent, &id_table, scmi_match_by_id_table);
 	if (!dev)
@@ -282,8 +283,7 @@ static int scmi_device_uevent(const struct device *dev, struct kobj_uevent_env *
 	const struct scmi_device *scmi_dev = to_scmi_dev(dev);
 
 	return add_uevent_var(env, "MODALIAS=" SCMI_UEVENT_MODALIAS_FMT,
-			      dev_name(&scmi_dev->dev), scmi_dev->protocol_id,
-			      scmi_dev->name);
+			      scmi_dev->protocol_id, scmi_dev->name);
 }
 
 static ssize_t modalias_show(struct device *dev,
@@ -291,9 +291,8 @@ static ssize_t modalias_show(struct device *dev,
 {
 	struct scmi_device *scmi_dev = to_scmi_dev(dev);
 
-	return sysfs_emit(buf, SCMI_UEVENT_MODALIAS_FMT,
-			  dev_name(&scmi_dev->dev), scmi_dev->protocol_id,
-			  scmi_dev->name);
+	return sysfs_emit(buf, SCMI_UEVENT_MODALIAS_FMT "\n",
+			  scmi_dev->protocol_id, scmi_dev->name);
 }
 static DEVICE_ATTR_RO(modalias);
 
diff --git a/include/linux/device-id/scmi.h b/include/linux/device-id/scmi.h
new file mode 100644
index 000000000000..1b4ccfa9dcc5
--- /dev/null
+++ b/include/linux/device-id/scmi.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef LINUX_DEVICE_ID_SCMI_H
+#define LINUX_DEVICE_ID_SCMI_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#endif
+
+#define SCMI_NAME_SIZE		32
+#define SCMI_MODULE_PREFIX	"scmi:"
+
+struct scmi_device_id {
+	__u8 protocol_id;
+	char name[SCMI_NAME_SIZE];
+};
+
+#endif /* ifndef LINUX_DEVICE_ID_SCMI_H */
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 5ab73b1ab9aa..ba53302d95f5 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -9,6 +9,7 @@
 #define _LINUX_SCMI_PROTOCOL_H
 
 #include <linux/bitfield.h>
+#include <linux/device-id/scmi.h>
 #include <linux/device.h>
 #include <linux/notifier.h>
 #include <linux/types.h>
@@ -951,11 +952,6 @@ struct scmi_device {
 
 #define to_scmi_dev(d) container_of_const(d, struct scmi_device, dev)
 
-struct scmi_device_id {
-	u8 protocol_id;
-	const char *name;
-};
-
 struct scmi_driver {
 	const char *name;
 	int (*probe)(struct scmi_device *sdev);
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index b4178c42d08f..91ec3704ee2b 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #define COMPILE_OFFSETS
+#include <linux/device-id/scmi.h>
 #include <linux/kbuild.h>
 #include <linux/mod_devicetable.h>
 
@@ -144,6 +145,10 @@ int main(void)
 	DEVID(rpmsg_device_id);
 	DEVID_FIELD(rpmsg_device_id, name);
 
+	DEVID(scmi_device_id);
+	DEVID_FIELD(scmi_device_id, protocol_id);
+	DEVID_FIELD(scmi_device_id, name);
+
 	DEVID(i2c_device_id);
 	DEVID_FIELD(i2c_device_id, name);
 
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 8d36c74dec2d..5379b1def07b 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -121,6 +121,7 @@ typedef struct {
 /* Big exception to the "don't include kernel headers into userspace, which
  * even potentially has different endianness and word sizes, since
  * we handle those differences explicitly below */
+#include "../../include/linux/device-id/scmi.h"
 #include "../../include/linux/mod_devicetable.h"
 
 struct devtable {
@@ -852,6 +853,16 @@ static void do_rpmsg_entry(struct module *mod, void *symval)
 	module_alias_printf(mod, false, RPMSG_DEVICE_MODALIAS_FMT, *name);
 }
 
+/* Looks like: scmi:NN:S */
+static void do_scmi_entry(struct module *mod, void *symval)
+{
+	DEF_FIELD(symval, scmi_device_id, protocol_id);
+	DEF_FIELD_ADDR(symval, scmi_device_id, name);
+
+	module_alias_printf(mod, false, SCMI_MODULE_PREFIX "%02x:%s",
+			    protocol_id, *name);
+}
+
 /* Looks like: i2c:S */
 static void do_i2c_entry(struct module *mod, void *symval)
 {
@@ -1491,6 +1502,7 @@ static const struct devtable devtable[] = {
 	{"virtio", SIZE_virtio_device_id, do_virtio_entry},
 	{"vmbus", SIZE_hv_vmbus_device_id, do_vmbus_entry},
 	{"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry},
+	{"scmi", SIZE_scmi_device_id, do_scmi_entry},
 	{"i2c", SIZE_i2c_device_id, do_i2c_entry},
 	{"i3c", SIZE_i3c_device_id, do_i3c_entry},
 	{"slim", SIZE_slim_device_id, do_slim_entry},
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v4 2/3] firmware: arm_scmi: Pre-register protocol, name tupples for standard protocols
  2026-08-26 10:27 [PATCH v4 0/3] firmware: arm_scmi: fix module auto-loading Hans de Goede
  2026-08-26 10:27 ` [PATCH v4 1/3] module: add SCMI device table alias support Hans de Goede
@ 2026-08-26 10:27 ` Hans de Goede
  2026-08-26 10:40   ` sashiko-bot
  2026-08-26 10:27 ` [PATCH v4 3/3] firmware: arm_scmi: Pre-register protocol, name tupples for IMX protocols Hans de Goede
  2 siblings, 1 reply; 6+ messages in thread
From: Hans de Goede @ 2026-08-26 10:27 UTC (permalink / raw)
  To: Bjorn Andersson, Cristian Marussi, Sudeep Holla
  Cc: Hans de Goede, Daniel Lezcano, arm-scmi, linux-arm-kernel,
	linux-arm-msm, imx, linux-kernel

From: Cristian Marussi <cristian.marussi@arm.com>

Driver module auto-loading requires the devices to already be created for
udev to get the necessary uevents based on which udev auto-loads modules.
But SCMI devices are only created after their { protocol, name } tupples
have been registered which is done from scmi_driver_register().

This creates a circular dependency where device creation is waiting for
the driver to register and loading the module with the driver is waiting
for the device to be created.

Pre-register the tupples for standard protocols to break this circular
dependency.

Tested-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
---
Changes in v3:
- Drop adding of a bus uevent function this is already done
- Update comments and commit message with a better explanation of why
- Link to v1/RFC: https://patch.msgid.link/20250203100154.140877-2-cristian.marussi@arm.com
---
 drivers/firmware/arm_scmi/bus.c | 47 ++++++++++++++++++++++++++++-----
 1 file changed, 40 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index d12d5de15a1a..111727904a89 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -77,12 +77,13 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
 	if (phead) {
 		head = phead;
 		list_for_each_entry(rdev, head, node) {
+			/* pr_debug() because dups are expected for std protocols */
 			if (!strcmp(rdev->id_table->name, id_table->name)) {
-				pr_err("Ignoring duplicate request [%d] %s\n",
-				       rdev->id_table->protocol_id,
-				       rdev->id_table->name);
-				ret = -EINVAL;
-				goto out;
+				pr_debug("Device already requested [%d] %s\n",
+					 rdev->id_table->protocol_id,
+					 rdev->id_table->name);
+				mutex_unlock(&scmi_requested_devices_mtx);
+				return 0;
 			}
 		}
 	}
@@ -579,17 +580,49 @@ static void scmi_devices_unregister(void)
 	bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister);
 }
 
+/* Standard protocols table */
+static const struct scmi_device_id scmi_std_id_table[] = {
+	{ SCMI_PROTOCOL_POWER, "genpd" },
+	{ SCMI_PROTOCOL_SYSTEM, "syspower" },
+	{ SCMI_PROTOCOL_PERF, "perf" },
+	{ SCMI_PROTOCOL_PERF, "cpufreq" },
+	{ SCMI_PROTOCOL_CLOCK, "clocks" },
+	{ SCMI_PROTOCOL_SENSOR, "hwmon" },
+	{ SCMI_PROTOCOL_SENSOR, "iiodev" },
+	{ SCMI_PROTOCOL_RESET, "reset" },
+	{ SCMI_PROTOCOL_VOLTAGE, "regulator" },
+	{ SCMI_PROTOCOL_POWERCAP, "powercap" },
+	{ SCMI_PROTOCOL_PINCTRL, "pinctrl" },
+	{ SCMI_PROTOCOL_PINCTRL, "pinctrl-imx" },
+	{ },
+};
+
 static int __init scmi_bus_init(void)
 {
 	int retval;
 
 	retval = bus_register(&scmi_bus_type);
-	if (retval)
+	if (retval) {
 		pr_err("SCMI protocol bus register failed (%d)\n", retval);
+		return retval;
+	}
+
+	/*
+	 * Driver module auto-loading requires the devices to already be created
+	 * for udev to get the necessary uevents. But the devices are only
+	 * created after their { protocol, name } tupples have been registered
+	 * which is done from scmi_driver_register(). Pre-register the tupples
+	 * for known (in tree) drivers to break this circular dependency.
+	 */
+	retval = scmi_protocol_table_register(scmi_std_id_table);
+	if (retval) {
+		bus_unregister(&scmi_bus_type);
+		return retval;
+	}
 
 	pr_info("SCMI protocol bus registered\n");
 
-	return retval;
+	return 0;
 }
 subsys_initcall(scmi_bus_init);
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v4 3/3] firmware: arm_scmi: Pre-register protocol, name tupples for IMX protocols
  2026-08-26 10:27 [PATCH v4 0/3] firmware: arm_scmi: fix module auto-loading Hans de Goede
  2026-08-26 10:27 ` [PATCH v4 1/3] module: add SCMI device table alias support Hans de Goede
  2026-08-26 10:27 ` [PATCH v4 2/3] firmware: arm_scmi: Pre-register protocol, name tupples for standard protocols Hans de Goede
@ 2026-08-26 10:27 ` Hans de Goede
  2026-08-26 10:43   ` sashiko-bot
  2 siblings, 1 reply; 6+ messages in thread
From: Hans de Goede @ 2026-08-26 10:27 UTC (permalink / raw)
  To: Bjorn Andersson, Cristian Marussi, Sudeep Holla
  Cc: Hans de Goede, Daniel Lezcano, arm-scmi, linux-arm-kernel,
	linux-arm-msm, imx, linux-kernel

There are in tree drivers for various IMX vendor protocols, also
pre-register the { protocol, name } tupples for these to make module
auto-loading work for these in tree drivers.

Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
---
Changes in v3:
- New patch in v3 of this patch-set
---
 drivers/firmware/arm_scmi/bus.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index 111727904a89..9f5740dc606f 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/device.h>
+#include <linux/scmi_imx_protocol.h>
 
 #include "common.h"
 
@@ -580,8 +581,8 @@ static void scmi_devices_unregister(void)
 	bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister);
 }
 
-/* Standard protocols table */
 static const struct scmi_device_id scmi_std_id_table[] = {
+	/* Standard protocols */
 	{ SCMI_PROTOCOL_POWER, "genpd" },
 	{ SCMI_PROTOCOL_SYSTEM, "syspower" },
 	{ SCMI_PROTOCOL_PERF, "perf" },
@@ -594,6 +595,12 @@ static const struct scmi_device_id scmi_std_id_table[] = {
 	{ SCMI_PROTOCOL_POWERCAP, "powercap" },
 	{ SCMI_PROTOCOL_PINCTRL, "pinctrl" },
 	{ SCMI_PROTOCOL_PINCTRL, "pinctrl-imx" },
+	/* Vendor protocols with in tree drivers */
+	{ SCMI_PROTOCOL_IMX_BBM, "imx-bbm-key" },
+	{ SCMI_PROTOCOL_IMX_BBM, "imx-bbm-rtc" },
+	{ SCMI_PROTOCOL_IMX_CPU, "imx-cpu" },
+	{ SCMI_PROTOCOL_IMX_LMM, "imx-lmm" },
+	{ SCMI_PROTOCOL_IMX_MISC, "imx-misc-ctrl" },
 	{ },
 };
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v4 2/3] firmware: arm_scmi: Pre-register protocol, name tupples for standard protocols
  2026-08-26 10:27 ` [PATCH v4 2/3] firmware: arm_scmi: Pre-register protocol, name tupples for standard protocols Hans de Goede
@ 2026-08-26 10:40   ` sashiko-bot
  0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-08-26 10:40 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Frank.Li, imx

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Unloading a standard SCMI driver destructively removes the pre-registered protocol tuple, permanently breaking udev auto-loading for subsequent SCMI servers.
- [Medium] Memory leak of pre-registered standard protocol entries on `scmi_bus_init` failure and `scmi-core` module unload.
--

commit da17ae54ea251ed3f7712cc26cfcce57fdfbf1f9
Author: Cristian Marussi <cristian.marussi@arm.com>

firmware: arm_scmi: Pre-register protocol, name tupples for standard protocols

This commit pre-registers standard protocol names to resolve a circular
dependency between udev module auto-loading and scmi device creation.

Link: https://patch.msgid.link/20250203100154.140877-2-cristian.marussi@arm.com

> diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
> index d12d5de15a1a4..111727904a892 100644
> --- a/drivers/firmware/arm_scmi/bus.c
> +++ b/drivers/firmware/arm_scmi/bus.c
> @@ -77,12 +77,13 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
>  	if (phead) {
>  		head = phead;
>  		list_for_each_entry(rdev, head, node) {
> +			/* pr_debug() because dups are expected for std protocols */
>  			if (!strcmp(rdev->id_table->name, id_table->name)) {
> -				pr_err("Ignoring duplicate request [%d] %s\n",
> -				       rdev->id_table->protocol_id,
> -				       rdev->id_table->name);
> -				ret = -EINVAL;
> -				goto out;
> +				pr_debug("Device already requested [%d] %s\n",
> +					 rdev->id_table->protocol_id,
> +					 rdev->id_table->name);
> +				mutex_unlock(&scmi_requested_devices_mtx);
> +				return 0;

[Severity: High]
Will unloading a standard scmi driver permanently break udev auto-loading
for subsequent scmi servers?

Since this function now returns success on duplicate requests without
maintaining a reference count, the pre-registered tuple shares the same
lifecycle as the driver registration.

If a user unloads a standard scmi driver module, scmi_driver_unregister()
calls scmi_protocol_table_unregister(). This function finds and
unconditionally deletes the pre-registered tuple from the
scmi_requested_devices idr:

scmi_protocol_device_unrequest()
    ...
    list_del(&victim->node);

If a new scmi server is later hotplugged, scmi_device_create() will fail
to find the protocol because the unregistration deleted it, preventing
device creation and subsequent auto-loading.

>  			}
>  		}
>  	}

[ ... ]

> @@ -579,17 +580,49 @@ static void scmi_devices_unregister(void)

[ ... ]

>  static int __init scmi_bus_init(void)
>  {
>  	int retval;
>  
>  	retval = bus_register(&scmi_bus_type);
> -	if (retval)
> +	if (retval) {
>  		pr_err("SCMI protocol bus register failed (%d)\n", retval);
> +		return retval;
> +	}
> +
> +	/*
> +	 * Driver module auto-loading requires the devices to already be created
> +	 * for udev to get the necessary uevents. But the devices are only
> +	 * created after their { protocol, name } tupples have been registered
> +	 * which is done from scmi_driver_register(). Pre-register the tupples
> +	 * for known (in tree) drivers to break this circular dependency.
> +	 */
> +	retval = scmi_protocol_table_register(scmi_std_id_table);
> +	if (retval) {
> +		bus_unregister(&scmi_bus_type);
> +		return retval;

[Severity: Medium]
Does this code leak the memory allocated for the standard protocol entries
if scmi_protocol_table_register() fails halfway?

If scmi_protocol_table_register() encounters an error midway, it returns
early without cleaning up the successfully registered entries in
scmi_requested_devices.

Additionally, if the scmi-core module is successfully loaded but later
unloaded, does the module exit path need a corresponding
scmi_protocol_table_unregister() call to clean up unclaimed standard
protocol devices?

> +	}
>  
>  	pr_info("SCMI protocol bus registered\n");
>  
> -	return retval;
> +	return 0;
>  }
>  subsys_initcall(scmi_bus_init);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260826102734.31766-1-johannes.goede@oss.qualcomm.com?part=2

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v4 3/3] firmware: arm_scmi: Pre-register protocol, name tupples for IMX protocols
  2026-08-26 10:27 ` [PATCH v4 3/3] firmware: arm_scmi: Pre-register protocol, name tupples for IMX protocols Hans de Goede
@ 2026-08-26 10:43   ` sashiko-bot
  0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-08-26 10:43 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Frank.Li, imx

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] SCMI bus initialization fails and aborts entirely when SCMI RAW mode is enabled without COEX.
- [High] Adding vendor-specific protocol IDs to the global `scmi_std_id_table` causes cross-vendor namespace collisions and type confusion on non-IMX platforms.
- [Medium] Dynamic allocations for SCMI requested devices are leaked on module initialization failure and module unload.
--

commit 80137af0c1515baef478cde4cc26837986f858f7
Author: Hans de Goede <johannes.goede@oss.qualcomm.com>

firmware: arm_scmi: Pre-register protocol, name tupples for IMX protocols

This patch pre-registers IMX vendor protocols to enable module auto-loading.
I've been reviewing this patchset and noticed a few regressions related to
these changes.

> diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
> index 111727904a892..9f5740dc606fa 100644
> --- a/drivers/firmware/arm_scmi/bus.c
> +++ b/drivers/firmware/arm_scmi/bus.c
[ ... ]
> @@ -594,6 +595,12 @@ static const struct scmi_device_id scmi_std_id_table[] = {
>  	{ SCMI_PROTOCOL_POWERCAP, "powercap" },
>  	{ SCMI_PROTOCOL_PINCTRL, "pinctrl" },
>  	{ SCMI_PROTOCOL_PINCTRL, "pinctrl-imx" },
> +	/* Vendor protocols with in tree drivers */
> +	{ SCMI_PROTOCOL_IMX_BBM, "imx-bbm-key" },
> +	{ SCMI_PROTOCOL_IMX_BBM, "imx-bbm-rtc" },

[Severity: High]
By adding vendor-specific protocol IDs (like SCMI_PROTOCOL_IMX_BBM, which
maps to 0x81) to the global scmi_std_id_table, any SCMI platform
(e.g., Mediatek) that implements its own custom vendor protocol 0x81
will now trigger the creation of an imx-bbm-key SCMI device during boot.

This causes the NXP/IMX driver to probe and request protocol ops for 0x81.

Because the SCMI core looks up protocols by the platform's vendor_id, it
returns the other vendor's protocol operations struct (as a void *).

The IMX driver then casts this to struct scmi_imx_bbm_proto_ops * and
dereferences it.

Could this lead to arbitrary function pointer execution or memory corruption
on non-IMX platforms?


I also noticed a few other regressions introduced in this patchset regarding
the scmi_bus_init() changes.

[Severity: High]
When CONFIG_ARM_SCMI_RAW_MODE_SUPPORT is enabled and
CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX is disabled,
scmi_protocol_device_request() unconditionally returns -EINVAL.

Because this patchset moved the global
scmi_protocol_table_register(scmi_std_id_table) call into scmi_bus_init(),
the -EINVAL error now propagates up:

drivers/firmware/arm_scmi/bus.c:scmi_bus_init() {
    ...
	retval = scmi_protocol_table_register(scmi_std_id_table);
	if (retval) {
		bus_unregister(&scmi_bus_type);
		return retval;
	}
    ...
}

Will this cause the entire SCMI bus initialization to fail and abort when
SCMI RAW mode is enabled without COEX?


[Severity: Medium]
The scmi_bus_init() function dynamically allocates entries in the
scmi_requested_devices IDR via scmi_protocol_table_register().

However, scmi_bus_exit() omits the call to
scmi_protocol_table_unregister(scmi_std_id_table) to free these entries:

drivers/firmware/arm_scmi/bus.c:scmi_bus_exit() {
	/*
	 * Destroy all remaining devices: just in case the drivers were
	 * manually unbound and at first and then the modules unloaded.
	 */
	scmi_devices_unregister();
	bus_unregister(&scmi_bus_type);
	ida_destroy(&scmi_bus_id);
}

Furthermore, if scmi_protocol_table_register() fails halfway through (e.g.
due to -ENOMEM), it does not clean up the already allocated entries.

Are the struct scmi_requested_dev allocations leaking on module unload or
initialization failure?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260826102734.31766-1-johannes.goede@oss.qualcomm.com?part=3

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-08-26 10:43 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-26 10:27 [PATCH v4 0/3] firmware: arm_scmi: fix module auto-loading Hans de Goede
2026-08-26 10:27 ` [PATCH v4 1/3] module: add SCMI device table alias support Hans de Goede
2026-08-26 10:27 ` [PATCH v4 2/3] firmware: arm_scmi: Pre-register protocol, name tupples for standard protocols Hans de Goede
2026-08-26 10:40   ` sashiko-bot
2026-08-26 10:27 ` [PATCH v4 3/3] firmware: arm_scmi: Pre-register protocol, name tupples for IMX protocols Hans de Goede
2026-08-26 10:43   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox