netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/4] net: dsa: add master interface
@ 2017-08-31 18:37 Vivien Didelot
  2017-08-31 18:37 ` [PATCH net-next 1/4] net: dsa: introduce dsa_master Vivien Didelot
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Vivien Didelot @ 2017-08-31 18:37 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot

Currently the SoC network interface (called master) to which a switch
fabric hangs, has its dsa_ptr pointing to a dsa_switch_tree instance.

This is not quite correct, because this interface is physically wired to
one of the switch ports (called CPU port), and because in a switch
fabric with multiple CPU ports, several master interfaces will point to
several CPU ports of the same dsa_switch_tree.

This patchset adds a new dsa_master structure to represent the pipe
between the SoC master interface and its switch CPU port. This structure
will store specific data such as the master ethtool_ops copy and the
tagging protocol used to pass frames with the associated slave ports.
The dsa_ptr is changed to a dsa_master instance, and each DSA slave now
has a pointer to a master port.

This is a step forward better control over the CPU conduit and support
for multiple CPU ports.

Vivien Didelot (4):
  net: dsa: introduce dsa_master
  net: dsa: move master ethtool ops in dsa_master
  net: dsa: change dsa_ptr for a dsa_master
  net: dsa: assign a master to slave ports

 drivers/net/dsa/b53/b53_common.c |   4 +-
 drivers/net/dsa/bcm_sf2.c        |   8 +--
 drivers/net/dsa/mt7530.c         |   4 +-
 drivers/net/dsa/mv88e6060.c      |   2 +-
 drivers/net/dsa/qca8k.c          |   2 +-
 include/linux/netdevice.h        |   4 +-
 include/net/dsa.h                |  42 +++++------
 net/dsa/Makefile                 |   2 +-
 net/dsa/dsa.c                    |  34 +--------
 net/dsa/dsa2.c                   |  38 +++++-----
 net/dsa/dsa_priv.h               |  24 +++----
 net/dsa/legacy.c                 |  34 +++++----
 net/dsa/master.c                 | 149 +++++++++++++++++++++++++++++++++++++++
 net/dsa/slave.c                  | 117 +++++-------------------------
 net/dsa/tag_brcm.c               |   5 +-
 net/dsa/tag_dsa.c                |   3 +-
 net/dsa/tag_edsa.c               |   3 +-
 net/dsa/tag_ksz.c                |   5 +-
 net/dsa/tag_lan9303.c            |   6 +-
 net/dsa/tag_mtk.c                |  12 +---
 net/dsa/tag_qca.c                |  12 +---
 net/dsa/tag_trailer.c            |   5 +-
 22 files changed, 265 insertions(+), 250 deletions(-)
 create mode 100644 net/dsa/master.c

-- 
2.14.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net-next 1/4] net: dsa: introduce dsa_master
  2017-08-31 18:37 [PATCH net-next 0/4] net: dsa: add master interface Vivien Didelot
@ 2017-08-31 18:37 ` Vivien Didelot
  2017-08-31 18:37 ` [PATCH net-next 2/4] net: dsa: move master ethtool ops in dsa_master Vivien Didelot
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Vivien Didelot @ 2017-08-31 18:37 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot

Add a new dsa_master structure to represent the DSA switch port
physically linked to the CPU master Ethernet device.

This device, a.k.a. a CPU port, is responsible to receive/send frames
from/to the DSA slave ports, a.k.a. user ports.

For the moment, this structure only contains a pointer to a dsa_port
(i.e. the switch device side) and a pointer to the master interface
(i.e. the SoC CPU side).

The structure will be extended with master-specific data such as the
tagging operations or the master ethtool_ops copies.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 drivers/net/dsa/b53/b53_common.c |  4 ++--
 drivers/net/dsa/bcm_sf2.c        |  8 ++++----
 drivers/net/dsa/mt7530.c         |  4 ++--
 drivers/net/dsa/mv88e6060.c      |  2 +-
 drivers/net/dsa/qca8k.c          |  2 +-
 include/net/dsa.h                | 12 ++++++++----
 net/dsa/Makefile                 |  2 +-
 net/dsa/dsa2.c                   | 27 ++++++++++++++-------------
 net/dsa/dsa_priv.h               |  8 ++++++--
 net/dsa/legacy.c                 | 21 ++++++++++++---------
 net/dsa/master.c                 | 30 ++++++++++++++++++++++++++++++
 net/dsa/slave.c                  |  6 +-----
 12 files changed, 82 insertions(+), 44 deletions(-)
 create mode 100644 net/dsa/master.c

diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 274f3679f33d..798045939281 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1280,7 +1280,7 @@ EXPORT_SYMBOL(b53_fdb_dump);
 int b53_br_join(struct dsa_switch *ds, int port, struct net_device *br)
 {
 	struct b53_device *dev = ds->priv;
-	s8 cpu_port = ds->dst->cpu_dp->index;
+	s8 cpu_port = ds->dst->master->port->index;
 	u16 pvlan, reg;
 	unsigned int i;
 
@@ -1326,7 +1326,7 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *br)
 {
 	struct b53_device *dev = ds->priv;
 	struct b53_vlan *vl = &dev->vlans[0];
-	s8 cpu_port = ds->dst->cpu_dp->index;
+	s8 cpu_port = ds->dst->master->port->index;
 	unsigned int i;
 	u16 pvlan, reg, pvid;
 
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 8492c9d64004..39468a0c1cee 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -227,7 +227,7 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
 			      struct phy_device *phy)
 {
 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
-	s8 cpu_port = ds->dst->cpu_dp->index;
+	s8 cpu_port = ds->dst->master->port->index;
 	unsigned int i;
 	u32 reg;
 
@@ -788,7 +788,7 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds)
 static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
 			       struct ethtool_wolinfo *wol)
 {
-	struct net_device *p = ds->dst->cpu_dp->netdev;
+	struct net_device *p = ds->dst->master->netdev;
 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 	struct ethtool_wolinfo pwol;
 
@@ -811,9 +811,9 @@ static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
 static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
 			      struct ethtool_wolinfo *wol)
 {
-	struct net_device *p = ds->dst->cpu_dp->netdev;
+	struct net_device *p = ds->dst->master->netdev;
 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
-	s8 cpu_port = ds->dst->cpu_dp->index;
+	s8 cpu_port = ds->dst->master->port->index;
 	struct ethtool_wolinfo pwol;
 
 	p->ethtool_ops->get_wol(p, &pwol);
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index c142b97add2c..4998c05dba1b 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -928,11 +928,11 @@ mt7530_setup(struct dsa_switch *ds)
 	struct device_node *dn;
 	struct mt7530_dummy_poll p;
 
-	/* The parent node of cpu_dp->netdev which holds the common system
+	/* The parent node of master->netdev which holds the common system
 	 * controller also is the container for two GMACs nodes representing
 	 * as two netdev instances.
 	 */
-	dn = ds->dst->cpu_dp->netdev->dev.of_node->parent;
+	dn = ds->dst->master->netdev->dev.of_node->parent;
 	priv->ethernet = syscon_node_to_regmap(dn);
 	if (IS_ERR(priv->ethernet))
 		return PTR_ERR(priv->ethernet);
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index dce7fa57eb55..6a30e15b9c01 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -176,7 +176,7 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
 		  ((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) |
 		   (dsa_is_cpu_port(ds, p) ?
 			ds->enabled_port_mask :
-			BIT(ds->dst->cpu_dp->index)));
+			BIT(ds->dst->master->port->index)));
 
 	/* Port Association Vector: when learning source addresses
 	 * of packets, add the address to the address database using
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 5ada7a41449c..c34d6c82efb3 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -506,7 +506,7 @@ qca8k_setup(struct dsa_switch *ds)
 		pr_warn("regmap initialization failed");
 
 	/* Initialize CPU port pad mode (xMII type, delays...) */
-	phy_mode = of_get_phy_mode(ds->dst->cpu_dp->dn);
+	phy_mode = of_get_phy_mode(ds->dst->master->port->dn);
 	if (phy_mode < 0) {
 		pr_err("Can't find phy-mode for master device\n");
 		return phy_mode;
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 398ca8d70ccd..217e36cfc69f 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -138,7 +138,7 @@ struct dsa_switch_tree {
 	/*
 	 * The switch port to which the CPU is attached.
 	 */
-	struct dsa_port		*cpu_dp;
+	struct dsa_master	*master;
 
 	/*
 	 * Data for the individual switch chips.
@@ -173,6 +173,10 @@ struct dsa_mall_tc_entry {
 	};
 };
 
+struct dsa_master {
+	struct dsa_port *port;
+	struct net_device *netdev;
+};
 
 struct dsa_port {
 	struct dsa_switch	*ds;
@@ -273,10 +277,10 @@ static inline u8 dsa_upstream_port(struct dsa_switch *ds)
 	 * Else return the (DSA) port number that connects to the
 	 * switch that is one hop closer to the cpu.
 	 */
-	if (dst->cpu_dp->ds == ds)
-		return dst->cpu_dp->index;
+	if (dst->master->port->ds == ds)
+		return dst->master->port->index;
 	else
-		return ds->rtable[dst->cpu_dp->ds->index];
+		return ds->rtable[dst->master->port->ds->index];
 }
 
 typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index fcce25da937c..2e7ac8bab19d 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -1,6 +1,6 @@
 # the core
 obj-$(CONFIG_NET_DSA) += dsa_core.o
-dsa_core-y += dsa.o dsa2.o legacy.o port.o slave.o switch.o
+dsa_core-y += dsa.o dsa2.o legacy.o master.o port.o slave.o switch.o
 
 # tagging formats
 dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index cceaa4dd9f53..4c4381b7aafb 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -337,7 +337,7 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, struct dsa_switch *ds)
 		return err;
 
 	if (ds->ops->set_addr) {
-		err = ds->ops->set_addr(ds, dst->cpu_dp->netdev->dev_addr);
+		err = ds->ops->set_addr(ds, dst->master->netdev->dev_addr);
 		if (err < 0)
 			return err;
 	}
@@ -433,8 +433,8 @@ static int dsa_dst_apply(struct dsa_switch_tree *dst)
 			return err;
 	}
 
-	if (dst->cpu_dp) {
-		err = dsa_cpu_port_ethtool_setup(dst->cpu_dp);
+	if (dst->master) {
+		err = dsa_cpu_port_ethtool_setup(dst->master->port);
 		if (err)
 			return err;
 	}
@@ -444,7 +444,7 @@ static int dsa_dst_apply(struct dsa_switch_tree *dst)
 	 * sent to the tag format's receive function.
 	 */
 	wmb();
-	dst->cpu_dp->netdev->dsa_ptr = dst;
+	dst->master->netdev->dsa_ptr = dst;
 	dst->applied = true;
 
 	return 0;
@@ -458,7 +458,7 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst)
 	if (!dst->applied)
 		return;
 
-	dst->cpu_dp->netdev->dsa_ptr = NULL;
+	dst->master->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
@@ -474,9 +474,9 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst)
 		dsa_ds_unapply(dst, ds);
 	}
 
-	if (dst->cpu_dp) {
-		dsa_cpu_port_ethtool_restore(dst->cpu_dp);
-		dst->cpu_dp = NULL;
+	if (dst->master) {
+		dsa_cpu_port_ethtool_restore(dst->master->port);
+		dst->master = NULL;
 	}
 
 	pr_info("DSA: tree %d unapplied\n", dst->tree);
@@ -504,9 +504,10 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
 	if (!ethernet_dev)
 		return -EPROBE_DEFER;
 
-	if (!dst->cpu_dp) {
-		dst->cpu_dp = port;
-		dst->cpu_dp->netdev = ethernet_dev;
+	if (!dst->master) {
+		dst->master = dsa_master_create(port, ethernet_dev);
+		if (!dst->master)
+			return -ENOMEM;
 	}
 
 	/* Initialize cpu_port_mask now for drv->setup()
@@ -577,7 +578,7 @@ static int dsa_dst_parse(struct dsa_switch_tree *dst)
 			return err;
 	}
 
-	if (!dst->cpu_dp->netdev) {
+	if (!dst->master) {
 		pr_warn("Tree has no master device\n");
 		return -EINVAL;
 	}
@@ -595,7 +596,7 @@ static int dsa_dst_parse(struct dsa_switch_tree *dst)
 			    dsa_port_is_cpu(dp))
 				continue;
 
-			dp->cpu_dp = dst->cpu_dp;
+			dp->cpu_dp = dst->master->port;
 		}
 	}
 
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 9c3eeb72462d..70f576b3d6fb 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -112,6 +112,10 @@ int dsa_legacy_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
 		       struct net_device *dev,
 		       const unsigned char *addr, u16 vid);
 
+/* master.c */
+struct dsa_master *dsa_master_create(struct dsa_port *port,
+				     struct net_device *netdev);
+
 /* port.c */
 int dsa_port_set_state(struct dsa_port *dp, u8 state,
 		       struct switchdev_trans *trans);
@@ -177,12 +181,12 @@ extern const struct dsa_device_ops trailer_netdev_ops;
 
 static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
 {
-	return p->dp->cpu_dp->netdev;
+	return p->dp->ds->dst->master->netdev;
 }
 
 static inline struct dsa_port *dsa_get_cpu_port(struct dsa_switch_tree *dst)
 {
-	return dst->cpu_dp;
+	return dst->master->port;
 }
 
 #endif
diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
index 91e6f7981d39..7a21415d2a81 100644
--- a/net/dsa/legacy.c
+++ b/net/dsa/legacy.c
@@ -114,13 +114,16 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
 			continue;
 
 		if (!strcmp(name, "cpu")) {
-			if (dst->cpu_dp) {
+			if (dst->master) {
 				netdev_err(master,
 					   "multiple cpu ports?!\n");
 				return -EINVAL;
 			}
-			dst->cpu_dp = &ds->ports[i];
-			dst->cpu_dp->netdev = master;
+
+			dst->master = dsa_master_create(&ds->ports[i], master);
+			if (!dst->master)
+				return -ENOMEM;
+
 			ds->cpu_port_mask |= 1 << i;
 		} else if (!strcmp(name, "dsa")) {
 			ds->dsa_port_mask |= 1 << i;
@@ -143,7 +146,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
 	 * tagging protocol to the preferred tagging format of this
 	 * switch.
 	 */
-	if (dst->cpu_dp->ds == ds) {
+	if (dst->master->port->ds == ds) {
 		enum dsa_tag_protocol tag_protocol;
 
 		tag_protocol = ops->get_tag_protocol(ds);
@@ -189,7 +192,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
 	 */
 	for (i = 0; i < ds->num_ports; i++) {
 		ds->ports[i].dn = cd->port_dn[i];
-		ds->ports[i].cpu_dp = dst->cpu_dp;
+		ds->ports[i].cpu_dp = dst->master->port;
 
 		if (!(ds->enabled_port_mask & (1 << i)))
 			continue;
@@ -206,7 +209,7 @@ 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);
+	ret = dsa_cpu_port_ethtool_setup(ds->dst->master->port);
 	if (ret)
 		return ret;
 
@@ -671,7 +674,7 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
 {
 	int i;
 
-	dst->cpu_dp->netdev->dsa_ptr = NULL;
+	dst->master->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
@@ -686,9 +689,9 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
 			dsa_switch_destroy(ds);
 	}
 
-	dsa_cpu_port_ethtool_restore(dst->cpu_dp);
+	dsa_cpu_port_ethtool_restore(dst->master->port);
 
-	dev_put(dst->cpu_dp->netdev);
+	dev_put(dst->master->netdev);
 }
 
 static int dsa_remove(struct platform_device *pdev)
diff --git a/net/dsa/master.c b/net/dsa/master.c
new file mode 100644
index 000000000000..294b82b9c114
--- /dev/null
+++ b/net/dsa/master.c
@@ -0,0 +1,30 @@
+/*
+ * Handling of a master port, receiving/sending frames from/to slave ports
+ *
+ * Copyright (c) 2017 Savoir-faire Linux Inc.
+ *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "dsa_priv.h"
+
+struct dsa_master *dsa_master_create(struct dsa_port *port,
+				     struct net_device *netdev)
+{
+	struct device *dev = port->ds->dev;
+	struct dsa_master *master;
+
+	master = devm_kzalloc(dev, sizeof(struct dsa_master), GFP_KERNEL);
+	if (!master)
+		return NULL;
+
+	master->port = port;
+	master->netdev = netdev;
+	master->port->netdev = netdev;
+
+	return master;
+}
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 78e78a6e6833..6d47eca47a0c 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1250,15 +1250,11 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
 {
 	struct dsa_switch *ds = port->ds;
 	struct dsa_switch_tree *dst = ds->dst;
-	struct net_device *master;
+	struct net_device *master = dst->master->netdev;
 	struct net_device *slave_dev;
 	struct dsa_slave_priv *p;
-	struct dsa_port *cpu_dp;
 	int ret;
 
-	cpu_dp = ds->dst->cpu_dp;
-	master = cpu_dp->netdev;
-
 	slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv), name,
 				 NET_NAME_UNKNOWN, ether_setup);
 	if (slave_dev == NULL)
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH net-next 2/4] net: dsa: move master ethtool ops in dsa_master
  2017-08-31 18:37 [PATCH net-next 0/4] net: dsa: add master interface Vivien Didelot
  2017-08-31 18:37 ` [PATCH net-next 1/4] net: dsa: introduce dsa_master Vivien Didelot
