diff options
Diffstat (limited to 'drivers/usb/host/ohci-pci.c')
-rw-r--r-- | drivers/usb/host/ohci-pci.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 5f22e6590cd1..1b09dde068e1 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -105,13 +105,36 @@ ohci_pci_start (struct usb_hcd *hcd) | |||
105 | 105 | ||
106 | static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | 106 | static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) |
107 | { | 107 | { |
108 | /* root hub was already suspended */ | 108 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
109 | return 0; | 109 | unsigned long flags; |
110 | int rc = 0; | ||
111 | |||
112 | /* Root hub was already suspended. Disable irq emission and | ||
113 | * mark HW unaccessible, bail out if RH has been resumed. Use | ||
114 | * the spinlock to properly synchronize with possible pending | ||
115 | * RH suspend or resume activity. | ||
116 | * | ||
117 | * This is still racy as hcd->state is manipulated outside of | ||
118 | * any locks =P But that will be a different fix. | ||
119 | */ | ||
120 | spin_lock_irqsave (&ohci->lock, flags); | ||
121 | if (hcd->state != HC_STATE_SUSPENDED) { | ||
122 | rc = -EINVAL; | ||
123 | goto bail; | ||
124 | } | ||
125 | ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | ||
126 | (void)ohci_readl(ohci, &ohci->regs->intrdisable); | ||
127 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
128 | bail: | ||
129 | spin_unlock_irqrestore (&ohci->lock, flags); | ||
130 | |||
131 | return rc; | ||
110 | } | 132 | } |
111 | 133 | ||
112 | 134 | ||
113 | static int ohci_pci_resume (struct usb_hcd *hcd) | 135 | static int ohci_pci_resume (struct usb_hcd *hcd) |
114 | { | 136 | { |
137 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
115 | usb_hcd_resume_root_hub(hcd); | 138 | usb_hcd_resume_root_hub(hcd); |
116 | return 0; | 139 | return 0; |
117 | } | 140 | } |