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> > >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; >+ >+ if (priv->vlan) { >+ pvid = priv->vlan_id[priv->pvid[port]]; >+ mode = AR8327_PORT_VLAN1_OUT_MODE_UNMOD; >+ ingress = AR8216_IN_SECURE; >+ } else { >+ pvid = port; >+ mode = 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; > priv->write(priv, AR8327_REG_PORT_VLAN1(port), t); >@@ -1851,23 +1859,21 @@ ar8xxx_sw_get_port_link(struct switch_dev *dev, int >port, > } > > static int >-ar8xxx_sw_get_ports(struct switch_dev *dev, struct switch_val *val) >+ar8xxx_sw_get_ports(struct switch_val *val, int ports, u8 port_mask, u8 >tagged) > { >- 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++) { >+ for (i = 0; i < ports; i++) { > struct switch_port *p; > >- if (!(ports & (1 << i))) >+ if (!(port_mask & BIT(i))) > continue; > > p = &val->value.ports[val->len++]; > p->id = i; >- if (priv->vlan_tagged & (1 << i)) >- p->flags = (1 << SWITCH_PORT_FLAG_TAGGED); >+ if (tagged & BIT(i)) >+ p->flags = BIT(SWITCH_PORT_FLAG_TAGGED); > else > p->flags = 0; > } >@@ -1875,20 +1881,55 @@ ar8xxx_sw_get_ports(struct switch_dev *dev, struct >switch_val *val) > } > > static int >-ar8xxx_sw_set_ports(struct switch_dev *dev, struct switch_val *val) >+ar8216_sw_get_ports(struct switch_dev *dev, struct switch_val *val) >+{ >+ int ports = dev->ports; >+ struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); >+ u8 port_mask = priv->vlan_table[val->port_vlan]; >+ u8 tagged = priv->chip_data.ar8216.vlan_tagged; >+ >+ return ar8xxx_sw_get_ports(val, ports, port_mask, tagged); >+} >+ >+static int >+ar8327_sw_get_ports(struct switch_dev *dev, struct switch_val *val) >+{ >+ int ports = dev->ports; >+ struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); >+ u8 port_mask = priv->vlan_table[val->port_vlan]; >+ u8 tagged = priv->chip_data.ar8327.vlan_tagged[val->port_vlan]; >+ >+ return ar8xxx_sw_get_ports(val, ports, port_mask, tagged); >+} >+ >+static int >+ar8216_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]; >+ u8 *tagged = &priv->chip_data.ar8216.vlan_tagged; > 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)) { >- priv->vlan_tagged |= (1 << p->id); >+ if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) { >+ >+ /* if port was untagged before then >+ * remove him from other vlans */ >+ if(*tagged & BIT(p->id)){ >+ for (j = 0; j < AR8X16_MAX_VLANS; j++) { >+ if (j == val->port_vlan) >+ continue; >+ >+ priv->vlan_table[j] &= ~(BIT(p->id)); >+ } >+ } >+ >+ *tagged |= BIT(p->id); > } else { >- priv->vlan_tagged &= ~(1 << p->id); >+ *tagged &= ~(BIT(p->id)); > priv->pvid[p->id] = val->port_vlan; > > /* make sure that an untagged port does not >@@ -1896,11 +1937,38 @@ ar8xxx_sw_set_ports(struct switch_dev *dev, struct >switch_val *val) > for (j = 0; j < AR8X16_MAX_VLANS; j++) { > if (j == val->port_vlan) > continue; >- priv->vlan_table[j] &= ~(1 << p->id); >+ >+ priv->vlan_table[j] &= ~(BIT(p->id)); > } > } > >- *vt |= 1 << p->id; >+ *vt |= BIT(p->id); >+ } >+ 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]; >+ u8 *vlan_tagged = priv->chip_data.ar8327.vlan_tagged; >+ u8 *tagged = &vlan_tagged[val->port_vlan]; >+ >+ int i; >+ >+ *vt = 0; >+ *tagged = 0; >+ for (i = 0; i < val->len; i++) { >+ struct switch_port *p = &val->value.ports[i]; >+ >+ if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) { >+ *tagged |= BIT(p->id); >+ } else { >+ priv->pvid[p->id] = val->port_vlan; >+ } >+ >+ *vt |= BIT(p->id); > } > return 0; > } >@@ -2019,13 +2087,12 @@ ar8xxx_sw_hw_apply(struct switch_dev *dev) > continue; > > for (i = 0; i < dev->ports; i++) { >- u8 mask = (1 << i); >+ u8 mask = BIT(i); > if (vp & mask) > portmask[i] |= vp & ~mask; > } > >- priv->chip->vtu_load_vlan(priv, priv->vlan_id[j], >- priv->vlan_table[j]); >+ priv->chip->vtu_load_vlan(priv, j); > } > } else { > /* vlan disabled: >@@ -2034,8 +2101,8 @@ ar8xxx_sw_hw_apply(struct switch_dev *dev) > if (i == AR8216_PORT_CPU) > continue; > >- portmask[i] = 1 << AR8216_PORT_CPU; >- portmask[AR8216_PORT_CPU] |= (1 << i); >+ portmask[i] = BIT(AR8216_PORT_CPU); >+ portmask[AR8216_PORT_CPU] |= BIT(i); > } > } > >@@ -2046,7 +2113,7 @@ ar8xxx_sw_hw_apply(struct switch_dev *dev) > > if (priv->vlan) { > pvid = priv->vlan_id[priv->pvid[i]]; >- if (priv->vlan_tagged & (1 << i)) >+ if (priv->chip_data.ar8216.vlan_tagged & BIT(i)) > egress = AR8216_OUT_ADD_VLAN; > else > egress = AR8216_OUT_STRIP_VLAN; >@@ -2442,8 +2509,8 @@ static const struct switch_dev_ops ar8xxx_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 = ar8216_sw_get_ports, >+ .set_vlan_ports = ar8216_sw_set_ports, > .apply_config = ar8xxx_sw_hw_apply, > .reset_switch = ar8xxx_sw_reset_switch, > .get_port_link = ar8xxx_sw_get_port_link, >@@ -2464,8 +2531,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, >_______________________________________________ >openwrt-devel mailing list >openwrt-devel@lists.openwrt.org >https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel