Commit 275ddfeb authored by Luiz Augusto von Dentz's avatar Luiz Augusto von Dentz
Browse files

Bluetooth: hci_core: Fix triggering cmd_timer for HCI_OP_NOP



HCI_OP_NOP means no command was actually sent so there is no point in
triggering cmd_timer which may cause a hdev->reset in the process since
it is assumed that the controller is stuck processing a command.

Fixes: e2d471b7 ("Bluetooth: ISO: Fix not using SID from adv report")
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent 4015b979
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -4121,7 +4121,7 @@ static void hci_rx_work(struct work_struct *work)
	}
}

static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb)
static int hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb)
{
	int err;

@@ -4133,16 +4133,19 @@ static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb)
	if (!hdev->sent_cmd) {
		skb_queue_head(&hdev->cmd_q, skb);
		queue_work(hdev->workqueue, &hdev->cmd_work);
		return;
		return -EINVAL;
	}

	if (hci_skb_opcode(skb) != HCI_OP_NOP) {
		err = hci_send_frame(hdev, skb);
		if (err < 0) {
			hci_cmd_sync_cancel_sync(hdev, -err);
			return;
			return err;
		}
		atomic_dec(&hdev->cmd_cnt);
	} else {
		err = -ENODATA;
		kfree_skb(skb);
	}

	if (hdev->req_status == HCI_REQ_PEND &&
@@ -4150,12 +4153,15 @@ static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb)
		kfree_skb(hdev->req_skb);
		hdev->req_skb = skb_clone(hdev->sent_cmd, GFP_KERNEL);
	}

	return err;
}

static void hci_cmd_work(struct work_struct *work)
{
	struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_work);
	struct sk_buff *skb;
	int err;

	BT_DBG("%s cmd_cnt %d cmd queued %d", hdev->name,
	       atomic_read(&hdev->cmd_cnt), skb_queue_len(&hdev->cmd_q));
@@ -4166,7 +4172,9 @@ static void hci_cmd_work(struct work_struct *work)
		if (!skb)
			return;

		hci_send_cmd_sync(hdev, skb);
		err = hci_send_cmd_sync(hdev, skb);
		if (err)
			return;

		rcu_read_lock();
		if (test_bit(HCI_RESET, &hdev->flags) ||