Page MenuHomeFreeBSD

D28137.diff
No OneTemporary

D28137.diff

diff --git a/sys/dev/ixl/i40e_osdep.c b/sys/dev/ixl/i40e_osdep.c
--- a/sys/dev/ixl/i40e_osdep.c
+++ b/sys/dev/ixl/i40e_osdep.c
@@ -51,14 +51,14 @@
i40e_status
i40e_allocate_virt_mem(struct i40e_hw *hw, struct i40e_virt_mem *mem, u32 size)
{
- mem->va = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
+ mem->va = malloc(size, M_IXL, M_NOWAIT | M_ZERO);
return (mem->va == NULL);
}
i40e_status
i40e_free_virt_mem(struct i40e_hw *hw, struct i40e_virt_mem *mem)
{
- free(mem->va, M_DEVBUF);
+ free(mem->va, M_IXL);
mem->va = NULL;
return (I40E_SUCCESS);
diff --git a/sys/dev/ixl/iavf.h b/sys/dev/ixl/iavf.h
--- a/sys/dev/ixl/iavf.h
+++ b/sys/dev/ixl/iavf.h
@@ -43,6 +43,13 @@
#define IAVF_MAX_QUEUES 16
#define IAVF_AQ_TIMEOUT (1 * hz)
+/* MacVlan Flags */
+#define IAVF_FILTER_USED (u16)(1 << 0)
+#define IAVF_FILTER_VLAN (u16)(1 << 1)
+#define IAVF_FILTER_ADD (u16)(1 << 2)
+#define IAVF_FILTER_DEL (u16)(1 << 3)
+#define IAVF_FILTER_MC (u16)(1 << 4)
+
#define IAVF_FLAG_AQ_ENABLE_QUEUES (u32)(1 << 0)
#define IAVF_FLAG_AQ_DISABLE_QUEUES (u32)(1 << 1)
#define IAVF_FLAG_AQ_ADD_MAC_FILTER (u32)(1 << 2)
diff --git a/sys/dev/ixl/iavf_vc.c b/sys/dev/ixl/iavf_vc.c
--- a/sys/dev/ixl/iavf_vc.c
+++ b/sys/dev/ixl/iavf_vc.c
@@ -456,7 +456,7 @@
/* Get count of VLAN filters to add */
SLIST_FOREACH(f, sc->vlan_filters, next) {
- if (f->flags & IXL_FILTER_ADD)
+ if (f->flags & IAVF_FILTER_ADD)
cnt++;
}
@@ -484,9 +484,9 @@
/* Scan the filter array */
SLIST_FOREACH_SAFE(f, sc->vlan_filters, next, ftmp) {
- if (f->flags & IXL_FILTER_ADD) {
+ if (f->flags & IAVF_FILTER_ADD) {
bcopy(&f->vlan, &v->vlan_id[i], sizeof(u16));
- f->flags = IXL_FILTER_USED;
+ f->flags = IAVF_FILTER_USED;
i++;
}
if (i == cnt)
@@ -514,7 +514,7 @@
/* Get count of VLAN filters to delete */
SLIST_FOREACH(f, sc->vlan_filters, next) {
- if (f->flags & IXL_FILTER_DEL)
+ if (f->flags & IAVF_FILTER_DEL)
cnt++;
}
@@ -542,7 +542,7 @@
/* Scan the filter array */
SLIST_FOREACH_SAFE(f, sc->vlan_filters, next, ftmp) {
- if (f->flags & IXL_FILTER_DEL) {
+ if (f->flags & IAVF_FILTER_DEL) {
bcopy(&f->vlan, &v->vlan_id[i], sizeof(u16));
i++;
SLIST_REMOVE(sc->vlan_filters, f, iavf_vlan_filter, next);
@@ -575,7 +575,7 @@
/* Get count of MAC addresses to add */
SLIST_FOREACH(f, sc->mac_filters, next) {
- if (f->flags & IXL_FILTER_ADD)
+ if (f->flags & IAVF_FILTER_ADD)
cnt++;
}
if (cnt == 0) { /* Should not happen... */
@@ -597,9 +597,9 @@
/* Scan the filter array */
SLIST_FOREACH(f, sc->mac_filters, next) {
- if (f->flags & IXL_FILTER_ADD) {
+ if (f->flags & IAVF_FILTER_ADD) {
bcopy(f->macaddr, a->list[j].addr, ETHER_ADDR_LEN);
- f->flags &= ~IXL_FILTER_ADD;
+ f->flags &= ~IAVF_FILTER_ADD;
j++;
iavf_dbg_vc(sc, "ADD: " MAC_FORMAT "\n",
@@ -633,7 +633,7 @@
/* Get count of MAC addresses to delete */
SLIST_FOREACH(f, sc->mac_filters, next) {
- if (f->flags & IXL_FILTER_DEL)
+ if (f->flags & IAVF_FILTER_DEL)
cnt++;
}
if (cnt == 0) {
@@ -655,7 +655,7 @@
/* Scan the filter array */
SLIST_FOREACH_SAFE(f, sc->mac_filters, next, f_temp) {
- if (f->flags & IXL_FILTER_DEL) {
+ if (f->flags & IAVF_FILTER_DEL) {
bcopy(f->macaddr, d->list[j].addr, ETHER_ADDR_LEN);
iavf_dbg_vc(sc, "DEL: " MAC_FORMAT "\n",
MAC_FORMAT_ARGS(f->macaddr));
diff --git a/sys/dev/ixl/if_iavf.c b/sys/dev/ixl/if_iavf.c
--- a/sys/dev/ixl/if_iavf.c
+++ b/sys/dev/ixl/if_iavf.c
@@ -663,7 +663,7 @@
iavf_send_vc_msg(sc, IAVF_FLAG_AQ_DISABLE_QUEUES);
bcopy(IF_LLADDR(ifp), tmpaddr, ETHER_ADDR_LEN);
- if (!cmp_etheraddr(hw->mac.addr, tmpaddr) &&
+ if (!ixl_ether_is_equal(hw->mac.addr, tmpaddr) &&
(i40e_validate_mac_addr(tmpaddr) == I40E_SUCCESS)) {
error = iavf_del_mac_filter(sc, hw->mac.addr);
if (error == 0)
@@ -1233,7 +1233,7 @@
struct iavf_sc *sc = arg;
int error;
- error = iavf_add_mac_filter(sc, (u8*)LLADDR(sdl), IXL_FILTER_MC);
+ error = iavf_add_mac_filter(sc, (u8*)LLADDR(sdl), IAVF_FILTER_MC);
return (!error);
}
@@ -1404,7 +1404,7 @@
v = malloc(sizeof(struct iavf_vlan_filter), M_IAVF, M_WAITOK | M_ZERO);
SLIST_INSERT_HEAD(sc->vlan_filters, v, next);
v->vlan = vtag;
- v->flags = IXL_FILTER_ADD;
+ v->flags = IAVF_FILTER_ADD;
iavf_send_vc_msg(sc, IAVF_FLAG_AQ_ADD_VLAN_FILTER);
}
@@ -1422,7 +1422,7 @@
SLIST_FOREACH(v, sc->vlan_filters, next) {
if (v->vlan == vtag) {
- v->flags = IXL_FILTER_DEL;
+ v->flags = IAVF_FILTER_DEL;
++i;
--vsi->num_vlans;
}
@@ -1624,7 +1624,7 @@
bool match = FALSE;
SLIST_FOREACH(f, sc->mac_filters, next) {
- if (cmp_etheraddr(f->macaddr, macaddr)) {
+ if (ixl_ether_is_equal(f->macaddr, macaddr)) {
match = TRUE;
break;
}
@@ -1828,9 +1828,9 @@
/* First clear any multicast filters */
SLIST_FOREACH(f, sc->mac_filters, next) {
- if ((f->flags & IXL_FILTER_USED)
- && (f->flags & IXL_FILTER_MC)) {
- f->flags |= IXL_FILTER_DEL;
+ if ((f->flags & IAVF_FILTER_USED)
+ && (f->flags & IAVF_FILTER_MC)) {
+ f->flags |= IAVF_FILTER_DEL;
mcnt++;
}
}
@@ -2034,7 +2034,7 @@
MAC_FORMAT_ARGS(macaddr));
bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN);
- f->flags |= (IXL_FILTER_ADD | IXL_FILTER_USED);
+ f->flags |= (IAVF_FILTER_ADD | IAVF_FILTER_USED);
f->flags |= flags;
return (0);
}
@@ -2051,7 +2051,7 @@
if (f == NULL)
return (ENOENT);
- f->flags |= IXL_FILTER_DEL;
+ f->flags |= IAVF_FILTER_DEL;
return (0);
}
diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c
--- a/sys/dev/ixl/if_ixl.c
+++ b/sys/dev/ixl/if_ixl.c
@@ -127,7 +127,6 @@
#endif
/*** Other ***/
-static u_int ixl_mc_filter_apply(void *, struct sockaddr_dl *, u_int);
static void ixl_save_pf_tunables(struct ixl_pf *);
static int ixl_allocate_pci_resources(struct ixl_pf *);
static void ixl_setup_ssctx(struct ixl_pf *pf);
@@ -862,7 +861,7 @@
ixl_pf_qmgr_destroy(&pf->qmgr);
ixl_free_pci_resources(pf);
- ixl_free_mac_filters(vsi);
+ ixl_free_filters(&vsi->ftl);
INIT_DBG_DEV(dev, "end");
return (0);
}
@@ -937,9 +936,9 @@
/* Get the latest mac address... User might use a LAA */
bcopy(IF_LLADDR(vsi->ifp), tmpaddr, ETH_ALEN);
- if (!cmp_etheraddr(hw->mac.addr, tmpaddr) &&
+ if (!ixl_ether_is_equal(hw->mac.addr, tmpaddr) &&
(i40e_validate_mac_addr(tmpaddr) == I40E_SUCCESS)) {
- ixl_del_filter(vsi, hw->mac.addr, IXL_VLAN_ANY);
+ ixl_del_all_vlan_filters(vsi, hw->mac.addr);
bcopy(tmpaddr, hw->mac.addr, ETH_ALEN);
ret = i40e_aq_mac_address_write(hw,
I40E_AQC_WRITE_TYPE_LAA_ONLY,
@@ -948,7 +947,10 @@
device_printf(dev, "LLA address change failed!!\n");
return;
}
- ixl_add_filter(vsi, hw->mac.addr, IXL_VLAN_ANY);
+ /*
+ * New filters are configured by ixl_reconfigure_filters
+ * at the end of ixl_init_locked.
+ */
}
iflib_set_mac(ctx, hw->mac.addr);
@@ -1385,7 +1387,7 @@
struct i40e_hw *hw = &pf->hw;
u16 pending;
- if (pf->state & IXL_PF_STATE_ADAPTER_RESETTING)
+ if (IXL_PF_IS_RESETTING(pf))
ixl_handle_empr_reset(pf);
/*
@@ -1418,32 +1420,22 @@
struct ixl_pf *pf = iflib_get_softc(ctx);
struct ixl_vsi *vsi = &pf->vsi;
struct i40e_hw *hw = vsi->hw;
- int mcnt, flags;
- int del_mcnt;
+ int mcnt;
IOCTL_DEBUGOUT("ixl_if_multi_set: begin");
- mcnt = min(if_llmaddr_count(iflib_get_ifp(ctx)), MAX_MULTICAST_ADDR);
/* Delete filters for removed multicast addresses */
- del_mcnt = ixl_del_multi(vsi);
- vsi->num_macs -= del_mcnt;
+ ixl_del_multi(vsi, false);
+ mcnt = min(if_llmaddr_count(iflib_get_ifp(ctx)), MAX_MULTICAST_ADDR);
if (__predict_false(mcnt == MAX_MULTICAST_ADDR)) {
i40e_aq_set_vsi_multicast_promiscuous(hw,
vsi->seid, TRUE, NULL);
+ ixl_del_multi(vsi, true);
return;
}
- /* (re-)install filters for all mcast addresses */
- /* XXX: This bypasses filter count tracking code! */
- mcnt = if_foreach_llmaddr(iflib_get_ifp(ctx), ixl_mc_filter_apply, vsi);
- if (mcnt > 0) {
- vsi->num_macs += mcnt;
- flags = (IXL_FILTER_ADD | IXL_FILTER_USED | IXL_FILTER_MC);
- ixl_add_hw_filters(vsi, flags, mcnt);
- }
- ixl_dbg_filter(pf, "%s: filter mac total: %d\n",
- __func__, vsi->num_macs);
+ ixl_add_multi(vsi);
IOCTL_DEBUGOUT("ixl_if_multi_set: end");
}
@@ -1661,12 +1653,35 @@
struct ixl_pf *pf = iflib_get_softc(ctx);
struct ixl_vsi *vsi = &pf->vsi;
struct i40e_hw *hw = vsi->hw;
+ if_t ifp = iflib_get_ifp(ctx);
if ((vtag == 0) || (vtag > 4095)) /* Invalid */
return;
+ /*
+ * Keep track of registered VLANS to know what
+ * filters have to be configured when VLAN_HWFILTER
+ * capability is enabled.
+ */
++vsi->num_vlans;
- ixl_add_filter(vsi, hw->mac.addr, vtag);
+ bit_set(vsi->vlans_map, vtag);
+
+ if ((if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER) == 0)
+ return;
+
+ if (vsi->num_vlans < IXL_MAX_VLAN_FILTERS)
+ ixl_add_filter(vsi, hw->mac.addr, vtag);
+ else if (vsi->num_vlans == IXL_MAX_VLAN_FILTERS) {
+ /*
+ * There is not enough HW resources to add filters
+ * for all registered VLANs. Re-configure filtering
+ * to allow reception of all expected traffic.
+ */
+ device_printf(vsi->dev,
+ "Not enough HW filters for all VLANs. VLAN HW filtering disabled");
+ ixl_del_all_vlan_filters(vsi, hw->mac.addr);
+ ixl_add_filter(vsi, hw->mac.addr, IXL_VLAN_ANY);
+ }
}
static void
@@ -1675,12 +1690,23 @@
struct ixl_pf *pf = iflib_get_softc(ctx);
struct ixl_vsi *vsi = &pf->vsi;
struct i40e_hw *hw = vsi->hw;
+ if_t ifp = iflib_get_ifp(ctx);
if ((vtag == 0) || (vtag > 4095)) /* Invalid */
return;
--vsi->num_vlans;
- ixl_del_filter(vsi, hw->mac.addr, vtag);
+ bit_clear(vsi->vlans_map, vtag);
+
+ if ((if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER) == 0)
+ return;
+
+ if (vsi->num_vlans < IXL_MAX_VLAN_FILTERS)
+ ixl_del_filter(vsi, hw->mac.addr, vtag);
+ else if (vsi->num_vlans == IXL_MAX_VLAN_FILTERS) {
+ ixl_del_filter(vsi, hw->mac.addr, IXL_VLAN_ANY);
+ ixl_add_vlan_filters(vsi, hw->mac.addr);
+ }
}
static uint64_t
@@ -1798,15 +1824,6 @@
}
}
-static u_int
-ixl_mc_filter_apply(void *arg, struct sockaddr_dl *sdl, u_int count __unused)
-{
- struct ixl_vsi *vsi = arg;
-
- ixl_add_mc_filter(vsi, (u8*)LLADDR(sdl));
- return (1);
-}
-
/*
* Sanity check and save off tunable values.
*/
diff --git a/sys/dev/ixl/ixl.h b/sys/dev/ixl/ixl.h
--- a/sys/dev/ixl/ixl.h
+++ b/sys/dev/ixl/ixl.h
@@ -53,6 +53,7 @@
#include <sys/eventhandler.h>
#include <sys/syslog.h>
#include <sys/priv.h>
+#include <sys/bitstring.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -187,15 +188,15 @@
#define IXL_BULK_LATENCY 2
/* MacVlan Flags */
-#define IXL_FILTER_USED (u16)(1 << 0)
-#define IXL_FILTER_VLAN (u16)(1 << 1)
-#define IXL_FILTER_ADD (u16)(1 << 2)
-#define IXL_FILTER_DEL (u16)(1 << 3)
-#define IXL_FILTER_MC (u16)(1 << 4)
+#define IXL_FILTER_VLAN (u16)(1 << 0)
+#define IXL_FILTER_MC (u16)(1 << 1)
/* used in the vlan field of the filter when not a vlan */
#define IXL_VLAN_ANY -1
+/* Maximum number of MAC/VLAN filters supported by HW */
+#define IXL_MAX_VLAN_FILTERS 256
+
#define CSUM_OFFLOAD_IPV4 (CSUM_IP|CSUM_TCP|CSUM_UDP|CSUM_SCTP)
#define CSUM_OFFLOAD_IPV6 (CSUM_TCP_IPV6|CSUM_UDP_IPV6|CSUM_SCTP_IPV6)
#define CSUM_OFFLOAD (CSUM_OFFLOAD_IPV4|CSUM_OFFLOAD_IPV6|CSUM_TSO)
@@ -303,16 +304,18 @@
/* For stats sysctl naming */
#define IXL_QUEUE_NAME_LEN 32
+MALLOC_DECLARE(M_IXL);
+
#define IXL_DEV_ERR(_dev, _format, ...) \
device_printf(_dev, "%s: " _format " (%s:%d)\n", __func__, ##__VA_ARGS__, __FILE__, __LINE__)
/*
*****************************************************************************
* vendor_info_array
- *
+ *
* This array contains the list of Subvendor/Subdevice IDs on which the driver
* should load.
- *
+ *
*****************************************************************************
*/
typedef struct _ixl_vendor_info_t {
@@ -328,7 +331,7 @@
** addresses, vlans, and mac filters all use it.
*/
struct ixl_mac_filter {
- SLIST_ENTRY(ixl_mac_filter) next;
+ LIST_ENTRY(ixl_mac_filter) ftle;
u8 macaddr[ETHER_ADDR_LEN];
s16 vlan;
u16 flags;
@@ -414,7 +417,7 @@
/*
** Virtual Station Interface
*/
-SLIST_HEAD(ixl_ftl_head, ixl_mac_filter);
+LIST_HEAD(ixl_ftl_head, ixl_mac_filter);
struct ixl_vsi {
if_ctx_t ctx;
if_softc_ctx_t shared;
@@ -452,6 +455,8 @@
/* Contains readylist & stat counter id */
struct i40e_aqc_vsi_properties_data info;
+#define IXL_VLANS_MAP_LEN EVL_VLID_MASK + 1
+ bitstr_t bit_decl(vlans_map, IXL_VLANS_MAP_LEN);
u16 num_vlans;
/* Per-VSI stats from hardware */
@@ -478,32 +483,16 @@
struct sysctl_ctx_list sysctl_ctx;
};
-/*
-** Creates new filter with given MAC address and VLAN ID
-*/
-static inline struct ixl_mac_filter *
-ixl_new_filter(struct ixl_vsi *vsi, const u8 *macaddr, s16 vlan)
-{
- struct ixl_mac_filter *f;
-
- /* create a new empty filter */
- f = malloc(sizeof(struct ixl_mac_filter),
- M_DEVBUF, M_NOWAIT | M_ZERO);
- if (f) {
- SLIST_INSERT_HEAD(&vsi->ftl, f, next);
- bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN);
- f->vlan = vlan;
- f->flags |= (IXL_FILTER_ADD | IXL_FILTER_USED);
- }
-
- return (f);
-}
+struct ixl_add_maddr_arg {
+ struct ixl_ftl_head to_add;
+ struct ixl_vsi *vsi;
+};
/*
** Compare two ethernet addresses
*/
static inline bool
-cmp_etheraddr(const u8 *ea1, const u8 *ea2)
+ixl_ether_is_equal(const u8 *ea1, const u8 *ea2)
{
return (bcmp(ea1, ea2, ETHER_ADDR_LEN) == 0);
}
diff --git a/sys/dev/ixl/ixl_iw.c b/sys/dev/ixl/ixl_iw.c
--- a/sys/dev/ixl/ixl_iw.c
+++ b/sys/dev/ixl/ixl_iw.c
@@ -238,7 +238,7 @@
}
pf_entry = malloc(sizeof(struct ixl_iw_pf_entry),
- M_DEVBUF, M_NOWAIT | M_ZERO);
+ M_IXL, M_NOWAIT | M_ZERO);
if (pf_entry == NULL) {
device_printf(pf->dev,
"%s: failed to allocate memory to attach new PF\n",
@@ -289,7 +289,7 @@
goto out;
}
LIST_REMOVE(pf_entry, node);
- free(pf_entry, M_DEVBUF);
+ free(pf_entry, M_IXL);
ixl_iw_ref_cnt--;
out:
@@ -414,7 +414,7 @@
taskqueue_start_threads(&ixl_iw.tq, 1, PI_NET, "ixl iw");
ixl_iw.ops = malloc(sizeof(struct ixl_iw_ops),
- M_DEVBUF, M_NOWAIT | M_ZERO);
+ M_IXL, M_NOWAIT | M_ZERO);
if (ixl_iw.ops == NULL) {
printf("%s: failed to allocate memory\n", __func__);
taskqueue_free(ixl_iw.tq);
@@ -481,7 +481,7 @@
taskqueue_drain(ixl_iw.tq, &pf_entry->iw_task);
taskqueue_free(ixl_iw.tq);
ixl_iw.tq = NULL;
- free(ixl_iw.ops, M_DEVBUF);
+ free(ixl_iw.ops, M_IXL);
ixl_iw.ops = NULL;
return (0);
diff --git a/sys/dev/ixl/ixl_pf.h b/sys/dev/ixl/ixl_pf.h
--- a/sys/dev/ixl/ixl_pf.h
+++ b/sys/dev/ixl/ixl_pf.h
@@ -78,7 +78,7 @@
/* Used in struct ixl_pf's state field */
enum ixl_pf_state {
IXL_PF_STATE_RECOVERY_MODE = (1 << 0),
- IXL_PF_STATE_ADAPTER_RESETTING = (1 << 1),
+ IXL_PF_STATE_RESETTING = (1 << 1),
IXL_PF_STATE_MDD_PENDING = (1 << 2),
IXL_PF_STATE_PF_RESET_REQ = (1 << 3),
IXL_PF_STATE_VF_RESET_REQ = (1 << 4),
@@ -93,6 +93,8 @@
#define IXL_PF_IN_RECOVERY_MODE(pf) \
((atomic_load_acq_32(&pf->state) & IXL_PF_STATE_RECOVERY_MODE) != 0)
+#define IXL_PF_IS_RESETTING(pf) \
+ ((atomic_load_acq_32(&pf->state) & IXL_PF_STATE_RESETTING) != 0)
struct ixl_vf {
struct ixl_vsi vsi;
@@ -258,8 +260,6 @@
"\t1 - Enable (VEB)\n" \
"Enabling this will allow VFs in separate VMs to communicate over the hardware bridge."
-MALLOC_DECLARE(M_IXL);
-
/*** Functions / Macros ***/
/* Adjust the level here to 10 or over to print stats messages */
#define I40E_VC_DEBUG(p, level, ...) \
@@ -367,6 +367,8 @@
void ixl_add_filter(struct ixl_vsi *, const u8 *, s16 vlan);
void ixl_del_filter(struct ixl_vsi *, const u8 *, s16 vlan);
+void ixl_add_vlan_filters(struct ixl_vsi *, const u8 *);
+void ixl_del_all_vlan_filters(struct ixl_vsi *, const u8 *);
void ixl_reconfigure_filters(struct ixl_vsi *vsi);
int ixl_disable_rings(struct ixl_pf *, struct ixl_vsi *, struct ixl_pf_qtag *);
@@ -391,16 +393,15 @@
void ixl_disable_rings_intr(struct ixl_vsi *);
void ixl_set_promisc(struct ixl_vsi *);
void ixl_add_multi(struct ixl_vsi *);
-int ixl_del_multi(struct ixl_vsi *);
+void ixl_del_multi(struct ixl_vsi *, bool);
void ixl_setup_vlan_filters(struct ixl_vsi *);
void ixl_init_filters(struct ixl_vsi *);
-void ixl_add_hw_filters(struct ixl_vsi *, int, int);
-void ixl_del_hw_filters(struct ixl_vsi *, int);
+void ixl_free_filters(struct ixl_ftl_head *);
+void ixl_add_hw_filters(struct ixl_vsi *, struct ixl_ftl_head *, int);
+void ixl_del_hw_filters(struct ixl_vsi *, struct ixl_ftl_head *, int);
void ixl_del_default_hw_filters(struct ixl_vsi *);
struct ixl_mac_filter *
- ixl_find_filter(struct ixl_vsi *, const u8 *, s16);
-void ixl_add_mc_filter(struct ixl_vsi *, u8 *);
-void ixl_free_mac_filters(struct ixl_vsi *vsi);
+ ixl_find_filter(struct ixl_ftl_head *, const u8 *, s16);
void ixl_update_vsi_stats(struct ixl_vsi *);
void ixl_vsi_reset_stats(struct ixl_vsi *);
diff --git a/sys/dev/ixl/ixl_pf_iflib.c b/sys/dev/ixl/ixl_pf_iflib.c
--- a/sys/dev/ixl/ixl_pf_iflib.c
+++ b/sys/dev/ixl/ixl_pf_iflib.c
@@ -185,7 +185,7 @@
}
device_printf(dev, "Reset Requested! (%s)\n", reset_type);
/* overload admin queue task to check reset progress */
- atomic_set_int(&pf->state, IXL_PF_STATE_ADAPTER_RESETTING);
+ atomic_set_int(&pf->state, IXL_PF_STATE_RESETTING);
do_task = TRUE;
}
@@ -866,41 +866,6 @@
}
}
-/*
-** This routine updates vlan filters, called by init
-** it scans the filter table and then updates the hw
-** after a soft reset.
-*/
-void
-ixl_setup_vlan_filters(struct ixl_vsi *vsi)
-{
- struct ixl_mac_filter *f;
- int cnt = 0, flags;
-
- if (vsi->num_vlans == 0)
- return;
- /*
- ** Scan the filter list for vlan entries,
- ** mark them for addition and then call
- ** for the AQ update.
- */
- SLIST_FOREACH(f, &vsi->ftl, next) {
- if (f->flags & IXL_FILTER_VLAN) {
- f->flags |=
- (IXL_FILTER_ADD |
- IXL_FILTER_USED);
- cnt++;
- }
- }
- if (cnt == 0) {
- printf("setup vlan: no filters found!\n");
- return;
- }
- flags = IXL_FILTER_VLAN;
- flags |= (IXL_FILTER_ADD | IXL_FILTER_USED);
- ixl_add_hw_filters(vsi, flags, cnt);
-}
-
/* For PF VSI only */
int
ixl_enable_rings(struct ixl_vsi *vsi)
diff --git a/sys/dev/ixl/ixl_pf_iov.c b/sys/dev/ixl/ixl_pf_iov.c
--- a/sys/dev/ixl/ixl_pf_iov.c
+++ b/sys/dev/ixl/ixl_pf_iov.c
@@ -1025,7 +1025,7 @@
* is not its assigned MAC.
*/
if (!(vf->vf_flags & VF_FLAG_SET_MAC_CAP) &&
- !(ETHER_IS_MULTICAST(addr) || cmp_etheraddr(addr, vf->mac)))
+ !(ETHER_IS_MULTICAST(addr) || !ixl_ether_is_equal(addr, vf->mac)))
return (EPERM);
return (0);
@@ -1717,7 +1717,7 @@
if (pf->vfs[i].vsi.seid != 0)
i40e_aq_delete_element(hw, pf->vfs[i].vsi.seid, NULL);
ixl_pf_qmgr_release(&pf->qmgr, &pf->vfs[i].qtag);
- ixl_free_mac_filters(&pf->vfs[i].vsi);
+ ixl_free_filters(&pf->vfs[i].vsi.ftl);
ixl_dbg_iov(pf, "VF %d: %d released\n",
i, pf->vfs[i].qtag.num_allocated);
ixl_dbg_iov(pf, "Unallocated total: %d\n", ixl_pf_qmgr_get_num_free(&pf->qmgr));
diff --git a/sys/dev/ixl/ixl_pf_main.c b/sys/dev/ixl/ixl_pf_main.c
--- a/sys/dev/ixl/ixl_pf_main.c
+++ b/sys/dev/ixl/ixl_pf_main.c
@@ -326,7 +326,7 @@
len = 40 * sizeof(struct i40e_aqc_list_capabilities_element_resp);
retry:
if (!(buf = (struct i40e_aqc_list_capabilities_element_resp *)
- malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO))) {
+ malloc(len, M_IXL, M_NOWAIT | M_ZERO))) {
device_printf(dev, "Unable to allocate cap memory\n");
return (ENOMEM);
}
@@ -334,7 +334,7 @@
/* This populates the hw struct */
status = i40e_aq_discover_capabilities(hw, buf, len,
&needed, i40e_aqc_opc_list_func_capabilities, NULL);
- free(buf, M_DEVBUF);
+ free(buf, M_IXL);
if ((pf->hw.aq.asq_last_status == I40E_AQ_RC_ENOMEM) &&
(again == TRUE)) {
/* retry once with a larger buffer */
@@ -452,12 +452,67 @@
return (status);
}
+/*
+** Creates new filter with given MAC address and VLAN ID
+*/
+static struct ixl_mac_filter *
+ixl_new_filter(struct ixl_ftl_head *headp, const u8 *macaddr, s16 vlan)
+{
+ struct ixl_mac_filter *f;
+
+ /* create a new empty filter */
+ f = malloc(sizeof(struct ixl_mac_filter),
+ M_IXL, M_NOWAIT | M_ZERO);
+ if (f) {
+ LIST_INSERT_HEAD(headp, f, ftle);
+ bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN);
+ f->vlan = vlan;
+ }
+
+ return (f);
+}
+
+/**
+ * ixl_free_filters - Free all filters in given list
+ * headp - pointer to list head
+ *
+ * Frees memory used by each entry in the list.
+ * Does not remove filters from HW.
+ */
+void
+ixl_free_filters(struct ixl_ftl_head *headp)
+{
+ struct ixl_mac_filter *f, *nf;
+
+ f = LIST_FIRST(headp);
+ while (f != NULL) {
+ nf = LIST_NEXT(f, ftle);
+ free(f, M_IXL);
+ f = nf;
+ }
+
+ LIST_INIT(headp);
+}
+
static u_int
ixl_add_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
{
- struct ixl_vsi *vsi = arg;
+ struct ixl_add_maddr_arg *ama = arg;
+ struct ixl_vsi *vsi = ama->vsi;
+ const u8 *macaddr = (u8*)LLADDR(sdl);
+ struct ixl_mac_filter *f;
- ixl_add_mc_filter(vsi, (u8*)LLADDR(sdl));
+ /* Does one already exist */
+ f = ixl_find_filter(&vsi->ftl, macaddr, IXL_VLAN_ANY);
+ if (f != NULL)
+ return (0);
+
+ f = ixl_new_filter(&ama->to_add, macaddr, IXL_VLAN_ANY);
+ if (f == NULL) {
+ device_printf(vsi->dev, "WARNING: no filter available!!\n");
+ return (0);
+ }
+ f->flags |= IXL_FILTER_MC;
return (1);
}
@@ -473,28 +528,26 @@
{
struct ifnet *ifp = vsi->ifp;
struct i40e_hw *hw = vsi->hw;
- int mcnt = 0, flags;
+ int mcnt = 0;
+ struct ixl_add_maddr_arg cb_arg;
IOCTL_DEBUGOUT("ixl_add_multi: begin");
- /*
- ** First just get a count, to decide if we
- ** we simply use multicast promiscuous.
- */
mcnt = if_llmaddr_count(ifp);
if (__predict_false(mcnt >= MAX_MULTICAST_ADDR)) {
- /* delete existing MC filters */
- ixl_del_hw_filters(vsi, mcnt);
i40e_aq_set_vsi_multicast_promiscuous(hw,
vsi->seid, TRUE, NULL);
+ /* delete all existing MC filters */
+ ixl_del_multi(vsi, true);
return;
}
- mcnt = if_foreach_llmaddr(ifp, ixl_add_maddr, vsi);
- if (mcnt > 0) {
- flags = (IXL_FILTER_ADD | IXL_FILTER_USED | IXL_FILTER_MC);
- ixl_add_hw_filters(vsi, flags, mcnt);
- }
+ cb_arg.vsi = vsi;
+ LIST_INIT(&cb_arg.to_add);
+
+ mcnt = if_foreach_llmaddr(ifp, ixl_add_maddr, &cb_arg);
+ if (mcnt > 0)
+ ixl_add_hw_filters(vsi, &cb_arg.to_add, mcnt);
IOCTL_DEBUGOUT("ixl_add_multi: end");
}
@@ -504,34 +557,36 @@
{
struct ixl_mac_filter *f = arg;
- if (cmp_etheraddr(f->macaddr, (u8 *)LLADDR(sdl)))
+ if (ixl_ether_is_equal(f->macaddr, (u8 *)LLADDR(sdl)))
return (1);
else
return (0);
}
-int
-ixl_del_multi(struct ixl_vsi *vsi)
+void
+ixl_del_multi(struct ixl_vsi *vsi, bool all)
{
+ struct ixl_ftl_head to_del;
struct ifnet *ifp = vsi->ifp;
- struct ixl_mac_filter *f;
+ struct ixl_mac_filter *f, *fn;
int mcnt = 0;
IOCTL_DEBUGOUT("ixl_del_multi: begin");
+ LIST_INIT(&to_del);
/* Search for removed multicast addresses */
- SLIST_FOREACH(f, &vsi->ftl, next)
- if ((f->flags & IXL_FILTER_USED) &&
- (f->flags & IXL_FILTER_MC) &&
- (if_foreach_llmaddr(ifp, ixl_match_maddr, f) == 0)) {
- f->flags |= IXL_FILTER_DEL;
- mcnt++;
- }
+ LIST_FOREACH_SAFE(f, &vsi->ftl, ftle, fn) {
+ if ((f->flags & IXL_FILTER_MC) == 0 ||
+ (!all && (if_foreach_llmaddr(ifp, ixl_match_maddr, f) == 0)))
+ continue;
- if (mcnt > 0)
- ixl_del_hw_filters(vsi, mcnt);
+ LIST_REMOVE(f, ftle);
+ LIST_INSERT_HEAD(&to_del, f, ftle);
+ mcnt++;
+ }
- return (mcnt);
+ if (mcnt > 0)
+ ixl_del_hw_filters(vsi, &to_del, mcnt);
}
void
@@ -738,20 +793,6 @@
return (ret);
}
-void
-ixl_free_mac_filters(struct ixl_vsi *vsi)
-{
- struct ixl_mac_filter *f;
-
- while (!SLIST_EMPTY(&vsi->ftl)) {
- f = SLIST_FIRST(&vsi->ftl);
- SLIST_REMOVE_HEAD(&vsi->ftl, next);
- free(f, M_DEVBUF);
- }
-
- vsi->num_hw_filters = 0;
-}
-
void
ixl_vsi_add_sysctls(struct ixl_vsi * vsi, const char * sysctl_name, bool queues_sysctls)
{
@@ -1019,7 +1060,7 @@
ixl_dbg_filter(pf, "%s: start\n", __func__);
/* Initialize mac filter list for VSI */
- SLIST_INIT(&vsi->ftl);
+ LIST_INIT(&vsi->ftl);
vsi->num_hw_filters = 0;
/* Receive broadcast Ethernet frames */
@@ -1045,30 +1086,35 @@
#endif
}
-/*
-** This routine adds mulicast filters
-*/
void
-ixl_add_mc_filter(struct ixl_vsi *vsi, u8 *macaddr)
+ixl_reconfigure_filters(struct ixl_vsi *vsi)
{
- struct ixl_mac_filter *f;
+ struct i40e_hw *hw = vsi->hw;
+ struct ixl_ftl_head tmp;
+ int cnt;
- /* Does one already exist */
- f = ixl_find_filter(vsi, macaddr, IXL_VLAN_ANY);
- if (f != NULL)
- return;
+ /*
+ * The ixl_add_hw_filters function adds filters configured
+ * in HW to a list in VSI. Move all filters to a temporary
+ * list to avoid corrupting it by concatenating to itself.
+ */
+ LIST_INIT(&tmp);
+ LIST_CONCAT(&tmp, &vsi->ftl, ixl_mac_filter, ftle);
+ cnt = vsi->num_hw_filters;
+ vsi->num_hw_filters = 0;
- f = ixl_new_filter(vsi, macaddr, IXL_VLAN_ANY);
- if (f != NULL)
- f->flags |= IXL_FILTER_MC;
- else
- printf("WARNING: no filter available!!\n");
-}
+ ixl_add_hw_filters(vsi, &tmp, cnt);
-void
-ixl_reconfigure_filters(struct ixl_vsi *vsi)
-{
- ixl_add_hw_filters(vsi, IXL_FILTER_USED, vsi->num_macs);
+ /* Filter could be removed if MAC address was changed */
+ ixl_add_filter(vsi, hw->mac.addr, IXL_VLAN_ANY);
+
+ if ((if_getcapenable(vsi->ifp) & IFCAP_VLAN_HWFILTER) == 0)
+ return;
+ /*
+ * VLAN HW filtering is enabled, make sure that filters
+ * for all registered VLAN tags are configured
+ */
+ ixl_add_vlan_filters(vsi, hw->mac.addr);
}
/*
@@ -1082,82 +1128,205 @@
struct ixl_mac_filter *f, *tmp;
struct ixl_pf *pf;
device_t dev;
+ struct ixl_ftl_head to_add;
+ int to_add_cnt;
pf = vsi->back;
dev = pf->dev;
+ to_add_cnt = 1;
ixl_dbg_filter(pf, "ixl_add_filter: " MAC_FORMAT ", vlan %4d\n",
MAC_FORMAT_ARGS(macaddr), vlan);
/* Does one already exist */
- f = ixl_find_filter(vsi, macaddr, vlan);
+ f = ixl_find_filter(&vsi->ftl, macaddr, vlan);
if (f != NULL)
return;
+
+ LIST_INIT(&to_add);
+ f = ixl_new_filter(&to_add, macaddr, vlan);
+ if (f == NULL) {
+ device_printf(dev, "WARNING: no filter available!!\n");
+ return;
+ }
+ if (f->vlan != IXL_VLAN_ANY)
+ f->flags |= IXL_FILTER_VLAN;
+ else
+ vsi->num_macs++;
+
/*
** Is this the first vlan being registered, if so we
** need to remove the ANY filter that indicates we are
** not in a vlan, and replace that with a 0 filter.
*/
if ((vlan != IXL_VLAN_ANY) && (vsi->num_vlans == 1)) {
- tmp = ixl_find_filter(vsi, macaddr, IXL_VLAN_ANY);
+ tmp = ixl_find_filter(&vsi->ftl, macaddr, IXL_VLAN_ANY);
if (tmp != NULL) {
- ixl_del_filter(vsi, macaddr, IXL_VLAN_ANY);
- ixl_add_filter(vsi, macaddr, 0);
+ struct ixl_ftl_head to_del;
+
+ /* Prepare new filter first to avoid removing
+ * VLAN_ANY filter if allocation fails */
+ f = ixl_new_filter(&to_add, macaddr, 0);
+ if (f == NULL) {
+ device_printf(dev, "WARNING: no filter available!!\n");
+ free(LIST_FIRST(&to_add), M_IXL);
+ return;
+ }
+ to_add_cnt++;
+
+ LIST_REMOVE(tmp, ftle);
+ LIST_INIT(&to_del);
+ LIST_INSERT_HEAD(&to_del, tmp, ftle);
+ ixl_del_hw_filters(vsi, &to_del, 1);
}
}
- f = ixl_new_filter(vsi, macaddr, vlan);
- if (f == NULL) {
- device_printf(dev, "WARNING: no filter available!!\n");
+ ixl_add_hw_filters(vsi, &to_add, to_add_cnt);
+}
+
+/**
+ * ixl_add_vlan_filters - Add MAC/VLAN filters for all registered VLANs
+ * @vsi: pointer to VSI
+ * @macaddr: MAC address
+ *
+ * Adds MAC/VLAN filter for each VLAN configured on the interface
+ * if there is enough HW filters. Otherwise adds a single filter
+ * for all tagged and untagged frames to allow all configured VLANs
+ * to recieve traffic.
+ */
+void
+ixl_add_vlan_filters(struct ixl_vsi *vsi, const u8 *macaddr)
+{
+ struct ixl_ftl_head to_add;
+ struct ixl_mac_filter *f;
+ int to_add_cnt = 0;
+ int i, vlan = 0;
+
+ if (vsi->num_vlans == 0 || vsi->num_vlans > IXL_MAX_VLAN_FILTERS) {
+ ixl_add_filter(vsi, macaddr, IXL_VLAN_ANY);
return;
}
- if (f->vlan != IXL_VLAN_ANY)
- f->flags |= IXL_FILTER_VLAN;
- else
- vsi->num_macs++;
+ LIST_INIT(&to_add);
+
+ /* Add filter for untagged frames if it does not exist yet */
+ f = ixl_find_filter(&vsi->ftl, macaddr, 0);
+ if (f == NULL) {
+ f = ixl_new_filter(&to_add, macaddr, 0);
+ if (f == NULL) {
+ device_printf(vsi->dev, "WARNING: no filter available!!\n");
+ return;
+ }
+ to_add_cnt++;
+ }
+
+ for (i = 1; i < EVL_VLID_MASK; i = vlan + 1) {
+ bit_ffs_at(vsi->vlans_map, i, IXL_VLANS_MAP_LEN, &vlan);
+ if (vlan == -1)
+ break;
- f->flags |= IXL_FILTER_USED;
- ixl_add_hw_filters(vsi, f->flags, 1);
+ /* Does one already exist */
+ f = ixl_find_filter(&vsi->ftl, macaddr, vlan);
+ if (f != NULL)
+ continue;
+
+ f = ixl_new_filter(&to_add, macaddr, vlan);
+ if (f == NULL) {
+ device_printf(vsi->dev, "WARNING: no filter available!!\n");
+ ixl_free_filters(&to_add);
+ return;
+ }
+ to_add_cnt++;
+ }
+
+ ixl_add_hw_filters(vsi, &to_add, to_add_cnt);
}
void
ixl_del_filter(struct ixl_vsi *vsi, const u8 *macaddr, s16 vlan)
{
- struct ixl_mac_filter *f;
+ struct ixl_mac_filter *f, *tmp;
+ struct ixl_ftl_head ftl_head;
+ int to_del_cnt = 1;
ixl_dbg_filter((struct ixl_pf *)vsi->back,
"ixl_del_filter: " MAC_FORMAT ", vlan %4d\n",
MAC_FORMAT_ARGS(macaddr), vlan);
- f = ixl_find_filter(vsi, macaddr, vlan);
+ f = ixl_find_filter(&vsi->ftl, macaddr, vlan);
if (f == NULL)
return;
- f->flags |= IXL_FILTER_DEL;
- ixl_del_hw_filters(vsi, 1);
+ LIST_REMOVE(f, ftle);
+ LIST_INIT(&ftl_head);
+ LIST_INSERT_HEAD(&ftl_head, f, ftle);
if (f->vlan == IXL_VLAN_ANY && (f->flags & IXL_FILTER_VLAN) != 0)
vsi->num_macs--;
- /* Check if this is the last vlan removal */
- if (vlan != IXL_VLAN_ANY && vsi->num_vlans == 0) {
- /* Switch back to a non-vlan filter */
- ixl_del_filter(vsi, macaddr, 0);
- ixl_add_filter(vsi, macaddr, IXL_VLAN_ANY);
+ /* If this is not the last vlan just remove the filter */
+ if (vlan == IXL_VLAN_ANY || vsi->num_vlans > 0) {
+ ixl_del_hw_filters(vsi, &ftl_head, to_del_cnt);
+ return;
+ }
+
+ /* It's the last vlan, we need to switch back to a non-vlan filter */
+ tmp = ixl_find_filter(&vsi->ftl, macaddr, 0);
+ if (tmp != NULL) {
+ LIST_REMOVE(tmp, ftle);
+ LIST_INSERT_AFTER(f, tmp, ftle);
+ to_del_cnt++;
+ }
+ ixl_del_hw_filters(vsi, &ftl_head, to_del_cnt);
+
+ ixl_add_filter(vsi, macaddr, IXL_VLAN_ANY);
+}
+
+/**
+ * ixl_del_all_vlan_filters - Delete all VLAN filters with given MAC
+ * @vsi: VSI which filters need to be removed
+ * @macaddr: MAC address
+ *
+ * Remove all MAC/VLAN filters with a given MAC address. For multicast
+ * addresses there is always single filter for all VLANs used (IXL_VLAN_ANY)
+ * so skip them to speed up processing. Those filters should be removed
+ * using ixl_del_filter function.
+ */
+void
+ixl_del_all_vlan_filters(struct ixl_vsi *vsi, const u8 *macaddr)
+{
+ struct ixl_mac_filter *f, *tmp;
+ struct ixl_ftl_head to_del;
+ int to_del_cnt = 0;
+
+ LIST_INIT(&to_del);
+
+ LIST_FOREACH_SAFE(f, &vsi->ftl, ftle, tmp) {
+ if ((f->flags & IXL_FILTER_MC) != 0 ||
+ !ixl_ether_is_equal(f->macaddr, macaddr))
+ continue;
+
+ LIST_REMOVE(f, ftle);
+ LIST_INSERT_HEAD(&to_del, f, ftle);
+ to_del_cnt++;
}
- return;
+
+ ixl_dbg_filter((struct ixl_pf *)vsi->back,
+ "%s: " MAC_FORMAT ", to_del_cnt: %d\n",
+ __func__, MAC_FORMAT_ARGS(macaddr), to_del_cnt);
+ if (to_del_cnt > 0)
+ ixl_del_hw_filters(vsi, &to_del, to_del_cnt);
}
/*
** Find the filter with both matching mac addr and vlan id
*/
struct ixl_mac_filter *
-ixl_find_filter(struct ixl_vsi *vsi, const u8 *macaddr, s16 vlan)
+ixl_find_filter(struct ixl_ftl_head *headp, const u8 *macaddr, s16 vlan)
{
struct ixl_mac_filter *f;
- SLIST_FOREACH(f, &vsi->ftl, next) {
- if ((cmp_etheraddr(f->macaddr, macaddr) != 0)
- && (f->vlan == vlan)) {
+ LIST_FOREACH(f, headp, ftle) {
+ if (ixl_ether_is_equal(f->macaddr, macaddr) &&
+ (f->vlan == vlan)) {
return (f);
}
}
@@ -1171,10 +1340,10 @@
** the filters in the hardware.
*/
void
-ixl_add_hw_filters(struct ixl_vsi *vsi, int flags, int cnt)
+ixl_add_hw_filters(struct ixl_vsi *vsi, struct ixl_ftl_head *to_add, int cnt)
{
struct i40e_aqc_add_macvlan_element_data *a, *b;
- struct ixl_mac_filter *f;
+ struct ixl_mac_filter *f, *fn;
struct ixl_pf *pf;
struct i40e_hw *hw;
device_t dev;
@@ -1185,8 +1354,7 @@
dev = vsi->dev;
hw = &pf->hw;
- ixl_dbg_filter(pf,
- "ixl_add_hw_filters: flags: %d cnt: %d\n", flags, cnt);
+ ixl_dbg_filter(pf, "ixl_add_hw_filters: cnt: %d\n", cnt);
if (cnt < 1) {
ixl_dbg_info(pf, "ixl_add_hw_filters: cnt == 0\n");
@@ -1194,51 +1362,71 @@
}
a = malloc(sizeof(struct i40e_aqc_add_macvlan_element_data) * cnt,
- M_DEVBUF, M_NOWAIT | M_ZERO);
+ M_IXL, M_NOWAIT | M_ZERO);
if (a == NULL) {
device_printf(dev, "add_hw_filters failed to get memory\n");
return;
}
- /*
- ** Scan the filter list, each time we find one
- ** we add it to the admin queue array and turn off
- ** the add bit.
- */
- SLIST_FOREACH(f, &vsi->ftl, next) {
- if ((f->flags & flags) == flags) {
- b = &a[j]; // a pox on fvl long names :)
- bcopy(f->macaddr, b->mac_addr, ETHER_ADDR_LEN);
- if (f->vlan == IXL_VLAN_ANY) {
- b->vlan_tag = 0;
- b->flags = CPU_TO_LE16(
- I40E_AQC_MACVLAN_ADD_IGNORE_VLAN);
- } else {
- b->vlan_tag = CPU_TO_LE16(f->vlan);
- b->flags = 0;
- }
- b->flags |= CPU_TO_LE16(
- I40E_AQC_MACVLAN_ADD_PERFECT_MATCH);
- f->flags &= ~IXL_FILTER_ADD;
- j++;
-
- ixl_dbg_filter(pf, "ADD: " MAC_FORMAT "\n",
- MAC_FORMAT_ARGS(f->macaddr));
+ LIST_FOREACH(f, to_add, ftle) {
+ b = &a[j]; // a pox on fvl long names :)
+ bcopy(f->macaddr, b->mac_addr, ETHER_ADDR_LEN);
+ if (f->vlan == IXL_VLAN_ANY) {
+ b->vlan_tag = 0;
+ b->flags = I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
+ } else {
+ b->vlan_tag = f->vlan;
+ b->flags = 0;
}
- if (j == cnt)
+ b->flags |= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;
+ ixl_dbg_filter(pf, "ADD: " MAC_FORMAT "\n",
+ MAC_FORMAT_ARGS(f->macaddr));
+
+ if (++j == cnt)
break;
}
- if (j > 0) {
- status = i40e_aq_add_macvlan(hw, vsi->seid, a, j, NULL);
- if (status)
- device_printf(dev, "i40e_aq_add_macvlan status %s, "
- "error %s\n", i40e_stat_str(hw, status),
- i40e_aq_str(hw, hw->aq.asq_last_status));
- else
- vsi->num_hw_filters += j;
+ if (j != cnt) {
+ /* Something went wrong */
+ device_printf(dev,
+ "%s ERROR: list of filters to short expected: %d, found: %d\n",
+ __func__, cnt, j);
+ ixl_free_filters(to_add);
+ goto out_free;
+ }
+
+ status = i40e_aq_add_macvlan(hw, vsi->seid, a, j, NULL);
+ if (status == I40E_SUCCESS) {
+ LIST_CONCAT(&vsi->ftl, to_add, ixl_mac_filter, ftle);
+ vsi->num_hw_filters += j;
+ goto out_free;
}
- free(a, M_DEVBUF);
- return;
+
+ device_printf(dev,
+ "i40e_aq_add_macvlan status %s, error %s\n",
+ i40e_stat_str(hw, status),
+ i40e_aq_str(hw, hw->aq.asq_last_status));
+ j = 0;
+
+ /* Verify which filters were actually configured in HW
+ * and add them to the list */
+ LIST_FOREACH_SAFE(f, to_add, ftle, fn) {
+ LIST_REMOVE(f, ftle);
+ if (a[j].match_method == I40E_AQC_MM_ERR_NO_RES) {
+ ixl_dbg_filter(pf,
+ "%s filter " MAC_FORMAT " VTAG: %d not added\n",
+ __func__,
+ MAC_FORMAT_ARGS(f->macaddr),
+ f->vlan);
+ free(f, M_IXL);
+ } else {
+ LIST_INSERT_HEAD(&vsi->ftl, f, ftle);
+ vsi->num_hw_filters++;
+ }
+ j++;
+ }
+
+out_free:
+ free(a, M_IXL);
}
/*
@@ -1247,7 +1435,7 @@
** the filters in the hardware.
*/
void
-ixl_del_hw_filters(struct ixl_vsi *vsi, int cnt)
+ixl_del_hw_filters(struct ixl_vsi *vsi, struct ixl_ftl_head *to_del, int cnt)
{
struct i40e_aqc_remove_macvlan_element_data *d, *e;
struct ixl_pf *pf;
@@ -1264,52 +1452,62 @@
ixl_dbg_filter(pf, "%s: start, cnt: %d\n", __func__, cnt);
d = malloc(sizeof(struct i40e_aqc_remove_macvlan_element_data) * cnt,
- M_DEVBUF, M_NOWAIT | M_ZERO);
+ M_IXL, M_NOWAIT | M_ZERO);
if (d == NULL) {
device_printf(dev, "%s: failed to get memory\n", __func__);
return;
}
- SLIST_FOREACH_SAFE(f, &vsi->ftl, next, f_temp) {
- if (f->flags & IXL_FILTER_DEL) {
- e = &d[j]; // a pox on fvl long names :)
- bcopy(f->macaddr, e->mac_addr, ETHER_ADDR_LEN);
- e->flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
- if (f->vlan == IXL_VLAN_ANY) {
- e->vlan_tag = 0;
- e->flags |= I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
- } else {
- e->vlan_tag = f->vlan;
- }
+ LIST_FOREACH_SAFE(f, to_del, ftle, f_temp) {
+ e = &d[j]; // a pox on fvl long names :)
+ bcopy(f->macaddr, e->mac_addr, ETHER_ADDR_LEN);
+ e->flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
+ if (f->vlan == IXL_VLAN_ANY) {
+ e->vlan_tag = 0;
+ e->flags |= I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
+ } else {
+ e->vlan_tag = f->vlan;
+ }
- ixl_dbg_filter(pf, "DEL: " MAC_FORMAT "\n",
- MAC_FORMAT_ARGS(f->macaddr));
+ ixl_dbg_filter(pf, "DEL: " MAC_FORMAT "\n",
+ MAC_FORMAT_ARGS(f->macaddr));
- /* delete entry from vsi list */
- SLIST_REMOVE(&vsi->ftl, f, ixl_mac_filter, next);
- free(f, M_DEVBUF);
- j++;
- }
- if (j == cnt)
+ /* delete entry from the list */
+ LIST_REMOVE(f, ftle);
+ free(f, M_IXL);
+ if (++j == cnt)
break;
}
- if (j > 0) {
- status = i40e_aq_remove_macvlan(hw, vsi->seid, d, j, NULL);
- if (status) {
- int sc = 0;
- for (int i = 0; i < j; i++)
- sc += (!d[i].error_code);
- vsi->num_hw_filters -= sc;
+ if (j != cnt || !LIST_EMPTY(to_del)) {
+ /* Something went wrong */
+ device_printf(dev,
+ "%s ERROR: wrong size of list of filters, expected: %d, found: %d\n",
+ __func__, cnt, j);
+ ixl_free_filters(to_del);
+ goto out_free;
+ }
+ status = i40e_aq_remove_macvlan(hw, vsi->seid, d, j, NULL);
+ if (status) {
+ device_printf(dev,
+ "%s: i40e_aq_remove_macvlan status %s, error %s\n",
+ __func__, i40e_stat_str(hw, status),
+ i40e_aq_str(hw, hw->aq.asq_last_status));
+ for (int i = 0; i < j; i++) {
+ if (d[i].error_code == 0)
+ continue;
device_printf(dev,
- "Failed to remove %d/%d filters, error %s\n",
- j - sc, j, i40e_aq_str(hw, hw->aq.asq_last_status));
- } else
- vsi->num_hw_filters -= j;
+ "%s Filter does not exist " MAC_FORMAT " VTAG: %d\n",
+ __func__, MAC_FORMAT_ARGS(d[i].mac_addr),
+ d[i].vlan_tag);
+ }
}
- free(d, M_DEVBUF);
+
+ vsi->num_hw_filters -= j;
+
+out_free:
+ free(d, M_IXL);
ixl_dbg_filter(pf, "%s: end\n", __func__);
- return;
}
int
@@ -1726,7 +1924,7 @@
ixl_rebuild_hw_structs_after_reset(pf, is_up);
- atomic_clear_32(&pf->state, IXL_PF_STATE_ADAPTER_RESETTING);
+ atomic_clear_32(&pf->state, IXL_PF_STATE_RESETTING);
}
void
@@ -2805,16 +3003,16 @@
if (pf->dbg_mask & IXL_DBG_NVMUPD)
ixl_print_nvm_cmd(dev, nvma);
- if (pf->state & IXL_PF_STATE_ADAPTER_RESETTING) {
+ if (IXL_PF_IS_RESETTING(pf)) {
int count = 0;
while (count++ < 100) {
i40e_msec_delay(100);
- if (!(pf->state & IXL_PF_STATE_ADAPTER_RESETTING))
+ if (!(IXL_PF_IS_RESETTING(pf)))
break;
}
}
- if (pf->state & IXL_PF_STATE_ADAPTER_RESETTING) {
+ if (IXL_PF_IS_RESETTING(pf)) {
device_printf(dev,
"%s: timeout waiting for EMP reset to finish\n",
__func__);
@@ -3151,13 +3349,13 @@
/* Print MAC filters */
sbuf_printf(buf, "PF Filters:\n");
- SLIST_FOREACH(f, &vsi->ftl, next)
+ LIST_FOREACH(f, &vsi->ftl, ftle)
ftl_len++;
if (ftl_len < 1)
sbuf_printf(buf, "(none)\n");
else {
- SLIST_FOREACH(f, &vsi->ftl, next) {
+ LIST_FOREACH(f, &vsi->ftl, ftle) {
sbuf_printf(buf,
MAC_FORMAT ", vlan %4d, flags %#06x",
MAC_FORMAT_ARGS(f->macaddr), f->vlan, f->flags);
@@ -3180,13 +3378,13 @@
vsi = &vf->vsi;
ftl_len = 0, ftl_counter = 0;
sbuf_printf(buf, "VF-%d Filters:\n", vf->vf_num);
- SLIST_FOREACH(f, &vsi->ftl, next)
+ LIST_FOREACH(f, &vsi->ftl, ftle)
ftl_len++;
if (ftl_len < 1)
sbuf_printf(buf, "(none)\n");
else {
- SLIST_FOREACH(f, &vsi->ftl, next) {
+ LIST_FOREACH(f, &vsi->ftl, ftle) {
sbuf_printf(buf,
MAC_FORMAT ", vlan %4d, flags %#06x\n",
MAC_FORMAT_ARGS(f->macaddr), f->vlan, f->flags);
@@ -4037,7 +4235,7 @@
u8 *final_buff;
/* This amount is only necessary if reading the entire cluster into memory */
#define IXL_FINAL_BUFF_SIZE (1280 * 1024)
- final_buff = malloc(IXL_FINAL_BUFF_SIZE, M_DEVBUF, M_NOWAIT);
+ final_buff = malloc(IXL_FINAL_BUFF_SIZE, M_IXL, M_NOWAIT);
if (final_buff == NULL) {
device_printf(dev, "Could not allocate memory for output.\n");
goto out;
@@ -4099,7 +4297,7 @@
}
free_out:
- free(final_buff, M_DEVBUF);
+ free(final_buff, M_IXL);
out:
error = sbuf_finish(buf);
if (error)
@@ -4173,9 +4371,6 @@
device_printf(dev, "FW LLDP agent is already stopped\n");
}
-#ifndef EXTERNAL_RELEASE
- /* Let the FW set default DCB configuration on link UP as described in DCR 307.1 */
-#endif
i40e_aq_set_dcb_parameters(hw, true, NULL);
atomic_set_32(&pf->state, IXL_PF_STATE_FW_LLDP_DISABLED);
return (0);

File Metadata

Mime Type
text/plain
Expires
Thu, Nov 7, 9:34 PM (21 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14521288
Default Alt Text
D28137.diff (40 KB)

Event Timeline