netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Marcin Wojtas <mw@semihalf.com>
To: linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, netdev@vger.kernel.org
Cc: davem@davemloft.net, linux@arm.linux.org.uk,
	sebastian.hesselbarth@gmail.com, andrew@lunn.ch,
	jason@lakedaemon.net, thomas.petazzoni@free-electrons.com,
	gregory.clement@free-electrons.com, simon.guinot@sequanux.org,
	nadavh@marvell.com, alior@marvell.com, xswang@marvell.com,
	myair@marvell.com, nitroshift@yahoo.com, mw@semihalf.com,
	jaz@semihalf.com, tn@semihalf.com
Subject: [PATCH 06/13] net: mvneta: enable mixed egress processing using HR timer
Date: Sun, 22 Nov 2015 08:53:52 +0100	[thread overview]
Message-ID: <1448178839-3541-7-git-send-email-mw@semihalf.com> (raw)
In-Reply-To: <1448178839-3541-1-git-send-email-mw@semihalf.com>

Mixed approach allows using higher interrupt threshold (increased back to
15 packets), useful in high throughput. In case of small amount of data
or very short TX queues HR timer ensures releasing buffers with small
latency.

Along with existing tx_done processing by coalescing interrupts this
commit enables triggering HR timer each time the packets are sent.
Time threshold can also be configured, using ethtool.

Signed-off-by: Marcin Wojtas <mw@semihalf.com>
Signed-off-by: Simon Guinot <simon.guinot@sequanux.org>
---
 drivers/net/ethernet/marvell/mvneta.c | 89 +++++++++++++++++++++++++++++++++--
 1 file changed, 85 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 9c9e858..f5acaf6 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -21,6 +21,8 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/if_vlan.h>
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
 #include <linux/io.h>
@@ -226,7 +228,8 @@
 /* Various constants */
 
 /* Coalescing */
-#define MVNETA_TXDONE_COAL_PKTS		1
+#define MVNETA_TXDONE_COAL_PKTS		15
+#define MVNETA_TXDONE_COAL_USEC		100
 #define MVNETA_RX_COAL_PKTS		32
 #define MVNETA_RX_COAL_USEC		100
 