@ 2017-08-31 18:37 ` Vivien Didelot
  2017-08-31 18:37 ` [PATCH net-next 3/4] net: dsa: change dsa_ptr for a dsa_master Vivien Didelot
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Vivien Didelot @ 2017-08-31 18:37 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot

The copy of the master netdev ethtool_ops is currently stored in the
dsa_port structure, but it is specific to the DSA master (CPU) port.

Move it in the new dsa_master structure. While modifying the ethtool
functions to take this structure as argument, move them in a new
master.c DSA core file.

Also the ethtool ops were the only remaining users for
master->port->netdev thus remove this assignment now.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 include/net/dsa.h  |   9 ++---
 net/dsa/dsa.c      |  28 --------------
 net/dsa/dsa2.c     |   4 +-
 net/dsa/dsa_priv.h |   5 +--
 net/dsa/legacy.c   |   4 +-
 net/dsa/master.c   | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 net/dsa/slave.c    |  80 ----------------------------------------
 7 files changed, 114 insertions(+), 121 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 217e36cfc69f..f4a5afc4255b 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -176,6 +176,10 @@ struct dsa_mall_tc_entry {
 struct dsa_master {
 	struct dsa_port *port;
 	struct net_device *netdev;
+
+	/* Original copy of the master netdev ethtool_ops */
+	const struct ethtool_ops *orig_ethtool_ops;
+	struct ethtool_ops ethtool_ops;
 };
 
 struct dsa_port {
@@ -189,11 +193,6 @@ struct dsa_port {
 	u8			stp_state;
 	struct net_device	*bridge_dev;
 	struct devlink_port	devlink_port;
-	/*
-	 * Original copy of the master netdev ethtool_ops
-	 */
-	struct ethtool_ops	ethtool_ops;
-	const struct ethtool_ops *orig_ethtool_ops;
 };
 
 struct dsa_switch {
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 03c58b0eb082..81c852e32821 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -112,34 +112,6 @@ const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol)
 	return ops;
 }
 
-int dsa_cpu_port_ethtool_setup(struct dsa_port *cpu_dp)
-{
-	struct dsa_switch *ds = cpu_dp->ds;
-	struct net_device *master;
-	struct ethtool_ops *cpu_ops;
-
-	master = cpu_dp->netdev;
-
-	cpu_ops = devm_kzalloc(ds->dev, sizeof(*cpu_ops), GFP_KERNEL);
-	if (!cpu_ops)
-		return -ENOMEM;
-
-	memcpy(&cpu_dp->ethtool_ops, master->ethtool_ops,
-	       sizeof(struct ethtool_ops));
-	cpu_dp->orig_ethtool_ops = master->ethtool_ops;
-	memcpy(cpu_ops, &cpu_dp->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_port *cpu_dp)
-{
-	cpu_dp->netdev->ethtool_ops = cpu_dp->orig_ethtool_ops;
-}
-
 void dsa_cpu_dsa_destroy(struct dsa_port *port)
 {
 	struct device_node *port_dn = port->dn;
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 4c4381b7aafb..d60f681b96cc 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -434,7 +434,7 @@ static int dsa_dst_apply(struct dsa_switch_tree *dst)
 	}
 
 	if (dst->master) {
-		err = dsa_cpu_port_ethtool_setup(dst->master->port);
+		err = dsa_master_ethtool_setup(dst->master);
 		if (err)
 			return err;
 	}
@@ -475,7 +475,7 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst)
 	}
 
 	if (dst->master) {
-		dsa_cpu_port_ethtool_restore(dst->master->port);
+		dsa_master_ethtool_restore(dst->master);
 		dst->master = NULL;
 	}
 
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 70f576b3d6fb..4fa14b4305b9 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -97,8 +97,6 @@ struct dsa_slave_priv {
 int dsa_cpu_dsa_setup(struct dsa_port *port);
 void dsa_cpu_dsa_destroy(struct dsa_port *dport);
 const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol);
-int dsa_cpu_port_ethtool_setup(struct dsa_port *cpu_dp);
-void dsa_cpu_port_ethtool_restore(struct dsa_port *cpu_dp);
 bool dsa_schedule_work(struct work_struct *work);
 
 /* legacy.c */
@@ -115,6 +113,8 @@ int dsa_legacy_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
 /* master.c */
 struct dsa_master *dsa_master_create(struct dsa_port *port,
 				     struct net_device *netdev);
+int dsa_master_ethtool_setup(struct dsa_master *master);
+void dsa_master_ethtool_restore(struct dsa_master *master);
 
 /* port.c */
 int dsa_port_set_state(struct dsa_port *dp, u8 state,
@@ -143,7 +143,6 @@ int dsa_port_vlan_del(struct dsa_port *dp,
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
 void dsa_slave_mii_bus_init(struct dsa_switch *ds);
-void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops);
 int dsa_slave_create(struct dsa_port *port, const char *name);
 void dsa_slave_destroy(struct net_device *slave_dev);
 int dsa_slave_suspend(struct net_device *slave_dev);
diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
index 7a21415d2a81..acd81c488bf4 100644
--- a/net/dsa/legacy.c
+++ b/net/dsa/legacy.c
@@ -209,7 +209,7 @@ 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->master->port);
+	ret = dsa_master_ethtool_setup(ds->dst->master);
 	if (ret)
 		return ret;
 
@@ -689,7 +689,7 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
 			dsa_switch_destroy(ds);
 	}
 
-	dsa_cpu_port_ethtool_restore(dst->master->port);
+	dsa_master_ethtool_restore(dst->master);
 
 	dev_put(dst->master->netdev);
 }
diff --git a/net/dsa/master.c b/net/dsa/master.c
index 294b82b9c114..9ecce3e7c8df 100644
--- a/net/dsa/master.c
+++ b/net/dsa/master.c
@@ -12,6 +12,110 @@
 
 #include "dsa_priv.h"
 
