aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-02-20 15:00:53 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-02-23 18:03:46 -0500
commitb5e795f8df42936590ba9c606edc715fe3593284 (patch)
treeed0f132edc4d050407c4ba0b4582f167db86ba72
parentaa084f3efe5fb7e9c0d5b54ce704f0de69bbf27c (diff)
USB: make autosuspend delay a module parameter
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>
-rw-r--r--Documentation/kernel-parameters.txt7
-rw-r--r--drivers/usb/core/driver.c16
-rw-r--r--drivers/usb/core/quirks.c6
-rw-r--r--drivers/usb/core/usb.c12
-rw-r--r--drivers/usb/core/usb.h2
-rw-r--r--include/linux/usb.h3
6 files changed, 36 insertions, 10 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index c479d30eeaa3..03eb5ed503f7 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1758,6 +1758,13 @@ and is between 256 and 4096 characters. It is defined in the file
1758 Note that genuine overcurrent events won't be 1758 Note that genuine overcurrent events won't be
1759 reported either. 1759 reported either.
1760 1760
1761 usbcore.autosuspend=
1762 [USB] The autosuspend time delay (in seconds) used
1763 for newly-detected USB devices (default 2). This
1764 is the time required before an idle device will be
1765 autosuspended. Devices for which the delay is set
1766 to 0 won't be autosuspended at all.
1767
1761 usbhid.mousepoll= 1768 usbhid.mousepoll=
1762 [USBHID] The interval which mice are to be polled at. 1769 [USBHID] The interval which mice are to be polled at.
1763 1770
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index f9196a0a9412..a420d72a0254 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -963,12 +963,16 @@ static int autosuspend_check(struct usb_device *udev)
963 int i; 963 int i;
964 struct usb_interface *intf; 964 struct usb_interface *intf;
965 965
966 /* For autosuspend, fail fast if anything is in use. 966 /* For autosuspend, fail fast if anything is in use or autosuspend
967 * Also fail if any interfaces require remote wakeup but it 967 * is disabled. Also fail if any interfaces require remote wakeup
968 * isn't available. */ 968 * but it isn't available.
969 */
969 udev->do_remote_wakeup = device_may_wakeup(&udev->dev); 970 udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
970 if (udev->pm_usage_cnt > 0) 971 if (udev->pm_usage_cnt > 0)
971 return -EBUSY; 972 return -EBUSY;
973 if (!udev->autosuspend_delay)
974 return -EPERM;
975
972 if (udev->actconfig) { 976 if (udev->actconfig) {
973 for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { 977 for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
974 intf = udev->actconfig->interface[i]; 978 intf = udev->actconfig->interface[i];
@@ -991,7 +995,7 @@ static int autosuspend_check(struct usb_device *udev)
991 995
992#define autosuspend_check(udev) 0 996#define autosuspend_check(udev) 0
993 997
994#endif 998#endif /* CONFIG_USB_SUSPEND */
995 999
996/** 1000/**
997 * usb_suspend_both - suspend a USB device and its interfaces 1001 * 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)
1186 udev->pm_usage_cnt -= inc_usage_cnt; 1190 udev->pm_usage_cnt -= inc_usage_cnt;
1187 } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0) 1191 } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
1188 queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, 1192 queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
1189 USB_AUTOSUSPEND_DELAY); 1193 udev->autosuspend_delay);
1190 usb_pm_unlock(udev); 1194 usb_pm_unlock(udev);
1191 return status; 1195 return status;
1192} 1196}
@@ -1270,7 +1274,7 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
1270 intf->pm_usage_cnt -= inc_usage_cnt; 1274 intf->pm_usage_cnt -= inc_usage_cnt;
1271 } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0) 1275 } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
1272 queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, 1276 queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
1273 USB_AUTOSUSPEND_DELAY); 1277 udev->autosuspend_delay);
1274 } 1278 }
1275 usb_pm_unlock(udev); 1279 usb_pm_unlock(udev);
1276 return status; 1280 return status;
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index ea0e48e9f611..0e5c646cb4f6 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -39,8 +39,10 @@ static const struct usb_device_id usb_quirk_list[] = {
39 39
40static void usb_autosuspend_quirk(struct usb_device *udev) 40static void usb_autosuspend_quirk(struct usb_device *udev)
41{ 41{
42 /* unbalanced resume to prevent autosuspends */ 42#ifdef CONFIG_USB_SUSPEND
43 usb_autoresume_device(udev); 43 /* disable autosuspend, but allow the user to re-enable it via sysfs */
44 udev->autosuspend_delay = 0;
45#endif
44} 46}
45 47
46static const struct usb_device_id *find_id(struct usb_device *udev) 48static const struct usb_device_id *find_id(struct usb_device *udev)
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 3db721cd557a..54b42ce311c1 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -22,6 +22,7 @@
22 */ 22 */
23 23
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/moduleparam.h>
25#include <linux/string.h> 26#include <linux/string.h>
26#include <linux/bitops.h> 27#include <linux/bitops.h>
27#include <linux/slab.h> 28#include <linux/slab.h>
@@ -50,6 +51,16 @@ static int nousb; /* Disable USB when built into kernel image */
50 51
51struct workqueue_struct *ksuspend_usb_wq; /* For autosuspend */ 52struct workqueue_struct *ksuspend_usb_wq; /* For autosuspend */
52 53
54#ifdef CONFIG_USB_SUSPEND
55static int usb_autosuspend_delay = 2; /* Default delay value,
56 * in seconds */
57module_param_named(autosuspend, usb_autosuspend_delay, uint, 0644);
58MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
59
60#else
61#define usb_autosuspend_delay 0
62#endif
63
53 64
54/** 65/**
55 * usb_ifnum_to_if - get the interface object with a given interface number 66 * 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)
306#ifdef CONFIG_PM 317#ifdef CONFIG_PM
307 mutex_init(&dev->pm_mutex); 318 mutex_init(&dev->pm_mutex);
308 INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); 319 INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
320 dev->autosuspend_delay = usb_autosuspend_delay * HZ;
309#endif 321#endif
310 return dev; 322 return dev;
311} 323}
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 045cbd111887..b0a35f45b099 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -65,8 +65,6 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
65 65
66#ifdef CONFIG_USB_SUSPEND 66#ifdef CONFIG_USB_SUSPEND
67 67
68#define USB_AUTOSUSPEND_DELAY (HZ*2)
69
70extern void usb_autosuspend_device(struct usb_device *udev); 68extern void usb_autosuspend_device(struct usb_device *udev);
71extern int usb_autoresume_device(struct usb_device *udev); 69extern int usb_autoresume_device(struct usb_device *udev);
72 70
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 37e522eba47f..87dc75a6cee1 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -389,10 +389,13 @@ struct usb_device {
389 389
390 int pm_usage_cnt; /* usage counter for autosuspend */ 390 int pm_usage_cnt; /* usage counter for autosuspend */
391 u32 quirks; /* quirks of the whole device */ 391 u32 quirks; /* quirks of the whole device */
392
392#ifdef CONFIG_PM 393#ifdef CONFIG_PM
393 struct delayed_work autosuspend; /* for delayed autosuspends */ 394 struct delayed_work autosuspend; /* for delayed autosuspends */
394 struct mutex pm_mutex; /* protects PM operations */ 395 struct mutex pm_mutex; /* protects PM operations */
395 396
397 unsigned autosuspend_delay; /* in jiffies */
398
396 unsigned auto_pm:1; /* autosuspend/resume in progress */ 399 unsigned auto_pm:1; /* autosuspend/resume in progress */
397 unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */ 400 unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */
398#endif 401#endif