Commit 1c766495 authored by Kiran K's avatar Kiran K Committed by Luiz Augusto von Dentz
Browse files

Bluetooth: btintel_pcie: Add additional to checks to clear TX/RX paths



Due to a hardware issue, there is a possibility that the driver may miss
an MSIx interrupt on the RX/TX data path. Since the TX and RX paths are
independent, when a TX MSIx interrupt occurs, the driver can check the
RX queue for any pending data and process it if present. The same
approach applies to the RX path.

Fixes: c2b636b3 ("Bluetooth: btintel_pcie: Add support for PCIe transport")
Signed-off-by: default avatarChandrashekar Devegowda <chandrashekar.devegowda@intel.com>
Signed-off-by: default avatarKiran K <kiran.k@intel.com>
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent 0b6d58bc
Loading
Loading
Loading
Loading
+19 −5
Original line number Diff line number Diff line
@@ -1272,10 +1272,8 @@ static void btintel_pcie_msix_rx_handle(struct btintel_pcie_data *data)
	bt_dev_dbg(hdev, "RXQ: cr_hia: %u  cr_tia: %u", cr_hia, cr_tia);

	/* Check CR_TIA and CR_HIA for change */
	if (cr_tia == cr_hia) {
		bt_dev_warn(hdev, "RXQ: no new CD found");
	if (cr_tia == cr_hia)
		return;
	}

	rxq = &data->rxq;

@@ -1311,6 +1309,16 @@ static irqreturn_t btintel_pcie_msix_isr(int irq, void *data)
	return IRQ_WAKE_THREAD;
}

static inline bool btintel_pcie_is_rxq_empty(struct btintel_pcie_data *data)
{
	return data->ia.cr_hia[BTINTEL_PCIE_RXQ_NUM] == data->ia.cr_tia[BTINTEL_PCIE_RXQ_NUM];
}

static inline bool btintel_pcie_is_txackq_empty(struct btintel_pcie_data *data)
{
	return data->ia.cr_tia[BTINTEL_PCIE_TXQ_NUM] == data->ia.cr_hia[BTINTEL_PCIE_TXQ_NUM];
}

static irqreturn_t btintel_pcie_irq_msix_handler(int irq, void *dev_id)
{
	struct msix_entry *entry = dev_id;
@@ -1342,12 +1350,18 @@ static irqreturn_t btintel_pcie_irq_msix_handler(int irq, void *dev_id)
		btintel_pcie_msix_gp0_handler(data);

	/* For TX */
	if (intr_fh & BTINTEL_PCIE_MSIX_FH_INT_CAUSES_0)
	if (intr_fh & BTINTEL_PCIE_MSIX_FH_INT_CAUSES_0) {
		btintel_pcie_msix_tx_handle(data);
		if (!btintel_pcie_is_rxq_empty(data))
			btintel_pcie_msix_rx_handle(data);
	}

	/* For RX */
	if (intr_fh & BTINTEL_PCIE_MSIX_FH_INT_CAUSES_1)
	if (intr_fh & BTINTEL_PCIE_MSIX_FH_INT_CAUSES_1) {
		btintel_pcie_msix_rx_handle(data);
		if (!btintel_pcie_is_txackq_empty(data))
			btintel_pcie_msix_tx_handle(data);
	}

	/*
	 * Before sending the interrupt the HW disables it to prevent a nested