Module Name: src Committed By: ryo Date: Mon Feb 10 05:53:12 UTC 2020
Modified Files: src/share/man/man4: aq.4 src/sys/dev/pci: if_aq.c Log Message: add support VLAN HW filter To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/share/man/man4/aq.4 cvs rdiff -u -r1.9 -r1.10 src/sys/dev/pci/if_aq.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/share/man/man4/aq.4 diff -u src/share/man/man4/aq.4:1.2 src/share/man/man4/aq.4:1.3 --- src/share/man/man4/aq.4:1.2 Wed Jan 1 20:13:19 2020 +++ src/share/man/man4/aq.4 Mon Feb 10 05:53:11 2020 @@ -1,4 +1,4 @@ -.\" $NetBSD: aq.4,v 1.2 2020/01/01 20:13:19 wiz Exp $ +.\" $NetBSD: aq.4,v 1.3 2020/02/10 05:53:11 ryo Exp $ .\" .\" Copyright (c) 2020 Ryo Shimizu <r...@nerv.org> .\" All rights reserved. @@ -24,7 +24,7 @@ .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd January 1, 2020 +.Dd February 10, 2020 .Dt AQ 4 .Os .Sh NAME @@ -71,6 +71,7 @@ D109 2.5 Gigabit Network Adapter .Xr ifmedia 4 , .Xr netintro 4 , .Xr pci 4 , +.Xr vlan 4 , .Xr ifconfig 8 .Sh HISTORY The @@ -80,7 +81,3 @@ driver first appeared in and is based on the .Fx driver of the same name, but has been drastically rewritten by Ryo Shimizu. -.Sh BUGS -The -.Nm -driver does not support the VLAN hardware filter. Index: src/sys/dev/pci/if_aq.c diff -u src/sys/dev/pci/if_aq.c:1.9 src/sys/dev/pci/if_aq.c:1.10 --- src/sys/dev/pci/if_aq.c:1.9 Mon Feb 10 05:07:28 2020 +++ src/sys/dev/pci/if_aq.c Mon Feb 10 05:53:12 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: if_aq.c,v 1.9 2020/02/10 05:07:28 ryo Exp $ */ +/* $NetBSD: if_aq.c,v 1.10 2020/02/10 05:53:12 ryo Exp $ */ /** * aQuantia Corporation Network Driver @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.9 2020/02/10 05:07:28 ryo Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.10 2020/02/10 05:53:12 ryo Exp $"); #ifdef _KERNEL_OPT #include "opt_if_aq.h" @@ -1051,6 +1051,7 @@ static int aq_establish_msix_intr(struct static int aq_ifmedia_change(struct ifnet * const); static void aq_ifmedia_status(struct ifnet * const, struct ifmediareq *); +static int aq_vlan_cb(struct ethercom *ec, uint16_t vid, bool set); static int aq_ifflags_cb(struct ethercom *); static int aq_init(struct ifnet *); static void aq_send_common_locked(struct ifnet *, struct aq_softc *, @@ -1404,14 +1405,15 @@ aq_attach(device_t parent, device_t self #if notyet /* TODO */ sc->sc_ethercom.ec_capabilities |= ETHERCAP_EEE; - sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_HWFILTER; #endif sc->sc_ethercom.ec_capabilities |= ETHERCAP_JUMBO_MTU | ETHERCAP_VLAN_MTU | - ETHERCAP_VLAN_HWTAGGING; + ETHERCAP_VLAN_HWTAGGING | + ETHERCAP_VLAN_HWFILTER; sc->sc_ethercom.ec_capenable |= - ETHERCAP_VLAN_HWTAGGING; + ETHERCAP_VLAN_HWTAGGING | + ETHERCAP_VLAN_HWFILTER; ifp->if_capabilities = 0; ifp->if_capenable = 0; @@ -1446,6 +1448,7 @@ aq_attach(device_t parent, device_t self if_attach(ifp); if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->sc_enaddr.ether_addr_octet); + ether_set_vlan_cb(&sc->sc_ethercom, aq_vlan_cb); ether_set_ifflags_cb(&sc->sc_ethercom, aq_ifflags_cb); aq_enable_intr(sc, true, false); /* only intr about link */ @@ -2944,7 +2947,7 @@ aq_hw_init_rx_path(struct aq_softc *sc) ETHERTYPE_QINQ); AQ_WRITE_REG_BIT(sc, RPF_VLAN_TPID_REG, RPF_VLAN_TPID_INNER, ETHERTYPE_VLAN); - AQ_WRITE_REG_BIT(sc, RPF_VLAN_MODE_REG, RPF_VLAN_MODE_PROMISC, 1); + AQ_WRITE_REG_BIT(sc, RPF_VLAN_MODE_REG, RPF_VLAN_MODE_PROMISC, 0); if (sc->sc_features & FEATURES_REV_B) { AQ_WRITE_REG_BIT(sc, RPF_VLAN_MODE_REG, @@ -3216,18 +3219,55 @@ aq_hw_l3_filter_set(struct aq_softc *sc) } static void -aq_update_vlan_filters(struct aq_softc *sc) +aq_set_vlan_filters(struct aq_softc *sc) { - /* XXX: notyet. vlan always promisc */ + struct ethercom *ec = &sc->sc_ethercom; + struct ifnet *ifp = &sc->sc_ethercom.ec_if; + struct vlanid_list *vlanidp; int i; - for (i = 0; i < RPF_VLAN_MAX_FILTERS; i++) { + ETHER_LOCK(ec); + + /* disable all vlan filters */ + for (i = 0; i < RPF_VLAN_MAX_FILTERS; i++) + AQ_WRITE_REG(sc, RPF_VLAN_FILTER_REG(i), 0); + + /* count VID */ + i = 0; + SIMPLEQ_FOREACH(vlanidp, &ec->ec_vids, vid_list) + i++; + + if (((sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_HWFILTER) == 0) || + (ifp->if_flags & IFF_PROMISC) || + (i > RPF_VLAN_MAX_FILTERS)) { + /* + * no vlan hwfilter, in promiscuous mode, or too many VID? + * must receive all VID + */ + AQ_WRITE_REG_BIT(sc, RPF_VLAN_MODE_REG, + RPF_VLAN_MODE_PROMISC, 1); + goto done; + } + + /* receive only selected VID */ + AQ_WRITE_REG_BIT(sc, RPF_VLAN_MODE_REG, RPF_VLAN_MODE_PROMISC, 0); + i = 0; + SIMPLEQ_FOREACH(vlanidp, &ec->ec_vids, vid_list) { AQ_WRITE_REG_BIT(sc, RPF_VLAN_FILTER_REG(i), - RPF_VLAN_FILTER_EN, 0); + RPF_VLAN_FILTER_EN, 1); AQ_WRITE_REG_BIT(sc, RPF_VLAN_FILTER_REG(i), RPF_VLAN_FILTER_RXQ_EN, 0); + AQ_WRITE_REG_BIT(sc, RPF_VLAN_FILTER_REG(i), + RPF_VLAN_FILTER_RXQ, 0); + AQ_WRITE_REG_BIT(sc, RPF_VLAN_FILTER_REG(i), + RPF_VLAN_FILTER_ACTION, RPF_ACTION_HOST); + AQ_WRITE_REG_BIT(sc, RPF_VLAN_FILTER_REG(i), + RPF_VLAN_FILTER_ID, vlanidp->vid); + i++; } - AQ_WRITE_REG_BIT(sc, RPF_VLAN_MODE_REG, RPF_VLAN_MODE_PROMISC, 1); + + done: + ETHER_UNLOCK(ec); } static int @@ -4389,6 +4429,16 @@ aq_rx_intr(void *arg) } static int +aq_vlan_cb(struct ethercom *ec, uint16_t vid, bool set) +{ + struct ifnet *ifp = &ec->ec_if; + struct aq_softc *sc = ifp->if_softc; + + aq_set_vlan_filters(sc); + return 0; +} + +static int aq_ifflags_cb(struct ethercom *ec) { struct ifnet *ifp = &ec->ec_if; @@ -4412,6 +4462,10 @@ aq_ifflags_cb(struct ethercom *ec) } } + /* vlan configuration depends on also interface promiscuous mode */ + if ((ecchange & ETHERCAP_VLAN_HWFILTER) || (iffchange & IFF_PROMISC)) + aq_set_vlan_filters(sc); + sc->sc_ec_capenable = ec->ec_capenable; sc->sc_if_flags = ifp->if_flags; @@ -4428,7 +4482,7 @@ aq_init(struct ifnet *ifp) AQ_LOCK(sc); - aq_update_vlan_filters(sc); + aq_set_vlan_filters(sc); aq_set_capability(sc); for (i = 0; i < sc->sc_nqueues; i++) {