This is a note to let you know that I've just added the patch titled

     Subject: USB: autosuspend code consolidation

to my gregkh-2.6 tree.  Its filename is

     usb-autosuspend-code-consolidation.patch

This tree can be found at 
    http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/


>From [EMAIL PROTECTED] Mon Oct 30 14:06:47 2006
Date: Mon, 30 Oct 2006 17:06:45 -0500 (EST)
From: Alan Stern <[EMAIL PROTECTED]>
To: Greg KH <[EMAIL PROTECTED]>, Oliver Neukum <[EMAIL PROTECTED]>
cc: USB development list <linux-usb-devel@lists.sourceforge.net>
Subject: USB: autosuspend code consolidation
Message-ID: <[EMAIL PROTECTED]>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII

This patch (as813) gathers together common code for USB interface
autosuspend/autoresume. 

It also adds some simple checking at the time an autosuspend request
is made, to see whether the request will fail.  This way we don't
add a workqueue entry when it would end up doing nothing.

Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>

---
 drivers/usb/core/driver.c |  112 +++++++++++++++++++++++++++-------------------
 1 file changed, 67 insertions(+), 45 deletions(-)

--- gregkh-2.6.orig/drivers/usb/core/driver.c
+++ gregkh-2.6/drivers/usb/core/driver.c
@@ -944,6 +944,36 @@ done:
        return status;
 }
 
+/* Internal routine to check whether we may autosuspend a device. */
+static int autosuspend_check(struct usb_device *udev)
+{
+       int                     i;
+       struct usb_interface    *intf;
+
+       /* For autosuspend, fail fast if anything is in use.
+        * Also fail if any interfaces require remote wakeup but it
+        * isn't available. */
+       udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+       if (udev->pm_usage_cnt > 0)
+               return -EBUSY;
+       if (udev->actconfig) {
+               for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+                       intf = udev->actconfig->interface[i];
+                       if (!is_active(intf))
+                               continue;
+                       if (intf->pm_usage_cnt > 0)
+                               return -EBUSY;
+                       if (intf->needs_remote_wakeup &&
+                                       !udev->do_remote_wakeup) {
+                               dev_dbg(&udev->dev, "remote wakeup needed "
+                                               "for autosuspend\n");
+                               return -EOPNOTSUPP;
+                       }
+               }
+       }
+       return 0;
+}
+
 /**
  * usb_suspend_both - suspend a USB device and its interfaces
  * @udev: the usb_device to suspend
@@ -995,28 +1025,10 @@ int usb_suspend_both(struct usb_device *
 
        udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
 
-       /* For autosuspend, fail fast if anything is in use.
-        * Also fail if any interfaces require remote wakeup but it
-        * isn't available. */
        if (udev->auto_pm) {
-               if (udev->pm_usage_cnt > 0)
-                       return -EBUSY;
-               if (udev->actconfig) {
-                       for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
-                               intf = udev->actconfig->interface[i];
-                               if (!is_active(intf))
-                                       continue;
-                               if (intf->pm_usage_cnt > 0)
-                                       return -EBUSY;
-                               if (intf->needs_remote_wakeup &&
-                                               !udev->do_remote_wakeup) {
-                                       dev_dbg(&udev->dev,
-       "remote wakeup needed for autosuspend\n");
-                                       return -EOPNOTSUPP;
-                               }
-                       }
-                       i = 0;
-               }
+               status = autosuspend_check(udev);
+               if (status < 0)
+                       return status;
        }
 
        /* Suspend all the interfaces and then udev itself */
