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 @@ -1016,6 +1016,8 @@ static void btintel_pcie_msix_gp0_handle * register-based fallback, which can run concurrently. */ spin_lock(&data->irq_lock); + data->boot_stage_cache = btintel_pcie_rd_reg32(data, + BTINTEL_PCIE_CSR_BOOT_STAGE_REG); switch (data->alive_intr_ctxt) { case BTINTEL_PCIE_ROM: data->alive_intr_ctxt = BTINTEL_PCIE_FW_DL; @@ -1071,12 +1073,12 @@ static void btintel_pcie_msix_gp0_handle data->alive_intr_ctxt); break; } - spin_unlock(&data->irq_lock); if (submit_rx) { btintel_pcie_reset_ia(data); btintel_pcie_start_rx(data); } + spin_unlock(&data->irq_lock); if (signal_waitq) { bt_dev_dbg(data->hdev, "wake up gp0 wait_q"); @@ -3086,40 +3088,34 @@ static int btintel_pcie_set_dxstate(stru * knows. Refresh the cache here and retry only if the state check still * fails. */ + spin_lock(&data->irq_lock); 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)) { - bool armed; + err = 0; /* Claim the transition under irq_lock so a * concurrent gp0 handler run cannot also arm RX. */ - spin_lock(&data->irq_lock); - armed = data->alive_intr_ctxt == BTINTEL_PCIE_D0; - if (!armed) + if (data->alive_intr_ctxt != BTINTEL_PCIE_D0) { data->alive_intr_ctxt = BTINTEL_PCIE_D0; - spin_unlock(&data->irq_lock); - if (armed) - return 0; - - /* Do what the handler's D3 -> D0 branch - * would have done, unless it already has. - */ - btintel_pcie_reset_ia(data); - err = btintel_pcie_start_rx(data); - if (err) - return err; + /* Do what the handler's D3 -> D0 branch + * would have done, unless it already has. + */ + btintel_pcie_reset_ia(data); + err = btintel_pcie_start_rx(data); + } + spin_unlock(&data->irq_lock); - return 0; + return err; } } else { if (btintel_pcie_in_d3(data)) { /* Do what the handler's D0 -> D3 branch * would have done, unless it already has. */ - spin_lock(&data->irq_lock); if (data->alive_intr_ctxt != BTINTEL_PCIE_D3) data->alive_intr_ctxt = BTINTEL_PCIE_D3; spin_unlock(&data->irq_lock); @@ -3127,6 +3123,7 @@ static int btintel_pcie_set_dxstate(stru return 0; } } + spin_unlock(&data->irq_lock); } while (++retry < BTINTEL_PCIE_DX_TRANSITION_MAX_RETRIES);