* [PATCH] driver core: hand off fwnode ownership when shared fwnode owner is rejected
@ 2026-09-28 11:49 Peng Fan (OSS)
2026-09-28 12:09 ` Sudeep Holla
0 siblings, 1 reply; 5+ messages in thread
From: Peng Fan (OSS) @ 2026-09-28 11:49 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Saravana Kannan, Sudeep Holla, Hans de Goede
Cc: driver-core, linux-kernel, imx, Peng Fan, stable
From: Peng Fan <peng.fan@nxp.com>
When multiple devices share the same fwnode (e.g. the SCMI bus creates
both "pinctrl" and "pinctrl-imx" devices for SCMI_PROTOCOL_PINCTRL), only
the first device registered becomes the fwnode owner (fwnode->dev, set in
device_add()). If that owner never binds -- for example its driver returns
-ENODEV because it is blocklisted on this SoC, or because its driver is
not compiled in at all -- then driver_bound() is never called for it, so
fwnode_links_purge_suppliers() and fw_devlink_pickup_dangling_consumers()
are never run for the fwnode. The child fwnode supplier links (pin group
nodes such as lpi2c3grp, uart5grp, ...) stay unsatisfied and every
consumer of those child nodes defers probe forever.
On i.MX95 this manifests as a complete boot failure: the generic "pinctrl"
SCMI device claims fwnode ownership but its driver returns -ENODEV, while
the vendor "pinctrl-imx" device binds successfully. Because
dev->fwnode->dev still points at the rejected "pinctrl" device,
driver_bound() of "pinctrl-imx" skips the supplier purge and dangling
consumer pickup, so all I2C buses, SPI, UART, MMC, USB and PCIe
controllers wait forever for their pinctrl suppliers.
Fix this in two places:
1. In really_probe() failure path: when the driver definitively rejects
a device (-ENODEV / -ENXIO), fw_devlink_release_shared_fwnode() is
called. If the rejected device is the fwnode owner, it either
transfers ownership to an already-bound sibling (and runs the
purge/pickup on its behalf) or clears ownership so the next sibling
to bind can re-acquire it.
2. In device_links_driver_bound(): re-acquire the fwnode when it is
unowned (!fwnode->dev) or when the current owner has no driver at
all (!fwnode->dev->driver, meaning the driver was never compiled in
or loaded as a module). This covers the case where probe rejection
never happens because no driver ever matches.
fwnode->dev is not serialized by a lock; instead every writer only ever
touches a fwnode->dev it already owns (== dev, as device_del() does when
it clears ownership) or one that is currently unowned (== NULL, as
device_add() does when it claims ownership). This patch follows the same
discipline: fw_devlink_release_shared_fwnode() only writes fwnode->dev
when this device is the current owner; device_links_driver_bound() only
claims fwnode->dev when it is NULL or when the current owner has no
driver (and therefore cannot be in the process of binding).
Fixes: f9aa460672c9 ("driver core: Refactor fw_devlink feature")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
This issue is triggered by
aac4e67d6eb9 ("firmware: arm_scmi: Always create devices for standard protocols")
in linux-next next-20260925.
But I think this is a fix to
f9aa460672c9 ("driver core: Refactor fw_devlink feature")
Detailed information could be found in patch commit log.
---
drivers/base/base.h | 1 +
drivers/base/core.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/base/dd.c | 9 ++++++++
3 files changed, 73 insertions(+)
diff --git a/drivers/base/base.h b/drivers/base/base.h
index a5b7abc10ff0..36d34aa328c5 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -292,6 +292,7 @@ void device_links_unbind_consumers(struct device *dev);
bool device_link_flag_is_sync_state_only(u32 flags);
void fw_devlink_drivers_done(void);
void fw_devlink_probing_done(void);
+void fw_devlink_release_shared_fwnode(struct device *dev);
#define dev_for_each_link_to_supplier(__link, __dev) \
list_for_each_entry_srcu(__link, &(__dev)->links.suppliers, c_node, \
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 5daa88fa724a..e76153d5f124 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1376,6 +1376,20 @@ void device_links_driver_bound(struct device *dev)
struct device_link *link, *ln;
LIST_HEAD(sync_list);
+ /*
+ * Multiple devices may share the same fwnode (e.g. the SCMI bus
+ * creates several devices per protocol node). The first one
+ * registered owns the fwnode; if that owner's driver is rejected
+ * it relinquishes ownership (fwnode->dev == NULL, see
+ * fw_devlink_release_shared_fwnode()). If the owning device has
+ * no driver at all (driver never compiled / loaded as module), it
+ * will never bind, so it is safe to take over. Re-acquire the
+ * fwnode here so the purge/pickup still happens.
+ */
+ if (dev->fwnode && (!dev->fwnode->dev ||
+ (dev->fwnode->dev != dev && !dev->fwnode->dev->driver)))
+ dev->fwnode->dev = dev;
+
/*
* If a device binds successfully, it's expected to have created all
* the device links it needs to or make new device links as it needs
@@ -1390,6 +1404,7 @@ void device_links_driver_bound(struct device *dev)
* consumers to defer probe indefinitely waiting for a device for the
* child firmware node.
*/
+
if (dev->fwnode && dev->fwnode->dev == dev) {
fwnode_links_purge_suppliers(dev->fwnode);
fw_devlink_pickup_dangling_consumers(dev);
@@ -1474,6 +1489,54 @@ void device_links_driver_bound(struct device *dev)
device_links_flush_sync_list(&sync_list, dev);
}
+static int fwnode_shared_bound_match(struct device *dev, const void *data)
+{
+ const struct device *rejected = data;
+
+ return dev != rejected && dev->fwnode == rejected->fwnode &&
+ device_is_bound(dev);
+}
+
+/**
+ * fw_devlink_release_shared_fwnode - Hand off a shared fwnode on probe reject.
+ * @dev: Device whose driver just definitively rejected it (-ENODEV/-ENXIO).
+ *
+ * Several devices can share one fwnode (e.g. the SCMI bus creates both a
+ * "pinctrl" and a "pinctrl-imx" device for one protocol node). Only the first
+ * one registered owns the fwnode (fwnode->dev). If that owner's driver rejects
+ * the device, driver_bound() never runs for it, so the dangling consumers of
+ * the fwnode's child nodes are never picked up and defer probe forever.
+ *
+ * When the rejected device is the fwnode owner, relinquish ownership so those
+ * consumers can be resolved by a sibling that does bind:
+ *
+ * - If a sibling has already bound, transfer ownership to it and run the
+ * purge/pickup the owner could not do.
+ * - Otherwise clear ownership so the next sibling to bind re-acquires it in
+ * device_links_driver_bound() and runs the purge/pickup there.
+ *
+ * fwnode->dev is not lock-serialized; this only ever writes it when @dev is
+ * the current owner (fwnode->dev == dev), the same ownership-gated rule
+ * device_del() uses when it clears fwnode->dev on the owner.
+ */
+void fw_devlink_release_shared_fwnode(struct device *dev)
+{
+ struct device *sibling;
+
+ if (!dev->fwnode || dev->fwnode->dev != dev)
+ return;
+
+ sibling = bus_find_device(dev->bus, NULL, dev, fwnode_shared_bound_match);
+ if (sibling) {
+ dev->fwnode->dev = sibling;
+ fwnode_links_purge_suppliers(dev->fwnode);
+ fw_devlink_pickup_dangling_consumers(sibling);
+ put_device(sibling);
+ } else {
+ dev->fwnode->dev = NULL;
+ }
+}
+
/**
* __device_links_no_driver - Update links of a device without a driver.
* @dev: Device without a drvier.
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index f6525a7ee8c5..e19cfc91ebe1 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -762,6 +762,15 @@ static int really_probe(struct device *dev, const struct device_driver *drv)
dev_groups_failed:
device_remove(dev);
probe_failed:
+ /*
+ * -ENODEV/-ENXIO mean the driver definitively rejected this device
+ * (errors are returned as positive values at this label). If it owns a
+ * fwnode shared with sibling devices (e.g. SCMI creates several devices
+ * per protocol node), hand the fwnode off so its dangling child
+ * consumers can be resolved by a sibling instead of deferring forever.
+ */
+ if (ret == ENODEV || ret == ENXIO)
+ fw_devlink_release_shared_fwnode(dev);
driver_sysfs_remove(dev);
sysfs_failed:
bus_notify(dev, BUS_NOTIFY_DRIVER_NOT_BOUND);
---
base-commit: f5f84daefcd92d7a630066635ecea1433ed5eac7
change-id: 20260928-driver-core-f1d9e991edb2
Best regards,
--
Peng Fan <peng.fan@nxp.com>
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] driver core: hand off fwnode ownership when shared fwnode owner is rejected
2026-09-28 11:49 [PATCH] driver core: hand off fwnode ownership when shared fwnode owner is rejected Peng Fan (OSS)
@ 2026-09-28 12:09 ` Sudeep Holla
2026-09-29 1:47 ` Peng Fan
0 siblings, 1 reply; 5+ messages in thread
From: Sudeep Holla @ 2026-09-28 12:09 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Saravana Kannan, Hans de Goede, driver-core, linux-kernel, imx,
Peng Fan, stable
On Mon, Sep 28, 2026 at 07:49:01PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> When multiple devices share the same fwnode (e.g. the SCMI bus creates
> both "pinctrl" and "pinctrl-imx" devices for SCMI_PROTOCOL_PINCTRL), only
> the first device registered becomes the fwnode owner (fwnode->dev, set in
This has been rejected in the past. Apart from the trigger in -next,
anything else has changed ?
> device_add()). If that owner never binds -- for example its driver returns
> -ENODEV because it is blocklisted on this SoC, or because its driver is
> not compiled in at all -- then driver_bound() is never called for it, so
> fwnode_links_purge_suppliers() and fw_devlink_pickup_dangling_consumers()
> are never run for the fwnode. The child fwnode supplier links (pin group
> nodes such as lpi2c3grp, uart5grp, ...) stay unsatisfied and every
> consumer of those child nodes defers probe forever.
>
> On i.MX95 this manifests as a complete boot failure: the generic "pinctrl"
> SCMI device claims fwnode ownership but its driver returns -ENODEV, while
> the vendor "pinctrl-imx" device binds successfully. Because
> dev->fwnode->dev still points at the rejected "pinctrl" device,
> driver_bound() of "pinctrl-imx" skips the supplier purge and dangling
> consumer pickup, so all I2C buses, SPI, UART, MMC, USB and PCIe
> controllers wait forever for their pinctrl suppliers.
>
> Fix this in two places:
>
> 1. In really_probe() failure path: when the driver definitively rejects
> a device (-ENODEV / -ENXIO), fw_devlink_release_shared_fwnode() is
> called. If the rejected device is the fwnode owner, it either
> transfers ownership to an already-bound sibling (and runs the
> purge/pickup on its behalf) or clears ownership so the next sibling
> to bind can re-acquire it.
>
> 2. In device_links_driver_bound(): re-acquire the fwnode when it is
> unowned (!fwnode->dev) or when the current owner has no driver at
> all (!fwnode->dev->driver, meaning the driver was never compiled in
> or loaded as a module). This covers the case where probe rejection
> never happens because no driver ever matches.
>
> fwnode->dev is not serialized by a lock; instead every writer only ever
> touches a fwnode->dev it already owns (== dev, as device_del() does when
> it clears ownership) or one that is currently unowned (== NULL, as
> device_add() does when it claims ownership). This patch follows the same
> discipline: fw_devlink_release_shared_fwnode() only writes fwnode->dev
> when this device is the current owner; device_links_driver_bound() only
> claims fwnode->dev when it is NULL or when the current owner has no
> driver (and therefore cannot be in the process of binding).
>
> Fixes: f9aa460672c9 ("driver core: Refactor fw_devlink feature")
> Cc: stable@vger.kernel.org
> Assisted-by: LLM
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
> This issue is triggered by
> aac4e67d6eb9 ("firmware: arm_scmi: Always create devices for standard protocols")
> in linux-next next-20260925.
>
> But I think this is a fix to
> f9aa460672c9 ("driver core: Refactor fw_devlink feature")
>
Does dropping i.MX specials from list of devices solves the problem ?
I am more than happy to drop i.MX special in the code and let you
sort the pinmux mess you guys have created.
And also I remember you creating situation disabling cpufreq in the cmdline.
Will that be ever used on those i.MX platforms ?
I am not against the patch if others are OK.
--
Regards,
Sudeep
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] driver core: hand off fwnode ownership when shared fwnode owner is rejected
2026-09-28 12:09 ` Sudeep Holla
@ 2026-09-29 1:47 ` Peng Fan
2026-09-29 8:35 ` Sudeep Holla
0 siblings, 1 reply; 5+ messages in thread
From: Peng Fan @ 2026-09-29 1:47 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi
Cc: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Saravana Kannan, Hans de Goede, driver-core, linux-kernel, imx,
Peng Fan, stable
Hi Sudeep,
On Mon, Sep 28, 2026 at 01:09:08PM +0100, Sudeep Holla wrote:
>On Mon, Sep 28, 2026 at 07:49:01PM +0800, Peng Fan (OSS) wrote:
>> From: Peng Fan <peng.fan@nxp.com>
>>
>> When multiple devices share the same fwnode (e.g. the SCMI bus creates
>> both "pinctrl" and "pinctrl-imx" devices for SCMI_PROTOCOL_PINCTRL), only
>> the first device registered becomes the fwnode owner (fwnode->dev, set in
>
>This has been rejected in the past. Apart from the trigger in -next,
>anything else has changed ?
When both pinctrl-scmi.c and pinctrl-imx-scmi.c are built into the
kernel Image, both drivers call module_scmi_driver() at init time, which
goes through:
scmi_driver_register()
→ scmi_protocol_table_register(id_table)
→ scmi_protocol_device_request()
→ scmi_device_request_notifier()
→ scmi_create_protocol_devices(fwnode, ..., "pinctrl-imx")
So the on-demand path already creates both "pinctrl" and "pinctrl-imx"
devices for protocol@19, sharing the same fwnode, regardless of
scmi_std_id_table. aac4e67d6eb9 just added a second path that does
the same thing earlier - the fundamental problem existed before it.
This issue has been here for 2 years.
I proposed a patch in scmi side [1][2], but never made into mainline.
[1] https://lore.kernel.org/all/CAGETcx87Stfkru9gJrc1sf=PtFGLY7=jrfFaCzK5Z4hq+2TCzg@mail.gmail.com/
[2] https://lore.kernel.org/arm-scmi/ZryUgTOVr_haiHuh@pluto/
The issue is not specific to pinctrl w/o imx.
The problem is that two devices share one fwnode, the first one registered
claims fwnode->dev, and if it never binds, driver_bound() of the second
device skips the dangling consumer pickup because fwnode->dev != dev.
>
>> device_add()). If that owner never binds -- for example its driver returns
>> -ENODEV because it is blocklisted on this SoC, or because its driver is
>> not compiled in at all -- then driver_bound() is never called for it, so
>> fwnode_links_purge_suppliers() and fw_devlink_pickup_dangling_consumers()
>> are never run for the fwnode. The child fwnode supplier links (pin group
>> nodes such as lpi2c3grp, uart5grp, ...) stay unsatisfied and every
>> consumer of those child nodes defers probe forever.
>>
>> On i.MX95 this manifests as a complete boot failure: the generic "pinctrl"
>> SCMI device claims fwnode ownership but its driver returns -ENODEV, while
>> the vendor "pinctrl-imx" device binds successfully. Because
>> dev->fwnode->dev still points at the rejected "pinctrl" device,
>> driver_bound() of "pinctrl-imx" skips the supplier purge and dangling
>> consumer pickup, so all I2C buses, SPI, UART, MMC, USB and PCIe
>> controllers wait forever for their pinctrl suppliers.
>>
>> Fix this in two places:
>>
>> 1. In really_probe() failure path: when the driver definitively rejects
>> a device (-ENODEV / -ENXIO), fw_devlink_release_shared_fwnode() is
>> called. If the rejected device is the fwnode owner, it either
>> transfers ownership to an already-bound sibling (and runs the
>> purge/pickup on its behalf) or clears ownership so the next sibling
>> to bind can re-acquire it.
>>
>> 2. In device_links_driver_bound(): re-acquire the fwnode when it is
>> unowned (!fwnode->dev) or when the current owner has no driver at
>> all (!fwnode->dev->driver, meaning the driver was never compiled in
>> or loaded as a module). This covers the case where probe rejection
>> never happens because no driver ever matches.
>>
>> fwnode->dev is not serialized by a lock; instead every writer only ever
>> touches a fwnode->dev it already owns (== dev, as device_del() does when
>> it clears ownership) or one that is currently unowned (== NULL, as
>> device_add() does when it claims ownership). This patch follows the same
>> discipline: fw_devlink_release_shared_fwnode() only writes fwnode->dev
>> when this device is the current owner; device_links_driver_bound() only
>> claims fwnode->dev when it is NULL or when the current owner has no
>> driver (and therefore cannot be in the process of binding).
>>
>> Fixes: f9aa460672c9 ("driver core: Refactor fw_devlink feature")
>> Cc: stable@vger.kernel.org
>> Assisted-by: LLM
>> Signed-off-by: Peng Fan <peng.fan@nxp.com>
>> ---
>> This issue is triggered by
>> aac4e67d6eb9 ("firmware: arm_scmi: Always create devices for standard protocols")
>> in linux-next next-20260925.
>>
>> But I think this is a fix to
>> f9aa460672c9 ("driver core: Refactor fw_devlink feature")
>>
>
>Does dropping i.MX specials from list of devices solves the problem ?
No - dropping "pinctrl-imx" from scmi_std_id_table would not fix it
when both drivers are built-in, because scmi_protocol_device_request()
from the driver registration path still creates both devices.
>I am more than happy to drop i.MX special in the code and let you
>sort the pinmux mess you guys have created.
I understand the concern about platform-specific code in the standard
table. But the issue is not specific to pinctrl-imx - it is a generic
fw_devlink gap that affects any bus creating multiple devices per fwnode.
The same structural pattern exists for SCMI_PROTOCOL_PERF ("perf" +
"cpufreq") and SCMI_PROTOCOL_SENSOR ("hwmon" + "iiodev").
Cristian also shared his insights before, in [3].
"
....while other drivers exists that share the usage of the same protocol
(HWMON/IIO GENPD/CPUFREQ), they use the same protocol to achieve different
things in different subsytems...and they are anyway impacted (even to a less
degree) by this fw_devlink issue AFAIU so the problem indeed exist also
out of pinctrl-imx
"
[3] https://lore.kernel.org/all/Z65U2SMwSiOFYC0v@pluto/
>
>And also I remember you creating situation disabling cpufreq in the cmdline.
>Will that be ever used on those i.MX platforms ?
For the PERF pair, both drivers bind successfully today so there is no
issue in practice. But if "perf" (the fwnode owner) fails probe while
"cpufreq" binds, the same fwnode ownership deadlock occurs. This is not
about disabling cpufreq - it is about the owner device failing to bind
for any reason.
>
>I am not against the patch if others are OK.
Thanks. The patch fixes a generic fw_devlink gap in driver_bound()
where a device binding successfully on a shared fwnode cannot resolve
dangling consumers of child fwnodes because it is not the fwnode owner.
The fix follows the existing fwnode->dev ownership discipline (only
writing fwnode->dev when it is NULL, owned by self, or owned by a
driverless device) and handles all three scenarios:
1. Owner probe rejected (-ENODEV/-ENXIO) - owner hands off in
really_probe() failure path
2. Owner rejected earlier, fwnode now unowned - sibling re-acquires
in driver_bound()
3. Owner's driver never compiled/loaded - sibling takes over from
driverless owner in driver_bound()
If driver core maintainers have better solution for the case that
multiple devices share one fwnode, I would appreciate.
Thanks
Peng
>
>--
>Regards,
>Sudeep
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] driver core: hand off fwnode ownership when shared fwnode owner is rejected
2026-09-29 1:47 ` Peng Fan
@ 2026-09-29 8:35 ` Sudeep Holla
2026-09-29 15:56 ` Sudeep Holla
0 siblings, 1 reply; 5+ messages in thread
From: Sudeep Holla @ 2026-09-29 8:35 UTC (permalink / raw)
To: Peng Fan
Cc: Cristian Marussi, Sudeep Holla, Greg Kroah-Hartman,
Rafael J. Wysocki, Danilo Krummrich, Saravana Kannan,
Hans de Goede, driver-core, linux-kernel, imx, Peng Fan, stable
On Tue, Sep 29, 2026 at 09:47:42AM +0800, Peng Fan wrote:
> Hi Sudeep,
>
> On Mon, Sep 28, 2026 at 01:09:08PM +0100, Sudeep Holla wrote:
> >On Mon, Sep 28, 2026 at 07:49:01PM +0800, Peng Fan (OSS) wrote:
> >> From: Peng Fan <peng.fan@nxp.com>
> >>
> >> When multiple devices share the same fwnode (e.g. the SCMI bus creates
> >> both "pinctrl" and "pinctrl-imx" devices for SCMI_PROTOCOL_PINCTRL), only
> >> the first device registered becomes the fwnode owner (fwnode->dev, set in
> >
> >This has been rejected in the past. Apart from the trigger in -next,
> >anything else has changed ?
>
> When both pinctrl-scmi.c and pinctrl-imx-scmi.c are built into the
> kernel Image, both drivers call module_scmi_driver() at init time, which
> goes through:
> scmi_driver_register()
> → scmi_protocol_table_register(id_table)
> → scmi_protocol_device_request()
> → scmi_device_request_notifier()
> → scmi_create_protocol_devices(fwnode, ..., "pinctrl-imx")
> So the on-demand path already creates both "pinctrl" and "pinctrl-imx"
Yes, but this particular device is i.MX specific issue as it should
have never been there. So I will discard that in any future discussion.
Use the SCMI pinmux driver and get rid of SCMI pinctrl-imx.
> devices for protocol@19, sharing the same fwnode, regardless of
> scmi_std_id_table. aac4e67d6eb9 just added a second path that does
> the same thing earlier - the fundamental problem existed before it.
>
> This issue has been here for 2 years.
Thanks for clarifying this. You initial email seem to directly blame
the commit in -next. Please don't bring that commit into discussion then.
It was completely misleading.
> I proposed a patch in scmi side [1][2], but never made into mainline.
> [1] https://lore.kernel.org/all/CAGETcx87Stfkru9gJrc1sf=PtFGLY7=jrfFaCzK5Z4hq+2TCzg@mail.gmail.com/
> [2] https://lore.kernel.org/arm-scmi/ZryUgTOVr_haiHuh@pluto/
>
> The issue is not specific to pinctrl w/o imx.
>
Agreed. Perf/cpufreq is another possible issue you have brought up IIRC.
Since cpufreq must not have dependency like pinmux, we should be able to solve
it in some other way.
> The problem is that two devices share one fwnode, the first one registered
> claims fwnode->dev, and if it never binds, driver_bound() of the second
> device skips the dangling consumer pickup because fwnode->dev != dev.
>
Agreed, but it shouldn't be the normal case unless there is a strong need
and there is the dependency you mention or you mess up by creating duplicate
devices like pinmux-imx. That's you own doing, sorry.
[...]
> >
> >Does dropping i.MX specials from list of devices solves the problem ?
>
> No - dropping "pinctrl-imx" from scmi_std_id_table would not fix it
> when both drivers are built-in, because scmi_protocol_device_request()
> from the driver registration path still creates both devices.
>
OK, thanks for the confirmation.
> >I am more than happy to drop i.MX special in the code and let you
> >sort the pinmux mess you guys have created.
>
> I understand the concern about platform-specific code in the standard
> table. But the issue is not specific to pinctrl-imx - it is a generic
> fw_devlink gap that affects any bus creating multiple devices per fwnode.
> The same structural pattern exists for SCMI_PROTOCOL_PERF ("perf" +
> "cpufreq") and SCMI_PROTOCOL_SENSOR ("hwmon" + "iiodev").
>
Yes perf/cpufreq case I recall and we should be able to work out something.
Sensor has no dependency like pinmux and shouldn't be a problem. Have you
faced real issue with it ?
> Cristian also shared his insights before, in [3].
>
> "
> ....while other drivers exists that share the usage of the same protocol
> (HWMON/IIO GENPD/CPUFREQ), they use the same protocol to achieve different
> things in different subsytems...and they are anyway impacted (even to a less
> degree) by this fw_devlink issue AFAIU so the problem indeed exist also
> out of pinctrl-imx
> "
>
> [3] https://lore.kernel.org/all/Z65U2SMwSiOFYC0v@pluto/
>
I agree and that's what I mean above.
> >
> >And also I remember you creating situation disabling cpufreq in the cmdline.
> >Will that be ever used on those i.MX platforms ?
>
> For the PERF pair, both drivers bind successfully today so there is no
> issue in practice. But if "perf" (the fwnode owner) fails probe while
> "cpufreq" binds, the same fwnode ownership deadlock occurs. This is not
> about disabling cpufreq - it is about the owner device failing to bind
> for any reason.
>
Thanks for the explanation.
> >
> >I am not against the patch if others are OK.
>
> Thanks. The patch fixes a generic fw_devlink gap in driver_bound()
> where a device binding successfully on a shared fwnode cannot resolve
> dangling consumers of child fwnodes because it is not the fwnode owner.
> The fix follows the existing fwnode->dev ownership discipline (only
> writing fwnode->dev when it is NULL, owned by self, or owned by a
> driverless device) and handles all three scenarios:
> 1. Owner probe rejected (-ENODEV/-ENXIO) - owner hands off in
> really_probe() failure path
> 2. Owner rejected earlier, fwnode now unowned - sibling re-acquires
> in driver_bound()
> 3. Owner's driver never compiled/loaded - sibling takes over from
> driverless owner in driver_bound()
>
>
> If driver core maintainers have better solution for the case that
> multiple devices share one fwnode, I would appreciate.
>
IIRC, they don't want to use 2 device pointing to same fwnode.
--
Regards,
Sudeep
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] driver core: hand off fwnode ownership when shared fwnode owner is rejected
2026-09-29 8:35 ` Sudeep Holla
@ 2026-09-29 15:56 ` Sudeep Holla
0 siblings, 0 replies; 5+ messages in thread
From: Sudeep Holla @ 2026-09-29 15:56 UTC (permalink / raw)
To: Peng Fan
Cc: Cristian Marussi, Sudeep Holla, Greg Kroah-Hartman,
Rafael J. Wysocki, Danilo Krummrich, Saravana Kannan,
Hans de Goede, driver-core, linux-kernel, imx, Peng Fan, stable
On Tue, Sep 29, 2026 at 09:35:21AM +0100, Sudeep Holla wrote:
> On Tue, Sep 29, 2026 at 09:47:42AM +0800, Peng Fan wrote:
> > Hi Sudeep,
> >
> > On Mon, Sep 28, 2026 at 01:09:08PM +0100, Sudeep Holla wrote:
> > >On Mon, Sep 28, 2026 at 07:49:01PM +0800, Peng Fan (OSS) wrote:
> > >> From: Peng Fan <peng.fan@nxp.com>
> > >>
> > >> When multiple devices share the same fwnode (e.g. the SCMI bus creates
> > >> both "pinctrl" and "pinctrl-imx" devices for SCMI_PROTOCOL_PINCTRL), only
> > >> the first device registered becomes the fwnode owner (fwnode->dev, set in
> > >
> > >This has been rejected in the past. Apart from the trigger in -next,
> > >anything else has changed ?
> >
> > When both pinctrl-scmi.c and pinctrl-imx-scmi.c are built into the
> > kernel Image, both drivers call module_scmi_driver() at init time, which
> > goes through:
> > scmi_driver_register()
> > → scmi_protocol_table_register(id_table)
> > → scmi_protocol_device_request()
> > → scmi_device_request_notifier()
> > → scmi_create_protocol_devices(fwnode, ..., "pinctrl-imx")
> > So the on-demand path already creates both "pinctrl" and "pinctrl-imx"
>
> Yes, but this particular device is i.MX specific issue as it should
> have never been there. So I will discard that in any future discussion.
> Use the SCMI pinmux driver and get rid of SCMI pinctrl-imx.
>
Anyways, I cooked up a patch that may prevent the issue with pinmux.
See if something like below on top -next helps.
Regards,
Sudeep
-->8
diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index 25197197db8e..cee7cc777724 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -60,13 +60,6 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
pr_debug("Requesting SCMI device (%s) for protocol %x\n",
id_table->name, id_table->protocol_id);
- if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT) &&
- !IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX)) {
- pr_warn("SCMI Raw mode active. Rejecting '%s'/0x%02X\n",
- id_table->name, id_table->protocol_id);
- return -EINVAL;
- }
-
/*
* Find the matching protocol rdev list and then search of any
* existent equally named device...fails if any duplicate found.
@@ -181,12 +174,35 @@ static void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table
}
}
+static bool scmi_device_id_in_std_id_table(const struct scmi_device_id *id)
+{
+ for (int i = 0; scmi_std_id_table[i].name[0]; i++) {
+ if (scmi_std_id_table[i].protocol_id == id->protocol_id &&
+ !strcmp(scmi_std_id_table[i].name, id->name))
+ return true;
+ }
+
+ return false;
+}
+
static int scmi_protocol_table_register(const struct scmi_device_id *id_table)
{
const struct scmi_device_id *entry;
int ret;
for (entry = id_table; entry->name[0]; entry++) {
+ if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT) &&
+ !IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX)) {
+ pr_warn("SCMI Raw mode active. Rejecting '%s'/0x%02X\n",
+ entry->name, entry->protocol_id);
+ ret = -EINVAL;
+ goto err_unrequest;
+ }
+
+ /* Standard devices are created independently of their drivers. */
+ if (scmi_device_id_in_std_id_table(entry))
+ continue;
+
ret = scmi_protocol_device_request(entry);
if (ret)
goto err_unrequest;
@@ -195,8 +211,11 @@ static int scmi_protocol_table_register(const struct scmi_device_id *id_table)
return 0;
err_unrequest:
- while (entry != id_table)
- scmi_protocol_device_unrequest(--entry);
+ while (entry != id_table) {
+ --entry;
+ if (!scmi_device_id_in_std_id_table(entry))
+ scmi_protocol_device_unrequest(entry);
+ }
return ret;
}
@@ -206,8 +225,10 @@ scmi_protocol_table_unregister(const struct scmi_device_id *id_table)
{
const struct scmi_device_id *entry;
- for (entry = id_table; entry->name[0]; entry++)
- scmi_protocol_device_unrequest(entry);
+ for (entry = id_table; entry->name[0]; entry++) {
+ if (!scmi_device_id_in_std_id_table(entry))
+ scmi_protocol_device_unrequest(entry);
+ }
}
static bool scmi_device_is_transport(const struct scmi_device *scmi_dev)
@@ -545,21 +566,9 @@ static const struct scmi_device_id scmi_std_id_table[] = {
{ SCMI_PROTOCOL_VOLTAGE, "regulator" },
{ SCMI_PROTOCOL_POWERCAP, "powercap" },
{ SCMI_PROTOCOL_PINCTRL, "pinctrl" },
- { SCMI_PROTOCOL_PINCTRL, "pinctrl-imx" },
{ },
};
-static bool scmi_device_id_in_std_id_table(const struct scmi_device_id *id)
-{
- for (int i = 0; scmi_std_id_table[i].name[0]; i++) {
- if (scmi_std_id_table[i].protocol_id == id->protocol_id &&
- !strcmp(scmi_std_id_table[i].name, id->name))
- return true;
- }
-
- return false;
-}
-
/**
* scmi_device_create - A method to create one or more SCMI devices
*
diff --git a/drivers/pinctrl/freescale/pinctrl-imx-scmi.c b/drivers/pinctrl/freescale/pinctrl-imx-scmi.c
index 613552e35070..b259a526ccc1 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx-scmi.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx-scmi.c
@@ -354,7 +354,7 @@ static int scmi_pinctrl_imx_probe(struct scmi_device *sdev)
}
static const struct scmi_device_id scmi_id_table[] = {
- { SCMI_PROTOCOL_PINCTRL, "pinctrl-imx" },
+ { SCMI_PROTOCOL_PINCTRL, "pinctrl" },
{ }
};
MODULE_DEVICE_TABLE(scmi, scmi_id_table);
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-29 15:56 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-28 11:49 [PATCH] driver core: hand off fwnode ownership when shared fwnode owner is rejected Peng Fan (OSS)
2026-09-28 12:09 ` Sudeep Holla
2026-09-29 1:47 ` Peng Fan
2026-09-29 8:35 ` Sudeep Holla
2026-09-29 15:56 ` Sudeep Holla
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®