On Thu, 9 Nov 2017, Mike Looijmans wrote: > Sometimes the USB device gets confused about the state of the initialization and > the connection fails. In particular, the device thinks that it's already set up > and running while the host thinks the device still needs to be configured. To > work around this issue, power-cycle the hub's output to issue a sort of "reset" > to the device. This makes the device restart its state machine and then the > initialization succeeds. > > This fixes problems where the kernel reports a list of errors like this: > > usb 1-1.3: device not accepting address 19, error -71 > > The end result is a non-functioning device. After this patch, the sequence > becomes like this: > > usb 1-1.3: new high-speed USB device number 18 using ci_hdrc > usb 1-1.3: device not accepting address 18, error -71 > usb 1-1.3: new high-speed USB device number 19 using ci_hdrc > usb 1-1.3: device not accepting address 19, error -71 > usb 1-1-port3: attempt power cycle > usb 1-1.3: new high-speed USB device number 21 using ci_hdrc > usb-storage 1-1.3:1.2: USB Mass Storage device detected > > Signed-off-by: Mike Looijmans <mike.looijmans@xxxxxxxx> > --- > v2: On feedback from Alan Stern: > No blank line changes > Don't further increase the retry count > Delay 2x the power-up delay (100ms minimum) instead of magic "800" > > drivers/usb/core/hub.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > > diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c > index e9ce6bb..8f7d942 100644 > --- a/drivers/usb/core/hub.c > +++ b/drivers/usb/core/hub.c > @@ -4935,6 +4935,15 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, > usb_put_dev(udev); > if ((status == -ENOTCONN) || (status == -ENOTSUPP)) > break; > + > + /* When halfway through our retry count, power-cycle the port */ > + if (i == (SET_CONFIG_TRIES / 2) - 1) { > + dev_info(&port_dev->dev, "attempt power cycle\n"); > + usb_hub_set_port_power(hdev, hub, port1, false); > + msleep(2 * hub_power_on_good_delay(hub)); > + usb_hub_set_port_power(hdev, hub, port1, true); > + msleep(hub_power_on_good_delay(hub)); > + } > } > if (hub->hdev->parent || > !hcd->driver->port_handed_over || Acked-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html