Skip to content

Commit 89a33de

Browse files
kirankrishnappa-intelVudentz
authored andcommitted
Bluetooth: btintel_pcie: Fix potential race condition in firmware download
During firmware download, if an error occurs, interrupts must be disabled, synchronized, and re-enabled before retrying the download. This change ensures proper interrupt handling to prevent race conditions. Signed-off-by: Chandrashekar Devegowda <[email protected]> Signed-off-by: Kiran K <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent e0fca6f commit 89a33de

File tree

1 file changed

+31
-2
lines changed

1 file changed

+31
-2
lines changed

drivers/bluetooth/btintel_pcie.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2033,6 +2033,28 @@ static void btintel_pcie_release_hdev(struct btintel_pcie_data *data)
20332033
data->hdev = NULL;
20342034
}
20352035

2036+
static void btintel_pcie_disable_interrupts(struct btintel_pcie_data *data)
2037+
{
2038+
spin_lock(&data->irq_lock);
2039+
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, data->fh_init_mask);
2040+
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, data->hw_init_mask);
2041+
spin_unlock(&data->irq_lock);
2042+
}
2043+
2044+
static void btintel_pcie_enable_interrupts(struct btintel_pcie_data *data)
2045+
{
2046+
spin_lock(&data->irq_lock);
2047+
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, ~data->fh_init_mask);
2048+
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, ~data->hw_init_mask);
2049+
spin_unlock(&data->irq_lock);
2050+
}
2051+
2052+
static void btintel_pcie_synchronize_irqs(struct btintel_pcie_data *data)
2053+
{
2054+
for (int i = 0; i < data->alloc_vecs; i++)
2055+
synchronize_irq(data->msix_entries[i].vector);
2056+
}
2057+
20362058
static int btintel_pcie_setup_internal(struct hci_dev *hdev)
20372059
{
20382060
struct btintel_pcie_data *data = hci_get_drvdata(hdev);
@@ -2152,13 +2174,16 @@ static int btintel_pcie_setup(struct hci_dev *hdev)
21522174
bt_dev_err(hdev, "Firmware download retry count: %d",
21532175
fw_dl_retry);
21542176
btintel_pcie_dump_debug_registers(hdev);
2177+
btintel_pcie_disable_interrupts(data);
2178+
btintel_pcie_synchronize_irqs(data);
21552179
err = btintel_pcie_reset_bt(data);
21562180
if (err) {
21572181
bt_dev_err(hdev, "Failed to do shr reset: %d", err);
21582182
break;
21592183
}
21602184
usleep_range(10000, 12000);
21612185
btintel_pcie_reset_ia(data);
2186+
btintel_pcie_enable_interrupts(data);
21622187
btintel_pcie_config_msix(data);
21632188
err = btintel_pcie_enable_bt(data);
21642189
if (err) {
@@ -2291,6 +2316,12 @@ static void btintel_pcie_remove(struct pci_dev *pdev)
22912316

22922317
data = pci_get_drvdata(pdev);
22932318

2319+
btintel_pcie_disable_interrupts(data);
2320+
2321+
btintel_pcie_synchronize_irqs(data);
2322+
2323+
flush_work(&data->rx_work);
2324+
22942325
btintel_pcie_reset_bt(data);
22952326
for (int i = 0; i < data->alloc_vecs; i++) {
22962327
struct msix_entry *msix_entry;
@@ -2303,8 +2334,6 @@ static void btintel_pcie_remove(struct pci_dev *pdev)
23032334

23042335
btintel_pcie_release_hdev(data);
23052336

2306-
flush_work(&data->rx_work);
2307-
23082337
destroy_workqueue(data->workqueue);
23092338

23102339
btintel_pcie_free(data);

0 commit comments

Comments
 (0)