Q1: If the SoC always enables the bt_en pin via hardware and the driver cannot control the bt_en pin of the SoC chip, then during SSR, the QCA_SSR_TRIGGERED and QCA_IBS_DISABLED bits cannot be cleared. This leads to a reset command timeout failure. Fix1: To address this, clear QCA_SSR_TRIGGERED and QCA_IBS_DISABLED bits after the coredump collection is complete. Also, add msleep delay to wait for controller to complete SSR. Q2: When the SSR (Sub-System Restart) duration exceeds 2 seconds, it triggers host tx_idle_timeout, which sets host TX state to sleep. due to the hardware pulling up bt_en, the firmware is not downloaded after the SSR. As a result, the controller does not enter sleep mode. Consequently, when the host sends a command afterward, it sends 0xFD to the controller, but the controller does not respond, leading to a command timeout. Fix2: Reset the tx_idle_timer after SSR (Sub-System Restart). Changes in v2: - Modified the format. - Add changes to fix tx_idle_timeout - Link to v1: https://lore.kernel.org/all/20250609105553.3756688-1-quic_shuaz@xxxxxxxxxxx/ Signed-off-by: Shuai Zhang <quic_shuaz@xxxxxxxxxxx> --- drivers/bluetooth/hci_qca.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 4e56782b0..d415a3f31 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1653,6 +1653,24 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code) skb_queue_purge(&qca->rx_memdump_q); } + /* If the SoC always enables the bt_en pin via hardware and the driver + * cannot control the bt_en pin of the SoC chip, then during SSR, + * the QCA_SSR_TRIGGERED and QCA_IBS_DISABLED bits cannot be cleared. + * This leads to a reset command timeout failure. + * + * To address this, clear QCA_SSR_TRIGGERED and QCA_IBS_DISABLED bits + * after the coredump collection is complete. + * Also, add msleep delay to wait for controller to complete SSR. + */ + if (!test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks)) { + clear_bit(QCA_SSR_TRIGGERED, &qca->flags); + clear_bit(QCA_IBS_DISABLED, &qca->flags); + mod_timer(&qca->tx_idle_timer, jiffies + + msecs_to_jiffies(qca->tx_idle_delay)); + qca->tx_ibs_state = HCI_IBS_TX_AWAKE; + msleep(50); + } + clear_bit(QCA_HW_ERROR_EVENT, &qca->flags); } @@ -2478,7 +2496,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) return PTR_ERR(qcadev->susclk); } } - + err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto); if (err) { BT_ERR("serdev registration failed"); -- 2.34.1