+static void dsa_master_get_ethtool_stats(struct net_device *dev,
+					 struct ethtool_stats *stats,
+					 uint64_t *data)
+{
+	struct dsa_switch_tree *dst = dev->dsa_ptr;
+	struct dsa_master *master = dst->master;
+	struct dsa_port *port = master->port;
+	struct dsa_switch *ds = port->ds;
+	int count = 0;
+
+	if (master->ethtool_ops.get_sset_count) {
+		count = master->ethtool_ops.get_sset_count(dev, ETH_SS_STATS);
+		master->ethtool_ops.get_ethtool_stats(dev, stats, data);
+	}
+
+	if (ds->ops->get_ethtool_stats)
+		ds->ops->get_ethtool_stats(ds, port->index, data + count);
+}
+
+static int dsa_master_get_sset_count(struct net_device *dev, int sset)
+{
+	struct dsa_switch_tree *dst = dev->dsa_ptr;
+	struct dsa_master *master = dst->master;
+	struct dsa_port *port = master->port;
+	struct dsa_switch *ds = port->ds;
+	int count = 0;
+
+	if (master->ethtool_ops.get_sset_count)
+		count += master->ethtool_ops.get_sset_count(dev, sset);
+
+	if (sset == ETH_SS_STATS && ds->ops->get_sset_count)
+		count += ds->ops->get_sset_count(ds);
+
+	return count;
+}
+
+static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset,
+				   uint8_t *data)
+{
+	struct dsa_switch_tree *dst = dev->dsa_ptr;
+	struct dsa_master *master = dst->master;
+	struct dsa_port *port = master->port;
+	struct dsa_switch *ds = port->ds;
+	int len = ETH_GSTRING_LEN;
+	int mcount = 0, count;
+	unsigned int i;
+	uint8_t pfx[4];
+	uint8_t *ndata;
+
+	snprintf(pfx, sizeof(pfx), "p%.2d", port->index);
+	/* We do not want to be NULL-terminated, since this is a prefix */
+	pfx[sizeof(pfx) - 1] = '_';
+
+	if (master->ethtool_ops.get_sset_count) {
+		mcount = master->ethtool_ops.get_sset_count(dev, ETH_SS_STATS);
+		master->ethtool_ops.get_strings(dev, stringset, data);
+	}
+
+	if (stringset == ETH_SS_STATS && ds->ops->get_strings) {
+		ndata = data + mcount * len;
+		/* This function copies ETH_GSTRINGS_LEN bytes, we will mangle
+		 * the output after to prepend our CPU port prefix we
+		 * constructed earlier
+		 */
+		ds->ops->get_strings(ds, port->index, ndata);
+		count = ds->ops->get_sset_count(ds);
+		for (i = 0; i < count; i++) {
+			memmove(ndata + (i * len + sizeof(pfx)),
+				ndata + i * len, len - sizeof(pfx));
+			memcpy(ndata + i * len, pfx, sizeof(pfx));
+		}
+	}
+}
+
+int dsa_master_ethtool_setup(struct dsa_master *master)
+{
+	struct device *dev = master->port->ds->dev;
+	struct net_device *netdev = master->netdev;
+	struct ethtool_ops *ops;
+
+	ops = devm_kzalloc(dev, sizeof(*ops), GFP_KERNEL);
+	if (!ops)
+		return -ENOMEM;
+
+	/* Back up the original master netdev ethtool_ops */
+	master->orig_ethtool_ops = netdev->ethtool_ops;
+	memcpy(&master->ethtool_ops, master->orig_ethtool_ops, sizeof(*ops));
+	memcpy(ops, &master->ethtool_ops, sizeof(*ops));
+
+	/* Change the master netdev ethtool_ops */
+	ops->get_sset_count = dsa_master_get_sset_count;
+	ops->get_ethtool_stats = dsa_master_get_ethtool_stats;
+	ops->get_strings = dsa_master_get_strings;
+	netdev->ethtool_ops = ops;
+
+	return 0;
+}
+
+void dsa_master_ethtool_restore(struct dsa_master *master)
+{
+	master->netdev->ethtool_ops = master->orig_ethtool_ops;
+	master->orig_ethtool_ops = NULL;
+}
+
 struct dsa_master *dsa_master_create(struct dsa_port *port,
 				     struct net_device *netdev)
 {
@@ -24,7 +128,6 @@ struct dsa_master *dsa_master_create(struct dsa_port *port,
 
 	master->port = port;
 	master->netdev = netdev;
-	master->port->netdev = netdev;
 
 	return master;
 }
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 6d47eca47a0c..99f9e48a6cee 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -567,79 +567,6 @@ static void dsa_slave_get_strings(struct net_device *dev,
 	}
 }
 
-static void dsa_cpu_port_get_ethtool_stats(struct net_device *dev,
-					   struct ethtool_stats *stats,
-					   uint64_t *data)
-{
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
-	struct dsa_switch *ds = cpu_dp->ds;
-	s8 cpu_port = cpu_dp->index;
-	int count = 0;
-
-	if (cpu_dp->ethtool_ops.get_sset_count) {
-		count = cpu_dp->ethtool_ops.get_sset_count(dev, ETH_SS_STATS);
-		cpu_dp->ethtool_ops.get_ethtool_stats(dev, stats, data);
-	}
-
-	if (ds->ops->get_ethtool_stats)
-		ds->ops->get_ethtool_stats(ds, cpu_port, data + count);
-}
-
-static int dsa_cpu_port_get_sset_count(struct net_device *dev, int sset)
-{
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
-	struct dsa_switch *ds = cpu_dp->ds;
-	int count = 0;
-
-	if (cpu_dp->ethtool_ops.get_sset_count)
-		count += cpu_dp->ethtool_ops.get_sset_count(dev, sset);
-
-	if (sset == ETH_SS_STATS && ds->ops->get_sset_count)
-		count += ds->ops->get_sset_count(ds);
-
-	return count;
-}
-
-static void dsa_cpu_port_get_strings(struct net_device *dev,
-				     uint32_t stringset, uint8_t *data)
-{
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
-	struct dsa_switch *ds = cpu_dp->ds;
-	s8 cpu_port = cpu_dp->index;
-	int len = ETH_GSTRING_LEN;
-	int mcount = 0, count;
-	unsigned int i;
-	uint8_t pfx[4];
-	uint8_t *ndata;
-
-	snprintf(pfx, sizeof(pfx), "p%.2d", cpu_port);
-	/* We do not want to be NULL-terminated, since this is a prefix */
-	pfx[sizeof(pfx) - 1] = '_';
-
-	if (cpu_dp->ethtool_ops.get_sset_count) {
-		mcount = cpu_dp->ethtool_ops.get_sset_count(dev, ETH_SS_STATS);
-		cpu_dp->ethtool_ops.get_strings(dev, stringset, data);
-	}
-
-	if (stringset == ETH_SS_STATS && ds->ops->get_strings) {
-		ndata = data + mcount * len;
-		/* This function copies ETH_GSTRINGS_LEN bytes, we will mangle
-		 * the output after to prepend our CPU port prefix we
-		 * constructed earlier
-		 */
-		ds->ops->get_strings(ds, cpu_port, ndata);
-		count = ds->ops->get_sset_count(ds);
-		for (i = 0; i < count; i++) {
-			memmove(ndata + (i * len + sizeof(pfx)),
-				ndata + i * len, len - sizeof(pfx));
-			memcpy(ndata + i * len, pfx, sizeof(pfx));
-		}
-	}
-}
-
 static void dsa_slave_get_ethtool_stats(struct net_device *dev,
 					struct ethtool_stats *stats,
 					uint64_t *data)
@@ -976,13 +903,6 @@ static void dsa_slave_get_stats64(struct net_device *dev,
 	}
 }
 
-void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops)
-{
-	ops->get_sset_count = dsa_cpu_port_get_sset_count;
-	ops->get_ethtool_stats = dsa_cpu_port_get_ethtool_stats;
-	ops->get_strings = dsa_cpu_port_get_strings;
-}
-
 static int dsa_slave_get_rxnfc(struct net_device *dev,
 			       struct ethtool_rxnfc *nfc, u32 *rule_locs)
 {
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH net-next 3/4] net: dsa: change dsa_ptr for a dsa_master
  2017-08-31 18:37 [PATCH net-next 0/4] net: dsa: add master interface Vivien Didelot
  2017-08-31 18:37 ` [PATCH net-next 1/4] net: dsa: introduce dsa_master Vivien Didelot
  2017-08-31 18:37 ` [PATCH net-next 2/4] net: dsa: move master ethtool ops in dsa_master Vivien Didelot
@ 2017-08-31 18:37 ` Vivien Didelot
  2017-09-02 15:30   ` Andrew Lunn
  2017-08-31 18:37 ` [PATCH net-next 4/4] net: dsa: assign a master to slave ports Vivien Didelot
  2017-09-02 16:42 ` [PATCH net-next 0/4] net: dsa: add master interface Florian Fainelli
  4 siblings, 1 reply; 9+ messages in thread
From: Vivien Didelot @ 2017-08-31 18:37 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot

The dsa_ptr of a net_device currently points to a dsa_switch_tree.

This is not correct because the interface is physically linked to a
switch port, and because several network interface could point to
several (so called "CPU") ports of the same DSA switch tree.

