USB: use the no_callbacks flag for interfaces
authorMing Lei <tom.leiming@gmail.com>
Mon, 15 Nov 2010 20:56:54 +0000 (15:56 -0500)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 16 Nov 2010 22:02:00 +0000 (14:02 -0800)
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>
drivers/usb/core/driver.c
drivers/usb/core/message.c

index c0e60fb..eda2d2c 100644 (file)
@@ -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;
 }
 
index d6e3e41..f377e49 100644 (file)
@@ -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);