From patchwork Thu Mar 18 19:20:10 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Glendinning X-Patchwork-Id: 48081 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 962E6B7D11 for ; Fri, 19 Mar 2010 06:20:21 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752061Ab0CRTUO (ORCPT ); Thu, 18 Mar 2010 15:20:14 -0400 Received: from 77-44-110-64.xdsl.murphx.net ([77.44.110.64]:33320 "EHLO drevil2.shawell.net" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751823Ab0CRTUN (ORCPT ); Thu, 18 Mar 2010 15:20:13 -0400 Received: from localhost.localdomain (unknown [10.0.20.109]) by drevil2.shawell.net (Postfix) with ESMTP id 6A79267BC8 for ; Thu, 18 Mar 2010 19:20:10 +0000 (GMT) From: Steve Glendinning To: netdev@vger.kernel.org Subject: [PATCH] smsc95xx: Fix tx checksum offload for small packets Date: Thu, 18 Mar 2010 19:20:10 +0000 Message-Id: <1268940010-19394-1-git-send-email-steve.glendinning@smsc.com> X-Mailer: git-send-email 1.6.6.1 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org TX checksum offload does not work properly when transmitting UDP packets with 0, 1 or 2 bytes of data. This patch works around the problem by calculating checksums for these packets in the driver. Signed-off-by: Steve Glendinning --- drivers/net/usb/smsc95xx.c | 18 +++++++++++++++--- 1 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index d222d7e..829963f 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1189,9 +1189,21 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, } if (csum) { - u32 csum_preamble = smsc95xx_calc_csum_preamble(skb); - skb_push(skb, 4); - memcpy(skb->data, &csum_preamble, 4); + if (skb->len <= 45) { + /* workaround - hardware tx checksum does not work + * properly with extremely small packets */ + long csstart = skb->csum_start - skb_headroom(skb); + __wsum calc = csum_partial(skb->data + csstart, + skb->len - csstart, 0); + *((__sum16 *)(skb->data + csstart + + skb->csum_offset)) = csum_fold(calc); + + csum = false; + } else { + u32 csum_preamble = smsc95xx_calc_csum_preamble(skb); + skb_push(skb, 4); + memcpy(skb->data, &csum_preamble, 4); + } } skb_push(skb, 4);