Re: [RFC v2 10/11] USB: Rip out recursive call on warm port reset.

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

 



On Tue, 4 Dec 2012, Sarah Sharp wrote:

> When a hot reset fails on a USB 3.0 port, the current port reset code
> recursively calls hub_port_reset inside hub_port_wait_reset.  This isn't
> ideal, since we should avoid recursive calls in the kernel, and it also
> doesn't allow us to issue multiple warm resets on reset failures.
> 
> Rip out the recursive call.  Instead, add code to hub_port_reset to
> issue a warm reset if the hot reset fails, and try multiple warm resets
> before giving up on the port.

This is better than before.  There is still a little bit I don't quite
follow...

> In hub_port_wait_reset, remove the recursive call and re-indent.  The
> code is basically the same, except:
> 
> 1. It bails out early if the port has transitioned to Inactive or
> Compliance Mode after the reset completed.
> 
> 2. It doesn't consider a connect status change to be a failed reset.  If
> multiple warm resets needed to be issued, the connect status may have
> changed, so we need to ignore that and look at the port link state
> instead.  hub_port_reset will now do that.

In fact, we might as well do the same thing for non-SuperSpeed
connections too.  The kernel probably is smart enough not to get
confused if the user manages to replace one device with another while a
reset is in progress.

> 3. It unconditionally sets udev->speed on all types of successful
> resets.  The old recursive code would set the port speed when the second
> hub_port_reset returned.
> 
> With the new code in hub_port_reset, the 'warm' variable may change on a
> transition from a hot reset to a warm reset.  So hub_port_finish_reset
> could be called with 'warm' set to true when a connected USB device has
> been reset.  Fix the code by unconditionally updating the device number,
> informing the host that the device has been reset, and setting the
> device state to default.

Why was it necessary to skip these things before, when "warm" was set?  
Was it merely an optimization?  If not, do the same reasons still 
apply?

> In hub_port_finish_reset, unconditionally clear the connect status
> change (CSC) bit for USB 3.0 hubs when the port reset is done.  If we
> had to issue multiple warm resets for a device, that bit may have been
> set if the device went into SS.Inactive and then was successfully warm
> reset.
> 
> Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx>
> ---
>  drivers/usb/core/hub.c |  159 +++++++++++++++++++++--------------------------
>  1 files changed, 71 insertions(+), 88 deletions(-)
> 
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index d8de712..a502857 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -2538,80 +2538,39 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,

> -			if (!(portstatus & USB_PORT_STAT_CONNECTION) ||
> -					hub_port_warm_reset_required(hub,
> -						portstatus))
> -				return -ENOTCONN;
> +		/* if we've finished resetting, then break out of
> +		 * the loop
> +		 */
> +		if (!(portstatus & USB_PORT_STAT_RESET) &&

This test is redundant thanks to your 5/11 patch, right?

> @@ -2703,10 +2663,33 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
>  						status);
>  		}
>  
> -		/* return on disconnect or reset */
> +		/* Check for disconnect or reset */
>  		if (status == 0 || status == -ENOTCONN || status == -ENODEV) {
> -			hub_port_finish_reset(hub, port1, udev, &status, warm);
> -			goto done;
> +			hub_port_finish_reset(hub, port1, udev, &status);
> +
> +			if (!hub_is_superspeed(hub->hdev))
> +				goto done;
> +
> +			/*
> +			 * If a USB 3.0 device migrates from reset to an error
> +			 * state, re-issue the warm reset.
> +			 */
> +			if (hub_port_status(hub, port1,
> +					&portstatus, &portchange) < 0)
> +				goto done;

Hmmm.  Is there any reasonable way to get the portstatus value from 
hub_port_finish_reset instead of asking for it again?

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