* [PATCH v3 0/2] Bluetooth: hci_qca: Reopen port after power on for QCA2066
@ 2026-10-28 11:18 Shuai Zhang
2026-10-28 11:18 ` [PATCH v3 1/2] " Shuai Zhang
2026-10-28 11:18 ` [PATCH v3 2/2] Bluetooth: hci_qca: Don't use the serdev port after a failed reopen Shuai Zhang
0 siblings, 2 replies; 5+ messages in thread
From: Shuai Zhang @ 2026-10-28 11:18 UTC (permalink / raw)
To: Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz
Cc: linux-arm-msm, linux-bluetooth, linux-kernel, chejiang,
quic_chezhou, wei.deng, jinwang.li, mengshi.wu, Shuai Zhang
QCA2066 needs the serial port reopened after the controller is powered
on, otherwise the host and the controller run into RTS/CTS
synchronization issues.
Patch 1 reopens the port in qca_power_on() for QCA2066, as in v2.
Patch 2 keeps HCI_UART_PROTO_READY in sync with the port state, so that a
port which failed to reopen is not closed or flushed again.
Changes in v3:
- Patch 1 is unchanged from v2.
- Add patch 2. If serdev_device_open() fails during the reopen, the
port stays closed but HCI_UART_PROTO_READY stays set, so the later
serdev_device_close() and hci_uart_flush() use a closed port. Keep
the flag in sync with the port state and skip the port flush when
the port is not open.
- Link to v2:
https://lore.kernel.org/all/20261016022302.4003647-1-shuai.zhang@oss.qualcomm.com/
Changes in v2:
- Use a separate case for clearer logic.
- Link to v1:
https://lore.kernel.org/all/20261015092224.262158-1-shuai.zhang@oss.qualcomm.com/
Shuai Zhang (2):
Bluetooth: hci_qca: Reopen port after power on for QCA2066
Bluetooth: hci_qca: Don't use the serdev port after a failed reopen
drivers/bluetooth/hci_qca.c | 46 +++++++++++++++++++++++++++++-----
drivers/bluetooth/hci_serdev.c | 6 +++--
2 files changed, 44 insertions(+), 8 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 1/2] Bluetooth: hci_qca: Reopen port after power on for QCA2066
2026-10-28 11:18 [PATCH v3 0/2] Bluetooth: hci_qca: Reopen port after power on for QCA2066 Shuai Zhang
@ 2026-10-28 11:18 ` Shuai Zhang
2026-10-28 17:43 ` bluez.test.bot
2026-10-28 11:18 ` [PATCH v3 2/2] Bluetooth: hci_qca: Don't use the serdev port after a failed reopen Shuai Zhang
1 sibling, 1 reply; 5+ messages in thread
From: Shuai Zhang @ 2026-10-28 11:18 UTC (permalink / raw)
To: Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz
Cc: linux-arm-msm, linux-bluetooth, linux-kernel, chejiang,
quic_chezhou, wei.deng, jinwang.li, mengshi.wu, Shuai Zhang
QCA2066 needs the serial port reopened after the controller is powered
on, otherwise the host and the controller run into RTS/CTS
synchronization issues.
Reopen the port in qca_power_on() for QCA2066, once the controller has
been powered on.
Signed-off-by: Shuai Zhang <shuai.zhang@oss.qualcomm.com>
---
drivers/bluetooth/hci_qca.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 7089e9b63..ee3ccb59e 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -1867,6 +1867,19 @@ static int qca_power_on(struct hci_dev *hdev)
ret = qca_regulator_init(hu);
break;
+ case QCA_QCA2066:
+ qcadev = serdev_device_get_drvdata(hu->serdev);
+ if (qcadev->bt_en) {
+ gpiod_set_value_cansleep(qcadev->bt_en, 0);
+ msleep(50);
+ gpiod_set_value_cansleep(qcadev->bt_en, 1);
+ /* Controller needs time to bootup. */
+ msleep(50);
+ }
+
+ ret = qca_port_reopen(hu);
+ break;
+
default:
qcadev = serdev_device_get_drvdata(hu->serdev);
if (qcadev->bt_en) {
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v3 2/2] Bluetooth: hci_qca: Don't use the serdev port after a failed reopen
2026-10-28 11:18 [PATCH v3 0/2] Bluetooth: hci_qca: Reopen port after power on for QCA2066 Shuai Zhang
2026-10-28 11:18 ` [PATCH v3 1/2] " Shuai Zhang
@ 2026-10-28 11:18 ` Shuai Zhang
1 sibling, 0 replies; 5+ messages in thread
From: Shuai Zhang @ 2026-10-28 11:18 UTC (permalink / raw)
To: Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz
Cc: linux-arm-msm, linux-bluetooth, linux-kernel, chejiang,
quic_chezhou, wei.deng, jinwang.li, mengshi.wu, Shuai Zhang
If serdev_device_open() fails in qca_port_reopen(), qca_regulator_init()
or the qca_setup() retry path, the port is left closed but
HCI_UART_PROTO_READY stays set. The error reaches qca_setup(), whose
retry loop calls serdev_device_close() again, and hci_uart_close() or
hci_uart_unregister_device() close it once more later. The HCI core
also calls hci_uart_flush() from hci_dev_close_sync() before
hdev->close(), which writes to the closed port.
serdev_device_close() and serdev_device_write_flush() have no "not open"
check. ttyport_open() clears serport->tty when it fails, so both end up
passing NULL to the tty layer, and the runtime PM usage count is dropped
once too often.
Keep HCI_UART_PROTO_READY in sync with the port state in hci_qca: clear
it when the port is closed, set it only after a successful open, and
only call serdev_device_close() when it was set. hci_uart_open() already
treats the flag as "port is open" and reopens the port when it is
clear, so the next power on recovers. Make hci_uart_flush() skip the
port flush when the flag is clear, as it already does for the proto
flush.
Signed-off-by: Shuai Zhang <shuai.zhang@oss.qualcomm.com>
---
drivers/bluetooth/hci_qca.c | 33 +++++++++++++++++++++++++++------
drivers/bluetooth/hci_serdev.c | 6 ++++--
2 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index ee3ccb59e..66332e744 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -1745,6 +1745,27 @@ static bool qca_wakeup(struct hci_dev *hdev)
return wakeup;
}
+static void qca_port_close(struct hci_uart *hu)
+{
+ /* HCI_UART_PROTO_READY tracks whether the port is open, so a port
+ * left closed by a failed qca_port_open() is not closed again by
+ * hci_uart_close() or hci_uart_unregister_device().
+ */
+ if (test_and_clear_bit(HCI_UART_PROTO_READY, &hu->flags))
+ serdev_device_close(hu->serdev);
+}
+
+static int qca_port_open(struct hci_uart *hu)
+{
+ int ret;
+
+ ret = serdev_device_open(hu->serdev);
+ if (!ret)
+ set_bit(HCI_UART_PROTO_READY, &hu->flags);
+
+ return ret;
+}
+
static int qca_port_reopen(struct hci_uart *hu)
{
int ret;
@@ -1754,8 +1775,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);
+ qca_port_close(hu);
+ ret = qca_port_open(hu);
if (ret) {
bt_dev_err(hu->hdev, "failed to open port");
return ret;
@@ -1779,12 +1800,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);
+ qca_port_close(hu);
ret = qca_regulator_enable(qcadev);
if (ret)
return ret;
- ret = serdev_device_open(hu->serdev);
+ ret = qca_port_open(hu);
if (ret) {
bt_dev_err(hu->hdev, "failed to open port");
return ret;
@@ -2073,8 +2094,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);
+ qca_port_close(hu);
+ ret = qca_port_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..d2c48df34 100644
--- a/drivers/bluetooth/hci_serdev.c
+++ b/drivers/bluetooth/hci_serdev.c
@@ -101,11 +101,13 @@ static int hci_uart_flush(struct hci_dev *hdev)
kfree_skb(hu->tx_skb); hu->tx_skb = NULL;
}
+ if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
+ return 0;
+
/* Flush any pending characters in the driver and discipline. */
serdev_device_write_flush(hu->serdev);
- if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
- hu->proto->flush(hu);
+ hu->proto->flush(hu);
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] Bluetooth: hci_qca: Reopen port after power on for QCA2066
@ 2026-10-15 9:22 Shuai Zhang
2026-10-15 12:41 ` bluez.test.bot
0 siblings, 1 reply; 5+ messages in thread
From: Shuai Zhang @ 2026-10-15 9:22 UTC (permalink / raw)
To: Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz
Cc: linux-arm-msm, linux-bluetooth, linux-kernel, chejiang,
quic_chezhou, wei.deng, jinwang.li, mengshi.wu, Shuai Zhang
QCA2066 requires the serial port to be reopened after the controller
is powered on, otherwise the host and the device run into RTS/CTS
synchronization issues. Call the existing qca_port_reopen() helper
for QCA_QCA2066 in the default power-on path, leaving the behaviour
for other default-path controllers unchanged.
Signed-off-by: Shuai Zhang <shuai.zhang@oss.qualcomm.com>
---
drivers/bluetooth/hci_qca.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 7089e9b63..c24f4e6c9 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -1873,6 +1873,12 @@ static int qca_power_on(struct hci_dev *hdev)
gpiod_set_value_cansleep(qcadev->bt_en, 1);
/* Controller needs time to bootup. */
msleep(150);
+
+ if (soc_type == QCA_QCA2066) {
+ ret = qca_port_reopen(hu);
+ if (ret)
+ break;
+ }
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-28 17:43 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-28 11:18 [PATCH v3 0/2] Bluetooth: hci_qca: Reopen port after power on for QCA2066 Shuai Zhang
2026-10-28 11:18 ` [PATCH v3 1/2] " Shuai Zhang
2026-10-28 17:43 ` bluez.test.bot
2026-10-28 11:18 ` [PATCH v3 2/2] Bluetooth: hci_qca: Don't use the serdev port after a failed reopen Shuai Zhang
-- strict thread matches above, loose matches on Subject: below --
2026-10-15 9:22 [PATCH] Bluetooth: hci_qca: Reopen port after power on for QCA2066 Shuai Zhang
2026-10-15 12:41 ` bluez.test.bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox