forked from mirrors/linux
		
	usbcore: add sysfs support to xHCI usb3 hardware LPM
Add a sysfs node to make it easier to verify if LPM is supported and being enabled for USB 3.0 devices. Signed-off-by: Kevin Strasser <kevin.strasser@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									eb4861c3ce
								
							
						
					
					
						commit
						655fe4effe
					
				
					 4 changed files with 62 additions and 2 deletions
				
			
		| 
						 | 
				
			
			@ -114,6 +114,20 @@ Description:
 | 
			
		|||
		enabled for the device. Developer can write y/Y/1 or n/N/0 to
 | 
			
		||||
		the file to enable/disable the feature.
 | 
			
		||||
 | 
			
		||||
What:		/sys/bus/usb/devices/.../power/usb3_hardware_lpm
 | 
			
		||||
Date:		June 2015
 | 
			
		||||
Contact:	Kevin Strasser <kevin.strasser@linux.intel.com>
 | 
			
		||||
Description:
 | 
			
		||||
		If CONFIG_PM_RUNTIME is set and a USB 3.0 lpm-capable device is
 | 
			
		||||
		plugged in to a xHCI host which supports link PM, it will check
 | 
			
		||||
		if U1 and U2 exit latencies have been set in the BOS
 | 
			
		||||
		descriptor; if the check is is passed and the host supports
 | 
			
		||||
		USB3 hardware LPM, USB3 hardware LPM will be enabled for the
 | 
			
		||||
		device and the USB device directory will contain a file named
 | 
			
		||||
		power/usb3_hardware_lpm. The file holds a string value (enable
 | 
			
		||||
		or disable) indicating whether or not USB3 hardware LPM is
 | 
			
		||||
		enabled for the device.
 | 
			
		||||
 | 
			
		||||
What:		/sys/bus/usb/devices/.../removable
 | 
			
		||||
Date:		February 2012
 | 
			
		||||
Contact:	Matthew Garrett <mjg@redhat.com>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -521,10 +521,10 @@ enabling hardware LPM, the host can automatically put the device into
 | 
			
		|||
lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices),
 | 
			
		||||
which state device can enter and resume very quickly.
 | 
			
		||||
 | 
			
		||||
The user interface for controlling USB2 hardware LPM is located in the
 | 
			
		||||
The user interface for controlling hardware LPM is located in the
 | 
			
		||||
power/ subdirectory of each USB device's sysfs directory, that is, in
 | 
			
		||||
/sys/bus/usb/devices/.../power/ where "..." is the device's ID. The
 | 
			
		||||
relevant attribute files is usb2_hardware_lpm.
 | 
			
		||||
relevant attribute files are usb2_hardware_lpm and usb3_hardware_lpm.
 | 
			
		||||
 | 
			
		||||
	power/usb2_hardware_lpm
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -537,6 +537,17 @@ relevant attribute files is usb2_hardware_lpm.
 | 
			
		|||
		can write y/Y/1 or n/N/0 to the file to	enable/disable
 | 
			
		||||
		USB2 hardware LPM manually. This is for	test purpose mainly.
 | 
			
		||||
 | 
			
		||||
	power/usb3_hardware_lpm
 | 
			
		||||
 | 
			
		||||
		When a USB 3.0 lpm-capable device is plugged in to a
 | 
			
		||||
		xHCI host which supports link PM, it will check if U1
 | 
			
		||||
		and U2 exit latencies have been set in the BOS
 | 
			
		||||
		descriptor; if the check is is passed and the host
 | 
			
		||||
		supports USB3 hardware LPM, USB3 hardware LPM will be
 | 
			
		||||
		enabled for the device and this file will be created.
 | 
			
		||||
		The file holds a string value (enable or disable)
 | 
			
		||||
		indicating whether or not USB3 hardware LPM is
 | 
			
		||||
		enabled for the device.
 | 
			
		||||
 | 
			
		||||
	USB Port Power Control
 | 
			
		||||
	----------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3950,6 +3950,8 @@ int usb_disable_lpm(struct usb_device *udev)
 | 
			
		|||
	if (usb_disable_link_state(hcd, udev, USB3_LPM_U2))
 | 
			
		||||
		goto enable_lpm;
 | 
			
		||||
 | 
			
		||||
	udev->usb3_lpm_enabled = 0;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
