diff options
author | ru <ru@FreeBSD.org> | 2006-11-30 21:01:59 +0000 |
---|---|---|
committer | ru <ru@FreeBSD.org> | 2006-11-30 21:01:59 +0000 |
commit | 15c02497e5bfe211fbb9da19f6e3f1b10fcb441f (patch) | |
tree | 4c61db5041c90727324edbce2677adcb9754feaf /sys/dev/vge | |
parent | 7a56ec02c0689eb39209938c7934c6833ed44923 (diff) | |
download | FreeBSD-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.c | 9 |
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); |