@@ -356,6 +359,11 @@ struct mvneta_port {
 	struct net_device *dev;
 	struct notifier_block cpu_notifier;
 
+	/* Egress finalization */
+	struct tasklet_struct tx_done_tasklet;
+	struct hrtimer tx_done_timer;
+	bool timer_scheduled;
+
 	/* Core clock */
 	struct clk *clk;
 	u8 mcast_count[256];
@@ -481,6 +489,7 @@ struct mvneta_tx_queue {
 	int txq_get_index;
 
 	u32 done_pkts_coal;
+	u32 done_time_coal;
 
 	/* Virtual address of the TX DMA descriptors array */
 	struct mvneta_tx_desc *descs;
@@ -1791,6 +1800,30 @@ error:
 	return -ENOMEM;
 }
 
+/* Trigger HR timer for TX processing */
+static void mvneta_timer_set(struct mvneta_port *pp)
+{
+	ktime_t interval;
+
+	if (!pp->timer_scheduled) {
+		pp->timer_scheduled = true;
+		interval = ktime_set(0, pp->txqs[0].done_time_coal * 1000);
+		hrtimer_start(&pp->tx_done_timer, interval,
+			      HRTIMER_MODE_REL_PINNED);
+	}
+}
+
+/* TX processing HR timer callback */
+static enum hrtimer_restart mvneta_hr_timer_cb(struct hrtimer *timer)
+{
+	struct mvneta_port *pp = container_of(timer, struct mvneta_port,
+					      tx_done_timer);
+
+	tasklet_schedule(&pp->tx_done_tasklet);
+
+	return HRTIMER_NORESTART;
+}
+
 /* Main tx processing */
 static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
 {
@@ -1862,10 +1895,13 @@ out:
 		if (txq->count >= txq->tx_stop_threshold)
 			netif_tx_stop_queue(nq);
 
-		if (!skb->xmit_more || netif_xmit_stopped(nq))
+		if (!skb->xmit_more || netif_xmit_stopped(nq)) {
 			mvneta_txq_pend_desc_add(pp, txq, frags);
-		else
+			if (txq->done_time_coal && !pp->timer_scheduled)
+				mvneta_timer_set(pp);
+		} else {
 			txq->pending += frags;
+		}
 
 		u64_stats_update_begin(&stats->syncp);
 		stats->tx_packets++;
@@ -1902,6 +1938,7 @@ static void mvneta_tx_done_gbe(struct mvneta_port *pp, u32 cause_tx_done)
 {
 	struct mvneta_tx_queue *txq;
 	struct netdev_queue *nq;
+	unsigned int tx_todo = 0;
 
 	while (cause_tx_done) {
 		txq = mvneta_tx_done_policy(pp, cause_tx_done);
@@ -1909,12 +1946,40 @@ static void mvneta_tx_done_gbe(struct mvneta_port *pp, u32 cause_tx_done)
 		nq = netdev_get_tx_queue(pp->dev, txq->id);
 		__netif_tx_lock(nq, smp_processor_id());
 
-		if (txq->count)
+		if (txq->count) {
 			mvneta_txq_done(pp, txq);
+			tx_todo += txq->count;
+		}
 
 		__netif_tx_unlock(nq);
 		cause_tx_done &= ~((1 << txq->id));
 	}
+
+	if (!pp->txqs[0].done_time_coal)
+		return;
+
+	/* Set the timer in case not all the packets were
+	 * processed. Otherwise attempt to cancel timer.
+	 */
+	if (tx_todo)
+		mvneta_timer_set(pp);
+	else if (pp->timer_scheduled)
+		hrtimer_cancel(&pp->tx_done_timer);
+}
+
+/* TX done processing tasklet */
+static void mvneta_tx_done_proc(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct mvneta_port *pp = netdev_priv(dev);
+
+	if (!netif_running(dev))
+		return;
+
+	pp->timer_scheduled = false;
+
+	/* Process all Tx queues */
+	mvneta_tx_done_gbe(pp, (1 << txq_number) - 1);
 }
 
 /* Compute crc8 of the specified address, using a unique algorithm ,
@@ -2910,6 +2975,11 @@ static int mvneta_stop(struct net_device *dev)
 	for_each_present_cpu(cpu)
 		smp_call_function_single(cpu, mvneta_percpu_disable, pp, true);
 	free_percpu_irq(dev->irq, pp->ports);
+
+	hrtimer_cancel(&pp->tx_done_timer);
+	pp->timer_scheduled = false;
+	tasklet_kill(&pp->tx_done_tasklet);
+
 	mvneta_cleanup_rxqs(pp);
 	mvneta_cleanup_txqs(pp);
 
@@ -2967,6 +3037,7 @@ static int mvneta_ethtool_set_coalesce(struct net_device *dev,
 
 	for (queue = 0; queue < txq_number; queue++) {
 		struct mvneta_tx_queue *txq = &pp->txqs[queue];
+		txq->done_time_coal = c->tx_coalesce_usecs;
 		txq->done_pkts_coal = c->tx_max_coalesced_frames;
 		mvneta_tx_done_pkts_coal_set(pp, txq, txq->done_pkts_coal);
 	}
@@ -2983,6 +3054,7 @@ static int mvneta_ethtool_get_coalesce(struct net_device *dev,
 	c->rx_coalesce_usecs        = pp->rxqs[0].time_coal;
 	c->rx_max_coalesced_frames  = pp->rxqs[0].pkts_coal;
 
+	c->tx_coalesce_usecs = pp->txqs[0].done_time_coal;
 	c->tx_max_coalesced_frames =  pp->txqs[0].done_pkts_coal;
 	return 0;
 }
@@ -3146,6 +3218,7 @@ static int mvneta_init(struct device *dev, struct mvneta_port *pp)
 		txq->id = queue;
 		txq->size = pp->tx_ring_size;
 		txq->done_pkts_coal = MVNETA_TXDONE_COAL_PKTS;
+		txq->done_time_coal = MVNETA_TXDONE_COAL_USEC;
 	}
 
 	pp->rxqs = devm_kcalloc(dev, rxq_number, sizeof(struct mvneta_rx_queue),
@@ -3388,6 +3461,14 @@ static int mvneta_probe(struct platform_device *pdev)
 		port->pp = pp;
 	}
 
+	hrtimer_init(&pp->tx_done_timer, CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL_PINNED);
+	pp->tx_done_timer.function = mvneta_hr_timer_cb;
+	pp->timer_scheduled = false;
+
+	tasklet_init(&pp->tx_done_tasklet, mvneta_tx_done_proc,
+		     (unsigned long)dev);
+
 	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
 	dev->hw_features |= dev->features;
 	dev->vlan_features |= dev->features;
-- 
1.8.3.1

  parent reply	other threads:[~2015-11-22  7:53 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-22  7:53 [PATCH 00/13] mvneta Buffer Management and enhancements Marcin Wojtas
2015-11-22  7:53 ` [PATCH 01/13] net: mvneta: add configuration for MBUS windows access protection Marcin Wojtas
2015-11-25 18:19   ` Gregory CLEMENT
2015-11-22  7:53 ` [PATCH 02/13] net: mvneta: enable IP checksum with jumbo frames for Armada 38x on Port0 Marcin Wojtas
2015-11-22 20:00   ` Arnd Bergmann
2015-11-22 21:04     ` Marcin Wojtas
2015-11-22 21:32       ` Arnd Bergmann
2015-11-22 21:55         ` Marcin Wojtas
2015-11-22  7:53 ` [PATCH 03/13] net: mvneta: fix bit assignment in MVNETA_RXQ_CONFIG_REG Marcin Wojtas
2015-11-25 18:25   ` Gregory CLEMENT
2015-11-22  7:53 ` [PATCH 04/13] net: mvneta: enable suspend/resume support Marcin Wojtas
2015-11-25 18:35   ` Gregory CLEMENT
2015-11-26 17:39     ` Marcin Wojtas
2015-11-22  7:53 ` [PATCH 05/13] net: mvneta: add xmit_more support Marcin Wojtas
2015-11-22  7:53 ` Marcin Wojtas [this message]
2015-11-26 16:45   ` [PATCH 06/13] net: mvneta: enable mixed egress processing using HR timer Simon Guinot
2015-11-30 15:57     ` Marcin Wojtas
2015-12-02 10:03       ` Marcin Wojtas
2015-11-22  7:53 ` [PATCH 07/13] bus: mvebu-mbus: provide api for obtaining IO and DRAM window information Marcin Wojtas
2015-11-22 20:02   ` Arnd Bergmann
2015-11-22 21:24     ` Marcin Wojtas
2015-11-23 16:58       ` Arnd Bergmann
2015-11-22  7:53 ` [PATCH 08/13] ARM: mvebu: enable SRAM support in mvebu_v7_defconfig Marcin Wojtas
2016-02-16 10:51   ` Gregory CLEMENT
2015-11-22  7:53 ` [PATCH 09/13] net: mvneta: bm: add support for hardware buffer management Marcin Wojtas
2015-11-22  7:53 ` [PATCH 10/13] ARM: mvebu: add buffer manager nodes to armada-38x.dtsi Marcin Wojtas
2015-11-22  9:41   ` Sergei Shtylyov
2015-11-22  7:53 ` [PATCH 11/13] ARM: mvebu: enable buffer manager support on Armada 38x boards Marcin Wojtas
2015-11-22  7:53 ` [PATCH 12/13] ARM: mvebu: add buffer manager nodes to armada-xp.dtsi Marcin Wojtas
2015-11-22  7:53 ` [PATCH 13/13] ARM: mvebu: enable buffer manager support on Armada XP boards Marcin Wojtas
2015-11-22 20:06 ` [PATCH 00/13] mvneta Buffer Management and enhancements Arnd Bergmann
2015-11-22 21:37   ` Marcin Wojtas
2015-11-24 16:22 ` David Miller
2015-11-24 16:47   ` Marcin Wojtas
2015-11-25 18:34 ` Florian Fainelli
2015-11-29 13:21   ` Marcin Wojtas
2015-11-30  2:02     ` David Miller
2015-11-30 14:13       ` Marcin Wojtas
2015-11-30 16:25         ` David Miller
2015-12-02  8:26           ` Marcin Wojtas
2015-12-04 20:15             ` Florian Fainelli
2015-12-08 10:56               ` Marcin Wojtas
2015-12-08 16:57                 ` David Miller
2015-11-30 17:16 ` Gregory CLEMENT
2015-11-30 19:53   ` Marcin Wojtas
2015-12-01 13:12     ` Gregory CLEMENT
2015-12-01 21:40       ` Marcin Wojtas
2015-12-01 23:34         ` Marcin Wojtas
2015-12-02 10:40           ` Gregory CLEMENT
2015-12-02 16:21             ` Gregory CLEMENT
2015-12-02 22:15               ` Marcin Wojtas
2015-12-02 22:56                 ` Gregory CLEMENT

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1448178839-3541-7-git-send-email-mw@semihalf.com \
    --to=mw@semihalf.com \
    --cc=alior@marvell.com \
    --cc=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=gregory.clement@free-electrons.com \
    --cc=jason@lakedaemon.net \
    --cc=jaz@semihalf.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@arm.linux.org.uk \
    --cc=myair@marvell.com \
    --cc=nadavh@marvell.com \
    --cc=netdev@vger.kernel.org \
    --cc=nitroshift@yahoo.com \
    --cc=sebastian.hesselbarth@gmail.com \
    --cc=simon.guinot@sequanux.org \
    --cc=thomas.petazzoni@free-electrons.com \
    --cc=tn@semihalf.com \
    --cc=xswang@marvell.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).