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 Thu, 21 May 2015, Robert Schlabbach wrote:

> Thanks for the reply, Alan.
> 
> The USB device is initially in link state 0, and only after the "cold"
> reset in link state SS.inactive. After the following warm reset, it is
> in link state 0 again.
> 
> > ... 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.
> 
> Looking at the code, I'd say the hub_port_finish_reset() call is actually
> in the _right_ place, because that's where we know that a reset was really
> initiated (that step could have errored out) and the reset _try_ should be
> finished before the next retry.

On closer inspection, the situation looks rather mixed up.  
hub_port_finish_reset() does two types of things:

	Things that need to happen after each reset in a retry
	sequence (like clearing USB_PORT_FEAT_C_RESET);

	Things that need to happen after the entire retry sequence
	is over (like the TRSTRCY delay and calling 
	usb_set_device_state).

These shouldn't all be in the same subroutine.  Maybe the first class
of actions should be moved into hub_port_wait_reset.  Or maybe the 
second class should be moved into hub_port_reset.

> What is in the wrong place is coincidentally that code fragment at the
> end of hub_port_finish_reset() which I had quoted last time:
> 
> >     if (udev)
> >         usb_set_device_state(udev, *status
> >             ? USB_STATE_NOTATTACHED
> >             : USB_STATE_DEFAULT);
> 
> That part should be done after the retry loop, because the device state
> should not be set based on the result of an "interim" reset result
> (especially not when the setting may be irrevocable), but rather based
> on the final reset result.
> 
> So I moved this code fragment from hub_port_finish_reset() to the end of
> hub_port_reset() and made sure it only gets there when a reset attempt
> was actually made. The following diff is based on kernel sources 3.19.8:

Kernel hackers always use the unified diff format.  We are so used it 
that we can't even read the old format.  :-)

> That also alters the handling of some errors which before the patch caused
> hub_port_finish_reset() never to be called and thus the USB device state
> not to be altered, but I think it is actually more appropriate to set a
> USB device to NOTATTACHED if the reset could not even be initiated, e.g.
> because of ENODEV...
> 
> It will still leave the USB device state unchanged if it errors out at the
> initial "double check" if a warm reset is needed, as the current code
> does. It might be more appropriate to just skip the double check rather
> than exiting, though...
> 
> What do you think, is that an appropriate fix?

I suspect you have not divided up all the actions in the correct way.  
Look at everything in hub_port_finish_reset and think carefully about
where each one belongs.

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