mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 13:44:15 +08:00
Bluetooth: hci_sync: Fix not processing all entries on cmd_sync_work
hci_cmd_sync_queue can be called multiple times, each adding a
hci_cmd_sync_work_entry, before hci_cmd_sync_work is run so this makes
sure they are all dequeued properly otherwise it creates a backlog of
entries that are never run.
Link: https://lore.kernel.org/all/CAJCQCtSeUtHCgsHXLGrSTWKmyjaQDbDNpP4rb0i+RE+L2FTXSA@mail.gmail.com/T/
Fixes: 6a98e3836f
("Bluetooth: Add helper for serialized HCI command execution")
Tested-by: Chris Clayton <chris2553@googlemail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
815d512192
commit
008ee9eb8a
@ -276,40 +276,37 @@ EXPORT_SYMBOL(__hci_cmd_sync_status);
|
||||
static void hci_cmd_sync_work(struct work_struct *work)
|
||||
{
|
||||
struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_sync_work);
|
||||
struct hci_cmd_sync_work_entry *entry;
|
||||
hci_cmd_sync_work_func_t func;
|
||||
hci_cmd_sync_work_destroy_t destroy;
|
||||
void *data;
|
||||
|
||||
bt_dev_dbg(hdev, "");
|
||||
|
||||
mutex_lock(&hdev->cmd_sync_work_lock);
|
||||
entry = list_first_entry(&hdev->cmd_sync_work_list,
|
||||
struct hci_cmd_sync_work_entry, list);
|
||||
if (entry) {
|
||||
list_del(&entry->list);
|
||||
func = entry->func;
|
||||
data = entry->data;
|
||||
destroy = entry->destroy;
|
||||
/* Dequeue all entries and run them */
|
||||
while (1) {
|
||||
struct hci_cmd_sync_work_entry *entry;
|
||||
|
||||
mutex_lock(&hdev->cmd_sync_work_lock);
|
||||
entry = list_first_entry_or_null(&hdev->cmd_sync_work_list,
|
||||
struct hci_cmd_sync_work_entry,
|
||||
list);
|
||||
if (entry)
|
||||
list_del(&entry->list);
|
||||
mutex_unlock(&hdev->cmd_sync_work_lock);
|
||||
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
bt_dev_dbg(hdev, "entry %p", entry);
|
||||
|
||||
if (entry->func) {
|
||||
int err;
|
||||
|
||||
hci_req_sync_lock(hdev);
|
||||
err = entry->func(hdev, entry->data);
|
||||
if (entry->destroy)
|
||||
entry->destroy(hdev, entry->data, err);
|
||||
hci_req_sync_unlock(hdev);
|
||||
}
|
||||
|
||||
kfree(entry);
|
||||
} else {
|
||||
func = NULL;
|
||||
data = NULL;
|
||||
destroy = NULL;
|
||||
}
|
||||
mutex_unlock(&hdev->cmd_sync_work_lock);
|
||||
|
||||
if (func) {
|
||||
int err;
|
||||
|
||||
hci_req_sync_lock(hdev);
|
||||
|
||||
err = func(hdev, data);
|
||||
|
||||
if (destroy)
|
||||
destroy(hdev, data, err);
|
||||
|
||||
hci_req_sync_unlock(hdev);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user