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>
This commit is contained in:
Cristian Marussi
2026-05-10 17:05:27 +01:00
committed by Sudeep Holla
parent c08051901a
commit 524abd2fa6

View 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");