diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2008-11-25 16:39:18 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-01-07 13:00:03 -0500 |
commit | 65bfd2967c906ca322a4bb69a285fe0de8916ac6 (patch) | |
tree | ddd3293f945613d0d27ec1dbd36030c079fb9492 /drivers/usb | |
parent | 4ec06d629628b6e5c7ff50d349a26ef5c35696e3 (diff) |
USB: Enhance usage of pm_message_t
This patch (as1177) modifies the USB core suspend and resume
routines. The resume functions now will take a pm_message_t argument,
so they will know what sort of resume is occurring. The new argument
is also passed to the port suspend/resume and bus suspend/resume
routines (although they don't use it for anything but debugging).
In addition, special pm_message_t values are used for user-initiated,
device-initiated (i.e., remote wakeup), and automatic suspend/resume.
By testing these values, drivers can tell whether or not a particular
suspend was an autosuspend. Unfortunately, they can't do the same for
resumes -- not until the pm_message_t argument is also passed to the
drivers' resume methods. That will require a bigger change.
IMO, the whole Power Management framework should have been set up this
way in the first place.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 2 | ||||
-rw-r--r-- | drivers/usb/class/cdc-wdm.c | 3 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 61 | ||||
-rw-r--r-- | drivers/usb/core/generic.c | 10 | ||||
-rw-r--r-- | drivers/usb/core/hcd.c | 10 | ||||
-rw-r--r-- | drivers/usb/core/hcd.h | 4 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 16 | ||||
-rw-r--r-- | drivers/usb/core/sysfs.c | 6 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 8 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 15 |
10 files changed, 73 insertions, 62 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index d50a99f70aee..00b47ea24f86 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -1275,7 +1275,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) | |||
1275 | struct acm *acm = usb_get_intfdata(intf); | 1275 | struct acm *acm = usb_get_intfdata(intf); |
1276 | int cnt; | 1276 | int cnt; |
1277 | 1277 | ||
1278 | if (acm->dev->auto_pm) { | 1278 | if (message.event & PM_EVENT_AUTO) { |
1279 | int b; | 1279 | int b; |
1280 | 1280 | ||
1281 | spin_lock_irq(&acm->read_lock); | 1281 | spin_lock_irq(&acm->read_lock); |
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 5a8ecc045e3f..3771d6e6d0cc 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
@@ -764,7 +764,8 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) | |||
764 | 764 | ||
765 | mutex_lock(&desc->plock); | 765 | mutex_lock(&desc->plock); |
766 | #ifdef CONFIG_PM | 766 | #ifdef CONFIG_PM |
767 | if (interface_to_usbdev(desc->intf)->auto_pm && test_bit(WDM_IN_USE, &desc->flags)) { | 767 | if ((message.event & PM_EVENT_AUTO) && |
768 | test_bit(WDM_IN_USE, &desc->flags)) { | ||
768 | rv = -EBUSY; | 769 | rv = -EBUSY; |
769 | } else { | 770 | } else { |
770 | #endif | 771 | #endif |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 0226e019326a..41c06025506e 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -922,7 +922,7 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg) | |||
922 | } | 922 | } |
923 | 923 | ||
924 | /* Caller has locked udev's pm_mutex */ | 924 | /* Caller has locked udev's pm_mutex */ |
925 | static int usb_resume_device(struct usb_device *udev) | 925 | static int usb_resume_device(struct usb_device *udev, pm_message_t msg) |
926 | { | 926 | { |
927 | struct usb_device_driver *udriver; | 927 | struct usb_device_driver *udriver; |
928 | int status = 0; | 928 | int status = 0; |
@@ -940,7 +940,7 @@ static int usb_resume_device(struct usb_device *udev) | |||
940 | udev->reset_resume = 1; | 940 | udev->reset_resume = 1; |
941 | 941 | ||
942 | udriver = to_usb_device_driver(udev->dev.driver); | 942 | udriver = to_usb_device_driver(udev->dev.driver); |
943 | status = udriver->resume(udev); | 943 | status = udriver->resume(udev, msg); |
944 | 944 | ||
945 | done: | 945 | done: |
946 | dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status); | 946 | dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status); |
@@ -969,7 +969,7 @@ static int usb_suspend_interface(struct usb_device *udev, | |||
969 | status = driver->suspend(intf, msg); | 969 | status = driver->suspend(intf, msg); |
970 | if (status == 0) | 970 | if (status == 0) |
971 | mark_quiesced(intf); | 971 | mark_quiesced(intf); |
972 | else if (!udev->auto_pm) | 972 | else if (!(msg.event & PM_EVENT_AUTO)) |
973 | dev_err(&intf->dev, "%s error %d\n", | 973 | dev_err(&intf->dev, "%s error %d\n", |
974 | "suspend", status); | 974 | "suspend", status); |
975 | } else { | 975 | } else { |
@@ -987,7 +987,7 @@ static int usb_suspend_interface(struct usb_device *udev, | |||
987 | 987 | ||
988 | /* Caller has locked intf's usb_device's pm_mutex */ | 988 | /* Caller has locked intf's usb_device's pm_mutex */ |
989 | static int usb_resume_interface(struct usb_device *udev, | 989 | static int usb_resume_interface(struct usb_device *udev, |
990 | struct usb_interface *intf, int reset_resume) | 990 | struct usb_interface *intf, pm_message_t msg, int reset_resume) |
991 | { | 991 | { |
992 | struct usb_driver *driver; | 992 | struct usb_driver *driver; |
993 | int status = 0; | 993 | int status = 0; |
@@ -1138,10 +1138,9 @@ static inline int autosuspend_check(struct usb_device *udev, int reschedule) | |||
1138 | * all the interfaces which were suspended are resumed so that they remain | 1138 | * all the interfaces which were suspended are resumed so that they remain |
1139 | * in the same state as the device. | 1139 | * in the same state as the device. |
1140 | * | 1140 | * |
1141 | * If an autosuspend is in progress (@udev->auto_pm is set), the routine | 1141 | * If an autosuspend is in progress the routine checks first to make sure |
1142 | * checks first to make sure that neither the device itself or any of its | 1142 | * that neither the device itself or any of its active interfaces is in use |
1143 | * active interfaces is in use (pm_usage_cnt is greater than 0). If they | 1143 | * (pm_usage_cnt is greater than 0). If they are, the autosuspend fails. |
1144 | * are, the autosuspend fails. | ||
1145 | * | 1144 | * |
1146 | * If the suspend succeeds, the routine recursively queues an autosuspend | 1145 | * If the suspend succeeds, the routine recursively queues an autosuspend |
1147 | * request for @udev's parent device, thereby propagating the change up | 1146 | * request for @udev's parent device, thereby propagating the change up |
@@ -1176,7 +1175,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1176 | 1175 | ||
1177 | udev->do_remote_wakeup = device_may_wakeup(&udev->dev); | 1176 | udev->do_remote_wakeup = device_may_wakeup(&udev->dev); |
1178 | 1177 | ||
1179 | if (udev->auto_pm) { | 1178 | if (msg.event & PM_EVENT_AUTO) { |
1180 | status = autosuspend_check(udev, 0); | 1179 | status = autosuspend_check(udev, 0); |
1181 | if (status < 0) | 1180 | if (status < 0) |
1182 | goto done; | 1181 | goto done; |
@@ -1196,13 +1195,16 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1196 | 1195 | ||
1197 | /* If the suspend failed, resume interfaces that did get suspended */ | 1196 | /* If the suspend failed, resume interfaces that did get suspended */ |
1198 | if (status != 0) { | 1197 | if (status != 0) { |
1198 | pm_message_t msg2; | ||
1199 | |||
1200 | msg2.event = msg.event ^ (PM_EVENT_SUSPEND | PM_EVENT_RESUME); | ||
1199 | while (--i >= 0) { | 1201 | while (--i >= 0) { |
1200 | intf = udev->actconfig->interface[i]; | 1202 | intf = udev->actconfig->interface[i]; |
1201 | usb_resume_interface(udev, intf, 0); | 1203 | usb_resume_interface(udev, intf, msg2, 0); |
1202 | } | 1204 | } |
1203 | 1205 | ||
1204 | /* Try another autosuspend when the interfaces aren't busy */ | 1206 | /* Try another autosuspend when the interfaces aren't busy */ |
1205 | if (udev->auto_pm) | 1207 | if (msg.event & PM_EVENT_AUTO) |
1206 | autosuspend_check(udev, status == -EBUSY); | 1208 | autosuspend_check(udev, status == -EBUSY); |
1207 | 1209 | ||
1208 | /* If the suspend succeeded then prevent any more URB submissions, | 1210 | /* If the suspend succeeded then prevent any more URB submissions, |
@@ -1232,6 +1234,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1232 | /** | 1234 | /** |
1233 | * usb_resume_both - resume a USB device and its interfaces | 1235 | * usb_resume_both - resume a USB device and its interfaces |
1234 | * @udev: the usb_device to resume | 1236 | * @udev: the usb_device to resume |
1237 | * @msg: Power Management message describing this state transition | ||
1235 | * | 1238 | * |
1236 | * This is the central routine for resuming USB devices. It calls the | 1239 | * This is the central routine for resuming USB devices. It calls the |
1237 | * the resume method for @udev and then calls the resume methods for all | 1240 | * the resume method for @udev and then calls the resume methods for all |
@@ -1257,7 +1260,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1257 | * | 1260 | * |
1258 | * This routine can run only in process context. | 1261 | * This routine can run only in process context. |
1259 | */ | 1262 | */ |
1260 | static int usb_resume_both(struct usb_device *udev) | 1263 | static int usb_resume_both(struct usb_device *udev, pm_message_t msg) |
1261 | { | 1264 | { |
1262 | int status = 0; | 1265 | int status = 0; |
1263 | int i; | 1266 | int i; |
@@ -1273,14 +1276,15 @@ static int usb_resume_both(struct usb_device *udev) | |||
1273 | 1276 | ||
1274 | /* Propagate the resume up the tree, if necessary */ | 1277 | /* Propagate the resume up the tree, if necessary */ |
1275 | if (udev->state == USB_STATE_SUSPENDED) { | 1278 | if (udev->state == USB_STATE_SUSPENDED) { |
1276 | if (udev->auto_pm && udev->autoresume_disabled) { | 1279 | if ((msg.event & PM_EVENT_AUTO) && |
1280 | udev->autoresume_disabled) { | ||
1277 | status = -EPERM; | 1281 | status = -EPERM; |
1278 | goto done; | 1282 | goto done; |
1279 | } | 1283 | } |
1280 | if (parent) { | 1284 | if (parent) { |
1281 | status = usb_autoresume_device(parent); | 1285 | status = usb_autoresume_device(parent); |
1282 | if (status == 0) { | 1286 | if (status == 0) { |
1283 | status = usb_resume_device(udev); | 1287 | status = usb_resume_device(udev, msg); |
1284 | if (status || udev->state == | 1288 | if (status || udev->state == |
1285 | USB_STATE_NOTATTACHED) { | 1289 | USB_STATE_NOTATTACHED) { |
1286 | usb_autosuspend_device(parent); | 1290 | usb_autosuspend_device(parent); |
@@ -1303,15 +1307,16 @@ static int usb_resume_both(struct usb_device *udev) | |||
1303 | /* We can't progagate beyond the USB subsystem, | 1307 | /* We can't progagate beyond the USB subsystem, |
1304 | * so if a root hub's controller is suspended | 1308 | * so if a root hub's controller is suspended |
1305 | * then we're stuck. */ | 1309 | * then we're stuck. */ |
1306 | status = usb_resume_device(udev); | 1310 | status = usb_resume_device(udev, msg); |
1307 | } | 1311 | } |
1308 | } else if (udev->reset_resume) | 1312 | } else if (udev->reset_resume) |
1309 | status = usb_resume_device(udev); | 1313 | status = usb_resume_device(udev, msg); |
1310 | 1314 | ||
1311 | if (status == 0 && udev->actconfig) { | 1315 | if (status == 0 && udev->actconfig) { |
1312 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { | 1316 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { |
1313 | intf = udev->actconfig->interface[i]; | 1317 | intf = udev->actconfig->interface[i]; |
1314 | usb_resume_interface(udev, intf, udev->reset_resume); | 1318 | usb_resume_interface(udev, intf, msg, |
1319 | udev->reset_resume); | ||
1315 | } | 1320 | } |
1316 | } | 1321 | } |
1317 | 1322 | ||
@@ -1339,13 +1344,13 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt) | |||
1339 | udev->last_busy = jiffies; | 1344 | udev->last_busy = jiffies; |
1340 | if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) { | 1345 | if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) { |
1341 | if (udev->state == USB_STATE_SUSPENDED) | 1346 | if (udev->state == USB_STATE_SUSPENDED) |
1342 | status = usb_resume_both(udev); | 1347 | status = usb_resume_both(udev, PMSG_AUTO_RESUME); |
1343 | if (status != 0) | 1348 | if (status != 0) |
1344 | udev->pm_usage_cnt -= inc_usage_cnt; | 1349 | udev->pm_usage_cnt -= inc_usage_cnt; |
1345 | else if (inc_usage_cnt) | 1350 | else if (inc_usage_cnt) |
1346 | udev->last_busy = jiffies; | 1351 | udev->last_busy = jiffies; |
1347 | } else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) { | 1352 | } else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) { |
1348 | status = usb_suspend_both(udev, PMSG_SUSPEND); | 1353 | status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); |
1349 | } | 1354 | } |
1350 | usb_pm_unlock(udev); | 1355 | usb_pm_unlock(udev); |
1351 | return status; | 1356 | return status; |
@@ -1469,13 +1474,14 @@ static int usb_autopm_do_interface(struct usb_interface *intf, | |||
1469 | udev->last_busy = jiffies; | 1474 | udev->last_busy = jiffies; |
1470 | if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) { | 1475 | if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) { |
1471 | if (udev->state == USB_STATE_SUSPENDED) | 1476 | if (udev->state == USB_STATE_SUSPENDED) |
1472 | status = usb_resume_both(udev); | 1477 | status = usb_resume_both(udev, |
1478 | PMSG_AUTO_RESUME); | ||
1473 | if (status != 0) | 1479 | if (status != 0) |
1474 | intf->pm_usage_cnt -= inc_usage_cnt; | 1480 | intf->pm_usage_cnt -= inc_usage_cnt; |
1475 | else | 1481 | else |
1476 | udev->last_busy = jiffies; | 1482 | udev->last_busy = jiffies; |
1477 | } else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) { | 1483 | } else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) { |
1478 | status = usb_suspend_both(udev, PMSG_SUSPEND); | 1484 | status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); |
1479 | } | 1485 | } |
1480 | } | 1486 | } |
1481 | usb_pm_unlock(udev); | 1487 | usb_pm_unlock(udev); |
@@ -1700,6 +1706,7 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg) | |||
1700 | /** | 1706 | /** |
1701 | * usb_external_resume_device - external resume of a USB device and its interfaces | 1707 | * usb_external_resume_device - external resume of a USB device and its interfaces |
1702 | * @udev: the usb_device to resume | 1708 | * @udev: the usb_device to resume |
1709 | * @msg: Power Management message describing this state transition | ||
1703 | * | 1710 | * |
1704 | * This routine handles external resume requests: ones not generated | 1711 | * This routine handles external resume requests: ones not generated |
1705 | * internally by a USB driver (autoresume) but rather coming from the user | 1712 | * internally by a USB driver (autoresume) but rather coming from the user |
@@ -1708,13 +1715,13 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg) | |||
1708 | * | 1715 | * |
1709 | * The caller must hold @udev's device lock. | 1716 | * The caller must hold @udev's device lock. |
1710 | */ | 1717 | */ |
1711 | int usb_external_resume_device(struct usb_device *udev) | 1718 | int usb_external_resume_device(struct usb_device *udev, pm_message_t msg) |
1712 | { | 1719 | { |
1713 | int status; | 1720 | int status; |
1714 | 1721 | ||
1715 | usb_pm_lock(udev); | 1722 | usb_pm_lock(udev); |
1716 | udev->auto_pm = 0; | 1723 | udev->auto_pm = 0; |
1717 | status = usb_resume_both(udev); | 1724 | status = usb_resume_both(udev, msg); |
1718 | udev->last_busy = jiffies; | 1725 | udev->last_busy = jiffies; |
1719 | usb_pm_unlock(udev); | 1726 | usb_pm_unlock(udev); |
1720 | if (status == 0) | 1727 | if (status == 0) |
@@ -1727,7 +1734,7 @@ int usb_external_resume_device(struct usb_device *udev) | |||
1727 | return status; | 1734 | return status; |
1728 | } | 1735 | } |
1729 | 1736 | ||
1730 | int usb_suspend(struct device *dev, pm_message_t message) | 1737 | int usb_suspend(struct device *dev, pm_message_t msg) |
1731 | { | 1738 | { |
1732 | struct usb_device *udev; | 1739 | struct usb_device *udev; |
1733 | 1740 | ||
@@ -1746,10 +1753,10 @@ int usb_suspend(struct device *dev, pm_message_t message) | |||
1746 | } | 1753 | } |
1747 | 1754 | ||
1748 | udev->skip_sys_resume = 0; | 1755 | udev->skip_sys_resume = 0; |
1749 | return usb_external_suspend_device(udev, message); | 1756 | return usb_external_suspend_device(udev, msg); |
1750 | } | 1757 | } |
1751 | 1758 | ||
1752 | int usb_resume(struct device *dev) | 1759 | int usb_resume(struct device *dev, pm_message_t msg) |
1753 | { | 1760 | { |
1754 | struct usb_device *udev; | 1761 | struct usb_device *udev; |
1755 | 1762 | ||
@@ -1761,7 +1768,7 @@ int usb_resume(struct device *dev) | |||
1761 | */ | 1768 | */ |
1762 | if (udev->skip_sys_resume) | 1769 | if (udev->skip_sys_resume) |
1763 | return 0; | 1770 | return 0; |
1764 | return usb_external_resume_device(udev); | 1771 | return usb_external_resume_device(udev, msg); |
1765 | } | 1772 | } |
1766 | 1773 | ||
1767 | #endif /* CONFIG_PM */ | 1774 | #endif /* CONFIG_PM */ |
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 7e912f21fd36..30ecac3af15a 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c | |||
@@ -200,18 +200,18 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg) | |||
200 | * interfaces manually by doing a bus (or "global") suspend. | 200 | * interfaces manually by doing a bus (or "global") suspend. |
201 | */ | 201 | */ |
202 | if (!udev->parent) | 202 | if (!udev->parent) |
203 | rc = hcd_bus_suspend(udev); | 203 | rc = hcd_bus_suspend(udev, msg); |
204 | 204 | ||
205 | /* Non-root devices don't need to do anything for FREEZE or PRETHAW */ | 205 | /* Non-root devices don't need to do anything for FREEZE or PRETHAW */ |
206 | else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW) | 206 | else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW) |
207 | rc = 0; | 207 | rc = 0; |
208 | else | 208 | else |
209 | rc = usb_port_suspend(udev); | 209 | rc = usb_port_suspend(udev, msg); |
210 | 210 | ||
211 | return rc; | 211 | return rc; |
212 | } | 212 | } |
213 | 213 | ||
214 | static int generic_resume(struct usb_device *udev) | 214 | static int generic_resume(struct usb_device *udev, pm_message_t msg) |
215 | { | 215 | { |
216 | int rc; | 216 | int rc; |
217 | 217 | ||
@@ -221,9 +221,9 @@ static int generic_resume(struct usb_device *udev) | |||
221 | * interfaces manually by doing a bus (or "global") resume. | 221 | * interfaces manually by doing a bus (or "global") resume. |
222 | */ | 222 | */ |
223 | if (!udev->parent) | 223 | if (!udev->parent) |
224 | rc = hcd_bus_resume(udev); | 224 | rc = hcd_bus_resume(udev, msg); |
225 | else | 225 | else |
226 | rc = usb_port_resume(udev); | 226 | rc = usb_port_resume(udev, msg); |
227 | return rc; | 227 | return rc; |
228 | } | 228 | } |
229 | 229 | ||
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 7403ed871abd..a0079876d74e 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -1573,14 +1573,14 @@ int usb_hcd_get_frame_number (struct usb_device *udev) | |||
1573 | 1573 | ||
1574 | #ifdef CONFIG_PM | 1574 | #ifdef CONFIG_PM |
1575 | 1575 | ||
1576 | int hcd_bus_suspend(struct usb_device *rhdev) | 1576 | int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) |
1577 | { | 1577 | { |
1578 | struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); | 1578 | struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); |
1579 | int status; | 1579 | int status; |
1580 | int old_state = hcd->state; | 1580 | int old_state = hcd->state; |
1581 | 1581 | ||
1582 | dev_dbg(&rhdev->dev, "bus %s%s\n", | 1582 | dev_dbg(&rhdev->dev, "bus %s%s\n", |
1583 | rhdev->auto_pm ? "auto-" : "", "suspend"); | 1583 | (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend"); |
1584 | if (!hcd->driver->bus_suspend) { | 1584 | if (!hcd->driver->bus_suspend) { |
1585 | status = -ENOENT; | 1585 | status = -ENOENT; |
1586 | } else { | 1586 | } else { |
@@ -1598,14 +1598,14 @@ int hcd_bus_suspend(struct usb_device *rhdev) | |||
1598 | return status; | 1598 | return status; |
1599 | } | 1599 | } |
1600 | 1600 | ||
1601 | int hcd_bus_resume(struct usb_device *rhdev) | 1601 | int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) |
1602 | { | 1602 | { |
1603 | struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); | 1603 | struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); |
1604 | int status; | 1604 | int status; |
1605 | int old_state = hcd->state; | 1605 | int old_state = hcd->state; |
1606 | 1606 | ||
1607 | dev_dbg(&rhdev->dev, "usb %s%s\n", | 1607 | dev_dbg(&rhdev->dev, "usb %s%s\n", |
1608 | rhdev->auto_pm ? "auto-" : "", "resume"); | 1608 | (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume"); |
1609 | if (!hcd->driver->bus_resume) | 1609 | if (!hcd->driver->bus_resume) |
1610 | return -ENOENT; | 1610 | return -ENOENT; |
1611 | if (hcd->state == HC_STATE_RUNNING) | 1611 | if (hcd->state == HC_STATE_RUNNING) |
@@ -1638,7 +1638,7 @@ static void hcd_resume_work(struct work_struct *work) | |||
1638 | 1638 | ||
1639 | usb_lock_device(udev); | 1639 | usb_lock_device(udev); |
1640 | usb_mark_last_busy(udev); | 1640 | usb_mark_last_busy(udev); |
1641 | usb_external_resume_device(udev); | 1641 | usb_external_resume_device(udev, PMSG_REMOTE_RESUME); |
1642 | usb_unlock_device(udev); | 1642 | usb_unlock_device(udev); |
1643 | } | 1643 | } |
1644 | 1644 | ||
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 0aaa9cea6b38..aa5da82d9071 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
@@ -388,8 +388,8 @@ extern int usb_find_interface_driver(struct usb_device *dev, | |||
388 | #ifdef CONFIG_PM | 388 | #ifdef CONFIG_PM |
389 | extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd); | 389 | extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd); |
390 | extern void usb_root_hub_lost_power(struct usb_device *rhdev); | 390 | extern void usb_root_hub_lost_power(struct usb_device *rhdev); |
391 | extern int hcd_bus_suspend(struct usb_device *rhdev); | 391 | extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg); |
392 | extern int hcd_bus_resume(struct usb_device *rhdev); | 392 | extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg); |
393 | #else | 393 | #else |
394 | static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd) | 394 | static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd) |
395 | { | 395 | { |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index ff066edf4dca..fc99ef67761d 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1984,7 +1984,7 @@ static int check_port_resume_type(struct usb_device *udev, | |||
1984 | * | 1984 | * |
1985 | * Returns 0 on success, else negative errno. | 1985 | * Returns 0 on success, else negative errno. |
1986 | */ | 1986 | */ |
1987 | int usb_port_suspend(struct usb_device *udev) | 1987 | int usb_port_suspend(struct usb_device *udev, pm_message_t msg) |
1988 | { | 1988 | { |
1989 | struct usb_hub *hub = hdev_to_hub(udev->parent); | 1989 | struct usb_hub *hub = hdev_to_hub(udev->parent); |
1990 | int port1 = udev->portnum; | 1990 | int port1 = udev->portnum; |
@@ -2023,7 +2023,7 @@ int usb_port_suspend(struct usb_device *udev) | |||
2023 | } else { | 2023 | } else { |
2024 | /* device has up to 10 msec to fully suspend */ | 2024 | /* device has up to 10 msec to fully suspend */ |
2025 | dev_dbg(&udev->dev, "usb %ssuspend\n", | 2025 | dev_dbg(&udev->dev, "usb %ssuspend\n", |
2026 | udev->auto_pm ? "auto-" : ""); | 2026 | (msg.event & PM_EVENT_AUTO ? "auto-" : "")); |
2027 | usb_set_device_state(udev, USB_STATE_SUSPENDED); | 2027 | usb_set_device_state(udev, USB_STATE_SUSPENDED); |
2028 | msleep(10); | 2028 | msleep(10); |
2029 | } | 2029 | } |
@@ -2142,7 +2142,7 @@ static int finish_port_resume(struct usb_device *udev) | |||
2142 | * | 2142 | * |
2143 | * Returns 0 on success, else negative errno. | 2143 | * Returns 0 on success, else negative errno. |
2144 | */ | 2144 | */ |
2145 | int usb_port_resume(struct usb_device *udev) | 2145 | int usb_port_resume(struct usb_device *udev, pm_message_t msg) |
2146 | { | 2146 | { |
2147 | struct usb_hub *hub = hdev_to_hub(udev->parent); | 2147 | struct usb_hub *hub = hdev_to_hub(udev->parent); |
2148 | int port1 = udev->portnum; | 2148 | int port1 = udev->portnum; |
@@ -2167,7 +2167,7 @@ int usb_port_resume(struct usb_device *udev) | |||
2167 | } else { | 2167 | } else { |
2168 | /* drive resume for at least 20 msec */ | 2168 | /* drive resume for at least 20 msec */ |
2169 | dev_dbg(&udev->dev, "usb %sresume\n", | 2169 | dev_dbg(&udev->dev, "usb %sresume\n", |
2170 | udev->auto_pm ? "auto-" : ""); | 2170 | (msg.event & PM_EVENT_AUTO ? "auto-" : "")); |
2171 | msleep(25); | 2171 | msleep(25); |
2172 | 2172 | ||
2173 | /* Virtual root hubs can trigger on GET_PORT_STATUS to | 2173 | /* Virtual root hubs can trigger on GET_PORT_STATUS to |
@@ -2208,7 +2208,7 @@ static int remote_wakeup(struct usb_device *udev) | |||
2208 | if (udev->state == USB_STATE_SUSPENDED) { | 2208 | if (udev->state == USB_STATE_SUSPENDED) { |
2209 | dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); | 2209 | dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); |
2210 | usb_mark_last_busy(udev); | 2210 | usb_mark_last_busy(udev); |
2211 | status = usb_external_resume_device(udev); | 2211 | status = usb_external_resume_device(udev, PMSG_REMOTE_RESUME); |
2212 | } | 2212 | } |
2213 | return status; | 2213 | return status; |
2214 | } | 2214 | } |
@@ -2217,14 +2217,14 @@ static int remote_wakeup(struct usb_device *udev) | |||
2217 | 2217 | ||
2218 | /* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */ | 2218 | /* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */ |
2219 | 2219 | ||
2220 | int usb_port_suspend(struct usb_device *udev) | 2220 | int usb_port_suspend(struct usb_device *udev, pm_message_t msg) |
2221 | { | 2221 | { |
2222 | return 0; | 2222 | return 0; |
2223 | } | 2223 | } |
2224 | 2224 | ||
2225 | /* However we may need to do a reset-resume */ | 2225 | /* However we may need to do a reset-resume */ |
2226 | 2226 | ||
2227 | int usb_port_resume(struct usb_device *udev) | 2227 | int usb_port_resume(struct usb_device *udev, pm_message_t msg) |
2228 | { | 2228 | { |
2229 | struct usb_hub *hub = hdev_to_hub(udev->parent); | 2229 | struct usb_hub *hub = hdev_to_hub(udev->parent); |
2230 | int port1 = udev->portnum; | 2230 | int port1 = udev->portnum; |
@@ -2264,7 +2264,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
2264 | 2264 | ||
2265 | udev = hdev->children [port1-1]; | 2265 | udev = hdev->children [port1-1]; |
2266 | if (udev && udev->can_submit) { | 2266 | if (udev && udev->can_submit) { |
2267 | if (!hdev->auto_pm) | 2267 | if (!(msg.event & PM_EVENT_AUTO)) |
2268 | dev_dbg(&intf->dev, "port %d nyet suspended\n", | 2268 | dev_dbg(&intf->dev, "port %d nyet suspended\n", |
2269 | port1); | 2269 | port1); |
2270 | return -EBUSY; | 2270 | return -EBUSY; |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 8c65fa75b5c2..0f0ccf640114 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -359,19 +359,19 @@ set_level(struct device *dev, struct device_attribute *attr, | |||
359 | strncmp(buf, on_string, len) == 0) { | 359 | strncmp(buf, on_string, len) == 0) { |
360 | udev->autosuspend_disabled = 1; | 360 | udev->autosuspend_disabled = 1; |
361 | udev->autoresume_disabled = 0; | 361 | udev->autoresume_disabled = 0; |
362 | rc = usb_external_resume_device(udev); | 362 | rc = usb_external_resume_device(udev, PMSG_USER_RESUME); |
363 | 363 | ||
364 | } else if (len == sizeof auto_string - 1 && | 364 | } else if (len == sizeof auto_string - 1 && |
365 | strncmp(buf, auto_string, len) == 0) { | 365 | strncmp(buf, auto_string, len) == 0) { |
366 | udev->autosuspend_disabled = 0; | 366 | udev->autosuspend_disabled = 0; |
367 | udev->autoresume_disabled = 0; | 367 | udev->autoresume_disabled = 0; |
368 | rc = usb_external_resume_device(udev); | 368 | rc = usb_external_resume_device(udev, PMSG_USER_RESUME); |
369 | 369 | ||
370 | } else if (len == sizeof suspend_string - 1 && | 370 | } else if (len == sizeof suspend_string - 1 && |
371 | strncmp(buf, suspend_string, len) == 0) { | 371 | strncmp(buf, suspend_string, len) == 0) { |
372 | udev->autosuspend_disabled = 0; | 372 | udev->autosuspend_disabled = 0; |
373 | udev->autoresume_disabled = 1; | 373 | udev->autoresume_disabled = 1; |
374 | rc = usb_external_suspend_device(udev, PMSG_SUSPEND); | 374 | rc = usb_external_suspend_device(udev, PMSG_USER_SUSPEND); |
375 | 375 | ||
376 | } else | 376 | } else |
377 | rc = -EINVAL; | 377 | rc = -EINVAL; |
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 51854c2bc912..4c98f3975afe 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -253,7 +253,7 @@ static int usb_dev_prepare(struct device *dev) | |||
253 | static void usb_dev_complete(struct device *dev) | 253 | static void usb_dev_complete(struct device *dev) |
254 | { | 254 | { |
255 | /* Currently used only for rebinding interfaces */ | 255 | /* Currently used only for rebinding interfaces */ |
256 | usb_resume(dev); /* Implement eventually? */ | 256 | usb_resume(dev, PMSG_RESUME); /* Message event is meaningless */ |
257 | } | 257 | } |
258 | 258 | ||
259 | static int usb_dev_suspend(struct device *dev) | 259 | static int usb_dev_suspend(struct device *dev) |
@@ -263,7 +263,7 @@ static int usb_dev_suspend(struct device *dev) | |||
263 | 263 | ||
264 | static int usb_dev_resume(struct device *dev) | 264 | static int usb_dev_resume(struct device *dev) |
265 | { | 265 | { |
266 | return usb_resume(dev); | 266 | return usb_resume(dev, PMSG_RESUME); |
267 | } | 267 | } |
268 | 268 | ||
269 | static int usb_dev_freeze(struct device *dev) | 269 | static int usb_dev_freeze(struct device *dev) |
@@ -273,7 +273,7 @@ static int usb_dev_freeze(struct device *dev) | |||
273 | 273 | ||
274 | static int usb_dev_thaw(struct device *dev) | 274 | static int usb_dev_thaw(struct device *dev) |
275 | { | 275 | { |
276 | return usb_resume(dev); | 276 | return usb_resume(dev, PMSG_THAW); |
277 | } | 277 | } |
278 | 278 | ||
279 | static int usb_dev_poweroff(struct device *dev) | 279 | static int usb_dev_poweroff(struct device *dev) |
@@ -283,7 +283,7 @@ static int usb_dev_poweroff(struct device *dev) | |||
283 | 283 | ||
284 | static int usb_dev_restore(struct device *dev) | 284 | static int usb_dev_restore(struct device *dev) |
285 | { | 285 | { |
286 | return usb_resume(dev); | 286 | return usb_resume(dev, PMSG_RESTORE); |
287 | } | 287 | } |
288 | 288 | ||
289 | static struct dev_pm_ops usb_device_pm_ops = { | 289 | static struct dev_pm_ops usb_device_pm_ops = { |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index b60ebb4de1a8..9fb195665fa8 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -1,3 +1,5 @@ | |||
1 | #include <linux/pm.h> | ||
2 | |||
1 | /* Functions local to drivers/usb/core/ */ | 3 | /* Functions local to drivers/usb/core/ */ |
2 | 4 | ||
3 | extern int usb_create_sysfs_dev_files(struct usb_device *dev); | 5 | extern int usb_create_sysfs_dev_files(struct usb_device *dev); |
@@ -42,15 +44,16 @@ extern void usb_host_cleanup(void); | |||
42 | #ifdef CONFIG_PM | 44 | #ifdef CONFIG_PM |
43 | 45 | ||
44 | extern int usb_suspend(struct device *dev, pm_message_t msg); | 46 | extern int usb_suspend(struct device *dev, pm_message_t msg); |
45 | extern int usb_resume(struct device *dev); | 47 | extern int usb_resume(struct device *dev, pm_message_t msg); |
46 | 48 | ||
47 | extern void usb_autosuspend_work(struct work_struct *work); | 49 | extern void usb_autosuspend_work(struct work_struct *work); |
48 | extern void usb_autoresume_work(struct work_struct *work); | 50 | extern void usb_autoresume_work(struct work_struct *work); |
49 | extern int usb_port_suspend(struct usb_device *dev); | 51 | extern int usb_port_suspend(struct usb_device *dev, pm_message_t msg); |
50 | extern int usb_port_resume(struct usb_device *dev); | 52 | extern int usb_port_resume(struct usb_device *dev, pm_message_t msg); |
51 | extern int usb_external_suspend_device(struct usb_device *udev, | 53 | extern int usb_external_suspend_device(struct usb_device *udev, |
52 | pm_message_t msg); | 54 | pm_message_t msg); |
53 | extern int usb_external_resume_device(struct usb_device *udev); | 55 | extern int usb_external_resume_device(struct usb_device *udev, |
56 | pm_message_t msg); | ||
54 | 57 | ||
55 | static inline void usb_pm_lock(struct usb_device *udev) | 58 | static inline void usb_pm_lock(struct usb_device *udev) |
56 | { | 59 | { |
@@ -64,12 +67,12 @@ static inline void usb_pm_unlock(struct usb_device *udev) | |||
64 | 67 | ||
65 | #else | 68 | #else |
66 | 69 | ||
67 | static inline int usb_port_suspend(struct usb_device *udev) | 70 | static inline int usb_port_suspend(struct usb_device *udev, pm_message_t msg) |
68 | { | 71 | { |
69 | return 0; | 72 | return 0; |
70 | } | 73 | } |
71 | 74 | ||
72 | static inline int usb_port_resume(struct usb_device *udev) | 75 | static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg) |
73 | { | 76 | { |
74 | return 0; | 77 | return 0; |
75 | } | 78 | } |