Both the suspected quirky Synopsys xHC [1] and the port-pm-runtime-resume path need to issue warm resets to reliably bring ports back to an operational state. Per Alan's observation this also arranges for these warm resets to be queued asynchronously. Per my previous testing I found cases where khubd takes actions on ports that are known to still be in recovery (unintended disconnects). This set mitigates those interactions by pushing resume operations into khubd context by making khubd a workqueue. Please focus review on patch 4. usb_port_resume() running in khubd context may turn out to not be necessary, but I need to test more. The expected sequence of events for the hub_resume case is: 1/ hub_resume 2/ scan through all ports and queue (async) port warm resets if necessary 3/ kick_khubd 4/ hub_event() syncs all in-flight resets 5/ child device resume proceeds in parallel with hub_event as before (child device resume also syncs in-flight warm resets if it happens to occur before hub_event() runs) The sequence of events in the pm-runtime case is: 1/ usb_port_runtime_resume queues an async warm reset, and requests a reset-resume of the child device if present 2/ child device resume syncs the in-flight reset and optionally does reset-resume Note that this only implements the reset for the pm-runtime case. xhci_port_resume() is where the xHC quirk can be placed to do the same for the hub_resume() case. Only lightly tested. Looking for positive feedback before rebasing the rest of the port power rework on top of this approach. [1]: http://marc.info/?l=linux-usb&m=138683173421509&w=2 --- Dan Williams (4): usb: introduce hub->resume_bits and HCD_FLAG_RESET_RESUME usb: convert khubd to a workqueue usb: reset resume in khubd context usb: port pm recovery drivers/usb/core/driver.c | 40 +++++++- drivers/usb/core/generic.c | 23 ++++- drivers/usb/core/hub.c | 211 +++++++++++++++++------------------------- drivers/usb/core/hub.h | 25 +---- drivers/usb/core/port.c | 80 +++++++++++----- drivers/usb/core/usb.c | 1 drivers/usb/core/usb.h | 8 ++ drivers/usb/host/xhci-pci.c | 1 drivers/usb/host/xhci-plat.c | 1 drivers/usb/host/xhci.c | 8 ++ drivers/usb/host/xhci.h | 2 include/linux/usb.h | 6 + include/linux/usb/hcd.h | 7 + 13 files changed, 235 insertions(+), 178 deletions(-) ...not that I expect any review over the weekend, but wanted to get this out before heading home. -- Dan One more note, the udev->reset_resume to hub->resume_bit conversion also needs the below two patches, but I left them out of the series for now to keep the patch count lower. commit e724d476af11c1066d425fa64d2fedcc0a4415b0 Author: Dan Williams <dan.j.williams@xxxxxxxxx> Date: Wed Dec 18 14:43:47 2013 -0800 p54usb: set USB_QUIRK_RESET_RESUME ...rather than scheduling a single shot at probe. Found by inspection not sure if this will cause regressions since only the first resume is guaranteed to trigger a reset. I.e. this device may now see more resets. Cc: Christian Lamparter <chunkeey@xxxxxxxxxxxxxx> Cc: linux-wireless@xxxxxxxxxxxxxxx Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx> diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index e328d3058c41..f27674c46c1b 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -1035,10 +1035,8 @@ static int p54u_probe(struct usb_interface *intf, priv->common.open = p54u_open; priv->common.stop = p54u_stop; if (recognized_pipes < P54U_PIPE_NUMBER) { -#ifdef CONFIG_PM /* ISL3887 needs a full reset on resume */ - udev->reset_resume = 1; -#endif /* CONFIG_PM */ + udev->quirks |= USB_QUIRK_RESET_RESUME; err = p54u_device_reset(dev); priv->hw_type = P54U_3887; commit 0dda95bd66c4a59d4c8dc247a998bbed658a26c4 Author: Dan Williams <dan.j.williams@xxxxxxxxx> Date: Wed Dec 18 14:32:22 2013 -0800 ath9k_hif_usb: set USB_QUIRK_RESET_RESUME ...rather than scheduling a single shot at probe. Found by inspection not sure if this will cause regressions since only the first resume is guaranteed to trigger a reset. I.e. this device may now see more resets. Cc: Luis R. Rodriguez <mcgrof@xxxxxxxxxxxxxxxx> Cc: Jouni Malinen <jouni@xxxxxxxxxxxxxxxx> Cc: Vasanthakumar Thiagarajan <vthiagar@xxxxxxxxxxxxxxxx> Cc: Senthil Balasubramanian <senthilb@xxxxxxxxxxxxxxxx> Cc: linux-wireless@xxxxxxxxxxxxxxx Cc: ath9k-devel@xxxxxxxxxxxxxxx Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx> diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 6d5d716adc1b..44e5b3ee2938 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -1205,9 +1205,7 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, hif_dev->udev = udev; hif_dev->interface = interface; hif_dev->usb_device_id = id; -#ifdef CONFIG_PM - udev->reset_resume = 1; -#endif + udev->quirks |= USB_QUIRK_RESET_RESUME; usb_set_intfdata(interface, hif_dev); init_completion(&hif_dev->fw_done); -- 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