aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
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 /drivers/usb
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>
Diffstat (limited to 'drivers/usb')
-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
4 files changed, 26 insertions, 10 deletions
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