@@ -1155,7 +1167,7 @@ void usb_autosuspend_device(struct usb_d
 {
        usb_pm_lock(udev);
        udev->pm_usage_cnt -= dec_usage_cnt;
-       if (udev->pm_usage_cnt <= 0)
+       if (autosuspend_check(udev) == 0)
                queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
                                USB_AUTOSUSPEND_DELAY);
        usb_pm_unlock(udev);
@@ -1204,6 +1216,33 @@ int usb_autoresume_device(struct usb_dev
        return status;
 }
 
+/* Internal routine to adjust an interface's usage counter and change
+ * its device's autosuspend state.
+ */
+static int usb_autopm_do_interface(struct usb_interface *intf,
+               int inc_usage_cnt)
+{
+       struct usb_device       *udev = interface_to_usbdev(intf);
+       int                     status = 0;
+
+       usb_pm_lock(udev);
+       if (intf->condition == USB_INTERFACE_UNBOUND)
+               status = -ENODEV;
+       else {
+               intf->pm_usage_cnt += inc_usage_cnt;
+               if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
+                       udev->auto_pm = 1;
+                       status = usb_resume_both(udev);
+                       if (status != 0)
+                               intf->pm_usage_cnt -= inc_usage_cnt;
+               } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
+                       queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+                                       USB_AUTOSUSPEND_DELAY);
+       }
+       usb_pm_unlock(udev);
+       return status;
+}
+
 /**
  * usb_autopm_put_interface - decrement a USB interface's PM-usage counter
  * @intf: the usb_interface whose counter should be decremented
@@ -1237,17 +1276,11 @@ int usb_autoresume_device(struct usb_dev
  */
 void usb_autopm_put_interface(struct usb_interface *intf)
 {
-       struct usb_device       *udev = interface_to_usbdev(intf);
+       int     status;
 
-       usb_pm_lock(udev);
-       if (intf->condition != USB_INTERFACE_UNBOUND &&
-                       --intf->pm_usage_cnt <= 0) {
-               queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
-                               USB_AUTOSUSPEND_DELAY);
-       }
-       usb_pm_unlock(udev);
-       // dev_dbg(&intf->dev, "%s: cnt %d\n",
-       //              __FUNCTION__, intf->pm_usage_cnt);
+       status = usb_autopm_do_interface(intf, -1);
+       // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+       //              __FUNCTION__, status, intf->pm_usage_cnt);
 }
 EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
 
@@ -1284,20 +1317,9 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interfa
  */
 int usb_autopm_get_interface(struct usb_interface *intf)
 {
-       struct usb_device       *udev = interface_to_usbdev(intf);
-       int                     status;
+       int     status;
 
-       usb_pm_lock(udev);
-       if (intf->condition == USB_INTERFACE_UNBOUND)
-               status = -ENODEV;
-       else {
-               ++intf->pm_usage_cnt;
-               udev->auto_pm = 1;
-               status = usb_resume_both(udev);
-               if (status != 0)
-                       --intf->pm_usage_cnt;
-       }
-       usb_pm_unlock(udev);
+       status = usb_autopm_do_interface(intf, 1);
        // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
        //              __FUNCTION__, status, intf->pm_usage_cnt);
        return status;


Patches currently in gregkh-2.6 which might be from [EMAIL PROTECTED] are

usb/ehci-hcd-fix-budget_pool-allocation-for-machines-with-multiple-ehci-controllers.patch
usb/usb-core-don-t-match-interface-descriptors-for-vendor-specific-devices.patch
usb/usb-hid-handle-stall-on-interrupt-endpoint.patch
usb/usb-takes-31-devices-per-hub.patch
usb/usb-hub-root-hub-code-takes-more-than-15-devices.patch
usb/usb-ohci-disable-rhsc-inside-interrupt-handler.patch
usb/usb-ohci-fix-root-hub-resume-bug.patch
usb/usb-ohci-hcd-fix-compiler-warning.patch
usb/usb-ohci-remove-stale-testing-code-from-root-hub-resume.patch
usb/usb-autosuspend-code-consolidation.patch
usb/usb-expand-autosuspend-autoresume-api.patch
g-usb-hub-autosuspend-autoresume.patch
g-ehci-repair-remote-wakeup-support.patch

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to