From: Sudeep Holla Date: Mon, 17 Feb 2025 15:38:49 +0000 (+0000) Subject: firmware: arm_ffa: Unregister the FF-A devices when cleaning up the partitions X-Git-Tag: v6.15-rc1~158^2~14^2~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=46dcd68aaccac0812c12ec3f4e59c8963e2760ad;p=thirdparty%2Fkernel%2Flinux.git firmware: arm_ffa: Unregister the FF-A devices when cleaning up the partitions 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 Message-Id: <20250217-ffa_updates-v3-8-bd1d9de615e7@arm.com> Signed-off-by: Sudeep Holla --- diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c index a90e2faa99021..98118823cf849 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 320ae654cb968..15305920ca9f2 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -1494,10 +1494,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; } @@ -1507,6 +1505,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 e8b8ae8b192ab..ca2ad5b0ac430 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)