@@ -804,6 +804,69 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port,
804804 return 0 ;
805805}
806806
807+ static void
808+ mt7530_port_set_vlan_unaware (struct dsa_switch * ds , int port )
809+ {
810+ struct mt7530_priv * priv = ds -> priv ;
811+ bool all_user_ports_removed = true;
812+ int i ;
813+
814+ /* When a port is removed from the bridge, the port would be set up
815+ * back to the default as is at initial boot which is a VLAN-unaware
816+ * port.
817+ */
818+ mt7530_rmw (priv , MT7530_PCR_P (port ), PCR_PORT_VLAN_MASK ,
819+ MT7530_PORT_MATRIX_MODE );
820+ mt7530_rmw (priv , MT7530_PVC_P (port ), VLAN_ATTR_MASK ,
821+ VLAN_ATTR (MT7530_VLAN_TRANSPARENT ));
822+
823+ priv -> ports [port ].vlan_filtering = false;
824+
825+ for (i = 0 ; i < MT7530_NUM_PORTS ; i ++ ) {
826+ if (dsa_is_user_port (ds , i ) &&
827+ priv -> ports [i ].vlan_filtering ) {
828+ all_user_ports_removed = false;
829+ break ;
830+ }
831+ }
832+
833+ /* CPU port also does the same thing until all user ports belonging to
834+ * the CPU port get out of VLAN filtering mode.
835+ */
836+ if (all_user_ports_removed ) {
837+ mt7530_write (priv , MT7530_PCR_P (MT7530_CPU_PORT ),
838+ PCR_MATRIX (dsa_user_ports (priv -> ds )));
839+ mt7530_write (priv , MT7530_PVC_P (MT7530_CPU_PORT ),
840+ PORT_SPEC_TAG );
841+ }
842+ }
843+
844+ static void
845+ mt7530_port_set_vlan_aware (struct dsa_switch * ds , int port )
846+ {
847+ struct mt7530_priv * priv = ds -> priv ;
848+
849+ /* The real fabric path would be decided on the membership in the
850+ * entry of VLAN table. PCR_MATRIX set up here with ALL_MEMBERS
851+ * means potential VLAN can be consisting of certain subset of all
852+ * ports.
853+ */
854+ mt7530_rmw (priv , MT7530_PCR_P (port ),
855+ PCR_MATRIX_MASK , PCR_MATRIX (MT7530_ALL_MEMBERS ));
856+
857+ /* Trapped into security mode allows packet forwarding through VLAN
858+ * table lookup.
859+ */
860+ mt7530_rmw (priv , MT7530_PCR_P (port ), PCR_PORT_VLAN_MASK ,
861+ MT7530_PORT_SECURITY_MODE );
862+
863+ /* Set the port as a user port which is to be able to recognize VID
864+ * from incoming packets before fetching entry within the VLAN table.
865+ */
866+ mt7530_rmw (priv , MT7530_PVC_P (port ), VLAN_ATTR_MASK ,
867+ VLAN_ATTR (MT7530_VLAN_USER ));
868+ }
869+
807870static void
808871mt7530_port_bridge_leave (struct dsa_switch * ds , int port ,
809872 struct net_device * bridge )
@@ -817,8 +880,11 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
817880 /* Remove this port from the port matrix of the other ports
818881 * in the same bridge. If the port is disabled, port matrix
819882 * is kept and not being setup until the port becomes enabled.
883+ * And the other port's port matrix cannot be broken when the
884+ * other port is still a VLAN-aware port.
820885 */
821- if (dsa_is_user_port (ds , i ) && i != port ) {
886+ if (!priv -> ports [i ].vlan_filtering &&
887+ dsa_is_user_port (ds , i ) && i != port ) {
822888 if (dsa_to_port (ds , i )-> bridge_dev != bridge )
823889 continue ;
824890 if (priv -> ports [i ].enable )
@@ -836,6 +902,8 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
836902 PCR_MATRIX (BIT (MT7530_CPU_PORT )));
837903 priv -> ports [port ].pm = PCR_MATRIX (BIT (MT7530_CPU_PORT ));
838904
905+ mt7530_port_set_vlan_unaware (ds , port );
906+
839907 mutex_unlock (& priv -> reg_mutex );
840908}
841909
@@ -906,6 +974,220 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port,
906974 return 0 ;
907975}
908976
977+ static int
978+ mt7530_vlan_cmd (struct mt7530_priv * priv , enum mt7530_vlan_cmd cmd , u16 vid )
979+ {
980+ struct mt7530_dummy_poll p ;
981+ u32 val ;
982+ int ret ;
983+
984+ val = VTCR_BUSY | VTCR_FUNC (cmd ) | vid ;
985+ mt7530_write (priv , MT7530_VTCR , val );
986+
987+ INIT_MT7530_DUMMY_POLL (& p , priv , MT7530_VTCR );
988+ ret = readx_poll_timeout (_mt7530_read , & p , val ,
989+ !(val & VTCR_BUSY ), 20 , 20000 );
990+ if (ret < 0 ) {
991+ dev_err (priv -> dev , "poll timeout\n" );
992+ return ret ;
993+ }
994+
995+ val = mt7530_read (priv , MT7530_VTCR );
996+ if (val & VTCR_INVALID ) {
997+ dev_err (priv -> dev , "read VTCR invalid\n" );
998+ return - EINVAL ;
999+ }
1000+
1001+ return 0 ;
1002+ }
1003+
1004+ static int
1005+ mt7530_port_vlan_filtering (struct dsa_switch * ds , int port ,
1006+ bool vlan_filtering )
1007+ {
1008+ struct mt7530_priv * priv = ds -> priv ;
1009+
1010+ priv -> ports [port ].vlan_filtering = vlan_filtering ;
1011+
1012+ if (vlan_filtering ) {
1013+ /* The port is being kept as VLAN-unaware port when bridge is
1014+ * set up with vlan_filtering not being set, Otherwise, the
1015+ * port and the corresponding CPU port is required the setup
1016+ * for becoming a VLAN-aware port.
1017+ */
1018+ mt7530_port_set_vlan_aware (ds , port );
1019+ mt7530_port_set_vlan_aware (ds , MT7530_CPU_PORT );
1020+ }
1021+
1022+ return 0 ;
1023+ }
1024+
1025+ static int
1026+ mt7530_port_vlan_prepare (struct dsa_switch * ds , int port ,
1027+ const struct switchdev_obj_port_vlan * vlan )
1028+ {
1029+ /* nothing needed */
1030+
1031+ return 0 ;
1032+ }
1033+
1034+ static void
1035+ mt7530_hw_vlan_add (struct mt7530_priv * priv ,
1036+ struct mt7530_hw_vlan_entry * entry )
1037+ {
1038+ u8 new_members ;
1039+ u32 val ;
1040+
1041+ new_members = entry -> old_members | BIT (entry -> port ) |
1042+ BIT (MT7530_CPU_PORT );
1043+
1044+ /* Validate the entry with independent learning, create egress tag per
1045+ * VLAN and joining the port as one of the port members.
1046+ */
1047+ val = IVL_MAC | VTAG_EN | PORT_MEM (new_members ) | VLAN_VALID ;
1048+ mt7530_write (priv , MT7530_VAWD1 , val );
1049+
1050+ /* Decide whether adding tag or not for those outgoing packets from the
1051+ * port inside the VLAN.
1052+ */
1053+ val = entry -> untagged ? MT7530_VLAN_EGRESS_UNTAG :
1054+ MT7530_VLAN_EGRESS_TAG ;
1055+ mt7530_rmw (priv , MT7530_VAWD2 ,
1056+ ETAG_CTRL_P_MASK (entry -> port ),
1057+ ETAG_CTRL_P (entry -> port , val ));
1058+
1059+ /* CPU port is always taken as a tagged port for serving more than one
1060+ * VLANs across and also being applied with egress type stack mode for
1061+ * that VLAN tags would be appended after hardware special tag used as
1062+ * DSA tag.
1063+ */
1064+ mt7530_rmw (priv , MT7530_VAWD2 ,
1065+ ETAG_CTRL_P_MASK (MT7530_CPU_PORT ),
1066+ ETAG_CTRL_P (MT7530_CPU_PORT ,
1067+ MT7530_VLAN_EGRESS_STACK ));
1068+ }
1069+
1070+ static void
1071+ mt7530_hw_vlan_del (struct mt7530_priv * priv ,
1072+ struct mt7530_hw_vlan_entry * entry )
1073+ {
1074+ u8 new_members ;
1075+ u32 val ;
1076+
1077+ new_members = entry -> old_members & ~BIT (entry -> port );
1078+
1079+ val = mt7530_read (priv , MT7530_VAWD1 );
1080+ if (!(val & VLAN_VALID )) {
1081+ dev_err (priv -> dev ,
1082+ "Cannot be deleted due to invalid entry\n" );
1083+ return ;
1084+ }
1085+
1086+ /* If certain member apart from CPU port is still alive in the VLAN,
1087+ * the entry would be kept valid. Otherwise, the entry is got to be
1088+ * disabled.
1089+ */
1090+ if (new_members && new_members != BIT (MT7530_CPU_PORT )) {
1091+ val = IVL_MAC | VTAG_EN | PORT_MEM (new_members ) |
1092+ VLAN_VALID ;
1093+ mt7530_write (priv , MT7530_VAWD1 , val );
1094+ } else {
1095+ mt7530_write (priv , MT7530_VAWD1 , 0 );
1096+ mt7530_write (priv , MT7530_VAWD2 , 0 );
1097+ }
1098+ }
1099+
1100+ static void
1101+ mt7530_hw_vlan_update (struct mt7530_priv * priv , u16 vid ,
1102+ struct mt7530_hw_vlan_entry * entry ,
1103+ mt7530_vlan_op vlan_op )
1104+ {
1105+ u32 val ;
1106+
1107+ /* Fetch entry */
1108+ mt7530_vlan_cmd (priv , MT7530_VTCR_RD_VID , vid );
1109+
1110+ val = mt7530_read (priv , MT7530_VAWD1 );
1111+
1112+ entry -> old_members = (val >> PORT_MEM_SHFT ) & PORT_MEM_MASK ;
1113+
1114+ /* Manipulate entry */
1115+ vlan_op (priv , entry );
1116+
1117+ /* Flush result to hardware */
1118+ mt7530_vlan_cmd (priv , MT7530_VTCR_WR_VID , vid );
1119+ }
1120+
1121+ static void
1122+ mt7530_port_vlan_add (struct dsa_switch * ds , int port ,
1123+ const struct switchdev_obj_port_vlan * vlan )
1124+ {
1125+ bool untagged = vlan -> flags & BRIDGE_VLAN_INFO_UNTAGGED ;
1126+ bool pvid = vlan -> flags & BRIDGE_VLAN_INFO_PVID ;
1127+ struct mt7530_hw_vlan_entry new_entry ;
1128+ struct mt7530_priv * priv = ds -> priv ;
1129+ u16 vid ;
1130+
1131+ /* The port is kept as VLAN-unaware if bridge with vlan_filtering not
1132+ * being set.
1133+ */
1134+ if (!priv -> ports [port ].vlan_filtering )
1135+ return ;
1136+
1137+ mutex_lock (& priv -> reg_mutex );
1138+
1139+ for (vid = vlan -> vid_begin ; vid <= vlan -> vid_end ; ++ vid ) {
1140+ mt7530_hw_vlan_entry_init (& new_entry , port , untagged );
1141+ mt7530_hw_vlan_update (priv , vid , & new_entry ,
1142+ mt7530_hw_vlan_add );
1143+ }
1144+
1145+ if (pvid ) {
1146+ mt7530_rmw (priv , MT7530_PPBV1_P (port ), G0_PORT_VID_MASK ,
1147+ G0_PORT_VID (vlan -> vid_end ));
1148+ priv -> ports [port ].pvid = vlan -> vid_end ;
1149+ }
1150+
1151+ mutex_unlock (& priv -> reg_mutex );
1152+ }
1153+
1154+ static int
1155+ mt7530_port_vlan_del (struct dsa_switch * ds , int port ,
1156+ const struct switchdev_obj_port_vlan * vlan )
1157+ {
1158+ struct mt7530_hw_vlan_entry target_entry ;
1159+ struct mt7530_priv * priv = ds -> priv ;
1160+ u16 vid , pvid ;
1161+
1162+ /* The port is kept as VLAN-unaware if bridge with vlan_filtering not
1163+ * being set.
1164+ */
1165+ if (!priv -> ports [port ].vlan_filtering )
1166+ return 0 ;
1167+
1168+ mutex_lock (& priv -> reg_mutex );
1169+
1170+ pvid = priv -> ports [port ].pvid ;
1171+ for (vid = vlan -> vid_begin ; vid <= vlan -> vid_end ; ++ vid ) {
1172+ mt7530_hw_vlan_entry_init (& target_entry , port , 0 );
1173+ mt7530_hw_vlan_update (priv , vid , & target_entry ,
1174+ mt7530_hw_vlan_del );
1175+
1176+ /* PVID is being restored to the default whenever the PVID port
1177+ * is being removed from the VLAN.
1178+ */
1179+ if (pvid == vid )
1180+ pvid = G0_PORT_VID_DEF ;
1181+ }
1182+
1183+ mt7530_rmw (priv , MT7530_PPBV1_P (port ), G0_PORT_VID_MASK , pvid );
1184+ priv -> ports [port ].pvid = pvid ;
1185+
1186+ mutex_unlock (& priv -> reg_mutex );
1187+
1188+ return 0 ;
1189+ }
1190+
9091191static enum dsa_tag_protocol
9101192mtk_get_tag_protocol (struct dsa_switch * ds , int port )
9111193{
@@ -1035,6 +1317,10 @@ static const struct dsa_switch_ops mt7530_switch_ops = {
10351317 .port_fdb_add = mt7530_port_fdb_add ,
10361318 .port_fdb_del = mt7530_port_fdb_del ,
10371319 .port_fdb_dump = mt7530_port_fdb_dump ,
1320+ .port_vlan_filtering = mt7530_port_vlan_filtering ,
1321+ .port_vlan_prepare = mt7530_port_vlan_prepare ,
1322+ .port_vlan_add = mt7530_port_vlan_add ,
1323+ .port_vlan_del = mt7530_port_vlan_del ,
10381324};
10391325
10401326static int
0 commit comments