diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 7 | ||||
-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 | ||||
-rw-r--r-- | include/linux/usb.h | 3 |
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 | ||
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 | ||
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 |