Re: [RFC v2 05/11] USB: Ignore port state until reset completes.

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

 



On Tue, 4 Dec 2012, Sarah Sharp wrote:

> The port reset code bails out early if the current connect status is
> cleared (device disconnected).  If we're issuing a hot reset, it may
> also look at the link state before the reset is finished.
> 
> Section 10.14.2.6 of the USB 3.0 spec says that when a port enters the
> Error state or Resetting state, the port connection bit retains the
> value from the previous state.  Therefore we can't trust it until the
> reset finishes.  Also, the xHCI spec section 4.19.1.2.5 says software
> shall ignore the link state while the port is resetting, as it can be in
> an unknown state.
> 
> The port state during reset is also unknown for USB 2.0 hubs.  The hub
> sends a reset signal by driving the bus into an SE0 state.  This
> overwhelms the "connect" signal from the device, so the port can't tell
> whether anything is connected or not.
> 
> Fix the port reset code to ignore the port link state and current
> connect bit until the reset finishes.
> 
> This patch should be backported to all stable kernels.
> 
> Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx>
> Cc: stable@xxxxxxxxxxxxxxx
> ---
>  drivers/usb/core/hub.c |    5 +++++
>  1 files changed, 5 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index b9ce5e8..b7b055f 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -2534,6 +2534,10 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
>  		if (ret < 0)
>  			return ret;
>  
> +		/* The port state is unknown until the reset completes. */
> +		if ((portstatus & USB_PORT_STAT_RESET))
> +			goto delay;
> +
>  		/*
>  		 * Some buggy devices require a warm reset to be issued even
>  		 * when the port appears not to be connected.
> @@ -2601,6 +2605,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
>  				return 0;
>  		}
>  
> +delay:
>  		/* switch to the long delay after two short delay failures */
>  		if (delay_time >= 2 * HUB_SHORT_RESET_TIME)
>  			delay = HUB_LONG_RESET_TIME;

At some point this entire loop should be turned inside out.  The
outline should be:

	for (delay_time = 0; ...) {
		msleep(delay);

		ret = hub_port_status(...);
		if (reset finished)
			break;

		adjust the delay time
	}

	Do all the stuff involving the various status bits...

Maybe you'd prefer to make this change after some of the other patches 
in this series.  That would be fine, so long as it does eventually get 
made.

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