From patchwork Mon Feb 14 05:27:17 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guo-Fu Tseng X-Patchwork-Id: 83042 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 17871B716D for ; Mon, 14 Feb 2011 16:27:48 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750800Ab1BNF1g (ORCPT ); Mon, 14 Feb 2011 00:27:36 -0500 Received: from cooldavid.org ([114.33.45.68]:39362 "EHLO cooldavid.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750703Ab1BNF1e (ORCPT ); Mon, 14 Feb 2011 00:27:34 -0500 Received: from kh (cooldavid-1-pt.tunnel.tserv3.fmt2.ipv6.he.net [IPv6:2001:470:1f04:16bf::2]) by cooldavid.org (Postfix) with SMTP id DB378247C72; Mon, 14 Feb 2011 13:27:35 +0800 (CST) Received: by kh (sSMTP sendmail emulation); Mon, 14 Feb 2011 13:27:19 +0800 From: "Guo-Fu Tseng" To: "David Miller" Cc: Guo-Fu Tseng , "linux-netdev" , "Aries Lee" , "Devinchiu" , "Ethan Hsiao" Subject: [PATCH net-next-2.6 1/2] jme: Don't show UDP Checksum error if HW misjudged Date: Mon, 14 Feb 2011 13:27:17 +0800 Message-Id: <1297661238-1467-1-git-send-email-cooldavid@cooldavid.org> X-Mailer: git-send-email 1.7.2.2 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Guo-Fu Tseng Some JMicron Chip treat 0 as error checksum for UDP packets. Which should be "No checksum needed". Reported-by: Adam Swift Confirmed-by: "Aries Lee" Signed-off-by: Guo-Fu Tseng --- drivers/net/jme.c | 32 +++++++++++++++++++++++++++++--- 1 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/net/jme.c b/drivers/net/jme.c index ed35e17..5b441b7 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -956,8 +956,34 @@ jme_disable_rx_engine(struct jme_adapter *jme) jme_mac_rxclk_off(jme); } +static u16 +jme_udpsum(struct sk_buff *skb) +{ + u16 csum = 0xFFFFu; + + if (skb->len < (ETH_HLEN + sizeof(struct iphdr))) + return csum; + if (skb->protocol != htons(ETH_P_IP)) + return csum; + skb_set_network_header(skb, ETH_HLEN); + if ((ip_hdr(skb)->protocol != IPPROTO_UDP) || + (skb->len < (ETH_HLEN + + (ip_hdr(skb)->ihl << 2) + + sizeof(struct udphdr)))) { + skb_reset_network_header(skb); + return csum; + } + skb_set_transport_header(skb, + ETH_HLEN + (ip_hdr(skb)->ihl << 2)); + csum = udp_hdr(skb)->check; + skb_reset_transport_header(skb); + skb_reset_network_header(skb); + + return csum; +} + static int -jme_rxsum_ok(struct jme_adapter *jme, u16 flags) +jme_rxsum_ok(struct jme_adapter *jme, u16 flags, struct sk_buff *skb) { if (!(flags & (RXWBFLAG_TCPON | RXWBFLAG_UDPON | RXWBFLAG_IPV4))) return false; @@ -970,7 +996,7 @@ jme_rxsum_ok(struct jme_adapter *jme, u16 flags) } if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_UDPON | RXWBFLAG_UDPCS)) - == RXWBFLAG_UDPON)) { + == RXWBFLAG_UDPON) && jme_udpsum(skb)) { if (flags & RXWBFLAG_IPV4) netif_err(jme, rx_err, jme->dev, "UDP Checksum error\n"); return false; @@ -1018,7 +1044,7 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx) skb_put(skb, framesize); skb->protocol = eth_type_trans(skb, jme->dev); - if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags))) + if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags), skb)) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb_checksum_none_assert(skb);