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>