[arswitch] add initial functionality for AR8327 ATU management.

* Add the bulk of the ATU table read function
* Correct how the ATU function and WAIT bits work

TODO:

* more testing, figure out how the multi-vlan table stuff works and push that
  up to userspace
This commit is contained in:
Adrian Chadd 2018-02-03 00:59:08 +00:00
parent 46b59ac82b
commit 65d59686e1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=328823
2 changed files with 109 additions and 6 deletions

View File

@ -1100,16 +1100,78 @@ ar8327_atu_flush_port(struct arswitch_softc *sc, int port)
return (ret);
}
/*
* Fetch a single entry from the ATU.
*/
static int
ar8327_atu_fetch_table(struct arswitch_softc *sc, etherswitch_atu_entry_t *e,
int atu_fetch_op)
{
uint32_t ret0, ret1, ret2, val;
/* XXX TODO */
return (ENXIO);
ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
switch (atu_fetch_op) {
case 0:
/* Initialise things for the first fetch */
DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: initializing\n", __func__);
(void) ar8327_atu_wait_ready(sc);
arswitch_writereg(sc->sc_dev,
AR8327_REG_ATU_FUNC, AR8327_ATU_FUNC_OP_GET_NEXT);
arswitch_writereg(sc->sc_dev, AR8327_REG_ATU_DATA0, 0);
arswitch_writereg(sc->sc_dev, AR8327_REG_ATU_DATA1, 0);
arswitch_writereg(sc->sc_dev, AR8327_REG_ATU_DATA2, 0);
return (0);
case 1:
DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: reading next\n", __func__);
/*
* Attempt to read the next address entry; don't modify what
* is there in these registers as its used for the next fetch
*/
(void) ar8327_atu_wait_ready(sc);
/* Begin the next read event; not modifying anything */
val = arswitch_readreg(sc->sc_dev, AR8327_REG_ATU_FUNC);
val |= AR8327_ATU_FUNC_BUSY;
arswitch_writereg(sc->sc_dev, AR8327_REG_ATU_FUNC, val);
/* Wait for it to complete */
(void) ar8327_atu_wait_ready(sc);
/* Fetch the ethernet address and ATU status */
ret0 = arswitch_readreg(sc->sc_dev, AR8327_REG_ATU_DATA0);
ret1 = arswitch_readreg(sc->sc_dev, AR8327_REG_ATU_DATA1);
ret2 = arswitch_readreg(sc->sc_dev, AR8327_REG_ATU_DATA2);
/* If the status is zero, then we're done */
if (MS(ret2, AR8327_ATU_FUNC_DATA2_STATUS) == 0)
return (-1);
/* MAC address */
e->es_macaddr[5] = MS(ret1, AR8327_ATU_DATA1_MAC_ADDR5);
e->es_macaddr[4] = MS(ret1, AR8327_ATU_DATA1_MAC_ADDR4);
e->es_macaddr[3] = MS(ret0, AR8327_ATU_DATA0_MAC_ADDR3);
e->es_macaddr[2] = MS(ret0, AR8327_ATU_DATA0_MAC_ADDR2);
e->es_macaddr[1] = MS(ret0, AR8327_ATU_DATA0_MAC_ADDR1);
e->es_macaddr[0] = MS(ret0, AR8327_ATU_DATA0_MAC_ADDR0);
/* Bitmask of ports this entry is for */
e->es_portmask = MS(ret1, AR8327_ATU_DATA1_DEST_PORT);
/* TODO: other flags that are interesting */
DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: MAC %6D portmask 0x%08x\n",
__func__,
e->es_macaddr, ":", e->es_portmask);
return (0);
default:
return (-1);
}
return (-1);
}
static int
ar8327_flush_dot1q_vlan(struct arswitch_softc *sc)
{

View File

@ -485,11 +485,42 @@
#define AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH 3
#define AR8327_REG_ATU_DATA0 0x600
#define AR8327_ATU_DATA0_MAC_ADDR3 BITS(0, 8)
#define AR8327_ATU_DATA0_MAC_ADDR3_S 0
#define AR8327_ATU_DATA0_MAC_ADDR2 BITS(8, 8)
#define AR8327_ATU_DATA0_MAC_ADDR2_S 8
#define AR8327_ATU_DATA0_MAC_ADDR1 BITS(16, 8)
#define AR8327_ATU_DATA0_MAC_ADDR1_S 16
#define AR8327_ATU_DATA0_MAC_ADDR0 BITS(24, 8)
#define AR8327_ATU_DATA0_MAC_ADDR0_S 24
#define AR8327_REG_ATU_DATA1 0x604
#define AR8327_ATU_DATA1_MAC_ADDR4 BITS(0, 8)
#define AR8327_ATU_DATA1_MAC_ADDR4_S 0
#define AR8327_ATU_DATA1_MAC_ADDR5 BITS(8, 8)
#define AR8327_ATU_DATA1_MAC_ADDR5_S 0
#define AR8327_ATU_DATA1_DEST_PORT BITS(16, 7)
#define AR8327_ATU_DATA1_DEST_PORT_S 16
#define AR8327_ATU_DATA1_CROSS_PORT_STATE_EN BIT(23)
#define AR8327_ATU_DATA1_PRI BITS(24, 3)
#define AR8327_ATU_DATA1_SVL_ENTRY BIT(27)
#define AR8327_ATU_DATA1_PRI_OVER_EN BIT(28)
#define AR8327_ATU_DATA1_MIRROR_EN BIT(29)
#define AR8327_ATU_DATA1_SA_DROP_EN BIT(30)
#define AR8327_ATU_DATA1_HASH_HIGH_ADDR BIT(31)
#define AR8327_REG_ATU_DATA2 0x608
#define AR8327_ATU_FUNC_DATA2_STATUS BITS(0, 4)
#define AR8327_ATU_FUNC_DATA2_STATUS_S 0
#define AR8327_ATU_FUNC_DATA2_VLAN_LEAKY_EN BIT(4)
#define AR8327_ATU_FUNC_DATA2_REDIRECT_TO_CPU BIT(5)
#define AR8327_ATU_FUNC_DATA2_COPY_TO_CPU BIT(6)
#define AR8327_ATU_FUNC_DATA2_SHORT_LOOP BIT(7)
#define AR8327_ATU_FUNC_DATA2_ATU_VID BITS(8, 12)
#define AR8327_ATU_FUNC_DATA2_ATU_VID_S 8
#define AR8327_REG_ATU_FUNC 0x60c
#define AR8327_ATU_FUNC_OP BITS(0, 3)
#define AR8327_ATU_FUNC_OP BITS(0, 4)
#define AR8327_ATU_FUNC_OP_NOOP 0x0
#define AR8327_ATU_FUNC_OP_FLUSH 0x1
#define AR8327_ATU_FUNC_OP_LOAD 0x2
@ -499,9 +530,19 @@
#define AR8327_ATU_FUNC_OP_GET_NEXT 0x6
#define AR8327_ATU_FUNC_OP_SEARCH_MAC 0x7
#define AR8327_ATU_FUNC_OP_CHANGE_TRUNK 0x8
#define AR8327_ATU_FUNC_BUSY BIT(3)
#define AR8327_ATU_FUNC_FLUSH_STATIC_EN BIT(4)
#define AR8327_ATU_FUNC_ENTRY_TYPE BIT(5)
#define AR8327_ATU_FUNC_PORT_NUM BITS(8, 4)
#define AR8327_ATU_FUNC_PORT_NUM_S 8
#define AR8327_ATU_FUNC_FULL_VIOLATION BIT(12)
#define AR8327_ATU_FUNC_MULTI_EN BIT(13) /* for GET_NEXT */
#define AR8327_ATU_FUNC_PORT_EN BIT(14) /* for GET_NEXT */
#define AR8327_ATU_FUNC_VID_EN BIT(15) /* for GET_NEXT */
#define AR8327_ATU_FUNC_ATU_INDEX BITS(16, 5)
#define AR8327_ATU_FUNC_ATU_INDEX_S 16
#define AR8327_ATU_FUNC_TRUNK_PORT_NUM BITS(22, 3) /* for CHANGE_TRUNK */
#define AR8327_ATU_FUNC_TRUNK_PORT_NUM_S 22
#define AR8327_ATU_FUNC_BUSY BIT(31)
#define AR8327_REG_VTU_FUNC0 0x0610
#define AR8327_VTU_FUNC0_EG_MODE BITS(4, 14)