ramips: Allow to receive vlan over untag ports on MT7530
[openwrt/svn-archive/archive.git] / target / linux / ramips / files / drivers / net / ethernet / ralink / mt7530.c
index 51e16f26b9c336360af2b36fe39b3ac9cd87c92b..4e00315452d5bb94d4a49f2e8bf317087b45a6d4 100644 (file)
@@ -484,6 +484,8 @@ mt7530_apply_config(struct switch_dev *dev)
 {
        struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
        int i, j;
+       u8 tag_ports;
+       u8 untag_ports;
 
        if (!priv->global_vlan_enable) {
                for (i = 0; i < MT7530_NUM_PORTS; i++)
@@ -499,9 +501,37 @@ mt7530_apply_config(struct switch_dev *dev)
        for (i = 0; i < MT7530_NUM_PORTS; i++)
                mt7530_w32(priv, REG_ESW_PORT_PCR(i), 0x00ff0003);
 
-       /* set all ports as user port */
-       for (i = 0; i < MT7530_NUM_PORTS; i++)
-               mt7530_w32(priv, REG_ESW_PORT_PVC(i), 0x81000000);
+       /* check if a port is used in tag/untag vlan egress mode */
+       tag_ports = 0;
+       untag_ports = 0;
+
+       for (i = 0; i < MT7530_NUM_VLANS; i++) {
+               u8 member = priv->vlan_entries[i].member;
+               u8 etags = priv->vlan_entries[i].etags;
+
+               if (!member)
+                       continue;
+
+               for (j = 0; j < MT7530_NUM_PORTS; j++) {
+                       if (!(member & BIT(j)))
+                               continue;
+
+                       if (etags & BIT(j))
+                               tag_ports |= 1u << j;
+                       else
+                               untag_ports |= 1u << j;
+               }
+       }
+
+       /* set all untag-only ports as transparent and the rest as user port */
+       for (i = 0; i < MT7530_NUM_PORTS; i++) {
+               u32 pvc_mode = 0x81000000;
+
+               if (untag_ports & BIT(i) && !(tag_ports & BIT(i)))
+                       pvc_mode = 0x810000c0;
+
+               mt7530_w32(priv, REG_ESW_PORT_PVC(i), pvc_mode);
+       }
 
        for (i = 0; i < MT7530_NUM_VLANS; i++) {
                u16 vid = priv->vlan_entries[i].vid;