diff options
Diffstat (limited to 'drivers/usb/host/ohci-s3c2410.c')
-rw-r--r-- | drivers/usb/host/ohci-s3c2410.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index b5bf9b7a54fc..be3429e08d90 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -426,15 +426,28 @@ static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev) static int ohci_hcd_s3c2410_drv_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); + struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct platform_device *pdev = to_platform_device(dev); - bool do_wakeup = device_may_wakeup(dev); + unsigned long flags; int rc = 0; - rc = ohci_suspend(hcd, do_wakeup); - if (rc) - return rc; + /* + * Root hub was already suspended. Disable irq emission and + * mark HW unaccessible, bail out if RH has been resumed. Use + * the spinlock to properly synchronize with possible pending + * RH suspend or resume activity. + */ + spin_lock_irqsave(&ohci->lock, flags); + if (ohci->rh_state != OHCI_RH_SUSPENDED) { + rc = -EINVAL; + goto bail; + } + + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); s3c2410_stop_hc(pdev); +bail: + spin_unlock_irqrestore(&ohci->lock, flags); return rc; } |