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
@ -114,6 +114,20 @@ Description:
|
|||||||
enabled for the device. Developer can write y/Y/1 or n/N/0 to
|
enabled for the device. Developer can write y/Y/1 or n/N/0 to
|
||||||
the file to enable/disable the feature.
|
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
|
What: /sys/bus/usb/devices/.../removable
|
||||||
Date: February 2012
|
Date: February 2012
|
||||||
Contact: Matthew Garrett <mjg@redhat.com>
|
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),
|
lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices),
|
||||||
which state device can enter and resume very quickly.
|
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
|
power/ subdirectory of each USB device's sysfs directory, that is, in
|
||||||
/sys/bus/usb/devices/.../power/ where "..." is the device's ID. The
|
/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
|
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
|
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.
|
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
|
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))
|
if (usb_disable_link_state(hcd, udev, USB3_LPM_U2))
|
||||||
goto enable_lpm;
|
goto enable_lpm;
|
||||||
|
|
||||||
|
udev->usb3_lpm_enabled = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
enable_lpm:
|
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_U1);
|
||||||
usb_enable_link_state(hcd, udev, USB3_LPM_U2);
|
usb_enable_link_state(hcd, udev, USB3_LPM_U2);
|
||||||
|
|
||||||
|
udev->usb3_lpm_enabled = 1;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(usb_enable_lpm);
|
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 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[] = {
|
static struct attribute *usb2_hardware_lpm_attr[] = {
|
||||||
&dev_attr_usb2_hardware_lpm.attr,
|
&dev_attr_usb2_hardware_lpm.attr,
|
||||||
&dev_attr_usb2_lpm_l1_timeout.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,
|
.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[] = {
|
static struct attribute *power_attrs[] = {
|
||||||
&dev_attr_autosuspend.attr,
|
&dev_attr_autosuspend.attr,
|
||||||
&dev_attr_level.attr,
|
&dev_attr_level.attr,
|
||||||
@ -564,6 +592,9 @@ static int add_power_attributes(struct device *dev)
|
|||||||
if (udev->usb2_hw_lpm_capable == 1)
|
if (udev->usb2_hw_lpm_capable == 1)
|
||||||
rc = sysfs_merge_group(&dev->kobj,
|
rc = sysfs_merge_group(&dev->kobj,
|
||||||
&usb2_hardware_lpm_attr_group);
|
&usb2_hardware_lpm_attr_group);
|
||||||
|
if (udev->lpm_capable == 1)
|
||||||
|
rc = sysfs_merge_group(&dev->kobj,
|
||||||
|
&usb3_hardware_lpm_attr_group);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
Loading…
Reference in New Issue
Block a user