* [PATCH 0/4] Bluetooth: qca: Fix WCN3950 power-off
@ 2026-10-28 22:34 Michael McAllister
2026-10-28 22:34 ` [PATCH 2/4] Bluetooth: hci_serdev: Track whether the serial port is open Michael McAllister
` (4 more replies)
0 siblings, 5 replies; 17+ messages in thread
From: Michael McAllister @ 2026-10-28 22:34 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, Bartosz Golaszewski,
linux-bluetooth
Cc: linux-arm-msm, linux-kernel, Balakrishna Godavarthi,
Dmitry Baryshkov, Matthias Kaehlcke, Michael McAllister
Hi,
Turning Bluetooth off on my Moto G10 leaves all four WCN3950 regulator
votes enabled. This series fixes the shared UART cleanup and shutdown
ordering first, then adds WCN3950 to the existing power-off paths.
Thanks,
Michael
Michael McAllister (4):
Bluetooth: qca: Restore flow control after a failed power pulse
Bluetooth: hci_serdev: Track whether the serial port is open
Bluetooth: qca: Power off after unregistering the HCI device
Bluetooth: qca: Power off WCN3950
drivers/bluetooth/hci_mrvl.c | 4 ++--
drivers/bluetooth/hci_qca.c | 38 ++++++++++------------------------
drivers/bluetooth/hci_serdev.c | 37 ++++++++++++++++++++++++++-------
drivers/bluetooth/hci_uart.h | 3 +++
4 files changed, 46 insertions(+), 36 deletions(-)
base-commit: 1081a6ef8f1e0661fd52eb3f878691b0b96cdff9
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 2/4] Bluetooth: hci_serdev: Track whether the serial port is open 2026-10-28 22:34 [PATCH 0/4] Bluetooth: qca: Fix WCN3950 power-off Michael McAllister @ 2026-10-28 22:34 ` Michael McAllister 2026-10-29 2:09 ` Bluetooth: qca: Fix WCN3950 power-off bluez.test.bot 2026-11-12 18:56 ` [PATCH 2/4] Bluetooth: hci_serdev: Track whether the serial port is open Markus Probst 2026-10-28 22:34 ` [PATCH 1/4] Bluetooth: qca: Restore flow control after a failed power pulse Michael McAllister ` (3 subsequent siblings) 4 siblings, 2 replies; 17+ messages in thread From: Michael McAllister @ 2026-10-28 22:34 UTC (permalink / raw) To: Marcel Holtmann, Luiz Augusto von Dentz, Bartosz Golaszewski, linux-bluetooth Cc: linux-arm-msm, linux-kernel, Balakrishna Godavarthi, Dmitry Baryshkov, Matthias Kaehlcke, Michael McAllister QCA setup temporarily closes the serial port while enabling the supplies. If enabling the supplies or reopening the port fails, PROTO_READY stays set. Error cleanup can then flush or close an already-closed port. Track the open state separately from protocol readiness. Use the same open and close helpers in the transport and the QCA and Marvell drivers, so setup retries do not close the port twice. Skip the serial flush when the port is closed, while still flushing the protocol queues. Close the port during unregister according to its actual open state. Signed-off-by: Michael McAllister <me@michaelmcallister.org> --- drivers/bluetooth/hci_mrvl.c | 4 ++-- drivers/bluetooth/hci_qca.c | 12 +++++------ drivers/bluetooth/hci_serdev.c | 37 +++++++++++++++++++++++++++------- drivers/bluetooth/hci_uart.h | 3 +++ 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/drivers/bluetooth/hci_mrvl.c b/drivers/bluetooth/hci_mrvl.c index 5798a8db0..38d9add89 100644 --- a/drivers/bluetooth/hci_mrvl.c +++ b/drivers/bluetooth/hci_mrvl.c @@ -76,7 +76,7 @@ static int mrvl_open(struct hci_uart *hu) hu->priv = mrvl; if (hu->serdev) { - ret = serdev_device_open(hu->serdev); + ret = hci_uart_serdev_open(hu); if (ret) goto err; } @@ -95,7 +95,7 @@ static int mrvl_close(struct hci_uart *hu) BT_DBG("hu %p", hu); if (hu->serdev) - serdev_device_close(hu->serdev); + hci_uart_serdev_close(hu); skb_queue_purge(&mrvl->txq); skb_queue_purge(&mrvl->rawq); diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 8705c4543..3d9e6cd15 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1755,8 +1755,8 @@ static int qca_port_reopen(struct hci_uart *hu) * Without this, we will have RTS and CTS synchronization * issues. */ - serdev_device_close(hu->serdev); - ret = serdev_device_open(hu->serdev); + hci_uart_serdev_close(hu); + ret = hci_uart_serdev_open(hu); if (ret) { bt_dev_err(hu->hdev, "failed to open port"); return ret; @@ -1780,12 +1780,12 @@ static int qca_regulator_init(struct hci_uart *hu) qcadev = serdev_device_get_drvdata(hu->serdev); if (!qcadev->bt_power->vregs_on) { - serdev_device_close(hu->serdev); + hci_uart_serdev_close(hu); ret = qca_regulator_enable(qcadev); if (ret) return ret; - ret = serdev_device_open(hu->serdev); + ret = hci_uart_serdev_open(hu); if (ret) { bt_dev_err(hu->hdev, "failed to open port"); return ret; @@ -2061,8 +2061,8 @@ static int qca_setup(struct hci_uart *hu) if (retries < MAX_INIT_RETRIES) { bt_dev_warn(hdev, "Retry BT power ON:%d", retries); if (hu->serdev) { - serdev_device_close(hu->serdev); - ret = serdev_device_open(hu->serdev); + hci_uart_serdev_close(hu); + ret = hci_uart_serdev_open(hu); if (ret) { bt_dev_err(hdev, "failed to open port"); return ret; diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 48ba017e2..05aa490a9 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -21,6 +21,29 @@ #include "hci_uart.h" +int hci_uart_serdev_open(struct hci_uart *hu) +{ + int err; + + if (hu->serdev_open) + return 0; + + err = serdev_device_open(hu->serdev); + if (!err) + hu->serdev_open = true; + + return err; +} + +void hci_uart_serdev_close(struct hci_uart *hu) +{ + if (!hu->serdev_open) + return; + + hu->serdev_open = false; + serdev_device_close(hu->serdev); +} + static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type) { struct hci_dev *hdev = hu->hdev; @@ -102,7 +125,8 @@ static int hci_uart_flush(struct hci_dev *hdev) } /* Flush any pending characters in the driver and discipline. */ - serdev_device_write_flush(hu->serdev); + if (hu->serdev_open) + serdev_device_write_flush(hu->serdev); if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) hu->proto->flush(hu); @@ -123,7 +147,7 @@ static int hci_uart_open(struct hci_dev *hdev) * BT OFF. Upon next BT ON UART port should be opened. */ if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) { - err = serdev_device_open(hu->serdev); + err = hci_uart_serdev_open(hu); if (err) return err; set_bit(HCI_UART_PROTO_READY, &hu->flags); @@ -154,7 +178,7 @@ static int hci_uart_close(struct hci_dev *hdev) */ if (hci_test_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP)) { clear_bit(HCI_UART_PROTO_READY, &hu->flags); - serdev_device_close(hu->serdev); + hci_uart_serdev_close(hu); } return 0; @@ -314,7 +338,7 @@ int hci_uart_register_device_priv(struct hci_uart *hu, if (percpu_init_rwsem(&hu->proto_lock)) return -ENOMEM; - err = serdev_device_open(hu->serdev); + err = hci_uart_serdev_open(hu); if (err) goto err_rwsem; @@ -385,7 +409,7 @@ int hci_uart_register_device_priv(struct hci_uart *hu, clear_bit(HCI_UART_PROTO_READY, &hu->flags); p->close(hu); err_open: - serdev_device_close(hu->serdev); + hci_uart_serdev_close(hu); err_rwsem: percpu_free_rwsem(&hu->proto_lock); return err; @@ -438,8 +462,7 @@ void hci_uart_unregister_device(struct hci_uart *hu) */ hu->proto->close(hu); - if (proto_ready) - serdev_device_close(hu->serdev); + hci_uart_serdev_close(hu); hci_free_dev(hdev); diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index 7fbe8dffa..2f8e346f3 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h @@ -66,6 +66,7 @@ struct hci_uart_proto { struct hci_uart { struct tty_struct *tty; struct serdev_device *serdev; + bool serdev_open; struct hci_dev *hdev; unsigned long flags; unsigned long hdev_flags; @@ -112,6 +113,8 @@ static inline int hci_uart_register_device(struct hci_uart *hu, } void hci_uart_unregister_device(struct hci_uart *hu); +int hci_uart_serdev_open(struct hci_uart *hu); +void hci_uart_serdev_close(struct hci_uart *hu); int hci_uart_tx_wakeup(struct hci_uart *hu); int hci_uart_wait_until_sent(struct hci_uart *hu); ^ permalink raw reply related [flat|nested] 17+ messages in thread
* RE: Bluetooth: qca: Fix WCN3950 power-off 2026-10-28 22:34 ` [PATCH 2/4] Bluetooth: hci_serdev: Track whether the serial port is open Michael McAllister @ 2026-10-29 2:09 ` bluez.test.bot 2026-11-12 18:56 ` [PATCH 2/4] Bluetooth: hci_serdev: Track whether the serial port is open Markus Probst 1 sibling, 0 replies; 17+ messages in thread From: bluez.test.bot @ 2026-10-29 2:09 UTC (permalink / raw) To: linux-bluetooth, me [-- Attachment #1: Type: text/plain, Size: 1302 bytes --] 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/1195776/ ---Test result--- Test Summary: CheckPatch PASS 3.03 seconds VerifyFixes PASS 0.07 seconds VerifySignedoff PASS 0.07 seconds GitLint PASS 0.93 seconds SubjectPrefix PASS 0.27 seconds BuildKernel PASS 32.82 seconds CheckAllWarning PASS 36.55 seconds CheckSparse WARNING 40.78 seconds BuildKernel32 PASS 35.33 seconds CheckKernelLLVM PASS 36.31 seconds TestRunnerSetup PASS 768.31 seconds IncrementalBuild PASS 37.75 seconds Details ############################## Test: CheckSparse - WARNING Desc: Run sparse tool with linux kernel Output: drivers/bluetooth/hci_mrvl.c:170:23: warning: restricted __le16 degrades to integerdrivers/bluetooth/hci_mrvl.c:203:23: warning: restricted __le16 degrades to integer https://github.com/bluez/bluetooth-next/pull/1018 --- Regards, Linux Bluetooth ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/4] Bluetooth: hci_serdev: Track whether the serial port is open 2026-10-28 22:34 ` [PATCH 2/4] Bluetooth: hci_serdev: Track whether the serial port is open Michael McAllister 2026-10-29 2:09 ` Bluetooth: qca: Fix WCN3950 power-off bluez.test.bot @ 2026-11-12 18:56 ` Markus Probst 2026-11-14 16:15 ` [PATCH 0/1] Bluetooth: hci_mrvl: Fix duplicate serdev open/close Michael McAllister 1 sibling, 1 reply; 17+ messages in thread From: Markus Probst @ 2026-11-12 18:56 UTC (permalink / raw) To: Michael McAllister, Marcel Holtmann, Luiz Augusto von Dentz, Bartosz Golaszewski, linux-bluetooth Cc: linux-arm-msm, linux-kernel, Balakrishna Godavarthi, Dmitry Baryshkov, Matthias Kaehlcke [-- Attachment #1: Type: text/plain, Size: 7741 bytes --] On Wed, 2026-10-28 at 22:34 +0000, Michael McAllister wrote: > QCA setup temporarily closes the serial port while enabling the supplies. > If enabling the supplies or reopening the port fails, PROTO_READY stays > set. Error cleanup can then flush or close an already-closed port. > > Track the open state separately from protocol readiness. Use the same > open and close helpers in the transport and the QCA and Marvell drivers, > so setup retries do not close the port twice. Skip the serial flush when > the port is closed, while still flushing the protocol queues. > > Close the port during unregister according to its actual open state. > > Signed-off-by: Michael McAllister <me@michaelmcallister.org> > --- > drivers/bluetooth/hci_mrvl.c | 4 ++-- > drivers/bluetooth/hci_qca.c | 12 +++++------ > drivers/bluetooth/hci_serdev.c | 37 +++++++++++++++++++++++++++------- > drivers/bluetooth/hci_uart.h | 3 +++ > 4 files changed, 41 insertions(+), 15 deletions(-) > > diff --git a/drivers/bluetooth/hci_mrvl.c b/drivers/bluetooth/hci_mrvl.c > index 5798a8db0..38d9add89 100644 > --- a/drivers/bluetooth/hci_mrvl.c > +++ b/drivers/bluetooth/hci_mrvl.c > @@ -76,7 +76,7 @@ static int mrvl_open(struct hci_uart *hu) > hu->priv = mrvl; > > if (hu->serdev) { > - ret = serdev_device_open(hu->serdev); > + ret = hci_uart_serdev_open(hu); Hi, Why is `serdev_device_open`/`hci_uart_serdev_open` even called here? According to Sashiko [1], `hci_uart_register_device` already calls `serdev_device_open` and directly after that `p->open` (effectively `mvrl_open` and thus another `serdev_device_open`). If Sashiko is right (which appears to be the case at first look), the device is always opened twice on probe. From what I can tell, opening it twice is *undefined behaviour*. This patch adds a check if the device is open, before calling `serdev_device_open`. This solves the issue (possibly by accident), but does not explain why it exists in the first place. My patch [2] would instead return the error -EALREADY, which could prevent it to probe entirely. It would also allow calling `serdev_device_close` on a already closed serdev device, which makes the use in the commit message obsolete. Thanks - Markus Probst [1] https://lore.kernel.org/linux-serial/sashiko-outbox-211656@kernel.org/ [2] https://lore.kernel.org/linux-serial/20261112-rust_serdev_probe_refactor-v6-1-3568ed56264c@posteo.de/ > if (ret) > goto err; > } > @@ -95,7 +95,7 @@ static int mrvl_close(struct hci_uart *hu) > BT_DBG("hu %p", hu); > > if (hu->serdev) > - serdev_device_close(hu->serdev); > + hci_uart_serdev_close(hu); > > skb_queue_purge(&mrvl->txq); > skb_queue_purge(&mrvl->rawq); > diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c > index 8705c4543..3d9e6cd15 100644 > --- a/drivers/bluetooth/hci_qca.c > +++ b/drivers/bluetooth/hci_qca.c > @@ -1755,8 +1755,8 @@ static int qca_port_reopen(struct hci_uart *hu) > * Without this, we will have RTS and CTS synchronization > * issues. > */ > - serdev_device_close(hu->serdev); > - ret = serdev_device_open(hu->serdev); > + hci_uart_serdev_close(hu); > + ret = hci_uart_serdev_open(hu); > if (ret) { > bt_dev_err(hu->hdev, "failed to open port"); > return ret; > @@ -1780,12 +1780,12 @@ static int qca_regulator_init(struct hci_uart *hu) > qcadev = serdev_device_get_drvdata(hu->serdev); > > if (!qcadev->bt_power->vregs_on) { > - serdev_device_close(hu->serdev); > + hci_uart_serdev_close(hu); > ret = qca_regulator_enable(qcadev); > if (ret) > return ret; > > - ret = serdev_device_open(hu->serdev); > + ret = hci_uart_serdev_open(hu); > if (ret) { > bt_dev_err(hu->hdev, "failed to open port"); > return ret; > @@ -2061,8 +2061,8 @@ static int qca_setup(struct hci_uart *hu) > if (retries < MAX_INIT_RETRIES) { > bt_dev_warn(hdev, "Retry BT power ON:%d", retries); > if (hu->serdev) { > - serdev_device_close(hu->serdev); > - ret = serdev_device_open(hu->serdev); > + hci_uart_serdev_close(hu); > + ret = hci_uart_serdev_open(hu); > if (ret) { > bt_dev_err(hdev, "failed to open port"); > return ret; > diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c > index 48ba017e2..05aa490a9 100644 > --- a/drivers/bluetooth/hci_serdev.c > +++ b/drivers/bluetooth/hci_serdev.c > @@ -21,6 +21,29 @@ > > #include "hci_uart.h" > > +int hci_uart_serdev_open(struct hci_uart *hu) > +{ > + int err; > + > + if (hu->serdev_open) > + return 0; > + > + err = serdev_device_open(hu->serdev); > + if (!err) > + hu->serdev_open = true; > + > + return err; > +} > + > +void hci_uart_serdev_close(struct hci_uart *hu) > +{ > + if (!hu->serdev_open) > + return; > + > + hu->serdev_open = false; > + serdev_device_close(hu->serdev); > +} > + > static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type) > { > struct hci_dev *hdev = hu->hdev; > @@ -102,7 +125,8 @@ static int hci_uart_flush(struct hci_dev *hdev) > } > > /* Flush any pending characters in the driver and discipline. */ > - serdev_device_write_flush(hu->serdev); > + if (hu->serdev_open) > + serdev_device_write_flush(hu->serdev); > > if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) > hu->proto->flush(hu); > @@ -123,7 +147,7 @@ static int hci_uart_open(struct hci_dev *hdev) > * BT OFF. Upon next BT ON UART port should be opened. > */ > if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) { > - err = serdev_device_open(hu->serdev); > + err = hci_uart_serdev_open(hu); > if (err) > return err; > set_bit(HCI_UART_PROTO_READY, &hu->flags); > @@ -154,7 +178,7 @@ static int hci_uart_close(struct hci_dev *hdev) > */ > if (hci_test_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP)) { > clear_bit(HCI_UART_PROTO_READY, &hu->flags); > - serdev_device_close(hu->serdev); > + hci_uart_serdev_close(hu); > } > > return 0; > @@ -314,7 +338,7 @@ int hci_uart_register_device_priv(struct hci_uart *hu, > if (percpu_init_rwsem(&hu->proto_lock)) > return -ENOMEM; > > - err = serdev_device_open(hu->serdev); > + err = hci_uart_serdev_open(hu); > if (err) > goto err_rwsem; > > @@ -385,7 +409,7 @@ int hci_uart_register_device_priv(struct hci_uart *hu, > clear_bit(HCI_UART_PROTO_READY, &hu->flags); > p->close(hu); > err_open: > - serdev_device_close(hu->serdev); > + hci_uart_serdev_close(hu); > err_rwsem: > percpu_free_rwsem(&hu->proto_lock); > return err; > @@ -438,8 +462,7 @@ void hci_uart_unregister_device(struct hci_uart *hu) > */ > hu->proto->close(hu); > > - if (proto_ready) > - serdev_device_close(hu->serdev); > + hci_uart_serdev_close(hu); > > hci_free_dev(hdev); > > diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h > index 7fbe8dffa..2f8e346f3 100644 > --- a/drivers/bluetooth/hci_uart.h > +++ b/drivers/bluetooth/hci_uart.h > @@ -66,6 +66,7 @@ struct hci_uart_proto { > struct hci_uart { > struct tty_struct *tty; > struct serdev_device *serdev; > + bool serdev_open; > struct hci_dev *hdev; > unsigned long flags; > unsigned long hdev_flags; > @@ -112,6 +113,8 @@ static inline int hci_uart_register_device(struct hci_uart *hu, > } > > void hci_uart_unregister_device(struct hci_uart *hu); > +int hci_uart_serdev_open(struct hci_uart *hu); > +void hci_uart_serdev_close(struct hci_uart *hu); > > int hci_uart_tx_wakeup(struct hci_uart *hu); > int hci_uart_wait_until_sent(struct hci_uart *hu); [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 870 bytes --] ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 0/1] Bluetooth: hci_mrvl: Fix duplicate serdev open/close 2026-11-12 18:56 ` [PATCH 2/4] Bluetooth: hci_serdev: Track whether the serial port is open Markus Probst @ 2026-11-14 16:15 ` Michael McAllister 2026-11-14 16:15 ` [PATCH 1/1] Bluetooth: hci_mrvl: Leave the serdev port lifetime to hci_serdev Michael McAllister 2026-11-14 17:06 ` [PATCH 0/1] " Markus Probst 0 siblings, 2 replies; 17+ messages in thread From: Michael McAllister @ 2026-11-14 16:15 UTC (permalink / raw) To: markus.probst, luiz.dentz, marcel; +Cc: linux-bluetooth, linux-kernel Hi Markus, thanks for flagging this! You're right, hci_serdev already opens and closes the port, so the extra calls in the Marvell driver aren't needed. This removes them as a separate fix. I've build-tested it and checked that the duplicate-open reproducer passes with the fix, but I don't have Marvell hardware to test on. Thanks, Michael ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 1/1] Bluetooth: hci_mrvl: Leave the serdev port lifetime to hci_serdev 2026-11-14 16:15 ` [PATCH 0/1] Bluetooth: hci_mrvl: Fix duplicate serdev open/close Michael McAllister @ 2026-11-14 16:15 ` Michael McAllister 2026-11-14 20:46 ` Bluetooth: hci_mrvl: Fix duplicate serdev open/close bluez.test.bot 2026-11-14 17:06 ` [PATCH 0/1] " Markus Probst 1 sibling, 1 reply; 17+ messages in thread From: Michael McAllister @ 2026-11-14 16:15 UTC (permalink / raw) To: markus.probst, luiz.dentz, marcel; +Cc: linux-bluetooth, linux-kernel hci_uart_register_device_priv() opens the port before calling mrvl_open(), so Marvell opens it twice. Likewise, mrvl_close() closes it before the transport closes it again during unregister or registration error cleanup. Remove the extra calls and let hci_serdev own the port lifetime. This also avoids failing probe when serdev rejects a second open with -EALREADY. Fixes: be70e5e774a6 ("Bluetooth: hci_mrvl: Add serdev support") Reported-by: Markus Probst <markus.probst@posteo.de> Closes: https://lore.kernel.org/341e56b1ff7d8a5b109e26e30dfed61faa54d603.camel@posteo.de/ Assisted-by: LLM Signed-off-by: Michael McAllister <me@michaelmcallister.org> --- drivers/bluetooth/hci_mrvl.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/bluetooth/hci_mrvl.c b/drivers/bluetooth/hci_mrvl.c index 5798a8db0..def19907c 100644 --- a/drivers/bluetooth/hci_mrvl.c +++ b/drivers/bluetooth/hci_mrvl.c @@ -57,7 +57,6 @@ struct hci_mrvl_pkt { static int mrvl_open(struct hci_uart *hu) { struct mrvl_data *mrvl; - int ret; BT_DBG("hu %p", hu); @@ -75,17 +74,7 @@ static int mrvl_open(struct hci_uart *hu) hu->priv = mrvl; - if (hu->serdev) { - ret = serdev_device_open(hu->serdev); - if (ret) - goto err; - } - return 0; -err: - kfree(mrvl); - - return ret; } static int mrvl_close(struct hci_uart *hu) @@ -94,9 +83,6 @@ static int mrvl_close(struct hci_uart *hu) BT_DBG("hu %p", hu); - if (hu->serdev) - serdev_device_close(hu->serdev); - skb_queue_purge(&mrvl->txq); skb_queue_purge(&mrvl->rawq); kfree_skb(mrvl->rx_skb); -- 2.39.5 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* RE: Bluetooth: hci_mrvl: Fix duplicate serdev open/close 2026-11-14 16:15 ` [PATCH 1/1] Bluetooth: hci_mrvl: Leave the serdev port lifetime to hci_serdev Michael McAllister @ 2026-11-14 20:46 ` bluez.test.bot 0 siblings, 0 replies; 17+ messages in thread From: bluez.test.bot @ 2026-11-14 20:46 UTC (permalink / raw) To: linux-bluetooth, me [-- Attachment #1: Type: text/plain, Size: 2077 bytes --] 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/1211439/ ---Test result--- Test Summary: CheckPatch FAIL 0.66 seconds VerifyFixes PASS 0.13 seconds VerifySignedoff PASS 0.13 seconds GitLint PASS 0.32 seconds SubjectPrefix PASS 0.13 seconds BuildKernel PASS 23.28 seconds CheckAllWarning PASS 26.65 seconds CheckSparse WARNING 28.66 seconds BuildKernel32 PASS 23.36 seconds CheckKernelLLVM PASS 24.29 seconds TestRunnerSetup PASS 550.59 seconds IncrementalBuild PASS 22.06 seconds Details ############################## Test: CheckPatch - FAIL Desc: Run checkpatch.pl script Output: [1/1] Bluetooth: hci_mrvl: Leave the serdev port lifetime to hci_serdev WARNING: Non-standard signature: Assisted-by: #94: Assisted-by: LLM ERROR: Unrecognized email address: 'LLM' #94: Assisted-by: LLM total: 1 errors, 1 warnings, 33 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /home/runner/work/bluetooth-next/bluetooth-next/src/patch/14984056.patch has style problems, please review. NOTE: Ignored message types: UNKNOWN_COMMIT_ID NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. ############################## Test: CheckSparse - WARNING Desc: Run sparse tool with linux kernel Output: drivers/bluetooth/hci_mrvl.c:156:23: warning: restricted __le16 degrades to integerdrivers/bluetooth/hci_mrvl.c:189:23: warning: restricted __le16 degrades to integer https://github.com/bluez/bluetooth-next/pull/1134 --- Regards, Linux Bluetooth ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/1] Bluetooth: hci_mrvl: Fix duplicate serdev open/close 2026-11-14 16:15 ` [PATCH 0/1] Bluetooth: hci_mrvl: Fix duplicate serdev open/close Michael McAllister 2026-11-14 16:15 ` [PATCH 1/1] Bluetooth: hci_mrvl: Leave the serdev port lifetime to hci_serdev Michael McAllister @ 2026-11-14 17:06 ` Markus Probst 1 sibling, 0 replies; 17+ messages in thread From: Markus Probst @ 2026-11-14 17:06 UTC (permalink / raw) To: Michael McAllister, luiz.dentz, marcel, Loic Poulain, Sascha Hauer, Stefan Eichenberger, Gongwei Li, Marcel Ziswiler, Vitor Soares, Hiago De Franco, Laurent Pinchart Cc: linux-bluetooth, linux-kernel [-- Attachment #1: Type: text/plain, Size: 769 bytes --] On Sat, 2026-11-14 at 16:15 +0000, Michael McAllister wrote: > Hi Markus, thanks for flagging this! > > You're right, hci_serdev already opens and closes the port, so the extra > calls in the Marvell driver aren't needed. This removes them as a > separate fix. > > I've build-tested it and checked that the duplicate-open reproducer > passes with the fix, but I don't have Marvell hardware to test on. > > Thanks, > Michael Hi, Thanks for the patch! I added some more people from the git history (incl. from existing device trees that have this hardware) to CC here in the hope that they can test it. If nobody tests it, there is still be linux-next. But its generally better if it gets tested once before that. Thanks - Markus Probst [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 870 bytes --] ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 1/4] Bluetooth: qca: Restore flow control after a failed power pulse 2026-10-28 22:34 [PATCH 0/4] Bluetooth: qca: Fix WCN3950 power-off Michael McAllister 2026-10-28 22:34 ` [PATCH 2/4] Bluetooth: hci_serdev: Track whether the serial port is open Michael McAllister @ 2026-10-28 22:34 ` Michael McAllister 2026-10-28 22:34 ` [PATCH 4/4] Bluetooth: qca: Power off WCN3950 Michael McAllister ` (2 subsequent siblings) 4 siblings, 0 replies; 17+ messages in thread From: Michael McAllister @ 2026-10-28 22:34 UTC (permalink / raw) To: Marcel Holtmann, Luiz Augusto von Dentz, Bartosz Golaszewski, linux-bluetooth Cc: linux-arm-msm, linux-kernel, Balakrishna Godavarthi, Dmitry Baryshkov, Matthias Kaehlcke, Michael McAllister qca_send_power_pulse() disables hardware flow control before writing to the UART. If the write fails, it returns without restoring flow control. Restore flow control on the error path as on success. Fixes: f9558270b85c ("Bluetooth: hci_qca: use wait_until_sent() for power pulses") Signed-off-by: Michael McAllister <me@michaelmcallister.org> --- drivers/bluetooth/hci_qca.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 7089e9b63..8705c4543 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1424,6 +1424,7 @@ static int qca_send_power_pulse(struct hci_uart *hu, bool on) ret = serdev_device_write_buf(hu->serdev, &cmd, sizeof(cmd)); if (ret < 0) { bt_dev_err(hu->hdev, "failed to send power pulse %02x", cmd); + hci_uart_set_flow_control(hu, false); return ret; } ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 4/4] Bluetooth: qca: Power off WCN3950 2026-10-28 22:34 [PATCH 0/4] Bluetooth: qca: Fix WCN3950 power-off Michael McAllister 2026-10-28 22:34 ` [PATCH 2/4] Bluetooth: hci_serdev: Track whether the serial port is open Michael McAllister 2026-10-28 22:34 ` [PATCH 1/4] Bluetooth: qca: Restore flow control after a failed power pulse Michael McAllister @ 2026-10-28 22:34 ` Michael McAllister 2026-10-28 22:34 ` [PATCH 3/4] Bluetooth: qca: Power off after unregistering the HCI device Michael McAllister 2026-11-14 18:39 ` [PATCH v2 0/4] Bluetooth: qca: Power off WCN3950 Michael McAllister 4 siblings, 0 replies; 17+ messages in thread From: Michael McAllister @ 2026-10-28 22:34 UTC (permalink / raw) To: Marcel Holtmann, Luiz Augusto von Dentz, Bartosz Golaszewski, linux-bluetooth Cc: linux-arm-msm, linux-kernel, Balakrishna Godavarthi, Dmitry Baryshkov, Matthias Kaehlcke, Michael McAllister Turning Bluetooth off on the Moto G10 leaves the WCN3950 regulator votes enabled. qca_power_off() handles the other WCN39xx controllers but omits WCN3950 from both switches. Add it to the existing power-off pulse and regulator-disable paths. Fixes: d5712c511cb3 ("Bluetooth: qca: add WCN3950 support") Signed-off-by: Michael McAllister <me@michaelmcallister.org> --- drivers/bluetooth/hci_qca.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 3d688ab75..540014182 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2249,6 +2249,7 @@ static void qca_power_off(struct hci_uart *hu) power = qcadev->bt_power; switch (soc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -2269,6 +2270,7 @@ static void qca_power_off(struct hci_uart *hu) } switch (soc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 3/4] Bluetooth: qca: Power off after unregistering the HCI device 2026-10-28 22:34 [PATCH 0/4] Bluetooth: qca: Fix WCN3950 power-off Michael McAllister ` (2 preceding siblings ...) 2026-10-28 22:34 ` [PATCH 4/4] Bluetooth: qca: Power off WCN3950 Michael McAllister @ 2026-10-28 22:34 ` Michael McAllister 2026-11-14 18:39 ` [PATCH v2 0/4] Bluetooth: qca: Power off WCN3950 Michael McAllister 4 siblings, 0 replies; 17+ messages in thread From: Michael McAllister @ 2026-10-28 22:34 UTC (permalink / raw) To: Marcel Holtmann, Luiz Augusto von Dentz, Bartosz Golaszewski, linux-bluetooth Cc: linux-arm-msm, linux-kernel, Balakrishna Godavarthi, Dmitry Baryshkov, Matthias Kaehlcke, Michael McAllister qca_serdev_remove() powers off the controller while HCI setup and transmission can still be running. Leave power-off to qca_close(), which runs after HCI unregistration and write-work cancellation, while the serial transport is still available. Use the serial port's open state for the power-pulse check. PROTO_READY is already clear during protocol cleanup, even when the port is open. The open-state check also skips serial I/O after a failed setup reopen. Mark a newly allocated serdev controller as off until power-on is tried, so registration failures do not send a power pulse before HCI allocation. Signed-off-by: Michael McAllister <me@michaelmcallister.org> --- drivers/bluetooth/hci_qca.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 3d9e6cd15..3d688ab75 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -619,6 +619,7 @@ static int qca_open(struct hci_uart *hu) hu->priv = qca; if (hu->serdev) { + set_bit(QCA_BT_OFF, &qca->flags); qcadev = serdev_device_get_drvdata(hu->serdev); switch (qcadev->btsoc_type) { @@ -2252,11 +2253,7 @@ static void qca_power_off(struct hci_uart *hu) case QCA_WCN3990: case QCA_WCN3991: case QCA_WCN3998: - /* Both of these write to the serial port which may have - * already been closed by hci_uart_close(), which closes - * the port if HCI_QUIRK_NON_PERSISTENT_SETUP is set. - */ - if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) { + if (hu->serdev_open) { host_set_baudrate(hu, 2400); qca_send_power_pulse(hu, false); } @@ -2580,22 +2577,6 @@ static int qca_serdev_probe(struct serdev_device *serdev) static void qca_serdev_remove(struct serdev_device *serdev) { struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); - struct qca_power *power = qcadev->bt_power; - - switch (qcadev->btsoc_type) { - case QCA_WCN3988: - case QCA_WCN3990: - case QCA_WCN3991: - case QCA_WCN3998: - case QCA_WCN6750: - case QCA_WCN6855: - case QCA_WCN7850: - if (power->vregs_on) - qca_power_off(&qcadev->serdev_hu); - break; - default: - break; - } hci_uart_unregister_device(&qcadev->serdev_hu); } ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 0/4] Bluetooth: qca: Power off WCN3950 2026-10-28 22:34 [PATCH 0/4] Bluetooth: qca: Fix WCN3950 power-off Michael McAllister ` (3 preceding siblings ...) 2026-10-28 22:34 ` [PATCH 3/4] Bluetooth: qca: Power off after unregistering the HCI device Michael McAllister @ 2026-11-14 18:39 ` Michael McAllister 2026-11-14 18:39 ` [PATCH v2 2/4] Bluetooth: qca: Power off after unregistering the HCI device Michael McAllister ` (3 more replies) 4 siblings, 4 replies; 17+ messages in thread From: Michael McAllister @ 2026-11-14 18:39 UTC (permalink / raw) To: Marcel Holtmann, Luiz Augusto von Dentz Cc: brgl, linux-bluetooth, linux-arm-msm, linux-kernel, quic_bgodavar, lumag, mka, me, markus.probst, shuai.zhang Hi, Thanks for the review. I've split this into four patches, with the Marvell fix kept separate. I've tested a backport on my Moto G10, including power cycling and unbind/rebind with Bluetooth both on and off. Thanks, Michael --- base-commit: da3cc02587c629420603df4395179ec82955c941 prerequisite-patch-id: 517b9cfef6a60777b0869a8f46d4c07be7f77c13 ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2 2/4] Bluetooth: qca: Power off after unregistering the HCI device 2026-11-14 18:39 ` [PATCH v2 0/4] Bluetooth: qca: Power off WCN3950 Michael McAllister @ 2026-11-14 18:39 ` Michael McAllister 2026-11-14 18:39 ` [PATCH v2 3/4] Bluetooth: qca: Handle failed power-pulse writes Michael McAllister ` (2 subsequent siblings) 3 siblings, 0 replies; 17+ messages in thread From: Michael McAllister @ 2026-11-14 18:39 UTC (permalink / raw) To: Marcel Holtmann, Luiz Augusto von Dentz Cc: brgl, linux-bluetooth, linux-arm-msm, linux-kernel, quic_bgodavar, lumag, mka, me, markus.probst, shuai.zhang qca_serdev_remove() powers off while HCI setup and UART writes can still be running. Leave power-off to qca_close(), after HCI unregistration and write-work cancellation, while the serial transport is still available. Check the actual port state before sending the power-off pulse, since PROTO_READY is already clear during protocol cleanup. Start serdev controllers in QCA_BT_OFF so registration failure does not send a pulse before HCI allocation or power-on. Drain HCI setup before clearing protocol readiness, so a setup reopen cannot re-enable UART write work after cancellation. Leave HCI flush and close callbacks to the transport teardown during unregister; the port stays open until protocol close has sent the power-off pulse. Flush controller TX after stopping UART work, before protocol and port close, so previously accepted bytes are discarded rather than drained. Signed-off-by: Michael McAllister <me@michaelmcallister.org> --- drivers/bluetooth/hci_qca.c | 24 ++---------------------- drivers/bluetooth/hci_serdev.c | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 28e84fc24..ddbeb0787 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -620,6 +620,7 @@ static int qca_open(struct hci_uart *hu) hu->priv = qca; if (hu->serdev) { + set_bit(QCA_BT_OFF, &qca->flags); qcadev = serdev_device_get_drvdata(hu->serdev); switch (qcadev->btsoc_type) { @@ -2285,11 +2286,7 @@ static void qca_power_off(struct hci_uart *hu) case QCA_WCN3990: case QCA_WCN3991: case QCA_WCN3998: - /* Both of these write to the serial port which may have - * already been closed by hci_uart_close(), which closes - * the port if HCI_QUIRK_NON_PERSISTENT_SETUP is set. - */ - if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) { + if (hu->serdev_open) { host_set_baudrate(hu, 2400); qca_send_power_pulse(hu, false); } @@ -2618,23 +2615,6 @@ static int qca_serdev_probe(struct serdev_device *serdev) static void qca_serdev_remove(struct serdev_device *serdev) { struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); - struct qca_power *power = qcadev->bt_power; - - switch (qcadev->btsoc_type) { - case QCA_WCN3988: - case QCA_WCN3990: - case QCA_WCN3991: - case QCA_WCN3998: - case QCA_WCN6750: - case QCA_QCA2066: - case QCA_WCN6855: - case QCA_WCN7850: - if (power->vregs_on) - qca_power_off(&qcadev->serdev_hu); - break; - default: - break; - } hci_uart_unregister_device(&qcadev->serdev_hu); } diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 3d10d8d75..e279a7d61 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -120,6 +120,9 @@ static int hci_uart_flush(struct hci_dev *hdev) BT_DBG("hdev %p serdev %p", hdev, hu->serdev); + if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) + return 0; + if (hu->tx_skb) { kfree_skb(hu->tx_skb); hu->tx_skb = NULL; } @@ -167,6 +170,9 @@ static int hci_uart_close(struct hci_dev *hdev) BT_DBG("hdev %p", hdev); + if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) + return 0; + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) return 0; @@ -425,6 +431,10 @@ void hci_uart_unregister_device(struct hci_uart *hu) /* Wait for init_ready to finish to prevent registration races */ cancel_work_sync(&hu->init_ready); + /* Drain HCI setup before clearing protocol readiness. */ + if (test_bit(HCI_UART_REGISTERED, &hu->flags)) + hci_unregister_dev(hdev); + proto_ready = test_bit(HCI_UART_PROTO_READY, &hu->flags); if (proto_ready) { /* Clear HCI_UART_PROTO_READY under the write lock so a @@ -446,16 +456,16 @@ void hci_uart_unregister_device(struct hci_uart *hu) cancel_work_sync(&hu->write_work); /* Free any partially transmitted frame left over by write_work now - * that the transmit path is fully quiesced. hci_uart_close() would - * skip hci_uart_flush() because HCI_UART_PROTO_READY is cleared. + * that the transmit path is fully quiesced. The HCI close and flush + * callbacks leave transport teardown to us during unregister. */ if (hu->tx_skb) { kfree_skb(hu->tx_skb); hu->tx_skb = NULL; } - if (test_bit(HCI_UART_REGISTERED, &hu->flags)) - hci_unregister_dev(hdev); + if (hu->serdev_open) + serdev_device_write_flush(hu->serdev); /* Close the protocol before freeing hdev (intrinsically purges queues). * Some protocol close handlers (e.g. qca_close) may still access the -- 2.39.5 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 3/4] Bluetooth: qca: Handle failed power-pulse writes 2026-11-14 18:39 ` [PATCH v2 0/4] Bluetooth: qca: Power off WCN3950 Michael McAllister 2026-11-14 18:39 ` [PATCH v2 2/4] Bluetooth: qca: Power off after unregistering the HCI device Michael McAllister @ 2026-11-14 18:39 ` Michael McAllister 2026-11-14 18:39 ` [PATCH v2 1/4] Bluetooth: hci_serdev: Track whether the serial port is open Michael McAllister 2026-11-14 18:39 ` [PATCH v2 4/4] Bluetooth: qca: Power off WCN3950 Michael McAllister 3 siblings, 0 replies; 17+ messages in thread From: Michael McAllister @ 2026-11-14 18:39 UTC (permalink / raw) To: Marcel Holtmann, Luiz Augusto von Dentz Cc: brgl, linux-bluetooth, linux-arm-msm, linux-kernel, quic_bgodavar, lumag, mka, me, markus.probst, shuai.zhang A failed UART write leaves hardware flow control disabled. A zero-byte write is also treated as success even though no pulse was queued. Require the one-byte pulse to be accepted and restore flow control on the error path, returning -EIO for a zero-byte write. Fixes: f9558270b85c ("Bluetooth: hci_qca: use wait_until_sent() for power pulses") Signed-off-by: Michael McAllister <me@michaelmcallister.org> --- drivers/bluetooth/hci_qca.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index ddbeb0787..6642af781 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1430,9 +1430,10 @@ static int qca_send_power_pulse(struct hci_uart *hu, bool on) serdev_device_write_flush(hu->serdev); hci_uart_set_flow_control(hu, true); ret = serdev_device_write_buf(hu->serdev, &cmd, sizeof(cmd)); - if (ret < 0) { + if (ret != sizeof(cmd)) { bt_dev_err(hu->hdev, "failed to send power pulse %02x", cmd); - return ret; + hci_uart_set_flow_control(hu, false); + return ret < 0 ? ret : -EIO; } serdev_device_wait_until_sent(hu->serdev, timeout); -- 2.39.5 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 1/4] Bluetooth: hci_serdev: Track whether the serial port is open 2026-11-14 18:39 ` [PATCH v2 0/4] Bluetooth: qca: Power off WCN3950 Michael McAllister 2026-11-14 18:39 ` [PATCH v2 2/4] Bluetooth: qca: Power off after unregistering the HCI device Michael McAllister 2026-11-14 18:39 ` [PATCH v2 3/4] Bluetooth: qca: Handle failed power-pulse writes Michael McAllister @ 2026-11-14 18:39 ` Michael McAllister 2026-11-14 20:46 ` [v2,1/4] " bluez.test.bot 2026-11-14 18:39 ` [PATCH v2 4/4] Bluetooth: qca: Power off WCN3950 Michael McAllister 3 siblings, 1 reply; 17+ messages in thread From: Michael McAllister @ 2026-11-14 18:39 UTC (permalink / raw) To: Marcel Holtmann, Luiz Augusto von Dentz Cc: brgl, linux-bluetooth, linux-arm-msm, linux-kernel, quic_bgodavar, lumag, mka, me, markus.probst, shuai.zhang HCI_UART_PROTO_READY is cleared before protocol close during unregister, even though the serial port stays open. QCA needs to distinguish that case from a port left closed by a failed setup reopen before sending its power-off pulse. Track the port state in the transport and QCA open/close helpers. Keep the existing PROTO_READY handling for setup failures and use the actual open state when closing the port during unregister. Signed-off-by: Michael McAllister <me@michaelmcallister.org> --- drivers/bluetooth/hci_qca.c | 4 ++-- drivers/bluetooth/hci_serdev.c | 34 ++++++++++++++++++++++++++++------ drivers/bluetooth/hci_uart.h | 3 +++ 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index d693e2842..28e84fc24 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1762,14 +1762,14 @@ static void qca_port_close(struct hci_uart *hu) * hci_uart_close() or hci_uart_unregister_device(). */ if (test_and_clear_bit(HCI_UART_PROTO_READY, &hu->flags)) - serdev_device_close(hu->serdev); + hci_uart_serdev_close(hu); } static int qca_port_open(struct hci_uart *hu) { int ret; - ret = serdev_device_open(hu->serdev); + ret = hci_uart_serdev_open(hu); if (!ret) set_bit(HCI_UART_PROTO_READY, &hu->flags); diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index d2c48df34..3d10d8d75 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -21,6 +21,29 @@ #include "hci_uart.h" +int hci_uart_serdev_open(struct hci_uart *hu) +{ + int err; + + if (hu->serdev_open) + return 0; + + err = serdev_device_open(hu->serdev); + if (!err) + hu->serdev_open = true; + + return err; +} + +void hci_uart_serdev_close(struct hci_uart *hu) +{ + if (!hu->serdev_open) + return; + + hu->serdev_open = false; + serdev_device_close(hu->serdev); +} + static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type) { struct hci_dev *hdev = hu->hdev; @@ -125,7 +148,7 @@ static int hci_uart_open(struct hci_dev *hdev) * BT OFF. Upon next BT ON UART port should be opened. */ if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) { - err = serdev_device_open(hu->serdev); + err = hci_uart_serdev_open(hu); if (err) return err; set_bit(HCI_UART_PROTO_READY, &hu->flags); @@ -156,7 +179,7 @@ static int hci_uart_close(struct hci_dev *hdev) */ if (hci_test_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP)) { clear_bit(HCI_UART_PROTO_READY, &hu->flags); - serdev_device_close(hu->serdev); + hci_uart_serdev_close(hu); } return 0; @@ -316,7 +339,7 @@ int hci_uart_register_device_priv(struct hci_uart *hu, if (percpu_init_rwsem(&hu->proto_lock)) return -ENOMEM; - err = serdev_device_open(hu->serdev); + err = hci_uart_serdev_open(hu); if (err) goto err_rwsem; @@ -387,7 +410,7 @@ int hci_uart_register_device_priv(struct hci_uart *hu, clear_bit(HCI_UART_PROTO_READY, &hu->flags); p->close(hu); err_open: - serdev_device_close(hu->serdev); + hci_uart_serdev_close(hu); err_rwsem: percpu_free_rwsem(&hu->proto_lock); return err; @@ -440,8 +463,7 @@ void hci_uart_unregister_device(struct hci_uart *hu) */ hu->proto->close(hu); - if (proto_ready) - serdev_device_close(hu->serdev); + hci_uart_serdev_close(hu); hci_free_dev(hdev); diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index 7fbe8dffa..2f8e346f3 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h @@ -66,6 +66,7 @@ struct hci_uart_proto { struct hci_uart { struct tty_struct *tty; struct serdev_device *serdev; + bool serdev_open; struct hci_dev *hdev; unsigned long flags; unsigned long hdev_flags; @@ -112,6 +113,8 @@ static inline int hci_uart_register_device(struct hci_uart *hu, } void hci_uart_unregister_device(struct hci_uart *hu); +int hci_uart_serdev_open(struct hci_uart *hu); +void hci_uart_serdev_close(struct hci_uart *hu); int hci_uart_tx_wakeup(struct hci_uart *hu); int hci_uart_wait_until_sent(struct hci_uart *hu); -- 2.39.5 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* RE: [v2,1/4] Bluetooth: hci_serdev: Track whether the serial port is open 2026-11-14 18:39 ` [PATCH v2 1/4] Bluetooth: hci_serdev: Track whether the serial port is open Michael McAllister @ 2026-11-14 20:46 ` bluez.test.bot 0 siblings, 0 replies; 17+ messages in thread From: bluez.test.bot @ 2026-11-14 20:46 UTC (permalink / raw) To: linux-bluetooth, me [-- Attachment #1: Type: text/plain, Size: 1020 bytes --] 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/1211540/ ---Test result--- Test Summary: CheckPatch PASS 3.32 seconds VerifyFixes PASS 0.13 seconds VerifySignedoff PASS 0.13 seconds GitLint PASS 1.33 seconds SubjectPrefix PASS 0.51 seconds BuildKernel PASS 24.01 seconds CheckAllWarning PASS 27.63 seconds CheckSparse PASS 30.16 seconds BuildKernel32 PASS 24.23 seconds CheckKernelLLVM PASS 24.51 seconds TestRunnerSetup PASS 556.91 seconds IncrementalBuild PASS 28.40 seconds https://github.com/bluez/bluetooth-next/pull/1135 --- Regards, Linux Bluetooth ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2 4/4] Bluetooth: qca: Power off WCN3950 2026-11-14 18:39 ` [PATCH v2 0/4] Bluetooth: qca: Power off WCN3950 Michael McAllister ` (2 preceding siblings ...) 2026-11-14 18:39 ` [PATCH v2 1/4] Bluetooth: hci_serdev: Track whether the serial port is open Michael McAllister @ 2026-11-14 18:39 ` Michael McAllister 3 siblings, 0 replies; 17+ messages in thread From: Michael McAllister @ 2026-11-14 18:39 UTC (permalink / raw) To: Marcel Holtmann, Luiz Augusto von Dentz Cc: brgl, linux-bluetooth, linux-arm-msm, linux-kernel, quic_bgodavar, lumag, mka, me, markus.probst, shuai.zhang Turning Bluetooth off on the Moto G10 leaves the WCN3950 regulator votes enabled. qca_power_off() handles the other WCN39xx controllers but omits WCN3950 from both switches. Add it to the existing power-off pulse and regulator-disable paths. Fixes: d5712c511cb3 ("Bluetooth: qca: add WCN3950 support") Signed-off-by: Michael McAllister <me@michaelmcallister.org> --- drivers/bluetooth/hci_qca.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 6642af781..bd8cfe95c 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2283,6 +2283,7 @@ static void qca_power_off(struct hci_uart *hu) power = qcadev->bt_power; switch (soc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -2303,6 +2304,7 @@ static void qca_power_off(struct hci_uart *hu) } switch (soc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: -- 2.39.5 ^ permalink raw reply related [flat|nested] 17+ messages in thread
end of thread, other threads:[~2026-11-14 20:46 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-28 22:34 [PATCH 0/4] Bluetooth: qca: Fix WCN3950 power-off Michael McAllister 2026-10-28 22:34 ` [PATCH 2/4] Bluetooth: hci_serdev: Track whether the serial port is open Michael McAllister 2026-10-29 2:09 ` Bluetooth: qca: Fix WCN3950 power-off bluez.test.bot 2026-11-12 18:56 ` [PATCH 2/4] Bluetooth: hci_serdev: Track whether the serial port is open Markus Probst 2026-11-14 16:15 ` [PATCH 0/1] Bluetooth: hci_mrvl: Fix duplicate serdev open/close Michael McAllister 2026-11-14 16:15 ` [PATCH 1/1] Bluetooth: hci_mrvl: Leave the serdev port lifetime to hci_serdev Michael McAllister 2026-11-14 20:46 ` Bluetooth: hci_mrvl: Fix duplicate serdev open/close bluez.test.bot 2026-11-14 17:06 ` [PATCH 0/1] " Markus Probst 2026-10-28 22:34 ` [PATCH 1/4] Bluetooth: qca: Restore flow control after a failed power pulse Michael McAllister 2026-10-28 22:34 ` [PATCH 4/4] Bluetooth: qca: Power off WCN3950 Michael McAllister 2026-10-28 22:34 ` [PATCH 3/4] Bluetooth: qca: Power off after unregistering the HCI device Michael McAllister 2026-11-14 18:39 ` [PATCH v2 0/4] Bluetooth: qca: Power off WCN3950 Michael McAllister 2026-11-14 18:39 ` [PATCH v2 2/4] Bluetooth: qca: Power off after unregistering the HCI device Michael McAllister 2026-11-14 18:39 ` [PATCH v2 3/4] Bluetooth: qca: Handle failed power-pulse writes Michael McAllister 2026-11-14 18:39 ` [PATCH v2 1/4] Bluetooth: hci_serdev: Track whether the serial port is open Michael McAllister 2026-11-14 20:46 ` [v2,1/4] " bluez.test.bot 2026-11-14 18:39 ` [PATCH v2 4/4] Bluetooth: qca: Power off WCN3950 Michael McAllister
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox