Commit 61d2cfd9 authored by qizhong cheng's avatar qizhong cheng Committed by Ma Wupeng
Browse files

PCI: mediatek: Clear interrupt status before dispatching handler

stable inclusion
from stable-v6.6.14
commit 3206a188cfe122d87b531b12a8a45633d776a2eb
bugzilla: https://gitee.com/openeuler/kernel/issues/I99TJK

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=3206a188cfe122d87b531b12a8a45633d776a2eb

--------------------------------

commit 4e11c29873a8a296a20f99b3e03095e65ebf897d upstream.

We found a failure when using the iperf tool during WiFi performance
testing, where some MSIs were received while clearing the interrupt
status, and these MSIs cannot be serviced.

The interrupt status can be cleared even if the MSI status remains pending.
As such, given the edge-triggered interrupt type, its status should be
cleared before being dispatched to the handler of the underling device.

[kwilczynski: commit log, code comment wording]
Link: https://lore.kernel.org/linux-pci/20231211094923.31967-1-jianjun.wang@mediatek.com


Fixes: 43e6409d ("PCI: mediatek: Add MSI support for MT2712 and MT7622")
Signed-off-by: default avatarqizhong cheng <qizhong.cheng@mediatek.com>
Signed-off-by: default avatarJianjun Wang <jianjun.wang@mediatek.com>
Signed-off-by: default avatarKrzysztof Wilczyński <kwilczynski@kernel.org>
[bhelgaas: rewrap comment]
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Cc:  <stable@vger.kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarZhangPeng <zhangpeng362@huawei.com>
parent 13e74741
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -617,12 +617,18 @@ static void mtk_pcie_intr_handler(struct irq_desc *desc)
		if (status & MSI_STATUS){
			unsigned long imsi_status;

			/*
			 * The interrupt status can be cleared even if the
			 * MSI status remains pending. As such, given the
			 * edge-triggered interrupt type, its status should
			 * be cleared before being dispatched to the
			 * handler of the underlying device.
			 */
			writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
			while ((imsi_status = readl(port->base + PCIE_IMSI_STATUS))) {
				for_each_set_bit(bit, &imsi_status, MTK_MSI_IRQS_NUM)
					generic_handle_domain_irq(port->inner_domain, bit);
			}
			/* Clear MSI interrupt status */
			writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
		}
	}