RE: [PATCH v2] usb: xhci: lack of clearing xHC resources

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

 



>> The xHC resources allocated for USB devices are not released in
>> correct order after resuming in case when while suspend device was
>reconnected.
>>
>> This issue has been detected during the fallowing scenario:
>> - connect hub HS to root port
>> - connect LS/FS device to hub port
>> - wait for enumeration to finish
>> - force host to suspend
>> - reconnect hub attached to root port
>> - wake host
>>
>> For this scenario during enumeration of USB LS/FS device the Cadence
>> xHC reports completion error code for xHC commands because the xHC
>> resources used for devices has not been property released.
>
>s/property/properly/
>
>> XHCI specification doesn't mention that device can be reset in any
>> order so, we should not treat this issue as Cadence xHC controller bug.
>> Similar as during disconnecting in this case the device resources
>> should be cleared starting form the last usb device in tree toward the root
>hub.
>> To fix this issue usbcore driver should call hcd->driver->reset_device
>> for all USB devices connected to hub which was reconnected while
>> suspending.
>>
>> Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence
>> USBSSP DRD Driver")
>> cc: <stable@xxxxxxxxxxxxxxx>
>> Signed-off-by: Pawel Laszczak <pawell@xxxxxxxxxxx>
>>
>> ---
>> Changelog:
>> v2:
>> - Replaced disconnection procedure with releasing only the xHC
>> resources
>>
>>  drivers/usb/core/hub.c | 33 +++++++++++++++++++++++++++++++++
>>  1 file changed, 33 insertions(+)
>>
>> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index
>> a76bb50b6202..d3f89528a414 100644
>> --- a/drivers/usb/core/hub.c
>> +++ b/drivers/usb/core/hub.c
>> @@ -6065,6 +6065,36 @@ void usb_hub_cleanup(void)
>>  	usb_deregister(&hub_driver);
>>  } /* usb_hub_cleanup() */
>>
>> +/**
>> + * hub_hc_release_resources - clear resources used by host controller
>> + * @pdev: pointer to device being released
>> + *
>> + * Context: task context, might sleep
>> + *
>> + * Function releases the host controller resources in correct order
>> +before
>> + * making any operation on resuming usb device. The host controller
>> +resources
>> + * allocated for devices in tree should be released starting from the
>> +last
>> + * usb device in tree toward the root hub. This function is used only
>> +during
>> + * resuming device when usb device require reinitialization - that
>> +is, when
>> + * flag udev->reset_resume is set.
>> + *
>> + * This call is synchronous, and may not be used in an interrupt context.
>> + */
>> +static void hub_hc_release_resources(struct usb_device *udev) {
>> +	struct usb_hub *hub = usb_hub_to_struct_hub(udev);
>> +	struct usb_hcd *hcd = bus_to_hcd(udev->bus);
>> +	int i;
>> +
>> +	/* Release up resources for all children before this device */
>> +	for (i = 0; i < udev->maxchild; i++)
>> +		if (hub->ports[i]->child)
>> +			hub_hc_release_resources(hub->ports[i]->child);
>> +
>> +	if (hcd->driver->reset_device)
>> +		hcd->driver->reset_device(hcd, udev); }
>> +
>>  /**
>>   * usb_reset_and_verify_device - perform a USB port reset to reinitialize a
>device
>>   * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) @@
>> -6131,6 +6161,9 @@ static int usb_reset_and_verify_device(struct
>> usb_device *udev)
>>
>>  	mutex_lock(hcd->address0_mutex);
>>
>> +	if (udev->reset_resume)
>> +		hub_hc_release_resources(udev);
>
>Don't you want to do this before taking the address0_mutex lock?

I will move it.

>
>> +
>>  	for (i = 0; i < PORT_INIT_TRIES; ++i) {
>>  		if (hub_port_stop_enumerate(parent_hub, port1, i)) {
>>  			ret = -ENODEV;
>
>Doing it this way, you will call hcd->driver->reset_device() multiple times for the
>same device: once for the hub(s) above the device and then once for the device
>itself.  But since this isn't a hot path, maybe that doesn't matter.

Yes, it true but the function xhci_discover_or_reset_device which is associated with
hcd->driver->reset_device() include the checking whether device is in SLOT_STATE_DISABLED.
It allows to detect whether device has been already reset and do not repeat the
reset procedure.

Thanks
Pawel Laszczak
>
>Alan Stern





[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux