]>
Commit | Line | Data |
---|---|---|
6ea0374e GKH |
1 | From 32868e126c78876a8a5ddfcb6ac8cb2fffcf4d27 Mon Sep 17 00:00:00 2001 |
2 | From: Johan Hovold <johan+linaro@kernel.org> | |
3 | Date: Tue, 16 Apr 2024 11:15:09 +0200 | |
4 | Subject: Bluetooth: qca: fix invalid device address check | |
5 | ||
6 | From: Johan Hovold <johan+linaro@kernel.org> | |
7 | ||
8 | commit 32868e126c78876a8a5ddfcb6ac8cb2fffcf4d27 upstream. | |
9 | ||
10 | Qualcomm Bluetooth controllers may not have been provisioned with a | |
11 | valid device address and instead end up using the default address | |
12 | 00:00:00:00:5a:ad. | |
13 | ||
14 | This was previously believed to be due to lack of persistent storage for | |
15 | the address but it may also be due to integrators opting to not use the | |
16 | on-chip OTP memory and instead store the address elsewhere (e.g. in | |
17 | storage managed by secure world firmware). | |
18 | ||
19 | According to Qualcomm, at least WCN6750, WCN6855 and WCN7850 have | |
20 | on-chip OTP storage for the address. | |
21 | ||
22 | As the device type alone cannot be used to determine when the address is | |
23 | valid, instead read back the address during setup() and only set the | |
24 | HCI_QUIRK_USE_BDADDR_PROPERTY flag when needed. | |
25 | ||
26 | This specifically makes sure that controllers that have been provisioned | |
27 | with an address do not start as unconfigured. | |
28 | ||
29 | Reported-by: Janaki Ramaiah Thota <quic_janathot@quicinc.com> | |
30 | Link: https://lore.kernel.org/r/124a7d54-5a18-4be7-9a76-a12017f6cce5@quicinc.com/ | |
31 | Fixes: 5971752de44c ("Bluetooth: hci_qca: Set HCI_QUIRK_USE_BDADDR_PROPERTY for wcn3990") | |
32 | Fixes: e668eb1e1578 ("Bluetooth: hci_core: Don't stop BT if the BD address missing in dts") | |
33 | Fixes: 6945795bc81a ("Bluetooth: fix use-bdaddr-property quirk") | |
34 | Cc: stable@vger.kernel.org # 6.5 | |
35 | Cc: Matthias Kaehlcke <mka@chromium.org> | |
36 | Signed-off-by: Johan Hovold <johan+linaro@kernel.org> | |
37 | Reported-by: Janaki Ramaiah Thota <quic_janathot@quicinc.com> | |
38 | Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | |
39 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
40 | --- | |
41 | drivers/bluetooth/btqca.c | 38 ++++++++++++++++++++++++++++++++++++++ | |
42 | drivers/bluetooth/hci_qca.c | 2 -- | |
43 | 2 files changed, 38 insertions(+), 2 deletions(-) | |
44 | ||
45 | --- a/drivers/bluetooth/btqca.c | |
46 | +++ b/drivers/bluetooth/btqca.c | |
47 | @@ -15,6 +15,8 @@ | |
48 | ||
49 | #define VERSION "0.1" | |
50 | ||
51 | +#define QCA_BDADDR_DEFAULT (&(bdaddr_t) {{ 0xad, 0x5a, 0x00, 0x00, 0x00, 0x00 }}) | |
52 | + | |
53 | int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver, | |
54 | enum qca_btsoc_type soc_type) | |
55 | { | |
56 | @@ -612,6 +614,38 @@ int qca_set_bdaddr_rome(struct hci_dev * | |
57 | } | |
58 | EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome); | |
59 | ||
60 | +static int qca_check_bdaddr(struct hci_dev *hdev) | |
61 | +{ | |
62 | + struct hci_rp_read_bd_addr *bda; | |
63 | + struct sk_buff *skb; | |
64 | + int err; | |
65 | + | |
66 | + if (bacmp(&hdev->public_addr, BDADDR_ANY)) | |
67 | + return 0; | |
68 | + | |
69 | + skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL, | |
70 | + HCI_INIT_TIMEOUT); | |
71 | + if (IS_ERR(skb)) { | |
72 | + err = PTR_ERR(skb); | |
73 | + bt_dev_err(hdev, "Failed to read device address (%d)", err); | |
74 | + return err; | |
75 | + } | |
76 | + | |
77 | + if (skb->len != sizeof(*bda)) { | |
78 | + bt_dev_err(hdev, "Device address length mismatch"); | |
79 | + kfree_skb(skb); | |
80 | + return -EIO; | |
81 | + } | |
82 | + | |
83 | + bda = (struct hci_rp_read_bd_addr *)skb->data; | |
84 | + if (!bacmp(&bda->bdaddr, QCA_BDADDR_DEFAULT)) | |
85 | + set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); | |
86 | + | |
87 | + kfree_skb(skb); | |
88 | + | |
89 | + return 0; | |
90 | +} | |
91 | + | |
92 | static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size, | |
93 | struct qca_btsoc_version ver, u8 rom_ver, u16 bid) | |
94 | { | |
95 | @@ -818,6 +852,10 @@ int qca_uart_setup(struct hci_dev *hdev, | |
96 | break; | |
97 | } | |
98 | ||
99 | + err = qca_check_bdaddr(hdev); | |
100 | + if (err) | |
101 | + return err; | |
102 | + | |
103 | bt_dev_info(hdev, "QCA setup on UART is completed"); | |
104 | ||
105 | return 0; | |
106 | --- a/drivers/bluetooth/hci_qca.c | |
107 | +++ b/drivers/bluetooth/hci_qca.c | |
108 | @@ -1905,8 +1905,6 @@ retry: | |
109 | case QCA_WCN6750: | |
110 | case QCA_WCN6855: | |
111 | case QCA_WCN7850: | |
112 | - set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); | |
113 | - | |
114 | qcadev = serdev_device_get_drvdata(hu->serdev); | |
115 | if (qcadev->bdaddr_property_broken) | |
116 | set_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks); |