[SRU] [B/C/D/Unstable] [PATCH 0/2] Fix non-working QCA Rome Bluetooth after S3

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

[SRU] [B/C/D/Unstable] [PATCH 0/2] Fix non-working QCA Rome Bluetooth after S3

Kai-Heng Feng
BugLink: https://bugs.launchpad.net/bugs/1812812

[Impact]
Sometimes QCA Rome Bluetooth USB host doesn't work after S3:
[ 165.110742] Bluetooth: hci0: using NVM file: qca/nvm_usb_00000302.bin
[ 168.432065] Bluetooth: hci0: Failed to send body at 4 of 1953 (-110)

This is due to USB core enables LPM two times after S3.

[Fix]
Only enable LPM once.

[Test]
The Bluetooth USB works all the time after applying the fix.

[Regression Potential]
Low. Enabling a hardware feature twice in a row isn't right, I'd be
surprise if any hardware relies on this driver behavior.

Kai-Heng Feng (2):
  USB: Add new USB LPM helpers
  USB: Consolidate LPM checks to avoid enabling LPM twice

 drivers/usb/core/driver.c  | 23 +++++++++++++++++++----
 drivers/usb/core/hub.c     | 16 ++++++----------
 drivers/usb/core/message.c |  3 +--
 drivers/usb/core/sysfs.c   |  5 ++++-
 drivers/usb/core/usb.h     | 10 ++++++++--
 5 files changed, 38 insertions(+), 19 deletions(-)

--
2.17.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[C/D/Unstable] [PATCH 1/2] USB: Add new USB LPM helpers

Kai-Heng Feng
BugLink: https://bugs.launchpad.net/bugs/1812812

Use new helpers to make LPM enabling/disabling more clear.

This is a preparation to subsequent patch.

Signed-off-by: Kai-Heng Feng <[hidden email]>
Cc: stable <[hidden email]> # after much soaking
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
(cherry picked from commit 7529b2574a7aaf902f1f8159fbc2a7caa74be559 linux-next)
Signed-off-by: Kai-Heng Feng <[hidden email]>
---
 drivers/usb/core/driver.c  | 12 +++++++++++-
 drivers/usb/core/hub.c     | 12 ++++++------
 drivers/usb/core/message.c |  2 +-
 drivers/usb/core/sysfs.c   |  5 ++++-
 drivers/usb/core/usb.h     | 10 ++++++++--
 5 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 53564386ed57..c276ffc5561f 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1896,7 +1896,7 @@ int usb_runtime_idle(struct device *dev)
  return -EBUSY;
 }
 
-int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
+static int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
 {
  struct usb_hcd *hcd = bus_to_hcd(udev->bus);
  int ret = -EPERM;
@@ -1913,6 +1913,16 @@ int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
  return ret;
 }
 
+int usb_enable_usb2_hardware_lpm(struct usb_device *udev)
+{
+ return usb_set_usb2_hardware_lpm(udev, 1);
+}
+
+int usb_disable_usb2_hardware_lpm(struct usb_device *udev)
+{
+ return usb_set_usb2_hardware_lpm(udev, 0);
+}
+
 #endif /* CONFIG_PM */
 
 struct bus_type usb_bus_type = {
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 1d1e61e980f3..ca38ff8124a7 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3221,7 +3221,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 
  /* disable USB2 hardware LPM */
  if (udev->usb2_hw_lpm_enabled == 1)
- usb_set_usb2_hardware_lpm(udev, 0);
+ usb_disable_usb2_hardware_lpm(udev);
 
  if (usb_disable_ltm(udev)) {
  dev_err(&udev->dev, "Failed to disable LTM before suspend\n");
@@ -3260,7 +3260,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
  err_ltm:
  /* Try to enable USB2 hardware LPM again */
  if (udev->usb2_hw_lpm_capable == 1)
- usb_set_usb2_hardware_lpm(udev, 1);
+ usb_enable_usb2_hardware_lpm(udev);
 
  if (udev->do_remote_wakeup)
  (void) usb_disable_remote_wakeup(udev);
@@ -3544,7 +3544,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
  } else  {
  /* Try to enable USB2 hardware LPM */
  if (udev->usb2_hw_lpm_capable == 1)
- usb_set_usb2_hardware_lpm(udev, 1);
+ usb_enable_usb2_hardware_lpm(udev);
 
  /* Try to enable USB3 LTM */
  usb_enable_ltm(udev);
@@ -4435,7 +4435,7 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
  if ((udev->bos->ext_cap->bmAttributes & cpu_to_le32(USB_BESL_SUPPORT)) ||
  connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
  udev->usb2_hw_lpm_allowed = 1;
- usb_set_usb2_hardware_lpm(udev, 1);
+ usb_enable_usb2_hardware_lpm(udev);
  }
 }
 
@@ -5650,7 +5650,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
  * It will be re-enabled by the enumeration process.
  */
  if (udev->usb2_hw_lpm_enabled == 1)
- usb_set_usb2_hardware_lpm(udev, 0);
+ usb_disable_usb2_hardware_lpm(udev);
 
  /* Disable LPM while we reset the device and reinstall the alt settings.
  * Device-initiated LPM, and system exit latency settings are cleared
@@ -5753,7 +5753,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
 
 done:
  /* Now that the alt settings are re-installed, enable LTM and LPM. */
- usb_set_usb2_hardware_lpm(udev, 1);
+ usb_enable_usb2_hardware_lpm(udev);
  usb_unlocked_enable_lpm(udev);
  usb_enable_ltm(udev);
  usb_release_bos_descriptor(udev);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index bfa5eda0cc26..35951aea7f50 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1244,7 +1244,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
  }
 
  if (dev->usb2_hw_lpm_enabled == 1)
- usb_set_usb2_hardware_lpm(dev, 0);
+ usb_disable_usb2_hardware_lpm(dev);
  usb_unlocked_disable_lpm(dev);
  usb_disable_ltm(dev);
 
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index ea18284dfa9a..7e88fdfe3cf5 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -528,7 +528,10 @@ static ssize_t usb2_hardware_lpm_store(struct device *dev,
 
  if (!ret) {
  udev->usb2_hw_lpm_allowed = value;
- ret = usb_set_usb2_hardware_lpm(udev, value);
+ if (value)
+ ret = usb_enable_usb2_hardware_lpm(udev);
+ else
+ ret = usb_disable_usb2_hardware_lpm(udev);
  }
 
  usb_unlock_device(udev);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 546a2219454b..d95a5358f73d 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -92,7 +92,8 @@ extern int usb_remote_wakeup(struct usb_device *dev);
 extern int usb_runtime_suspend(struct device *dev);
 extern int usb_runtime_resume(struct device *dev);
 extern int usb_runtime_idle(struct device *dev);
-extern int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable);
+extern int usb_enable_usb2_hardware_lpm(struct usb_device *udev);
+extern int usb_disable_usb2_hardware_lpm(struct usb_device *udev);
 
 #else
 
@@ -112,7 +113,12 @@ static inline int usb_autoresume_device(struct usb_device *udev)
  return 0;
 }
 
-static inline int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
+static inline int usb_enable_usb2_hardware_lpm(struct usb_device *udev)
+{
+ return 0;
+}
+
+static inline int usb_disable_usb2_hardware_lpm(struct usb_device *udev)
 {
  return 0;
 }
--
2.17.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[B] [PATCH 1/2] USB: Add new USB LPM helpers

Kai-Heng Feng
In reply to this post by Kai-Heng Feng
BugLink: https://bugs.launchpad.net/bugs/1812812

Use new helpers to make LPM enabling/disabling more clear.

This is a preparation to subsequent patch.

