Merge tag 'rproc-v4.8' of git://github.com/andersson/remoteproc
[deliverable/linux.git] / net / dsa / dsa.c
index ce3b942dce76f6db4078ca1e556819fff2e86a60..7e68bc6bc8537e793e7b41a9753ef75d8a5112d2 100644 (file)
@@ -266,6 +266,41 @@ const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol)
        return ops;
 }
 
+int dsa_cpu_port_ethtool_setup(struct dsa_switch *ds)
+{
+       struct net_device *master;
+       struct ethtool_ops *cpu_ops;
+
+       master = ds->dst->master_netdev;
+       if (ds->master_netdev)
+               master = ds->master_netdev;
+
+       cpu_ops = devm_kzalloc(ds->dev, sizeof(*cpu_ops), GFP_KERNEL);
+       if (!cpu_ops)
+               return -ENOMEM;
+
+       memcpy(&ds->dst->master_ethtool_ops, master->ethtool_ops,
+              sizeof(struct ethtool_ops));
+       ds->dst->master_orig_ethtool_ops = master->ethtool_ops;
+       memcpy(cpu_ops, &ds->dst->master_ethtool_ops,
+              sizeof(struct ethtool_ops));
+       dsa_cpu_port_ethtool_init(cpu_ops);
+       master->ethtool_ops = cpu_ops;
+
+       return 0;
+}
+
+void dsa_cpu_port_ethtool_restore(struct dsa_switch *ds)
+{
+       struct net_device *master;
+
+       master = ds->dst->master_netdev;
+       if (ds->master_netdev)
+               master = ds->master_netdev;
+
+       master->ethtool_ops = ds->dst->master_orig_ethtool_ops;
+}
+
 static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 {
        struct dsa_switch_driver *drv = ds->drv;
@@ -379,6 +414,10 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
                ret = 0;
        }
 
+       ret = dsa_cpu_port_ethtool_setup(ds);
+       if (ret)
+               return ret;
+
 #ifdef CONFIG_NET_DSA_HWMON
        /* If the switch provides a temperature sensor,
         * register with hardware monitoring subsystem.
@@ -735,11 +774,17 @@ static int dsa_of_probe(struct device *dev)
 
        chip_index = -1;
        for_each_available_child_of_node(np, child) {
+               int i;
+
                chip_index++;
                cd = &pd->chip[chip_index];
 
                cd->of_node = child;
 
+               /* Initialize the routing table */
+               for (i = 0; i < DSA_MAX_SWITCHES; ++i)
+                       cd->rtable[i] = DSA_RTABLE_NONE;
+
                /* When assigning the host device, increment its refcount */
                cd->host_dev = get_device(&mdio_bus->dev);
 
@@ -963,6 +1008,8 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
                        dsa_switch_destroy(ds);
        }
 
+       dsa_cpu_port_ethtool_restore(dst->ds[0]);
+
        dev_put(dst->master_netdev);
 }
 
This page took 0.039135 seconds and 5 git commands to generate.