aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ohci-hub.c')
-rw-r--r--drivers/usb/host/ohci-hub.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index e01e77bc324b..4b2226d77b34 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -53,6 +53,11 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
spin_lock_irqsave (&ohci->lock, flags);
+ if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
+ spin_unlock_irqrestore (&ohci->lock, flags);
+ return -ESHUTDOWN;
+ }
+
ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
switch (ohci->hc_control & OHCI_CTRL_HCFS) {
case OHCI_USB_RESUME:
@@ -140,11 +145,19 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
u32 temp, enables;
int status = -EINPROGRESS;
+ unsigned long flags;
if (time_before (jiffies, ohci->next_statechange))
msleep(5);
- spin_lock_irq (&ohci->lock);
+ spin_lock_irqsave (&ohci->lock, flags);
+
+ if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
+ spin_unlock_irqrestore (&ohci->lock, flags);
+ return -ESHUTDOWN;
+ }
+
+
ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
@@ -179,7 +192,7 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
ohci_dbg (ohci, "lost power\n");
status = -EBUSY;
}
- spin_unlock_irq (&ohci->lock);
+ spin_unlock_irqrestore (&ohci->lock, flags);
if (status == -EBUSY) {
(void) ohci_init (ohci);
return ohci_restart (ohci);
@@ -297,8 +310,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
/* handle autosuspended root: finish resuming before
* letting khubd or root hub timer see state changes.
*/
- if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
- || !HC_IS_RUNNING(hcd->state)) {
+ if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
+ || !HC_IS_RUNNING(hcd->state))) {
can_suspend = 0;
goto done;
}
@@ -359,7 +372,7 @@ done:
& ohci->hc_control)
== OHCI_USB_OPER
&& time_after (jiffies, ohci->next_statechange)
- && usb_trylock_device (hcd->self.root_hub)
+ && usb_trylock_device (hcd->self.root_hub) == 0
) {
ohci_vdbg (ohci, "autosuspend\n");
(void) ohci_bus_suspend (hcd);
@@ -508,6 +521,9 @@ static int ohci_hub_control (
u32 temp;
int retval = 0;
+ if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
+ return -ESHUTDOWN;
+
switch (typeReq) {
case ClearHubFeature:
switch (wValue) {