Re: [RFC PATCH 2/2] usb: core: hub: avoid reset hub during probe

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

 



On Fri, Mar 03, 2023 at 05:28:38PM +0800, Linyu Yuan wrote:
> When start probe hub, during INIT, INTT2, INIT3 stage, when link state
> change to inactive, currently it will reset the device, maybe it will
> trigger warning in usb_submit_urb() due to urb->hcpriv is still active.

You need to explain this in much greater detail.

	What will reset the device?

	What is the code path for this reset?

	Why will urb->hcpriv still be active?

> Add a flag name init_stage to avoid reset the device.

Why do you want to avoid resetting the device?

Doesn't the reset code already include a check for whether the device is 
disconnected?

> 
> Signed-off-by: Linyu Yuan <quic_linyyuan@xxxxxxxxxxx>
> ---
>  drivers/usb/core/hub.c | 20 +++++++++++++++++++-
>  drivers/usb/core/hub.h |  1 +
>  2 files changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index 97a0f8f..3cb1137 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -1290,6 +1290,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
>  	if (type == HUB_INIT2 || type == HUB_INIT3) {
>  		/* Allow autosuspend if it was suppressed */
>   disconnected:
> +		hub->init_stage = 0;
>  		usb_autopm_put_interface_async(to_usb_interface(hub->intfdev));
>  		device_unlock(&hdev->dev);
>  	}
> @@ -1872,6 +1873,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
>  	kref_init(&hub->kref);
>  	hub->intfdev = &intf->dev;
>  	hub->hdev = hdev;
> +	hub->init_stage = 1;
>  	INIT_DELAYED_WORK(&hub->leds, led_work);
>  	INIT_DELAYED_WORK(&hub->init_work, NULL);
>  	INIT_WORK(&hub->events, hub_event);
> @@ -5587,6 +5589,21 @@ static void port_over_current_notify(struct usb_port *port_dev)
>  	kfree(port_dev_path);
>  }
>  
> +static bool port_child_avoid_reset(struct usb_device *udev)
> +{
> +	struct usb_hub *hub;
> +
> +	if (udev->descriptor.bDeviceClass == USB_CLASS_HUB &&
> +	    udev->state == USB_STATE_CONFIGURED) {
> +		hub = usb_get_intfdata(udev->actconfig->interface[0]);
> +
> +		if (hub && hub->init_stage)
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
>  static void port_event(struct usb_hub *hub, int port1)
>  		__must_hold(&port_dev->status_lock)
>  {
> @@ -5699,7 +5716,8 @@ static void port_event(struct usb_hub *hub, int port1)
>  			dev_dbg(&port_dev->dev, "do warm reset, full device\n");
>  			usb_unlock_port(port_dev);
>  			usb_lock_device(udev);
> -			usb_reset_device(udev);
> +			if (!port_child_avoid_reset(udev))
> +				usb_reset_device(udev);
>  			usb_unlock_device(udev);

Doesn't usb_lock_device() already prevent this code from running during 
the INIT, INIT2, and INIT3 stages of hub preparation?

Alan Stern



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

  Powered by Linux