From 5c50a856d550b3bf6a731f6e33a794ed5c519817 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Mon, 29 Oct 2012 08:45:11 +0000 Subject: drivers: net: ethernet: cpsw: add multicast address to ALE table Adding multicast address to ALE table via netdev ops to subscribe, transmit or receive multicast frames to and from the network Signed-off-by: Mugunthan V N Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw_ale.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'drivers/net/ethernet/ti/cpsw_ale.c') diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c index ca0d48a7e508..0e9ccc2cf91f 100644 --- a/drivers/net/ethernet/ti/cpsw_ale.c +++ b/drivers/net/ethernet/ti/cpsw_ale.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "cpsw_ale.h" @@ -211,10 +212,34 @@ static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry, mask &= ~port_mask; /* free if only remaining port is host port */ - if (mask == BIT(ale->params.ale_ports)) - cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); - else + if (mask) cpsw_ale_set_port_mask(ale_entry, mask); + else + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); +} + +int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask) +{ + u32 ale_entry[ALE_ENTRY_WORDS]; + int ret, idx; + + for (idx = 0; idx < ale->params.ale_entries; idx++) { + cpsw_ale_read(ale, idx, ale_entry); + ret = cpsw_ale_get_entry_type(ale_entry); + if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR) + continue; + + if (cpsw_ale_get_mcast(ale_entry)) { + u8 addr[6]; + + cpsw_ale_get_addr(ale_entry, addr); + if (!is_broadcast_ether_addr(addr)) + cpsw_ale_flush_mcast(ale, ale_entry, port_mask); + } + + cpsw_ale_write(ale, idx, ale_entry); + } + return 0; } static void cpsw_ale_flush_ucast(struct cpsw_ale *ale, u32 *ale_entry, -- cgit v1.2.3