From c536da365b2101afcd2516650ce58d4d511ddc85 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Sun, 12 Jun 2016 15:38:54 +0200
Subject: [PATCH] lantiq: add VLAN handling fixes to xrx200 ethernet driver

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 ...0025-NET-MIPS-lantiq-adds-xrx200-net.patch | 54 +++++++++++++------
 1 file changed, 37 insertions(+), 17 deletions(-)

diff --git a/target/linux/lantiq/patches-4.4/0025-NET-MIPS-lantiq-adds-xrx200-net.patch b/target/linux/lantiq/patches-4.4/0025-NET-MIPS-lantiq-adds-xrx200-net.patch
index 7d81720213..07df336d2f 100644
--- a/target/linux/lantiq/patches-4.4/0025-NET-MIPS-lantiq-adds-xrx200-net.patch
+++ b/target/linux/lantiq/patches-4.4/0025-NET-MIPS-lantiq-adds-xrx200-net.patch
@@ -209,7 +209,7 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
 +};
 --- /dev/null
 +++ b/drivers/net/ethernet/lantiq_xrx200.c
-@@ -0,0 +1,1810 @@
+@@ -0,0 +1,1830 @@
 +/*
 + *   This program is free software; you can redistribute it and/or modify it
 + *   under the terms of the GNU General Public License version 2 as published
@@ -234,6 +234,7 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
 +#include <linux/platform_device.h>
 +#include <linux/interrupt.h>
 +#include <linux/clk.h>
++#include <linux/if_vlan.h>
 +#include <asm/delay.h>
 +
 +#include <linux/of_net.h>
@@ -248,14 +249,9 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
 +
 +#define SW_POLLING
 +#define SW_ROUTING
-+/* #define SW_PORTMAP */
 +
 +#ifdef SW_ROUTING
-+  #ifdef SW_PORTMAP
 +#define XRX200_MAX_DEV		2
-+  #else
-+#define XRX200_MAX_DEV		2
-+  #endif
 +#else
 +#define XRX200_MAX_DEV		1
 +#endif
@@ -435,6 +431,8 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
 +	struct mii_bus *mii_bus;
 +
 +	struct xrx200_chan chan[XRX200_MAX_DMA];
++	u16 vlan_vid[XRX200_MAX_VLAN];
++	u16 vlan_port_map[XRX200_MAX_VLAN];
 +
 +	struct net_device *devs[XRX200_MAX_DEV];
 +	int num_devs;
@@ -735,6 +733,7 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
 +static int xrx200sw_set_vlan_vid(struct switch_dev *dev, const struct switch_attr *attr,
 +				 struct switch_val *val)
 +{
++	struct xrx200_hw *hw = container_of(dev, struct xrx200_hw, swdev);
 +	int i;
 +	struct xrx200_pce_table_entry tev;
 +	struct xrx200_pce_table_entry tem;
@@ -749,6 +748,8 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
 +			return -EINVAL;
 +	}
 +
++	hw->vlan_vid[val->port_vlan] = val->value.i;
++
 +	tev.index = val->port_vlan;
 +	xrx200_pce_table_entry_read(&tev);
 +	tev.key[0] = val->value.i;
@@ -780,6 +781,7 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
 +
 +static int xrx200sw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val)
 +{
++	struct xrx200_hw *hw = container_of(dev, struct xrx200_hw, swdev);
 +	int i, portmap, tagmap, untagged;
 +	struct xrx200_pce_table_entry tem;
 +
@@ -830,6 +832,10 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
 +	tem.val[2] = tagmap;
 +	xrx200_pce_table_entry_write(&tem);
 +
++	ltq_switch_w32_mask(0, portmap, PCE_PMAP2);
++	ltq_switch_w32_mask(0, portmap, PCE_PMAP3);
++	hw->vlan_port_map[val->port_vlan] = portmap;
++
 +	xrx200sw_fixup_pvids();
 +
 +	return 0;
@@ -1156,7 +1162,7 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
 +	if (ret) {
 +		netdev_err(dev,
 +			"failed to allocate new rx buffer\n");
-+		return 0;
++		return;
 +	}
 +
 +	skb_put(skb, len);
@@ -1258,11 +1264,7 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
 +	u32 byte_offset;
 +	int len;
 +#ifdef SW_ROUTING
-+  #ifdef SW_PORTMAP
-+	u32 special_tag = (SPID_CPU_PORT << SPID_SHIFT) | PORT_MAP_SEL | PORT_MAP_EN | DPID_ENABLE;
-+  #else
 +	u32 special_tag = (SPID_CPU_PORT << SPID_SHIFT) | DPID_ENABLE;
-+  #endif
 +#endif
 +
 +	skb->dev = dev;
@@ -1274,12 +1276,27 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
 +		return NETDEV_TX_BUSY;
 +	}
 +#ifdef SW_ROUTING
-+  #ifdef SW_PORTMAP
++	if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {
++		u16 port_map = priv->port_map;
++		special_tag |= PORT_MAP_SEL | PORT_MAP_EN;
++		if (skb->protocol == htons(ETH_P_8021Q)) {
++			u16 vid;
++			int i;
++
++			if (!__vlan_get_tag(skb, &vid)) {
++				for (i = 0; i < XRX200_MAX_VLAN; i++) {
++					if (priv->hw->vlan_vid[i] != vid)
++						continue;
++					port_map = priv->hw->vlan_port_map[i];
++					break;
++				}
++			}
++		}
++		special_tag |= port_map << PORT_MAP_SHIFT;
++	}
 +	special_tag |= priv->port_map << PORT_MAP_SHIFT;
-+  #else
 +	if(priv->id)
 +		special_tag |= (1 << DPID_SHIFT);
-+  #endif
 +	if(skb_headroom(skb) < 4) {
 +		struct sk_buff *tmp = skb_realloc_headroom(skb, 4);
 +		dev_kfree_skb_any(skb);
@@ -1702,9 +1719,9 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
 +	xrx200_pci_microcode();
 +
 +	/* Default unknown Broadcat/Multicast/Unicast port maps */
-+	ltq_switch_w32(0x7f, PCE_PMAP1);
-+	ltq_switch_w32(0x7f, PCE_PMAP2);
-+	ltq_switch_w32(0x7f, PCE_PMAP3);
++	ltq_switch_w32(0x40, PCE_PMAP1);
++	ltq_switch_w32(0x40, PCE_PMAP2);
++	ltq_switch_w32(0x40, PCE_PMAP3);
 +
 +	/* RMON Counter Enable for all physical ports */
 +	for (i = 0; i < 7; i++)
@@ -1745,6 +1762,9 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
 +	ltq_switch_w32_mask(0, BIT(3), MAC_CTRL_REG(6, 2));
 +	ltq_switch_w32(1518 + 8 + 4 * 2, MAC_FLEN_REG);
 +	xrx200sw_write_x(1, XRX200_BM_QUEUE_GCTRL_GL_MOD, 0);
++
++	for (i = 0; i < XRX200_MAX_VLAN; i++)
++		hw->vlan_vid[i] = i;
 +}
 +
 +static void xrx200_hw_cleanup(struct xrx200_hw *hw)
-- 
GitLab