Skip to content

Commit

Permalink
USB: skip autosuspended devices during system resume
Browse files Browse the repository at this point in the history
System suspends and hibernation are supposed to be as transparent as
possible.  By this reasoning, if a USB device is already autosuspended
before the system sleep begins then it should remain autosuspended
after the system wakes up.

This patch (as1001) adds a skip_sys_resume flag to the usb_device
structure and uses it to avoid waking up devices which were suspended
when a system sleep began.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Oct 12, 2007
1 parent 32fe019 commit 271f9e6
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 7 deletions.
27 changes: 20 additions & 7 deletions drivers/usb/core/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1540,9 +1540,21 @@ int usb_external_resume_device(struct usb_device *udev)

static int usb_suspend(struct device *dev, pm_message_t message)
{
struct usb_device *udev;

if (!is_usb_device(dev)) /* Ignore PM for interfaces */
return 0;
return usb_external_suspend_device(to_usb_device(dev), message);
udev = to_usb_device(dev);

/* If udev is already suspended, we can skip this suspend and
* we should also skip the upcoming system resume. */
if (udev->state == USB_STATE_SUSPENDED) {
udev->skip_sys_resume = 1;
return 0;
}

udev->skip_sys_resume = 0;
return usb_external_suspend_device(udev, message);
}

static int usb_resume(struct device *dev)
Expand All @@ -1553,13 +1565,14 @@ static int usb_resume(struct device *dev)
return 0;
udev = to_usb_device(dev);

/* If autoresume is disabled then we also want to prevent resume
* during system wakeup. However, a "persistent-device" reset-resume
* after power loss counts as a wakeup event. So allow a
* reset-resume to occur if remote wakeup is enabled. */
if (udev->autoresume_disabled) {
/* If udev->skip_sys_resume is set then udev was already suspended
* when the system suspend started, so we don't want to resume
* udev during this system wakeup. However a reset-resume counts
* as a wakeup event, so allow a reset-resume to occur if remote
* wakeup is enabled. */
if (udev->skip_sys_resume) {
if (!(udev->reset_resume && udev->do_remote_wakeup))
return -EPERM;
return -EHOSTUNREACH;
}
return usb_external_resume_device(udev);
}
Expand Down
1 change: 1 addition & 0 deletions include/linux/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ struct usb_device {
unsigned persist_enabled:1; /* USB_PERSIST enabled for this dev */
unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
unsigned autoresume_disabled:1; /* disabled by the user */
unsigned skip_sys_resume:1; /* skip the next system resume */
#endif
};
#define to_usb_device(d) container_of(d, struct usb_device, dev)
Expand Down

0 comments on commit 271f9e6

Please sign in to comment.