From 3206a188cfe122d87b531b12a8a45633d776a2eb Mon Sep 17 00:00:00 2001 From: qizhong cheng Date: Mon, 11 Dec 2023 17:49:23 +0800 Subject: [PATCH] PCI: mediatek: Clear interrupt status before dispatching handler MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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: 43e6409db64d ("PCI: mediatek: Add MSI support for MT2712 and MT7622") Signed-off-by: qizhong cheng Signed-off-by: Jianjun Wang Signed-off-by: Krzysztof Wilczyński [bhelgaas: rewrap comment] Signed-off-by: Bjorn Helgaas Reviewed-by: AngeloGioacchino Del Regno Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/pci/controller/pcie-mediatek.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c index 66a8f73..4837201 100644 --- a/drivers/pci/controller/pcie-mediatek.c +++ b/drivers/pci/controller/pcie-mediatek.c @@ -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); } } -- 2.7.4