summaryrefslogtreecommitdiffstats
path: root/sys/dev/fxp
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2008-12-02 02:30:12 +0000
committeryongari <yongari@FreeBSD.org>2008-12-02 02:30:12 +0000
commitdcd51aaf54363f860c85b26b4e370144981127c2 (patch)
tree480b047fdad42b1d176ec9e80f402d8be589e5d4 /sys/dev/fxp
parent8e7bf5db05cbd45c637ce2dfba0177dd461700b6 (diff)
downloadFreeBSD-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.c28
-rw-r--r--sys/dev/fxp/if_fxpreg.h3
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 */
OpenPOWER on IntegriCloud