Re: [PATCH] driver core: introduce PROBE_FORCE_ASYNCHRONOUS
Dmitry Torokhov <[email protected]> Tue, 28 Jul 2026 22:40:29 -0700
| Newsgroups | dev.linux.lists.driver-core,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On Mon, Jul 27, 2026 at 08:25:51AM +0200, Greg Kroah-Hartman wrote: > On Sun, Jul 26, 2026 at 10:54:54PM -0700, Dmitry Torokhov wrote: > > On Mon, Jul 27, 2026 at 07:40:57AM +0200, Greg Kroah-Hartman wrote: > > > On Sun, Jul 26, 2026 at 10:31:41PM -0700, Dmitry Torokhov wrote: > > > > Add PROBE_FORCE_ASYNCHRONOUS probe type enum and update > > > > driver_allows_async_probing() to allow asynchronous probing for drivers > > > > marked with this type. > > > > > > > > While PROBE_PREFER_ASYNCHRONOUS exists, it represents a temporary opt-in > > > > preference. Subsystems that require asynchronous probing (such as slow > > > > legacy buses) need a dedicated probe type to guarantee asynchronous > > > > execution. > > > > > > > > Assisted-by: Antigravity:gemini-3.5-flash > > > > Signed-off-by: Dmitry Torokhov <[email protected]> > > > > --- > > > > > > > > I am planning to rework serio and gameport subsystems to rely on > > > > asynchronous probing instead of rolling their own implementations. > > > > > > What do you mean? Why doesn't the PROBE_PREFER_ASYNCHRONOUS work for > > > you for those subsystems? > > > > It shows the intent. It is not "preference" anymore, it is a "must". If > > we ever introduce switch to make probing synchronous for some reason it > > should not affect drivers that must be probed asynchronously. > > I'm sorry, but I don't understand. PROBE_PREFER_ASYNCHRONOUS says that the driver prefers to be probe asynchronously but it can also be probed synchronously if needed. PROBE_FORCE_ASYNCHRONOUS indicates that the driver *must* be probed asynchronously, or the kernel will break. Currently there is no difference in behavior, but it documents the intent. > And as there's no users for this, we > really can't take it until we see those users at the same time :) I am planning to use it in serio and gameport bus implementations that currently roll their own asynchronous registration which is quite ugly. Because we have nested serio ports probing *must* be done asynchronously or it will deadlock. I would like to merge the new constant early so that I do not have dependency when I am ready to merge input changes. Below is how it will look like (just a small part of a WIP series). Thanks. -- Dmitry Input: serio - use PROBE_FORCE_ASYNCHRONOUS and make port registration synchronous From: Dmitry Torokhov <[email protected]> Mark serio drivers as using PROBE_FORCE_ASYNCHRONOUS instead of PROBE_PREFER_ASYNCHRONOUS during registration. At the same time, rework __serio_register_port() to run synchronously under serio_mutex instead of queuing a SERIO_REGISTER_PORT event to kseriod. This ensures port registration happens synchronously while driver probing is handled asynchronously by the driver core. Assisted-by: Antigravity:gemini-3.5-flash Signed-off-by: Dmitry Torokhov <[email protected]> --- drivers/input/serio/serio.c | 46 +++++-------------------------------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index dd53c2b7a39d..f47d90f0507b 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -124,7 +124,6 @@ enum serio_event_type { SERIO_RESCAN_PORT, SERIO_RECONNECT_PORT, SERIO_RECONNECT_SUBTREE, - SERIO_REGISTER_PORT, }; struct serio_event { @@ -190,11 +189,6 @@ static void serio_handle_event(struct work_struct *work) while ((event = serio_get_event())) { switch (event->type) { - - case SERIO_REGISTER_PORT: - serio_add_port(event->object); - break; - case SERIO_RECONNECT_PORT: serio_reconnect_port(event->object); break; @@ -279,30 +273,6 @@ static void serio_remove_pending_events(void *object) } } -/* - * Locate child serio port (if any) that has not been fully registered yet. - * - * Children are registered by driver's connect() handler so there can't be a - * grandchild pending registration together with a child. - */ -static struct serio *serio_get_pending_child(struct serio *parent) -{ - struct serio_event *event; - struct serio *serio; - - guard(spinlock_irqsave)(&serio_event_lock); - - list_for_each_entry(event, &serio_event_list, node) { - if (event->type == SERIO_REGISTER_PORT) { - serio = event->object; - if (serio->parent == parent) - return serio; - } - } - - return NULL; -} - /* * Serio port operations */ @@ -516,13 +486,6 @@ static void serio_add_port(struct serio *serio) */ static void serio_destroy_port(struct serio *serio) { - struct serio *child; - - while ((child = serio_get_pending_child(serio)) != NULL) { - serio_remove_pending_events(child); - put_device(&child->dev); - } - if (serio->stop) serio->stop(serio); @@ -653,13 +616,14 @@ void serio_reconnect(struct serio *serio) EXPORT_SYMBOL(serio_reconnect); /* - * Submits register request to kseriod for subsequent execution. - * Note that port registration is always asynchronous. + * Synchronously registers serio port. */ int __serio_register_port(struct serio *serio, struct module *owner) { serio_init_port(serio); - serio_queue_event(serio, owner, SERIO_REGISTER_PORT); + + guard(mutex)(&serio_mutex); + serio_add_port(serio); return 0; } @@ -778,7 +742,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons * Mark all serio drivers as using asynchronous probe because serio * devices are slow and their probing takes long time. */ - drv->driver.probe_type = PROBE_PREFER_ASYNCHRONOUS; + drv->driver.probe_type = PROBE_FORCE_ASYNCHRONOUS; error = driver_register(&drv->driver); if (error) {