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 9cd1d259b7..4aa44fdc55 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 @@ -199,6 +199,40 @@ struct rteth_ctrl { struct rteth_tx *tx_data; }; +static void rteth_disable_all_irqs(struct rteth_ctrl *ctrl) +{ + int registers = ((ctrl->r->rx_rings * 2 + 7) / 32) + 1; + + for (int reg = 0; reg < registers; reg++) { + sw_w32(0, ctrl->r->dma_if_intr_msk + reg * 4); + sw_w32(GENMASK(31, 0), ctrl->r->dma_if_intr_sts + reg * 4); + } +} + +static void rteth_enable_all_rx_irqs(struct rteth_ctrl *ctrl) +{ + int mask, shift, reg; + + /* + * The hardware has several types of interrupts. Basically for rx/tx completion and + * if hardware queues run out. For now the driver only needs notification about new + * incoming packets. Leave everything else disabled. + */ + mask = GENMASK(ctrl->r->rx_rings - 1, 0); + shift = ctrl->r->rx_rings % 32; + reg = ctrl->r->rx_rings / 32; + sw_w32_mask(0, mask << shift, ctrl->r->dma_if_intr_msk + reg * 4); + + /* + * RTL839x has additional L2 notification interrupts. Simply activate them. All other + * devices that do not have the feature have adequate reserved bit space and ignore it. + */ + mask = GENMASK(2, 0); + shift = (ctrl->r->rx_rings * 2 + 4) % 32; + reg = (ctrl->r->rx_rings * 2 + 4) / 32; + sw_w32_mask(0, mask << shift, ctrl->r->dma_if_intr_msk + reg * 4); +} + /* On the RTL93XX, the RTL93XX_DMA_IF_RX_RING_CNTR track the fill level of * the rings. Writing x into these registers substracts x from its content. * When the content reaches the ring size, the ASIC no longer adds @@ -455,10 +489,6 @@ static void rteth_nic_reset(struct rteth_ctrl *ctrl, int reset_mask) static void rteth_838x_hw_reset(struct rteth_ctrl *ctrl) { - /* Disable and clear interrupts */ - sw_w32(0x00000000, ctrl->r->dma_if_intr_msk); - sw_w32(0xffffffff, ctrl->r->dma_if_intr_sts); - rteth_nic_reset(ctrl, 0xc); /* Free floating rings without space tracking */ @@ -469,10 +499,6 @@ static void rteth_839x_hw_reset(struct rteth_ctrl *ctrl) { u32 int_saved, nbuf; - /* Disable and clear interrupts */ - sw_w32(0x00000000, ctrl->r->dma_if_intr_msk); - sw_w32(0xffffffff, ctrl->r->dma_if_intr_sts); - /* Preserve L2 notification and NBUF settings */ int_saved = sw_r32(ctrl->r->dma_if_intr_msk); nbuf = sw_r32(RTL839X_DMA_IF_NBUF_BASE_DESC_ADDR_CTRL); @@ -499,14 +525,6 @@ static void rteth_839x_hw_reset(struct rteth_ctrl *ctrl) static void rteth_93xx_hw_reset(struct rteth_ctrl *ctrl) { - /* Disable and clear interrupts */ - sw_w32(0x00000000, ctrl->r->dma_if_intr_msk); - sw_w32(0xffffffff, ctrl->r->dma_if_intr_sts); - sw_w32(0x00000000, ctrl->r->dma_if_intr_rx_done_msk); - sw_w32(0xffffffff, ctrl->r->dma_if_intr_rx_done_sts); - sw_w32(0x00000000, ctrl->r->dma_if_intr_tx_done_msk); - sw_w32(0x0000000f, ctrl->r->dma_if_intr_tx_done_sts); - rteth_nic_reset(ctrl, 0x6); /* Setup Head of Line */ @@ -580,8 +598,7 @@ static void rtl838x_hw_en_rxtx(struct rteth_ctrl *ctrl) /* Truncate RX buffer to DEFAULT_MTU bytes, pad TX */ sw_w32((DEFAULT_MTU << 16) | RX_TRUNCATE_EN_83XX | TX_PAD_EN_838X, ctrl->r->dma_if_ctrl); - /* Enable RX done and RX overflow, TX done interrupts not needed */ - sw_w32(0xffff, ctrl->r->dma_if_intr_msk); + rteth_enable_all_rx_irqs(ctrl); /* Enable DMA, engine expects empty FCS field */ sw_w32_mask(0, RX_EN | TX_EN, ctrl->r->dma_if_ctrl); @@ -604,8 +621,7 @@ static void rtl839x_hw_en_rxtx(struct rteth_ctrl *ctrl) /* Setup CPU-Port: RX Buffer */ sw_w32((DEFAULT_MTU << 5) | RX_TRUNCATE_EN_83XX, ctrl->r->dma_if_ctrl); - /* Enable Notify, RX done and RX overflow, TX done interrupts not needed */ - sw_w32(0x0070ffff, ctrl->r->dma_if_intr_msk); /* Notify IRQ! */ + rteth_enable_all_rx_irqs(ctrl); /* Enable DMA */ sw_w32_mask(0, RX_EN | TX_EN, ctrl->r->dma_if_ctrl); @@ -640,10 +656,7 @@ static void rtl93xx_hw_en_rxtx(struct rteth_ctrl *ctrl) sw_w32_mask(0x3ff << pos, v, ctrl->r->dma_if_rx_ring_cntr(i)); } - /* Enable Notify, RX done and RX overflow, TX done interrupts not needed */ - sw_w32(0xffffffff, ctrl->r->dma_if_intr_msk); - sw_w32(0xffffffff, ctrl->r->dma_if_intr_rx_done_msk); - sw_w32(0x00000000, ctrl->r->dma_if_intr_tx_done_msk); + rteth_enable_all_rx_irqs(ctrl); /* Enable DMA */ sw_w32_mask(0, RX_EN_93XX | TX_EN_93XX, ctrl->r->dma_if_ctrl); @@ -789,7 +802,6 @@ static int rteth_open(struct net_device *ndev) static void rtl838x_hw_stop(struct rteth_ctrl *ctrl) { u32 force_mac = ctrl->r->family_id == RTL8380_FAMILY_ID ? 0x6192C : 0x75; - u32 clear_irq = ctrl->r->family_id == RTL8380_FAMILY_ID ? 0x000fffff : 0x007fffff; /* Disable RX/TX from/to CPU-port */ sw_w32_mask(0x3, 0, ctrl->r->mac_l2_port_ctrl); @@ -833,18 +845,7 @@ static void rtl838x_hw_stop(struct rteth_ctrl *ctrl) sw_w32_mask(BIT(0) | BIT(9), 0, ctrl->r->mac_force_mode_ctrl + ctrl->r->cpu_port * 4); mdelay(100); - /* Disable all TX/RX interrupts */ - if (ctrl->r->family_id == RTL9300_FAMILY_ID || ctrl->r->family_id == RTL9310_FAMILY_ID) { - sw_w32(0x00000000, ctrl->r->dma_if_intr_msk); - sw_w32(0xffffffff, ctrl->r->dma_if_intr_sts); - sw_w32(0x00000000, ctrl->r->dma_if_intr_rx_done_msk); - sw_w32(0xffffffff, ctrl->r->dma_if_intr_rx_done_sts); - sw_w32(0x00000000, ctrl->r->dma_if_intr_tx_done_msk); - sw_w32(0x0000000f, ctrl->r->dma_if_intr_tx_done_sts); - } else { - sw_w32(0x00000000, ctrl->r->dma_if_intr_msk); - sw_w32(clear_irq, ctrl->r->dma_if_intr_sts); - } + rteth_disable_all_irqs(ctrl); /* Disable TX/RX DMA */ sw_w32(0x00000000, ctrl->r->dma_if_ctrl); @@ -1702,6 +1703,7 @@ static int rtl838x_eth_probe(struct platform_device *pdev) if (dev->irq < 0) return -ENODEV; + rteth_disable_all_irqs(ctrl); err = devm_request_irq(&pdev->dev, dev->irq, ctrl->r->net_irq, IRQF_SHARED, dev->name, dev); if (err) {