mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [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
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ 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] 6+ 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 11:18 ` [PATCH v3 2/2] Bluetooth: hci_qca: Don't use the serdev port after a failed reopen Shuai Zhang
  2026-10-30  9:29 ` [PATCH v3 0/2] Bluetooth: hci_qca: Reopen port after power on for QCA2066 Bartosz Golaszewski
  2 siblings, 0 replies; 6+ 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	[flat|nested] 6+ 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
  2026-10-30  9:29 ` [PATCH v3 0/2] Bluetooth: hci_qca: Reopen port after power on for QCA2066 Bartosz Golaszewski
  2 siblings, 0 replies; 6+ 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	[flat|nested] 6+ messages in thread

* Re: [PATCH v3 0/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 ` [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
@ 2026-10-30  9:29 ` Bartosz Golaszewski
  2026-11-06  6:35   ` Shuai Zhang
  2 siblings, 1 reply; 6+ messages in thread
From: Bartosz Golaszewski @ 2026-10-30  9:29 UTC (permalink / raw)
  To: Shuai Zhang
  Cc: Marcel Holtmann, Luiz Augusto von Dentz, linux-arm-msm,
	linux-bluetooth, linux-kernel, chejiang, quic_chezhou, wei.deng,
	jinwang.li, mengshi.wu

On Wed, Oct 28, 2026 at 07:18:37PM +0800, Shuai Zhang wrote:
> 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
>

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v3 0/2] Bluetooth: hci_qca: Reopen port after power on for QCA2066
  2026-10-30  9:29 ` [PATCH v3 0/2] Bluetooth: hci_qca: Reopen port after power on for QCA2066 Bartosz Golaszewski
@ 2026-11-06  6:35   ` Shuai Zhang
  2026-11-06  9:17     ` Bartosz Golaszewski
  0 siblings, 1 reply; 6+ messages in thread
From: Shuai Zhang @ 2026-11-06  6:35 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Marcel Holtmann, Luiz Augusto von Dentz, linux-arm-msm,
	linux-bluetooth, linux-kernel, chejiang, quic_chezhou, wei.deng,
	jinwang.li, mengshi.wu

Hi Bartosz

On 10/30/2026 5:29 PM, Bartosz Golaszewski wrote:
> On Wed, Oct 28, 2026 at 07:18:37PM +0800, Shuai Zhang wrote:
>> 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
>>
> Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>

Just want to confirm if there's anything else I need to do before 
applying it.


Thanks,

Shuai



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v3 0/2] Bluetooth: hci_qca: Reopen port after power on for QCA2066
  2026-11-06  6:35   ` Shuai Zhang
@ 2026-11-06  9:17     ` Bartosz Golaszewski
  0 siblings, 0 replies; 6+ messages in thread
From: Bartosz Golaszewski @ 2026-11-06  9:17 UTC (permalink / raw)
  To: Shuai Zhang
  Cc: Marcel Holtmann, Luiz Augusto von Dentz, linux-arm-msm,
	linux-bluetooth, linux-kernel, chejiang, quic_chezhou, wei.deng,
	jinwang.li, mengshi.wu

On Fri, Nov 06, 2026 at 02:35:25PM +0800, Shuai Zhang wrote:
> Hi Bartosz
> 
> On 10/30/2026 5:29 PM, Bartosz Golaszewski wrote:
> > On Wed, Oct 28, 2026 at 07:18:37PM +0800, Shuai Zhang wrote:
> > > 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
> > > 
> > Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> 
> Just want to confirm if there's anything else I need to do before applying
> it.
>

Luiz uses patchwork, I'm pretty sure the patch won't get lost.

Bart

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-11-06  9:17 UTC | newest]

Thread overview: 6+ 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 11:18 ` [PATCH v3 2/2] Bluetooth: hci_qca: Don't use the serdev port after a failed reopen Shuai Zhang
2026-10-30  9:29 ` [PATCH v3 0/2] Bluetooth: hci_qca: Reopen port after power on for QCA2066 Bartosz Golaszewski
2026-11-06  6:35   ` Shuai Zhang
2026-11-06  9:17     ` Bartosz Golaszewski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®