Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 67d8cee4 authored by John Keeping's avatar John Keeping Committed by Marcel Holtmann
Browse files

Bluetooth: use wait_event API instead of open-coding it



I've seen timeout errors from HCI commands where it looks like
schedule_timeout() has returned immediately; additional logging for the
error case gives:

	req_status=1 req_result=0 remaining=10000 jiffies

so the device is still in state HCI_REQ_PEND and the value returned by
schedule_timeout() is the same as the original timeout (HCI_INIT_TIMEOUT
on a system with HZ=1000).

Use wait_event_interruptible_timeout() instead of open-coding similar
behaviour which is subject to the spurious failure described above.

Signed-off-by: default avatarJohn Keeping <john@metanate.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent ee649346
Loading
Loading
Loading
Loading
+7 −23
Original line number Original line Diff line number Diff line
@@ -122,7 +122,6 @@ void hci_req_sync_cancel(struct hci_dev *hdev, int err)
struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
				  const void *param, u8 event, u32 timeout)
				  const void *param, u8 event, u32 timeout)
{
{
	DECLARE_WAITQUEUE(wait, current);
	struct hci_request req;
	struct hci_request req;
	struct sk_buff *skb;
	struct sk_buff *skb;
	int err = 0;
	int err = 0;
@@ -135,21 +134,14 @@ struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,


	hdev->req_status = HCI_REQ_PEND;
	hdev->req_status = HCI_REQ_PEND;


	add_wait_queue(&hdev->req_wait_q, &wait);
	set_current_state(TASK_INTERRUPTIBLE);

	err = hci_req_run_skb(&req, hci_req_sync_complete);
	err = hci_req_run_skb(&req, hci_req_sync_complete);
	if (err < 0) {
	if (err < 0)
		remove_wait_queue(&hdev->req_wait_q, &wait);
		set_current_state(TASK_RUNNING);
		return ERR_PTR(err);
		return ERR_PTR(err);
	}


	schedule_timeout(timeout);
	err = wait_event_interruptible_timeout(hdev->req_wait_q,
			hdev->req_status != HCI_REQ_PEND, timeout);


	remove_wait_queue(&hdev->req_wait_q, &wait);
	if (err == -ERESTARTSYS)

	if (signal_pending(current))
		return ERR_PTR(-EINTR);
		return ERR_PTR(-EINTR);


	switch (hdev->req_status) {
	switch (hdev->req_status) {
@@ -197,7 +189,6 @@ int __hci_req_sync(struct hci_dev *hdev, int (*func)(struct hci_request *req,
		   unsigned long opt, u32 timeout, u8 *hci_status)
		   unsigned long opt, u32 timeout, u8 *hci_status)
{
{
	struct hci_request req;
	struct hci_request req;
	DECLARE_WAITQUEUE(wait, current);
	int err = 0;
	int err = 0;


	BT_DBG("%s start", hdev->name);
	BT_DBG("%s start", hdev->name);
@@ -213,16 +204,10 @@ int __hci_req_sync(struct hci_dev *hdev, int (*func)(struct hci_request *req,
		return err;
		return err;
	}
	}


	add_wait_queue(&hdev->req_wait_q, &wait);
	set_current_state(TASK_INTERRUPTIBLE);

	err = hci_req_run_skb(&req, hci_req_sync_complete);
	err = hci_req_run_skb(&req, hci_req_sync_complete);
	if (err < 0) {
	if (err < 0) {
		hdev->req_status = 0;
		hdev->req_status = 0;


		remove_wait_queue(&hdev->req_wait_q, &wait);
		set_current_state(TASK_RUNNING);

		/* ENODATA means the HCI request command queue is empty.
		/* ENODATA means the HCI request command queue is empty.
		 * This can happen when a request with conditionals doesn't
		 * This can happen when a request with conditionals doesn't
		 * trigger any commands to be sent. This is normal behavior
		 * trigger any commands to be sent. This is normal behavior
@@ -240,11 +225,10 @@ int __hci_req_sync(struct hci_dev *hdev, int (*func)(struct hci_request *req,
		return err;
		return err;
	}
	}


	schedule_timeout(timeout);
	err = wait_event_interruptible_timeout(hdev->req_wait_q,

			hdev->req_status != HCI_REQ_PEND, timeout);
	remove_wait_queue(&hdev->req_wait_q, &wait);


	if (signal_pending(current))
	if (err == -ERESTARTSYS)
		return -EINTR;
		return -EINTR;


	switch (hdev->req_status) {
	switch (hdev->req_status) {