]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-6.1/bluetooth-qca-fix-device-address-endianness.patch
6.1-stable patches
[thirdparty/kernel/stable-queue.git] / queue-6.1 / bluetooth-qca-fix-device-address-endianness.patch
CommitLineData
2c86f966
GKH
1From 77f45cca8bc55d00520a192f5a7715133591c83e Mon Sep 17 00:00:00 2001
2From: Johan Hovold <johan+linaro@kernel.org>
3Date: Wed, 20 Mar 2024 08:55:54 +0100
4Subject: Bluetooth: qca: fix device-address endianness
5
6From: Johan Hovold <johan+linaro@kernel.org>
7
8commit 77f45cca8bc55d00520a192f5a7715133591c83e upstream.
9
10The WCN6855 firmware on the Lenovo ThinkPad X13s expects the Bluetooth
11device address in big-endian order when setting it using the
12EDL_WRITE_BD_ADDR_OPCODE command.
13
14Presumably, this is the case for all non-ROME devices which all use the
15EDL_WRITE_BD_ADDR_OPCODE command for this (unlike the ROME devices which
16use a different command and expect the address in little-endian order).
17
18Reverse the little-endian address before setting it to make sure that
19the address can be configured using tools like btmgmt or using the
20'local-bd-address' devicetree property.
21
22Note that this can potentially break systems with boot firmware which
23has started relying on the broken behaviour and is incorrectly passing
24the address via devicetree in big-endian order.
25
26The only device affected by this should be the WCN3991 used in some
27Chromebooks. As ChromeOS updates the kernel and devicetree in lockstep,
28the new 'qcom,local-bd-address-broken' property can be used to determine
29if the firmware is buggy so that the underlying driver bug can be fixed
30without breaking backwards compatibility.
31
32Set the HCI_QUIRK_BDADDR_PROPERTY_BROKEN quirk for such platforms so
33that the address is reversed when parsing the address property.
34
35Fixes: 5c0a1001c8be ("Bluetooth: hci_qca: Add helper to set device address")
36Cc: stable@vger.kernel.org # 5.1
37Cc: Balakrishna Godavarthi <quic_bgodavar@quicinc.com>
38Cc: Matthias Kaehlcke <mka@chromium.org>
39Tested-by: Nikita Travkin <nikita@trvn.ru> # sc7180
40Reviewed-by: Douglas Anderson <dianders@chromium.org>
41Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
42Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
43Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
44---
45 drivers/bluetooth/btqca.c | 8 ++++++--
46 drivers/bluetooth/hci_qca.c | 10 ++++++++++
47 2 files changed, 16 insertions(+), 2 deletions(-)
48
49--- a/drivers/bluetooth/btqca.c
50+++ b/drivers/bluetooth/btqca.c
51@@ -758,11 +758,15 @@ EXPORT_SYMBOL_GPL(qca_uart_setup);
52
53 int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
54 {
55+ bdaddr_t bdaddr_swapped;
56 struct sk_buff *skb;
57 int err;
58
59- skb = __hci_cmd_sync_ev(hdev, EDL_WRITE_BD_ADDR_OPCODE, 6, bdaddr,
60- HCI_EV_VENDOR, HCI_INIT_TIMEOUT);
61+ baswap(&bdaddr_swapped, bdaddr);
62+
63+ skb = __hci_cmd_sync_ev(hdev, EDL_WRITE_BD_ADDR_OPCODE, 6,
64+ &bdaddr_swapped, HCI_EV_VENDOR,
65+ HCI_INIT_TIMEOUT);
66 if (IS_ERR(skb)) {
67 err = PTR_ERR(skb);
68 bt_dev_err(hdev, "QCA Change address cmd failed (%d)", err);
69--- a/drivers/bluetooth/hci_qca.c
70+++ b/drivers/bluetooth/hci_qca.c
71@@ -225,6 +225,7 @@ struct qca_serdev {
72 struct qca_power *bt_power;
73 u32 init_speed;
74 u32 oper_speed;
75+ bool bdaddr_property_broken;
76 const char *firmware_name;
77 };
78
79@@ -1787,6 +1788,7 @@ static int qca_setup(struct hci_uart *hu
80 const char *firmware_name = qca_get_firmware_name(hu);
81 int ret;
82 struct qca_btsoc_version ver;
83+ struct qca_serdev *qcadev;
84 const char *soc_name;
85
86 ret = qca_check_speeds(hu);
87@@ -1845,6 +1847,11 @@ retry:
88 case QCA_WCN6855:
89 case QCA_WCN7850:
90 set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
91+
92+ qcadev = serdev_device_get_drvdata(hu->serdev);
93+ if (qcadev->bdaddr_property_broken)
94+ set_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks);
95+
96 hci_set_aosp_capable(hdev);
97
98 ret = qca_read_soc_version(hdev, &ver, soc_type);
99@@ -2212,6 +2219,9 @@ static int qca_serdev_probe(struct serde
100 if (!qcadev->oper_speed)
101 BT_DBG("UART will pick default operating speed");
102
103+ qcadev->bdaddr_property_broken = device_property_read_bool(&serdev->dev,
104+ "qcom,local-bd-address-broken");
105+
106 if (data)
107 qcadev->btsoc_type = data->soc_type;
108 else