ramips: fix MT7621 switch driver IRQ storm on init with linux 4.14
authorFelix Fietkau <nbd@nbd.name>
Wed, 21 Feb 2018 13:45:48 +0000 (14:45 +0100)
committerFelix Fietkau <nbd@nbd.name>
Wed, 21 Feb 2018 13:46:45 +0000 (14:46 +0100)
The hardware emits some interrupts while initializing and handling them
can mess up the state or cause infinite loops.
Fix this by disabling IRQs during init and re-enabling them afterwards

Signed-off-by: Felix Fietkau <nbd@nbd.name>
target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/gsw_mt7621.c

index ef0b79e09da088048f7598e2aa52655343babc73..c9fea0caa2ae195df95fa94e53c12af3619c37a6 100644 (file)
@@ -41,6 +41,7 @@ static irqreturn_t gsw_interrupt_mt7621(int irq, void *_priv)
        u32 reg, i;
 
        reg = mt7530_mdio_r32(gsw, 0x700c);
        u32 reg, i;
 
        reg = mt7530_mdio_r32(gsw, 0x700c);
+       mt7530_mdio_w32(gsw, 0x700c, reg);
 
        for (i = 0; i < 5; i++)
                if (reg & BIT(i)) {
 
        for (i = 0; i < 5; i++)
                if (reg & BIT(i)) {
@@ -61,7 +62,6 @@ static irqreturn_t gsw_interrupt_mt7621(int irq, void *_priv)
                }
 
        mt7620_handle_carrier(priv);
                }
 
        mt7620_handle_carrier(priv);
-       mt7530_mdio_w32(gsw, 0x700c, 0x1f);
 
        return IRQ_HANDLED;
 }
 
        return IRQ_HANDLED;
 }
@@ -193,9 +193,8 @@ static void mt7621_hw_init(struct mt7620_gsw *gsw, struct device_node *np)
                _mt7620_mii_write(gsw, i, 0, val);
        }
 
                _mt7620_mii_write(gsw, i, 0, val);
        }
 
-       /* mask irq */
-       mt7530_mdio_w32(gsw, 0x7008, 0x1f);
        /* enable irq */
        /* enable irq */
+       mt7530_mdio_w32(gsw, 0x7008, 0x1f);
        val = mt7530_mdio_r32(gsw, 0x7808);
        val |= 3 << 16;
        mt7530_mdio_w32(gsw, 0x7808, val);
        val = mt7530_mdio_r32(gsw, 0x7808);
        val |= 3 << 16;
        mt7530_mdio_w32(gsw, 0x7808, val);
@@ -225,10 +224,14 @@ int mtk_gsw_init(struct fe_priv *priv)
        if (gsw->irq) {
                request_irq(gsw->irq, gsw_interrupt_mt7621, 0,
                            "gsw", priv);
        if (gsw->irq) {
                request_irq(gsw->irq, gsw_interrupt_mt7621, 0,
                            "gsw", priv);
-               mt7530_mdio_w32(gsw, 0x7008, ~0x1f);
+               disable_irq(gsw->irq);
        }
        }
+
        mt7621_hw_init(gsw, np);
 
        mt7621_hw_init(gsw, np);
 
+       if (gsw->irq)
+               enable_irq(gsw->irq);
+
        return 0;
 }
 
        return 0;
 }