On Thu, Feb 06, 2025 at 11:39:50AM -0800, Elson Roy Serrao wrote: > The role switch registration and set_role() can happen in parallel as they > are invoked independent of each other. There is a possibility that a driver > might spend significant amount of time in usb_role_switch_register() API > due to the presence of time intensive operations like component_add() > which operate under common mutex. This leads to a time window after > allocating the switch and before setting the registered flag where the set > role notifications are dropped. Below timeline summarizes this behavior > > Thread1 | Thread2 > usb_role_switch_register() | > | | > ---> allocate switch | > | | > ---> component_add() | usb_role_switch_set_role() > | | | > | | --> Drop role notifications > | | since sw->registered > | | flag is not set. > | | > --->Set registered flag.| > > To avoid this, set the registered flag early on in the switch register > API. > > Fixes: b787a3e78175 ("usb: roles: don't get/set_role() when usb_role_switch is unregistered") > cc: stable@xxxxxxxxxxxxxxx > Signed-off-by: Elson Roy Serrao <quic_eserrao@xxxxxxxxxxx> Reviewed-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx> > --- > Changes in v2: > - Set the switch registered flag from the get-go as suggested by > Heikki. > - Modified subject line and commit next as per the new logic. > - Link to v1: https://lore.kernel.org/all/20250127230715.6142-1-quic_eserrao@xxxxxxxxxxx/ > > drivers/usb/roles/class.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c > index c58a12c147f4..30482d4cf826 100644 > --- a/drivers/usb/roles/class.c > +++ b/drivers/usb/roles/class.c > @@ -387,8 +387,11 @@ usb_role_switch_register(struct device *parent, > dev_set_name(&sw->dev, "%s-role-switch", > desc->name ? desc->name : dev_name(parent)); > > + sw->registered = true; > + > ret = device_register(&sw->dev); > if (ret) { > + sw->registered = false; > put_device(&sw->dev); > return ERR_PTR(ret); > } > @@ -399,8 +402,6 @@ usb_role_switch_register(struct device *parent, > dev_warn(&sw->dev, "failed to add component\n"); > } > > - sw->registered = true; > - > /* TODO: Symlinks for the host port and the device controller. */ > > return sw; > -- > 2.17.1 -- heikki