]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Bluetooth: btintel_pcie: Make driver wait for alive interrupt
authorKiran K <kiran.k@intel.com>
Mon, 21 Jul 2025 09:44:36 +0000 (15:14 +0530)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 23 Jul 2025 14:34:14 +0000 (10:34 -0400)
The firmware raises an alive interrupt upon receiving the HCI_RESET or
BTINTEL_HCI_OP_RESET (Intel reset - 0xfc01) command. This change fixes
the driver to properly wait for the alive interrupt to avoid driver
sending commands to firmware before it is ready to process.

For details on the handshake between the driver and firmware, refer to
commit 05c200c8f029 ("Bluetooth: btintel_pcie: Add handshake between
driver and firmware").

As the driver needs to handle two interrupts for HCI_OP_RESET and
BTINTEL_HCI_OP_RESET, the firmware ensures that the TX completion
interrupt is always followed by the alive interrupt.

Fixes: 05c200c8f029 ("Bluetooth: btintel_pcie: Add handshake between driver and firmware")
Signed-off-by: Sai Teja Aluvala <aluvala.sai.teja@intel.com>
Signed-off-by: Kiran K <kiran.k@intel.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
drivers/bluetooth/btintel_pcie.c

index 60528bdc4316feb4b302988d2b2b7e54a3968ce9..a17c438784ae6d0d9a00e5bc126138b86d447d03 100644 (file)
@@ -947,11 +947,13 @@ static void btintel_pcie_msix_gp0_handler(struct btintel_pcie_data *data)
        case BTINTEL_PCIE_INTEL_HCI_RESET1:
                if (btintel_pcie_in_op(data)) {
                        submit_rx = true;
+                       signal_waitq = true;
                        break;
                }
 
                if (btintel_pcie_in_iml(data)) {
                        submit_rx = true;
+                       signal_waitq = true;
                        data->alive_intr_ctxt = BTINTEL_PCIE_FW_DL;
                        break;
                }
@@ -1985,8 +1987,11 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
                        if (opcode == BTINTEL_HCI_OP_RESET)
                                btintel_pcie_inject_cmd_complete(hdev, opcode);
                }
-               /* Firmware raises alive interrupt on HCI_OP_RESET */
-               if (opcode == HCI_OP_RESET)
+
+               /* Firmware raises alive interrupt on HCI_OP_RESET or
+                * BTINTEL_HCI_OP_RESET
+                */
+               if (opcode == HCI_OP_RESET || opcode == BTINTEL_HCI_OP_RESET)
                        data->gp0_received = false;
 
                hdev->stat.cmd_tx++;
@@ -2025,17 +2030,16 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
                bt_dev_dbg(data->hdev, "sent cmd: 0x%4.4x alive context changed: %s  ->  %s",
                           opcode, btintel_pcie_alivectxt_state2str(old_ctxt),
                           btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt));
-               if (opcode == HCI_OP_RESET) {
-                       ret = wait_event_timeout(data->gp0_wait_q,
-                                                data->gp0_received,
-                                                msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS));
-                       if (!ret) {
-                               hdev->stat.err_tx++;
-                               bt_dev_err(hdev, "No alive interrupt received for %s",
-                                          btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt));
-                               ret = -ETIME;
-                               goto exit_error;
-                       }
+               ret = wait_event_timeout(data->gp0_wait_q,
+                                        data->gp0_received,
+                                        msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS));
+               if (!ret) {
+                       hdev->stat.err_tx++;
+                       bt_dev_err(hdev, "Timeout on alive interrupt (%u ms). Alive context: %s",
+                                  BTINTEL_DEFAULT_INTR_TIMEOUT_MS,
+                                  btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt));
+                       ret = -ETIME;
+                       goto exit_error;
                }
        }
        hdev->stat.byte_tx += skb->len;