mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-22 17:33:01 +00:00
USB 3.0 Link PM fixes.
Hi Greg, Here's four fixes for the USB 3.0 Link Power Management code. They work around some USB 3.0 devices that don't support LPM, like the Western Digital My Passport hard drive. They also fix an LPM disable ref count bug that would cause LPM to remain disabled for a device after a failed probe. Please queue for 3.7 after the merge window closes. Several patches are marked for stable. Sarah Sharp -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJQdzkvAAoJEBMGWMLi1Gc5GyYP/1RoDNMNVS+AZVxaoC6t6FhT rWyg74vWZqnfrf6XKnZshELjJ5rK52ZvKykmnAjIXT0y9D9bOKxkxi0008GMeGNO UulYZH5TAxlCsIqjzYmb87lJ42+CzNOhWrCNwQdn5BdM/gypDHcKx7kb2b+Jljky Xe6mdSDo+KGScBRLJPPvAIuk/IsZIFarcZruYP55PPJ44Q9LWR4Uq8zm6t8qJYkP 0s8KNHYXeKZBg2z50iILo7WWRoNIHvAH9xJigU5T2QQCSzBeE/ILkNzkkSrBfoJp 0DAV9fpdkYLhx1aSp628uorcn4D0lOCSoCasVdgeUSdi/XVpJWU1DbAPljfPK7lH JBS4ba3s6/25Dl+BRgz+MUq6PBbAexmqg+5jhTkP2GKU8nSsXI1ZkahjRFgAgWxC FRHhNINTq56rnY3s3Ts30pjtZ9tai7BnWVKU9/0cNeaks8OMZ0ANBr/j2qkm+Jjg lBZtyxsg73yt/PDLZuJPnULMJ1QQZoIsJXZcBxLNcYtpCC/0AdH8bl/PdCjAcnUt RL1BLcWLLqIki90LHx/aPx2UCmhtOv8JWzJ5vgysh89BqNLWFhuJHF615nlSkwQj UkjcLWmVwT52+00gkD/cWWgueOkTx0Aokb6l3tYckyWk3d4BOshaWQL54haTvqQL 5fz9MQUslawTDjv7igT+ =n/bA -----END PGP SIGNATURE----- Merge tag 'for-usb-linus-2012-10-11' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-linus USB 3.0 Link PM fixes. Hi Greg, Here's four fixes for the USB 3.0 Link Power Management code. They work around some USB 3.0 devices that don't support LPM, like the Western Digital My Passport hard drive. They also fix an LPM disable ref count bug that would cause LPM to remain disabled for a device after a failed probe. Please queue for 3.7 after the merge window closes. Several patches are marked for stable. Sarah Sharp
This commit is contained in:
commit
b001b29791
@ -367,6 +367,10 @@ static int usb_probe_interface(struct device *dev)
|
||||
intf->condition = USB_INTERFACE_UNBOUND;
|
||||
usb_cancel_queued_reset(intf);
|
||||
|
||||
/* If the LPM disable succeeded, balance the ref counts. */
|
||||
if (!lpm_disable_error)
|
||||
usb_unlocked_enable_lpm(udev);
|
||||
|
||||
/* Unbound interfaces are always runtime-PM-disabled and -suspended */
|
||||
if (driver->supports_autosuspend)
|
||||
pm_runtime_disable(dev);
|
||||
|
@ -3241,8 +3241,7 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)
|
||||
(state == USB3_LPM_U2 &&
|
||||
(u2_sel > USB3_LPM_MAX_U2_SEL_PEL ||
|
||||
u2_pel > USB3_LPM_MAX_U2_SEL_PEL))) {
|
||||
dev_dbg(&udev->dev, "Device-initiated %s disabled due "
|
||||
"to long SEL %llu ms or PEL %llu ms\n",
|
||||
dev_dbg(&udev->dev, "Device-initiated %s disabled due to long SEL %llu us or PEL %llu us\n",
|
||||
usb3_lpm_names[state], u1_sel, u1_pel);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -3319,16 +3318,6 @@ static int usb_set_device_initiated_lpm(struct usb_device *udev,
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
/*
|
||||
* First, let the device know about the exit latencies
|
||||
* associated with the link state we're about to enable.
|
||||
*/
|
||||
ret = usb_req_set_sel(udev, state);
|
||||
if (ret < 0) {
|
||||
dev_warn(&udev->dev, "Set SEL for device-initiated "
|
||||
"%s failed.\n", usb3_lpm_names[state]);
|
||||
return -EBUSY;
|
||||
}
|
||||
/*
|
||||
* Now send the control transfer to enable device-initiated LPM
|
||||
* for either U1 or U2.
|
||||
@ -3414,7 +3403,28 @@ static int usb_set_lpm_timeout(struct usb_device *udev,
|
||||
static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
|
||||
enum usb3_link_state state)
|
||||
{
|
||||
int timeout;
|
||||
int timeout, ret;
|
||||
__u8 u1_mel = udev->bos->ss_cap->bU1devExitLat;
|
||||
__le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat;
|
||||
|
||||
/* If the device says it doesn't have *any* exit latency to come out of
|
||||
* U1 or U2, it's probably lying. Assume it doesn't implement that link
|
||||
* state.
|
||||
*/
|
||||
if ((state == USB3_LPM_U1 && u1_mel == 0) ||
|
||||
(state == USB3_LPM_U2 && u2_mel == 0))
|
||||
return;
|
||||
|
||||
/*
|
||||
* First, let the device know about the exit latencies
|
||||
* associated with the link state we're about to enable.
|
||||
*/
|
||||
ret = usb_req_set_sel(udev, state);
|
||||
if (ret < 0) {
|
||||
dev_warn(&udev->dev, "Set SEL for device-initiated %s failed.\n",
|
||||
usb3_lpm_names[state]);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We allow the host controller to set the U1/U2 timeout internally
|
||||
* first, so that it can change its schedule to account for the
|
||||
|
Loading…
Reference in New Issue
Block a user