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
This commit is contained in:
Adrian Chadd 2014-03-02 05:48:56 +00:00
parent 93f5e67e02
commit 4ff2f60db6
3 changed files with 79 additions and 1 deletions

View File

@ -255,6 +255,28 @@ ar8xxx_port_init(struct arswitch_softc *sc, int port)
}
}
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)
{
@ -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_softc *sc)
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_softc *sc)
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_softc *sc)
"\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_softc *sc)
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

View File

@ -637,6 +637,9 @@ ar8327_hw_global_setup(struct arswitch_softc *sc)
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 *sc, int port, int pvid)
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;

View File

@ -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 *);