From b74e261d5607054c96ac257709d1eaf6f7c8462a Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Sat, 14 Feb 2026 19:40:31 +0100 Subject: [PATCH] realtek: eth: merge & simplify irq handlers Two different irq handlers exist for RTL83xx and RTL93xx. Basically they do always the same. - Check transmit interrupts (not needed anymore) - Check rx overflow interrupts (not needed anymore) - Determine rx interrupts and queues that must be processed. - In case of RTL839x check for L2 interrupts With all the recent refactoring their logic is more or less the same. Merge them into one handler. For better readability add a helper that determines the work (aka rings) that needs to be processed. Signed-off-by: Markus Stockhausen Link: https://github.com/openwrt/openwrt/pull/22023 Signed-off-by: Hauke Mehrtens --- .../drivers/net/ethernet/rtl838x_eth.c | 89 +++++-------------- .../drivers/net/ethernet/rtl838x_eth.h | 9 +- 2 files changed, 24 insertions(+), 74 deletions(-) diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c index cf6caf60e8c..4dfe1452eb7 100644 --- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c @@ -196,6 +196,24 @@ struct rteth_ctrl { struct rteth_tx *tx_data; }; +static inline void rteth_confirm_and_disable_irqs(struct rteth_ctrl *ctrl, + unsigned long *rings, bool *l2) +{ + u32 mask = GENMASK(ctrl->r->rx_rings - 1, 0); + u32 shift = ctrl->r->rx_rings % 32; + u32 reg = ctrl->r->rx_rings / 32; + u32 active; + + /* get all irqs, disable only rx (on RTL839x this keeps L2), confirm all */ + active = sw_r32(ctrl->r->dma_if_intr_sts + reg * 4); + sw_w32_mask(active & (mask << shift), 0, ctrl->r->dma_if_intr_msk + reg * 4); + sw_w32(active, ctrl->r->dma_if_intr_sts + reg * 4); + + /* ~mask filters out RTL93xx devices */ + *l2 = !!(active & ~mask & RTL839X_DMA_IF_INTR_NOTIFY_MASK); + *rings = (active >> shift) & mask; +} + static void rteth_disable_all_irqs(struct rteth_ctrl *ctrl) { int registers = ((ctrl->r->rx_rings * 2 + 7) / 32) + 1; @@ -386,74 +404,22 @@ static void rtl839x_l2_notification_handler(struct rteth_ctrl *ctrl) ctrl->lastEvent = e; } -static irqreturn_t rteth_83xx_net_irq(int irq, void *dev_id) +static irqreturn_t rteth_net_irq(int irq, void *dev_id) { struct net_device *ndev = dev_id; struct rteth_ctrl *ctrl = netdev_priv(ndev); - u32 status = sw_r32(ctrl->r->dma_if_intr_sts); unsigned long ring, rings; + bool l2; - netdev_dbg(ndev, "rx interrupt received, status %08x\n", status); - - if (status & RTL83XX_DMA_IF_INTR_RX_RUN_OUT_MASK) - if (net_ratelimit()) - netdev_warn(ndev, "rx ring overrun, status 0x%08x, mask 0x%08x\n", - status, sw_r32(ctrl->r->dma_if_intr_msk)); - - rings = FIELD_GET(RTL83XX_DMA_IF_INTR_RX_DONE_MASK, status); + rteth_confirm_and_disable_irqs(ctrl, &rings, &l2); for_each_set_bit(ring, &rings, RTETH_RX_RINGS) { netdev_dbg(ndev, "schedule rx ring %lu\n", ring); - sw_w32_mask(RTL83XX_DMA_IF_INTR_RX_MASK(ring), 0, ctrl->r->dma_if_intr_msk); napi_schedule(&ctrl->rx_qs[ring].napi); } - if (status & RTL839X_DMA_IF_INTR_NOTIFY_MASK) + if (unlikely(l2)) rtl839x_l2_notification_handler(ctrl); - sw_w32(status, ctrl->r->dma_if_intr_sts); - - return IRQ_HANDLED; -} - -static irqreturn_t rteth_93xx_net_irq(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct rteth_ctrl *ctrl = netdev_priv(dev); - u32 status_rx_r = sw_r32(ctrl->r->dma_if_intr_sts); - u32 status_rx = sw_r32(ctrl->r->dma_if_intr_rx_done_sts); - u32 status_tx = sw_r32(ctrl->r->dma_if_intr_tx_done_sts); - - pr_debug("In %s, status_tx: %08x, status_rx: %08x, status_rx_r: %08x\n", - __func__, status_tx, status_rx, status_rx_r); - - /* Ignore TX interrupt */ - if (status_tx) { - /* Clear ISR */ - pr_debug("TX done\n"); - sw_w32(status_tx, ctrl->r->dma_if_intr_tx_done_sts); - } - - /* RX interrupt */ - if (status_rx) { - pr_debug("RX IRQ\n"); - /* ACK and disable RX interrupt for given rings */ - sw_w32(status_rx, ctrl->r->dma_if_intr_rx_done_sts); - sw_w32_mask(status_rx, 0, ctrl->r->dma_if_intr_rx_done_msk); - for (int i = 0; i < RTETH_RX_RINGS; i++) { - if (status_rx & BIT(i)) { - pr_debug("Scheduling queue: %d\n", i); - napi_schedule(&ctrl->rx_qs[i].napi); - } - } - } - - /* RX buffer overrun */ - if (status_rx_r) { - pr_debug("RX buffer overrun: status %x, mask: %x\n", - status_rx_r, sw_r32(ctrl->r->dma_if_intr_msk)); - sw_w32(status_rx_r, ctrl->r->dma_if_intr_sts); - } - return IRQ_HANDLED; } @@ -1419,7 +1385,6 @@ static const struct rteth_config rteth_838x_cfg = { .rx_rings = 8, .tx_rx_enable = 0xc, .tx_trigger_mask = BIT(1), - .net_irq = rteth_83xx_net_irq, .mac_l2_port_ctrl = RTETH_838X_MAC_L2_PORT_CTRL, .qm_pkt2cpu_intpri_map = RTETH_838X_QM_PKT2CPU_INTPRI_MAP, .qm_rsn2cpuqid_ctrl = RTETH_838X_QM_PKT2CPU_INTPRI_0, @@ -1467,7 +1432,6 @@ static const struct rteth_config rteth_839x_cfg = { .rx_rings = 8, .tx_rx_enable = 0xc, .tx_trigger_mask = BIT(1), - .net_irq = rteth_83xx_net_irq, .mac_l2_port_ctrl = RTETH_839X_MAC_L2_PORT_CTRL, .qm_pkt2cpu_intpri_map = RTETH_839X_QM_PKT2CPU_INTPRI_MAP, .qm_rsn2cpuqid_ctrl = RTETH_839X_QM_PKT2CPU_INTPRI_0, @@ -1515,16 +1479,13 @@ static const struct rteth_config rteth_930x_cfg = { .rx_rings = 32, .tx_rx_enable = 0x30, .tx_trigger_mask = GENMASK(3, 2), - .net_irq = rteth_93xx_net_irq, .mac_l2_port_ctrl = RTETH_930X_MAC_L2_PORT_CTRL, .qm_rsn2cpuqid_ctrl = RTETH_930X_QM_RSN2CPUQID_CTRL_0, .qm_rsn2cpuqid_cnt = RTETH_930X_QM_RSN2CPUQID_CTRL_CNT, .dma_if_intr_sts = RTETH_930X_DMA_IF_INTR_STS, - .dma_if_intr_rx_done_sts = RTL930X_DMA_IF_INTR_RX_DONE_STS, .dma_if_intr_tx_done_sts = RTL930X_DMA_IF_INTR_TX_DONE_STS, .dma_if_intr_msk = RTETH_930X_DMA_IF_INTR_MSK, .dma_if_intr_rx_done_msk = RTL930X_DMA_IF_INTR_RX_DONE_MSK, - .dma_if_intr_tx_done_msk = RTL930X_DMA_IF_INTR_TX_DONE_MSK, .l2_ntfy_if_intr_sts = RTL930X_L2_NTFY_IF_INTR_STS, .l2_ntfy_if_intr_msk = RTL930X_L2_NTFY_IF_INTR_MSK, .dma_if_ctrl = RTL930X_DMA_IF_CTRL, @@ -1567,16 +1528,13 @@ static const struct rteth_config rteth_931x_cfg = { .rx_rings = 32, .tx_rx_enable = 0x30, .tx_trigger_mask = GENMASK(3, 2), - .net_irq = rteth_93xx_net_irq, .mac_l2_port_ctrl = RTETH_931X_MAC_L2_PORT_CTRL, .qm_rsn2cpuqid_ctrl = RTETH_931X_QM_RSN2CPUQID_CTRL_0, .qm_rsn2cpuqid_cnt = RTETH_931X_QM_RSN2CPUQID_CTRL_CNT, .dma_if_intr_sts = RTETH_931X_DMA_IF_INTR_STS, - .dma_if_intr_rx_done_sts = RTL931X_DMA_IF_INTR_RX_DONE_STS, .dma_if_intr_tx_done_sts = RTL931X_DMA_IF_INTR_TX_DONE_STS, .dma_if_intr_msk = RTETH_931X_DMA_IF_INTR_MSK, .dma_if_intr_rx_done_msk = RTL931X_DMA_IF_INTR_RX_DONE_MSK, - .dma_if_intr_tx_done_msk = RTL931X_DMA_IF_INTR_TX_DONE_MSK, .l2_ntfy_if_intr_sts = RTL931X_L2_NTFY_IF_INTR_STS, .l2_ntfy_if_intr_msk = RTL931X_L2_NTFY_IF_INTR_MSK, .dma_if_ctrl = RTL931X_DMA_IF_CTRL, @@ -1680,8 +1638,7 @@ static int rtl838x_eth_probe(struct platform_device *pdev) return -ENODEV; rteth_disable_all_irqs(ctrl); - err = devm_request_irq(&pdev->dev, dev->irq, ctrl->r->net_irq, - IRQF_SHARED, dev->name, dev); + err = devm_request_irq(&pdev->dev, dev->irq, rteth_net_irq, IRQF_SHARED, dev->name, dev); if (err) { dev_err(&pdev->dev, "%s: could not acquire interrupt: %d\n", __func__, err); diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h index 5e1b86b052b..ce8ad5add8d 100644 --- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h +++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h @@ -64,26 +64,22 @@ #define RTL839X_DMA_IF_CTRL (0x786c) #define RTL930X_DMA_IF_CTRL (0xe028) -#define RTL930X_DMA_IF_INTR_RX_DONE_STS (0xe020) #define RTL930X_DMA_IF_INTR_TX_DONE_STS (0xe024) #define RTL930X_DMA_IF_INTR_RX_DONE_MSK (0xe014) -#define RTL930X_DMA_IF_INTR_TX_DONE_MSK (0xe018) #define RTL930X_L2_NTFY_IF_INTR_MSK (0xe04C) #define RTL930X_L2_NTFY_IF_INTR_STS (0xe050) /* TODO: RTL931X_DMA_IF_CTRL has different bits meanings */ #define RTL931X_DMA_IF_CTRL (0x0928) -#define RTL931X_DMA_IF_INTR_RX_DONE_STS (0x0920) #define RTL931X_DMA_IF_INTR_TX_DONE_STS (0x0924) #define RTL931X_DMA_IF_INTR_RX_DONE_MSK (0x0914) -#define RTL931X_DMA_IF_INTR_TX_DONE_MSK (0x0918) #define RTL931X_L2_NTFY_IF_INTR_MSK (0x09E4) #define RTL931X_L2_NTFY_IF_INTR_STS (0x09E8) #define RTL839X_DMA_IF_INTR_NOTIFY_MASK GENMASK(22, 20) #define RTL83XX_DMA_IF_INTR_RX_DONE_MASK GENMASK(15, 8) #define RTL83XX_DMA_IF_INTR_RX_RUN_OUT_MASK GENMASK(7, 0) -#define RTL83XX_DMA_IF_INTR_RX_MASK(ring) (BIT(ring) | BIT(ring + 8)) +#define RTL83XX_DMA_IF_INTR_RX_MASK(ring) (BIT(ring + 8)) #define RTL93XX_DMA_IF_INTR_RX_MASK(ring) (BIT(ring)) /* MAC address settings */ @@ -411,17 +407,14 @@ struct rteth_config { int rx_rings; int tx_rx_enable; int tx_trigger_mask; - irqreturn_t (*net_irq)(int irq, void *dev_id); int mac_l2_port_ctrl; int qm_pkt2cpu_intpri_map; int qm_rsn2cpuqid_ctrl; int qm_rsn2cpuqid_cnt; int dma_if_intr_sts; int dma_if_intr_msk; - int dma_if_intr_rx_done_sts; int dma_if_intr_tx_done_sts; int dma_if_intr_rx_done_msk; - int dma_if_intr_tx_done_msk; int l2_ntfy_if_intr_sts; int l2_ntfy_if_intr_msk; int dma_if_ctrl; -- 2.47.3