From 2df754472e7a650f6a3a3a73042f078887758877 Mon Sep 17 00:00:00 2001 From: yongari Date: Wed, 16 Dec 2009 18:03:25 +0000 Subject: 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. --- sys/dev/vge/if_vge.c | 39 +++++++++++++++++++++++++++++++++------ 1 file 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); -- cgit v1.1