Discussion:
[PATCH v2 7/7] driver-core: add preferred async probe option for built-in and modules
Luis R. Rodriguez
2014-10-03 21:44:43 UTC
Permalink
From: "Luis R. Rodriguez" <***@suse.com>

At times we may wish to express the desire to prefer to have
a device driver probe asynchronously by default. We cannot
simply enable all device drivers to do this without vetting
that userspace is prepared for this though given that some
old userspace is expected to exist which is not equipped to
deal with broad async probe support. This defines a new kernel
parameter, bus.enable_kern_async=1, to help address this both to
help enable async probe support for built-in drivers and to
enable drivers to specify a preference to opt in for async
probe support.

If you have a device driver that should use async probe
support when possible enable the prefer_async_probe bool.

Folks wishing to test enabling async probe for all built-in
drivers can enable bus.__DEBUG__kernel_force_mod_async_probe=1,
if you use that though you are on your own.

Cc: Tejun Heo <***@kernel.org>
Cc: Arjan van de Ven <***@linux.intel.com>
Cc: Greg Kroah-Hartman <***@linuxfoundation.org>
Cc: Tetsuo Handa <penguin-***@I-love.SAKURA.ne.jp>
Cc: Joseph Salisbury <***@canonical.com>
Cc: Kay Sievers <***@vrfy.org>
Cc: One Thousand Gnomes <***@lxorguk.ukuu.org.uk>
Cc: Tim Gardner <***@canonical.com>
Cc: Pierre Fersing <pierre-***@pierref.org>
Cc: Andrew Morton <***@linux-foundation.org>
Cc: Oleg Nesterov <***@redhat.com>
Cc: Benjamin Poirier <***@suse.de>
Cc: Nagalakshmi Nandigama <***@avagotech.com>
Cc: Praveen Krishnamoorthy <***@avagotech.com>
Cc: Sreekanth Reddy <***@avagotech.com>
Cc: Abhijit Mahajan <***@avagotech.com>
Cc: Casey Leedom <***@chelsio.com>
Cc: Hariprasad S <***@chelsio.com>
Cc: Santosh Rastapur <***@chelsio.com>
Cc: MPT-***@avagotech.com
Cc: linux-***@vger.kernel.org
Cc: linux-***@vger.kernel.org
Cc: ***@vger.kernel.org
Signed-off-by: Luis R. Rodriguez <***@suse.com>
---
Documentation/kernel-parameters.txt | 9 +++++++
drivers/base/bus.c | 52 ++++++++++++++++++++++++++++++-------
include/linux/device.h | 9 +++++++
3 files changed, 60 insertions(+), 10 deletions(-)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index e4be3b8..56f4d4e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -914,12 +914,21 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
Enable debug messages at boot time. See
Documentation/dynamic-debug-howto.txt for details.

+ bus.enable_kern_async=1 [KNL]
+ This tells the kernel userspace has been vetted for
+ asynchronous probe support and can listen to the device
+ driver prefer_async_probe flag for both built-in device
+ drivers and modules.
module.async_probe [KNL]
Enable asynchronous probe on this module.
bus.__DEBUG__module_force_mod_async_probe=1 [KNL]
Enable asynchronous probe on all modules. This is
testing parameter and using it will taint your
kernel.
+ bus.__DEBUG__kernel_force_mod_async_probe=1 [KNL]
+ Enable asynchronous probe on all built-in drivers. This
+ is testing parameter and using it will taint your
+ kernel.

early_ioremap_debug [KNL]
Enable debug messages in early_ioremap support. This
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index ec203d6..25d0412 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -695,8 +695,10 @@ int bus_driver_async_probe(struct device_driver *drv)
INIT_WORK(&priv->attach_work->work, driver_attach_workfn);

/* Keep this as pr_info() until this is prevalent */
- pr_info("bus: '%s': probe for driver %s is run asynchronously\n",
- drv->bus->name, drv->name);
+ pr_info("bus: '%s': probe for %s driver %s is run asynchronously\n",
+ drv->bus->name,
+ drv->owner ? "module" : "built-in",
+ drv->name);

queue_work(system_unbound_wq, &priv->attach_work->work);

