Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Bluetooth: btintel_pcie: Fix Alive Context State Handling

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>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

authored by

Kiran K and committed by
Luiz Augusto von Dentz
54713670 69b3d3ac

+62 -55
+62 -55
drivers/bluetooth/btintel_pcie.c
··· 118 118 static LIST_HEAD(btintel_pcie_recovery_list); 119 119 static DEFINE_SPINLOCK(btintel_pcie_recovery_lock); 120 120 121 + static inline char *btintel_pcie_alivectxt_state2str(u32 alive_intr_ctxt) 122 + { 123 + switch (alive_intr_ctxt) { 124 + case BTINTEL_PCIE_ROM: 125 + return "rom"; 126 + case BTINTEL_PCIE_FW_DL: 127 + return "fw_dl"; 128 + case BTINTEL_PCIE_D0: 129 + return "d0"; 130 + case BTINTEL_PCIE_D3: 131 + return "d3"; 132 + case BTINTEL_PCIE_HCI_RESET: 133 + return "hci_reset"; 134 + case BTINTEL_PCIE_INTEL_HCI_RESET1: 135 + return "intel_reset1"; 136 + case BTINTEL_PCIE_INTEL_HCI_RESET2: 137 + return "intel_reset2"; 138 + default: 139 + return "unknown"; 140 + } 141 + } 142 + 121 143 /* This function initializes the memory for DBGC buffers and formats the 122 144 * DBGC fragment which consists header info and DBGC buffer's LSB, MSB and 123 145 * size as the payload ··· 340 318 } 341 319 342 320 static int btintel_pcie_send_sync(struct btintel_pcie_data *data, 343 - struct sk_buff *skb) 321 + struct sk_buff *skb, u32 pkt_type, u16 opcode) 344 322 { 345 323 int ret; 346 324 u16 tfd_index; 325 + u32 old_ctxt; 326 + bool wait_on_alive = false; 327 + struct hci_dev *hdev = data->hdev; 328 + 347 329 struct txq *txq = &data->txq; 348 330 349 331 tfd_index = data->ia.tr_hia[BTINTEL_PCIE_TXQ_NUM]; 350 332 351 333 if (tfd_index > txq->count) 352 334 return -ERANGE; 335 + 336 + /* Firmware raises alive interrupt on HCI_OP_RESET or 337 + * BTINTEL_HCI_OP_RESET 338 + */ 339 + wait_on_alive = (pkt_type == BTINTEL_PCIE_HCI_CMD_PKT && 340 + (opcode == BTINTEL_HCI_OP_RESET || opcode == HCI_OP_RESET)); 341 + 342 + if (wait_on_alive) { 343 + data->gp0_received = false; 344 + old_ctxt = data->alive_intr_ctxt; 345 + data->alive_intr_ctxt = 346 + (opcode == BTINTEL_HCI_OP_RESET ? BTINTEL_PCIE_INTEL_HCI_RESET1 : 347 + BTINTEL_PCIE_HCI_RESET); 348 + bt_dev_dbg(data->hdev, "sending cmd: 0x%4.4x alive context changed: %s -> %s", 349 + opcode, btintel_pcie_alivectxt_state2str(old_ctxt), 350 + btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); 351 + } 352 + 353 + memcpy(skb_push(skb, BTINTEL_PCIE_HCI_TYPE_LEN), &pkt_type, 354 + BTINTEL_PCIE_HCI_TYPE_LEN); 353 355 354 356 /* Prepare for TX. It updates the TFD with the length of data and 355 357 * address of the DMA buffer, and copy the data to the DMA buffer ··· 393 347 ret = wait_event_timeout(data->tx_wait_q, data->tx_wait_done, 394 348 msecs_to_jiffies(BTINTEL_PCIE_TX_WAIT_TIMEOUT_MS)); 395 349 if (!ret) { 396 - bt_dev_err(data->hdev, "tx completion timeout"); 350 + bt_dev_err(data->hdev, "Timeout (%u ms) on tx completion", 351 + BTINTEL_PCIE_TX_WAIT_TIMEOUT_MS); 397 352 btintel_pcie_dump_debug_registers(data->hdev); 398 353 return -ETIME; 399 354 } 400 355 356 + if (wait_on_alive) { 357 + ret = wait_event_timeout(data->gp0_wait_q, 358 + data->gp0_received, 359 + msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS)); 360 + if (!ret) { 361 + hdev->stat.err_tx++; 362 + bt_dev_err(hdev, "Timeout (%u ms) on alive interrupt, alive context: %s", 363 + BTINTEL_DEFAULT_INTR_TIMEOUT_MS, 364 + btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); 365 + return -ETIME; 366 + } 367 + } 401 368 return 0; 402 369 } 403 370 ··· 887 828 { 888 829 bt_dev_dbg(data->hdev, "writing sleep_ctl_reg: 0x%8.8x", dxstate); 889 830 btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_IPC_SLEEP_CTL_REG, dxstate); 890 - } 891 - 892 - static inline char *btintel_pcie_alivectxt_state2str(u32 alive_intr_ctxt) 893 - { 894 - switch (alive_intr_ctxt) { 895 - case BTINTEL_PCIE_ROM: 896 - return "rom"; 897 - case BTINTEL_PCIE_FW_DL: 898 - return "fw_dl"; 899 - case BTINTEL_PCIE_D0: 900 - return "d0"; 901 - case BTINTEL_PCIE_D3: 902 - return "d3"; 903 - case BTINTEL_PCIE_HCI_RESET: 904 - return "hci_reset"; 905 - case BTINTEL_PCIE_INTEL_HCI_RESET1: 906 - return "intel_reset1"; 907 - case BTINTEL_PCIE_INTEL_HCI_RESET2: 908 - return "intel_reset2"; 909 - default: 910 - return "unknown"; 911 - } 912 831 } 913 832 914 833 static int btintel_pcie_read_device_mem(struct btintel_pcie_data *data, ··· 1988 1951 __u16 opcode = ~0; 1989 1952 int ret; 1990 1953 u32 type; 1991 - u32 old_ctxt; 1992 1954 1993 1955 if (test_bit(BTINTEL_PCIE_CORE_HALTED, &data->flags)) 1994 1956 return -ENODEV; ··· 2024 1988 btintel_pcie_inject_cmd_complete(hdev, opcode); 2025 1989 } 2026 1990 2027 - /* Firmware raises alive interrupt on HCI_OP_RESET or 2028 - * BTINTEL_HCI_OP_RESET 2029 - */ 2030 - if (opcode == HCI_OP_RESET || opcode == BTINTEL_HCI_OP_RESET) 2031 - data->gp0_received = false; 2032 - 2033 1991 hdev->stat.cmd_tx++; 2034 1992 break; 2035 1993 case HCI_ACLDATA_PKT: ··· 2041 2011 bt_dev_err(hdev, "Unknown HCI packet type"); 2042 2012 return -EILSEQ; 2043 2013 } 2044 - memcpy(skb_push(skb, BTINTEL_PCIE_HCI_TYPE_LEN), &type, 2045 - BTINTEL_PCIE_HCI_TYPE_LEN); 2046 2014 2047 - ret = btintel_pcie_send_sync(data, skb); 2015 + ret = btintel_pcie_send_sync(data, skb, type, opcode); 2048 2016 if (ret) { 2049 2017 hdev->stat.err_tx++; 2050 2018 bt_dev_err(hdev, "Failed to send frame (%d)", ret); 2051 2019 goto exit_error; 2052 2020 } 2053 2021 2054 - if (type == BTINTEL_PCIE_HCI_CMD_PKT && 2055 - (opcode == HCI_OP_RESET || opcode == BTINTEL_HCI_OP_RESET)) { 2056 - old_ctxt = data->alive_intr_ctxt; 2057 - data->alive_intr_ctxt = 2058 - (opcode == BTINTEL_HCI_OP_RESET ? BTINTEL_PCIE_INTEL_HCI_RESET1 : 2059 - BTINTEL_PCIE_HCI_RESET); 2060 - bt_dev_dbg(data->hdev, "sent cmd: 0x%4.4x alive context changed: %s -> %s", 2061 - opcode, btintel_pcie_alivectxt_state2str(old_ctxt), 2062 - btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); 2063 - ret = wait_event_timeout(data->gp0_wait_q, 2064 - data->gp0_received, 2065 - msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS)); 2066 - if (!ret) { 2067 - hdev->stat.err_tx++; 2068 - bt_dev_err(hdev, "Timeout on alive interrupt (%u ms). Alive context: %s", 2069 - BTINTEL_DEFAULT_INTR_TIMEOUT_MS, 2070 - btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); 2071 - ret = -ETIME; 2072 - goto exit_error; 2073 - } 2074 - } 2075 2022 hdev->stat.byte_tx += skb->len; 2076 2023 kfree_skb(skb); 2077 2024