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 <[email protected]>
.\" 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++) {