Because the tagging operations are specific to the DSA master port and
not the whole switch tree, move the tag_ops pointer in dsa_master.

Finally change the dsa_ptr from dsa_switch_tree to a dsa_master.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 include/linux/netdevice.h |  4 ++--
 include/net/dsa.h         | 21 ++++++++++-----------
 net/dsa/dsa.c             |  6 +++---
 net/dsa/dsa2.c            | 13 +++++--------
 net/dsa/dsa_priv.h        |  8 ++------
 net/dsa/legacy.c          | 13 ++++---------
 net/dsa/master.c          | 28 ++++++++++++++++++++++------
 net/dsa/slave.c           |  2 +-
 net/dsa/tag_brcm.c        |  5 ++---
 net/dsa/tag_dsa.c         |  3 ++-
 net/dsa/tag_edsa.c        |  3 ++-
 net/dsa/tag_ksz.c         |  5 ++---
 net/dsa/tag_lan9303.c     |  6 ++----
 net/dsa/tag_mtk.c         | 12 ++----------
 net/dsa/tag_qca.c         | 12 ++----------
 net/dsa/tag_trailer.c     |  5 ++---
 16 files changed, 65 insertions(+), 81 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 29bf06ff157c..eb0501c9afc5 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -55,7 +55,7 @@
 struct netpoll_info;
 struct device;
 struct phy_device;
-struct dsa_switch_tree;
+struct dsa_master;
 
 /* 802.11 specific */
 struct wireless_dev;