Signed-off-by: Kai-Heng Feng <[hidden email]>
Cc: stable <[hidden email]> # after much soaking
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
(backported from commit 7529b2574a7aaf902f1f8159fbc2a7caa74be559 linux-next)
Signed-off-by: Kai-Heng Feng <[hidden email]>
---
 drivers/usb/core/driver.c  | 12 +++++++++++-
 drivers/usb/core/hub.c     | 12 ++++++------
 drivers/usb/core/message.c |  2 +-
 drivers/usb/core/sysfs.c   |  5 ++++-
 drivers/usb/core/usb.h     | 10 ++++++++--
 5 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 5d3408010112..f3ba386a2acd 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1899,7 +1899,7 @@ int usb_runtime_idle(struct device *dev)
  return -EBUSY;
 }
 
-int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
+static int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
 {
  struct usb_hcd *hcd = bus_to_hcd(udev->bus);
  int ret = -EPERM;
@@ -1916,6 +1916,16 @@ int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
  return ret;
 }
 
+int usb_enable_usb2_hardware_lpm(struct usb_device *udev)
+{
+ return usb_set_usb2_hardware_lpm(udev, 1);
+}
+
+int usb_disable_usb2_hardware_lpm(struct usb_device *udev)
+{
+ return usb_set_usb2_hardware_lpm(udev, 0);
+}
+
 #endif /* CONFIG_PM */
 
 struct bus_type usb_bus_type = {
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 91c895f41fd0..f929f4b5fd75 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3167,7 +3167,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 
  /* disable USB2 hardware LPM */
  if (udev->usb2_hw_lpm_enabled == 1)
- usb_set_usb2_hardware_lpm(udev, 0);
+ usb_disable_usb2_hardware_lpm(udev);
 
  if (usb_disable_ltm(udev)) {
  dev_err(&udev->dev, "Failed to disable LTM before suspend\n.");
@@ -3206,7 +3206,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
  err_ltm:
  /* Try to enable USB2 hardware LPM again */
  if (udev->usb2_hw_lpm_capable == 1)
- usb_set_usb2_hardware_lpm(udev, 1);
+ usb_enable_usb2_hardware_lpm(udev);
 
  if (udev->do_remote_wakeup)
  (void) usb_disable_remote_wakeup(udev);
@@ -3486,7 +3486,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
  } else  {
  /* Try to enable USB2 hardware LPM */
  if (udev->usb2_hw_lpm_capable == 1)
- usb_set_usb2_hardware_lpm(udev, 1);
+ usb_enable_usb2_hardware_lpm(udev);
 
  /* Try to enable USB3 LTM */
  usb_enable_ltm(udev);
@@ -4335,7 +4335,7 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
  if ((udev->bos->ext_cap->bmAttributes & cpu_to_le32(USB_BESL_SUPPORT)) ||
  connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
  udev->usb2_hw_lpm_allowed = 1;
- usb_set_usb2_hardware_lpm(udev, 1);
+ usb_enable_usb2_hardware_lpm(udev);
  }
 }
 
@@ -5493,7 +5493,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
  * It will be re-enabled by the enumeration process.
  */
  if (udev->usb2_hw_lpm_enabled == 1)
- usb_set_usb2_hardware_lpm(udev, 0);
+ usb_disable_usb2_hardware_lpm(udev);
 
  /* Disable LPM while we reset the device and reinstall the alt settings.
  * Device-initiated LPM, and system exit latency settings are cleared
@@ -5596,7 +5596,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
 
 done:
  /* Now that the alt settings are re-installed, enable LTM and LPM. */
- usb_set_usb2_hardware_lpm(udev, 1);
+ usb_enable_usb2_hardware_lpm(udev);
  usb_unlocked_enable_lpm(udev);
  usb_enable_ltm(udev);
  usb_release_bos_descriptor(udev);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index a4025760dd84..576a3bd72f85 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1218,7 +1218,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
  }
 
  if (dev->usb2_hw_lpm_enabled == 1)
