diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 16dcbf36f8cc..a2206117729f 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -570,7 +570,7 @@ static inline int cpsw_get_slave_port(u32 slave_num) return slave_num + 1; } -static void cpsw_add_mcast(struct cpsw_priv *priv, u8 *addr) +static void cpsw_add_mcast(struct cpsw_priv *priv, const u8 *addr) { struct cpsw_common *cpsw = priv->cpsw; @@ -662,16 +662,35 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) } } -static void cpsw_ndo_set_rx_mode(struct net_device *ndev) +static int cpsw_add_mc_addr(struct net_device *ndev, const u8 *addr) +{ + struct cpsw_priv *priv = netdev_priv(ndev); + + cpsw_add_mcast(priv, addr); + return 0; +} + +static int cpsw_del_mc_addr(struct net_device *ndev, const u8 *addr) { struct cpsw_priv *priv = netdev_priv(ndev); struct cpsw_common *cpsw = priv->cpsw; - int vid; + int vid, flags; - if (cpsw->data.dual_emac) + if (cpsw->data.dual_emac) { vid = cpsw->slaves[priv->emac_port].port_vlan; - else - vid = cpsw->data.default_vlan; + flags = ALE_VLAN; + } else { + vid = 0; + flags = 0; + } + + cpsw_ale_del_mcast(cpsw->ale, addr, 0, flags, vid); + return 0; +} + +static void cpsw_ndo_set_rx_mode(struct net_device *ndev) +{ + struct cpsw_common *cpsw = ndev_to_cpsw(ndev); if (ndev->flags & IFF_PROMISC) { /* Enable promiscuous mode */ @@ -684,19 +703,9 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev) } /* Restore allmulti on vlans if necessary */ - cpsw_ale_set_allmulti(cpsw->ale, priv->ndev->flags & IFF_ALLMULTI); + cpsw_ale_set_allmulti(cpsw->ale, ndev->flags & IFF_ALLMULTI); - /* Clear all mcast from ALE */ - cpsw_ale_flush_multicast(cpsw->ale, ALE_ALL_PORTS, vid); - - if (!netdev_mc_empty(ndev)) { - struct netdev_hw_addr *ha; - - /* program multicast address list into ALE register */ - netdev_for_each_mc_addr(ha, ndev) { - cpsw_add_mcast(priv, ha->addr); - } - } + __dev_mc_sync(ndev, cpsw_add_mc_addr, cpsw_del_mc_addr); } static void cpsw_intr_enable(struct cpsw_common *cpsw) @@ -1956,6 +1965,7 @@ static int cpsw_ndo_stop(struct net_device *ndev) struct cpsw_common *cpsw = priv->cpsw; cpsw_info(priv, ifdown, "shutting down cpsw device\n"); + __dev_mc_unsync(priv->ndev, cpsw_del_mc_addr); netif_tx_stop_all_queues(priv->ndev); netif_carrier_off(priv->ndev);