]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/dsa/legacy.c
net: dsa: Fix dependencies on bridge
[mirror_ubuntu-bionic-kernel.git] / net / dsa / legacy.c
index 91e6f7981d3912b5187494183a812c3a281ba766..84611d7fcfa2c973c02b08b55e048d69ca4837c1 100644 (file)
@@ -86,7 +86,7 @@ static int dsa_cpu_dsa_setups(struct dsa_switch *ds)
                if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
                        continue;
 
-               ret = dsa_cpu_dsa_setup(&ds->ports[port]);
+               ret = dsa_port_fixed_link_register_of(&ds->ports[port]);
                if (ret)
                        return ret;
        }
@@ -101,6 +101,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
        struct dsa_chip_data *cd = ds->cd;
        bool valid_name_found = false;
        int index = ds->index;
+       struct dsa_port *dp;
        int i, ret;
 
        /*
@@ -109,9 +110,12 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
        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) {
@@ -120,12 +124,12 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
                                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;
        }
@@ -136,7 +140,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
        /* 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
@@ -144,14 +148,19 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
         * 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));
@@ -167,12 +176,6 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
        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(ds->dev);
                if (!ds->slave_mii_bus)
@@ -191,10 +194,10 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
                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->ports[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);
@@ -206,10 +209,6 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
                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;
 }
 
@@ -263,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)
@@ -598,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)
@@ -671,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];
@@ -686,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)
@@ -745,8 +724,7 @@ int dsa_legacy_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                       const unsigned char *addr, u16 vid,
                       u16 flags)
 {
-       struct dsa_slave_priv *p = netdev_priv(dev);
-       struct dsa_port *dp = p->dp;
+       struct dsa_port *dp = dsa_slave_to_port(dev);
 
        return dsa_port_fdb_add(dp, addr, vid);
 }
@@ -755,8 +733,7 @@ int dsa_legacy_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
                       struct net_device *dev,
                       const unsigned char *addr, u16 vid)
 {
-       struct dsa_slave_priv *p = netdev_priv(dev);
-       struct dsa_port *dp = p->dp;
+       struct dsa_port *dp = dsa_slave_to_port(dev);
 
        return dsa_port_fdb_del(dp, addr, vid);
 }