@@ -604,32 +604,66 @@ static int icssg_prueth_del_mcast(struct net_device *ndev, const u8 *addr)
604604 return 0 ;
605605}
606606
607- 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 )
608609{
609- struct prueth_emac * emac = netdev_priv (ndev );
610- struct prueth * prueth = emac -> prueth ;
611-
612- icssg_fdb_add_del (emac , addr , prueth -> default_vlan ,
610+ icssg_fdb_add_del (emac , addr , vid ,
613611 ICSSG_FDB_ENTRY_P0_MEMBERSHIP |
614612 ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
615613 ICSSG_FDB_ENTRY_P2_MEMBERSHIP |
616- 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+ }
617642
618- icssg_vtbl_modify (emac , emac -> port_vlan , BIT (emac -> port_id ),
619- BIT (emac -> port_id ), true);
620643 return 0 ;
621644}
622645
623646static int icssg_prueth_hsr_del_mcast (struct net_device * ndev , const u8 * addr )
624647{
625- struct prueth_emac * emac = netdev_priv (ndev );
626- struct prueth * prueth = emac -> prueth ;
648+ struct net_device * real_dev ;
649+ struct prueth_emac * emac ;
650+ u8 vlan_id , i ;
627651
628- icssg_fdb_add_del (emac , addr , prueth -> default_vlan ,
629- ICSSG_FDB_ENTRY_P0_MEMBERSHIP |
630- ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
631- ICSSG_FDB_ENTRY_P2_MEMBERSHIP |
632- ICSSG_FDB_ENTRY_BLOCK , false);
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+ }
633667
634668 return 0 ;
635669}
@@ -647,8 +681,14 @@ static int icssg_update_vlan_mcast(struct net_device *vdev, int vid,
647681 vdev -> addr_len );
648682 netif_addr_unlock_bh (vdev );
649683
650- __hw_addr_sync_dev (& emac -> vlan_mcast_list [vid ], vdev ,
651- icssg_prueth_add_mcast , icssg_prueth_del_mcast );
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 );
652692
653693 return 0 ;
654694}
@@ -893,6 +933,11 @@ static void emac_ndo_set_rx_mode_work(struct work_struct *work)
893933 if (emac -> prueth -> is_hsr_offload_mode ) {
894934 __dev_mc_sync (ndev , icssg_prueth_hsr_add_mcast ,
895935 icssg_prueth_hsr_del_mcast );
936+ if (rtnl_trylock ()) {
937+ vlan_for_each (emac -> prueth -> hsr_dev ,
938+ icssg_update_vlan_mcast , emac );
939+ rtnl_unlock ();
940+ }
896941 } else {
897942 __dev_mc_sync (ndev , icssg_prueth_add_mcast ,
898943 icssg_prueth_del_mcast );
@@ -1290,7 +1335,7 @@ static int prueth_netdevice_port_link(struct net_device *ndev,
12901335 if (prueth -> br_members & BIT (PRUETH_PORT_MII0 ) &&
12911336 prueth -> br_members & BIT (PRUETH_PORT_MII1 )) {
12921337 prueth -> is_switch_mode = true;
1293- prueth -> default_vlan = 1 ;
1338+ prueth -> default_vlan = PRUETH_DFLT_VLAN_SW ;
12941339 emac -> port_vlan = prueth -> default_vlan ;
12951340 icssg_change_mode (prueth );
12961341 }
@@ -1348,7 +1393,7 @@ static int prueth_hsr_port_link(struct net_device *ndev)
13481393 NETIF_PRUETH_HSR_OFFLOAD_FEATURES ))
13491394 return - EOPNOTSUPP ;
13501395 prueth -> is_hsr_offload_mode = true;
1351- prueth -> default_vlan = 1 ;
1396+ prueth -> default_vlan = PRUETH_DFLT_VLAN_HSR ;
13521397 emac0 -> port_vlan = prueth -> default_vlan ;
13531398 emac1 -> port_vlan = prueth -> default_vlan ;
13541399 icssg_change_mode (prueth );
0 commit comments