diff options
Diffstat (limited to '')
-rw-r--r-- | drivers/net/ethernet/ti/cpsw_ale.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c index e7c24396933e..723f742e6437 100644 --- a/drivers/net/ethernet/ti/cpsw_ale.c +++ b/drivers/net/ethernet/ti/cpsw_ale.c @@ -5,6 +5,8 @@ * Copyright (C) 2012 Texas Instruments * */ +#include <linux/bitmap.h> +#include <linux/if_vlan.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -415,6 +417,17 @@ static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry, writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx)); } +static void cpsw_ale_set_vlan_untag(struct cpsw_ale *ale, u32 *ale_entry, + u16 vid, int untag_mask) +{ + cpsw_ale_set_vlan_untag_force(ale_entry, + untag_mask, ale->vlan_field_bits); + if (untag_mask & ALE_PORT_HOST) + bitmap_set(ale->p0_untag_vid_mask, vid, 1); + else + bitmap_clear(ale->p0_untag_vid_mask, vid, 1); +} + int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag, int reg_mcast, int unreg_mcast) { @@ -427,8 +440,8 @@ int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag, cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN); cpsw_ale_set_vlan_id(ale_entry, vid); + cpsw_ale_set_vlan_untag(ale, ale_entry, vid, untag); - cpsw_ale_set_vlan_untag_force(ale_entry, untag, ale->vlan_field_bits); if (!ale->params.nu_switch_ale) { cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast, ale->vlan_field_bits); @@ -460,6 +473,7 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask) return -ENOENT; cpsw_ale_read(ale, idx, ale_entry); + cpsw_ale_set_vlan_untag(ale, ale_entry, vid, 0); if (port_mask) cpsw_ale_set_vlan_member_list(ale_entry, port_mask, @@ -792,6 +806,13 @@ struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params) if (!ale) return NULL; + ale->p0_untag_vid_mask = + devm_kmalloc_array(params->dev, BITS_TO_LONGS(VLAN_N_VID), + sizeof(unsigned long), + GFP_KERNEL); + if (!ale->p0_untag_vid_mask) + return ERR_PTR(-ENOMEM); + ale->params = *params; ale->ageout = ale->params.ale_ageout * HZ; |