mvsw61xx: track and set per-VLAN port state in STU
Since the driver doesn't know anything about (M)STP we just hard-set the ports to be enabled if they are part of the VLAN. Signed-off-by: Claudio Leite <leitec@staticky.com> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@43938 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
245edbac0b
commit
1a59c96060
|
@ -2,6 +2,7 @@
|
||||||
* Marvell 88E61xx switch driver
|
* Marvell 88E61xx switch driver
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014 Claudio Leite <leitec@staticky.com>
|
* Copyright (c) 2014 Claudio Leite <leitec@staticky.com>
|
||||||
|
* Copyright (c) 2014 Nikita Nazarenko <nnazarenko@radiofid.com>
|
||||||
*
|
*
|
||||||
* Based on code (c) 2008 Felix Fietkau <nbd@openwrt.org>
|
* Based on code (c) 2008 Felix Fietkau <nbd@openwrt.org>
|
||||||
*
|
*
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Marvell 88E61xx Switch driver");
|
MODULE_DESCRIPTION("Marvell 88E61xx Switch driver");
|
||||||
MODULE_AUTHOR("Claudio Leite <leitec@staticky.com>");
|
MODULE_AUTHOR("Claudio Leite <leitec@staticky.com>");
|
||||||
|
MODULE_AUTHOR("Nikita Nazarenko <nnazarenko@radiofid.com>");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
MODULE_ALIAS("platform:mvsw61xx");
|
MODULE_ALIAS("platform:mvsw61xx");
|
||||||
|
|
||||||
|
@ -333,6 +335,7 @@ static int mvsw61xx_set_vlan_ports(struct switch_dev *dev,
|
||||||
|
|
||||||
state->vlans[vno].mask = 0;
|
state->vlans[vno].mask = 0;
|
||||||
state->vlans[vno].port_mode = 0;
|
state->vlans[vno].port_mode = 0;
|
||||||
|
state->vlans[vno].port_sstate = 0;
|
||||||
|
|
||||||
if(state->vlans[vno].vid == 0)
|
if(state->vlans[vno].vid == 0)
|
||||||
state->vlans[vno].vid = vno;
|
state->vlans[vno].vid = vno;
|
||||||
|
@ -348,6 +351,8 @@ static int mvsw61xx_set_vlan_ports(struct switch_dev *dev,
|
||||||
mode = MV_VTUCTL_EGRESS_UNTAGGED;
|
mode = MV_VTUCTL_EGRESS_UNTAGGED;
|
||||||
|
|
||||||
state->vlans[vno].port_mode |= mode << (pno * 4);
|
state->vlans[vno].port_mode |= mode << (pno * 4);
|
||||||
|
state->vlans[vno].port_sstate |=
|
||||||
|
MV_STUCTL_STATE_FORWARDING << (pno * 4 + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -447,7 +452,7 @@ static int mvsw61xx_set_enable_vlan(struct switch_dev *dev,
|
||||||
static int mvsw61xx_vtu_program(struct switch_dev *dev)
|
static int mvsw61xx_vtu_program(struct switch_dev *dev)
|
||||||
{
|
{
|
||||||
struct mvsw61xx_state *state = get_state(dev);
|
struct mvsw61xx_state *state = get_state(dev);
|
||||||
u16 v1, v2;
|
u16 v1, v2, s1, s2;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Flush */
|
/* Flush */
|
||||||
|
@ -466,14 +471,32 @@ static int mvsw61xx_vtu_program(struct switch_dev *dev)
|
||||||
mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
|
mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
|
||||||
MV_VTUOP_INPROGRESS, 0);
|
MV_VTUOP_INPROGRESS, 0);
|
||||||
|
|
||||||
|
/* Write per-VLAN port state into STU */
|
||||||
|
s1 = (u16) (state->vlans[i].port_sstate & 0xffff);
|
||||||
|
s2 = (u16) ((state->vlans[i].port_sstate >> 16) & 0xffff);
|
||||||
|
|
||||||
|
sw16(dev, MV_GLOBALREG(VTU_VID), MV_VTU_VID_VALID);
|
||||||
|
sw16(dev, MV_GLOBALREG(VTU_SID), i);
|
||||||
|
sw16(dev, MV_GLOBALREG(VTU_DATA1), s1);
|
||||||
|
sw16(dev, MV_GLOBALREG(VTU_DATA2), s2);
|
||||||
|
sw16(dev, MV_GLOBALREG(VTU_DATA3), 0);
|
||||||
|
|
||||||
|
sw16(dev, MV_GLOBALREG(VTU_OP),
|
||||||
|
MV_VTUOP_INPROGRESS | MV_VTUOP_STULOAD);
|
||||||
|
mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
|
||||||
|
MV_VTUOP_INPROGRESS, 0);
|
||||||
|
|
||||||
|
/* Write VLAN information into VTU */
|
||||||
|
v1 = (u16) (state->vlans[i].port_mode & 0xffff);
|
||||||
|
v2 = (u16) ((state->vlans[i].port_mode >> 16) & 0xffff);
|
||||||
|
|
||||||
sw16(dev, MV_GLOBALREG(VTU_VID),
|
sw16(dev, MV_GLOBALREG(VTU_VID),
|
||||||
MV_VTU_VID_VALID | state->vlans[i].vid);
|
MV_VTU_VID_VALID | state->vlans[i].vid);
|
||||||
|
sw16(dev, MV_GLOBALREG(VTU_SID), i);
|
||||||
v1 = (u16)(state->vlans[i].port_mode & 0xffff);
|
sw16(dev, MV_GLOBALREG(VTU_FID), 0);
|
||||||
v2 = (u16)((state->vlans[i].port_mode >> 16) & 0xffff);
|
|
||||||
|
|
||||||
sw16(dev, MV_GLOBALREG(VTU_DATA1), v1);
|
sw16(dev, MV_GLOBALREG(VTU_DATA1), v1);
|
||||||
sw16(dev, MV_GLOBALREG(VTU_DATA2), v2);
|
sw16(dev, MV_GLOBALREG(VTU_DATA2), v2);
|
||||||
|
sw16(dev, MV_GLOBALREG(VTU_DATA3), 0);
|
||||||
|
|
||||||
sw16(dev, MV_GLOBALREG(VTU_OP),
|
sw16(dev, MV_GLOBALREG(VTU_OP),
|
||||||
MV_VTUOP_INPROGRESS | MV_VTUOP_LOAD);
|
MV_VTUOP_INPROGRESS | MV_VTUOP_LOAD);
|
||||||
|
@ -514,8 +537,6 @@ static int mvsw61xx_update_state(struct switch_dev *dev)
|
||||||
if (!state->registered)
|
if (!state->registered)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mvsw61xx_vtu_program(dev);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set 802.1q-only mode if vlan_enabled is true.
|
* Set 802.1q-only mode if vlan_enabled is true.
|
||||||
*
|
*
|
||||||
|
@ -568,6 +589,8 @@ static int mvsw61xx_update_state(struct switch_dev *dev)
|
||||||
sw16(dev, MV_PORTREG(CONTROL2, i), reg);
|
sw16(dev, MV_PORTREG(CONTROL2, i), reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mvsw61xx_vtu_program(dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,6 +638,7 @@ static int mvsw61xx_reset(struct switch_dev *dev)
|
||||||
state->vlans[i].mask = 0;
|
state->vlans[i].mask = 0;
|
||||||
state->vlans[i].vid = 0;
|
state->vlans[i].vid = 0;
|
||||||
state->vlans[i].port_mode = 0;
|
state->vlans[i].port_mode = 0;
|
||||||
|
state->vlans[i].port_sstate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->vlan_enabled = 0;
|
state->vlan_enabled = 0;
|
||||||
|
|
|
@ -249,6 +249,7 @@ struct mvsw61xx_state {
|
||||||
u16 mask;
|
u16 mask;
|
||||||
u16 vid;
|
u16 vid;
|
||||||
u32 port_mode;
|
u32 port_mode;
|
||||||
|
u32 port_sstate;
|
||||||
} vlans[MV_VLANS];
|
} vlans[MV_VLANS];
|
||||||
|
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
Loading…
Reference in New Issue