|
@@ -3,9 +3,6 @@
|
|
|
*
|
|
|
* Copyright (c) 2008 Marvell Semiconductor
|
|
|
*
|
|
|
- * Copyright (c) 2015 CMC Electronics, Inc.
|
|
|
- * Added support for VLAN Table Unit operations
|
|
|
- *
|
|
|
* Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
|
|
|
*
|
|
|
* Copyright (c) 2016-2017 Savoir-faire Linux Inc.
|
|
@@ -680,31 +677,6 @@ static int mv88e6xxx_phy_ppu_write(struct mv88e6xxx_chip *chip,
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static bool mv88e6xxx_6097_family(struct mv88e6xxx_chip *chip)
|
|
|
-{
|
|
|
- return chip->info->family == MV88E6XXX_FAMILY_6097;
|
|
|
-}
|
|
|
-
|
|
|
-static bool mv88e6xxx_6165_family(struct mv88e6xxx_chip *chip)
|
|
|
-{
|
|
|
- return chip->info->family == MV88E6XXX_FAMILY_6165;
|
|
|
-}
|
|
|
-
|
|
|
-static bool mv88e6xxx_6341_family(struct mv88e6xxx_chip *chip)
|
|
|
-{
|
|
|
- return chip->info->family == MV88E6XXX_FAMILY_6341;
|
|
|
-}
|
|
|
-
|
|
|
-static bool mv88e6xxx_6351_family(struct mv88e6xxx_chip *chip)
|
|
|
-{
|
|
|
- return chip->info->family == MV88E6XXX_FAMILY_6351;
|
|
|
-}
|
|
|
-
|
|
|
-static bool mv88e6xxx_6352_family(struct mv88e6xxx_chip *chip)
|
|
|
-{
|
|
|
- return chip->info->family == MV88E6XXX_FAMILY_6352;
|
|
|
-}
|
|
|
-
|
|
|
static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
|
|
|
int link, int speed, int duplex,
|
|
|
phy_interface_t mode)
|
|
@@ -1266,169 +1238,30 @@ static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
|
|
|
netdev_err(ds->ports[port].netdev, "failed to flush ATU\n");
|
|
|
}
|
|
|
|
|
|
-static int _mv88e6xxx_vtu_wait(struct mv88e6xxx_chip *chip)
|
|
|
-{
|
|
|
- return mv88e6xxx_g1_wait(chip, GLOBAL_VTU_OP, GLOBAL_VTU_OP_BUSY);
|
|
|
-}
|
|
|
-
|
|
|
-static int _mv88e6xxx_vtu_cmd(struct mv88e6xxx_chip *chip, u16 op)
|
|
|
+static int mv88e6xxx_vtu_setup(struct mv88e6xxx_chip *chip)
|
|
|
{
|
|
|
- int err;
|
|
|
-
|
|
|
- err = mv88e6xxx_g1_write(chip, GLOBAL_VTU_OP, op);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- return _mv88e6xxx_vtu_wait(chip);
|
|
|
-}
|
|
|
-
|
|
|
-static int _mv88e6xxx_vtu_stu_flush(struct mv88e6xxx_chip *chip)
|
|
|
-{
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = _mv88e6xxx_vtu_wait(chip);
|
|
|
- if (ret < 0)
|
|
|
- return ret;
|
|
|
+ if (!chip->info->max_vid)
|
|
|
+ return 0;
|
|
|
|
|
|
- return _mv88e6xxx_vtu_cmd(chip, GLOBAL_VTU_OP_FLUSH_ALL);
|
|
|
+ return mv88e6xxx_g1_vtu_flush(chip);
|
|
|
}
|
|
|
|
|
|
-static int _mv88e6xxx_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
|
|
|
- struct mv88e6xxx_vtu_entry *entry,
|
|
|
- unsigned int nibble_offset)
|
|
|
+static int mv88e6xxx_vtu_getnext(struct mv88e6xxx_chip *chip,
|
|
|
+ struct mv88e6xxx_vtu_entry *entry)
|
|
|
{
|
|
|
- u16 regs[3];
|
|
|
- int i, err;
|
|
|
-
|
|
|
- for (i = 0; i < 3; ++i) {
|
|
|
- u16 *reg = ®s[i];
|
|
|
-
|
|
|
- err = mv88e6xxx_g1_read(chip, GLOBAL_VTU_DATA_0_3 + i, reg);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
- }
|
|
|
-
|
|
|
- for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
|
|
|
- unsigned int shift = (i % 4) * 4 + nibble_offset;
|
|
|
- u16 reg = regs[i / 4];
|
|
|
-
|
|
|
- entry->data[i] = (reg >> shift) & GLOBAL_VTU_STU_DATA_MASK;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
+ if (!chip->info->ops->vtu_getnext)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
|
|
|
-static int mv88e6xxx_vtu_data_read(struct mv88e6xxx_chip *chip,
|
|
|
- struct mv88e6xxx_vtu_entry *entry)
|
|
|
-{
|
|
|
- return _mv88e6xxx_vtu_stu_data_read(chip, entry, 0);
|
|
|
+ return chip->info->ops->vtu_getnext(chip, entry);
|
|
|
}
|
|
|
|
|
|
-static int mv88e6xxx_stu_data_read(struct mv88e6xxx_chip *chip,
|
|
|
+static int mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_chip *chip,
|
|
|
struct mv88e6xxx_vtu_entry *entry)
|
|
|
{
|
|
|
- return _mv88e6xxx_vtu_stu_data_read(chip, entry, 2);
|
|
|
-}
|
|
|
-
|
|
|
-static int _mv88e6xxx_vtu_stu_data_write(struct mv88e6xxx_chip *chip,
|
|
|
- struct mv88e6xxx_vtu_entry *entry,
|
|
|
- unsigned int nibble_offset)
|
|
|
-{
|
|
|
- u16 regs[3] = { 0 };
|
|
|
- int i, err;
|
|
|
-
|
|
|
- for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
|
|
|
- unsigned int shift = (i % 4) * 4 + nibble_offset;
|
|
|
- u8 data = entry->data[i];
|
|
|
-
|
|
|
- regs[i / 4] |= (data & GLOBAL_VTU_STU_DATA_MASK) << shift;
|
|
|
- }
|
|
|
-
|
|
|
- for (i = 0; i < 3; ++i) {
|
|
|
- u16 reg = regs[i];
|
|
|
-
|
|
|
- err = mv88e6xxx_g1_write(chip, GLOBAL_VTU_DATA_0_3 + i, reg);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int mv88e6xxx_vtu_data_write(struct mv88e6xxx_chip *chip,
|
|
|
- struct mv88e6xxx_vtu_entry *entry)
|
|
|
-{
|
|
|
- return _mv88e6xxx_vtu_stu_data_write(chip, entry, 0);
|
|
|
-}
|
|
|
-
|
|
|
-static int mv88e6xxx_stu_data_write(struct mv88e6xxx_chip *chip,
|
|
|
- struct mv88e6xxx_vtu_entry *entry)
|
|
|
-{
|
|
|
- return _mv88e6xxx_vtu_stu_data_write(chip, entry, 2);
|
|
|
-}
|
|
|
-
|
|
|
-static int _mv88e6xxx_vtu_vid_write(struct mv88e6xxx_chip *chip, u16 vid)
|
|
|
-{
|
|
|
- return mv88e6xxx_g1_write(chip, GLOBAL_VTU_VID,
|
|
|
- vid & GLOBAL_VTU_VID_MASK);
|
|
|
-}
|
|
|
-
|
|
|
-static int _mv88e6xxx_vtu_getnext(struct mv88e6xxx_chip *chip,
|
|
|
- struct mv88e6xxx_vtu_entry *entry)
|
|
|
-{
|
|
|
- struct mv88e6xxx_vtu_entry next = { 0 };
|
|
|
- u16 val;
|
|
|
- int err;
|
|
|
-
|
|
|
- err = _mv88e6xxx_vtu_wait(chip);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- err = _mv88e6xxx_vtu_cmd(chip, GLOBAL_VTU_OP_VTU_GET_NEXT);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- err = mv88e6xxx_g1_read(chip, GLOBAL_VTU_VID, &val);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- next.vid = val & GLOBAL_VTU_VID_MASK;
|
|
|
- next.valid = !!(val & GLOBAL_VTU_VID_VALID);
|
|
|
-
|
|
|
- if (next.valid) {
|
|
|
- err = mv88e6xxx_vtu_data_read(chip, &next);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G1_VTU_FID)) {
|
|
|
- err = mv88e6xxx_g1_read(chip, GLOBAL_VTU_FID, &val);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- next.fid = val & GLOBAL_VTU_FID_MASK;
|
|
|
- } 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
|
|
|
- */
|
|
|
- err = mv88e6xxx_g1_read(chip, GLOBAL_VTU_OP, &val);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- next.fid = (val & 0xf00) >> 4;
|
|
|
- next.fid |= val & 0xf;
|
|
|
- }
|
|
|
-
|
|
|
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_STU)) {
|
|
|
- err = mv88e6xxx_g1_read(chip, GLOBAL_VTU_SID, &val);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- next.sid = val & GLOBAL_VTU_SID_MASK;
|
|
|
- }
|
|
|
- }
|
|
|
+ if (!chip->info->ops->vtu_loadpurge)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
|
|
|
- *entry = next;
|
|
|
- return 0;
|
|
|
+ return chip->info->ops->vtu_loadpurge(chip, entry);
|
|
|
}
|
|
|
|
|
|
static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
|
|
@@ -1436,11 +1269,13 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
|
|
|
int (*cb)(struct switchdev_obj *obj))
|
|
|
{
|
|
|
struct mv88e6xxx_chip *chip = ds->priv;
|
|
|
- struct mv88e6xxx_vtu_entry next;
|
|
|
+ struct mv88e6xxx_vtu_entry next = {
|
|
|
+ .vid = chip->info->max_vid,
|
|
|
+ };
|
|
|
u16 pvid;
|
|
|
int err;
|
|
|
|
|
|
- if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_VTU))
|
|
|
+ if (!chip->info->max_vid)
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
mutex_lock(&chip->reg_lock);
|
|
@@ -1449,19 +1284,15 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
|
|
|
if (err)
|
|
|
goto unlock;
|
|
|
|
|
|
- err = _mv88e6xxx_vtu_vid_write(chip, GLOBAL_VTU_VID_MASK);
|
|
|
- if (err)
|
|
|
- goto unlock;
|
|
|
-
|
|
|
do {
|
|
|
- err = _mv88e6xxx_vtu_getnext(chip, &next);
|
|
|
+ err = mv88e6xxx_vtu_getnext(chip, &next);
|
|
|
if (err)
|
|
|
break;
|
|
|
|
|
|
if (!next.valid)
|
|
|
break;
|
|
|
|
|
|
- if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
|
|
|
+ if (next.member[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
|
|
|
continue;
|
|
|
|
|
|
/* reinit and dump this VLAN obj */
|
|
@@ -1469,7 +1300,7 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
|
|
|
vlan->vid_end = next.vid;
|
|
|
vlan->flags = 0;
|
|
|
|
|
|
- if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED)
|
|
|
+ if (next.member[port] == GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED)
|
|
|
vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
|
|
|
|
|
|
if (next.vid == pvid)
|
|
@@ -1478,7 +1309,7 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
|
|
|
err = cb(&vlan->obj);
|
|
|
if (err)
|
|
|
break;
|
|
|
- } while (next.vid < GLOBAL_VTU_VID_MASK);
|
|
|
+ } while (next.vid < chip->info->max_vid);
|
|
|
|
|
|
unlock:
|
|
|
mutex_unlock(&chip->reg_lock);
|
|
@@ -1486,133 +1317,12 @@ 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;
|
|
|
- u16 reg = 0;
|
|
|
- int err;
|
|
|
-
|
|
|
- err = _mv88e6xxx_vtu_wait(chip);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- if (!entry->valid)
|
|
|
- goto loadpurge;
|
|
|
-
|
|
|
- /* Write port member tags */
|
|
|
- err = mv88e6xxx_vtu_data_write(chip, entry);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_STU)) {
|
|
|
- reg = entry->sid & GLOBAL_VTU_SID_MASK;
|
|
|
- err = mv88e6xxx_g1_write(chip, GLOBAL_VTU_SID, reg);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
- }
|
|
|
-
|
|
|
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G1_VTU_FID)) {
|
|
|
- reg = entry->fid & GLOBAL_VTU_FID_MASK;
|
|
|
- err = mv88e6xxx_g1_write(chip, GLOBAL_VTU_FID, reg);
|
|
|
- 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;
|
|
|
- }
|
|
|
-
|
|
|
- reg = GLOBAL_VTU_VID_VALID;
|
|
|
-loadpurge:
|
|
|
- reg |= entry->vid & GLOBAL_VTU_VID_MASK;
|
|
|
- err = mv88e6xxx_g1_write(chip, GLOBAL_VTU_VID, reg);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- return _mv88e6xxx_vtu_cmd(chip, op);
|
|
|
-}
|
|
|
-
|
|
|
-static int _mv88e6xxx_stu_getnext(struct mv88e6xxx_chip *chip, u8 sid,
|
|
|
- struct mv88e6xxx_vtu_entry *entry)
|
|
|
-{
|
|
|
- struct mv88e6xxx_vtu_entry next = { 0 };
|
|
|
- u16 val;
|
|
|
- int err;
|
|
|
-
|
|
|
- err = _mv88e6xxx_vtu_wait(chip);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- err = mv88e6xxx_g1_write(chip, GLOBAL_VTU_SID,
|
|
|
- sid & GLOBAL_VTU_SID_MASK);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- err = _mv88e6xxx_vtu_cmd(chip, GLOBAL_VTU_OP_STU_GET_NEXT);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- err = mv88e6xxx_g1_read(chip, GLOBAL_VTU_SID, &val);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- next.sid = val & GLOBAL_VTU_SID_MASK;
|
|
|
-
|
|
|
- err = mv88e6xxx_g1_read(chip, GLOBAL_VTU_VID, &val);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- next.valid = !!(val & GLOBAL_VTU_VID_VALID);
|
|
|
-
|
|
|
- if (next.valid) {
|
|
|
- err = mv88e6xxx_stu_data_read(chip, &next);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
- }
|
|
|
-
|
|
|
- *entry = next;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int _mv88e6xxx_stu_loadpurge(struct mv88e6xxx_chip *chip,
|
|
|
- struct mv88e6xxx_vtu_entry *entry)
|
|
|
-{
|
|
|
- u16 reg = 0;
|
|
|
- int err;
|
|
|
-
|
|
|
- err = _mv88e6xxx_vtu_wait(chip);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- if (!entry->valid)
|
|
|
- goto loadpurge;
|
|
|
-
|
|
|
- /* Write port states */
|
|
|
- err = mv88e6xxx_stu_data_write(chip, entry);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- reg = GLOBAL_VTU_VID_VALID;
|
|
|
-loadpurge:
|
|
|
- err = mv88e6xxx_g1_write(chip, GLOBAL_VTU_VID, reg);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- reg = entry->sid & GLOBAL_VTU_SID_MASK;
|
|
|
- err = mv88e6xxx_g1_write(chip, GLOBAL_VTU_SID, reg);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- return _mv88e6xxx_vtu_cmd(chip, GLOBAL_VTU_OP_STU_LOAD_PURGE);
|
|
|
-}
|
|
|
-
|
|
|
static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid)
|
|
|
{
|
|
|
DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
|
|
|
- struct mv88e6xxx_vtu_entry vlan;
|
|
|
+ struct mv88e6xxx_vtu_entry vlan = {
|
|
|
+ .vid = chip->info->max_vid,
|
|
|
+ };
|
|
|
int i, err;
|
|
|
|
|
|
bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);
|
|
@@ -1627,12 +1337,8 @@ static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid)
|
|
|
}
|
|
|
|
|
|
/* Set every FID bit used by the VLAN entries */
|
|
|
- err = _mv88e6xxx_vtu_vid_write(chip, GLOBAL_VTU_VID_MASK);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
do {
|
|
|
- err = _mv88e6xxx_vtu_getnext(chip, &vlan);
|
|
|
+ err = mv88e6xxx_vtu_getnext(chip, &vlan);
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
@@ -1640,7 +1346,7 @@ static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid)
|
|
|
break;
|
|
|
|
|
|
set_bit(vlan.fid, fid_bitmap);
|
|
|
- } while (vlan.vid < GLOBAL_VTU_VID_MASK);
|
|
|
+ } while (vlan.vid < chip->info->max_vid);
|
|
|
|
|
|
/* The reset value 0x000 is used to indicate that multiple address
|
|
|
* databases are not needed. Return the next positive available.
|
|
@@ -1653,89 +1359,52 @@ 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.data[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;
|
|
|
-
|
|
|
- if (mv88e6xxx_6097_family(chip) || mv88e6xxx_6165_family(chip) ||
|
|
|
- mv88e6xxx_6351_family(chip) || mv88e6xxx_6352_family(chip) ||
|
|
|
- mv88e6xxx_6341_family(chip)) {
|
|
|
- struct mv88e6xxx_vtu_entry vstp;
|
|
|
-
|
|
|
- /* Adding a VTU entry requires a valid STU entry. As VSTP is not
|
|
|
- * implemented, only one STU entry is needed to cover all VTU
|
|
|
- * entries. Thus, validate the SID 0.
|
|
|
- */
|
|
|
- vlan.sid = 0;
|
|
|
- err = _mv88e6xxx_stu_getnext(chip, GLOBAL_VTU_SID_MASK, &vstp);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- if (vstp.sid != vlan.sid || !vstp.valid) {
|
|
|
- memset(&vstp, 0, sizeof(vstp));
|
|
|
- vstp.valid = true;
|
|
|
- vstp.sid = vlan.sid;
|
|
|
-
|
|
|
- err = _mv88e6xxx_stu_loadpurge(chip, &vstp);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- *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;
|
|
|
|
|
|
if (!vid)
|
|
|
return -EINVAL;
|
|
|
|
|
|
- err = _mv88e6xxx_vtu_vid_write(chip, vid - 1);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
+ entry->vid = vid - 1;
|
|
|
+ entry->valid = false;
|
|
|
|
|
|
- err = _mv88e6xxx_vtu_getnext(chip, entry);
|
|
|
+ err = mv88e6xxx_vtu_getnext(chip, entry);
|
|
|
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,
|
|
|
u16 vid_begin, u16 vid_end)
|
|
|
{
|
|
|
struct mv88e6xxx_chip *chip = ds->priv;
|
|
|
- struct mv88e6xxx_vtu_entry vlan;
|
|
|
+ struct mv88e6xxx_vtu_entry vlan = {
|
|
|
+ .vid = vid_begin - 1,
|
|
|
+ };
|
|
|
int i, err;
|
|
|
|
|
|
if (!vid_begin)
|
|
@@ -1743,12 +1412,8 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
|
|
|
|
|
|
mutex_lock(&chip->reg_lock);
|
|
|
|
|
|
- err = _mv88e6xxx_vtu_vid_write(chip, vid_begin - 1);
|
|
|
- if (err)
|
|
|
- goto unlock;
|
|
|
-
|
|
|
do {
|
|
|
- err = _mv88e6xxx_vtu_getnext(chip, &vlan);
|
|
|
+ err = mv88e6xxx_vtu_getnext(chip, &vlan);
|
|
|
if (err)
|
|
|
goto unlock;
|
|
|
|
|
@@ -1765,7 +1430,7 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
|
|
|
if (!ds->ports[port].netdev)
|
|
|
continue;
|
|
|
|
|
|
- if (vlan.data[i] ==
|
|
|
+ if (vlan.member[i] ==
|
|
|
GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
|
|
|
continue;
|
|
|
|
|
@@ -1799,7 +1464,7 @@ static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
|
|
|
PORT_CONTROL_2_8021Q_DISABLED;
|
|
|
int err;
|
|
|
|
|
|
- if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_VTU))
|
|
|
+ if (!chip->info->max_vid)
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
mutex_lock(&chip->reg_lock);
|
|
@@ -1817,7 +1482,7 @@ mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
|
|
|
struct mv88e6xxx_chip *chip = ds->priv;
|
|
|
int err;
|
|
|
|
|
|
- if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_VTU))
|
|
|
+ if (!chip->info->max_vid)
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
/* If the requested port doesn't belong to the same bridge as the VLAN
|
|
@@ -1840,15 +1505,15 @@ 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;
|
|
|
|
|
|
- vlan.data[port] = untagged ?
|
|
|
+ vlan.member[port] = untagged ?
|
|
|
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,
|
|
@@ -1860,7 +1525,7 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
|
|
|
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
|
|
|
u16 vid;
|
|
|
|
|
|
- if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_VTU))
|
|
|
+ if (!chip->info->max_vid)
|
|
|
return;
|
|
|
|
|
|
mutex_lock(&chip->reg_lock);
|
|
@@ -1885,15 +1550,15 @@ 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;
|
|
|
|
|
|
/* Tell switchdev if this VLAN is handled in software */
|
|
|
- if (vlan.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
|
|
|
+ if (vlan.member[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
- vlan.data[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
|
|
|
+ vlan.member[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
|
|
|
|
|
|
/* keep the VLAN unless all ports are excluded */
|
|
|
vlan.valid = false;
|
|
@@ -1901,13 +1566,13 @@ static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip,
|
|
|
if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
|
|
|
continue;
|
|
|
|
|
|
- if (vlan.data[i] != GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
|
|
|
+ if (vlan.member[i] != GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
|
|
|
vlan.valid = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- err = _mv88e6xxx_vtu_loadpurge(chip, &vlan);
|
|
|
+ err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
@@ -1921,7 +1586,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
|
|
|
u16 pvid, vid;
|
|
|
int err = 0;
|
|
|
|
|
|
- if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_VTU))
|
|
|
+ if (!chip->info->max_vid)
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
mutex_lock(&chip->reg_lock);
|
|
@@ -1960,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;
|
|
|
|
|
@@ -2090,7 +1755,7 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
|
|
|
int (*cb)(struct switchdev_obj *obj))
|
|
|
{
|
|
|
struct mv88e6xxx_vtu_entry vlan = {
|
|
|
- .vid = GLOBAL_VTU_VID_MASK, /* all ones */
|
|
|
+ .vid = chip->info->max_vid,
|
|
|
};
|
|
|
u16 fid;
|
|
|
int err;
|
|
@@ -2105,12 +1770,8 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
|
|
|
return err;
|
|
|
|
|
|
/* Dump VLANs' Filtering Information Databases */
|
|
|
- err = _mv88e6xxx_vtu_vid_write(chip, vlan.vid);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
do {
|
|
|
- err = _mv88e6xxx_vtu_getnext(chip, &vlan);
|
|
|
+ err = mv88e6xxx_vtu_getnext(chip, &vlan);
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
@@ -2121,7 +1782,7 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
|
|
|
obj, cb);
|
|
|
if (err)
|
|
|
return err;
|
|
|
- } while (vlan.vid < GLOBAL_VTU_VID_MASK);
|
|
|
+ } while (vlan.vid < chip->info->max_vid);
|
|
|
|
|
|
return err;
|
|
|
}
|
|
@@ -2617,11 +2278,6 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
|
- /* Clear all the VTU and STU entries */
|
|
|
- err = _mv88e6xxx_vtu_stu_flush(chip);
|
|
|
- if (err < 0)
|
|
|
- return err;
|
|
|
-
|
|
|
/* Configure the IP ToS mapping registers. */
|
|
|
err = mv88e6xxx_g1_write(chip, GLOBAL_IP_PRI_0, 0x0000);
|
|
|
if (err)
|
|
@@ -2702,6 +2358,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
|
|
|
goto unlock;
|
|
|
}
|
|
|
|
|
|
+ err = mv88e6xxx_vtu_setup(chip);
|
|
|
+ if (err)
|
|
|
+ goto unlock;
|
|
|
+
|
|
|
err = mv88e6xxx_pvt_setup(chip);
|
|
|
if (err)
|
|
|
goto unlock;
|
|
@@ -2956,6 +2616,8 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
|
|
|
.ppu_enable = mv88e6185_g1_ppu_enable,
|
|
|
.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 = {
|
|
@@ -2977,6 +2639,8 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
|
|
|
.ppu_enable = mv88e6185_g1_ppu_enable,
|
|
|
.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 = {
|
|
@@ -3005,6 +2669,8 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
|
|
|
.watchdog_ops = &mv88e6097_watchdog_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 = {
|
|
@@ -3028,6 +2694,8 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
|
|
|
.watchdog_ops = &mv88e6097_watchdog_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 = {
|
|
@@ -3057,6 +2725,8 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
|
|
|
.ppu_enable = mv88e6185_g1_ppu_enable,
|
|
|
.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 = {
|
|
@@ -3088,6 +2758,8 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
|
|
|
.watchdog_ops = &mv88e6390_watchdog_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 = {
|
|
@@ -3116,6 +2788,8 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
|
|
|
.watchdog_ops = &mv88e6097_watchdog_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 = {
|
|
@@ -3137,6 +2811,8 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
|
|
|
.watchdog_ops = &mv88e6097_watchdog_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 = {
|
|
@@ -3166,6 +2842,8 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
|
|
|
.watchdog_ops = &mv88e6097_watchdog_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 = {
|
|
@@ -3197,6 +2875,8 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
|
|
|
.watchdog_ops = &mv88e6097_watchdog_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 = {
|
|
@@ -3226,6 +2906,8 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
|
|
|
.watchdog_ops = &mv88e6097_watchdog_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 = {
|
|
@@ -3257,6 +2939,8 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
|
|
|
.watchdog_ops = &mv88e6097_watchdog_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 = {
|
|
@@ -3282,6 +2966,8 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
|
|
|
.ppu_enable = mv88e6185_g1_ppu_enable,
|
|
|
.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 = {
|
|
@@ -3312,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 = {
|
|
@@ -3342,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 = {
|
|
@@ -3372,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 = {
|
|
@@ -3403,6 +3095,8 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
|
|
|
.watchdog_ops = &mv88e6097_watchdog_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 = {
|
|
@@ -3434,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 = {
|
|
@@ -3463,6 +3159,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
|
|
|
.g1_set_egress_port = mv88e6095_g1_set_egress_port,
|
|
|
.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 = {
|
|
@@ -3491,6 +3189,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
|
|
|
.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
|
|
|
.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 = {
|
|
@@ -3522,6 +3222,8 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
|
|
|
.watchdog_ops = &mv88e6390_watchdog_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 = {
|
|
@@ -3551,6 +3253,8 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
|
|
|
.watchdog_ops = &mv88e6097_watchdog_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 = {
|
|
@@ -3580,6 +3284,8 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
|
|
|
.watchdog_ops = &mv88e6097_watchdog_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 = {
|
|
@@ -3611,6 +3317,8 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
|
|
|
.watchdog_ops = &mv88e6097_watchdog_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 = {
|
|
@@ -3644,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 = {
|
|
@@ -3676,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[] = {
|
|
@@ -3685,6 +3397,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6085",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 10,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -3702,6 +3415,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6095/88E6095F",
|
|
|
.num_databases = 256,
|
|
|
.num_ports = 11,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -3718,6 +3432,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6097/88E6097F",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 11,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -3735,6 +3450,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6123",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 3,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -3752,6 +3468,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6131",
|
|
|
.num_databases = 256,
|
|
|
.num_ports = 8,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -3768,6 +3485,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6341",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 6,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 3750,
|
|
@@ -3784,6 +3502,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6161",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 6,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -3801,6 +3520,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6165",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 6,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -3818,6 +3538,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6171",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 7,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -3835,6 +3556,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6172",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 7,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -3852,6 +3574,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6175",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 7,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -3869,6 +3592,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6176",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 7,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -3886,6 +3610,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6185",
|
|
|
.num_databases = 256,
|
|
|
.num_ports = 10,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -3902,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,
|
|
@@ -3919,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,
|
|
@@ -3936,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,
|
|
@@ -3953,6 +3681,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6240",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 7,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -3970,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,
|
|
@@ -3987,6 +3717,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6320",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 7,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -4004,6 +3735,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6321",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 7,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -4020,6 +3752,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6341",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 6,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 3750,
|
|
@@ -4036,6 +3769,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6350",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 7,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -4053,6 +3787,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6351",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 7,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -4070,6 +3805,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.name = "Marvell 88E6352",
|
|
|
.num_databases = 4096,
|
|
|
.num_ports = 7,
|
|
|
+ .max_vid = 4095,
|
|
|
.port_base_addr = 0x10,
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 15000,
|
|
@@ -4086,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,
|
|
@@ -4102,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,
|