summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMing Lei <tom.leiming@gmail.com>2010-11-15 23:56:54 +0300
committerGreg Kroah-Hartman <gregkh@suse.de>2010-11-17 01:02:00 +0300
commit63defa73c8c1193c1273474440c30d34c2524597 (patch)
tree3d7cbe9351e507ca2e55a874e496398979602ec1 /drivers
parentf646cf94520e22cb11eb5d2e9a35b33bfe4bea1b (diff)
downloadlinux-63defa73c8c1193c1273474440c30d34c2524597.tar.xz
USB: use the no_callbacks flag for interfaces
Call pm_runtime_no_callbacks to set no_callbacks flag for USB interfaces. Since interfaces cannot be power-managed separately from their parent devices, there's no reason for the runtime-PM core to invoke any callbacks for them. Signed-off-by: Ming Lei <tom.leiming@gmail.com> Reviewed-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/core/driver.c82
-rw-r--r--drivers/usb/core/message.c2
2 files changed, 31 insertions, 53 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index c0e60fbcb048..eda2d2c25459 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1612,18 +1612,9 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
*/
int usb_autopm_get_interface_async(struct usb_interface *intf)
{
- int status = 0;
- enum rpm_status s;
-
- /* Don't request a resume unless the interface is already suspending
- * or suspended. Doing so would force a running suspend timer to be
- * cancelled.
- */
- pm_runtime_get_noresume(&intf->dev);
- s = ACCESS_ONCE(intf->dev.power.runtime_status);
- if (s == RPM_SUSPENDING || s == RPM_SUSPENDED)
- status = pm_request_resume(&intf->dev);
+ int status;
+ status = pm_runtime_get(&intf->dev);
if (status < 0 && status != -EINPROGRESS)
pm_runtime_put_noidle(&intf->dev);
else
@@ -1717,71 +1708,56 @@ static int autosuspend_check(struct usb_device *udev)
static int usb_runtime_suspend(struct device *dev)
{
- int status = 0;
+ struct usb_device *udev = to_usb_device(dev);
+ int status;
/* A USB device can be suspended if it passes the various autosuspend
* checks. Runtime suspend for a USB device means suspending all the
* interfaces and then the device itself.
*/
- if (is_usb_device(dev)) {
- struct usb_device *udev = to_usb_device(dev);
-
- if (autosuspend_check(udev) != 0)
- return -EAGAIN;
-
- status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
+ if (autosuspend_check(udev) != 0)
+ return -EAGAIN;
- /* If an interface fails the suspend, adjust the last_busy
- * time so that we don't get another suspend attempt right
- * away.
- */
- if (status) {
- udev->last_busy = jiffies +
- (udev->autosuspend_delay == 0 ?
- HZ/2 : 0);
- }
+ status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
- /* Prevent the parent from suspending immediately after */
- else if (udev->parent)
- udev->parent->last_busy = jiffies;
+ /* If an interface fails the suspend, adjust the last_busy
+ * time so that we don't get another suspend attempt right
+ * away.
+ */
+ if (status) {
+ udev->last_busy = jiffies +
+ (udev->autosuspend_delay == 0 ? HZ/2 : 0);
}
- /* Runtime suspend for a USB interface doesn't mean anything. */
+ /* Prevent the parent from suspending immediately after */
+ else if (udev->parent)
+ udev->parent->last_busy = jiffies;
+
return status;
}
static int usb_runtime_resume(struct device *dev)
{
+ struct usb_device *udev = to_usb_device(dev);
+ int status;
+
/* Runtime resume for a USB device means resuming both the device
* and all its interfaces.
*/
- if (is_usb_device(dev)) {
- struct usb_device *udev = to_usb_device(dev);
- int status;
-
- status = usb_resume_both(udev, PMSG_AUTO_RESUME);
- udev->last_busy = jiffies;
- return status;
- }
-
- /* Runtime resume for a USB interface doesn't mean anything. */
- return 0;
+ status = usb_resume_both(udev, PMSG_AUTO_RESUME);
+ udev->last_busy = jiffies;
+ return status;
}
static int usb_runtime_idle(struct device *dev)
{
+ struct usb_device *udev = to_usb_device(dev);
+
/* An idle USB device can be suspended if it passes the various
- * autosuspend checks. An idle interface can be suspended at
- * any time.
+ * autosuspend checks.
*/
- if (is_usb_device(dev)) {
- struct usb_device *udev = to_usb_device(dev);
-
- if (autosuspend_check(udev) != 0)
- return 0;
- }
-
- pm_runtime_suspend(dev);
+ if (autosuspend_check(udev) == 0)
+ pm_runtime_suspend(dev);
return 0;
}
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index d6e3e410477e..f377e49fcb30 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -12,6 +12,7 @@
#include <linux/ctype.h>
#include <linux/nls.h>
#include <linux/device.h>
+#include <linux/pm_runtime.h>
#include <linux/scatterlist.h>
#include <linux/usb/quirks.h>
#include <linux/usb/hcd.h> /* for usbcore internals */
@@ -1804,6 +1805,7 @@ free_interfaces:
INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
intf->minor = -1;
device_initialize(&intf->dev);
+ pm_runtime_no_callbacks(&intf->dev);
dev_set_name(&intf->dev, "%d-%s:%d.%d",
dev->bus->busnum, dev->devpath,
configuration, alt->desc.bInterfaceNumber);