87 lines
2.6 KiB
Diff
87 lines
2.6 KiB
Diff
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);
|
|
|