aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-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