summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/ti/cpsw_ale.c
diff options
context:
space:
mode:
authorMugunthan V N <mugunthanvnm@ti.com>2012-10-29 08:45:11 +0000
committerDavid S. Miller <davem@davemloft.net>2012-11-01 12:21:29 -0400
commit5c50a856d550b3bf6a731f6e33a794ed5c519817 (patch)
tree3435bb193aac26e54094a022f809cbe33079a4f0 /drivers/net/ethernet/ti/cpsw_ale.c
parent8ef29f8aae524bd51298fb10ac6a5ce6c4c5a3d8 (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.c31
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,