Skip to content

Commit 7f67ec0

Browse files
plappermaulhauke
authored andcommitted
realtek: eth: introduce global interrupt helpers
Global interrupt enabling/disabling is scattered around the code. Provide two helpers to handle this code centrally. Make use of them where needed. This refactoring brings multiple enhancements: 1. Only activate the rx interrupts and ignore the run out (aka rx overflow) interrupts. Overflow was used to spit out log messages to identify driver issues. Nowadays it is stable enough and these messages are not needed any longer. 2. With generic register setting some family checks can be dropped. 3. Last but not least this commit fixes a bug in the probing of the ethernet driver. In rare case (especially during TFTP boot) U-Boot loader leaves a pending rx interrupt that instantly fires when the driver registers its interrupt via devm_request_irq(). To mitigate this, reorder the interrupt disabling from ndo_open() to driver probing. Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de> Link: openwrt/openwrt#21893 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
1 parent f617d3e commit 7f67ec0

File tree

1 file changed

+39
-37
lines changed
  • target/linux/realtek/files-6.12/drivers/net/ethernet

1 file changed

+39
-37
lines changed

target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,40 @@ struct rteth_ctrl {
199199
struct rteth_tx *tx_data;
200200
};
201201

202+
static void rteth_disable_all_irqs(struct rteth_ctrl *ctrl)
203+
{
204+
int registers = ((ctrl->r->rx_rings * 2 + 7) / 32) + 1;
205+
206+
for (int reg = 0; reg < registers; reg++) {
207+
sw_w32(0, ctrl->r->dma_if_intr_msk + reg * 4);
208+
sw_w32(GENMASK(31, 0), ctrl->r->dma_if_intr_sts + reg * 4);
209+
}
210+
}
211+
212+
static void rteth_enable_all_rx_irqs(struct rteth_ctrl *ctrl)
213+
{
214+
int mask, shift, reg;
215+
216+
/*
217+
* The hardware has several types of interrupts. Basically for rx/tx completion and
218+
* if hardware queues run out. For now the driver only needs notification about new
219+
* incoming packets. Leave everything else disabled.
220+
*/
221+
mask = GENMASK(ctrl->r->rx_rings - 1, 0);
222+
shift = ctrl->r->rx_rings % 32;
223+
reg = ctrl->r->rx_rings / 32;
224+
sw_w32_mask(0, mask << shift, ctrl->r->dma_if_intr_msk + reg * 4);
225+
226+
/*
227+
* RTL839x has additional L2 notification interrupts. Simply activate them. All other
228+
* devices that do not have the feature have adequate reserved bit space and ignore it.
229+
*/
230+
mask = GENMASK(2, 0);
231+
shift = (ctrl->r->rx_rings * 2 + 4) % 32;
232+
reg = (ctrl->r->rx_rings * 2 + 4) / 32;
233+
sw_w32_mask(0, mask << shift, ctrl->r->dma_if_intr_msk + reg * 4);
234+
}
235+
202236
/* On the RTL93XX, the RTL93XX_DMA_IF_RX_RING_CNTR track the fill level of
203237
* the rings. Writing x into these registers substracts x from its content.
204238
* 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)
455489

456490
static void rteth_838x_hw_reset(struct rteth_ctrl *ctrl)
457491
{
458-
/* Disable and clear interrupts */
459-
sw_w32(0x00000000, ctrl->r->dma_if_intr_msk);
460-
sw_w32(0xffffffff, ctrl->r->dma_if_intr_sts);
461-
462492
rteth_nic_reset(ctrl, 0xc);
463493

464494
/* Free floating rings without space tracking */
@@ -469,10 +499,6 @@ static void rteth_839x_hw_reset(struct rteth_ctrl *ctrl)
469499
{
470500
u32 int_saved, nbuf;
471501

472-
/* Disable and clear interrupts */
473-
sw_w32(0x00000000, ctrl->r->dma_if_intr_msk);
474-
sw_w32(0xffffffff, ctrl->r->dma_if_intr_sts);
475-
476502
/* Preserve L2 notification and NBUF settings */
477503
int_saved = sw_r32(ctrl->r->dma_if_intr_msk);
478504
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)
499525

