driver-core: add driver module asynchronous probe support
authorLuis R. Rodriguez <mcgrof@suse.com>
Mon, 30 Mar 2015 23:20:05 +0000 (16:20 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 May 2015 07:25:24 +0000 (00:25 -0700)
Some init systems may wish to express the desire to have device drivers
run their probe() code asynchronously. This implements support for this
and allows userspace to request async probe as a preference through a
generic shared device driver module parameter, async_probe.

Implementation for async probe is supported through a module parameter
given that since synchronous probe has been prevalent for years some
userspace might exist which relies on the fact that the device driver
will probe synchronously and the assumption that devices it provides
will be immediately available after this.

Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Documentation/kernel-parameters.txt
drivers/base/dd.c
include/linux/device.h
include/linux/module.h
kernel/module.c

index 61ab1628a057cc2c4d8b11d892d834f7e5f7773a..e89fdd5aa605f78b97d0ae2d94c68c7066c97c0f 100644 (file)
@@ -943,6 +943,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        auto    selects the default scheme, which automatically
                                enables eagerfpu restore for xsaveopt.
 
+       module.async_probe [KNL]
+                       Enable asynchronous probe on this module.
+
        early_ioremap_debug [KNL]
                        Enable debug messages in early_ioremap support. This
                        is useful for tracking down temporary early mappings
index 2ad33b21888c855b9c30160df78b9865113ef2a9..7a2fa5dcead7c924ce2fd5af2b08fc3d97944efa 100644 (file)
@@ -419,7 +419,13 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
 
 bool driver_allows_async_probing(struct device_driver *drv)
 {
-       return drv->probe_type == PROBE_PREFER_ASYNCHRONOUS;
+       if (drv->probe_type == PROBE_PREFER_ASYNCHRONOUS)
+               return true;
+
+       if (drv->owner && drv->owner->async_probe_requested)
+               return true;
+
+       return false;
 }
 
 struct device_attach_data {
index 7857b46c548b77fa72c0f9807e4a21a22f979614..77b7cd9e54671cb00b150d4d93cd85fd3a687484 100644 (file)
@@ -201,10 +201,12 @@ extern struct klist *bus_get_device_klist(struct bus_type *bus);
  *     respective probe routines. This tells the core what to
  *     expect and prefer.
  *
- * @PROBE_SYNCHRONOUS: Default. Drivers expect their probe routines
+ * @PROBE_DEFAULT_STRATEGY: Drivers expect their probe routines
  *     to run synchronously with driver and device registration
  *     (with the exception of -EPROBE_DEFER handling - re-probing
- *     always ends up being done asynchronously).
+ *     always ends up being done asynchronously) unless user
+ *     explicitly requested asynchronous probing via module
+ *     parameter.
  * @PROBE_PREFER_ASYNCHRONOUS: Drivers for "slow" devices which
  *     probing order is not essential for booting the system may
  *     opt into executing their probes asynchronously.
@@ -216,7 +218,7 @@ extern struct klist *bus_get_device_klist(struct bus_type *bus);
  * drivers.
  */
 enum probe_type {
-       PROBE_SYNCHRONOUS,
+       PROBE_DEFAULT_STRATEGY,
        PROBE_PREFER_ASYNCHRONOUS,
 };
 
index c883b86ea9649ae62ca485dd3843e51e43edc346..f46a47d3c0dcfb7f4bcd690095d2d77a1b35d8ee 100644 (file)
@@ -257,6 +257,8 @@ struct module {
        bool sig_ok;
 #endif
 
+       bool async_probe_requested;
+
        /* symbols that will be GPL-only in the near future. */
        const struct kernel_symbol *gpl_future_syms;
        const unsigned long *gpl_future_crcs;
index 24d1f31d02f237f3db445dde9c5b3cc9cfe59687..ea941bc327d57fd7989dd57be77ff93fccfb5215 100644 (file)
@@ -3107,7 +3107,7 @@ static noinline int do_init_module(struct module *mod)
         *
         * http://thread.gmane.org/gmane.linux.kernel/1420814
         */
-       if (current->flags & PF_USED_ASYNC)
+       if (!mod->async_probe_requested && (current->flags & PF_USED_ASYNC))
                async_synchronize_full();
 
        mutex_lock(&module_mutex);
@@ -3240,8 +3240,16 @@ out:
 static int unknown_module_param_cb(char *param, char *val, const char *modname,
                                   void *arg)
 {
+       struct module *mod = arg;
+       int ret;
+
+       if (strcmp(param, "async_probe") == 0) {
+               mod->async_probe_requested = true;
+               return 0;
+       }
+
        /* Check for magic 'dyndbg' arg */
-       int ret = ddebug_dyndbg_module_param_cb(param, val, modname);
+       ret = ddebug_dyndbg_module_param_cb(param, val, modname);
        if (ret != 0)
                pr_warn("%s: unknown parameter '%s' ignored\n", modname, param);
        return 0;