summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorloos <loos@FreeBSD.org>2014-07-03 19:50:50 +0000
committerloos <loos@FreeBSD.org>2014-07-03 19:50:50 +0000
commit96e0511f76f7debf0367ed7cd41ea6c63cff6c10 (patch)
tree2d7d9ab9723a22c6942df7f4c8eeb1931c0f47be /sys/dev
parente485fdb2be7a90a72fae6d2ca4a25b3be290cfb8 (diff)
downloadFreeBSD-src-96e0511f76f7debf0367ed7cd41ea6c63cff6c10.zip
FreeBSD-src-96e0511f76f7debf0367ed7cd41ea6c63cff6c10.tar.gz
Initialize the switch vlan table at attachment.
Update some comments on code, specifying the correct vlans used on switch setup. Advertise the proper switch operation mode (the rtl8366rb only support dot1q vlans). This fixes the breakage that i introduced on r249752 and make the rtl8366rb switch works again with etherswitchcfg(8). Tested on TP-Link 1043ND. Tested by: me, Harm Weites (harm at weites.com)
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/etherswitch/rtl8366/rtl8366rb.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/sys/dev/etherswitch/rtl8366/rtl8366rb.c b/sys/dev/etherswitch/rtl8366/rtl8366rb.c
index 115fa62..78eae5d 100644
--- a/sys/dev/etherswitch/rtl8366/rtl8366rb.c
+++ b/sys/dev/etherswitch/rtl8366/rtl8366rb.c
@@ -75,7 +75,8 @@ struct rtl8366rb_softc {
static etherswitch_info_t etherswitch_info = {
.es_nports = RTL8366RB_NUM_PORTS,
.es_nvlangroups = RTL8366RB_NUM_VLANS,
- .es_name = "Realtek RTL8366RB"
+ .es_name = "Realtek RTL8366RB",
+ .es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q,
};
#define RTL_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
@@ -148,6 +149,9 @@ rtl8366rb_probe(device_t dev)
static void
rtl8366rb_init(device_t dev)
{
+ int i;
+ struct rtl8366rb_softc *sc;
+
/* Initialisation for TL-WR1043ND */
smi_rmw(dev, RTL8366RB_RCR,
RTL8366RB_RCR_HARD_RESET,
@@ -157,17 +161,21 @@ rtl8366rb_init(device_t dev)
smi_rmw(dev, RTL8366RB_SGCR,
RTL8366RB_SGCR_EN_VLAN | RTL8366RB_SGCR_EN_VLAN_4KTB,
RTL8366RB_SGCR_EN_VLAN, RTL_WAITOK);
- /* remove port 0 form VLAN 0 */
+ /* Initialize our vlan table. */
+ sc = device_get_softc(dev);
+ for (i = 0; i <= 1; i++)
+ sc->vid[i] = (i + 1) | ETHERSWITCH_VID_VALID;
+ /* Remove port 0 from VLAN 1. */
smi_rmw(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, 0),
(1 << 0), 0, RTL_WAITOK);
- /* add port 0 untagged and port 5 tagged to VLAN 1 */
+ /* Add port 0 untagged and port 5 tagged to VLAN 2. */
smi_rmw(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, 1),
((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_MEMBER_SHIFT)
| ((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_UNTAG_SHIFT),
((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_MEMBER_SHIFT
| ((1 << 0) << RTL8366RB_VMCR_MU_UNTAG_SHIFT)),
RTL_WAITOK);
- /* set PVLAN 1 for port 0 */
+ /* Set PVID 2 for port 0. */
smi_rmw(dev, RTL8366RB_PVCR_REG(0),
RTL8366RB_PVCR_VAL(0, RTL8366RB_PVCR_PORT_MASK),
RTL8366RB_PVCR_VAL(0, 1), RTL_WAITOK);
@@ -560,7 +568,7 @@ rtl_getport(device_t dev, etherswitch_port_t *p)
sc = device_get_softc(dev);
vlangroup = RTL8366RB_PVCR_GET(p->es_port,
rtl_readreg(dev, RTL8366RB_PVCR_REG(p->es_port)));
- p->es_pvid = sc->vid[vlangroup];
+ p->es_pvid = sc->vid[vlangroup] & ETHERSWITCH_VID_MASK;
if (p->es_port < RTL8366RB_NUM_PHYS) {
mii = device_get_softc(sc->miibus[p->es_port]);
@@ -595,7 +603,7 @@ rtl_setport(device_t dev, etherswitch_port_t *p)
sc = device_get_softc(dev);
vlangroup = -1;
for (i = 0; i < RTL8366RB_NUM_VLANS; i++) {
- if (sc->vid[i] == p->es_pvid) {
+ if ((sc->vid[i] & ETHERSWITCH_VID_MASK) == p->es_pvid) {
vlangroup = i;
break;
}
@@ -618,13 +626,15 @@ rtl_setport(device_t dev, etherswitch_port_t *p)
static int
rtl_getvgroup(device_t dev, etherswitch_vlangroup_t *vg)
{
+ struct rtl8366rb_softc *sc;
uint16_t vmcr[3];
int i;
for (i=0; i<3; i++)
vmcr[i] = rtl_readreg(dev, RTL8366RB_VMCR(i, vg->es_vlangroup));
- vg->es_vid = RTL8366RB_VMCR_VID(vmcr) | ETHERSWITCH_VID_VALID;
+ sc = device_get_softc(dev);
+ vg->es_vid = sc->vid[vg->es_vlangroup];
vg->es_member_ports = RTL8366RB_VMCR_MEMBER(vmcr);
vg->es_untagged_ports = RTL8366RB_VMCR_UNTAG(vmcr);
vg->es_fid = RTL8366RB_VMCR_FID(vmcr);
@@ -639,6 +649,10 @@ rtl_setvgroup(device_t dev, etherswitch_vlangroup_t *vg)
sc = device_get_softc(dev);
sc->vid[g] = vg->es_vid;
+ /* VLAN group disabled ? */
+ if (vg->es_member_ports == 0 && vg->es_untagged_ports == 0 && vg->es_vid == 0)
+ return (0);
+ sc->vid[g] |= ETHERSWITCH_VID_VALID;
rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_DOT1Q_REG, g),
(vg->es_vid << RTL8366RB_VMCR_DOT1Q_VID_SHIFT) & RTL8366RB_VMCR_DOT1Q_VID_MASK);
rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, g),
@@ -650,6 +664,17 @@ rtl_setvgroup(device_t dev, etherswitch_vlangroup_t *vg)
}
static int
+rtl_getconf(device_t dev, etherswitch_conf_t *conf)
+{
+
+ /* Return the VLAN mode. */
+ conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
+ conf->vlan_mode = ETHERSWITCH_VLAN_DOT1Q;
+
+ return (0);
+}
+
+static int
rtl_readphy(device_t dev, int phy, int reg)
{
struct rtl8366rb_softc *sc = device_get_softc(dev);
@@ -748,6 +773,7 @@ static device_method_t rtl8366rb_methods[] = {
DEVMETHOD(miibus_writereg, rtl_writephy),
/* etherswitch interface */
+ DEVMETHOD(etherswitch_getconf, rtl_getconf),
DEVMETHOD(etherswitch_getinfo, rtl_getinfo),
DEVMETHOD(etherswitch_readreg, rtl_readreg),
DEVMETHOD(etherswitch_writereg, rtl_writereg),
OpenPOWER on IntegriCloud