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:
Родитель
815d512192
Коммит
008ee9eb8a
|
@ -276,40 +276,37 @@ EXPORT_SYMBOL(__hci_cmd_sync_status);
|
||||||
static void hci_cmd_sync_work(struct work_struct *work)
|
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_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, "");
|
bt_dev_dbg(hdev, "");
|
||||||
|
|
||||||
mutex_lock(&hdev->cmd_sync_work_lock);
|
/* Dequeue all entries and run them */
|
||||||
entry = list_first_entry(&hdev->cmd_sync_work_list,
|
while (1) {
|
||||||
struct hci_cmd_sync_work_entry, list);
|
struct hci_cmd_sync_work_entry *entry;
|
||||||
if (entry) {
|
|
||||||
list_del(&entry->list);
|
mutex_lock(&hdev->cmd_sync_work_lock);
|
||||||
func = entry->func;
|
entry = list_first_entry_or_null(&hdev->cmd_sync_work_list,
|
||||||
data = entry->data;
|
struct hci_cmd_sync_work_entry,
|
||||||
destroy = entry->destroy;
|
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);
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче