* [PATCH v3 1/2] Bluetooth: btintel_pcie: Make driver wait for alive interrupt
@ 2025-07-21 9:44 Kiran K
2025-07-21 9:44 ` [PATCH v3 2/2] Bluetooth: btintel_pcie: Fix Alive Context State Handling Kiran K
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Kiran K @ 2025-07-21 9:44 UTC (permalink / raw)
To: linux-bluetooth
Cc: ravishankar.srivatsa, chethan.tumkur.narayan,
chandrashekar.devegowda, aluvala.sai.teja, Kiran K
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>
---
changes in v3:
- No change
changes in v2:
- Address review comments
drivers/bluetooth/btintel_pcie.c | 30 +++++++++++++++++-------------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index 60528bdc4316..a17c438784ae 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -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;
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH v3 2/2] Bluetooth: btintel_pcie: Fix Alive Context State Handling 2025-07-21 9:44 [PATCH v3 1/2] Bluetooth: btintel_pcie: Make driver wait for alive interrupt Kiran K @ 2025-07-21 9:44 ` Kiran K 2025-07-21 10:10 ` [v3,1/2] Bluetooth: btintel_pcie: Make driver wait for alive interrupt bluez.test.bot 2025-07-21 13:40 ` [PATCH v3 1/2] " patchwork-bot+bluetooth 2 siblings, 0 replies; 4+ messages in thread From: Kiran K @ 2025-07-21 9:44 UTC (permalink / raw) To: linux-bluetooth Cc: ravishankar.srivatsa, chethan.tumkur.narayan, chandrashekar.devegowda, aluvala.sai.teja, Kiran K The firmware raises an alive interrupt upon sending the HCI_RESET or BTINTEL_HCI_OP_RESET command. As part of handling the reset command, firmware initializes the hardware and data path and raises the alive interrupt. Upon receiving the alive interrupt, the driver must enable the data path and grant RX buffers to the firmware before sending any commands. The alive context maintained in the driver must be updated before sending BTINTEL_HCI_OP_RESET or HCI_OP_RESET to prevent a potential race condition where the context is also updated in the threaded IRQ. The issue was observed in a stress reboot usecase (1/25) using "sudo reboot" command where the firmware download was failing as the driver was not granting RX buffer to firmware due to race condition. Bluetooth: hci0: API lock is disabled Bluetooth: hci0: Debug lock is disabled Bluetooth: hci0: Minimum firmware build 1 week 10 2014 Bluetooth: hci0: Bootloader timestamp 2023.43 buildtype 1 build 11631 Bluetooth: hci0: Found device firmware: intel/ibt-00a0-00a1-iml.sfi Bluetooth: hci0: Boot Address: 0xb0301000 Bluetooth: hci0: Firmware Version: 167-12.25 Bluetooth: hci0: Waiting for firmware download to complete Bluetooth: hci0: Firmware loaded in 99902 usecs Bluetooth: hci0: Alive context: fw_dl old_boot_stage: 0xa0db0003 new_boot_stage: 0xa0db0003 Bluetooth: hci0: sent cmd: 0xfc01 alive context changed: fw_dl -> intel_reset1 Bluetooth: hci0: Waiting for device to boot Bluetooth: hci0: Device boot timeout Bluetooth: hci0: Firmware download retry count: 1 Fixes: 05c200c8f029 ("Bluetooth: btintel_pcie: Add handshake between driver and firmware") Signed-off-by: Kiran K <kiran.k@intel.com> Signed-off-by: Sai Teja Aluvala <aluvala.sai.teja@intel.com> --- changes in v3: - Move wait_event_timeout() for alive interrupt inside btintel_pcie_send_sync() changes in v2: - Address review comments drivers/bluetooth/btintel_pcie.c | 117 ++++++++++++++++--------------- 1 file changed, 62 insertions(+), 55 deletions(-) diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c index a17c438784ae..6e7bbbd35279 100644 --- a/drivers/bluetooth/btintel_pcie.c +++ b/drivers/bluetooth/btintel_pcie.c @@ -118,6 +118,28 @@ struct btintel_pcie_removal { static LIST_HEAD(btintel_pcie_recovery_list); static DEFINE_SPINLOCK(btintel_pcie_recovery_lock); +static inline char *btintel_pcie_alivectxt_state2str(u32 alive_intr_ctxt) +{ + switch (alive_intr_ctxt) { + case BTINTEL_PCIE_ROM: + return "rom"; + case BTINTEL_PCIE_FW_DL: + return "fw_dl"; + case BTINTEL_PCIE_D0: + return "d0"; + case BTINTEL_PCIE_D3: + return "d3"; + case BTINTEL_PCIE_HCI_RESET: + return "hci_reset"; + case BTINTEL_PCIE_INTEL_HCI_RESET1: + return "intel_reset1"; + case BTINTEL_PCIE_INTEL_HCI_RESET2: + return "intel_reset2"; + default: + return "unknown"; + } +} + /* This function initializes the memory for DBGC buffers and formats the * DBGC fragment which consists header info and DBGC buffer's LSB, MSB and * size as the payload @@ -318,10 +340,14 @@ static inline void btintel_pcie_dump_debug_registers(struct hci_dev *hdev) } static int btintel_pcie_send_sync(struct btintel_pcie_data *data, - struct sk_buff *skb) + struct sk_buff *skb, u32 pkt_type, u16 opcode) { int ret; u16 tfd_index; + u32 old_ctxt; + bool wait_on_alive = false; + struct hci_dev *hdev = data->hdev; + struct txq *txq = &data->txq; tfd_index = data->ia.tr_hia[BTINTEL_PCIE_TXQ_NUM]; @@ -329,6 +355,26 @@ static int btintel_pcie_send_sync(struct btintel_pcie_data *data, if (tfd_index > txq->count) return -ERANGE; + /* Firmware raises alive interrupt on HCI_OP_RESET or + * BTINTEL_HCI_OP_RESET + */ + wait_on_alive = (pkt_type == BTINTEL_PCIE_HCI_CMD_PKT && + (opcode == BTINTEL_HCI_OP_RESET || opcode == HCI_OP_RESET)); + + if (wait_on_alive) { + data->gp0_received = false; + old_ctxt = data->alive_intr_ctxt; + data->alive_intr_ctxt = + (opcode == BTINTEL_HCI_OP_RESET ? BTINTEL_PCIE_INTEL_HCI_RESET1 : + BTINTEL_PCIE_HCI_RESET); + bt_dev_dbg(data->hdev, "sending cmd: 0x%4.4x alive context changed: %s -> %s", + opcode, btintel_pcie_alivectxt_state2str(old_ctxt), + btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); + } + + memcpy(skb_push(skb, BTINTEL_PCIE_HCI_TYPE_LEN), &pkt_type, + BTINTEL_PCIE_HCI_TYPE_LEN); + /* Prepare for TX. It updates the TFD with the length of data and * address of the DMA buffer, and copy the data to the DMA buffer */ @@ -347,11 +393,24 @@ static int btintel_pcie_send_sync(struct btintel_pcie_data *data, ret = wait_event_timeout(data->tx_wait_q, data->tx_wait_done, msecs_to_jiffies(BTINTEL_PCIE_TX_WAIT_TIMEOUT_MS)); if (!ret) { - bt_dev_err(data->hdev, "tx completion timeout"); + bt_dev_err(data->hdev, "Timeout (%u ms) on tx completion", + BTINTEL_PCIE_TX_WAIT_TIMEOUT_MS); btintel_pcie_dump_debug_registers(data->hdev); return -ETIME; } + if (wait_on_alive) { + 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 (%u ms) on alive interrupt, alive context: %s", + BTINTEL_DEFAULT_INTR_TIMEOUT_MS, + btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); + return -ETIME; + } + } return 0; } @@ -830,28 +889,6 @@ static void btintel_pcie_wr_sleep_cntrl(struct btintel_pcie_data *data, btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_IPC_SLEEP_CTL_REG, dxstate); } -static inline char *btintel_pcie_alivectxt_state2str(u32 alive_intr_ctxt) -{ - switch (alive_intr_ctxt) { - case BTINTEL_PCIE_ROM: - return "rom"; - case BTINTEL_PCIE_FW_DL: - return "fw_dl"; - case BTINTEL_PCIE_D0: - return "d0"; - case BTINTEL_PCIE_D3: - return "d3"; - case BTINTEL_PCIE_HCI_RESET: - return "hci_reset"; - case BTINTEL_PCIE_INTEL_HCI_RESET1: - return "intel_reset1"; - case BTINTEL_PCIE_INTEL_HCI_RESET2: - return "intel_reset2"; - default: - return "unknown"; - } -} - static int btintel_pcie_read_device_mem(struct btintel_pcie_data *data, void *buf, u32 dev_addr, int len) { @@ -1951,7 +1988,6 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, __u16 opcode = ~0; int ret; u32 type; - u32 old_ctxt; if (test_bit(BTINTEL_PCIE_CORE_HALTED, &data->flags)) return -ENODEV; @@ -1988,12 +2024,6 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, btintel_pcie_inject_cmd_complete(hdev, opcode); } - /* 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++; break; case HCI_ACLDATA_PKT: @@ -2011,37 +2041,14 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, bt_dev_err(hdev, "Unknown HCI packet type"); return -EILSEQ; } - memcpy(skb_push(skb, BTINTEL_PCIE_HCI_TYPE_LEN), &type, - BTINTEL_PCIE_HCI_TYPE_LEN); - ret = btintel_pcie_send_sync(data, skb); + ret = btintel_pcie_send_sync(data, skb, type, opcode); if (ret) { hdev->stat.err_tx++; bt_dev_err(hdev, "Failed to send frame (%d)", ret); goto exit_error; } - if (type == BTINTEL_PCIE_HCI_CMD_PKT && - (opcode == HCI_OP_RESET || opcode == BTINTEL_HCI_OP_RESET)) { - old_ctxt = data->alive_intr_ctxt; - data->alive_intr_ctxt = - (opcode == BTINTEL_HCI_OP_RESET ? BTINTEL_PCIE_INTEL_HCI_RESET1 : - BTINTEL_PCIE_HCI_RESET); - 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)); - 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; kfree_skb(skb); -- 2.43.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* RE: [v3,1/2] Bluetooth: btintel_pcie: Make driver wait for alive interrupt 2025-07-21 9:44 [PATCH v3 1/2] Bluetooth: btintel_pcie: Make driver wait for alive interrupt Kiran K 2025-07-21 9:44 ` [PATCH v3 2/2] Bluetooth: btintel_pcie: Fix Alive Context State Handling Kiran K @ 2025-07-21 10:10 ` bluez.test.bot 2025-07-21 13:40 ` [PATCH v3 1/2] " patchwork-bot+bluetooth 2 siblings, 0 replies; 4+ messages in thread From: bluez.test.bot @ 2025-07-21 10:10 UTC (permalink / raw) To: linux-bluetooth, kiran.k [-- Attachment #1: Type: text/plain, Size: 2456 bytes --] This is automated email and please do not reply to this email! Dear submitter, Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series: PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=984250 ---Test result--- Test Summary: CheckPatch PENDING 0.26 seconds GitLint PENDING 0.27 seconds SubjectPrefix PASS 3.36 seconds BuildKernel PASS 24.37 seconds CheckAllWarning PASS 26.94 seconds CheckSparse PASS 31.39 seconds BuildKernel32 PASS 24.48 seconds TestRunnerSetup PASS 479.39 seconds TestRunner_l2cap-tester PASS 25.48 seconds TestRunner_iso-tester PASS 42.71 seconds TestRunner_bnep-tester PASS 6.03 seconds TestRunner_mgmt-tester FAIL 132.29 seconds TestRunner_rfcomm-tester PASS 9.54 seconds TestRunner_sco-tester PASS 14.92 seconds TestRunner_ioctl-tester PASS 10.28 seconds TestRunner_mesh-tester FAIL 11.46 seconds TestRunner_smp-tester PASS 8.85 seconds TestRunner_userchan-tester PASS 6.37 seconds IncrementalBuild PENDING 0.43 seconds Details ############################## Test: CheckPatch - PENDING Desc: Run checkpatch.pl script Output: ############################## Test: GitLint - PENDING Desc: Run gitlint Output: ############################## Test: TestRunner_mgmt-tester - FAIL Desc: Run mgmt-tester with test-runner Output: Total: 490, Passed: 483 (98.6%), Failed: 3, Not Run: 4 Failed Test Cases LL Privacy - Add Device 2 (2 Devices to AL) Failed 0.204 seconds LL Privacy - Add Device 3 (AL is full) Failed 0.237 seconds LL Privacy - Set Flags 3 (2 Devices to RL) Failed 0.220 seconds ############################## Test: TestRunner_mesh-tester - FAIL Desc: Run mesh-tester with test-runner Output: Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0 Failed Test Cases Mesh - Send cancel - 1 Timed out 1.981 seconds Mesh - Send cancel - 2 Timed out 1.999 seconds ############################## Test: IncrementalBuild - PENDING Desc: Incremental build with the patches in the series Output: --- Regards, Linux Bluetooth ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3 1/2] Bluetooth: btintel_pcie: Make driver wait for alive interrupt 2025-07-21 9:44 [PATCH v3 1/2] Bluetooth: btintel_pcie: Make driver wait for alive interrupt Kiran K 2025-07-21 9:44 ` [PATCH v3 2/2] Bluetooth: btintel_pcie: Fix Alive Context State Handling Kiran K 2025-07-21 10:10 ` [v3,1/2] Bluetooth: btintel_pcie: Make driver wait for alive interrupt bluez.test.bot @ 2025-07-21 13:40 ` patchwork-bot+bluetooth 2 siblings, 0 replies; 4+ messages in thread From: patchwork-bot+bluetooth @ 2025-07-21 13:40 UTC (permalink / raw) To: Kiran K Cc: linux-bluetooth, ravishankar.srivatsa, chethan.tumkur.narayan, chandrashekar.devegowda, aluvala.sai.teja Hello: This series was applied to bluetooth/bluetooth-next.git (master) by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>: On Mon, 21 Jul 2025 15:14:36 +0530 you wrote: > 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"). > > [...] Here is the summary with links: - [v3,1/2] Bluetooth: btintel_pcie: Make driver wait for alive interrupt https://git.kernel.org/bluetooth/bluetooth-next/c/3bf15df70a10 - [v3,2/2] Bluetooth: btintel_pcie: Fix Alive Context State Handling https://git.kernel.org/bluetooth/bluetooth-next/c/b4e417d5d32c You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-07-21 13:39 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-07-21 9:44 [PATCH v3 1/2] Bluetooth: btintel_pcie: Make driver wait for alive interrupt Kiran K 2025-07-21 9:44 ` [PATCH v3 2/2] Bluetooth: btintel_pcie: Fix Alive Context State Handling Kiran K 2025-07-21 10:10 ` [v3,1/2] Bluetooth: btintel_pcie: Make driver wait for alive interrupt bluez.test.bot 2025-07-21 13:40 ` [PATCH v3 1/2] " patchwork-bot+bluetooth
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox