On 23-09-2026 14:09, Vinayak Katoch wrote: > of_platform_populate() only guarantees that child devices are registered, > not that their probes have completed before it returns. This creates a > window where fastrpc_cb_init() may not have run for all context bank > nodes, leaving the channel context partially initialised. > > Introduce fastrpc_cb_devices_create() to iterate over child DT nodes > directly and call fastrpc_cb_init() synchronously for each > qcom,fastrpc-compute-cb node. This ensures all context banks are fully > initialised before fastrpc_rpmsg_probe() returns. > > Introduce fastrpc_cb_devices_destroy() as the symmetric counterpart. > Before destroying the CB platform devices, invalidate all sessions under > the channel lock so that any fastrpc_user still holding a reference to > the channel context cannot acquire a new session backed by a destroyed > device. > > Since fastrpc_cb_driver is no longer needed as an independent platform > driver, remove it along with its match table and remove callback. Use > module_rpmsg_driver() now that only a single driver registration remains. > > Signed-off-by: Vinayak Katoch <[email protected]> > --- > drivers/misc/fastrpc.c | 104 > ++++++++++++++++++++++++------------------------- > 1 file changed, 52 insertions(+), 52 deletions(-) > > diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c > index af18ff1992ee..f20d3e5ecc81 100644 > --- a/drivers/misc/fastrpc.c > +++ b/drivers/misc/fastrpc.c > @@ -2333,7 +2333,7 @@ static const struct file_operations fastrpc_fops = { > .compat_ioctl = fastrpc_device_ioctl, > }; > > -static int fastrpc_cb_probe(struct platform_device *pdev) > +static int fastrpc_cb_init(struct platform_device *pdev) > { > struct fastrpc_channel_ctx *cctx; > struct fastrpc_session_ctx *sess; > @@ -2355,7 +2355,7 @@ static int fastrpc_cb_probe(struct platform_device > *pdev) > spin_lock_irqsave(&cctx->lock, flags); > if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) { > spin_unlock_irqrestore(&cctx->lock, flags); > - dev_err(&pdev->dev, "too many sessions\n"); > + dev_err(dev, "too many sessions\n"); > return -ENOSPC; > } > dma_bits = cctx->soc_data->dma_addr_bits_default; > @@ -2389,37 +2389,63 @@ static int fastrpc_cb_probe(struct platform_device > *pdev) > return 0; > } > > -static void fastrpc_cb_remove(struct platform_device *pdev) > +static void fastrpc_cb_devices_destroy(struct rpmsg_device *rpdev) > { > - struct fastrpc_channel_ctx *cctx = dev_get_drvdata(pdev->dev.parent); > - struct fastrpc_session_ctx *sess = dev_get_drvdata(&pdev->dev); if this dev_get_drvdata() is not used, can you also remove dev_set_drvdata()?> + struct fastrpc_channel_ctx *cctx = dev_get_drvdata(&rpdev->dev); > + struct device *rdev = &rpdev->dev; > + struct platform_device *pdev; > + struct device_node *np; > unsigned long flags; > int i; > > spin_lock_irqsave(&cctx->lock, flags); > - for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) { > - if (cctx->session[i].sid == sess->sid) { > - cctx->session[i].valid = false; > - cctx->sesscount--; > + for (i = 0; i < cctx->sesscount; i++) > + cctx->session[i].valid = false; > + spin_unlock_irqrestore(&cctx->lock, flags); > + > + for_each_available_child_of_node(rdev->of_node, np) { > + if (!of_device_is_compatible(np, "qcom,fastrpc-compute-cb")) { can there be any such case?> + of_node_put(np); > + continue; > } > + > + pdev = of_find_device_by_node(np); > + of_node_put(np); > + if (pdev) > + of_platform_device_destroy(&pdev->dev, NULL); > } can you check if this works here instead of above blob: device_for_each_child_reverse(rdev, NULL, of_platform_device_destroy);> - spin_unlock_irqrestore(&cctx->lock, flags); > } > > -static const struct of_device_id fastrpc_match_table[] = { > - { .compatible = "qcom,fastrpc-compute-cb" }, > - { } > -}; > +static int fastrpc_cb_devices_create(struct rpmsg_device *rpdev) > +{ > + struct device *rdev = &rpdev->dev; > + struct platform_device *pdev; > + struct device_node *np; > + int err; > > -static struct platform_driver fastrpc_cb_driver = { > - .probe = fastrpc_cb_probe, > - .remove = fastrpc_cb_remove, > - .driver = { > - .name = "qcom,fastrpc-cb", > - .of_match_table = fastrpc_match_table, > - .suppress_bind_attrs = true, > - }, > -}; > + for_each_available_child_of_node(rdev->of_node, np) { > + if (!of_device_is_compatible(np, "qcom,fastrpc-compute-cb")) { > + of_node_put(np); > + continue; > + } > + > + pdev = of_platform_device_create(np, NULL, rdev); > + if (!pdev) { > + of_node_put(np); > + fastrpc_cb_devices_destroy(rpdev); > + return -EINVAL; -ENODEV?> + } > + > + err = fastrpc_cb_init(pdev); > + if (err) { > + of_node_put(np); > + fastrpc_cb_devices_destroy(rpdev); > + return err; > + } > + } > + > + return 0; > +} > > static int fastrpc_device_register(struct device *dev, struct > fastrpc_channel_ctx *cctx, > bool is_secured, const char *domain) > @@ -2639,7 +2665,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device > *rpdev) > data->rpdev = rpdev; > dev_set_drvdata(&rpdev->dev, data); > > - err = of_platform_populate(rdev->of_node, NULL, NULL, rdev); > + err = fastrpc_cb_devices_create(rpdev); > if (err) > goto err_deregister_fdev; > > @@ -2711,7 +2737,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device > *rpdev) > &cctx->remote_heap_addr, > cctx->remote_heap_size, err); > } > > - of_platform_depopulate(&rpdev->dev); > + fastrpc_cb_devices_destroy(rpdev); > > fastrpc_channel_ctx_put(cctx); > } > @@ -2798,33 +2824,7 @@ static struct rpmsg_driver fastrpc_driver = { > }, > }; > > -static int fastrpc_init(void) > -{ > - int ret; > - > - ret = platform_driver_register(&fastrpc_cb_driver); > - if (ret < 0) { > - pr_err("fastrpc: failed to register cb driver\n"); > - return ret; > - } > - > - ret = register_rpmsg_driver(&fastrpc_driver); > - if (ret < 0) { > - pr_err("fastrpc: failed to register rpmsg driver\n"); > - platform_driver_unregister(&fastrpc_cb_driver); > - return ret; > - } > - > - return 0; > -} > -module_init(fastrpc_init); > - > -static void fastrpc_exit(void) > -{ > - platform_driver_unregister(&fastrpc_cb_driver); > - unregister_rpmsg_driver(&fastrpc_driver); > -} > -module_exit(fastrpc_exit); > +module_rpmsg_driver(fastrpc_driver); > > MODULE_DESCRIPTION("Qualcomm FastRPC"); > MODULE_LICENSE("GPL v2"); >
