The XGMAC DMA_MODE register has an INTM field (bits 13:12) that controls interrupt routing behavior for DMA transfer completion events: 00 (default): sbd_perch_* are pulse signals, sbd_intr_o is also asserted for each completion event. 01: sbd_perch_* are level signals, sbd_intr_o is NOT asserted for packet transfer completion events. When multi-MSI is enabled, per-channel TX/RX interrupts are expected to arrive on their dedicated lines. In the default INTM=00 mode, sbd_intr_o also fires for DMA completion events, but the multi-MSI handler stmmac_mac_interrupt() only processes MAC-layer events (LPI, PMT, timestamps) and returns IRQ_NONE for every DMA completion interrupt, resulting in a continuous stream of unhandled interrupts on the common IRQ. Hardware verification with XGMAC and multi-MSI enabled: INTM=00: 5.4 million common IRQ interrupts in 3 seconds, ~1.8 million IRQ_NONE returns per second. INTM=01: 0 common IRQ interrupts, per-channel IRQs work normally, 10G line rate works correctly. Set INTM to mode 1 when multi-MSI is enabled. This matches the existing GMAC4 implementation. XGMAC multi-MSI has never worked correctly since it was introduced. Signed-off-by: Zxyan Zhu --- drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 2 ++ drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index 61b6d45a02f5..f8ab347f7b5b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -320,6 +320,8 @@ /* DMA Registers */ #define XGMAC_DMA_MODE 0x00003000 #define XGMAC_SWR BIT(0) +#define XGMAC_INTM_MASK GENMASK(13, 12) +#define XGMAC_INTM_MODE1 0x1 #define XGMAC_DMA_SYSBUS_MODE 0x00003004 #define XGMAC_WR_OSR_LMT GENMASK(29, 24) #define XGMAC_RD_OSR_LMT GENMASK(21, 16) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index 03437f1cf3df..ff83858ebc1f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -31,6 +31,16 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr, value |= XGMAC_EAME; writel(value, ioaddr + XGMAC_DMA_SYSBUS_MODE); + + /* + * Route DMA interrupts to per-channel lines when multi-MSI enabled. + */ + if (dma_cfg->multi_msi_en) { + value = readl(ioaddr + XGMAC_DMA_MODE); + value = u32_replace_bits(value, XGMAC_INTM_MODE1, + XGMAC_INTM_MASK); + writel(value, ioaddr + XGMAC_DMA_MODE); + } } static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv, base-commit: 1df10cef2d1e7f9f2fb7eddb67fc70d3abf101f9 -- 2.34.1