@@ -344,7 +344,8 @@ static void b53_set_forwarding(struct b53_device *dev, int enable)
344
344
b53_write8 (dev , B53_CTRL_PAGE , B53_SWITCH_CTRL , mgmt );
345
345
}
346
346
347
- static void b53_enable_vlan (struct b53_device * dev , bool enable )
347
+ static void b53_enable_vlan (struct b53_device * dev , bool enable ,
348
+ bool enable_filtering )
348
349
{
349
350
u8 mgmt , vc0 , vc1 , vc4 = 0 , vc5 ;
350
351
@@ -369,8 +370,13 @@ static void b53_enable_vlan(struct b53_device *dev, bool enable)
369
370
vc0 |= VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID ;
370
371
vc1 |= VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN ;
371
372
vc4 &= ~VC4_ING_VID_CHECK_MASK ;
372
- vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S ;
373
- vc5 |= VC5_DROP_VTABLE_MISS ;
373
+ if (enable_filtering ) {
374
+ vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S ;
375
+ vc5 |= VC5_DROP_VTABLE_MISS ;
376
+ } else {
377
+ vc4 |= VC4_ING_VID_VIO_FWD << VC4_ING_VID_CHECK_S ;
378
+ vc5 &= ~VC5_DROP_VTABLE_MISS ;
379
+ }
374
380
375
381
if (is5325 (dev ))
376
382
vc0 &= ~VC0_RESERVED_1 ;
@@ -420,6 +426,9 @@ static void b53_enable_vlan(struct b53_device *dev, bool enable)
420
426
}
421
427
422
428
b53_write8 (dev , B53_CTRL_PAGE , B53_SWITCH_MODE , mgmt );
429
+
430
+ dev -> vlan_enabled = enable ;
431
+ dev -> vlan_filtering_enabled = enable_filtering ;
423
432
}
424
433
425
434
static int b53_set_jumbo (struct b53_device * dev , bool enable , bool allow_10_100 )
@@ -656,7 +665,7 @@ int b53_configure_vlan(struct dsa_switch *ds)
656
665
b53_do_vlan_op (dev , VTA_CMD_CLEAR );
657
666
}
658
667
659
- b53_enable_vlan (dev , false);
668
+ b53_enable_vlan (dev , false, dev -> vlan_filtering_enabled );
660
669
661
670
b53_for_each_port (dev , i )
662
671
b53_write16 (dev , B53_VLAN_PAGE ,
@@ -1265,6 +1274,46 @@ EXPORT_SYMBOL(b53_phylink_mac_link_up);
1265
1274
1266
1275
int b53_vlan_filtering (struct dsa_switch * ds , int port , bool vlan_filtering )
1267
1276
{
1277
+ struct b53_device * dev = ds -> priv ;
1278
+ struct net_device * bridge_dev ;
1279
+ unsigned int i ;
1280
+ u16 pvid , new_pvid ;
1281
+
1282
+ /* Handle the case were multiple bridges span the same switch device
1283
+ * and one of them has a different setting than what is being requested
1284
+ * which would be breaking filtering semantics for any of the other
1285
+ * bridge devices.
1286
+ */
1287
+ b53_for_each_port (dev , i ) {
1288
+ bridge_dev = dsa_to_port (ds , i )-> bridge_dev ;
1289
+ if (bridge_dev &&
1290
+ bridge_dev != dsa_to_port (ds , port )-> bridge_dev &&
1291
+ br_vlan_enabled (bridge_dev ) != vlan_filtering ) {
1292
+ netdev_err (bridge_dev ,
1293
+ "VLAN filtering is global to the switch!\n" );
1294
+ return - EINVAL ;
1295
+ }
1296
+ }
1297
+
1298
+ b53_read16 (dev , B53_VLAN_PAGE , B53_VLAN_PORT_DEF_TAG (port ), & pvid );
1299
+ new_pvid = pvid ;
1300
+ if (dev -> vlan_filtering_enabled && !vlan_filtering ) {
1301
+ /* Filtering is currently enabled, use the default PVID since
1302
+ * the bridge does not expect tagging anymore
1303
+ */
1304
+ dev -> ports [port ].pvid = pvid ;
1305
+ new_pvid = b53_default_pvid (dev );
1306
+ } else if (!dev -> vlan_filtering_enabled && vlan_filtering ) {
1307
+ /* Filtering is currently disabled, restore the previous PVID */
1308
+ new_pvid = dev -> ports [port ].pvid ;
1309
+ }
1310
+
1311
+ if (pvid != new_pvid )
1312
+ b53_write16 (dev , B53_VLAN_PAGE , B53_VLAN_PORT_DEF_TAG (port ),
1313
+ new_pvid );
1314
+
1315
+ b53_enable_vlan (dev , dev -> vlan_enabled , vlan_filtering );
1316
+
1268
1317
return 0 ;
1269
1318
}
1270
1319
EXPORT_SYMBOL (b53_vlan_filtering );
@@ -1280,7 +1329,7 @@ int b53_vlan_prepare(struct dsa_switch *ds, int port,
1280
1329
if (vlan -> vid_end > dev -> num_vlans )
1281
1330
return - ERANGE ;
1282
1331
1283
- b53_enable_vlan (dev , true);
1332
+ b53_enable_vlan (dev , true, dev -> vlan_filtering_enabled );
1284
1333
1285
1334
return 0 ;
1286
1335
}
0 commit comments