@@ -1752,7 +1752,7 @@ struct net_device {
 	struct vlan_info __rcu	*vlan_info;
 #endif
 #if IS_ENABLED(CONFIG_NET_DSA)
-	struct dsa_switch_tree	*dsa_ptr;
+	struct dsa_master	*dsa_ptr;
 #endif
 #if IS_ENABLED(CONFIG_TIPC)
 	struct tipc_bearer __rcu *tipc_ptr;
diff --git a/include/net/dsa.h b/include/net/dsa.h
index f4a5afc4255b..d5b24cd10f79 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -130,11 +130,6 @@ struct dsa_switch_tree {
 	 */
 	struct dsa_platform_data	*pd;
 
-	/* Copy of tag_ops->rcv for faster access in hot path */
-	struct sk_buff *	(*rcv)(struct sk_buff *skb,
-				       struct net_device *dev,
-				       struct packet_type *pt);
-
 	/*
 	 * The switch port to which the CPU is attached.
 	 */
@@ -144,12 +139,6 @@ struct dsa_switch_tree {
 	 * Data for the individual switch chips.
 	 */
 	struct dsa_switch	*ds[DSA_MAX_SWITCHES];
-
-	/*
-	 * Tagging protocol operations for adding and removing an
-	 * encapsulation tag.
-	 */
-	const struct dsa_device_ops *tag_ops;
 };
 
 /* TC matchall action types, only mirroring for now */
@@ -177,6 +166,16 @@ struct dsa_master {
 	struct dsa_port *port;
 	struct net_device *netdev;
 
+	/*
+	 * Tagging protocol operations for adding and removing an
+	 * encapsulation tag.
+	 */
+	const struct dsa_device_ops *tag_ops;
+
+	/* Copy of tag_ops->rcv for faster access in hot path */
+	struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
+			       struct packet_type *pt);
+
 	/* Original copy of the master netdev ethtool_ops */
 	const struct ethtool_ops *orig_ethtool_ops;
 	struct ethtool_ops ethtool_ops;
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 81c852e32821..f2ebd3572d6f 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -160,12 +160,12 @@ EXPORT_SYMBOL_GPL(dsa_dev_to_net_device);
 static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
 			  struct packet_type *pt, struct net_device *unused)
 {
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
+	struct dsa_master *master = dev->dsa_ptr;
 	struct sk_buff *nskb = NULL;
 	struct pcpu_sw_netstats *s;
 	struct dsa_slave_priv *p;
 
-	if (unlikely(dst == NULL)) {
+	if (unlikely(!master)) {
 		kfree_skb(skb);
 		return 0;
 	}
@@ -174,7 +174,7 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (!skb)
 		return 0;
 
-	nskb = dst->rcv(skb, dev, pt);
+	nskb = master->rcv(skb, dev, pt);
 	if (!nskb) {
 		kfree_skb(skb);
 		return 0;
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index d60f681b96cc..80a9706324f2 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -444,7 +444,7 @@ static int dsa_dst_apply(struct dsa_switch_tree *dst)
 	 * sent to the tag format's receive function.
 	 */
 	wmb();
-	dst->master->netdev->dsa_ptr = dst;
+	dst->master->netdev->dsa_ptr = dst->master;
 	dst->applied = true;
 
 	return 0;
@@ -487,9 +487,9 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
 			 struct dsa_switch_tree *dst,
 			 struct dsa_switch *ds)
 {
-	enum dsa_tag_protocol tag_protocol;
 	struct net_device *ethernet_dev;
 	struct device_node *ethernet;
+	int err;
 
 	if (port->dn) {
 		ethernet = of_parse_phandle(port->dn, "ethernet", 0);
@@ -516,16 +516,13 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
 	 */
 	ds->cpu_port_mask |= BIT(index);
 
-	tag_protocol = ds->ops->get_tag_protocol(ds);
-	dst->tag_ops = dsa_resolve_tag_protocol(tag_protocol);
-	if (IS_ERR(dst->tag_ops)) {
+	err = dsa_master_tag_protocol(dst->master);
+	if (err) {
 		dev_warn(ds->dev, "No tagger for this switch\n");
 		ds->cpu_port_mask &= ~BIT(index);
-		return PTR_ERR(dst->tag_ops);
+		return err;
 	}
 
-	dst->rcv = dst->tag_ops->rcv;
-
 	return 0;
 }
 
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 4fa14b4305b9..59f155cbbe87 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -66,7 +66,7 @@ struct dsa_notifier_vlan_info {
 };
 
 struct dsa_slave_priv {
-	/* Copy of dp->ds->dst->tag_ops->xmit for faster access in hot path */
+	/* Copy of the master xmit tagging op for faster access in hot path */
 	struct sk_buff *	(*xmit)(struct sk_buff *skb,
 					struct net_device *dev);
 
@@ -115,6 +115,7 @@ struct dsa_master *dsa_master_create(struct dsa_port *port,
 				     struct net_device *netdev);
 int dsa_master_ethtool_setup(struct dsa_master *master);
 void dsa_master_ethtool_restore(struct dsa_master *master);
+int dsa_master_tag_protocol(struct dsa_master *master);
 
 /* port.c */
 int dsa_port_set_state(struct dsa_port *dp, u8 state,
@@ -183,9 +184,4 @@ static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
 	return p->dp->ds->dst->master->netdev;
 }
 
-static inline struct dsa_port *dsa_get_cpu_port(struct dsa_switch_tree *dst)
-{
-	return dst->master->port;
-}
-
 #endif
diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
index acd81c488bf4..3afedd9758c5 100644
--- a/net/dsa/legacy.c
+++ b/net/dsa/legacy.c
@@ -147,14 +147,9 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
 	 * switch.
 	 */
 	if (dst->master->port->ds == ds) {
-		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);
-
-		dst->rcv = dst->tag_ops->rcv;
+		ret = dsa_master_tag_protocol(dst->master);
+		if (ret)
+			return ret;
 	}
 
 	memcpy(ds->rtable, cd->rtable, sizeof(ds->rtable));
@@ -607,7 +602,7 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
 	 * sent to the tag format's receive function.
 	 */
 	wmb();
-	dev->dsa_ptr = dst;
+	dev->dsa_ptr = dst->master;
 
 	return 0;
 }
diff --git a/net/dsa/master.c b/net/dsa/master.c
index 9ecce3e7c8df..6714750ee13f 100644
--- a/net/dsa/master.c
+++ b/net/dsa/master.c
@@ -16,8 +16,7 @@ static void dsa_master_get_ethtool_stats(struct net_device *dev,
 					 struct ethtool_stats *stats,
 					 uint64_t *data)
 {
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_master *master = dst->master;
+	struct dsa_master *master = dev->dsa_ptr;
 	struct dsa_port *port = master->port;
 	struct dsa_switch *ds = port->ds;
 	int count = 0;
@@ -33,8 +32,7 @@ static void dsa_master_get_ethtool_stats(struct net_device *dev,
 
 static int dsa_master_get_sset_count(struct net_device *dev, int sset)
 {
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_master *master = dst->master;
+	struct dsa_master *master = dev->dsa_ptr;
 	struct dsa_port *port = master->port;
 	struct dsa_switch *ds = port->ds;
 	int count = 0;
@@ -51,8 +49,7 @@ static int dsa_master_get_sset_count(struct net_device *dev, int sset)
 static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset,
 				   uint8_t *data)
 {
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_master *master = dst->master;
+	struct dsa_master *master = dev->dsa_ptr;
 	struct dsa_port *port = master->port;
 	struct dsa_switch *ds = port->ds;
 	int len = ETH_GSTRING_LEN;
@@ -116,6 +113,25 @@ void dsa_master_ethtool_restore(struct dsa_master *master)
 	master->orig_ethtool_ops = NULL;
 }
 
+int dsa_master_tag_protocol(struct dsa_master *master)
+{
+	struct dsa_switch *ds = master->port->ds;
+	enum dsa_tag_protocol proto;
+
+	if (!ds->ops->get_tag_protocol)
+		return -EOPNOTSUPP;
+
+	proto = ds->ops->get_tag_protocol(ds);
+
+	master->tag_ops = dsa_resolve_tag_protocol(proto);
+	if (IS_ERR(master->tag_ops))
+		return PTR_ERR(master->tag_ops);
+
+	master->rcv = master->tag_ops->rcv;
+
+	return 0;
+}
+
 struct dsa_master *dsa_master_create(struct dsa_port *port,
 				     struct net_device *netdev)
 {
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 99f9e48a6cee..d5a03ef8d0e0 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1206,7 +1206,7 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
 	}
 	p->dp = port;
 	INIT_LIST_HEAD(&p->mall_tc_list);
-	p->xmit = dst->tag_ops->xmit;
+	p->xmit = dst->master->tag_ops->xmit;
 
 	p->old_pause = -1;
 	p->old_link = -1;
diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c
index de74c3f77818..417266f23bed 100644
--- a/net/dsa/tag_brcm.c
+++ b/net/dsa/tag_brcm.c
@@ -91,9 +91,8 @@ static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev
 static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
 				    struct packet_type *pt)
 {
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
-	struct dsa_switch *ds = cpu_dp->ds;
+	struct dsa_master *master = dev->dsa_ptr;
+	struct dsa_switch *ds = master->port->ds;
 	int source_port;
 	u8 *brcm_tag;
 
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
index fbf9ca954773..7897bbd1a110 100644
--- a/net/dsa/tag_dsa.c
+++ b/net/dsa/tag_dsa.c
@@ -67,7 +67,8 @@ static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev)
 static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev,
 			       struct packet_type *pt)
 {
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
+	struct dsa_master *master = dev->dsa_ptr;
+	struct dsa_switch_tree *dst = master->port->ds->dst;
 	struct dsa_switch *ds;
 	u8 *dsa_header;
 	int source_device;
diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c
index 76367ba1b2e2..12f9efed6251 100644
--- a/net/dsa/tag_edsa.c
+++ b/net/dsa/tag_edsa.c
@@ -80,7 +80,8 @@ static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)
 static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev,
 				struct packet_type *pt)
 {
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
+	struct dsa_master *master = dev->dsa_ptr;
+	struct dsa_switch_tree *dst = master->port->ds->dst;
 	struct dsa_switch *ds;
 	u8 *edsa_header;
 	int source_device;
diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
index 17f30675c15c..7043d51a7a80 100644
--- a/net/dsa/tag_ksz.c
+++ b/net/dsa/tag_ksz.c
@@ -78,9 +78,8 @@ static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev)
 static struct sk_buff *ksz_rcv(struct sk_buff *skb, struct net_device *dev,
 			       struct packet_type *pt)
 {
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
-	struct dsa_switch *ds = cpu_dp->ds;
+	struct dsa_master *master = dev->dsa_ptr;
+	struct dsa_switch *ds = master->port->ds;
 	u8 *tag;
 	int source_port;
 
diff --git a/net/dsa/tag_lan9303.c b/net/dsa/tag_lan9303.c
index 0b9826105e42..afb3df46712a 100644
--- a/net/dsa/tag_lan9303.c
+++ b/net/dsa/tag_lan9303.c
@@ -70,13 +70,11 @@ static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev)
 static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
 			struct packet_type *pt)
 {
+	struct dsa_master *master = dev->dsa_ptr;
+	struct dsa_switch *ds = master->port->ds;
 	u16 *lan9303_tag;
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_switch *ds;
 	unsigned int source_port;
 
-	ds = dst->ds[0];
-
 	if (unlikely(!ds)) {
 		dev_warn_ratelimited(&dev->dev, "Dropping packet, due to missing DSA switch device\n");
 		return NULL;
diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index ec8ee5f43255..7af26afaa8ac 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -46,8 +46,8 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
 static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
 				   struct packet_type *pt)
 {
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_switch *ds;
+	struct dsa_master *master = dev->dsa_ptr;
+	struct dsa_switch *ds = master->port->ds;
 	int port;
 	__be16 *phdr, hdr;
 
@@ -68,14 +68,6 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
 		skb->data - ETH_HLEN - MTK_HDR_LEN,
 		2 * ETH_ALEN);
 
-	/* This protocol doesn't support cascading multiple
-	 * switches so it's safe to assume the switch is first
-	 * in the tree.
-	 */
-	ds = dst->ds[0];
-	if (!ds)
-		return NULL;
-
 	/* Get source port information */
 	port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK);
 	if (!ds->ports[port].netdev)
diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c
index 1d4c70711c0f..a49cc7c6fac9 100644
--- a/net/dsa/tag_qca.c
+++ b/net/dsa/tag_qca.c
@@ -65,9 +65,8 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev)
 static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
 				   struct packet_type *pt)
 {
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
-	struct dsa_switch *ds;
+	struct dsa_master *master = dev->dsa_ptr;
+	struct dsa_switch *ds = master->port->ds;
 	u8 ver;
 	int port;
 	__be16 *phdr, hdr;
@@ -92,13 +91,6 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
 	memmove(skb->data - ETH_HLEN, skb->data - ETH_HLEN - QCA_HDR_LEN,
 		ETH_HLEN - QCA_HDR_LEN);
 
-	/* This protocol doesn't support cascading multiple switches so it's
-	 * safe to assume the switch is first in the tree
-	 */
-	ds = cpu_dp->ds;
-	if (!ds)
-		return NULL;
-
 	/* Get source port information */
 	port = (hdr & QCA_HDR_RECV_SOURCE_PORT_MASK);
 	if (!ds->ports[port].netdev)
diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c
index 8707157dea32..a3dacfb48dc0 100644
--- a/net/dsa/tag_trailer.c
+++ b/net/dsa/tag_trailer.c
@@ -58,9 +58,8 @@ static struct sk_buff *trailer_xmit(struct sk_buff *skb, struct net_device *dev)
 static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev,
 				   struct packet_type *pt)
 {
-	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
-	struct dsa_switch *ds = cpu_dp->ds;
+	struct dsa_master *master = dev->dsa_ptr;
+	struct dsa_switch *ds = master->port->ds;
 	u8 *trailer;
 	int source_port;
 
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH net-next 4/4] net: dsa: assign a master to slave ports
  2017-08-31 18:37 [PATCH net-next 0/4] net: dsa: add master interface Vivien Didelot
                   ` (2 preceding siblings ...)
  2017-08-31 18:37 ` [PATCH net-next 3/4] net: dsa: change dsa_ptr for a dsa_master Vivien Didelot
