@@ -561,61 +561,134 @@ const struct icss_iep_clockops prueth_iep_clockops = {
561
561
562
562
static int icssg_prueth_add_mcast (struct net_device * ndev , const u8 * addr )
563
563
{
564
- struct prueth_emac * emac = netdev_priv (ndev );
565
- int port_mask = BIT (emac -> port_id );
564
+ struct net_device * real_dev ;
565
+ struct prueth_emac * emac ;
566
+ int port_mask ;
567
+ u8 vlan_id ;
566
568
567
- port_mask |= icssg_fdb_lookup (emac , addr , 0 );
568
- icssg_fdb_add_del (emac , addr , 0 , port_mask , true);
569
- icssg_vtbl_modify (emac , 0 , port_mask , port_mask , true);
569
+ vlan_id = is_vlan_dev (ndev ) ? vlan_dev_vlan_id (ndev ) : PRUETH_DFLT_VLAN_MAC ;
570
+ real_dev = is_vlan_dev (ndev ) ? vlan_dev_real_dev (ndev ) : ndev ;
571
+ emac = netdev_priv (real_dev );
572
+
573
+ port_mask = BIT (emac -> port_id ) | icssg_fdb_lookup (emac , addr , vlan_id );
574
+ icssg_fdb_add_del (emac , addr , vlan_id , port_mask , true);
575
+ icssg_vtbl_modify (emac , vlan_id , port_mask , port_mask , true);
570
576
571
577
return 0 ;
572
578
}
573
579
574
580
static int icssg_prueth_del_mcast (struct net_device * ndev , const u8 * addr )
575
581
{
576
- struct prueth_emac * emac = netdev_priv ( ndev ) ;
577
- int port_mask = BIT ( emac -> port_id ) ;
582
+ struct net_device * real_dev ;
583
+ struct prueth_emac * emac ;
578
584
int other_port_mask ;
585
+ int port_mask ;
586
+ u8 vlan_id ;
587
+
588
+ vlan_id = is_vlan_dev (ndev ) ? vlan_dev_vlan_id (ndev ) : PRUETH_DFLT_VLAN_MAC ;
589
+ real_dev = is_vlan_dev (ndev ) ? vlan_dev_real_dev (ndev ) : ndev ;
590
+ emac = netdev_priv (real_dev );
579
591
580
- other_port_mask = port_mask ^ icssg_fdb_lookup (emac , addr , 0 );
592
+ port_mask = BIT (emac -> port_id );
593
+ other_port_mask = port_mask ^ icssg_fdb_lookup (emac , addr , vlan_id );
581
594
582
- icssg_fdb_add_del (emac , addr , 0 , port_mask , false);
583
- icssg_vtbl_modify (emac , 0 , port_mask , port_mask , false);
595
+ icssg_fdb_add_del (emac , addr , vlan_id , port_mask , false);
596
+ icssg_vtbl_modify (emac , vlan_id , port_mask , port_mask , false);
584
597
585
598
if (other_port_mask ) {
586
- icssg_fdb_add_del (emac , addr , 0 , other_port_mask , true);
587
- icssg_vtbl_modify (emac , 0 , other_port_mask , other_port_mask , true);
599
+ icssg_fdb_add_del (emac , addr , vlan_id , other_port_mask , true);
600
+ icssg_vtbl_modify (emac , vlan_id , other_port_mask ,
601
+ other_port_mask , true);
588
602
}
589
603
590
604
return 0 ;
591
605
}
592
606
593
- static int icssg_prueth_hsr_add_mcast (struct net_device * ndev , const u8 * addr )
607
+ static void icssg_prueth_hsr_fdb_add_del (struct prueth_emac * emac ,
608
+ const u8 * addr , u8 vid , bool add )
594
609
{
595
- struct prueth_emac * emac = netdev_priv (ndev );
596
- struct prueth * prueth = emac -> prueth ;
597
-
598
- icssg_fdb_add_del (emac , addr , prueth -> default_vlan ,
610
+ icssg_fdb_add_del (emac , addr , vid ,
599
611
ICSSG_FDB_ENTRY_P0_MEMBERSHIP |
600
612
ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
601
613
ICSSG_FDB_ENTRY_P2_MEMBERSHIP |
602
- ICSSG_FDB_ENTRY_BLOCK , true);
614
+ ICSSG_FDB_ENTRY_BLOCK , add );
615
+
616
+ if (add )
617
+ icssg_vtbl_modify (emac , vid , BIT (emac -> port_id ),
618
+ BIT (emac -> port_id ), add );
619
+ }
620
+
621
+ static int icssg_prueth_hsr_add_mcast (struct net_device * ndev , const u8 * addr )
622
+ {
623
+ struct net_device * real_dev ;
624
+ struct prueth_emac * emac ;
625
+ u8 vlan_id , i ;
626
+
627
+ vlan_id = is_vlan_dev (ndev ) ? vlan_dev_vlan_id (ndev ) : PRUETH_DFLT_VLAN_HSR ;
628
+ real_dev = is_vlan_dev (ndev ) ? vlan_dev_real_dev (ndev ) : ndev ;
629
+
630
+ if (is_hsr_master (real_dev )) {
631
+ for (i = HSR_PT_SLAVE_A ; i < HSR_PT_INTERLINK ; i ++ ) {
632
+ emac = netdev_priv (hsr_get_port_ndev (real_dev , i ));
633
+ if (!emac )
634
+ return - EINVAL ;
635
+ icssg_prueth_hsr_fdb_add_del (emac , addr , vlan_id ,
636
+ true);
637
+ }
638
+ } else {
639
+ emac = netdev_priv (real_dev );
640
+ icssg_prueth_hsr_fdb_add_del (emac , addr , vlan_id , true);
641
+ }
603
642
604
- icssg_vtbl_modify (emac , emac -> port_vlan , BIT (emac -> port_id ),
605
- BIT (emac -> port_id ), true);
606
643
return 0 ;
607
644
}
608
645
609
646
static int icssg_prueth_hsr_del_mcast (struct net_device * ndev , const u8 * addr )
610
647
{
611
- struct prueth_emac * emac = netdev_priv (ndev );
612
- struct prueth * prueth = emac -> prueth ;
648
+ struct net_device * real_dev ;
649
+ struct prueth_emac * emac ;
650
+ u8 vlan_id , i ;
651
+
652
+ vlan_id = is_vlan_dev (ndev ) ? vlan_dev_vlan_id (ndev ) : PRUETH_DFLT_VLAN_HSR ;
653
+ real_dev = is_vlan_dev (ndev ) ? vlan_dev_real_dev (ndev ) : ndev ;
654
+
655
+ if (is_hsr_master (real_dev )) {
656
+ for (i = HSR_PT_SLAVE_A ; i < HSR_PT_INTERLINK ; i ++ ) {
657
+ emac = netdev_priv (hsr_get_port_ndev (real_dev , i ));
658
+ if (!emac )
659
+ return - EINVAL ;
660
+ icssg_prueth_hsr_fdb_add_del (emac , addr , vlan_id ,
661
+ false);
662
+ }
663
+ } else {
664
+ emac = netdev_priv (real_dev );
665
+ icssg_prueth_hsr_fdb_add_del (emac , addr , vlan_id , false);
666
+ }
613
667
614
- icssg_fdb_add_del (emac , addr , prueth -> default_vlan ,
615
- ICSSG_FDB_ENTRY_P0_MEMBERSHIP |
616
- ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
617
- ICSSG_FDB_ENTRY_P2_MEMBERSHIP |
618
- ICSSG_FDB_ENTRY_BLOCK , false);
668
+ return 0 ;
669
+ }
670
+
671
+ static int icssg_update_vlan_mcast (struct net_device * vdev , int vid ,
672
+ void * args )
673
+ {
674
+ struct prueth_emac * emac = args ;
675
+
676
+ if (!vdev || !vid )
677
+ return 0 ;
678
+
679
+ netif_addr_lock_bh (vdev );
680
+ __hw_addr_sync_multiple (& emac -> vlan_mcast_list [vid ], & vdev -> mc ,
681
+ vdev -> addr_len );
682
+ netif_addr_unlock_bh (vdev );
683
+
684
+ if (emac -> prueth -> is_hsr_offload_mode )
685
+ __hw_addr_sync_dev (& emac -> vlan_mcast_list [vid ], vdev ,
686
+ icssg_prueth_hsr_add_mcast ,
687
+ icssg_prueth_hsr_del_mcast );
688
+ else
689
+ __hw_addr_sync_dev (& emac -> vlan_mcast_list [vid ], vdev ,
690
+ icssg_prueth_add_mcast ,
691
+ icssg_prueth_del_mcast );
619
692
620
693
return 0 ;
621
694
}
@@ -857,12 +930,22 @@ static void emac_ndo_set_rx_mode_work(struct work_struct *work)
857
930
return ;
858
931
}
859
932
860
- if (emac -> prueth -> is_hsr_offload_mode )
933
+ if (emac -> prueth -> is_hsr_offload_mode ) {
861
934
__dev_mc_sync (ndev , icssg_prueth_hsr_add_mcast ,
862
935
icssg_prueth_hsr_del_mcast );
863
- else
936
+ if (rtnl_trylock ()) {
937
+ vlan_for_each (emac -> prueth -> hsr_dev ,
938
+ icssg_update_vlan_mcast , emac );
939
+ rtnl_unlock ();
940
+ }
941
+ } else {
864
942
__dev_mc_sync (ndev , icssg_prueth_add_mcast ,
865
943
icssg_prueth_del_mcast );
944
+ if (rtnl_trylock ()) {
945
+ vlan_for_each (ndev , icssg_update_vlan_mcast , emac );
946
+ rtnl_unlock ();
947
+ }
948
+ }
866
949
}
867
950
868
951
/**
@@ -907,19 +990,19 @@ static int emac_ndo_vlan_rx_add_vid(struct net_device *ndev,
907
990
{
908
991
struct prueth_emac * emac = netdev_priv (ndev );
909
992
struct prueth * prueth = emac -> prueth ;
993
+ int port_mask = BIT (emac -> port_id );
910
994
int untag_mask = 0 ;
911
- int port_mask ;
912
995
913
- if (prueth -> is_hsr_offload_mode ) {
914
- port_mask = BIT (PRUETH_PORT_HOST ) | BIT (emac -> port_id );
915
- untag_mask = 0 ;
996
+ if (prueth -> is_hsr_offload_mode )
997
+ port_mask |= BIT (PRUETH_PORT_HOST );
916
998
917
- netdev_dbg (emac -> ndev , "VID add vid:%u port_mask:%X untag_mask %X\n" ,
918
- vid , port_mask , untag_mask );
999
+ __hw_addr_init (& emac -> vlan_mcast_list [vid ]);
1000
+ netdev_dbg (emac -> ndev , "VID add vid:%u port_mask:%X untag_mask %X\n" ,
1001
+ vid , port_mask , untag_mask );
1002
+
1003
+ icssg_vtbl_modify (emac , vid , port_mask , untag_mask , true);
1004
+ icssg_set_pvid (emac -> prueth , vid , emac -> port_id );
919
1005
920
- icssg_vtbl_modify (emac , vid , port_mask , untag_mask , true);
921
- icssg_set_pvid (emac -> prueth , vid , emac -> port_id );
922
- }
923
1006
return 0 ;
924
1007
}
925
1008
@@ -928,18 +1011,16 @@ static int emac_ndo_vlan_rx_del_vid(struct net_device *ndev,
928
1011
{
929
1012
struct prueth_emac * emac = netdev_priv (ndev );
930
1013
struct prueth * prueth = emac -> prueth ;
1014
+ int port_mask = BIT (emac -> port_id );
931
1015
int untag_mask = 0 ;
932
- int port_mask ;
933
1016
934
- if (prueth -> is_hsr_offload_mode ) {
1017
+ if (prueth -> is_hsr_offload_mode )
935
1018
port_mask = BIT (PRUETH_PORT_HOST );
936
- untag_mask = 0 ;
937
1019
938
- netdev_dbg (emac -> ndev , "VID del vid:%u port_mask:%X untag_mask %X\n" ,
939
- vid , port_mask , untag_mask );
1020
+ netdev_dbg (emac -> ndev , "VID del vid:%u port_mask:%X untag_mask %X\n" ,
1021
+ vid , port_mask , untag_mask );
1022
+ icssg_vtbl_modify (emac , vid , port_mask , untag_mask , false);
940
1023
941
- icssg_vtbl_modify (emac , vid , port_mask , untag_mask , false);
942
- }
943
1024
return 0 ;
944
1025
}
945
1026
@@ -1254,7 +1335,7 @@ static int prueth_netdevice_port_link(struct net_device *ndev,
1254
1335
if (prueth -> br_members & BIT (PRUETH_PORT_MII0 ) &&
1255
1336
prueth -> br_members & BIT (PRUETH_PORT_MII1 )) {
1256
1337
prueth -> is_switch_mode = true;
1257
- prueth -> default_vlan = 1 ;
1338
+ prueth -> default_vlan = PRUETH_DFLT_VLAN_SW ;
1258
1339
emac -> port_vlan = prueth -> default_vlan ;
1259
1340
icssg_change_mode (prueth );
1260
1341
}
@@ -1312,7 +1393,7 @@ static int prueth_hsr_port_link(struct net_device *ndev)
1312
1393
NETIF_PRUETH_HSR_OFFLOAD_FEATURES ))
1313
1394
return - EOPNOTSUPP ;
1314
1395
prueth -> is_hsr_offload_mode = true;
1315
- prueth -> default_vlan = 1 ;
1396
+ prueth -> default_vlan = PRUETH_DFLT_VLAN_HSR ;
1316
1397
emac0 -> port_vlan = prueth -> default_vlan ;
1317
1398
emac1 -> port_vlan = prueth -> default_vlan ;
1318
1399
icssg_change_mode (prueth );
0 commit comments