]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.9/usb-consolidate-lpm-checks-to-avoid-enabling-lpm-twice.patch
4.19-stable patches
[thirdparty/kernel/stable-queue.git] / queue-4.9 / usb-consolidate-lpm-checks-to-avoid-enabling-lpm-twice.patch
1 From d7a6c0ce8d26412903c7981503bad9e1cc7c45d2 Mon Sep 17 00:00:00 2001
2 From: Kai-Heng Feng <kai.heng.feng@canonical.com>
3 Date: Sat, 12 Jan 2019 03:54:25 +0800
4 Subject: USB: Consolidate LPM checks to avoid enabling LPM twice
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 From: Kai-Heng Feng <kai.heng.feng@canonical.com>
10
11 commit d7a6c0ce8d26412903c7981503bad9e1cc7c45d2 upstream.
12
13 USB Bluetooth controller QCA ROME (0cf3:e007) sometimes stops working
14 after S3:
15 [ 165.110742] Bluetooth: hci0: using NVM file: qca/nvm_usb_00000302.bin
16 [ 168.432065] Bluetooth: hci0: Failed to send body at 4 of 1953 (-110)
17
18 After some experiments, I found that disabling LPM can workaround the
19 issue.
20
21 On some platforms, the USB power is cut during S3, so the driver uses
22 reset-resume to resume the device. During port resume, LPM gets enabled
23 twice, by usb_reset_and_verify_device() and usb_port_resume().
24
25 Consolidate all checks into new LPM helpers to make sure LPM only gets
26 enabled once.
27
28 Fixes: de68bab4fa96 ("usb: Don't enable USB 2.0 Link PM by default.”)
29 Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
30 Cc: stable <stable@vger.kernel.org> # after much soaking
31 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
32 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
33
34 ---
35 drivers/usb/core/driver.c | 11 ++++++++---
36 drivers/usb/core/hub.c | 12 ++++--------
37 drivers/usb/core/message.c | 3 +--
38 3 files changed, 13 insertions(+), 13 deletions(-)
39
40 --- a/drivers/usb/core/driver.c
41 +++ b/drivers/usb/core/driver.c
42 @@ -1893,9 +1893,6 @@ static int usb_set_usb2_hardware_lpm(str
43 struct usb_hcd *hcd = bus_to_hcd(udev->bus);
44 int ret = -EPERM;
45
46 - if (enable && !udev->usb2_hw_lpm_allowed)
47 - return 0;
48 -
49 if (hcd->driver->set_usb2_hw_lpm) {
50 ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, enable);
51 if (!ret)
52 @@ -1907,11 +1904,19 @@ static int usb_set_usb2_hardware_lpm(str
53
54 int usb_enable_usb2_hardware_lpm(struct usb_device *udev)
55 {
56 + if (!udev->usb2_hw_lpm_capable ||
57 + !udev->usb2_hw_lpm_allowed ||
58 + udev->usb2_hw_lpm_enabled)
59 + return 0;
60 +
61 return usb_set_usb2_hardware_lpm(udev, 1);
62 }
63
64 int usb_disable_usb2_hardware_lpm(struct usb_device *udev)
65 {
66 + if (!udev->usb2_hw_lpm_enabled)
67 + return 0;
68 +
69 return usb_set_usb2_hardware_lpm(udev, 0);
70 }
71
72 --- a/drivers/usb/core/hub.c
73 +++ b/drivers/usb/core/hub.c
74 @@ -3168,8 +3168,7 @@ int usb_port_suspend(struct usb_device *
75 }
76
77 /* disable USB2 hardware LPM */
78 - if (udev->usb2_hw_lpm_enabled == 1)
79 - usb_disable_usb2_hardware_lpm(udev);
80 + usb_disable_usb2_hardware_lpm(udev);
81
82 if (usb_disable_ltm(udev)) {
83 dev_err(&udev->dev, "Failed to disable LTM before suspend\n.");
84 @@ -3215,8 +3214,7 @@ int usb_port_suspend(struct usb_device *
85 usb_enable_ltm(udev);
86 err_ltm:
87 /* Try to enable USB2 hardware LPM again */
88 - if (udev->usb2_hw_lpm_capable == 1)
89 - usb_enable_usb2_hardware_lpm(udev);
90 + usb_enable_usb2_hardware_lpm(udev);
91
92 if (udev->do_remote_wakeup)
93 (void) usb_disable_remote_wakeup(udev);
94 @@ -3499,8 +3497,7 @@ int usb_port_resume(struct usb_device *u
95 hub_port_logical_disconnect(hub, port1);
96 } else {
97 /* Try to enable USB2 hardware LPM */
98 - if (udev->usb2_hw_lpm_capable == 1)
99 - usb_enable_usb2_hardware_lpm(udev);
100 + usb_enable_usb2_hardware_lpm(udev);
101
102 /* Try to enable USB3 LTM and LPM */
103 usb_enable_ltm(udev);
104 @@ -5481,8 +5478,7 @@ static int usb_reset_and_verify_device(s
105 /* Disable USB2 hardware LPM.
106 * It will be re-enabled by the enumeration process.
107 */
108 - if (udev->usb2_hw_lpm_enabled == 1)
109 - usb_disable_usb2_hardware_lpm(udev);
110 + usb_disable_usb2_hardware_lpm(udev);
111
112 /* Disable LPM and LTM while we reset the device and reinstall the alt
113 * settings. Device-initiated LPM settings, and system exit latency
114 --- a/drivers/usb/core/message.c
115 +++ b/drivers/usb/core/message.c
116 @@ -1181,8 +1181,7 @@ void usb_disable_device(struct usb_devic
117 dev->actconfig->interface[i] = NULL;
118 }
119
120 - if (dev->usb2_hw_lpm_enabled == 1)
121 - usb_disable_usb2_hardware_lpm(dev);
122 + usb_disable_usb2_hardware_lpm(dev);
123 usb_unlocked_disable_lpm(dev);
124 usb_disable_ltm(dev);
125