diff options
author | Mugunthan V N <mugunthanvnm@ti.com> | 2012-10-29 08:45:11 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-01 12:21:29 -0400 |
commit | 5c50a856d550b3bf6a731f6e33a794ed5c519817 (patch) | |
tree | 3435bb193aac26e54094a022f809cbe33079a4f0 /drivers/net/ethernet/ti/cpsw_ale.c | |
parent | 8ef29f8aae524bd51298fb10ac6a5ce6c4c5a3d8 (diff) |
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 <mugunthanvnm@ti.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/ti/cpsw_ale.c')
-rw-r--r-- | drivers/net/ethernet/ti/cpsw_ale.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c index ca0d48a7e50..0e9ccc2cf91 100644 --- a/drivers/net/ethernet/ti/cpsw_ale.c +++ b/drivers/net/ethernet/ti/cpsw_ale.c @@ -20,6 +20,7 @@ #include <linux/io.h> #include <linux/stat.h> #include <linux/sysfs.h> +#include <linux/etherdevice.h> #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, |