diff options
Diffstat (limited to 'net/dsa/legacy.c')
-rw-r--r-- | net/dsa/legacy.c | 113 |
1 files changed, 55 insertions, 58 deletions
diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c index 1d7a3282f2a7..84611d7fcfa2 100644 --- a/net/dsa/legacy.c +++ b/net/dsa/legacy.c @@ -78,31 +78,30 @@ dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr, } /* basic switch operations **************************************************/ -static int dsa_cpu_dsa_setups(struct dsa_switch *ds, struct device *dev) +static int dsa_cpu_dsa_setups(struct dsa_switch *ds) { - struct dsa_port *dport; int ret, port; for (port = 0; port < ds->num_ports; port++) { if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))) continue; - dport = &ds->ports[port]; - ret = dsa_cpu_dsa_setup(ds, dev, dport, port); + ret = dsa_port_fixed_link_register_of(&ds->ports[port]); if (ret) return ret; } return 0; } -static int dsa_switch_setup_one(struct dsa_switch *ds, struct net_device *master, - struct device *parent) +static int dsa_switch_setup_one(struct dsa_switch *ds, + struct net_device *master) { const struct dsa_switch_ops *ops = ds->ops; struct dsa_switch_tree *dst = ds->dst; struct dsa_chip_data *cd = ds->cd; bool valid_name_found = false; int index = ds->index; + struct dsa_port *dp; int i, ret; /* @@ -111,9 +110,12 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct net_device *master for (i = 0; i < ds->num_ports; i++) { char *name; + dp = &ds->ports[i]; + name = cd->port_names[i]; if (name == NULL) continue; + dp->name = name; if (!strcmp(name, "cpu")) { if (dst->cpu_dp) { @@ -122,12 +124,12 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct net_device *master return -EINVAL; } dst->cpu_dp = &ds->ports[i]; - dst->cpu_dp->netdev = master; - ds->cpu_port_mask |= 1 << i; + dst->cpu_dp->master = master; + dp->type = DSA_PORT_TYPE_CPU; } else if (!strcmp(name, "dsa")) { - ds->dsa_port_mask |= 1 << i; + dp->type = DSA_PORT_TYPE_DSA; } else { - ds->enabled_port_mask |= 1 << i; + dp->type = DSA_PORT_TYPE_USER; } valid_name_found = true; } @@ -138,7 +140,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct net_device *master /* Make the built-in MII bus mask match the number of ports, * switch drivers can override this later */ - ds->phys_mii_mask = ds->enabled_port_mask; + ds->phys_mii_mask |= dsa_user_ports(ds); /* * If the CPU connects to this switch, set the switch tree @@ -146,14 +148,19 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct net_device *master * switch. */ if (dst->cpu_dp->ds == ds) { + const struct dsa_device_ops *tag_ops; enum dsa_tag_protocol tag_protocol; - tag_protocol = ops->get_tag_protocol(ds); - dst->tag_ops = dsa_resolve_tag_protocol(tag_protocol); - if (IS_ERR(dst->tag_ops)) - return PTR_ERR(dst->tag_ops); + tag_protocol = ops->get_tag_protocol(ds, dst->cpu_dp->index); + tag_ops = dsa_resolve_tag_protocol(tag_protocol); + if (IS_ERR(tag_ops)) + return PTR_ERR(tag_ops); + + dst->cpu_dp->tag_ops = tag_ops; - dst->rcv = dst->tag_ops->rcv; + /* Few copies for faster access in master receive hot path */ + dst->cpu_dp->rcv = dst->cpu_dp->tag_ops->rcv; + dst->cpu_dp->dst = dst; } memcpy(ds->rtable, cd->rtable, sizeof(ds->rtable)); @@ -169,14 +176,8 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct net_device *master if (ret) return ret; - if (ops->set_addr) { - ret = ops->set_addr(ds, master->dev_addr); - if (ret < 0) - return ret; - } - if (!ds->slave_mii_bus && ops->phy_read) { - ds->slave_mii_bus = devm_mdiobus_alloc(parent); + ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev); if (!ds->slave_mii_bus) return -ENOMEM; dsa_slave_mii_bus_init(ds); @@ -193,25 +194,21 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct net_device *master ds->ports[i].dn = cd->port_dn[i]; ds->ports[i].cpu_dp = dst->cpu_dp; - if (!(ds->enabled_port_mask & (1 << i))) + if (dsa_is_user_port(ds, i)) continue; - ret = dsa_slave_create(ds, parent, i, cd->port_names[i]); + ret = dsa_slave_create(&ds->ports[i]); if (ret < 0) netdev_err(master, "[%d]: can't create dsa slave device for port %d(%s): %d\n", index, i, cd->port_names[i], ret); } /* Perform configuration of the CPU and DSA ports */ - ret = dsa_cpu_dsa_setups(ds, parent); + ret = dsa_cpu_dsa_setups(ds); if (ret < 0) netdev_err(master, "[%d] : can't configure CPU and DSA ports\n", index); - ret = dsa_cpu_port_ethtool_setup(ds->dst->cpu_dp); - if (ret) - return ret; - return 0; } @@ -252,7 +249,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, struct net_device *master, ds->ops = ops; ds->priv = priv; - ret = dsa_switch_setup_one(ds, master, parent); + ret = dsa_switch_setup_one(ds, master); if (ret) return ERR_PTR(ret); @@ -265,24 +262,20 @@ static void dsa_switch_destroy(struct dsa_switch *ds) /* Destroy network devices for physical switch ports. */ for (port = 0; port < ds->num_ports; port++) { - if (!(ds->enabled_port_mask & (1 << port))) + if (!dsa_is_user_port(ds, port)) continue; - if (!ds->ports[port].netdev) + if (!ds->ports[port].slave) continue; - dsa_slave_destroy(ds->ports[port].netdev); + dsa_slave_destroy(ds->ports[port].slave); } /* Disable configuration of the CPU and DSA ports */ for (port = 0; port < ds->num_ports; port++) { if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))) continue; - dsa_cpu_dsa_destroy(&ds->ports[port]); - - /* Clearing a bit which is not set does no harm */ - ds->cpu_port_mask |= ~(1 << port); - ds->dsa_port_mask |= ~(1 << port); + dsa_port_fixed_link_unregister_of(&ds->ports[port]); } if (ds->slave_mii_bus && ds->ops->phy_read) @@ -600,15 +593,7 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev, if (!configured) return -EPROBE_DEFER; - /* - * If we use a tagging format that doesn't have an ethertype - * field, make sure that all packets from this point on get - * sent to the tag format's receive function. - */ - wmb(); - dev->dsa_ptr = dst; - - return 0; + return dsa_master_setup(dst->cpu_dp->master, dst->cpu_dp); } static int dsa_probe(struct platform_device *pdev) @@ -673,13 +658,7 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst) { int i; - dst->cpu_dp->netdev->dsa_ptr = NULL; - - /* If we used a tagging format that doesn't have an ethertype - * field, make sure that all packets from this point get sent - * without the tag and go through the regular receive path. - */ - wmb(); + dsa_master_teardown(dst->cpu_dp->master); for (i = 0; i < dst->pd->nr_chips; i++) { struct dsa_switch *ds = dst->ds[i]; @@ -688,9 +667,7 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst) dsa_switch_destroy(ds); } - dsa_cpu_port_ethtool_restore(dst->cpu_dp); - - dev_put(dst->cpu_dp->netdev); + dev_put(dst->cpu_dp->master); } static int dsa_remove(struct platform_device *pdev) @@ -741,6 +718,26 @@ static int dsa_resume(struct device *d) } #endif +/* legacy way, bypassing the bridge *****************************************/ +int dsa_legacy_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], + struct net_device *dev, + const unsigned char *addr, u16 vid, + u16 flags) +{ + struct dsa_port *dp = dsa_slave_to_port(dev); + + return dsa_port_fdb_add(dp, addr, vid); +} + +int dsa_legacy_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], + struct net_device *dev, + const unsigned char *addr, u16 vid) +{ + struct dsa_port *dp = dsa_slave_to_port(dev); + + return dsa_port_fdb_del(dp, addr, vid); +} + static SIMPLE_DEV_PM_OPS(dsa_pm_ops, dsa_suspend, dsa_resume); static const struct of_device_id dsa_of_match_table[] = { |