On Tue, 30 Oct 2018, Mathias Nyman wrote: > On 30.10.2018 07:54, Kai-Heng Feng wrote: > > 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(). > > > > So let's enable LPM for just once, as this solves the issue for the > > device in question. > > > > Signed-off-by: Kai-Heng Feng <kai.heng.feng@xxxxxxxxxxxxx> > > --- > > drivers/usb/core/driver.c | 3 ++- > > 1 file changed, 2 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c > > index 53564386ed57..e11d2eac76b6 100644 > > --- a/drivers/usb/core/driver.c > > +++ b/drivers/usb/core/driver.c > > @@ -1901,7 +1901,8 @@ 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) > > + if (enable && !udev->usb2_hw_lpm_allowed || > > + udev->usb2_hw_lpm_enabled == enable) > > return 0; > > > > if (hcd->driver->set_usb2_hw_lpm) { > > > > Something like that would probably work. > > Would it make sense to skip USB2 hw LPM enabling in usb_port_resume() if > port was just reset (and thus LPM enabled)? > > something like this: > > --- a/drivers/usb/core/hub.c > +++ b/drivers/usb/core/hub.c > @@ -3520,7 +3520,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) > + if (udev->usb2_hw_lpm_capable == 1 && !udev->reset_resume) > usb_set_usb2_hardware_lpm(udev, 1); > > /* Try to enable USB3 LTM */ Why not simply test whether udev->usb2_hw_lpm_enabled is already true? if (udev->usb2_hw_lpm_capable == 1 && !udev->usb2_hw_lpm_enabled) Or even put this extra test into usb_set_usb2_hardware_lpm(). Alan Stern