Skip to content

Commit 4b41d34

Browse files
grygoriySdavem330
authored andcommitted
net: ethernet: ti: cpsw: allow untagged traffic on host port
Now untagged vlan traffic is not support on Host P0 port. This patch adds in ALE context bitmap of VLANs for which Host P0 port bit set in Force Untagged Packet Egress bitmask in VLANs ALE entries, and adds corresponding check in VLAN incapsulation header parsing function cpsw_rx_vlan_encap(). Signed-off-by: Grygorii Strashko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7fe579d commit 4b41d34

File tree

3 files changed

+35
-10
lines changed

3 files changed

+35
-10
lines changed

drivers/net/ethernet/ti/cpsw.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -428,17 +428,16 @@ static void cpsw_rx_vlan_encap(struct sk_buff *skb)
428428
/* Ignore vid 0 and pass packet as is */
429429
if (!vid)
430430
return;
431-
/* Ignore default vlans in dual mac mode */
432-
if (cpsw->data.dual_emac &&
433-
vid == cpsw->slaves[priv->emac_port].port_vlan)
434-
return;
435431

436-
prio = (rx_vlan_encap_hdr >>
437-
CPSW_RX_VLAN_ENCAP_HDR_PRIO_SHIFT) &
438-
CPSW_RX_VLAN_ENCAP_HDR_PRIO_MSK;
432+
/* Untag P0 packets if set for vlan */
433+
if (!cpsw_ale_get_vlan_p0_untag(cpsw->ale, vid)) {
434+
prio = (rx_vlan_encap_hdr >>
435+
CPSW_RX_VLAN_ENCAP_HDR_PRIO_SHIFT) &
436+
CPSW_RX_VLAN_ENCAP_HDR_PRIO_MSK;
439437

440-
vtag = (prio << VLAN_PRIO_SHIFT) | vid;
441-
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vtag);
438+
vtag = (prio << VLAN_PRIO_SHIFT) | vid;
439+
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vtag);
440+
}
442441

443442
/* strip vlan tag for VLAN-tagged packet */
444443
if (pkt_type == CPSW_RX_VLAN_ENCAP_HDR_PKT_VLAN_TAG) {

drivers/net/ethernet/ti/cpsw_ale.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* Copyright (C) 2012 Texas Instruments
66
*
77
*/
8+
#include <linux/bitmap.h>
9+
#include <linux/if_vlan.h>
810
#include <linux/kernel.h>
911
#include <linux/module.h>
1012
#include <linux/platform_device.h>
@@ -415,6 +417,17 @@ static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,
415417
writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
416418
}
417419

420+
static void cpsw_ale_set_vlan_untag(struct cpsw_ale *ale, u32 *ale_entry,
421+
u16 vid, int untag_mask)
422+
{
423+
cpsw_ale_set_vlan_untag_force(ale_entry,
424+
untag_mask, ale->vlan_field_bits);
425+
if (untag_mask & ALE_PORT_HOST)
426+
bitmap_set(ale->p0_untag_vid_mask, vid, 1);
427+
else
428+
bitmap_clear(ale->p0_untag_vid_mask, vid, 1);
429+
}
430+
418431
int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
419432
int reg_mcast, int unreg_mcast)
420433
{
@@ -427,8 +440,8 @@ int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
427440

428441
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
429442
cpsw_ale_set_vlan_id(ale_entry, vid);
443+
cpsw_ale_set_vlan_untag(ale, ale_entry, vid, untag);
430444

431-
cpsw_ale_set_vlan_untag_force(ale_entry, untag, ale->vlan_field_bits);
432445
if (!ale->params.nu_switch_ale) {
433446
cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast,
434447
ale->vlan_field_bits);
@@ -460,6 +473,7 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
460473
return -ENOENT;
461474

462475
cpsw_ale_read(ale, idx, ale_entry);
476+
cpsw_ale_set_vlan_untag(ale, ale_entry, vid, 0);
463477

464478
if (port_mask)
465479
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)
792806
if (!ale)
793807
return NULL;
794808

809+
ale->p0_untag_vid_mask =
810+
devm_kmalloc_array(params->dev, BITS_TO_LONGS(VLAN_N_VID),
811+
sizeof(unsigned long),
812+
GFP_KERNEL);
813+
if (!ale->p0_untag_vid_mask)
814+
return ERR_PTR(-ENOMEM);
815+
795816
ale->params = *params;
796817
ale->ageout = ale->params.ale_ageout * HZ;
797818

drivers/net/ethernet/ti/cpsw_ale.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ struct cpsw_ale {
3535
u32 port_mask_bits;
3636
u32 port_num_bits;
3737
u32 vlan_field_bits;
38+
unsigned long *p0_untag_vid_mask;
3839
};
3940

4041
enum cpsw_ale_control {
@@ -115,4 +116,8 @@ int cpsw_ale_control_set(struct cpsw_ale *ale, int port,
115116
int control, int value);
116117
void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data);
117118

119+
static inline int cpsw_ale_get_vlan_p0_untag(struct cpsw_ale *ale, u16 vid)
120+
{
121+
return test_bit(vid, ale->p0_untag_vid_mask);
122+
}
118123
#endif

0 commit comments

Comments
 (0)