|
@@ -1123,27 +1123,42 @@ out:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port)
|
|
|
+static u16 mv88e6xxx_port_vlan(struct mv88e6xxx_chip *chip, int dev, int port)
|
|
|
{
|
|
|
- struct dsa_switch *ds = chip->ds;
|
|
|
- struct net_device *bridge = ds->ports[port].bridge_dev;
|
|
|
- u16 output_ports = 0;
|
|
|
+ struct dsa_switch *ds = NULL;
|
|
|
+ struct net_device *br;
|
|
|
+ u16 pvlan;
|
|
|
int i;
|
|
|
|
|
|
- /* allow CPU port or DSA link(s) to send frames to every port */
|
|
|
- if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
|
|
|
- output_ports = ~0;
|
|
|
- } else {
|
|
|
- for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
|
|
|
- /* allow sending frames to every group member */
|
|
|
- if (bridge && ds->ports[i].bridge_dev == bridge)
|
|
|
- output_ports |= BIT(i);
|
|
|
+ if (dev < DSA_MAX_SWITCHES)
|
|
|
+ ds = chip->ds->dst->ds[dev];
|
|
|
|
|
|
- /* allow sending frames to CPU port and DSA link(s) */
|
|
|
- if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
|
|
|
- output_ports |= BIT(i);
|
|
|
- }
|
|
|
- }
|
|
|
+ /* Prevent frames from unknown switch or port */
|
|
|
+ if (!ds || port >= ds->num_ports)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* Frames from DSA links and CPU ports can egress any local port */
|
|
|
+ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
|
|
|
+ return mv88e6xxx_port_mask(chip);
|
|
|
+
|
|
|
+ br = ds->ports[port].bridge_dev;
|
|
|
+ pvlan = 0;
|
|
|
+
|
|
|
+ /* Frames from user ports can egress any local DSA links and CPU ports,
|
|
|
+ * as well as any local member of their bridge group.
|
|
|
+ */
|
|
|
+ for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
|
|
|
+ if (dsa_is_cpu_port(chip->ds, i) ||
|
|
|
+ dsa_is_dsa_port(chip->ds, i) ||
|
|
|
+ (br && chip->ds->ports[i].bridge_dev == br))
|
|
|
+ pvlan |= BIT(i);
|
|
|
+
|
|
|
+ return pvlan;
|
|
|
+}
|
|
|
+
|
|
|
+static int mv88e6xxx_port_vlan_map(struct mv88e6xxx_chip *chip, int port)
|
|
|
+{
|
|
|
+ u16 output_ports = mv88e6xxx_port_vlan(chip, chip->ds->index, port);
|
|
|
|
|
|
/* prevent frames from going back out of the port they came in on */
|
|
|
output_ports &= ~BIT(port);
|
|
@@ -1198,6 +1213,46 @@ static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip)
|
|
|
return mv88e6xxx_g1_atu_set_age_time(chip, 300000);
|
|
|
}
|
|
|
|
|
|
+static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port)
|
|
|
+{
|
|
|
+ u16 pvlan = 0;
|
|
|
+
|
|
|
+ if (!mv88e6xxx_has_pvt(chip))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ /* Skip the local source device, which uses in-chip port VLAN */
|
|
|
+ if (dev != chip->ds->index)
|
|
|
+ pvlan = mv88e6xxx_port_vlan(chip, dev, port);
|
|
|
+
|
|
|
+ return mv88e6xxx_g2_pvt_write(chip, dev, port, pvlan);
|
|
|
+}
|
|
|
+
|
|
|
+static int mv88e6xxx_pvt_setup(struct mv88e6xxx_chip *chip)
|
|
|
+{
|
|
|
+ int dev, port;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ if (!mv88e6xxx_has_pvt(chip))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* Clear 5 Bit Port for usage with Marvell Link Street devices:
|
|
|
+ * use 4 bits for the Src_Port/Src_Trunk and 5 bits for the Src_Dev.
|
|
|
+ */
|
|
|
+ err = mv88e6xxx_g2_misc_4_bit_port(chip);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ for (dev = 0; dev < MV88E6XXX_MAX_PVT_SWITCHES; ++dev) {
|
|
|
+ for (port = 0; port < MV88E6XXX_MAX_PVT_PORTS; ++port) {
|
|
|
+ err = mv88e6xxx_pvt_map(chip, dev, port);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
|
|
|
{
|
|
|
struct mv88e6xxx_chip *chip = ds->priv;
|
|
@@ -2085,23 +2140,52 @@ static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
|
|
|
- struct net_device *br)
|
|
|
+static int mv88e6xxx_bridge_map(struct mv88e6xxx_chip *chip,
|
|
|
+ struct net_device *br)
|
|
|
{
|
|
|
- struct mv88e6xxx_chip *chip = ds->priv;
|
|
|
- int i, err = 0;
|
|
|
-
|
|
|
- mutex_lock(&chip->reg_lock);
|
|
|
+ struct dsa_switch *ds;
|
|
|
+ int port;
|
|
|
+ int dev;
|
|
|
+ int err;
|
|
|
|
|
|
- /* Remap each port's VLANTable */
|
|
|
- for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
|
|
|
- if (ds->ports[i].bridge_dev == br) {
|
|
|
- err = _mv88e6xxx_port_based_vlan_map(chip, i);
|
|
|
+ /* Remap the Port VLAN of each local bridge group member */
|
|
|
+ for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) {
|
|
|
+ if (chip->ds->ports[port].bridge_dev == br) {
|
|
|
+ err = mv88e6xxx_port_vlan_map(chip, port);
|
|
|
if (err)
|
|
|
- break;
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!mv88e6xxx_has_pvt(chip))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* Remap the Port VLAN of each cross-chip bridge group member */
|
|
|
+ for (dev = 0; dev < DSA_MAX_SWITCHES; ++dev) {
|
|
|
+ ds = chip->ds->dst->ds[dev];
|
|
|
+ if (!ds)
|
|
|
+ break;
|
|
|
+
|
|
|
+ for (port = 0; port < ds->num_ports; ++port) {
|
|
|
+ if (ds->ports[port].bridge_dev == br) {
|
|
|
+ err = mv88e6xxx_pvt_map(chip, dev, port);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
|
|
|
+ struct net_device *br)
|
|
|
+{
|
|
|
+ struct mv88e6xxx_chip *chip = ds->priv;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ mutex_lock(&chip->reg_lock);
|
|
|
+ err = mv88e6xxx_bridge_map(chip, br);
|
|
|
mutex_unlock(&chip->reg_lock);
|
|
|
|
|
|
return err;
|
|
@@ -2111,17 +2195,41 @@ static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port,
|
|
|
struct net_device *br)
|
|
|
{
|
|
|
struct mv88e6xxx_chip *chip = ds->priv;
|
|
|
- int i;
|
|
|
|
|
|
mutex_lock(&chip->reg_lock);
|
|
|
+ if (mv88e6xxx_bridge_map(chip, br) ||
|
|
|
+ mv88e6xxx_port_vlan_map(chip, port))
|
|
|
+ dev_err(ds->dev, "failed to remap in-chip Port VLAN\n");
|
|
|
+ mutex_unlock(&chip->reg_lock);
|
|
|
+}
|
|
|
|
|
|
- /* Remap each port's VLANTable */
|
|
|
- for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
|
|
|
- if (i == port || ds->ports[i].bridge_dev == br)
|
|
|
- if (_mv88e6xxx_port_based_vlan_map(chip, i))
|
|
|
- netdev_warn(ds->ports[i].netdev,
|
|
|
- "failed to remap\n");
|
|
|
+static int mv88e6xxx_crosschip_bridge_join(struct dsa_switch *ds, int dev,
|
|
|
+ int port, struct net_device *br)
|
|
|
+{
|
|
|
+ struct mv88e6xxx_chip *chip = ds->priv;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ if (!mv88e6xxx_has_pvt(chip))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ mutex_lock(&chip->reg_lock);
|
|
|
+ err = mv88e6xxx_pvt_map(chip, dev, port);
|
|
|
+ mutex_unlock(&chip->reg_lock);
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static void mv88e6xxx_crosschip_bridge_leave(struct dsa_switch *ds, int dev,
|
|
|
+ int port, struct net_device *br)
|
|
|
+{
|
|
|
+ struct mv88e6xxx_chip *chip = ds->priv;
|
|
|
|
|
|
+ if (!mv88e6xxx_has_pvt(chip))
|
|
|
+ return;
|
|
|
+
|
|
|
+ mutex_lock(&chip->reg_lock);
|
|
|
+ if (mv88e6xxx_pvt_map(chip, dev, port))
|
|
|
+ dev_err(ds->dev, "failed to remap cross-chip Port VLAN\n");
|
|
|
mutex_unlock(&chip->reg_lock);
|
|
|
}
|
|
|
|
|
@@ -2435,7 +2543,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
|
- err = _mv88e6xxx_port_based_vlan_map(chip, port);
|
|
|
+ err = mv88e6xxx_port_vlan_map(chip, port);
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
@@ -2594,6 +2702,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
|
|
|
goto unlock;
|
|
|
}
|
|
|
|
|
|
+ err = mv88e6xxx_pvt_setup(chip);
|
|
|
+ if (err)
|
|
|
+ goto unlock;
|
|
|
+
|
|
|
err = mv88e6xxx_atu_setup(chip);
|
|
|
if (err)
|
|
|
goto unlock;
|
|
@@ -3578,6 +3690,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 8,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_DSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6097,
|
|
|
.ops = &mv88e6085_ops,
|
|
@@ -3610,6 +3723,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 8,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6097,
|
|
|
.ops = &mv88e6097_ops,
|
|
@@ -3626,6 +3740,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_DSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6165,
|
|
|
.ops = &mv88e6123_ops,
|
|
@@ -3657,6 +3772,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 3750,
|
|
|
.atu_move_port_mask = 0x1f,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6341,
|
|
|
.ops = &mv88e6141_ops,
|
|
@@ -3673,6 +3789,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_DSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6165,
|
|
|
.ops = &mv88e6161_ops,
|
|
@@ -3689,6 +3806,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_DSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6165,
|
|
|
.ops = &mv88e6165_ops,
|
|
@@ -3705,6 +3823,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6351,
|
|
|
.ops = &mv88e6171_ops,
|
|
@@ -3721,6 +3840,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6352,
|
|
|
.ops = &mv88e6172_ops,
|
|
@@ -3737,6 +3857,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6351,
|
|
|
.ops = &mv88e6175_ops,
|
|
@@ -3753,6 +3874,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6352,
|
|
|
.ops = &mv88e6176_ops,
|
|
@@ -3785,6 +3907,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.tag_protocol = DSA_TAG_PROTO_DSA,
|
|
|
.age_time_coeff = 3750,
|
|
|
.g1_irqs = 9,
|
|
|
+ .pvt = true,
|
|
|
.atu_move_port_mask = 0x1f,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6390,
|
|
|
.ops = &mv88e6190_ops,
|
|
@@ -3801,6 +3924,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 3750,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0x1f,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_DSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6390,
|
|
|
.ops = &mv88e6190x_ops,
|
|
@@ -3817,6 +3941,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 3750,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0x1f,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_DSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6390,
|
|
|
.ops = &mv88e6191_ops,
|
|
@@ -3833,6 +3958,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6352,
|
|
|
.ops = &mv88e6240_ops,
|
|
@@ -3849,6 +3975,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 3750,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0x1f,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_DSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6390,
|
|
|
.ops = &mv88e6290_ops,
|
|
@@ -3865,6 +3992,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 8,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6320,
|
|
|
.ops = &mv88e6320_ops,
|
|
@@ -3896,6 +4024,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.global1_addr = 0x1b,
|
|
|
.age_time_coeff = 3750,
|
|
|
.atu_move_port_mask = 0x1f,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6341,
|
|
|
.ops = &mv88e6341_ops,
|
|
@@ -3912,6 +4041,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6351,
|
|
|
.ops = &mv88e6350_ops,
|
|
@@ -3928,6 +4058,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6351,
|
|
|
.ops = &mv88e6351_ops,
|
|
@@ -3944,6 +4075,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 15000,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0xf,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6352,
|
|
|
.ops = &mv88e6352_ops,
|
|
@@ -3959,6 +4091,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 3750,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0x1f,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_DSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6390,
|
|
|
.ops = &mv88e6390_ops,
|
|
@@ -3974,6 +4107,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|
|
.age_time_coeff = 3750,
|
|
|
.g1_irqs = 9,
|
|
|
.atu_move_port_mask = 0x1f,
|
|
|
+ .pvt = true,
|
|
|
.tag_protocol = DSA_TAG_PROTO_DSA,
|
|
|
.flags = MV88E6XXX_FLAGS_FAMILY_6390,
|
|
|
.ops = &mv88e6390x_ops,
|
|
@@ -4209,6 +4343,8 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
|
|
|
.port_mdb_add = mv88e6xxx_port_mdb_add,
|
|
|
.port_mdb_del = mv88e6xxx_port_mdb_del,
|
|
|
.port_mdb_dump = mv88e6xxx_port_mdb_dump,
|
|
|
+ .crosschip_bridge_join = mv88e6xxx_crosschip_bridge_join,
|
|
|
+ .crosschip_bridge_leave = mv88e6xxx_crosschip_bridge_leave,
|
|
|
};
|
|
|
|
|
|
static struct dsa_switch_driver mv88e6xxx_switch_drv = {
|
|
@@ -4220,7 +4356,7 @@ static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
|
|
|
struct device *dev = chip->dev;
|
|
|
struct dsa_switch *ds;
|
|
|
|
|
|
- ds = dsa_switch_alloc(dev, DSA_MAX_PORTS);
|
|
|
+ ds = dsa_switch_alloc(dev, mv88e6xxx_num_ports(chip));
|
|
|
if (!ds)
|
|
|
return -ENOMEM;
|
|
|
|