summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis R. Rodriguez <mcgrof@suse.com>2015-03-30 16:20:05 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-05-20 00:25:24 -0700
commitf2411da746985e60d4d087f3a43e271c61785927 (patch)
tree09b6c3b2abd4774f63e4a0d467e3c70daa52663e
parent765230b5f084863183aa8adb3405ab3f32c0b16e (diff)
downloadop-kernel-dev-f2411da746985e60d4d087f3a43e271c61785927.zip
op-kernel-dev-f2411da746985e60d4d087f3a43e271c61785927.tar.gz
driver-core: add driver module asynchronous probe support
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>
-rw-r--r--Documentation/kernel-parameters.txt3
-rw-r--r--drivers/base/dd.c8
-rw-r--r--include/linux/device.h8
-rw-r--r--include/linux/module.h2
-rw-r--r--kernel/module.c12
5 files changed, 27 insertions, 6 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 61ab162..e89fdd5 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -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
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 2ad33b2..7a2fa5d 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -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 {
diff --git a/include/linux/device.h b/include/linux/device.h
index 7857b46c..77b7cd9 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -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,
};
diff --git a/include/linux/module.h b/include/linux/module.h
index c883b86..f46a47d 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -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;
diff --git a/kernel/module.c b/kernel/module.c
index 24d1f31..ea941bc 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -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;
OpenPOWER on IntegriCloud