Files
omarchy-pkgs/pkgbuilds/linux-omarchy-eevdf/0668-btintel-pcie-dstate-races.patch
T

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);