Merge tag 'acpi-extra-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / net / dsa / mv88e6xxx / chip.c
index 1e14edebc0c7fd1bae158fd91e3c2f9e4fbce9bf..19581d783d8ec7dc9ed9e5fd5a2891e8f2d22135 100644 (file)
@@ -1255,6 +1255,15 @@ static int mv88e6xxx_vtu_getnext(struct mv88e6xxx_chip *chip,
        return chip->info->ops->vtu_getnext(chip, entry);
 }
 
+static int mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_chip *chip,
+                                  struct mv88e6xxx_vtu_entry *entry)
+{
+       if (!chip->info->ops->vtu_loadpurge)
+               return -EOPNOTSUPP;
+
+       return chip->info->ops->vtu_loadpurge(chip, entry);
+}
+
 static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
                                    struct switchdev_obj_port_vlan *vlan,
                                    int (*cb)(struct switchdev_obj *obj))
@@ -1308,53 +1317,6 @@ unlock:
        return err;
 }
 
-static int _mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_chip *chip,
-                                   struct mv88e6xxx_vtu_entry *entry)
-{
-       u16 op = GLOBAL_VTU_OP_VTU_LOAD_PURGE;
-       int err;
-
-       err = mv88e6xxx_g1_vtu_op_wait(chip);
-       if (err)
-               return err;
-
-       err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
-       if (err)
-               return err;
-
-       if (!entry->valid)
-               goto loadpurge;
-
-       /* Write port member tags */
-       err = mv88e6185_g1_vtu_data_write(chip, entry);
-       if (err)
-               return err;
-
-       if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_STU)) {
-               err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
-               if (err)
-                       return err;
-
-               err = mv88e6xxx_g1_vtu_op(chip, GLOBAL_VTU_OP_STU_LOAD_PURGE);
-               if (err)
-                       return err;
-       }
-
-       if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G1_VTU_FID)) {
-               err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
-               if (err)
-                       return err;
-       } else if (mv88e6xxx_num_databases(chip) == 256) {
-               /* VTU DBNum[7:4] are located in VTU Operation 11:8, and
-                * VTU DBNum[3:0] are located in VTU Operation 3:0
-                */
-               op |= (entry->fid & 0xf0) << 8;
-               op |= entry->fid & 0xf;
-       }
-loadpurge:
-       return mv88e6xxx_g1_vtu_op(chip, op);
-}
-
 static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid)
 {
        DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
@@ -1397,33 +1359,8 @@ static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid)
        return mv88e6xxx_g1_atu_flush(chip, *fid, true);
 }
 
-static int _mv88e6xxx_vtu_new(struct mv88e6xxx_chip *chip, u16 vid,
-                             struct mv88e6xxx_vtu_entry *entry)
-{
-       struct dsa_switch *ds = chip->ds;
-       struct mv88e6xxx_vtu_entry vlan = {
-               .valid = true,
-               .vid = vid,
-       };
-       int i, err;
-
-       err = mv88e6xxx_atu_new(chip, &vlan.fid);
-       if (err)
-               return err;
-
-       /* exclude all ports except the CPU and DSA ports */
-       for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
-               vlan.member[i] = dsa_is_cpu_port(ds, i) ||
-                       dsa_is_dsa_port(ds, i)
-                       ? GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED
-                       : GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
-
-       *entry = vlan;
-       return 0;
-}
-
-static int _mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,
-                             struct mv88e6xxx_vtu_entry *entry, bool creat)
+static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,
+                            struct mv88e6xxx_vtu_entry *entry, bool new)
 {
        int err;
 
@@ -1437,17 +1374,28 @@ static int _mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,
        if (err)
                return err;
 
-       if (entry->vid != vid || !entry->valid) {
-               if (!creat)
-                       return -EOPNOTSUPP;
-               /* -ENOENT would've been more appropriate, but switchdev expects
-                * -EOPNOTSUPP to inform bridge about an eventual software VLAN.
-                */
+       if (entry->vid == vid && entry->valid)
+               return 0;
+
+       if (new) {
+               int i;
 
-               err = _mv88e6xxx_vtu_new(chip, vid, entry);
+               /* Initialize a fresh VLAN entry */
+               memset(entry, 0, sizeof(*entry));
+               entry->valid = true;
+               entry->vid = vid;
+
+               /* Include only CPU and DSA ports */
+               for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
+                       entry->member[i] = dsa_is_normal_port(chip->ds, i) ?
+                               GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER :
+                               GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED;
+
+               return mv88e6xxx_atu_new(chip, &entry->fid);
        }
 
-       return err;
+       /* switchdev expects -EOPNOTSUPP to honor software VLANs */
+       return -EOPNOTSUPP;
 }
 
 static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
@@ -1557,7 +1505,7 @@ static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port,
        struct mv88e6xxx_vtu_entry vlan;
        int err;
 
-       err = _mv88e6xxx_vtu_get(chip, vid, &vlan, true);
+       err = mv88e6xxx_vtu_get(chip, vid, &vlan, true);
        if (err)
                return err;
 
@@ -1565,7 +1513,7 @@ static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port,
                GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED :
                GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED;
 
-       return _mv88e6xxx_vtu_loadpurge(chip, &vlan);
+       return mv88e6xxx_vtu_loadpurge(chip, &vlan);
 }
 
 static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
