aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorqizhong cheng <[email protected]>2023-12-11 17:49:23 +0800
committerBjorn Helgaas <[email protected]>2024-01-09 16:41:23 -0600
commit4e11c29873a8a296a20f99b3e03095e65ebf897d (patch)
treef23661404feacf15bb12bf1656d867cb30e4d898
parentb85ea95d086471afb4ad062012a4d73cd328fa86 (diff)
PCI: mediatek: Clear interrupt status before dispatching handler
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/[email protected] Fixes: 43e6409db64d ("PCI: mediatek: Add MSI support for MT2712 and MT7622") Signed-off-by: qizhong cheng <[email protected]> Signed-off-by: Jianjun Wang <[email protected]> Signed-off-by: Krzysztof WilczyƄski <[email protected]> [bhelgaas: rewrap comment] Signed-off-by: Bjorn Helgaas <[email protected]> Reviewed-by: AngeloGioacchino Del Regno <[email protected]> Cc: <[email protected]>
-rw-r--r--drivers/pci/controller/pcie-mediatek.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
index 66a8f73296fc..48372013f26d 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);
}
}