- usb_set_usb2_hardware_lpm(dev, 0);
+ usb_disable_usb2_hardware_lpm(dev);
  usb_unlocked_disable_lpm(dev);
  usb_disable_ltm(dev);
 
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 27bb34043053..91a2e79cabda 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -508,7 +508,10 @@ static ssize_t usb2_hardware_lpm_store(struct device *dev,
 
  if (!ret) {
  udev->usb2_hw_lpm_allowed = value;
- ret = usb_set_usb2_hardware_lpm(udev, value);
+ if (value)
+ ret = usb_enable_usb2_hardware_lpm(udev);
+ else
+ ret = usb_disable_usb2_hardware_lpm(udev);
  }
 
  usb_unlock_device(udev);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index bb95f98fe48c..2b8012339908 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -91,7 +91,8 @@ extern int usb_remote_wakeup(struct usb_device *dev);
 extern int usb_runtime_suspend(struct device *dev);
 extern int usb_runtime_resume(struct device *dev);
 extern int usb_runtime_idle(struct device *dev);
-extern int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable);
+extern int usb_enable_usb2_hardware_lpm(struct usb_device *udev);
+extern int usb_disable_usb2_hardware_lpm(struct usb_device *udev);
 
 #else
 
@@ -111,7 +112,12 @@ static inline int usb_autoresume_device(struct usb_device *udev)
  return 0;
 }
 
-static inline int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
+static inline int usb_enable_usb2_hardware_lpm(struct usb_device *udev)
+{
+ return 0;
+}
+
+static inline int usb_disable_usb2_hardware_lpm(struct usb_device *udev)
 {
  return 0;
 }
--
2.17.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[C/D/Unstable] [PATCH 2/2] USB: Consolidate LPM checks to avoid enabling LPM twice

Kai-Heng Feng
In reply to this post by Kai-Heng Feng
BugLink: https://bugs.launchpad.net/bugs/1812812

USB Bluetooth controller QCA ROME (0cf3:e007) sometimes stops working
after S3:
[ 165.110742] Bluetooth: hci0: using NVM file: qca/nvm_usb_00000302.bin
[ 168.432065] Bluetooth: hci0: Failed to send body at 4 of 1953 (-110)

After some experiments, I found that disabling LPM can workaround the
issue.

On some platforms, the USB power is cut during S3, so the driver uses
reset-resume to resume the device. During port resume, LPM gets enabled
twice, by usb_reset_and_verify_device() and usb_port_resume().

Consolidate all checks into new LPM helpers to make sure LPM only gets
enabled once.

Fixes: de68bab4fa96 ("usb: Don't enable USB 2.0 Link PM by default.”)
Signed-off-by: Kai-Heng Feng <[hidden email]>
Cc: stable <[hidden email]> # after much soaking
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
(cherry picked from commit d7a6c0ce8d26412903c7981503bad9e1cc7c45d2 linux-next)
Signed-off-by: Kai-Heng Feng <[hidden email]>
---
 drivers/usb/core/driver.c  | 11 ++++++++---
 drivers/usb/core/hub.c     | 12 ++++--------
 drivers/usb/core/message.c |  3 +--
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index c276ffc5561f..8987cec9549d 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1901,9 +1901,6 @@ static int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
  struct usb_hcd *hcd = bus_to_hcd(udev->bus);
  int ret = -EPERM;
 
- if (enable && !udev->usb2_hw_lpm_allowed)
- return 0;
-
  if (hcd->driver->set_usb2_hw_lpm) {
  ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, enable);
  if (!ret)
@@ -1915,11 +1912,19 @@ static int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
 
 int usb_enable_usb2_hardware_lpm(struct usb_device *udev)
 {
+ if (!udev->usb2_hw_lpm_capable ||
+    !udev->usb2_hw_lpm_allowed ||
+    udev->usb2_hw_lpm_enabled)
+ return 0;
+
  return usb_set_usb2_hardware_lpm(udev, 1);
 }
 
 int usb_disable_usb2_hardware_lpm(struct usb_device *udev)
 {
+ if (!udev->usb2_hw_lpm_enabled)
+ return 0;
+
  return usb_set_usb2_hardware_lpm(udev, 0);
 }
 
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index ca38ff8124a7..55c87be5764c 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3220,8 +3220,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
  }
 
  /* disable USB2 hardware LPM */
