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: 3d82904559f4 ("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>

authored by Pawel Laszczak and committed by Greg Kroah-Hartman 2b66ef84 552ca6b8

+33
+33
drivers/usb/core/hub.c
··· 6066 6066 } /* usb_hub_cleanup() */ 6067 6067 6068 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 + 6098 + /** 6069 6099 * usb_reset_and_verify_device - perform a USB port reset to reinitialize a device 6070 6100 * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) 6071 6101 * ··· 6158 6128 6159 6129 bos = udev->bos; 6160 6130 udev->bos = NULL; 6131 + 6132 + if (udev->reset_resume) 6133 + hub_hc_release_resources(udev); 6161 6134 6162 6135 mutex_lock(hcd->address0_mutex); 6163 6136