@@ -687,8 +687,8 @@ static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
687
687
shifts = ksz8 -> shifts ;
688
688
689
689
ksz8_r_table (dev , TABLE_VLAN , addr , & data );
690
- addr *= dev -> phy_port_cnt ;
691
- for (i = 0 ; i < dev -> phy_port_cnt ; i ++ ) {
690
+ addr *= 4 ;
691
+ for (i = 0 ; i < 4 ; i ++ ) {
692
692
dev -> vlan_cache [addr + i ].table [0 ] = (u16 )data ;
693
693
data >>= shifts [VLAN_TABLE ];
694
694
}
@@ -702,7 +702,7 @@ static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan)
702
702
u64 buf ;
703
703
704
704
data = (u16 * )& buf ;
705
- addr = vid / dev -> phy_port_cnt ;
705
+ addr = vid / 4 ;
706
706
index = vid & 3 ;
707
707
ksz8_r_table (dev , TABLE_VLAN , addr , & buf );
708
708
* vlan = data [index ];
@@ -716,7 +716,7 @@ static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
716
716
u64 buf ;
717
717
718
718
data = (u16 * )& buf ;
719
- addr = vid / dev -> phy_port_cnt ;
719
+ addr = vid / 4 ;
720
720
index = vid & 3 ;
721
721
ksz8_r_table (dev , TABLE_VLAN , addr , & buf );
722
722
data [index ] = vlan ;
@@ -1119,24 +1119,67 @@ static int ksz8_port_vlan_filtering(struct dsa_switch *ds, int port, bool flag,
1119
1119
if (ksz_is_ksz88x3 (dev ))
1120
1120
return - ENOTSUPP ;
1121
1121
1122
+ /* Discard packets with VID not enabled on the switch */
1122
1123
ksz_cfg (dev , S_MIRROR_CTRL , SW_VLAN_ENABLE , flag );
1123
1124
1125
+ /* Discard packets with VID not enabled on the ingress port */
1126
+ for (port = 0 ; port < dev -> phy_port_cnt ; ++ port )
1127
+ ksz_port_cfg (dev , port , REG_PORT_CTRL_2 , PORT_INGRESS_FILTER ,
1128
+ flag );
1129
+
1124
1130
return 0 ;
1125
1131
}
1126
1132
1133
+ static void ksz8_port_enable_pvid (struct ksz_device * dev , int port , bool state )
1134
+ {
1135
+ if (ksz_is_ksz88x3 (dev )) {
1136
+ ksz_cfg (dev , REG_SW_INSERT_SRC_PVID ,
1137
+ 0x03 << (4 - 2 * port ), state );
1138
+ } else {
1139
+ ksz_pwrite8 (dev , port , REG_PORT_CTRL_12 , state ? 0x0f : 0x00 );
1140
+ }
1141
+ }
1142
+
1127
1143
static int ksz8_port_vlan_add (struct dsa_switch * ds , int port ,
1128
1144
const struct switchdev_obj_port_vlan * vlan ,
1129
1145
struct netlink_ext_ack * extack )
1130
1146
{
1131
1147
bool untagged = vlan -> flags & BRIDGE_VLAN_INFO_UNTAGGED ;
1132
1148
struct ksz_device * dev = ds -> priv ;
1149
+ struct ksz_port * p = & dev -> ports [port ];
1133
1150
u16 data , new_pvid = 0 ;
1134
1151
u8 fid , member , valid ;
1135
1152
1136
1153
if (ksz_is_ksz88x3 (dev ))
1137
1154
return - ENOTSUPP ;
1138
1155
1139
- ksz_port_cfg (dev , port , P_TAG_CTRL , PORT_REMOVE_TAG , untagged );
1156
+ /* If a VLAN is added with untagged flag different from the
1157
+ * port's Remove Tag flag, we need to change the latter.
1158
+ * Ignore VID 0, which is always untagged.
1159
+ * Ignore CPU port, which will always be tagged.
1160
+ */
1161
+ if (untagged != p -> remove_tag && vlan -> vid != 0 &&
1162
+ port != dev -> cpu_port ) {
1163
+ unsigned int vid ;
1164
+
1165
+ /* Reject attempts to add a VLAN that requires the
1166
+ * Remove Tag flag to be changed, unless there are no
1167
+ * other VLANs currently configured.
1168
+ */
1169
+ for (vid = 1 ; vid < dev -> num_vlans ; ++ vid ) {
1170
+ /* Skip the VID we are going to add or reconfigure */
1171
+ if (vid == vlan -> vid )
1172
+ continue ;
1173
+
1174
+ ksz8_from_vlan (dev , dev -> vlan_cache [vid ].table [0 ],
1175
+ & fid , & member , & valid );
1176
+ if (valid && (member & BIT (port )))
1177
+ return - EINVAL ;
1178
+ }
1179
+
1180
+ ksz_port_cfg (dev , port , P_TAG_CTRL , PORT_REMOVE_TAG , untagged );
1181
+ p -> remove_tag = untagged ;
1182
+ }
1140
1183
1141
1184
ksz8_r_vlan_table (dev , vlan -> vid , & data );
1142
1185
ksz8_from_vlan (dev , data , & fid , & member , & valid );
@@ -1160,9 +1203,11 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
1160
1203
u16 vid ;
1161
1204
1162
1205
ksz_pread16 (dev , port , REG_PORT_CTRL_VID , & vid );
1163
- vid &= 0xfff ;
1206
+ vid &= ~ VLAN_VID_MASK ;
1164
1207
vid |= new_pvid ;
1165
1208
ksz_pwrite16 (dev , port , REG_PORT_CTRL_VID , vid );
1209
+
1210
+ ksz8_port_enable_pvid (dev , port , true);
1166
1211
}
1167
1212
1168
1213
return 0 ;
@@ -1171,9 +1216,8 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
1171
1216
static int ksz8_port_vlan_del (struct dsa_switch * ds , int port ,
1172
1217
const struct switchdev_obj_port_vlan * vlan )
1173
1218
{
1174
- bool untagged = vlan -> flags & BRIDGE_VLAN_INFO_UNTAGGED ;
1175
1219
struct ksz_device * dev = ds -> priv ;
1176
- u16 data , pvid , new_pvid = 0 ;
1220
+ u16 data , pvid ;
1177
1221
u8 fid , member , valid ;
1178
1222
1179
1223
if (ksz_is_ksz88x3 (dev ))
@@ -1182,8 +1226,6 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
1182
1226
ksz_pread16 (dev , port , REG_PORT_CTRL_VID , & pvid );
1183
1227
pvid = pvid & 0xFFF ;
1184
1228
1185
- ksz_port_cfg (dev , port , P_TAG_CTRL , PORT_REMOVE_TAG , untagged );
1186
-
1187
1229
ksz8_r_vlan_table (dev , vlan -> vid , & data );
1188
1230
ksz8_from_vlan (dev , data , & fid , & member , & valid );
1189
1231
@@ -1195,14 +1237,11 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
1195
1237
valid = 0 ;
1196
1238
}
1197
1239
1198
- if (pvid == vlan -> vid )
1199
- new_pvid = 1 ;
1200
-
1201
1240
ksz8_to_vlan (dev , fid , member , valid , & data );
1202
1241
ksz8_w_vlan_table (dev , vlan -> vid , data );
1203
1242
1204
- if (new_pvid != pvid )
1205
- ksz_pwrite16 (dev , port , REG_PORT_CTRL_VID , pvid );
1243
+ if (pvid == vlan -> vid )
1244
+ ksz8_port_enable_pvid (dev , port , false );
1206
1245
1207
1246
return 0 ;
1208
1247
}
@@ -1435,6 +1474,9 @@ static int ksz8_setup(struct dsa_switch *ds)
1435
1474
1436
1475
ksz_cfg (dev , S_MIRROR_CTRL , SW_MIRROR_RX_TX , false);
1437
1476
1477
+ if (!ksz_is_ksz88x3 (dev ))
1478
+ ksz_cfg (dev , REG_SW_CTRL_19 , SW_INS_TAG_ENABLE , true);
1479
+
1438
1480
/* set broadcast storm protection 10% rate */
1439
1481
regmap_update_bits (dev -> regmap [1 ], S_REPLACE_VID_CTRL ,
1440
1482
BROADCAST_STORM_RATE ,
@@ -1717,6 +1759,16 @@ static int ksz8_switch_init(struct ksz_device *dev)
1717
1759
/* set the real number of ports */
1718
1760
dev -> ds -> num_ports = dev -> port_cnt ;
1719
1761
1762
+ /* We rely on software untagging on the CPU port, so that we
1763
+ * can support both tagged and untagged VLANs
1764
+ */
1765
+ dev -> ds -> untag_bridge_pvid = true;
1766
+
1767
+ /* VLAN filtering is partly controlled by the global VLAN
1768
+ * Enable flag
1769
+ */
1770
+ dev -> ds -> vlan_filtering_is_global = true;
1771
+
1720
1772
return 0 ;
1721
1773
}
1722
1774
0 commit comments