Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/350337/?format=api
{ "id": 350337, "url": "http://patchwork.ozlabs.org/api/patches/350337/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/1400518800-6111-5-git-send-email-ezequiel.garcia@free-electrons.com/", "project": { "id": 7, "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api", "name": "Linux network development", "link_name": "netdev", "list_id": "netdev.vger.kernel.org", "list_email": "netdev@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<1400518800-6111-5-git-send-email-ezequiel.garcia@free-electrons.com>", "list_archive_url": null, "date": "2014-05-19T16:59:55", "name": "[4/9] net: mvneta: Implement software TSO", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": true, "hash": "27852108d8d3f5ef0a062b5dc814ed5245f602fb", "submitter": { "id": 20433, "url": "http://patchwork.ozlabs.org/api/people/20433/?format=api", "name": "Ezequiel Garcia", "email": "ezequiel.garcia@free-electrons.com" }, "delegate": { "id": 34, "url": "http://patchwork.ozlabs.org/api/users/34/?format=api", "username": "davem", "first_name": "David", "last_name": "Miller", "email": "davem@davemloft.net" }, "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/1400518800-6111-5-git-send-email-ezequiel.garcia@free-electrons.com/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/350337/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/350337/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<netdev-owner@vger.kernel.org>", "X-Original-To": "patchwork-incoming@ozlabs.org", "Delivered-To": "patchwork-incoming@ozlabs.org", "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id DAEF714008E\n\tfor <patchwork-incoming@ozlabs.org>;\n\tTue, 20 May 2014 03:01:18 +1000 (EST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S932762AbaESRBM (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tMon, 19 May 2014 13:01:12 -0400", "from top.free-electrons.com ([176.31.233.9]:53605 \"EHLO\n\tmail.free-electrons.com\" rhost-flags-OK-OK-OK-FAIL) by\n\tvger.kernel.org with ESMTP id S932566AbaESRBG (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Mon, 19 May 2014 13:01:06 -0400", "by mail.free-electrons.com (Postfix, from userid 106)\n\tid A4B828F6; Mon, 19 May 2014 19:01:09 +0200 (CEST)", "from localhost.localdomain (unknown [190.2.108.30])\n\tby mail.free-electrons.com (Postfix) with ESMTPSA id 3014B7A9;\n\tMon, 19 May 2014 19:01:05 +0200 (CEST)" ], "X-Spam-Checker-Version": "SpamAssassin 3.3.2 (2011-06-06) on\n\tmail.free-electrons.com", "X-Spam-Level": "", "X-Spam-Status": "No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT\n\tshortcircuit=ham autolearn=disabled version=3.3.2", "From": "Ezequiel Garcia <ezequiel.garcia@free-electrons.com>", "To": "<netdev@vger.kernel.org>, David Miller <davem@davemloft.net>,\n\tEric Dumazet <eric.dumazet@gmail.com>", "Cc": "Willy Tarreau <w@1wt.eu>,\n\tThomas Petazzoni <thomas.petazzoni@free-electrons.com>,\n\tGregory Clement <gregory.clement@free-electrons.com>,\n\tSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>,\n\tTawfik Bayouk <tawfik@marvell.com>, Lior Amsalem <alior@marvell.com>,\n\tEzequiel Garcia <ezequiel.garcia@free-electrons.com>", "Subject": "[PATCH 4/9] net: mvneta: Implement software TSO", "Date": "Mon, 19 May 2014 13:59:55 -0300", "Message-Id": "<1400518800-6111-5-git-send-email-ezequiel.garcia@free-electrons.com>", "X-Mailer": "git-send-email 1.9.1", "In-Reply-To": "<1400518800-6111-1-git-send-email-ezequiel.garcia@free-electrons.com>", "References": "<1400518800-6111-1-git-send-email-ezequiel.garcia@free-electrons.com>", "Sender": "netdev-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<netdev.vger.kernel.org>", "X-Mailing-List": "netdev@vger.kernel.org" }, "content": "Now that the TSO helper API has been introduced, this commit makes use\nof it to implement the TSO in this driver.\n\nUsing iperf to test and vmstat to check the CPU usage, shows a substantial\nCPU usage drop when TSO is on (~15% vs. ~25%). HTTP-based tests performed\nby Willy Tarreau have shown performance improvements.\n\nSigned-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>\n---\n drivers/net/ethernet/marvell/mvneta.c | 153 +++++++++++++++++++++++++++++++++-\n 1 file changed, 152 insertions(+), 1 deletion(-)", "diff": "diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c\nindex 8509029..18c698d 100644\n--- a/drivers/net/ethernet/marvell/mvneta.c\n+++ b/drivers/net/ethernet/marvell/mvneta.c\n@@ -23,6 +23,7 @@\n #include <net/ip.h>\n #include <net/ipv6.h>\n #include <linux/io.h>\n+#include <net/tso.h>\n #include <linux/of.h>\n #include <linux/of_irq.h>\n #include <linux/of_mdio.h>\n@@ -244,6 +245,9 @@\n \n #define MVNETA_TX_MTU_MAX\t\t0x3ffff\n \n+/* TSO header size */\n+#define TSO_HEADER_SIZE 128\n+\n /* Max number of Rx descriptors */\n #define MVNETA_MAX_RXD 128\n \n@@ -413,6 +417,12 @@ struct mvneta_tx_queue {\n \n \t/* Index of the next TX DMA descriptor to process */\n \tint next_desc_to_proc;\n+\n+\t/* DMA buffers for TSO headers */\n+\tchar *tso_hdrs;\n+\n+\t/* DMA address of TSO headers */\n+\tdma_addr_t tso_hdrs_phys;\n };\n \n struct mvneta_rx_queue {\n@@ -1519,6 +1529,126 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,\n \treturn rx_done;\n }\n \n+static inline void\n+mvneta_tso_put_hdr(struct sk_buff *skb,\n+\t\t struct mvneta_port *pp, struct mvneta_tx_queue *txq)\n+{\n+\tstruct mvneta_tx_desc *tx_desc;\n+\tint hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);\n+\n+\ttxq->tx_skb[txq->txq_put_index] = NULL;\n+\ttx_desc = mvneta_txq_next_desc_get(txq);\n+\ttx_desc->data_size = hdr_len;\n+\ttx_desc->command = mvneta_skb_tx_csum(pp, skb);\n+\ttx_desc->command |= MVNETA_TXD_F_DESC;\n+\ttx_desc->buf_phys_addr = txq->tso_hdrs_phys +\n+\t\t\t\t txq->txq_put_index * TSO_HEADER_SIZE;\n+\tmvneta_txq_inc_put(txq);\n+}\n+\n+static inline int\n+mvneta_tso_put_data(struct net_device *dev, struct mvneta_tx_queue *txq,\n+\t\t struct sk_buff *skb, char *data, int size,\n+\t\t bool last_tcp, bool is_last)\n+{\n+\tstruct mvneta_tx_desc *tx_desc;\n+\n+\ttx_desc = mvneta_txq_next_desc_get(txq);\n+\ttx_desc->data_size = size;\n+\ttx_desc->buf_phys_addr = dma_map_single(dev->dev.parent, data,\n+\t\t\t\t\t\tsize, DMA_TO_DEVICE);\n+\tif (unlikely(dma_mapping_error(dev->dev.parent,\n+\t\t tx_desc->buf_phys_addr))) {\n+\t\tmvneta_txq_desc_put(txq);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\ttx_desc->command = 0;\n+\ttxq->tx_skb[txq->txq_put_index] = NULL;\n+\n+\tif (last_tcp) {\n+\t\t/* last descriptor in the TCP packet */\n+\t\ttx_desc->command = MVNETA_TXD_L_DESC;\n+\n+\t\t/* last descriptor in SKB */\n+\t\tif (is_last)\n+\t\t\ttxq->tx_skb[txq->txq_put_index] = skb;\n+\t}\n+\tmvneta_txq_inc_put(txq);\n+\treturn 0;\n+}\n+\n+static int mvneta_tx_tso(struct sk_buff *skb, struct net_device *dev,\n+\t\t\t struct mvneta_tx_queue *txq)\n+{\n+\tint total_len, data_left;\n+\tint desc_count = 0;\n+\tstruct mvneta_port *pp = netdev_priv(dev);\n+\tstruct tso_t tso;\n+\tint hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);\n+\tint i;\n+\n+\t/* Count needed descriptors */\n+\tif ((txq->count + tso_count_descs(skb)) >= txq->size)\n+\t\treturn 0;\n+\n+\tif (skb_headlen(skb) < (skb_transport_offset(skb) + tcp_hdrlen(skb))) {\n+\t\tpr_info(\"*** Is this even possible???!?!?\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\t/* Initialize the TSO handler, and prepare the first payload */\n+\ttso_start(skb, &tso);\n+\n+\ttotal_len = skb->len - hdr_len;\n+\twhile (total_len > 0) {\n+\t\tchar *hdr;\n+\n+\t\tdata_left = min_t(int, skb_shinfo(skb)->gso_size, total_len);\n+\t\ttotal_len -= data_left;\n+\t\tdesc_count++;\n+\n+\t\t/* prepare packet headers: MAC + IP + TCP */\n+\t\thdr = txq->tso_hdrs + txq->txq_put_index * TSO_HEADER_SIZE;\n+\t\ttso_build_hdr(skb, hdr, &tso, data_left, total_len == 0);\n+\n+\t\tmvneta_tso_put_hdr(skb, pp, txq);\n+\n+\t\twhile (data_left > 0) {\n+\t\t\tint size;\n+\t\t\tdesc_count++;\n+\n+\t\t\tsize = min_t(int, tso.size, data_left);\n+\n+\t\t\tif (mvneta_tso_put_data(dev, txq, skb,\n+\t\t\t\t\t\t tso.data, size,\n+\t\t\t\t\t\t size == data_left,\n+\t\t\t\t\t\t total_len == 0))\n+\t\t\t\tgoto err_release;\n+\t\t\tdata_left -= size;\n+\n+\t\t\ttso_build_data(skb, &tso, size);\n+\t\t}\n+\t}\n+\n+\treturn desc_count;\n+\n+err_release:\n+\t/* Release all used data descriptors; header descriptors must not\n+\t * be DMA-unmapped.\n+\t */\n+\tfor (i = desc_count - 1; i >= 0; i--) {\n+\t\tstruct mvneta_tx_desc *tx_desc = txq->descs + i;\n+\t\tif (!(tx_desc->command & MVNETA_TXD_F_DESC))\n+\t\t\tdma_unmap_single(pp->dev->dev.parent,\n+\t\t\t\t\t tx_desc->buf_phys_addr,\n+\t\t\t\t\t tx_desc->data_size,\n+\t\t\t\t\t DMA_TO_DEVICE);\n+\t\tmvneta_txq_desc_put(txq);\n+\t}\n+\treturn 0;\n+}\n+\n /* Handle tx fragmentation processing */\n static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb,\n \t\t\t\t struct mvneta_tx_queue *txq)\n@@ -1590,6 +1720,11 @@ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)\n \tif (!netif_running(dev))\n \t\tgoto out;\n \n+\tif (skb_is_gso(skb)) {\n+\t\tfrags = mvneta_tx_tso(skb, dev, txq);\n+\t\tgoto out;\n+\t}\n+\n \tfrags = skb_shinfo(skb)->nr_frags + 1;\n \n \t/* Get a descriptor for the first part of the packet */\n@@ -2108,6 +2243,18 @@ static int mvneta_txq_init(struct mvneta_port *pp,\n \t\t\t\t txq->descs, txq->descs_phys);\n \t\treturn -ENOMEM;\n \t}\n+\n+\t/* Allocate DMA buffers for TSO MAC/IP/TCP headers */\n+\ttxq->tso_hdrs = dma_alloc_coherent(pp->dev->dev.parent,\n+\t\t\t\t\t txq->size * TSO_HEADER_SIZE,\n+\t\t\t\t\t &txq->tso_hdrs_phys, GFP_KERNEL);\n+\tif (txq->tso_hdrs == NULL) {\n+\t\tkfree(txq->tx_skb);\n+\t\tdma_free_coherent(pp->dev->dev.parent,\n+\t\t\t\t txq->size * MVNETA_DESC_ALIGNED_SIZE,\n+\t\t\t\t txq->descs, txq->descs_phys);\n+\t\treturn -ENOMEM;\n+\t}\n \tmvneta_tx_done_pkts_coal_set(pp, txq, txq->done_pkts_coal);\n \n \treturn 0;\n@@ -2119,6 +2266,10 @@ static void mvneta_txq_deinit(struct mvneta_port *pp,\n {\n \tkfree(txq->tx_skb);\n \n+\tif (txq->tso_hdrs)\n+\t\tdma_free_coherent(pp->dev->dev.parent,\n+\t\t\t\t txq->size * TSO_HEADER_SIZE,\n+\t\t\t\t txq->tso_hdrs, txq->tso_hdrs_phys);\n \tif (txq->descs)\n \t\tdma_free_coherent(pp->dev->dev.parent,\n \t\t\t\t txq->size * MVNETA_DESC_ALIGNED_SIZE,\n@@ -2894,7 +3045,7 @@ static int mvneta_probe(struct platform_device *pdev)\n \n \tnetif_napi_add(dev, &pp->napi, mvneta_poll, pp->weight);\n \n-\tdev->features = NETIF_F_SG | NETIF_F_IP_CSUM;\n+\tdev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;\n \tdev->hw_features |= dev->features;\n \tdev->vlan_features |= dev->features;\n \tdev->priv_flags |= IFF_UNICAST_FLT;\n", "prefixes": [ "4/9" ] }