drivers/bus/fsl-mc/fsl-mc-bus.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-)
From: Vincent Jardin <vjardin@free.fr>
Unbinding and re-binding the root DPRC fails with:
sysfs: cannot create duplicate filename '/dev/char/10:256'
misc_register / fsl_mc_uapi_create_device_file /
dprc_setup / dprc_probe
Cc: stable+noautosel@kernel.org # niche: root DPRC unbind/rebind only
Fixes: 2cf1e703f066 ("bus: fsl-mc: add fsl-mc userspace support")
Signed-off-by: Vincent Jardin <vjardin@free.fr>
---
Issue found when unbinding/rebinding the root DPRC on an LX2160A.
The failure is silent at bind time and only shows up as a
duplicate /dev/char entry on the second bind.
---
drivers/bus/fsl-mc/fsl-mc-bus.c | 40 ++++++++++++++++++++++++----------------
1 file changed, 24 insertions(+), 16 deletions(-)
diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 66a4fa73c5b86..7f283844e4500 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -1264,35 +1264,43 @@ static int __init fsl_mc_bus_driver_init(void)
error = bus_register(&fsl_mc_bus_type);
if (error < 0) {
pr_err("bus type registration failed: %d\n", error);
- goto error_cleanup_cache;
+ return error;
}
- error = platform_driver_register(&fsl_mc_bus_driver);
- if (error < 0) {
- pr_err("platform_driver_register() failed: %d\n", error);
+ error = bus_register_notifier(&platform_bus_type, &fsl_mc_nb);
+ if (error < 0)
goto error_cleanup_bus;
- }
+
+ return 0;
+
+error_cleanup_bus:
+ bus_unregister(&fsl_mc_bus_type);
+ return error;
+}
+postcore_initcall(fsl_mc_bus_driver_init);
+
+static int __init fsl_mc_bus_drivers_init(void)
+{
+ int error;
error = dprc_driver_init();
if (error < 0)
- goto error_cleanup_driver;
+ return error;
error = fsl_mc_allocator_driver_init();
if (error < 0)
goto error_cleanup_dprc_driver;
- return bus_register_notifier(&platform_bus_type, &fsl_mc_nb);
+ error = platform_driver_register(&fsl_mc_bus_driver);
+ if (error < 0) {
+ pr_err("platform_driver_register() failed: %d\n", error);
+ goto error_cleanup_dprc_driver;
+ }
+
+ return 0;
error_cleanup_dprc_driver:
dprc_driver_exit();
-
-error_cleanup_driver:
- platform_driver_unregister(&fsl_mc_bus_driver);
-
-error_cleanup_bus:
- bus_unregister(&fsl_mc_bus_type);
-
-error_cleanup_cache:
return error;
}
-postcore_initcall(fsl_mc_bus_driver_init);
+subsys_initcall_sync(fsl_mc_bus_drivers_init);
---
base-commit: 786262be6048deab760f68c8acc2c85607165894
change-id: 20260922-for-upstream-fsl-mc-initcall-order-e3316390712b
Best regards,
--
Vincent Jardin <vjardin@free.fr>
On Tue, Sep 01, 2026 at 10:04:37PM +0200, Vincent Jardin via B4 Relay wrote: > From: Vincent Jardin <vjardin@free.fr> > > Unbinding and re-binding the root DPRC fails with: > > sysfs: cannot create duplicate filename '/dev/char/10:256' > misc_register / fsl_mc_uapi_create_device_file / > dprc_setup / dprc_probe > I have no comments on the actual code changes, only that the patch would benefit from a more complete message. Please explain a bit when the issue happens (only when the fsl-mc bus probe is not defered - meaning no smmu). Also mention in the commit message as well that you are moving the dprc and allocator drivers registration at the subsys_initcall_sync stage while the misc_init() is called at subsys_initcall. Ioana
On Tue, Sep 01, 2026 at 10:04:37PM +0200, Vincent Jardin via B4 Relay wrote: > From: Vincent Jardin <vjardin@free.fr> > > Unbinding and re-binding the root DPRC fails with: > > sysfs: cannot create duplicate filename '/dev/char/10:256' > misc_register / fsl_mc_uapi_create_device_file / > dprc_setup / dprc_probe > Do you mean that the above error messages are triggered by an unbind and bind sequence like below? $ echo dprc.1 > /sys/bus/fsl-mc/drivers/fsl_mc_dprc/unbind $ echo dprc.1 > /sys/bus/fsl-mc/drivers/fsl_mc_dprc/bind I am asking this because I cannot seem to trigger it myself. There is a misc_deregister() which should remove the char device upon unbinding the root DPRC. Ioana
Hi Ioana,
> Do you mean that the above error messages are triggered by an unbind and
> bind sequence like below?
>
> $ echo dprc.1 > /sys/bus/fsl-mc/drivers/fsl_mc_dprc/unbind
> $ echo dprc.1 > /sys/bus/fsl-mc/drivers/fsl_mc_dprc/bind
Yes, same sequence on the root DPRC
> I am asking this because I cannot seem to trigger it myself. There is a
> misc_deregister() which should remove the char device upon unbinding the
> root DPRC.
It does for every normal misc device, but not for this one, because the
root DPRC's misc device is created classless.
You can check the states with:
grep dprc /proc/misc # e.g. "256 dprc.1" -> registered
ls /sys/class/misc/ | grep dprc
If dprc.1 shows in /proc/misc but is absent from /sys/class/misc, its
misc device is classless and the unbind/bind should collide. If it is
present under /sys/class/misc, it was created after misc_class and the
sequence is clean on your setup.
fsl_mc_bus_driver_init() is a postcore_initcall, it registers both the
platform and the dprc drivers.
The fsl-mc DT node is populated at arch_initcall_sync, so the root DPRC
probes synchronously.
dprc_setup() -> fsl_mc_uapi_create_device_file() -> misc_register() runs
before misc_init() does class_register(&misc_class) at subsys_initcall.
misc_register() does not fail in that window: device_create_with_groups()
with an unregistered class creates the device with no misc_class
membership and still returns 0.
-> So at unbind, misc_deregister() -> device_destroy(&misc_class, devt)
cannot find the device within misc_class, it returns without removing it,
and then it leaks the device + its /sys/dev/char/10:<minor> link while freeing
the minor. The next bind reuses the minor and dies on the
duplicate /sys/dev/char/ entry.
I guess, from my setup, it happens when the root DPRC's misc device is
created during the early probe, which needs CONFIG_FSL_MC_UAPI_SUPPORT=y,
fsl-mc built in (not a module), and the root DPRC probe not going through
EPROBE_DEFER.
If it defers, the retry runs after subsys_initcall, misc_class exists,
and unbind/bind is clean -> which is probably what you are seeing.
I started to face this issue when I did try to restart
the MC from Linux userland instead of uboot in order to be able to adapt
with some DPC changes during the runtime.
see https://github.com/vjardin/lx2160-sdx/blob/main/src/lx2160-mc.c
But I guess this issue should be quite generic.
best regards,
Vincent
On Mon, Sep 07, 2026 at 06:30:17PM +0200, Vincent Jardin wrote: > Hi Ioana, > > > Do you mean that the above error messages are triggered by an unbind and > > bind sequence like below? > > > > $ echo dprc.1 > /sys/bus/fsl-mc/drivers/fsl_mc_dprc/unbind > > $ echo dprc.1 > /sys/bus/fsl-mc/drivers/fsl_mc_dprc/bind > > Yes, same sequence on the root DPRC > > > I am asking this because I cannot seem to trigger it myself. There is a > > misc_deregister() which should remove the char device upon unbinding the > > root DPRC. > > It does for every normal misc device, but not for this one, because the > root DPRC's misc device is created classless. > > You can check the states with: > grep dprc /proc/misc # e.g. "256 dprc.1" -> registered > ls /sys/class/misc/ | grep dprc > > If dprc.1 shows in /proc/misc but is absent from /sys/class/misc, its > misc device is classless and the unbind/bind should collide. If it is > present under /sys/class/misc, it was created after misc_class and the > sequence is clean on your setup. Yes, it is present under /sys/class/misc. $ grep dprc /proc/misc 260 dprc.1 $ ls /sys/class/misc/ | grep dprc dprc.1 > > fsl_mc_bus_driver_init() is a postcore_initcall, it registers both the > platform and the dprc drivers. > > The fsl-mc DT node is populated at arch_initcall_sync, so the root DPRC > probes synchronously. > > dprc_setup() -> fsl_mc_uapi_create_device_file() -> misc_register() runs > before misc_init() does class_register(&misc_class) at subsys_initcall. > > misc_register() does not fail in that window: device_create_with_groups() > with an unregistered class creates the device with no misc_class > membership and still returns 0. > > -> So at unbind, misc_deregister() -> device_destroy(&misc_class, devt) > cannot find the device within misc_class, it returns without removing it, > and then it leaks the device + its /sys/dev/char/10:<minor> link while freeing > the minor. The next bind reuses the minor and dies on the > duplicate /sys/dev/char/ entry. > > I guess, from my setup, it happens when the root DPRC's misc device is > created during the early probe, which needs CONFIG_FSL_MC_UAPI_SUPPORT=y, > fsl-mc built in (not a module), and the root DPRC probe not going through > EPROBE_DEFER. > > If it defers, the retry runs after subsys_initcall, misc_class exists, > and unbind/bind is clean -> which is probably what you are seeing. I am indeed in the case in which the uapi support is builtin but the dprc.1 probing is deferred, thus it will get executed after misc_init() had a chance to run. The deferral happens because of_dma_configure_id() returns EPROBE_DEFER since it waits for arm-ssmu to probe. How did you get past this deferral? > > I started to face this issue when I did try to restart > the MC from Linux userland instead of uboot in order to be able to adapt > with some DPC changes during the runtime. > see https://github.com/vjardin/lx2160-sdx/blob/main/src/lx2160-mc.c > But I guess this issue should be quite generic. Can you reproduce it without restarting the MC: boot to prompt, echo dprc.1 > .../unbind, echo dprc.1 > ..../bind ? Ioana
Hi Ioana,
> I am indeed in the case in which the uapi support is builtin but the
> dprc.1 probing is deferred, thus it will get executed after misc_init()
> had a chance to run.
>
> The deferral happens because of_dma_configure_id() returns EPROBE_DEFER
> since it waits for arm-ssmu to probe. How did you get past this
> deferral?
I think I isolated the difference: I guess you have smmu enabled while I
did disable it. I checked and when smmu is enabled back, the issue does
not show up anymore. But it is not my goal.
I do have with my dts,
&smmu {
status = "disabled";
};
for the mc to load, you need:
fsl_mc: fsl-mc@80c000000 {
compatible = "fsl,qoriq-mc";
...
iommu-map = <0 &smmu 0 0>;
dma-coherent;
};
it seems due to,
of_dma_configure_id() -> of_iommu_configure() ends up with "no IOMMU" and
it returns 0 instead of -EPROBE_DEFER.
So the root DPRC, populated at arch_initcall_sync, probes now
synchronously, before misc_init() registers misc_class at subsys_initcall
and so dprc.1 is created classless. (I hope I did not miss something).
> > I started to face this issue when I did try to restart
> > the MC from Linux userland instead of uboot in order to be able to adapt
> > with some DPC changes during the runtime.
> > see https://github.com/vjardin/lx2160-sdx/blob/main/src/lx2160-mc.c
> > But I guess this issue should be quite generic.
>
> Can you reproduce it without restarting the MC: boot to prompt, echo
> dprc.1 > .../unbind, echo dprc.1 > ..../bind ?
Yes, see below, even without restarting the MC.
smmu disabled / without the patch of this serie:
# grep dprc /proc/misc
256 dprc.1
# ls /sys/class/misc/ | grep dprc # nothing: not in the class
# ls -l /sys/dev/char/10:256
... /sys/dev/char/10:256 -> ../../devices/dprc.1 <- not under devices/virtual/misc
Unbind: the minor is freed but the char link leaks:
# echo dprc.1 > /sys/bus/fsl-mc/drivers/fsl_mc_dprc/unbind
[ 201.633695] fsl_mc_dprc dprc.1: DPRC device unbound from driver
# grep dprc /proc/misc <- gone (minor 256 freed)
# ls -l /sys/dev/char/10:256
... /sys/dev/char/10:256 -> ../../devices/dprc.1 <- still here: leaked
Bind:
# echo dprc.1 > /sys/bus/fsl-mc/drivers/fsl_mc_dprc/bind
sh: write error: Resource temporarily unavailable
[ 203.306315] sysfs: cannot create duplicate filename '/dev/char/10:256'
[ 203.306356] Call trace:
...
[ 203.306440] misc_register+0xcc/0x158
[ 203.306449] fsl_mc_uapi_create_device_file+0x44/0x74
[ 203.306462] dprc_setup+0x134/0x214
[ 203.306471] dprc_probe+0x18/0xec
[ 203.306480] fsl_mc_probe+0x1c/0x30
...
[ 203.306517] bind_store+0xa8/0xc4
With the patch applied on the same board, smmu disabled, then, it is fine.
This apply patch should be ok for smmu and not smmu in order to cover any cases now.
best regards,
Vincent
On Tue, Sep 08, 2026 at 06:17:24PM +0200, Vincent Jardin wrote:
> Hi Ioana,
>
> > I am indeed in the case in which the uapi support is builtin but the
> > dprc.1 probing is deferred, thus it will get executed after misc_init()
> > had a chance to run.
> >
> > The deferral happens because of_dma_configure_id() returns EPROBE_DEFER
> > since it waits for arm-ssmu to probe. How did you get past this
> > deferral?
>
> I think I isolated the difference: I guess you have smmu enabled while I
> did disable it. I checked and when smmu is enabled back, the issue does
> not show up anymore. But it is not my goal.
I am not trying to convince you that the patch is not necessary, I am
just trying to identify the scope of the issue correctly.
>
> I do have with my dts,
> &smmu {
> status = "disabled";
> };
>
> for the mc to load, you need:
> fsl_mc: fsl-mc@80c000000 {
> compatible = "fsl,qoriq-mc";
> ...
> iommu-map = <0 &smmu 0 0>;
> dma-coherent;
> };
>
> it seems due to,
> of_dma_configure_id() -> of_iommu_configure() ends up with "no IOMMU" and
> it returns 0 instead of -EPROBE_DEFER.
>
> So the root DPRC, populated at arch_initcall_sync, probes now
> synchronously, before misc_init() registers misc_class at subsys_initcall
> and so dprc.1 is created classless. (I hope I did not miss something).
With smmu disabled from the DT, I can now reproduce the problem.
Thanks!
© 2016 - 2026 Red Hat, Inc.