Move the FF-A core bring-up and teardown paths into platform driver probe and remove callbacks, and register a synthetic arm-ffa platform device to bind the driver.
This makes the FF-A core lifetime follow the driver model while keeping the device creation internal to the FF-A core. Use normal platform driver registration so the probe path has standard driver-core semantics. The synthetic platform device is a temporary bridge until ACPI and devicetree describe the FF-A core device or object. Once those firmware description paths are defined, the internal platform device creation can be dropped and the driver can bind to the firmware-described device directly. Since the transport selection now happens from the platform probe path, drop the __init annotation from ffa_transport_init(). Signed-off-by: Sudeep Holla <[email protected]> --- drivers/firmware/arm_ffa/common.h | 4 +-- drivers/firmware/arm_ffa/driver.c | 53 ++++++++++++++++++++++++++++++++++----- drivers/firmware/arm_ffa/smccc.c | 2 +- 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/drivers/firmware/arm_ffa/common.h b/drivers/firmware/arm_ffa/common.h index 9c6425a81d0d..5cdf4bd222c6 100644 --- a/drivers/firmware/arm_ffa/common.h +++ b/drivers/firmware/arm_ffa/common.h @@ -18,9 +18,9 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev); void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid); #ifdef CONFIG_ARM_FFA_SMCCC -int __init ffa_transport_init(ffa_fn **invoke_ffa_fn); +int ffa_transport_init(ffa_fn **invoke_ffa_fn); #else -static inline int __init ffa_transport_init(ffa_fn **invoke_ffa_fn) +static inline int ffa_transport_init(ffa_fn **invoke_ffa_fn) { return -EOPNOTSUPP; } diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index 6efb85787e6e..97ecdb5dac09 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -36,6 +36,7 @@ #include <linux/mm.h> #include <linux/mutex.h> #include <linux/of_irq.h> +#include <linux/platform_device.h> #include <linux/scatterlist.h> #include <linux/slab.h> #include <linux/smp.h> @@ -46,6 +47,7 @@ #define FFA_DRIVER_VERSION FFA_VERSION_1_2 #define FFA_MIN_VERSION FFA_VERSION_1_0 +#define FFA_PLATFORM_NAME "arm-ffa" #define SENDER_ID_MASK GENMASK(31, 16) #define RECEIVER_ID_MASK GENMASK(15, 0) @@ -114,6 +116,7 @@ struct ffa_drv_info { }; static struct ffa_drv_info *drv_info; +static struct platform_device *ffa_pdev; /* * The driver must be able to support all the versions from the earliest @@ -2029,7 +2032,7 @@ static void ffa_notifications_setup(void) ffa_notifications_cleanup(); } -static int __init ffa_init(void) +static int ffa_probe(struct platform_device *pdev) { int ret; u32 buf_sz; @@ -2042,6 +2045,7 @@ static int __init ffa_init(void) drv_info = kzalloc_obj(*drv_info); if (!drv_info) return -ENOMEM; + platform_set_drvdata(pdev, drv_info); ret = ffa_version_check(&drv_info->version); if (ret) @@ -2103,19 +2107,56 @@ static int __init ffa_init(void) free_pages_exact(drv_info->tx_buffer, rxtx_bufsz); free_pages_exact(drv_info->rx_buffer, rxtx_bufsz); free_drv_info: + platform_set_drvdata(pdev, NULL); kfree(drv_info); + drv_info = NULL; return ret; } -module_init(ffa_init); -static void __exit ffa_exit(void) +static void ffa_remove(struct platform_device *pdev) { + struct ffa_drv_info *info = platform_get_drvdata(pdev); + ffa_notifications_cleanup(); ffa_partitions_cleanup(); ffa_rxtx_unmap(); - free_pages_exact(drv_info->tx_buffer, drv_info->rxtx_bufsz); - free_pages_exact(drv_info->rx_buffer, drv_info->rxtx_bufsz); - kfree(drv_info); + free_pages_exact(info->tx_buffer, info->rxtx_bufsz); + free_pages_exact(info->rx_buffer, info->rxtx_bufsz); + kfree(info); + platform_set_drvdata(pdev, NULL); + drv_info = NULL; +} + +static struct platform_driver ffa_driver = { + .probe = ffa_probe, + .remove = ffa_remove, + .driver = { + .name = FFA_PLATFORM_NAME, + }, +}; + +static int __init ffa_init(void) +{ + int ret; + + ffa_pdev = platform_device_register_simple(FFA_PLATFORM_NAME, + PLATFORM_DEVID_NONE, + NULL, 0); + if (IS_ERR(ffa_pdev)) + return PTR_ERR(ffa_pdev); + + ret = platform_driver_register(&ffa_driver); + if (ret) + platform_device_unregister(ffa_pdev); + + return ret; +} +module_init(ffa_init); + +static void __exit ffa_exit(void) +{ + platform_device_unregister(ffa_pdev); + platform_driver_unregister(&ffa_driver); } module_exit(ffa_exit); diff --git a/drivers/firmware/arm_ffa/smccc.c b/drivers/firmware/arm_ffa/smccc.c index 4d85bfff0a4e..e6125dd9f58f 100644 --- a/drivers/firmware/arm_ffa/smccc.c +++ b/drivers/firmware/arm_ffa/smccc.c @@ -17,7 +17,7 @@ static void __arm_ffa_fn_hvc(ffa_value_t args, ffa_value_t *res) arm_smccc_1_2_hvc(&args, res); } -int __init ffa_transport_init(ffa_fn **invoke_ffa_fn) +int ffa_transport_init(ffa_fn **invoke_ffa_fn) { enum arm_smccc_conduit conduit; -- 2.43.0

