@@ -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 )
@@ -632,25 +641,35 @@ static void b53_enable_mib(struct b53_device *dev)
632
641
b53_write8 (dev , B53_MGMT_PAGE , B53_GLOBAL_CONFIG , gc );
633
642
}
634
643
644
+ static u16 b53_default_pvid (struct b53_device * dev )
645
+ {
646
+ if (is5325 (dev ) || is5365 (dev ))
647
+ return 1 ;
648
+ else
649
+ return 0 ;
650
+ }
651
+
635
652
int b53_configure_vlan (struct dsa_switch * ds )
636
653
{
637
654
struct b53_device * dev = ds -> priv ;
638
655
struct b53_vlan vl = { 0 };
639
- int i ;
656
+ int i , def_vid ;
657
+
658
+ def_vid = b53_default_pvid (dev );
640
659
641
660
/* clear all vlan entries */
642
661
if (is5325 (dev ) || is5365 (dev )) {
643
- for (i = 1 ; i < dev -> num_vlans ; i ++ )
662
+ for (i = def_vid ; i < dev -> num_vlans ; i ++ )
644
663
b53_set_vlan_entry (dev , i , & vl );
645
664
} else {
646
665
b53_do_vlan_op (dev , VTA_CMD_CLEAR );
647
666
}
648
667
649
- b53_enable_vlan (dev , false);
668
+ b53_enable_vlan (dev , false, dev -> vlan_filtering_enabled );
650
669
651
670
b53_for_each_port (dev , i )
652
671
b53_write16 (dev , B53_VLAN_PAGE ,
653
- B53_VLAN_PORT_DEF_TAG (i ), 1 );
672
+ B53_VLAN_PORT_DEF_TAG (i ), def_vid );
654
673
655
674
if (!is5325 (dev ) && !is5365 (dev ))
656
675
b53_set_jumbo (dev , dev -> enable_jumbo , false);
@@ -1255,6 +1274,46 @@ EXPORT_SYMBOL(b53_phylink_mac_link_up);
1255
1274
1256
1275
int b53_vlan_filtering (struct dsa_switch * ds , int port , bool vlan_filtering )
1257
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
+
1258
1317
return 0 ;
1259
1318
}
1260
1319
EXPORT_SYMBOL (b53_vlan_filtering );
@@ -1270,7 +1329,7 @@ int b53_vlan_prepare(struct dsa_switch *ds, int port,
1270
1329
if (vlan -> vid_end > dev -> num_vlans )
1271
1330
return - ERANGE ;
1272
1331
1273
- b53_enable_vlan (dev , true);
1332
+ b53_enable_vlan (dev , true, dev -> vlan_filtering_enabled );
1274
1333
1275
1334
return 0 ;
1276
1335
}
@@ -1300,7 +1359,7 @@ void b53_vlan_add(struct dsa_switch *ds, int port,
1300
1359
b53_fast_age_vlan (dev , vid );
1301
1360
}
1302
1361
1303
- if (pvid ) {
1362
+ if (pvid && ! dsa_is_cpu_port ( ds , port ) ) {
1304
1363
b53_write16 (dev , B53_VLAN_PAGE , B53_VLAN_PORT_DEF_TAG (port ),
1305
1364
vlan -> vid_end );
1306
1365
b53_fast_age_vlan (dev , vid );
@@ -1326,12 +1385,8 @@ int b53_vlan_del(struct dsa_switch *ds, int port,
1326
1385
1327
1386
vl -> members &= ~BIT (port );
1328
1387
1329
- if (pvid == vid ) {
1330
- if (is5325 (dev ) || is5365 (dev ))
1331
- pvid = 1 ;
1332
- else
1333
- pvid = 0 ;
1334
- }
1388
+ if (pvid == vid )
1389
+ pvid = b53_default_pvid (dev );
1335
1390
1336
1391
if (untagged && !dsa_is_cpu_port (ds , port ))
1337
1392
vl -> untag &= ~(BIT (port ));
@@ -1644,10 +1699,7 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *br)
1644
1699
b53_write16 (dev , B53_PVLAN_PAGE , B53_PVLAN_PORT_MASK (port ), pvlan );
1645
1700
dev -> ports [port ].vlan_ctl_mask = pvlan ;
1646
1701
1647
- if (is5325 (dev ) || is5365 (dev ))
1648
- pvid = 1 ;
1649
- else
1650
- pvid = 0 ;
1702
+ pvid = b53_default_pvid (dev );
1651
1703
1652
1704
/* Make this port join all VLANs without VLAN entries */
1653
1705
if (is58xx (dev )) {
0 commit comments