@ 2017-08-31 18:37 ` Vivien Didelot
  2017-09-02 15:34   ` Andrew Lunn
  2017-09-02 16:42 ` [PATCH net-next 0/4] net: dsa: add master interface Florian Fainelli
  4 siblings, 1 reply; 9+ messages in thread
From: Vivien Didelot @ 2017-08-31 18:37 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot

Because each DSA slave port may use a different DSA master port, add a
pointer to a master in the slave structure. This is a preparatory patch
for multiple CPU ports.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/dsa_priv.h |  7 ++-----
 net/dsa/slave.c    | 33 ++++++++++++++++++---------------
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 59f155cbbe87..a8cd6cbe4061 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -66,6 +66,8 @@ struct dsa_notifier_vlan_info {
 };
 
 struct dsa_slave_priv {
+	struct dsa_master *master;
+
 	/* Copy of the master xmit tagging op for faster access in hot path */
 	struct sk_buff *	(*xmit)(struct sk_buff *skb,
 					struct net_device *dev);
@@ -179,9 +181,4 @@ extern const struct dsa_device_ops qca_netdev_ops;
 /* tag_trailer.c */
 extern const struct dsa_device_ops trailer_netdev_ops;
 
-static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
-{
-	return p->dp->ds->dst->master->netdev;
-}
-
 #endif
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index d5a03ef8d0e0..107ed0c4a850 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -66,7 +66,7 @@ static int dsa_slave_get_iflink(const struct net_device *dev)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
 
-	return dsa_master_netdev(p)->ifindex;
+	return p->master->netdev->ifindex;
 }
 
 static int dsa_slave_open(struct net_device *dev)
@@ -74,7 +74,7 @@ static int dsa_slave_open(struct net_device *dev)
 	struct dsa_slave_priv *p = netdev_priv(dev);
 	struct dsa_port *dp = p->dp;
 	struct dsa_switch *ds = dp->ds;
-	struct net_device *master = dsa_master_netdev(p);
+	struct net_device *master = p->master->netdev;
 	u8 stp_state = dp->bridge_dev ? BR_STATE_BLOCKING : BR_STATE_FORWARDING;
 	int err;
 
@@ -127,7 +127,7 @@ static int dsa_slave_open(struct net_device *dev)
 static int dsa_slave_close(struct net_device *dev)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
-	struct net_device *master = dsa_master_netdev(p);
+	struct net_device *master = p->master->netdev;
 	struct dsa_switch *ds = p->dp->ds;
 
 	if (p->phy)
@@ -154,7 +154,7 @@ static int dsa_slave_close(struct net_device *dev)
 static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
-	struct net_device *master = dsa_master_netdev(p);
+	struct net_device *master = p->master->netdev;
 
 	if (change & IFF_ALLMULTI)
 		dev_set_allmulti(master, dev->flags & IFF_ALLMULTI ? 1 : -1);
@@ -165,7 +165,7 @@ static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
 static void dsa_slave_set_rx_mode(struct net_device *dev)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
-	struct net_device *master = dsa_master_netdev(p);
+	struct net_device *master = p->master->netdev;
 
 	dev_mc_sync(master, dev);
 	dev_uc_sync(master, dev);
@@ -174,7 +174,7 @@ static void dsa_slave_set_rx_mode(struct net_device *dev)
 static int dsa_slave_set_mac_address(struct net_device *dev, void *a)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
-	struct net_device *master = dsa_master_netdev(p);
+	struct net_device *master = p->master->netdev;
 	struct sockaddr *addr = a;
 	int err;
 
@@ -427,7 +427,7 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* Queue the SKB for transmission on the parent interface, but
 	 * do not modify its EtherType
 	 */
-	nskb->dev = dsa_master_netdev(p);
+	nskb->dev = p->master->netdev;
 	dev_queue_xmit(nskb);
 
 	return NETDEV_TX_OK;
@@ -687,7 +687,7 @@ static int dsa_slave_netpoll_setup(struct net_device *dev,
 				   struct netpoll_info *ni)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
-	struct net_device *master = dsa_master_netdev(p);
+	struct net_device *master = p->master->netdev;
 	struct netpoll *netpoll;
 	int err = 0;
 
@@ -1170,7 +1170,7 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
 {
 	struct dsa_switch *ds = port->ds;
 	struct dsa_switch_tree *dst = ds->dst;
-	struct net_device *master = dst->master->netdev;
+	struct dsa_master *master = dst->master;
 	struct net_device *slave_dev;
 	struct dsa_slave_priv *p;
 	int ret;
@@ -1180,10 +1180,10 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
 	if (slave_dev == NULL)
 		return -ENOMEM;
 
-	slave_dev->features = master->vlan_features | NETIF_F_HW_TC;
+	slave_dev->features = master->netdev->vlan_features | NETIF_F_HW_TC;
 	slave_dev->hw_features |= NETIF_F_HW_TC;
 	slave_dev->ethtool_ops = &dsa_slave_ethtool_ops;
-	eth_hw_addr_inherit(slave_dev, master);
+	eth_hw_addr_inherit(slave_dev, master->netdev);
 	slave_dev->priv_flags |= IFF_NO_QUEUE;
 	slave_dev->netdev_ops = &dsa_slave_netdev_ops;
 	slave_dev->switchdev_ops = &dsa_slave_switchdev_ops;
@@ -1196,7 +1196,7 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
 
 	SET_NETDEV_DEV(slave_dev, port->ds->dev);
 	slave_dev->dev.of_node = port->dn;
-	slave_dev->vlan_features = master->vlan_features;
+	slave_dev->vlan_features = master->netdev->vlan_features;
 
 	p = netdev_priv(slave_dev);
 	p->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
@@ -1206,7 +1206,8 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
 	}
 	p->dp = port;
 	INIT_LIST_HEAD(&p->mall_tc_list);
-	p->xmit = dst->master->tag_ops->xmit;
+	p->master = master;
+	p->xmit = master->tag_ops->xmit;
 
 	p->old_pause = -1;
 	p->old_link = -1;
@@ -1215,7 +1216,8 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
 	port->netdev = slave_dev;
 	ret = register_netdev(slave_dev);
 	if (ret) {
-		netdev_err(master, "error %d registering interface %s\n",
+		netdev_err(master->netdev,
+			   "error %d registering interface %s\n",
 			   ret, slave_dev->name);
 		port->netdev = NULL;
 		free_percpu(p->stats64);
@@ -1227,7 +1229,8 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
 
 	ret = dsa_slave_phy_setup(p, slave_dev);
 	if (ret) {
-		netdev_err(master, "error %d setting up slave phy\n", ret);
+		netdev_err(master->netdev,
+			   "error %d setting up slave phy\n", ret);
 		unregister_netdev(slave_dev);
 		free_percpu(p->stats64);
 		free_netdev(slave_dev);
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next 3/4] net: dsa: change dsa_ptr for a dsa_master
  2017-08-31 18:37 ` [PATCH net-next 3/4] net: dsa: change dsa_ptr for a dsa_master Vivien Didelot
@ 2017-09-02 15:30   ` Andrew Lunn
  0 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2017-09-02 15:30 UTC (permalink / raw)
  To: Vivien Didelot
  Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli

Hi Vivien


> diff --git a/include/net/dsa.h b/include/net/dsa.h
> index f4a5afc4255b..d5b24cd10f79 100644
> --- a/include/net/dsa.h
> +++ b/include/net/dsa.h
> @@ -130,11 +130,6 @@ struct dsa_switch_tree {
>  	 */
>  	struct dsa_platform_data	*pd;
>  
> -	/* Copy of tag_ops->rcv for faster access in hot path */
> -	struct sk_buff *	(*rcv)(struct sk_buff *skb,
> -				       struct net_device *dev,
> -				       struct packet_type *pt);
> -
>  	/*
>  	 * The switch port to which the CPU is attached.
>  	 */


> diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
> index fbf9ca954773..7897bbd1a110 100644
> --- a/net/dsa/tag_dsa.c
> +++ b/net/dsa/tag_dsa.c
> @@ -67,7 +67,8 @@ static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev)
>  static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev,
>  			       struct packet_type *pt)
>  {
> -	struct dsa_switch_tree *dst = dev->dsa_ptr;
> +	struct dsa_master *master = dev->dsa_ptr;
> +	struct dsa_switch_tree *dst = master->port->ds->dst;

This is on the hot path. Every frame received comes through here. We
have gone from one dereference to 4 dereference. That is going to
impact performance. 

How about keeping a copy of dst and ds in master?

    Andrew

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next 4/4] net: dsa: assign a master to slave ports
  2017-08-31 18:37 ` [PATCH net-next 4/4] net: dsa: assign a master to slave ports Vivien Didelot
