Hi,
there's more work to be done for fec, but this will allow changing changing address/ifconfig up&down etc. without the freeze/kernel hangup preventing ie. autoinstall i've reported to bugs@. i didn't see these while loops being done in nbsd if_enet, where i think fec originates from. -Artturi diff --git a/sys/arch/armv7/imx/if_fec.c b/sys/arch/armv7/imx/if_fec.c index 899c1904144..5b494a6c92c 100644 --- a/sys/arch/armv7/imx/if_fec.c +++ b/sys/arch/armv7/imx/if_fec.c @@ -181,6 +181,8 @@ #define ENET_TXD_INT (1 << 30) #endif +#define ENET_MII_TIMEOUT 100000 /* --loop_cnt { delay(5); } */ + /* * Bus dma allocation structure used by * fec_dma_malloc and fec_dma_free. @@ -339,7 +341,6 @@ fec_attach(struct device *parent, struct device *self, void *aux) /* reset the controller */ HSET4(sc, ENET_ECR, ENET_ECR_RESET); - while(HREAD4(sc, ENET_ECR) & ENET_ECR_RESET); HWRITE4(sc, ENET_EIMR, 0); HWRITE4(sc, ENET_EIR, 0xffffffff); @@ -604,7 +605,6 @@ fec_init(struct fec_softc *sc) /* reset the controller */ HSET4(sc, ENET_ECR, ENET_ECR_RESET); - while(HREAD4(sc, ENET_ECR) & ENET_ECR_RESET); /* set hw address */ HWRITE4(sc, ENET_PALR, @@ -616,7 +616,8 @@ fec_init(struct fec_softc *sc) (sc->sc_ac.ac_enaddr[4] << 24) | (sc->sc_ac.ac_enaddr[5] << 16)); - /* clear outstanding interrupts */ + /* mask and clear all interrupts */ + HWRITE4(sc, ENET_EIMR, 0); HWRITE4(sc, ENET_EIR, 0xffffffff); /* set max receive buffer size, 3-0 bits always zero for alignment */ @@ -692,6 +693,8 @@ fec_stop(struct fec_softc *sc) { struct ifnet *ifp = &sc->sc_ac.ac_if; + HCLR4(sc, ENET_ECR, ENET_ECR_ETHEREN); + /* * Mark the interface down and cancel the watchdog timer. */ @@ -701,9 +704,7 @@ fec_stop(struct fec_softc *sc) timeout_del(&sc->sc_tick); - /* reset the controller */ - HSET4(sc, ENET_ECR, ENET_ECR_RESET); - while(HREAD4(sc, ENET_ECR) & ENET_ECR_RESET); + mii_down(&sc->sc_mii); } void @@ -996,6 +997,7 @@ fec_miibus_readreg(struct device *dev, int phy, int reg) { int r = 0; struct fec_softc *sc = (struct fec_softc *)dev; + u_int timo = ENET_MII_TIMEOUT; HSET4(sc, ENET_EIR, ENET_EIR_MII); @@ -1003,10 +1005,16 @@ fec_miibus_readreg(struct device *dev, int phy, int reg) ENET_MMFR_ST | ENET_MMFR_OP_RD | ENET_MMFR_TA | phy << ENET_MMFR_PA_SHIFT | reg << ENET_MMFR_RA_SHIFT); - while(!(HREAD4(sc, ENET_EIR) & ENET_EIR_MII)); + while (!(HREAD4(sc, ENET_EIR) & ENET_EIR_MII) && --timo) + delay(5); r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ENET_MMFR); +#ifdef DIAGNOSTIC + if (!timo) + printf("%s: %s timeout\n", sc->sc_dev.dv_xname, __func__); +#endif + return (r & 0xffff); } @@ -1014,6 +1022,7 @@ void fec_miibus_writereg(struct device *dev, int phy, int reg, int val) { struct fec_softc *sc = (struct fec_softc *)dev; + u_int timo = ENET_MII_TIMEOUT; HSET4(sc, ENET_EIR, ENET_EIR_MII); @@ -1022,7 +1031,12 @@ fec_miibus_writereg(struct device *dev, int phy, int reg, int val) phy << ENET_MMFR_PA_SHIFT | reg << ENET_MMFR_RA_SHIFT | (val & 0xffff)); - while(!(HREAD4(sc, ENET_EIR) & ENET_EIR_MII)); + while (!(HREAD4(sc, ENET_EIR) & ENET_EIR_MII) && --timo) + delay(5); +#ifdef DIAGNOSTIC + if (!timo) + printf("%s: %s timeout\n", sc->sc_dev.dv_xname, __func__); +#endif return; }