netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 net-next 0/3] Improvements to the DSA deferred xmit
@ 2020-01-04  0:37 Vladimir Oltean
  2020-01-04  0:37 ` [PATCH v2 net-next 1/3] net: dsa: sja1105: Always send through management routes in slot 0 Vladimir Oltean
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Vladimir Oltean @ 2020-01-04  0:37 UTC (permalink / raw)
  To: f.fainelli, vivien.didelot, andrew, davem; +Cc: netdev, Vladimir Oltean

After the feedback received on v1:
https://www.spinics.net/lists/netdev/msg622617.html

I've decided to move the deferred xmit implementation completely within
the sja1105 driver.

The executive summary for this series is the same as it was for v1
(better for everybody):

- For those who don't use it, thanks to one less assignment in the
  hotpath (and now also thanks to less code in the DSA core)
- For those who do, by making its scheduling more amenable and moving it
  outside the generic workqueue (since it still deals with packet
  hotpath, after all)

There are some simplification (1/3) and cosmetic (3/3) patches in the
areas next to the code touched by the main patch (2/3).

Vladimir Oltean (3):
  net: dsa: sja1105: Always send through management routes in slot 0
  net: dsa: Make deferred_xmit private to sja1105
  net: dsa: tag_sja1105: Slightly improve the Xmas tree in sja1105_xmit

 drivers/net/dsa/sja1105/sja1105_main.c | 120 +++++++++++++++----------
 include/linux/dsa/sja1105.h            |   4 +-
 include/net/dsa.h                      |   9 --
 net/dsa/dsa_priv.h                     |   2 -
 net/dsa/slave.c                        |  37 +-------
 net/dsa/tag_sja1105.c                  |  18 +++-
 6 files changed, 94 insertions(+), 96 deletions(-)

-- 
2.17.1


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

* [PATCH v2 net-next 1/3] net: dsa: sja1105: Always send through management routes in slot 0
  2020-01-04  0:37 [PATCH v2 net-next 0/3] Improvements to the DSA deferred xmit Vladimir Oltean
@ 2020-01-04  0:37 ` Vladimir Oltean
  2020-01-05  4:42   ` Florian Fainelli
  2020-01-04  0:37 ` [PATCH v2 net-next 2/3] net: dsa: Make deferred_xmit private to sja1105 Vladimir Oltean
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Vladimir Oltean @ 2020-01-04  0:37 UTC (permalink / raw)
  To: f.fainelli, vivien.didelot, andrew, davem; +Cc: netdev, Vladimir Oltean

I finally found out how the 4 management route slots are supposed to
be used, but.. it's not worth it.

The description from the comment I've just deleted in this commit is
still true: when more than 1 management slot is active at the same time,
the switch will match frames incoming [from the CPU port] on the lowest
numbered management slot that matches the frame's DMAC.

My issue was that one was not supposed to statically assign each port a
slot. Yes, there are 4 slots and also 4 non-CPU ports, but that is a
mere coincidence.

Instead, the switch can be used like this: every management frame gets a
slot at the right of the most recently assigned slot:

Send mgmt frame 1 through S0:    S0 x  x  x
Send mgmt frame 2 through S1:    S0 S1 x  x
Send mgmt frame 3 through S2:    S0 S1 S2 x
Send mgmt frame 4 through S3:    S0 S1 S2 S3

The difference compared to the old usage is that the transmission of
frames 1-4 doesn't need to wait until the completion of the management
route. It is safe to use a slot to the right of the most recently used
one, because by protocol nobody will program a slot to your left and
"steal" your route towards the correct egress port.

So there is a potential throughput benefit here.

But mgmt frame 5 has no more free slot to use, so it has to wait until
_all_ of S0, S1, S2, S3 are full, in order to use S0 again.

And that's actually exactly the problem: I was looking for something
that would bring more predictable transmission latency, but this is
exactly the opposite: 3 out of 4 frames would be transmitted quicker,
but the 4th would draw the short straw and have a worse worst-case
latency than before.

Useless.

Things are made even worse by PTP TX timestamping, which is something I
won't go deeply into here. Suffice to say that the fact there is a
driver-level lock on the SPI bus offsets any potential throughput gains
that parallelism might bring.

So there's no going back to the multi-slot scheme, remove the
"mgmt_slot" variable from sja1105_port and the dummy static assignment
made at probe time.

While passing by, also remove the assignment to casc_port altogether.
Don't pretend that we support cascaded setups.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
---
Changes in v2:
- Patch is new.

 drivers/net/dsa/sja1105/sja1105_main.c | 26 +-------------------------
 include/linux/dsa/sja1105.h            |  1 -
 2 files changed, 1 insertion(+), 26 deletions(-)

diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 1da5ac111499..79dd965227bc 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -426,14 +426,6 @@ static int sja1105_init_general_params(struct sja1105_private *priv)
 		.tpid2 = ETH_P_SJA1105,
 	};
 	struct sja1105_table *table;
-	int i, k = 0;
-
-	for (i = 0; i < SJA1105_NUM_PORTS; i++) {
-		if (dsa_is_dsa_port(priv->ds, i))
-			default_general_params.casc_port = i;
-		else if (dsa_is_user_port(priv->ds, i))
-			priv->ports[i].mgmt_slot = k++;
-	}
 
 	table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS];
 
@@ -1827,30 +1819,14 @@ static netdev_tx_t sja1105_port_deferred_xmit(struct dsa_switch *ds, int port,
 					      struct sk_buff *skb)
 {
 	struct sja1105_private *priv = ds->priv;
-	struct sja1105_port *sp = &priv->ports[port];
-	int slot = sp->mgmt_slot;
 	struct sk_buff *clone;
 
-	/* The tragic fact about the switch having 4x2 slots for installing
-	 * management routes is that all of them except one are actually
-	 * useless.
-	 * If 2 slots are simultaneously configured for two BPDUs sent to the
-	 * same (multicast) DMAC but on different egress ports, the switch
-	 * would confuse them and redirect first frame it receives on the CPU
-	 * port towards the port configured on the numerically first slot
-	 * (therefore wrong port), then second received frame on second slot
-	 * (also wrong port).
-	 * So for all practical purposes, there needs to be a lock that
-	 * prevents that from happening. The slot used here is utterly useless
-	 * (could have simply been 0 just as fine), but we are doing it
-	 * nonetheless, in case a smarter idea ever comes up in the future.
-	 */
 	mutex_lock(&priv->mgmt_lock);
 
 	/* The clone, if there, was made by dsa_skb_tx_timestamp */
 	clone = DSA_SKB_CB(skb)->clone;
 
-	sja1105_mgmt_xmit(ds, port, slot, skb, !!clone);
+	sja1105_mgmt_xmit(ds, port, 0, skb, !!clone);
 
 	if (!clone)
 		goto out;
diff --git a/include/linux/dsa/sja1105.h b/include/linux/dsa/sja1105.h
index c0b6a603ea8c..317e05b2584b 100644
--- a/include/linux/dsa/sja1105.h
+++ b/include/linux/dsa/sja1105.h
@@ -56,7 +56,6 @@ struct sja1105_port {
 	struct sja1105_tagger_data *data;
 	struct dsa_port *dp;
 	bool hwts_tx_en;
-	int mgmt_slot;
 };
 
 #endif /* _NET_DSA_SJA1105_H */
-- 
2.17.1


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

* [PATCH v2 net-next 2/3] net: dsa: Make deferred_xmit private to sja1105
  2020-01-04  0:37 [PATCH v2 net-next 0/3] Improvements to the DSA deferred xmit Vladimir Oltean
  2020-01-04  0:37 ` [PATCH v2 net-next 1/3] net: dsa: sja1105: Always send through management routes in slot 0 Vladimir Oltean
@ 2020-01-04  0:37 ` Vladimir Oltean
  2020-01-05  4:39   ` Florian Fainelli
  2020-01-04  0:37 ` [PATCH v2 net-next 3/3] net: dsa: tag_sja1105: Slightly improve the Xmas tree in sja1105_xmit Vladimir Oltean
  2020-01-05 23:13 ` [PATCH v2 net-next 0/3] Improvements to the DSA deferred xmit David Miller
  3 siblings, 1 reply; 8+ messages in thread
From: Vladimir Oltean @ 2020-01-04  0:37 UTC (permalink / raw)
  To: f.fainelli, vivien.didelot, andrew, davem; +Cc: netdev, Vladimir Oltean

There are 3 things that are wrong with the DSA deferred xmit mechanism:

1. Its introduction has made the DSA hotpath ever so slightly more
   inefficient for everybody, since DSA_SKB_CB(skb)->deferred_xmit needs
   to be initialized to false for every transmitted frame, in order to
   figure out whether the driver requested deferral or not (a very rare
   occasion, rare even for the only driver that does use this mechanism:
   sja1105). That was necessary to avoid kfree_skb from freeing the skb.

2. Because L2 PTP is a link-local protocol like STP, it requires
   management routes and deferred xmit with this switch. But as opposed
   to STP, the deferred work mechanism needs to schedule the packet
   rather quickly for the TX timstamp to be collected in time and sent
   to user space. But there is no provision for controlling the
   scheduling priority of this deferred xmit workqueue. Too bad this is
   a rather specific requirement for a feature that nobody else uses
   (more below).

3. Perhaps most importantly, it makes the DSA core adhere a bit too
   much to the NXP company-wide policy "Innovate Where It Doesn't
   Matter". The sja1105 is probably the only DSA switch that requires
   some frames sent from the CPU to be routed to the slave port via an
   out-of-band configuration (register write) rather than in-band (DSA
   tag). And there are indeed very good reasons to not want to do that:
   if that out-of-band register is at the other end of a slow bus such
   as SPI, then you limit that Ethernet flow's throughput to effectively
   the throughput of the SPI bus. So hardware vendors should definitely
   not be encouraged to design this way. We do _not_ want more
   widespread use of this mechanism.

Luckily we have a solution for each of the 3 issues:

For 1, we can just remove that variable in the skb->cb and counteract
the effect of kfree_skb with skb_get, much to the same effect. The
advantage, of course, being that anybody who doesn't use deferred xmit
doesn't need to do any extra operation in the hotpath.

For 2, we can create a kernel thread for each port's deferred xmit work.
If the user switch ports are named swp0, swp1, swp2, the kernel threads
will be named swp0_xmit, swp1_xmit, swp2_xmit (there appears to be a 15
character length limit on kernel thread names). With this, the user can
change the scheduling priority with chrt $(pidof swp2_xmit).

For 3, we can actually move the entire implementation to the sja1105
driver.

So this patch deletes the generic implementation from the DSA core and
adds a new one, more adequate to the requirements of PTP TX
timestamping, in sja1105_main.c.

Suggested-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
---
Changes in v2:
- Moved implementation completely within the sja1105 driver.
- Renamed dsa_swpN_xmit to swpN_xmit.

 drivers/net/dsa/sja1105/sja1105_main.c | 96 ++++++++++++++++++++------
 include/linux/dsa/sja1105.h            |  3 +
 include/net/dsa.h                      |  9 ---
 net/dsa/dsa_priv.h                     |  2 -
 net/dsa/slave.c                        | 37 +---------
 net/dsa/tag_sja1105.c                  | 15 +++-
 6 files changed, 93 insertions(+), 69 deletions(-)

diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 79dd965227bc..61795833c8f5 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -1732,6 +1732,16 @@ static int sja1105_setup(struct dsa_switch *ds)
 static void sja1105_teardown(struct dsa_switch *ds)
 {
 	struct sja1105_private *priv = ds->priv;
+	int port;
+
+	for (port = 0; port < SJA1105_NUM_PORTS; port++) {
+		struct sja1105_port *sp = &priv->ports[port];
+
+		if (!dsa_is_user_port(ds, port))
+			continue;
+
+		kthread_destroy_worker(sp->xmit_worker);
+	}
 
 	sja1105_tas_teardown(ds);
 	sja1105_ptp_clock_unregister(ds);
@@ -1753,6 +1763,18 @@ static int sja1105_port_enable(struct dsa_switch *ds, int port,
 	return 0;
 }
 
+static void sja1105_port_disable(struct dsa_switch *ds, int port)
+{
+	struct sja1105_private *priv = ds->priv;
+	struct sja1105_port *sp = &priv->ports[port];
+
+	if (!dsa_is_user_port(ds, port))
+		return;
+
+	kthread_cancel_work_sync(&sp->xmit_work);
+	skb_queue_purge(&sp->xmit_queue);
+}
+
 static int sja1105_mgmt_xmit(struct dsa_switch *ds, int port, int slot,
 			     struct sk_buff *skb, bool takets)
 {
@@ -1811,31 +1833,36 @@ static int sja1105_mgmt_xmit(struct dsa_switch *ds, int port, int slot,
 	return NETDEV_TX_OK;
 }
 
+#define work_to_port(work) \
+		container_of((work), struct sja1105_port, xmit_work)
+#define tagger_to_sja1105(t) \
+		container_of((t), struct sja1105_private, tagger_data)
+
 /* Deferred work is unfortunately necessary because setting up the management
  * route cannot be done from atomit context (SPI transfer takes a sleepable
  * lock on the bus)
  */
-static netdev_tx_t sja1105_port_deferred_xmit(struct dsa_switch *ds, int port,
-					      struct sk_buff *skb)
+static void sja1105_port_deferred_xmit(struct kthread_work *work)
 {
-	struct sja1105_private *priv = ds->priv;
-	struct sk_buff *clone;
-
-	mutex_lock(&priv->mgmt_lock);
+	struct sja1105_port *sp = work_to_port(work);
+	struct sja1105_tagger_data *tagger_data = sp->data;
+	struct sja1105_private *priv = tagger_to_sja1105(tagger_data);
+	int port = sp - priv->ports;
+	struct sk_buff *skb;
 
-	/* The clone, if there, was made by dsa_skb_tx_timestamp */
-	clone = DSA_SKB_CB(skb)->clone;
+	while ((skb = skb_dequeue(&sp->xmit_queue)) != NULL) {
+		struct sk_buff *clone = DSA_SKB_CB(skb)->clone;
 
-	sja1105_mgmt_xmit(ds, port, 0, skb, !!clone);
+		mutex_lock(&priv->mgmt_lock);
 
-	if (!clone)
-		goto out;
+		sja1105_mgmt_xmit(priv->ds, port, 0, skb, !!clone);
 
-	sja1105_ptp_txtstamp_skb(ds, port, clone);
+		/* The clone, if there, was made by dsa_skb_tx_timestamp */
+		if (clone)
+			sja1105_ptp_txtstamp_skb(priv->ds, port, clone);
 
-out:
-	mutex_unlock(&priv->mgmt_lock);
-	return NETDEV_TX_OK;
+		mutex_unlock(&priv->mgmt_lock);
+	}
 }
 
 /* The MAXAGE setting belongs to the L2 Forwarding Parameters table,
@@ -1966,6 +1993,7 @@ static const struct dsa_switch_ops sja1105_switch_ops = {
 	.get_sset_count		= sja1105_get_sset_count,
 	.get_ts_info		= sja1105_get_ts_info,
 	.port_enable		= sja1105_port_enable,
+	.port_disable		= sja1105_port_disable,
 	.port_fdb_dump		= sja1105_fdb_dump,
 	.port_fdb_add		= sja1105_fdb_add,
 	.port_fdb_del		= sja1105_fdb_del,
@@ -1979,7 +2007,6 @@ static const struct dsa_switch_ops sja1105_switch_ops = {
 	.port_mdb_prepare	= sja1105_mdb_prepare,
 	.port_mdb_add		= sja1105_mdb_add,
 	.port_mdb_del		= sja1105_mdb_del,
-	.port_deferred_xmit	= sja1105_port_deferred_xmit,
 	.port_hwtstamp_get	= sja1105_hwtstamp_get,
 	.port_hwtstamp_set	= sja1105_hwtstamp_set,
 	.port_rxtstamp		= sja1105_port_rxtstamp,
@@ -2031,7 +2058,7 @@ static int sja1105_probe(struct spi_device *spi)
 	struct device *dev = &spi->dev;
 	struct sja1105_private *priv;
 	struct dsa_switch *ds;
-	int rc, i;
+	int rc, port;
 
 	if (!dev->of_node) {
 		dev_err(dev, "No DTS bindings for SJA1105 driver\n");
@@ -2096,15 +2123,42 @@ static int sja1105_probe(struct spi_device *spi)
 		return rc;
 
 	/* Connections between dsa_port and sja1105_port */
-	for (i = 0; i < SJA1105_NUM_PORTS; i++) {
-		struct sja1105_port *sp = &priv->ports[i];
+	for (port = 0; port < SJA1105_NUM_PORTS; port++) {
+		struct sja1105_port *sp = &priv->ports[port];
+		struct dsa_port *dp = dsa_to_port(ds, port);
+		struct net_device *slave;
+
+		if (!dsa_is_user_port(ds, port))
+			continue;
 
-		dsa_to_port(ds, i)->priv = sp;
-		sp->dp = dsa_to_port(ds, i);
+		dp->priv = sp;
+		sp->dp = dp;
 		sp->data = tagger_data;
+		slave = dp->slave;
+		kthread_init_work(&sp->xmit_work, sja1105_port_deferred_xmit);
+		sp->xmit_worker = kthread_create_worker(0, "%s_xmit",
+							slave->name);
+		if (IS_ERR(sp->xmit_worker)) {
+			rc = PTR_ERR(sp->xmit_worker);
+			dev_err(ds->dev,
+				"failed to create deferred xmit thread: %d\n",
+				rc);
+			goto out;
+		}
+		skb_queue_head_init(&sp->xmit_queue);
 	}
 
 	return 0;
+out:
+	while (port-- > 0) {
+		struct sja1105_port *sp = &priv->ports[port];
+
+		if (!dsa_is_user_port(ds, port))
+			continue;
+
+		kthread_destroy_worker(sp->xmit_worker);
+	}
+	return rc;
 }
 
 static int sja1105_remove(struct spi_device *spi)
diff --git a/include/linux/dsa/sja1105.h b/include/linux/dsa/sja1105.h
index 317e05b2584b..fa5735c353cd 100644
--- a/include/linux/dsa/sja1105.h
+++ b/include/linux/dsa/sja1105.h
@@ -53,6 +53,9 @@ struct sja1105_skb_cb {
 	((struct sja1105_skb_cb *)DSA_SKB_CB_PRIV(skb))
 
 struct sja1105_port {
+	struct kthread_worker *xmit_worker;
+	struct kthread_work xmit_work;
+	struct sk_buff_head xmit_queue;
 	struct sja1105_tagger_data *data;
 	struct dsa_port *dp;
 	bool hwts_tx_en;
diff --git a/include/net/dsa.h b/include/net/dsa.h
index da5578db228e..23b1c58656d4 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -90,7 +90,6 @@ struct dsa_device_ops {
 
 struct dsa_skb_cb {
 	struct sk_buff *clone;
-	bool deferred_xmit;
 };
 
 struct __dsa_skb_cb {
@@ -192,9 +191,6 @@ struct dsa_port {
 	struct phylink		*pl;
 	struct phylink_config	pl_config;
 
-	struct work_struct	xmit_work;
-	struct sk_buff_head	xmit_queue;
-
 	struct list_head list;
 
 	/*
@@ -564,11 +560,6 @@ struct dsa_switch_ops {
 	bool	(*port_rxtstamp)(struct dsa_switch *ds, int port,
 				 struct sk_buff *skb, unsigned int type);
 
-	/*
-	 * Deferred frame Tx
-	 */
-	netdev_tx_t (*port_deferred_xmit)(struct dsa_switch *ds, int port,
-					  struct sk_buff *skb);
 	/* Devlink parameters */
 	int	(*devlink_param_get)(struct dsa_switch *ds, u32 id,
 				     struct devlink_param_gset_ctx *ctx);
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 09ea2fd78c74..8a162605b861 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -162,8 +162,6 @@ int dsa_slave_resume(struct net_device *slave_dev);
 int dsa_slave_register_notifier(void);
 void dsa_slave_unregister_notifier(void);
 
-void *dsa_defer_xmit(struct sk_buff *skb, struct net_device *dev);
-
 static inline struct dsa_port *dsa_slave_to_port(const struct net_device *dev)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 78ffc87dc25e..c1828bdc79dc 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -116,9 +116,6 @@ static int dsa_slave_close(struct net_device *dev)
 	struct net_device *master = dsa_slave_to_master(dev);
 	struct dsa_port *dp = dsa_slave_to_port(dev);
 
-	cancel_work_sync(&dp->xmit_work);
-	skb_queue_purge(&dp->xmit_queue);
-
 	phylink_stop(dp->pl);
 
 	dsa_port_disable(dp);
@@ -518,7 +515,6 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
 	s->tx_bytes += skb->len;
 	u64_stats_update_end(&s->syncp);
 
-	DSA_SKB_CB(skb)->deferred_xmit = false;
 	DSA_SKB_CB(skb)->clone = NULL;
 
 	/* Identify PTP protocol packets, clone them, and pass them to the
@@ -531,39 +527,13 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
 	 */
 	nskb = p->xmit(skb, dev);
 	if (!nskb) {
-		if (!DSA_SKB_CB(skb)->deferred_xmit)
-			kfree_skb(skb);
+		kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
 
 	return dsa_enqueue_skb(nskb, dev);
 }
 
-void *dsa_defer_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct dsa_port *dp = dsa_slave_to_port(dev);
-
-	DSA_SKB_CB(skb)->deferred_xmit = true;
-
-	skb_queue_tail(&dp->xmit_queue, skb);
-	schedule_work(&dp->xmit_work);
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(dsa_defer_xmit);
-
-static void dsa_port_xmit_work(struct work_struct *work)
-{
-	struct dsa_port *dp = container_of(work, struct dsa_port, xmit_work);
-	struct dsa_switch *ds = dp->ds;
-	struct sk_buff *skb;
-
-	if (unlikely(!ds->ops->port_deferred_xmit))
-		return;
-
-	while ((skb = skb_dequeue(&dp->xmit_queue)) != NULL)
-		ds->ops->port_deferred_xmit(ds, dp->index, skb);
-}
-
 /* ethtool operations *******************************************************/
 
 static void dsa_slave_get_drvinfo(struct net_device *dev,
@@ -1367,9 +1337,6 @@ int dsa_slave_suspend(struct net_device *slave_dev)
 	if (!netif_running(slave_dev))
 		return 0;
 
-	cancel_work_sync(&dp->xmit_work);
-	skb_queue_purge(&dp->xmit_queue);
-
 	netif_device_detach(slave_dev);
 
 	rtnl_lock();
@@ -1455,8 +1422,6 @@ int dsa_slave_create(struct dsa_port *port)
 	}
 	p->dp = port;
 	INIT_LIST_HEAD(&p->mall_tc_list);
-	INIT_WORK(&port->xmit_work, dsa_port_xmit_work);
-	skb_queue_head_init(&port->xmit_queue);
 	p->xmit = cpu_dp->tag_ops->xmit;
 	port->slave = slave_dev;
 
diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c
index 63ef2a14c934..7c2b84393cc6 100644
--- a/net/dsa/tag_sja1105.c
+++ b/net/dsa/tag_sja1105.c
@@ -83,6 +83,19 @@ static bool sja1105_filter(const struct sk_buff *skb, struct net_device *dev)
 	return false;
 }
 
+/* Calls sja1105_port_deferred_xmit in sja1105_main.c */
+static struct sk_buff *sja1105_defer_xmit(struct sja1105_port *sp,
+					  struct sk_buff *skb)
+{
+	/* Increase refcount so the kfree_skb in dsa_slave_xmit
+	 * won't really free the packet.
+	 */
+	skb_queue_tail(&sp->xmit_queue, skb_get(skb));
+	kthread_queue_work(sp->xmit_worker, &sp->xmit_work);
+
+	return NULL;
+}
+
 static struct sk_buff *sja1105_xmit(struct sk_buff *skb,
 				    struct net_device *netdev)
 {
@@ -97,7 +110,7 @@ static struct sk_buff *sja1105_xmit(struct sk_buff *skb,
 	 * is the .port_deferred_xmit driver callback.
 	 */
 	if (unlikely(sja1105_is_link_local(skb)))
-		return dsa_defer_xmit(skb, netdev);
+		return sja1105_defer_xmit(dp->priv, skb);
 
 	/* If we are under a vlan_filtering bridge, IP termination on
 	 * switch ports based on 802.1Q tags is simply too brittle to
-- 
2.17.1


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

* [PATCH v2 net-next 3/3] net: dsa: tag_sja1105: Slightly improve the Xmas tree in sja1105_xmit
  2020-01-04  0:37 [PATCH v2 net-next 0/3] Improvements to the DSA deferred xmit Vladimir Oltean
  2020-01-04  0:37 ` [PATCH v2 net-next 1/3] net: dsa: sja1105: Always send through management routes in slot 0 Vladimir Oltean
  2020-01-04  0:37 ` [PATCH v2 net-next 2/3] net: dsa: Make deferred_xmit private to sja1105 Vladimir Oltean
@ 2020-01-04  0:37 ` Vladimir Oltean
  2020-01-05  4:40   ` Florian Fainelli
  2020-01-05 23:13 ` [PATCH v2 net-next 0/3] Improvements to the DSA deferred xmit David Miller
  3 siblings, 1 reply; 8+ messages in thread
From: Vladimir Oltean @ 2020-01-04  0:37 UTC (permalink / raw)
  To: f.fainelli, vivien.didelot, andrew, davem; +Cc: netdev, Vladimir Oltean

This is a cosmetic patch that makes the dp, tx_vid, queue_mapping and
pcp local variable definitions a bit closer in length, so they don't
look like an eyesore as much.

The 'ds' variable is not used otherwise, except for ds->dp.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
---
Changes in v2:
- Patch is new.

 net/dsa/tag_sja1105.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c
index 7c2b84393cc6..5366ea430349 100644
--- a/net/dsa/tag_sja1105.c
+++ b/net/dsa/tag_sja1105.c
@@ -100,8 +100,7 @@ static struct sk_buff *sja1105_xmit(struct sk_buff *skb,
 				    struct net_device *netdev)
 {
 	struct dsa_port *dp = dsa_slave_to_port(netdev);
-	struct dsa_switch *ds = dp->ds;
-	u16 tx_vid = dsa_8021q_tx_vid(ds, dp->index);
+	u16 tx_vid = dsa_8021q_tx_vid(dp->ds, dp->index);
 	u16 queue_mapping = skb_get_queue_mapping(skb);
 	u8 pcp = netdev_txq_to_tc(netdev, queue_mapping);
 
-- 
2.17.1


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

* Re: [PATCH v2 net-next 2/3] net: dsa: Make deferred_xmit private to sja1105
  2020-01-04  0:37 ` [PATCH v2 net-next 2/3] net: dsa: Make deferred_xmit private to sja1105 Vladimir Oltean
@ 2020-01-05  4:39   ` Florian Fainelli
  0 siblings, 0 replies; 8+ messages in thread
From: Florian Fainelli @ 2020-01-05  4:39 UTC (permalink / raw)
  To: Vladimir Oltean, vivien.didelot, andrew, davem; +Cc: netdev



On 1/3/2020 4:37 PM, Vladimir Oltean wrote:
> There are 3 things that are wrong with the DSA deferred xmit mechanism:
> 
> 1. Its introduction has made the DSA hotpath ever so slightly more
>    inefficient for everybody, since DSA_SKB_CB(skb)->deferred_xmit needs
>    to be initialized to false for every transmitted frame, in order to
>    figure out whether the driver requested deferral or not (a very rare
>    occasion, rare even for the only driver that does use this mechanism:
>    sja1105). That was necessary to avoid kfree_skb from freeing the skb.
> 
> 2. Because L2 PTP is a link-local protocol like STP, it requires
>    management routes and deferred xmit with this switch. But as opposed
>    to STP, the deferred work mechanism needs to schedule the packet
>    rather quickly for the TX timstamp to be collected in time and sent
>    to user space. But there is no provision for controlling the
>    scheduling priority of this deferred xmit workqueue. Too bad this is
>    a rather specific requirement for a feature that nobody else uses
>    (more below).
> 
> 3. Perhaps most importantly, it makes the DSA core adhere a bit too
>    much to the NXP company-wide policy "Innovate Where It Doesn't
>    Matter". The sja1105 is probably the only DSA switch that requires
>    some frames sent from the CPU to be routed to the slave port via an
>    out-of-band configuration (register write) rather than in-band (DSA
>    tag). And there are indeed very good reasons to not want to do that:
>    if that out-of-band register is at the other end of a slow bus such
>    as SPI, then you limit that Ethernet flow's throughput to effectively
>    the throughput of the SPI bus. So hardware vendors should definitely
>    not be encouraged to design this way. We do _not_ want more
>    widespread use of this mechanism.
> 
> Luckily we have a solution for each of the 3 issues:
> 
> For 1, we can just remove that variable in the skb->cb and counteract
> the effect of kfree_skb with skb_get, much to the same effect. The
> advantage, of course, being that anybody who doesn't use deferred xmit
> doesn't need to do any extra operation in the hotpath.
> 
> For 2, we can create a kernel thread for each port's deferred xmit work.
> If the user switch ports are named swp0, swp1, swp2, the kernel threads
> will be named swp0_xmit, swp1_xmit, swp2_xmit (there appears to be a 15
> character length limit on kernel thread names). With this, the user can
> change the scheduling priority with chrt $(pidof swp2_xmit).
> 
> For 3, we can actually move the entire implementation to the sja1105
> driver.
> 
> So this patch deletes the generic implementation from the DSA core and
> adds a new one, more adequate to the requirements of PTP TX
> timestamping, in sja1105_main.c.
> 
> Suggested-by: Florian Fainelli <f.fainelli@gmail.com>
> Signed-off-by: Vladimir Oltean <olteanv@gmail.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

Thanks for addressing this so quickly.
-- 
Florian

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

* Re: [PATCH v2 net-next 3/3] net: dsa: tag_sja1105: Slightly improve the Xmas tree in sja1105_xmit
  2020-01-04  0:37 ` [PATCH v2 net-next 3/3] net: dsa: tag_sja1105: Slightly improve the Xmas tree in sja1105_xmit Vladimir Oltean
@ 2020-01-05  4:40   ` Florian Fainelli
  0 siblings, 0 replies; 8+ messages in thread
From: Florian Fainelli @ 2020-01-05  4:40 UTC (permalink / raw)
  To: Vladimir Oltean, vivien.didelot, andrew, davem; +Cc: netdev



On 1/3/2020 4:37 PM, Vladimir Oltean wrote:
> This is a cosmetic patch that makes the dp, tx_vid, queue_mapping and
> pcp local variable definitions a bit closer in length, so they don't
> look like an eyesore as much.
> 
> The 'ds' variable is not used otherwise, except for ds->dp.
> 
> Signed-off-by: Vladimir Oltean <olteanv@gmail.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

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

* Re: [PATCH v2 net-next 1/3] net: dsa: sja1105: Always send through management routes in slot 0
  2020-01-04  0:37 ` [PATCH v2 net-next 1/3] net: dsa: sja1105: Always send through management routes in slot 0 Vladimir Oltean
@ 2020-01-05  4:42   ` Florian Fainelli
  0 siblings, 0 replies; 8+ messages in thread
From: Florian Fainelli @ 2020-01-05  4:42 UTC (permalink / raw)
  To: Vladimir Oltean, vivien.didelot, andrew, davem; +Cc: netdev



On 1/3/2020 4:37 PM, Vladimir Oltean wrote:
> I finally found out how the 4 management route slots are supposed to
> be used, but.. it's not worth it.
> 
> The description from the comment I've just deleted in this commit is
> still true: when more than 1 management slot is active at the same time,
> the switch will match frames incoming [from the CPU port] on the lowest
> numbered management slot that matches the frame's DMAC.
> 
> My issue was that one was not supposed to statically assign each port a
> slot. Yes, there are 4 slots and also 4 non-CPU ports, but that is a
> mere coincidence.
> 
> Instead, the switch can be used like this: every management frame gets a
> slot at the right of the most recently assigned slot:
> 
> Send mgmt frame 1 through S0:    S0 x  x  x
> Send mgmt frame 2 through S1:    S0 S1 x  x
> Send mgmt frame 3 through S2:    S0 S1 S2 x
> Send mgmt frame 4 through S3:    S0 S1 S2 S3
> 
> The difference compared to the old usage is that the transmission of
> frames 1-4 doesn't need to wait until the completion of the management
> route. It is safe to use a slot to the right of the most recently used
> one, because by protocol nobody will program a slot to your left and
> "steal" your route towards the correct egress port.
> 
> So there is a potential throughput benefit here.
> 
> But mgmt frame 5 has no more free slot to use, so it has to wait until
> _all_ of S0, S1, S2, S3 are full, in order to use S0 again.
> 
> And that's actually exactly the problem: I was looking for something
> that would bring more predictable transmission latency, but this is
> exactly the opposite: 3 out of 4 frames would be transmitted quicker,
> but the 4th would draw the short straw and have a worse worst-case
> latency than before.
> 
> Useless.
> 
> Things are made even worse by PTP TX timestamping, which is something I
> won't go deeply into here. Suffice to say that the fact there is a
> driver-level lock on the SPI bus offsets any potential throughput gains
> that parallelism might bring.
> 
> So there's no going back to the multi-slot scheme, remove the
> "mgmt_slot" variable from sja1105_port and the dummy static assignment
> made at probe time.
> 
> While passing by, also remove the assignment to casc_port altogether.
> Don't pretend that we support cascaded setups.
> 
> Signed-off-by: Vladimir Oltean <olteanv@gmail.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

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

* Re: [PATCH v2 net-next 0/3] Improvements to the DSA deferred xmit
  2020-01-04  0:37 [PATCH v2 net-next 0/3] Improvements to the DSA deferred xmit Vladimir Oltean
                   ` (2 preceding siblings ...)
  2020-01-04  0:37 ` [PATCH v2 net-next 3/3] net: dsa: tag_sja1105: Slightly improve the Xmas tree in sja1105_xmit Vladimir Oltean
@ 2020-01-05 23:13 ` David Miller
  3 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2020-01-05 23:13 UTC (permalink / raw)
  To: olteanv; +Cc: f.fainelli, vivien.didelot, andrew, netdev

From: Vladimir Oltean <olteanv@gmail.com>
Date: Sat,  4 Jan 2020 02:37:08 +0200

> After the feedback received on v1:
> https://www.spinics.net/lists/netdev/msg622617.html
> 
> I've decided to move the deferred xmit implementation completely within
> the sja1105 driver.
> 
> The executive summary for this series is the same as it was for v1
> (better for everybody):
> 
> - For those who don't use it, thanks to one less assignment in the
>   hotpath (and now also thanks to less code in the DSA core)
> - For those who do, by making its scheduling more amenable and moving it
>   outside the generic workqueue (since it still deals with packet
>   hotpath, after all)
> 
> There are some simplification (1/3) and cosmetic (3/3) patches in the
> areas next to the code touched by the main patch (2/3).

Series applied, thanks.

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

end of thread, other threads:[~2020-01-05 23:13 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-04  0:37 [PATCH v2 net-next 0/3] Improvements to the DSA deferred xmit Vladimir Oltean
2020-01-04  0:37 ` [PATCH v2 net-next 1/3] net: dsa: sja1105: Always send through management routes in slot 0 Vladimir Oltean
2020-01-05  4:42   ` Florian Fainelli
2020-01-04  0:37 ` [PATCH v2 net-next 2/3] net: dsa: Make deferred_xmit private to sja1105 Vladimir Oltean
2020-01-05  4:39   ` Florian Fainelli
2020-01-04  0:37 ` [PATCH v2 net-next 3/3] net: dsa: tag_sja1105: Slightly improve the Xmas tree in sja1105_xmit Vladimir Oltean
2020-01-05  4:40   ` Florian Fainelli
2020-01-05 23:13 ` [PATCH v2 net-next 0/3] Improvements to the DSA deferred xmit David Miller

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).