diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/core/driver.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 6a3b5cae3a6e..64b91d6c5a5d 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -1263,13 +1263,47 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg) | |||
1263 | return status; | 1263 | return status; |
1264 | } | 1264 | } |
1265 | 1265 | ||
1266 | static void choose_wakeup(struct usb_device *udev, pm_message_t msg) | ||
1267 | { | ||
1268 | int w, i; | ||
1269 | struct usb_interface *intf; | ||
1270 | |||
1271 | /* Remote wakeup is needed only when we actually go to sleep. | ||
1272 | * For things like FREEZE and QUIESCE, if the device is already | ||
1273 | * autosuspended then its current wakeup setting is okay. | ||
1274 | */ | ||
1275 | if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_QUIESCE) { | ||
1276 | if (udev->state != USB_STATE_SUSPENDED) | ||
1277 | udev->do_remote_wakeup = 0; | ||
1278 | return; | ||
1279 | } | ||
1280 | |||
1281 | /* If remote wakeup is permitted, see whether any interface drivers | ||
1282 | * actually want it. | ||
1283 | */ | ||
1284 | w = 0; | ||
1285 | if (device_may_wakeup(&udev->dev) && udev->actconfig) { | ||
1286 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { | ||
1287 | intf = udev->actconfig->interface[i]; | ||
1288 | w |= intf->needs_remote_wakeup; | ||
1289 | } | ||
1290 | } | ||
1291 | |||
1292 | /* If the device is autosuspended with the wrong wakeup setting, | ||
1293 | * autoresume now so the setting can be changed. | ||
1294 | */ | ||
1295 | if (udev->state == USB_STATE_SUSPENDED && w != udev->do_remote_wakeup) | ||
1296 | pm_runtime_resume(&udev->dev); | ||
1297 | udev->do_remote_wakeup = w; | ||
1298 | } | ||
1299 | |||
1266 | /* The device lock is held by the PM core */ | 1300 | /* The device lock is held by the PM core */ |
1267 | int usb_suspend(struct device *dev, pm_message_t msg) | 1301 | int usb_suspend(struct device *dev, pm_message_t msg) |
1268 | { | 1302 | { |
1269 | struct usb_device *udev = to_usb_device(dev); | 1303 | struct usb_device *udev = to_usb_device(dev); |
1270 | 1304 | ||
1271 | do_unbind_rebind(udev, DO_UNBIND); | 1305 | do_unbind_rebind(udev, DO_UNBIND); |
1272 | udev->do_remote_wakeup = device_may_wakeup(&udev->dev); | 1306 | choose_wakeup(udev, msg); |
1273 | return usb_suspend_both(udev, msg); | 1307 | return usb_suspend_both(udev, msg); |
1274 | } | 1308 | } |
1275 | 1309 | ||