summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/driver.c9
-rw-r--r--drivers/usb/core/hub.c6
-rw-r--r--drivers/usb/host/ehci-hub.c4
-rw-r--r--drivers/usb/host/ehci-pci.c1
4 files changed, 14 insertions, 6 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 801b6f142fa..ebccdefcc6f 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1523,9 +1523,14 @@ static int usb_suspend(struct device *dev, pm_message_t message)
udev = to_usb_device(dev);
/* If udev is already suspended, we can skip this suspend and
- * we should also skip the upcoming system resume. */
+ * we should also skip the upcoming system resume. High-speed
+ * root hubs are an exception; they need to resume whenever the
+ * system wakes up in order for USB-PERSIST port handover to work
+ * properly.
+ */
if (udev->state == USB_STATE_SUSPENDED) {
- udev->skip_sys_resume = 1;
+ if (udev->parent || udev->speed != USB_SPEED_HIGH)
+ udev->skip_sys_resume = 1;
return 0;
}
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 57aeca160f3..a42db75c233 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2890,7 +2890,13 @@ loop:
static int hub_thread(void *__unused)
{
+ /* khubd needs to be freezable to avoid intefering with USB-PERSIST
+ * port handover. Otherwise it might see that a full-speed device
+ * was gone before the EHCI controller had handed its port over to
+ * the companion full-speed controller.
+ */
set_freezable();
+
do {
hub_events();
wait_event_freezable(khubd_wait,
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 4e065e556e4..8d513a15d0c 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -281,9 +281,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
spin_unlock_irq (&ehci->lock);
-
- if (!power_okay)
- ehci_handover_companion_ports(ehci);
+ ehci_handover_companion_ports(ehci);
return 0;
}
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 72ccd56e36d..040bd8632eb 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -329,7 +329,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
/* here we "know" root ports should always stay powered */
ehci_port_power(ehci, 1);
- ehci_handover_companion_ports(ehci);
hcd->state = HC_STATE_SUSPENDED;
return 0;