Skip to content

Commit 5d44ab9

Browse files
stephan-ghVudentz
authored andcommitted
Bluetooth: btqcomsmd: Fix command timeout after setting BD address
On most devices using the btqcomsmd driver (e.g. the DragonBoard 410c and other devices based on the Qualcomm MSM8916/MSM8909/... SoCs) the Bluetooth firmware seems to become unresponsive for a while after setting the BD address. On recent kernel versions (at least 5.17+) this often causes timeouts for subsequent commands, e.g. the HCI reset sent by the Bluetooth core during initialization: Bluetooth: hci0: Opcode 0x c03 failed: -110 Unfortunately this behavior does not seem to be documented anywhere. Experimentation suggests that the minimum necessary delay to avoid the problem is ~150us. However, to be sure add a sleep for > 1ms in case it is a bit longer on other firmware versions. Older kernel versions are likely also affected, although perhaps with slightly different errors or less probability. Side effects can easily hide the issue in most cases, e.g. unrelated incoming interrupts that cause the necessary delay. Fixes: 1511cc7 ("Bluetooth: Introduce Qualcomm WCNSS SMD based HCI driver") Signed-off-by: Stephan Gerhold <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 902160c commit 5d44ab9

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

drivers/bluetooth/btqcomsmd.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,21 @@ static int btqcomsmd_setup(struct hci_dev *hdev)
122122
return 0;
123123
}
124124

125+
static int btqcomsmd_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
126+
{
127+
int ret;
128+
129+
ret = qca_set_bdaddr_rome(hdev, bdaddr);
130+
if (ret)
131+
return ret;
132+
133+
/* The firmware stops responding for a while after setting the bdaddr,
134+
* causing timeouts for subsequent commands. Sleep a bit to avoid this.
135+
*/
136+
usleep_range(1000, 10000);
137+
return 0;
138+
}
139+
125140
static int btqcomsmd_probe(struct platform_device *pdev)
126141
{
127142
struct btqcomsmd *btq;
@@ -162,7 +177,7 @@ static int btqcomsmd_probe(struct platform_device *pdev)
162177
hdev->close = btqcomsmd_close;
163178
hdev->send = btqcomsmd_send;
164179
hdev->setup = btqcomsmd_setup;
165-
hdev->set_bdaddr = qca_set_bdaddr_rome;
180+
hdev->set_bdaddr = btqcomsmd_set_bdaddr;
166181

167182
ret = hci_register_dev(hdev);
168183
if (ret < 0)

0 commit comments

Comments
 (0)