diff options
| author | Kiran K <kiran.k@intel.com> | 2025-01-31 18:30:19 +0530 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2025-02-21 14:01:18 +0100 |
| commit | a700e50fcf960c2a96bd31a4ba61d7bb3dac2c3d (patch) | |
| tree | ccaf32401a59aa9c836abc807fdfbcf69998647f /drivers/bluetooth | |
| parent | 390bf69dcb2056a16506111b4f46b04145280a12 (diff) | |
| download | linux-a700e50fcf960c2a96bd31a4ba61d7bb3dac2c3d.tar.gz linux-a700e50fcf960c2a96bd31a4ba61d7bb3dac2c3d.tar.bz2 linux-a700e50fcf960c2a96bd31a4ba61d7bb3dac2c3d.zip | |
Bluetooth: btintel_pcie: Fix a potential race condition
[ Upstream commit 872274b992839ff64fe560767fe7ee5f942ccdb1 ]
On HCI_OP_RESET command, firmware raises alive interrupt. Driver needs
to wait for this before sending other command. This patch fixes the potential
miss of alive interrupt due to which HCI_OP_RESET can timeout.
Expected flow:
If tx command is HCI_OP_RESET,
1. set data->gp0_received = false
2. send HCI_OP_RESET
3. wait for alive interrupt
Actual flow having potential race:
If tx command is HCI_OP_RESET,
1. send HCI_OP_RESET
1a. Firmware raises alive interrupt here and in ISR
data->gp0_received is set to true
2. set data->gp0_received = false
3. wait for alive interrupt
Signed-off-by: Kiran K <kiran.k@intel.com>
Fixes: 05c200c8f029 ("Bluetooth: btintel_pcie: Add handshake between driver and firmware")
Reported-by: Bjorn Helgaas <helgaas@kernel.org>
Closes: https://patchwork.kernel.org/project/bluetooth/patch/20241001104451.626964-1-kiran.k@intel.com/
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/bluetooth')
| -rw-r--r-- | drivers/bluetooth/btintel_pcie.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c index 8bd663f4bac1..53f6b4f76bcc 100644 --- a/drivers/bluetooth/btintel_pcie.c +++ b/drivers/bluetooth/btintel_pcie.c @@ -1312,6 +1312,10 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, if (opcode == 0xfc01) btintel_pcie_inject_cmd_complete(hdev, opcode); } + /* Firmware raises alive interrupt on HCI_OP_RESET */ + if (opcode == HCI_OP_RESET) + data->gp0_received = false; + hdev->stat.cmd_tx++; break; case HCI_ACLDATA_PKT: @@ -1349,7 +1353,6 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, opcode, btintel_pcie_alivectxt_state2str(old_ctxt), btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); if (opcode == HCI_OP_RESET) { - data->gp0_received = false; ret = wait_event_timeout(data->gp0_wait_q, data->gp0_received, msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS)); |
