@@ -804,6 +804,69 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port,
804
804
return 0 ;
805
805
}
806
806
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
+
807
870
static void
808
871
mt7530_port_bridge_leave (struct dsa_switch * ds , int port ,
809
872
struct net_device * bridge )
@@ -817,8 +880,11 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
817
880
/* Remove this port from the port matrix of the other ports
818
881
* in the same bridge. If the port is disabled, port matrix
819
882
* 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.
820
885
*/
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 ) {
822
888
if (dsa_to_port (ds , i )-> bridge_dev != bridge )
823
889
continue ;
824
890
if (priv -> ports [i ].enable )
@@ -836,6 +902,8 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
836
902
PCR_MATRIX (BIT (MT7530_CPU_PORT )));
837
903
priv -> ports [port ].pm = PCR_MATRIX (BIT (MT7530_CPU_PORT ));
838
904
905
+ mt7530_port_set_vlan_unaware (ds , port );
906
+
839
907
mutex_unlock (& priv -> reg_mutex );
840
908
}
841
909
@@ -906,6 +974,220 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port,
906
974
return 0 ;
907
975
}
908
976
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
+
909
1191
static enum dsa_tag_protocol
910
1192
mtk_get_tag_protocol (struct dsa_switch * ds , int port )
911
1193
{
@@ -1035,6 +1317,10 @@ static const struct dsa_switch_ops mt7530_switch_ops = {
1035
1317
.port_fdb_add = mt7530_port_fdb_add ,
1036
1318
.port_fdb_del = mt7530_port_fdb_del ,
1037
1319
.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 ,
1038
1324
};
1039
1325
1040
1326
static int
0 commit comments