Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19c26239 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

USB: export autosuspend delay in sysfs



This patch (as861) adds sysfs attributes to expose the autosuspend
delay value for each USB device.  If the user changes the delay from 0
(no autosuspend) to a positive value, an autosuspend is attempted.

Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent dfa87c82
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -1224,6 +1224,26 @@ void usb_autosuspend_device(struct usb_device *udev)
	//		__FUNCTION__, udev->pm_usage_cnt);
}

/**
 * usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces
 * @udev: the usb_device to autosuspend
 *
 * This routine should be called when a core subsystem thinks @udev may
 * be ready to autosuspend.
 *
 * @udev's usage counter left unchanged.  If it or any of the usage counters
 * for an active interface is greater than 0, or autosuspend is not allowed
 * for any other reason, no autosuspend request will be queued.
 *
 * This routine can run only in process context.
 */
void usb_try_autosuspend_device(struct usb_device *udev)
{
	usb_autopm_do_device(udev, 0);
	// dev_dbg(&udev->dev, "%s: cnt %d\n",
	// 		__FUNCTION__, udev->pm_usage_cnt);
}

/**
 * usb_autoresume_device - immediately autoresume a USB device and its interfaces
 * @udev: the usb_device to autoresume
+64 −0
Original line number Diff line number Diff line
@@ -158,6 +158,65 @@ show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
}
static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);

#ifdef	CONFIG_USB_SUSPEND

static ssize_t
show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct usb_device *udev = to_usb_device(dev);

	return sprintf(buf, "%u\n", udev->autosuspend_delay / HZ);
}

static ssize_t
set_autosuspend(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{
	struct usb_device *udev = to_usb_device(dev);
	unsigned value, old;

	if (sscanf(buf, "%u", &value) != 1 || value >= INT_MAX/HZ)
		return -EINVAL;
	value *= HZ;

	old = udev->autosuspend_delay;
	udev->autosuspend_delay = value;
	if (value > 0 && old == 0)
		usb_try_autosuspend_device(udev);

	return count;
}

static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
		show_autosuspend, set_autosuspend);

static char power_group[] = "power";

static int add_power_attributes(struct device *dev)
{
	int rc = 0;

	if (is_usb_device(dev))
		rc = sysfs_add_file_to_group(&dev->kobj,
				&dev_attr_autosuspend.attr,
				power_group);
	return rc;
}

static void remove_power_attributes(struct device *dev)
{
	sysfs_remove_file_from_group(&dev->kobj,
			&dev_attr_autosuspend.attr,
			power_group);
}

#else

#define add_power_attributes(dev)	0
#define remove_power_attributes(dev)	do {} while (0)

#endif	/* CONFIG_USB_SUSPEND */

/* Descriptor fields */
#define usb_descriptor_attr_le16(field, format_string)			\
static ssize_t								\
@@ -230,6 +289,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
	if (retval)
		return retval;

	retval = add_power_attributes(dev);
	if (retval)
		goto error;

	if (udev->manufacturer) {
		retval = device_create_file(dev, &dev_attr_manufacturer);
		if (retval)
@@ -262,6 +325,7 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
	device_remove_file(dev, &dev_attr_manufacturer);
	device_remove_file(dev, &dev_attr_product);
	device_remove_file(dev, &dev_attr_serial);
	remove_power_attributes(dev);
	sysfs_remove_group(&dev->kobj, &dev_attr_grp);
}

+3 −1
Original line number Diff line number Diff line
@@ -66,11 +66,13 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
#ifdef CONFIG_USB_SUSPEND

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

#else

#define usb_autosuspend_device(udev)		do {} while (0)
#define usb_try_autosuspend_device(udev)	do {} while (0)
static inline int usb_autoresume_device(struct usb_device *udev)
{
	return 0;