Commit 65bfd296 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 4ec06d62
...@@ -1275,7 +1275,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) ...@@ -1275,7 +1275,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
struct acm *acm = usb_get_intfdata(intf); struct acm *acm = usb_get_intfdata(intf);
int cnt; int cnt;
if (acm->dev->auto_pm) { if (message.event & PM_EVENT_AUTO) {
int b; int b;
spin_lock_irq(&acm->read_lock); spin_lock_irq(&acm->read_lock);
......
...@@ -764,7 +764,8 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) ...@@ -764,7 +764,8 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
mutex_lock(&desc->plock); mutex_lock(&desc->plock);
#ifdef CONFIG_PM #ifdef CONFIG_PM
if (interface_to_usbdev(desc->intf)->auto_pm && test_bit(WDM_IN_USE, &desc->flags)) { if ((message.event & PM_EVENT_AUTO) &&
test_bit(WDM_IN_USE, &desc->flags)) {
rv = -EBUSY; rv = -EBUSY;
} else { } else {
#endif #endif
......
...@@ -922,7 +922,7 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg) ...@@ -922,7 +922,7 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
} }
/* Caller has locked udev's pm_mutex */ /* Caller has locked udev's pm_mutex */
static int usb_resume_device(struct usb_device *udev) static int usb_resume_device(struct usb_device *udev, pm_message_t msg)
{ {
struct usb_device_driver *udriver; struct usb_device_driver *udriver;
int status = 0; int status = 0;
...@@ -940,7 +940,7 @@ static int usb_resume_device(struct usb_device *udev) ...@@ -940,7 +940,7 @@ static int usb_resume_device(struct usb_device *udev)
udev->reset_resume = 1; udev->reset_resume = 1;
udriver = to_usb_device_driver(udev->dev.driver); udriver = to_usb_device_driver(udev->dev.driver);
status = udriver->resume(udev); status = udriver->resume(udev, msg);
done: done:
dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status); dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
...@@ -969,7 +969,7 @@ static int usb_suspend_interface(struct usb_device *udev, ...@@ -969,7 +969,7 @@ static int usb_suspend_interface(struct usb_device *udev,
status = driver->suspend(intf, msg); status = driver->suspend(intf, msg);
if (status == 0) if (status == 0)
mark_quiesced(intf); mark_quiesced(intf);
else if (!udev->auto_pm) else if (!(msg.event & PM_EVENT_AUTO))
dev_err(&intf->dev, "%s error %d\n", dev_err(&intf->dev, "%s error %d\n",
"suspend", status); "suspend", status);
} else { } else {
...@@ -987,7 +987,7 @@ static int usb_suspend_interface(struct usb_device *udev, ...@@ -987,7 +987,7 @@ static int usb_suspend_interface(struct usb_device *udev,
/* Caller has locked intf's usb_device's pm_mutex */ /* Caller has locked intf's usb_device's pm_mutex */
static int usb_resume_interface(struct usb_device *udev, static int usb_resume_interface(struct usb_device *udev,
struct usb_interface *intf, int reset_resume) struct usb_interface *intf, pm_message_t msg, int reset_resume)
{ {
struct usb_driver *driver; struct usb_driver *driver;
int status = 0; int status = 0;
...@@ -1138,10 +1138,9 @@ static inline int autosuspend_check(struct usb_device *udev, int reschedule) ...@@ -1138,10 +1138,9 @@ static inline int autosuspend_check(struct usb_device *udev, int reschedule)
* all the interfaces which were suspended are resumed so that they remain * all the interfaces which were suspended are resumed so that they remain
* in the same state as the device. * in the same state as the device.
* *
* If an autosuspend is in progress (@udev->auto_pm is set), the routine * If an autosuspend is in progress the routine checks first to make sure
* checks first to make sure that neither the device itself or any of its * that neither the device itself or any of its active interfaces is in use
* active interfaces is in use (pm_usage_cnt is greater than 0). If they * (pm_usage_cnt is greater than 0). If they are, the autosuspend fails.
* are, the autosuspend fails.
* *
* If the suspend succeeds, the routine recursively queues an autosuspend * If the suspend succeeds, the routine recursively queues an autosuspend
* request for @udev's parent device, thereby propagating the change up * 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,7 +1175,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
udev->do_remote_wakeup = device_may_wakeup(&udev->dev); udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
if (udev->auto_pm) { if (msg.event & PM_EVENT_AUTO) {
status = autosuspend_check(udev, 0); status = autosuspend_check(udev, 0);
if (status < 0) if (status < 0)
goto done; goto done;
...@@ -1196,13 +1195,16 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) ...@@ -1196,13 +1195,16 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
/* If the suspend failed, resume interfaces that did get suspended */ /* If the suspend failed, resume interfaces that did get suspended */
if (status != 0) { if (status != 0) {
pm_message_t msg2;
msg2.event = msg.event ^ (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
while (--i >= 0) { while (--i >= 0) {
intf = udev->actconfig->interface[i]; intf = udev->actconfig->interface[i];
usb_resume_interface(udev, intf, 0); usb_resume_interface(udev, intf, msg2, 0);
} }
/* Try another autosuspend when the interfaces aren't busy */ /* Try another autosuspend when the interfaces aren't busy */
if (udev->auto_pm) if (msg.event & PM_EVENT_AUTO)
autosuspend_check(udev, status == -EBUSY); autosuspend_check(udev, status == -EBUSY);
/* If the suspend succeeded then prevent any more URB submissions, /* 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,6 +1234,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
/** /**
* usb_resume_both - resume a USB device and its interfaces * usb_resume_both - resume a USB device and its interfaces
* @udev: the usb_device to resume * @udev: the usb_device to resume
* @msg: Power Management message describing this state transition
* *
* This is the central routine for resuming USB devices. It calls the * This is the central routine for resuming USB devices. It calls the
* the resume method for @udev and then calls the resume methods for all * 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,7 +1260,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
* *
* This routine can run only in process context. * This routine can run only in process context.
*/ */
static int usb_resume_both(struct usb_device *udev) static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
{ {
int status = 0; int status = 0;
int i; int i;
...@@ -1273,14 +1276,15 @@ static int usb_resume_both(struct usb_device *udev) ...@@ -1273,14 +1276,15 @@ static int usb_resume_both(struct usb_device *udev)
/* Propagate the resume up the tree, if necessary */ /* Propagate the resume up the tree, if necessary */
if (udev->state == USB_STATE_SUSPENDED) { if (udev->state == USB_STATE_SUSPENDED) {
if (udev->auto_pm && udev->autoresume_disabled) { if ((msg.event & PM_EVENT_AUTO) &&
udev->autoresume_disabled) {
status = -EPERM; status = -EPERM;
goto done; goto done;
} }
if (parent) { if (parent) {
status = usb_autoresume_device(parent); status = usb_autoresume_device(parent);
if (status == 0) { if (status == 0) {
status = usb_resume_device(udev); status = usb_resume_device(udev, msg);
if (status || udev->state == if (status || udev->state ==
USB_STATE_NOTATTACHED) { USB_STATE_NOTATTACHED) {
usb_autosuspend_device(parent); usb_autosuspend_device(parent);
...@@ -1303,15 +1307,16 @@ static int usb_resume_both(struct usb_device *udev) ...@@ -1303,15 +1307,16 @@ static int usb_resume_both(struct usb_device *udev)
/* We can't progagate beyond the USB subsystem, /* We can't progagate beyond the USB subsystem,
* so if a root hub's controller is suspended * so if a root hub's controller is suspended
* then we're stuck. */ * then we're stuck. */
status = usb_resume_device(udev); status = usb_resume_device(udev, msg);
} }
} else if (udev->reset_resume) } else if (udev->reset_resume)
status = usb_resume_device(udev); status = usb_resume_device(udev, msg);
if (status == 0 && udev->actconfig) { if (status == 0 && udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i]; intf = udev->actconfig->interface[i];
usb_resume_interface(udev, intf, udev->reset_resume); usb_resume_interface(udev, intf, msg,
udev->reset_resume);
} }
} }
...@@ -1339,13 +1344,13 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt) ...@@ -1339,13 +1344,13 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
udev->last_busy = jiffies; udev->last_busy = jiffies;
if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) { if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
if (udev->state == USB_STATE_SUSPENDED) if (udev->state == USB_STATE_SUSPENDED)
status = usb_resume_both(udev); status = usb_resume_both(udev, PMSG_AUTO_RESUME);
if (status != 0) if (status != 0)
udev->pm_usage_cnt -= inc_usage_cnt; udev->pm_usage_cnt -= inc_usage_cnt;
else if (inc_usage_cnt) else if (inc_usage_cnt)
udev->last_busy = jiffies; udev->last_busy = jiffies;
} else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) { } else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) {
status = usb_suspend_both(udev, PMSG_SUSPEND); status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
} }
usb_pm_unlock(udev); usb_pm_unlock(udev);
return status; return status;
...@@ -1469,13 +1474,14 @@ static int usb_autopm_do_interface(struct usb_interface *intf, ...@@ -1469,13 +1474,14 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
udev->last_busy = jiffies; udev->last_busy = jiffies;
if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) { if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
if (udev->state == USB_STATE_SUSPENDED) if (udev->state == USB_STATE_SUSPENDED)
status = usb_resume_both(udev); status = usb_resume_both(udev,
PMSG_AUTO_RESUME);
if (status != 0) if (status != 0)
intf->pm_usage_cnt -= inc_usage_cnt; intf->pm_usage_cnt -= inc_usage_cnt;
else else
udev->last_busy = jiffies; udev->last_busy = jiffies;
} else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) { } else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) {
status = usb_suspend_both(udev, PMSG_SUSPEND); status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
} }
} }
usb_pm_unlock(udev); usb_pm_unlock(udev);
...@@ -1700,6 +1706,7 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg) ...@@ -1700,6 +1706,7 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg)
/** /**
* usb_external_resume_device - external resume of a USB device and its interfaces * usb_external_resume_device - external resume of a USB device and its interfaces
* @udev: the usb_device to resume * @udev: the usb_device to resume
* @msg: Power Management message describing this state transition
* *
* This routine handles external resume requests: ones not generated * This routine handles external resume requests: ones not generated
* internally by a USB driver (autoresume) but rather coming from the user * 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,13 +1715,13 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg)
* *
* The caller must hold @udev's device lock. * The caller must hold @udev's device lock.
*/ */
int usb_external_resume_device(struct usb_device *udev) int usb_external_resume_device(struct usb_device *udev, pm_message_t msg)
{ {
int status; int status;
usb_pm_lock(udev); usb_pm_lock(udev);
udev->auto_pm = 0; udev->auto_pm = 0;
status = usb_resume_both(udev); status = usb_resume_both(udev, msg);
udev->last_busy = jiffies; udev->last_busy = jiffies;
usb_pm_unlock(udev); usb_pm_unlock(udev);
if (status == 0) if (status == 0)
...@@ -1727,7 +1734,7 @@ int usb_external_resume_device(struct usb_device *udev) ...@@ -1727,7 +1734,7 @@ int usb_external_resume_device(struct usb_device *udev)
return status; return status;
} }
int usb_suspend(struct device *dev, pm_message_t message) int usb_suspend(struct device *dev, pm_message_t msg)
{ {
struct usb_device *udev; struct usb_device *udev;
...@@ -1746,10 +1753,10 @@ int usb_suspend(struct device *dev, pm_message_t message) ...@@ -1746,10 +1753,10 @@ int usb_suspend(struct device *dev, pm_message_t message)
} }
udev->skip_sys_resume = 0; udev->skip_sys_resume = 0;
return usb_external_suspend_device(udev, message); return usb_external_suspend_device(udev, msg);
} }
int usb_resume(struct device *dev) int usb_resume(struct device *dev, pm_message_t msg)
{ {
struct usb_device *udev; struct usb_device *udev;
...@@ -1761,7 +1768,7 @@ int usb_resume(struct device *dev) ...@@ -1761,7 +1768,7 @@ int usb_resume(struct device *dev)
*/ */
if (udev->skip_sys_resume) if (udev->skip_sys_resume)
return 0; return 0;
return usb_external_resume_device(udev); return usb_external_resume_device(udev, msg);
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
......
...@@ -200,18 +200,18 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg) ...@@ -200,18 +200,18 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg)
* interfaces manually by doing a bus (or "global") suspend. * interfaces manually by doing a bus (or "global") suspend.
*/ */
if (!udev->parent) if (!udev->parent)
rc = hcd_bus_suspend(udev); rc = hcd_bus_suspend(udev, msg);
/* Non-root devices don't need to do anything for FREEZE or PRETHAW */ /* Non-root devices don't need to do anything for FREEZE or PRETHAW */
else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW) else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW)
rc = 0; rc = 0;
else else
rc = usb_port_suspend(udev); rc = usb_port_suspend(udev, msg);
return rc; return rc;
} }
static int generic_resume(struct usb_device *udev) static int generic_resume(struct usb_device *udev, pm_message_t msg)
{ {
int rc; int rc;
...@@ -221,9 +221,9 @@ static int generic_resume(struct usb_device *udev) ...@@ -221,9 +221,9 @@ static int generic_resume(struct usb_device *udev)
* interfaces manually by doing a bus (or "global") resume. * interfaces manually by doing a bus (or "global") resume.
*/ */
if (!udev->parent) if (!udev->parent)
rc = hcd_bus_resume(udev); rc = hcd_bus_resume(udev, msg);
else else
rc = usb_port_resume(udev); rc = usb_port_resume(udev, msg);
return rc; return rc;
} }
......
...@@ -1573,14 +1573,14 @@ int usb_hcd_get_frame_number (struct usb_device *udev) ...@@ -1573,14 +1573,14 @@ int usb_hcd_get_frame_number (struct usb_device *udev)
#ifdef CONFIG_PM #ifdef CONFIG_PM
int hcd_bus_suspend(struct usb_device *rhdev) int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
{ {
struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self);
int status; int status;
int old_state = hcd->state; int old_state = hcd->state;
dev_dbg(&rhdev->dev, "bus %s%s\n", dev_dbg(&rhdev->dev, "bus %s%s\n",
rhdev->auto_pm ? "auto-" : "", "suspend"); (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend");
if (!hcd->driver->bus_suspend) { if (!hcd->driver->bus_suspend) {
status = -ENOENT; status = -ENOENT;
} else { } else {
...@@ -1598,14 +1598,14 @@ int hcd_bus_suspend(struct usb_device *rhdev) ...@@ -1598,14 +1598,14 @@ int hcd_bus_suspend(struct usb_device *rhdev)
return status; return status;
} }
int hcd_bus_resume(struct usb_device *rhdev) int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
{ {
struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self);
int status; int status;
int old_state = hcd->state; int old_state = hcd->state;
dev_dbg(&rhdev->dev, "usb %s%s\n", dev_dbg(&rhdev->dev, "usb %s%s\n",
rhdev->auto_pm ? "auto-" : "", "resume"); (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume");
if (!hcd->driver->bus_resume) if (!hcd->driver->bus_resume)
return -ENOENT; return -ENOENT;
if (hcd->state == HC_STATE_RUNNING) if (hcd->state == HC_STATE_RUNNING)
...@@ -1638,7 +1638,7 @@ static void hcd_resume_work(struct work_struct *work) ...@@ -1638,7 +1638,7 @@ static void hcd_resume_work(struct work_struct *work)
usb_lock_device(udev); usb_lock_device(udev);
usb_mark_last_busy(udev); usb_mark_last_busy(udev);
usb_external_resume_device(udev); usb_external_resume_device(udev, PMSG_REMOTE_RESUME);
usb_unlock_device(udev); usb_unlock_device(udev);
} }
......
...@@ -388,8 +388,8 @@ extern int usb_find_interface_driver(struct usb_device *dev, ...@@ -388,8 +388,8 @@ extern int usb_find_interface_driver(struct usb_device *dev,
#ifdef CONFIG_PM #ifdef CONFIG_PM
extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd); extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
extern void usb_root_hub_lost_power(struct usb_device *rhdev); extern void usb_root_hub_lost_power(struct usb_device *rhdev);
extern int hcd_bus_suspend(struct usb_device *rhdev); extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg);
extern int hcd_bus_resume(struct usb_device *rhdev); extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg);
#else #else
static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd) static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
{ {
......
...@@ -1984,7 +1984,7 @@ static int check_port_resume_type(struct usb_device *udev, ...@@ -1984,7 +1984,7 @@ static int check_port_resume_type(struct usb_device *udev,
* *
* Returns 0 on success, else negative errno. * Returns 0 on success, else negative errno.
*/ */
int usb_port_suspend(struct usb_device *udev) int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
{ {
struct usb_hub *hub = hdev_to_hub(udev->parent); struct usb_hub *hub = hdev_to_hub(udev->parent);
int port1 = udev->portnum; int port1 = udev->portnum;
...@@ -2023,7 +2023,7 @@ int usb_port_suspend(struct usb_device *udev) ...@@ -2023,7 +2023,7 @@ int usb_port_suspend(struct usb_device *udev)
} else { } else {
/* device has up to 10 msec to fully suspend */ /* device has up to 10 msec to fully suspend */
dev_dbg(&udev->dev, "usb %ssuspend\n", dev_dbg(&udev->dev, "usb %ssuspend\n",
udev->auto_pm ? "auto-" : ""); (msg.event & PM_EVENT_AUTO ? "auto-" : ""));
usb_set_device_state(udev, USB_STATE_SUSPENDED); usb_set_device_state(udev, USB_STATE_SUSPENDED);
msleep(10); msleep(10);
} }
...@@ -2142,7 +2142,7 @@ static int finish_port_resume(struct usb_device *udev) ...@@ -2142,7 +2142,7 @@ static int finish_port_resume(struct usb_device *udev)
* *
* Returns 0 on success, else negative errno. * Returns 0 on success, else negative errno.
*/ */
int usb_port_resume(struct usb_device *udev) int usb_port_resume(struct usb_device *udev, pm_message_t msg)
{ {
struct usb_hub *hub = hdev_to_hub(udev->parent); struct usb_hub *hub = hdev_to_hub(udev->parent);
int port1 = udev->portnum; int port1 = udev->portnum;
...@@ -2167,7 +2167,7 @@ int usb_port_resume(struct usb_device *udev) ...@@ -2167,7 +2167,7 @@ int usb_port_resume(struct usb_device *udev)
} else { } else {
/* drive resume for at least 20 msec */ /* drive resume for at least 20 msec */
dev_dbg(&udev->dev, "usb %sresume\n", dev_dbg(&udev->dev, "usb %sresume\n",
udev->auto_pm ? "auto-" : ""); (msg.event & PM_EVENT_AUTO ? "auto-" : ""));
msleep(25); msleep(25);
/* Virtual root hubs can trigger on GET_PORT_STATUS to /* Virtual root hubs can trigger on GET_PORT_STATUS to
...@@ -2208,7 +2208,7 @@ static int remote_wakeup(struct usb_device *udev) ...@@ -2208,7 +2208,7 @@ static int remote_wakeup(struct usb_device *udev)
if (udev->state == USB_STATE_SUSPENDED) { if (udev->state == USB_STATE_SUSPENDED) {
dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
usb_mark_last_busy(udev); usb_mark_last_busy(udev);
status = usb_external_resume_device(udev); status = usb_external_resume_device(udev, PMSG_REMOTE_RESUME);
} }
return status; return status;
} }
...@@ -2217,14 +2217,14 @@ static int remote_wakeup(struct usb_device *udev) ...@@ -2217,14 +2217,14 @@ static int remote_wakeup(struct usb_device *udev)
/* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */ /* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */
int usb_port_suspend(struct usb_device *udev) int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
{ {
return 0; return 0;
} }
/* However we may need to do a reset-resume */ /* However we may need to do a reset-resume */
int usb_port_resume(struct usb_device *udev) int usb_port_resume(struct usb_device *udev, pm_message_t msg)
{ {
struct usb_hub *hub = hdev_to_hub(udev->parent); struct usb_hub *hub = hdev_to_hub(udev->parent);
int port1 = udev->portnum; int port1 = udev->portnum;
...@@ -2264,7 +2264,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) ...@@ -2264,7 +2264,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
udev = hdev->children [port1-1]; udev = hdev->children [port1-1];
if (udev && udev->can_submit) { if (udev && udev->can_submit) {
if (!hdev->auto_pm) if (!(msg.event & PM_EVENT_AUTO))
dev_dbg(&intf->dev, "port %d nyet suspended\n", dev_dbg(&intf->dev, "port %d nyet suspended\n",
port1); port1);
return -EBUSY; return -EBUSY;
......
...@@ -359,19 +359,19 @@ set_level(struct device *dev, struct device_attribute *attr, ...@@ -359,19 +359,19 @@ set_level(struct device *dev, struct device_attribute *attr,
strncmp(buf, on_string, len) == 0) { strncmp(buf, on_string, len) == 0) {
udev->autosuspend_disabled = 1; udev->autosuspend_disabled = 1;
udev->autoresume_disabled = 0; udev->autoresume_disabled = 0;
rc = usb_external_resume_device(udev); rc = usb_external_resume_device(udev, PMSG_USER_RESUME);
} else if (len == sizeof auto_string - 1 && } else if (len == sizeof auto_string - 1 &&
strncmp(buf, auto_string, len) == 0) { strncmp(buf, auto_string, len) == 0) {
udev->autosuspend_disabled = 0; udev->autosuspend_disabled = 0;
udev->autoresume_disabled = 0; udev->autoresume_disabled = 0;
rc = usb_external_resume_device(udev); rc = usb_external_resume_device(udev, PMSG_USER_RESUME);
} else if (len == sizeof suspend_string - 1 && } else if (len == sizeof suspend_string - 1 &&
strncmp(buf, suspend_string, len) == 0) { strncmp(buf, suspend_string, len) == 0) {
udev->autosuspend_disabled = 0; udev->autosuspend_disabled = 0;
udev->autoresume_disabled = 1; udev->autoresume_disabled = 1;
rc = usb_external_suspend_device(udev, PMSG_SUSPEND); rc = usb_external_suspend_device(udev, PMSG_USER_SUSPEND);
} else } else
rc = -EINVAL; rc = -EINVAL;
......
...@@ -253,7 +253,7 @@ static int usb_dev_prepare(struct device *dev) ...@@ -253,7 +253,7 @@ static int usb_dev_prepare(struct device *dev)
static void usb_dev_complete(struct device *dev) static void usb_dev_complete(struct device *dev)
{ {
/* Currently used only for rebinding interfaces */ /* Currently used only for rebinding interfaces */
usb_resume(dev); /* Implement eventually? */ usb_resume(dev, PMSG_RESUME); /* Message event is meaningless */
} }
static int usb_dev_suspend(struct device *dev) static int usb_dev_suspend(struct device *dev)
...@@ -263,7 +263,7 @@ static int usb_dev_suspend(struct device *dev) ...@@ -263,7 +263,7 @@ static int usb_dev_suspend(struct device *dev)
static int usb_dev_resume(struct device *dev) static int usb_dev_resume(struct device *dev)
{ {
return usb_resume(dev); return usb_resume(dev, PMSG_RESUME);
} }
static int usb_dev_freeze(struct device *dev) static int usb_dev_freeze(struct device *dev)
...@@ -273,7 +273,7 @@ static int usb_dev_freeze(struct device *dev) ...@@ -273,7 +273,7 @@ static int usb_dev_freeze(struct device *dev)
static int usb_dev_thaw(struct device *dev) static int usb_dev_thaw(struct device *dev)
{ {
return usb_resume(dev); return usb_resume(dev, PMSG_THAW);
} }
static int usb_dev_poweroff(struct device *dev) static int usb_dev_poweroff(struct device *dev)
...@@ -283,7 +283,7 @@ static int usb_dev_poweroff(struct device *dev) ...@@ -283,7 +283,7 @@ static int usb_dev_poweroff(struct device *dev)
static int usb_dev_restore(struct device *dev) static int usb_dev_restore(struct device *dev)
{ {
return usb_resume(dev); return usb_resume(dev, PMSG_RESTORE);
} }
static struct dev_pm_ops usb_device_pm_ops = { static struct dev_pm_ops usb_device_pm_ops = {
......
#include <linux/pm.h>
/* Functions local to drivers/usb/core/ */ /* Functions local to drivers/usb/core/ */
extern int usb_create_sysfs_dev_files(struct usb_device *dev); extern int usb_create_sysfs_dev_files(struct usb_device *dev);
...@@ -42,15 +44,16 @@ extern void usb_host_cleanup(void); ...@@ -42,15 +44,16 @@ extern void usb_host_cleanup(void);
#ifdef CONFIG_PM #ifdef CONFIG_PM
extern int usb_suspend(struct device *dev, pm_message_t msg); extern int usb_suspend(struct device *dev, pm_message_t msg);
extern int usb_resume(struct device *dev); extern int usb_resume(struct device *dev, pm_message_t msg);
extern void usb_autosuspend_work(struct work_struct *work); extern void usb_autosuspend_work(struct work_struct *work);
extern void usb_autoresume_work(struct work_struct *work); extern void usb_autoresume_work(struct work_struct *work);
extern int usb_port_suspend(struct usb_device *dev); extern int usb_port_suspend(struct usb_device *dev, pm_message_t msg);
extern int usb_port_resume(struct usb_device *dev); extern int usb_port_resume(struct usb_device *dev, pm_message_t msg);
extern int usb_external_suspend_device(struct usb_device *udev, extern int usb_external_suspend_device(struct usb_device *udev,
pm_message_t msg); pm_message_t msg);
extern int usb_external_resume_device(struct usb_device *udev); extern int usb_external_resume_device(struct usb_device *udev,
pm_message_t msg);
static inline void usb_pm_lock(struct usb_device *udev) static inline void usb_pm_lock(struct usb_device *udev)
{ {
...@@ -64,12 +67,12 @@ static inline void usb_pm_unlock(struct usb_device *udev) ...@@ -64,12 +67,12 @@ static inline void usb_pm_unlock(struct usb_device *udev)
#else #else
static inline int usb_port_suspend(struct usb_device *udev) static inline int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
{ {
return 0; return 0;
} }
static inline int usb_port_resume(struct usb_device *udev) static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)
{ {
return 0; return 0;
} }
......
...@@ -1067,7 +1067,7 @@ struct usb_device_driver { ...@@ -1067,7 +1067,7 @@ struct usb_device_driver {
void (*disconnect) (struct usb_device *udev); void (*disconnect) (struct usb_device *udev);
int (*suspend) (struct usb_device *udev, pm_message_t message); int (*suspend) (struct usb_device *udev, pm_message_t message);
int (*resume) (struct usb_device *udev); int (*resume) (struct usb_device *udev, pm_message_t message);
struct usbdrv_wrap drvwrap; struct usbdrv_wrap drvwrap;
unsigned int supports_autosuspend:1; unsigned int supports_autosuspend:1;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment