Commit cfa59dab authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

USB: Don't resume root hub if the controller is suspended

Root hubs can't be resumed if their parent controller device is still
suspended.  This patch (as925) adds a check for that condition in
hcd_bus_resume() and prevents it from being treated as a fatal
controller failure.

ehci-hcd is updated to add the corresponding test.  Unnecessary
debugging messages are removed from uhci-hcd and dummy-hcd.  The
error return code from dummy-hcd is changed to -ESHUTDOWN, the same as
the others.  ohci-hcd doesn't need any changes.

Suspend handling in the non-PCI host drivers is somewhat hit-and-miss.
This patch shouldn't have any effect on them.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent e7e6da9e
...@@ -1291,6 +1291,7 @@ int hcd_bus_resume(struct usb_device *rhdev) ...@@ -1291,6 +1291,7 @@ int hcd_bus_resume(struct usb_device *rhdev)
{ {
struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self);
int status; int status;
int old_state = hcd->state;
dev_dbg(&rhdev->dev, "usb %s%s\n", dev_dbg(&rhdev->dev, "usb %s%s\n",
rhdev->auto_pm ? "auto-" : "", "resume"); rhdev->auto_pm ? "auto-" : "", "resume");
...@@ -1309,8 +1310,10 @@ int hcd_bus_resume(struct usb_device *rhdev) ...@@ -1309,8 +1310,10 @@ int hcd_bus_resume(struct usb_device *rhdev)
: USB_STATE_ADDRESS); : USB_STATE_ADDRESS);
hcd->state = HC_STATE_RUNNING; hcd->state = HC_STATE_RUNNING;
} else { } else {
hcd->state = old_state;
dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
"resume", status); "resume", status);
if (status != -ESHUTDOWN)
usb_hc_died(hcd); usb_hc_died(hcd);
} }
return status; return status;
......
...@@ -1784,8 +1784,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd) ...@@ -1784,8 +1784,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd)
spin_lock_irq (&dum->lock); spin_lock_irq (&dum->lock);
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n"); rc = -ESHUTDOWN;
rc = -ENODEV;
} else { } else {
dum->rh_state = DUMMY_RH_RUNNING; dum->rh_state = DUMMY_RH_RUNNING;
set_link_state (dum); set_link_state (dum);
......
...@@ -199,6 +199,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd) ...@@ -199,6 +199,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
if (time_before (jiffies, ehci->next_statechange)) if (time_before (jiffies, ehci->next_statechange))
msleep(5); msleep(5);
spin_lock_irq (&ehci->lock); spin_lock_irq (&ehci->lock);
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
spin_unlock_irq(&ehci->lock);
return -ESHUTDOWN;
}
/* Ideally and we've got a real resume here, and no port's power /* Ideally and we've got a real resume here, and no port's power
* was lost. (For PCI, that means Vaux was maintained.) But we * was lost. (For PCI, that means Vaux was maintained.) But we
......
...@@ -730,10 +730,9 @@ static int uhci_rh_resume(struct usb_hcd *hcd) ...@@ -730,10 +730,9 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
int rc = 0; int rc = 0;
spin_lock_irq(&uhci->lock); spin_lock_irq(&uhci->lock);
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n");
rc = -ESHUTDOWN; rc = -ESHUTDOWN;
} else if (!uhci->dead) else if (!uhci->dead)
wakeup_rh(uhci); wakeup_rh(uhci);
spin_unlock_irq(&uhci->lock); spin_unlock_irq(&uhci->lock);
return rc; return rc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment