From 5671ad9c5875a96d35add58e142730079f7c9ec2 Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Wed, 23 Sep 2026 14:09:33 +0530 Subject: [PATCH 1/3] FROMLIST: misc: fastrpc: iterate CB nodes manually instead of of_platform_populate 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. Link: https://lore.kernel.org/all/20260923-dup-sessions-v5-1-e953133a1827@oss.qualcomm.com/ Signed-off-by: Vinayak Katoch --- 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 2150bf00f518e..65bd1f7202740 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -2395,7 +2395,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; @@ -2412,8 +2412,8 @@ static int fastrpc_cb_probe(struct platform_device *pdev) spin_lock_irqsave(&cctx->lock, flags); if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) { - dev_err(&pdev->dev, "too many sessions\n"); spin_unlock_irqrestore(&cctx->lock, flags); + dev_err(dev, "too many sessions\n"); return -ENOSPC; } sess = &cctx->session[cctx->sesscount++]; @@ -2446,37 +2446,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); + 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")) { + 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); } - 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; + } + + 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) @@ -2731,7 +2757,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; @@ -2810,7 +2836,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) } } - of_platform_depopulate(&rpdev->dev); + fastrpc_cb_devices_destroy(rpdev); fastrpc_channel_ctx_put(cctx); } @@ -2871,33 +2897,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"); From 42937566e45ba77eaa442faecdf6bf5686d36c57 Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Wed, 23 Sep 2026 14:09:34 +0530 Subject: [PATCH 2/3] FROMLIST: misc: fastrpc: move ADSP duplicate session creation to the driver For ADSP, only a limited number of FastRPC context banks (CBs) are available. Each CB supports a single session, which means only a few processes can run on ADSP simultaneously. If all sessions are consumed by fastrpc daemons, no session remains available when a user application starts, causing the application to fail. To work around this, qcom,nsessions = <5> was set in DT to duplicate sessions inline during fastrpc_cb_init(). This policy does not belong in DT and should be handled at the driver level instead. Remove the qcom,nsessions DT property read and the per-CB duplication logic from fastrpc_cb_init(). After all context banks have been initialised in fastrpc_rpmsg_probe(), append FASTRPC_DUP_SESSIONS (4) copies of the last session for the ADSP domain. Link: https://lore.kernel.org/all/20260923-dup-sessions-v5-2-e953133a1827@oss.qualcomm.com/ Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 65bd1f7202740..05de9b07598a6 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -33,6 +33,7 @@ #define CDSP_DOMAIN_ID (3) #define GDSP_DOMAIN_ID (4) #define FASTRPC_MAX_SESSIONS 14 +#define FASTRPC_DUP_SESSIONS 4 #define FASTRPC_MAX_VMIDS 16 #define FASTRPC_ALIGN 128 #define FASTRPC_MAX_FDLIST 16 @@ -2400,15 +2401,16 @@ static int fastrpc_cb_init(struct platform_device *pdev) struct fastrpc_channel_ctx *cctx; struct fastrpc_session_ctx *sess; struct device *dev = &pdev->dev; - int i, sessions = 0; unsigned long flags; + u32 sid = 0; int rc; cctx = dev_get_drvdata(dev->parent); if (!cctx) return -EINVAL; - of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions); + if (of_property_read_u32(dev->of_node, "reg", &sid)) + dev_info(dev, "FastRPC Session ID not specified in DT\n"); spin_lock_irqsave(&cctx->lock, flags); if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) { @@ -2420,23 +2422,11 @@ static int fastrpc_cb_init(struct platform_device *pdev) sess->used = false; sess->valid = true; sess->dev = dev; + sess->sid = sid; sess->coherent = of_property_read_bool(dev->of_node, "dma-coherent"); dev_set_drvdata(dev, sess); - - if (of_property_read_u32(dev->of_node, "reg", &sess->sid)) - dev_info(dev, "FastRPC Session ID not specified in DT\n"); - - if (sessions > 0) { - struct fastrpc_session_ctx *dup_sess; - - for (i = 1; i < sessions; i++) { - if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) - break; - dup_sess = &cctx->session[cctx->sesscount++]; - memcpy(dup_sess, sess, sizeof(*dup_sess)); - } - } spin_unlock_irqrestore(&cctx->lock, flags); + rc = dma_set_mask(dev, DMA_BIT_MASK(32)); if (rc) { dev_err(dev, "32-bit DMA enable failed\n"); @@ -2761,6 +2751,22 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) if (err) goto err_deregister_fdev; + if (data->domain_id == ADSP_DOMAIN_ID && data->sesscount > 0) { + struct fastrpc_session_ctx *last_sess; + struct fastrpc_session_ctx *dup_sess; + unsigned long flags; + + spin_lock_irqsave(&data->lock, flags); + last_sess = &data->session[data->sesscount - 1]; + for (i = 0; i < FASTRPC_DUP_SESSIONS; i++) { + if (data->sesscount >= FASTRPC_MAX_SESSIONS) + break; + dup_sess = &data->session[data->sesscount++]; + memcpy(dup_sess, last_sess, sizeof(*dup_sess)); + } + spin_unlock_irqrestore(&data->lock, flags); + } + return 0; err_deregister_fdev: From c8866a3afd133aabb93eccd932a3e067e0c04343 Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Wed, 23 Sep 2026 14:09:35 +0530 Subject: [PATCH 3/3] FROMLIST: dt-bindings: misc: qcom,fastrpc: deprecate qcom,nsessions The qcom,nsessions property was used to duplicate FastRPC sessions inline during context bank initialisation. Session duplication is now handled at the driver level, making this DT property redundant. Mark it deprecated. Link: https://lore.kernel.org/all/20260923-dup-sessions-v5-3-e953133a1827@oss.qualcomm.com/ Reviewed-by: Krzysztof Kozlowski Signed-off-by: Vinayak Katoch --- Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml b/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml index 3f6199fc9ae6a..063a4f3995829 100644 --- a/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml +++ b/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml @@ -89,8 +89,10 @@ patternProperties: qcom,nsessions: $ref: /schemas/types.yaml#/definitions/uint32 default: 1 + deprecated: true description: > A value indicating how many sessions can share this context bank. + Session duplication is now handled by the driver. required: - compatible