]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
firmware: arm_ffa: Unregister the FF-A devices when cleaning up the partitions
authorSudeep Holla <sudeep.holla@arm.com>
Mon, 17 Feb 2025 15:38:49 +0000 (15:38 +0000)
committerSudeep Holla <sudeep.holla@arm.com>
Mon, 17 Feb 2025 15:42:04 +0000 (15:42 +0000)
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>
drivers/firmware/arm_ffa/bus.c
drivers/firmware/arm_ffa/driver.c
include/linux/arm_ffa.h

index a90e2faa990219574ff20b8f573dbb7ca76137d9..98118823cf84969480fc25c937881f9b773a38c2 100644 (file)
@@ -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)
 {
index 320ae654cb968ef573995764d9d35c027d74a33b..15305920ca9f2bcc72ac7453080f5c10430a3e26 100644 (file)
@@ -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);
index e8b8ae8b192ab11d5550c16fd33fa9d192b07f67..ca2ad5b0ac4309052d55dcf546d29423bbd40a67 100644 (file)
@@ -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)