@@ -1087,12 +1087,32 @@ static int mv88e6xxx_set_port_state(struct dsa_switch *ds, int port, u8 state)
1087
1087
return ret ;
1088
1088
}
1089
1089
1090
- static int _mv88e6xxx_port_vlan_map_set (struct dsa_switch * ds , int port ,
1091
- u16 output_ports )
1090
+ static int _mv88e6xxx_port_based_vlan_map (struct dsa_switch * ds , int port )
1092
1091
{
1093
1092
struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
1093
+ struct net_device * bridge = ps -> ports [port ].bridge_dev ;
1094
1094
const u16 mask = (1 << ps -> num_ports ) - 1 ;
1095
+ u16 output_ports = 0 ;
1095
1096
int reg ;
1097
+ int i ;
1098
+
1099
+ /* allow CPU port or DSA link(s) to send frames to every port */
1100
+ if (dsa_is_cpu_port (ds , port ) || dsa_is_dsa_port (ds , port )) {
1101
+ output_ports = mask ;
1102
+ } else {
1103
+ for (i = 0 ; i < ps -> num_ports ; ++ i ) {
1104
+ /* allow sending frames to every group member */
1105
+ if (bridge && ps -> ports [i ].bridge_dev == bridge )
1106
+ output_ports |= BIT (i );
1107
+
1108
+ /* allow sending frames to CPU port and DSA link(s) */
1109
+ if (dsa_is_cpu_port (ds , i ) || dsa_is_dsa_port (ds , i ))
1110
+ output_ports |= BIT (i );
1111
+ }
1112
+ }
1113
+
1114
+ /* prevent frames from going back out of the port they came in on */
1115
+ output_ports &= ~BIT (port );
1096
1116
1097
1117
reg = _mv88e6xxx_reg_read (ds , REG_PORT (port ), PORT_BASE_VLAN );
1098
1118
if (reg < 0 )
@@ -2114,7 +2134,17 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
2114
2134
if (err )
2115
2135
goto unlock ;
2116
2136
2137
+ /* Assign the bridge and remap each port's VLANTable */
2117
2138
ps -> ports [port ].bridge_dev = bridge ;
2139
+
2140
+ for (i = 0 ; i < ps -> num_ports ; ++ i ) {
2141
+ if (ps -> ports [i ].bridge_dev == bridge ) {
2142
+ err = _mv88e6xxx_port_based_vlan_map (ds , i );
2143
+ if (err )
2144
+ break ;
2145
+ }
2146
+ }
2147
+
2118
2148
unlock :
2119
2149
mutex_unlock (& ps -> smi_mutex );
2120
2150
@@ -2124,8 +2154,9 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
2124
2154
int mv88e6xxx_port_bridge_leave (struct dsa_switch * ds , int port )
2125
2155
{
2126
2156
struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
2157
+ struct net_device * bridge = ps -> ports [port ].bridge_dev ;
2127
2158
u16 fid ;
2128
- int err ;
2159
+ int i , err ;
2129
2160
2130
2161
mutex_lock (& ps -> smi_mutex );
2131
2162
@@ -2138,7 +2169,17 @@ int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
2138
2169
if (err )
2139
2170
goto unlock ;
2140
2171
2172
+ /* Unassign the bridge and remap each port's VLANTable */
2141
2173
ps -> ports [port ].bridge_dev = NULL ;
2174
+
2175
+ for (i = 0 ; i < ps -> num_ports ; ++ i ) {
2176
+ if (i == port || ps -> ports [i ].bridge_dev == bridge ) {
2177
+ err = _mv88e6xxx_port_based_vlan_map (ds , i );
2178
+ if (err )
2179
+ break ;
2180
+ }
2181
+ }
2182
+
2142
2183
unlock :
2143
2184
mutex_unlock (& ps -> smi_mutex );
2144
2185
@@ -2402,15 +2443,14 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
2402
2443
goto abort ;
2403
2444
2404
2445
/* Port based VLAN map: give each port its own address
2405
- * database, and allow every port to egress frames on all other ports.
2446
+ * database, and allow bidirectional communication between the
2447
+ * CPU and DSA port(s), and the other ports.
2406
2448
*/
2407
2449
ret = _mv88e6xxx_port_fid_set (ds , port , port + 1 );
2408
2450
if (ret )
2409
2451
goto abort ;
2410
2452
2411
- reg = BIT (ps -> num_ports ) - 1 ; /* all ports */
2412
- reg &= ~BIT (port ); /* except itself */
2413
- ret = _mv88e6xxx_port_vlan_map_set (ds , port , reg );
2453
+ ret = _mv88e6xxx_port_based_vlan_map (ds , port );
2414
2454
if (ret )
2415
2455
goto abort ;
2416
2456
0 commit comments