Re: [BUG] USB 3.0 device "lost for good" when in SS.inactive or Compliance Mode during hub_port_reset()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 20 May 2015, Robert Schlabbach wrote:

> Dear Linux USB experts,
> 
> I recently ran into an issue where Linux 3.19 would frequently "lose"
> a USB 3.0 stick it was supposed to boot from and bomb out because it
> couldn't mount the root fs.
> 
> Upon closer investigation, I found that the hub port the USB 3.0 stick
> is connected to apparently likes to go into SS.inactive state at
> initialization. Now looking at the code, it looks as if a "warm reset"
> is supposed to fix that. But in fact, it can't. Here's a crude draft
> of the calls inside /drivers/usb/core/hub.c I observed:
> 
> 1. hub_port_reset()

Is the port already in the INACTIVE state at this point?  If it is then 
hub_port_reset will carry out a warm reset.

> 2. > hub_port_wait_reset()
> 3. > > hub_port_status() returns port status 0x02C0
>        (link state = USB_SS_PORT_LS_SS_INACTIVE)

So following the reset, the port is still inactive.  If the reset was a 
warm reset then we can conclude that it failed, and the device really 
should be marked DISCONNECTED.

On the other hand, if it was a normal reset then we realize that 
we have to retry with a warm reset.  There is code to do this in 
hub_port_reset...

> 4. > > hub_port_warm_reset_required() returns TRUE due to
>        link_state == USB_SS_PORT_LS_SS_INACTIVE
> 5. > hub_port_wait_reset() returns -ENOTCONN due to the TRUE result
>      from hub_port_warm_reset_required()
> 6. > hub_port_finish_reset(... *status = -ENOTCONN)
> 7. > > usb_set_device_state(udev, USB_STATE_NOTATTACHED)

... but the code is in the wrong place.  The check needs to occur 
before hub_port_finish_reset, not after.  It's a bug to call 
hub_port_finish_reset before the retry loop is over; that call should 
happen after the end of the loop.

> I tried altering the end of hub_port_finish_reset() to:
> 
>     if (udev)
>         usb_set_device_state(udev, *status
>             ? USB_STATE_ATTACHED // FIX: was USB_STATE_NOTATTACHED
>             : USB_STATE_DEFAULT);
> 
> and that fixed the problem I was seeing, but I'm not sure if this is the
> proper way to fix this, or if it should be fixed e.g. in hub_port_reset()
> when it knows that a warm reset will still be tried.

The latter.

> Any thoughts if my assessment is right and how to properly fix this?

Do you want to try re-arranging the section surrounding the

		/* Check for disconnect or reset */

comment in hub_port_reset?

Alan Stern

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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux