Re: [OpenWrt-Devel] [RFC] Fix VLAN on Atheros AR8327N
Hi, Am 17.09.2014 19:50, schrieb John Crispin: On 17/09/2014 19:47, Florian Fainelli wrote: On 08/31/2014 10:42 AM, Jiri Pirko wrote: Sat, Jul 19, 2014 at 09:49:38PM CEST, nolt...@gmail.com wrote: Commit 40842 reverted the fix for tagged+untagged VLANs on AR8327: https://dev.openwrt.org/changeset/40777 https://dev.openwrt.org/changeset/40842 According to jow, some people experienced some issues on older devices. Can anyone tell me what were those issues? Anyway, that patch modified some parts of the ar8216/ar8236, so I suppose any device with those switches were affected. However, I've modified the patch keeping the ar8216/ar8236 as much untouched as possible. Could anyone test it on those devices? BTW, this works for me on a TP-Link WDR4300 (ar8327). I tested the patch on TL-WR1043ND v2 with Atheros AR8327 rev. 4. Vlans are working as expected. Please include this into BB (might need repost) Thanks! Tested-by: Jiri Pirko j...@resnulli.us Unless there are further objections, we should probably just go ahead and apply this patch since it affects a bunch of users. and then the other bunch complains, as we had before. we keep applying and reversing this i think. maybe we should just see what the real bug is ? John I'm interested in this feature. I tried to understand what the revoked patch changes and rewrote it. I submitted my changes two months ago: http://patchwork.openwrt.org/patch/5957/ http://patchwork.openwrt.org/patch/5958/ My patches attempt to minimize changes in non-ar8327-specific code. Neither the revert commit nor ticket #12181 describe the issues. So I'm not sure, if my patches have them too. Does anyone know details about the issues? - Valentin Spreckels Signed-off-by: Saverio Proto ziopr...@gmail.com Signed-off-by: Álvaro Fernández nolt...@gmail.com --- diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index 3846159..9eae624 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -78,7 +78,7 @@ struct ar8xxx_chip { u32 (*read_port_status)(struct ar8xxx_priv *priv, int port); int (*atu_flush)(struct ar8xxx_priv *priv); void (*vtu_flush)(struct ar8xxx_priv *priv); - void (*vtu_load_vlan)(struct ar8xxx_priv *priv, u32 vid, u32 port_mask); + void (*vtu_load_vlan)(struct ar8xxx_priv *priv, u32 vlan); const struct ar8xxx_mib_desc *mib_decs; unsigned num_mibs; @@ -112,7 +112,12 @@ struct ar8327_led { enum ar8327_led_pattern pattern; }; +struct ar8216_data { +u8 vlan_tagged; +}; + struct ar8327_data { +u8 vlan_tagged[AR8X16_MAX_VLANS]; u32 port0_status; u32 port6_status; @@ -138,6 +143,7 @@ struct ar8xxx_priv { u8 chip_rev; const struct ar8xxx_chip *chip; union { +struct ar8216_data ar8216; struct ar8327_data ar8327; } chip_data; bool initialized; @@ -159,7 +165,6 @@ struct ar8xxx_priv { bool vlan; u16 vlan_id[AR8X16_MAX_VLANS]; u8 vlan_table[AR8X16_MAX_VLANS]; -u8 vlan_tagged; u16 pvid[AR8X16_MAX_PORTS]; /* mirroring */ @@ -641,7 +646,7 @@ ar8216_mangle_rx(struct net_device *dev, struct sk_buff *skb) port = buf[0] 0xf; /* no need to fix up packets coming from a tagged source */ - if (priv-vlan_tagged (1 port)) + if (priv-chip_data.ar8216.vlan_tagged BIT(port)) return; /* lookup port vid from local table, the switch passes an invalid vlan id */ @@ -695,10 +700,13 @@ ar8216_vtu_flush(struct ar8xxx_priv *priv) } static void -ar8216_vtu_load_vlan(struct ar8xxx_priv *priv, u32 vid, u32 port_mask) +ar8216_vtu_load_vlan(struct ar8xxx_priv *priv, u32 vlan) { u32 op; + u32 vid = priv-vlan_id[vlan]; +u32 port_mask = priv-vlan_table[vlan]; + op = AR8216_VTU_OP_LOAD | (vid AR8216_VTU_VID_S); ar8216_vtu_op(priv, op, port_mask); } @@ -1705,12 +1713,16 @@ ar8327_vtu_flush(struct ar8xxx_priv *priv) } static void -ar8327_vtu_load_vlan(struct ar8xxx_priv *priv, u32 vid, u32 port_mask) +ar8327_vtu_load_vlan(struct ar8xxx_priv *priv, u32 vlan) { u32 op; u32 val; int i; + u32 vid = priv-vlan_id[vlan]; +u32 port_mask = priv-vlan_table[vlan]; + u32 tagged = priv-chip_data.ar8327.vlan_tagged[vlan]; + op = AR8327_VTU_FUNC1_OP_LOAD | (vid AR8327_VTU_FUNC1_VID_S); val = AR8327_VTU_FUNC0_VALID | AR8327_VTU_FUNC0_IVL; for (i = 0; i AR8327_NUM_PORTS; i++) { @@ -1720,7 +1732,7 @@ ar8327_vtu_load_vlan(struct ar8xxx_priv *priv, u32 vid, u32 port_mask) mode = AR8327_VTU_FUNC0_EG_MODE_NOT; else if (priv-vlan == 0) mode = AR8327_VTU_FUNC0_EG_MODE_KEEP; - else if (priv-vlan_tagged BIT(i)) + else if (tagged BIT(i)) mode = AR8327_VTU_FUNC0_EG_MODE_TAG; else mode = AR8327_VTU_FUNC0_EG_MODE_UNTAG; @@ -1734,26 +1746,22 @@ static void ar8327_setup_port(struct ar8xxx_priv *priv, int port, u32 egress, u32 ingress, u32 members, u32 pvid) { -u32 t; -u32 mode; +u32 mode, t
[OpenWrt-Devel] [PATCH 1/2] ar71xx: ar8216: move policies, pvid to setup_port
From: Valentin Spreckels valentin.spreck...@informatik.uni-oldenburg.de This moves ingress, egress policy and pvid decisions to setup_port methods. They arenow device type dependent. This allows policy changes on only one device type which is needed to allow tagged + untagged operation on ar8327. Tested on TP-LINK WDR-3600 (ar8327N). Signed-off-by: Valentin Spreckels valentin.spreck...@informatik.uni-oldenburg.de --- .../linux/generic/files/drivers/net/phy/ar8216.c | 93 -- 1 file changed, 52 insertions(+), 41 deletions(-) diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index 3846159..3efd460 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -73,8 +73,7 @@ struct ar8xxx_chip { void (*init_globals)(struct ar8xxx_priv *priv); void (*init_port)(struct ar8xxx_priv *priv, int port); - void (*setup_port)(struct ar8xxx_priv *priv, int port, u32 egress, - u32 ingress, u32 members, u32 pvid); + void (*setup_port)(struct ar8xxx_priv *priv, int port, u32 members); u32 (*read_port_status)(struct ar8xxx_priv *priv, int port); int (*atu_flush)(struct ar8xxx_priv *priv); void (*vtu_flush)(struct ar8xxx_priv *priv); @@ -722,10 +721,24 @@ ar8216_read_port_status(struct ar8xxx_priv *priv, int port) } static void -ar8216_setup_port(struct ar8xxx_priv *priv, int port, u32 egress, u32 ingress, - u32 members, u32 pvid) +ar8216_setup_port(struct ar8xxx_priv *priv, int port, u32 members) { u32 header; + u32 egress, ingress; + u32 pvid; + + if (priv-vlan) { + pvid = priv-vlan_id[priv-pvid[port]]; + if (priv-vlan_tagged (1 port)) + egress = AR8216_OUT_ADD_VLAN; + else + egress = AR8216_OUT_STRIP_VLAN; + ingress = AR8216_IN_SECURE; + } else { + pvid = port; + egress = AR8216_OUT_KEEP; + ingress = AR8216_IN_PORT_ONLY; + } if (chip_is_ar8216(priv) priv-vlan port == AR8216_PORT_CPU) header = AR8216_PORT_CTRL_HEADER; @@ -807,9 +820,24 @@ static const struct ar8xxx_chip ar8216_chip = { }; static void -ar8236_setup_port(struct ar8xxx_priv *priv, int port, u32 egress, u32 ingress, - u32 members, u32 pvid) +ar8236_setup_port(struct ar8xxx_priv *priv, int port, u32 members) { + u32 egress, ingress; + u32 pvid; + + if (priv-vlan) { + pvid = priv-vlan_id[priv-pvid[port]]; + if (priv-vlan_tagged (1 port)) + egress = AR8216_OUT_ADD_VLAN; + else + egress = AR8216_OUT_STRIP_VLAN; + ingress = AR8216_IN_SECURE; + } else { + pvid = port; + egress = AR8216_OUT_KEEP; + ingress = AR8216_IN_PORT_ONLY; + } + ar8xxx_rmw(priv, AR8216_REG_PORT_CTRL(port), AR8216_PORT_CTRL_LEARN | AR8216_PORT_CTRL_VLAN_MODE | AR8216_PORT_CTRL_SINGLE_VLAN | AR8216_PORT_CTRL_STATE | @@ -1731,31 +1759,31 @@ ar8327_vtu_load_vlan(struct ar8xxx_priv *priv, u32 vid, u32 port_mask) } static void -ar8327_setup_port(struct ar8xxx_priv *priv, int port, u32 egress, u32 ingress, - u32 members, u32 pvid) +ar8327_setup_port(struct ar8xxx_priv *priv, int port, u32 members) { u32 t; - u32 mode; + u32 egress, ingress; + u32 pvid; + + if (priv-vlan) { + pvid = priv-vlan_id[priv-pvid[port]]; + if (priv-vlan_tagged (1 port)) + egress = AR8327_PORT_VLAN1_OUT_MODE_TAG; + else + egress = AR8327_PORT_VLAN1_OUT_MODE_UNTAG; + ingress = AR8216_IN_SECURE; + } else { + pvid = port; + egress = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH; + ingress = AR8216_IN_PORT_ONLY; + } t = pvid AR8327_PORT_VLAN0_DEF_SVID_S; t |= pvid AR8327_PORT_VLAN0_DEF_CVID_S; priv-write(priv, AR8327_REG_PORT_VLAN0(port), t); - mode = AR8327_PORT_VLAN1_OUT_MODE_UNMOD; - switch (egress) { - case AR8216_OUT_KEEP: - mode = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH; - break; - case AR8216_OUT_STRIP_VLAN: - mode = AR8327_PORT_VLAN1_OUT_MODE_UNTAG; - break; - case AR8216_OUT_ADD_VLAN: - mode = AR8327_PORT_VLAN1_OUT_MODE_TAG; - break; - } - t = AR8327_PORT_VLAN1_PORT_VLAN_PROP; - t |= mode AR8327_PORT_VLAN1_OUT_MODE_S; + t |= egress AR8327_PORT_VLAN1_OUT_MODE_S; priv-write(priv, AR8327_REG_PORT_VLAN1(port), t); t = members; @@ -2041,24 +2069,7
[OpenWrt-Devel] [PATCH 2/2] ar71xx: ar8216: tagged+untagged on ar8327 (#12181)
From: Valentin Spreckels valentin.spreck...@informatik.uni-oldenburg.de This allows tagged and untagged traffic together on the same port on ar8327 switch devices. I looked at the first attempt to do this in r40777 (ar71xx: Fix tagged+untagged operation on AR8327N (#12181)). I also set the vlan and port egress policies like that change. But I change vlan_tagged in an less intrusive way. The tagged/untagged decision is now based on the following rules: - if vid != pvid then traffic is always tagged - if vid == pvid then vlan_tagged stores if the traffic should be tagged Tested on TP-Link WDR-3600 (ar8327N). Signed-off-by: Valentin Spreckels valentin.spreck...@informatik.uni-oldenburg.de --- .../linux/generic/files/drivers/net/phy/ar8216.c | 60 +++--- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index 3efd460..bd6cc97 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -1748,7 +1748,7 @@ ar8327_vtu_load_vlan(struct ar8xxx_priv *priv, u32 vid, u32 port_mask) mode = AR8327_VTU_FUNC0_EG_MODE_NOT; else if (priv-vlan == 0) mode = AR8327_VTU_FUNC0_EG_MODE_KEEP; - else if (priv-vlan_tagged BIT(i)) + else if ((priv-vlan_tagged BIT(i)) || (priv-vlan_id[priv-pvid[i]] != vid)) mode = AR8327_VTU_FUNC0_EG_MODE_TAG; else mode = AR8327_VTU_FUNC0_EG_MODE_UNTAG; @@ -1767,10 +1767,7 @@ ar8327_setup_port(struct ar8xxx_priv *priv, int port, u32 members) if (priv-vlan) { pvid = priv-vlan_id[priv-pvid[port]]; - if (priv-vlan_tagged (1 port)) - egress = AR8327_PORT_VLAN1_OUT_MODE_TAG; - else - egress = AR8327_PORT_VLAN1_OUT_MODE_UNTAG; + egress = AR8327_PORT_VLAN1_OUT_MODE_UNMOD; ingress = AR8216_IN_SECURE; } else { pvid = port; @@ -1903,6 +1900,30 @@ ar8xxx_sw_get_ports(struct switch_dev *dev, struct switch_val *val) } static int +ar8327_sw_get_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + u8 ports = priv-vlan_table[val-port_vlan]; + int i; + + val-len = 0; + for (i = 0; i dev-ports; i++) { + struct switch_port *p; + + if (!(ports (1 i))) + continue; + + p = val-value.ports[val-len++]; + p-id = i; + if ((priv-vlan_tagged (1 i)) || (priv-pvid[i] != val-port_vlan)) + p-flags = (1 SWITCH_PORT_FLAG_TAGGED); + else + p-flags = 0; + } + return 0; +} + +static int ar8xxx_sw_set_ports(struct switch_dev *dev, struct switch_val *val) { struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); @@ -1933,6 +1954,31 @@ ar8xxx_sw_set_ports(struct switch_dev *dev, struct switch_val *val) return 0; } +static int +ar8327_sw_set_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + u8 *vt = priv-vlan_table[val-port_vlan]; + int i, j; + + *vt = 0; + for (i = 0; i val-len; i++) { + struct switch_port *p = val-value.ports[i]; + + if (p-flags (1 SWITCH_PORT_FLAG_TAGGED)) { + if (val-port_vlan == priv-pvid[p-id]) { + priv-vlan_tagged |= (1 p-id); + } + } else { + priv-vlan_tagged = ~(1 p-id); + priv-pvid[p-id] = val-port_vlan; + } + + *vt |= 1 p-id; + } + return 0; +} + static void ar8327_set_mirror_regs(struct ar8xxx_priv *priv) { @@ -2475,8 +2521,8 @@ static const struct switch_dev_ops ar8327_sw_ops = { }, .get_port_pvid = ar8xxx_sw_get_pvid, .set_port_pvid = ar8xxx_sw_set_pvid, - .get_vlan_ports = ar8xxx_sw_get_ports, - .set_vlan_ports = ar8xxx_sw_set_ports, + .get_vlan_ports = ar8327_sw_get_ports, + .set_vlan_ports = ar8327_sw_set_ports, .apply_config = ar8xxx_sw_hw_apply, .reset_switch = ar8xxx_sw_reset_switch, .get_port_link = ar8xxx_sw_get_port_link, -- 1.8.5.5 ___ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
[OpenWrt-Devel] [PATCH 0/2] ar71xx: ar8216: tagged+untagged on ar8327 (#12181)
From: Valentin Spreckels valentin.spreck...@informatik.uni-oldenburg.de Hi, This is a small patch set to allow taged+untagged traffic on the same port of an ar8327 switch. The first patch does small refactoring. The real changes are in the second patch. I only included the changes for ar8327, because I only have ar8327 devices, but I think, that other ar8xxx types (but not ar8216) can also support this similar to ar8327. Valentin Spreckels (2): ar71xx: ar8216: move policies, pvid to setup_port ar71xx: ar8216: tagged+untagged on ar8327 (#12181) .../linux/generic/files/drivers/net/phy/ar8216.c | 145 ++--- 1 file changed, 101 insertions(+), 44 deletions(-) -- 1.8.5.5 ___ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel