From de74a350782cc5f42f2f3b58ffd6771c4dea27ab Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Thu, 16 Jun 2022 19:19:49 +0000
Subject: [PATCH] fix spreadtrum (sprd) bluetooth broken park link status

---
 drivers/bluetooth/hci_ldisc.c | 6 ++++++
 include/net/bluetooth/hci.h   | 6 ++++++
 net/bluetooth/hci_core.c      | 2 +-
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 5ed2cfa7da1..0c2448e73c1 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -652,6 +652,12 @@ static int hci_uart_register_dev(struct hci_uart *hu)
 	hdev->setup = hci_uart_setup;
 	SET_HCIDEV_DEV(hdev, hu->tty->dev);
 
+	// Set the broken Park link status quirk, specific for spreadtrum (sprd)
+	// bluetooth devices
+	if (hdev->manufacturer == 0xffff && hu->tty->driver &&
+		strncmp(hu->tty->driver->name, "ttyBT", 5) == 0)
+		set_bit(HCI_QUIRK_BROKEN_PARK_LINK_STATUS, &hdev->quirks);
+
 	if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
 		set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
 
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 2ed6af29352..5fef855cfdf 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -262,6 +262,12 @@ enum {
 	 * during the hdev->setup vendor callback.
 	 */
 	HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER,
+
+	/*
+	 * Device declares that support Park link status, but it really
+	 * does not support it and fails to initialize
+	 */
+	HCI_QUIRK_BROKEN_PARK_LINK_STATUS
 };
 
 /* HCI device flags */
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index cdca5373230..123ce7042bb 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -511,7 +511,7 @@ static void hci_setup_link_policy(struct hci_request *req)
 		link_policy |= HCI_LP_HOLD;
 	if (lmp_sniff_capable(hdev))
 		link_policy |= HCI_LP_SNIFF;
-	if (lmp_park_capable(hdev))
+	if (lmp_park_capable(hdev) && !test_bit(HCI_QUIRK_BROKEN_PARK_LINK_STATUS, &hdev->quirks))
 		link_policy |= HCI_LP_PARK;
 
 	cp.policy = cpu_to_le16(link_policy);
-- 
2.30.2

