--- x/net/bluetooth/hci_sync.c +++ y/net/bluetooth/hci_sync.c @@ -308,6 +308,7 @@ static void hci_cmd_sync_work(struct wor bt_dev_dbg(hdev, ""); + hci_req_sync_lock(hdev); /* Dequeue all entries and run them */ while (1) { struct hci_cmd_sync_work_entry *entry; @@ -328,15 +329,14 @@ static void hci_cmd_sync_work(struct wor 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); } + hci_req_sync_unlock(hdev); } static void hci_cmd_sync_cancel_work(struct work_struct *work) @@ -5185,6 +5185,15 @@ int hci_dev_close_sync(struct hci_dev *h cancel_delayed_work_sync(&adv_instance->rpa_expired_cb); } + mutex_lock(&hdev->cmd_sync_work_lock); + do { + struct hci_cmd_sync_work_entry *entry, *tmp; + + list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) + _hci_cmd_sync_cancel_entry(hdev, entry, -ECANCELED); + } while (0); + mutex_unlock(&hdev->cmd_sync_work_lock); + /* Avoid potential lockdep warnings from the *_flush() calls by * ensuring the workqueue is empty up front. */