diff options
-rw-r--r-- | sys/dev/pci/if_em.c | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c index 541f87f46f2..7d68e157a4a 100644 --- a/sys/dev/pci/if_em.c +++ b/sys/dev/pci/if_em.c @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ -/* $OpenBSD: if_em.c,v 1.192 2008/10/15 19:12:18 blambert Exp $ */ +/* $OpenBSD: if_em.c,v 1.193 2008/10/19 19:53:09 brad Exp $ */ /* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */ #include <dev/pci/if_em.h> @@ -178,6 +178,7 @@ void em_print_hw_stats(struct em_softc *); #endif void em_update_link_status(struct em_softc *); int em_get_buf(struct em_softc *, int); +void em_enable_hw_vlans(struct em_softc *); int em_encap(struct em_softc *, struct mbuf *); void em_smartspeed(struct em_softc *); int em_82547_fifo_workaround(struct em_softc *, int); @@ -739,6 +740,10 @@ em_init(void *arg) } em_update_link_status(sc); + E1000_WRITE_REG(&sc->hw, VET, ETHERTYPE_VLAN); + if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) + em_enable_hw_vlans(sc); + /* Prepare transmit descriptors and buffers */ if (em_setup_transmit_structures(sc)) { printf("%s: Could not setup transmit structures\n", @@ -1103,6 +1108,16 @@ em_encap(struct em_softc *sc, struct mbuf *m_head) else sc->num_tx_desc_avail -= map->dm_nsegs; + /* Find out if we are in VLAN mode */ + if (m_head->m_flags & M_VLANTAG) { + /* Set the VLAN id */ + current_tx_desc->upper.fields.special = + htole16(m_head->m_pkthdr.ether_vtag); + + /* Tell hardware to add tag */ + current_tx_desc->lower.data |= htole32(E1000_TXD_CMD_VLE); + } + tx_buffer->m_head = m_head; tx_buffer_mapped->map = tx_buffer->map; tx_buffer->map = map; @@ -1718,6 +1733,10 @@ em_setup_interface(struct em_softc *sc) ifp->if_capabilities = IFCAP_VLAN_MTU; +#if NVLAN > 0 + ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; +#endif + #ifdef EM_CSUM_OFFLOAD if (sc->hw.mac_type >= em_82543) ifp->if_capabilities |= IFCAP_CSUM_TCPv4|IFCAP_CSUM_UDPv4; @@ -2699,6 +2718,12 @@ em_rxeof(struct em_softc *sc, int count) ifp->if_ipackets++; em_receive_checksum(sc, current_desc, sc->fmp); + if (current_desc->status & E1000_RXD_STAT_VP) { + sc->fmp->m_pkthdr.ether_vtag = + (current_desc->special & + E1000_RXD_SPC_VLAN_MASK); + sc->fmp->m_flags |= M_VLANTAG; + } m = sc->fmp; sc->fmp = NULL; sc->lmp = NULL; @@ -2793,6 +2818,20 @@ em_receive_checksum(struct em_softc *sc, struct em_rx_desc *rx_desc, } } +/* + * This turns on the hardware offload of the VLAN + * tag insertion and strip + */ +void +em_enable_hw_vlans(struct em_softc *sc) +{ + uint32_t ctrl; + + ctrl = E1000_READ_REG(&sc->hw, CTRL); + ctrl |= E1000_CTRL_VME; + E1000_WRITE_REG(&sc->hw, CTRL, ctrl); +} + void em_enable_intr(struct em_softc *sc) { |