Bluetooth: restore powered-off Intel adapters
Subsystems (2)
v2 cover Bluetooth: restore powered-off Intel adapters
ACPI-managed internal USB ports can lose power while the Bluetooth adapter is closed. Intel controllers then lose their RAM firmware, and btusb's lack of a reset-resume callback causes the interfaces to rebind.
Preserve the binding only for a closed, fixed Intel combined adapter on an ACPI-power-manageable port, then rerun Intel setup when the adapter is next opened. Other adapters, and resets while HCI is running, retain the existing rebind behavior.
The first patch fixes detection of ACPI port power management while USB ports are being registered. The second adds the restricted btusb reset-resume path.
Tested on a Star Labs Lite Mk IV with Intel 8087:0aaa. Three Bluetooth off/on cycles reached ACPI D3cold, restored the same hci0 without a USB disconnect, and discovery found nearby devices after resume. With Bluetooth powered off before S3, the controller also reset in place and powered on successfully after resume.
Changes since v1:
- replace the open-adapter remote-wake policy with closed-adapter recovery;
- split the USB registration fix from the Bluetooth change;
- restrict recovery to fixed Intel combined adapters on ACPI-managed ports;
- add runtime testing covering D3cold, discovery and powered-off S3.
Sean Rhodes (2):
usb: core: check ACPI port power during registration
Bluetooth: btusb: restore powered-off Intel adapters
drivers/bluetooth/btusb_main.c | 33 +++++++++++++++++++++++++++++++++ drivers/usb/core/port.c | 7 +++---- drivers/usb/core/usb-acpi.c | 7 +++++++ drivers/usb/core/usb.h | 6 ++++++ 4 files changed, 49 insertions(+), 4 deletions(-)
PATCH v2 1/2 usb: core: check ACPI port power during registration
usb_hub_create_port_device() checks whether a port is power manageable before hdev->maxchild is set. usb_acpi_power_manageable() looks up the hub through usb_hub_to_struct_hub(), which rejects hubs while maxchild is zero.
The port device has already been registered and its ACPI companion bound at this point. Check that companion directly.
--- drivers/usb/core/port.c | 7 +++---- drivers/usb/core/usb-acpi.c | 7 +++++++ drivers/usb/core/usb.h | 6 ++++++ 3 files changed, 16 insertions(+), 4 deletions(-)
drivers/usb/core/port.c +3 -4
@@ -21,8 +21,7 @@ static int usb_port_block_power_off;static const struct attribute_group *port_dev_group[]; -static bool usb_port_allow_power_off (struct usb_device *hdev, -struct usb_hub *hub, +static bool usb_port_allow_power_off (struct usb_hub *hub,struct usb_port *port_dev) {if (hub_is_port_power_switchable (hub))
@@ -32,7 +31,7 @@ static bool usb_port_allow_power_off(struct usb_device *hdev,return false;return port_dev->connect_type ==USB_PORT_CONNECT_TYPE_HARD_WIRED && -usb_acpi_power_manageable (hdev, port_dev->portnum -1 ); +usb_acpi_port_power_manageable (port_dev); } static ssize_t early_stop_show(struct device *dev,
@@ -825,7 +824,7 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)* Keep hidden the ability to enable port-poweroff if neither the * USB hub nor platform firmware can manage downstream port power. */ -if (!usb_port_allow_power_off (hdev, hub, port_dev)) +if (!usb_port_allow_power_off (hub, port_dev))return 0 ;/* Attempt to let userspace take over the policy. */
drivers/usb/core/usb-acpi.c +7 -0
@@ -37,6 +37,13 @@ bool usb_acpi_power_manageable(struct usb_device *hdev, int index) }EXPORT_SYMBOL_GPL (usb_acpi_power_manageable); +bool usb_acpi_port_power_manageable (struct usb_port *port_dev) +{ +struct acpi_device *adev =ACPI_COMPANION (&port_dev->dev); + +return adev &&acpi_device_power_manageable (adev); +} +#define UUID_USB_CONTROLLER_DSM "ce2ee385-00e6-48cb-9f05-2edb927c4899"#define USB_DSM_DISABLE_U1_U2_FOR_PORT 5
drivers/usb/core/usb.h +6 -0
@@ -8,6 +8,7 @@struct usb_hub_descriptor ;struct usb_dev_state ; +struct usb_port ;/* Functions local to drivers/usb/core/ */
@@ -211,7 +212,12 @@ extern int usb_acpi_register(void);extern void usb_acpi_unregister (void );extern acpi_handle usb_get_hub_port_acpi_handle (struct usb_device *hdev,int port1); +bool usb_acpi_port_power_manageable (struct usb_port *port_dev);#else static inline int usb_acpi_register (void ) {return 0 ; };static inline void usb_acpi_unregister (void ) { }; +static inline bool usb_acpi_port_power_manageable (struct usb_port *port_dev) +{ +return false; +}#endif
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1168087/
---Test result---
Test Summary:
CheckPatch PASS 1.57 seconds VerifyFixes PASS 0.06 seconds VerifySignedoff PASS 0.06 seconds GitLint PASS 0.41 seconds SubjectPrefix FAIL 0.11 seconds BuildKernel PASS 29.99 seconds CheckAllWarning PASS 34.08 seconds CheckSparse PASS 36.76 seconds BuildKernel32 PASS 29.98 seconds CheckKernelLLVM PASS 36.07 seconds TestRunnerSetup PASS 825.96 seconds TestRunner_l2cap-tester PASS 16.70 seconds TestRunner_iso-tester PASS 28.99 seconds TestRunner_bnep-tester PASS 9.09 seconds TestRunner_mgmt-tester FAIL 61.44 seconds TestRunner_rfcomm-tester PASS 4.44 seconds TestRunner_sco-tester PASS 7.58 seconds TestRunner_ioctl-tester PASS 4.58 seconds TestRunner_mesh-tester FAIL 7.77 seconds TestRunner_smp-tester PASS 4.29 seconds TestRunner_userchan-tester PASS 3.13 seconds TestRunner_6lowpan-tester PASS 4.36 seconds IncrementalBuild PASS 30.50 seconds
Details
##############################
Test: SubjectPrefix - FAIL
Desc: Check subject contains "Bluetooth" prefix Output:
"Bluetooth: " prefix is not specified in the subject
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner Output:
Total: 501, Passed: 496 (99.0%), Failed: 1, Not Run: 4
Failed Test Cases
Read Exp Feature - Success Failed 0.022 seconds
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0
Failed Test Cases
Mesh - Send cancel - 1 Timed out 2.391 seconds Mesh - Send cancel - 2 Timed out 1.998 seconds
https://github.com/bluez/bluetooth-next/pull/785
---
Regards,
Linux Bluetooth
PATCH v2 2/2 Bluetooth: btusb: restore powered-off Intel adapters
In reply to Sean RhodesACPI-managed internal USB ports can lose power while the Bluetooth adapter is closed. The USB core then reset-resumes the device and, because btusb has no reset-resume callback, rebinds its interfaces.
For a closed, fixed Intel combined adapter on an ACPI-power-manageable port, preserve the binding and run the Intel setup again when the adapter is next opened. Keep the existing rebind behavior while HCI is running and keep runtime autosuspend blocked for other reset-resume-quirked adapters.
Tested on a Star Labs Lite Mk IV with Intel 8087:0aaa. Three Bluetooth off/on cycles reached ACPI D3cold, restored the same hci0 without a USB disconnect, and discovery found nearby devices after resume.
--- drivers/bluetooth/btusb_main.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
drivers/bluetooth/btusb_main.c +33 -0
@@ -2190,6 +2190,16 @@ static void btusb_prepare_reset(struct hci_dev *hdev)usb_kill_anchored_urbs (&data->tx_anchor); } +static bool btusb_intel_acpi_power_manageable (struct btusb_data *data) +{ +return IS_ENABLED (CONFIG_ACPI ) && + data->match_id->driver_info &BTUSB_INTEL_COMBINED && + data->udev->dev.removable ==DEVICE_FIXED && + data->udev->parent && data->udev->portnum && +usb_acpi_power_manageable (data->udev->parent, + data->udev->portnum -1 ); +} +static int btusb_close (struct hci_dev *hdev) {struct btusb_data *data =hci_get_drvdata (hdev);
@@ -4595,6 +4605,9 @@ static int btusb_probe(struct usb_interface *intf, hdev->send = btusb_send_frame_intel; hdev->reset = btusb_intel_reset; +if (btusb_intel_acpi_power_manageable (data)) +hci_set_quirk (hdev,HCI_QUIRK_NON_PERSISTENT_SETUP ); +if (id->driver_info &BTUSB_INTEL_NO_WBS_SUPPORT )btintel_set_flag (hdev,INTEL_ROM_LEGACY_NO_WBS_SUPPORT );
@@ -4912,6 +4925,12 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)BT_DBG ("intf %p" , intf); +/* reset_resume is only safe for the Intel ACPI path below. */ +if (PMSG_IS_AUTO (message) && + (data->udev->quirks &USB_QUIRK_RESET_RESUME ) && + !btusb_intel_acpi_power_manageable (data)) +return -EBUSY ; +/* * It is reported that remote wakeup events could sometimes cause some * adapters completely unresponsive. Resetting the xHCI root hub doesn't
@@ -5076,6 +5095,19 @@ static int btusb_resume(struct usb_interface *intf)return err; } +static int btusb_reset_resume (struct usb_interface *intf) +{ +struct btusb_data *data =usb_get_intfdata (intf); + +if (!btusb_intel_acpi_power_manageable (data) || +test_bit (HCI_RUNNING , &data->hdev->flags)) { + intf->needs_binding =1 ; +return 0 ; + } + +return btusb_resume (intf); +} +#ifdef CONFIG_DEV_COREDUMP static void btusb_coredump (struct device *dev) {
@@ -5093,6 +5125,7 @@ static struct usb_driver btusb_driver = { .disconnect = btusb_disconnect, .suspend = pm_ptr(btusb_suspend), .resume = pm_ptr(btusb_resume), + .reset_resume = pm_ptr(btusb_reset_resume), .id_table = btusb_table, .supports_autosuspend = 1, .disable_hub_initiated_lpm = 1,
Re: [PATCH v2 2/2] Bluetooth: btusb: restore powered-off Intel adapters
On 17.09.26 23:19, Sean Rhodes wrote:
Hi,
Quoted 3 lines
Tested on a Star Labs Lite Mk IV with Intel 8087:0aaa. Three Bluetooth off/on cycles reached ACPI D3cold, restored the same hci0 without a USB disconnect, and discovery found nearby devices after resume.
Have you tested this with a different device and S4?
Quoted 5 lines
Signed-off-by Sean Rhodes <[email protected]>--- drivers/bluetooth/btusb_main.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
[..]
drivers/bluetooth/btusb_main.c static struct usb_driver btusb_driver = { · line 5128
Quoted 8 lines
#ifdef CONFIG_DEV_COREDUMP static void btusb_coredump(struct device *dev) {drivers/bluetooth/btusb_main.c +1
-0@@ -5093,6 +5125,7 @@ static struct usb_driver btusb_driver = { .disconnect = btusb_disconnect, .suspend = pm_ptr(btusb_suspend), .resume = pm_ptr(btusb_resume), + .reset_resume = pm_ptr(btusb_reset_resume),
What happens to a connection if a lot of data has been lost?
Regards
Oliver