summaryrefslogtreecommitdiffstats
path: root/sys/dev/vge
diff options
context:
space:
mode:
authorru <ru@FreeBSD.org>2006-11-30 21:01:59 +0000
committerru <ru@FreeBSD.org>2006-11-30 21:01:59 +0000
commit15c02497e5bfe211fbb9da19f6e3f1b10fcb441f (patch)
tree4c61db5041c90727324edbce2677adcb9754feaf /sys/dev/vge
parent7a56ec02c0689eb39209938c7934c6833ed44923 (diff)
downloadFreeBSD-src-15c02497e5bfe211fbb9da19f6e3f1b10fcb441f.zip
FreeBSD-src-15c02497e5bfe211fbb9da19f6e3f1b10fcb441f.tar.gz
Fix the hardware VLAN tagging. TX was broken on little-endian
machines and both TX and RX were broken on big-endian machines. The chip design is crazy -- on RX, it puts the 16-bit VLAN tag in network byte order (big-endian) in the 32-bit little-endian register! Thanks to John Baldwin for helping me document this change! ;-) Tested by: sat (amd64), test program (sparc64) PR: kern/105054 MFC after: 3 days
Diffstat (limited to 'sys/dev/vge')
-rw-r--r--sys/dev/vge/if_vge.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/sys/dev/vge/if_vge.c b/sys/dev/vge/if_vge.c
index e73ceb7..234f7f7 100644
--- a/sys/dev/vge/if_vge.c
+++ b/sys/dev/vge/if_vge.c
@@ -1453,8 +1453,13 @@ vge_rxeof(sc)
}
if (rxstat & VGE_RDSTS_VTAG) {
+ /*
+ * The 32-bit rxctl register is stored in little-endian.
+ * However, the 16-bit vlan tag is stored in big-endian,
+ * so we have to byte swap it.
+ */
m->m_pkthdr.ether_vtag =
- ntohs((rxctl & VGE_RDCTL_VLANID));
+ bswap16(rxctl & VGE_RDCTL_VLANID);
m->m_flags |= M_VLANTAG;
}
@@ -1767,7 +1772,7 @@ vge_encap(sc, m_head, idx)
if (m_head->m_flags & M_VLANTAG)
sc->vge_ldata.vge_tx_list[idx].vge_ctl |=
- htole32(htons(m_head->m_pkthdr.ether_vtag) | VGE_TDCTL_VTAG);
+ htole32(m_head->m_pkthdr.ether_vtag | VGE_TDCTL_VTAG);
sc->vge_ldata.vge_tx_list[idx].vge_sts |= htole32(VGE_TDSTS_OWN);
OpenPOWER on IntegriCloud