diff options
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/driver.c | 9 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 15 |
2 files changed, 19 insertions, 5 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 888881e5f292..4aeb10034de7 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -1822,10 +1822,13 @@ int usb_runtime_suspend(struct device *dev) | |||
1822 | if (status == -EAGAIN || status == -EBUSY) | 1822 | if (status == -EAGAIN || status == -EBUSY) |
1823 | usb_mark_last_busy(udev); | 1823 | usb_mark_last_busy(udev); |
1824 | 1824 | ||
1825 | /* The PM core reacts badly unless the return code is 0, | 1825 | /* |
1826 | * -EAGAIN, or -EBUSY, so always return -EBUSY on an error. | 1826 | * The PM core reacts badly unless the return code is 0, |
1827 | * -EAGAIN, or -EBUSY, so always return -EBUSY on an error | ||
1828 | * (except for root hubs, because they don't suspend through | ||
1829 | * an upstream port like other USB devices). | ||
1827 | */ | 1830 | */ |
1828 | if (status != 0) | 1831 | if (status != 0 && udev->parent) |
1829 | return -EBUSY; | 1832 | return -EBUSY; |
1830 | return status; | 1833 | return status; |
1831 | } | 1834 | } |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 090469ebfcff..229a73f64304 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1691,8 +1691,19 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1691 | */ | 1691 | */ |
1692 | pm_runtime_set_autosuspend_delay(&hdev->dev, 0); | 1692 | pm_runtime_set_autosuspend_delay(&hdev->dev, 0); |
1693 | 1693 | ||
1694 | /* Hubs have proper suspend/resume support. */ | 1694 | /* |
1695 | usb_enable_autosuspend(hdev); | 1695 | * Hubs have proper suspend/resume support, except for root hubs |
1696 | * where the controller driver doesn't have bus_suspend and | ||
1697 | * bus_resume methods. | ||
1698 | */ | ||
1699 | if (hdev->parent) { /* normal device */ | ||
1700 | usb_enable_autosuspend(hdev); | ||
1701 | } else { /* root hub */ | ||
1702 | const struct hc_driver *drv = bus_to_hcd(hdev->bus)->driver; | ||
1703 | |||
1704 | if (drv->bus_suspend && drv->bus_resume) | ||
1705 | usb_enable_autosuspend(hdev); | ||
1706 | } | ||
1696 | 1707 | ||
1697 | if (hdev->level == MAX_TOPO_LEVEL) { | 1708 | if (hdev->level == MAX_TOPO_LEVEL) { |
1698 | dev_err(&intf->dev, | 1709 | dev_err(&intf->dev, |