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>
This commit is contained in:
parent
e7e6da9eb1
commit
cfa59dab27
|
@ -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,9 +1310,11 @@ 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);
|
||||||
usb_hc_died(hcd);
|
if (status != -ESHUTDOWN)
|
||||||
|
usb_hc_died(hcd);
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
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)
|
||||||
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;
|
||||||
|
|
Reference in New Issue