diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-02-20 15:00:53 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-02-23 18:03:46 -0500 |
commit | b5e795f8df42936590ba9c606edc715fe3593284 (patch) | |
tree | ed0f132edc4d050407c4ba0b4582f167db86ba72 /drivers/usb | |
parent | aa084f3efe5fb7e9c0d5b54ce704f0de69bbf27c (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.c | 16 | ||||
-rw-r--r-- | drivers/usb/core/quirks.c | 6 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 12 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 2 |
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 | ||
40 | static void usb_autosuspend_quirk(struct usb_device *udev) | 40 | static 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 | ||
46 | static const struct usb_device_id *find_id(struct usb_device *udev) | 48 | static 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 | ||
51 | struct workqueue_struct *ksuspend_usb_wq; /* For autosuspend */ | 52 | struct workqueue_struct *ksuspend_usb_wq; /* For autosuspend */ |
52 | 53 | ||
54 | #ifdef CONFIG_USB_SUSPEND | ||
55 | static int usb_autosuspend_delay = 2; /* Default delay value, | ||
56 | * in seconds */ | ||
57 | module_param_named(autosuspend, usb_autosuspend_delay, uint, 0644); | ||
58 | MODULE_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 | |||
70 | extern void usb_autosuspend_device(struct usb_device *udev); | 68 | extern void usb_autosuspend_device(struct usb_device *udev); |
71 | extern int usb_autoresume_device(struct usb_device *udev); | 69 | extern int usb_autoresume_device(struct usb_device *udev); |
72 | 70 | ||