diff options
author | Guo-Fu Tseng <cooldavid@cooldavid.org> | 2011-02-13 14:27:17 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-02-14 00:44:43 -0500 |
commit | c00cd82641023ade3c44b4f11140a8afad460415 (patch) | |
tree | ebabaf3e94536309efbfea8f0079d951db2b9114 /drivers/net/jme.c | |
parent | 8b53abae582cee9a17320460e0f05474097192b6 (diff) |
jme: Don't show UDP Checksum error if HW misjudged
Some JMicron Chip treat 0 as error checksum for UDP packets.
Which should be "No checksum needed".
Reported-by: Adam Swift <Adam.Swift@omnitude.net>
Confirmed-by: "Aries Lee" <arieslee@jmicron.com>
Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/jme.c')
-rw-r--r-- | 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 ed35e17f43dc..5b441b75e138 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c | |||
@@ -956,8 +956,34 @@ jme_disable_rx_engine(struct jme_adapter *jme) | |||
956 | jme_mac_rxclk_off(jme); | 956 | jme_mac_rxclk_off(jme); |
957 | } | 957 | } |
958 | 958 | ||
959 | static u16 | ||
960 | jme_udpsum(struct sk_buff *skb) | ||
961 | { | ||
962 | u16 csum = 0xFFFFu; | ||
963 | |||
964 | if (skb->len < (ETH_HLEN + sizeof(struct iphdr))) | ||
965 | return csum; | ||
966 | if (skb->protocol != htons(ETH_P_IP)) | ||
967 | return csum; | ||
968 | skb_set_network_header(skb, ETH_HLEN); | ||
969 | if ((ip_hdr(skb)->protocol != IPPROTO_UDP) || | ||
970 | (skb->len < (ETH_HLEN + | ||
971 | (ip_hdr(skb)->ihl << 2) + | ||
972 | sizeof(struct udphdr)))) { | ||
973 | skb_reset_network_header(skb); | ||
974 | return csum; | ||
975 | } | ||
976 | skb_set_transport_header(skb, | ||
977 | ETH_HLEN + (ip_hdr(skb)->ihl << 2)); | ||
978 | csum = udp_hdr(skb)->check; | ||
979 | skb_reset_transport_header(skb); | ||
980 | skb_reset_network_header(skb); | ||
981 | |||
982 | return csum; | ||
983 | } | ||
984 | |||
959 | static int | 985 | static int |
960 | jme_rxsum_ok(struct jme_adapter *jme, u16 flags) | 986 | jme_rxsum_ok(struct jme_adapter *jme, u16 flags, struct sk_buff *skb) |
961 | { | 987 | { |
962 | if (!(flags & (RXWBFLAG_TCPON | RXWBFLAG_UDPON | RXWBFLAG_IPV4))) | 988 | if (!(flags & (RXWBFLAG_TCPON | RXWBFLAG_UDPON | RXWBFLAG_IPV4))) |
963 | return false; | 989 | return false; |
@@ -970,7 +996,7 @@ jme_rxsum_ok(struct jme_adapter *jme, u16 flags) | |||
970 | } | 996 | } |
971 | 997 | ||
972 | if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_UDPON | RXWBFLAG_UDPCS)) | 998 | if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_UDPON | RXWBFLAG_UDPCS)) |
973 | == RXWBFLAG_UDPON)) { | 999 | == RXWBFLAG_UDPON) && jme_udpsum(skb)) { |
974 | if (flags & RXWBFLAG_IPV4) | 1000 | if (flags & RXWBFLAG_IPV4) |
975 | netif_err(jme, rx_err, jme->dev, "UDP Checksum error\n"); | 1001 | netif_err(jme, rx_err, jme->dev, "UDP Checksum error\n"); |
976 | return false; | 1002 | return false; |
@@ -1018,7 +1044,7 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx) | |||
1018 | skb_put(skb, framesize); | 1044 | skb_put(skb, framesize); |
1019 | skb->protocol = eth_type_trans(skb, jme->dev); | 1045 | skb->protocol = eth_type_trans(skb, jme->dev); |
1020 | 1046 | ||
1021 | if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags))) | 1047 | if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags), skb)) |
1022 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1048 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
1023 | else | 1049 | else |
1024 | skb_checksum_none_assert(skb); | 1050 | skb_checksum_none_assert(skb); |