- if (udev->usb2_hw_lpm_enabled == 1)
- usb_disable_usb2_hardware_lpm(udev);
+ usb_disable_usb2_hardware_lpm(udev);
 
  if (usb_disable_ltm(udev)) {
  dev_err(&udev->dev, "Failed to disable LTM before suspend\n");
@@ -3259,8 +3258,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
  usb_enable_ltm(udev);
  err_ltm:
  /* Try to enable USB2 hardware LPM again */
- if (udev->usb2_hw_lpm_capable == 1)
- usb_enable_usb2_hardware_lpm(udev);
+ usb_enable_usb2_hardware_lpm(udev);
 
  if (udev->do_remote_wakeup)
  (void) usb_disable_remote_wakeup(udev);
@@ -3543,8 +3541,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
  hub_port_logical_disconnect(hub, port1);
  } else  {
  /* Try to enable USB2 hardware LPM */
- if (udev->usb2_hw_lpm_capable == 1)
- usb_enable_usb2_hardware_lpm(udev);
+ usb_enable_usb2_hardware_lpm(udev);
 
  /* Try to enable USB3 LTM */
  usb_enable_ltm(udev);
@@ -5649,8 +5646,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
  /* Disable USB2 hardware LPM.
  * It will be re-enabled by the enumeration process.
  */
- if (udev->usb2_hw_lpm_enabled == 1)
- usb_disable_usb2_hardware_lpm(udev);
+ usb_disable_usb2_hardware_lpm(udev);
 
  /* Disable LPM while we reset the device and reinstall the alt settings.
  * Device-initiated LPM, and system exit latency settings are cleared
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 35951aea7f50..4f33eb632a88 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1243,8 +1243,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
  dev->actconfig->interface[i] = NULL;
  }
 
- if (dev->usb2_hw_lpm_enabled == 1)
- usb_disable_usb2_hardware_lpm(dev);
+ usb_disable_usb2_hardware_lpm(dev);
  usb_unlocked_disable_lpm(dev);
  usb_disable_ltm(dev);
 
--
2.17.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[B] [PATCH 2/2] USB: Consolidate LPM checks to avoid enabling LPM twice

Kai-Heng Feng
In reply to this post by Kai-Heng Feng
BugLink: https://bugs.launchpad.net/bugs/1812812

USB Bluetooth controller QCA ROME (0cf3:e007) sometimes stops working
after S3:
[ 165.110742] Bluetooth: hci0: using NVM file: qca/nvm_usb_00000302.bin
[ 168.432065] Bluetooth: hci0: Failed to send body at 4 of 1953 (-110)

After some experiments, I found that disabling LPM can workaround the
issue.

On some platforms, the USB power is cut during S3, so the driver uses
reset-resume to resume the device. During port resume, LPM gets enabled
twice, by usb_reset_and_verify_device() and usb_port_resume().

Consolidate all checks into new LPM helpers to make sure LPM only gets
enabled once.

Fixes: de68bab4fa96 ("usb: Don't enable USB 2.0 Link PM by default.”)
Signed-off-by: Kai-Heng Feng <[hidden email]>
Cc: stable <[hidden email]> # after much soaking
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
(backported from commit d7a6c0ce8d26412903c7981503bad9e1cc7c45d2 linux-next)
Signed-off-by: Kai-Heng Feng <[hidden email]>
---
 drivers/usb/core/driver.c  | 11 ++++++++---
 drivers/usb/core/hub.c     | 12 ++++--------
 drivers/usb/core/message.c |  3 +--
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index f3ba386a2acd..e05f97eb4164 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1904,9 +1904,6 @@ static int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
  struct usb_hcd *hcd = bus_to_hcd(udev->bus);
  int ret = -EPERM;
 
- if (enable && !udev->usb2_hw_lpm_allowed)
- return 0;
-
  if (hcd->driver->set_usb2_hw_lpm) {
  ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, enable);
  if (!ret)
@@ -1918,11 +1915,19 @@ static int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
 
 int usb_enable_usb2_hardware_lpm(struct usb_device *udev)
 {
+ if (!udev->usb2_hw_lpm_capable ||
+    !udev->usb2_hw_lpm_allowed ||
+    udev->usb2_hw_lpm_enabled)
+ return 0;
+
  return usb_set_usb2_hardware_lpm(udev, 1);
 }
 
 int usb_disable_usb2_hardware_lpm(struct usb_device *udev)
 {
+ if (!udev->usb2_hw_lpm_enabled)
+ return 0;
+
  return usb_set_usb2_hardware_lpm(udev, 0);
 }
 
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index f929f4b5fd75..b8a583616e9c 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3166,8 +3166,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
  }
 
  /* disable USB2 hardware LPM */
- if (udev->usb2_hw_lpm_enabled == 1)
- usb_disable_usb2_hardware_lpm(udev);
+ usb_disable_usb2_hardware_lpm(udev);
 
  if (usb_disable_ltm(udev)) {
  dev_err(&udev->dev, "Failed to disable LTM before suspend\n.");
@@ -3205,8 +3204,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
  usb_enable_ltm(udev);
  err_ltm:
  /* Try to enable USB2 hardware LPM again */
- if (udev->usb2_hw_lpm_capable == 1)
- usb_enable_usb2_hardware_lpm(udev);
+ usb_enable_usb2_hardware_lpm(udev);
 
  if (udev->do_remote_wakeup)
  (void) usb_disable_remote_wakeup(udev);
@@ -3485,8 +3483,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
  hub_port_logical_disconnect(hub, port1);
  } else  {
  /* Try to enable USB2 hardware LPM */
- if (udev->usb2_hw_lpm_capable == 1)
- usb_enable_usb2_hardware_lpm(udev);
+ usb_enable_usb2_hardware_lpm(udev);
 
  /* Try to enable USB3 LTM */
  usb_enable_ltm(udev);
@@ -5492,8 +5489,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
  /* Disable USB2 hardware LPM.
  * It will be re-enabled by the enumeration process.
  */
- if (udev->usb2_hw_lpm_enabled == 1)
- usb_disable_usb2_hardware_lpm(udev);
+ usb_disable_usb2_hardware_lpm(udev);
 
  /* Disable LPM while we reset the device and reinstall the alt settings.
  * Device-initiated LPM, and system exit latency settings are cleared
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 576a3bd72f85..cf1cc67dd6ef 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1217,8 +1217,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
  dev->actconfig->interface[i] = NULL;
  }
 
- if (dev->usb2_hw_lpm_enabled == 1)
- usb_disable_usb2_hardware_lpm(dev);
+ usb_disable_usb2_hardware_lpm(dev);
  usb_unlocked_disable_lpm(dev);
  usb_disable_ltm(dev);
 
--
2.17.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK / APPLIED[D/Unstable]: [SRU] [B/C/D/Unstable] [PATCH 0/2] Fix non-working QCA Rome Bluetooth after S3

Seth Forshee
In reply to this post by Kai-Heng Feng
On Tue, Jan 22, 2019 at 04:07:25PM +0800, Kai-Heng Feng wrote:

> BugLink: https://bugs.launchpad.net/bugs/1812812
>
> [Impact]
> Sometimes QCA Rome Bluetooth USB host doesn't work after S3:
> [ 165.110742] Bluetooth: hci0: using NVM file: qca/nvm_usb_00000302.bin
> [ 168.432065] Bluetooth: hci0: Failed to send body at 4 of 1953 (-110)
>
> This is due to USB core enables LPM two times after S3.
>
> [Fix]
> Only enable LPM once.
>
> [Test]
> The Bluetooth USB works all the time after applying the fix.
>
> [Regression Potential]
> Low. Enabling a hardware feature twice in a row isn't right, I'd be
> surprise if any hardware relies on this driver behavior.

Cherry picks from linux-next, seems reasonable and has positive testing.

Acked-by: Seth Forshee <[hidden email]>

Applied to disco/master-next and unstable/master, thanks!

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK: [SRU] [B/C/D/Unstable] [PATCH 0/2] Fix non-working QCA Rome Bluetooth after S3

Stefan Bader-2
In reply to this post by Kai-Heng Feng
On 22.01.19 09:07, Kai-Heng Feng wrote:

> BugLink: https://bugs.launchpad.net/bugs/1812812
>
> [Impact]
> Sometimes QCA Rome Bluetooth USB host doesn't work after S3:
> [ 165.110742] Bluetooth: hci0: using NVM file: qca/nvm_usb_00000302.bin
> [ 168.432065] Bluetooth: hci0: Failed to send body at 4 of 1953 (-110)
>
> This is due to USB core enables LPM two times after S3.
>
> [Fix]
> Only enable LPM once.
>
> [Test]
> The Bluetooth USB works all the time after applying the fix.
>
> [Regression Potential]
> Low. Enabling a hardware feature twice in a row isn't right, I'd be
> surprise if any hardware relies on this driver behavior.
>
> Kai-Heng Feng (2):
>   USB: Add new USB LPM helpers
>   USB: Consolidate LPM checks to avoid enabling LPM twice
>
>  drivers/usb/core/driver.c  | 23 +++++++++++++++++++----
>  drivers/usb/core/hub.c     | 16 ++++++----------
>  drivers/usb/core/message.c |  3 +--
>  drivers/usb/core/sysfs.c   |  5 ++++-
>  drivers/usb/core/usb.h     | 10 ++++++++--
>  5 files changed, 38 insertions(+), 19 deletions(-)
>
Acked-by: Stefan Bader <[hidden email]>


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

APPLIED(B, C): [SRU] [B/C/D/Unstable] [PATCH 0/2] Fix non-working QCA Rome Bluetooth after S3

Khaled Elmously
In reply to this post by Kai-Heng Feng
On 2019-01-22 16:07:25 , Kai-Heng Feng wrote:

> BugLink: https://bugs.launchpad.net/bugs/1812812
>
> [Impact]
> Sometimes QCA Rome Bluetooth USB host doesn't work after S3:
> [ 165.110742] Bluetooth: hci0: using NVM file: qca/nvm_usb_00000302.bin
> [ 168.432065] Bluetooth: hci0: Failed to send body at 4 of 1953 (-110)
>
> This is due to USB core enables LPM two times after S3.
>
> [Fix]
> Only enable LPM once.
>
> [Test]
> The Bluetooth USB works all the time after applying the fix.
>
> [Regression Potential]
> Low. Enabling a hardware feature twice in a row isn't right, I'd be
> surprise if any hardware relies on this driver behavior.
>
> Kai-Heng Feng (2):
>   USB: Add new USB LPM helpers
>   USB: Consolidate LPM checks to avoid enabling LPM twice
>
>  drivers/usb/core/driver.c  | 23 +++++++++++++++++++----
>  drivers/usb/core/hub.c     | 16 ++++++----------
>  drivers/usb/core/message.c |  3 +--
>  drivers/usb/core/sysfs.c   |  5 ++++-
>  drivers/usb/core/usb.h     | 10 ++++++++--
>  5 files changed, 38 insertions(+), 19 deletions(-)
>
> --
> 2.17.1
>
>
> --
> kernel-team mailing list
> [hidden email]
> https://lists.ubuntu.com/mailman/listinfo/kernel-team

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team