]> www.infradead.org Git - users/willy/pagecache.git/commitdiff
Bluetooth: btintel_pcie: Fix a potential race condition
authorKiran K <kiran.k@intel.com>
Fri, 31 Jan 2025 13:00:19 +0000 (18:30 +0530)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Thu, 13 Feb 2025 16:14:04 +0000 (11:14 -0500)
On HCI_OP_RESET command, firmware raises alive interrupt. Driver needs
to wait for this before sending other command. This patch fixes the potential
miss of alive interrupt due to which HCI_OP_RESET can timeout.

Expected flow:
If tx command is HCI_OP_RESET,
  1. set data->gp0_received = false
  2. send HCI_OP_RESET
  3. wait for alive interrupt

Actual flow having potential race:
If tx command is HCI_OP_RESET,
 1. send HCI_OP_RESET
   1a. Firmware raises alive interrupt here and in ISR
       data->gp0_received  is set to true
 2. set data->gp0_received = false
 3. wait for alive interrupt

Signed-off-by: Kiran K <kiran.k@intel.com>
Fixes: 05c200c8f029 ("Bluetooth: btintel_pcie: Add handshake between driver and firmware")
Reported-by: Bjorn Helgaas <helgaas@kernel.org>
Closes: https://patchwork.kernel.org/project/bluetooth/patch/20241001104451.626964-1-kiran.k@intel.com/
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
drivers/bluetooth/btintel_pcie.c

index 2b79952f3628de6690c2e415c59b2c0c1d7eaf4b..091ffe3e14954a99c03d1fe78502c882e304a3cc 100644 (file)
@@ -1320,6 +1320,10 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
                        if (opcode == 0xfc01)
                                btintel_pcie_inject_cmd_complete(hdev, opcode);
                }
+               /* Firmware raises alive interrupt on HCI_OP_RESET */
+               if (opcode == HCI_OP_RESET)
+                       data->gp0_received = false;
+
                hdev->stat.cmd_tx++;
                break;
        case HCI_ACLDATA_PKT:
@@ -1357,7 +1361,6 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
                           opcode, btintel_pcie_alivectxt_state2str(old_ctxt),
                           btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt));
                if (opcode == HCI_OP_RESET) {
-                       data->gp0_received = false;
                        ret = wait_event_timeout(data->gp0_wait_q,
                                                 data->gp0_received,
                                                 msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS));