summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2014-02-19 06:43:52 +0000
committeradrian <adrian@FreeBSD.org>2014-02-19 06:43:52 +0000
commita4be2232413af4c6cde63dfa8e7cab760cf94043 (patch)
tree8245200ae691abcaafaaf2cb297afe7b1291cd05
parentd45e8830ab8a2f2900aff4dc4e0aafff06e80681 (diff)
downloadFreeBSD-src-a4be2232413af4c6cde63dfa8e7cab760cf94043.zip
FreeBSD-src-a4be2232413af4c6cde63dfa8e7cab760cf94043.tar.gz
Extract out the port VLAN flags/setup code and throw it into two new
HAL methods. This allows the AR8327 code to override it as appropriate. Tested: * DB120 - AR8327 and AR9340 on-board switch; only running 'etherswitchcfg' to check configs. The actual VLAN programming wasn't tested.
-rw-r--r--sys/dev/etherswitch/arswitch/arswitch.c113
1 files changed, 70 insertions, 43 deletions
diff --git a/sys/dev/etherswitch/arswitch/arswitch.c b/sys/dev/etherswitch/arswitch/arswitch.c
index 8a30d41..d8fea9e 100644
--- a/sys/dev/etherswitch/arswitch/arswitch.c
+++ b/sys/dev/etherswitch/arswitch/arswitch.c
@@ -80,6 +80,10 @@ static inline int arswitch_portforphy(int phy);
static void arswitch_tick(void *arg);
static int arswitch_ifmedia_upd(struct ifnet *);
static void arswitch_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static int ar8xxx_port_vlan_setup(struct arswitch_softc *sc,
+ etherswitch_port_t *p);
+static int ar8xxx_port_vlan_get(struct arswitch_softc *sc,
+ etherswitch_port_t *p);
static int
arswitch_probe(device_t dev)
@@ -224,7 +228,7 @@ arswitch_set_vlan_mode(struct arswitch_softc *sc, uint32_t mode)
}
static void
-arswitch_port_init_8xxx(struct arswitch_softc *sc, int port)
+ar8xxx_port_init(struct arswitch_softc *sc, int port)
{
/* Port0 - CPU */
@@ -267,7 +271,9 @@ arswitch_attach(device_t dev)
sizeof(sc->info.es_name));
/* Default HAL methods */
- sc->hal.arswitch_port_init = arswitch_port_init_8xxx;
+ sc->hal.arswitch_port_init = ar8xxx_port_init;
+ sc->hal.arswitch_port_vlan_setup = ar8xxx_port_vlan_setup;
+ sc->hal.arswitch_port_vlan_get = ar8xxx_port_vlan_get;
/*
* Attach switch related functions
@@ -525,17 +531,9 @@ arswitch_getinfo(device_t dev)
}
static int
-arswitch_getport(device_t dev, etherswitch_port_t *p)
+ar8xxx_port_vlan_get(struct arswitch_softc *sc, etherswitch_port_t *p)
{
- struct arswitch_softc *sc;
- struct ifmediareq *ifmr;
- struct mii_data *mii;
uint32_t reg;
- int err;
-
- sc = device_get_softc(dev);
- if (p->es_port < 0 || p->es_port > sc->numphys)
- return (ENXIO);
ARSWITCH_LOCK(sc);
@@ -553,9 +551,29 @@ arswitch_getport(device_t dev, etherswitch_port_t *p)
p->es_flags |= ETHERSWITCH_PORT_STRIPTAG;
ARSWITCH_UNLOCK(sc);
+ return (0);
+}
+
+static int
+arswitch_getport(device_t dev, etherswitch_port_t *p)
+{
+ struct arswitch_softc *sc;
+ struct mii_data *mii;
+ struct ifmediareq *ifmr;
+ int err;
+
+ sc = device_get_softc(dev);
+ if (p->es_port < 0 || p->es_port > sc->numphys)
+ return (ENXIO);
+
+ err = sc->hal.arswitch_port_vlan_get(sc, p);
+ if (err != 0)
+ return (err);
+
mii = arswitch_miiforport(sc, p->es_port);
- if (p->es_port == 0) {
+ if (p->es_port == AR8X16_PORT_CPU) {
/* fill in fixed values for CPU port */
+ /* XXX is this valid in all cases? */
p->es_flags |= ETHERSWITCH_PORT_CPU;
ifmr = &p->es_ifmr;
ifmr->ifm_count = 0;
@@ -575,10 +593,47 @@ arswitch_getport(device_t dev, etherswitch_port_t *p)
}
static int
+ar8xxx_port_vlan_setup(struct arswitch_softc *sc, etherswitch_port_t *p)
+{
+ uint32_t reg;
+ int err;
+
+ ARSWITCH_LOCK(sc);
+
+ /* Set the PVID. */
+ if (p->es_pvid != 0)
+ arswitch_set_pvid(sc, p->es_port, p->es_pvid);
+
+ /* Mutually exclusive. */
+ if (p->es_flags & ETHERSWITCH_PORT_ADDTAG &&
+ p->es_flags & ETHERSWITCH_PORT_STRIPTAG) {
+ ARSWITCH_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ reg = 0;
+ if (p->es_flags & ETHERSWITCH_PORT_DOUBLE_TAG)
+ reg |= AR8X16_PORT_CTRL_DOUBLE_TAG;
+ if (p->es_flags & ETHERSWITCH_PORT_ADDTAG)
+ reg |= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_ADD <<
+ AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
+ if (p->es_flags & ETHERSWITCH_PORT_STRIPTAG)
+ reg |= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_STRIP <<
+ AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
+
+ err = arswitch_modifyreg(sc->sc_dev,
+ AR8X16_REG_PORT_CTRL(p->es_port),
+ 0x3 << AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT |
+ AR8X16_PORT_CTRL_DOUBLE_TAG, reg);
+
+ ARSWITCH_UNLOCK(sc);
+ return (err);
+}
+
+static int
arswitch_setport(device_t dev, etherswitch_port_t *p)
{
int err;
- uint32_t reg;
struct arswitch_softc *sc;
struct ifmedia *ifm;
struct mii_data *mii;
@@ -590,38 +645,10 @@ arswitch_setport(device_t dev, etherswitch_port_t *p)
/* Port flags. */
if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
-
- ARSWITCH_LOCK(sc);
- /* Set the PVID. */
- if (p->es_pvid != 0)
- arswitch_set_pvid(sc, p->es_port, p->es_pvid);
-
- /* Mutually exclusive. */
- if (p->es_flags & ETHERSWITCH_PORT_ADDTAG &&
- p->es_flags & ETHERSWITCH_PORT_STRIPTAG) {
- ARSWITCH_UNLOCK(sc);
- return (EINVAL);
- }
-
- reg = 0;
- if (p->es_flags & ETHERSWITCH_PORT_DOUBLE_TAG)
- reg |= AR8X16_PORT_CTRL_DOUBLE_TAG;
- if (p->es_flags & ETHERSWITCH_PORT_ADDTAG)
- reg |= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_ADD <<
- AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
- if (p->es_flags & ETHERSWITCH_PORT_STRIPTAG)
- reg |= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_STRIP <<
- AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
-
- err = arswitch_modifyreg(sc->sc_dev,
- AR8X16_REG_PORT_CTRL(p->es_port),
- 0x3 << AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT |
- AR8X16_PORT_CTRL_DOUBLE_TAG, reg);
-
- ARSWITCH_UNLOCK(sc);
+ err = sc->hal.arswitch_port_vlan_setup(sc, p);
if (err)
return (err);
- }
+ }
/* Do not allow media changes on CPU port. */
if (p->es_port == AR8X16_PORT_CPU)
OpenPOWER on IntegriCloud