Skip to content

Commit

Permalink
Enable VLAN hardware tag insertion/stripping. Due to lack of SiS190
Browse files Browse the repository at this point in the history
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 >
  • Loading branch information
yongari authored and yongari committed Apr 29, 2010
1 parent a570282 commit 1294f27
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 6 deletions.
58 changes: 54 additions & 4 deletions sys/dev/sge/if_sge.c
Expand Up @@ -137,6 +137,7 @@ static int sge_get_mac_addr_eeprom(struct sge_softc *, uint8_t *);
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 *);
Expand Down Expand Up @@ -483,6 +484,25 @@ sge_rxfilter(struct sge_softc *sc)
CSR_WRITE_4(sc, RxHashTable2, hashes[1]);
}

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)
{
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1422,6 +1448,11 @@ sge_encap(struct sge_softc *sc, struct mbuf **m_head)
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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1653,7 +1685,7 @@ sge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
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;
Expand All @@ -1675,6 +1707,7 @@ sge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
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) {
Expand All @@ -1687,7 +1720,24 @@ sge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
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:
Expand Down
8 changes: 6 additions & 2 deletions sys/dev/sge/if_sgereg.h
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand Down

0 comments on commit 1294f27

Please sign in to comment.