diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c --- a/drivers/bluetooth/btintel_pcie.c +++ b/drivers/bluetooth/btintel_pcie.c @@ -3069,10 +3069,12 @@ static int btintel_pcie_set_dxstate(struct btintel_pcie_data *data, u32 dxstate) BTINTEL_PCIE_CSR_MSIX_HW_INT_CAUSES, BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0); - /* A hardware bug may cause the alive interrupt to be missed. - * Check if the controller reached the expected state and retry - * the operation only if it hasn't. + /* A hardware bug may cause the alive interrupt to be missed. Refresh + * boot_stage_cache from hardware, since only the interrupt handler + * updates it. Finally retry only if the state check still fails. */ + data->boot_stage_cache = btintel_pcie_rd_reg32(data, + BTINTEL_PCIE_CSR_BOOT_STAGE_REG); if (dxstate == BTINTEL_PCIE_STATE_D0) { if (btintel_pcie_in_d0(data)) return 0; diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h --- a/drivers/bluetooth/btintel_pcie.h +++ b/drivers/bluetooth/btintel_pcie.h @@ -50,6 +50,7 @@ #define BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_HALTED (BIT(14)) #define BTINTEL_PCIE_CSR_BOOT_STAGE_MAC_ACCESS_ON (BIT(16)) #define BTINTEL_PCIE_CSR_BOOT_STAGE_ALIVE (BIT(23)) +/* Reflects live D-state. Updated by hardware on every D-state transition. */ #define BTINTEL_PCIE_CSR_BOOT_STAGE_D3_STATE_READY (BIT(24)) /* Registers for MSI-X */