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:
parent
93f5e67e02
commit
4ff2f60db6
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 *);
|
||||
|
Loading…
Reference in New Issue
Block a user