@ 2017-09-02 15:34   ` Andrew Lunn
  2017-09-02 16:29     ` Florian Fainelli
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Lunn @ 2017-09-02 15:34 UTC (permalink / raw)
  To: Vivien Didelot
  Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli

On Thu, Aug 31, 2017 at 02:37:46PM -0400, Vivien Didelot wrote:
> Because each DSA slave port may use a different DSA master port, add a
> pointer to a master in the slave structure. This is a preparatory patch
> for multiple CPU ports.
> 
> Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
> ---
>  net/dsa/dsa_priv.h |  7 ++-----
>  net/dsa/slave.c    | 33 ++++++++++++++++++---------------
>  2 files changed, 20 insertions(+), 20 deletions(-)
> 
> diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
> index 59f155cbbe87..a8cd6cbe4061 100644
> --- a/net/dsa/dsa_priv.h
> +++ b/net/dsa/dsa_priv.h
> @@ -66,6 +66,8 @@ struct dsa_notifier_vlan_info {
>  };
>  
>  struct dsa_slave_priv {
> +	struct dsa_master *master;
> +
>  	/* Copy of the master xmit tagging op for faster access in hot path */
>  	struct sk_buff *	(*xmit)(struct sk_buff *skb,
>  					struct net_device *dev);
> @@ -179,9 +181,4 @@ extern const struct dsa_device_ops qca_netdev_ops;
>  /* tag_trailer.c */
>  extern const struct dsa_device_ops trailer_netdev_ops;
>  
> -static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
> -{
> -	return p->dp->ds->dst->master->netdev;
> -}
> -

Hi Vivien

Why remove this helper, when it could become p->master->netdev ?

    Andrew

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next 4/4] net: dsa: assign a master to slave ports
  2017-09-02 15:34   ` Andrew Lunn
@ 2017-09-02 16:29     ` Florian Fainelli
  0 siblings, 0 replies; 9+ messages in thread
From: Florian Fainelli @ 2017-09-02 16:29 UTC (permalink / raw)
  To: Andrew Lunn, Vivien Didelot; +Cc: netdev, linux-kernel, kernel, David S. Miller



On 09/02/2017 08:34 AM, Andrew Lunn wrote:
> On Thu, Aug 31, 2017 at 02:37:46PM -0400, Vivien Didelot wrote:
>> Because each DSA slave port may use a different DSA master port, add a
>> pointer to a master in the slave structure. This is a preparatory patch
>> for multiple CPU ports.
>>
>> Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
>> ---
>>  net/dsa/dsa_priv.h |  7 ++-----
>>  net/dsa/slave.c    | 33 ++++++++++++++++++---------------
>>  2 files changed, 20 insertions(+), 20 deletions(-)
>>
>> diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
>> index 59f155cbbe87..a8cd6cbe4061 100644
>> --- a/net/dsa/dsa_priv.h
>> +++ b/net/dsa/dsa_priv.h
>> @@ -66,6 +66,8 @@ struct dsa_notifier_vlan_info {
>>  };
>>  
>>  struct dsa_slave_priv {
>> +	struct dsa_master *master;
>> +
>>  	/* Copy of the master xmit tagging op for faster access in hot path */
>>  	struct sk_buff *	(*xmit)(struct sk_buff *skb,
>>  					struct net_device *dev);
>> @@ -179,9 +181,4 @@ extern const struct dsa_device_ops qca_netdev_ops;
>>  /* tag_trailer.c */
>>  extern const struct dsa_device_ops trailer_netdev_ops;
>>  
>> -static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
>> -{
>> -	return p->dp->ds->dst->master->netdev;
>> -}
>> -
> 
> Hi Vivien
> 
> Why remove this helper, when it could become p->master->netdev ?

Agreed, I would keep the helper at this point to minimize the delta, it
should really identical in terms of code generated.
-- 
Florian

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next 0/4] net: dsa: add master interface
  2017-08-31 18:37 [PATCH net-next 0/4] net: dsa: add master interface Vivien Didelot
                   ` (3 preceding siblings ...)
  2017-08-31 18:37 ` [PATCH net-next 4/4] net: dsa: assign a master to slave ports Vivien Didelot
@ 2017-09-02 16:42 ` Florian Fainelli
  4 siblings, 0 replies; 9+ messages in thread
From: Florian Fainelli @ 2017-09-02 16:42 UTC (permalink / raw)
  To: Vivien Didelot, netdev; +Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn

Hi Vivien,

On 08/31/2017 11:37 AM, Vivien Didelot wrote:
> Currently the SoC network interface (called master) to which a switch
> fabric hangs, has its dsa_ptr pointing to a dsa_switch_tree instance.
> 
> This is not quite correct, because this interface is physically wired to
> one of the switch ports (called CPU port), and because in a switch
> fabric with multiple CPU ports, several master interfaces will point to
> several CPU ports of the same dsa_switch_tree.
> 
> This patchset adds a new dsa_master structure to represent the pipe
> between the SoC master interface and its switch CPU port. This structure
> will store specific data such as the master ethtool_ops copy and the
> tagging protocol used to pass frames with the associated slave ports.
> The dsa_ptr is changed to a dsa_master instance, and each DSA slave now
> has a pointer to a master port.
> 
> This is a step forward better control over the CPU conduit and support
> for multiple CPU ports.

Looked briefly over this series and this looks good to me, Andrew has a
valid point about reducing the number of dereferences in hot paths
though. Thanks!

> 
> Vivien Didelot (4):
>   net: dsa: introduce dsa_master
>   net: dsa: move master ethtool ops in dsa_master
>   net: dsa: change dsa_ptr for a dsa_master
>   net: dsa: assign a master to slave ports
> 
>  drivers/net/dsa/b53/b53_common.c |   4 +-
>  drivers/net/dsa/bcm_sf2.c        |   8 +--
>  drivers/net/dsa/mt7530.c         |   4 +-
>  drivers/net/dsa/mv88e6060.c      |   2 +-
>  drivers/net/dsa/qca8k.c          |   2 +-
>  include/linux/netdevice.h        |   4 +-
>  include/net/dsa.h                |  42 +++++------
>  net/dsa/Makefile                 |   2 +-
>  net/dsa/dsa.c                    |  34 +--------
>  net/dsa/dsa2.c                   |  38 +++++-----
>  net/dsa/dsa_priv.h               |  24 +++----
>  net/dsa/legacy.c                 |  34 +++++----
>  net/dsa/master.c                 | 149 +++++++++++++++++++++++++++++++++++++++
>  net/dsa/slave.c                  | 117 +++++-------------------------
>  net/dsa/tag_brcm.c               |   5 +-
>  net/dsa/tag_dsa.c                |   3 +-
>  net/dsa/tag_edsa.c               |   3 +-
>  net/dsa/tag_ksz.c                |   5 +-
>  net/dsa/tag_lan9303.c            |   6 +-
>  net/dsa/tag_mtk.c                |  12 +---
>  net/dsa/tag_qca.c                |  12 +---
>  net/dsa/tag_trailer.c            |   5 +-
>  22 files changed, 265 insertions(+), 250 deletions(-)
>  create mode 100644 net/dsa/master.c
> 

-- 
Florian

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2017-09-02 16:42 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-31 18:37 [PATCH net-next 0/4] net: dsa: add master interface Vivien Didelot
2017-08-31 18:37 ` [PATCH net-next 1/4] net: dsa: introduce dsa_master Vivien Didelot
2017-08-31 18:37 ` [PATCH net-next 2/4] net: dsa: move master ethtool ops in dsa_master Vivien Didelot
2017-08-31 18:37 ` [PATCH net-next 3/4] net: dsa: change dsa_ptr for a dsa_master Vivien Didelot
2017-09-02 15:30   ` Andrew Lunn
2017-08-31 18:37 ` [PATCH net-next 4/4] net: dsa: assign a master to slave ports Vivien Didelot
2017-09-02 15:34   ` Andrew Lunn
2017-09-02 16:29     ` Florian Fainelli
2017-09-02 16:42 ` [PATCH net-next 0/4] net: dsa: add master interface Florian Fainelli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).