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;
}