Hardware & Environment
- Model: Apple MacBook Pro (14-inch, M2 Pro, 2023) (
Mac14,9)
- Device Tree Compatible:
apple,j414s, apple,t6020, apple,arm-platform
- OS / Distribution: Arch Linux ARM / Omarchy (Kernel:
Linux 7.1.6-1-1-ARCH aarch64)
- Bluetooth Device:
01:00.1 Network controller [0280]: Broadcom Inc. and subsidiaries BCM4388 Bluetooth Controller [14e4:5f72] (rev 04)
- Subsystem:
Apple Inc. Device [106b:4388]
- Device Tree Node:
/sys/firmware/devicetree/base/soc/pcie@580000000/pci@0,0/bluetooth@0,1
- Driver:
hci_bcm4377
- BlueZ Version:
5.87-2
Description
When rfkill block bluetooth is triggered while the Bluetooth adapter is actively scanning (e.g., active LE discovery in a desktop environment) or exchanging traffic, hci_rfkill_set_block() calls hci_dev_do_poweroff(). The BCM4388 controller fails to respond to poweroff opcodes, resulting in an HCI tx timeout (-ETIMEDOUT / -110).
The kernel then attempts fallback device teardown via hci_dev_do_close(), where bcm4377_hci_close() attempts to destroy all 10 PCIe transfer and completion rings. Because the controller firmware is locked up, every ring destruction request times out (1s each, stalling the workqueue for ~10 seconds).
Crucially, unlike runtime command timeouts (e.g. as reported in #604 where the subsystem's cmd_timer initiates an automatic hci_bcm4377: resetting... reset done), in this rfkill teardown path NO automatic driver reset is ever triggered.
The device is left marked down in userland, but the underlying PCIe hardware / DMA engine remains in an unrecoverable dirty state. Subsequent calls to rfkill unblock bluetooth and bluetoothctl power on (hci_dev_open()) fail with Failed to set mode: Failed (0x03) / org.bluez.Error.Failed.
The only recovery without a full system reboot is manually unbinding and rebinding the PCIe driver via sysfs (echo 0000:01:00.1 > /sys/bus/pci/drivers/hci_bcm4377/unbind && echo 0000:01:00.1 > .../bind), which forces a clean hardware reset (hci_bcm4377: resetting... reset done).
(Note: This is distinct from #604: this occurs on BCM4388 [14e4:5f72] / M2 Pro, does not involve any WiFi brcmfmac errors or A2DP streaming crashes, is triggered directly by rfkill during LE scan, and does not automatically recover via driver reset).
Steps to Reproduce
- Ensure Bluetooth is powered on and actively discovering (e.g.
bluetoothctl scan on, or opening a desktop environment status panel like GNOME/Omarchy Bluetooth panel).
- Soft-block Bluetooth via
rfkill block bluetooth directly (without executing bluetoothctl power off first).
- Observe
dmesg: HCI poweroff opcodes time out with -110, followed by 10 consecutive ring destruction timeouts taking ~10 seconds.
- Execute
rfkill unblock bluetooth.
- Attempt to power the adapter back on:
bluetoothctl power on.
- Result:
bluetoothctl fails with Failed to set power on: org.bluez.Error.Failed and bluetoothd logs Failed to set mode: Failed (0x03).
Kernel Log (journalctl -k / dmesg)
Bluetooth: hci0: command 0x0c01 tx timeout
Bluetooth: hci0: Opcode 0x2005 failed: -110
Bluetooth: hci0: Opcode 0x2041 failed: -110
Bluetooth: hci0: command 0x0c01 tx timeout
Bluetooth: hci0: Opcode 0x2039 failed: -110
Bluetooth: hci0: Error when powering off device on rfkill (-110)
hci_bcm4377 0000:01:00.1: failed to destroy transfer ring 6
hci_bcm4377 0000:01:00.1: failed to destroy transfer ring 5
hci_bcm4377 0000:01:00.1: failed to destroy transfer ring 4
hci_bcm4377 0000:01:00.1: failed to destroy transfer ring 3
hci_bcm4377 0000:01:00.1: failed to destroy transfer ring 2
hci_bcm4377 0000:01:00.1: failed to destroy transfer ring 1
hci_bcm4377 0000:01:00.1: failed to destroy completion ring 4
hci_bcm4377 0000:01:00.1: failed to destroy completion ring 3
hci_bcm4377 0000:01:00.1: failed to destroy completion ring 2
hci_bcm4377 0000:01:00.1: failed to destroy completion ring 1
Subsequent bluetoothctl power on:
bluetoothd[961]: Failed to set mode: Failed (0x03)
Manual recovery via sysfs unbind/bind:
hci_bcm4377 0000:01:00.1: resetting
hci_bcm4377 0000:01:00.1: reset done
Bluetooth: MGMT ver 1.23
Analysis of drivers/bluetooth/hci_bcm4377.c
hci_rfkill_set_block() calls hci_dev_do_poweroff(hdev), which fails due to opcode timeouts and returns -ETIMEDOUT.
hci_rfkill_set_block() catches the error, logs "Error when powering off device on rfkill (-110)", and falls back to hci_dev_do_close(hdev).
- In
hci_bcm4377.c, bcm4377_hci_close() loops through:
bcm4377_destroy_transfer_ring() for 6 transfer rings
bcm4377_destroy_completion_ring() for 4 completion rings
- Each call uses
wait_for_completion_interruptible_timeout(&event, BCM4377_TIMEOUT) (1 second). When the chip is locked up, every call times out.
- Because this teardown occurred inside the intentional
close path, the kernel core marks the device closed and does NOT trigger an automatic PCIe device reset.
- When
bcm4377_hci_open() is called later, it attempts to recreate rings and talk to a chip whose firmware/DMA engine is still hung from the uncompleted poweroff.
Suggested Driver Improvements
- Trigger PCIe Reset on Dirty Close / Re-Open:
If bcm4377_hci_close() fails to cleanly destroy any transfer or completion rings, flag the device instance (e.g. bcm4377->needs_reset = true). In bcm4377_hci_open(), if needs_reset is set, perform a full chip reset (similar to probe / bcm4377_pci_reset) before attempting to initialize rings.
- Fast-Fail on Ring Destruction:
If the control ring fails to acknowledge the first BCM4377_CONTROL_MSG_DESTROY_XFER_RING with a timeout, subsequent ring destroy operations are guaranteed to fail as well. Fast-failing the remaining rings instead of waiting 1 second per ring would prevent blocking kernel workqueues for 10 seconds.
Hardware & Environment
Mac14,9)apple,j414s,apple,t6020,apple,arm-platformLinux 7.1.6-1-1-ARCH aarch64)01:00.1 Network controller [0280]: Broadcom Inc. and subsidiaries BCM4388 Bluetooth Controller [14e4:5f72] (rev 04)Apple Inc. Device [106b:4388]/sys/firmware/devicetree/base/soc/pcie@580000000/pci@0,0/bluetooth@0,1hci_bcm43775.87-2Description
When
rfkill block bluetoothis triggered while the Bluetooth adapter is actively scanning (e.g., active LE discovery in a desktop environment) or exchanging traffic,hci_rfkill_set_block()callshci_dev_do_poweroff(). The BCM4388 controller fails to respond to poweroff opcodes, resulting in an HCI tx timeout (-ETIMEDOUT/-110).The kernel then attempts fallback device teardown via
hci_dev_do_close(), wherebcm4377_hci_close()attempts to destroy all 10 PCIe transfer and completion rings. Because the controller firmware is locked up, every ring destruction request times out (1s each, stalling the workqueue for ~10 seconds).Crucially, unlike runtime command timeouts (e.g. as reported in #604 where the subsystem's cmd_timer initiates an automatic
hci_bcm4377: resetting... reset done), in this rfkill teardown path NO automatic driver reset is ever triggered.The device is left marked down in userland, but the underlying PCIe hardware / DMA engine remains in an unrecoverable dirty state. Subsequent calls to
rfkill unblock bluetoothandbluetoothctl power on(hci_dev_open()) fail withFailed to set mode: Failed (0x03)/org.bluez.Error.Failed.The only recovery without a full system reboot is manually unbinding and rebinding the PCIe driver via sysfs (
echo 0000:01:00.1 > /sys/bus/pci/drivers/hci_bcm4377/unbind && echo 0000:01:00.1 > .../bind), which forces a clean hardware reset (hci_bcm4377: resetting... reset done).(Note: This is distinct from #604: this occurs on BCM4388 [14e4:5f72] / M2 Pro, does not involve any WiFi
brcmfmacerrors or A2DP streaming crashes, is triggered directly by rfkill during LE scan, and does not automatically recover via driver reset).Steps to Reproduce
bluetoothctl scan on, or opening a desktop environment status panel like GNOME/Omarchy Bluetooth panel).rfkill block bluetoothdirectly (without executingbluetoothctl power offfirst).dmesg: HCI poweroff opcodes time out with-110, followed by 10 consecutive ring destruction timeouts taking ~10 seconds.rfkill unblock bluetooth.bluetoothctl power on.bluetoothctlfails withFailed to set power on: org.bluez.Error.FailedandbluetoothdlogsFailed to set mode: Failed (0x03).Kernel Log (
journalctl -k/dmesg)Subsequent
bluetoothctl power on:Manual recovery via sysfs unbind/bind:
Analysis of
drivers/bluetooth/hci_bcm4377.chci_rfkill_set_block()callshci_dev_do_poweroff(hdev), which fails due to opcode timeouts and returns-ETIMEDOUT.hci_rfkill_set_block()catches the error, logs"Error when powering off device on rfkill (-110)", and falls back tohci_dev_do_close(hdev).hci_bcm4377.c,bcm4377_hci_close()loops through:bcm4377_destroy_transfer_ring()for 6 transfer ringsbcm4377_destroy_completion_ring()for 4 completion ringswait_for_completion_interruptible_timeout(&event, BCM4377_TIMEOUT)(1 second). When the chip is locked up, every call times out.closepath, the kernel core marks the device closed and does NOT trigger an automatic PCIe device reset.bcm4377_hci_open()is called later, it attempts to recreate rings and talk to a chip whose firmware/DMA engine is still hung from the uncompleted poweroff.Suggested Driver Improvements
If
bcm4377_hci_close()fails to cleanly destroy any transfer or completion rings, flag the device instance (e.g.bcm4377->needs_reset = true). Inbcm4377_hci_open(), ifneeds_resetis set, perform a full chip reset (similar to probe /bcm4377_pci_reset) before attempting to initialize rings.If the control ring fails to acknowledge the first
BCM4377_CONTROL_MSG_DESTROY_XFER_RINGwith a timeout, subsequent ring destroy operations are guaranteed to fail as well. Fast-failing the remaining rings instead of waiting 1 second per ring would prevent blocking kernel workqueues for 10 seconds.