Date: Sun, 2 Mar 2014 05:48:56 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r262681 - head/sys/dev/etherswitch/arswitch Message-ID: <201403020548.s225mupU078678@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Sun Mar 2 05:48:56 2014 New Revision: 262681 URL: http://svnweb.freebsd.org/changeset/base/262681 Log: Add ATU flush support. The OpenWRT AR8xxx switch support flushes the ATU (address translation unit) after each port link 'up' status change. I've modified this to just flush on any port transition. Whilst here, bump the number of ports on the AR8327 to 6, rather than the default of 5. It's DB120 specific; I'll go and make this configurable later. There's some debugging code in here still; I am still debugging whether this is or isn't working fully. Tested: * DB120, AR9344 + AR8327 switch Obtained from: OpenWRT Modified: head/sys/dev/etherswitch/arswitch/arswitch.c head/sys/dev/etherswitch/arswitch/arswitch_8327.c head/sys/dev/etherswitch/arswitch/arswitchvar.h Modified: head/sys/dev/etherswitch/arswitch/arswitch.c ============================================================================== --- head/sys/dev/etherswitch/arswitch/arswitch.c Sun Mar 2 05:47:05 2014 (r262680) +++ head/sys/dev/etherswitch/arswitch/arswitch.c Sun Mar 2 05:48:56 2014 (r262681) @@ -256,6 +256,28 @@ ar8xxx_port_init(struct arswitch_softc * } static int +ar8xxx_atu_flush(struct arswitch_softc *sc) +{ + int ret; + + ret = arswitch_waitreg(sc->sc_dev, + AR8216_REG_ATU, + AR8216_ATU_ACTIVE, + 0, + 1000); + + if (ret) + device_printf(sc->sc_dev, "%s: waitreg failed\n", __func__); + + if (!ret) + arswitch_writereg(sc->sc_dev, + AR8216_REG_ATU, + AR8216_ATU_OP_FLUSH); + + return (ret); +} + +static int arswitch_attach(device_t dev) { struct arswitch_softc *sc; @@ -280,6 +302,7 @@ arswitch_attach(device_t dev) sc->hal.arswitch_vlan_setvgroup = ar8xxx_setvgroup; sc->hal.arswitch_vlan_get_pvid = ar8xxx_get_pvid; sc->hal.arswitch_vlan_set_pvid = ar8xxx_set_pvid; + sc->hal.arswitch_atu_flush = ar8xxx_atu_flush; /* * Attach switch related functions @@ -469,6 +492,7 @@ arswitch_miipollstat(struct arswitch_sof struct mii_data *mii; struct mii_softc *miisc; int portstatus; + int port_flap = 0; ARSWITCH_LOCK_ASSERT(sc, MA_OWNED); @@ -484,7 +508,6 @@ arswitch_miipollstat(struct arswitch_sof else portstatus = arswitch_readreg(sc->sc_dev, AR8X16_REG_PORT_STS(arswitch_portforphy(i))); - #if 0 DPRINTF(sc->sc_dev, "p[%d]=%b\n", i, @@ -492,6 +515,27 @@ arswitch_miipollstat(struct arswitch_sof "\20\3TXMAC\4RXMAC\5TXFLOW\6RXFLOW\7" "DUPLEX\11LINK_UP\12LINK_AUTO\13LINK_PAUSE"); #endif + /* + * If the current status is down, but we have a link + * status showing up, we need to do an ATU flush. + */ + if ((mii->mii_media_status & IFM_ACTIVE) == 0 && + (portstatus & AR8X16_PORT_STS_LINK_UP) != 0) { + device_printf(sc->sc_dev, "%s: port %d: port -> UP\n", + __func__, + i); + port_flap = 1; + } + /* + * and maybe if a port goes up->down? + */ + if ((mii->mii_media_status & IFM_ACTIVE) != 0 && + (portstatus & AR8X16_PORT_STS_LINK_UP) == 0) { + device_printf(sc->sc_dev, "%s: port %d: port -> DOWN\n", + __func__, + i); + port_flap = 1; + } arswitch_update_ifmedia(portstatus, &mii->mii_media_status, &mii->mii_media_active); LIST_FOREACH(miisc, &mii->mii_phys, mii_list) { @@ -501,6 +545,10 @@ arswitch_miipollstat(struct arswitch_sof mii_phy_update(miisc, MII_POLLSTAT); } } + + /* If a port went from down->up, flush the ATU */ + if (port_flap) + sc->hal.arswitch_atu_flush(sc); } static void Modified: head/sys/dev/etherswitch/arswitch/arswitch_8327.c ============================================================================== --- head/sys/dev/etherswitch/arswitch/arswitch_8327.c Sun Mar 2 05:47:05 2014 (r262680) +++ head/sys/dev/etherswitch/arswitch/arswitch_8327.c Sun Mar 2 05:48:56 2014 (r262681) @@ -637,6 +637,9 @@ ar8327_hw_global_setup(struct arswitch_s arswitch_modifyreg(sc->sc_dev, AR8327_REG_MODULE_EN, AR8327_MODULE_EN_MIB, AR8327_MODULE_EN_MIB); + /* Set the right number of ports */ + sc->info.es_nports = 6; + return (0); } @@ -784,6 +787,28 @@ ar8327_set_pvid(struct arswitch_softc *s return (0); } +static int +ar8327_atu_flush(struct arswitch_softc *sc) +{ + + int ret; + + ret = arswitch_waitreg(sc->sc_dev, + AR8327_REG_ATU_FUNC, + AR8327_ATU_FUNC_BUSY, + 0, + 1000); + + if (ret) + device_printf(sc->sc_dev, "%s: waitreg failed\n", __func__); + + if (!ret) + arswitch_writereg(sc->sc_dev, + AR8327_REG_ATU_FUNC, + AR8327_ATU_FUNC_OP_FLUSH); + return (ret); +} + void ar8327_attach(struct arswitch_softc *sc) { @@ -801,6 +826,8 @@ ar8327_attach(struct arswitch_softc *sc) sc->hal.arswitch_vlan_get_pvid = ar8327_get_pvid; sc->hal.arswitch_vlan_set_pvid = ar8327_set_pvid; + sc->hal.arswitch_atu_flush = ar8327_atu_flush; + /* Set the switch vlan capabilities. */ sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q | ETHERSWITCH_VLAN_PORT | ETHERSWITCH_VLAN_DOUBLE_TAG; Modified: head/sys/dev/etherswitch/arswitch/arswitchvar.h ============================================================================== --- head/sys/dev/etherswitch/arswitch/arswitchvar.h Sun Mar 2 05:47:05 2014 (r262680) +++ head/sys/dev/etherswitch/arswitch/arswitchvar.h Sun Mar 2 05:48:56 2014 (r262681) @@ -81,6 +81,9 @@ struct arswitch_softc { /* Port functions */ void (* arswitch_port_init) (struct arswitch_softc *, int); + /* ATU functions */ + int (* arswitch_atu_flush) (struct arswitch_softc *); + /* VLAN functions */ int (* arswitch_port_vlan_setup) (struct arswitch_softc *, etherswitch_port_t *);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201403020548.s225mupU078678>