svn commit: r319886 - head/sys/dev/etherswitch/e6000sw
Luiz Otavio O Souza
loos at FreeBSD.org
Tue Jun 13 00:42:24 UTC 2017
Author: loos
Date: Tue Jun 13 00:42:23 2017
New Revision: 319886
URL: https://svnweb.freebsd.org/changeset/base/319886
Log:
Add the initial support for the Marvell 88E6141 and 88E6341 switches.
Right now the driver only supports port VLANs, so make sure
etherswitch_getinfo() return the proper switch capabilities.
Handle the cases where not all ports are in use (that will also require
etherswitch cooperation).
Sponsored by: Rubicon Communications, LLC (Netgate)
Modified:
head/sys/dev/etherswitch/e6000sw/e6000sw.c
Modified: head/sys/dev/etherswitch/e6000sw/e6000sw.c
==============================================================================
--- head/sys/dev/etherswitch/e6000sw/e6000sw.c Tue Jun 13 00:31:16 2017 (r319885)
+++ head/sys/dev/etherswitch/e6000sw/e6000sw.c Tue Jun 13 00:42:23 2017 (r319886)
@@ -73,6 +73,8 @@ typedef struct e6000sw_softc {
uint32_t cpuports_mask;
uint32_t fixed_mask;
+ uint32_t ports_mask;
+ int phy_base;
int sw_addr;
int num_ports;
boolean_t multi_chip;
@@ -85,6 +87,7 @@ typedef struct e6000sw_softc {
static etherswitch_info_t etherswitch_info = {
.es_nports = 0,
.es_nvlangroups = E6000SW_NUM_VGROUPS,
+ .es_vlan_caps = ETHERSWITCH_VLAN_PORT,
.es_name = "Marvell 6000 series switch"
};
@@ -95,6 +98,7 @@ static int e6000sw_detach(device_t);
static int e6000sw_readphy(device_t, int, int);
static int e6000sw_writephy(device_t, int, int, int);
static etherswitch_info_t* e6000sw_getinfo(device_t);
+static int e6000sw_getconf(device_t, etherswitch_conf_t *);
static void e6000sw_lock(device_t);
static void e6000sw_unlock(device_t);
static int e6000sw_getport(device_t, etherswitch_port_t *);
@@ -123,6 +127,7 @@ static int e6000sw_set_pvid(e6000sw_softc_t *, int, in
static __inline bool e6000sw_is_cpuport(e6000sw_softc_t *, int);
static __inline bool e6000sw_is_fixedport(e6000sw_softc_t *, int);
static __inline bool e6000sw_is_phyport(e6000sw_softc_t *, int);
+static __inline bool e6000sw_is_portenabled(e6000sw_softc_t *, int);
static __inline struct mii_data *e6000sw_miiforphy(e6000sw_softc_t *,
unsigned int);
@@ -142,6 +147,7 @@ static device_method_t e6000sw_methods[] = {
/* etherswitch interface */
DEVMETHOD(etherswitch_getinfo, e6000sw_getinfo),
+ DEVMETHOD(etherswitch_getconf, e6000sw_getconf),
DEVMETHOD(etherswitch_lock, e6000sw_lock),
DEVMETHOD(etherswitch_unlock, e6000sw_unlock),
DEVMETHOD(etherswitch_getport, e6000sw_getport),
@@ -202,7 +208,6 @@ e6000sw_probe(device_t dev)
return (ENXIO);
sc = device_get_softc(dev);
- bzero(sc, sizeof(e6000sw_softc_t));
sc->dev = dev;
sc->node = switch_node;
@@ -219,14 +224,27 @@ e6000sw_probe(device_t dev)
E6000SW_UNLOCK(sc);
switch (id & 0xfff0) {
+ case 0x3400:
+ description = "Marvell 88E6141";
+ sc->phy_base = 0x10;
+ sc->num_ports = 6;
+ break;
+ case 0x3410:
+ description = "Marvell 88E6341";
+ sc->phy_base = 0x10;
+ sc->num_ports = 6;
+ break;
case 0x3520:
description = "Marvell 88E6352";
+ sc->num_ports = 7;
break;
case 0x1720:
description = "Marvell 88E6172";
+ sc->num_ports = 7;
break;
case 0x1760:
description = "Marvell 88E6176";
+ sc->num_ports = 7;
break;
default:
sx_destroy(&sc->sx);
@@ -240,17 +258,17 @@ e6000sw_probe(device_t dev)
}
static int
-e6000sw_parse_child_fdt(device_t dev, phandle_t child, uint32_t *fixed_mask,
- uint32_t *cpu_mask, int *pport, int *pvlangroup)
+e6000sw_parse_child_fdt(e6000sw_softc_t *sc, phandle_t child,
+ uint32_t *fixed_mask, uint32_t *cpu_mask, int *pport, int *pvlangroup)
{
+ boolean_t fixed_link;
char portlabel[100];
uint32_t port, vlangroup;
- boolean_t fixed_link;
if (fixed_mask == NULL || cpu_mask == NULL || pport == NULL)
return (ENXIO);
- OF_getprop(child, "label", (void *)portlabel, 100);
+ OF_getprop(child, "label", (void *)portlabel, sizeof(portlabel));
OF_getencprop(child, "reg", (void *)&port, sizeof(port));
if (OF_getencprop(child, "vlangroup", (void *)&vlangroup,
@@ -262,22 +280,21 @@ e6000sw_parse_child_fdt(device_t dev, phandle_t child,
*pvlangroup = -1;
}
- if (port >= E6000SW_MAX_PORTS)
+ if (port >= sc->num_ports)
return (ENXIO);
*pport = port;
if (strncmp(portlabel, "cpu", 3) == 0) {
- device_printf(dev, "CPU port at %d\n", port);
+ device_printf(sc->dev, "CPU port at %d\n", port);
*cpu_mask |= (1 << port);
- return (0);
}
fixed_link = OF_child(child);
if (fixed_link) {
*fixed_mask |= (1 << port);
- device_printf(dev, "fixed port at %d\n", port);
+ device_printf(sc->dev, "fixed port at %d\n", port);
} else {
- device_printf(dev, "PHY at port %d\n", port);
+ device_printf(sc->dev, "PHY at port %d\n", port);
}
return (0);
@@ -314,7 +331,7 @@ e6000sw_attach_miibus(e6000sw_softc_t *sc, int port)
err = mii_attach(sc->dev, &sc->miibus[port], sc->ifp[port],
e6000sw_ifmedia_upd, e6000sw_ifmedia_sts, BMSR_DEFCAPMASK,
- port, MII_OFFSET_ANY, 0);
+ port + sc->phy_base, MII_OFFSET_ANY, 0);
if (err != 0)
return (err);
@@ -343,7 +360,7 @@ e6000sw_attach(device_t dev)
bzero(member_ports, sizeof(member_ports));
for (child = OF_child(sc->node); child != 0; child = OF_peer(child)) {
- err = e6000sw_parse_child_fdt(dev, child, &sc->fixed_mask,
+ err = e6000sw_parse_child_fdt(sc, child, &sc->fixed_mask,
&sc->cpuports_mask, &port, &vlangroup);
if (err != 0) {
device_printf(sc->dev, "failed to parse DTS\n");
@@ -353,7 +370,8 @@ e6000sw_attach(device_t dev)
if (vlangroup != -1)
member_ports[vlangroup] |= (1 << port);
- sc->num_ports++;
+ /* Port is in use. */
+ sc->ports_mask |= (1 << port);
err = e6000sw_init_interface(sc, port);
if (err != 0) {
@@ -529,6 +547,17 @@ e6000sw_getinfo(device_t dev)
return (ðerswitch_info);
}
+static int
+e6000sw_getconf(device_t dev __unused, etherswitch_conf_t *conf)
+{
+
+ /* Return the VLAN mode. */
+ conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
+ conf->vlan_mode = ETHERSWITCH_VLAN_PORT;
+
+ return (0);
+}
+
static void
e6000sw_lock(device_t dev)
{
@@ -563,6 +592,8 @@ e6000sw_getport(device_t dev, etherswitch_port_t *p)
if (p->es_port >= sc->num_ports || p->es_port < 0)
return (EINVAL);
+ if (!e6000sw_is_portenabled(sc, p->es_port))
+ return (0);
err = 0;
E6000SW_LOCK(sc);
@@ -605,12 +636,15 @@ e6000sw_setport(device_t dev, etherswitch_port_t *p)
if (p->es_port >= sc->num_ports || p->es_port < 0)
return (EINVAL);
+ if (!e6000sw_is_portenabled(sc, p->es_port))
+ return (0);
err = 0;
E6000SW_LOCK(sc);
if (p->es_pvid != 0)
e6000sw_set_pvid(sc, p->es_port, p->es_pvid);
- if (!e6000sw_is_cpuport(sc, p->es_port)) {
+ if (!e6000sw_is_cpuport(sc, p->es_port) &&
+ !e6000sw_is_fixedport(sc, p->es_port)) {
mii = e6000sw_miiforphy(sc, p->es_port);
err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, &mii->mii_media,
SIOCSIFMEDIA);
@@ -780,8 +814,7 @@ e6000sw_setvgroup(device_t dev, etherswitch_vlangroup_
vg->es_untagged_ports &= PORT_VLAN_MAP_TABLE_MASK;
fid = vg->es_vlangroup + 1;
for (port = 0; port < sc->num_ports; port++) {
- if ((sc->members[vg->es_vlangroup] & (1 << port)) ||
- (vg->es_untagged_ports & (1 << port)))
+ if ((sc->members[sc->vgroup[port]] & (1 << port)))
e6000sw_flush_port(sc, port);
if (vg->es_untagged_ports & (1 << port))
e6000sw_port_assign_vgroup(sc, port, fid,
@@ -805,7 +838,8 @@ e6000sw_getvgroup(device_t dev, etherswitch_vlangroup_
return (EINVAL);
vg->es_untagged_ports = vg->es_member_ports =
sc->members[vg->es_vlangroup];
- vg->es_vid = ETHERSWITCH_VID_VALID;
+ if (vg->es_untagged_ports != 0)
+ vg->es_vid = ETHERSWITCH_VID_VALID;
return (0);
}
@@ -936,6 +970,13 @@ e6000sw_is_phyport(e6000sw_softc_t *sc, int port)
return ((phy_mask & (1 << port)) ? true : false);
}
+static __inline bool
+e6000sw_is_portenabled(e6000sw_softc_t *sc, int port)
+{
+
+ return ((sc->ports_mask & (1 << port)) ? true : false);
+}
+
static __inline int
e6000sw_set_pvid(e6000sw_softc_t *sc, int port, int pvid)
{
@@ -1010,7 +1051,8 @@ e6000sw_tick (void *arg)
E6000SW_LOCK(sc);
for (port = 0; port < sc->num_ports; port++) {
/* Tick only on PHY ports */
- if (!e6000sw_is_phyport(sc, port))
+ if (!e6000sw_is_portenabled(sc, port) ||
+ !e6000sw_is_phyport(sc, port))
continue;
mii = e6000sw_miiforphy(sc, port);
@@ -1090,6 +1132,8 @@ e6000sw_port_vlan_conf(e6000sw_softc_t *sc)
/* Set port priority */
for (port = 0; port < sc->num_ports; port++) {
+ if (!e6000sw_is_portenabled(sc, port))
+ continue;
ret = e6000sw_readreg(sc, REG_PORT(port), PORT_VID);
ret &= ~PORT_VID_PRIORITY_MASK;
e6000sw_writereg(sc, REG_PORT(port), PORT_VID, ret);
@@ -1097,6 +1141,8 @@ e6000sw_port_vlan_conf(e6000sw_softc_t *sc)
/* Set VID map */
for (port = 0; port < sc->num_ports; port++) {
+ if (!e6000sw_is_portenabled(sc, port))
+ continue;
ret = e6000sw_readreg(sc, REG_PORT(port), PORT_VID);
ret &= ~PORT_VID_DEF_VID_MASK;
ret |= (port + 1);
@@ -1105,6 +1151,8 @@ e6000sw_port_vlan_conf(e6000sw_softc_t *sc)
/* Enable all ports */
for (port = 0; port < sc->num_ports; port++) {
+ if (!e6000sw_is_portenabled(sc, port))
+ continue;
ret = e6000sw_readreg(sc, REG_PORT(port), PORT_CONTROL);
e6000sw_writereg(sc, REG_PORT(port), PORT_CONTROL, (ret |
PORT_CONTROL_ENABLE));
More information about the svn-src-all
mailing list