diff mbox series

[v7,2/2] Bluetooth: qca: Fix BT enable failure for QCA6390 after disable then warm reboot

Message ID 1713932807-19619-3-git-send-email-quic_zijuhu@quicinc.com
State Superseded
Headers show
Series Fix two BT regression issues for QCA6390 | expand

Commit Message

quic_zijuhu April 24, 2024, 4:26 a.m. UTC
From: Zijun Hu <zijuhu@qti.qualcomm.com>

Commit 272970be3dab ("Bluetooth: hci_qca: Fix driver shutdown on closed
serdev") will cause below regression issue:

BT can't be enabled after below steps:
cold boot -> enable BT -> disable BT -> warm reboot -> BT enable failure
if property enable-gpios is not configured within DT|ACPI for QCA6390.

The commit is to fix a use-after-free issue within qca_serdev_shutdown()
during reboot, but also introduces this regression issue regarding above
steps since the VSC is not sent to reset controller during warm reboot.

Fixed by sending the VSC to reset controller within qca_serdev_shutdown()
once BT was ever enabled, and the use-after-free issue is also be fixed
by this change since serdev is still opened when send to serdev.

Fixes: 272970be3dab ("Bluetooth: hci_qca: Fix driver shutdown on closed serdev")
Cc: stable@vge.kernel.org
Reported-by: Wren Turkal <wt@penguintechs.org>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218726
Signed-off-by: Zijun Hu <zijuhu@qti.qualcomm.com>
Tested-by: Wren Turkal <wt@penguintechs.org>
---
Changes:
V6 -> V7: Add stable tag
V3 -> V6: Correct title and commit message
V1 -> V3: Remove debugging logs

 drivers/bluetooth/hci_qca.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

Comments

Wren Turkal April 26, 2024, 8:42 p.m. UTC | #1
On Tuesday, April 23, 2024 9:34:43 PM PDT Greg KH wrote:
> On Wed, Apr 24, 2024 at 12:26:47PM +0800, Zijun Hu wrote:
> > From: Zijun Hu <zijuhu@qti.qualcomm.com>
> > 
> > Commit 272970be3dab ("Bluetooth: hci_qca: Fix driver shutdown on closed
> > serdev") will cause below regression issue:
> > 
> > BT can't be enabled after below steps:
> > cold boot -> enable BT -> disable BT -> warm reboot -> BT enable failure
> > if property enable-gpios is not configured within DT|ACPI for QCA6390.
> > 
> > The commit is to fix a use-after-free issue within qca_serdev_shutdown()
> > during reboot, but also introduces this regression issue regarding above
> > steps since the VSC is not sent to reset controller during warm reboot.
> > 
> > Fixed by sending the VSC to reset controller within qca_serdev_shutdown()
> > once BT was ever enabled, and the use-after-free issue is also be fixed
> > by this change since serdev is still opened when send to serdev.
> > 
> > Fixes: 272970be3dab ("Bluetooth: hci_qca: Fix driver shutdown on closed
> > serdev") Cc: stable@vge.kernel.org
> 
> That is not a valid email address :(

@ziljun, can you please post this patch in a new patch series by itself? The 
warm boot problem is fixed by this patch, and I think it would be better to 
have a thread dedicated to this fix so that it doesn't get lost.

FWIW, I think that this may be the correct technical change. I would like to 
try to help get this patch landed, and I think a clean thread for only this 
change would help.

Just so everyone is aware, I am a concerned user of the hardware, and not a 
kernel dev myself. I have tested this change. This patch on top of Linus' 
mainline does allow qca6390 to work after warm reboot on my laptop.

wt
diff mbox series

Patch

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 4079254fb1c8..fc027da98297 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -2439,13 +2439,12 @@  static void qca_serdev_shutdown(struct device *dev)
 	struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
 	struct hci_uart *hu = &qcadev->serdev_hu;
 	struct hci_dev *hdev = hu->hdev;
-	struct qca_data *qca = hu->priv;
 	const u8 ibs_wake_cmd[] = { 0xFD };
 	const u8 edl_reset_soc_cmd[] = { 0x01, 0x00, 0xFC, 0x01, 0x05 };
 
 	if (qcadev->btsoc_type == QCA_QCA6390) {
-		if (test_bit(QCA_BT_OFF, &qca->flags) ||
-		    !test_bit(HCI_RUNNING, &hdev->flags))
+		if (test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks) ||
+		    hci_dev_test_flag(hdev, HCI_SETUP))
 			return;
 
 		serdev_device_write_flush(serdev);