vfio: platform: use list of registered reset function
authorEric Auger <eric.auger@linaro.org>
Tue, 3 Nov 2015 18:12:17 +0000 (18:12 +0000)
committerAlex Williamson <alex.williamson@redhat.com>
Tue, 3 Nov 2015 19:55:03 +0000 (12:55 -0700)
Remove the static lookup table and use the dynamic list of registered
reset functions instead. Also load the reset module through its alias.
The reset struct module pointer is stored in vfio_platform_device.

We also remove the useless struct device pointer parameter in
vfio_platform_get_reset.

This patch fixes the issue related to the usage of __symbol_get, which
besides from being moot, prevented compilation with CONFIG_MODULES
disabled.

Also usage of MODULE_ALIAS makes possible to add a new reset module
without needing to update the framework. This was suggested by Arnd.

Signed-off-by: Eric Auger <eric.auger@linaro.org>
Reported-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c
drivers/vfio/platform/vfio_platform_common.c
drivers/vfio/platform/vfio_platform_private.h

index 80718f20d5d377b75dfac797480f4f9c777bf77d..640f5d87d4225edf9a6f2d17967c19d409b35dee 100644 (file)
@@ -76,7 +76,6 @@ int vfio_platform_calxedaxgmac_reset(struct vfio_platform_device *vdev)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(vfio_platform_calxedaxgmac_reset);
 
 module_vfio_reset_handler("calxeda,hb-xgmac", vfio_platform_calxedaxgmac_reset);
 
index d8df8a4318daae0b1f243465582338dc2bb6636a..ac0229622c1f603216afd1d4a3076ae66f6cf352 100644 (file)
 static LIST_HEAD(reset_list);
 static DEFINE_MUTEX(driver_lock);
 
-static const struct vfio_platform_reset_combo reset_lookup_table[] = {
-       {
-               .compat = "calxeda,hb-xgmac",
-               .reset_function_name = "vfio_platform_calxedaxgmac_reset",
-               .module_name = "vfio-platform-calxedaxgmac",
-       },
-};
-
-static void vfio_platform_get_reset(struct vfio_platform_device *vdev,
-                                   struct device *dev)
+static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
+                                       struct module **module)
 {
-       int (*reset)(struct vfio_platform_device *);
-       int i;
+       struct vfio_platform_reset_node *iter;
+       vfio_platform_reset_fn_t reset_fn = NULL;
 
-       for (i = 0 ; i < ARRAY_SIZE(reset_lookup_table); i++) {
-               if (!strcmp(reset_lookup_table[i].compat, vdev->compat)) {
-                       request_module(reset_lookup_table[i].module_name);
-                       reset = __symbol_get(
-                               reset_lookup_table[i].reset_function_name);
-                       if (reset) {
-                               vdev->reset = reset;
-                               return;
-                       }
+       mutex_lock(&driver_lock);
+       list_for_each_entry(iter, &reset_list, link) {
+               if (!strcmp(iter->compat, compat) &&
+                       try_module_get(iter->owner)) {
+                       *module = iter->owner;
+                       reset_fn = iter->reset;
+                       break;
                }
        }
+       mutex_unlock(&driver_lock);
+       return reset_fn;
+}
+
+static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
+{
+       char modname[256];
+
+       vdev->reset = vfio_platform_lookup_reset(vdev->compat,
+                                               &vdev->reset_module);
+       if (!vdev->reset) {
+               snprintf(modname, 256, "vfio-reset:%s", vdev->compat);
+               request_module(modname);
+               vdev->reset = vfio_platform_lookup_reset(vdev->compat,
+                                                        &vdev->reset_module);
+       }
 }
 
 static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
 {
        if (vdev->reset)
-               symbol_put_addr(vdev->reset);
+               module_put(vdev->reset_module);
 }
 
 static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
@@ -557,7 +563,7 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
                return ret;
        }
 
-       vfio_platform_get_reset(vdev, dev);
+       vfio_platform_get_reset(vdev);
 
        mutex_init(&vdev->igate);
 
index 415310f62b06cc4a8a76153c15b00b45e7c09279..d1b0668fe39408cc208e469b6c8236c319412a67 100644 (file)
@@ -58,6 +58,7 @@ struct vfio_platform_device {
        struct mutex                    igate;
        struct module                   *parent_module;
        const char                      *compat;
+       struct module                   *reset_module;
 
        /*
         * These fields should be filled by the bus specific binder
@@ -81,12 +82,6 @@ struct vfio_platform_reset_node {
        vfio_platform_reset_fn_t reset;
 };
 
-struct vfio_platform_reset_combo {
-       const char *compat;
-       const char *reset_function_name;
-       const char *module_name;
-};
-
 extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
                                      struct device *dev);
 extern struct vfio_platform_device *vfio_platform_remove_common