summaryrefslogtreecommitdiffstats
path: root/sys/dev/vge/if_vge.c
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2009-12-16 18:03:25 +0000
committeryongari <yongari@FreeBSD.org>2009-12-16 18:03:25 +0000
commit2df754472e7a650f6a3a3a73042f078887758877 (patch)
tree8872d1ea341063db61d4510497bb07a3ed057331 /sys/dev/vge/if_vge.c
parentbed52cb4e194198e2efee8ee0af65890c6e8306a (diff)
downloadFreeBSD-src-2df754472e7a650f6a3a3a73042f078887758877.zip
FreeBSD-src-2df754472e7a650f6a3a3a73042f078887758877.tar.gz
All vge(4) controllers support RX/TX checksum offloading for VLAN
tagged frames so add checksum offloading capabilities. Also add missing VLAN hardware tagging control in ioctl handler and let upper stack know current VLAN capabilities.
Diffstat (limited to 'sys/dev/vge/if_vge.c')
-rw-r--r--sys/dev/vge/if_vge.c39
1 files changed, 33 insertions, 6 deletions
diff --git a/sys/dev/vge/if_vge.c b/sys/dev/vge/if_vge.c
index e95a364..0c9718a 100644
--- a/sys/dev/vge/if_vge.c
+++ b/sys/dev/vge/if_vge.c
@@ -180,6 +180,7 @@ static void vge_reset(struct vge_softc *);
static int vge_rx_list_init(struct vge_softc *);
static int vge_rxeof(struct vge_softc *, int);
static void vge_setmulti(struct vge_softc *);
+static void vge_setvlan(struct vge_softc *);
static void vge_start(struct ifnet *);
static void vge_start_locked(struct ifnet *);
static void vge_stop(struct vge_softc *);
@@ -504,6 +505,23 @@ fail:
return (error);
}
+static void
+vge_setvlan(struct vge_softc *sc)
+{
+ struct ifnet *ifp;
+ uint8_t cfg;
+
+ VGE_LOCK_ASSERT(sc);
+
+ ifp = sc->vge_ifp;
+ cfg = CSR_READ_1(sc, VGE_RXCFG);
+ if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0)
+ cfg |= VGE_VTAG_OPT2;
+ else
+ cfg &= ~VGE_VTAG_OPT2;
+ CSR_WRITE_1(sc, VGE_RXCFG, cfg);
+}
+
/*
* Program the multicast filter. We use the 64-entry CAM filter
* for perfect filtering. If there's more than 64 multicast addresses,
@@ -1050,7 +1068,8 @@ vge_attach(device_t dev)
ifp->if_capabilities = IFCAP_VLAN_MTU;
ifp->if_start = vge_start;
ifp->if_hwassist = VGE_CSUM_FEATURES;
- ifp->if_capabilities |= IFCAP_HWCSUM|IFCAP_VLAN_HWTAGGING;
+ ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM |
+ IFCAP_VLAN_HWTAGGING;
ifp->if_capenable = ifp->if_capabilities;
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
@@ -2010,7 +2029,7 @@ vge_init_locked(struct vge_softc *sc)
* reception of VLAN tagged frames.
*/
CSR_CLRBIT_1(sc, VGE_RXCFG, VGE_RXCFG_FIFO_THR|VGE_RXCFG_VTAGOPT);
- CSR_SETBIT_1(sc, VGE_RXCFG, VGE_RXFIFOTHR_128BYTES|VGE_VTAG_OPT2);
+ CSR_SETBIT_1(sc, VGE_RXCFG, VGE_RXFIFOTHR_128BYTES);
/* Set DMA burst length */
CSR_CLRBIT_1(sc, VGE_DMACFG0, VGE_DMACFG0_BURSTLEN);
@@ -2072,6 +2091,7 @@ vge_init_locked(struct vge_softc *sc)
/* Init the multicast filter. */
vge_setmulti(sc);
+ vge_setvlan(sc);
/* Enable flow control */
@@ -2242,7 +2262,7 @@ vge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct vge_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
struct mii_data *mii;
- int error = 0;
+ int error = 0, mask;
switch (command) {
case SIOCSIFMTU:
@@ -2287,8 +2307,7 @@ vge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
break;
case SIOCSIFCAP:
- {
- int mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+ mask = ifr->ifr_reqcap ^ ifp->if_capenable;
#ifdef DEVICE_POLLING
if (mask & IFCAP_POLLING) {
if (ifr->ifr_reqcap & IFCAP_POLLING) {
@@ -2325,8 +2344,16 @@ vge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if ((mask & IFCAP_RXCSUM) != 0 &&
(ifp->if_capabilities & IFCAP_RXCSUM) != 0)
ifp->if_capenable ^= IFCAP_RXCSUM;
+ if ((mask & IFCAP_VLAN_HWCSUM) != 0 &&
+ (ifp->if_capabilities & IFCAP_VLAN_HWCSUM) != 0)
+ ifp->if_capenable ^= IFCAP_VLAN_HWCSUM;
+ if ((mask & IFCAP_VLAN_HWTAGGING) != 0 &&
+ (IFCAP_VLAN_HWTAGGING & ifp->if_capabilities) != 0) {
+ ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
+ vge_setvlan(sc);
+ }
VGE_UNLOCK(sc);
- }
+ VLAN_CAPABILITIES(ifp);
break;
default:
error = ether_ioctl(ifp, command, data);
OpenPOWER on IntegriCloud