enable_lpm:
 | 
			
		||||
| 
						 | 
				
			
			@ -4007,6 +4009,8 @@ void usb_enable_lpm(struct usb_device *udev)
 | 
			
		|||
 | 
			
		||||
	usb_enable_link_state(hcd, udev, USB3_LPM_U1);
 | 
			
		||||
	usb_enable_link_state(hcd, udev, USB3_LPM_U2);
 | 
			
		||||
 | 
			
		||||
	udev->usb3_lpm_enabled = 1;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(usb_enable_lpm);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -531,6 +531,25 @@ static ssize_t usb2_lpm_besl_store(struct device *dev,
 | 
			
		|||
}
 | 
			
		||||
static DEVICE_ATTR_RW(usb2_lpm_besl);
 | 
			
		||||
 | 
			
		||||
static ssize_t usb3_hardware_lpm_show(struct device *dev,
 | 
			
		||||
				      struct device_attribute *attr, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	struct usb_device *udev = to_usb_device(dev);
 | 
			
		||||
	const char *p;
 | 
			
		||||
 | 
			
		||||
	usb_lock_device(udev);
 | 
			
		||||
 | 
			
		||||
	if (udev->usb3_lpm_enabled)
 | 
			
		||||
		p = "enabled";
 | 
			
		||||
	else
 | 
			
		||||
		p = "disabled";
 | 
			
		||||
 | 
			
		||||
	usb_unlock_device(udev);
 | 
			
		||||
 | 
			
		||||
	return sprintf(buf, "%s\n", p);
 | 
			
		||||
}
 | 
			
		||||
static DEVICE_ATTR_RO(usb3_hardware_lpm);
 | 
			
		||||
 | 
			
		||||
static struct attribute *usb2_hardware_lpm_attr[] = {
 | 
			
		||||
	&dev_attr_usb2_hardware_lpm.attr,
 | 
			
		||||
	&dev_attr_usb2_lpm_l1_timeout.attr,
 | 
			
		||||
| 
						 | 
				
			
			@ -542,6 +561,15 @@ static struct attribute_group usb2_hardware_lpm_attr_group = {
 | 
			
		|||
	.attrs	= usb2_hardware_lpm_attr,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct attribute *usb3_hardware_lpm_attr[] = {
 | 
			
		||||
	&dev_attr_usb3_hardware_lpm.attr,
 | 
			
		||||
	NULL,
 | 
			
		||||
};
 | 
			
		||||
static struct attribute_group usb3_hardware_lpm_attr_group = {
 | 
			
		||||
	.name	= power_group_name,
 | 
			
		||||
	.attrs	= usb3_hardware_lpm_attr,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct attribute *power_attrs[] = {
 | 
			
		||||
	&dev_attr_autosuspend.attr,
 | 
			
		||||
	&dev_attr_level.attr,
 | 
			
		||||
| 
						 | 
				
			
			@ -564,6 +592,9 @@ static int add_power_attributes(struct device *dev)
 | 
			
		|||
		if (udev->usb2_hw_lpm_capable == 1)
 | 
			
		||||
			rc = sysfs_merge_group(&dev->kobj,
 | 
			
		||||
					&usb2_hardware_lpm_attr_group);
 | 
			
		||||
		if (udev->lpm_capable == 1)
 | 
			
		||||
			rc = sysfs_merge_group(&dev->kobj,
 | 
			
		||||
					&usb3_hardware_lpm_attr_group);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return rc;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue