]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/6.6.26/bluetooth-qca-fix-device-address-endianness.patch
Linux 6.6.26
[thirdparty/kernel/stable-queue.git] / releases / 6.6.26 / bluetooth-qca-fix-device-address-endianness.patch
1 From 77f45cca8bc55d00520a192f5a7715133591c83e Mon Sep 17 00:00:00 2001
2 From: Johan Hovold <johan+linaro@kernel.org>
3 Date: Wed, 20 Mar 2024 08:55:54 +0100
4 Subject: Bluetooth: qca: fix device-address endianness
5
6 From: Johan Hovold <johan+linaro@kernel.org>
7
8 commit 77f45cca8bc55d00520a192f5a7715133591c83e upstream.
9
10 The WCN6855 firmware on the Lenovo ThinkPad X13s expects the Bluetooth
11 device address in big-endian order when setting it using the
12 EDL_WRITE_BD_ADDR_OPCODE command.
13
14 Presumably, this is the case for all non-ROME devices which all use the
15 EDL_WRITE_BD_ADDR_OPCODE command for this (unlike the ROME devices which
16 use a different command and expect the address in little-endian order).
17
18 Reverse the little-endian address before setting it to make sure that
19 the address can be configured using tools like btmgmt or using the
20 'local-bd-address' devicetree property.
21
22 Note that this can potentially break systems with boot firmware which
23 has started relying on the broken behaviour and is incorrectly passing
24 the address via devicetree in big-endian order.
25
26 The only device affected by this should be the WCN3991 used in some
27 Chromebooks. As ChromeOS updates the kernel and devicetree in lockstep,
28 the new 'qcom,local-bd-address-broken' property can be used to determine
29 if the firmware is buggy so that the underlying driver bug can be fixed
30 without breaking backwards compatibility.
31
32 Set the HCI_QUIRK_BDADDR_PROPERTY_BROKEN quirk for such platforms so
33 that the address is reversed when parsing the address property.
34
35 Fixes: 5c0a1001c8be ("Bluetooth: hci_qca: Add helper to set device address")
36 Cc: stable@vger.kernel.org # 5.1
37 Cc: Balakrishna Godavarthi <quic_bgodavar@quicinc.com>
38 Cc: Matthias Kaehlcke <mka@chromium.org>
39 Tested-by: Nikita Travkin <nikita@trvn.ru> # sc7180
40 Reviewed-by: Douglas Anderson <dianders@chromium.org>
41 Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
42 Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
43 Signed-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 @@ -1824,6 +1825,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 @@ -1882,6 +1884,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 @@ -2253,6 +2260,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