Commit 9f3956d6 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Luiz Augusto von Dentz says:

====================
bluetooth pull request for net:

 - Fix regression with processing of MGMT commands
 - Fix unbalanced unlock in Set Device Flags

* tag 'for-net-2022-03-03' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
  Bluetooth: hci_sync: Fix not processing all entries on cmd_sync_work
  Bluetooth: hci_core: Fix unbalanced unlock in set_device_flags()
====================

Link: https://lore.kernel.org/r/20220303210743.314679-1-luiz.dentz@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents b949c21f 008ee9eb
Loading
Loading
Loading
Loading
+23 −26
Original line number Original line Diff line number Diff line
@@ -276,41 +276,38 @@ 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, "");


	/* Dequeue all entries and run them */
	while (1) {
		struct hci_cmd_sync_work_entry *entry;

		mutex_lock(&hdev->cmd_sync_work_lock);
		mutex_lock(&hdev->cmd_sync_work_lock);
	entry = list_first_entry(&hdev->cmd_sync_work_list,
		entry = list_first_entry_or_null(&hdev->cmd_sync_work_list,
				 struct hci_cmd_sync_work_entry, list);
						 struct hci_cmd_sync_work_entry,
	if (entry) {
						 list);
		if (entry)
			list_del(&entry->list);
			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);
		mutex_unlock(&hdev->cmd_sync_work_lock);


	if (func) {
		if (!entry)
		int err;
			break;

		hci_req_sync_lock(hdev);


		err = func(hdev, data);
		bt_dev_dbg(hdev, "entry %p", entry);


		if (destroy)
		if (entry->func) {
			destroy(hdev, data, err);
			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);
			hci_req_sync_unlock(hdev);
		}
		}

		kfree(entry);
	}
}
}


static void hci_cmd_sync_cancel_work(struct work_struct *work)
static void hci_cmd_sync_cancel_work(struct work_struct *work)
+1 −1
Original line number Original line Diff line number Diff line
@@ -4541,9 +4541,9 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
		}
		}
	}
	}


done:
	hci_dev_unlock(hdev);
	hci_dev_unlock(hdev);


done:
	if (status == MGMT_STATUS_SUCCESS)
	if (status == MGMT_STATUS_SUCCESS)
		device_flags_changed(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
		device_flags_changed(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
				     supported_flags, current_flags);
				     supported_flags, current_flags);