Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 9 Dec 2008 04:30:47 +0000 (UTC)
From:      Pyun YongHyeon <yongari@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r185784 - head/sys/dev/sis
Message-ID:  <200812090430.mB94UlWU079916@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: yongari
Date: Tue Dec  9 04:30:47 2008
New Revision: 185784
URL: http://svn.freebsd.org/changeset/base/185784

Log:
  Fix a long standing VLAN tagged frame handling bug.
  When VLAN tagged frame is received the hardware sets 'LONG' bit of
  Rx status word. It is always set when the size of received frame
  exceeded 1518 bytes, including CRC. This VLAN tagged frame clears
  'OK' bit of Rx status word such that driver should not rely on 'OK'
  bit of Rx status word to pass the VLAN tagged frame to upper stack.
  
  To fix the bug, don't use SIS_CMDSTS_PKT_OK for Rx error check and
  introduce SIS_RXSTAT_ERROR macro that checks Rx errors. If we are
  configured to accept VLAN tagged frames and the received frame size
  is less than or equal to maximum allowed length of VLAN tagged
  frame, clear 'LONG' bit of Rx status word before checking Rx
  errors.
  
  Reported by:	Vladimir Ermako	< samflanker <> gmail DOT com >
  Tested by:	Vladimir Ermako	< samflanker <> gmail DOT com >

Modified:
  head/sys/dev/sis/if_sis.c
  head/sys/dev/sis/if_sisreg.h

Modified: head/sys/dev/sis/if_sis.c
==============================================================================
--- head/sys/dev/sis/if_sis.c	Tue Dec  9 04:17:44 2008	(r185783)
+++ head/sys/dev/sis/if_sis.c	Tue Dec  9 04:30:47 2008	(r185784)
@@ -1432,7 +1432,11 @@ sis_rxeof(struct sis_softc *sc)
 		 * it should simply get re-used next time this descriptor
 	 	 * comes up in the ring.
 		 */
-		if (!(rxstat & SIS_CMDSTS_PKT_OK)) {
+		if ((ifp->if_capenable & IFCAP_VLAN_MTU) != 0 &&
+		    total_len <= (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN -
+		    ETHER_CRC_LEN))
+			rxstat &= ~SIS_RXSTAT_GIANT;
+		if (SIS_RXSTAT_ERROR(rxstat) != 0) {
 			ifp->if_ierrors++;
 			if (rxstat & SIS_RXSTAT_COLL)
 				ifp->if_collisions++;

Modified: head/sys/dev/sis/if_sisreg.h
==============================================================================
--- head/sys/dev/sis/if_sisreg.h	Tue Dec  9 04:17:44 2008	(r185783)
+++ head/sys/dev/sis/if_sisreg.h	Tue Dec  9 04:30:47 2008	(r185784)
@@ -348,6 +348,11 @@ struct sis_desc {
 #define SIS_RXSTAT_OVERRUN	0x02000000
 #define SIS_RXSTAT_RX_ABORT	0x04000000
 
+#define	SIS_RXSTAT_ERROR(x)						\
+	((x) & (SIS_RXSTAT_RX_ABORT | SIS_RXSTAT_OVERRUN |		\
+	SIS_RXSTAT_GIANT | SIS_RXSTAT_SYMBOLERR | SIS_RXSTAT_RUNT |	\
+	SIS_RXSTAT_CRCERR | SIS_RXSTAT_ALIGNERR))
+
 #define SIS_DSTCLASS_REJECT	0x00000000
 #define SIS_DSTCLASS_UNICAST	0x00800000
 #define SIS_DSTCLASS_MULTICAST	0x01000000



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812090430.mB94UlWU079916>