netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Willy Tarreau <w@1wt.eu>
To: davem@davemloft.net
Cc: netdev@vger.kernel.org, Willy Tarreau <w@1wt.eu>,
	Thomas Petazzoni <thomas.petazzoni@free-electrons.com>,
	Gregory CLEMENT <gregory.clement@free-electrons.com>
Subject: [PATCH 11/13] net: mvneta: implement rx_copybreak
Date: Thu, 16 Jan 2014 08:20:17 +0100	[thread overview]
Message-ID: <1389856819-6503-12-git-send-email-w@1wt.eu> (raw)
In-Reply-To: <1389856819-6503-1-git-send-email-w@1wt.eu>

calling dma_map_single()/dma_unmap_single() is quite expensive compared
to copying a small packet. So let's copy short frames and keep the buffers
mapped. We set the limit to 256 bytes which seems to give good results both
on the XP-GP board and on the AX3/4.

The Rx small packet rate increased by 16.4% doing this, from 486kpps to
573kpps. It is worth noting that even the call to the function
dma_sync_single_range_for_cpu() is expensive (300 ns) although less
than dma_unmap_single(). Without it, the packet rate raises to 711kpps
(+24% more). Thus on systems where coherency from device to CPU is
guaranteed by a snoop control unit, this patch should provide even more
gains, and probably rx_copybreak could be increased.

Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Gregory CLEMENT <gregory.clement@free-electrons.com>
Tested-by: Arnaud Ebalard <arno@natisbad.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/net/ethernet/marvell/mvneta.c | 44 ++++++++++++++++++++++++++++++-----
 1 file changed, 38 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 726a8d2..f5fc7a2 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -444,6 +444,8 @@ static int txq_number = 8;
 
 static int rxq_def;
 
+static int rx_copybreak __read_mostly = 256;
+
 #define MVNETA_DRIVER_NAME "mvneta"
 #define MVNETA_DRIVER_VERSION "1.0"
 
@@ -1463,22 +1465,51 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
 		rx_done++;
 		rx_filled++;
 		rx_status = rx_desc->status;
+		rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
 		data = (unsigned char *)rx_desc->buf_cookie;
 
 		if (!mvneta_rxq_desc_is_first_last(rx_status) ||
-		    (rx_status & MVNETA_RXD_ERR_SUMMARY) ||
-		    !(skb = build_skb(data, pp->frag_size > PAGE_SIZE ? 0 : pp->frag_size))) {
+		    (rx_status & MVNETA_RXD_ERR_SUMMARY)) {
+		err_drop_frame:
 			dev->stats.rx_errors++;
 			mvneta_rx_error(pp, rx_desc);
 			/* leave the descriptor untouched */
 			continue;
 		}
 
