Skip to content
This repository was archived by the owner on Jan 10, 2023. It is now read-only.

Commit 8603d49

Browse files
jprvitagregkh
authored andcommitted
Bluetooth: Ignore CC events not matching the last HCI command
[ Upstream commit f80c5dad7b6467b884c445ffea45985793b4b2d0 ] This commit makes the kernel not send the next queued HCI command until a command complete arrives for the last HCI command sent to the controller. This change avoids a problem with some buggy controllers (seen on two SKUs of QCA9377) that send an extra command complete event for the previous command after the kernel had already sent a new HCI command to the controller. The problem was reproduced when starting an active scanning procedure, where an extra command complete event arrives for the LE_SET_RANDOM_ADDR command. When this happends the kernel ends up not processing the command complete for the following commmand, LE_SET_SCAN_PARAM, and ultimately behaving as if a passive scanning procedure was being performed, when in fact controller is performing an active scanning procedure. This makes it impossible to discover BLE devices as no device found events are sent to userspace. This problem is reproducible on 100% of the attempts on the affected controllers. The extra command complete event can be seen at timestamp 27.420131 on the btmon logs bellow. Bluetooth monitor ver 5.50 = Note: Linux version 5.0.0+ (x86_64) 0.352340 = Note: Bluetooth subsystem version 2.22 0.352343 = New Index: 80:C5:F2:8F:87:84 (Primary,USB,hci0) [hci0] 0.352344 = Open Index: 80:C5:F2:8F:87:84 [hci0] 0.352345 = Index Info: 80:C5:F2:8F:87:84 (Qualcomm) [hci0] 0.352346 @ MGMT Open: bluetoothd (privileged) version 1.14 {0x0001} 0.352347 @ MGMT Open: btmon (privileged) version 1.14 {0x0002} 0.352366 @ MGMT Open: btmgmt (privileged) version 1.14 {0x0003} 27.302164 @ MGMT Command: Start Discovery (0x0023) plen 1 {0x0003} [hci0] 27.302310 Address type: 0x06 LE Public LE Random < HCI Command: LE Set Random Address (0x08|0x0005) plen 6 #1 [hci0] 27.302496 Address: 15:60:F2:91:B2:24 (Non-Resolvable) > HCI Event: Command Complete (0x0e) plen 4 #2 [hci0] 27.419117 LE Set Random Address (0x08|0x0005) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7 #3 [hci0] 27.419244 Type: Active (0x01) Interval: 11.250 msec (0x0012) Window: 11.250 msec (0x0012) Own address type: Random (0x01) Filter policy: Accept all advertisement (0x00) > HCI Event: Command Complete (0x0e) plen 4 #4 [hci0] 27.420131 LE Set Random Address (0x08|0x0005) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 #5 [hci0] 27.420259 Scanning: Enabled (0x01) Filter duplicates: Enabled (0x01) > HCI Event: Command Complete (0x0e) plen 4 #6 [hci0] 27.420969 LE Set Scan Parameters (0x08|0x000b) ncmd 1 Status: Success (0x00) > HCI Event: Command Complete (0x0e) plen 4 #7 [hci0] 27.421983 LE Set Scan Enable (0x08|0x000c) ncmd 1 Status: Success (0x00) @ MGMT Event: Command Complete (0x0001) plen 4 {0x0003} [hci0] 27.422059 Start Discovery (0x0023) plen 1 Status: Success (0x00) Address type: 0x06 LE Public LE Random @ MGMT Event: Discovering (0x0013) plen 2 {0x0003} [hci0] 27.422067 Address type: 0x06 LE Public LE Random Discovery: Enabled (0x01) @ MGMT Event: Discovering (0x0013) plen 2 {0x0002} [hci0] 27.422067 Address type: 0x06 LE Public LE Random Discovery: Enabled (0x01) @ MGMT Event: Discovering (0x0013) plen 2 {0x0001} [hci0] 27.422067 Address type: 0x06 LE Public LE Random Discovery: Enabled (0x01) Signed-off-by: João Paulo Rechi Vita <jprvita@endlessm.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 6d9cfab commit 8603d49

5 files changed

Lines changed: 24 additions & 0 deletions

File tree

include/net/bluetooth/hci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ enum {
270270
HCI_FORCE_BREDR_SMP,
271271
HCI_FORCE_STATIC_ADDR,
272272
HCI_LL_RPA_RESOLUTION,
273+
HCI_CMD_PENDING,
273274

274275
__HCI_NUM_FLAGS,
275276
};

net/bluetooth/hci_core.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4274,6 +4274,9 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status,
42744274
return;
42754275
}
42764276

4277+
/* If we reach this point this event matches the last command sent */
4278+
hci_dev_clear_flag(hdev, HCI_CMD_PENDING);
4279+
42774280
/* If the command succeeded and there's still more commands in
42784281
* this request the request is not yet complete.
42794282
*/
@@ -4384,6 +4387,8 @@ static void hci_cmd_work(struct work_struct *work)
43844387

43854388
hdev->sent_cmd = skb_clone(skb, GFP_KERNEL);
43864389
if (hdev->sent_cmd) {
4390+
if (hci_req_status_pend(hdev))
4391+
hci_dev_set_flag(hdev, HCI_CMD_PENDING);
43874392
atomic_dec(&hdev->cmd_cnt);
43884393
hci_send_frame(hdev, skb);
43894394
if (test_bit(HCI_RESET, &hdev->flags))

net/bluetooth/hci_event.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3357,6 +3357,12 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
33573357
hci_req_cmd_complete(hdev, *opcode, *status, req_complete,
33583358
req_complete_skb);
33593359

3360+
if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
3361+
bt_dev_err(hdev,
3362+
"unexpected event for opcode 0x%4.4x", *opcode);
3363+
return;
3364+
}
3365+
33603366
if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
33613367
queue_work(hdev->workqueue, &hdev->cmd_work);
33623368
}
@@ -3464,6 +3470,12 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
34643470
hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete,
34653471
req_complete_skb);
34663472

3473+
if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
3474+
bt_dev_err(hdev,
3475+
"unexpected event for opcode 0x%4.4x", *opcode);
3476+
return;
3477+
}
3478+
34673479
if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
34683480
queue_work(hdev->workqueue, &hdev->cmd_work);
34693481
}

net/bluetooth/hci_request.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ void hci_req_purge(struct hci_request *req)
4646
skb_queue_purge(&req->cmd_q);
4747
}
4848

49+
bool hci_req_status_pend(struct hci_dev *hdev)
50+
{
51+
return hdev->req_status == HCI_REQ_PEND;
52+
}
53+
4954
static int req_run(struct hci_request *req, hci_req_complete_t complete,
5055
hci_req_complete_skb_t complete_skb)
5156
{

net/bluetooth/hci_request.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ struct hci_request {
3737

3838
void hci_req_init(struct hci_request *req, struct hci_dev *hdev);
3939
void hci_req_purge(struct hci_request *req);
40+
bool hci_req_status_pend(struct hci_dev *hdev);
4041
int hci_req_run(struct hci_request *req, hci_req_complete_t complete);
4142
int hci_req_run_skb(struct hci_request *req, hci_req_complete_skb_t complete);
4243
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen,

0 commit comments

Comments
 (0)