]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
arge_mdio: fix barriers; correctly check MII indicator register.
authoradrian <adrian@FreeBSD.org>
Fri, 30 Oct 2015 23:59:52 +0000 (23:59 +0000)
committeradrian <adrian@FreeBSD.org>
Fri, 30 Oct 2015 23:59:52 +0000 (23:59 +0000)
* use barriers in a slightly better fashion.  You can blame this
  glass of whiskey on putting barriers in the wrong spot.  Grr adrian.

* steal/rewrite the mdio busy check from ag7100 from openwrt and
  refactor the existing code out.  This is .. more correct.

This seems to fix the boot-to-boot variation that I've been seeing
and it quietens the switch port status flapping.

Tested:

* QCA9558 SoC (AP135.)

Obtained from: Linux OpenWRT

sys/mips/atheros/if_arge.c

index 5d595c6e211d2301b38a03907dd06d70f7c79036..36362bce8a8f53b00a4fc004ed57af41be531091 100644 (file)
@@ -1066,35 +1066,48 @@ arge_hinted_child(device_t bus, const char *dname, int dunit)
        device_printf(bus, "hinted child %s%d\n", dname, dunit);
 }
 
+static int
+arge_mdio_busy(struct arge_softc *sc)
+{
+       int i,result;
+
+       for (i = 0; i < ARGE_MII_TIMEOUT; i++) {
+               DELAY(5);
+               ARGE_MDIO_BARRIER_READ(sc);
+               result = ARGE_MDIO_READ(sc, AR71XX_MAC_MII_INDICATOR);
+               if (! result)
+                       return (0);
+               DELAY(5);
+       }
+       return (-1);
+}
+
 static int
 arge_miibus_readreg(device_t dev, int phy, int reg)
 {
        struct arge_softc * sc = device_get_softc(dev);
-       int i, result;
+       int result;
        uint32_t addr = (phy << MAC_MII_PHY_ADDR_SHIFT)
            | (reg & MAC_MII_REG_MASK);
 
        mtx_lock(&miibus_mtx);
+       ARGE_MDIO_BARRIER_RW(sc);
        ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_WRITE);
+       ARGE_MDIO_BARRIER_WRITE(sc);
        ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_ADDR, addr);
+       ARGE_MDIO_BARRIER_WRITE(sc);
        ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_READ);
 
-       i = ARGE_MII_TIMEOUT;
-       while ((ARGE_MDIO_READ(sc, AR71XX_MAC_MII_INDICATOR) & 
-           MAC_MII_INDICATOR_BUSY) && (i--)) {
-               ARGE_MDIO_BARRIER_READ(sc);
-               DELAY(5);
-       }
-
-       if (i < 0) {
+       if (arge_mdio_busy(sc) != 0) {
                mtx_unlock(&miibus_mtx);
                ARGEDEBUG(sc, ARGE_DBG_MII, "%s timedout\n", __func__);
                /* XXX: return ERRNO istead? */
                return (-1);
        }
 
-       result = ARGE_MDIO_READ(sc, AR71XX_MAC_MII_STATUS) & MAC_MII_STATUS_MASK;
        ARGE_MDIO_BARRIER_READ(sc);
+       result = ARGE_MDIO_READ(sc, AR71XX_MAC_MII_STATUS) & MAC_MII_STATUS_MASK;
+       ARGE_MDIO_BARRIER_RW(sc);
        ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_WRITE);
        mtx_unlock(&miibus_mtx);
 
@@ -1109,7 +1122,6 @@ static int
 arge_miibus_writereg(device_t dev, int phy, int reg, int data)
 {
        struct arge_softc * sc = device_get_softc(dev);
-       int i;
        uint32_t addr =
            (phy << MAC_MII_PHY_ADDR_SHIFT) | (reg & MAC_MII_REG_MASK);
 
@@ -1117,24 +1129,20 @@ arge_miibus_writereg(device_t dev, int phy, int reg, int data)
            phy, reg, data);
 
        mtx_lock(&miibus_mtx);
+       ARGE_MDIO_BARRIER_RW(sc);
        ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_ADDR, addr);
+       ARGE_MDIO_BARRIER_WRITE(sc);
        ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CONTROL, data);
+       ARGE_MDIO_BARRIER_WRITE(sc);
 
-       i = ARGE_MII_TIMEOUT;
-       while ((ARGE_MDIO_READ(sc, AR71XX_MAC_MII_INDICATOR) & 
-           MAC_MII_INDICATOR_BUSY) && (i--)) {
-               ARGE_MDIO_BARRIER_READ(sc);
-               DELAY(5);
-       }
-
-       mtx_unlock(&miibus_mtx);
-
-       if (i < 0) {
+       if (arge_mdio_busy(sc) != 0) {
+               mtx_unlock(&miibus_mtx);
                ARGEDEBUG(sc, ARGE_DBG_MII, "%s timedout\n", __func__);
                /* XXX: return ERRNO istead? */
                return (-1);
        }
 
+       mtx_unlock(&miibus_mtx);
        return (0);
 }