summaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-03-08 21:42:30 +0100
committerJeff Garzik <jeff@garzik.org>2007-03-09 17:51:32 +0100
commit874183072de73a36a958585e3186639fd2634701 (patch)
tree9218c90305ca2622da826801d65c9a1a3a689a15 /drivers/net/sky2.c
parentmv643xx: Clear pending interrupts before calling request_irq (diff)
downloadlinux-874183072de73a36a958585e3186639fd2634701.tar.xz
linux-874183072de73a36a958585e3186639fd2634701.zip
sky2: turn off Rx checksum on bad hardware
On Yukon FE, occasional hardware receive checksum errors are seen. An early indication of the problem is single bit differences in the two checksum engines. Use this as a detection mechanism to turn off Rx checksumming. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r--drivers/net/sky2.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 53839979cfb8..ab0ab92583fe 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -2165,9 +2165,27 @@ force_update:
/* fall through */
#endif
case OP_RXCHKS:
- skb = sky2->rx_ring[sky2->rx_next].skb;
- skb->ip_summed = CHECKSUM_COMPLETE;
- skb->csum = status & 0xffff;
+ if (!sky2->rx_csum)
+ break;
+
+ /* Both checksum counters are programmed to start at
+ * the same offset, so unless there is a problem they
+ * should match. This failure is an early indication that
+ * hardware receive checksumming won't work.
+ */
+ if (likely(status >> 16 == (status & 0xffff))) {
+ skb = sky2->rx_ring[sky2->rx_next].skb;
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ skb->csum = status & 0xffff;
+ } else {
+ printk(KERN_NOTICE PFX "%s: hardware receive "
+ "checksum problem (status = %#x)\n",
+ dev->name, status);
+ sky2->rx_csum = 0;
+ sky2_write32(sky2->hw,
+ Q_ADDR(rxqaddr[le->link], Q_CSR),
+ BMU_DIS_RX_CHKSUM);
+ }
break;
case OP_TXINDEXLE: