[PATCH] parser: Use a series even if the version differs

Stephen Finucane stephen at that.guru
Mon Jun 26 06:55:09 AEST 2017


Currently, once we've found a series for a new submission, we check to
ensure that the version of that series matches that of the submission,
and we discard the series if not. The original intention for this was
given in commit 'c21b30525', where this was added:

  There are some things you probably shouldn't do on public mailing
  lists, but which people do anyway.

  - [PATCH 1/2] test: Add some lorem ipsum
    - [PATCH 2/2] test: Convert to Markdown
      - [PATCH v2 1/2] test: Add some lorem ipsum
        - [PATCH v2 2/2] test: Convert to Markdown

  We should correctly parse these...

This is unnecessary for two reasons:

- If the series is using proper references, then the mechanism that
  we use to prevent this issue with unversioned follow ups (also added
  in that patch) will work here: namely, we don't add submissions if an
  submission with a given number already exists in that series.
- If the series is not using references, we already have a check for
  version.

Seeing as this check is actually causing issues for legitimate typos, we
should just remove this check. Do so, adding a check to ensure we don't
regress.

Signed-off-by: Stephen Finucane <stephen at that.guru>
Closes-bug: #105
---
 patchwork/parser.py                                |   1 -
 .../tests/series/base-different-versions.mbox      | 908 +++++++++++++++++++++
 patchwork/tests/test_series.py                     |  18 +
 3 files changed, 926 insertions(+), 1 deletion(-)
 create mode 100644 patchwork/tests/series/base-different-versions.mbox

