@@ -570,21 +570,6 @@ static inline int cpsw_get_slave_port(u32 slave_num)
570570 return slave_num + 1 ;
571571}
572572
573- static void cpsw_add_mcast (struct cpsw_priv * priv , const u8 * addr )
574- {
575- struct cpsw_common * cpsw = priv -> cpsw ;
576-
577- if (cpsw -> data .dual_emac ) {
578- struct cpsw_slave * slave = cpsw -> slaves + priv -> emac_port ;
579-
580- cpsw_ale_add_mcast (cpsw -> ale , addr , ALE_PORT_HOST ,
581- ALE_VLAN , slave -> port_vlan , 0 );
582- return ;
583- }
584-
585- cpsw_ale_add_mcast (cpsw -> ale , addr , ALE_ALL_PORTS , 0 , 0 , 0 );
586- }
587-
588573static void cpsw_set_promiscious (struct net_device * ndev , bool enable )
589574{
590575 struct cpsw_common * cpsw = ndev_to_cpsw (ndev );
@@ -640,7 +625,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
640625
641626 /* Clear all mcast from ALE */
642627 cpsw_ale_flush_multicast (ale , ALE_ALL_PORTS , -1 );
643- __dev_mc_unsync ( ndev , NULL );
628+ __hw_addr_ref_unsync_dev ( & ndev -> mc , ndev , NULL );
644629
645630 /* Flood All Unicast Packets to Host port */
646631 cpsw_ale_control_set (ale , 0 , ALE_P0_UNI_FLOOD , 1 );
@@ -661,29 +646,148 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
661646 }
662647}
663648
664- static int cpsw_add_mc_addr (struct net_device * ndev , const u8 * addr )
649+ struct addr_sync_ctx {
650+ struct net_device * ndev ;
651+ const u8 * addr ; /* address to be synched */
652+ int consumed ; /* number of address instances */
653+ int flush ; /* flush flag */
654+ };
655+
656+ /**
657+ * cpsw_set_mc - adds multicast entry to the table if it's not added or deletes
658+ * if it's not deleted
659+ * @ndev: device to sync
660+ * @addr: address to be added or deleted
661+ * @vid: vlan id, if vid < 0 set/unset address for real device
662+ * @add: add address if the flag is set or remove otherwise
663+ */
664+ static int cpsw_set_mc (struct net_device * ndev , const u8 * addr ,
665+ int vid , int add )
665666{
666667 struct cpsw_priv * priv = netdev_priv (ndev );
668+ struct cpsw_common * cpsw = priv -> cpsw ;
669+ int mask , flags , ret ;
670+
671+ if (vid < 0 ) {
672+ if (cpsw -> data .dual_emac )
673+ vid = cpsw -> slaves [priv -> emac_port ].port_vlan ;
674+ else
675+ vid = 0 ;
676+ }
677+
678+ mask = cpsw -> data .dual_emac ? ALE_PORT_HOST : ALE_ALL_PORTS ;
679+ flags = vid ? ALE_VLAN : 0 ;
680+
681+ if (add )
682+ ret = cpsw_ale_add_mcast (cpsw -> ale , addr , mask , flags , vid , 0 );
683+ else
684+ ret = cpsw_ale_del_mcast (cpsw -> ale , addr , 0 , flags , vid );
685+
686+ return ret ;
687+ }
688+
689+ static int cpsw_update_vlan_mc (struct net_device * vdev , int vid , void * ctx )
690+ {
691+ struct addr_sync_ctx * sync_ctx = ctx ;
692+ struct netdev_hw_addr * ha ;
693+ int found = 0 , ret = 0 ;
694+
695+ if (!vdev || !(vdev -> flags & IFF_UP ))
696+ return 0 ;
697+
698+ /* vlan address is relevant if its sync_cnt != 0 */
699+ netdev_for_each_mc_addr (ha , vdev ) {
700+ if (ether_addr_equal (ha -> addr , sync_ctx -> addr )) {
701+ found = ha -> sync_cnt ;
702+ break ;
703+ }
704+ }
705+
706+ if (found )
707+ sync_ctx -> consumed ++ ;
708+
709+ if (sync_ctx -> flush ) {
710+ if (!found )
711+ cpsw_set_mc (sync_ctx -> ndev , sync_ctx -> addr , vid , 0 );
712+ return 0 ;
713+ }
714+
715+ if (found )
716+ ret = cpsw_set_mc (sync_ctx -> ndev , sync_ctx -> addr , vid , 1 );
717+
718+ return ret ;
719+ }
720+
721+ static int cpsw_add_mc_addr (struct net_device * ndev , const u8 * addr , int num )
722+ {
723+ struct addr_sync_ctx sync_ctx ;
724+ int ret ;
725+
726+ sync_ctx .consumed = 0 ;
727+ sync_ctx .addr = addr ;
728+ sync_ctx .ndev = ndev ;
729+ sync_ctx .flush = 0 ;
730+
731+ ret = vlan_for_each (ndev , cpsw_update_vlan_mc , & sync_ctx );
732+ if (sync_ctx .consumed < num && !ret )
733+ ret = cpsw_set_mc (ndev , addr , -1 , 1 );
734+
735+ return ret ;
736+ }
737+
738+ static int cpsw_del_mc_addr (struct net_device * ndev , const u8 * addr , int num )
739+ {
740+ struct addr_sync_ctx sync_ctx ;
741+
742+ sync_ctx .consumed = 0 ;
743+ sync_ctx .addr = addr ;
744+ sync_ctx .ndev = ndev ;
745+ sync_ctx .flush = 1 ;
746+
747+ vlan_for_each (ndev , cpsw_update_vlan_mc , & sync_ctx );
748+ if (sync_ctx .consumed == num )
749+ cpsw_set_mc (ndev , addr , -1 , 0 );
667750
668- cpsw_add_mcast (priv , addr );
669751 return 0 ;
670752}
671753
672- static int cpsw_del_mc_addr (struct net_device * ndev , const u8 * addr )
754+ static int cpsw_purge_vlan_mc (struct net_device * vdev , int vid , void * ctx )
673755{
674- struct cpsw_priv * priv = netdev_priv ( ndev ) ;
675- struct cpsw_common * cpsw = priv -> cpsw ;
676- int vid , flags ;
756+ struct addr_sync_ctx * sync_ctx = ctx ;
757+ struct netdev_hw_addr * ha ;
758+ int found = 0 ;
677759
678- if (cpsw -> data .dual_emac ) {
679- vid = cpsw -> slaves [priv -> emac_port ].port_vlan ;
680- flags = ALE_VLAN ;
681- } else {
682- vid = 0 ;
683- flags = 0 ;
760+ if (!vdev || !(vdev -> flags & IFF_UP ))
761+ return 0 ;
762+
763+ /* vlan address is relevant if its sync_cnt != 0 */
764+ netdev_for_each_mc_addr (ha , vdev ) {
765+ if (ether_addr_equal (ha -> addr , sync_ctx -> addr )) {
766+ found = ha -> sync_cnt ;
767+ break ;
768+ }
684769 }
685770
686- cpsw_ale_del_mcast (cpsw -> ale , addr , 0 , flags , vid );
771+ if (!found )
772+ return 0 ;
773+
774+ sync_ctx -> consumed ++ ;
775+ cpsw_set_mc (sync_ctx -> ndev , sync_ctx -> addr , vid , 0 );
776+ return 0 ;
777+ }
778+
779+ static int cpsw_purge_all_mc (struct net_device * ndev , const u8 * addr , int num )
780+ {
781+ struct addr_sync_ctx sync_ctx ;
782+
783+ sync_ctx .addr = addr ;
784+ sync_ctx .ndev = ndev ;
785+ sync_ctx .consumed = 0 ;
786+
787+ vlan_for_each (ndev , cpsw_purge_vlan_mc , & sync_ctx );
788+ if (sync_ctx .consumed < num )
789+ cpsw_set_mc (ndev , addr , -1 , 0 );
790+
687791 return 0 ;
688792}
689793
@@ -704,7 +808,9 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
704808 /* Restore allmulti on vlans if necessary */
705809 cpsw_ale_set_allmulti (cpsw -> ale , ndev -> flags & IFF_ALLMULTI );
706810
707- __dev_mc_sync (ndev , cpsw_add_mc_addr , cpsw_del_mc_addr );
811+ /* add/remove mcast address either for real netdev or for vlan */
812+ __hw_addr_ref_sync_dev (& ndev -> mc , ndev , cpsw_add_mc_addr ,
813+ cpsw_del_mc_addr );
708814}
709815
710816static void cpsw_intr_enable (struct cpsw_common * cpsw )
@@ -1964,7 +2070,7 @@ static int cpsw_ndo_stop(struct net_device *ndev)
19642070 struct cpsw_common * cpsw = priv -> cpsw ;
19652071
19662072 cpsw_info (priv , ifdown , "shutting down cpsw device\n" );
1967- __dev_mc_unsync ( priv -> ndev , cpsw_del_mc_addr );
2073+ __hw_addr_ref_unsync_dev ( & ndev -> mc , ndev , cpsw_purge_all_mc );
19682074 netif_tx_stop_all_queues (priv -> ndev );
19692075 netif_carrier_off (priv -> ndev );
19702076
@@ -2415,6 +2521,7 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
24152521 HOST_PORT_NUM , ALE_VLAN , vid );
24162522 ret |= cpsw_ale_del_mcast (cpsw -> ale , priv -> ndev -> broadcast ,
24172523 0 , ALE_VLAN , vid );
2524+ ret |= cpsw_ale_flush_multicast (cpsw -> ale , 0 , vid );
24182525err :
24192526 pm_runtime_put (cpsw -> dev );
24202527 return ret ;
0 commit comments