diff options
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r-- | drivers/usb/core/driver.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 34e3da5aa72a..45887a0ff873 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include <linux/device.h> | 25 | #include <linux/device.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/export.h> | ||
27 | #include <linux/usb.h> | 28 | #include <linux/usb.h> |
28 | #include <linux/usb/quirks.h> | 29 | #include <linux/usb/quirks.h> |
29 | #include <linux/usb/hcd.h> | 30 | #include <linux/usb/hcd.h> |
@@ -1046,8 +1047,7 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg) | |||
1046 | /* Non-root devices on a full/low-speed bus must wait for their | 1047 | /* Non-root devices on a full/low-speed bus must wait for their |
1047 | * companion high-speed root hub, in case a handoff is needed. | 1048 | * companion high-speed root hub, in case a handoff is needed. |
1048 | */ | 1049 | */ |
1049 | if (!(msg.event & PM_EVENT_AUTO) && udev->parent && | 1050 | if (!PMSG_IS_AUTO(msg) && udev->parent && udev->bus->hs_companion) |
1050 | udev->bus->hs_companion) | ||
1051 | device_pm_wait_for_dev(&udev->dev, | 1051 | device_pm_wait_for_dev(&udev->dev, |
1052 | &udev->bus->hs_companion->root_hub->dev); | 1052 | &udev->bus->hs_companion->root_hub->dev); |
1053 | 1053 | ||
@@ -1075,7 +1075,7 @@ static int usb_suspend_interface(struct usb_device *udev, | |||
1075 | 1075 | ||
1076 | if (driver->suspend) { | 1076 | if (driver->suspend) { |
1077 | status = driver->suspend(intf, msg); | 1077 | status = driver->suspend(intf, msg); |
1078 | if (status && !(msg.event & PM_EVENT_AUTO)) | 1078 | if (status && !PMSG_IS_AUTO(msg)) |
1079 | dev_err(&intf->dev, "%s error %d\n", | 1079 | dev_err(&intf->dev, "%s error %d\n", |
1080 | "suspend", status); | 1080 | "suspend", status); |
1081 | } else { | 1081 | } else { |
@@ -1189,7 +1189,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1189 | status = usb_suspend_interface(udev, intf, msg); | 1189 | status = usb_suspend_interface(udev, intf, msg); |
1190 | 1190 | ||
1191 | /* Ignore errors during system sleep transitions */ | 1191 | /* Ignore errors during system sleep transitions */ |
1192 | if (!(msg.event & PM_EVENT_AUTO)) | 1192 | if (!PMSG_IS_AUTO(msg)) |
1193 | status = 0; | 1193 | status = 0; |
1194 | if (status != 0) | 1194 | if (status != 0) |
1195 | break; | 1195 | break; |
@@ -1199,7 +1199,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1199 | status = usb_suspend_device(udev, msg); | 1199 | status = usb_suspend_device(udev, msg); |
1200 | 1200 | ||
1201 | /* Again, ignore errors during system sleep transitions */ | 1201 | /* Again, ignore errors during system sleep transitions */ |
1202 | if (!(msg.event & PM_EVENT_AUTO)) | 1202 | if (!PMSG_IS_AUTO(msg)) |
1203 | status = 0; | 1203 | status = 0; |
1204 | } | 1204 | } |
1205 | 1205 | ||
@@ -1583,7 +1583,7 @@ int usb_autopm_get_interface_async(struct usb_interface *intf) | |||
1583 | dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", | 1583 | dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", |
1584 | __func__, atomic_read(&intf->dev.power.usage_count), | 1584 | __func__, atomic_read(&intf->dev.power.usage_count), |
1585 | status); | 1585 | status); |
1586 | if (status > 0) | 1586 | if (status > 0 || status == -EINPROGRESS) |
1587 | status = 0; | 1587 | status = 0; |
1588 | return status; | 1588 | return status; |
1589 | } | 1589 | } |
@@ -1668,6 +1668,11 @@ int usb_runtime_suspend(struct device *dev) | |||
1668 | return -EAGAIN; | 1668 | return -EAGAIN; |
1669 | 1669 | ||
1670 | status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); | 1670 | status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); |
1671 | |||
1672 | /* Allow a retry if autosuspend failed temporarily */ | ||
1673 | if (status == -EAGAIN || status == -EBUSY) | ||
1674 | usb_mark_last_busy(udev); | ||
1675 | |||
1671 | /* The PM core reacts badly unless the return code is 0, | 1676 | /* The PM core reacts badly unless the return code is 0, |
1672 | * -EAGAIN, or -EBUSY, so always return -EBUSY on an error. | 1677 | * -EAGAIN, or -EBUSY, so always return -EBUSY on an error. |
1673 | */ | 1678 | */ |
@@ -1700,6 +1705,20 @@ int usb_runtime_idle(struct device *dev) | |||
1700 | return 0; | 1705 | return 0; |
1701 | } | 1706 | } |
1702 | 1707 | ||
1708 | int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) | ||
1709 | { | ||
1710 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); | ||
1711 | int ret = -EPERM; | ||
1712 | |||
1713 | if (hcd->driver->set_usb2_hw_lpm) { | ||
1714 | ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, enable); | ||
1715 | if (!ret) | ||
1716 | udev->usb2_hw_lpm_enabled = enable; | ||
1717 | } | ||
1718 | |||
1719 | return ret; | ||
1720 | } | ||
1721 | |||
1703 | #endif /* CONFIG_USB_SUSPEND */ | 1722 | #endif /* CONFIG_USB_SUSPEND */ |
1704 | 1723 | ||
1705 | struct bus_type usb_bus_type = { | 1724 | struct bus_type usb_bus_type = { |