aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAyaz Abdulla <aabdulla@nvidia.com>2008-01-13 16:02:55 -0500
committerDavid S. Miller <davem@davemloft.net>2008-02-03 07:28:37 -0500
commitbfaffe8fae0273b57f2146d1759cbd25d07c81e9 (patch)
tree126bdea1b8f7d8d2231a32ddd5dda4a349905a8a /drivers
parent0a62677b26ccb31cd81fc55d14d27d8cd3560d7d (diff)
forcedeth: checksum fix
The driver should inform the stack when checksum has been performed by the HW when both IP and TCP (or UDP) checksum flags are indicated by HW. Previously, it would also inform the stack when only IP checksum flag was indicated by HW. This can cause data corruption when IP fragments are used. The IP Identification field can wrap around and cause data from new fragments to fill into older fragment slots with same IP Id. The stack would then not perform TCP/UDP checksum (after re-assembly of all fragments) since driver falsely stated it was already calculated. Signed-off-by: Ayaz Abdulla <aabdulla@nvidia.com> Signed-off-by: Jeff Garzik <jeff@garzik.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/forcedeth.c24
1 files changed, 7 insertions, 17 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index ce3f25ff2737..d73ca2439681 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -471,9 +471,9 @@ union ring_type {
471#define NV_RX_AVAIL (1<<31) 471#define NV_RX_AVAIL (1<<31)
472 472
473#define NV_RX2_CHECKSUMMASK (0x1C000000) 473#define NV_RX2_CHECKSUMMASK (0x1C000000)
474#define NV_RX2_CHECKSUMOK1 (0x10000000) 474#define NV_RX2_CHECKSUM_IP (0x10000000)
475#define NV_RX2_CHECKSUMOK2 (0x14000000) 475#define NV_RX2_CHECKSUM_IP_TCP (0x14000000)
476#define NV_RX2_CHECKSUMOK3 (0x18000000) 476#define NV_RX2_CHECKSUM_IP_UDP (0x18000000)
477#define NV_RX2_DESCRIPTORVALID (1<<29) 477#define NV_RX2_DESCRIPTORVALID (1<<29)
478#define NV_RX2_SUBSTRACT1 (1<<25) 478#define NV_RX2_SUBSTRACT1 (1<<25)
479#define NV_RX2_ERROR1 (1<<18) 479#define NV_RX2_ERROR1 (1<<18)
@@ -2375,14 +2375,9 @@ static int nv_rx_process(struct net_device *dev, int limit)
2375 goto next_pkt; 2375 goto next_pkt;
2376 } 2376 }
2377 } 2377 }
2378 if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK2)/*ip and tcp */ { 2378 if (((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_TCP) || /*ip and tcp */
2379 ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_UDP)) /*ip and udp */
2379 skb->ip_summed = CHECKSUM_UNNECESSARY; 2380 skb->ip_summed = CHECKSUM_UNNECESSARY;
2380 } else {
2381 if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK1 ||
2382 (flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK3) {
2383 skb->ip_summed = CHECKSUM_UNNECESSARY;
2384 }
2385 }
2386 } else { 2381 } else {
2387 dev_kfree_skb(skb); 2382 dev_kfree_skb(skb);
2388 goto next_pkt; 2383 goto next_pkt;
@@ -2474,14 +2469,9 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
2474 } 2469 }
2475 } 2470 }
2476 2471
2477 if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK2)/*ip and tcp */ { 2472 if (((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_TCP) || /*ip and tcp */
2473 ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_UDP)) /*ip and udp */
2478 skb->ip_summed = CHECKSUM_UNNECESSARY; 2474 skb->ip_summed = CHECKSUM_UNNECESSARY;
2479 } else {
2480 if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK1 ||
2481 (flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK3) {
2482 skb->ip_summed = CHECKSUM_UNNECESSARY;
2483 }
2484 }
2485 2475
2486 /* got a valid packet - forward it to the network core */ 2476 /* got a valid packet - forward it to the network core */
2487 skb_put(skb, len); 2477 skb_put(skb, len);