]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
firmware: arm_scmi: optee: Rework transport probe sequence
authorCristian Marussi <cristian.marussi@arm.com>
Sun, 10 May 2026 16:05:27 +0000 (17:05 +0100)
committerSudeep Holla <sudeep.holla@kernel.org>
Thu, 21 May 2026 16:31:51 +0000 (17:31 +0100)
Use the new per-instance transport handles helpers to synchronize and
optionally defer the core SCMI driver probe up until the transport driver
has completely been initialized and it is fully operational as a supplier.

Introduce proper module init/exit routines while removing the ugly trick of
registering a driver from within the probe sequence of another one, just to
avoid to have to deal with probe deferrals.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Link: https://patch.msgid.link/20260510160527.3537474-5-cristian.marussi@arm.com
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
drivers/firmware/arm_scmi/transports/optee.c

index 07ae18d5279d9efe9fc160bd7198ad581351befb..dbe32e141748b32821535f16e5a97f91a07bdf1d 100644 (file)
@@ -154,6 +154,8 @@ static struct scmi_transport_core_operations *core;
 /* There can be only 1 SCMI service in OP-TEE we connect to */
 static struct scmi_optee_agent *scmi_optee_private;
 
+static DEFINE_SCMI_TRANSPORT_SUPPLIER(scmi_optee_supplier);
+
 /* Open a session toward SCMI OP-TEE service with REE_KERNEL identity */
 static int open_session(struct scmi_optee_agent *agent, u32 *tee_session)
 {
@@ -522,7 +524,7 @@ static struct scmi_desc scmi_optee_desc = {
 };
 
 static const struct of_device_id scmi_of_match[] = {
-       { .compatible = "linaro,scmi-optee" },
+       { .compatible = "linaro,scmi-optee", .data = &scmi_optee_supplier.th},
        { /* Sentinel */ },
 };
 
@@ -561,18 +563,20 @@ static int scmi_optee_service_probe(struct tee_client_device *scmi_pta)
        if (ret)
                goto err;
 
-       /* Ensure agent resources are all visible before scmi_optee_private is */
+       /* Ensure initialized scmi_optee_private is visible */
        smp_mb();
        scmi_optee_private = agent;
 
-       ret = platform_driver_register(&scmi_optee_driver);
-       if (ret) {
-               scmi_optee_private = NULL;
-               goto err;
-       }
+       ret = scmi_transport_supplier_put(&scmi_optee_supplier.th, agent->dev);
+       if (ret)
+               goto err_put;
 
        return 0;
 
+err_put:
+       /* Ensure cleared reference is visible before resources are released */
+       smp_store_mb(scmi_optee_private, NULL);
+
 err:
        tee_client_close_context(tee_ctx);
 
@@ -586,13 +590,12 @@ static void scmi_optee_service_remove(struct tee_client_device *scmi_pta)
        if (!scmi_optee_private)
                return;
 
-       platform_driver_unregister(&scmi_optee_driver);
-
        if (!list_empty(&scmi_optee_private->channel_list))
                return;
 
        /* Ensure cleared reference is visible before resources are released */
        smp_store_mb(scmi_optee_private, NULL);
+       scmi_transport_supplier_put(&scmi_optee_supplier.th, agent->dev);
 
        tee_client_close_context(agent->tee_ctx);
 }
@@ -616,7 +619,30 @@ static struct tee_client_driver scmi_optee_service_driver = {
        },
 };
 
-module_tee_client_driver(scmi_optee_service_driver);
+static int __init scmi_transport_optee_init(void)
+{
+       int ret;
+
+       ret = tee_client_driver_register(&scmi_optee_service_driver);
+       if (ret)
+               return ret;
+
+       ret = platform_driver_register(&scmi_optee_driver);
+       if (ret) {
+               tee_client_driver_unregister(&scmi_optee_service_driver);
+               return ret;
+       }
+
+       return ret;
+}
+module_init(scmi_transport_optee_init);
+
+static void __exit scmi_transport_optee_exit(void)
+{
+       platform_driver_unregister(&scmi_optee_driver);
+       tee_client_driver_unregister(&scmi_optee_service_driver);
+}
+module_exit(scmi_transport_optee_exit);
 
 MODULE_AUTHOR("Etienne Carriere <etienne.carriere@foss.st.com>");
 MODULE_DESCRIPTION("SCMI OPTEE Transport driver");