drivers: net: cpsw: Add helper functions for VLAN ALE implementation
Add helper functions for VLAN ALE implementations for Add, Delete Dump VLAN related ALE entries Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -148,7 +148,7 @@ static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
|
||||
return idx;
|
||||
}
|
||||
|
||||
static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
|
||||
int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr, u16 vid)
|
||||
{
|
||||
u32 ale_entry[ALE_ENTRY_WORDS];
|
||||
int type, idx;
|
||||
@@ -160,6 +160,8 @@ static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
|
||||
type = cpsw_ale_get_entry_type(ale_entry);
|
||||
if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
|
||||
continue;
|
||||
if (cpsw_ale_get_vlan_id(ale_entry) != vid)
|
||||
continue;
|
||||
cpsw_ale_get_addr(ale_entry, entry_addr);
|
||||
if (memcmp(entry_addr, addr, 6) == 0)
|
||||
return idx;
|
||||
@@ -167,6 +169,22 @@ static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
|
||||
{
|
||||
u32 ale_entry[ALE_ENTRY_WORDS];
|
||||
int type, idx;
|
||||
|
||||
for (idx = 0; idx < ale->params.ale_entries; idx++) {
|
||||
cpsw_ale_read(ale, idx, ale_entry);
|
||||
type = cpsw_ale_get_entry_type(ale_entry);
|
||||
if (type != ALE_TYPE_VLAN)
|
||||
continue;
|
||||
if (cpsw_ale_get_vlan_id(ale_entry) == vid)
|
||||
return idx;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int cpsw_ale_match_free(struct cpsw_ale *ale)
|
||||
{
|
||||
u32 ale_entry[ALE_ENTRY_WORDS];
|
||||
@@ -274,19 +292,32 @@ int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
|
||||
static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,
|
||||
int flags, u16 vid)
|
||||
{
|
||||
if (flags & ALE_VLAN) {
|
||||
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
|
||||
cpsw_ale_set_vlan_id(ale_entry, vid);
|
||||
} else {
|
||||
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
|
||||
}
|
||||
}
|
||||
|
||||
int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
|
||||
int flags, u16 vid)
|
||||
{
|
||||
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
|
||||
int idx;
|
||||
|
||||
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
|
||||
cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
|
||||
|
||||
cpsw_ale_set_addr(ale_entry, addr);
|
||||
cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
|
||||
cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
|
||||
cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
|
||||
cpsw_ale_set_port_num(ale_entry, port);
|
||||
|
||||
idx = cpsw_ale_match_addr(ale, addr);
|
||||
idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
|
||||
if (idx < 0)
|
||||
idx = cpsw_ale_match_free(ale);
|
||||
if (idx < 0)
|
||||
@@ -298,12 +329,13 @@ int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port)
|
||||
int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
|
||||
int flags, u16 vid)
|
||||
{
|
||||
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
|
||||
int idx;
|
||||
|
||||
idx = cpsw_ale_match_addr(ale, addr);
|
||||
idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
|
||||
if (idx < 0)
|
||||
return -ENOENT;
|
||||
|
||||
@@ -313,18 +345,19 @@ int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port)
|
||||
}
|
||||
|
||||
int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
|
||||
int super, int mcast_state)
|
||||
int flags, u16 vid, int mcast_state)
|
||||
{
|
||||
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
|
||||
int idx, mask;
|
||||
|
||||
idx = cpsw_ale_match_addr(ale, addr);
|
||||
idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
|
||||
if (idx >= 0)
|
||||
cpsw_ale_read(ale, idx, ale_entry);
|
||||
|
||||
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
|
||||
cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
|
||||
|
||||
cpsw_ale_set_addr(ale_entry, addr);
|
||||
cpsw_ale_set_super(ale_entry, super);
|
||||
cpsw_ale_set_super(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
|
||||
cpsw_ale_set_mcast_state(ale_entry, mcast_state);
|
||||
|
||||
mask = cpsw_ale_get_port_mask(ale_entry);
|
||||
@@ -342,12 +375,13 @@ int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
|
||||
int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
|
||||
int flags, u16 vid)
|
||||
{
|
||||
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
|
||||
int idx;
|
||||
|
||||
idx = cpsw_ale_match_addr(ale, addr);
|
||||
idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
|
||||
if (idx < 0)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -362,6 +396,55 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
|
||||
int reg_mcast, int unreg_mcast)
|
||||
{
|
||||
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
|
||||
int idx;
|
||||
|
||||
idx = cpsw_ale_match_vlan(ale, vid);
|
||||
if (idx >= 0)
|
||||
cpsw_ale_read(ale, idx, ale_entry);
|
||||
|
||||
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
|
||||
cpsw_ale_set_vlan_id(ale_entry, vid);
|
||||
|
||||
cpsw_ale_set_vlan_untag_force(ale_entry, untag);
|
||||
cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast);
|
||||
cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast);
|
||||
cpsw_ale_set_vlan_member_list(ale_entry, port);
|
||||
|
||||
if (idx < 0)
|
||||
idx = cpsw_ale_match_free(ale);
|
||||
if (idx < 0)
|
||||
idx = cpsw_ale_find_ageable(ale);
|
||||
if (idx < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
cpsw_ale_write(ale, idx, ale_entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
|
||||
{
|
||||
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
|
||||
int idx;
|
||||
|
||||
idx = cpsw_ale_match_vlan(ale, vid);
|
||||
if (idx < 0)
|
||||
return -ENOENT;
|
||||
|
||||
cpsw_ale_read(ale, idx, ale_entry);
|
||||
|
||||
if (port_mask)
|
||||
cpsw_ale_set_vlan_member_list(ale_entry, port_mask);
|
||||
else
|
||||
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
|
||||
|
||||
cpsw_ale_write(ale, idx, ale_entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ale_control_info {
|
||||
const char *name;
|
||||
int offset, port_offset;
|
||||
|
Reference in New Issue
Block a user