@@ -708,6 +710,16 @@ module_param_named(__DEBUG__module_force_mod_async_probe, force_mod_async, bool,
MODULE_PARM_DESC(__DEBUG__module_force_mod_async_probe,
"Force async probe on all modules");

+static bool force_kern_async = false;
+module_param_named(__DEBUG__kernel_force_mod_async_probe, force_kern_async, bool, 0400);
+MODULE_PARM_DESC(__DEBUG__kernel_force_mod_async_probe,
+ "Force async probe on all modules");
+
+static bool enable_kern_async = false;
+module_param_named(enable_kern_async, enable_kern_async, bool, 0400);
+MODULE_PARM_DESC(enable_kern_async,
+ "Userspace is vetted to handle driver async probe");
+
/**
* drv_enable_async_probe - evaluates if async probe should be used
* @drv: device driver to evaluate
@@ -722,25 +734,41 @@ MODULE_PARM_DESC(__DEBUG__module_force_mod_async_probe,
* be used on it.
*
* Drivers can be built-in or modules. Userspace can inform the kernel that
- * it is prepared for async probe by passing the module parameter
- * async_probe on each module it wishes to load. The async_probe parameter is
+ * it is prepared for async probe by either passing the module parameter
+ * async_probe on each module it wishes to load or by enabling the
+ * bus.enable_kern_async=1 kernel parameter. The async_probe parameter is
* module specific and gives userspace the flexibility to opt out of using
- * async probe for certain types of modules. Built-in drivers are currently
- * not supported for async probe.
+ * async probe for certain types of modules. Built-in drivers and modules which
+ * are known to work well with async probe can enable @drv->prefer_async_probe,
+ * async probe will be used for it if the kernel parameter but only if the
+ * kernel parameter bus.enable_kern_async=1 has been set.
*
* If you'd like to test enabling async probe for all modules you can enable
- * the bus.__DEBUG__module_force_mod_async_probe=1 kernel parameter. This
- * parameter should only be used to help test and should be used with caution.
+ * the bus.__DEBUG__module_force_mod_async_probe=1 kernel parameter. If you'd
+ * like to test enabling async probe for all built-in drivers you can enable
+ * the bus.__DEBUG__kernel_force_mod_async_probe=1 kernel parameter. These
+ * parameters should only be used to help test and should be used with caution.
*/
static bool drv_enable_async_probe(struct device_driver *drv,
struct bus_type *bus)
{
struct module *mod;

- if (!drv->owner || drv->sync_probe)
+ if (drv->sync_probe)
+ return false;
+
+ /* built-in drivers */
+ if (!drv->owner) {
+ if (!enable_kern_async)
+ return false;
+ if (drv->prefer_async_probe || force_kern_async)
+ return true;
return false;
+ }

- if (force_mod_async)
+ /* modules */
+ if ((enable_kern_async && drv->prefer_async_probe) ||
+ force_mod_async)
return true;

mod = drv->owner;
@@ -1364,6 +1392,10 @@ int __init buses_init(void)
pr_info("Enabling force_mod_async -- you're on your own!\n");
add_taint(TAINT_DEBUG, LOCKDEP_STILL_OK);
}
+ if (unlikely(force_kern_async)) {
+ pr_info("Enabling force_kern_async -- you're on your own!\n");
+ add_taint(TAINT_DEBUG, LOCKDEP_STILL_OK);
+ }

bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
if (!bus_kset)
diff --git a/include/linux/device.h b/include/linux/device.h
index aa14b95..058a8e0 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -202,6 +202,14 @@ extern struct klist *bus_get_device_klist(struct bus_type *bus);
* @suppress_bind_attrs: Disables bind/unbind via sysfs.
* @sync_probe: Use this to annotate drivers which don't work well with
* async probe.
+ * @prefer_async_probe: if userspace is vetted for async probe support enable
+ * async probe on this device driver whether module or built-in.
+ * Userspace expresses it is vetted for async probe support by
+ * enabling the bus.enable_kern_async=1 kernel parameter. Without
+ * this option enabled userspace can still request modules to be
+ * loaded asynchronously by using the shared async_probe module
+ * parameter. Built-in drivers must however enable
+ * prefer_async_probe and cope with bus.enable_kern_async=1
* @of_match_table: The open firmware table.
* @acpi_match_table: The ACPI match table.
* @probe: Called to query the existence of a specific device,
@@ -236,6 +244,7 @@ struct device_driver {

bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
bool sync_probe;
+ bool prefer_async_probe;

const struct of_device_id *of_match_table;
const struct acpi_device_id *acpi_match_table;
--
2.1.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Luis R. Rodriguez
2014-10-03 21:44:42 UTC
Permalink
From: "Luis R. Rodriguez" <***@suse.com>

Some init systems may wish to express the desire to have
device drivers run their device driver's bus probe() run
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. Implemention 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.

Some device driver might not be able to run async probe
so we enable device drivers to annotate this to prevent
this module parameter from having any effect on them.

This implementation uses queue_work(system_unbound_wq)
to queue async probes, this should enable probe to run
slightly *faster* if the driver's probe path did not
have much interaction with other workqueues otherwise
it may run _slightly_ slower. Tests were done with cxgb4,
which is known to take long on probe, both without
having to run request_firmware() [0] and then by
requiring it to use request_firmware() [1]. The
difference in run time are only measurable in microseconds:

=====================================================================|
strategy fw (usec) no-fw (usec) |
---------------------------------------------------------------------|
synchronous 24472569 1307563 |
kthread 25066415.5 1309868.5 |
queue_work(system_unbound_wq) 24913661.5 1307631 |
---------------------------------------------------------------------|

In practice, in seconds, the difference is barely noticeable:

=====================================================================|
strategy fw (s) no-fw (s) |
---------------------------------------------------------------------|
synchronous 24.47 1.31 |
kthread 25.07 1.31 |
queue_work(system_unbound_wq) 24.91 1.31 |
---------------------------------------------------------------------|

[0] Loading Image...
[1] Loading Image...

Systemd should consider enabling async probe on device drivers
it loads through systemd-udev but probably does not want to
enable it for modules loaded through systemd-modules-load
(modules-load.d). At least on my booting enabling async probe
for all modules fails to boot as such in order to make this
a bit more useful we whitelist a few buses where it should be
at least in theory safe to try to enable async probe. This
way even if systemd tried to ask to enable async probe for all
its device drivers the kernel won't blindly do this. We also
have the sync_probe flag which device drivers can themselves
enable *iff* its known the device driver should never async
probe.

In order to help *test* things folks can use the kernel parameter
bus.__DEBUG__module_safe_mod_async_probe=1 which will work as if
userspace would have requested all modules to load with async probe.
Daring folks can also use bus.__DEBUG__module_force_mod_async_probe=1
which will enable asynch probe even on buses not tested in any way yet,
if you use that though you're on your own. Both of these flag taint
the kernel as being in a debug intrusive mode to avoid spurious bug
reports while this mechanism gets tested.

Cc: Tejun Heo <***@kernel.org>
Cc: Arjan van de Ven <***@linux.intel.com>
Cc: Greg Kroah-Hartman <***@linuxfoundation.org>
Cc: Tetsuo Handa <penguin-***@I-love.SAKURA.ne.jp>
Cc: Joseph Salisbury <***@canonical.com>
Cc: Kay Sievers <***@vrfy.org>
Cc: One Thousand Gnomes <***@lxorguk.ukuu.org.uk>
Cc: Tim Gardner <***@canonical.com>
Cc: Pierre Fersing <pierre-***@pierref.org>
Cc: Andrew Morton <***@linux-foundation.org>
Cc: Oleg Nesterov <***@redhat.com>
Cc: Benjamin Poirier <***@suse.de>
Cc: Nagalakshmi Nandigama <***@avagotech.com>
Cc: Praveen Krishnamoorthy <***@avagotech.com>
Cc: Sreekanth Reddy <***@avagotech.com>
Cc: Abhijit Mahajan <***@avagotech.com>
Cc: Casey Leedom <***@chelsio.com>
Cc: Hariprasad S <***@chelsio.com>
Cc: Santosh Rastapur <***@chelsio.com>
Cc: MPT-***@avagotech.com
Cc: linux-***@vger.kernel.org
Cc: linux-***@vger.kernel.org
Cc: ***@vger.kernel.org
Acked-by: Tom Gundersen <***@jklm.no>
Signed-off-by: Luis R. Rodriguez <***@suse.com>
---
Documentation/kernel-parameters.txt | 7 +++
drivers/base/base.h | 6 +++
drivers/base/bus.c | 104 ++++++++++++++++++++++++++++++++++--
drivers/base/dd.c | 7 +++
include/linux/module.h | 2 +
kernel/module.c | 12 ++++-
6 files changed, 133 insertions(+), 5 deletions(-)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 10d51c2..e4be3b8 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -914,6 +914,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
Enable debug messages at boot time. See
Documentation/dynamic-debug-howto.txt for details.

+ module.async_probe [KNL]
+ Enable asynchronous probe on this module.
+ bus.__DEBUG__module_force_mod_async_probe=1 [KNL]
+ Enable asynchronous probe on all modules. This is
+ testing parameter and using it will taint your
+ kernel.
+
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/base.h b/drivers/base/base.h
index 251c5d3..24836f1 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -43,11 +43,17 @@ struct subsys_private {
};
#define to_subsys_private(obj) container_of(obj, struct subsys_private, subsys.kobj)

+struct driver_attach_work {
+ struct work_struct work;
+ struct device_driver *driver;
+};
+
struct driver_private {
struct kobject kobj;
struct klist klist_devices;
struct klist_node knode_bus;
struct module_kobject *mkobj;
+ struct driver_attach_work *attach_work;
struct device_driver *driver;
};
#define to_driver(obj) container_of(obj, struct driver_private, kobj)
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index a5f41e4..ec203d6 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -85,6 +85,7 @@ static void driver_release(struct kobject *kobj)
struct driver_private *drv_priv = to_driver(kobj);

pr_debug("driver: '%s': %s\n", kobject_name(kobj), __func__);
+ kfree(drv_priv->attach_work);
kfree(drv_priv);
}

@@ -662,10 +663,93 @@ static void remove_driver_private(struct device_driver *drv)
struct driver_private *priv = drv->p;

kobject_put(&priv->kobj);
+ kfree(priv->attach_work);
kfree(priv);
drv->p = NULL;
}

