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: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 5254c50..963520f 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1291,6 +1291,7 @@
{
struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self);
int status;
+ int old_state = hcd->state;
dev_dbg(&rhdev->dev, "usb %s%s\n",
rhdev->auto_pm ? "auto-" : "", "resume");
@@ -1309,9 +1310,11 @@
: USB_STATE_ADDRESS);
hcd->state = HC_STATE_RUNNING;
} else {
+ hcd->state = old_state;
dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
"resume", status);
- usb_hc_died(hcd);
+ if (status != -ESHUTDOWN)
+ usb_hc_died(hcd);
}
return status;
}
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index fcb5526..9040b50 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -1784,8 +1784,7 @@
spin_lock_irq (&dum->lock);
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n");
- rc = -ENODEV;
+ rc = -ESHUTDOWN;
} else {
dum->rh_state = DUMMY_RH_RUNNING;
set_link_state (dum);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 71aeca0..0dcb416 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -199,6 +199,10 @@
if (time_before (jiffies, ehci->next_statechange))
msleep(5);
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
* was lost. (For PCI, that means Vaux was maintained.) But we
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index d22da26..76c555a 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -730,10 +730,9 @@
int rc = 0;
spin_lock_irq(&uhci->lock);
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n");
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
rc = -ESHUTDOWN;
- } else if (!uhci->dead)
+ else if (!uhci->dead)
wakeup_rh(uhci);
spin_unlock_irq(&uhci->lock);
return rc;