From patchwork Wed Sep 24 06:05:30 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nimrod Andy X-Patchwork-Id: 392744 X-Patchwork-Delegate: davem@davemloft.net Return-Path: 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]) by ozlabs.org (Postfix) with ESMTP id 97E53140082 for ; Wed, 24 Sep 2014 16:33:58 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751543AbaIXGdy (ORCPT ); Wed, 24 Sep 2014 02:33:54 -0400 Received: from mail-bn1bon0115.outbound.protection.outlook.com ([157.56.111.115]:10555 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751122AbaIXGdw (ORCPT ); Wed, 24 Sep 2014 02:33:52 -0400 Received: from CH1PR03CA002.namprd03.prod.outlook.com (10.255.156.147) by BL2PR03MB371.namprd03.prod.outlook.com (10.141.89.14) with Microsoft SMTP Server (TLS) id 15.0.1039.15; Wed, 24 Sep 2014 06:33:50 +0000 Received: from BN1BFFO11FD005.protection.gbl (10.255.156.132) by CH1PR03CA002.outlook.office365.com (10.255.156.147) with Microsoft SMTP Server (TLS) id 15.0.1034.13 via Frontend Transport; Wed, 24 Sep 2014 06:33:49 +0000 Received: from tx30smr01.am.freescale.net (192.88.168.50) by BN1BFFO11FD005.mail.protection.outlook.com (10.58.144.68) with Microsoft SMTP Server (TLS) id 15.0.1029.15 via Frontend Transport; Wed, 24 Sep 2014 06:33:49 +0000 Received: from shlinux1.ap.freescale.net (shlinux1.ap.freescale.net [10.192.225.216]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id s8O6XjVA029781; Tue, 23 Sep 2014 23:33:46 -0700 From: Fugang Duan To: , CC: , , , Subject: [PATCH] net: fec: remove memory copy for rx path Date: Wed, 24 Sep 2014 14:05:30 +0800 Message-ID: <1411538730-31480-1-git-send-email-b38611@freescale.com> X-Mailer: git-send-email 1.7.8 X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:192.88.168.50; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(189002)(199003)(107046002)(229853001)(97736003)(46102003)(77982003)(80022003)(47776003)(64706001)(20776003)(74662003)(81542003)(74502003)(81342003)(79102003)(62966002)(77156001)(99396003)(33646002)(87286001)(36756003)(106466001)(104166001)(105606002)(104016003)(95666004)(83072002)(85852003)(85306004)(88136002)(87936001)(89996001)(50466002)(48376002)(6806004)(76482002)(83322001)(19580405001)(31966008)(50986999)(4396001)(44976005)(50226001)(102836001)(84676001)(92566001)(19580395003)(21056001)(93916002)(68736004)(120916001)(10300001)(92726001)(42262002); DIR:OUT; SFP:1102; SCL:1; SRVR:BL2PR03MB371; H:tx30smr01.am.freescale.net; FPR:; MLV:sfv; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Antispam: UriScan:; X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:;SRVR:BL2PR03MB371; X-Forefront-PRVS: 03449D5DD1 Received-SPF: Fail (protection.outlook.com: domain of freescale.com does not designate 192.88.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=fugang.duan@freescale.com; X-OriginatorOrg: freescale.com Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Re-allocate skb instead of memory copy skb data in rx path to improve enet rx performance. Signed-off-by: Fugang Duan Signed-off-by: Frank Li --- drivers/net/ethernet/freescale/fec_main.c | 90 +++++++++++++++-------------- 1 files changed, 47 insertions(+), 43 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 2b16ead..1fc8e52 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1322,6 +1322,28 @@ fec_enet_tx(struct net_device *ndev) return; } +static int +fec_enet_new_rxbdp(struct net_device *ndev, struct bufdesc *bdp, struct sk_buff *skb) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + int off; + + off = ((unsigned long)skb->data) & fep->rx_align; + if (off) + skb_reserve(skb, fep->rx_align + 1 - off); + + bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data, + FEC_ENET_RX_FRSIZE - fep->rx_align, + DMA_FROM_DEVICE); + if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) { + if (net_ratelimit()) + netdev_err(ndev, "Rx DMA memory map failed\n"); + return -ENOMEM; + } + + return 0; +} + /* During a receive, the cur_rx points to the current incoming buffer. * When we update through the ring, if the next incoming buffer has * not been given to the system, we just set the empty indicator, @@ -1336,7 +1358,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) struct fec_enet_priv_rx_q *rxq; struct bufdesc *bdp; unsigned short status; - struct sk_buff *skb; + struct sk_buff *skb_new = NULL; + struct sk_buff *skb_cur; ushort pkt_len; __u8 *data; int pkt_received = 0; @@ -1402,9 +1425,10 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) index = fec_enet_get_bd_index(rxq->rx_bd_base, bdp, fep); data = rxq->rx_skbuff[index]->data; - dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr, - FEC_ENET_RX_FRSIZE - fep->rx_align, - DMA_FROM_DEVICE); + skb_cur = rxq->rx_skbuff[index]; + dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, + FEC_ENET_RX_FRSIZE - fep->rx_align, + DMA_FROM_DEVICE); if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) swap_buffer(data, pkt_len); @@ -1427,57 +1451,50 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) vlan_packet_rcvd = true; } - /* This does 16 byte alignment, exactly what we need. - * The packet length includes FCS, but we don't want to - * include that when passing upstream as it messes up - * bridging applications. - */ - skb = netdev_alloc_skb(ndev, pkt_len - 4 + NET_IP_ALIGN); + skb_new = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE); - if (unlikely(!skb)) { + if (unlikely(!skb_new)) { ndev->stats.rx_dropped++; } else { - int payload_offset = (2 * ETH_ALEN); - skb_reserve(skb, NET_IP_ALIGN); - skb_put(skb, pkt_len - 4); /* Make room */ + skb_put(skb_cur, pkt_len - 4); /* Make room */ /* Extract the frame data without the VLAN header. */ - skb_copy_to_linear_data(skb, data, (2 * ETH_ALEN)); - if (vlan_packet_rcvd) - payload_offset = (2 * ETH_ALEN) + VLAN_HLEN; - skb_copy_to_linear_data_offset(skb, (2 * ETH_ALEN), - data + payload_offset, - pkt_len - 4 - (2 * ETH_ALEN)); + if (vlan_packet_rcvd) { + skb_copy_to_linear_data_offset(skb_cur, VLAN_HLEN, + data, (2 * ETH_ALEN)); + skb_pull(skb_cur, VLAN_HLEN); + } - skb->protocol = eth_type_trans(skb, ndev); + skb_cur->protocol = eth_type_trans(skb_cur, ndev); /* Get receive timestamp from the skb */ if (fep->hwts_rx_en && fep->bufdesc_ex) fec_enet_hwtstamp(fep, ebdp->ts, - skb_hwtstamps(skb)); + skb_hwtstamps(skb_cur)); if (fep->bufdesc_ex && (fep->csum_flags & FLAG_RX_CSUM_ENABLED)) { if (!(ebdp->cbd_esc & FLAG_RX_CSUM_ERROR)) { /* don't check it */ - skb->ip_summed = CHECKSUM_UNNECESSARY; + skb_cur->ip_summed = CHECKSUM_UNNECESSARY; } else { - skb_checksum_none_assert(skb); + skb_checksum_none_assert(skb_cur); } } /* Handle received VLAN packets */ if (vlan_packet_rcvd) - __vlan_hwaccel_put_tag(skb, + __vlan_hwaccel_put_tag(skb_cur, htons(ETH_P_8021Q), vlan_tag); - napi_gro_receive(&fep->napi, skb); + napi_gro_receive(&fep->napi, skb_cur); } - dma_sync_single_for_device(&fep->pdev->dev, bdp->cbd_bufaddr, - FEC_ENET_RX_FRSIZE - fep->rx_align, - DMA_FROM_DEVICE); + /* set the new skb */ + rxq->rx_skbuff[index] = skb_new; + fec_enet_new_rxbdp(ndev, bdp, skb_new); + rx_processing_done: /* Clear the status flags for this buffer */ status &= ~BD_ENET_RX_STATS; @@ -2553,33 +2570,20 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue) struct sk_buff *skb; struct bufdesc *bdp; struct fec_enet_priv_rx_q *rxq; - unsigned int off; rxq = fep->rx_queue[queue]; bdp = rxq->rx_bd_base; for (i = 0; i < rxq->rx_ring_size; i++) { - dma_addr_t addr; - skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE); if (!skb) goto err_alloc; - off = ((unsigned long)skb->data) & fep->rx_align; - if (off) - skb_reserve(skb, fep->rx_align + 1 - off); - - addr = dma_map_single(&fep->pdev->dev, skb->data, - FEC_ENET_RX_FRSIZE - fep->rx_align, DMA_FROM_DEVICE); - - if (dma_mapping_error(&fep->pdev->dev, addr)) { + if (fec_enet_new_rxbdp(ndev, bdp, skb)) { dev_kfree_skb(skb); - if (net_ratelimit()) - netdev_err(ndev, "Rx DMA memory map failed\n"); goto err_alloc; } rxq->rx_skbuff[i] = skb; - bdp->cbd_bufaddr = addr; bdp->cbd_sc = BD_ENET_RX_EMPTY; if (fep->bufdesc_ex) {