From patchwork Wed Oct 10 13:48:42 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Campbell X-Patchwork-Id: 190641 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 BBC1F2C008A for ; Thu, 11 Oct 2012 00:48:46 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756435Ab2JJNsp (ORCPT ); Wed, 10 Oct 2012 09:48:45 -0400 Received: from smtp02.citrix.com ([66.165.176.63]:57157 "EHLO SMTP02.CITRIX.COM" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754659Ab2JJNso (ORCPT ); Wed, 10 Oct 2012 09:48:44 -0400 X-IronPort-AV: E=Sophos;i="4.80,564,1344211200"; d="scan'208";a="210838394" Received: from ftlpmailmx02.citrite.net ([10.13.107.66]) by FTLPIPO02.CITRIX.COM with ESMTP/TLS/RC4-MD5; 10 Oct 2012 13:48:43 +0000 Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com (10.13.107.66) with Microsoft SMTP Server id 8.3.279.1; Wed, 10 Oct 2012 09:48:43 -0400 Received: from cosworth.uk.xensource.com ([10.80.16.52] ident=ianc) by ukmail1.uk.xensource.com with esmtp (Exim 4.69) (envelope-from ) id 1TLweQ-0005jZ-K7; Wed, 10 Oct 2012 14:48:42 +0100 From: Ian Campbell To: netdev@vger.kernel.org, xen-devel@lists.xen.org CC: Ian Campbell , Eric Dumazet , Konrad Rzeszutek Wilk , Sander Eikelenboom Subject: [PATCH V2] xen: netback: handle compound page fragments on transmit. Date: Wed, 10 Oct 2012 14:48:42 +0100 Message-ID: <1349876922-11907-1-git-send-email-ian.campbell@citrix.com> X-Mailer: git-send-email 1.7.2.5 MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org An SKB paged fragment can consist of a compound page with order > 0. However the netchannel protocol deals only in PAGE_SIZE frames. Handle this in netbk_gop_frag_copy and xen_netbk_count_skb_slots by iterating over the frames which make up the page. Signed-off-by: Ian Campbell Cc: Eric Dumazet Cc: Konrad Rzeszutek Wilk Cc: Sander Eikelenboom Tested-by: Konrad Rzeszutek Wilk --- v2: Only move to next frame if there is data remaining. --- drivers/net/xen-netback/netback.c | 40 ++++++++++++++++++++++++++++++++---- 1 files changed, 35 insertions(+), 5 deletions(-) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 4ebfcf3..f2d6b78 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -335,21 +335,35 @@ unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]); + unsigned long offset = skb_shinfo(skb)->frags[i].page_offset; unsigned long bytes; + + offset &= ~PAGE_MASK; + while (size > 0) { + BUG_ON(offset >= PAGE_SIZE); BUG_ON(copy_off > MAX_BUFFER_OFFSET); - if (start_new_rx_buffer(copy_off, size, 0)) { + bytes = PAGE_SIZE - offset; + + if (bytes > size) + bytes = size; + + if (start_new_rx_buffer(copy_off, bytes, 0)) { count++; copy_off = 0; } - bytes = size; if (copy_off + bytes > MAX_BUFFER_OFFSET) bytes = MAX_BUFFER_OFFSET - copy_off; copy_off += bytes; + + offset += bytes; size -= bytes; + + if (offset == PAGE_SIZE) + offset = 0; } } return count; @@ -403,14 +417,24 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, unsigned long bytes; /* Data must not cross a page boundary. */ - BUG_ON(size + offset > PAGE_SIZE); + BUG_ON(size + offset > PAGE_SIZE<meta + npo->meta_prod - 1; + /* Skip unused frames from start of page */ + page += offset >> PAGE_SHIFT; + offset &= ~PAGE_MASK; + while (size > 0) { + BUG_ON(offset >= PAGE_SIZE); BUG_ON(npo->copy_off > MAX_BUFFER_OFFSET); - if (start_new_rx_buffer(npo->copy_off, size, *head)) { + bytes = PAGE_SIZE - offset; + + if (bytes > size) + bytes = size; + + if (start_new_rx_buffer(npo->copy_off, bytes, *head)) { /* * Netfront requires there to be some data in the head * buffer. @@ -420,7 +444,6 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, meta = get_next_rx_buffer(vif, npo); } - bytes = size; if (npo->copy_off + bytes > MAX_BUFFER_OFFSET) bytes = MAX_BUFFER_OFFSET - npo->copy_off; @@ -453,6 +476,13 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, offset += bytes; size -= bytes; + /* Next frame */ + if (offset == PAGE_SIZE && size) { + BUG_ON(!PageCompound(page)); + page++; + offset = 0; + } + /* Leave a gap for the GSO descriptor. */ if (*head && skb_shinfo(skb)->gso_size && !vif->gso_prefix) vif->rx.req_cons++;