Commit 008ee9eb authored by Luiz Augusto von Dentz's avatar Luiz Augusto von Dentz Committed by Marcel Holtmann

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: 6a98e383 ("Bluetooth: Add helper for serialized HCI command execution")
Tested-by: default avatarChris Clayton <chris2553@googlemail.com>
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 815d5121
......@@ -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;
kfree(entry);
} else {
func = NULL;
data = NULL;
destroy = NULL;
}
mutex_unlock(&hdev->cmd_sync_work_lock);
/* Dequeue all entries and run them */
while (1) {
struct hci_cmd_sync_work_entry *entry;
if (func) {
int err;
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;
hci_req_sync_lock(hdev);
bt_dev_dbg(hdev, "entry %p", entry);
err = func(hdev, data);
if (entry->func) {
int err;
if (destroy)
destroy(hdev, data, 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);
}
hci_req_sync_unlock(hdev);
kfree(entry);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment