Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 29 Apr 2010 18:14:14 +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: r207380 - head/sys/dev/sge
Message-ID:  <201004291814.o3TIEE7S020594@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: yongari
Date: Thu Apr 29 18:14:14 2010
New Revision: 207380
URL: http://svn.freebsd.org/changeset/base/207380

Log:
  Enable VLAN hardware tag insertion/stripping. Due to lack of SiS190
  controller, I'm not sure whether this is also applicable to SiS190
  so this feature is only activated on SiS191 controller.
  In theory, controller reinitialization is not needed when VLAN tag
  configuration is changed, but xclin said controller was not stable
  whenever toggling VLAN tag bit. To address that, sge(4)
  reinitialize controller for VLAN configuration which seems to work
  as expected. VLAN tag information for TX/RX descriptor and
  configure bit of RxMacControl register was found by xclin.
  
  Submitted by:	xclin <xclin <> cs dot nctu dot edu dot tw > (initial version)
  Tested by:	xclin <xclin <> cs dot nctu dot edu dot tw >

Modified:
  head/sys/dev/sge/if_sge.c
  head/sys/dev/sge/if_sgereg.h

Modified: head/sys/dev/sge/if_sge.c
==============================================================================
--- head/sys/dev/sge/if_sge.c	Thu Apr 29 18:00:42 2010	(r207379)
+++ head/sys/dev/sge/if_sge.c	Thu Apr 29 18:14:14 2010	(r207380)
@@ -137,6 +137,7 @@ static int	sge_get_mac_addr_eeprom(struc
 static uint16_t	sge_read_eeprom(struct sge_softc *, int);
 
 static void	sge_rxfilter(struct sge_softc *);
+static void	sge_setvlan(struct sge_softc *);
 static void	sge_reset(struct sge_softc *);
 static int	sge_list_rx_init(struct sge_softc *);
 static int	sge_list_rx_free(struct sge_softc *);
@@ -484,6 +485,25 @@ sge_rxfilter(struct sge_softc *sc)
 }
 
 static void
+sge_setvlan(struct sge_softc *sc)
+{
+	struct ifnet *ifp;
+	uint16_t rxfilt;
+
+	SGE_LOCK_ASSERT(sc);
+
+	ifp = sc->sge_ifp;
+	if ((ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0)
+		return;
+	rxfilt = CSR_READ_2(sc, RxMacControl);
+	if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0)
+		rxfilt |= RXMAC_STRIP_VLAN;
+	else
+		rxfilt &= ~RXMAC_STRIP_VLAN;
+	CSR_WRITE_2(sc, RxMacControl, rxfilt);
+}
+
+static void
 sge_reset(struct sge_softc *sc)
 {
 
@@ -619,6 +639,9 @@ sge_attach(device_t dev)
 	ether_ifattach(ifp, eaddr);
 
 	/* VLAN setup. */
+	if ((sc->sge_flags & SGE_FLAG_SIS190) == 0)
+		ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING |
+		    IFCAP_VLAN_HWCSUM;
 	ifp->if_capabilities |= IFCAP_VLAN_MTU;
 	ifp->if_capenable = ifp->if_capabilities;
 	/* Tell the upper layer(s) we support long frames. */
@@ -1175,9 +1198,12 @@ sge_rxeof(struct sge_softc *sc)
 				m->m_pkthdr.csum_data = 0xffff;
 			}
 		}
-		/*
-		 * TODO : VLAN hardware tag stripping.
-		 */
+		/* Check for VLAN tagged frame. */
+		if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 &&
+		    (rxstat & RDS_VLAN) != 0) {
+			m->m_pkthdr.ether_vtag = rxinfo & RDC_VLAN_MASK;
+			m->m_flags |= M_VLANTAG;
+		}
 		if ((sc->sge_flags & SGE_FLAG_SIS190) == 0) {
 			/*
 			 * Account for 10bytes auto padding which is used
@@ -1422,6 +1448,11 @@ sge_encap(struct sge_softc *sc, struct m
 	desc->sge_flags = htole32(txsegs[0].ds_len);
 	if (prod == SGE_TX_RING_CNT - 1)
 		desc->sge_flags |= htole32(RING_END);
+	/* Configure VLAN. */
+	if(((*m_head)->m_flags & M_VLANTAG) != 0) {
+		cflags |= (*m_head)->m_pkthdr.ether_vtag;
+		desc->sge_sts_size |= htole32(TDS_INS_VLAN);
+	}
 	desc->sge_cmdsts = htole32(TDC_DEF | TDC_CRC | TDC_PAD | cflags);
 #if 1
 	if ((sc->sge_flags & SGE_FLAG_SPEED_1000) != 0)
@@ -1563,6 +1594,7 @@ sge_init_locked(struct sge_softc *sc)
 		rxfilt |= RXMAC_STRIP_FCS | RXMAC_PAD_ENB;
 	CSR_WRITE_2(sc, RxMacControl, rxfilt);
 	sge_rxfilter(sc);
+	sge_setvlan(sc);
 
 	/* Initialize default speed/duplex information. */
 	if ((sc->sge_flags & SGE_FLAG_FASTETHER) == 0)
@@ -1653,7 +1685,7 @@ sge_ioctl(struct ifnet *ifp, u_long comm
 	struct sge_softc *sc;
 	struct ifreq *ifr;
 	struct mii_data *mii;
-	int error = 0, mask;
+	int error = 0, mask, reinit;
 
 	sc = ifp->if_softc;
 	ifr = (struct ifreq *)data;
@@ -1675,6 +1707,7 @@ sge_ioctl(struct ifnet *ifp, u_long comm
 		break;
 	case SIOCSIFCAP:
 		SGE_LOCK(sc);
+		reinit = 0;
 		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
 		if ((mask & IFCAP_TXCSUM) != 0 &&
 		    (ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
@@ -1687,7 +1720,24 @@ sge_ioctl(struct ifnet *ifp, u_long comm
 		if ((mask & IFCAP_RXCSUM) != 0 &&
 		    (ifp->if_capabilities & IFCAP_RXCSUM) != 0)
 			ifp->if_capenable ^= IFCAP_RXCSUM;
+		if ((mask & IFCAP_VLAN_HWCSUM) != 0 &&
+		    (ifp->if_capabilities & IFCAP_VLAN_HWCSUM) != 0)
+			ifp->if_capenable ^= IFCAP_VLAN_HWCSUM;
+		if ((mask & IFCAP_VLAN_HWTAGGING) != 0 &&
+		    (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0) {
+			/*
+			 * Due to unknown reason, toggling VLAN hardware
+			 * tagging require interface reinitialization.
+			 */
+			ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
+			reinit = 1;
+		}
+		if (reinit > 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+			sge_init_locked(sc);
+		}
 		SGE_UNLOCK(sc);
+		VLAN_CAPABILITIES(ifp);
 		break;
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:

Modified: head/sys/dev/sge/if_sgereg.h
==============================================================================
--- head/sys/dev/sge/if_sgereg.h	Thu Apr 29 18:00:42 2010	(r207379)
+++ head/sys/dev/sge/if_sgereg.h	Thu Apr 29 18:14:14 2010	(r207380)
@@ -137,6 +137,7 @@
 #define	AcceptAllPhys		0x0100
 #define	AcceptErr		0x0020
 #define	AcceptRunt		0x0010
+#define	RXMAC_STRIP_VLAN	0x0020
 #define	RXMAC_STRIP_FCS		0x0010
 #define	RXMAC_PAD_ENB		0x0004
 
@@ -187,12 +188,14 @@
 #define	TDC_COL			0x00040000
 #define	TDC_CRC			0x00020000
 #define	TDC_PAD			0x00010000
+#define	TDC_VLAN_MASK		0x0000FFFF
 
 #define	SGE_TX_INTR_FRAMES	32
 
 /*
  * TX descriptor status bits.
  */
+#define	TDS_INS_VLAN		0x80000000
 #define	TDS_OWC			0x00080000
 #define	TDS_ABT			0x00040000
 #define	TDS_FIFO		0x00020000
@@ -219,11 +222,12 @@
 #define	RDC_UCAST		0x00040000
 #define	RDC_CRCOFF		0x00020000
 #define	RDC_PREADD		0x00010000
+#define	RDC_VLAN_MASK		0x0000FFFF
 
 /*
  * RX descriptor status bits
  */
-#define	RDS_TAGON		0x80000000
+#define	RDS_VLAN		0x80000000
 #define	RDS_DESCS		0x3f000000
 #define	RDS_ABORT		0x00800000
 #define	RDS_SHORT		0x00400000
@@ -240,7 +244,7 @@
 #define	RX_ERR_BITS 		"\20"					\
 				"\21CRCOK\22COLON\23NIBON\24OVRUN"	\
 				"\25MIIER\26LIMIT\27SHORT\30ABORT"	\
-				"\40TAGON"
+				"\40VLAN"
 
 #define	RING_END		0x80000000
 #define	SGE_RX_BYTES(x)		((x) & 0xFFFF)



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