aboutsummaryrefslogtreecommitdiffstats
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)
257static int ehci_pci_resume(struct usb_hcd *hcd) 257static int ehci_pci_resume(struct usb_hcd *hcd)
258{ 258{
259 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 259 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
260 unsigned port;
261 struct pci_dev *pdev = to_pci_dev(hcd->self.controller); 260 struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
262 int retval = -EINVAL;
263 261
264 // maybe restore FLADJ 262 // maybe restore FLADJ
265 263
@@ -269,27 +267,19 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
269 /* Mark hardware accessible again as we are out of D3 state by now */ 267 /* Mark hardware accessible again as we are out of D3 state by now */
270 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 268 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
271 269
272 /* If CF is clear, we lost PCI Vaux power and need to restart. */ 270 /* If CF is still set, we maintained PCI Vaux power.
273 if (readl(&ehci->regs->configured_flag) != FLAG_CF) 271 * Just undo the effect of ehci_pci_suspend().
274 goto restart;
275
276 /* If any port is suspended (or owned by the companion),
277 * we know we can/must resume the HC (and mustn't reset it).
278 * We just defer that to the root hub code.
279 */ 272 */
280 for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) { 273 if (readl(&ehci->regs->configured_flag) == FLAG_CF) {
281 u32 status; 274 int mask = INTR_MASK;
282 port--; 275
283 status = readl(&ehci->regs->port_status [port]); 276 if (!device_may_wakeup(&hcd->self.root_hub->dev))
284 if (!(status & PORT_POWER)) 277 mask &= ~STS_PCD;
285 continue; 278 writel(mask, &ehci->regs->intr_enable);
286 if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) { 279 readl(&ehci->regs->intr_enable);
287 usb_hcd_resume_root_hub(hcd); 280 return 0;
288 return 0;
289 }
290 } 281 }
291 282
292restart:
293 ehci_dbg(ehci, "lost power, restarting\n"); 283 ehci_dbg(ehci, "lost power, restarting\n");
294 usb_root_hub_lost_power(hcd->self.root_hub); 284 usb_root_hub_lost_power(hcd->self.root_hub);
295 285
@@ -307,13 +297,15 @@ restart:
307 ehci_work(ehci); 297 ehci_work(ehci);
308 spin_unlock_irq(&ehci->lock); 298 spin_unlock_irq(&ehci->lock);
309 299
310 /* restart; khubd will disconnect devices */
311 retval = ehci_run(hcd);
312
313 /* here we "know" root ports should always stay powered */ 300 /* here we "know" root ports should always stay powered */
314 ehci_port_power(ehci, 1); 301 ehci_port_power(ehci, 1);
315 302
316 return retval; 303 writel(ehci->command, &ehci->regs->command);
304 writel(FLAG_CF, &ehci->regs->configured_flag);
305 readl(&ehci->regs->command); /* unblock posted writes */
306
307 hcd->state = HC_STATE_SUSPENDED;
308 return 0;
317} 309}
318#endif 310#endif
319 311