Skip to content

Commit

Permalink
USB: make autosuspend delay a module parameter
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Feb 23, 2007
1 parent aa084f3 commit b5e795f
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 10 deletions.
7 changes: 7 additions & 0 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1758,6 +1758,13 @@ and is between 256 and 4096 characters. It is defined in the file
Note that genuine overcurrent events won't be
reported either.

usbcore.autosuspend=
[USB] The autosuspend time delay (in seconds) used
for newly-detected USB devices (default 2). This
is the time required before an idle device will be
autosuspended. Devices for which the delay is set
to 0 won't be autosuspended at all.

usbhid.mousepoll=
[USBHID] The interval which mice are to be polled at.

Expand Down
16 changes: 10 additions & 6 deletions drivers/usb/core/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -963,12 +963,16 @@ static int autosuspend_check(struct usb_device *udev)
int i;
struct usb_interface *intf;

/* For autosuspend, fail fast if anything is in use.
* Also fail if any interfaces require remote wakeup but it
* isn't available. */
/* For autosuspend, fail fast if anything is in use or autosuspend
* is disabled. Also fail if any interfaces require remote wakeup
* but it isn't available.
*/
udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
if (udev->pm_usage_cnt > 0)
return -EBUSY;
if (!udev->autosuspend_delay)
return -EPERM;

if (udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
Expand All @@ -991,7 +995,7 @@ static int autosuspend_check(struct usb_device *udev)

#define autosuspend_check(udev) 0

#endif
#endif /* CONFIG_USB_SUSPEND */

/**
* usb_suspend_both - suspend a USB device and its interfaces
Expand Down Expand Up @@ -1186,7 +1190,7 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
udev->pm_usage_cnt -= inc_usage_cnt;
} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
USB_AUTOSUSPEND_DELAY);
udev->autosuspend_delay);
usb_pm_unlock(udev);
return status;
}
Expand Down Expand Up @@ -1270,7 +1274,7 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
intf->pm_usage_cnt -= inc_usage_cnt;
} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
USB_AUTOSUSPEND_DELAY);
udev->autosuspend_delay);
}
usb_pm_unlock(udev);
return status;
Expand Down
6 changes: 4 additions & 2 deletions drivers/usb/core/quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ static const struct usb_device_id usb_quirk_list[] = {

static void usb_autosuspend_quirk(struct usb_device *udev)
{
/* unbalanced resume to prevent autosuspends */
usb_autoresume_device(udev);
#ifdef CONFIG_USB_SUSPEND
/* disable autosuspend, but allow the user to re-enable it via sysfs */
udev->autosuspend_delay = 0;
#endif
}

static const struct usb_device_id *find_id(struct usb_device *udev)
Expand Down
12 changes: 12 additions & 0 deletions drivers/usb/core/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
*/

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/bitops.h>
#include <linux/slab.h>
Expand Down Expand Up @@ -50,6 +51,16 @@ static int nousb; /* Disable USB when built into kernel image */

struct workqueue_struct *ksuspend_usb_wq; /* For autosuspend */

#ifdef CONFIG_USB_SUSPEND
static int usb_autosuspend_delay = 2; /* Default delay value,
* in seconds */
module_param_named(autosuspend, usb_autosuspend_delay, uint, 0644);
MODULE_PARM_DESC(autosuspend, "default autosuspend delay");

#else
#define usb_autosuspend_delay 0
#endif


/**
* usb_ifnum_to_if - get the interface object with a given interface number
Expand Down Expand Up @@ -306,6 +317,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
#ifdef CONFIG_PM
mutex_init(&dev->pm_mutex);
INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
dev->autosuspend_delay = usb_autosuspend_delay * HZ;
#endif
return dev;
}
Expand Down
2 changes: 0 additions & 2 deletions drivers/usb/core/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}

#ifdef CONFIG_USB_SUSPEND

#define USB_AUTOSUSPEND_DELAY (HZ*2)

extern void usb_autosuspend_device(struct usb_device *udev);
extern int usb_autoresume_device(struct usb_device *udev);

Expand Down
3 changes: 3 additions & 0 deletions include/linux/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,10 +389,13 @@ struct usb_device {

int pm_usage_cnt; /* usage counter for autosuspend */
u32 quirks; /* quirks of the whole device */

#ifdef CONFIG_PM
struct delayed_work autosuspend; /* for delayed autosuspends */
struct mutex pm_mutex; /* protects PM operations */

unsigned autosuspend_delay; /* in jiffies */

unsigned auto_pm:1; /* autosuspend/resume in progress */
unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */
#endif
Expand Down

0 comments on commit b5e795f

Please sign in to comment.