summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCristian Marussi <cristian.marussi@arm.com>2026-05-10 19:05:27 +0300
committerSudeep Holla <sudeep.holla@kernel.org>2026-05-21 19:31:51 +0300
commit524abd2fa6907ebe2762342be339afcc5b227dc4 (patch)
tree079e4d2b33ae502a12ac8af55fe326daa4c81448
parentc08051901a55f8574968b606f960a70415be303c (diff)
downloadlinux-524abd2fa6907ebe2762342be339afcc5b227dc4.tar.xz
firmware: arm_scmi: optee: Rework transport probe sequence
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>
-rw-r--r--drivers/firmware/arm_scmi/transports/optee.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/drivers/firmware/arm_scmi/transports/optee.c b/drivers/firmware/arm_scmi/transports/optee.c
index 07ae18d5279d..dbe32e141748 100644
--- a/drivers/firmware/arm_scmi/transports/optee.c
+++ b/drivers/firmware/arm_scmi/transports/optee.c
@@ -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");