500526
static void rteth_93xx_hw_reset(struct rteth_ctrl *ctrl)
501527
{
502-
/* Disable and clear interrupts */
503-
sw_w32(0x00000000, ctrl->r->dma_if_intr_msk);
504-
sw_w32(0xffffffff, ctrl->r->dma_if_intr_sts);
505-
sw_w32(0x00000000, ctrl->r->dma_if_intr_rx_done_msk);
506-
sw_w32(0xffffffff, ctrl->r->dma_if_intr_rx_done_sts);
507-
sw_w32(0x00000000, ctrl->r->dma_if_intr_tx_done_msk);
508-
sw_w32(0x0000000f, ctrl->r->dma_if_intr_tx_done_sts);
509-
510528
rteth_nic_reset(ctrl, 0x6);
511529

512530
/* Setup Head of Line */
@@ -580,8 +598,7 @@ static void rtl838x_hw_en_rxtx(struct rteth_ctrl *ctrl)
580598
/* Truncate RX buffer to DEFAULT_MTU bytes, pad TX */
581599
sw_w32((DEFAULT_MTU << 16) | RX_TRUNCATE_EN_83XX | TX_PAD_EN_838X, ctrl->r->dma_if_ctrl);
582600

583-
/* Enable RX done and RX overflow, TX done interrupts not needed */
584-
sw_w32(0xffff, ctrl->r->dma_if_intr_msk);
601+
rteth_enable_all_rx_irqs(ctrl);
585602

586603
/* Enable DMA, engine expects empty FCS field */
587604
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)
604621
/* Setup CPU-Port: RX Buffer */
605622
sw_w32((DEFAULT_MTU << 5) | RX_TRUNCATE_EN_83XX, ctrl->r->dma_if_ctrl);
606623

607-
/* Enable Notify, RX done and RX overflow, TX done interrupts not needed */
608-
sw_w32(0x0070ffff, ctrl->r->dma_if_intr_msk); /* Notify IRQ! */
624+
rteth_enable_all_rx_irqs(ctrl);
609625

610626
/* Enable DMA */
611627
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)
640656
sw_w32_mask(0x3ff << pos, v, ctrl->r->dma_if_rx_ring_cntr(i));
641657
}
642658

643-
/* Enable Notify, RX done and RX overflow, TX done interrupts not needed */
644-
sw_w32(0xffffffff, ctrl->r->dma_if_intr_msk);
645-
sw_w32(0xffffffff, ctrl->r->dma_if_intr_rx_done_msk);
646-
sw_w32(0x00000000, ctrl->r->dma_if_intr_tx_done_msk);
659+
rteth_enable_all_rx_irqs(ctrl);
647660

648661
/* Enable DMA */
649662
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)
789802
static void rtl838x_hw_stop(struct rteth_ctrl *ctrl)
790803
{
791804
u32 force_mac = ctrl->r->family_id == RTL8380_FAMILY_ID ? 0x6192C : 0x75;
792-
u32 clear_irq = ctrl->r->family_id == RTL8380_FAMILY_ID ? 0x000fffff : 0x007fffff;
793805

794806
/* Disable RX/TX from/to CPU-port */
795807
sw_w32_mask(0x3, 0, ctrl->r->mac_l2_port_ctrl);
@@ -833,18 +845,7 @@ static void rtl838x_hw_stop(struct rteth_ctrl *ctrl)
833845
sw_w32_mask(BIT(0) | BIT(9), 0, ctrl->r->mac_force_mode_ctrl + ctrl->r->cpu_port * 4);
834846
mdelay(100);
835847

836-
/* Disable all TX/RX interrupts */
837-
if (ctrl->r->family_id == RTL9300_FAMILY_ID || ctrl->r->family_id == RTL9310_FAMILY_ID) {
838-
sw_w32(0x00000000, ctrl->r->dma_if_intr_msk);
839-
sw_w32(0xffffffff, ctrl->r->dma_if_intr_sts);
840-
sw_w32(0x00000000, ctrl->r->dma_if_intr_rx_done_msk);
841-
sw_w32(0xffffffff, ctrl->r->dma_if_intr_rx_done_sts);
842-
sw_w32(0x00000000, ctrl->r->dma_if_intr_tx_done_msk);
843-
sw_w32(0x0000000f, ctrl->r->dma_if_intr_tx_done_sts);
844-
} else {
845-
sw_w32(0x00000000, ctrl->r->dma_if_intr_msk);
846-
sw_w32(clear_irq, ctrl->r->dma_if_intr_sts);
847-
}
848+
rteth_disable_all_irqs(ctrl);
848849

849850
/* Disable TX/RX DMA */
850851
sw_w32(0x00000000, ctrl->r->dma_if_ctrl);
@@ -1702,6 +1703,7 @@ static int rtl838x_eth_probe(struct platform_device *pdev)
17021703
if (dev->irq < 0)
17031704
return -ENODEV;
17041705

1706+
rteth_disable_all_irqs(ctrl);
17051707
err = devm_request_irq(&pdev->dev, dev->irq, ctrl->r->net_irq,
17061708
IRQF_SHARED, dev->name, dev);
17071709
if (err) {

0 commit comments

Comments
 (0)