164164#define VSC73XX_AGENCTRL 0xf0
165165#define VSC73XX_CAPRST 0xff
166166
167+ #define VSC73XX_SRCMASKS_CPU_COPY BIT(27)
168+ #define VSC73XX_SRCMASKS_MIRROR BIT(26)
169+ #define VSC73XX_SRCMASKS_PORTS_MASK GENMASK(7, 0)
170+
167171#define VSC73XX_MACACCESS_CPU_COPY BIT(14)
168172#define VSC73XX_MACACCESS_FWD_KILL BIT(13)
169173#define VSC73XX_MACACCESS_IGNORE_VLAN BIT(12)
@@ -623,9 +627,6 @@ static int vsc73xx_setup(struct dsa_switch *ds)
623627 vsc73xx_write (vsc , VSC73XX_BLOCK_SYSTEM , 0 , VSC73XX_GMIIDELAY ,
624628 VSC73XX_GMIIDELAY_GMII0_GTXDELAY_2_0_NS |
625629 VSC73XX_GMIIDELAY_GMII0_RXDELAY_2_0_NS );
626- /* Enable reception of frames on all ports */
627- vsc73xx_write (vsc , VSC73XX_BLOCK_ANALYZER , 0 , VSC73XX_RECVMASK ,
628- 0x5f );
629630 /* IP multicast flood mask (table 144) */
630631 vsc73xx_write (vsc , VSC73XX_BLOCK_ANALYZER , 0 , VSC73XX_IFLODMSK ,
631632 0xff );
@@ -788,10 +789,6 @@ static void vsc73xx_mac_link_down(struct phylink_config *config,
788789 /* Allow backward dropping of frames from this port */
789790 vsc73xx_update_bits (vsc , VSC73XX_BLOCK_ARBITER , 0 ,
790791 VSC73XX_SBACKWDROP , BIT (port ), BIT (port ));
791-
792- /* Receive mask (disable forwarding) */
793- vsc73xx_update_bits (vsc , VSC73XX_BLOCK_ANALYZER , 0 ,
794- VSC73XX_RECVMASK , BIT (port ), 0 );
795792}
796793
797794static void vsc73xx_mac_link_up (struct phylink_config * config ,
@@ -844,10 +841,6 @@ static void vsc73xx_mac_link_up(struct phylink_config *config,
844841 vsc73xx_update_bits (vsc , VSC73XX_BLOCK_ARBITER , 0 ,
845842 VSC73XX_ARBDISC , BIT (port ), 0 );
846843
847- /* Enable port (forwarding) in the receive mask */
848- vsc73xx_update_bits (vsc , VSC73XX_BLOCK_ANALYZER , 0 ,
849- VSC73XX_RECVMASK , BIT (port ), BIT (port ));
850-
851844 /* Disallow backward dropping of frames from this port */
852845 vsc73xx_update_bits (vsc , VSC73XX_BLOCK_ARBITER , 0 ,
853846 VSC73XX_SBACKWDROP , BIT (port ), 0 );
@@ -1039,6 +1032,86 @@ static void vsc73xx_phylink_get_caps(struct dsa_switch *dsa, int port,
10391032 config -> mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000 ;
10401033}
10411034
1035+ static void vsc73xx_refresh_fwd_map (struct dsa_switch * ds , int port , u8 state )
1036+ {
1037+ struct dsa_port * other_dp , * dp = dsa_to_port (ds , port );
1038+ struct vsc73xx * vsc = ds -> priv ;
1039+ u16 mask ;
1040+
1041+ if (state != BR_STATE_FORWARDING ) {
1042+ /* Ports that aren't in the forwarding state must not
1043+ * forward packets anywhere.
1044+ */
1045+ vsc73xx_update_bits (vsc , VSC73XX_BLOCK_ANALYZER , 0 ,
1046+ VSC73XX_SRCMASKS + port ,
1047+ VSC73XX_SRCMASKS_PORTS_MASK , 0 );
1048+
1049+ dsa_switch_for_each_available_port (other_dp , ds ) {
1050+ if (other_dp == dp )
1051+ continue ;
1052+ vsc73xx_update_bits (vsc , VSC73XX_BLOCK_ANALYZER , 0 ,
1053+ VSC73XX_SRCMASKS + other_dp -> index ,
1054+ BIT (port ), 0 );
1055+ }
1056+
1057+ return ;
1058+ }
1059+
1060+ /* Forwarding ports must forward to the CPU and to other ports
1061+ * in the same bridge
1062+ */
1063+ vsc73xx_update_bits (vsc , VSC73XX_BLOCK_ANALYZER , 0 ,
1064+ VSC73XX_SRCMASKS + CPU_PORT , BIT (port ), BIT (port ));
1065+
1066+ mask = BIT (CPU_PORT );
1067+
1068+ dsa_switch_for_each_user_port (other_dp , ds ) {
1069+ int other_port = other_dp -> index ;
1070+
1071+ if (port == other_port || !dsa_port_bridge_same (dp , other_dp ) ||
1072+ other_dp -> stp_state != BR_STATE_FORWARDING )
1073+ continue ;
1074+
1075+ mask |= BIT (other_port );
1076+
1077+ vsc73xx_update_bits (vsc , VSC73XX_BLOCK_ANALYZER , 0 ,
1078+ VSC73XX_SRCMASKS + other_port ,
1079+ BIT (port ), BIT (port ));
1080+ }
1081+
1082+ vsc73xx_update_bits (vsc , VSC73XX_BLOCK_ANALYZER , 0 ,
1083+ VSC73XX_SRCMASKS + port ,
1084+ VSC73XX_SRCMASKS_PORTS_MASK , mask );
1085+ }
1086+
1087+ /* FIXME: STP frames aren't forwarded at this moment. BPDU frames are
1088+ * forwarded only from and to PI/SI interface. For more info see chapter
1089+ * 2.7.1 (CPU Forwarding) in datasheet.
1090+ * This function is required for tag_8021q operations.
1091+ */
1092+ static void vsc73xx_port_stp_state_set (struct dsa_switch * ds , int port ,
1093+ u8 state )
1094+ {
1095+ struct vsc73xx * vsc = ds -> priv ;
1096+ u32 val ;
1097+
1098+ val = (state == BR_STATE_BLOCKING || state == BR_STATE_DISABLED ) ?
1099+ 0 : BIT (port );
1100+ vsc73xx_update_bits (vsc , VSC73XX_BLOCK_ANALYZER , 0 ,
1101+ VSC73XX_RECVMASK , BIT (port ), val );
1102+
1103+ val = (state == BR_STATE_LEARNING || state == BR_STATE_FORWARDING ) ?
1104+ BIT (port ) : 0 ;
1105+ vsc73xx_update_bits (vsc , VSC73XX_BLOCK_ANALYZER , 0 ,
1106+ VSC73XX_LEARNMASK , BIT (port ), val );
1107+
1108+ /* CPU Port should always forward packets when user ports are forwarding
1109+ * so let's configure it from other ports only.
1110+ */
1111+ if (port != CPU_PORT )
1112+ vsc73xx_refresh_fwd_map (ds , port , state );
1113+ }
1114+
10421115static const struct phylink_mac_ops vsc73xx_phylink_mac_ops = {
10431116 .mac_config = vsc73xx_mac_config ,
10441117 .mac_link_down = vsc73xx_mac_link_down ,
@@ -1057,6 +1130,7 @@ static const struct dsa_switch_ops vsc73xx_ds_ops = {
10571130 .port_disable = vsc73xx_port_disable ,
10581131 .port_change_mtu = vsc73xx_change_mtu ,
10591132 .port_max_mtu = vsc73xx_get_max_mtu ,
1133+ .port_stp_state_set = vsc73xx_port_stp_state_set ,
10601134 .phylink_get_caps = vsc73xx_phylink_get_caps ,
10611135};
10621136
0 commit comments