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 diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 2150bf00f518e..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 @@ -2395,12 +2396,11 @@ 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; struct device *dev = &pdev->dev; - int i, sessions = 0; unsigned long flags; int rc; @@ -2408,12 +2408,10 @@ static int fastrpc_cb_probe(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) { - 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++]; @@ -2426,16 +2424,6 @@ static int fastrpc_cb_probe(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) { @@ -2446,38 +2434,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 +2687,45 @@ 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; + } + + 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: + of_platform_depopulate(rdev); err_deregister_fdev: if (data->fdevice) misc_deregister(&data->fdevice->miscdev); @@ -2772,7 +2761,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 +2799,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 +2867,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);