From patchwork Thu Mar 15 06:18:32 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Dumazet X-Patchwork-Id: 146840 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 1EA26B6FA3 for ; Thu, 15 Mar 2012 17:18:41 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755371Ab2COGSj (ORCPT ); Thu, 15 Mar 2012 02:18:39 -0400 Received: from mail-pz0-f52.google.com ([209.85.210.52]:33291 "EHLO mail-pz0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754897Ab2COGSh (ORCPT ); Thu, 15 Mar 2012 02:18:37 -0400 Received: by dadp12 with SMTP id p12so4297616dad.11 for ; Wed, 14 Mar 2012 23:18:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:subject:from:to:cc:date:content-type:x-mailer :content-transfer-encoding:mime-version; bh=PtP4W7iDs6bj8YT7enJVQUL2nNnYLSApkSSYL5+TABc=; b=o6ysPZtIqZhi80nEgMa0E3VbmAT6f1MwZsIOy5bq4Epc1I+OXpbZ7ilyOmP2lbjblw eZ0XdQloj99kZc/OUDrBCdv4I/w39vR2cA45WsVNhNJfSnffgO6A2bWDZv84gQC2eGgN J1E8oR4JrPM8jjPAAxepaQgQS5X/1azFiq/GiHqD9WB/WKqog2VqlzzsNVxjGvr3HzWW LHNqKHL5OrluzjQ7P6aFJ09SHRfA/RlUlVfyuuretKmGjgNhQsOZjb9r15KnAwlRK65y RLJz4BDCAPqJqZVEDaj2XWE2ppLmpkbqkP8cawHPEKSqBdk1f8gJ2kCWu9+ZJboytfTD /FJg== Received: by 10.68.226.170 with SMTP id rt10mr2344446pbc.117.1331792316527; Wed, 14 Mar 2012 23:18:36 -0700 (PDT) Received: from [10.0.0.8] (c-107-3-167-36.hsd1.ca.comcast.net. [107.3.167.36]) by mx.google.com with ESMTPS id f7sm1177801pbr.3.2012.03.14.23.18.33 (version=SSLv3 cipher=OTHER); Wed, 14 Mar 2012 23:18:34 -0700 (PDT) Message-ID: <1331792312.2543.16.camel@edumazet-laptop> Subject: [PATCH net-next] asix: asix_rx_fixup surgery to reduce skb truesizes From: Eric Dumazet To: Greg Kroah-Hartman , David Miller Cc: linux-usb@vger.kernel.org, netdev , Aurelien Jacobs , Trond Wuellner , Grant Grundler , Paul Stewart Date: Wed, 14 Mar 2012 23:18:32 -0700 X-Mailer: Evolution 3.2.2- Mime-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org asix_rx_fixup() is complex, and does some unnecessary memory copies (at least on x86 where NET_IP_ALIGN is 0) Also, it tends to provide skbs with a big truesize (4096+256 with MTU=1500) to upper stack, so incoming trafic consume a lot of memory and I noticed early packet drops because we hit socket rcvbuf too fast. Switch to a different strategy, using copybreak so that we provide nice skbs to upper stack (including the NET_SKB_PAD to avoid future head reallocations in some paths) With this patch, I no longer see packets drops or tcp collapses on various tcp workload with a AX88772 adapter. Signed-off-by: Eric Dumazet Cc: Aurelien Jacobs Cc: Greg Kroah-Hartman Cc: Trond Wuellner Cc: Grant Grundler Cc: Paul Stewart Reviewed-by: Grant Grundler Reviewed-by: Grant Grundler Reviewed-by: Grant Grundler --- drivers/net/usb/asix.c | 90 +++++++++------------------------------ 1 file changed, 21 insertions(+), 69 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 8e84f5b..27d5440 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -305,88 +305,40 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { - u8 *head; - u32 header; - char *packet; - struct sk_buff *ax_skb; - u16 size; + int offset = 0; - head = (u8 *) skb->data; - memcpy(&header, head, sizeof(header)); - le32_to_cpus(&header); - packet = head + sizeof(header); - - skb_pull(skb, 4); - - while (skb->len > 0) { - if ((header & 0x07ff) != ((~header >> 16) & 0x07ff)) - netdev_err(dev->net, "asix_rx_fixup() Bad Header Length\n"); + while (offset + sizeof(u32) < skb->len) { + struct sk_buff *ax_skb; + u16 size; + u32 header = get_unaligned_le32(skb->data + offset); + offset += sizeof(u32); + /* get the packet length */ - size = (u16) (header & 0x000007ff); - - if ((skb->len) - ((size + 1) & 0xfffe) == 0) { - u8 alignment = (unsigned long)skb->data & 0x3; - if (alignment != 0x2) { - /* - * not 16bit aligned so use the room provided by - * the 32 bit header to align the data - * - * note we want 16bit alignment as MAC header is - * 14bytes thus ip header will be aligned on - * 32bit boundary so accessing ipheader elements - * using a cast to struct ip header wont cause - * an unaligned accesses. - */ - u8 realignment = (alignment + 2) & 0x3; - memmove(skb->data - realignment, - skb->data, - size); - skb->data -= realignment; - skb_set_tail_pointer(skb, size); - } - return 2; + size = (u16) (header & 0x7ff); + if (size != ((~header >> 16) & 0x07ff)) { + netdev_err(dev->net, "asix_rx_fixup() Bad Header Length\n"); + return 0; } - if (size > dev->net->mtu + ETH_HLEN) { + if ((size > dev->net->mtu + ETH_HLEN) || + (size + offset > skb->len)) { netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", size); return 0; } - ax_skb = skb_clone(skb, GFP_ATOMIC); - if (ax_skb) { - u8 alignment = (unsigned long)packet & 0x3; - ax_skb->len = size; - - if (alignment != 0x2) { - /* - * not 16bit aligned use the room provided by - * the 32 bit header to align the data - */ - u8 realignment = (alignment + 2) & 0x3; - memmove(packet - realignment, packet, size); - packet -= realignment; - } - ax_skb->data = packet; - skb_set_tail_pointer(ax_skb, size); - usbnet_skb_return(dev, ax_skb); - } else { + ax_skb = netdev_alloc_skb_ip_align(dev->net, size); + if (!ax_skb) return 0; - } - - skb_pull(skb, (size + 1) & 0xfffe); - if (skb->len < sizeof(header)) - break; + skb_put(ax_skb, size); + memcpy(ax_skb->data, skb->data + offset, size); + usbnet_skb_return(dev, ax_skb); - head = (u8 *) skb->data; - memcpy(&header, head, sizeof(header)); - le32_to_cpus(&header); - packet = head + sizeof(header); - skb_pull(skb, 4); + offset += (size + 1) & 0xfffe; } - if (skb->len < 0) { + if (skb->len != offset) { netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d\n", skb->len); return 0; @@ -1541,7 +1493,7 @@ static const struct driver_info ax88772_info = { .status = asix_status, .link_reset = ax88772_link_reset, .reset = ax88772_reset, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET, .rx_fixup = asix_rx_fixup, .tx_fixup = asix_tx_fixup, };