Module Name:    src
Committed By:   msaitoh
Date:           Tue Oct  2 15:22:46 UTC 2012

Modified Files:
        src/sys/dev/marvell: if_mvgbe.c

Log Message:
- Fix a bug that a fragmented packet is marked as bad checksum. It causes
  a real bug when HW checksum offload function is used. It was easy to
  reproduce with NFS UDP mount.
- Fix a potential bug that a packet other than TCP and UDP is marked as bad
  checksum.


To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 src/sys/dev/marvell/if_mvgbe.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/marvell/if_mvgbe.c
diff -u src/sys/dev/marvell/if_mvgbe.c:1.20 src/sys/dev/marvell/if_mvgbe.c:1.21
--- src/sys/dev/marvell/if_mvgbe.c:1.20	Fri Sep 21 00:26:15 2012
+++ src/sys/dev/marvell/if_mvgbe.c	Tue Oct  2 15:22:46 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_mvgbe.c,v 1.20 2012/09/21 00:26:15 msaitoh Exp $	*/
+/*	$NetBSD: if_mvgbe.c,v 1.21 2012/10/02 15:22:46 msaitoh Exp $	*/
 /*
  * Copyright (c) 2007, 2008 KIYOHARA Takashi
  * All rights reserved.
@@ -25,7 +25,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.20 2012/09/21 00:26:15 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.21 2012/10/02 15:22:46 msaitoh Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -1676,6 +1676,7 @@ mvgbe_rxeof(struct mvgbe_softc *sc)
 	struct mbuf *m;
 	bus_dmamap_t dmamap;
 	uint32_t rxstat;
+	uint16_t bufsize;
 	int idx, cur, total_len;
 
 	idx = sc->sc_cdata.mvgbe_rx_prod;
@@ -1715,6 +1716,7 @@ mvgbe_rxeof(struct mvgbe_softc *sc)
 		cdata->mvgbe_rx_chain[idx].mvgbe_mbuf = NULL;
 		total_len = cur_rx->bytecnt;
 		rxstat = cur_rx->cmdsts;
+		bufsize = cur_rx->bufsize;
 
 		cdata->mvgbe_rx_map[idx] = NULL;
 
@@ -1743,20 +1745,30 @@ mvgbe_rxeof(struct mvgbe_softc *sc)
 			goto sw_csum;
 
 		if (rxstat & MVGBE_RX_IP_FRAME_TYPE) {
+			int flgs = 0;
+
 			/* Check IPv4 header checksum */
 			m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
 			if (!(rxstat & MVGBE_RX_IP_HEADER_OK))
-				m->m_pkthdr.csum_flags |=
-				    M_CSUM_IPv4_BAD;
+				flgs |= M_CSUM_IPv4_BAD;
+
 			/* Check TCPv4/UDPv4 checksum */
-			if ((rxstat & MVGBE_RX_L4_TYPE_MASK) ==
-			    MVGBE_RX_L4_TYPE_TCP)
-				m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
-			else if ((rxstat & MVGBE_RX_L4_TYPE_MASK) ==
-			    MVGBE_RX_L4_TYPE_UDP)
-				m->m_pkthdr.csum_flags |= M_CSUM_UDPv4;
-			if (!(rxstat & MVGBE_RX_L4_CHECKSUM))
-				m->m_pkthdr.csum_flags |= M_CSUM_TCP_UDP_BAD;
+			if ((bufsize & MVGBE_RX_MAX_FRAME_LEN_ERROR) == 0) {
+				/* Not fragmented */
+
+				if ((rxstat & MVGBE_RX_L4_TYPE_MASK) ==
+				    MVGBE_RX_L4_TYPE_TCP)
+					flgs |= M_CSUM_TCPv4;
+				else if ((rxstat & MVGBE_RX_L4_TYPE_MASK) ==
+				    MVGBE_RX_L4_TYPE_UDP)
+					flgs |= M_CSUM_UDPv4;
+
+				if (((flgs & (M_CSUM_TCPv4|M_CSUM_UDPv4)) != 0)
+				    && !(rxstat & MVGBE_RX_L4_CHECKSUM))
+					flgs |= M_CSUM_TCP_UDP_BAD;
+			}
+
+			m->m_pkthdr.csum_flags = flgs;
 		}
 sw_csum:
 

Reply via email to