Skip to content

Commit 2b66ef8

Browse files
pawellcdnsgregkh
authored andcommitted
usb: hub: lack of clearing xHC resources
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 properly released. 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: 3d82904 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver") Cc: stable <stable@kernel.org> Signed-off-by: Pawel Laszczak <pawell@cadence.com> Reviewed-by: Alan Stern <stern@rowland.harvard.edu> Link: https://lore.kernel.org/r/PH7PR07MB953841E38C088678ACDCF6EEDDCC2@PH7PR07MB9538.namprd07.prod.outlook.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 552ca6b commit 2b66ef8

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

drivers/usb/core/hub.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6065,6 +6065,36 @@ void usb_hub_cleanup(void)
60656065
usb_deregister(&hub_driver);
60666066
} /* usb_hub_cleanup() */
60676067

6068+
/**
6069+
* hub_hc_release_resources - clear resources used by host controller
6070+
* @udev: pointer to device being released
6071+
*
6072+
* Context: task context, might sleep
6073+
*
6074+
* Function releases the host controller resources in correct order before
6075+
* making any operation on resuming usb device. The host controller resources
6076+
* allocated for devices in tree should be released starting from the last
6077+
* usb device in tree toward the root hub. This function is used only during
6078+
* resuming device when usb device require reinitialization – that is, when
6079+
* flag udev->reset_resume is set.
6080+
*
6081+
* This call is synchronous, and may not be used in an interrupt context.
6082+
*/
6083+
static void hub_hc_release_resources(struct usb_device *udev)
6084+
{
6085+
struct usb_hub *hub = usb_hub_to_struct_hub(udev);
6086+
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
6087+
int i;
6088+
6089+
/* Release up resources for all children before this device */
6090+
for (i = 0; i < udev->maxchild; i++)
6091+
if (hub->ports[i]->child)
6092+
hub_hc_release_resources(hub->ports[i]->child);
6093+
6094+
if (hcd->driver->reset_device)
6095+
hcd->driver->reset_device(hcd, udev);
6096+
}
6097+
60686098
/**
60696099
* usb_reset_and_verify_device - perform a USB port reset to reinitialize a device
60706100
* @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
@@ -6129,6 +6159,9 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
61296159
bos = udev->bos;
61306160
udev->bos = NULL;
61316161

6162+
if (udev->reset_resume)
6163+
hub_hc_release_resources(udev);
6164+
61326165
mutex_lock(hcd->address0_mutex);
61336166

61346167
for (i = 0; i < PORT_INIT_TRIES; ++i) {

0 commit comments

Comments
 (0)