diff mbox

[v2,7/7] driver-core: add preferred async probe option for built-in and modules

Message ID 1412372683-2003-8-git-send-email-mcgrof@do-not-panic.com
State Not Applicable, archived
Delegated to: David Miller
Headers show

Commit Message

Luis R. Rodriguez Oct. 3, 2014, 9:44 p.m. UTC
From: "Luis R. Rodriguez" <mcgrof@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 <tj@kernel.org>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Cc: Joseph Salisbury <joseph.salisbury@canonical.com>
Cc: Kay Sievers <kay@vrfy.org>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Tim Gardner <tim.gardner@canonical.com>
Cc: Pierre Fersing <pierre-fersing@pierref.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Benjamin Poirier <bpoirier@suse.de>
Cc: Nagalakshmi Nandigama <nagalakshmi.nandigama@avagotech.com>
Cc: Praveen Krishnamoorthy <praveen.krishnamoorthy@avagotech.com>
Cc: Sreekanth Reddy <sreekanth.reddy@avagotech.com>
Cc: Abhijit Mahajan <abhijit.mahajan@avagotech.com>
Cc: Casey Leedom <leedom@chelsio.com>
Cc: Hariprasad S <hariprasad@chelsio.com>
Cc: Santosh Rastapur <santosh@chelsio.com>
Cc: MPT-FusionLinux.pdl@avagotech.com
Cc: linux-scsi@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
---
 Documentation/kernel-parameters.txt |  9 +++++++
 drivers/base/bus.c                  | 52 ++++++++++++++++++++++++++++++-------
 include/linux/device.h              |  9 +++++++
 3 files changed, 60 insertions(+), 10 deletions(-)

Comments

Tejun Heo Oct. 6, 2014, 8:19 p.m. UTC | #1
Hello, Luis.

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

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

A question below.

On Fri, Oct 03, 2014 at 02:44:43PM -0700, Luis R. Rodriguez wrote:
> +	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.
Luis R. Rodriguez Oct. 6, 2014, 8:36 p.m. UTC | #2
On Mon, Oct 06, 2014 at 04:19:26PM -0400, Tejun Heo wrote:
> Hello, Luis.
> 
> The patchset generally looks good to me.  Please feel free to add
> 
>  Reviewed-by: Tejun Heo <tj@kernel.org>

Will do.

> A question below.
> 
> On Fri, Oct 03, 2014 at 02:44:43PM -0700, Luis R. Rodriguez wrote:
> > +	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
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Dmitry Torokhov Oct. 6, 2014, 8:41 p.m. UTC | #3
Hi Luis,

On Fri, Oct 03, 2014 at 02:44:43PM -0700, Luis R. Rodriguez wrote:
> From: "Luis R. Rodriguez" <mcgrof@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.

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.
Tejun Heo Oct. 6, 2014, 9:01 p.m. UTC | #4
Hello,

On Mon, Oct 06, 2014 at 10:36:27PM +0200, Luis R. Rodriguez wrote:
> > 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.
Luis R. Rodriguez Oct. 6, 2014, 11:10 p.m. UTC | #5
On Mon, Oct 06, 2014 at 05:01:18PM -0400, Tejun Heo wrote:
> Hello,
> 
> On Mon, Oct 06, 2014 at 10:36:27PM +0200, Luis R. Rodriguez wrote:
> > > 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.

> 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.

> 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
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tejun Heo Oct. 7, 2014, 5:34 p.m. UTC | #6
Hello,

On Tue, Oct 07, 2014 at 01:10:46AM +0200, Luis R. Rodriguez wrote:
> On Mon, Oct 06, 2014 at 05:01:18PM -0400, Tejun Heo wrote:
> > 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.

> 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().

...
> 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.
Luis R. Rodriguez Oct. 7, 2014, 5:50 p.m. UTC | #7
On Tue, Oct 07, 2014 at 01:34:04PM -0400, Tejun Heo wrote:
> Hello,
> 
> On Tue, Oct 07, 2014 at 01:10:46AM +0200, Luis R. Rodriguez wrote:
> > On Mon, Oct 06, 2014 at 05:01:18PM -0400, Tejun Heo wrote:
> > > 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.
> 
> > 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?

> ...
> > 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 netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tejun Heo Oct. 7, 2014, 5:55 p.m. UTC | #8
Hello,

On Tue, Oct 07, 2014 at 07:50:10PM +0200, Luis R. Rodriguez wrote:
> On Tue, Oct 07, 2014 at 01:34:04PM -0400, Tejun Heo wrote:
> > 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.
Luis R. Rodriguez Oct. 7, 2014, 6:55 p.m. UTC | #9
On Tue, Oct 7, 2014 at 10:55 AM, Tejun Heo <tj@kernel.org> wrote:
> Hello,
>
> On Tue, Oct 07, 2014 at 07:50:10PM +0200, Luis R. Rodriguez wrote:
>> On Tue, Oct 07, 2014 at 01:34:04PM -0400, Tejun Heo wrote:
>> > 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 netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Luis R. Rodriguez Oct. 7, 2014, 7:07 p.m. UTC | #10
On Tue, Oct 7, 2014 at 11:55 AM, Luis R. Rodriguez <mcgrof@suse.com> wrote:
> 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 netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

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;