Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102042486
D28137.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
40 KB
Referenced Files
None
Subscribers
None
D28137.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D28137: ixl(4): Fix VLAN HW filtering
Attached
Detach File
Event Timeline
Log In to Comment