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_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_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask) { u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; int idx, mask; idx = cpsw_ale_match_addr(ale, addr); if (idx >= 0) cpsw_ale_read(ale, idx, ale_entry); cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR); cpsw_ale_set_addr(ale_entry, addr); cpsw_ale_set_mcast_state(ale_entry, ALE_MCAST_FWD_2); mask = cpsw_ale_get_port_mask(ale_entry); port_mask |= mask; cpsw_ale_set_port_mask(ale_entry, port_mask); 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; }
static void cpsw_ale_flush_ucast(struct cpsw_ale *ale, u32 *ale_entry, int port_mask) { int port; port = cpsw_ale_get_port_num(ale_entry); if ((BIT(port) & port_mask) == 0) return; /* ports dont intersect, not interested */ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); }
int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port) { u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; int idx; idx = cpsw_ale_match_addr(ale, addr); if (idx < 0) return -ENOENT; cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); cpsw_ale_write(ale, idx, ale_entry); return 0; }
static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry, int port_mask) { int mask; mask = cpsw_ale_get_port_mask(ale_entry); if ((mask & port_mask) == 0) return; /* ports dont intersect, not interested */ mask &= ~port_mask; /* free if only remaining port is host port */ if (mask) cpsw_ale_set_port_mask(ale_entry, mask); else cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); }
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; }
int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask) { u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; int idx; idx = cpsw_ale_match_addr(ale, addr); if (idx < 0) return -EINVAL; cpsw_ale_read(ale, idx, ale_entry); if (port_mask) cpsw_ale_set_port_mask(ale_entry, port_mask); else cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); cpsw_ale_write(ale, idx, ale_entry); return 0; }
int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags) { u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; int idx; cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR); 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); 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; }