USB: make autosuspend delay a module parameter
authorAlan Stern <stern@rowland.harvard.edu>
Tue, 20 Feb 2007 20:00:53 +0000 (15:00 -0500)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 23 Feb 2007 23:03:46 +0000 (15:03 -0800)
This patch (as859) makes the default USB autosuspend delay a module
parameter of usbcore.  By setting the delay value at boot time, users
will be able to prevent the system from autosuspending devices which
for some reason can't handle it.

The patch also stores the autosuspend delay as a per-device value.  A
later patch will allow the user to change the value, tailoring the
delay for each individual device.  A delay value of 0 will prevent
autosuspend.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Documentation/kernel-parameters.txt
drivers/usb/core/driver.c
drivers/usb/core/quirks.c
drivers/usb/core/usb.c
drivers/usb/core/usb.h
include/linux/usb.h

index c479d30eeaa384c019550194d12c94c10bf1e948..03eb5ed503f7745e9e30f177fd35baba8ff96779 100644 (file)
@@ -1758,6 +1758,13 @@ and is between 256 and 4096 characters. It is defined in the file
                        Note that genuine overcurrent events won't be
                        reported either.
 
+       usbcore.autosuspend=
+                       [USB] The autosuspend time delay (in seconds) used
+                       for newly-detected USB devices (default 2).  This
+                       is the time required before an idle device will be
+                       autosuspended.  Devices for which the delay is set
+                       to 0 won't be autosuspended at all.
+
        usbhid.mousepoll=
                        [USBHID] The interval which mice are to be polled at.
 
index f9196a0a941206155249c1f60b1c1d11f925f286..a420d72a02541a3af1ef5234faa4cca4a6bbc617 100644 (file)
@@ -963,12 +963,16 @@ 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. */
+       /* For autosuspend, fail fast if anything is in use or autosuspend
+        * is disabled.  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->autosuspend_delay)
+               return -EPERM;
+
        if (udev->actconfig) {
                for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
                        intf = udev->actconfig->interface[i];
@@ -991,7 +995,7 @@ static int autosuspend_check(struct usb_device *udev)
 
 #define autosuspend_check(udev)                0
 
-#endif
+#endif /* CONFIG_USB_SUSPEND */
 
 /**
  * usb_suspend_both - suspend a USB device and its interfaces
@@ -1186,7 +1190,7 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
                        udev->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);
+                               udev->autosuspend_delay);
        usb_pm_unlock(udev);
        return status;
 }
@@ -1270,7 +1274,7 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
                                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);
+                                       udev->autosuspend_delay);
        }
        usb_pm_unlock(udev);
        return status;
index ea0e48e9f611169695bfe022003f73b46ee515ff..0e5c646cb4f600f02036a78cc678fae5d9293327 100644 (file)
@@ -39,8 +39,10 @@ static const struct usb_device_id usb_quirk_list[] = {
 
 static void usb_autosuspend_quirk(struct usb_device *udev)
 {
-       /* unbalanced resume to prevent autosuspends */
-       usb_autoresume_device(udev);
+#ifdef CONFIG_USB_SUSPEND
+       /* disable autosuspend, but allow the user to re-enable it via sysfs */
+       udev->autosuspend_delay = 0;
+#endif
 }
 
 static const struct usb_device_id *find_id(struct usb_device *udev)
index 3db721cd557a61eed125e2eba770389b28bc6d8a..54b42ce311c1887acf51ce225d91f9adfada78b8 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
@@ -50,6 +51,16 @@ static int nousb;    /* Disable USB when built into kernel image */
 
 struct workqueue_struct *ksuspend_usb_wq;      /* For autosuspend */
 
+#ifdef CONFIG_USB_SUSPEND
+static int usb_autosuspend_delay = 2;          /* Default delay value,
+                                                * in seconds */
+module_param_named(autosuspend, usb_autosuspend_delay, uint, 0644);
+MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
+
+#else
+#define usb_autosuspend_delay          0
+#endif
+
 
 /**
  * usb_ifnum_to_if - get the interface object with a given interface number
@@ -306,6 +317,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
 #ifdef CONFIG_PM
        mutex_init(&dev->pm_mutex);
        INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
+       dev->autosuspend_delay = usb_autosuspend_delay * HZ;
 #endif
        return dev;
 }
index 045cbd11188779c10d06756aa13a590c83aba715..b0a35f45b099ddcfe53bee573a10e82c162c6561 100644 (file)
@@ -65,8 +65,6 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
 
 #ifdef CONFIG_USB_SUSPEND
 
-#define USB_AUTOSUSPEND_DELAY  (HZ*2)
-
 extern void usb_autosuspend_device(struct usb_device *udev);
 extern int usb_autoresume_device(struct usb_device *udev);
 
index 37e522eba47fc7843bde0d15c6f1f79fc75c15d2..87dc75a6cee14e00a755cc49f9dd50e567373e19 100644 (file)
@@ -389,10 +389,13 @@ struct usb_device {
 
        int pm_usage_cnt;               /* usage counter for autosuspend */
        u32 quirks;                     /* quirks of the whole device */
+
 #ifdef CONFIG_PM
        struct delayed_work autosuspend; /* for delayed autosuspends */
        struct mutex pm_mutex;          /* protects PM operations */
 
+       unsigned autosuspend_delay;     /* in jiffies */
+
        unsigned auto_pm:1;             /* autosuspend/resume in progress */
        unsigned do_remote_wakeup:1;    /* remote wakeup should be enabled */
 #endif