]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
Bluetooth: hci_core: Fix triggering cmd_timer for HCI_OP_NOP
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Thu, 13 Nov 2025 14:49:27 +0000 (09:49 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 6 Dec 2025 21:27:30 +0000 (06:27 +0900)
[ Upstream commit 275ddfeb3fdc274050c2173ffd985b1e80a9aa37 ]

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: e2d471b7806b ("Bluetooth: ISO: Fix not using SID from adv report")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/bluetooth/hci_core.c

index 55e0722fd06622310fb0b28b380860c49b9b277a..72c7607aac209bdb8e9d84d02062e4808baa0ee9 100644 (file)
@@ -4093,7 +4093,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;
 
@@ -4105,16 +4105,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 &&
@@ -4122,12 +4125,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));
@@ -4138,7 +4144,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) ||