aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2016-06-07 19:32:42 -0400
committerDavid S. Miller <davem@davemloft.net>2016-06-08 14:23:42 -0400
commit0c73c523cf737b5d446705392e0e14ee0411a351 (patch)
tree153ba2b1b3dd0f85c6d6a22e75bc5096bf25249f /net/dsa
parentaf42192c47c41ec132bda736a78d6d5e0d2999a9 (diff)
net: dsa: Initialize CPU port ethtool ops per tree
Now that we can properly support multiple distinct trees in the system, using a global variable: dsa_cpu_port_ethtool_ops is getting clobbered as soon as the second switch tree gets probed, and we don't want that. We need to move this to be dynamically allocated, and since we can't really be comparing addresses anymore to determine first time initialization versus any other times, just move this to dsa.c and dsa2.c where the remainder of the dst/ds initialization happens. The operations teardown restores the master netdev's ethtool_ops to its original ethtool_ops pointer (typically within the Ethernet driver) Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa')
-rw-r--r--net/dsa/dsa.c41
-rw-r--r--net/dsa/dsa2.c6
-rw-r--r--net/dsa/dsa_priv.h2
-rw-r--r--net/dsa/slave.c10
4 files changed, 49 insertions, 10 deletions
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index ce3b942dce76..766d2a525ada 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -266,6 +266,41 @@ const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol)
266 return ops; 266 return ops;
267} 267}
268 268
269int dsa_cpu_port_ethtool_setup(struct dsa_switch *ds)
270{
271 struct net_device *master;
272 struct ethtool_ops *cpu_ops;
273
274 master = ds->dst->master_netdev;
275 if (ds->master_netdev)
276 master = ds->master_netdev;
277
278 cpu_ops = devm_kzalloc(ds->dev, sizeof(*cpu_ops), GFP_KERNEL);
279 if (!cpu_ops)
280 return -ENOMEM;
281
282 memcpy(&ds->dst->master_ethtool_ops, master->ethtool_ops,
283 sizeof(struct ethtool_ops));
284 ds->dst->master_orig_ethtool_ops = master->ethtool_ops;
285 memcpy(cpu_ops, &ds->dst->master_ethtool_ops,
286 sizeof(struct ethtool_ops));
287 dsa_cpu_port_ethtool_init(cpu_ops);
288 master->ethtool_ops = cpu_ops;
289
290 return 0;
291}
292
293void dsa_cpu_port_ethtool_restore(struct dsa_switch *ds)
294{
295 struct net_device *master;
296
297 master = ds->dst->master_netdev;
298 if (ds->master_netdev)
299 master = ds->master_netdev;
300
301 master->ethtool_ops = ds->dst->master_orig_ethtool_ops;
302}
303
269static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) 304static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
270{ 305{
271 struct dsa_switch_driver *drv = ds->drv; 306 struct dsa_switch_driver *drv = ds->drv;
@@ -379,6 +414,10 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
379 ret = 0; 414 ret = 0;
380 } 415 }
381 416
417 ret = dsa_cpu_port_ethtool_setup(ds);
418 if (ret)
419 return ret;
420
382#ifdef CONFIG_NET_DSA_HWMON 421#ifdef CONFIG_NET_DSA_HWMON
383 /* If the switch provides a temperature sensor, 422 /* If the switch provides a temperature sensor,
384 * register with hardware monitoring subsystem. 423 * register with hardware monitoring subsystem.
@@ -963,6 +1002,8 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
963 dsa_switch_destroy(ds); 1002 dsa_switch_destroy(ds);
964 } 1003 }
965 1004
1005 dsa_cpu_port_ethtool_restore(dst->ds[0]);
1006
966 dev_put(dst->master_netdev); 1007 dev_put(dst->master_netdev);
967} 1008}
968 1009
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 4e0f3c268103..83b95fc4cede 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -394,6 +394,10 @@ static int dsa_dst_apply(struct dsa_switch_tree *dst)
394 return err; 394 return err;
395 } 395 }
396 396
397 err = dsa_cpu_port_ethtool_setup(dst->ds[0]);
398 if (err)
399 return err;
400
397 /* If we use a tagging format that doesn't have an ethertype 401 /* If we use a tagging format that doesn't have an ethertype
398 * field, make sure that all packets from this point on get 402 * field, make sure that all packets from this point on get
399 * sent to the tag format's receive function. 403 * sent to the tag format's receive function.
@@ -429,6 +433,8 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst)
429 dsa_ds_unapply(dst, ds); 433 dsa_ds_unapply(dst, ds);
430 } 434 }
431 435
436 dsa_cpu_port_ethtool_restore(dst->ds[0]);
437
432 pr_info("DSA: tree %d unapplied\n", dst->tree); 438 pr_info("DSA: tree %d unapplied\n", dst->tree);
433 dst->applied = false; 439 dst->applied = false;
434} 440}
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 106a9f067f94..00077a9c97f4 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -54,6 +54,8 @@ int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct device *dev,
54 struct device_node *port_dn, int port); 54 struct device_node *port_dn, int port);
55void dsa_cpu_dsa_destroy(struct device_node *port_dn); 55void dsa_cpu_dsa_destroy(struct device_node *port_dn);
56const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol); 56const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol);
57int dsa_cpu_port_ethtool_setup(struct dsa_switch *ds);
58void dsa_cpu_port_ethtool_restore(struct dsa_switch *ds);
57 59
58/* slave.c */ 60/* slave.c */
59extern const struct dsa_device_ops notag_netdev_ops; 61extern const struct dsa_device_ops notag_netdev_ops;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 8d159932e082..7236eb26dc97 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -892,8 +892,6 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
892 .get_eee = dsa_slave_get_eee, 892 .get_eee = dsa_slave_get_eee,
893}; 893};
894 894
895static struct ethtool_ops dsa_cpu_port_ethtool_ops;
896
897static const struct net_device_ops dsa_slave_netdev_ops = { 895static const struct net_device_ops dsa_slave_netdev_ops = {
898 .ndo_open = dsa_slave_open, 896 .ndo_open = dsa_slave_open,
899 .ndo_stop = dsa_slave_close, 897 .ndo_stop = dsa_slave_close,
@@ -1126,14 +1124,6 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
1126 1124
1127 slave_dev->features = master->vlan_features; 1125 slave_dev->features = master->vlan_features;
1128 slave_dev->ethtool_ops = &dsa_slave_ethtool_ops; 1126 slave_dev->ethtool_ops = &dsa_slave_ethtool_ops;
1129 if (master->ethtool_ops != &dsa_cpu_port_ethtool_ops) {
1130 memcpy(&dst->master_ethtool_ops, master->ethtool_ops,
1131 sizeof(struct ethtool_ops));
1132 memcpy(&dsa_cpu_port_ethtool_ops, &dst->master_ethtool_ops,
1133 sizeof(struct ethtool_ops));
1134 dsa_cpu_port_ethtool_init(&dsa_cpu_port_ethtool_ops);
1135 master->ethtool_ops = &dsa_cpu_port_ethtool_ops;
1136 }
1137 eth_hw_addr_inherit(slave_dev, master); 1127 eth_hw_addr_inherit(slave_dev, master);
1138 slave_dev->priv_flags |= IFF_NO_QUEUE; 1128 slave_dev->priv_flags |= IFF_NO_QUEUE;
1139 slave_dev->netdev_ops = &dsa_slave_netdev_ops; 1129 slave_dev->netdev_ops = &dsa_slave_netdev_ops;