From: zhangchen200426@163.com
To: luiz.von.dentz@intel.com, pav@iki.fi
Cc: linux-bluetooth@vger.kernel.org, Chen Zhang <zhangchen01@kylinos.cn>
Subject: [PATCH] Bluetooth: Reject controller operations while powering down
Date: Mon, 31 Aug 2026 16:43:29 +0800 [thread overview]
Message-ID: <20260831084329.3141802-1-zhangchen200426@163.com> (raw)
From: Chen Zhang <zhangchen01@kylinos.cn>
When an adapter is powered off with devices still connected (e.g. a
Bluetooth keyboard or mouse), the shutdown sequence issues an HCI reset
which returns Command Complete while the controller firmware is still
rebooting. A concurrent command sent through a raw socket during this
window (e.g. periodic hciconfig queries triggered by the Bluetooth
status change) can leave the firmware in a stuck state where it stops
answering any HCI command. The subsequent power on then fails with
'Bluetooth: hci0: Opcode 0x0c03 failed: -110' and the adapter is lost
until reboot or re-enumeration.
Reject controller operations while HCI_POWERING_DOWN is set at the
public entry points in hci_core.c, which covers the ioctl (HCIDEVUP,
HCIDEVDOWN, HCIDEVRESET) and raw socket bind paths:
- hci_dev_open(): return -EBUSY
- hci_dev_close(): return -EBUSY
- hci_dev_reset(): return -EBUSY
In addition reject raw command transmission from an already bound
socket during the power down sequence in hci_sock_sendmsg()
(-ENETDOWN), and fail early in hci_sock_bind() (-EBUSY) to avoid
toggling HCI_USER_CHANNEL while powering down.
Signed-off-by: Chen Zhang <zhangchen01@kylinos.cn>
---
net/bluetooth/hci_core.c | 28 ++++++++++++++++++++++++++++
net/bluetooth/hci_sock.c | 4 +++-
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index d1e78ae7728e..a0533f260471 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -445,6 +445,16 @@ int hci_dev_open(__u16 dev)
if (!hdev)
return -ENODEV;
+ /* Reject opening the controller while it is being powered down:
+ * the firmware is rebooting after the shutdown reset and any
+ * concurrent command sent during this window can leave it in a
+ * stuck state where it stops answering HCI commands.
+ */
+ if (hci_dev_test_flag(hdev, HCI_POWERING_DOWN)) {
+ err = -EBUSY;
+ goto done;
+ }
+
/* Devices that are marked as unconfigured can only be powered
* up as user channel. Trying to bring them up as normal devices
* will result into a failure. Only user channel operation is
@@ -515,6 +525,14 @@ int hci_dev_close(__u16 dev)
if (!hdev)
return -ENODEV;
+ /* Reject closing the controller while the power off sequence
+ * is already in progress (see hci_dev_open for details).
+ */
+ if (hci_dev_test_flag(hdev, HCI_POWERING_DOWN)) {
+ err = -EBUSY;
+ goto done;
+ }
+
if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
err = -EBUSY;
goto done;
@@ -556,6 +574,16 @@ int hci_dev_reset(__u16 dev)
if (!hdev)
return -ENODEV;
+ /* Reject resetting the controller while the power off sequence
+ * is in progress: the shutdown routine already issues its own
+ * HCI reset and a concurrent one would hit the firmware while
+ * it is rebooting (see hci_dev_open for details).
+ */
+ if (hci_dev_test_flag(hdev, HCI_POWERING_DOWN)) {
+ err = -EBUSY;
+ goto done;
+ }
+
if (!test_bit(HCI_UP, &hdev->flags)) {
err = -ENETDOWN;
goto done;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 070ca388f9ac..897596614939 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -1296,6 +1296,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr_unsized *addr,
if (test_bit(HCI_INIT, &hdev->flags) ||
hci_dev_test_flag(hdev, HCI_SETUP) ||
hci_dev_test_flag(hdev, HCI_CONFIG) ||
+ hci_dev_test_flag(hdev, HCI_POWERING_DOWN) ||
(!hci_dev_test_flag(hdev, HCI_AUTO_OFF) &&
test_bit(HCI_UP, &hdev->flags))) {
err = -EBUSY;
@@ -1850,7 +1851,8 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
goto drop;
}
- if (!test_bit(HCI_UP, &hdev->flags)) {
+ if (!test_bit(HCI_UP, &hdev->flags) ||
+ hci_dev_test_flag(hdev, HCI_POWERING_DOWN)) {
err = -ENETDOWN;
goto drop;
}
--
2.25.1
next reply other threads:[~2026-08-31 8:44 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-31 8:43 zhangchen200426 [this message]
2026-08-31 12:45 ` Bluetooth: Reject controller operations while powering down bluez.test.bot
2026-08-31 15:54 ` [PATCH] " Luiz Augusto von Dentz
2026-09-01 2:00 ` [PATCH v2] Bluetooth: hci_sock: Reject raw " zhangchen200426
2026-09-01 7:27 ` [v2] " bluez.test.bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260831084329.3141802-1-zhangchen200426@163.com \
--to=zhangchen200426@163.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=luiz.von.dentz@intel.com \
--cc=pav@iki.fi \
--cc=zhangchen01@kylinos.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox