Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci ixl(4) supports ETHERCAP_VLAN_HWFILTER
details: https://anonhg.NetBSD.org/src/rev/64d773b49460
branches: trunk
changeset: 1005771:64d773b49460
user: yamaguchi <yamaguchi%NetBSD.org@localhost>
date: Fri Dec 20 02:19:27 2019 +0000
description:
ixl(4) supports ETHERCAP_VLAN_HWFILTER
the feature is disable by default.
reviewed by msaitoh and knakahara
diffstat:
sys/dev/pci/if_ixl.c | 239 ++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 190 insertions(+), 49 deletions(-)
diffs (truncated from 393 to 300 lines):
diff -r 3798766e991a -r 64d773b49460 sys/dev/pci/if_ixl.c
--- a/sys/dev/pci/if_ixl.c Fri Dec 20 02:12:31 2019 +0000
+++ b/sys/dev/pci/if_ixl.c Fri Dec 20 02:19:27 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_ixl.c,v 1.11 2019/12/20 02:12:31 yamaguchi Exp $ */
+/* $NetBSD: if_ixl.c,v 1.12 2019/12/20 02:19:27 yamaguchi Exp $ */
/*
* Copyright (c) 2013-2015, Intel Corporation
@@ -646,8 +646,8 @@
static void ixl_config_rss(struct ixl_softc *);
static int ixl_add_macvlan(struct ixl_softc *, const uint8_t *,
uint16_t, uint16_t);
-static int ixl_remove_macvlan(struct ixl_softc *, uint8_t *, uint16_t,
- uint16_t);
+static int ixl_remove_macvlan(struct ixl_softc *, const uint8_t *,
+ uint16_t, uint16_t);
static void ixl_arq(void *);
static void ixl_hmc_pack(void *, const void *,
const struct ixl_hmc_pack *, unsigned int);
@@ -725,7 +725,10 @@
ixl_lookup(const struct pci_attach_args *pa);
static void ixl_link_state_update(struct ixl_softc *,
const struct ixl_aq_desc *);
-static int ixl_set_macvlan(struct ixl_softc *);
+static int ixl_vlan_cb(struct ethercom *, uint16_t, bool);
+static int ixl_setup_vlan_hwfilter(struct ixl_softc *);
+static void ixl_teardown_vlan_hwfilter(struct ixl_softc *);
+static int ixl_update_macvlan(struct ixl_softc *);
static int ixl_setup_interrupts(struct ixl_softc *);;
static void ixl_teardown_interrupts(struct ixl_softc *);
static int ixl_setup_stats(struct ixl_softc *);
@@ -1194,10 +1197,15 @@
IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx |
IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx;
#endif
+ ether_set_vlan_cb(&sc->sc_ec, ixl_vlan_cb);
sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_MTU;
sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_HWTAGGING;
+ sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_HWFILTER;
sc->sc_ec.ec_capenable = sc->sc_ec.ec_capabilities;
+ /* Disable VLAN_HWFILTER by default */
+ CLR(sc->sc_ec.ec_capenable, ETHERCAP_VLAN_HWFILTER);
+
sc->sc_cur_ec_capenable = sc->sc_ec.ec_capenable;
sc->sc_ec.ec_ifmedia = &sc->sc_media;
@@ -1219,7 +1227,25 @@
ixl_config_other_intr(sc);
ixl_enable_other_intr(sc);
- ixl_set_macvlan(sc);
+ /* remove default mac filter and replace it so we can see vlans */
+ rv = ixl_remove_macvlan(sc, sc->sc_enaddr, 0, 0);
+ if (rv != ENOENT) {
+ aprint_debug_dev(self,
+ "unable to remove macvlan %u\n", rv);
+ }
+ rv = ixl_remove_macvlan(sc, sc->sc_enaddr, 0,
+ IXL_AQ_OP_REMOVE_MACVLAN_IGNORE_VLAN);
+ if (rv != ENOENT) {
+ aprint_debug_dev(self,
+ "unable to remove macvlan, ignore vlan %u\n", rv);
+ }
+
+ if (ixl_update_macvlan(sc) != 0) {
+ aprint_debug_dev(self,
+ "couldn't enable vlan hardware filter\n");
+ CLR(sc->sc_ec.ec_capenable, ETHERCAP_VLAN_HWFILTER);
+ CLR(sc->sc_cur_ec_capenable, ETHERCAP_VLAN_HWFILTER);
+ }
sc->sc_txrx_workqueue = true;
sc->sc_tx_process_limit = IXL_TX_PROCESS_LIMIT;
@@ -1380,6 +1406,34 @@
return 0;
}
+static int
+ixl_vlan_cb(struct ethercom *ec, uint16_t vid, bool set)
+{
+ struct ifnet *ifp = &ec->ec_if;
+ struct ixl_softc *sc = ifp->if_softc;
+ int rv;
+
+ if (!ISSET(sc->sc_cur_ec_capenable, ETHERCAP_VLAN_HWFILTER)) {
+ return 0;
+ }
+
+ if (set) {
+ rv = ixl_add_macvlan(sc, sc->sc_enaddr, vid,
+ IXL_AQ_OP_ADD_MACVLAN_PERFECT_MATCH);
+ if (rv == 0) {
+ rv = ixl_add_macvlan(sc, etherbroadcastaddr,
+ vid, IXL_AQ_OP_ADD_MACVLAN_PERFECT_MATCH);
+ }
+ } else {
+ rv = ixl_remove_macvlan(sc, sc->sc_enaddr, vid,
+ IXL_AQ_OP_REMOVE_MACVLAN_PERFECT_MATCH);
+ (void)ixl_remove_macvlan(sc, etherbroadcastaddr, vid,
+ IXL_AQ_OP_REMOVE_MACVLAN_PERFECT_MATCH);
+ }
+
+ return rv;
+}
+
static void
ixl_media_add(struct ixl_softc *sc, uint64_t phy_types)
{
@@ -1460,6 +1514,7 @@
return ENETRESET;
}
+ /* multicast address can not use VLAN HWFILTER */
rv = ixl_add_macvlan(sc, addrlo, 0,
IXL_AQ_OP_ADD_MACVLAN_IGNORE_VLAN);
@@ -1726,7 +1781,6 @@
if (ixl_set_vsi(sc) != 0)
return EIO;
-
for (i = 0; i < sc->sc_nqueue_pairs; i++) {
txr = sc->sc_qps[i].qp_txr;
rxr = sc->sc_qps[i].qp_rxr;
@@ -1752,7 +1806,6 @@
ixl_wr(sc, txr->txr_tail, txr->txr_prod);
ixl_wr(sc, rxr->rxr_tail, rxr->rxr_prod);
-
/* ixl_rxfill() needs lock held */
mutex_enter(&rxr->rxr_lock);
ixl_rxfill(sc, rxr);
@@ -1791,7 +1844,7 @@
{
struct ifnet *ifp = &sc->sc_ec.ec_if;
unsigned int i;
- int error;
+ int error, eccap_change;
KASSERT(mutex_owned(&sc->sc_cfg_lock));
@@ -1802,7 +1855,18 @@
return ENXIO;
}
- sc->sc_cur_ec_capenable = sc->sc_ec.ec_capenable;
+ eccap_change = sc->sc_ec.ec_capenable ^ sc->sc_cur_ec_capenable;
+ if (ISSET(eccap_change, ETHERCAP_VLAN_HWTAGGING))
+ sc->sc_cur_ec_capenable ^= ETHERCAP_VLAN_HWTAGGING;
+
+ if (ISSET(eccap_change, ETHERCAP_VLAN_HWFILTER)) {
+ if (ixl_update_macvlan(sc) == 0) {
+ sc->sc_cur_ec_capenable ^= ETHERCAP_VLAN_HWFILTER;
+ } else {
+ CLR(sc->sc_ec.ec_capenable, ETHERCAP_VLAN_HWFILTER);
+ CLR(sc->sc_cur_ec_capenable, ETHERCAP_VLAN_HWFILTER);
+ }
+ }
if (sc->sc_intrtype != PCI_INTR_TYPE_MSIX)
sc->sc_nqueue_pairs = 1;
@@ -1856,6 +1920,7 @@
struct ixl_atq iatq;
struct ixl_aq_desc *iaq;
struct ixl_aq_vsi_promisc_param *param;
+ uint16_t flag_add, flag_del;
int error;
if (!ISSET(ifp->if_flags, IFF_RUNNING))
@@ -1867,8 +1932,14 @@
iaq->iaq_opcode = htole16(IXL_AQ_OP_SET_VSI_PROMISC);
param = (struct ixl_aq_vsi_promisc_param *)&iaq->iaq_param;
- param->flags = htole16(IXL_AQ_VSI_PROMISC_FLAG_BCAST |
- IXL_AQ_VSI_PROMISC_FLAG_VLAN);
+ param->flags = htole16(0);
+
+ if (!ISSET(sc->sc_cur_ec_capenable, ETHERCAP_VLAN_HWFILTER)
+ || ISSET(ifp->if_flags, IFF_PROMISC)) {
+ param->flags |= htole16(IXL_AQ_VSI_PROMISC_FLAG_BCAST |
+ IXL_AQ_VSI_PROMISC_FLAG_VLAN);
+ }
+
if (ISSET(ifp->if_flags, IFF_PROMISC)) {
param->flags |= htole16(IXL_AQ_VSI_PROMISC_FLAG_UCAST |
IXL_AQ_VSI_PROMISC_FLAG_MCAST);
@@ -1888,12 +1959,18 @@
return EIO;
if (memcmp(sc->sc_enaddr, CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN) != 0) {
- ixl_remove_macvlan(sc, sc->sc_enaddr, 0,
- IXL_AQ_OP_REMOVE_MACVLAN_IGNORE_VLAN);
+ if (ISSET(sc->sc_cur_ec_capenable, ETHERCAP_VLAN_HWFILTER)) {
+ flag_add = IXL_AQ_OP_ADD_MACVLAN_PERFECT_MATCH;
+ flag_del = IXL_AQ_OP_REMOVE_MACVLAN_PERFECT_MATCH;
+ } else {
+ flag_add = IXL_AQ_OP_ADD_MACVLAN_IGNORE_VLAN;
+ flag_del = IXL_AQ_OP_REMOVE_MACVLAN_IGNORE_VLAN;
+ }
+
+ ixl_remove_macvlan(sc, sc->sc_enaddr, 0, flag_del);
memcpy(sc->sc_enaddr, CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
- ixl_add_macvlan(sc, sc->sc_enaddr, 0,
- IXL_AQ_OP_ADD_MACVLAN_IGNORE_VLAN);
+ ixl_add_macvlan(sc, sc->sc_enaddr, 0, flag_add);
}
return 0;
}
@@ -3959,7 +4036,14 @@
return ETIMEDOUT;
}
- if (iaq.iaq_retval != htole16(IXL_AQ_RC_OK)) {
+ switch (le16toh(iaq.iaq_retval)) {
+ case IXL_AQ_RC_OK:
+ break;
+ case IXL_AQ_RC_ENOENT:
+ return ENOENT;
+ case IXL_AQ_RC_EACCES:
+ return EACCES;
+ default:
return EIO;
}
@@ -4027,7 +4111,14 @@
return ETIMEDOUT;
}
- if (iaq.iaq_retval != htole16(IXL_AQ_RC_OK)) {
+ switch (le16toh(iaq.iaq_retval)) {
+ case IXL_AQ_RC_OK:
+ break;
+ case IXL_AQ_RC_ENOENT:
+ return ENOENT;
+ case IXL_AQ_RC_EACCES:
+ return EACCES;
+ default:
return EIO;
}
@@ -4243,7 +4334,7 @@
}
static int
-ixl_remove_macvlan(struct ixl_softc *sc, uint8_t *macaddr,
+ixl_remove_macvlan(struct ixl_softc *sc, const uint8_t *macaddr,
uint16_t vlan, uint16_t flags)
{
struct ixl_aq_desc iaq;
@@ -4821,39 +4912,80 @@
}
static int
-ixl_set_macvlan(struct ixl_softc *sc)
+ixl_setup_vlan_hwfilter(struct ixl_softc *sc)
{
- int error, rv = 0;
-
- /* remove default mac filter and replace it so we can see vlans */
-
- error = ixl_remove_macvlan(sc, sc->sc_enaddr, 0, 0);
- if (error != 0 && error != ENOENT) {
- aprint_debug_dev(sc->sc_dev, "unable to remove macvlan\n");
- rv = -1;
- }
-
- error = ixl_remove_macvlan(sc, sc->sc_enaddr, 0,
+ struct ethercom *ec = &sc->sc_ec;
+ struct vlanid_list *vlanidp;
+ int rv;
+
+ ixl_remove_macvlan(sc, sc->sc_enaddr, 0,
+ IXL_AQ_OP_REMOVE_MACVLAN_IGNORE_VLAN);
+ ixl_remove_macvlan(sc, etherbroadcastaddr, 0,
IXL_AQ_OP_REMOVE_MACVLAN_IGNORE_VLAN);
- if (error != 0 && error != ENOENT) {
- aprint_debug_dev(sc->sc_dev,
- "unable to remove macvlan(IGNORE_VLAN)\n");
- rv = -1;
- }
-
- error = ixl_add_macvlan(sc, sc->sc_enaddr, 0,
+
+ rv = ixl_add_macvlan(sc, sc->sc_enaddr, 0,
+ IXL_AQ_OP_ADD_MACVLAN_PERFECT_MATCH);
+ if (rv != 0)
+ return rv;
+ rv = ixl_add_macvlan(sc, etherbroadcastaddr, 0,
+ IXL_AQ_OP_ADD_MACVLAN_PERFECT_MATCH);
+ if (rv != 0)
+ return rv;
+
+ ETHER_LOCK(ec);
+ SIMPLEQ_FOREACH(vlanidp, &ec->ec_vids, vid_list) {
+ rv = ixl_add_macvlan(sc, sc->sc_enaddr,
+ vlanidp->vid, IXL_AQ_OP_ADD_MACVLAN_PERFECT_MATCH);
+ if (rv != 0)
Home |
Main Index |
Thread Index |
Old Index