@@ -1602,7 +1550,7 @@ static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip,
        struct mv88e6xxx_vtu_entry vlan;
        int i, err;
 
-       err = _mv88e6xxx_vtu_get(chip, vid, &vlan, false);
+       err = mv88e6xxx_vtu_get(chip, vid, &vlan, false);
        if (err)
                return err;
 
@@ -1624,7 +1572,7 @@ static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip,
                }
        }
 
-       err = _mv88e6xxx_vtu_loadpurge(chip, &vlan);
+       err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
        if (err)
                return err;
 
@@ -1677,7 +1625,7 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
        if (vid == 0)
                err = mv88e6xxx_port_get_fid(chip, port, &vlan.fid);
        else
-               err = _mv88e6xxx_vtu_get(chip, vid, &vlan, false);
+               err = mv88e6xxx_vtu_get(chip, vid, &vlan, false);
        if (err)
                return err;
 
@@ -2669,6 +2617,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
        .ppu_disable = mv88e6185_g1_ppu_disable,
        .reset = mv88e6185_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6095_ops = {
@@ -2691,6 +2640,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
        .ppu_disable = mv88e6185_g1_ppu_disable,
        .reset = mv88e6185_g1_reset,
        .vtu_getnext = mv88e6185_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6097_ops = {
@@ -2720,6 +2670,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6123_ops = {
@@ -2744,6 +2695,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6131_ops = {
@@ -2774,6 +2726,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
        .ppu_disable = mv88e6185_g1_ppu_disable,
        .reset = mv88e6185_g1_reset,
        .vtu_getnext = mv88e6185_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6141_ops = {
@@ -2806,6 +2759,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
        .mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6161_ops = {
@@ -2835,6 +2789,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6165_ops = {
@@ -2857,6 +2812,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6171_ops = {
@@ -2887,6 +2843,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6172_ops = {
@@ -2919,6 +2876,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6175_ops = {
@@ -2949,6 +2907,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6176_ops = {
@@ -2981,6 +2940,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6185_ops = {
@@ -3007,6 +2967,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
        .ppu_disable = mv88e6185_g1_ppu_disable,
        .reset = mv88e6185_g1_reset,
        .vtu_getnext = mv88e6185_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6190_ops = {
@@ -3037,6 +2998,8 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
+       .vtu_getnext = mv88e6390_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6190x_ops = {
@@ -3067,6 +3030,8 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
+       .vtu_getnext = mv88e6390_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6191_ops = {
@@ -3097,6 +3062,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
+       .vtu_getnext = mv88e6390_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6240_ops = {
@@ -3129,6 +3096,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6290_ops = {
@@ -3160,6 +3128,8 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
+       .vtu_getnext = mv88e6390_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6320_ops = {
@@ -3190,6 +3160,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6185_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6321_ops = {
@@ -3219,6 +3190,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
        .g1_set_egress_port = mv88e6095_g1_set_egress_port,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6185_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6341_ops = {
@@ -3251,6 +3223,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
        .mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6350_ops = {
@@ -3281,6 +3254,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6351_ops = {
@@ -3311,6 +3285,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6352_ops = {
@@ -3343,6 +3318,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6390_ops = {
@@ -3376,6 +3352,8 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
+       .vtu_getnext = mv88e6390_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_ops mv88e6390x_ops = {
@@ -3408,6 +3386,8 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
+       .vtu_getnext = mv88e6390_g1_vtu_getnext,
+       .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
 };
 
 static const struct mv88e6xxx_info mv88e6xxx_table[] = {
@@ -3647,6 +3627,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .name = "Marvell 88E6190",
                .num_databases = 4096,
                .num_ports = 11,        /* 10 + Z80 */
+               .max_vid = 8191,
                .port_base_addr = 0x0,
                .global1_addr = 0x1b,
                .tag_protocol = DSA_TAG_PROTO_DSA,
@@ -3664,6 +3645,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .name = "Marvell 88E6190X",
                .num_databases = 4096,
                .num_ports = 11,        /* 10 + Z80 */
+               .max_vid = 8191,
                .port_base_addr = 0x0,
                .global1_addr = 0x1b,
                .age_time_coeff = 3750,
@@ -3681,6 +3663,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .name = "Marvell 88E6191",
                .num_databases = 4096,
                .num_ports = 11,        /* 10 + Z80 */
+               .max_vid = 8191,
                .port_base_addr = 0x0,
                .global1_addr = 0x1b,
                .age_time_coeff = 3750,
@@ -3716,6 +3699,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .name = "Marvell 88E6290",
                .num_databases = 4096,
                .num_ports = 11,        /* 10 + Z80 */
+               .max_vid = 8191,
                .port_base_addr = 0x0,
                .global1_addr = 0x1b,
                .age_time_coeff = 3750,
@@ -3838,6 +3822,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .name = "Marvell 88E6390",
                .num_databases = 4096,
                .num_ports = 11,        /* 10 + Z80 */
+               .max_vid = 8191,
                .port_base_addr = 0x0,
                .global1_addr = 0x1b,
                .age_time_coeff = 3750,
@@ -3854,6 +3839,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .name = "Marvell 88E6390X",
                .num_databases = 4096,
                .num_ports = 11,        /* 10 + Z80 */
+               .max_vid = 8191,
                .port_base_addr = 0x0,
                .global1_addr = 0x1b,
                .age_time_coeff = 3750,