summary refs log tree commit diff
path: root/drivers/usb/host/ehci-pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-pci.c')
-rw-r--r--drivers/usb/host/ehci-pci.c40
1 files changed, 16 insertions, 24 deletions
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index e51c1ed81ac4..4bc7970ba3ef 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -257,9 +257,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
 static int ehci_pci_resume(struct usb_hcd *hcd)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
-	unsigned		port;
 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
-	int			retval = -EINVAL;
 
 	// maybe restore FLADJ
 
@@ -269,27 +267,19 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
 	/* Mark hardware accessible again as we are out of D3 state by now */
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
-	/* If CF is clear, we lost PCI Vaux power and need to restart.  */
-	if (readl(&ehci->regs->configured_flag) != FLAG_CF)
-		goto restart;
-
-	/* If any port is suspended (or owned by the companion),
-	 * we know we can/must resume the HC (and mustn't reset it).
-	 * We just defer that to the root hub code.
+	/* If CF is still set, we maintained PCI Vaux power.
+	 * Just undo the effect of ehci_pci_suspend().
 	 */
-	for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
-		u32	status;
-		port--;
-		status = readl(&ehci->regs->port_status [port]);
-		if (!(status & PORT_POWER))
-			continue;
-		if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) {
-			usb_hcd_resume_root_hub(hcd);
-			return 0;
-		}
+	if (readl(&ehci->regs->configured_flag) == FLAG_CF) {
+		int	mask = INTR_MASK;
+
+		if (!device_may_wakeup(&hcd->self.root_hub->dev))
+			mask &= ~STS_PCD;
+		writel(mask, &ehci->regs->intr_enable);
+		readl(&ehci->regs->intr_enable);
+		return 0;
 	}
 
-restart:
 	ehci_dbg(ehci, "lost power, restarting\n");
 	usb_root_hub_lost_power(hcd->self.root_hub);
 
@@ -307,13 +297,15 @@ restart:
 	ehci_work(ehci);
 	spin_unlock_irq(&ehci->lock);
 
-	/* restart; khubd will disconnect devices */
-	retval = ehci_run(hcd);
-
 	/* here we "know" root ports should always stay powered */
 	ehci_port_power(ehci, 1);
 
-	return retval;
+	writel(ehci->command, &ehci->regs->command);
+	writel(FLAG_CF, &ehci->regs->configured_flag);
+	readl(&ehci->regs->command);	/* unblock posted writes */
+
+	hcd->state = HC_STATE_SUSPENDED;
+	return 0;
 }
 #endif