| From 80c61470a111e9d1fc019d0fe7152ee36dd0285a Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 3 Dec 2025 11:37:12 +0800 |
| Subject: Bluetooth: hci_qca: Fix SSR (SubSystem Restart) fail when BT_EN is |
| pulled up by hw |
| |
| From: Shuai Zhang <shuai.zhang@oss.qualcomm.com> |
| |
| [ Upstream commit fce1a9244a0f85683be8530e623bc729f24c5067 ] |
| |
| On QCS9075 and QCA8275 platforms, the BT_EN pin is always pulled up by hw |
| and cannot be controlled by the host. As a result, in case of a firmware |
| crash, the host cannot trigger a cold reset. Instead, the BT controller |
| performs a warm restart on its own, without reloading the firmware. |
| |
| This leads to the controller remaining in IBS_WAKE state, while the host |
| expects it to be in sleep mode. The mismatch causes HCI reset commands |
| to time out. Additionally, the driver does not clear internal flags |
| QCA_SSR_TRIGGERED and QCA_IBS_DISABLED, which blocks the reset sequence. |
| If the SSR duration exceeds 2 seconds, the host may enter TX sleep mode |
| due to tx_idle_timeout, further preventing recovery. Also, memcoredump_flag |
| is not cleared, so only the first SSR generates a coredump. |
| |
| Tell the driver that the BT controller has undergone a proper restart sequence: |
| |
| - Clear QCA_SSR_TRIGGERED and QCA_IBS_DISABLED flags after SSR. |
| - Add a 50ms delay to allow the controller to complete its warm reset. |
| - Reset tx_idle_timer to prevent the host from entering TX sleep mode. |
| - Clear memcoredump_flag to allow multiple coredump captures. |
| |
| Apply these steps only when HCI_QUIRK_NON_PERSISTENT_SETUP is not set, |
| which indicates that BT_EN is defined in DTS and cannot be toggled. |
| |
| Refer to the comment in include/net/bluetooth/hci.h for details on |
| HCI_QUIRK_NON_PERSISTENT_SETUP. |
| |
| Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> |
| Signed-off-by: Shuai Zhang <shuai.zhang@oss.qualcomm.com> |
| Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/bluetooth/hci_qca.c | 33 +++++++++++++++++++++++++++++++++ |
| 1 file changed, 33 insertions(+) |
| |
| diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c |
| index 888176b0faa90..a3c217571c3c4 100644 |
| --- a/drivers/bluetooth/hci_qca.c |
| +++ b/drivers/bluetooth/hci_qca.c |
| @@ -1653,6 +1653,39 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code) |
| skb_queue_purge(&qca->rx_memdump_q); |
| } |
| |
| + /* |
| + * If the BT chip's bt_en pin is connected to a 3.3V power supply via |
| + * hardware and always stays high, driver cannot control the bt_en pin. |
| + * As a result, during SSR (SubSystem Restart), QCA_SSR_TRIGGERED and |
| + * QCA_IBS_DISABLED flags cannot be cleared, which leads to a reset |
| + * command timeout. |
| + * Add an msleep delay to ensure controller completes the SSR process. |
| + * |
| + * Host will not download the firmware after SSR, controller to remain |
| + * in the IBS_WAKE state, and the host needs to synchronize with it |
| + * |
| + * Since the bluetooth chip has been reset, clear the memdump state. |
| + */ |
| + if (!hci_test_quirk(hu->hdev, HCI_QUIRK_NON_PERSISTENT_SETUP)) { |
| + /* |
| + * When the SSR (SubSystem Restart) duration exceeds 2 seconds, |
| + * it triggers host tx_idle_delay, which sets host TX state |
| + * to sleep. Reset tx_idle_timer after SSR to prevent |
| + * host enter TX IBS_Sleep mode. |
| + */ |
| + mod_timer(&qca->tx_idle_timer, jiffies + |
| + msecs_to_jiffies(qca->tx_idle_delay)); |
| + |
| + /* Controller reset completion time is 50ms */ |
| + msleep(50); |
| + |
| + clear_bit(QCA_SSR_TRIGGERED, &qca->flags); |
| + clear_bit(QCA_IBS_DISABLED, &qca->flags); |
| + |
| + qca->tx_ibs_state = HCI_IBS_TX_AWAKE; |
| + qca->memdump_state = QCA_MEMDUMP_IDLE; |
| + } |
| + |
| clear_bit(QCA_HW_ERROR_EVENT, &qca->flags); |
| } |
| |
| -- |
| 2.51.0 |
| |