From 587d5e790ac6117f82850ab36a799af8703a7988 Mon Sep 17 00:00:00 2001 From: tsutsui Date: Sat, 21 Oct 2006 16:26:35 +0000 Subject: [PATCH] Fix hardware VLAN tagging support on vge(4): - On TX, vge(4) seems to assume that tags are written in little endian. We already use htole32() to write values into descriptors, so extra byteswap by htons() is not needed there. - On RX, vge(4) seems to store tags in network byteorder. We have to swap byteorder regardless of host's byteorder (i.e. we have to use bswap16() rather than ntohs()) because we already use le32toh() to read values from descriptors. Anyway, no need to use htons()/ntohs() because there is no stream data. Tested on both i386 and macppc, and OK'ed by Pavel Cahyna. --- sys/dev/pci/if_vge.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/sys/dev/pci/if_vge.c b/sys/dev/pci/if_vge.c index 7baa8f55346d..b0d338eec4df 100644 --- a/sys/dev/pci/if_vge.c +++ b/sys/dev/pci/if_vge.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_vge.c,v 1.19 2006/10/17 09:55:12 tsutsui Exp $ */ +/* $NetBSD: if_vge.c,v 1.20 2006/10/21 16:26:35 tsutsui Exp $ */ /*- * Copyright (c) 2004 @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_vge.c,v 1.19 2006/10/17 09:55:12 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_vge.c,v 1.20 2006/10/21 16:26:35 tsutsui Exp $"); /* * VIA Networking Technologies VT612x PCI gigabit ethernet NIC driver. @@ -1223,9 +1223,16 @@ vge_rxeof(struct vge_softc *sc) m->m_pkthdr.csum_flags |= M_CSUM_TCP_UDP_BAD; } - if (rxstat & VGE_RDSTS_VTAG) + if (rxstat & VGE_RDSTS_VTAG) { + /* + * We use bswap16() here because: + * On LE machines, tag is stored in BE as stream data. + * On BE machines, tag is stored in BE as stream data + * but it was already swapped by le32toh() above. + */ VLAN_INPUT_TAG(ifp, m, - ntohs((rxctl & VGE_RDCTL_VLANID)), continue); + bswap16(rxctl & VGE_RDCTL_VLANID), continue); + } #if NBPFILTER > 0 /* @@ -1581,9 +1588,14 @@ vge_encap(struct vge_softc *sc, struct mbuf *m_head, int idx) */ mtag = VLAN_OUTPUT_TAG(&sc->sc_ethercom, m_head); - if (mtag != NULL) - d->vge_ctl |= - htole32(htons(VLAN_TAG_VALUE(mtag)) | VGE_TDCTL_VTAG); + if (mtag != NULL) { + /* + * No need htons() here since vge(4) chip assumes + * that tags are written in little endian and + * we already use htole32() here. + */ + d->vge_ctl |= htole32(VLAN_TAG_VALUE(mtag) | VGE_TDCTL_VTAG); + } d->vge_sts |= htole32(VGE_TDSTS_OWN);