+static void driver_attach_workfn(struct work_struct *work)
+{
+ struct driver_attach_work *attach_work =
+ container_of(work, struct driver_attach_work, work);
+ struct device_driver *drv = attach_work->driver;
+ int ret;
+
+ ret = driver_attach(drv);
+ if (ret != 0) {
+ remove_driver_private(drv);
+ bus_put(drv->bus);
+ }
+}
+
+int bus_driver_async_probe(struct device_driver *drv)
+{
+ struct driver_private *priv = drv->p;
+
+ priv->attach_work = kzalloc(sizeof(struct driver_attach_work),
+ GFP_KERNEL);
+ if (!priv->attach_work)
+ return -ENOMEM;
+
+ priv->attach_work->driver = drv;
+ INIT_WORK(&priv->attach_work->work, driver_attach_workfn);
+
+ /* Keep this as pr_info() until this is prevalent */
+ pr_info("bus: '%s': probe for driver %s is run asynchronously\n",
+ drv->bus->name, drv->name);
+
+ queue_work(system_unbound_wq, &priv->attach_work->work);
+
+ return 0;
+}
+
+static bool force_mod_async = false;
+module_param_named(__DEBUG__module_force_mod_async_probe, force_mod_async, bool, 0400);
+MODULE_PARM_DESC(__DEBUG__module_force_mod_async_probe,
+ "Force async probe on all modules");
+
+/**
+ * drv_enable_async_probe - evaluates if async probe should be used
+ * @drv: device driver to evaluate
+ * @bus: the bus for the device driver
+ *
+ * The driver core supports enabling asynchronous probe on device drivers
+ * through a few mechanisms. We're careful to ensure that async probe can
+ * only be used by userspace that is prepared and has been vetted to support
+ * async probe support given that the driver core has historically only
+ * supported synchronous probe. If any driver is known to not work well with
+ * async probe the @drv can enable sync_probe and asynchronous probe will never
+ * be used on it.
+ *
+ * Drivers can be built-in or modules. Userspace can inform the kernel that
+ * it is prepared for async probe by passing the module parameter
+ * async_probe on each module it wishes to load. The async_probe parameter is
+ * module specific and gives userspace the flexibility to opt out of using
+ * async probe for certain types of modules. Built-in drivers are currently
+ * not supported for async probe.
+ *
+ * If you'd like to test enabling async probe for all modules you can enable
+ * the bus.__DEBUG__module_force_mod_async_probe=1 kernel parameter. This
+ * parameter should only be used to help test and should be used with caution.
+ */
+static bool drv_enable_async_probe(struct device_driver *drv,
+ struct bus_type *bus)
+{
+ struct module *mod;
+
+ if (!drv->owner || drv->sync_probe)
+ return false;
+
+ if (force_mod_async)
+ return true;
+
+ mod = drv->owner;
+ if (!mod->async_probe_requested)
+ return false;
+
+ return true;
+}
+
/**
* bus_add_driver - Add a driver to the bus.
* @drv: driver.
@@ -675,6 +759,7 @@ int bus_add_driver(struct device_driver *drv)
struct bus_type *bus;
struct driver_private *priv;
int error = 0;
+ bool async_probe = false;

bus = bus_get(drv->bus);
if (!bus)
@@ -696,11 +781,19 @@ int bus_add_driver(struct device_driver *drv)
if (error)
goto out_unregister;

+ async_probe = drv_enable_async_probe(drv, bus);
+
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
if (drv->bus->p->drivers_autoprobe) {
- error = driver_attach(drv);
- if (error)
- goto out_unregister;
+ if (async_probe) {
+ error = bus_driver_async_probe(drv);
+ if (error)
+ goto out_unregister;
+ } else {
+ error = driver_attach(drv);
+ if (error)
+ goto out_unregister;
+ }
}
module_add_driver(drv->owner, drv);

@@ -1267,6 +1360,11 @@ EXPORT_SYMBOL_GPL(subsys_virtual_register);

int __init buses_init(void)
{
+ if (unlikely(force_mod_async)) {
+ pr_info("Enabling force_mod_async -- you're on your own!\n");
+ add_taint(TAINT_DEBUG, LOCKDEP_STILL_OK);
+ }
+
bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
if (!bus_kset)
return -ENOMEM;
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index e4ffbcf..7999aba 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -507,6 +507,13 @@ static void __device_release_driver(struct device *dev)

drv = dev->driver;
if (drv) {
+ if (drv->owner && !drv->sync_probe) {
+ struct module *mod = drv->owner;
+ struct driver_private *priv = drv->p;
+
+ if (mod->async_probe_requested)
+ flush_work(&priv->attach_work->work);
+ }
pm_runtime_get_sync(dev);

driver_sysfs_remove(dev);
diff --git a/include/linux/module.h b/include/linux/module.h
index 71f282a..1e9e017 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -271,6 +271,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 6a07671..f5f709d 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3175,8 +3175,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;
@@ -3278,7 +3286,7 @@ static int load_module(struct load_info *info, const char __user *uargs,

/* Module is ready to execute: parsing args may do that. */
after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
- -32768, 32767, NULL,
+ -32768, 32767, mod,
unknown_module_param_cb);
if (IS_ERR(after_dashes)) {
err = PTR_ERR(after_dashes);
--
2.1.1
Tejun Heo
2014-10-06 20:19:26 UTC
Permalink
Hello, Luis.

The patchset generally looks good to me. Please feel free to add

Reviewed-by: Tejun Heo <***@kernel.org>

A question below.
Post by Luis R. Rodriguez
+ bus.enable_kern_async=1 [KNL]
+ This tells the kernel userspace has been vetted for
+ asynchronous probe support and can listen to the device
+ driver prefer_async_probe flag for both built-in device
+ drivers and modules.
Do we intend to keep this param permanently? Isn't this more of a
temp tool to be used during development? If so, maybe we should make
that clear with __DEVEL__ too?

Thanks.
--
tejun
Luis R. Rodriguez
2014-10-06 20:36:27 UTC
Permalink
Post by Tejun Heo
Hello, Luis.
The patchset generally looks good to me. Please feel free to add
Will do.
Post by Tejun Heo
A question below.
Post by Luis R. Rodriguez
+ bus.enable_kern_async=1 [KNL]
+ This tells the kernel userspace has been vetted for
+ asynchronous probe support and can listen to the device
+ driver prefer_async_probe flag for both built-in device
+ drivers and modules.
Do we intend to keep this param permanently? Isn't this more of a
temp tool to be used during development? If so, maybe we should make
that clear with __DEVEL__ too?
As its designed right now no, its not a temp tool, its there to
require compatibility with old userspace. For modules we can require
the module parameter but for built-in we need something else and this
is what came to mind. It is also what would allow the prefer_async_probe
flag too as otherwise we won't know if userspace is prepared.

If we want to get rid of it, it would mean that we're letting go of the idea
that some userspace might exist which depends on *not* doing async probe. As
such I would not consider it a __DEVEL__ param and it'd be a judgement call
to eventually *not require* it. I can see that happening but perhaps a large
series of kernels down the road?

Luis
Tejun Heo
2014-10-06 21:01:18 UTC
Permalink
Hello,
Post by Luis R. Rodriguez
Post by Tejun Heo
Do we intend to keep this param permanently? Isn't this more of a
temp tool to be used during development? If so, maybe we should make
that clear with __DEVEL__ too?
As its designed right now no, its not a temp tool, its there to
require compatibility with old userspace. For modules we can require
the module parameter but for built-in we need something else and this
is what came to mind. It is also what would allow the prefer_async_probe
flag too as otherwise we won't know if userspace is prepared.
I don't get it. For in-kernel stuff, we already have a clear
synchronization point where we already synchronize all async calls.
Shouldn't we be flushing these async probes there too? insmod'ing is
userland visible but there's no reason this has to be for the built-in
drivers.

Thanks.
--
tejun
Luis R. Rodriguez
2014-10-06 23:10:46 UTC
Permalink
Post by Tejun Heo
Hello,
Post by Luis R. Rodriguez
Post by Tejun Heo
Do we intend to keep this param permanently? Isn't this more of a
temp tool to be used during development? If so, maybe we should make
that clear with __DEVEL__ too?
As its designed right now no, its not a temp tool, its there to
require compatibility with old userspace. For modules we can require
the module parameter but for built-in we need something else and this
is what came to mind. It is also what would allow the prefer_async_probe
flag too as otherwise we won't know if userspace is prepared.
I don't get it.
By prepared I meant that userspace can handle async probe, but
you're right that we don't need to know that. I don't see how
we'd be breaking old userspace by doing async probe of a driver
is built-in right now... unless of course built-in always assumes
all possible devices would be present after right before userspace
init.
Post by Tejun Heo
For in-kernel stuff, we already have a clear
synchronization point where we already synchronize all async calls.
Shouldn't we be flushing these async probes there too?
This seems to be addressing if what I meant by prepared, "ready", so let
me address this as I do think its important.

By async calls do you mean users of async_schedule()? I see it
also uses system_unbound_wq as well but I do not see anyone calling
flush_workqueue(system_unbound_wq) on the kernel. We do use
async_synchronize_full() on kernel_init() but that just waits.

As it is we don't wait on init then, should we? Must we? Could / should
we use bus.enable_kern_async=1 to enable avoiding having to wait ? At
this point I'd prefer to address what we must do only.
Post by Tejun Heo
insmod'ing is
userland visible but there's no reason this has to be for the built-in
drivers.
Good point.

bus.enable_kern_async=1 would still also serve as a helper for the driver core
to figure out if it should use async probe then on modules if prefer_async_probe
was enabled. Let me know if you figure out a way to avoid it.

Luis
Tejun Heo
2014-10-07 17:34:04 UTC
Permalink
Hello,
Post by Luis R. Rodriguez
Post by Tejun Heo
For in-kernel stuff, we already have a clear
synchronization point where we already synchronize all async calls.
Shouldn't we be flushing these async probes there too?
This seems to be addressing if what I meant by prepared, "ready", so let
me address this as I do think its important.
By async calls do you mean users of async_schedule()? I see it
Yes.
Post by Luis R. Rodriguez
also uses system_unbound_wq as well but I do not see anyone calling
flush_workqueue(system_unbound_wq) on the kernel. We do use
async_synchronize_full() on kernel_init() but that just waits.
But you can create a new workqueue and queue all the async probing
work items there and flush the workqueue right after
async_synchronize_full().

...
Post by Luis R. Rodriguez
bus.enable_kern_async=1 would still also serve as a helper for the driver core
to figure out if it should use async probe then on modules if prefer_async_probe
was enabled. Let me know if you figure out a way to avoid it.
Why do we need the choice at all? It always should, no?

Thanks.
--
tejun
Luis R. Rodriguez
2014-10-07 17:50:10 UTC
Permalink
Post by Tejun Heo
Hello,
Post by Luis R. Rodriguez
Post by Tejun Heo
For in-kernel stuff, we already have a clear
synchronization point where we already synchronize all async calls.
Shouldn't we be flushing these async probes there too?
This seems to be addressing if what I meant by prepared, "ready", so let
me address this as I do think its important.
By async calls do you mean users of async_schedule()? I see it
Yes.
Post by Luis R. Rodriguez
also uses system_unbound_wq as well but I do not see anyone calling
flush_workqueue(system_unbound_wq) on the kernel. We do use
async_synchronize_full() on kernel_init() but that just waits.
But you can create a new workqueue and queue all the async probing
work items there and flush the workqueue right after
async_synchronize_full().
On second thought I would prefer to avoid this, I see this being good
to help with old userspace but other than that I don't see a requirement
for new userspace. Do you?
Post by Tejun Heo
...
Post by Luis R. Rodriguez
bus.enable_kern_async=1 would still also serve as a helper for the driver core
to figure out if it should use async probe then on modules if prefer_async_probe
was enabled. Let me know if you figure out a way to avoid it.
Why do we need the choice at all? It always should, no?
I'm OK to live with that, in that case I see no point to bus.enable_kern_async=1
at all.

Luis
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Tejun Heo
2014-10-07 17:55:03 UTC
Permalink
Hello,
Post by Luis R. Rodriguez
Post by Tejun Heo
But you can create a new workqueue and queue all the async probing
work items there and flush the workqueue right after
async_synchronize_full().
On second thought I would prefer to avoid this, I see this being good
to help with old userspace but other than that I don't see a requirement
for new userspace. Do you?
Hmmm... we batch up and do everything parallel, so I'm not sure how
much gain we'd be looking at by not waiting for at the end before
jumping into the userland. Also, it's a bit of an orthogonal issue.
If we wanna skip such synchornization point before passing control to
userland, why are we applying that to this but not
async_synchronize_full() which has a far larger impact? It's weird to
synchronize one while not the other, so yeah, if there are actual
benefits we can consider it but let's do it separately.

Thanks.
--
tejun
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Luis R. Rodriguez
2014-10-07 18:55:16 UTC
Permalink
Post by Tejun Heo
Hello,
Post by Luis R. Rodriguez
Post by Tejun Heo
But you can create a new workqueue and queue all the async probing
work items there and flush the workqueue right after
async_synchronize_full().
On second thought I would prefer to avoid this, I see this being good
to help with old userspace but other than that I don't see a requirement
for new userspace. Do you?
Hmmm... we batch up and do everything parallel, so I'm not sure how
much gain we'd be looking at by not waiting for at the end before
jumping into the userland. Also, it's a bit of an orthogonal issue.
If we wanna skip such synchornization point before passing control to
userland, why are we applying that to this but not
async_synchronize_full() which has a far larger impact? It's weird to
synchronize one while not the other, so yeah, if there are actual
benefits we can consider it but let's do it separately.
OK I'll just kill bus.enable_kern_async=1 to enable built-in async
probe support *and* also have prefer_async_probe *always* be
respected, whether modular or not.

Luis
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Luis R. Rodriguez
2014-10-07 19:07:29 UTC
Permalink
Post by Luis R. Rodriguez
OK I'll just kill bus.enable_kern_async=1 to enable built-in async
probe support *and* also have prefer_async_probe *always* be
respected, whether modular or not.
Well and I just realized you *do* want to flush, so will throw that in
too without an option to skip it.

Luis
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Dmitry Torokhov
2014-10-06 20:41:55 UTC
Permalink
Hi Luis,
Post by Luis R. Rodriguez
At times we may wish to express the desire to prefer to have
a device driver probe asynchronously by default. We cannot
simply enable all device drivers to do this without vetting
that userspace is prepared for this though given that some
old userspace is expected to exist which is not equipped to
deal with broad async probe support. This defines a new kernel
parameter, bus.enable_kern_async=1, to help address this both to
help enable async probe support for built-in drivers and to
enable drivers to specify a preference to opt in for async
probe support.
If you have a device driver that should use async probe
support when possible enable the prefer_async_probe bool.
Folks wishing to test enabling async probe for all built-in
drivers can enable bus.__DEBUG__kernel_force_mod_async_probe=1,
if you use that though you are on your own.
Thank you for working on this. However there are still couple of issues
with the async probe.

1. As far as I can see you only handle the case when device is already
present and you load a driver. In this case we will do either async or
sync probing, depending on the driver/module settings. However if driver
has already been loaded/registered and we are adding a new device
(another module load, for example you load i2c controller module and it
enumerates its children, or driver signalled deferral during binding)
the probe will be synchronous regardless of the settings.

2. I thin kin the current implementation deferred binding process is
still single-threaded and basically synchronous.

Both of these issues stem form the fact that you only plugging into
bus_add_driver(), but you also need to plug into bus_probe_device(). I
believe I handled these 2 cases properly in the version of patch I sent
a couple of weeks ago so if you could incorporate that in your work that
would be great.

Thanks.
--
Dmitry
Loading...