[openwrt/openwrt] realtek: eth: merge & simplify irq handlers

LEDE Commits lede-commits at lists.infradead.org
Sat Feb 21 11:31:08 PST 2026


hauke pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/b74e261d5607054c96ac257709d1eaf6f7c8462a

commit b74e261d5607054c96ac257709d1eaf6f7c8462a
Author: Markus Stockhausen <markus.stockhausen at gmx.de>
AuthorDate: Sat Feb 14 19:40:31 2026 +0100

    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 <markus.stockhausen at gmx.de>
    Link: https://github.com/openwrt/openwrt/pull/22023
    Signed-off-by: Hauke Mehrtens <hauke at hauke-m.de>
---
 .../files-6.12/drivers/net/ethernet/rtl838x_eth.c  | 89 ++++++----------------
 .../files-6.12/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 cf6caf60e8..4dfe1452eb 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 5e1b86b052..ce8ad5add8 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;




More information about the lede-commits mailing list