bus: fsl-mc: register the object drivers after misc_class exists

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

It happens when the fsl-mc bus probe is not deferred, without SMMU:
- the dprc driver is registered at postcore_initcall,
- the DT node is populated at arch_initcall_sync,
- the root DPRC probes right there, before misc_init() has
  registered misc_class at subsys_initcall.

misc_register() still succeeds but the device gets
no class, so misc_deregister() at unbind cannot find it:
the minor is freed while the device and its /sys/dev/char/ link leak,
and then the next bind collides on the same minor.

Let's move the dprc and allocator drivers registration, and
platform_driver_register(), to subsys_initcall_sync, after misc_init()
at subsys_initcall.
bus_register() and the platform-bus notifier stay at postcore_initcall
so that fsl_mc_bus_notifier() still pauses the MC before the SMMU is probed.

Cc: stable+noautosel@kernel.org # niche: root DPRC unbind/rebind only
Fixes: 2cf1e703f0 ("bus: fsl-mc: add fsl-mc userspace support")
Signed-off-by: Vincent Jardin <vjardin@free.fr>
Reviewed-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Link: https://lore.kernel.org/r/20260909-for-upstream-fsl-mc-initcall-order-v2-1-b7a04634fcf1@free.fr
Signed-off-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
This commit is contained in:
Vincent Jardin 2026-09-09 19:04:40 +02:00 committed by Christophe Leroy (CS GROUP)
parent f85e5ec18e
commit 7e9023a18e

View File

@ -1265,35 +1265,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);