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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
4ec06d6296
commit
65bfd2967c
@@ -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)
|
|||||||
|
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
/* 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)
|
|||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
/**
|
/**
|
||||||
* 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)
|
|||||||
*
|
*
|
||||||
* 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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
/* 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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
/**
|
/**
|
||||||
* 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)
|
|||||||
*
|
*
|
||||||
* 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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
* 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)
|
|||||||
* 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)
|
|||||||
|
|
||||||
#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)
|
|||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
#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,
|
|||||||
*
|
*
|
||||||
* 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)
|
|||||||
} 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)
|
|||||||
*
|
*
|
||||||
* 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)
|
|||||||
} 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)
|
|||||||
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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 = {
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#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);
|
|||||||
#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)
|
|||||||
|
|
||||||
#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 {
|
|||||||
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;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user