diff options
author | yongari <yongari@FreeBSD.org> | 2008-12-02 02:30:12 +0000 |
---|---|---|
committer | yongari <yongari@FreeBSD.org> | 2008-12-02 02:30:12 +0000 |
commit | dcd51aaf54363f860c85b26b4e370144981127c2 (patch) | |
tree | 480b047fdad42b1d176ec9e80f402d8be589e5d4 /sys/dev/fxp | |
parent | 8e7bf5db05cbd45c637ce2dfba0177dd461700b6 (diff) | |
download | FreeBSD-src-dcd51aaf54363f860c85b26b4e370144981127c2.zip FreeBSD-src-dcd51aaf54363f860c85b26b4e370144981127c2.tar.gz |
Add VLAN hardware tag insertion/stripping support. Tx/Rx checksum
offload for VLAN frames are also supported. The VLAN hardware
assistance is available only on 82550/82551 based controllers.
While I'm here change the confusing name of bit1 in byte 22 of
configuration block to vlan_drop_en. The bit controls whether
hardware strips VLAN tagged frame or not. Special thanks to wpaul
who sent valuable VLAN related information to me.
Tested on: i386, sparc64
Diffstat (limited to 'sys/dev/fxp')
-rw-r--r-- | sys/dev/fxp/if_fxp.c | 28 | ||||
-rw-r--r-- | sys/dev/fxp/if_fxpreg.h | 3 |
2 files changed, 29 insertions, 2 deletions
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c index b2f492a..cd7a9a6 100644 --- a/sys/dev/fxp/if_fxp.c +++ b/sys/dev/fxp/if_fxp.c @@ -830,6 +830,12 @@ fxp_attach(device_t dev) ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); ifp->if_capabilities |= IFCAP_VLAN_MTU; ifp->if_capenable |= IFCAP_VLAN_MTU; /* the hw bits already set */ + if ((sc->flags & FXP_FLAG_EXT_RFA) != 0) { + ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | + IFCAP_VLAN_HWCSUM; + ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | + IFCAP_VLAN_HWCSUM; + } /* * Let the system queue as many packets as we have available @@ -1554,6 +1560,12 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head) FXP_IPCB_TCP_PACKET | FXP_IPCB_TCPUDP_CHECKSUM_ENABLE; } + /* Configure VLAN hardware tag insertion. */ + if ((m->m_flags & M_VLANTAG) != 0) { + cbp->ipcb_vlan_id = htons(m->m_pkthdr.ether_vtag); + txp->tx_cb->ipcb_ip_activation_high |= + FXP_IPCB_INSERTVLAN_ENABLE; + } txp->tx_mbuf = m; txp->tx_cb->cb_status = 0; @@ -1913,6 +1925,12 @@ fxp_intr_body(struct fxp_softc *sc, struct ifnet *ifp, uint8_t statack, /* Do IP checksum checking. */ if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) fxp_rxcsum(sc, ifp, m, status, total_len); + if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 && + (status & FXP_RFA_STATUS_VLAN) != 0) { + m->m_pkthdr.ether_vtag = + ntohs(rfa->rfax_vlan_id); + m->m_flags |= M_VLANTAG; + } /* * Drop locks before calling if_input() since it * may re-enter fxp_start() in the netisr case. @@ -2284,6 +2302,8 @@ fxp_init_body(struct fxp_softc *sc) cbp->multi_ia = 0; /* (don't) accept multiple IAs */ cbp->mc_all = sc->flags & FXP_FLAG_ALL_MCAST ? 1 : 0; cbp->gamla_rx = sc->flags & FXP_FLAG_EXT_RFA ? 1 : 0; + cbp->vlan_strip_en = ((sc->flags & FXP_FLAG_EXT_RFA) != 0 && + (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) ? 1 : 0; if (sc->tunable_noflow || sc->revision == FXP_REV_82557) { /* @@ -2763,9 +2783,15 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data) if (ifp->if_flags & IFF_UP) reinit++; } - if (reinit > 0) + if ((mask & IFCAP_VLAN_HWTAGGING) != 0 && + (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0) { + ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; + reinit++; + } + if (reinit > 0 && ifp->if_flags & IFF_UP) fxp_init_body(sc); FXP_UNLOCK(sc); + VLAN_CAPABILITIES(ifp); break; default: diff --git a/sys/dev/fxp/if_fxpreg.h b/sys/dev/fxp/if_fxpreg.h index a0bd142..9831bd2 100644 --- a/sys/dev/fxp/if_fxpreg.h +++ b/sys/dev/fxp/if_fxpreg.h @@ -224,7 +224,7 @@ struct fxp_cb_config { /* Bytes 22 - 31 -- i82550 only */ u_int __FXP_BITFIELD3(gamla_rx:1, - vlan_drop_en:1, + vlan_strip_en:1, :6); uint8_t pad[9]; }; @@ -377,6 +377,7 @@ struct fxp_rfa { #define FXP_RFA_STATUS_RNR 0x0200 /* no resources */ #define FXP_RFA_STATUS_ALIGN 0x0400 /* alignment error */ #define FXP_RFA_STATUS_CRC 0x0800 /* CRC error */ +#define FXP_RFA_STATUS_VLAN 0x1000 /* VLAN tagged frame */ #define FXP_RFA_STATUS_OK 0x2000 /* packet received okay */ #define FXP_RFA_STATUS_C 0x8000 /* packet reception complete */ #define FXP_RFA_CONTROL_SF 0x08 /* simple/flexible memory mode */ |