-		dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
+		if (rx_bytes <= rx_copybreak) {
+			/* better copy a small frame and not unmap the DMA region */
+			skb = netdev_alloc_skb_ip_align(dev, rx_bytes);
+			if (unlikely(!skb))
+				goto err_drop_frame;
+
+			dma_sync_single_range_for_cpu(dev->dev.parent,
+			                              rx_desc->buf_phys_addr,
+			                              MVNETA_MH_SIZE + NET_SKB_PAD,
+			                              rx_bytes,
+			                              DMA_FROM_DEVICE);
+			memcpy(skb_put(skb, rx_bytes),
+			       data + MVNETA_MH_SIZE + NET_SKB_PAD,
+			       rx_bytes);
+
+			skb->protocol = eth_type_trans(skb, dev);
+			mvneta_rx_csum(pp, rx_status, skb);
+			napi_gro_receive(&pp->napi, skb);
+
+			rcvd_pkts++;
+			rcvd_bytes += rx_bytes;
+
+			/* leave the descriptor and buffer untouched */
+			continue;
+		}
+
+		skb = build_skb(data, pp->frag_size > PAGE_SIZE ? 0 : pp->frag_size);
+		if (!skb)
+			goto err_drop_frame;
+
+		dma_unmap_single(dev->dev.parent, rx_desc->buf_phys_addr,
 				 MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
 
-		rx_bytes = rx_desc->data_size -
-			(ETH_FCS_LEN + MVNETA_MH_SIZE);
 		rcvd_pkts++;
 		rcvd_bytes += rx_bytes;
 
@@ -1495,7 +1526,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
 		/* Refill processing */
 		err = mvneta_rx_refill(pp, rx_desc);
 		if (err) {
-			netdev_err(pp->dev, "Linux processing - Can't refill\n");
+			netdev_err(dev, "Linux processing - Can't refill\n");
 			rxq->missed++;
 			rx_filled--;
 		}
@@ -2945,3 +2976,4 @@ module_param(rxq_number, int, S_IRUGO);
 module_param(txq_number, int, S_IRUGO);
 
 module_param(rxq_def, int, S_IRUGO);
+module_param(rx_copybreak, int, S_IRUGO | S_IWUSR);
-- 
1.7.12.2.21.g234cd45.dirty

  parent reply	other threads:[~2014-01-16  7:21 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-16  7:20 [PATCH 00/13] Assorted mvneta fixes and improvements Willy Tarreau
2014-01-16  7:20 ` [PATCH 01/13] net: mvneta: increase the 64-bit rx/tx stats out of the hot path Willy Tarreau
2014-01-16  7:20 ` [PATCH 02/13] net: mvneta: use per_cpu stats to fix an SMP lock up Willy Tarreau
2014-01-16  7:20 ` [PATCH 03/13] net: mvneta: do not schedule in mvneta_tx_timeout Willy Tarreau
2014-01-16  7:20 ` [PATCH 04/13] net: mvneta: add missing bit descriptions for interrupt masks and causes Willy Tarreau
2014-01-16  7:20 ` [PATCH 05/13] net: mvneta: replace Tx timer with a real interrupt Willy Tarreau
2014-01-16  7:20 ` [PATCH 06/13] net: mvneta: remove tests for impossible cases in the tx_done path Willy Tarreau
2014-01-16  7:20 ` [PATCH 07/13] net: mvneta: factor rx refilling code Willy Tarreau
2014-01-16  7:20 ` [PATCH 08/13] net: mvneta: simplify access to the rx descriptor status Willy Tarreau
2014-01-16  7:20 ` [PATCH 09/13] net: mvneta: prefetch next rx descriptor instead of current one Willy Tarreau
2014-01-16  7:20 ` [PATCH 10/13] net: mvneta: convert to build_skb() Willy Tarreau
2014-01-16  7:20 ` Willy Tarreau [this message]
2014-01-16  9:14   ` [PATCH 11/13] net: mvneta: implement rx_copybreak David Laight
2014-01-16  9:36     ` Willy Tarreau
2014-01-16 19:49       ` David Miller
2014-01-16 20:07         ` Willy Tarreau
2014-01-16 20:11           ` David Miller
2014-01-17  9:28           ` David Laight
2014-01-17  9:48             ` Willy Tarreau
2014-01-17  9:32         ` David Laight
2014-01-16  7:20 ` [PATCH 12/13] net: mvneta: mvneta_tx_done_gbe() cleanups Willy Tarreau
2014-01-16  7:20 ` [PATCH 13/13] net: mvneta: make mvneta_txq_done() return void Willy Tarreau
2014-01-16  7:22 ` [PATCH net-next 00/13] Assorted mvneta fixes and improvements Willy Tarreau
2014-01-16 23:21 ` [PATCH " David Miller

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=1389856819-6503-12-git-send-email-w@1wt.eu \
    --to=w@1wt.eu \
    --cc=davem@davemloft.net \
    --cc=gregory.clement@free-electrons.com \
    --cc=netdev@vger.kernel.org \
    --cc=thomas.petazzoni@free-electrons.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).