6.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla sudeep.holla@arm.com
[ Upstream commit 46dcd68aaccac0812c12ec3f4e59c8963e2760ad ]
Both the FF-A core and the bus were in a single module before the commit 18c250bd7ed0 ("firmware: arm_ffa: Split bus and driver into distinct modules").
The arm_ffa_bus_exit() takes care of unregistering all the FF-A devices. Now that there are 2 distinct modules, if the core driver is unloaded and reloaded, it will end up adding duplicate FF-A devices as the previously registered devices weren't unregistered when we cleaned up the modules.
Fix the same by unregistering all the FF-A devices on the FF-A bus during the cleaning up of the partitions and hence the cleanup of the module.
Fixes: 18c250bd7ed0 ("firmware: arm_ffa: Split bus and driver into distinct modules") Tested-by: Viresh Kumar viresh.kumar@linaro.org Message-Id: 20250217-ffa_updates-v3-8-bd1d9de615e7@arm.com Signed-off-by: Sudeep Holla sudeep.holla@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/firmware/arm_ffa/bus.c | 3 ++- drivers/firmware/arm_ffa/driver.c | 7 ++++--- include/linux/arm_ffa.h | 3 +++ 3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c index dfda5ffc14db7..fa09a82b44921 100644 --- a/drivers/firmware/arm_ffa/bus.c +++ b/drivers/firmware/arm_ffa/bus.c @@ -160,11 +160,12 @@ static int __ffa_devices_unregister(struct device *dev, void *data) return 0; }
-static void ffa_devices_unregister(void) +void ffa_devices_unregister(void) { bus_for_each_dev(&ffa_bus_type, NULL, NULL, __ffa_devices_unregister); } +EXPORT_SYMBOL_GPL(ffa_devices_unregister);
bool ffa_device_is_valid(struct ffa_device *ffa_dev) { diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index 353900c33eee3..8aa05bbab5c8d 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -1451,10 +1451,8 @@ static int ffa_setup_partitions(void)
/* Allocate for the host */ ret = ffa_xa_add_partition_info(drv_info->vm_id); - if (ret) { - /* Already registered devices are freed on bus_exit */ + if (ret) ffa_partitions_cleanup(); - }
return ret; } @@ -1464,6 +1462,9 @@ static void ffa_partitions_cleanup(void) struct ffa_dev_part_info *info; unsigned long idx;
+ /* Clean up/free all registered devices */ + ffa_devices_unregister(); + xa_for_each(&drv_info->partition_info, idx, info) { xa_erase(&drv_info->partition_info, idx); kfree(info); diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h index 74169dd0f6594..53f2837ce7df4 100644 --- a/include/linux/arm_ffa.h +++ b/include/linux/arm_ffa.h @@ -176,6 +176,7 @@ void ffa_device_unregister(struct ffa_device *ffa_dev); int ffa_driver_register(struct ffa_driver *driver, struct module *owner, const char *mod_name); void ffa_driver_unregister(struct ffa_driver *driver); +void ffa_devices_unregister(void); bool ffa_device_is_valid(struct ffa_device *ffa_dev);
#else @@ -188,6 +189,8 @@ ffa_device_register(const struct ffa_partition_info *part_info,
static inline void ffa_device_unregister(struct ffa_device *dev) {}
+static inline void ffa_devices_unregister(void) {} + static inline int ffa_driver_register(struct ffa_driver *driver, struct module *owner, const char *mod_name)