diff --git a/patchwork/parser.py b/patchwork/parser.py
index 794a5ea..c43fe76 100644
--- a/patchwork/parser.py
+++ b/patchwork/parser.py
@@ -911,7 +911,6 @@ def parse_mail(mail, list_id=None):
         #    * the version doesn't match
         #    * we have a patch with this number already
         if n and ((not series) or
-                  (series.version != version) or
                   (SeriesPatch.objects.filter(series=series, number=x).count()
                    )):
             series = Series(project=project,
diff --git a/patchwork/tests/series/base-different-versions.mbox b/patchwork/tests/series/base-different-versions.mbox
new file mode 100644
index 0000000..85bf888
--- /dev/null
+++ b/patchwork/tests/series/base-different-versions.mbox
@@ -0,0 +1,908 @@
+From f.fainelli at gmail.com Tue Jun 13 19:17:21 2017
+From: Florian Fainelli <f.fainelli at gmail.com>
+To: netdev at vger.kernel.org
+Cc: davem at davemloft.net, andrew at lunn.ch,
+	vivien.didelot at savoirfairelinux.com, john at phrozen.org,
+	Florian Fainelli <f.fainelli at gmail.com>
+Subject: [PATCH net-next v3 0/4] net: dsa: Multi-CPU ground work (v3)
+Date: Tue, 13 Jun 2017 12:17:21 -0700
+Message-Id: <20170613191725.26625-1-f.fainelli at gmail.com>
+X-Mailer: git-send-email 2.9.3
+List-ID: <netdev.vger.kernel.org>
+
+Hi all,
+
+This patch series prepares the ground for adding mutliple CPU port support to
+DSA, and starts by removing redundant pieces of information such as
+master_netdev which is cpu_dp->ethernet. Finally drivers are moved away from
+directly accessing ds->dst->cpu_dp and use appropriate helper functions.
+
+Note that if you have Device Tree blobs/platform configurations that are
+currently listing multiple CPU ports, the proposed behavior in
+dsa_ds_get_cpu_dp() will be to return the last bit set in ds->cpu_port_mask.
+
+Future plans include:
+- making dst->cpu_dp a flexible data structure (array, list, you name it)
+- having the ability for drivers to return a default/preferred CPU port (if
+  necessary)
+
+Changes in v3:
+
+- removed the last patch since it causes problems with bcm_sf2/b53 in a
+  dual-CPU case (root cause known, proper fix underway)
+
+- removed dsa_ds_get_cpu_dp()
+
+Changes in v2:
+
+- added Reviewed-by tags
+- assign port->cpu_dp earlier before ops->setup() has run
+
+Florian Fainelli (5):
+  net: dsa: Remove master_netdev and use dst->cpu_dp->netdev
+  net: dsa: Relocate master ethtool operations
+  net: dsa: Associate slave network device with CPU port
+  net: dsa: Introduce dsa_dst_get_cpu_dp()
+  net: dsa: Stop accessing ds->dst->cpu_dp in drivers
+
+ drivers/net/dsa/b53/b53_common.c |  4 +--
+ drivers/net/dsa/bcm_sf2.c        | 10 +++++---
+ drivers/net/dsa/mt7530.c         |  6 +++--
+ drivers/net/dsa/mv88e6060.c      |  2 +-
+ drivers/net/dsa/qca8k.c          |  2 +-
+ include/net/dsa.h                | 29 +++++++++-------------
+ net/dsa/dsa.c                    | 19 ++++----------
+ net/dsa/dsa2.c                   | 27 ++++++++++++--------
+ net/dsa/dsa_priv.h               | 10 ++++++++
+ net/dsa/legacy.c                 | 23 ++++++++++-------
+ net/dsa/slave.c                  | 53 ++++++++++++++++++++--------------------
+ net/dsa/tag_brcm.c               |  5 ++--
+ net/dsa/tag_ksz.c                |  5 ++--
+ net/dsa/tag_qca.c                |  3 ++-
+ net/dsa/tag_trailer.c            |  5 ++--
+ 15 files changed, 107 insertions(+), 96 deletions(-)
+
+
+From f.fainelli at gmail.com Tue Jun 13 19:17:22 2017
+From: Florian Fainelli <f.fainelli at gmail.com>
+To: netdev at vger.kernel.org
+Cc: davem at davemloft.net, andrew at lunn.ch,
+	vivien.didelot at savoirfairelinux.com, john at phrozen.org,
+	Florian Fainelli <f.fainelli at gmail.com>
+Subject: [PATCH 1/4] net: dsa: Remove master_netdev and use
+	dst->cpu_dp->netdev
+Date: Tue, 13 Jun 2017 12:17:22 -0700
+Message-Id: <20170613191725.26625-2-f.fainelli at gmail.com>
+X-Mailer: git-send-email 2.9.3
+In-Reply-To: <20170613191725.26625-1-f.fainelli at gmail.com>
+References: <20170613191725.26625-1-f.fainelli at gmail.com>
+List-ID: <netdev.vger.kernel.org>
+
+In preparation for supporting multiple CPU ports, remove
+dst->master_netdev and ds->master_netdev and replace them with only one
+instance of the common object we have for a port: struct
+dsa_port::netdev. ds->master_netdev is currently write only and would be
+helpful in the case where we have two switches, both with CPU ports, and
+also connected within each other, which the multi-CPU port patch series
+would address.
+
+While at it, introduce a helper function used in net/dsa/slave.c to
+immediately get a reference on the master network device called
+dsa_master_netdev().
+
+Reviewed-by: Vivien Didelot <vivien.didelot at savoirfairelinux.com>
+Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
+---
+ drivers/net/dsa/bcm_sf2.c |  4 ++--
+ drivers/net/dsa/mt7530.c  |  4 ++--
+ include/net/dsa.h         |  5 -----
+ net/dsa/dsa.c             |  9 ++-------
+ net/dsa/dsa2.c            | 18 +++++++-----------
+ net/dsa/dsa_priv.h        |  5 +++++
+ net/dsa/legacy.c          | 22 +++++++++++++---------
+ net/dsa/slave.c           | 20 +++++++++-----------
+ 8 files changed, 40 insertions(+), 47 deletions(-)
+
+diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
+index 687a8bae5d73..76e98e8ed315 100644
+--- a/drivers/net/dsa/bcm_sf2.c
++++ b/drivers/net/dsa/bcm_sf2.c
+@@ -806,7 +806,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[ds->index].master_netdev;
++	struct net_device *p = ds->dst[ds->index].cpu_dp->netdev;
+ 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
+ 	struct ethtool_wolinfo pwol;
+ 
+@@ -829,7 +829,7 @@ 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[ds->index].master_netdev;
++	struct net_device *p = ds->dst[ds->index].cpu_dp->netdev;
+ 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
+ 	s8 cpu_port = ds->dst->cpu_dp->index;
+ 	struct ethtool_wolinfo pwol;
+diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
+index 25e00d5e0eec..1e46418a3b74 100644
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -912,11 +912,11 @@ mt7530_setup(struct dsa_switch *ds)
+ 	struct device_node *dn;
+ 	struct mt7530_dummy_poll p;
+ 
+-	/* The parent node of master_netdev which holds the common system
++	/* The parent node of cpu_dp->netdev which holds the common system
+ 	 * controller also is the container for two GMACs nodes representing
+ 	 * as two netdev instances.
+ 	 */
+-	dn = ds->master_netdev->dev.of_node->parent;
++	dn = ds->dst->cpu_dp->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/include/net/dsa.h b/include/net/dsa.h
+index 2effb0af9d7c..b2fb53f5e28e 100644
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -227,11 +227,6 @@ struct dsa_switch {
+ 	s8		rtable[DSA_MAX_SWITCHES];
+ 
+ 	/*
+-	 * The lower device this switch uses to talk to the host
+-	 */
+-	struct net_device *master_netdev;
+-
+-	/*
+ 	 * Slave mii_bus and devices for the individual ports.
+ 	 */
+ 	u32			dsa_port_mask;
+diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
+index 517215391514..6aacc2314a8f 100644
+--- a/net/dsa/dsa.c
++++ b/net/dsa/dsa.c
+@@ -118,10 +118,7 @@ int dsa_cpu_port_ethtool_setup(struct dsa_port *cpu_dp)
+ 	struct net_device *master;
+ 	struct ethtool_ops *cpu_ops;
+ 
+-	master = ds->dst->master_netdev;
+-	if (ds->master_netdev)
+-		master = ds->master_netdev;
+-
++	master = ds->dst->cpu_dp->netdev;
+ 	cpu_ops = devm_kzalloc(ds->dev, sizeof(*cpu_ops), GFP_KERNEL);
+ 	if (!cpu_ops)
+ 		return -ENOMEM;
+@@ -142,9 +139,7 @@ void dsa_cpu_port_ethtool_restore(struct dsa_port *cpu_dp)
+ 	struct dsa_switch *ds = cpu_dp->ds;
+ 	struct net_device *master;
+ 
+-	master = ds->dst->master_netdev;
+-	if (ds->master_netdev)
+-		master = ds->master_netdev;
++	master = ds->dst->cpu_dp->netdev;
+ 
+ 	master->ethtool_ops = ds->dst->master_orig_ethtool_ops;
+ }
+diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
+index f88e1dddb74a..ab48c4f989da 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->master_netdev->dev_addr);
++		err = ds->ops->set_addr(ds, dst->cpu_dp->netdev->dev_addr);
+ 		if (err < 0)
+ 			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->master_netdev->dsa_ptr = dst;
++	dst->cpu_dp->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->master_netdev->dsa_ptr = NULL;
++	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
+@@ -504,14 +504,10 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
+ 	if (!ethernet_dev)
+ 		return -EPROBE_DEFER;
+ 
+-	if (!ds->master_netdev)
+-		ds->master_netdev = ethernet_dev;
+-
+-	if (!dst->master_netdev)
+-		dst->master_netdev = ethernet_dev;
+-
+-	if (!dst->cpu_dp)
++	if (!dst->cpu_dp) {
+ 		dst->cpu_dp = port;
++		dst->cpu_dp->netdev = ethernet_dev;
++	}
+ 
+ 	tag_protocol = ds->ops->get_tag_protocol(ds);
+ 	dst->tag_ops = dsa_resolve_tag_protocol(tag_protocol);
+@@ -578,7 +574,7 @@ static int dsa_dst_parse(struct dsa_switch_tree *dst)
+ 			return err;
+ 	}
+ 
+-	if (!dst->master_netdev) {
++	if (!dst->cpu_dp->netdev) {
+ 		pr_warn("Tree has no master device\n");
+ 		return -EINVAL;
+ 	}
+diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
+index 66ee248796c8..5c510f4ba0ce 100644
+--- a/net/dsa/dsa_priv.h
++++ b/net/dsa/dsa_priv.h
+@@ -183,4 +183,9 @@ 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->cpu_dp->netdev;
++}
++
+ #endif
+diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
+index 3a56de8f51a8..5d4f6ffa3424 100644
+--- a/net/dsa/legacy.c
++++ b/net/dsa/legacy.c
+@@ -101,9 +101,12 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
+ 	struct dsa_switch_tree *dst = ds->dst;
+ 	struct dsa_chip_data *cd = ds->cd;
+ 	bool valid_name_found = false;
++	struct net_device *master;
+ 	int index = ds->index;
+ 	int i, ret;
+ 
++	master = dst->cpu_dp->netdev;
++
+ 	/*
+ 	 * Validate supplied switch configuration.
+ 	 */
+@@ -116,7 +119,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
+ 
+ 		if (!strcmp(name, "cpu")) {
+ 			if (dst->cpu_dp) {
+-				netdev_err(dst->master_netdev,
++				netdev_err(master,
+ 					   "multiple cpu ports?!\n");
+ 				return -EINVAL;
+ 			}
+@@ -168,7 +171,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
+ 		return ret;
+ 
+ 	if (ops->set_addr) {
+-		ret = ops->set_addr(ds, dst->master_netdev->dev_addr);
++		ret = ops->set_addr(ds, master->dev_addr);
+ 		if (ret < 0)
+ 			return ret;
+ 	}
+@@ -195,14 +198,14 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
+ 
+ 		ret = dsa_slave_create(ds, parent, i, cd->port_names[i]);
+ 		if (ret < 0)
+-			netdev_err(dst->master_netdev, "[%d]: can't create dsa slave device for port %d(%s): %d\n",
++			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);
+ 	if (ret < 0)
+-		netdev_err(dst->master_netdev, "[%d] : can't configure CPU and DSA ports\n",
++		netdev_err(master, "[%d] : can't configure CPU and DSA ports\n",
+ 			   index);
+ 
+ 	ret = dsa_cpu_port_ethtool_setup(ds->dst->cpu_dp);
+@@ -217,6 +220,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
+ 		 struct device *parent, struct device *host_dev)
+ {
+ 	struct dsa_chip_data *cd = dst->pd->chip + index;
++	struct net_device *master = dst->cpu_dp->netdev;
+ 	const struct dsa_switch_ops *ops;
+ 	struct dsa_switch *ds;
+ 	int ret;
+@@ -228,11 +232,11 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
+ 	 */
+ 	ops = dsa_switch_probe(parent, host_dev, cd->sw_addr, &name, &priv);
+ 	if (!ops) {
+-		netdev_err(dst->master_netdev, "[%d]: could not detect attached switch\n",
++		netdev_err(master, "[%d]: could not detect attached switch\n",
+ 			   index);
+ 		return ERR_PTR(-EINVAL);
+ 	}
+-	netdev_info(dst->master_netdev, "[%d]: detected a %s switch\n",
++	netdev_info(master, "[%d]: detected a %s switch\n",
+ 		    index, name);
+ 
+ 
+@@ -575,7 +579,7 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
+ 	unsigned configured = 0;
+ 
+ 	dst->pd = pd;
+-	dst->master_netdev = dev;
++	dst->cpu_dp->netdev = dev;
+ 
+ 	for (i = 0; i < pd->nr_chips; i++) {
+ 		struct dsa_switch *ds;
+@@ -671,7 +675,7 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
+ {
+ 	int i;
+ 
+-	dst->master_netdev->dsa_ptr = NULL;
++	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
+@@ -688,7 +692,7 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
+ 
+ 	dsa_cpu_port_ethtool_restore(dst->cpu_dp);
+ 
+-	dev_put(dst->master_netdev);
++	dev_put(dst->cpu_dp->netdev);
+ }
+ 
+ static int dsa_remove(struct platform_device *pdev)
+diff --git a/net/dsa/slave.c b/net/dsa/slave.c
+index 5e45ae5c3f71..95031b31d64b 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 p->dp->ds->dst->master_netdev->ifindex;
++	return dsa_master_netdev(p)->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 = ds->dst->master_netdev;
++	struct net_device *master = dsa_master_netdev(p);
+ 	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 = p->dp->ds->dst->master_netdev;
++	struct net_device *master = dsa_master_netdev(p);
+ 	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 = p->dp->ds->dst->master_netdev;
++	struct net_device *master = dsa_master_netdev(p);
+ 
+ 	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 = p->dp->ds->dst->master_netdev;
++	struct net_device *master = dsa_master_netdev(p);
+ 
+ 	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 = p->dp->ds->dst->master_netdev;
++	struct net_device *master = dsa_master_netdev(p);
+ 	struct sockaddr *addr = a;
+ 	int err;
+ 
+@@ -375,7 +375,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 = p->dp->ds->dst->master_netdev;
++	nskb->dev = dsa_master_netdev(p);
+ 	dev_queue_xmit(nskb);
+ 
+ 	return NETDEV_TX_OK;
+@@ -685,7 +685,7 @@ static int dsa_slave_netpoll_setup(struct net_device *dev,
+ {
+ 	struct dsa_slave_priv *p = netdev_priv(dev);
+ 	struct dsa_switch *ds = p->dp->ds;
+-	struct net_device *master = ds->dst->master_netdev;
++	struct net_device *master = dsa_master_netdev(p);
+ 	struct netpoll *netpoll;
+ 	int err = 0;
+ 
+@@ -1143,9 +1143,7 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
+ 	struct dsa_slave_priv *p;
+ 	int ret;
+ 
+-	master = ds->dst->master_netdev;
+-	if (ds->master_netdev)
+-		master = ds->master_netdev;
++	master = ds->dst->cpu_dp->netdev;
+ 
+ 	slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv), name,
+ 				 NET_NAME_UNKNOWN, ether_setup);
+
+
+From f.fainelli at gmail.com Tue Jun 13 19:17:23 2017
+From: Florian Fainelli <f.fainelli at gmail.com>
+To: netdev at vger.kernel.org
+Cc: davem at davemloft.net, andrew at lunn.ch,
+	vivien.didelot at savoirfairelinux.com, john at phrozen.org,
+	Florian Fainelli <f.fainelli at gmail.com>
+Subject: [PATCH 2/4] net: dsa: Relocate master ethtool operations
+Date: Tue, 13 Jun 2017 12:17:23 -0700
+Message-Id: <20170613191725.26625-3-f.fainelli at gmail.com>
+X-Mailer: git-send-email 2.9.3
+In-Reply-To: <20170613191725.26625-1-f.fainelli at gmail.com>
+References: <20170613191725.26625-1-f.fainelli at gmail.com>
+List-ID: <netdev.vger.kernel.org>
+
+Relocate master_ethtool_ops and master_orig_ethtool_ops into struct
+dsa_port in order to be both consistent, and make things self contained
+within the dsa_port structure.
+
+This is a preliminary change to supporting multiple CPU port interfaces.
+
+Reviewed-by: Vivien Didelot <vivien.didelot at savoirfairelinux.com>
+Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
+---
+ include/net/dsa.h | 17 +++++------------
+ net/dsa/dsa.c     | 16 ++++++----------
+ net/dsa/slave.c   | 16 ++++++++--------
+ 3 files changed, 19 insertions(+), 30 deletions(-)
+
+diff --git a/include/net/dsa.h b/include/net/dsa.h
+index b2fb53f5e28e..7e93869819f9 100644
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -122,12 +122,6 @@ struct dsa_switch_tree {
+ 	 */
+ 	struct dsa_platform_data	*pd;
+ 
+-	/*
+-	 * Reference to network device to use, and which tagging
+-	 * protocol to use.
+-	 */
+-	struct net_device	*master_netdev;
+-
+ 	/* Copy of tag_ops->rcv for faster access in hot path */
+ 	struct sk_buff *	(*rcv)(struct sk_buff *skb,
+ 				       struct net_device *dev,
+@@ -135,12 +129,6 @@ struct dsa_switch_tree {
+ 				       struct net_device *orig_dev);
+ 
+ 	/*
+-	 * Original copy of the master netdev ethtool_ops
+-	 */
+-	struct ethtool_ops	master_ethtool_ops;
+-	const struct ethtool_ops *master_orig_ethtool_ops;
+-
+-	/*
+ 	 * The switch port to which the CPU is attached.
+ 	 */
+ 	struct dsa_port		*cpu_dp;
+@@ -189,6 +177,11 @@ 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 6aacc2314a8f..416ac4ef9ba9 100644
+--- a/net/dsa/dsa.c
++++ b/net/dsa/dsa.c
+@@ -118,15 +118,16 @@ int dsa_cpu_port_ethtool_setup(struct dsa_port *cpu_dp)
+ 	struct net_device *master;
+ 	struct ethtool_ops *cpu_ops;
+ 
+-	master = ds->dst->cpu_dp->netdev;
++	master = cpu_dp->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,
++	memcpy(&cpu_dp->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,
++	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;
+@@ -136,12 +137,7 @@ int dsa_cpu_port_ethtool_setup(struct dsa_port *cpu_dp)
+ 
+ void dsa_cpu_port_ethtool_restore(struct dsa_port *cpu_dp)
+ {
+-	struct dsa_switch *ds = cpu_dp->ds;
+-	struct net_device *master;
+-
+-	master = ds->dst->cpu_dp->netdev;
+-
+-	master->ethtool_ops = ds->dst->master_orig_ethtool_ops;
++	cpu_dp->netdev->ethtool_ops = cpu_dp->orig_ethtool_ops;
+ }
+ 
+ void dsa_cpu_dsa_destroy(struct dsa_port *port)
+diff --git a/net/dsa/slave.c b/net/dsa/slave.c
+index 95031b31d64b..c33db4e3b445 100644
+--- a/net/dsa/slave.c
++++ b/net/dsa/slave.c
+@@ -524,10 +524,10 @@ static void dsa_cpu_port_get_ethtool_stats(struct net_device *dev,
+ 	s8 cpu_port = dst->cpu_dp->index;
+ 	int count = 0;
+ 
+-	if (dst->master_ethtool_ops.get_sset_count) {
+-		count = dst->master_ethtool_ops.get_sset_count(dev,
++	if (dst->cpu_dp->ethtool_ops.get_sset_count) {
++		count = dst->cpu_dp->ethtool_ops.get_sset_count(dev,
+ 							       ETH_SS_STATS);
+-		dst->master_ethtool_ops.get_ethtool_stats(dev, stats, data);
++		dst->cpu_dp->ethtool_ops.get_ethtool_stats(dev, stats, data);
+ 	}
+ 
+ 	if (ds->ops->get_ethtool_stats)
+@@ -540,8 +540,8 @@ static int dsa_cpu_port_get_sset_count(struct net_device *dev, int sset)
+ 	struct dsa_switch *ds = dst->cpu_dp->ds;
+ 	int count = 0;
+ 
+-	if (dst->master_ethtool_ops.get_sset_count)
+-		count += dst->master_ethtool_ops.get_sset_count(dev, sset);
++	if (dst->cpu_dp->ethtool_ops.get_sset_count)
++		count += dst->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);
+@@ -565,10 +565,10 @@ static void dsa_cpu_port_get_strings(struct net_device *dev,
+ 	/* We do not want to be NULL-terminated, since this is a prefix */
+ 	pfx[sizeof(pfx) - 1] = '_';
+ 
+-	if (dst->master_ethtool_ops.get_sset_count) {
+-		mcount = dst->master_ethtool_ops.get_sset_count(dev,
++	if (dst->cpu_dp->ethtool_ops.get_sset_count) {
++		mcount = dst->cpu_dp->ethtool_ops.get_sset_count(dev,
+ 								ETH_SS_STATS);
+-		dst->master_ethtool_ops.get_strings(dev, stringset, data);
++		dst->cpu_dp->ethtool_ops.get_strings(dev, stringset, data);
+ 	}
+ 
+ 	if (stringset == ETH_SS_STATS && ds->ops->get_strings) {
+
+
+From f.fainelli at gmail.com Tue Jun 13 19:17:24 2017
+From: Florian Fainelli <f.fainelli at gmail.com>
+To: netdev at vger.kernel.org
+Cc: davem at davemloft.net, andrew at lunn.ch,
+	vivien.didelot at savoirfairelinux.com, john at phrozen.org,
+	Florian Fainelli <f.fainelli at gmail.com>
+Subject: [PATCH 3/4] net: dsa: Associate slave network device with CPU port
+Date: Tue, 13 Jun 2017 12:17:24 -0700
+Message-Id: <20170613191725.26625-4-f.fainelli at gmail.com>
+X-Mailer: git-send-email 2.9.3
+In-Reply-To: <20170613191725.26625-1-f.fainelli at gmail.com>
+References: <20170613191725.26625-1-f.fainelli at gmail.com>
+List-ID: <netdev.vger.kernel.org>
+
+In preparation for supporting multiple CPU ports with DSA, have the
+dsa_port structure know which CPU it is associated with. This will be
+important in order to make sure the correct CPU is used for transmission
+of the frames. If not for functional reasons, for performance (e.g: load
+balancing) and forwarding decisions.
+
+Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
+Reviewed-by: Vivien Didelot <vivien.didelot at savoirfairelinux.com>
+---
+ include/net/dsa.h  |  1 +
+ net/dsa/dsa2.c     | 11 +++++++++++
+ net/dsa/dsa_priv.h |  2 +-
+ net/dsa/legacy.c   |  1 +
+ net/dsa/slave.c    |  4 +++-
+ 5 files changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/include/net/dsa.h b/include/net/dsa.h
+index 7e93869819f9..58969b9a090c 100644
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -171,6 +171,7 @@ struct dsa_port {
+ 	struct dsa_switch	*ds;
+ 	unsigned int		index;
+ 	const char		*name;
++	struct dsa_port		*cpu_dp;
+ 	struct net_device	*netdev;
+ 	struct device_node	*dn;
+ 	unsigned int		ageing_time;
+diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
+index ab48c4f989da..52af8401af07 100644
+--- a/net/dsa/dsa2.c
++++ b/net/dsa/dsa2.c
+@@ -490,6 +490,8 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
+ 	enum dsa_tag_protocol tag_protocol;
+ 	struct net_device *ethernet_dev;
+ 	struct device_node *ethernet;
++	struct dsa_port *p;
++	unsigned int i;
+ 
+ 	if (port->dn) {
+ 		ethernet = of_parse_phandle(port->dn, "ethernet", 0);
+@@ -507,6 +509,15 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
+ 	if (!dst->cpu_dp) {
+ 		dst->cpu_dp = port;
+ 		dst->cpu_dp->netdev = ethernet_dev;
++
++		for (i = 0; i < ds->num_ports; i++) {
++			p = &ds->ports[i];
++			if (!dsa_port_is_valid(p) ||
++			    i == index)
++				continue;
++
++			p->cpu_dp = port;
++		}
+ 	}
+ 
+ 	tag_protocol = ds->ops->get_tag_protocol(ds);
+diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
+index 5c510f4ba0ce..7c2326f3b538 100644
+--- a/net/dsa/dsa_priv.h
++++ b/net/dsa/dsa_priv.h
+@@ -185,7 +185,7 @@ 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->cpu_dp->netdev;
++	return p->dp->cpu_dp->netdev;
+ }
+ 
+ #endif
+diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
+index 5d4f6ffa3424..e60906125375 100644
+--- a/net/dsa/legacy.c
++++ b/net/dsa/legacy.c
+@@ -129,6 +129,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
+ 			ds->dsa_port_mask |= 1 << i;
+ 		} else {
+ 			ds->enabled_port_mask |= 1 << i;
++			ds->ports[i].cpu_dp = dst->cpu_dp;
+ 		}
+ 		valid_name_found = true;
+ 	}
+diff --git a/net/dsa/slave.c b/net/dsa/slave.c
+index c33db4e3b445..427f8afcfaf3 100644
+--- a/net/dsa/slave.c
++++ b/net/dsa/slave.c
+@@ -1141,9 +1141,11 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
+ 	struct net_device *master;
+ 	struct net_device *slave_dev;
+ 	struct dsa_slave_priv *p;
++	struct dsa_port *cpu_dp;
+ 	int ret;
+ 
+-	master = ds->dst->cpu_dp->netdev;
++	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);
+
+
+From f.fainelli at gmail.com Tue Jun 13 19:17:25 2017
+From: Florian Fainelli <f.fainelli at gmail.com>
+To: netdev at vger.kernel.org
+Cc: davem at davemloft.net, andrew at lunn.ch,
+	vivien.didelot at savoirfairelinux.com, john at phrozen.org,
+	Florian Fainelli <f.fainelli at gmail.com>
+Subject: [PATCH 4/4] net: dsa: Introduce dsa_get_cpu_port()
+Date: Tue, 13 Jun 2017 12:17:25 -0700
+Message-Id: <20170613191725.26625-5-f.fainelli at gmail.com>
+X-Mailer: git-send-email 2.9.3
+In-Reply-To: <20170613191725.26625-1-f.fainelli at gmail.com>
+References: <20170613191725.26625-1-f.fainelli at gmail.com>
+List-ID: <netdev.vger.kernel.org>
+
+Introduce a helper function which will return a reference to the CPU
+port used in a dsa_switch_tree. Right now this is a singleton, but this
+will change once we introduce multi-CPU port support, so ease the
+transition by converting the affected code paths.
+
+Reviewed-by: Vivien Didelot <vivien.didelot at savoirfairelinux.com>
+Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
+---
+ net/dsa/dsa_priv.h    |  5 +++++
+ net/dsa/slave.c       | 31 ++++++++++++++++---------------
+ net/dsa/tag_brcm.c    |  5 ++---
+ net/dsa/tag_ksz.c     |  5 ++---
+ net/dsa/tag_qca.c     |  3 ++-
+ net/dsa/tag_trailer.c |  5 ++---
+ 6 files changed, 29 insertions(+), 25 deletions(-)
+
+diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
+index 7c2326f3b538..55982cc39b24 100644
+--- a/net/dsa/dsa_priv.h
++++ b/net/dsa/dsa_priv.h
+@@ -188,4 +188,9 @@ static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
+ 	return p->dp->cpu_dp->netdev;
+ }
+ 
++static inline struct dsa_port *dsa_get_cpu_port(struct dsa_switch_tree *dst)
++{
++	return dst->cpu_dp;
++}
++
+ #endif
+diff --git a/net/dsa/slave.c b/net/dsa/slave.c
+index 427f8afcfaf3..845e0c3f871e 100644
+--- a/net/dsa/slave.c
++++ b/net/dsa/slave.c
+@@ -520,14 +520,14 @@ static void dsa_cpu_port_get_ethtool_stats(struct net_device *dev,
+ 					   uint64_t *data)
+ {
+ 	struct dsa_switch_tree *dst = dev->dsa_ptr;
+-	struct dsa_switch *ds = dst->cpu_dp->ds;
+-	s8 cpu_port = dst->cpu_dp->index;
++	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 (dst->cpu_dp->ethtool_ops.get_sset_count) {
+-		count = dst->cpu_dp->ethtool_ops.get_sset_count(dev,
+-							       ETH_SS_STATS);
+-		dst->cpu_dp->ethtool_ops.get_ethtool_stats(dev, stats, data);
++	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)
+@@ -537,11 +537,12 @@ static void dsa_cpu_port_get_ethtool_stats(struct net_device *dev,
+ static int dsa_cpu_port_get_sset_count(struct net_device *dev, int sset)
+ {
+ 	struct dsa_switch_tree *dst = dev->dsa_ptr;
+-	struct dsa_switch *ds = dst->cpu_dp->ds;
++	struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
++	struct dsa_switch *ds = cpu_dp->ds;
+ 	int count = 0;
+ 
+-	if (dst->cpu_dp->ethtool_ops.get_sset_count)
+-		count += dst->cpu_dp->ethtool_ops.get_sset_count(dev, sset);
++	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);
+@@ -553,8 +554,9 @@ 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_switch *ds = dst->cpu_dp->ds;
+-	s8 cpu_port = dst->cpu_dp->index;
++	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;
+@@ -565,10 +567,9 @@ static void dsa_cpu_port_get_strings(struct net_device *dev,
+ 	/* We do not want to be NULL-terminated, since this is a prefix */
+ 	pfx[sizeof(pfx) - 1] = '_';
+ 
+-	if (dst->cpu_dp->ethtool_ops.get_sset_count) {
+-		mcount = dst->cpu_dp->ethtool_ops.get_sset_count(dev,
+-								ETH_SS_STATS);
+-		dst->cpu_dp->ethtool_ops.get_strings(dev, stringset, data);
++	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) {
+diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c
+index c03860907f28..c697d9815177 100644
+--- a/net/dsa/tag_brcm.c
++++ b/net/dsa/tag_brcm.c
+@@ -93,12 +93,11 @@ static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
+ 				    struct net_device *orig_dev)
+ {
+ 	struct dsa_switch_tree *dst = dev->dsa_ptr;
+-	struct dsa_switch *ds;
++	struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
++	struct dsa_switch *ds = cpu_dp->ds;
+ 	int source_port;
+ 	u8 *brcm_tag;
+ 
+-	ds = dst->cpu_dp->ds;
+-
+ 	if (unlikely(!pskb_may_pull(skb, BRCM_TAG_LEN)))
+ 		return NULL;
+ 
+diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
+index b94a334a1d02..fab41de8e983 100644
+--- a/net/dsa/tag_ksz.c
++++ b/net/dsa/tag_ksz.c
+@@ -75,12 +75,11 @@ static struct sk_buff *ksz_rcv(struct sk_buff *skb, struct net_device *dev,
+ 			       struct net_device *orig_dev)
+ {
+ 	struct dsa_switch_tree *dst = dev->dsa_ptr;
+-	struct dsa_switch *ds;
++	struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
++	struct dsa_switch *ds = cpu_dp->ds;
+ 	u8 *tag;
+ 	int source_port;
+ 
+-	ds = dst->cpu_dp->ds;
+-
+ 	tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
+ 
+ 	source_port = tag[0] & 7;
+diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c
+index 4f43cf0b4eff..1867a3d11f28 100644
+--- a/net/dsa/tag_qca.c
++++ b/net/dsa/tag_qca.c
+@@ -67,6 +67,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
+ 				   struct net_device *orig_dev)
+ {
+ 	struct dsa_switch_tree *dst = dev->dsa_ptr;
++	struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
+ 	struct dsa_switch *ds;
+ 	u8 ver;
+ 	int port;
+@@ -95,7 +96,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	/* This protocol doesn't support cascading multiple switches so it's
+ 	 * safe to assume the switch is first in the tree
+ 	 */
+-	ds = dst->cpu_dp->ds;
++	ds = cpu_dp->ds;
+ 	if (!ds)
+ 		return NULL;
+ 
+diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c
+index b4f6db094409..172f13167896 100644
+--- a/net/dsa/tag_trailer.c
++++ b/net/dsa/tag_trailer.c
+@@ -61,12 +61,11 @@ static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev,
+ 				   struct net_device *orig_dev)
+ {
+ 	struct dsa_switch_tree *dst = dev->dsa_ptr;
+-	struct dsa_switch *ds;
++	struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
++	struct dsa_switch *ds = cpu_dp->ds;
+ 	u8 *trailer;
+ 	int source_port;
+ 
+-	ds = dst->cpu_dp->ds;
+-
+ 	if (skb_linearize(skb))
+ 		return NULL;
+ 
diff --git a/patchwork/tests/test_series.py b/patchwork/tests/test_series.py
index 0a33b75..390ee51 100644
--- a/patchwork/tests/test_series.py
+++ b/patchwork/tests/test_series.py
@@ -185,6 +185,24 @@ class BaseSeriesTest(_BaseTestCase):
 
         self.assertSerialized(patches_a + patches_b, [2, 2])
 
+    def test_different_versions(self):
+        """Series received with different version on cover to patches.
+
+        Input:
+          - [PATCH net-next v3 0/4] net: dsa: Multi-CPU ground work (v3)
+            - [PATCH 1/4] net: dsa: Remove master_netdev and use
+                dst->cpu_dp->netdev
+            - [PATCH 2/4] net: dsa: Relocate master ethtool operations
+            - [PATCH 3/4] net: dsa: Associate slave network device with CPU
+                port
+            - [PATCH 4/4] net: dsa: Introduce dsa_get_cpu_port()
+        """
+        covers, patches, _ = self._parse_mbox(
+            'base-different-versions.mbox', [1, 4, 0])
+
+        self.assertSerialized(covers, [1])
+        self.assertSerialized(patches, [4])
+
     def test_multiple_references(self):
         """Series received with multiple reference headers.
 
-- 
2.9.4



More information about the Patchwork mailing list