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.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 441c26064b44..14fff5714c1e 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -228,14 +228,36 @@ static int ehci_pci_reset(struct usb_hcd *hcd)
228static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) 228static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
229{ 229{
230 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 230 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
231 unsigned long flags;
232 int rc = 0;
231 233
232 if (time_before(jiffies, ehci->next_statechange)) 234 if (time_before(jiffies, ehci->next_statechange))
233 msleep(10); 235 msleep(10);
234 236
237 /* Root hub was already suspended. Disable irq emission and
238 * mark HW unaccessible, bail out if RH has been resumed. Use
239 * the spinlock to properly synchronize with possible pending
240 * RH suspend or resume activity.
241 *
242 * This is still racy as hcd->state is manipulated outside of
243 * any locks =P But that will be a different fix.
244 */
245 spin_lock_irqsave (&ehci->lock, flags);
246 if (hcd->state != HC_STATE_SUSPENDED) {
247 rc = -EINVAL;
248 goto bail;
249 }
250 writel (0, &ehci->regs->intr_enable);
251 (void)readl(&ehci->regs->intr_enable);
252
253 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
254 bail:
255 spin_unlock_irqrestore (&ehci->lock, flags);
256
235 // could save FLADJ in case of Vaux power loss 257 // could save FLADJ in case of Vaux power loss
236 // ... we'd only use it to handle clock skew 258 // ... we'd only use it to handle clock skew
237 259
238 return 0; 260 return rc;
239} 261}
240 262
241static int ehci_pci_resume(struct usb_hcd *hcd) 263static int ehci_pci_resume(struct usb_hcd *hcd)
@@ -251,6 +273,9 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
251 if (time_before(jiffies, ehci->next_statechange)) 273 if (time_before(jiffies, ehci->next_statechange))
252 msleep(100); 274 msleep(100);
253 275
276 /* Mark hardware accessible again as we are out of D3 state by now */
277 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
278
254 /* If CF is clear, we lost PCI Vaux power and need to restart. */ 279 /* If CF is clear, we lost PCI Vaux power and need to restart. */
255 if (readl(&ehci->regs->configured_flag) != FLAG_CF) 280 if (readl(&ehci->regs->configured_flag) != FLAG_CF)
256 goto restart; 281 goto restart;