| From 4e11c29873a8a296a20f99b3e03095e65ebf897d Mon Sep 17 00:00:00 2001 |
| From: qizhong cheng <qizhong.cheng@mediatek.com> |
| Date: Mon, 11 Dec 2023 17:49:23 +0800 |
| Subject: PCI: mediatek: Clear interrupt status before dispatching handler |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: qizhong cheng <qizhong.cheng@mediatek.com> |
| |
| 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 <qizhong.cheng@mediatek.com> |
| Signed-off-by: Jianjun Wang <jianjun.wang@mediatek.com> |
| Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> |
| [bhelgaas: rewrap comment] |
| Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> |
| Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/pci/controller/pcie-mediatek.c | 10 ++++++++-- |
| 1 file changed, 8 insertions(+), 2 deletions(-) |
| |
| --- 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 |
| 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); |
| } |
| } |
| |