[OpenWrt-Devel] [PATCH 4/4] mvsw61xx: track and set per-VLAN port state in STU

Claudio Leite leitec at staticky.com
Fri Jan 9 12:12:50 EST 2015


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 at staticky.com>
---
 .../linux/generic/files/drivers/net/phy/mvsw61xx.c | 38 ++++++++++++++++++----
 .../linux/generic/files/drivers/net/phy/mvsw61xx.h |  1 +
 2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/target/linux/generic/files/drivers/net/phy/mvsw61xx.c b/target/linux/generic/files/drivers/net/phy/mvsw61xx.c
index 7ddb13e..116f6cf 100644
--- a/target/linux/generic/files/drivers/net/phy/mvsw61xx.c
+++ b/target/linux/generic/files/drivers/net/phy/mvsw61xx.c
@@ -2,6 +2,7 @@
  * Marvell 88E61xx switch driver
  *
  * Copyright (c) 2014 Claudio Leite <leitec at staticky.com>
+ * Copyright (c) 2014 Nikita Nazarenko <nnazarenko at radiofid.com>
  *
  * Based on code (c) 2008 Felix Fietkau <nbd at openwrt.org>
  *
@@ -27,6 +28,7 @@
 
 MODULE_DESCRIPTION("Marvell 88E61xx Switch driver");
 MODULE_AUTHOR("Claudio Leite <leitec at staticky.com>");
+MODULE_AUTHOR("Nikita Nazarenko <nnazarenko at radiofid.com>");
 MODULE_LICENSE("GPL v2");
 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].port_mode = 0;
+	state->vlans[vno].port_sstate = 0;
 
 	if(state->vlans[vno].vid == 0)
 		state->vlans[vno].vid = vno;
@@ -348,6 +351,8 @@ static int mvsw61xx_set_vlan_ports(struct switch_dev *dev,
 			mode = MV_VTUCTL_EGRESS_UNTAGGED;
 
 		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)
 {
 	struct mvsw61xx_state *state = get_state(dev);
-	u16 v1, v2;
+	u16 v1, v2, s1, s2;
 	int i;
 
 	/* Flush */
@@ -466,14 +471,32 @@ static int mvsw61xx_vtu_program(struct switch_dev *dev)
 		mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
 				MV_VTUOP_INPROGRESS, 0);
 
-		sw16(dev, MV_GLOBALREG(VTU_VID),
-				MV_VTU_VID_VALID | state->vlans[i].vid);
+		/* 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);
 
-		v1 = (u16)(state->vlans[i].port_mode & 0xffff);
-		v2 = (u16)((state->vlans[i].port_mode >> 16) & 0xffff);
+		/* 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),
+				MV_VTU_VID_VALID | state->vlans[i].vid);
+		sw16(dev, MV_GLOBALREG(VTU_SID), i);
+		sw16(dev, MV_GLOBALREG(VTU_FID), 0);
 		sw16(dev, MV_GLOBALREG(VTU_DATA1), v1);
 		sw16(dev, MV_GLOBALREG(VTU_DATA2), v2);
+		sw16(dev, MV_GLOBALREG(VTU_DATA3), 0);
 
 		sw16(dev, MV_GLOBALREG(VTU_OP),
 				MV_VTUOP_INPROGRESS | MV_VTUOP_LOAD);
@@ -514,8 +537,6 @@ static int mvsw61xx_update_state(struct switch_dev *dev)
 	if (!state->registered)
 		return -EINVAL;
 
-	mvsw61xx_vtu_program(dev);
-
 	/*
 	 * 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);
 	}
 
+	mvsw61xx_vtu_program(dev);
+
 	return 0;
 }
 
@@ -615,6 +638,7 @@ static int mvsw61xx_reset(struct switch_dev *dev)
 		state->vlans[i].mask = 0;
 		state->vlans[i].vid = 0;
 		state->vlans[i].port_mode = 0;
+		state->vlans[i].port_sstate = 0;
 	}
 
 	state->vlan_enabled = 0;
diff --git a/target/linux/generic/files/drivers/net/phy/mvsw61xx.h b/target/linux/generic/files/drivers/net/phy/mvsw61xx.h
index 8bd6f9a..61e134c 100644
--- a/target/linux/generic/files/drivers/net/phy/mvsw61xx.h
+++ b/target/linux/generic/files/drivers/net/phy/mvsw61xx.h
@@ -249,6 +249,7 @@ struct mvsw61xx_state {
 		u16 mask;
 		u16 vid;
 		u32 port_mode;
+		u32 port_sstate;
 	} vlans[MV_VLANS];
 
 	char buf[128];
-- 
2.2.1
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list