From 4a9927e26fb95fefdc31c3929163696600ae1ba8 Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Wed, 26 Aug 2026 18:55:49 +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. Iterate over the child device tree nodes directly, initialising each qcom,fastrpc-compute-cb device synchronously. This ensures all context banks are fully initialised before fastrpc_rpmsg_probe() returns. Since fastrpc_cb_driver is no longer needed as an independent platform driver, remove it along with its match table and remove callback. Set OF_POPULATED_BUS on the rpmsg node so that of_platform_depopulate() correctly removes the manually created CB devices on teardown. Link: https://lore.kernel.org/all/20260826-dup-sessions-v4-1-35555d2bfed4@oss.qualcomm.com/ Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 84 +++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 55 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 2150bf00f518e..9963123b3029b 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,38 +2446,6 @@ static int fastrpc_cb_probe(struct platform_device *pdev) return 0; } -static void fastrpc_cb_remove(struct platform_device *pdev) -{ - struct fastrpc_channel_ctx *cctx = dev_get_drvdata(pdev->dev.parent); - struct fastrpc_session_ctx *sess = dev_get_drvdata(&pdev->dev); - 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--; - } - } - spin_unlock_irqrestore(&cctx->lock, flags); -} - -static const struct of_device_id fastrpc_match_table[] = { - { .compatible = "qcom,fastrpc-compute-cb", }, - {} -}; - -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, - }, -}; - static int fastrpc_device_register(struct device *dev, struct fastrpc_channel_ctx *cctx, bool is_secured, const char *domain) { @@ -2731,12 +2699,29 @@ 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); - if (err) - goto err_deregister_fdev; + of_node_set_flag(rdev->of_node, OF_POPULATED_BUS); + + for_each_available_child_of_node_scoped(rdev->of_node, np) { + struct platform_device *pdev; + + if (!of_device_is_compatible(np, "qcom,fastrpc-compute-cb")) + continue; + + pdev = of_platform_device_create(np, NULL, rdev); + if (!pdev) { + err = -EINVAL; + goto err_depopulate; + } + + err = fastrpc_cb_init(pdev); + if (err) + goto err_depopulate; + } return 0; +err_depopulate: + of_platform_depopulate(rdev); err_deregister_fdev: if (data->fdevice) misc_deregister(&data->fdevice->miscdev); @@ -2772,7 +2757,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) struct fastrpc_channel_ctx *cctx = dev_get_drvdata(&rpdev->dev); struct fastrpc_user *user; unsigned long flags; - int err; + int err, i; /* No invocations past this point */ spin_lock_irqsave(&cctx->lock, flags); @@ -2810,6 +2795,11 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) } } + spin_lock_irqsave(&cctx->lock, flags); + for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) + cctx->session[i].valid = false; + spin_unlock_irqrestore(&cctx->lock, flags); + of_platform_depopulate(&rpdev->dev); fastrpc_channel_ctx_put(cctx); @@ -2873,28 +2863,12 @@ 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; + return register_rpmsg_driver(&fastrpc_driver); } module_init(fastrpc_init); static void fastrpc_exit(void) { - platform_driver_unregister(&fastrpc_cb_driver); unregister_rpmsg_driver(&fastrpc_driver); } module_exit(fastrpc_exit); From 978136ff63bf02a94851f8cf18185e098691a5c9 Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Wed, 26 Aug 2026 18:55:50 +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/20260826-dup-sessions-v4-2-35555d2bfed4@oss.qualcomm.com/ Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 9963123b3029b..04b575ee9fa36 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,7 +2401,6 @@ 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; int rc; @@ -2408,8 +2408,6 @@ static int fastrpc_cb_init(struct platform_device *pdev) if (!cctx) return -EINVAL; - of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions); - spin_lock_irqsave(&cctx->lock, flags); if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) { spin_unlock_irqrestore(&cctx->lock, flags); @@ -2426,16 +2424,6 @@ static int fastrpc_cb_init(struct platform_device *pdev) 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) { @@ -2718,6 +2706,22 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) goto err_depopulate; } + 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_depopulate: From 000708b7be8e7837ba1a2eba8e70f030b13fb8a0 Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Wed, 26 Aug 2026 18:55:51 +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/20260826-dup-sessions-v4-3-35555d2bfed4@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