|
@@ -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:
|