Page MenuHomeFreeBSD

D5214.id13967.diff
No OneTemporary

D5214.id13967.diff

Index: sys/dev/ixl/i40e_osdep.c
===================================================================
--- sys/dev/ixl/i40e_osdep.c
+++ 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);
return(0);
}
Index: sys/dev/ixl/if_ixl.c
===================================================================
--- sys/dev/ixl/if_ixl.c
+++ sys/dev/ixl/if_ixl.c
@@ -38,6 +38,12 @@
#include "opt_rss.h"
#endif
+#ifndef IXL_DEBUG_SYSCTL
+#ifdef INVARIANTS
+#define IXL_DEBUG_SYSCTL
+#endif
+#endif
+
#include "ixl.h"
#include "ixl_pf.h"
@@ -45,6 +51,8 @@
#include <net/rss_config.h>
#endif
+#include "ifdi_if.h"
+
/*********************************************************************
* Driver version
*********************************************************************/
@@ -55,70 +63,45 @@
*
* Used by probe to select devices to load on
* Last field stores an index into ixl_strings
- * Last entry must be all 0s
+ * Last entry must be PVID_END
*
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
*********************************************************************/
-static ixl_vendor_info_t ixl_vendor_info_array[] =
+static pci_vendor_info_t ixl_vendor_info_array[] =
{
- {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710, 0, 0, 0},
- {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B, 0, 0, 0},
- {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C, 0, 0, 0},
- {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A, 0, 0, 0},
- {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B, 0, 0, 0},
- {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_C, 0, 0, 0},
- {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T, 0, 0, 0},
- {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T4, 0, 0, 0},
+ PVID(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710, "Intel(R) Ethernet Connection XL710 Driver"),
+ PVID(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B, "Intel(R) Ethernet Connection XL710 Driver"),
+ PVID(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C, "Intel(R) Ethernet Connection XL710 Driver"),
+ PVID(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A, "Intel(R) Ethernet Connection XL710 Driver"),
+ PVID(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B, "Intel(R) Ethernet Connection XL710 Driver"),
+ PVID(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_C, "Intel(R) Ethernet Connection XL710 Driver"),
+ PVID(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T, "Intel(R) Ethernet Connection XL710 Driver"),
+ PVID(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T4,"Intel(R) Ethernet Connection XL710 Driver"),
#ifdef X722_SUPPORT
- {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_X722, 0, 0, 0},
- {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_1G_BASE_T_X722, 0, 0, 0},
- {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T_X722, 0, 0, 0},
+ PVID(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_X722, "Intel(R) Ethernet Connection XL710 Driver"),
+ PVID(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_1G_BASE_T_X722, "Intel(R) Ethernet Connection XL710 Driver"),
+ PVID(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T_X722, "Intel(R) Ethernet Connection XL710 Driver"),
#endif
/* required last entry */
- {0, 0, 0, 0, 0}
-};
-
-/*********************************************************************
- * Table of branding strings
- *********************************************************************/
-
-static char *ixl_strings[] = {
- "Intel(R) Ethernet Connection XL710 Driver"
+ PVID_END
};
/*********************************************************************
* Function prototypes
*********************************************************************/
-static int ixl_probe(device_t);
-static int ixl_attach(device_t);
-static int ixl_detach(device_t);
-static int ixl_shutdown(device_t);
+static void *ixl_register(device_t);
static int ixl_get_hw_capabilities(struct ixl_pf *);
-static void ixl_cap_txcsum_tso(struct ixl_vsi *, struct ifnet *, int);
-static int ixl_ioctl(struct ifnet *, u_long, caddr_t);
-static void ixl_init(void *);
-static void ixl_init_locked(struct ixl_pf *);
-static void ixl_stop(struct ixl_pf *);
-static void ixl_media_status(struct ifnet *, struct ifmediareq *);
-static int ixl_media_change(struct ifnet *);
static void ixl_update_link_status(struct ixl_pf *);
static int ixl_allocate_pci_resources(struct ixl_pf *);
static u16 ixl_get_bus_info(struct i40e_hw *, device_t);
-static int ixl_setup_stations(struct ixl_pf *);
static int ixl_switch_config(struct ixl_pf *);
static int ixl_initialize_vsi(struct ixl_vsi *);
-static int ixl_assign_vsi_msix(struct ixl_pf *);
-static int ixl_assign_vsi_legacy(struct ixl_pf *);
-static int ixl_init_msix(struct ixl_pf *);
static void ixl_configure_msix(struct ixl_pf *);
static void ixl_configure_itr(struct ixl_pf *);
static void ixl_configure_legacy(struct ixl_pf *);
-static void ixl_init_taskqueues(struct ixl_pf *);
-static void ixl_free_taskqueues(struct ixl_pf *);
static void ixl_free_pci_resources(struct ixl_pf *);
-static void ixl_local_timer(void *);
static int ixl_setup_interface(device_t, struct ixl_vsi *);
static void ixl_link_event(struct ixl_pf *, struct i40e_arq_event_info *);
static void ixl_config_rss(struct ixl_vsi *);
@@ -129,21 +112,13 @@
static int ixl_enable_rings(struct ixl_vsi *);
static int ixl_disable_rings(struct ixl_vsi *);
static void ixl_enable_intr(struct ixl_vsi *);
-static void ixl_disable_intr(struct ixl_vsi *);
-static void ixl_disable_rings_intr(struct ixl_vsi *);
static void ixl_enable_adminq(struct i40e_hw *);
static void ixl_disable_adminq(struct i40e_hw *);
-static void ixl_enable_queue(struct i40e_hw *, int);
-static void ixl_disable_queue(struct i40e_hw *, int);
static void ixl_enable_legacy(struct i40e_hw *);
static void ixl_disable_legacy(struct i40e_hw *);
-static void ixl_set_promisc(struct ixl_vsi *);
-static void ixl_add_multi(struct ixl_vsi *);
static void ixl_del_multi(struct ixl_vsi *);
-static void ixl_register_vlan(void *, struct ifnet *, u16);
-static void ixl_unregister_vlan(void *, struct ifnet *, u16);
static void ixl_setup_vlan_filters(struct ixl_vsi *);
static void ixl_init_filters(struct ixl_vsi *);
@@ -165,14 +140,11 @@
#endif
/* The MSI/X Interrupt handlers */
-static void ixl_intr(void *);
-static void ixl_msix_que(void *);
-static void ixl_msix_adminq(void *);
+int ixl_intr(void *);
+static int ixl_msix_que(void *);
+static int ixl_msix_adminq(void *);
static void ixl_handle_mdd_event(struct ixl_pf *);
-/* Deferred interrupt tasklets */
-static void ixl_do_adminq(void *, int);
-
/* Sysctl handlers */
static int ixl_set_flowcntl(SYSCTL_HANDLER_ARGS);
static int ixl_set_advertise(SYSCTL_HANDLER_ARGS);
@@ -207,32 +179,63 @@
#ifdef PCI_IOV
static int ixl_adminq_err_to_errno(enum i40e_admin_queue_err err);
-static int ixl_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t*);
-static void ixl_iov_uninit(device_t dev);
-static int ixl_add_vf(device_t dev, uint16_t vfnum, const nvlist_t*);
+static int ixl_if_iov_init(if_ctx_t, uint16_t num_vfs, const nvlist_t*);
+static void ixl_if_iov_uninit(if_ctx_t);
+static int ixl_if_vf_add(if_ctx_t, uint16_t vfnum, const nvlist_t*);
static void ixl_handle_vf_msg(struct ixl_pf *,
struct i40e_arq_event_info *);
-static void ixl_handle_vflr(void *arg, int pending);
+static void ixl_if_handle_vflr(if_ctx_t ctx);
static void ixl_reset_vf(struct ixl_pf *pf, struct ixl_vf *vf);
static void ixl_reinit_vf(struct ixl_pf *pf, struct ixl_vf *vf);
#endif
+static int ixl_if_attach_pre(if_ctx_t);
+static int ixl_if_attach_post(if_ctx_t);
+static int ixl_if_msix_intr_assign(if_ctx_t, int);
+
+static int ixl_if_detach(if_ctx_t);
+
+static void ixl_if_init(if_ctx_t ctx);
+static void ixl_if_stop(if_ctx_t ctx);
+
+static void ixl_if_intr_enable(if_ctx_t ctx);
+static void ixl_if_intr_disable(if_ctx_t ctx);
+static void ixl_if_queue_intr_enable(if_ctx_t ctx, uint16_t qid);
+#if 0
+static void ixl_if_queue_intr_disable(if_ctx_t ctx, uint16_t qid);
+#endif
+static void ixl_if_multi_set(if_ctx_t);
+static void ixl_if_update_admin_status(if_ctx_t);
+static int ixl_if_mtu_set(if_ctx_t, uint32_t);
+
+static void ixl_if_media_status(if_ctx_t, struct ifmediareq *);
+
+static void ixl_if_vlan_register(if_ctx_t ctx, u16 vtag);
+static void ixl_if_vlan_unregister(if_ctx_t ctx, u16 vtag);
+
+
+
+static void ixl_if_timer(if_ctx_t, uint16_t);
+static int ixl_if_promisc_set(if_ctx_t ctx, int flags);
+
+
/*********************************************************************
* FreeBSD Device Interface Entry Points
*********************************************************************/
static device_method_t ixl_methods[] = {
/* Device interface */
- DEVMETHOD(device_probe, ixl_probe),
- DEVMETHOD(device_attach, ixl_attach),
- DEVMETHOD(device_detach, ixl_detach),
- DEVMETHOD(device_shutdown, ixl_shutdown),
+ DEVMETHOD(device_register, ixl_register),
+ DEVMETHOD(device_probe, iflib_device_probe),
+ DEVMETHOD(device_attach, iflib_device_attach),
+ DEVMETHOD(device_detach, iflib_device_detach),
+ DEVMETHOD(device_shutdown, iflib_device_suspend),
#ifdef PCI_IOV
- DEVMETHOD(pci_iov_init, ixl_iov_init),
- DEVMETHOD(pci_iov_uninit, ixl_iov_uninit),
- DEVMETHOD(pci_iov_add_vf, ixl_add_vf),
+ DEVMETHOD(pci_iov_init, iflib_device_iov_init),
+ DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit),
+ DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf),
#endif
{0, 0}
};
@@ -246,14 +249,43 @@
MODULE_DEPEND(ixl, pci, 1, 1, 1);
MODULE_DEPEND(ixl, ether, 1, 1, 1);
-#ifdef DEV_NETMAP
-MODULE_DEPEND(ixl, netmap, 1, 1, 1);
-#endif /* DEV_NETMAP */
+MODULE_DEPEND(ixl, iflib, 1, 1, 1);
+
+
+static device_method_t ixl_if_methods[] = {
+ DEVMETHOD(ifdi_attach_pre, ixl_if_attach_pre),
+ DEVMETHOD(ifdi_attach_post, ixl_if_attach_post),
+ DEVMETHOD(ifdi_detach, ixl_if_detach),
+ DEVMETHOD(ifdi_init, ixl_if_init),
+ DEVMETHOD(ifdi_stop, ixl_if_stop),
+ DEVMETHOD(ifdi_msix_intr_assign, ixl_if_msix_intr_assign),
+ DEVMETHOD(ifdi_intr_disable, ixl_if_intr_disable),
+ DEVMETHOD(ifdi_intr_enable, ixl_if_intr_enable),
+ DEVMETHOD(ifdi_queue_intr_enable, ixl_if_queue_intr_enable),
+ DEVMETHOD(ifdi_multi_set, ixl_if_multi_set),
+ DEVMETHOD(ifdi_queues_alloc, ixl_if_queues_alloc),
+ DEVMETHOD(ifdi_update_admin_status, ixl_if_update_admin_status),
+ DEVMETHOD(ifdi_mtu_set, ixl_if_mtu_set),
+ DEVMETHOD(ifdi_media_status, ixl_if_media_status),
+ DEVMETHOD(ifdi_media_change, ixl_if_media_change),
+ DEVMETHOD(ifdi_timer, ixl_if_timer),
+ DEVMETHOD(ifdi_promisc_set, ixl_if_promisc_set),
+ DEVMETHOD(ifdi_vlan_register, ixl_if_vlan_register),
+ DEVMETHOD(ifdi_vlan_unregister, ixl_if_vlan_unregister),
+ DEVMETHOD(ifdi_queues_free, ixl_if_queues_free),
+#ifdef PCI_IOV
+ DEVMETHOD(ifdi_vflr_handle, ixl_if_handle_vflr),
+ DEVMETHOD(ifdi_iov_init, ixl_if_iov_init),
+ DEVMETHOD(ifdi_iov_uninit, ixl_if_iov_uninit),
+ DEVMETHOD(ifdi_iov_vf_add, ixl_if_vf_add),
+#endif
+ DEVMETHOD_END
+};
+
+static driver_t ixl_if_driver = {
+ "ixl_if", ixl_if_methods, sizeof(struct ixl_pf),
+};
-/*
-** Global reset mutex
-*/
-static struct mtx ixl_reset_mtx;
/*
** TUNEABLE PARAMETERS:
@@ -280,16 +312,6 @@
SYSCTL_INT(_hw_ixl, OID_AUTO, ring_size, CTLFLAG_RDTUN,
&ixl_ringsz, 0, "Descriptor Ring Size");
-/*
-** This can be set manually, if left as 0 the
-** number of queues will be calculated based
-** on cpus and msix vectors available.
-*/
-int ixl_max_queues = 0;
-TUNABLE_INT("hw.ixl.max_queues", &ixl_max_queues);
-SYSCTL_INT(_hw_ixl, OID_AUTO, max_queues, CTLFLAG_RDTUN,
- &ixl_max_queues, 0, "Number of Queues");
-
/*
** Controls for Interrupt Throttling
** - true/false for dynamic adjustment
@@ -323,11 +345,6 @@
TUNABLE_INT("hw.ixl.atr_rate", &ixl_atr_rate);
#endif
-#ifdef DEV_NETMAP
-#define NETMAP_IXL_MAIN /* only bring in one part of the netmap code */
-#include <dev/netmap/if_ixl_netmap.h>
-#endif /* DEV_NETMAP */
-
static char *ixl_fc_string[6] = {
"None",
"Rx",
@@ -337,68 +354,54 @@
"Default"
};
-static MALLOC_DEFINE(M_IXL, "ixl", "ixl driver allocations");
+extern struct if_txrx ixl_txrx;
+
+static struct if_shared_ctx ixl_sctx_init = {
+ .isc_magic = IFLIB_MAGIC,
+ .isc_q_align = PAGE_SIZE,/* max(DBA_ALIGN, PAGE_SIZE) */
+ .isc_tx_maxsize = IXL_TSO_SIZE,
+
+ .isc_tx_maxsegsize = PAGE_SIZE,
+
+ .isc_rx_maxsize = PAGE_SIZE*4,
+ .isc_rx_nsegments = 1,
+ .isc_rx_maxsegsize = PAGE_SIZE*4,
+ .isc_ntxd = DEFAULT_RING,
+ .isc_nrxd = DEFAULT_RING,
+ .isc_nfl = 1,
+ .isc_qsizes[0] = roundup2((DEFAULT_RING * sizeof(struct i40e_tx_desc)) +
+ sizeof(u32), DBA_ALIGN),
+ .isc_qsizes[1] = roundup2(DEFAULT_RING *
+ sizeof(union i40e_rx_desc), DBA_ALIGN),
+ .isc_nqs = 2,
+ .isc_admin_intrcnt = 1,
+ .isc_vendor_info = ixl_vendor_info_array,
+ .isc_driver_version = ixl_driver_version,
+ .isc_txrx = &ixl_txrx,
+ .isc_driver = &ixl_if_driver,
+};
+
+if_shared_ctx_t ixl_sctx = &ixl_sctx_init;
+MALLOC_DEFINE(M_IXL, "ixl", "ixl driver allocations");
static uint8_t ixl_bcast_addr[ETHER_ADDR_LEN] =
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-/*********************************************************************
- * Device identification routine
- *
- * ixl_probe determines if the driver should be loaded on
- * the hardware based on PCI vendor/device id of the device.
- *
- * return BUS_PROBE_DEFAULT on success, positive on failure
- *********************************************************************/
-
-static int
-ixl_probe(device_t dev)
+static void *
+ixl_register(device_t dev)
{
- ixl_vendor_info_t *ent;
+ ixl_sctx->isc_ntxd = ixl_ringsz;
+ ixl_sctx->isc_nrxd = ixl_ringsz;
+ ixl_sctx->isc_qsizes[0] = roundup2((ixl_ringsz * sizeof(struct i40e_tx_desc)) +
+ sizeof(u32), DBA_ALIGN);
+ ixl_sctx->isc_qsizes[1] = roundup2(ixl_ringsz *
+ sizeof(union i40e_rx_desc), DBA_ALIGN);
- u16 pci_vendor_id, pci_device_id;
- u16 pci_subvendor_id, pci_subdevice_id;
- char device_name[256];
- static bool lock_init = FALSE;
- INIT_DEBUGOUT("ixl_probe: begin");
-
- pci_vendor_id = pci_get_vendor(dev);
- if (pci_vendor_id != I40E_INTEL_VENDOR_ID)
- return (ENXIO);
-
- pci_device_id = pci_get_device(dev);
- pci_subvendor_id = pci_get_subvendor(dev);
- pci_subdevice_id = pci_get_subdevice(dev);
-
- ent = ixl_vendor_info_array;
- while (ent->vendor_id != 0) {
- if ((pci_vendor_id == ent->vendor_id) &&
- (pci_device_id == ent->device_id) &&
-
- ((pci_subvendor_id == ent->subvendor_id) ||
- (ent->subvendor_id == 0)) &&
-
- ((pci_subdevice_id == ent->subdevice_id) ||
- (ent->subdevice_id == 0))) {
- sprintf(device_name, "%s, Version - %s",
- ixl_strings[ent->index],
- ixl_driver_version);
- device_set_desc_copy(dev, device_name);
- /* One shot mutex init */
- if (lock_init == FALSE) {
- lock_init = TRUE;
- mtx_init(&ixl_reset_mtx,
- "ixl_reset",
- "IXL RESET Lock", MTX_DEF);
- }
- return (BUS_PROBE_DEFAULT);
- }
- ent++;
- }
- return (ENXIO);
+ return (ixl_sctx);
}
+
/*********************************************************************
* Device initialization routine
*
@@ -410,37 +413,44 @@
*********************************************************************/
static int
-ixl_attach(device_t dev)
+ixl_if_attach_pre(if_ctx_t ctx)
{
+ device_t dev;
struct ixl_pf *pf;
struct i40e_hw *hw;
struct ixl_vsi *vsi;
- u16 bus;
int error = 0;
-#ifdef PCI_IOV
- nvlist_t *pf_schema, *vf_schema;
- int iov_error;
-#endif
INIT_DEBUGOUT("ixl_attach: begin");
- /* Allocate, clear, and link in our primary soft structure */
- pf = device_get_softc(dev);
- pf->dev = pf->osdep.dev = dev;
+ dev = iflib_get_dev(ctx);
+ pf = iflib_get_softc(ctx);
hw = &pf->hw;
+ vsi = &pf->vsi;
+ vsi->back = pf;
+ vsi->hw = &pf->hw;
+ vsi->id = 0;
+ vsi->num_vlans = 0;
+ vsi->ctx = ctx;
+ vsi->media = iflib_get_media(ctx);
+ vsi->shared = iflib_get_softc_ctx(ctx);
+ pf->dev = iflib_get_dev(ctx);
+
+ /*
+ * These are the same across all current ixl models
+ */
+ vsi->shared->isc_tx_nsegments = IXL_MAX_TX_SEGS;
+ vsi->shared->isc_msix_bar = PCIR_BAR(IXL_BAR);
+
+ vsi->shared->isc_tx_tso_segments_max = IXL_MAX_TSO_SEGS;
+ vsi->shared->isc_tx_tso_size_max = IXL_TSO_SIZE;
+ vsi->shared->isc_tx_tso_segsize_max = PAGE_SIZE;
/*
** Note this assumes we have a single embedded VSI,
** this could be enhanced later to allocate multiple
*/
vsi = &pf->vsi;
- vsi->dev = pf->dev;
-
- /* Core Lock Init*/
- IXL_PF_LOCK_INIT(pf, device_get_nameunit(dev));
-
- /* Set up the timer callout */
- callout_init_mtx(&pf->timer, &pf->pf_mtx, 0);
/* Set up sysctls */
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
@@ -539,6 +549,8 @@
hw->bus.func = pci_get_function(dev);
pf->vc_debug_lvl = 1;
+ hw->back = &pf->osdep;
+ pf->osdep.dev = dev;
/* Do PCI setup - map BAR0, etc */
if (ixl_allocate_pci_resources(pf)) {
@@ -581,7 +593,7 @@
}
device_printf(dev, "%s\n", ixl_fw_version_str(hw));
- if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
+ if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR)
device_printf(dev, "The driver for the device detected "
"a newer version of the NVM image than expected.\n"
@@ -626,50 +638,77 @@
goto err_mac_hmc;
}
bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN);
- i40e_get_port_mac_addr(hw, hw->mac.port_addr);
+ iflib_set_mac(ctx, hw->mac.addr);
- /* Set up VSI and queues */
- if (ixl_setup_stations(pf) != 0) {
- device_printf(dev, "setup stations failed!\n");
- error = ENOMEM;
- goto err_mac_hmc;
- }
+ i40e_get_port_mac_addr(hw, hw->mac.port_addr);
/* Initialize mac filter list for VSI */
SLIST_INIT(&vsi->ftl);
+ device_printf(dev, "%s success!\n", __FUNCTION__);
+ return (0);
- /* Set up interrupt routing here */
- if (pf->msix > 1)
- error = ixl_assign_vsi_msix(pf);
- else
- error = ixl_assign_vsi_legacy(pf);
- if (error)
- goto err_mac_hmc;
+err_mac_hmc:
+ i40e_shutdown_lan_hmc(hw);
+err_get_cap:
+ i40e_shutdown_adminq(hw);
+err_out:
+ ixl_free_pci_resources(pf);
+ ixl_free_mac_filters(vsi);
+ return (error);
+}
+
+static int
+ixl_if_attach_post(if_ctx_t ctx)
+{
+ device_t dev;
+ struct ixl_pf *pf;
+ struct i40e_hw *hw;
+ struct ixl_vsi *vsi;
+ int error = 0;
+ u16 bus;
+#ifdef PCI_IOV
+ nvlist_t *pf_schema, *vf_schema;
+ int iov_error;
+#endif
+
+ INIT_DEBUGOUT("ixl_attach: begin");
+
+ dev = iflib_get_dev(ctx);
+ vsi = iflib_get_softc(ctx);
+ vsi->ifp = iflib_get_ifp(ctx);
+ pf = (struct ixl_pf *)vsi;
+ hw = &pf->hw;
if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
(hw->aq.fw_maj_ver < 4)) {
i40e_msec_delay(75);
error = i40e_aq_set_link_restart_an(hw, TRUE, NULL);
- if (error)
+ if (error) {
device_printf(dev, "link restart failed, aq_err=%d\n",
- pf->hw.aq.asq_last_status);
+ pf->hw.aq.asq_last_status);
+ goto err_mac_hmc;
+ }
}
/* Determine link state */
i40e_aq_get_link_info(hw, TRUE, NULL, NULL);
i40e_get_link_status(hw, &pf->link_up);
- /* Setup OS specific network interface */
if (ixl_setup_interface(dev, vsi) != 0) {
device_printf(dev, "interface setup failed!\n");
error = EIO;
- goto err_late;
}
+ if (error) {
+ device_printf(dev, "Interface setup failed: %d\n", error);
+ goto err_mac_hmc;
+ } else
+ device_printf(dev, "%s success!\n", __FUNCTION__);
+
error = ixl_switch_config(pf);
if (error) {
device_printf(dev, "Initial switch config failed: %d\n", error);
- goto err_late;
+ goto err_mac_hmc;
}
/* Limit phy interrupts to link and modules failure */
@@ -682,20 +721,11 @@
bus = ixl_get_bus_info(hw, dev);
i40e_set_pci_config_data(hw, bus);
- /* Initialize taskqueues */
- ixl_init_taskqueues(pf);
-
/* Initialize statistics */
ixl_pf_reset_stats(pf);
ixl_update_stats_counters(pf);
ixl_add_hw_stats(pf);
- /* Register for VLAN events */
- vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
- ixl_register_vlan, vsi, EVENTHANDLER_PRI_FIRST);
- vsi->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
- ixl_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST);
-
#ifdef PCI_IOV
/* SR-IOV is only supported when MSI-X is in use. */
if (pf->msix > 1) {
@@ -716,24 +746,14 @@
iov_error);
}
#endif
-
-#ifdef DEV_NETMAP
- ixl_netmap_attach(vsi);
-#endif /* DEV_NETMAP */
INIT_DEBUGOUT("ixl_attach: end");
+ device_printf(dev, "%s success!\n", __FUNCTION__);
return (0);
-
-err_late:
- if (vsi->ifp != NULL)
- if_free(vsi->ifp);
err_mac_hmc:
i40e_shutdown_lan_hmc(hw);
-err_get_cap:
i40e_shutdown_adminq(hw);
-err_out:
ixl_free_pci_resources(pf);
- ixl_free_vsi(vsi);
- IXL_PF_LOCK_DESTROY(pf);
+ ixl_free_mac_filters(vsi);
return (error);
}
@@ -748,11 +768,11 @@
*********************************************************************/
static int
-ixl_detach(device_t dev)
+ixl_if_detach(if_ctx_t ctx)
{
- struct ixl_pf *pf = device_get_softc(dev);
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct ixl_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
- struct ixl_vsi *vsi = &pf->vsi;
i40e_status status;
#ifdef PCI_IOV
int error;
@@ -760,76 +780,33 @@
INIT_DEBUGOUT("ixl_detach: begin");
- /* Make sure VLANS are not using driver */
- if (vsi->ifp->if_vlantrunk != NULL) {
- device_printf(dev,"Vlan in use, detach first\n");
- return (EBUSY);
- }
-
#ifdef PCI_IOV
- error = pci_iov_detach(dev);
+ error = pci_iov_detach(iflib_get_dev(ctx));
if (error != 0) {
- device_printf(dev, "SR-IOV in use; detach first.\n");
+ device_printf(iflib_get_dev(ctx), "SR-IOV in use; detach first.\n");
return (error);
}
#endif
- ether_ifdetach(vsi->ifp);
- if (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING) {
- IXL_PF_LOCK(pf);
- ixl_stop(pf);
- IXL_PF_UNLOCK(pf);
- }
-
- ixl_free_taskqueues(pf);
-
/* Shutdown LAN HMC */
status = i40e_shutdown_lan_hmc(hw);
if (status)
- device_printf(dev,
+ device_printf(iflib_get_dev(ctx),
"Shutdown LAN HMC failed with code %d\n", status);
/* Shutdown admin queue */
status = i40e_shutdown_adminq(hw);
if (status)
- device_printf(dev,
+ device_printf(iflib_get_dev(ctx),
"Shutdown Admin queue failed with code %d\n", status);
-
- /* Unregister VLAN events */
- if (vsi->vlan_attach != NULL)
- EVENTHANDLER_DEREGISTER(vlan_config, vsi->vlan_attach);
- if (vsi->vlan_detach != NULL)
- EVENTHANDLER_DEREGISTER(vlan_unconfig, vsi->vlan_detach);
-
- callout_drain(&pf->timer);
-#ifdef DEV_NETMAP
- netmap_detach(vsi->ifp);
-#endif /* DEV_NETMAP */
+ else
+ device_printf(iflib_get_dev(ctx),
+ "Shutdown Admin queue success\n");
ixl_free_pci_resources(pf);
- bus_generic_detach(dev);
- if_free(vsi->ifp);
- ixl_free_vsi(vsi);
- IXL_PF_LOCK_DESTROY(pf);
- return (0);
-}
-
-/*********************************************************************
- *
- * Shutdown entry point
- *
- **********************************************************************/
-
-static int
-ixl_shutdown(device_t dev)
-{
- struct ixl_pf *pf = device_get_softc(dev);
- IXL_PF_LOCK(pf);
- ixl_stop(pf);
- IXL_PF_UNLOCK(pf);
+ ixl_free_mac_filters(vsi);
return (0);
}
-
/*********************************************************************
*
* Get the hardware capabilities
@@ -841,7 +818,7 @@
{
struct i40e_aqc_list_capabilities_element_resp *buf;
struct i40e_hw *hw = &pf->hw;
- device_t dev = pf->dev;
+ device_t dev = iflib_get_dev(((struct ixl_vsi *)pf)->ctx);
int error, len;
u16 needed;
bool again = TRUE;
@@ -849,7 +826,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);
}
@@ -857,7 +834,7 @@
/* This populates the hw struct */
error = 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 */
@@ -888,226 +865,27 @@
return (error);
}
-static void
-ixl_cap_txcsum_tso(struct ixl_vsi *vsi, struct ifnet *ifp, int mask)
-{
- device_t dev = vsi->dev;
-
- /* Enable/disable TXCSUM/TSO4 */
- if (!(ifp->if_capenable & IFCAP_TXCSUM)
- && !(ifp->if_capenable & IFCAP_TSO4)) {
- if (mask & IFCAP_TXCSUM) {
- ifp->if_capenable |= IFCAP_TXCSUM;
- /* enable TXCSUM, restore TSO if previously enabled */
- if (vsi->flags & IXL_FLAGS_KEEP_TSO4) {
- vsi->flags &= ~IXL_FLAGS_KEEP_TSO4;
- ifp->if_capenable |= IFCAP_TSO4;
- }
- }
- else if (mask & IFCAP_TSO4) {
- ifp->if_capenable |= (IFCAP_TXCSUM | IFCAP_TSO4);
- vsi->flags &= ~IXL_FLAGS_KEEP_TSO4;
- device_printf(dev,
- "TSO4 requires txcsum, enabling both...\n");
- }
- } else if((ifp->if_capenable & IFCAP_TXCSUM)
- && !(ifp->if_capenable & IFCAP_TSO4)) {
- if (mask & IFCAP_TXCSUM)
- ifp->if_capenable &= ~IFCAP_TXCSUM;
- else if (mask & IFCAP_TSO4)
- ifp->if_capenable |= IFCAP_TSO4;
- } else if((ifp->if_capenable & IFCAP_TXCSUM)
- && (ifp->if_capenable & IFCAP_TSO4)) {
- if (mask & IFCAP_TXCSUM) {
- vsi->flags |= IXL_FLAGS_KEEP_TSO4;
- ifp->if_capenable &= ~(IFCAP_TXCSUM | IFCAP_TSO4);
- device_printf(dev,
- "TSO4 requires txcsum, disabling both...\n");
- } else if (mask & IFCAP_TSO4)
- ifp->if_capenable &= ~IFCAP_TSO4;
- }
-
- /* Enable/disable TXCSUM_IPV6/TSO6 */
- if (!(ifp->if_capenable & IFCAP_TXCSUM_IPV6)
- && !(ifp->if_capenable & IFCAP_TSO6)) {
- if (mask & IFCAP_TXCSUM_IPV6) {
- ifp->if_capenable |= IFCAP_TXCSUM_IPV6;
- if (vsi->flags & IXL_FLAGS_KEEP_TSO6) {
- vsi->flags &= ~IXL_FLAGS_KEEP_TSO6;
- ifp->if_capenable |= IFCAP_TSO6;
- }
- } else if (mask & IFCAP_TSO6) {
- ifp->if_capenable |= (IFCAP_TXCSUM_IPV6 | IFCAP_TSO6);
- vsi->flags &= ~IXL_FLAGS_KEEP_TSO6;
- device_printf(dev,
- "TSO6 requires txcsum6, enabling both...\n");
- }
- } else if((ifp->if_capenable & IFCAP_TXCSUM_IPV6)
- && !(ifp->if_capenable & IFCAP_TSO6)) {
- if (mask & IFCAP_TXCSUM_IPV6)
- ifp->if_capenable &= ~IFCAP_TXCSUM_IPV6;
- else if (mask & IFCAP_TSO6)
- ifp->if_capenable |= IFCAP_TSO6;
- } else if ((ifp->if_capenable & IFCAP_TXCSUM_IPV6)
- && (ifp->if_capenable & IFCAP_TSO6)) {
- if (mask & IFCAP_TXCSUM_IPV6) {
- vsi->flags |= IXL_FLAGS_KEEP_TSO6;
- ifp->if_capenable &= ~(IFCAP_TXCSUM_IPV6 | IFCAP_TSO6);
- device_printf(dev,
- "TSO6 requires txcsum6, disabling both...\n");
- } else if (mask & IFCAP_TSO6)
- ifp->if_capenable &= ~IFCAP_TSO6;
- }
-}
-
/*********************************************************************
- * Ioctl entry point
- *
- * ixl_ioctl is called when the user wants to configure the
- * interface.
+ * Ioctl mtu entry point
*
- * return 0 on success, positive on failure
+ *
+ * return 0 on success, EINVAL on failure
**********************************************************************/
-
static int
-ixl_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
+ixl_if_mtu_set(if_ctx_t ctx, uint32_t mtu)
{
- struct ixl_vsi *vsi = ifp->if_softc;
- struct ixl_pf *pf = vsi->back;
- struct ifreq *ifr = (struct ifreq *) data;
-#if defined(INET) || defined(INET6)
- struct ifaddr *ifa = (struct ifaddr *)data;
- bool avoid_reset = FALSE;
-#endif
- int error = 0;
-
- switch (command) {
-
- case SIOCSIFADDR:
-#ifdef INET
- if (ifa->ifa_addr->sa_family == AF_INET)
- avoid_reset = TRUE;
-#endif
-#ifdef INET6
- if (ifa->ifa_addr->sa_family == AF_INET6)
- avoid_reset = TRUE;
-#endif
-#if defined(INET) || defined(INET6)
- /*
- ** Calling init results in link renegotiation,
- ** so we avoid doing it when possible.
- */
- if (avoid_reset) {
- ifp->if_flags |= IFF_UP;
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
- ixl_init(pf);
-#ifdef INET
- if (!(ifp->if_flags & IFF_NOARP))
- arp_ifinit(ifp, ifa);
-#endif
- } else
- error = ether_ioctl(ifp, command, data);
- break;
-#endif
- case SIOCSIFMTU:
- IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
- if (ifr->ifr_mtu > IXL_MAX_FRAME -
- ETHER_HDR_LEN - ETHER_CRC_LEN - ETHER_VLAN_ENCAP_LEN) {
- error = EINVAL;
- } else {
- IXL_PF_LOCK(pf);
- ifp->if_mtu = ifr->ifr_mtu;
- vsi->max_frame_size =
- ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN
- + ETHER_VLAN_ENCAP_LEN;
- ixl_init_locked(pf);
- IXL_PF_UNLOCK(pf);
- }
- break;
- case SIOCSIFFLAGS:
- IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)");
- IXL_PF_LOCK(pf);
- if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- if ((ifp->if_flags ^ pf->if_flags) &
- (IFF_PROMISC | IFF_ALLMULTI)) {
- ixl_set_promisc(vsi);
- }
- } else
- ixl_init_locked(pf);
- } else
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ixl_stop(pf);
- pf->if_flags = ifp->if_flags;
- IXL_PF_UNLOCK(pf);
- break;
- case SIOCADDMULTI:
- IOCTL_DEBUGOUT("ioctl: SIOCADDMULTI");
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- IXL_PF_LOCK(pf);
- ixl_disable_intr(vsi);
- ixl_add_multi(vsi);
- ixl_enable_intr(vsi);
- IXL_PF_UNLOCK(pf);
- }
- break;
- case SIOCDELMULTI:
- IOCTL_DEBUGOUT("ioctl: SIOCDELMULTI");
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- IXL_PF_LOCK(pf);
- ixl_disable_intr(vsi);
- ixl_del_multi(vsi);
- ixl_enable_intr(vsi);
- IXL_PF_UNLOCK(pf);
- }
- break;
- case SIOCSIFMEDIA:
- case SIOCGIFMEDIA:
-#ifdef IFM_ETH_XTYPE
- case SIOCGIFXMEDIA:
-#endif
- IOCTL_DEBUGOUT("ioctl: SIOCxIFMEDIA (Get/Set Interface Media)");
- error = ifmedia_ioctl(ifp, ifr, &vsi->media, command);
- break;
- case SIOCSIFCAP:
- {
- int mask = ifr->ifr_reqcap ^ ifp->if_capenable;
- IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)");
-
- ixl_cap_txcsum_tso(vsi, ifp, mask);
-
- if (mask & IFCAP_RXCSUM)
- ifp->if_capenable ^= IFCAP_RXCSUM;
- if (mask & IFCAP_RXCSUM_IPV6)
- ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
- if (mask & IFCAP_LRO)
- ifp->if_capenable ^= IFCAP_LRO;
- if (mask & IFCAP_VLAN_HWTAGGING)
- ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
- if (mask & IFCAP_VLAN_HWFILTER)
- ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
- if (mask & IFCAP_VLAN_HWTSO)
- ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- IXL_PF_LOCK(pf);
- ixl_init_locked(pf);
- IXL_PF_UNLOCK(pf);
- }
- VLAN_CAPABILITIES(ifp);
-
- break;
- }
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
- default:
- IOCTL_DEBUGOUT("ioctl: UNKNOWN (0x%X)\n", (int)command);
- error = ether_ioctl(ifp, command, data);
- break;
- }
+ IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
+ if (mtu > IXL_MAX_FRAME - ETHER_HDR_LEN - ETHER_CRC_LEN -
+ ETHER_VLAN_ENCAP_LEN)
+ return (EINVAL);
- return (error);
+ vsi->max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN +
+ ETHER_VLAN_ENCAP_LEN;
+ return (0);
}
-
/*********************************************************************
* Init entry point
*
@@ -1120,22 +898,21 @@
**********************************************************************/
static void
-ixl_init_locked(struct ixl_pf *pf)
+ixl_if_init(if_ctx_t ctx)
{
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct ixl_pf *pf = vsi->back;
+ device_t dev = iflib_get_dev(ctx);
+
struct i40e_hw *hw = &pf->hw;
- struct ixl_vsi *vsi = &pf->vsi;
- struct ifnet *ifp = vsi->ifp;
- device_t dev = pf->dev;
struct i40e_filter_control_settings filter;
u8 tmpaddr[ETHER_ADDR_LEN];
int ret;
- mtx_assert(&pf->pf_mtx, MA_OWNED);
INIT_DEBUGOUT("ixl_init: begin");
- ixl_stop(pf);
/* Get the latest mac address... User might use a LAA */
- bcopy(IF_LLADDR(vsi->ifp), tmpaddr,
+ bcopy(IF_LLADDR(iflib_get_ifp(ctx)), tmpaddr,
I40E_ETH_LENGTH_OF_ADDRESS);
if (!cmp_etheraddr(hw->mac.addr, tmpaddr) &&
(i40e_validate_mac_addr(tmpaddr) == I40E_SUCCESS)) {
@@ -1154,15 +931,6 @@
}
}
- /* Set the various hardware offload abilities */
- ifp->if_hwassist = 0;
- if (ifp->if_capenable & IFCAP_TSO)
- ifp->if_hwassist |= CSUM_TSO;
- if (ifp->if_capenable & IFCAP_TXCSUM)
- ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
- if (ifp->if_capenable & IFCAP_TXCSUM_IPV6)
- ifp->if_hwassist |= (CSUM_TCP_IPV6 | CSUM_UDP_IPV6);
-
/* Set up the device filtering */
bzero(&filter, sizeof(filter));
filter.enable_ethtype = TRUE;
@@ -1191,9 +959,6 @@
/* Setup vlan's if needed */
ixl_setup_vlan_filters(vsi);
- /* Start the local timer */
- callout_reset(&pf->timer, hz, ixl_local_timer, pf);
-
/* Set up MSI/X routing and the ITR settings */
if (ixl_enable_msix) {
ixl_configure_msix(pf);
@@ -1211,114 +976,45 @@
int aq_error = i40e_aq_set_mac_config(hw, vsi->max_frame_size,
TRUE, 0, NULL);
if (aq_error)
- device_printf(vsi->dev,
+ device_printf(dev,
"aq_set_mac_config in init error, code %d\n",
aq_error);
-
- /* And now turn on interrupts */
- ixl_enable_intr(vsi);
-
- /* Now inform the stack we're ready */
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
- return;
-}
-
-static void
-ixl_init(void *arg)
-{
- struct ixl_pf *pf = arg;
-
- IXL_PF_LOCK(pf);
- ixl_init_locked(pf);
- IXL_PF_UNLOCK(pf);
- return;
-}
-
-/*
-**
-** MSIX Interrupt Handlers and Tasklets
-**
-*/
-static void
-ixl_handle_que(void *context, int pending)
-{
- struct ixl_queue *que = context;
- struct ixl_vsi *vsi = que->vsi;
- struct i40e_hw *hw = vsi->hw;
- struct tx_ring *txr = &que->txr;
- struct ifnet *ifp = vsi->ifp;
- bool more;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- more = ixl_rxeof(que, IXL_RX_LIMIT);
- IXL_TX_LOCK(txr);
- ixl_txeof(que);
- if (!drbr_empty(ifp, txr->br))
- ixl_mq_start_locked(ifp, txr);
- IXL_TX_UNLOCK(txr);
- if (more) {
- taskqueue_enqueue(que->tq, &que->task);
- return;
- }
- }
-
- /* Reenable this interrupt - hmmm */
- ixl_enable_queue(hw, que->me);
- return;
}
-
/*********************************************************************
*
* Legacy Interrupt Service routine
*
**********************************************************************/
-void
+int
ixl_intr(void *arg)
{
struct ixl_pf *pf = arg;
struct i40e_hw *hw = &pf->hw;
struct ixl_vsi *vsi = &pf->vsi;
struct ixl_queue *que = vsi->queues;
- struct ifnet *ifp = vsi->ifp;
- struct tx_ring *txr = &que->txr;
- u32 reg, icr0, mask;
- bool more_tx, more_rx;
-
+ u32 reg, icr0, mask;
+
++que->irqs;
- /* Protect against spurious interrupts */
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return;
-
icr0 = rd32(hw, I40E_PFINT_ICR0);
reg = rd32(hw, I40E_PFINT_DYN_CTL0);
reg = reg | I40E_PFINT_DYN_CTL0_CLEARPBA_MASK;
wr32(hw, I40E_PFINT_DYN_CTL0, reg);
- mask = rd32(hw, I40E_PFINT_ICR0_ENA);
+ mask = rd32(hw, I40E_PFINT_ICR0_ENA);
#ifdef PCI_IOV
if (icr0 & I40E_PFINT_ICR0_VFLR_MASK)
- taskqueue_enqueue(pf->tq, &pf->vflr_task);
+ iflib_iov_intr_deferred(vsi->ctx);
#endif
if (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK) {
- taskqueue_enqueue(pf->tq, &pf->adminq);
- return;
+ iflib_admin_intr_deferred(vsi->ctx);
+ return (FILTER_HANDLED);
}
- more_rx = ixl_rxeof(que, IXL_RX_LIMIT);
-
- IXL_TX_LOCK(txr);
- more_tx = ixl_txeof(que);
- if (!drbr_empty(vsi->ifp, txr->br))
- more_tx = 1;
- IXL_TX_UNLOCK(txr);
-
/* re-enable other interrupt causes */
wr32(hw, I40E_PFINT_ICR0_ENA, mask);
@@ -1331,10 +1027,7 @@
reg |= I40E_QINT_TQCTL_CAUSE_ENA_MASK;
reg &= ~I40E_PFINT_ICR0_INTEVENT_MASK;
wr32(hw, I40E_QINT_TQCTL(0), reg);
-
- ixl_enable_legacy(hw);
-
- return;
+ return (FILTER_SCHEDULE_THREAD);
}
@@ -1343,43 +1036,15 @@
* MSIX VSI Interrupt Service routine
*
**********************************************************************/
-void
+int
ixl_msix_que(void *arg)
{
struct ixl_queue *que = arg;
- struct ixl_vsi *vsi = que->vsi;
- struct i40e_hw *hw = vsi->hw;
- struct tx_ring *txr = &que->txr;
- bool more_tx, more_rx;
-
- /* Protect against spurious interrupts */
- if (!(vsi->ifp->if_drv_flags & IFF_DRV_RUNNING))
- return;
-
- ++que->irqs;
-
- more_rx = ixl_rxeof(que, IXL_RX_LIMIT);
-
- IXL_TX_LOCK(txr);
- more_tx = ixl_txeof(que);
- /*
- ** Make certain that if the stack
- ** has anything queued the task gets
- ** scheduled to handle it.
- */
- if (!drbr_empty(vsi->ifp, txr->br))
- more_tx = 1;
- IXL_TX_UNLOCK(txr);
ixl_set_queue_rx_itr(que);
ixl_set_queue_tx_itr(que);
- if (more_tx || more_rx)
- taskqueue_enqueue(que->tq, &que->task);
- else
- ixl_enable_queue(hw, que->me);
-
- return;
+ return (FILTER_SCHEDULE_THREAD);
}
@@ -1388,7 +1053,7 @@
* MSIX Admin Queue Interrupt Service routine
*
**********************************************************************/
-static void
+int
ixl_msix_adminq(void *arg)
{
struct ixl_pf *pf = arg;
@@ -1412,7 +1077,7 @@
#ifdef PCI_IOV
if (reg & I40E_PFINT_ICR0_VFLR_MASK) {
mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK;
- taskqueue_enqueue(pf->tq, &pf->vflr_task);
+ iflib_iov_intr_deferred(pf->vsi.ctx);
}
#endif
@@ -1420,37 +1085,93 @@
reg = reg | I40E_PFINT_DYN_CTL0_CLEARPBA_MASK;
wr32(hw, I40E_PFINT_DYN_CTL0, reg);
- taskqueue_enqueue(pf->tq, &pf->adminq);
- return;
+ iflib_admin_intr_deferred(pf->vsi.ctx);
+ return (FILTER_HANDLED);
}
/*********************************************************************
*
- * Media Ioctl callback
- *
- * This routine is called whenever the user queries the status of
- * the interface using ifconfig.
+ * Setup MSIX Interrupt resources and handlers for the VSI
*
**********************************************************************/
-static void
-ixl_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
+int
+ixl_if_msix_intr_assign(if_ctx_t ctx, int msix)
{
- struct ixl_vsi *vsi = ifp->if_softc;
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
struct ixl_pf *pf = vsi->back;
- struct i40e_hw *hw = &pf->hw;
+ struct ixl_queue *que = vsi->queues;
+ int err, i, rid, vector = 0;
+ char buf[16];
- INIT_DEBUGOUT("ixl_media_status: begin");
- IXL_PF_LOCK(pf);
+ /* Admin Que is vector 0*/
+ rid = vector + 1;
- hw->phy.get_link_info = TRUE;
- i40e_get_link_status(hw, &pf->link_up);
- ixl_update_link_status(pf);
+ err = iflib_irq_alloc_generic(ctx, &vsi->irq, rid, IFLIB_INTR_ADMIN,
+ ixl_msix_adminq, pf, 0, "aq");
+ if (err) {
+ iflib_irq_free(ctx, &vsi->irq);
+ device_printf(iflib_get_dev(ctx), "Failed to register Admin que handler");
+ return (err);
+ }
+ pf->admvec = vector;
+ ++vector;
+ iflib_softirq_alloc_generic(ctx, rid, IFLIB_INTR_IOV, pf, 0, "ixl_iov");
+
+ /* Now set up the stations */
+ for (i = 0; i < vsi->num_queues; i++, vector++, que++) {
+ rid = vector + 1;
+
+ snprintf(buf, sizeof(buf), "rxq%d", i);
+ err = iflib_irq_alloc_generic(ctx, &que->que_irq, rid, IFLIB_INTR_RX,
+ ixl_msix_que, que, que->me, buf);
+ if (err) {
+ device_printf(iflib_get_dev(ctx), "Failed to allocate q int %d err: %d", i, err);
+ vsi->num_queues = i + 1;
+ goto fail;
+ }
+ que->msix = vector;
+ }
+
+ for (i = 0, que = vsi->queues; i < vsi->num_queues; i++, que++) {
+ snprintf(buf, sizeof(buf), "txq%d", i);
+ rid = que->msix + 1;
+ iflib_softirq_alloc_generic(ctx, rid, IFLIB_INTR_TX, que, que->me, buf);
+ }
+
+ return (0);
+fail:
+ iflib_irq_free(ctx, &vsi->irq);
+ que = vsi->queues;
+ for (int i = 0; i < vsi->num_queues; i++, que++)
+ iflib_irq_free(ctx, &que->que_irq);
+ return (err);
+}
+
+/*********************************************************************
+ *
+ * Media Ioctl callback
+ *
+ * This routine is called whenever the user queries the status of
+ * the interface using ifconfig.
+ *
+ **********************************************************************/
+static void
+ixl_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr)
+{
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct ixl_pf *pf = (struct ixl_pf *)vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+
+ INIT_DEBUGOUT("ixl_media_status: begin");
+
+ hw->phy.get_link_info = TRUE;
+ i40e_get_link_status(hw, &pf->link_up);
+ ixl_update_link_status(pf);
ifmr->ifm_status = IFM_AVALID;
ifmr->ifm_active = IFM_ETHER;
if (!pf->link_up) {
- IXL_PF_UNLOCK(pf);
return;
}
@@ -1550,33 +1271,6 @@
if (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX)
ifmr->ifm_active |= IFM_ETH_RXPAUSE;
- IXL_PF_UNLOCK(pf);
-
- return;
-}
-
-/*********************************************************************
- *
- * Media Ioctl callback
- *
- * This routine is called when the user changes speed/duplex using
- * media/mediopt option with ifconfig.
- *
- **********************************************************************/
-static int
-ixl_media_change(struct ifnet * ifp)
-{
- struct ixl_vsi *vsi = ifp->if_softc;
- struct ifmedia *ifm = &vsi->media;
-
- INIT_DEBUGOUT("ixl_media_change: begin");
-
- if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
- return (EINVAL);
-
- if_printf(ifp, "Media change is currently not supported.\n");
-
- return (ENODEV);
}
@@ -1588,9 +1282,10 @@
** implementation this is only available for TCP connections
*/
void
-ixl_atr(struct ixl_queue *que, struct tcphdr *th, int etype)
+ixl_atr(struct ixl_queue *que, int hflags, int etype)
{
struct ixl_vsi *vsi = que->vsi;
+ if_shared_ctx_t sctx = ixl_sctx;
struct tx_ring *txr = &que->txr;
struct i40e_filter_program_desc *FDIR;
u32 ptype, dtype;
@@ -1604,7 +1299,7 @@
** or at the selected sample rate
*/
txr->atr_count++;
- if (((th->th_flags & (TH_FIN | TH_SYN)) == 0) &&
+ if (((hflags & (TH_FIN | TH_SYN)) == 0) &&
(txr->atr_count < txr->atr_rate))
return;
txr->atr_count = 0;
@@ -1612,7 +1307,7 @@
/* Get a descriptor to use */
idx = txr->next_avail;
FDIR = (struct i40e_filter_program_desc *) &txr->base[idx];
- if (++idx == que->num_desc)
+ if (++idx == sctx->isc_ntxd)
idx = 0;
txr->avail--;
txr->next_avail = idx;
@@ -1634,7 +1329,7 @@
** We use the TCP TH_FIN as a trigger to remove
** the filter, otherwise its an update.
*/
- dtype |= (th->th_flags & TH_FIN) ?
+ dtype |= (hflags & TH_FIN) ?
(I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE <<
I40E_TXD_FLTR_QW1_PCMD_SHIFT) :
(I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE <<
@@ -1648,44 +1343,31 @@
FDIR->qindex_flex_ptype_vsi = htole32(ptype);
FDIR->dtype_cmd_cntindex = htole32(dtype);
- return;
}
#endif
-
-static void
-ixl_set_promisc(struct ixl_vsi *vsi)
+static int
+ixl_if_promisc_set(if_ctx_t ctx, int flags)
{
- struct ifnet *ifp = vsi->ifp;
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct ifnet *ifp = iflib_get_ifp(ctx);
struct i40e_hw *hw = vsi->hw;
- int err, mcnt = 0;
+ int err;
bool uni = FALSE, multi = FALSE;
- if (ifp->if_flags & IFF_ALLMULTI)
- multi = TRUE;
- else { /* Need to count the multicast addresses */
- struct ifmultiaddr *ifma;
- if_maddr_rlock(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (mcnt == MAX_MULTICAST_ADDR)
- break;
- mcnt++;
- }
- if_maddr_runlock(ifp);
- }
-
- if (mcnt >= MAX_MULTICAST_ADDR)
- multi = TRUE;
- if (ifp->if_flags & IFF_PROMISC)
+ if (flags & IFF_ALLMULTI ||
+ if_multiaddr_count(ifp, MAX_MULTICAST_ADDR) == MAX_MULTICAST_ADDR)
+ multi = TRUE;
+ if (flags & IFF_PROMISC)
uni = TRUE;
err = i40e_aq_set_vsi_unicast_promiscuous(hw,
vsi->seid, uni, NULL);
+ if (err)
+ return (err);
err = i40e_aq_set_vsi_multicast_promiscuous(hw,
vsi->seid, multi, NULL);
- return;
+ return (err);
}
/*********************************************************************
@@ -1695,92 +1377,64 @@
*
*********************************************************************/
static void
-ixl_add_multi(struct ixl_vsi *vsi)
+ixl_del_multi(struct ixl_vsi *vsi)
{
- struct ifmultiaddr *ifma;
- struct ifnet *ifp = vsi->ifp;
- struct i40e_hw *hw = vsi->hw;
- int mcnt = 0, flags;
+ struct ixl_mac_filter *f;
+ int mcnt = 0;
- IOCTL_DEBUGOUT("ixl_add_multi: begin");
+ IOCTL_DEBUGOUT("ixl_del_multi: begin");
- if_maddr_rlock(ifp);
- /*
- ** First just get a count, to decide if we
- ** we simply use multicast promiscuous.
- */
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- mcnt++;
+ SLIST_FOREACH(f, &vsi->ftl, next) {
+ if ((f->flags & (IXL_FILTER_USED|IXL_FILTER_MC)) == (IXL_FILTER_USED|IXL_FILTER_MC)){
+ f->flags |= IXL_FILTER_DEL;
+ mcnt++;
+ }
}
- if_maddr_runlock(ifp);
-
- if (__predict_false(mcnt >= MAX_MULTICAST_ADDR)) {
- /* delete existing MC filters */
+ if (mcnt > 0)
ixl_del_hw_filters(vsi, mcnt);
- i40e_aq_set_vsi_multicast_promiscuous(hw,
- vsi->seid, TRUE, NULL);
- return;
- }
+}
- mcnt = 0;
- if_maddr_rlock(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- ixl_add_mc_filter(vsi,
- (u8*)LLADDR((struct sockaddr_dl *) ifma->ifma_addr));
- mcnt++;
- }
- if_maddr_runlock(ifp);
- if (mcnt > 0) {
- flags = (IXL_FILTER_ADD | IXL_FILTER_USED | IXL_FILTER_MC);
- ixl_add_hw_filters(vsi, flags, mcnt);
- }
+static int
+ixl_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int count __unused)
+{
+ struct ixl_vsi *vsi = arg;
- IOCTL_DEBUGOUT("ixl_add_multi: end");
- return;
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ return (0);
+ ixl_add_mc_filter(vsi,
+ (u8*)LLADDR((struct sockaddr_dl *) ifma->ifma_addr));
+ return (1);
}
static void
-ixl_del_multi(struct ixl_vsi *vsi)
+ixl_if_multi_set(if_ctx_t ctx)
{
- struct ifnet *ifp = vsi->ifp;
- struct ifmultiaddr *ifma;
- struct ixl_mac_filter *f;
- int mcnt = 0;
- bool match = FALSE;
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct i40e_hw *hw = vsi->hw;
+ int mcnt = 0, flags;
- IOCTL_DEBUGOUT("ixl_del_multi: begin");
+ IOCTL_DEBUGOUT("ixl_if_multi_set: begin");
- /* Search for removed multicast addresses */
- if_maddr_rlock(ifp);
- SLIST_FOREACH(f, &vsi->ftl, next) {
- if ((f->flags & IXL_FILTER_USED) && (f->flags & IXL_FILTER_MC)) {
- match = FALSE;
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- u8 *mc_addr = (u8 *)LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
- if (cmp_etheraddr(f->macaddr, mc_addr)) {
- match = TRUE;
- break;
- }
- }
- if (match == FALSE) {
- f->flags |= IXL_FILTER_DEL;
- mcnt++;
- }
- }
+ mcnt = if_multiaddr_count(iflib_get_ifp(ctx), MAX_MULTICAST_ADDR);
+ /* delete existing MC filters */
+ ixl_del_multi(vsi);
+
+ if (__predict_false(mcnt == MAX_MULTICAST_ADDR)) {
+ i40e_aq_set_vsi_multicast_promiscuous(hw,
+ vsi->seid, TRUE, NULL);
+ return;
+ }
+ /* (re-)install filters for all mcast addresses */
+ mcnt = if_multi_apply(iflib_get_ifp(ctx), ixl_mc_filter_apply, vsi);
+
+ if (mcnt > 0) {
+ flags = (IXL_FILTER_ADD | IXL_FILTER_USED | IXL_FILTER_MC);
+ ixl_add_hw_filters(vsi, flags, mcnt);
}
- if_maddr_runlock(ifp);
- if (mcnt > 0)
- ixl_del_hw_filters(vsi, mcnt);
+ IOCTL_DEBUGOUT("ixl_if_multi_set: end");
}
-
/*********************************************************************
* Timer routine
*
@@ -1790,68 +1444,32 @@
**********************************************************************/
static void
-ixl_local_timer(void *arg)
+ixl_if_timer(if_ctx_t ctx, uint16_t qid)
{
- struct ixl_pf *pf = arg;
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct ixl_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
- struct ixl_vsi *vsi = &pf->vsi;
- struct ixl_queue *que = vsi->queues;
- device_t dev = pf->dev;
- int hung = 0;
+ struct ixl_queue *que = &vsi->queues[qid];
u32 mask;
- mtx_assert(&pf->pf_mtx, MA_OWNED);
-
- /* Fire off the adminq task */
- taskqueue_enqueue(pf->tq, &pf->adminq);
-
- /* Update stats */
- ixl_update_stats_counters(pf);
-
/*
** Check status of the queues
*/
mask = (I40E_PFINT_DYN_CTLN_INTENA_MASK |
I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK);
- for (int i = 0; i < vsi->num_queues; i++,que++) {
- /* Any queues with outstanding work get a sw irq */
- if (que->busy)
- wr32(hw, I40E_PFINT_DYN_CTLN(que->me), mask);
- /*
- ** Each time txeof runs without cleaning, but there
- ** are uncleaned descriptors it increments busy. If
- ** we get to 5 we declare it hung.
- */
- if (que->busy == IXL_QUEUE_HUNG) {
- ++hung;
- /* Mark the queue as inactive */
- vsi->active_queues &= ~((u64)1 << que->me);
- continue;
- } else {
- /* Check if we've come back from hung */
- if ((vsi->active_queues & ((u64)1 << que->me)) == 0)
- vsi->active_queues |= ((u64)1 << que->me);
- }
- if (que->busy >= IXL_MAX_TX_BUSY) {
-#ifdef IXL_DEBUG
- device_printf(dev,"Warning queue %d "
- "appears to be hung!\n", i);
-#endif
- que->busy = IXL_QUEUE_HUNG;
- ++hung;
- }
- }
- /* Only reinit if all queues show hung */
- if (hung == vsi->num_queues)
- goto hung;
+ /* Any queues with outstanding work get a sw irq */
+ if (que->busy)
+ wr32(hw, I40E_PFINT_DYN_CTLN(que->me), mask);
- callout_reset(&pf->timer, hz, ixl_local_timer, pf);
- return;
+ if (qid != 0)
+ return;
+
+ /* Fire off the adminq task */
+ iflib_admin_intr_deferred(ctx);
-hung:
- device_printf(dev, "Local Timer: HANG DETECT - Resetting!!\n");
- ixl_init_locked(pf);
+ /* Update stats */
+ ixl_update_stats_counters(pf);
}
/*
@@ -1864,8 +1482,7 @@
{
struct ixl_vsi *vsi = &pf->vsi;
struct i40e_hw *hw = &pf->hw;
- struct ifnet *ifp = vsi->ifp;
- device_t dev = pf->dev;
+ device_t dev = iflib_get_dev(vsi->ctx);
if (pf->link_up){
if (vsi->link_active == FALSE) {
@@ -1883,24 +1500,20 @@
** partition is not at least 10GB
*/
if (hw->func_caps.npar_enable &&
- (hw->phy.link_info.link_speed ==
- I40E_LINK_SPEED_1GB ||
- hw->phy.link_info.link_speed ==
- I40E_LINK_SPEED_100MB))
- device_printf(dev, "The partition detected"
- "link speed that is less than 10Gbps\n");
- if_link_state_change(ifp, LINK_STATE_UP);
+ (hw->phy.link_info.link_speed == I40E_LINK_SPEED_1GB ||
+ hw->phy.link_info.link_speed == I40E_LINK_SPEED_100MB))
+ device_printf(dev, "The partition detected link"
+ "speed that is less than 10Gbps\n");
+ iflib_link_state_change(vsi->ctx, LINK_STATE_UP);
}
} else { /* Link down */
if (vsi->link_active == TRUE) {
if (bootverbose)
device_printf(dev,"Link is Down\n");
- if_link_state_change(ifp, LINK_STATE_DOWN);
+ iflib_link_state_change(vsi->ctx, LINK_STATE_DOWN);
vsi->link_active = FALSE;
}
}
-
- return;
}
/*********************************************************************
@@ -1911,338 +1524,20 @@
**********************************************************************/
static void
-ixl_stop(struct ixl_pf *pf)
+ixl_if_stop(if_ctx_t ctx)
{
- struct ixl_vsi *vsi = &pf->vsi;
- struct ifnet *ifp = vsi->ifp;
-
- mtx_assert(&pf->pf_mtx, MA_OWNED);
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
- INIT_DEBUGOUT("ixl_stop: begin\n");
+ INIT_DEBUGOUT("ixl_if_stop: begin\n");
+#ifdef notyet
if (pf->num_vfs == 0)
ixl_disable_intr(vsi);
else
ixl_disable_rings_intr(vsi);
- ixl_disable_rings(vsi);
-
- /* Tell the stack that the interface is no longer active */
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-
- /* Stop the local timer */
- callout_stop(&pf->timer);
-
- return;
-}
-
-
-/*********************************************************************
- *
- * Setup MSIX Interrupt resources and handlers for the VSI
- *
- **********************************************************************/
-static int
-ixl_assign_vsi_legacy(struct ixl_pf *pf)
-{
- device_t dev = pf->dev;
- struct ixl_vsi *vsi = &pf->vsi;
- struct ixl_queue *que = vsi->queues;
- int error, rid = 0;
-
- if (pf->msix == 1)
- rid = 1;
- pf->res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &rid, RF_SHAREABLE | RF_ACTIVE);
- if (pf->res == NULL) {
- device_printf(dev,"Unable to allocate"
- " bus resource: vsi legacy/msi interrupt\n");
- return (ENXIO);
- }
-
- /* Set the handler function */
- error = bus_setup_intr(dev, pf->res,
- INTR_TYPE_NET | INTR_MPSAFE, NULL,
- ixl_intr, pf, &pf->tag);
- if (error) {
- pf->res = NULL;
- device_printf(dev, "Failed to register legacy/msi handler");
- return (error);
- }
- bus_describe_intr(dev, pf->res, pf->tag, "irq0");
- TASK_INIT(&que->tx_task, 0, ixl_deferred_mq_start, que);
- TASK_INIT(&que->task, 0, ixl_handle_que, que);
- que->tq = taskqueue_create_fast("ixl_que", M_NOWAIT,
- taskqueue_thread_enqueue, &que->tq);
- taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que",
- device_get_nameunit(dev));
- TASK_INIT(&pf->adminq, 0, ixl_do_adminq, pf);
-
-#ifdef PCI_IOV
- TASK_INIT(&pf->vflr_task, 0, ixl_handle_vflr, pf);
-#endif
-
- pf->tq = taskqueue_create_fast("ixl_adm", M_NOWAIT,
- taskqueue_thread_enqueue, &pf->tq);
- taskqueue_start_threads(&pf->tq, 1, PI_NET, "%s adminq",
- device_get_nameunit(dev));
-
- return (0);
-}
-
-static void
-ixl_init_taskqueues(struct ixl_pf *pf)
-{
- struct ixl_vsi *vsi = &pf->vsi;
- struct ixl_queue *que = vsi->queues;
- device_t dev = pf->dev;
-
- /* Tasklet for Admin Queue */
- TASK_INIT(&pf->adminq, 0, ixl_do_adminq, pf);
-#ifdef PCI_IOV
- /* VFLR Tasklet */
- TASK_INIT(&pf->vflr_task, 0, ixl_handle_vflr, pf);
-#endif
-
- /* Create and start PF taskqueue */
- pf->tq = taskqueue_create_fast("ixl_adm", M_NOWAIT,
- taskqueue_thread_enqueue, &pf->tq);
- taskqueue_start_threads(&pf->tq, 1, PI_NET, "%s adminq",
- device_get_nameunit(dev));
-
- /* Create queue tasks and start queue taskqueues */
- for (int i = 0; i < vsi->num_queues; i++, que++) {
- TASK_INIT(&que->tx_task, 0, ixl_deferred_mq_start, que);
- TASK_INIT(&que->task, 0, ixl_handle_que, que);
- que->tq = taskqueue_create_fast("ixl_que", M_NOWAIT,
- taskqueue_thread_enqueue, &que->tq);
-#ifdef RSS
- CPU_SETOF(cpu_id, &cpu_mask);
- taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET,
- &cpu_mask, "%s (bucket %d)",
- device_get_nameunit(dev), cpu_id);
-#else
- taskqueue_start_threads(&que->tq, 1, PI_NET,
- "%s (que %d)", device_get_nameunit(dev), que->me);
-#endif
- }
-
-}
-
-static void
-ixl_free_taskqueues(struct ixl_pf *pf)
-{
- struct ixl_vsi *vsi = &pf->vsi;
- struct ixl_queue *que = vsi->queues;
-
- if (pf->tq)
- taskqueue_free(pf->tq);
- for (int i = 0; i < vsi->num_queues; i++, que++) {
- if (que->tq)
- taskqueue_free(que->tq);
- }
-}
-
-/*********************************************************************
- *
- * Setup MSIX Interrupt resources and handlers for the VSI
- *
- **********************************************************************/
-static int
-ixl_assign_vsi_msix(struct ixl_pf *pf)
-{
- device_t dev = pf->dev;
- struct ixl_vsi *vsi = &pf->vsi;
- struct ixl_queue *que = vsi->queues;
- struct tx_ring *txr;
- int error, rid, vector = 0;
-#ifdef RSS
- cpuset_t cpu_mask;
-#endif
-
- /* Admin Que is vector 0*/
- rid = vector + 1;
- pf->res = bus_alloc_resource_any(dev,
- SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
- if (!pf->res) {
- device_printf(dev,"Unable to allocate"
- " bus resource: Adminq interrupt [%d]\n", rid);
- return (ENXIO);
- }
- /* Set the adminq vector and handler */
- error = bus_setup_intr(dev, pf->res,
- INTR_TYPE_NET | INTR_MPSAFE, NULL,
- ixl_msix_adminq, pf, &pf->tag);
- if (error) {
- pf->res = NULL;
- device_printf(dev, "Failed to register Admin que handler");
- return (error);
- }
- bus_describe_intr(dev, pf->res, pf->tag, "aq");
- pf->admvec = vector;
- ++vector;
-
- /* Now set up the stations */
- for (int i = 0; i < vsi->num_queues; i++, vector++, que++) {
- int cpu_id = i;
- rid = vector + 1;
- txr = &que->txr;
- que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
- if (que->res == NULL) {
- device_printf(dev,"Unable to allocate"
- " bus resource: que interrupt [%d]\n", vector);
- return (ENXIO);
- }
- /* Set the handler function */
- error = bus_setup_intr(dev, que->res,
- INTR_TYPE_NET | INTR_MPSAFE, NULL,
- ixl_msix_que, que, &que->tag);
- if (error) {
- que->res = NULL;
- device_printf(dev, "Failed to register que handler");
- return (error);
- }
- bus_describe_intr(dev, que->res, que->tag, "q%d", i);
- /* Bind the vector to a CPU */
-#ifdef RSS
- cpu_id = rss_getcpu(i % rss_getnumbuckets());
-#endif
- bus_bind_intr(dev, que->res, cpu_id);
- que->msix = vector;
- }
-
- return (0);
-}
-
-
-/*
- * Allocate MSI/X vectors
- */
-static int
-ixl_init_msix(struct ixl_pf *pf)
-{
- device_t dev = pf->dev;
- int rid, want, vectors, queues, available;
-
- /* Override by tuneable */
- if (ixl_enable_msix == 0)
- goto msi;
-
- /*
- ** When used in a virtualized environment
- ** PCI BUSMASTER capability may not be set
- ** so explicity set it here and rewrite
- ** the ENABLE in the MSIX control register
- ** at this point to cause the host to
- ** successfully initialize us.
- */
- {
- u16 pci_cmd_word;
- int msix_ctrl;
- pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2);
- pci_cmd_word |= PCIM_CMD_BUSMASTEREN;
- pci_write_config(dev, PCIR_COMMAND, pci_cmd_word, 2);
- pci_find_cap(dev, PCIY_MSIX, &rid);
- rid += PCIR_MSIX_CTRL;
- msix_ctrl = pci_read_config(dev, rid, 2);
- msix_ctrl |= PCIM_MSIXCTRL_MSIX_ENABLE;
- pci_write_config(dev, rid, msix_ctrl, 2);
- }
-
- /* First try MSI/X */
- rid = PCIR_BAR(IXL_BAR);
- pf->msix_mem = bus_alloc_resource_any(dev,
- SYS_RES_MEMORY, &rid, RF_ACTIVE);
- if (!pf->msix_mem) {
- /* May not be enabled */
- device_printf(pf->dev,
- "Unable to map MSIX table \n");
- goto msi;
- }
-
- available = pci_msix_count(dev);
- if (available == 0) { /* system has msix disabled */
- bus_release_resource(dev, SYS_RES_MEMORY,
- rid, pf->msix_mem);
- pf->msix_mem = NULL;
- goto msi;
- }
-
- /* Figure out a reasonable auto config value */
- queues = (mp_ncpus > (available - 1)) ? (available - 1) : mp_ncpus;
-
- /* Override with hardcoded value if it's less than autoconfig count */
- if ((ixl_max_queues != 0) && (ixl_max_queues <= queues))
- queues = ixl_max_queues;
- else if ((ixl_max_queues != 0) && (ixl_max_queues > queues))
- device_printf(dev, "ixl_max_queues > # of cpus, using "
- "autoconfig amount...\n");
- /* Or limit maximum auto-configured queues to 8 */
- else if ((ixl_max_queues == 0) && (queues > 8))
- queues = 8;
-
-#ifdef RSS
- /* If we're doing RSS, clamp at the number of RSS buckets */
- if (queues > rss_getnumbuckets())
- queues = rss_getnumbuckets();
-#endif
-
- /*
- ** Want one vector (RX/TX pair) per queue
- ** plus an additional for the admin queue.
- */
- want = queues + 1;
- if (want <= available) /* Have enough */
- vectors = want;
- else {
- device_printf(pf->dev,
- "MSIX Configuration Problem, "
- "%d vectors available but %d wanted!\n",
- available, want);
- return (0); /* Will go to Legacy setup */
- }
-
- if (pci_alloc_msix(dev, &vectors) == 0) {
- device_printf(pf->dev,
- "Using MSIX interrupts with %d vectors\n", vectors);
- pf->msix = vectors;
- pf->vsi.num_queues = queues;
-#ifdef RSS
- /*
- * If we're doing RSS, the number of queues needs to
- * match the number of RSS buckets that are configured.
- *
- * + If there's more queues than RSS buckets, we'll end
- * up with queues that get no traffic.
- *
- * + If there's more RSS buckets than queues, we'll end
- * up having multiple RSS buckets map to the same queue,
- * so there'll be some contention.
- */
- if (queues != rss_getnumbuckets()) {
- device_printf(dev,
- "%s: queues (%d) != RSS buckets (%d)"
- "; performance will be impacted.\n",
- __func__, queues, rss_getnumbuckets());
- }
#endif
- return (vectors);
- }
-msi:
- vectors = pci_msi_count(dev);
- pf->vsi.num_queues = 1;
- pf->msix = 1;
- ixl_max_queues = 1;
- ixl_enable_msix = 0;
- if (vectors == 1 && pci_alloc_msi(dev, &vectors) == 0)
- device_printf(pf->dev,"Using an MSI interrupt\n");
- else {
- pf->msix = 0;
- device_printf(pf->dev,"Using a Legacy interrupt\n");
- }
- return (vectors);
+ ixl_disable_rings(vsi);
}
-
/*
* Plumb MSI/X vectors
*/
@@ -2307,11 +1602,9 @@
struct i40e_hw *hw = &pf->hw;
u32 reg;
-
wr32(hw, I40E_PFINT_ITR0(0), 0);
wr32(hw, I40E_PFINT_ITR0(1), 0);
-
/* Setup "other" causes */
reg = I40E_PFINT_ICR0_ENA_ECC_ERR_MASK
| I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK
@@ -2395,7 +1688,7 @@
ixl_allocate_pci_resources(struct ixl_pf *pf)
{
int rid;
- device_t dev = pf->dev;
+ device_t dev = iflib_get_dev(pf->vsi.ctx);
rid = PCIR_BAR(0);
pf->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
@@ -2416,12 +1709,6 @@
pf->hw.back = &pf->osdep;
- /*
- ** Now setup MSI or MSI/X, should
- ** return us the number of supported
- ** vectors. (Will be 1 for MSI)
- */
- pf->msix = ixl_init_msix(pf);
return (0);
}
@@ -2430,54 +1717,25 @@
{
struct ixl_vsi *vsi = &pf->vsi;
struct ixl_queue *que = vsi->queues;
- device_t dev = pf->dev;
- int rid, memrid;
-
- memrid = PCIR_BAR(IXL_BAR);
+ device_t dev = iflib_get_dev(vsi->ctx);
/* We may get here before stations are setup */
if ((!ixl_enable_msix) || (que == NULL))
goto early;
+
/*
** Release all msix VSI resources:
*/
- for (int i = 0; i < vsi->num_queues; i++, que++) {
- rid = que->msix + 1;
- if (que->tag != NULL) {
- bus_teardown_intr(dev, que->res, que->tag);
- que->tag = NULL;
- }
- if (que->res != NULL)
- bus_release_resource(dev, SYS_RES_IRQ, rid, que->res);
- }
+ iflib_irq_free(vsi->ctx, &vsi->irq);
+ for (int i = 0; i < vsi->num_queues; i++, que++)
+ iflib_irq_free(vsi->ctx, &que->que_irq);
early:
- /* Clean the AdminQ interrupt last */
- if (pf->admvec) /* we are doing MSIX */
- rid = pf->admvec + 1;
- else
- (pf->msix != 0) ? (rid = 1):(rid = 0);
-
- if (pf->tag != NULL) {
- bus_teardown_intr(dev, pf->res, pf->tag);
- pf->tag = NULL;
- }
- if (pf->res != NULL)
- bus_release_resource(dev, SYS_RES_IRQ, rid, pf->res);
-
- if (pf->msix)
- pci_release_msi(dev);
-
- if (pf->msix_mem != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY,
- memrid, pf->msix_mem);
-
if (pf->pci_mem != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
PCIR_BAR(0), pf->pci_mem);
- return;
}
static void
@@ -2485,79 +1743,79 @@
{
/* Display supported media types */
if (phy_type & (1 << I40E_PHY_TYPE_100BASE_TX))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_100_TX, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_100_TX, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_1000BASE_T))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_1000_T, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_1000_T, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_1000BASE_SX))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_1000BASE_LX))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_1000_LX, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_1000_LX, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_XAUI) ||
phy_type & (1 << I40E_PHY_TYPE_XFI) ||
phy_type & (1 << I40E_PHY_TYPE_10GBASE_SFPP_CU))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_SR))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_LR))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_T))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_T, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_10G_T, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4) ||
phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4_CU) ||
phy_type & (1 << I40E_PHY_TYPE_40GBASE_AOC) ||
phy_type & (1 << I40E_PHY_TYPE_XLAUI) ||
phy_type & (1 << I40E_PHY_TYPE_40GBASE_KR4))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_CR4, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_40G_CR4, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_40GBASE_SR4))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_SR4, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_40G_SR4, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_40GBASE_LR4))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_LR4, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_40G_LR4, 0, NULL);
#ifndef IFM_ETH_XTYPE
if (phy_type & (1 << I40E_PHY_TYPE_1000BASE_KX))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_1000_CX, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_1000_CX, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_CR1_CU) ||
phy_type & (1 << I40E_PHY_TYPE_10GBASE_CR1) ||
phy_type & (1 << I40E_PHY_TYPE_10GBASE_AOC) ||
phy_type & (1 << I40E_PHY_TYPE_SFI))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_KX4))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_KR))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_40GBASE_KR4))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_SR4, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_40G_SR4, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_XLPPI))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_CR4, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_40G_CR4, 0, NULL);
#else
if (phy_type & (1 << I40E_PHY_TYPE_1000BASE_KX))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_1000_KX, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_1000_KX, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_CR1_CU)
|| phy_type & (1 << I40E_PHY_TYPE_10GBASE_CR1))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_CR1, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_10G_CR1, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_AOC))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_TWINAX_LONG, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_10G_TWINAX_LONG, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_SFI))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_SFI, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_10G_SFI, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_KX4))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_KX4, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_10G_KX4, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_KR))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_KR, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_10G_KR, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_20GBASE_KR2))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_20G_KR2, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_20G_KR2, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_40GBASE_KR4))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_KR4, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_40G_KR4, 0, NULL);
if (phy_type & (1 << I40E_PHY_TYPE_XLPPI))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_XLPPI, 0, NULL);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_40G_XLPPI, 0, NULL);
#endif
}
@@ -2569,58 +1827,26 @@
static int
ixl_setup_interface(device_t dev, struct ixl_vsi *vsi)
{
- struct ifnet *ifp;
- struct i40e_hw *hw = vsi->hw;
- struct ixl_queue *que = vsi->queues;
+ if_ctx_t ctx = vsi->ctx;
+ struct ixl_pf *pf = vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+ struct ifnet *ifp = iflib_get_ifp(ctx);
struct i40e_aq_get_phy_abilities_resp abilities;
enum i40e_status_code aq_error = 0;
+ uint64_t cap;
- INIT_DEBUGOUT("ixl_setup_interface: begin");
-
- ifp = vsi->ifp = if_alloc(IFT_ETHER);
- if (ifp == NULL) {
- device_printf(dev, "can not allocate ifnet structure\n");
- return (-1);
- }
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_mtu = ETHERMTU;
- ifp->if_baudrate = IF_Gbps(40);
- ifp->if_init = ixl_init;
- ifp->if_softc = vsi;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_ioctl = ixl_ioctl;
-
-#if __FreeBSD_version >= 1100036
- if_setgetcounterfn(ifp, ixl_get_counter);
-#endif
-
- ifp->if_transmit = ixl_mq_start;
-
- ifp->if_qflush = ixl_qflush;
-
- ifp->if_snd.ifq_maxlen = que->num_desc - 2;
-
- vsi->max_frame_size =
- ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN
- + ETHER_VLAN_ENCAP_LEN;
-
- /*
- * Tell the upper layer(s) we support long frames.
- */
- ifp->if_hdrlen = sizeof(struct ether_vlan_header);
-
- ifp->if_capabilities |= IFCAP_HWCSUM;
- ifp->if_capabilities |= IFCAP_HWCSUM_IPV6;
- ifp->if_capabilities |= IFCAP_TSO;
- ifp->if_capabilities |= IFCAP_JUMBO_MTU;
- ifp->if_capabilities |= IFCAP_LRO;
-
- /* VLAN capabilties */
- ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING
- | IFCAP_VLAN_HWTSO
- | IFCAP_VLAN_MTU
- | IFCAP_VLAN_HWCSUM;
- ifp->if_capenable = ifp->if_capabilities;
+ INIT_DEBUGOUT("ixl_setup_interface: begin");
+ /* initialize fast path functions */
+
+ cap = IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 | IFCAP_LRO | IFCAP_JUMBO_MTU | IFCAP_TSO;
+ cap |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO | IFCAP_VLAN_MTU | IFCAP_VLAN_HWCSUM;
+ if_setifheaderlen(ifp, sizeof(struct ether_vlan_header));
+ if_setcapabilitiesbit(ifp, cap, 0);
+ if_setcapenable(ifp, if_getcapabilities(ifp));
+ if_setbaudrate(ifp, 4000000000);
+ vsi->max_frame_size =
+ ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN
+ + ETHER_VLAN_ENCAP_LEN;
/*
** Don't turn this on by default, if vlans are
@@ -2632,13 +1858,6 @@
*/
ifp->if_capabilities |= IFCAP_VLAN_HWFILTER;
- /*
- * Specify the media types supported by this adapter and register
- * callbacks to update media and link information
- */
- ifmedia_init(&vsi->media, IFM_IMASK, ixl_media_change,
- ixl_media_status);
-
aq_error = i40e_aq_get_phy_capabilities(hw,
FALSE, TRUE, &abilities, NULL);
/* May need delay to detect fiber correctly */
@@ -2660,10 +1879,8 @@
ixl_add_ifmedia(vsi, abilities.phy_type);
/* Use autoselect media by default */
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_AUTO, 0, NULL);
- ifmedia_set(&vsi->media, IFM_ETHER | IFM_AUTO);
-
- ether_ifattach(ifp, hw->mac.addr);
+ ifmedia_add(vsi->media, IFM_ETHER | IFM_AUTO, 0, NULL);
+ ifmedia_set(vsi->media, IFM_ETHER | IFM_AUTO);
return (0);
}
@@ -2690,7 +1907,7 @@
if ((status->link_info & I40E_AQ_MEDIA_AVAILABLE) &&
(!(status->an_info & I40E_AQ_QUALIFIED_MODULE)) &&
(!(status->link_info & I40E_AQ_LINK_UP)))
- device_printf(pf->dev, "Link failed because "
+ device_printf(iflib_get_dev(pf->vsi.ctx), "Link failed because "
"an unqualified module was detected\n");
return;
@@ -2708,7 +1925,7 @@
{
struct i40e_hw *hw = &pf->hw;
struct ixl_vsi *vsi = &pf->vsi;
- device_t dev = vsi->dev;
+ device_t dev = iflib_get_dev(vsi->ctx);
struct i40e_aqc_get_switch_config_resp *sw_config;
u8 aq_buf[I40E_AQ_LARGE_BUF];
int ret;
@@ -2753,17 +1970,20 @@
static int
ixl_initialize_vsi(struct ixl_vsi *vsi)
{
- struct ixl_pf *pf = vsi->back;
+ if_shared_ctx_t sctx = ixl_sctx;
struct ixl_queue *que = vsi->queues;
- device_t dev = vsi->dev;
+ device_t dev = iflib_get_dev(vsi->ctx);
struct i40e_hw *hw = vsi->hw;
struct i40e_vsi_context ctxt;
int err = 0;
+ struct ifnet *ifp = iflib_get_ifp(vsi->ctx);
memset(&ctxt, 0, sizeof(ctxt));
ctxt.seid = vsi->seid;
+#ifdef notyet
if (pf->veb_seid != 0)
ctxt.uplink_seid = pf->veb_seid;
+#endif
ctxt.pf_num = hw->pf_id;
err = i40e_aq_get_vsi_params(hw, &ctxt, NULL);
if (err) {
@@ -2801,7 +2021,7 @@
/* Set VLAN receive stripping mode */
ctxt.info.valid_sections |= I40E_AQ_VSI_PROP_VLAN_VALID;
ctxt.info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_ALL;
- if (vsi->ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
+ if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH;
else
ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_EMOD_NOTHING;
@@ -2833,17 +2053,18 @@
/* Setup the HMC TX Context */
- size = que->num_desc * sizeof(struct i40e_tx_desc);
+ size = sctx->isc_ntxd * sizeof(struct i40e_tx_desc);
memset(&tctx, 0, sizeof(struct i40e_hmc_obj_txq));
tctx.new_context = 1;
- tctx.base = (txr->dma.pa/IXL_TX_CTX_BASE_UNITS);
- tctx.qlen = que->num_desc;
+
+ tctx.base = (txr->tx_paddr/IXL_TX_CTX_BASE_UNITS);
+ tctx.qlen = sctx->isc_ntxd;
tctx.fc_ena = 0;
tctx.rdylist = vsi->info.qs_handle[0]; /* index is TC */
/* Enable HEAD writeback */
tctx.head_wb_ena = 1;
- tctx.head_wb_addr = txr->dma.pa +
- (que->num_desc * sizeof(struct i40e_tx_desc));
+ tctx.head_wb_addr = txr->tx_paddr +
+ (sctx->isc_ntxd * sizeof(struct i40e_tx_desc));
tctx.rdylist_act = 0;
err = i40e_clear_lan_tx_queue_context(hw, i);
if (err) {
@@ -2863,7 +2084,7 @@
ixl_flush(hw);
/* Do ring (re)init */
- ixl_init_tx_ring(que);
+ ixl_init_tx_ring(vsi, que);
/* Next setup the HMC RX Context */
if (vsi->max_frame_size <= MCLBYTES)
@@ -2883,8 +2104,8 @@
rctx.dtype = 0;
rctx.dsize = 1; /* do 32byte descriptors */
rctx.hsplit_0 = 0; /* no HDR split initially */
- rctx.base = (rxr->dma.pa/IXL_RX_CTX_BASE_UNITS);
- rctx.qlen = que->num_desc;
+ rctx.base = (rxr->rx_paddr/IXL_RX_CTX_BASE_UNITS);
+ rctx.qlen = sctx->isc_nrxd;
rctx.tphrdesc_ena = 1;
rctx.tphwdesc_ena = 1;
rctx.tphdata_ena = 0;
@@ -2907,67 +2128,10 @@
device_printf(dev, "Unable to set RX context %d\n", i);
break;
}
- err = ixl_init_rx_ring(que);
- if (err) {
- device_printf(dev, "Fail in init_rx_ring %d\n", i);
- break;
- }
-#ifdef DEV_NETMAP
- /* preserve queue */
- if (vsi->ifp->if_capenable & IFCAP_NETMAP) {
- struct netmap_adapter *na = NA(vsi->ifp);
- struct netmap_kring *kring = &na->rx_rings[i];
- int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
- wr32(vsi->hw, I40E_QRX_TAIL(que->me), t);
- } else
-#endif /* DEV_NETMAP */
- wr32(vsi->hw, I40E_QRX_TAIL(que->me), que->num_desc - 1);
}
return (err);
}
-
-/*********************************************************************
- *
- * Free all VSI structs.
- *
- **********************************************************************/
-void
-ixl_free_vsi(struct ixl_vsi *vsi)
-{
- struct ixl_pf *pf = (struct ixl_pf *)vsi->back;
- struct ixl_queue *que = vsi->queues;
-
- /* Free station queues */
- for (int i = 0; i < vsi->num_queues; i++, que++) {
- struct tx_ring *txr = &que->txr;
- struct rx_ring *rxr = &que->rxr;
-
- if (!mtx_initialized(&txr->mtx)) /* uninitialized */
- continue;
- IXL_TX_LOCK(txr);
- ixl_free_que_tx(que);
- if (txr->base)
- i40e_free_dma_mem(&pf->hw, &txr->dma);
- IXL_TX_UNLOCK(txr);
- IXL_TX_LOCK_DESTROY(txr);
-
- if (!mtx_initialized(&rxr->mtx)) /* uninitialized */
- continue;
- IXL_RX_LOCK(rxr);
- ixl_free_que_rx(que);
- if (rxr->base)
- i40e_free_dma_mem(&pf->hw, &rxr->dma);
- IXL_RX_UNLOCK(rxr);
- IXL_RX_LOCK_DESTROY(rxr);
-
- }
- free(vsi->queues, M_DEVBUF);
-
- /* Free VSI filter list */
- ixl_free_mac_filters(vsi);
-}
-
static void
ixl_free_mac_filters(struct ixl_vsi *vsi)
{
@@ -2976,11 +2140,10 @@
while (!SLIST_EMPTY(&vsi->ftl)) {
f = SLIST_FIRST(&vsi->ftl);
SLIST_REMOVE_HEAD(&vsi->ftl, next);
- free(f, M_DEVBUF);
+ free(f, M_IXL);
}
}
-
/*********************************************************************
*
* Allocate memory for the VSI (virtual station interface) and their
@@ -2988,127 +2151,6 @@
* called only once at attach.
*
**********************************************************************/
-static int
-ixl_setup_stations(struct ixl_pf *pf)
-{
- device_t dev = pf->dev;
- struct ixl_vsi *vsi;
- struct ixl_queue *que;
- struct tx_ring *txr;
- struct rx_ring *rxr;
- int rsize, tsize;
- int error = I40E_SUCCESS;
-
- vsi = &pf->vsi;
- vsi->back = (void *)pf;
- vsi->hw = &pf->hw;
- vsi->id = 0;
- vsi->num_vlans = 0;
- vsi->back = pf;
-
- /* Get memory for the station queues */
- if (!(vsi->queues =
- (struct ixl_queue *) malloc(sizeof(struct ixl_queue) *
- vsi->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
- device_printf(dev, "Unable to allocate queue memory\n");
- error = ENOMEM;
- goto early;
- }
-
- for (int i = 0; i < vsi->num_queues; i++) {
- que = &vsi->queues[i];
- que->num_desc = ixl_ringsz;
- que->me = i;
- que->vsi = vsi;
- /* mark the queue as active */
- vsi->active_queues |= (u64)1 << que->me;
- txr = &que->txr;
- txr->que = que;
- txr->tail = I40E_QTX_TAIL(que->me);
-
- /* Initialize the TX lock */
- snprintf(txr->mtx_name, sizeof(txr->mtx_name), "%s:tx(%d)",
- device_get_nameunit(dev), que->me);
- mtx_init(&txr->mtx, txr->mtx_name, NULL, MTX_DEF);
- /* Create the TX descriptor ring */
- tsize = roundup2((que->num_desc *
- sizeof(struct i40e_tx_desc)) +
- sizeof(u32), DBA_ALIGN);
- if (i40e_allocate_dma_mem(&pf->hw,
- &txr->dma, i40e_mem_reserved, tsize, DBA_ALIGN)) {
- device_printf(dev,
- "Unable to allocate TX Descriptor memory\n");
- error = ENOMEM;
- goto fail;
- }
- txr->base = (struct i40e_tx_desc *)txr->dma.va;
- bzero((void *)txr->base, tsize);
- /* Now allocate transmit soft structs for the ring */
- if (ixl_allocate_tx_data(que)) {
- device_printf(dev,
- "Critical Failure setting up TX structures\n");
- error = ENOMEM;
- goto fail;
- }
- /* Allocate a buf ring */
- txr->br = buf_ring_alloc(4096, M_DEVBUF,
- M_WAITOK, &txr->mtx);
- if (txr->br == NULL) {
- device_printf(dev,
- "Critical Failure setting up TX buf ring\n");
- error = ENOMEM;
- goto fail;
- }
-
- /*
- * Next the RX queues...
- */
- rsize = roundup2(que->num_desc *
- sizeof(union i40e_rx_desc), DBA_ALIGN);
- rxr = &que->rxr;
- rxr->que = que;
- rxr->tail = I40E_QRX_TAIL(que->me);
-
- /* Initialize the RX side lock */
- snprintf(rxr->mtx_name, sizeof(rxr->mtx_name), "%s:rx(%d)",
- device_get_nameunit(dev), que->me);
- mtx_init(&rxr->mtx, rxr->mtx_name, NULL, MTX_DEF);
-
- if (i40e_allocate_dma_mem(&pf->hw,
- &rxr->dma, i40e_mem_reserved, rsize, 4096)) {
- device_printf(dev,
- "Unable to allocate RX Descriptor memory\n");
- error = ENOMEM;
- goto fail;
- }
- rxr->base = (union i40e_rx_desc *)rxr->dma.va;
- bzero((void *)rxr->base, rsize);
-
- /* Allocate receive soft structs for the ring*/
- if (ixl_allocate_rx_data(que)) {
- device_printf(dev,
- "Critical Failure setting up receive structs\n");
- error = ENOMEM;
- goto fail;
- }
- }
-
- return (0);
-
-fail:
- for (int i = 0; i < vsi->num_queues; i++) {
- que = &vsi->queues[i];
- rxr = &que->rxr;
- txr = &que->txr;
- if (rxr->base)
- i40e_free_dma_mem(&pf->hw, &rxr->dma);
- if (txr->base)
- i40e_free_dma_mem(&pf->hw, &txr->dma);
- }
-
-early:
- return (error);
-}
/*
** Provide a update to the queue RX
@@ -3180,7 +2222,6 @@
}
rxr->bytes = 0;
rxr->packets = 0;
- return;
}
@@ -3254,7 +2295,6 @@
}
txr->bytes = 0;
txr->packets = 0;
- return;
}
#define QUEUE_NAME_LEN 32
@@ -3267,7 +2307,7 @@
struct sysctl_oid_list *child;
struct sysctl_oid_list *vsi_list;
- tree = device_get_sysctl_tree(pf->dev);
+ tree = device_get_sysctl_tree(iflib_get_dev(vsi->ctx));
child = SYSCTL_CHILDREN(tree);
vsi->vsi_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, sysctl_name,
CTLFLAG_RD, NULL, "VSI Number");
@@ -3279,8 +2319,8 @@
static void
ixl_add_hw_stats(struct ixl_pf *pf)
{
- device_t dev = pf->dev;
struct ixl_vsi *vsi = &pf->vsi;
+ device_t dev = iflib_get_dev(vsi->ctx);
struct ixl_queue *queues = vsi->queues;
struct i40e_hw_port_stats *pf_stats = &pf->stats;
@@ -3317,9 +2357,6 @@
txr = &(queues[q].txr);
rxr = &(queues[q].rxr);
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "mbuf_defrag_failed",
- CTLFLAG_RD, &(queues[q].mbuf_defrag_failed),
- "m_defrag() failed");
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "dropped",
CTLFLAG_RD, &(queues[q].dropped_pkts),
"Driver dropped packets");
@@ -3329,12 +2366,6 @@
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx",
CTLFLAG_RD, &(queues[q].tso),
"TSO");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_dma_setup",
- CTLFLAG_RD, &(queues[q].tx_dma_setup),
- "Driver tx dma failure in xmit");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "no_desc_avail",
- CTLFLAG_RD, &(txr->no_desc),
- "Queue No Descriptor Available");
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets",
CTLFLAG_RD, &(txr->total_packets),
"Queue Packets Transmitted");
@@ -3446,8 +2477,6 @@
entry++;
}
}
-
-
/*
** ixl_config_rss - setup RSS
** - note this is done for the single vsi
@@ -3457,6 +2486,7 @@
struct ixl_pf *pf = (struct ixl_pf *)vsi->back;
struct i40e_hw *hw = vsi->hw;
u32 lut = 0;
+ u32 qf_ctl;
u64 set_hena = 0, hena;
int i, j, que_id;
#ifdef RSS
@@ -3515,6 +2545,14 @@
wr32(hw, I40E_PFQF_HENA(0), (u32)hena);
wr32(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32));
+ /* configure the RSS table size */
+ qf_ctl = rd32(hw, I40E_PFQF_CTL_0);
+ if (pf->hw.func_caps.rss_table_size == 512)
+ qf_ctl |= I40E_PFQF_CTL_0_HASHLUTSIZE_512;
+ else
+ qf_ctl &= ~I40E_PFQF_CTL_0_HASHLUTSIZE_512;
+ wr32(hw, I40E_PFQF_CTL_0, qf_ctl);
+
/* Populate the LUT with max no. of queues in round robin fashion */
for (i = j = 0; i < pf->hw.func_caps.rss_table_size; i++, j++) {
if (j == vsi->num_queues)
@@ -3540,57 +2578,6 @@
ixl_flush(hw);
}
-
-/*
-** This routine is run via an vlan config EVENT,
-** it enables us to use the HW Filter table since
-** we can get the vlan id. This just creates the
-** entry in the soft version of the VFTA, init will
-** repopulate the real table.
-*/
-static void
-ixl_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
-{
- struct ixl_vsi *vsi = ifp->if_softc;
- struct i40e_hw *hw = vsi->hw;
- struct ixl_pf *pf = (struct ixl_pf *)vsi->back;
-
- if (ifp->if_softc != arg) /* Not our event */
- return;
-
- if ((vtag == 0) || (vtag > 4095)) /* Invalid */
- return;
-
- IXL_PF_LOCK(pf);
- ++vsi->num_vlans;
- ixl_add_filter(vsi, hw->mac.addr, vtag);
- IXL_PF_UNLOCK(pf);
-}
-
-/*
-** This routine is run via an vlan
-** unconfig EVENT, remove our entry
-** in the soft vfta.
-*/
-static void
-ixl_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
-{
- struct ixl_vsi *vsi = ifp->if_softc;
- struct i40e_hw *hw = vsi->hw;
- struct ixl_pf *pf = (struct ixl_pf *)vsi->back;
-
- if (ifp->if_softc != arg)
- return;
-
- if ((vtag == 0) || (vtag > 4095)) /* Invalid */
- return;
-
- IXL_PF_LOCK(pf);
- --vsi->num_vlans;
- ixl_del_filter(vsi, hw->mac.addr, vtag);
- IXL_PF_UNLOCK(pf);
-}
-
/*
** This routine updates vlan filters, called by init
** it scans the filter table and then updates the hw
@@ -3624,7 +2611,6 @@
flags = IXL_FILTER_VLAN;
flags |= (IXL_FILTER_ADD | IXL_FILTER_USED);
ixl_add_hw_filters(vsi, flags, cnt);
- return;
}
/*
@@ -3660,8 +2646,6 @@
f->vlan = IXL_VLAN_ANY;
f->flags |= (IXL_FILTER_ADD | IXL_FILTER_USED
| IXL_FILTER_MC);
-
- return;
}
static void
@@ -3672,20 +2656,54 @@
}
/*
+** This routine is run via an vlan config EVENT,
+** it enables us to use the HW Filter table since
+** we can get the vlan id. This just creates the
+** entry in the soft version of the VFTA, init will
+** repopulate the real table.
+*/
+void
+ixl_if_vlan_register(if_ctx_t ctx, u16 vtag)
+{
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct i40e_hw *hw = vsi->hw;
+
+ if ((vtag == 0) || (vtag > 4095)) /* Invalid */
+ return;
+
+ ++vsi->num_vlans;
+ ixl_add_filter(vsi, hw->mac.addr, vtag);
+}
+
+/*
+** This routine is run via an vlan
+** unconfig EVENT, remove our entry
+** in the soft vfta.
+*/
+void
+ixl_if_vlan_unregister(if_ctx_t ctx, u16 vtag)
+{
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct i40e_hw *hw = vsi->hw;
+
+
+ if ((vtag == 0) || (vtag > 4095)) /* Invalid */
+ return;
+
+ --vsi->num_vlans;
+ ixl_del_filter(vsi, hw->mac.addr, vtag);
+}
+
+/*
** This routine adds macvlan filters
*/
-static void
+void
ixl_add_filter(struct ixl_vsi *vsi, u8 *macaddr, s16 vlan)
{
struct ixl_mac_filter *f, *tmp;
- struct ixl_pf *pf;
- device_t dev;
DEBUGOUT("ixl_add_filter: begin");
- pf = vsi->back;
- dev = pf->dev;
-
/* Does one already exist */
f = ixl_find_filter(vsi, macaddr, vlan);
if (f != NULL)
@@ -3705,7 +2723,7 @@
f = ixl_get_filter(vsi);
if (f == NULL) {
- device_printf(dev, "WARNING: no filter available!!\n");
+ device_printf(iflib_get_dev(vsi->ctx), "WARNING: no filter available!!\n");
return;
}
bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN);
@@ -3720,7 +2738,7 @@
return;
}
-static void
+void
ixl_del_filter(struct ixl_vsi *vsi, u8 *macaddr, s16 vlan)
{
struct ixl_mac_filter *f;
@@ -3775,18 +2793,12 @@
{
struct i40e_aqc_add_macvlan_element_data *a, *b;
struct ixl_mac_filter *f;
- struct ixl_pf *pf;
- struct i40e_hw *hw;
- device_t dev;
- int err, j = 0;
-
- pf = vsi->back;
- dev = pf->dev;
- hw = &pf->hw;
- IXL_PF_LOCK_ASSERT(pf);
+ struct i40e_hw *hw = vsi->hw;
+ device_t dev = iflib_get_dev(vsi->ctx);
+ int err, j = 0;
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;
@@ -3823,7 +2835,7 @@
else
vsi->hw_filters_add += j;
}
- free(a, M_DEVBUF);
+ free(a, M_IXL);
return;
}
@@ -3836,20 +2848,15 @@
ixl_del_hw_filters(struct ixl_vsi *vsi, int cnt)
{
struct i40e_aqc_remove_macvlan_element_data *d, *e;
- struct ixl_pf *pf;
- struct i40e_hw *hw;
- device_t dev;
+ struct i40e_hw *hw = vsi->hw;
+ device_t dev = iflib_get_dev(vsi->ctx);
struct ixl_mac_filter *f, *f_temp;
int err, j = 0;
DEBUGOUT("ixl_del_hw_filters: begin\n");
- pf = vsi->back;
- hw = &pf->hw;
- dev = pf->dev;
-
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) {
printf("del hw filter failed to get memory\n");
return;
@@ -3863,7 +2870,7 @@
e->flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
/* delete entry from vsi list */
SLIST_REMOVE(&vsi->ftl, f, ixl_mac_filter, next);
- free(f, M_DEVBUF);
+ free(f, M_IXL);
j++;
}
if (j == cnt)
@@ -3885,7 +2892,7 @@
} else
vsi->hw_filters_del += j;
}
- free(d, M_DEVBUF);
+ free(d, M_IXL);
DEBUGOUT("ixl_del_hw_filters: end\n");
return;
@@ -3916,7 +2923,7 @@
i40e_msec_delay(10);
}
if ((reg & I40E_QTX_ENA_QENA_STAT_MASK) == 0) {
- device_printf(pf->dev, "TX queue %d disabled!\n",
+ device_printf(iflib_get_dev(vsi->ctx), "TX queue %d disabled!\n",
index);
error = ETIMEDOUT;
}
@@ -3933,7 +2940,7 @@
i40e_msec_delay(10);
}
if ((reg & I40E_QRX_ENA_QENA_STAT_MASK) == 0) {
- device_printf(pf->dev, "RX queue %d disabled!\n",
+ device_printf(iflib_get_dev(vsi->ctx), "RX queue %d disabled!\n",
index);
error = ETIMEDOUT;
}
@@ -3942,6 +2949,55 @@
return (error);
}
+static void
+ixl_if_intr_enable(if_ctx_t ctx)
+{
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct i40e_hw *hw = vsi->hw;
+
+ if (ixl_enable_msix) {
+ ixl_enable_adminq(hw);
+ } else
+ ixl_enable_legacy(hw);
+}
+
+static void
+ixl_if_intr_disable(if_ctx_t ctx)
+{
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct i40e_hw *hw = vsi->hw;
+
+ if (ixl_enable_msix) {
+ ixl_disable_adminq(hw);
+ } else
+ ixl_disable_legacy(hw);
+}
+
+static void
+ixl_if_queue_intr_enable(if_ctx_t ctx, uint16_t qid)
+{
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ u32 reg;
+
+ reg = I40E_PFINT_DYN_CTLN_INTENA_MASK |
+ I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+ (IXL_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT);
+ wr32(vsi->hw, I40E_PFINT_DYN_CTLN(qid), reg);
+}
+
+#if 0
+static void
+ixl_if_queue_intr_disable(if_ctx_t ctx, uint16_t qid)
+{
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct i40e_hw *hw = vsi->hw;
+ u32 reg;
+
+ reg = IXL_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT;
+ wr32(hw, I40E_PFINT_DYN_CTLN(qid), reg);
+}
+#endif
+
static int
ixl_disable_rings(struct ixl_vsi *vsi)
{
@@ -3968,7 +3024,7 @@
i40e_msec_delay(10);
}
if (reg & I40E_QTX_ENA_QENA_STAT_MASK) {
- device_printf(pf->dev, "TX queue %d still enabled!\n",
+ device_printf(iflib_get_dev(vsi->ctx), "TX queue %d still enabled!\n",
index);
error = ETIMEDOUT;
}
@@ -3984,7 +3040,7 @@
i40e_msec_delay(10);
}
if (reg & I40E_QRX_ENA_QENA_STAT_MASK) {
- device_printf(pf->dev, "RX queue %d still enabled!\n",
+ device_printf(iflib_get_dev(vsi->ctx), "RX queue %d still enabled!\n",
index);
error = ETIMEDOUT;
}
@@ -4002,7 +3058,7 @@
static void ixl_handle_mdd_event(struct ixl_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
- device_t dev = pf->dev;
+ device_t dev = iflib_get_dev(pf->vsi.ctx);
bool mdd_detected = false;
bool pf_mdd_detected = false;
u32 reg;
@@ -4074,33 +3130,12 @@
if (ixl_enable_msix) {
ixl_enable_adminq(hw);
for (int i = 0; i < vsi->num_queues; i++, que++)
- ixl_enable_queue(hw, que->me);
+ ixl_if_queue_intr_enable(vsi->ctx, que->me);
} else
ixl_enable_legacy(hw);
}
static void
-ixl_disable_rings_intr(struct ixl_vsi *vsi)
-{
- struct i40e_hw *hw = vsi->hw;
- struct ixl_queue *que = vsi->queues;
-
- for (int i = 0; i < vsi->num_queues; i++, que++)
- ixl_disable_queue(hw, que->me);
-}
-
-static void
-ixl_disable_intr(struct ixl_vsi *vsi)
-{
- struct i40e_hw *hw = vsi->hw;
-
- if (ixl_enable_msix)
- ixl_disable_adminq(hw);
- else
- ixl_disable_legacy(hw);
-}
-
-static void
ixl_enable_adminq(struct i40e_hw *hw)
{
u32 reg;
@@ -4125,28 +3160,6 @@
}
static void
-ixl_enable_queue(struct i40e_hw *hw, int id)
-{
- u32 reg;
-
- reg = I40E_PFINT_DYN_CTLN_INTENA_MASK |
- I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
- (IXL_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT);
- wr32(hw, I40E_PFINT_DYN_CTLN(id), reg);
-}
-
-static void
-ixl_disable_queue(struct i40e_hw *hw, int id)
-{
- u32 reg;
-
- reg = IXL_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT;
- wr32(hw, I40E_PFINT_DYN_CTLN(id), reg);
-
- return;
-}
-
-static void
ixl_enable_legacy(struct i40e_hw *hw)
{
u32 reg;
@@ -4348,11 +3361,11 @@
** - do outside interrupt since it might sleep
*/
static void
-ixl_do_adminq(void *context, int pending)
+ixl_if_update_admin_status(if_ctx_t ctx)
{
- struct ixl_pf *pf = context;
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct ixl_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
- struct ixl_vsi *vsi = &pf->vsi;
struct i40e_arq_event_info event;
i40e_status ret;
u32 reg, loop = 0;
@@ -4360,13 +3373,12 @@
event.buf_len = IXL_AQ_BUF_SZ;
event.msg_buf = malloc(event.buf_len,
- M_DEVBUF, M_NOWAIT | M_ZERO);
+ M_IXL, M_NOWAIT | M_ZERO);
if (!event.msg_buf) {
printf("Unable to allocate adminq memory\n");
return;
}
- IXL_PF_LOCK(pf);
/* clean and process any events */
do {
ret = i40e_clean_arq_element(hw, &event, &result);
@@ -4397,18 +3409,17 @@
reg = rd32(hw, I40E_PFINT_ICR0_ENA);
reg |= I40E_PFINT_ICR0_ENA_ADMINQ_MASK;
wr32(hw, I40E_PFINT_ICR0_ENA, reg);
- free(event.msg_buf, M_DEVBUF);
+ free(event.msg_buf, M_IXL);
/*
* If there are still messages to process, reschedule ourselves.
* Otherwise, re-enable our interrupt and go to sleep.
*/
if (result > 0)
- taskqueue_enqueue(pf->tq, &pf->adminq);
+ iflib_admin_intr_deferred(ctx);
else
ixl_enable_intr(vsi);
- IXL_PF_UNLOCK(pf);
}
#ifdef IXL_DEBUG_SYSCTL
@@ -4438,16 +3449,12 @@
struct ixl_vsi *vsi = &pf->vsi;
struct ixl_queue *que = vsi->queues;
struct rx_ring *rxr = &que->rxr;
- struct tx_ring *txr = &que->txr;
u32 reg;
printf("Queue irqs = %jx\n", (uintmax_t)que->irqs);
printf("AdminQ irqs = %jx\n", (uintmax_t)pf->admin_irq);
- printf("RX next check = %x\n", rxr->next_check);
- printf("RX not ready = %jx\n", (uintmax_t)rxr->not_done);
printf("RX packets = %jx\n", (uintmax_t)rxr->rx_packets);
- printf("TX desc avail = %x\n", txr->avail);
reg = rd32(hw, I40E_GLV_GORCL(0xc));
printf("RX Bytes = %x\n", reg);
@@ -4487,6 +3494,7 @@
struct i40e_hw *hw = &pf->hw;
struct i40e_eth_stats *es;
struct i40e_eth_stats *oes;
+
struct i40e_hw_port_stats *nsd;
u16 stat_idx = vsi->info.stat_counter_idx;
@@ -4542,22 +3550,18 @@
ixl_update_vsi_stats(struct ixl_vsi *vsi)
{
struct ixl_pf *pf;
- struct ifnet *ifp;
struct i40e_eth_stats *es;
u64 tx_discards;
struct i40e_hw_port_stats *nsd;
pf = vsi->back;
- ifp = vsi->ifp;
es = &vsi->eth_stats;
nsd = &pf->stats;
ixl_update_eth_stats(vsi);
tx_discards = es->tx_discards + nsd->tx_dropped_link_down;
- for (int i = 0; i < vsi->num_queues; i++)
- tx_discards += vsi->queues[i].txr.br->br_drops;
/* Update ifnet stats */
IXL_SET_IPACKETS(vsi, es->rx_unicast +
@@ -4672,7 +3676,7 @@
*/
struct ixl_pf *pf = (struct ixl_pf *)arg1;
struct i40e_hw *hw = &pf->hw;
- device_t dev = pf->dev;
+ device_t dev = iflib_get_dev(pf->vsi.ctx);
int error = 0;
enum i40e_status_code aq_error = 0;
u8 fc_aq_err = 0;
@@ -4760,7 +3764,10 @@
ixl_set_advertised_speeds(struct ixl_pf *pf, int speeds)
{
struct i40e_hw *hw = &pf->hw;
- device_t dev = pf->dev;
+ if_ctx_t ctx = ((struct ixl_vsi *)pf)->ctx;
+ device_t dev = iflib_get_dev(ctx);
+ struct ifnet *ifp = iflib_get_ifp(ctx);
+
struct i40e_aq_get_phy_abilities_resp abilities;
struct i40e_aq_set_phy_config config;
enum i40e_status_code aq_error = 0;
@@ -4808,11 +3815,7 @@
** This seems a bit heavy handed, but we
** need to get a reinit on some devices
*/
- IXL_PF_LOCK(pf);
- ixl_stop(pf);
- ixl_init_locked(pf);
- IXL_PF_UNLOCK(pf);
-
+ ifp->if_init(ifp->if_softc);
return (0);
}
@@ -4831,7 +3834,7 @@
{
struct ixl_pf *pf = (struct ixl_pf *)arg1;
struct i40e_hw *hw = &pf->hw;
- device_t dev = pf->dev;
+ device_t dev = iflib_get_dev(pf->vsi.ctx);
int requested_ls = 0;
int error = 0;
@@ -5068,7 +4071,7 @@
}
buf_len = sizeof(char) * (entry_len + 1) * ftl_len + 2;
- buf = buf_i = malloc(buf_len, M_DEVBUF, M_NOWAIT);
+ buf = buf_i = malloc(buf_len, M_IXL, M_NOWAIT);
sprintf(buf_i++, "\n");
SLIST_FOREACH(f, &vsi->ftl, next) {
@@ -5086,7 +4089,7 @@
error = sysctl_handle_string(oidp, buf, strlen(buf), req);
if (error)
printf("sysctl error: %d\n", error);
- free(buf, M_DEVBUF);
+ free(buf, M_IXL);
return error;
}
@@ -5106,14 +4109,14 @@
{
struct ixl_pf *pf = (struct ixl_pf *)arg1;
struct i40e_hw *hw = &pf->hw;
- device_t dev = pf->dev;
+ device_t dev = iflib_get_dev(pf->vsi.ctx);
struct sbuf *buf;
int error = 0;
u8 num_entries;
struct i40e_aqc_switch_resource_alloc_element_resp resp[IXL_SW_RES_SIZE];
- buf = sbuf_new_for_sysctl(NULL, NULL, 0, req);
+ buf = sbuf_new(NULL, NULL, 1024, SBUF_AUTOEXTEND);
if (!buf) {
device_printf(dev, "Could not allocate sbuf for output.\n");
return (ENOMEM);
@@ -5154,6 +4157,7 @@
sbuf_cat(buf, "\n");
}
+ sbuf_trim(buf);
error = sbuf_finish(buf);
sbuf_delete(buf);
@@ -5203,7 +4207,7 @@
{
struct ixl_pf *pf = (struct ixl_pf *)arg1;
struct i40e_hw *hw = &pf->hw;
- device_t dev = pf->dev;
+ device_t dev = iflib_get_dev(pf->vsi.ctx);
struct sbuf *buf;
struct sbuf *nmbuf;
int error = 0;
@@ -5213,7 +4217,7 @@
struct i40e_aqc_get_switch_config_resp *sw_config;
sw_config = (struct i40e_aqc_get_switch_config_resp *)aq_buf;
- buf = sbuf_new_for_sysctl(NULL, NULL, 0, req);
+ buf = sbuf_new(NULL, NULL, 1024, SBUF_AUTOEXTEND);
if (!buf) {
device_printf(dev, "Could not allocate sbuf for sysctl output.\n");
return (ENOMEM);
@@ -5332,7 +4336,7 @@
code = i40e_aq_config_vsi_bw_limit(hw, vf->vsi.seid, 0, 0, NULL);
if (code != I40E_SUCCESS) {
- device_printf(pf->dev, "Failed to disable BW limit: %d\n",
+ device_printf(iflib_get_dev(pf->vsi.ctx), "Failed to disable BW limit: %d\n",
ixl_adminq_err_to_errno(hw->aq.asq_last_status));
return (ixl_adminq_err_to_errno(hw->aq.asq_last_status));
}
@@ -5530,7 +4534,7 @@
error = ixl_flush_pcie(pf, vf);
if (error != 0)
- device_printf(pf->dev,
+ device_printf(iflib_get_dev(pf->vsi.ctx),
"Timed out waiting for PCIe activity to stop on VF-%d\n",
vf->vf_num);
@@ -5543,7 +4547,7 @@
}
if (i == IXL_VF_RESET_TIMEOUT)
- device_printf(pf->dev, "VF %d failed to reset\n", vf->vf_num);
+ device_printf(iflib_get_dev(pf->vsi.ctx), "VF %d failed to reset\n", vf->vf_num);
wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_num), I40E_VFR_COMPLETED);
@@ -6416,7 +5420,7 @@
opcode = le32toh(event->desc.cookie_high);
if (vf_num >= pf->num_vfs) {
- device_printf(pf->dev, "Got msg from illegal VF: %d\n", vf_num);
+ device_printf(iflib_get_dev(pf->vsi.ctx), "Got msg from illegal VF: %d\n", vf_num);
return;
}
@@ -6480,7 +5484,7 @@
/* Handle any VFs that have reset themselves via a Function Level Reset(FLR). */
static void
-ixl_handle_vflr(void *arg, int pending)
+ixl_if_handle_vflr(if_ctx_t ctx)
{
struct ixl_pf *pf;
struct i40e_hw *hw;
@@ -6488,10 +5492,9 @@
uint32_t vflrstat_index, vflrstat_mask, vflrstat, icr0;
int i;
- pf = arg;
+ pf = iflib_get_softc(ctx);
hw = &pf->hw;
- IXL_PF_LOCK(pf);
for (i = 0; i < pf->num_vfs; i++) {
global_vf_num = hw->func_caps.vf_base_id + i;
@@ -6510,8 +5513,6 @@
icr0 |= I40E_PFINT_ICR0_ENA_VFLR_MASK;
wr32(hw, I40E_PFINT_ICR0_ENA, icr0);
ixl_flush(hw);
-
- IXL_PF_UNLOCK(pf);
}
static int
@@ -6569,19 +5570,20 @@
}
static int
-ixl_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *params)
+ixl_if_iov_init(if_ctx_t ctx, uint16_t num_vfs, const nvlist_t *params)
{
+ device_t dev;
struct ixl_pf *pf;
struct i40e_hw *hw;
struct ixl_vsi *pf_vsi;
enum i40e_status_code ret;
int i, error;
- pf = device_get_softc(dev);
+ dev = iflib_get_dev(ctx);
+ pf = iflib_get_softc(ctx);
hw = &pf->hw;
pf_vsi = &pf->vsi;
- IXL_PF_LOCK(pf);
pf->vfs = malloc(sizeof(struct ixl_vf) * num_vfs, M_IXL, M_NOWAIT |
M_ZERO);
@@ -6606,32 +5608,31 @@
ixl_enable_adminq(hw);
pf->num_vfs = num_vfs;
- IXL_PF_UNLOCK(pf);
return (0);
fail:
free(pf->vfs, M_IXL);
pf->vfs = NULL;
- IXL_PF_UNLOCK(pf);
return (error);
}
static void
-ixl_iov_uninit(device_t dev)
+ixl_if_iov_uninit(if_ctx_t ctx)
{
struct ixl_pf *pf;
struct i40e_hw *hw;
struct ixl_vsi *vsi;
struct ifnet *ifp;
struct ixl_vf *vfs;
+ device_t dev;
int i, num_vfs;
- pf = device_get_softc(dev);
+ dev = iflib_get_dev(ctx);
+ pf = iflib_get_softc(ctx);
hw = &pf->hw;
vsi = &pf->vsi;
ifp = vsi->ifp;
- IXL_PF_LOCK(pf);
for (i = 0; i < pf->num_vfs; i++) {
if (pf->vfs[i].vsi.seid != 0)
i40e_aq_delete_element(hw, pf->vfs[i].vsi.seid, NULL);
@@ -6642,19 +5643,14 @@
pf->veb_seid = 0;
}
-#if __FreeBSD_version > 1100022
if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0)
-#else
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
-#endif
- ixl_disable_intr(vsi);
+ ixl_if_intr_disable(ctx);
vfs = pf->vfs;
num_vfs = pf->num_vfs;
pf->vfs = NULL;
pf->num_vfs = 0;
- IXL_PF_UNLOCK(pf);
/* Do this after the unlock as sysctl_ctx_free might sleep. */
for (i = 0; i < num_vfs; i++)
@@ -6663,19 +5659,20 @@
}
static int
-ixl_add_vf(device_t dev, uint16_t vfnum, const nvlist_t *params)
+ixl_if_vf_add(if_ctx_t ctx, uint16_t vfnum, const nvlist_t *params)
{
char sysctl_name[QUEUE_NAME_LEN];
struct ixl_pf *pf;
struct ixl_vf *vf;
+ device_t dev;
const void *mac;
size_t size;
int error;
- pf = device_get_softc(dev);
+ dev = iflib_get_dev(ctx);
+ pf = iflib_get_softc(ctx);
vf = &pf->vfs[vfnum];
- IXL_PF_LOCK(pf);
vf->vf_num = vfnum;
vf->vsi.back = pf;
@@ -6709,7 +5706,6 @@
ixl_reset_vf(pf, vf);
out:
- IXL_PF_UNLOCK(pf);
if (error == 0) {
snprintf(sysctl_name, sizeof(sysctl_name), "vf%d", vfnum);
ixl_add_vsi_sysctls(pf, &vf->vsi, &vf->ctx, sysctl_name);
Index: sys/dev/ixl/if_ixl_common.c
===================================================================
--- /dev/null
+++ sys/dev/ixl/if_ixl_common.c
@@ -0,0 +1,96 @@
+#ifndef IXL_STANDALONE_BUILD
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#include "opt_rss.h"
+#endif
+
+#include "ixl.h"
+#include "ixl_pf.h"
+
+#ifdef RSS
+#include <net/rss_config.h>
+#endif
+
+#include "ifdi_if.h"
+
+
+/*********************************************************************
+ *
+ * Media Ioctl callback
+ *
+ * This routine is called when the user changes speed/duplex using
+ * media/mediopt option with ifconfig.
+ *
+ **********************************************************************/
+int
+ixl_if_media_change(if_ctx_t ctx)
+{
+ struct ifmedia *ifm = iflib_get_media(ctx);
+
+ INIT_DEBUGOUT("ixl_media_change: begin");
+
+ if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
+ return (EINVAL);
+
+ if_printf(iflib_get_ifp(ctx), "Media change is currently not supported.\n");
+ return (ENODEV);
+}
+
+int
+ixl_if_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nqs)
+{
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct ixl_queue *que;
+ struct ixl_tx_buf *bufs;
+ if_shared_ctx_t sctx;
+ int i;
+
+ MPASS(vsi->num_queues > 0);
+ MPASS(nqs == 2);
+ /* Allocate queue structure memory */
+ sctx = iflib_get_sctx(ctx);
+ if (!(vsi->queues =
+ (struct ixl_queue *) malloc(sizeof(struct ixl_queue) *
+ vsi->num_queues, M_IXL, M_NOWAIT | M_ZERO))) {
+ device_printf(iflib_get_dev(ctx), "Unable to allocate TX ring memory\n");
+ return (ENOMEM);
+ }
+ if ((bufs = malloc(sizeof(*bufs)*sctx->isc_ntxd*vsi->num_queues, M_IXL, M_WAITOK|M_ZERO)) == NULL) {
+ free(vsi->queues, M_IXL);
+ device_printf(iflib_get_dev(ctx), "failed to allocate sw bufs\n");
+ return (ENOMEM);
+ }
+
+ for (i = 0, que = vsi->queues; i < vsi->num_queues; i++, que++) {
+ struct tx_ring *txr = &que->txr;
+ struct rx_ring *rxr = &que->rxr;
+
+ que->me = i;
+ que->vsi = vsi;
+
+ /* get the virtual and physical address of the hardware queues */
+ txr->tail = I40E_QTX_TAIL(que->me);
+ txr->tx_base = (struct i40e_tx_desc *)vaddrs[i*2];
+ txr->tx_paddr = paddrs[i*2];
+ txr->tx_buffers = bufs + i*sctx->isc_ntxd;
+ rxr->tail = I40E_QRX_TAIL(que->me);
+ rxr->rx_base = (union i40e_rx_desc *)vaddrs[i*2 + 1];
+ rxr->rx_paddr = paddrs[i*2 + 1];
+ txr->que = rxr->que = que;
+ }
+
+ device_printf(iflib_get_dev(ctx), "allocated for %d queues\n", vsi->num_queues);
+ return (0);
+}
+
+void
+ixl_if_queues_free(if_ctx_t ctx)
+{
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct ixl_queue *que;
+
+ if ((que = vsi->queues) == NULL)
+ return;
+ free(que->txr.tx_buffers, M_IXL);
+ free(que, M_IXL);
+}
Index: sys/dev/ixl/if_ixlv.c
===================================================================
--- sys/dev/ixl/if_ixlv.c
+++ sys/dev/ixl/if_ixlv.c
@@ -60,59 +60,55 @@
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
*********************************************************************/
-static ixl_vendor_info_t ixlv_vendor_info_array[] =
+static struct pci_vendor_info ixlv_vendor_info_array[] =
{
- {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_VF, 0, 0, 0},
- {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_VF_HV, 0, 0, 0},
+ PVID(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_VF, "Intel(R) Ethernet Connection XL710 VF Driver"),
+ PVID(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_VF_HV, "Intel(R) Ethernet Connection XL710 VF HV Driver"),
/* required last entry */
- {0, 0, 0, 0, 0}
+ PVID_END
};
/*********************************************************************
- * Table of branding strings
- *********************************************************************/
-
-static char *ixlv_strings[] = {
- "Intel(R) Ethernet Connection XL710 VF Driver"
-};
-
-
-/*********************************************************************
* Function prototypes
*********************************************************************/
-static int ixlv_probe(device_t);
-static int ixlv_attach(device_t);
-static int ixlv_detach(device_t);
-static int ixlv_shutdown(device_t);
-static void ixlv_init_locked(struct ixlv_sc *);
+static void *ixlv_register(device_t);
+static int ixlv_if_attach_pre(if_ctx_t);
+static int ixlv_if_attach_post(if_ctx_t);
+static int ixlv_if_detach(if_ctx_t);
+static int ixlv_if_shutdown(if_ctx_t);
+static void ixlv_if_init(if_ctx_t);
+static void ixlv_if_stop(if_ctx_t);
+static void ixlv_if_intr_enable(if_ctx_t ctx);
+static void ixlv_if_intr_disable(if_ctx_t ctx);
+static void ixlv_if_queue_intr_enable(if_ctx_t ctx, uint16_t qid);
+static void ixlv_if_queue_intr_disable(if_ctx_t ctx, uint16_t qid);
+static void ixlv_if_media_status(if_ctx_t, struct ifmediareq *);
+static void ixlv_if_timer(if_ctx_t ctx, uint16_t qid);
+static int ixlv_if_msix_intr_assign(if_ctx_t ctx, int msix);
+static void ixlv_if_vlan_register(if_ctx_t ctx, u16 vtag);
+static void ixlv_if_vlan_unregister(if_ctx_t ctx, u16 vtag);
+static void ixlv_if_multi_set(if_ctx_t ctx);
+static void ixlv_if_update_admin_status(if_ctx_t ctx);
+static int ixlv_if_promisc_set(if_ctx_t ctx, int flags);
+static int ixlv_if_mtu_set(if_ctx_t ctx, uint32_t mtu);
+
static int ixlv_allocate_pci_resources(struct ixlv_sc *);
static void ixlv_free_pci_resources(struct ixlv_sc *);
-static int ixlv_assign_msix(struct ixlv_sc *);
-static int ixlv_init_msix(struct ixlv_sc *);
-static int ixlv_init_taskqueue(struct ixlv_sc *);
-static int ixlv_setup_queues(struct ixlv_sc *);
static void ixlv_config_rss(struct ixlv_sc *);
-static void ixlv_stop(struct ixlv_sc *);
-static void ixlv_add_multi(struct ixl_vsi *);
-static void ixlv_del_multi(struct ixl_vsi *);
-static void ixlv_free_queues(struct ixl_vsi *);
-static int ixlv_setup_interface(device_t, struct ixlv_sc *);
-
-static int ixlv_media_change(struct ifnet *);
-static void ixlv_media_status(struct ifnet *, struct ifmediareq *);
+static int ixlv_setup_interface(if_ctx_t ctx);
-static void ixlv_local_timer(void *);
+static void ixlv_init_internal(if_ctx_t ctx);
+static void ixlv_init_multi(struct ixl_vsi *vsi);
+static void ixlv_del_multi(struct ixl_vsi *vsi);
static int ixlv_add_mac_filter(struct ixlv_sc *, u8 *, u16);
static int ixlv_del_mac_filter(struct ixlv_sc *sc, u8 *macaddr);
static void ixlv_init_filters(struct ixlv_sc *);
static void ixlv_free_filters(struct ixlv_sc *);
-static void ixlv_msix_que(void *);
-static void ixlv_msix_adminq(void *);
-static void ixlv_do_adminq(void *, int);
+static int ixlv_msix_que(void *);
+static int ixlv_msix_adminq(void *);
static void ixlv_do_adminq_locked(struct ixlv_sc *sc);
-static void ixlv_handle_que(void *, int);
static int ixlv_reset(struct ixlv_sc *);
static int ixlv_reset_complete(struct i40e_hw *);
static void ixlv_set_queue_rx_itr(struct ixl_queue *);
@@ -122,20 +118,16 @@
static void ixlv_enable_adminq_irq(struct i40e_hw *);
static void ixlv_disable_adminq_irq(struct i40e_hw *);
-static void ixlv_enable_queue_irq(struct i40e_hw *, int);
-static void ixlv_disable_queue_irq(struct i40e_hw *, int);
static void ixlv_setup_vlan_filters(struct ixlv_sc *);
-static void ixlv_register_vlan(void *, struct ifnet *, u16);
-static void ixlv_unregister_vlan(void *, struct ifnet *, u16);
static void ixlv_init_hw(struct ixlv_sc *);
static int ixlv_setup_vc(struct ixlv_sc *);
static int ixlv_vf_config(struct ixlv_sc *);
-
+#if 0
static void ixlv_cap_txcsum_tso(struct ixl_vsi *,
struct ifnet *, int);
-
+#endif
static void ixlv_add_sysctls(struct ixlv_sc *);
static int ixlv_sysctl_qtx_tail_handler(SYSCTL_HANDLER_ARGS);
static int ixlv_sysctl_qrx_tail_handler(SYSCTL_HANDLER_ARGS);
@@ -146,11 +138,12 @@
static device_method_t ixlv_methods[] = {
/* Device interface */
- DEVMETHOD(device_probe, ixlv_probe),
- DEVMETHOD(device_attach, ixlv_attach),
- DEVMETHOD(device_detach, ixlv_detach),
- DEVMETHOD(device_shutdown, ixlv_shutdown),
- {0, 0}
+ DEVMETHOD(device_register, ixlv_register),
+ DEVMETHOD(device_probe, iflib_device_probe),
+ DEVMETHOD(device_attach, iflib_device_attach),
+ DEVMETHOD(device_detach, iflib_device_detach),
+ DEVMETHOD(device_shutdown, iflib_device_shutdown),
+ DEVMETHOD_END
};
static driver_t ixlv_driver = {
@@ -160,9 +153,42 @@
devclass_t ixlv_devclass;
DRIVER_MODULE(ixlv, pci, ixlv_driver, ixlv_devclass, 0, 0);
+MODULE_DEPEND(ixlv, iflib, 1, 1, 1);
MODULE_DEPEND(ixlv, pci, 1, 1, 1);
MODULE_DEPEND(ixlv, ether, 1, 1, 1);
+static device_method_t ixlv_if_methods[] = {
+ DEVMETHOD(ifdi_attach_pre, ixlv_if_attach_pre),
+ DEVMETHOD(ifdi_attach_post, ixlv_if_attach_post),
+ DEVMETHOD(ifdi_detach, ixlv_if_detach),
+ DEVMETHOD(ifdi_detach, ixlv_if_shutdown),
+ DEVMETHOD(ifdi_init, ixlv_if_init),
+ DEVMETHOD(ifdi_stop, ixlv_if_stop),
+ DEVMETHOD(ifdi_intr_disable, ixlv_if_intr_disable),
+ DEVMETHOD(ifdi_intr_enable, ixlv_if_intr_enable),
+ DEVMETHOD(ifdi_queue_intr_enable, ixlv_if_queue_intr_enable),
+ DEVMETHOD(ifdi_multi_set, ixlv_if_multi_set),
+ DEVMETHOD(ifdi_update_admin_status, ixlv_if_update_admin_status),
+ DEVMETHOD(ifdi_mtu_set, ixlv_if_mtu_set),
+ DEVMETHOD(ifdi_media_status, ixlv_if_media_status),
+ DEVMETHOD(ifdi_timer, ixlv_if_timer),
+ DEVMETHOD(ifdi_promisc_set, ixlv_if_promisc_set),
+ DEVMETHOD(ifdi_msix_intr_assign, ixlv_if_msix_intr_assign),
+ DEVMETHOD(ifdi_vlan_register, ixlv_if_vlan_register),
+ DEVMETHOD(ifdi_vlan_unregister, ixlv_if_vlan_unregister),
+
+ DEVMETHOD(ifdi_media_change, ixl_if_media_change),
+ DEVMETHOD(ifdi_queues_alloc, ixl_if_queues_alloc),
+ DEVMETHOD(ifdi_queues_free, ixl_if_queues_free),
+ DEVMETHOD_END
+};
+
+
+static driver_t ixlv_if_driver = {
+ "ixlv_if", ixlv_if_methods, sizeof(struct ixlv_sc),
+};
+
+
/*
** TUNEABLE PARAMETERS:
*/
@@ -221,54 +247,47 @@
SYSCTL_INT(_hw_ixlv, OID_AUTO, tx_itr, CTLFLAG_RDTUN,
&ixlv_tx_itr, 0, "TX Interrupt Rate");
-
-/*********************************************************************
- * Device identification routine
- *
- * ixlv_probe determines if the driver should be loaded on
- * the hardware based on PCI vendor/device id of the device.
- *
- * return BUS_PROBE_DEFAULT on success, positive on failure
- *********************************************************************/
-
-static int
-ixlv_probe(device_t dev)
-{
- ixl_vendor_info_t *ent;
+extern struct if_txrx ixl_txrx;
+
+static struct if_shared_ctx ixlv_sctx_init = {
+ .isc_magic = IFLIB_MAGIC,
+ .isc_q_align = PAGE_SIZE,/* max(DBA_ALIGN, PAGE_SIZE) */
+ .isc_tx_maxsize = IXL_TSO_SIZE,
+
+ .isc_tx_maxsegsize = PAGE_SIZE*4,
+
+ .isc_rx_maxsize = PAGE_SIZE*4,
+ .isc_rx_nsegments = 1,
+ .isc_rx_maxsegsize = PAGE_SIZE*4,
+ .isc_ntxd = DEFAULT_RING,
+ .isc_nrxd = DEFAULT_RING,
+ .isc_nfl = 1,
+ .isc_qsizes[0] = roundup2((DEFAULT_RING * sizeof(struct i40e_tx_desc)) +
+ sizeof(u32), DBA_ALIGN),
+ .isc_qsizes[1] = roundup2(DEFAULT_RING *
+ sizeof(union i40e_rx_desc), DBA_ALIGN),
+ .isc_nqs = 2,
+ .isc_admin_intrcnt = 1,
+ .isc_vendor_info = ixlv_vendor_info_array,
+ .isc_driver_version = ixlv_driver_version,
+ .isc_txrx = &ixl_txrx,
+ .isc_driver = &ixlv_if_driver,
+};
- u16 pci_vendor_id, pci_device_id;
- u16 pci_subvendor_id, pci_subdevice_id;
- char device_name[256];
+if_shared_ctx_t ixlv_sctx = &ixlv_sctx_init;
- INIT_DEBUGOUT("ixlv_probe: begin");
+static void *
+ixlv_register(device_t dev)
+{
+ ixlv_sctx->isc_ntxd = ixlv_ringsz;
+ ixlv_sctx->isc_nrxd = ixlv_ringsz;
+ ixlv_sctx->isc_qsizes[0] = roundup2((ixlv_ringsz * sizeof(struct i40e_tx_desc)) +
+ sizeof(u32), DBA_ALIGN);
+ ixlv_sctx->isc_qsizes[1] = roundup2(ixlv_ringsz *
+ sizeof(union i40e_rx_desc), DBA_ALIGN);
- pci_vendor_id = pci_get_vendor(dev);
- if (pci_vendor_id != I40E_INTEL_VENDOR_ID)
- return (ENXIO);
- pci_device_id = pci_get_device(dev);
- pci_subvendor_id = pci_get_subvendor(dev);
- pci_subdevice_id = pci_get_subdevice(dev);
-
- ent = ixlv_vendor_info_array;
- while (ent->vendor_id != 0) {
- if ((pci_vendor_id == ent->vendor_id) &&
- (pci_device_id == ent->device_id) &&
-
- ((pci_subvendor_id == ent->subvendor_id) ||
- (ent->subvendor_id == 0)) &&
-
- ((pci_subdevice_id == ent->subdevice_id) ||
- (ent->subdevice_id == 0))) {
- sprintf(device_name, "%s, Version - %s",
- ixlv_strings[ent->index],
- ixlv_driver_version);
- device_set_desc_copy(dev, device_name);
- return (BUS_PROBE_DEFAULT);
- }
- ent++;
- }
- return (ENXIO);
+ return (ixlv_sctx);
}
/*********************************************************************
@@ -281,22 +300,24 @@
* return 0 on success, positive on failure
*********************************************************************/
+/* XXX We fail without MSIX support */
static int
-ixlv_attach(device_t dev)
+ixlv_if_attach_pre(if_ctx_t ctx)
{
struct ixlv_sc *sc;
struct i40e_hw *hw;
struct ixl_vsi *vsi;
int error = 0;
+ device_t dev;
INIT_DBG_DEV(dev, "begin");
/* Allocate, clear, and link in our primary soft structure */
- sc = device_get_softc(dev);
+ dev = iflib_get_dev(ctx);
+ sc = iflib_get_softc(ctx);
sc->dev = sc->osdep.dev = dev;
hw = &sc->hw;
vsi = &sc->vsi;
- vsi->dev = dev;
/* Initialize hw struct */
ixlv_init_hw(sc);
@@ -304,13 +325,6 @@
/* Allocate filter lists */
ixlv_init_filters(sc);
- /* Core Lock Init*/
- mtx_init(&sc->mtx, device_get_nameunit(dev),
- "IXL SC Lock", MTX_DEF);
-
- /* Set up the timer callout */
- callout_init_mtx(&sc->timer, &sc->mtx, 0);
-
/* Do PCI setup - map BAR0, etc */
if (ixlv_allocate_pci_resources(sc)) {
device_printf(dev, "%s: Allocation of PCI resources failed\n",
@@ -399,17 +413,38 @@
vsi->id = sc->vsi_res->vsi_id;
vsi->back = (void *)sc;
sc->link_up = TRUE;
+ /* ATTACH_PRE end */
- /* This allocates the memory and early settings */
- if (ixlv_setup_queues(sc) != 0) {
- device_printf(dev, "%s: setup queues failed!\n",
- __func__);
- error = EIO;
- goto out;
- }
+ return (error);
+err_res_buf:
+ free(sc->vf_res, M_IXL);
+err_aq:
+ i40e_shutdown_adminq(hw);
+err_pci_res:
+ ixlv_free_pci_resources(sc);
+err_early:
+ ixlv_free_filters(sc);
+ INIT_DBG_DEV(dev, "end: error %d", error);
+ return (error);
+}
+
+static int
+ixlv_if_attach_post(if_ctx_t ctx)
+{
+ struct ixlv_sc *sc;
+ int error = 0;
+ device_t dev;
+ struct i40e_hw *hw;
+
+ INIT_DBG_DEV(dev, "begin");
+
+ /* Allocate, clear, and link in our primary soft structure */
+ dev = iflib_get_dev(ctx);
+ sc = iflib_get_softc(ctx);
+ hw = &sc->hw;
/* Setup the stack interface */
- if (ixlv_setup_interface(dev, sc) != 0) {
+ if (ixlv_setup_interface(ctx) != 0) {
device_printf(dev, "%s: setup interface failed!\n",
__func__);
error = EIO;
@@ -418,22 +453,10 @@
INIT_DBG_DEV(dev, "Queue memory and interface setup");
- /* Do queue interrupt setup */
- ixlv_assign_msix(sc);
-
- /* Start AdminQ taskqueue */
- ixlv_init_taskqueue(sc);
-
/* Initialize stats */
bzero(&sc->vsi.eth_stats, sizeof(struct i40e_eth_stats));
ixlv_add_sysctls(sc);
- /* Register for VLAN events */
- vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
- ixlv_register_vlan, vsi, EVENTHANDLER_PRI_FIRST);
- vsi->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
- ixlv_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST);
-
/* We want AQ enabled early */
ixlv_enable_adminq_irq(hw);
@@ -443,23 +466,13 @@
ixl_vc_init_mgr(sc, &sc->vc_mgr);
INIT_DBG_DEV(dev, "end");
- return (error);
-
+ return (0);
out:
- ixlv_free_queues(vsi);
-err_res_buf:
- free(sc->vf_res, M_DEVBUF);
-err_aq:
- i40e_shutdown_adminq(hw);
-err_pci_res:
- ixlv_free_pci_resources(sc);
-err_early:
- mtx_destroy(&sc->mtx);
- ixlv_free_filters(sc);
- INIT_DBG_DEV(dev, "end: error %d", error);
+ ixlv_if_detach(ctx);
return (error);
}
+
/*********************************************************************
* Device removal routine
*
@@ -471,47 +484,19 @@
*********************************************************************/
static int
-ixlv_detach(device_t dev)
+ixlv_if_detach(if_ctx_t ctx)
{
- struct ixlv_sc *sc = device_get_softc(dev);
- struct ixl_vsi *vsi = &sc->vsi;
-
+ struct ixlv_sc *sc = iflib_get_softc(ctx);
+#ifdef IXL_DEBUG
+ device_t dev = iflib_get_dev(ctx);
+#endif
INIT_DBG_DEV(dev, "begin");
- /* Make sure VLANS are not using driver */
- if (vsi->ifp->if_vlantrunk != NULL) {
- if_printf(vsi->ifp, "Vlan in use, detach first\n");
- INIT_DBG_DEV(dev, "end");
- return (EBUSY);
- }
-
- /* Stop driver */
- ether_ifdetach(vsi->ifp);
- if (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING) {
- mtx_lock(&sc->mtx);
- ixlv_stop(sc);
- mtx_unlock(&sc->mtx);
- }
-
- /* Unregister VLAN events */
- if (vsi->vlan_attach != NULL)
- EVENTHANDLER_DEREGISTER(vlan_config, vsi->vlan_attach);
- if (vsi->vlan_detach != NULL)
- EVENTHANDLER_DEREGISTER(vlan_unconfig, vsi->vlan_detach);
-
- /* Drain VC mgr */
- callout_drain(&sc->vc_mgr.callout);
-
i40e_shutdown_adminq(&sc->hw);
- taskqueue_free(sc->tq);
- if_free(vsi->ifp);
- free(sc->vf_res, M_DEVBUF);
+ free(sc->vf_res, M_IXL);
ixlv_free_pci_resources(sc);
- ixlv_free_queues(vsi);
- mtx_destroy(&sc->mtx);
ixlv_free_filters(sc);
- bus_generic_detach(dev);
INIT_DBG_DEV(dev, "end");
return (0);
}
@@ -523,20 +508,20 @@
**********************************************************************/
static int
-ixlv_shutdown(device_t dev)
+ixlv_if_shutdown(if_ctx_t ctx)
{
- struct ixlv_sc *sc = device_get_softc(dev);
-
+#ifdef IXL_DEBUG
+ device_t dev = iflib_get_dev(ctx);
+#endif
INIT_DBG_DEV(dev, "begin");
- mtx_lock(&sc->mtx);
- ixlv_stop(sc);
- mtx_unlock(&sc->mtx);
+ ixlv_if_stop(ctx);
INIT_DBG_DEV(dev, "end");
return (0);
}
+#ifdef notyet
/*
* Configure TXCSUM(IPV6) and TSO(4/6)
* - the hardware handles these together so we
@@ -612,6 +597,8 @@
}
}
+#endif
+
/*********************************************************************
* Ioctl entry point
*
@@ -620,7 +607,7 @@
*
* return 0 on success, positive on failure
**********************************************************************/
-
+#if 0
static int
ixlv_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
@@ -664,58 +651,32 @@
#endif
case SIOCSIFMTU:
IOCTL_DBG_IF2(ifp, "SIOCSIFMTU (Set Interface MTU)");
- mtx_lock(&sc->mtx);
- if (ifr->ifr_mtu > IXL_MAX_FRAME -
- ETHER_HDR_LEN - ETHER_CRC_LEN - ETHER_VLAN_ENCAP_LEN) {
- error = EINVAL;
- IOCTL_DBG_IF(ifp, "mtu too large");
- } else {
- IOCTL_DBG_IF2(ifp, "mtu: %lu -> %d", ifp->if_mtu, ifr->ifr_mtu);
- // ERJ: Interestingly enough, these types don't match
- ifp->if_mtu = (u_long)ifr->ifr_mtu;
- vsi->max_frame_size =
- ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN
- + ETHER_VLAN_ENCAP_LEN;
- ixlv_init_locked(sc);
- }
- mtx_unlock(&sc->mtx);
+
break;
- case SIOCSIFFLAGS:
- IOCTL_DBG_IF2(ifp, "SIOCSIFFLAGS (Set Interface Flags)");
- mtx_lock(&sc->mtx);
- if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- ixlv_init_locked(sc);
- } else
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ixlv_stop(sc);
- sc->if_flags = ifp->if_flags;
- mtx_unlock(&sc->mtx);
+
break;
case SIOCADDMULTI:
+#if 0
IOCTL_DBG_IF2(ifp, "SIOCADDMULTI");
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- mtx_lock(&sc->mtx);
- ixlv_disable_intr(vsi);
+
ixlv_add_multi(vsi);
- ixlv_enable_intr(vsi);
- mtx_unlock(&sc->mtx);
+
}
break;
+#endif
case SIOCDELMULTI:
IOCTL_DBG_IF2(ifp, "SIOCDELMULTI");
if (sc->init_state == IXLV_RUNNING) {
- mtx_lock(&sc->mtx);
- ixlv_disable_intr(vsi);
+
ixlv_del_multi(vsi);
- ixlv_enable_intr(vsi);
- mtx_unlock(&sc->mtx);
+
}
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
IOCTL_DBG_IF2(ifp, "SIOCxIFMEDIA (Get/Set Interface Media)");
- error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
+ error = ifmedia_ioctl(ifp, ifr, sc->media, command);
break;
case SIOCSIFCAP:
{
@@ -752,6 +713,7 @@
return (error);
}
+#endif
/*
** To do a reinit on the VF is unfortunately more complicated
@@ -774,7 +736,7 @@
INIT_DBG_IF(ifp, "begin");
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ixlv_stop(sc);
+ ixlv_if_stop(sc->vsi.ctx);
error = ixlv_reset(sc);
@@ -791,7 +753,7 @@
if (mf->flags & IXL_FILTER_DEL) {
SLIST_REMOVE(sc->mac_filters, mf,
ixlv_mac_filter, next);
- free(mf, M_DEVBUF);
+ free(mf, M_IXL);
} else
mf->flags |= IXL_FILTER_ADD;
}
@@ -802,7 +764,7 @@
while (!SLIST_EMPTY(sc->vlan_filters)) {
vf = SLIST_FIRST(sc->vlan_filters);
SLIST_REMOVE_HEAD(sc->vlan_filters, next);
- free(vf, M_DEVBUF);
+ free(vf, M_IXL);
}
}
@@ -834,8 +796,9 @@
}
static void
-ixlv_init_locked(struct ixlv_sc *sc)
+ixlv_init_internal(if_ctx_t ctx)
{
+ struct ixlv_sc *sc = iflib_get_softc(ctx);
struct i40e_hw *hw = &sc->hw;
struct ixl_vsi *vsi = &sc->vsi;
struct ixl_queue *que = vsi->queues;
@@ -844,8 +807,6 @@
INIT_DBG_IF(ifp, "begin");
- IXLV_CORE_LOCK_ASSERT(sc);
-
/* Do a reinit first if an init has already been done */
if ((sc->init_state == IXLV_RUNNING) ||
(sc->init_state == IXLV_RESET_REQUIRED) ||
@@ -887,17 +848,11 @@
/* Setup vlan's if needed */
ixlv_setup_vlan_filters(sc);
+ ixlv_init_multi(&sc->vsi);
+
/* Prepare the queues for operation */
for (int i = 0; i < vsi->num_queues; i++, que++) {
- struct rx_ring *rxr = &que->rxr;
-
- ixl_init_tx_ring(que);
-
- if (vsi->max_frame_size <= MCLBYTES)
- rxr->mbuf_sz = MCLBYTES;
- else
- rxr->mbuf_sz = MJUMPAGESIZE;
- ixl_init_rx_ring(que);
+ ixl_init_tx_ring(vsi, que);
}
/* Configure queues */
@@ -915,40 +870,39 @@
ixl_vc_enqueue(&sc->vc_mgr, &sc->enable_queues_cmd,
IXLV_FLAG_AQ_ENABLE_QUEUES, ixl_init_cmd_complete, sc);
- /* Start the local timer */
- callout_reset(&sc->timer, hz, ixlv_local_timer, sc);
-
sc->init_state = IXLV_RUNNING;
init_done:
INIT_DBG_IF(ifp, "end");
- return;
}
-/*
-** Init entry point for the stack
-*/
-void
-ixlv_init(void *arg)
+static void
+ixlv_if_init(if_ctx_t ctx)
{
- struct ixl_vsi *vsi = (struct ixl_vsi *)arg;
- struct ixlv_sc *sc = vsi->back;
- int retries = 0;
+ struct ifnet *ifp;
+ int retries;
- mtx_lock(&sc->mtx);
- ixlv_init_locked(sc);
- mtx_unlock(&sc->mtx);
+ ixlv_init_internal(ctx);
- /* Wait for init_locked to finish */
- while (!(vsi->ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ifp = iflib_get_ifp(ctx);
+ retries = 0;
+ /* Wait for init to finish */
+ while (!(ifp->if_drv_flags & IFF_DRV_RUNNING)
&& ++retries < 100) {
i40e_msec_delay(10);
}
if (retries >= IXLV_AQ_MAX_ERR)
- if_printf(vsi->ifp,
+ if_printf(ifp,
"Init failed to complete in alloted time!\n");
+
}
+void
+ixlv_init(void *arg)
+{
+ struct ixlv_sc *sc = arg;
+ ixlv_if_init(sc->vsi.ctx);
+}
/*
* ixlv_attach() helper function; gathers information about
* the (virtual) hardware for use elsewhere in the driver.
@@ -1103,7 +1057,7 @@
if (!sc->vf_res) {
bufsz = sizeof(struct i40e_virtchnl_vf_resource) +
(I40E_MAX_VF_VSI * sizeof(struct i40e_virtchnl_vsi_resource));
- sc->vf_res = malloc(bufsz, M_DEVBUF, M_NOWAIT);
+ sc->vf_res = malloc(bufsz, M_IXL, M_NOWAIT);
if (!sc->vf_res) {
device_printf(dev,
"%s: Unable to allocate memory for VF configuration"
@@ -1131,139 +1085,17 @@
goto done;
fail:
- free(sc->vf_res, M_DEVBUF);
+ free(sc->vf_res, M_IXL);
done:
return (ret_error);
}
-/*
- * Allocate MSI/X vectors, setup the AQ vector early
- */
-static int
-ixlv_init_msix(struct ixlv_sc *sc)
-{
- device_t dev = sc->dev;
- int rid, want, vectors, queues, available;
-
- rid = PCIR_BAR(IXL_BAR);
- sc->msix_mem = bus_alloc_resource_any(dev,
- SYS_RES_MEMORY, &rid, RF_ACTIVE);
- if (!sc->msix_mem) {
- /* May not be enabled */
- device_printf(sc->dev,
- "Unable to map MSIX table \n");
- goto fail;
- }
-
- available = pci_msix_count(dev);
- if (available == 0) { /* system has msix disabled */
- bus_release_resource(dev, SYS_RES_MEMORY,
- rid, sc->msix_mem);
- sc->msix_mem = NULL;
- goto fail;
- }
-
- /* Figure out a reasonable auto config value */
- queues = (mp_ncpus > (available - 1)) ? (available - 1) : mp_ncpus;
-
- /* Override with hardcoded value if sane */
- if ((ixlv_max_queues != 0) && (ixlv_max_queues <= queues))
- queues = ixlv_max_queues;
-#ifdef RSS
- /* If we're doing RSS, clamp at the number of RSS buckets */
- if (queues > rss_getnumbuckets())
- queues = rss_getnumbuckets();
-#endif
+#if 0
/* Enforce the VF max value */
if (queues > IXLV_MAX_QUEUES)
queues = IXLV_MAX_QUEUES;
-
- /*
- ** Want one vector (RX/TX pair) per queue
- ** plus an additional for the admin queue.
- */
- want = queues + 1;
- if (want <= available) /* Have enough */
- vectors = want;
- else {
- device_printf(sc->dev,
- "MSIX Configuration Problem, "
- "%d vectors available but %d wanted!\n",
- available, want);
- goto fail;
- }
-
-#ifdef RSS
- /*
- * If we're doing RSS, the number of queues needs to
- * match the number of RSS buckets that are configured.
- *
- * + If there's more queues than RSS buckets, we'll end
- * up with queues that get no traffic.
- *
- * + If there's more RSS buckets than queues, we'll end
- * up having multiple RSS buckets map to the same queue,
- * so there'll be some contention.
- */
- if (queues != rss_getnumbuckets()) {
- device_printf(dev,
- "%s: queues (%d) != RSS buckets (%d)"
- "; performance will be impacted.\n",
- __func__, queues, rss_getnumbuckets());
- }
#endif
- if (pci_alloc_msix(dev, &vectors) == 0) {
- device_printf(sc->dev,
- "Using MSIX interrupts with %d vectors\n", vectors);
- sc->msix = vectors;
- sc->vsi.num_queues = queues;
- }
-
- /*
- ** Explicitly set the guest PCI BUSMASTER capability
- ** and we must rewrite the ENABLE in the MSIX control
- ** register again at this point to cause the host to
- ** successfully initialize us.
- */
- {
- u16 pci_cmd_word;
- int msix_ctrl;
- pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2);
- pci_cmd_word |= PCIM_CMD_BUSMASTEREN;
- pci_write_config(dev, PCIR_COMMAND, pci_cmd_word, 2);
- pci_find_cap(dev, PCIY_MSIX, &rid);
- rid += PCIR_MSIX_CTRL;
- msix_ctrl = pci_read_config(dev, rid, 2);
- msix_ctrl |= PCIM_MSIXCTRL_MSIX_ENABLE;
- pci_write_config(dev, rid, msix_ctrl, 2);
- }
-
- /* Next we need to setup the vector for the Admin Queue */
- rid = 1; // zero vector + 1
- sc->res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &rid, RF_SHAREABLE | RF_ACTIVE);
- if (sc->res == NULL) {
- device_printf(dev,"Unable to allocate"
- " bus resource: AQ interrupt \n");
- goto fail;
- }
- if (bus_setup_intr(dev, sc->res,
- INTR_TYPE_NET | INTR_MPSAFE, NULL,
- ixlv_msix_adminq, sc, &sc->tag)) {
- sc->res = NULL;
- device_printf(dev, "Failed to register AQ handler");
- goto fail;
- }
- bus_describe_intr(dev, sc->res, sc->tag, "adminq");
-
- return (vectors);
-
-fail:
- /* The VF driver MUST use MSIX */
- return (0);
-}
-
static int
ixlv_allocate_pci_resources(struct ixlv_sc *sc)
{
@@ -1279,10 +1111,8 @@
return (ENXIO);
}
- sc->osdep.mem_bus_space_tag =
- rman_get_bustag(sc->pci_mem);
- sc->osdep.mem_bus_space_handle =
- rman_get_bushandle(sc->pci_mem);
+ sc->osdep.mem_bus_space_tag = rman_get_bustag(sc->pci_mem);
+ sc->osdep.mem_bus_space_handle = rman_get_bushandle(sc->pci_mem);
sc->osdep.mem_bus_space_size = rman_get_size(sc->pci_mem);
sc->osdep.flush_reg = I40E_VFGEN_RSTAT;
sc->hw.hw_addr = (u8 *) &sc->osdep.mem_bus_space_handle;
@@ -1292,145 +1122,18 @@
/* Disable adminq interrupts */
ixlv_disable_adminq_irq(&sc->hw);
- /*
- ** Now setup MSI/X, it will return
- ** us the number of supported vectors
- */
- sc->msix = ixlv_init_msix(sc);
-
- /* We fail without MSIX support */
- if (sc->msix == 0)
- return (ENXIO);
-
return (0);
}
static void
ixlv_free_pci_resources(struct ixlv_sc *sc)
{
- struct ixl_vsi *vsi = &sc->vsi;
- struct ixl_queue *que = vsi->queues;
device_t dev = sc->dev;
- /* We may get here before stations are setup */
- if (que == NULL)
- goto early;
-
- /*
- ** Release all msix queue resources:
- */
- for (int i = 0; i < vsi->num_queues; i++, que++) {
- int rid = que->msix + 1;
- if (que->tag != NULL) {
- bus_teardown_intr(dev, que->res, que->tag);
- que->tag = NULL;
- }
- if (que->res != NULL)
- bus_release_resource(dev, SYS_RES_IRQ, rid, que->res);
- }
-
-early:
- /* Clean the AdminQ interrupt */
- if (sc->tag != NULL) {
- bus_teardown_intr(dev, sc->res, sc->tag);
- sc->tag = NULL;
- }
- if (sc->res != NULL)
- bus_release_resource(dev, SYS_RES_IRQ, 1, sc->res);
-
- pci_release_msi(dev);
-
- if (sc->msix_mem != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY,
- PCIR_BAR(IXL_BAR), sc->msix_mem);
-
if (sc->pci_mem != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
PCIR_BAR(0), sc->pci_mem);
- return;
-}
-
-/*
- * Create taskqueue and tasklet for Admin Queue interrupts.
- */
-static int
-ixlv_init_taskqueue(struct ixlv_sc *sc)
-{
- int error = 0;
-
- TASK_INIT(&sc->aq_irq, 0, ixlv_do_adminq, sc);
-
- sc->tq = taskqueue_create_fast("ixl_adm", M_NOWAIT,
- taskqueue_thread_enqueue, &sc->tq);
- taskqueue_start_threads(&sc->tq, 1, PI_NET, "%s sc->tq",
- device_get_nameunit(sc->dev));
-
- return (error);
-}
-
-/*********************************************************************
- *
- * Setup MSIX Interrupt resources and handlers for the VSI queues
- *
- **********************************************************************/
-static int
-ixlv_assign_msix(struct ixlv_sc *sc)
-{
- device_t dev = sc->dev;
- struct ixl_vsi *vsi = &sc->vsi;
- struct ixl_queue *que = vsi->queues;
- struct tx_ring *txr;
- int error, rid, vector = 1;
-#ifdef RSS
- cpuset_t cpu_mask;
-#endif
-
- for (int i = 0; i < vsi->num_queues; i++, vector++, que++) {
- int cpu_id = i;
- rid = vector + 1;
- txr = &que->txr;
- que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
- if (que->res == NULL) {
- device_printf(dev,"Unable to allocate"
- " bus resource: que interrupt [%d]\n", vector);
- return (ENXIO);
- }
- /* Set the handler function */
- error = bus_setup_intr(dev, que->res,
- INTR_TYPE_NET | INTR_MPSAFE, NULL,
- ixlv_msix_que, que, &que->tag);
- if (error) {
- que->res = NULL;
- device_printf(dev, "Failed to register que handler");
- return (error);
- }
- bus_describe_intr(dev, que->res, que->tag, "que %d", i);
- /* Bind the vector to a CPU */
-#ifdef RSS
- cpu_id = rss_getcpu(i % rss_getnumbuckets());
-#endif
- bus_bind_intr(dev, que->res, cpu_id);
- que->msix = vector;
- vsi->que_mask |= (u64)(1 << que->msix);
- TASK_INIT(&que->tx_task, 0, ixl_deferred_mq_start, que);
- TASK_INIT(&que->task, 0, ixlv_handle_que, que);
- que->tq = taskqueue_create_fast("ixlv_que", M_NOWAIT,
- taskqueue_thread_enqueue, &que->tq);
-#ifdef RSS
- CPU_SETOF(cpu_id, &cpu_mask);
- taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET,
- &cpu_mask, "%s (bucket %d)",
- device_get_nameunit(dev), cpu_id);
-#else
- taskqueue_start_threads(&que->tq, 1, PI_NET,
- "%s que", device_get_nameunit(dev));
-#endif
-
- }
-
- return (0);
}
/*
@@ -1492,48 +1195,77 @@
return (EBUSY);
}
-
/*********************************************************************
*
- * Setup networking device structure and register an interface.
+ * Setup MSIX Interrupt resources and handlers for the VSI
*
**********************************************************************/
static int
-ixlv_setup_interface(device_t dev, struct ixlv_sc *sc)
+ixlv_if_msix_intr_assign(if_ctx_t ctx, int msix)
{
- struct ifnet *ifp;
- struct ixl_vsi *vsi = &sc->vsi;
- struct ixl_queue *que = vsi->queues;
+ struct ixl_vsi *vsi = iflib_get_softc(ctx);
+ struct ixl_pf *pf = vsi->back;
+ struct ixl_queue *que = vsi->queues;
+ int err, rid, vector = 0;
- INIT_DBG_DEV(dev, "begin");
+ /* Admin Que is vector 0*/
+ rid = vector + 1;
- ifp = vsi->ifp = if_alloc(IFT_ETHER);
- if (ifp == NULL) {
- device_printf(dev, "%s: could not allocate ifnet"
- " structure!\n", __func__);
- return (-1);
+ err = iflib_irq_alloc_generic(ctx, &vsi->irq, rid, IFLIB_INTR_ADMIN,
+ ixlv_msix_adminq, pf, 0, "aq");
+ if (err) {
+ iflib_irq_free(ctx, &vsi->irq);
+ device_printf(iflib_get_dev(ctx), "Failed to register Admin que handler");
+ return (err);
}
+ ++vector;
+ iflib_softirq_alloc_generic(ctx, rid, IFLIB_INTR_IOV, pf, 0, "ixl_iov");
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ /* Now set up the stations */
+ for (int i = 0; i < vsi->num_queues; i++, vector++, que++) {
+ char buf[16];
+ rid = vector + 1;
- ifp->if_mtu = ETHERMTU;
- ifp->if_baudrate = 4000000000; // ??
- ifp->if_init = ixlv_init;
- ifp->if_softc = vsi;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_ioctl = ixlv_ioctl;
+ snprintf(buf, sizeof(buf), "rxq%d", i);
+ err = iflib_irq_alloc_generic(ctx, &que->que_irq, rid, IFLIB_INTR_RX,
+ ixlv_msix_que, que, que->me, buf);
+ if (err) {
+ device_printf(iflib_get_dev(ctx), "Failed to allocate q int %d err: %d", i, err);
+ vsi->num_queues = i + 1;
+ goto fail;
+ }
+ snprintf(buf, sizeof(buf), "txq%d", i);
+ iflib_softirq_alloc_generic(ctx, rid, IFLIB_INTR_TX, que, que->me, buf);
+ que->msix = vector;
+ }
-#if __FreeBSD_version >= 1100000
- if_setgetcounterfn(ifp, ixl_get_counter);
-#endif
+ return (0);
+fail:
+ iflib_irq_free(ctx, &vsi->irq);
+ que = vsi->queues;
+ for (int i = 0; i < vsi->num_queues; i++, que++)
+ iflib_irq_free(ctx, &que->que_irq);
+ return (err);
+}
- ifp->if_transmit = ixl_mq_start;
+/*********************************************************************
+ *
+ * Setup networking device structure and register an interface.
+ *
+ **********************************************************************/
+static int
+ixlv_setup_interface(if_ctx_t ctx)
+{
+ struct ifnet *ifp;
+ struct ixlv_sc *sc = iflib_get_softc(ctx);
+ struct ixl_vsi *vsi = &sc->vsi;
- ifp->if_qflush = ixl_qflush;
- ifp->if_snd.ifq_maxlen = que->num_desc - 2;
+ INIT_DBG_DEV(dev, "begin");
- ether_ifattach(ifp, sc->hw.mac.addr);
+ ifp = vsi->ifp = iflib_get_ifp(ctx);
+ if_setbaudrate(ifp, 4000000000);
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
vsi->max_frame_size =
ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN
+ ETHER_VLAN_ENCAP_LEN;
@@ -1565,150 +1297,16 @@
*/
ifp->if_capabilities |= IFCAP_VLAN_HWFILTER;
- /*
- * Specify the media types supported by this adapter and register
- * callbacks to update media and link information
- */
- ifmedia_init(&sc->media, IFM_IMASK, ixlv_media_change,
- ixlv_media_status);
-
// JFV Add media types later?
- ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
- ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO);
+ ifmedia_add(sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
+ ifmedia_set(sc->media, IFM_ETHER | IFM_AUTO);
INIT_DBG_DEV(dev, "end");
return (0);
}
/*
-** Allocate and setup the interface queues
-*/
-static int
-ixlv_setup_queues(struct ixlv_sc *sc)
-{
- device_t dev = sc->dev;
- struct ixl_vsi *vsi;
- struct ixl_queue *que;
- struct tx_ring *txr;
- struct rx_ring *rxr;
- int rsize, tsize;
- int error = I40E_SUCCESS;
-
- vsi = &sc->vsi;
- vsi->back = (void *)sc;
- vsi->hw = &sc->hw;
- vsi->num_vlans = 0;
-
- /* Get memory for the station queues */
- if (!(vsi->queues =
- (struct ixl_queue *) malloc(sizeof(struct ixl_queue) *
- vsi->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
- device_printf(dev, "Unable to allocate queue memory\n");
- error = ENOMEM;
- goto early;
- }
-
- for (int i = 0; i < vsi->num_queues; i++) {
- que = &vsi->queues[i];
- que->num_desc = ixlv_ringsz;
- que->me = i;
- que->vsi = vsi;
- /* mark the queue as active */
- vsi->active_queues |= (u64)1 << que->me;
-
- txr = &que->txr;
- txr->que = que;
- txr->tail = I40E_QTX_TAIL1(que->me);
- /* Initialize the TX lock */
- snprintf(txr->mtx_name, sizeof(txr->mtx_name), "%s:tx(%d)",
- device_get_nameunit(dev), que->me);
- mtx_init(&txr->mtx, txr->mtx_name, NULL, MTX_DEF);
- /*
- ** Create the TX descriptor ring, the extra int is
- ** added as the location for HEAD WB.
- */
- tsize = roundup2((que->num_desc *
- sizeof(struct i40e_tx_desc)) +
- sizeof(u32), DBA_ALIGN);
- if (i40e_allocate_dma_mem(&sc->hw,
- &txr->dma, i40e_mem_reserved, tsize, DBA_ALIGN)) {
- device_printf(dev,
- "Unable to allocate TX Descriptor memory\n");
- error = ENOMEM;
- goto fail;
- }
- txr->base = (struct i40e_tx_desc *)txr->dma.va;
- bzero((void *)txr->base, tsize);
- /* Now allocate transmit soft structs for the ring */
- if (ixl_allocate_tx_data(que)) {
- device_printf(dev,
- "Critical Failure setting up TX structures\n");
- error = ENOMEM;
- goto fail;
- }
- /* Allocate a buf ring */
- txr->br = buf_ring_alloc(ixlv_txbrsz, M_DEVBUF,
- M_WAITOK, &txr->mtx);
- if (txr->br == NULL) {
- device_printf(dev,
- "Critical Failure setting up TX buf ring\n");
- error = ENOMEM;
- goto fail;
- }
-
- /*
- * Next the RX queues...
- */
- rsize = roundup2(que->num_desc *
- sizeof(union i40e_rx_desc), DBA_ALIGN);
- rxr = &que->rxr;
- rxr->que = que;
- rxr->tail = I40E_QRX_TAIL1(que->me);
-
- /* Initialize the RX side lock */
- snprintf(rxr->mtx_name, sizeof(rxr->mtx_name), "%s:rx(%d)",
- device_get_nameunit(dev), que->me);
- mtx_init(&rxr->mtx, rxr->mtx_name, NULL, MTX_DEF);
-
- if (i40e_allocate_dma_mem(&sc->hw,
- &rxr->dma, i40e_mem_reserved, rsize, 4096)) { //JFV - should this be DBA?
- device_printf(dev,
- "Unable to allocate RX Descriptor memory\n");
- error = ENOMEM;
- goto fail;
- }
- rxr->base = (union i40e_rx_desc *)rxr->dma.va;
- bzero((void *)rxr->base, rsize);
-
- /* Allocate receive soft structs for the ring*/
- if (ixl_allocate_rx_data(que)) {
- device_printf(dev,
- "Critical Failure setting up receive structs\n");
- error = ENOMEM;
- goto fail;
- }
- }
-
- return (0);
-
-fail:
- for (int i = 0; i < vsi->num_queues; i++) {
- que = &vsi->queues[i];
- rxr = &que->rxr;
- txr = &que->txr;
- if (rxr->base)
- i40e_free_dma_mem(&sc->hw, &rxr->dma);
- if (txr->base)
- i40e_free_dma_mem(&sc->hw, &txr->dma);
- }
- free(vsi->queues, M_DEVBUF);
-
-early:
- return (error);
-}
-
-/*
** This routine is run via an vlan config EVENT,
** it enables us to use the HW Filter table since
** we can get the vlan id. This just creates the
@@ -1716,16 +1314,13 @@
** repopulate the real table.
*/
static void
-ixlv_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
+ixlv_if_vlan_register(if_ctx_t ctx, u16 vtag)
{
- struct ixl_vsi *vsi = arg;
- struct ixlv_sc *sc = vsi->back;
+ struct ixlv_sc *sc = iflib_get_softc(ctx);
+ struct ixl_vsi *vsi = &sc->vsi;
struct ixlv_vlan_filter *v;
- if (ifp->if_softc != arg) /* Not our event */
- return;
-
if ((vtag == 0) || (vtag > 4095)) /* Invalid */
return;
@@ -1735,16 +1330,15 @@
return;
}
- mtx_lock(&sc->mtx);
++vsi->num_vlans;
- v = malloc(sizeof(struct ixlv_vlan_filter), M_DEVBUF, M_NOWAIT | M_ZERO);
+ /* should either fail or be M_WAITOK XXX */
+ v = malloc(sizeof(struct ixlv_vlan_filter), M_IXL, M_NOWAIT | M_ZERO);
+
SLIST_INSERT_HEAD(sc->vlan_filters, v, next);
v->vlan = vtag;
v->flags = IXL_FILTER_ADD;
ixl_vc_enqueue(&sc->vc_mgr, &sc->add_vlan_cmd,
IXLV_FLAG_AQ_ADD_VLAN_FILTER, ixl_init_cmd_complete, sc);
- mtx_unlock(&sc->mtx);
- return;
}
/*
@@ -1753,20 +1347,15 @@
** in the soft vfta.
*/
static void
-ixlv_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
+ixlv_if_vlan_unregister(if_ctx_t ctx, u16 vtag)
{
- struct ixl_vsi *vsi = arg;
- struct ixlv_sc *sc = vsi->back;
+ struct ixlv_sc *sc = iflib_get_softc(ctx);
+ struct ixl_vsi *vsi = &sc->vsi;
struct ixlv_vlan_filter *v;
int i = 0;
-
- if (ifp->if_softc != arg)
- return;
-
if ((vtag == 0) || (vtag > 4095)) /* Invalid */
return;
- mtx_lock(&sc->mtx);
SLIST_FOREACH(v, sc->vlan_filters, next) {
if (v->vlan == vtag) {
v->flags = IXL_FILTER_DEL;
@@ -1777,8 +1366,6 @@
if (i)
ixl_vc_enqueue(&sc->vc_mgr, &sc->del_vlan_cmd,
IXLV_FLAG_AQ_DEL_VLAN_FILTER, ixl_init_cmd_complete, sc);
- mtx_unlock(&sc->mtx);
- return;
}
/*
@@ -1790,7 +1377,7 @@
struct ixlv_mac_filter *f;
f = malloc(sizeof(struct ixlv_mac_filter),
- M_DEVBUF, M_NOWAIT | M_ZERO);
+ M_IXL, M_NOWAIT | M_ZERO);
if (f)
SLIST_INSERT_HEAD(sc->mac_filters, f, next);
@@ -1821,47 +1408,60 @@
/*
** Admin Queue interrupt handler
*/
-static void
+static int
ixlv_msix_adminq(void *arg)
{
struct ixlv_sc *sc = arg;
struct i40e_hw *hw = &sc->hw;
u32 reg, mask;
- reg = rd32(hw, I40E_VFINT_ICR01);
- mask = rd32(hw, I40E_VFINT_ICR0_ENA1);
+ reg = rd32(hw, I40E_VFINT_ICR01);
+ mask = rd32(hw, I40E_VFINT_ICR0_ENA1);
- reg = rd32(hw, I40E_VFINT_DYN_CTL01);
- reg |= I40E_VFINT_DYN_CTL01_CLEARPBA_MASK;
- wr32(hw, I40E_VFINT_DYN_CTL01, reg);
-
- /* schedule task */
- taskqueue_enqueue(sc->tq, &sc->aq_irq);
- return;
+ reg = rd32(hw, I40E_VFINT_DYN_CTL01);
+ reg |= I40E_VFINT_DYN_CTL01_CLEARPBA_MASK;
+ wr32(hw, I40E_VFINT_DYN_CTL01, reg);
+ iflib_admin_intr_deferred(sc->vsi.ctx);
+ return (FILTER_HANDLED);
}
void
-ixlv_enable_intr(struct ixl_vsi *vsi)
+ixlv_if_intr_enable(if_ctx_t ctx)
{
+ struct ixlv_sc *sc = iflib_get_softc(ctx);
+ struct ixl_vsi *vsi = &sc->vsi;
struct i40e_hw *hw = vsi->hw;
struct ixl_queue *que = vsi->queues;
ixlv_enable_adminq_irq(hw);
for (int i = 0; i < vsi->num_queues; i++, que++)
- ixlv_enable_queue_irq(hw, que->me);
+ ixlv_if_queue_intr_enable(ctx, que->me);
}
void
-ixlv_disable_intr(struct ixl_vsi *vsi)
+ixlv_enable_intr(struct ixl_vsi *vsi)
{
- struct i40e_hw *hw = vsi->hw;
- struct ixl_queue *que = vsi->queues;
+ ixlv_if_intr_enable(vsi->ctx);
+}
+
+void
+ixlv_if_intr_disable(if_ctx_t ctx)
+{
+ struct ixlv_sc *sc = iflib_get_softc(ctx);
+ struct ixl_vsi *vsi = &sc->vsi;
+ struct i40e_hw *hw = vsi->hw;
+ struct ixl_queue *que = vsi->queues;
ixlv_disable_adminq_irq(hw);
for (int i = 0; i < vsi->num_queues; i++, que++)
- ixlv_disable_queue_irq(hw, que->me);
+ ixlv_if_queue_intr_disable(ctx, que->me);
}
+void
+ixlv_disable_intr(struct ixl_vsi *vsi)
+{
+ ixlv_if_intr_disable(vsi->ctx);
+}
static void
ixlv_disable_adminq_irq(struct i40e_hw *hw)
@@ -1886,8 +1486,11 @@
}
static void
-ixlv_enable_queue_irq(struct i40e_hw *hw, int id)
+ixlv_if_queue_intr_enable(if_ctx_t ctx, uint16_t id)
{
+ struct ixlv_sc *sc = iflib_get_softc(ctx);
+ struct ixl_vsi *vsi = &sc->vsi;
+ struct i40e_hw *hw = vsi->hw;
u32 reg;
reg = I40E_VFINT_DYN_CTLN1_INTENA_MASK |
@@ -1896,11 +1499,14 @@
}
static void
-ixlv_disable_queue_irq(struct i40e_hw *hw, int id)
+ixlv_if_queue_intr_disable(if_ctx_t ctx, uint16_t qid)
{
- wr32(hw, I40E_VFINT_DYN_CTLN1(id), 0);
+ struct ixlv_sc *sc = iflib_get_softc(ctx);
+ struct ixl_vsi *vsi = &sc->vsi;
+ struct i40e_hw *hw = vsi->hw;
+
+ wr32(hw, I40E_VFINT_DYN_CTLN1(qid), 0);
rd32(hw, I40E_VFGEN_RSTAT);
- return;
}
@@ -2051,83 +1657,28 @@
return;
}
-
-/*
-**
-** MSIX Interrupt Handlers and Tasklets
-**
-*/
-static void
-ixlv_handle_que(void *context, int pending)
-{
- struct ixl_queue *que = context;
- struct ixl_vsi *vsi = que->vsi;
- struct i40e_hw *hw = vsi->hw;
- struct tx_ring *txr = &que->txr;
- struct ifnet *ifp = vsi->ifp;
- bool more;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- more = ixl_rxeof(que, IXL_RX_LIMIT);
- mtx_lock(&txr->mtx);
- ixl_txeof(que);
- if (!drbr_empty(ifp, txr->br))
- ixl_mq_start_locked(ifp, txr);
- mtx_unlock(&txr->mtx);
- if (more) {
- taskqueue_enqueue(que->tq, &que->task);
- return;
- }
- }
-
- /* Reenable this interrupt - hmmm */
- ixlv_enable_queue_irq(hw, que->me);
- return;
-}
-
-
/*********************************************************************
*
* MSIX Queue Interrupt Service routine
*
**********************************************************************/
-static void
+static int
ixlv_msix_que(void *arg)
{
struct ixl_queue *que = arg;
- struct ixl_vsi *vsi = que->vsi;
- struct i40e_hw *hw = vsi->hw;
- struct tx_ring *txr = &que->txr;
- bool more_tx, more_rx;
-
- /* Spurious interrupts are ignored */
- if (!(vsi->ifp->if_drv_flags & IFF_DRV_RUNNING))
- return;
-
- ++que->irqs;
-
- more_rx = ixl_rxeof(que, IXL_RX_LIMIT);
-
- mtx_lock(&txr->mtx);
- more_tx = ixl_txeof(que);
- /*
- ** Make certain that if the stack
- ** has anything queued the task gets
- ** scheduled to handle it.
- */
- if (!drbr_empty(vsi->ifp, txr->br))
- more_tx = 1;
- mtx_unlock(&txr->mtx);
ixlv_set_queue_rx_itr(que);
ixlv_set_queue_tx_itr(que);
+ return (FILTER_SCHEDULE_THREAD);
+}
- if (more_tx || more_rx)
- taskqueue_enqueue(que->tq, &que->task);
- else
- ixlv_enable_queue_irq(hw, que->me);
- return;
+/* XXX */
+void
+ixlv_update_link_status(struct ixlv_sc *sc)
+{
+ /* satisfy linker for the moment */
+ ;
}
@@ -2140,14 +1691,11 @@
*
**********************************************************************/
static void
-ixlv_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
+ixlv_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr)
{
- struct ixl_vsi *vsi = ifp->if_softc;
- struct ixlv_sc *sc = vsi->back;
-
+ struct ixlv_sc *sc = iflib_get_softc(ctx);
INIT_DBG_IF(ifp, "begin");
- mtx_lock(&sc->mtx);
ixlv_update_link_status(sc);
@@ -2155,7 +1703,6 @@
ifmr->ifm_active = IFM_ETHER;
if (!sc->link_up) {
- mtx_unlock(&sc->mtx);
INIT_DBG_IF(ifp, "end: link not up");
return;
}
@@ -2163,36 +1710,10 @@
ifmr->ifm_status |= IFM_ACTIVE;
/* Hardware is always full-duplex */
ifmr->ifm_active |= IFM_FDX;
- mtx_unlock(&sc->mtx);
INIT_DBG_IF(ifp, "end");
- return;
}
/*********************************************************************
- *
- * Media Ioctl callback
- *
- * This routine is called when the user changes speed/duplex using
- * media/mediopt option with ifconfig.
- *
- **********************************************************************/
-static int
-ixlv_media_change(struct ifnet * ifp)
-{
- struct ixl_vsi *vsi = ifp->if_softc;
- struct ifmedia *ifm = &vsi->media;
-
- INIT_DBG_IF(ifp, "begin");
-
- if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
- return (EINVAL);
-
- INIT_DBG_IF(ifp, "end");
- return (0);
-}
-
-
-/*********************************************************************
* Multicast Initialization
*
* This routine is called by init to reset a fresh state.
@@ -2224,51 +1745,37 @@
IOCTL_DBG_IF(vsi->ifp, "end");
}
+static int
+ixlv_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int count __unused)
+{
+ struct ixlv_sc *sc = arg;
+
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ return (0);
+ if (!ixlv_add_mac_filter(sc,
+ (u8*)LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
+ IXL_FILTER_MC))
+ return (1);
+
+ return (0);
+}
static void
-ixlv_add_multi(struct ixl_vsi *vsi)
+ixlv_if_multi_set(if_ctx_t ctx)
{
- struct ifmultiaddr *ifma;
- struct ifnet *ifp = vsi->ifp;
- struct ixlv_sc *sc = vsi->back;
+ struct ixlv_sc *sc = iflib_get_softc(ctx);
int mcnt = 0;
IOCTL_DBG_IF(ifp, "begin");
- if_maddr_rlock(ifp);
- /*
- ** Get a count, to decide if we
- ** simply use multicast promiscuous.
- */
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- mcnt++;
- }
- if_maddr_runlock(ifp);
+ mcnt = if_multiaddr_count(iflib_get_ifp(ctx), MAX_MULTICAST_ADDR);
+ /* XXX */
+ ixlv_del_multi(&sc->vsi);
- // TODO: Remove -- cannot set promiscuous mode in a VF
if (__predict_false(mcnt >= MAX_MULTICAST_ADDR)) {
- /* delete all multicast filters */
- ixlv_init_multi(vsi);
- sc->promiscuous_flags |= I40E_FLAG_VF_MULTICAST_PROMISC;
- ixl_vc_enqueue(&sc->vc_mgr, &sc->add_multi_cmd,
- IXLV_FLAG_AQ_CONFIGURE_PROMISC, ixl_init_cmd_complete,
- sc);
- IOCTL_DEBUGOUT("%s: end: too many filters", __func__);
+ IOCTL_DEBUGOUT("%s: end: too many filters - no promiscuous mode in VF", __func__);
return;
}
-
- mcnt = 0;
- if_maddr_rlock(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (!ixlv_add_mac_filter(sc,
- (u8*)LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
- IXL_FILTER_MC))
- mcnt++;
- }
- if_maddr_runlock(ifp);
+ mcnt = if_multi_apply(iflib_get_ifp(ctx), ixlv_mc_filter_apply, sc);
/*
** Notify AQ task that sw filters need to be
** added to hw list
@@ -2281,6 +1788,29 @@
IOCTL_DBG_IF(ifp, "end");
}
+static int
+ixlv_if_promisc_set(if_ctx_t ctx, int flags)
+{
+ if (flags & (IFF_ALLMULTI|IFF_PROMISC))
+ return (EINVAL);
+ return (0);
+}
+
+static int
+ixlv_if_mtu_set(if_ctx_t ctx, uint32_t mtu)
+{
+ struct ixlv_sc *sc;
+
+ sc = iflib_get_softc(ctx);
+ if (mtu > IXL_MAX_FRAME - ETHER_HDR_LEN - ETHER_CRC_LEN - ETHER_VLAN_ENCAP_LEN)
+ return (EINVAL);
+ else
+ sc->vsi.max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN
+ + ETHER_VLAN_ENCAP_LEN;
+ return (0);
+}
+
+
static void
ixlv_del_multi(struct ixl_vsi *vsi)
{
@@ -2341,22 +1871,28 @@
**********************************************************************/
static void
-ixlv_local_timer(void *arg)
+ixlv_if_timer(if_ctx_t ctx, uint16_t qid)
{
- struct ixlv_sc *sc = arg;
+ struct ixlv_sc *sc = iflib_get_softc(ctx);
struct i40e_hw *hw = &sc->hw;
struct ixl_vsi *vsi = &sc->vsi;
- struct ixl_queue *que = vsi->queues;
- device_t dev = sc->dev;
- int hung = 0;
+ struct ixl_queue *que = &vsi->queues[qid];
u32 mask, val;
- IXLV_CORE_LOCK_ASSERT(sc);
-
/* If Reset is in progress just bail */
if (sc->init_state == IXLV_RESET_PENDING)
return;
+ mask = (I40E_VFINT_DYN_CTLN1_INTENA_MASK |
+ I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK);
+ /* Any queues with outstanding work get a sw irq */
+ /* should be set by encap */
+ if (que->busy)
+ wr32(hw, I40E_VFINT_DYN_CTLN1(que->me), mask);
+
+ if (qid != 0)
+ return;
+
/* Check for when PF triggers a VF reset */
val = rd32(hw, I40E_VFGEN_RSTAT) &
I40E_VFGEN_RSTAT_VFR_STATE_MASK;
@@ -2369,51 +1905,10 @@
ixlv_request_stats(sc);
+#if 0
/* clean and process any events */
taskqueue_enqueue(sc->tq, &sc->aq_irq);
-
- /*
- ** Check status on the queues for a hang
- */
- mask = (I40E_VFINT_DYN_CTLN1_INTENA_MASK |
- I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK);
-
- for (int i = 0; i < vsi->num_queues; i++,que++) {
- /* Any queues with outstanding work get a sw irq */
- if (que->busy)
- wr32(hw, I40E_VFINT_DYN_CTLN1(que->me), mask);
- /*
- ** Each time txeof runs without cleaning, but there
- ** are uncleaned descriptors it increments busy. If
- ** we get to 5 we declare it hung.
- */
- if (que->busy == IXL_QUEUE_HUNG) {
- ++hung;
- /* Mark the queue as inactive */
- vsi->active_queues &= ~((u64)1 << que->me);
- continue;
- } else {
- /* Check if we've come back from hung */
- if ((vsi->active_queues & ((u64)1 << que->me)) == 0)
- vsi->active_queues |= ((u64)1 << que->me);
- }
- if (que->busy >= IXL_MAX_TX_BUSY) {
- device_printf(dev,"Warning queue %d "
- "appears to be hung!\n", i);
- que->busy = IXL_QUEUE_HUNG;
- ++hung;
- }
- }
- /* Only reset when all queues show hung */
- if (hung == vsi->num_queues)
- goto hung;
- callout_reset(&sc->timer, hz, ixlv_local_timer, sc);
- return;
-
-hung:
- device_printf(dev, "Local Timer: TX HANG DETECTED - Resetting!!\n");
- sc->init_state = IXLV_RESET_REQUIRED;
- ixlv_init_locked(sc);
+#endif
}
/*
@@ -2421,11 +1916,12 @@
** the real check of the hardware only happens with
** a link interrupt.
*/
-void
-ixlv_update_link_status(struct ixlv_sc *sc)
+static void
+ixlv_if_update_admin_status(if_ctx_t ctx)
{
+ struct ixlv_sc *sc = iflib_get_softc(ctx);
+ struct ifnet *ifp = iflib_get_ifp(ctx);
struct ixl_vsi *vsi = &sc->vsi;
- struct ifnet *ifp = vsi->ifp;
if (sc->link_up){
if (vsi->link_active == FALSE) {
@@ -2455,69 +1951,26 @@
**********************************************************************/
static void
-ixlv_stop(struct ixlv_sc *sc)
+ixlv_if_stop(if_ctx_t ctx)
{
struct ifnet *ifp;
+ struct ixlv_sc *sc;
int start;
- ifp = sc->vsi.ifp;
+ ifp = iflib_get_ifp(ctx);
+ sc = iflib_get_softc(ctx);
INIT_DBG_IF(ifp, "begin");
- IXLV_CORE_LOCK_ASSERT(sc);
-
ixl_vc_flush(&sc->vc_mgr);
- ixlv_disable_queues(sc);
start = ticks;
while ((ifp->if_drv_flags & IFF_DRV_RUNNING) &&
((ticks - start) < hz/10))
ixlv_do_adminq_locked(sc);
- /* Stop the local timer */
- callout_stop(&sc->timer);
-
INIT_DBG_IF(ifp, "end");
}
-
-/*********************************************************************
- *
- * Free all station queue structs.
- *
- **********************************************************************/
-static void
-ixlv_free_queues(struct ixl_vsi *vsi)
-{
- struct ixlv_sc *sc = (struct ixlv_sc *)vsi->back;
- struct ixl_queue *que = vsi->queues;
-
- for (int i = 0; i < vsi->num_queues; i++, que++) {
- struct tx_ring *txr = &que->txr;
- struct rx_ring *rxr = &que->rxr;
-
- if (!mtx_initialized(&txr->mtx)) /* uninitialized */
- continue;
- IXL_TX_LOCK(txr);
- ixl_free_que_tx(que);
- if (txr->base)
- i40e_free_dma_mem(&sc->hw, &txr->dma);
- IXL_TX_UNLOCK(txr);
- IXL_TX_LOCK_DESTROY(txr);
-
- if (!mtx_initialized(&rxr->mtx)) /* uninitialized */
- continue;
- IXL_RX_LOCK(rxr);
- ixl_free_que_rx(que);
- if (rxr->base)
- i40e_free_dma_mem(&sc->hw, &rxr->dma);
- IXL_RX_UNLOCK(rxr);
- IXL_RX_LOCK_DESTROY(rxr);
-
- }
- free(vsi->queues, M_DEVBUF);
-}
-
-
/*
** ixlv_config_rss - setup RSS
**
@@ -2698,21 +2151,6 @@
return (0);
}
-/*
-** Tasklet handler for MSIX Adminq interrupts
-** - done outside interrupt context since it might sleep
-*/
-static void
-ixlv_do_adminq(void *context, int pending)
-{
- struct ixlv_sc *sc = context;
-
- mtx_lock(&sc->mtx);
- ixlv_do_adminq_locked(sc);
- mtx_unlock(&sc->mtx);
- return;
-}
-
static void
ixlv_do_adminq_locked(struct ixlv_sc *sc)
{
@@ -2724,8 +2162,6 @@
u32 reg, oldreg;
i40e_status ret;
- IXLV_CORE_LOCK_ASSERT(sc);
-
event.buf_len = IXL_AQ_BUF_SZ;
event.msg_buf = sc->aq_buffer;
v_msg = (struct i40e_virtchnl_msg *)&event.desc;
@@ -2850,9 +2286,6 @@
txr = &(queues[q].txr);
rxr = &(queues[q].rxr);
- SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "mbuf_defrag_failed",
- CTLFLAG_RD, &(queues[q].mbuf_defrag_failed),
- "m_defrag() failed");
SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "dropped",
CTLFLAG_RD, &(queues[q].dropped_pkts),
"Driver dropped packets");
@@ -2862,12 +2295,6 @@
SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "tso_tx",
CTLFLAG_RD, &(queues[q].tso),
"TSO");
- SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "tx_dma_setup",
- CTLFLAG_RD, &(queues[q].tx_dma_setup),
- "Driver tx dma failure in xmit");
- SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "no_desc_avail",
- CTLFLAG_RD, &(txr->no_desc),
- "Queue No Descriptor Available");
SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "tx_packets",
CTLFLAG_RD, &(txr->total_packets),
"Queue Packets Transmitted");
@@ -2899,10 +2326,10 @@
ixlv_init_filters(struct ixlv_sc *sc)
{
sc->mac_filters = malloc(sizeof(struct ixlv_mac_filter),
- M_DEVBUF, M_NOWAIT | M_ZERO);
+ M_IXL, M_NOWAIT | M_ZERO);
SLIST_INIT(sc->mac_filters);
sc->vlan_filters = malloc(sizeof(struct ixlv_vlan_filter),
- M_DEVBUF, M_NOWAIT | M_ZERO);
+ M_IXL, M_NOWAIT | M_ZERO);
SLIST_INIT(sc->vlan_filters);
return;
}
@@ -2916,12 +2343,12 @@
while (!SLIST_EMPTY(sc->mac_filters)) {
f = SLIST_FIRST(sc->mac_filters);
SLIST_REMOVE_HEAD(sc->mac_filters, next);
- free(f, M_DEVBUF);
+ free(f, M_IXL);
}
while (!SLIST_EMPTY(sc->vlan_filters)) {
v = SLIST_FIRST(sc->vlan_filters);
SLIST_REMOVE_HEAD(sc->vlan_filters, next);
- free(v, M_DEVBUF);
+ free(v, M_IXL);
}
return;
}
@@ -2969,4 +2396,3 @@
return error;
return (0);
}
-
Index: sys/dev/ixl/ixl.h
===================================================================
--- sys/dev/ixl/ixl.h
+++ sys/dev/ixl/ixl.h
@@ -39,8 +39,6 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/buf_ring.h>
-#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/malloc.h>
@@ -60,6 +58,7 @@
#include <net/bpf.h>
#include <net/if_types.h>
#include <net/if_vlan_var.h>
+#include <net/iflib.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
@@ -85,7 +84,6 @@
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/endian.h>
-#include <sys/taskqueue.h>
#include <sys/pcpu.h>
#include <sys/smp.h>
#include <machine/smp.h>
@@ -96,12 +94,16 @@
#include <dev/pci/pci_iov.h>
#endif
+#include "ifdi_if.h"
#include "i40e_type.h"
#include "i40e_prototype.h"
+MALLOC_DECLARE(M_IXL);
+
#if defined(IXL_DEBUG) || defined(IXL_DEBUG_SYSCTL)
#include <sys/sbuf.h>
+
#define MAC_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x"
#define MAC_FORMAT_ARGS(mac_addr) \
(mac_addr)[0], (mac_addr)[1], (mac_addr)[2], (mac_addr)[3], \
@@ -210,7 +212,7 @@
#define IXL_BAR 3
#define IXL_ADM_LIMIT 2
-#define IXL_TSO_SIZE 65535
+#define IXL_TSO_SIZE ((255*1024)-1)
#define IXL_TX_BUF_SZ ((u32) 1514)
#define IXL_AQ_BUF_SZ ((u32) 4096)
#define IXL_RX_HDR 128
@@ -226,7 +228,6 @@
#define IXL_MAX_FRAME 0x2600
#define IXL_MAX_TX_SEGS 8
#define IXL_MAX_TSO_SEGS 66
-#define IXL_SPARSE_CHAIN 6
#define IXL_QUEUE_HUNG 0x80000000
#define IXL_KEYSZ 10
@@ -304,16 +305,6 @@
#define IXL_END_OF_INTR_LNKLST 0x7FF
-#define IXL_TX_LOCK(_sc) mtx_lock(&(_sc)->mtx)
-#define IXL_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
-#define IXL_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx)
-#define IXL_TX_TRYLOCK(_sc) mtx_trylock(&(_sc)->mtx)
-#define IXL_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED)
-
-#define IXL_RX_LOCK(_sc) mtx_lock(&(_sc)->mtx)
-#define IXL_RX_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
-#define IXL_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx)
-
#if __FreeBSD_version >= 1100036
#define IXL_SET_IPACKETS(vsi, count) (vsi)->ipackets = (count)
#define IXL_SET_IERRORS(vsi, count) (vsi)->ierrors = (count)
@@ -362,17 +353,6 @@
struct ixl_tx_buf {
u32 eop_index;
- struct mbuf *m_head;
- bus_dmamap_t map;
- bus_dma_tag_t tag;
-};
-
-struct ixl_rx_buf {
- struct mbuf *m_head;
- struct mbuf *m_pack;
- struct mbuf *fmp;
- bus_dmamap_t hmap;
- bus_dmamap_t pmap;
};
/*
@@ -391,24 +371,16 @@
* The Transmit ring control struct
*/
struct tx_ring {
- struct ixl_queue *que;
- struct mtx mtx;
+ struct ixl_queue *que;
u32 tail;
- struct i40e_tx_desc *base;
- struct i40e_dma_mem dma;
- u16 next_avail;
- u16 next_to_clean;
+ struct i40e_tx_desc *tx_base;
+ uint64_t tx_paddr;
u16 atr_rate;
u16 atr_count;
u16 itr;
u16 latency;
- struct ixl_tx_buf *buffers;
- volatile u16 avail;
- u32 cmd;
- bus_dma_tag_t tx_tag;
- bus_dma_tag_t tso_tag;
- char mtx_name[16];
- struct buf_ring *br;
+ struct ixl_tx_buf *tx_buffers;
+
/* Used for Dynamic ITR calculation */
u32 packets;
@@ -416,7 +388,6 @@
/* Soft Stats */
u64 tx_bytes;
- u64 no_desc;
u64 total_packets;
};
@@ -425,24 +396,15 @@
* The Receive ring control struct
*/
struct rx_ring {
- struct ixl_queue *que;
- struct mtx mtx;
- union i40e_rx_desc *base;
- struct i40e_dma_mem dma;
- struct lro_ctrl lro;
- bool lro_enabled;
- bool hdr_split;
+ struct ixl_queue *que;
+ union i40e_rx_desc *rx_base;
+ uint64_t rx_paddr;
bool discard;
- u16 next_refresh;
- u16 next_check;
u16 itr;
u16 latency;
- char mtx_name[16];
- struct ixl_rx_buf *buffers;
+
u32 mbuf_sz;
u32 tail;
- bus_dma_tag_t htag;
- bus_dma_tag_t ptag;
/* Used for Dynamic ITR calculation */
u32 packets;
@@ -453,7 +415,6 @@
u64 rx_packets;
u64 rx_bytes;
u64 discarded;
- u64 not_done;
};
/*
@@ -465,53 +426,54 @@
u32 me;
u32 msix; /* This queue's MSIX vector */
u32 eims; /* This queue's EIMS bit */
- struct resource *res;
- void *tag;
- int num_desc; /* both tx and rx */
int busy;
struct tx_ring txr;
struct rx_ring rxr;
- struct task task;
- struct task tx_task;
- struct taskqueue *tq;
+
+ struct if_irq que_irq;
/* Queue stats */
u64 irqs;
u64 tso;
- u64 mbuf_defrag_failed;
u64 mbuf_hdr_failed;
u64 mbuf_pkt_failed;
- u64 tx_map_avail;
- u64 tx_dma_setup;
u64 dropped_pkts;
};
+#define DOWNCAST(sctx) ((struct ixl_vsi *)(sctx))
/*
** Virtual Station interface:
** there would be one of these per traffic class/type
** for now just one, and its embedded in the pf
*/
SLIST_HEAD(ixl_ftl_head, ixl_mac_filter);
+
struct ixl_vsi {
+ if_ctx_t ctx;
+ if_softc_ctx_t shared;
+
+ struct ifnet *ifp;
+ struct ifmedia *media;
+
+#define num_queues shared->isc_nqsets
+#define max_frame_size shared->isc_max_frame_size
+
void *back;
- struct ifnet *ifp;
- struct device *dev;
struct i40e_hw *hw;
- struct ifmedia media;
u64 que_mask;
int id;
u16 vsi_num;
u16 msix_base; /* station base MSIX vector */
u16 first_queue;
- u16 num_queues;
u16 rx_itr_setting;
u16 tx_itr_setting;
struct ixl_queue *queues; /* head of queues */
bool link_active;
u16 seid;
+ u32 link_speed;
+ struct if_irq irq;
u16 uplink_seid;
u16 downlink_seid;
- u16 max_frame_size;
/* MAC/VLAN Filter list */
struct ixl_ftl_head ftl;
@@ -519,8 +481,6 @@
struct i40e_aqc_vsi_properties_data info;
- eventhandler_tag vlan_attach;
- eventhandler_tag vlan_detach;
u16 num_vlans;
/* Per-VSI stats from hardware */
@@ -551,21 +511,6 @@
};
/*
-** Find the number of unrefreshed RX descriptors
-*/
-static inline u16
-ixl_rx_unrefreshed(struct ixl_queue *que)
-{
- struct rx_ring *rxr = &que->rxr;
-
- if (rxr->next_check > rxr->next_refresh)
- return (rxr->next_check - rxr->next_refresh - 1);
- else
- return ((que->num_desc + rxr->next_check) -
- rxr->next_refresh - 1);
-}
-
-/*
** Find the next available unused filter
*/
static inline struct ixl_mac_filter *
@@ -575,7 +520,7 @@
/* create a new empty filter */
f = malloc(sizeof(struct ixl_mac_filter),
- M_DEVBUF, M_NOWAIT | M_ZERO);
+ M_IXL, M_NOWAIT | M_ZERO);
if (f)
SLIST_INSERT_HEAD(&vsi->ftl, f, next);
@@ -588,14 +533,8 @@
static inline bool
cmp_etheraddr(const u8 *ea1, const u8 *ea2)
{
- bool cmp = FALSE;
-
- if ((ea1[0] == ea2[0]) && (ea1[1] == ea2[1]) &&
- (ea1[2] == ea2[2]) && (ea1[3] == ea2[3]) &&
- (ea1[4] == ea2[4]) && (ea1[5] == ea2[5]))
- cmp = TRUE;
- return (cmp);
+ return (bcmp(ea1, ea2, 6) == 0);
}
/*
@@ -632,19 +571,8 @@
/*********************************************************************
* TXRX Function prototypes
*********************************************************************/
-int ixl_allocate_tx_data(struct ixl_queue *);
-int ixl_allocate_rx_data(struct ixl_queue *);
-void ixl_init_tx_ring(struct ixl_queue *);
-int ixl_init_rx_ring(struct ixl_queue *);
-bool ixl_rxeof(struct ixl_queue *, int);
-bool ixl_txeof(struct ixl_queue *);
-int ixl_mq_start(struct ifnet *, struct mbuf *);
-int ixl_mq_start_locked(struct ifnet *, struct tx_ring *);
-void ixl_deferred_mq_start(void *, int);
-void ixl_qflush(struct ifnet *);
-void ixl_free_vsi(struct ixl_vsi *);
-void ixl_free_que_tx(struct ixl_queue *);
-void ixl_free_que_rx(struct ixl_queue *);
+void ixl_init_tx_ring(struct ixl_vsi *, struct ixl_queue *);
+
#ifdef IXL_FDIR
void ixl_atr(struct ixl_queue *, struct tcphdr *, int);
#endif
@@ -652,4 +580,12 @@
uint64_t ixl_get_counter(if_t ifp, ift_counter cnt);
#endif
+/*********************************************************************
+ * common Function prototypes
+ *********************************************************************/
+
+int ixl_if_media_change(if_ctx_t);
+int ixl_if_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int);
+void ixl_if_queues_free(if_ctx_t ctx);
+
#endif /* _IXL_H_ */
Index: sys/dev/ixl/ixl_pf.h
===================================================================
--- sys/dev/ixl/ixl_pf.h
+++ sys/dev/ixl/ixl_pf.h
@@ -54,47 +54,40 @@
/* Physical controller structure */
struct ixl_pf {
+ /*
+ ** VSI - Stations:
+ ** These are the traffic class holders, and
+ ** will have a stack interface and queues
+ ** associated with them.
+ ** NOTE: for now using just one, so embed it.
+ ** also, to make it interchangeable place it _first_
+ */
+ struct ixl_vsi vsi;
+
+
struct i40e_hw hw;
struct i40e_osdep osdep;
- struct device *dev;
+ device_t dev;
struct resource *pci_mem;
- struct resource *msix_mem;
/*
* Interrupt resources: this set is
* either used for legacy, or for Link
* when doing MSIX
*/
- void *tag;
- struct resource *res;
- struct callout timer;
int msix;
int if_flags;
- struct mtx pf_mtx;
-
u32 qbase;
u32 admvec;
- struct task adminq;
- struct taskqueue *tq;
bool link_up;
u32 link_speed;
int advertised_speed;
int fc; /* local flow ctrl setting */
- /*
- ** Network interfaces
- ** These are the traffic class holders, and
- ** will have a stack interface and queues
- ** associated with them.
- ** NOTE: The PF has only a single interface,
- ** so it is embedded in the PF struct.
- */
- struct ixl_vsi vsi;
-
/* Misc stats maintained by the driver */
u64 watchdog_events;
u64 admin_irq;
@@ -129,11 +122,4 @@
#define i40e_send_vf_nack(pf, vf, op, st) \
ixl_send_vf_nack_msg((pf), (vf), (op), (st), __FILE__, __LINE__)
-#define IXL_PF_LOCK_INIT(_sc, _name) \
- mtx_init(&(_sc)->pf_mtx, _name, "IXL PF Lock", MTX_DEF)
-#define IXL_PF_LOCK(_sc) mtx_lock(&(_sc)->pf_mtx)
-#define IXL_PF_UNLOCK(_sc) mtx_unlock(&(_sc)->pf_mtx)
-#define IXL_PF_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->pf_mtx)
-#define IXL_PF_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->pf_mtx, MA_OWNED)
-
#endif /* _IXL_PF_H_ */
Index: sys/dev/ixl/ixl_txrx.c
===================================================================
--- sys/dev/ixl/ixl_txrx.c
+++ sys/dev/ixl/ixl_txrx.c
@@ -51,176 +51,163 @@
#endif
/* Local Prototypes */
-static void ixl_rx_checksum(struct mbuf *, u32, u32, u8);
-static void ixl_refresh_mbufs(struct ixl_queue *, int);
-static int ixl_xmit(struct ixl_queue *, struct mbuf **);
-static int ixl_tx_setup_offload(struct ixl_queue *,
- struct mbuf *, u32 *, u32 *);
-static bool ixl_tso_setup(struct ixl_queue *, struct mbuf *);
+static void ixl_rx_checksum(if_rxd_info_t ri, u32 status, u32 error, u8 ptype);
-static __inline void ixl_rx_discard(struct rx_ring *, int);
-static __inline void ixl_rx_input(struct rx_ring *, struct ifnet *,
- struct mbuf *, u8);
+static int ixl_isc_txd_encap(void *arg, if_pkt_info_t pi);
+static void ixl_isc_txd_flush(void *arg, uint16_t txqid, uint32_t pidx);
+static int ixl_isc_txd_credits_update(void *arg, uint16_t qid, uint32_t cidx, bool clear);
-#ifdef DEV_NETMAP
-#include <dev/netmap/if_ixl_netmap.h>
-#endif /* DEV_NETMAP */
+static void ixl_isc_rxd_refill(void *arg, uint16_t rxqid, uint8_t flid __unused,
+ uint32_t pidx, uint64_t *paddrs, caddr_t *vaddrs __unused, uint16_t count);
+static void ixl_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused, uint32_t pidx);
+static int ixl_isc_rxd_available(void *arg, uint16_t rxqid, uint32_t idx);
+static int ixl_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri);
-/*
-** Multiqueue Transmit driver
-*/
-int
-ixl_mq_start(struct ifnet *ifp, struct mbuf *m)
-{
- struct ixl_vsi *vsi = ifp->if_softc;
- struct ixl_queue *que;
- struct tx_ring *txr;
- int err, i;
-#ifdef RSS
- u32 bucket_id;
-#endif
+extern int ixl_intr(void *arg);
- /*
- ** Which queue to use:
- **
- ** When doing RSS, map it to the same outbound
- ** queue as the incoming flow would be mapped to.
- ** If everything is setup correctly, it should be
- ** the same bucket that the current CPU we're on is.
- */
- if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
-#ifdef RSS
- if (rss_hash2bucket(m->m_pkthdr.flowid,
- M_HASHTYPE_GET(m), &bucket_id) == 0) {
- i = bucket_id % vsi->num_queues;
- } else
-#endif
- i = m->m_pkthdr.flowid % vsi->num_queues;
- } else
- i = curcpu % vsi->num_queues;
- /*
- ** This may not be perfect, but until something
- ** better comes along it will keep from scheduling
- ** on stalled queues.
- */
- if (((1 << i) & vsi->active_queues) == 0)
- i = ffsl(vsi->active_queues);
+struct if_txrx ixl_txrx = {
+ ixl_isc_txd_encap,
+ ixl_isc_txd_flush,
+ ixl_isc_txd_credits_update,
+ ixl_isc_rxd_available,
+ ixl_isc_rxd_pkt_get,
+ ixl_isc_rxd_refill,
+ ixl_isc_rxd_flush,
+ ixl_intr
+};
- que = &vsi->queues[i];
- txr = &que->txr;
+extern if_shared_ctx_t ixl_sctx;
- err = drbr_enqueue(ifp, txr->br, m);
- if (err)
- return (err);
- if (IXL_TX_TRYLOCK(txr)) {
- ixl_mq_start_locked(ifp, txr);
- IXL_TX_UNLOCK(txr);
- } else
- taskqueue_enqueue(que->tq, &que->tx_task);
+
+/*
+** Find mbuf chains passed to the driver
+** that are 'sparse', using more than 8
+** segments to deliver an mss-size chunk of data
+*/
+static int
+ixl_tso_detect_sparse(bus_dma_segment_t *segs, int nsegs, int segsz)
+{
+ int i, count, curseg;
+
+ if (nsegs <= IXL_MAX_TX_SEGS-2)
+ return (0);
+ for (curseg = count = i = 0; i < nsegs; i++) {
+ curseg += segs[i].ds_len;
+ count++;
+ if (__predict_false(count == IXL_MAX_TX_SEGS-2))
+ return (1);
+ if (curseg > segsz) {
+ curseg -= segsz;
+ count = 1;
+ }
+ if (curseg == segsz)
+ curseg = count = 0;
+ }
return (0);
}
-int
-ixl_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr)
+/*********************************************************************
+ *
+ * Setup descriptor for hw offloads
+ *
+ **********************************************************************/
+
+static void
+ixl_tx_setup_offload(struct ixl_queue *que,
+ if_pkt_info_t pi, u32 *cmd, u32 *off)
{
- struct ixl_queue *que = txr->que;
- struct ixl_vsi *vsi = que->vsi;
- struct mbuf *next;
- int err = 0;
-
-
- if (((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) ||
- vsi->link_active == 0)
- return (ENETDOWN);
-
- /* Process the transmit queue */
- while ((next = drbr_peek(ifp, txr->br)) != NULL) {
- if ((err = ixl_xmit(que, &next)) != 0) {
- if (next == NULL)
- drbr_advance(ifp, txr->br);
- else
- drbr_putback(ifp, txr->br, next);
+
+
+ switch (pi->ipi_etype) {
+#ifdef INET
+ case ETHERTYPE_IP:
+ *cmd |= I40E_TX_DESC_CMD_IIPT_IPV4_CSUM;
break;
- }
- drbr_advance(ifp, txr->br);
- /* Send a copy of the frame to the BPF listener */
- ETHER_BPF_MTAP(ifp, next);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+#endif
+#ifdef INET6
+ case ETHERTYPE_IPV6:
+ *cmd |= I40E_TX_DESC_CMD_IIPT_IPV6;
+ break;
+#endif
+ default:
break;
}
- if (txr->avail < IXL_TX_CLEANUP_THRESHOLD)
- ixl_txeof(que);
-
- return (err);
-}
+ *off |= (pi->ipi_ehdrlen >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT;
+ *off |= (pi->ipi_ip_hlen >> 2) << I40E_TX_DESC_LENGTH_IPLEN_SHIFT;
-/*
- * Called from a taskqueue to drain queued transmit packets.
- */
-void
-ixl_deferred_mq_start(void *arg, int pending)
-{
- struct ixl_queue *que = arg;
- struct tx_ring *txr = &que->txr;
- struct ixl_vsi *vsi = que->vsi;
- struct ifnet *ifp = vsi->ifp;
-
- IXL_TX_LOCK(txr);
- if (!drbr_empty(ifp, txr->br))
- ixl_mq_start_locked(ifp, txr);
- IXL_TX_UNLOCK(txr);
-}
+ switch (pi->ipi_ipproto) {
+ case IPPROTO_TCP:
+ if (pi->ipi_csum_flags & (CSUM_TCP|CSUM_TCP_IPV6)) {
+ *cmd |= I40E_TX_DESC_CMD_L4T_EOFT_TCP;
+ *off |= (pi->ipi_tcp_hlen >> 2) <<
+ I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
+ }
+#ifdef IXL_FDIR
+ ixl_atr(que, pi->ipi_tcp_hflags, pi->ipi_etype);
+#endif
+ break;
+ case IPPROTO_UDP:
+ if (pi->ipi_csum_flags & (CSUM_UDP|CSUM_UDP_IPV6)) {
+ *cmd |= I40E_TX_DESC_CMD_L4T_EOFT_UDP;
+ *off |= (sizeof(struct udphdr) >> 2) <<
+ I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
+ }
+ break;
-/*
-** Flush all queue ring buffers
-*/
-void
-ixl_qflush(struct ifnet *ifp)
-{
- struct ixl_vsi *vsi = ifp->if_softc;
-
- for (int i = 0; i < vsi->num_queues; i++) {
- struct ixl_queue *que = &vsi->queues[i];
- struct tx_ring *txr = &que->txr;
- struct mbuf *m;
- IXL_TX_LOCK(txr);
- while ((m = buf_ring_dequeue_sc(txr->br)) != NULL)
- m_freem(m);
- IXL_TX_UNLOCK(txr);
+ case IPPROTO_SCTP:
+ if (pi->ipi_csum_flags & (CSUM_SCTP|CSUM_SCTP_IPV6)) {
+ *cmd |= I40E_TX_DESC_CMD_L4T_EOFT_SCTP;
+ *off |= (sizeof(struct sctphdr) >> 2) <<
+ I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
+ }
+ /* Fall Thru */
+ default:
+ break;
}
- if_qflush(ifp);
+
}
-/*
-** Find mbuf chains passed to the driver
-** that are 'sparse', using more than 8
-** mbufs to deliver an mss-size chunk of data
-*/
-static inline bool
-ixl_tso_detect_sparse(struct mbuf *mp)
+/**********************************************************************
+ *
+ * Setup context for hardware segmentation offload (TSO)
+ *
+ **********************************************************************/
+static int
+ixl_tso_setup(struct tx_ring *txr, if_pkt_info_t pi)
{
- struct mbuf *m;
- int num = 0, mss;
- bool ret = FALSE;
-
- mss = mp->m_pkthdr.tso_segsz;
- for (m = mp->m_next; m != NULL; m = m->m_next) {
- num++;
- mss -= m->m_len;
- if (mss < 1)
- break;
- if (m->m_next == NULL)
- break;
- }
- if (num > IXL_SPARSE_CHAIN)
- ret = TRUE;
+ struct i40e_tx_context_desc *TXD;
+ struct ixl_tx_buf *buf;
+ u32 cmd, mss, type, tsolen;
+ int idx;
+ u64 type_cmd_tso_mss;
+
+ idx = pi->ipi_pidx;
+ buf = &txr->tx_buffers[idx];
+ TXD = (struct i40e_tx_context_desc *) &txr->tx_base[idx];
+ tsolen = pi->ipi_len - (pi->ipi_ehdrlen + pi->ipi_ip_hlen + pi->ipi_tcp_hlen);
+
+ type = I40E_TX_DESC_DTYPE_CONTEXT;
+ cmd = I40E_TX_CTX_DESC_TSO;
+ mss = pi->ipi_tso_segsz;
+
+ type_cmd_tso_mss = ((u64)type << I40E_TXD_CTX_QW1_DTYPE_SHIFT) |
+ ((u64)cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) |
+ ((u64)tsolen << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) |
+ ((u64)mss << I40E_TXD_CTX_QW1_MSS_SHIFT);
+ TXD->type_cmd_tso_mss = htole64(type_cmd_tso_mss);
- return (ret);
+ TXD->tunneling_params = htole32(0);
+ buf->eop_index = -1;
+
+ if (++idx == ixl_sctx->isc_ntxd)
+ idx = 0;
+ return (idx);
}
+
/*********************************************************************
*
* This routine maps the mbufs to tx descriptors, allowing the
@@ -231,122 +218,55 @@
#define IXL_TXD_CMD (I40E_TX_DESC_CMD_EOP | I40E_TX_DESC_CMD_RS)
static int
-ixl_xmit(struct ixl_queue *que, struct mbuf **m_headp)
+ixl_isc_txd_encap(void *arg, if_pkt_info_t pi)
{
- struct ixl_vsi *vsi = que->vsi;
- struct i40e_hw *hw = vsi->hw;
+ struct ixl_vsi *vsi = arg;
+ struct ixl_queue *que = &vsi->queues[pi->ipi_qsidx];
struct tx_ring *txr = &que->txr;
+ int nsegs = pi->ipi_nsegs;
+ bus_dma_segment_t *segs = pi->ipi_segs;
struct ixl_tx_buf *buf;
struct i40e_tx_desc *txd = NULL;
- struct mbuf *m_head, *m;
- int i, j, error, nsegs, maxsegs;
+ int i, j;
int first, last = 0;
- u16 vtag = 0;
- u32 cmd, off;
- bus_dmamap_t map;
- bus_dma_tag_t tag;
- bus_dma_segment_t segs[IXL_MAX_TSO_SEGS];
+ u32 cmd, off;
cmd = off = 0;
- m_head = *m_headp;
/*
* Important to capture the first descriptor
* used because it will contain the index of
* the one we tell the hardware to report back
*/
- first = txr->next_avail;
- buf = &txr->buffers[first];
- map = buf->map;
- tag = txr->tx_tag;
- maxsegs = IXL_MAX_TX_SEGS;
-
- if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
- /* Use larger mapping for TSO */
- tag = txr->tso_tag;
- maxsegs = IXL_MAX_TSO_SEGS;
- if (ixl_tso_detect_sparse(m_head)) {
- m = m_defrag(m_head, M_NOWAIT);
- if (m == NULL) {
- m_freem(*m_headp);
- *m_headp = NULL;
- return (ENOBUFS);
- }
- *m_headp = m;
- }
- }
+ i = first = pi->ipi_pidx;
+ buf = &txr->tx_buffers[first];
- /*
- * Map the packet for DMA.
- */
- error = bus_dmamap_load_mbuf_sg(tag, map,
- *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
-
- if (error == EFBIG) {
- struct mbuf *m;
-
- m = m_defrag(*m_headp, M_NOWAIT);
- if (m == NULL) {
- que->mbuf_defrag_failed++;
- m_freem(*m_headp);
- *m_headp = NULL;
- return (ENOBUFS);
- }
- *m_headp = m;
-
- /* Try it again */
- error = bus_dmamap_load_mbuf_sg(tag, map,
- *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
-
- if (error == ENOMEM) {
- que->tx_dma_setup++;
- return (error);
- } else if (error != 0) {
- que->tx_dma_setup++;
- m_freem(*m_headp);
- *m_headp = NULL;
- return (error);
- }
- } else if (error == ENOMEM) {
- que->tx_dma_setup++;
- return (error);
- } else if (error != 0) {
- que->tx_dma_setup++;
- m_freem(*m_headp);
- *m_headp = NULL;
- return (error);
- }
-
- /* Make certain there are enough descriptors */
- if (nsegs > txr->avail - 2) {
- txr->no_desc++;
- error = ENOBUFS;
- goto xmit_fail;
- }
- m_head = *m_headp;
+ if (pi->ipi_flags & IPI_TX_INTR)
+ cmd |= (I40E_TX_DESC_CMD_RS << I40E_TXD_QW1_CMD_SHIFT);
/* Set up the TSO/CSUM offload */
- if (m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) {
- error = ixl_tx_setup_offload(que, m_head, &cmd, &off);
- if (error)
- goto xmit_fail;
+ if (pi->ipi_csum_flags & CSUM_OFFLOAD) {
+ /* Set up the TSO context descriptor if required */
+ if (pi->ipi_csum_flags & CSUM_TSO) {
+ if (ixl_tso_detect_sparse(segs, nsegs, pi->ipi_tso_segsz))
+ return (EFBIG);
+
+ i = ixl_tso_setup(txr, pi);
+ }
+ ixl_tx_setup_offload(que, pi, &cmd, &off);
}
- cmd |= I40E_TX_DESC_CMD_ICRC;
- /* Grab the VLAN tag */
- if (m_head->m_flags & M_VLANTAG) {
+ if (pi->ipi_mflags & M_VLANTAG)
cmd |= I40E_TX_DESC_CMD_IL2TAG1;
- vtag = htole16(m_head->m_pkthdr.ether_vtag);
- }
- i = txr->next_avail;
+ cmd |= I40E_TX_DESC_CMD_ICRC;
+
for (j = 0; j < nsegs; j++) {
bus_size_t seglen;
- buf = &txr->buffers[i];
- buf->tag = tag; /* Keep track of the type tag */
- txd = &txr->base[i];
+ buf = &txr->tx_buffers[i];
+ txd = &txr->tx_base[i];
seglen = segs[j].ds_len;
txd->buffer_addr = htole64(segs[j].ds_addr);
@@ -355,127 +275,39 @@
| ((u64)cmd << I40E_TXD_QW1_CMD_SHIFT)
| ((u64)off << I40E_TXD_QW1_OFFSET_SHIFT)
| ((u64)seglen << I40E_TXD_QW1_TX_BUF_SZ_SHIFT)
- | ((u64)vtag << I40E_TXD_QW1_L2TAG1_SHIFT));
+ | ((u64)htole16(pi->ipi_vtag) << I40E_TXD_QW1_L2TAG1_SHIFT));
last = i; /* descriptor that will get completion IRQ */
- if (++i == que->num_desc)
+ if (++i == ixl_sctx->isc_ntxd)
i = 0;
- buf->m_head = NULL;
buf->eop_index = -1;
}
/* Set the last descriptor for report */
txd->cmd_type_offset_bsz |=
htole64(((u64)IXL_TXD_CMD << I40E_TXD_QW1_CMD_SHIFT));
- txr->avail -= nsegs;
- txr->next_avail = i;
-
- buf->m_head = m_head;
- /* Swap the dma map between the first and last descriptor */
- txr->buffers[first].map = buf->map;
- buf->map = map;
- bus_dmamap_sync(tag, map, BUS_DMASYNC_PREWRITE);
+ pi->ipi_new_pidx = i;
- /* Set the index of the descriptor that will be marked done */
- buf = &txr->buffers[first];
- buf->eop_index = last;
+ /* Set the index of the descriptor that will be marked done */
+ txr->tx_buffers[first].eop_index = last;
- bus_dmamap_sync(txr->dma.tag, txr->dma.map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- /*
- * Advance the Transmit Descriptor Tail (Tdt), this tells the
- * hardware that this frame is available to transmit.
- */
++txr->total_packets;
- wr32(hw, txr->tail, i);
-
- /* Mark outstanding work */
- if (que->busy == 0)
- que->busy = 1;
return (0);
-
-xmit_fail:
- bus_dmamap_unload(tag, buf->map);
- return (error);
}
-
-/*********************************************************************
- *
- * Allocate memory for tx_buffer structures. The tx_buffer stores all
- * the information needed to transmit a packet on the wire. This is
- * called only once at attach, setup is done every reset.
- *
- **********************************************************************/
-int
-ixl_allocate_tx_data(struct ixl_queue *que)
+static void
+ixl_isc_txd_flush(void *arg, uint16_t txqid, uint32_t pidx)
{
- struct tx_ring *txr = &que->txr;
- struct ixl_vsi *vsi = que->vsi;
- device_t dev = vsi->dev;
- struct ixl_tx_buf *buf;
- int error = 0;
-
+ struct ixl_vsi *vsi = arg;
+ struct tx_ring *txr = &vsi->queues[txqid].txr;
/*
- * Setup DMA descriptor areas.
+ * Advance the Transmit Descriptor Tail (Tdt), this tells the
+ * hardware that this frame is available to transmit.
*/
- if ((error = bus_dma_tag_create(NULL, /* parent */
- 1, 0, /* alignment, bounds */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- IXL_TSO_SIZE, /* maxsize */
- IXL_MAX_TX_SEGS, /* nsegments */
- PAGE_SIZE, /* maxsegsize */
- 0, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockfuncarg */
- &txr->tx_tag))) {
- device_printf(dev,"Unable to allocate TX DMA tag\n");
- goto fail;
- }
-
- /* Make a special tag for TSO */
- if ((error = bus_dma_tag_create(NULL, /* parent */
- 1, 0, /* alignment, bounds */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- IXL_TSO_SIZE, /* maxsize */
- IXL_MAX_TSO_SEGS, /* nsegments */
- PAGE_SIZE, /* maxsegsize */
- 0, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockfuncarg */
- &txr->tso_tag))) {
- device_printf(dev,"Unable to allocate TX TSO DMA tag\n");
- goto fail;
- }
-
- if (!(txr->buffers =
- (struct ixl_tx_buf *) malloc(sizeof(struct ixl_tx_buf) *
- que->num_desc, M_DEVBUF, M_NOWAIT | M_ZERO))) {
- device_printf(dev, "Unable to allocate tx_buffer memory\n");
- error = ENOMEM;
- goto fail;
- }
-
- /* Create the descriptor buffer default dma maps */
- buf = txr->buffers;
- for (int i = 0; i < que->num_desc; i++, buf++) {
- buf->tag = txr->tx_tag;
- error = bus_dmamap_create(buf->tag, 0, &buf->map);
- if (error != 0) {
- device_printf(dev, "Unable to create TX DMA map\n");
- goto fail;
- }
- }
-fail:
- return (error);
+ wr32(vsi->hw, txr->tail, pidx);
}
-
/*********************************************************************
*
* (Re)Initialize a queue transmit ring.
@@ -484,32 +316,14 @@
*
**********************************************************************/
void
-ixl_init_tx_ring(struct ixl_queue *que)
+ixl_init_tx_ring(struct ixl_vsi *vsi, struct ixl_queue *que)
{
-#ifdef DEV_NETMAP
- struct netmap_adapter *na = NA(que->vsi->ifp);
- struct netmap_slot *slot;
-#endif /* DEV_NETMAP */
- struct tx_ring *txr = &que->txr;
- struct ixl_tx_buf *buf;
+ struct tx_ring *txr = &que->txr;
+ struct ixl_tx_buf *buf;
/* Clear the old ring contents */
- IXL_TX_LOCK(txr);
-
-#ifdef DEV_NETMAP
- /*
- * (under lock): if in netmap mode, do some consistency
- * checks and set slot to entry 0 of the netmap ring.
- */
- slot = netmap_reset(na, NR_TX, que->me, 0);
-#endif /* DEV_NETMAP */
-
- bzero((void *)txr->base,
- (sizeof(struct i40e_tx_desc)) * que->num_desc);
-
- /* Reset indices */
- txr->next_avail = 0;
- txr->next_to_clean = 0;
+ bzero((void *)txr->tx_base,
+ (sizeof(struct i40e_tx_desc)) * ixl_sctx->isc_ntxd);
#ifdef IXL_FDIR
/* Initialize flow director */
@@ -517,309 +331,16 @@
txr->atr_count = 0;
#endif
- /* Free any existing tx mbufs. */
- buf = txr->buffers;
- for (int i = 0; i < que->num_desc; i++, buf++) {
- if (buf->m_head != NULL) {
- bus_dmamap_sync(buf->tag, buf->map,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(buf->tag, buf->map);
- m_freem(buf->m_head);
- buf->m_head = NULL;
- }
-#ifdef DEV_NETMAP
- /*
- * In netmap mode, set the map for the packet buffer.
- * NOTE: Some drivers (not this one) also need to set
- * the physical buffer address in the NIC ring.
- * netmap_idx_n2k() maps a nic index, i, into the corresponding
- * netmap slot index, si
- */
- if (slot) {
- int si = netmap_idx_n2k(&na->tx_rings[que->me], i);
- netmap_load_map(na, buf->tag, buf->map, NMB(na, slot + si));
- }
-#endif /* DEV_NETMAP */
+ wr32(vsi->hw, I40E_QTX_TAIL(que->me), 0);
+ wr32(vsi->hw, I40E_QTX_HEAD(que->me), 0);
+ buf = txr->tx_buffers;
+ for (int i = 0; i < ixl_sctx->isc_ntxd; i++, buf++) {
+
/* Clear the EOP index */
buf->eop_index = -1;
- }
-
- /* Set number of descriptors available */
- txr->avail = que->num_desc;
-
- bus_dmamap_sync(txr->dma.tag, txr->dma.map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- IXL_TX_UNLOCK(txr);
-}
-
-
-/*********************************************************************
- *
- * Free transmit ring related data structures.
- *
- **********************************************************************/
-void
-ixl_free_que_tx(struct ixl_queue *que)
-{
- struct tx_ring *txr = &que->txr;
- struct ixl_tx_buf *buf;
-
- INIT_DBG_IF(que->vsi->ifp, "queue %d: begin", que->me);
-
- for (int i = 0; i < que->num_desc; i++) {
- buf = &txr->buffers[i];
- if (buf->m_head != NULL) {
- bus_dmamap_sync(buf->tag, buf->map,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(buf->tag,
- buf->map);
- m_freem(buf->m_head);
- buf->m_head = NULL;
- if (buf->map != NULL) {
- bus_dmamap_destroy(buf->tag,
- buf->map);
- buf->map = NULL;
- }
- } else if (buf->map != NULL) {
- bus_dmamap_unload(buf->tag,
- buf->map);
- bus_dmamap_destroy(buf->tag,
- buf->map);
- buf->map = NULL;
- }
- }
- if (txr->br != NULL)
- buf_ring_free(txr->br, M_DEVBUF);
- if (txr->buffers != NULL) {
- free(txr->buffers, M_DEVBUF);
- txr->buffers = NULL;
- }
- if (txr->tx_tag != NULL) {
- bus_dma_tag_destroy(txr->tx_tag);
- txr->tx_tag = NULL;
- }
- if (txr->tso_tag != NULL) {
- bus_dma_tag_destroy(txr->tso_tag);
- txr->tso_tag = NULL;
}
-
- INIT_DBG_IF(que->vsi->ifp, "queue %d: end", que->me);
- return;
}
-/*********************************************************************
- *
- * Setup descriptor for hw offloads
- *
- **********************************************************************/
-
-static int
-ixl_tx_setup_offload(struct ixl_queue *que,
- struct mbuf *mp, u32 *cmd, u32 *off)
-{
- struct ether_vlan_header *eh;
-#ifdef INET
- struct ip *ip = NULL;
-#endif
- struct tcphdr *th = NULL;
-#ifdef INET6
- struct ip6_hdr *ip6;
-#endif
- int elen, ip_hlen = 0, tcp_hlen;
- u16 etype;
- u8 ipproto = 0;
- bool tso = FALSE;
-
-
- /* Set up the TSO context descriptor if required */
- if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
- tso = ixl_tso_setup(que, mp);
- if (tso)
- ++que->tso;
- else
- return (ENXIO);
- }
-
- /*
- * Determine where frame payload starts.
- * Jump over vlan headers if already present,
- * helpful for QinQ too.
- */
- eh = mtod(mp, struct ether_vlan_header *);
- if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
- etype = ntohs(eh->evl_proto);
- elen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
- } else {
- etype = ntohs(eh->evl_encap_proto);
- elen = ETHER_HDR_LEN;
- }
-
- switch (etype) {
-#ifdef INET
- case ETHERTYPE_IP:
- ip = (struct ip *)(mp->m_data + elen);
- ip_hlen = ip->ip_hl << 2;
- ipproto = ip->ip_p;
- th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
- /* The IP checksum must be recalculated with TSO */
- if (tso)
- *cmd |= I40E_TX_DESC_CMD_IIPT_IPV4_CSUM;
- else
- *cmd |= I40E_TX_DESC_CMD_IIPT_IPV4;
- break;
-#endif
-#ifdef INET6
- case ETHERTYPE_IPV6:
- ip6 = (struct ip6_hdr *)(mp->m_data + elen);
- ip_hlen = sizeof(struct ip6_hdr);
- ipproto = ip6->ip6_nxt;
- th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
- *cmd |= I40E_TX_DESC_CMD_IIPT_IPV6;
- break;
-#endif
- default:
- break;
- }
-
- *off |= (elen >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT;
- *off |= (ip_hlen >> 2) << I40E_TX_DESC_LENGTH_IPLEN_SHIFT;
-
- switch (ipproto) {
- case IPPROTO_TCP:
- tcp_hlen = th->th_off << 2;
- if (mp->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_TCP_IPV6)) {
- *cmd |= I40E_TX_DESC_CMD_L4T_EOFT_TCP;
- *off |= (tcp_hlen >> 2) <<
- I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
- }
-#ifdef IXL_FDIR
- ixl_atr(que, th, etype);
-#endif
- break;
- case IPPROTO_UDP:
- if (mp->m_pkthdr.csum_flags & (CSUM_UDP|CSUM_UDP_IPV6)) {
- *cmd |= I40E_TX_DESC_CMD_L4T_EOFT_UDP;
- *off |= (sizeof(struct udphdr) >> 2) <<
- I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
- }
- break;
-
- case IPPROTO_SCTP:
- if (mp->m_pkthdr.csum_flags & (CSUM_SCTP|CSUM_SCTP_IPV6)) {
- *cmd |= I40E_TX_DESC_CMD_L4T_EOFT_SCTP;
- *off |= (sizeof(struct sctphdr) >> 2) <<
- I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
- }
- /* Fall Thru */
- default:
- break;
- }
-
- return (0);
-}
-
-
-/**********************************************************************
- *
- * Setup context for hardware segmentation offload (TSO)
- *
- **********************************************************************/
-static bool
-ixl_tso_setup(struct ixl_queue *que, struct mbuf *mp)
-{
- struct tx_ring *txr = &que->txr;
- struct i40e_tx_context_desc *TXD;
- struct ixl_tx_buf *buf;
- u32 cmd, mss, type, tsolen;
- u16 etype;
- int idx, elen, ip_hlen, tcp_hlen;
- struct ether_vlan_header *eh;
-#ifdef INET
- struct ip *ip;
-#endif
-#ifdef INET6
- struct ip6_hdr *ip6;
-#endif
-#if defined(INET6) || defined(INET)
- struct tcphdr *th;
-#endif
- u64 type_cmd_tso_mss;
-
- /*
- * Determine where frame payload starts.
- * Jump over vlan headers if already present
- */
- eh = mtod(mp, struct ether_vlan_header *);
- if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
- elen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
- etype = eh->evl_proto;
- } else {
- elen = ETHER_HDR_LEN;
- etype = eh->evl_encap_proto;
- }
-
- switch (ntohs(etype)) {
-#ifdef INET6
- case ETHERTYPE_IPV6:
- ip6 = (struct ip6_hdr *)(mp->m_data + elen);
- if (ip6->ip6_nxt != IPPROTO_TCP)
- return (ENXIO);
- ip_hlen = sizeof(struct ip6_hdr);
- th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
- th->th_sum = in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0);
- tcp_hlen = th->th_off << 2;
- break;
-#endif
-#ifdef INET
- case ETHERTYPE_IP:
- ip = (struct ip *)(mp->m_data + elen);
- if (ip->ip_p != IPPROTO_TCP)
- return (ENXIO);
- ip->ip_sum = 0;
- ip_hlen = ip->ip_hl << 2;
- th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
- th->th_sum = in_pseudo(ip->ip_src.s_addr,
- ip->ip_dst.s_addr, htons(IPPROTO_TCP));
- tcp_hlen = th->th_off << 2;
- break;
-#endif
- default:
- printf("%s: CSUM_TSO but no supported IP version (0x%04x)",
- __func__, ntohs(etype));
- return FALSE;
- }
-
- /* Ensure we have at least the IP+TCP header in the first mbuf. */
- if (mp->m_len < elen + ip_hlen + sizeof(struct tcphdr))
- return FALSE;
-
- idx = txr->next_avail;
- buf = &txr->buffers[idx];
- TXD = (struct i40e_tx_context_desc *) &txr->base[idx];
- tsolen = mp->m_pkthdr.len - (elen + ip_hlen + tcp_hlen);
-
- type = I40E_TX_DESC_DTYPE_CONTEXT;
- cmd = I40E_TX_CTX_DESC_TSO;
- mss = mp->m_pkthdr.tso_segsz;
-
- type_cmd_tso_mss = ((u64)type << I40E_TXD_CTX_QW1_DTYPE_SHIFT) |
- ((u64)cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) |
- ((u64)tsolen << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) |
- ((u64)mss << I40E_TXD_CTX_QW1_MSS_SHIFT);
- TXD->type_cmd_tso_mss = htole64(type_cmd_tso_mss);
-
- TXD->tunneling_params = htole32(0);
- buf->m_head = NULL;
- buf->eop_index = -1;
-
- if (++idx == que->num_desc)
- idx = 0;
-
- txr->avail--;
- txr->next_avail = idx;
-
- return TRUE;
-}
/*
** ixl_get_tx_head - Retrieve the value from the
@@ -829,7 +350,8 @@
ixl_get_tx_head(struct ixl_queue *que)
{
struct tx_ring *txr = &que->txr;
- void *head = &txr->base[que->num_desc];
+ void *head = &txr->tx_base[ixl_sctx->isc_ntxd];
+
return LE32_TO_CPU(*(volatile __le32 *)head);
}
@@ -840,37 +362,24 @@
* tx_buffer is put back on the free queue.
*
**********************************************************************/
-bool
-ixl_txeof(struct ixl_queue *que)
+static int
+ixl_isc_txd_credits_update(void *arg, uint16_t qid, uint32_t cidx, bool clear)
{
+ struct ixl_vsi *vsi = arg;
+ struct ixl_queue *que = &vsi->queues[qid];
struct tx_ring *txr = &que->txr;
u32 first, last, head, done, processed;
struct ixl_tx_buf *buf;
struct i40e_tx_desc *tx_desc, *eop_desc;
-
- mtx_assert(&txr->mtx, MA_OWNED);
-
-#ifdef DEV_NETMAP
- // XXX todo: implement moderation
- if (netmap_tx_irq(que->vsi->ifp, que->me))
- return FALSE;
-#endif /* DEF_NETMAP */
-
- /* These are not the descriptors you seek, move along :) */
- if (txr->avail == que->num_desc) {
- que->busy = 0;
- return FALSE;
- }
-
processed = 0;
- first = txr->next_to_clean;
- buf = &txr->buffers[first];
- tx_desc = (struct i40e_tx_desc *)&txr->base[first];
+ first = cidx;
+ buf = &txr->tx_buffers[first];
+ tx_desc = (struct i40e_tx_desc *)&txr->tx_base[first];
last = buf->eop_index;
if (last == -1)
- return FALSE;
- eop_desc = (struct i40e_tx_desc *)&txr->base[last];
+ return (0);
+ eop_desc = (struct i40e_tx_desc *)&txr->tx_base[last];
/* Get the Head WB value */
head = ixl_get_tx_head(que);
@@ -881,11 +390,9 @@
** I do this so the comparison in the
** inner while loop below can be simple
*/
- if (++last == que->num_desc) last = 0;
+ if (++last == ixl_sctx->isc_ntxd) last = 0;
done = last;
- bus_dmamap_sync(txr->dma.tag, txr->dma.map,
- BUS_DMASYNC_POSTREAD);
/*
** The HEAD index of the ring is written in a
** defined location, this rather than a done bit
@@ -893,74 +400,29 @@
** 'cleaned'.
*/
while (first != head) {
- /* We clean the range of the packet */
while (first != done) {
- ++txr->avail;
++processed;
-
- if (buf->m_head) {
- txr->bytes += /* for ITR adjustment */
- buf->m_head->m_pkthdr.len;
- txr->tx_bytes += /* for TX stats */
- buf->m_head->m_pkthdr.len;
- bus_dmamap_sync(buf->tag,
- buf->map,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(buf->tag,
- buf->map);
- m_freem(buf->m_head);
- buf->m_head = NULL;
- buf->map = NULL;
- }
- buf->eop_index = -1;
-
- if (++first == que->num_desc)
+ if (clear)
+ buf->eop_index = -1;
+ if (++first == ixl_sctx->isc_ntxd)
first = 0;
- buf = &txr->buffers[first];
- tx_desc = &txr->base[first];
+ buf = &txr->tx_buffers[first];
+ tx_desc = &txr->tx_base[first];
}
- ++txr->packets;
+ if (clear)
+ ++txr->packets;
/* See if there is more work now */
last = buf->eop_index;
- if (last != -1) {
- eop_desc = &txr->base[last];
- /* Get next done point */
- if (++last == que->num_desc) last = 0;
- done = last;
- } else
+ if (last == -1)
break;
- }
- bus_dmamap_sync(txr->dma.tag, txr->dma.map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
- txr->next_to_clean = first;
-
-
- /*
- ** Hang detection, we know there's
- ** work outstanding or the first return
- ** would have been taken, so indicate an
- ** unsuccessful pass, in local_timer if
- ** the value is too great the queue will
- ** be considered hung. If anything has been
- ** cleaned then reset the state.
- */
- if ((processed == 0) && (que->busy != IXL_QUEUE_HUNG))
- ++que->busy;
-
- if (processed)
- que->busy = 1; /* Note this turns off HUNG */
+ eop_desc = &txr->tx_base[last];
+ /* Get next done point */
+ if (++last == ixl_sctx->isc_ntxd) last = 0;
+ done = last;
- /*
- * If there are no pending descriptors, clear the timeout.
- */
- if (txr->avail == que->num_desc) {
- que->busy = 0;
- return FALSE;
}
-
- return TRUE;
+ return (processed);
}
/*********************************************************************
@@ -973,468 +435,56 @@
*
**********************************************************************/
static void
-ixl_refresh_mbufs(struct ixl_queue *que, int limit)
-{
- struct ixl_vsi *vsi = que->vsi;
- struct rx_ring *rxr = &que->rxr;
- bus_dma_segment_t hseg[1];
- bus_dma_segment_t pseg[1];
- struct ixl_rx_buf *buf;
- struct mbuf *mh, *mp;
- int i, j, nsegs, error;
- bool refreshed = FALSE;
-
- i = j = rxr->next_refresh;
- /* Control the loop with one beyond */
- if (++j == que->num_desc)
- j = 0;
-
- while (j != limit) {
- buf = &rxr->buffers[i];
- if (rxr->hdr_split == FALSE)
- goto no_split;
-
- if (buf->m_head == NULL) {
- mh = m_gethdr(M_NOWAIT, MT_DATA);
- if (mh == NULL)
- goto update;
- } else
- mh = buf->m_head;
-
- mh->m_pkthdr.len = mh->m_len = MHLEN;
- mh->m_len = MHLEN;
- mh->m_flags |= M_PKTHDR;
- /* Get the memory mapping */
- error = bus_dmamap_load_mbuf_sg(rxr->htag,
- buf->hmap, mh, hseg, &nsegs, BUS_DMA_NOWAIT);
- if (error != 0) {
- printf("Refresh mbufs: hdr dmamap load"
- " failure - %d\n", error);
- m_free(mh);
- buf->m_head = NULL;
- goto update;
- }
- buf->m_head = mh;
- bus_dmamap_sync(rxr->htag, buf->hmap,
- BUS_DMASYNC_PREREAD);
- rxr->base[i].read.hdr_addr =
- htole64(hseg[0].ds_addr);
-
-no_split:
- if (buf->m_pack == NULL) {
- mp = m_getjcl(M_NOWAIT, MT_DATA,
- M_PKTHDR, rxr->mbuf_sz);
- if (mp == NULL)
- goto update;
- } else
- mp = buf->m_pack;
-
- mp->m_pkthdr.len = mp->m_len = rxr->mbuf_sz;
- /* Get the memory mapping */
- error = bus_dmamap_load_mbuf_sg(rxr->ptag,
- buf->pmap, mp, pseg, &nsegs, BUS_DMA_NOWAIT);
- if (error != 0) {
- printf("Refresh mbufs: payload dmamap load"
- " failure - %d\n", error);
- m_free(mp);
- buf->m_pack = NULL;
- goto update;
- }
- buf->m_pack = mp;
- bus_dmamap_sync(rxr->ptag, buf->pmap,
- BUS_DMASYNC_PREREAD);
- rxr->base[i].read.pkt_addr =
- htole64(pseg[0].ds_addr);
- /* Used only when doing header split */
- rxr->base[i].read.hdr_addr = 0;
-
- refreshed = TRUE;
- /* Next is precalculated */
- i = j;
- rxr->next_refresh = i;
- if (++j == que->num_desc)
- j = 0;
- }
-update:
- if (refreshed) /* Update hardware tail index */
- wr32(vsi->hw, rxr->tail, rxr->next_refresh);
- return;
-}
-
-
-/*********************************************************************
- *
- * Allocate memory for rx_buffer structures. Since we use one
- * rx_buffer per descriptor, the maximum number of rx_buffer's
- * that we'll need is equal to the number of receive descriptors
- * that we've defined.
- *
- **********************************************************************/
-int
-ixl_allocate_rx_data(struct ixl_queue *que)
-{
- struct rx_ring *rxr = &que->rxr;
- struct ixl_vsi *vsi = que->vsi;
- device_t dev = vsi->dev;
- struct ixl_rx_buf *buf;
- int i, bsize, error;
-
- bsize = sizeof(struct ixl_rx_buf) * que->num_desc;
- if (!(rxr->buffers =
- (struct ixl_rx_buf *) malloc(bsize,
- M_DEVBUF, M_NOWAIT | M_ZERO))) {
- device_printf(dev, "Unable to allocate rx_buffer memory\n");
- error = ENOMEM;
- return (error);
- }
-
- if ((error = bus_dma_tag_create(NULL, /* parent */
- 1, 0, /* alignment, bounds */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MSIZE, /* maxsize */
- 1, /* nsegments */
- MSIZE, /* maxsegsize */
- 0, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockfuncarg */
- &rxr->htag))) {
- device_printf(dev, "Unable to create RX DMA htag\n");
- return (error);
- }
-
- if ((error = bus_dma_tag_create(NULL, /* parent */
- 1, 0, /* alignment, bounds */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MJUM16BYTES, /* maxsize */
- 1, /* nsegments */
- MJUM16BYTES, /* maxsegsize */
- 0, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockfuncarg */
- &rxr->ptag))) {
- device_printf(dev, "Unable to create RX DMA ptag\n");
- return (error);
- }
-
- for (i = 0; i < que->num_desc; i++) {
- buf = &rxr->buffers[i];
- error = bus_dmamap_create(rxr->htag,
- BUS_DMA_NOWAIT, &buf->hmap);
- if (error) {
- device_printf(dev, "Unable to create RX head map\n");
- break;
- }
- error = bus_dmamap_create(rxr->ptag,
- BUS_DMA_NOWAIT, &buf->pmap);
- if (error) {
- device_printf(dev, "Unable to create RX pkt map\n");
- break;
- }
- }
+ixl_isc_rxd_refill(void *arg, uint16_t rxqid, uint8_t flid __unused,
+ uint32_t pidx, uint64_t *paddrs, caddr_t *vaddrs __unused, uint16_t count)
- return (error);
-}
-
-
-/*********************************************************************
- *
- * (Re)Initialize the queue receive ring and its buffers.
- *
- **********************************************************************/
-int
-ixl_init_rx_ring(struct ixl_queue *que)
{
- struct rx_ring *rxr = &que->rxr;
- struct ixl_vsi *vsi = que->vsi;
-#if defined(INET6) || defined(INET)
- struct ifnet *ifp = vsi->ifp;
- struct lro_ctrl *lro = &rxr->lro;
-#endif
- struct ixl_rx_buf *buf;
- bus_dma_segment_t pseg[1], hseg[1];
- int rsize, nsegs, error = 0;
-#ifdef DEV_NETMAP
- struct netmap_adapter *na = NA(que->vsi->ifp);
- struct netmap_slot *slot;
-#endif /* DEV_NETMAP */
-
- IXL_RX_LOCK(rxr);
-#ifdef DEV_NETMAP
- /* same as in ixl_init_tx_ring() */
- slot = netmap_reset(na, NR_RX, que->me, 0);
-#endif /* DEV_NETMAP */
- /* Clear the ring contents */
- rsize = roundup2(que->num_desc *
- sizeof(union i40e_rx_desc), DBA_ALIGN);
- bzero((void *)rxr->base, rsize);
- /* Cleanup any existing buffers */
- for (int i = 0; i < que->num_desc; i++) {
- buf = &rxr->buffers[i];
- if (buf->m_head != NULL) {
- bus_dmamap_sync(rxr->htag, buf->hmap,
- BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(rxr->htag, buf->hmap);
- buf->m_head->m_flags |= M_PKTHDR;
- m_freem(buf->m_head);
- }
- if (buf->m_pack != NULL) {
- bus_dmamap_sync(rxr->ptag, buf->pmap,
- BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(rxr->ptag, buf->pmap);
- buf->m_pack->m_flags |= M_PKTHDR;
- m_freem(buf->m_pack);
- }
- buf->m_head = NULL;
- buf->m_pack = NULL;
- }
-
- /* header split is off */
- rxr->hdr_split = FALSE;
+ struct ixl_vsi *vsi = arg;
+ struct rx_ring *rxr = &vsi->queues[rxqid].rxr;
+ int i;
+ uint32_t next_pidx;
- /* Now replenish the mbufs */
- for (int j = 0; j != que->num_desc; ++j) {
- struct mbuf *mh, *mp;
-
- buf = &rxr->buffers[j];
-#ifdef DEV_NETMAP
- /*
- * In netmap mode, fill the map and set the buffer
- * address in the NIC ring, considering the offset
- * between the netmap and NIC rings (see comment in
- * ixgbe_setup_transmit_ring() ). No need to allocate
- * an mbuf, so end the block with a continue;
- */
- if (slot) {
- int sj = netmap_idx_n2k(&na->rx_rings[que->me], j);
- uint64_t paddr;
- void *addr;
-
- addr = PNMB(na, slot + sj, &paddr);
- netmap_load_map(na, rxr->dma.tag, buf->pmap, addr);
- /* Update descriptor and the cached value */
- rxr->base[j].read.pkt_addr = htole64(paddr);
- rxr->base[j].read.hdr_addr = 0;
- continue;
- }
-#endif /* DEV_NETMAP */
- /*
- ** Don't allocate mbufs if not
- ** doing header split, its wasteful
- */
- if (rxr->hdr_split == FALSE)
- goto skip_head;
-
- /* First the header */
- buf->m_head = m_gethdr(M_NOWAIT, MT_DATA);
- if (buf->m_head == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- m_adj(buf->m_head, ETHER_ALIGN);
- mh = buf->m_head;
- mh->m_len = mh->m_pkthdr.len = MHLEN;
- mh->m_flags |= M_PKTHDR;
- /* Get the memory mapping */
- error = bus_dmamap_load_mbuf_sg(rxr->htag,
- buf->hmap, buf->m_head, hseg,
- &nsegs, BUS_DMA_NOWAIT);
- if (error != 0) /* Nothing elegant to do here */
- goto fail;
- bus_dmamap_sync(rxr->htag,
- buf->hmap, BUS_DMASYNC_PREREAD);
- /* Update descriptor */
- rxr->base[j].read.hdr_addr = htole64(hseg[0].ds_addr);
-
-skip_head:
- /* Now the payload cluster */
- buf->m_pack = m_getjcl(M_NOWAIT, MT_DATA,
- M_PKTHDR, rxr->mbuf_sz);
- if (buf->m_pack == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- mp = buf->m_pack;
- mp->m_pkthdr.len = mp->m_len = rxr->mbuf_sz;
- /* Get the memory mapping */
- error = bus_dmamap_load_mbuf_sg(rxr->ptag,
- buf->pmap, mp, pseg,
- &nsegs, BUS_DMA_NOWAIT);
- if (error != 0)
- goto fail;
- bus_dmamap_sync(rxr->ptag,
- buf->pmap, BUS_DMASYNC_PREREAD);
- /* Update descriptor */
- rxr->base[j].read.pkt_addr = htole64(pseg[0].ds_addr);
- rxr->base[j].read.hdr_addr = 0;
- }
-
-
- /* Setup our descriptor indices */
- rxr->next_check = 0;
- rxr->next_refresh = 0;
- rxr->lro_enabled = FALSE;
- rxr->split = 0;
- rxr->bytes = 0;
- rxr->discard = FALSE;
-
- wr32(vsi->hw, rxr->tail, que->num_desc - 1);
- ixl_flush(vsi->hw);
-
-#if defined(INET6) || defined(INET)
- /*
- ** Now set up the LRO interface:
- */
- if (ifp->if_capenable & IFCAP_LRO) {
- int err = tcp_lro_init(lro);
- if (err) {
- if_printf(ifp, "queue %d: LRO Initialization failed!\n", que->me);
- goto fail;
- }
- INIT_DBG_IF(ifp, "queue %d: RX Soft LRO Initialized", que->me);
- rxr->lro_enabled = TRUE;
- lro->ifp = vsi->ifp;
+ for (i = 0, next_pidx = pidx; i < count; i++) {
+ rxr->rx_base[next_pidx].read.pkt_addr = htole64(paddrs[i]);
+ if (++next_pidx == ixl_sctx->isc_nrxd)
+ next_pidx = 0;
}
-#endif
-
- bus_dmamap_sync(rxr->dma.tag, rxr->dma.map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
-fail:
- IXL_RX_UNLOCK(rxr);
- return (error);
}
-
-/*********************************************************************
- *
- * Free station receive ring data structures
- *
- **********************************************************************/
-void
-ixl_free_que_rx(struct ixl_queue *que)
-{
- struct rx_ring *rxr = &que->rxr;
- struct ixl_rx_buf *buf;
-
- INIT_DBG_IF(que->vsi->ifp, "queue %d: begin", que->me);
-
- /* Cleanup any existing buffers */
- if (rxr->buffers != NULL) {
- for (int i = 0; i < que->num_desc; i++) {
- buf = &rxr->buffers[i];
- if (buf->m_head != NULL) {
- bus_dmamap_sync(rxr->htag, buf->hmap,
- BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(rxr->htag, buf->hmap);
- buf->m_head->m_flags |= M_PKTHDR;
- m_freem(buf->m_head);
- }
- if (buf->m_pack != NULL) {
- bus_dmamap_sync(rxr->ptag, buf->pmap,
- BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(rxr->ptag, buf->pmap);
- buf->m_pack->m_flags |= M_PKTHDR;
- m_freem(buf->m_pack);
- }
- buf->m_head = NULL;
- buf->m_pack = NULL;
- if (buf->hmap != NULL) {
- bus_dmamap_destroy(rxr->htag, buf->hmap);
- buf->hmap = NULL;
- }
- if (buf->pmap != NULL) {
- bus_dmamap_destroy(rxr->ptag, buf->pmap);
- buf->pmap = NULL;
- }
- }
- if (rxr->buffers != NULL) {
- free(rxr->buffers, M_DEVBUF);
- rxr->buffers = NULL;
- }
- }
-
- if (rxr->htag != NULL) {
- bus_dma_tag_destroy(rxr->htag);
- rxr->htag = NULL;
- }
- if (rxr->ptag != NULL) {
- bus_dma_tag_destroy(rxr->ptag);
- rxr->ptag = NULL;
- }
-
- INIT_DBG_IF(que->vsi->ifp, "queue %d: end", que->me);
- return;
-}
-
-static __inline void
-ixl_rx_input(struct rx_ring *rxr, struct ifnet *ifp, struct mbuf *m, u8 ptype)
+static void
+ixl_isc_rxd_flush(void * arg, uint16_t rxqid, uint8_t flid __unused, uint32_t pidx)
{
+ struct ixl_vsi *vsi = arg;
+ struct rx_ring *rxr = &vsi->queues[rxqid].rxr;
-#if defined(INET6) || defined(INET)
- /*
- * ATM LRO is only for IPv4/TCP packets and TCP checksum of the packet
- * should be computed by hardware. Also it should not have VLAN tag in
- * ethernet header.
- */
- if (rxr->lro_enabled &&
- (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 &&
- (m->m_pkthdr.csum_flags & (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) ==
- (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) {
- /*
- * Send to the stack if:
- ** - LRO not enabled, or
- ** - no LRO resources, or
- ** - lro enqueue fails
- */
- if (rxr->lro.lro_cnt != 0)
- if (tcp_lro_rx(&rxr->lro, m, 0) == 0)
- return;
- }
-#endif
- IXL_RX_UNLOCK(rxr);
- (*ifp->if_input)(ifp, m);
- IXL_RX_LOCK(rxr);
+ wr32(vsi->hw, rxr->tail, pidx);
}
-
-static __inline void
-ixl_rx_discard(struct rx_ring *rxr, int i)
+static int
+ixl_isc_rxd_available(void *arg, uint16_t rxqid, uint32_t idx)
{
- struct ixl_rx_buf *rbuf;
-
- rbuf = &rxr->buffers[i];
-
- if (rbuf->fmp != NULL) {/* Partial chain ? */
- rbuf->fmp->m_flags |= M_PKTHDR;
- m_freem(rbuf->fmp);
- rbuf->fmp = NULL;
- }
+ struct ixl_vsi *vsi = arg;
+ struct rx_ring *rxr = &vsi->queues[rxqid].rxr;
+ union i40e_rx_desc *cur;
+ u64 qword;
+ uint32_t status;
+ int cnt, i;
- /*
- ** With advanced descriptors the writeback
- ** clobbers the buffer addrs, so its easier
- ** to just free the existing mbufs and take
- ** the normal refresh path to get new buffers
- ** and mapping.
- */
- if (rbuf->m_head) {
- m_free(rbuf->m_head);
- rbuf->m_head = NULL;
- }
-
- if (rbuf->m_pack) {
- m_free(rbuf->m_pack);
- rbuf->m_pack = NULL;
+ for (cnt = 0, i = idx; cnt < ixl_sctx->isc_nrxd;) {
+ cur = &rxr->rx_base[i];
+ qword = le64toh(cur->wb.qword1.status_error_len);
+ status = (qword & I40E_RXD_QW1_STATUS_MASK)
+ >> I40E_RXD_QW1_STATUS_SHIFT;
+ if ((status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT)) == 0)
+ break;
+ cnt++;
+ if (++i == ixl_sctx->isc_nrxd)
+ i = 0;
}
- return;
+ return (cnt);
}
-#ifdef RSS
/*
** i40e_ptype_to_hash: parse the packet type
** to determine the appropriate hash.
@@ -1490,83 +540,53 @@
/* We should never get here!! */
return M_HASHTYPE_OPAQUE;
}
-#endif /* RSS */
+
/*********************************************************************
*
- * This routine executes in interrupt context. It replenishes
- * the mbufs in the descriptor and sends data which has been
+ * This routine executes in ithread context. It sends data which has been
* dma'ed into host memory to upper layer.
*
- * We loop at most count times if count is > 0, or until done if
- * count < 0.
- *
- * Return TRUE for more work, FALSE for all clean.
+ * Returns 0 upon success, errno on failure
*********************************************************************/
-bool
-ixl_rxeof(struct ixl_queue *que, int count)
+
+static int
+ixl_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri)
{
- struct ixl_vsi *vsi = que->vsi;
+ struct ixl_vsi *vsi = arg;
+ struct ixl_queue *que = &vsi->queues[ri->iri_qsidx];
struct rx_ring *rxr = &que->rxr;
- struct ifnet *ifp = vsi->ifp;
-#if defined(INET6) || defined(INET)
- struct lro_ctrl *lro = &rxr->lro;
- struct lro_entry *queued;
-#endif
- int i, nextp, processed = 0;
union i40e_rx_desc *cur;
- struct ixl_rx_buf *rbuf, *nbuf;
-
-
- IXL_RX_LOCK(rxr);
-
-#ifdef DEV_NETMAP
- if (netmap_rx_irq(ifp, que->me, &count)) {
- IXL_RX_UNLOCK(rxr);
- return (FALSE);
- }
-#endif /* DEV_NETMAP */
-
- for (i = rxr->next_check; count != 0;) {
- struct mbuf *sendmp, *mh, *mp;
- u32 rsc, status, error;
- u16 hlen, plen, vtag;
- u64 qword;
- u8 ptype;
- bool eop;
-
- /* Sync the ring. */
- bus_dmamap_sync(rxr->dma.tag, rxr->dma.map,
- BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
-
- cur = &rxr->base[i];
+ u32 status, error;
+ u16 hlen, plen, vtag;
+ u64 qword;
+ u8 ptype;
+ bool eop;
+ int i, cidx;
+
+ cidx = ri->iri_cidx;
+ i = 0;
+ do {
+ cur = &rxr->rx_base[cidx];
qword = le64toh(cur->wb.qword1.status_error_len);
status = (qword & I40E_RXD_QW1_STATUS_MASK)
- >> I40E_RXD_QW1_STATUS_SHIFT;
+ >> I40E_RXD_QW1_STATUS_SHIFT;
error = (qword & I40E_RXD_QW1_ERROR_MASK)
- >> I40E_RXD_QW1_ERROR_SHIFT;
+ >> I40E_RXD_QW1_ERROR_SHIFT;
plen = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK)
- >> I40E_RXD_QW1_LENGTH_PBUF_SHIFT;
+ >> I40E_RXD_QW1_LENGTH_PBUF_SHIFT;
hlen = (qword & I40E_RXD_QW1_LENGTH_HBUF_MASK)
- >> I40E_RXD_QW1_LENGTH_HBUF_SHIFT;
+ >> I40E_RXD_QW1_LENGTH_HBUF_SHIFT;
ptype = (qword & I40E_RXD_QW1_PTYPE_MASK)
- >> I40E_RXD_QW1_PTYPE_SHIFT;
+ >> I40E_RXD_QW1_PTYPE_SHIFT;
- if ((status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT)) == 0) {
- ++rxr->not_done;
- break;
- }
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- break;
+ /* we should never be called without a valid descriptor */
+ MPASS((status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT)) != 0);
+
+ ri->iri_len += plen;
+ rxr->rx_bytes += plen;
- count--;
- sendmp = NULL;
- nbuf = NULL;
- rsc = 0;
cur->wb.qword1.status_error_len = 0;
- rbuf = &rxr->buffers[i];
- mh = rbuf->m_head;
- mp = rbuf->m_pack;
eop = (status & (1 << I40E_RX_DESC_STATUS_EOF_SHIFT));
if (status & (1 << I40E_RX_DESC_STATUS_L2TAG1P_SHIFT))
vtag = le16toh(cur->wb.qword0.lo_dword.l2tag1);
@@ -1578,171 +598,31 @@
** note that only EOP descriptor has valid
** error results.
*/
- if (eop && (error & (1 << I40E_RX_DESC_ERROR_RXE_SHIFT))) {
+ if (eop && (error & (1 << I40E_RX_DESC_ERROR_RXE_SHIFT))) {
rxr->discarded++;
- ixl_rx_discard(rxr, i);
- goto next_desc;
- }
-
- /* Prefetch the next buffer */
- if (!eop) {
- nextp = i + 1;
- if (nextp == que->num_desc)
- nextp = 0;
- nbuf = &rxr->buffers[nextp];
- prefetch(nbuf);
- }
-
- /*
- ** The header mbuf is ONLY used when header
- ** split is enabled, otherwise we get normal
- ** behavior, ie, both header and payload
- ** are DMA'd into the payload buffer.
- **
- ** Rather than using the fmp/lmp global pointers
- ** we now keep the head of a packet chain in the
- ** buffer struct and pass this along from one
- ** descriptor to the next, until we get EOP.
- */
- if (rxr->hdr_split && (rbuf->fmp == NULL)) {
- if (hlen > IXL_RX_HDR)
- hlen = IXL_RX_HDR;
- mh->m_len = hlen;
- mh->m_flags |= M_PKTHDR;
- mh->m_next = NULL;
- mh->m_pkthdr.len = mh->m_len;
- /* Null buf pointer so it is refreshed */
- rbuf->m_head = NULL;
- /*
- ** Check the payload length, this
- ** could be zero if its a small
- ** packet.
- */
- if (plen > 0) {
- mp->m_len = plen;
- mp->m_next = NULL;
- mp->m_flags &= ~M_PKTHDR;
- mh->m_next = mp;
- mh->m_pkthdr.len += mp->m_len;
- /* Null buf pointer so it is refreshed */
- rbuf->m_pack = NULL;
- rxr->split++;
- }
- /*
- ** Now create the forward
- ** chain so when complete
- ** we wont have to.
- */
- if (eop == 0) {
- /* stash the chain head */
- nbuf->fmp = mh;
- /* Make forward chain */
- if (plen)
- mp->m_next = nbuf->m_pack;
- else
- mh->m_next = nbuf->m_pack;
- } else {
- /* Singlet, prepare to send */
- sendmp = mh;
- if (vtag) {
- sendmp->m_pkthdr.ether_vtag = vtag;
- sendmp->m_flags |= M_VLANTAG;
- }
- }
- } else {
- /*
- ** Either no header split, or a
- ** secondary piece of a fragmented
- ** split packet.
- */
- mp->m_len = plen;
- /*
- ** See if there is a stored head
- ** that determines what we are
- */
- sendmp = rbuf->fmp;
- rbuf->m_pack = rbuf->fmp = NULL;
-
- if (sendmp != NULL) /* secondary frag */
- sendmp->m_pkthdr.len += mp->m_len;
- else {
- /* first desc of a non-ps chain */
- sendmp = mp;
- sendmp->m_flags |= M_PKTHDR;
- sendmp->m_pkthdr.len = mp->m_len;
- if (vtag) {
- sendmp->m_pkthdr.ether_vtag = vtag;
- sendmp->m_flags |= M_VLANTAG;
- }
- }
- /* Pass the head pointer on */
- if (eop == 0) {
- nbuf->fmp = sendmp;
- sendmp = NULL;
- mp->m_next = nbuf->m_pack;
- }
- }
- ++processed;
- /* Sending this frame? */
- if (eop) {
- sendmp->m_pkthdr.rcvif = ifp;
- /* gather stats */
- rxr->rx_packets++;
- rxr->rx_bytes += sendmp->m_pkthdr.len;
- /* capture data for dynamic ITR adjustment */
- rxr->packets++;
- rxr->bytes += sendmp->m_pkthdr.len;
- if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
- ixl_rx_checksum(sendmp, status, error, ptype);
-#ifdef RSS
- sendmp->m_pkthdr.flowid =
- le32toh(cur->wb.qword0.hi_dword.rss);
- M_HASHTYPE_SET(sendmp, ixl_ptype_to_hash(ptype));
-#else
- sendmp->m_pkthdr.flowid = que->msix;
- M_HASHTYPE_SET(sendmp, M_HASHTYPE_OPAQUE);
-#endif
- }
-next_desc:
- bus_dmamap_sync(rxr->dma.tag, rxr->dma.map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
- /* Advance our pointers to the next descriptor. */
- if (++i == que->num_desc)
- i = 0;
-
- /* Now send to the stack or do LRO */
- if (sendmp != NULL) {
- rxr->next_check = i;
- ixl_rx_input(rxr, ifp, sendmp, ptype);
- i = rxr->next_check;
- }
-
- /* Every 8 descriptors we go to refresh mbufs */
- if (processed == 8) {
- ixl_refresh_mbufs(que, i);
- processed = 0;
+ return (EBADMSG);
}
- }
-
- /* Refresh any remaining buf structs */
- if (ixl_rx_unrefreshed(que))
- ixl_refresh_mbufs(que, i);
-
- rxr->next_check = i;
-
-#if defined(INET6) || defined(INET)
- /*
- * Flush any outstanding LRO work
- */
- while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lro->lro_active, next);
- tcp_lro_flush(lro, queued);
- }
-#endif
-
- IXL_RX_UNLOCK(rxr);
- return (FALSE);
+ ri->iri_frags[i].irf_flid = 0;
+ ri->iri_frags[i].irf_idx = cidx;
+ if (++cidx == ixl_sctx->isc_ntxd)
+ cidx = 0;
+ i++;
+ /* even a 16K packet shouldn't consume more than 8 clusters */
+ MPASS(i < 9);
+ } while (!eop);
+
+ rxr->rx_packets++;
+ /* capture data for dynamic ITR adjustment */
+ rxr->packets++;
+ if ((vsi->ifp->if_capenable & IFCAP_RXCSUM) != 0)
+ ixl_rx_checksum(ri, status, error, ptype);
+ ri->iri_flowid = le32toh(cur->wb.qword0.hi_dword.rss);
+ ri->iri_rsstype = ixl_ptype_to_hash(ptype);
+ ri->iri_vtag = vtag;
+ ri->iri_nfrags = i;
+ if (vtag)
+ ri->iri_flags |= M_VLANTAG;
+ return (0);
}
@@ -1754,7 +634,7 @@
*
*********************************************************************/
static void
-ixl_rx_checksum(struct mbuf * mp, u32 status, u32 error, u8 ptype)
+ixl_rx_checksum(if_rxd_info_t ri, u32 status, u32 error, u8 ptype)
{
struct i40e_rx_ptype_decoded decoded;
@@ -1763,7 +643,7 @@
/* Errors? */
if (error & ((1 << I40E_RX_DESC_ERROR_IPE_SHIFT) |
(1 << I40E_RX_DESC_ERROR_L4E_SHIFT))) {
- mp->m_pkthdr.csum_flags = 0;
+ ri->iri_csum_flags = 0;
return;
}
@@ -1772,19 +652,19 @@
decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV6)
if (status &
(1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT)) {
- mp->m_pkthdr.csum_flags = 0;
+ ri->iri_csum_flags = 0;
return;
}
/* IP Checksum Good */
- mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED;
- mp->m_pkthdr.csum_flags |= CSUM_IP_VALID;
+ ri->iri_csum_flags = CSUM_IP_CHECKED;
+ ri->iri_csum_flags |= CSUM_IP_VALID;
if (status & (1 << I40E_RX_DESC_STATUS_L3L4P_SHIFT)) {
- mp->m_pkthdr.csum_flags |=
+ ri->iri_csum_flags |=
(CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
- mp->m_pkthdr.csum_data |= htons(0xffff);
+ ri->iri_csum_data |= htons(0xffff);
}
return;
}
Index: sys/dev/ixl/ixlv.h
===================================================================
--- sys/dev/ixl/ixlv.h
+++ sys/dev/ixl/ixlv.h
@@ -104,7 +104,6 @@
struct device *dev;
struct resource *pci_mem;
- struct resource *msix_mem;
enum ixlv_state_t init_state;
@@ -114,8 +113,7 @@
void *tag;
struct resource *res; /* For the AQ */
- struct ifmedia media;
- struct callout timer;
+ struct ifmedia *media;
int msix;
int pf_version;
int if_flags;
@@ -123,15 +121,12 @@
bool link_up;
u32 link_speed;
- struct mtx mtx;
-
u32 qbase;
u32 admvec;
- struct timeout_task timeout;
+#ifdef notyet
struct task aq_irq;
struct task aq_sched;
- struct taskqueue *tq;
-
+#endif
struct ixl_vsi vsi;
/* Filter lists */
@@ -166,7 +161,6 @@
u8 aq_buffer[IXL_AQ_BUF_SZ];
};
-#define IXLV_CORE_LOCK_ASSERT(sc) mtx_assert(&(sc)->mtx, MA_OWNED)
/*
** This checks for a zero mac addr, something that will be likely
** unless the Admin on the Host has created one.
Index: sys/dev/ixl/ixlvc.c
===================================================================
--- sys/dev/ixl/ixlvc.c
+++ sys/dev/ixl/ixlvc.c
@@ -217,7 +217,7 @@
int retries = 0;
event.buf_len = IXL_AQ_BUFSZ;
- event.msg_buf = malloc(event.buf_len, M_DEVBUF, M_NOWAIT);
+ event.msg_buf = malloc(event.buf_len, M_IXL, M_NOWAIT);
if (!event.msg_buf) {
err = ENOMEM;
goto out;
@@ -257,7 +257,7 @@
sc->pf_version = pf_vvi->minor;
out_alloc:
- free(event.msg_buf, M_DEVBUF);
+ free(event.msg_buf, M_IXL);
out:
return err;
}
@@ -309,7 +309,7 @@
len = sizeof(struct i40e_virtchnl_vf_resource) +
sizeof(struct i40e_virtchnl_vsi_resource);
event.buf_len = len;
- event.msg_buf = malloc(event.buf_len, M_DEVBUF, M_NOWAIT);
+ event.msg_buf = malloc(event.buf_len, M_IXL, M_NOWAIT);
if (!event.msg_buf) {
err = ENOMEM;
goto out;
@@ -354,7 +354,7 @@
i40e_vf_parse_hw_config(hw, sc->vf_res);
out_alloc:
- free(event.msg_buf, M_DEVBUF);
+ free(event.msg_buf, M_IXL);
out:
return err;
}
@@ -372,6 +372,7 @@
struct ixl_queue *que = vsi->queues;
struct tx_ring *txr;
struct rx_ring *rxr;
+ if_shared_ctx_t sctx;
int len, pairs;
struct i40e_virtchnl_vsi_queue_config_info *vqci;
@@ -380,12 +381,13 @@
pairs = vsi->num_queues;
len = sizeof(struct i40e_virtchnl_vsi_queue_config_info) +
(sizeof(struct i40e_virtchnl_queue_pair_info) * pairs);
- vqci = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ vqci = malloc(len, M_IXL, M_NOWAIT | M_ZERO);
if (!vqci) {
device_printf(dev, "%s: unable to allocate memory\n", __func__);
ixl_vc_schedule_retry(&sc->vc_mgr);
return;
}
+ sctx = iflib_get_sctx(sc->vsi.ctx);
vqci->vsi_id = sc->vsi_res->vsi_id;
vqci->num_queue_pairs = pairs;
vqpi = vqci->qpair;
@@ -397,17 +399,17 @@
rxr = &que->rxr;
vqpi->txq.vsi_id = vqci->vsi_id;
vqpi->txq.queue_id = i;
- vqpi->txq.ring_len = que->num_desc;
- vqpi->txq.dma_ring_addr = txr->dma.pa;
+ vqpi->txq.ring_len = sctx->isc_ntxd;
+ vqpi->txq.dma_ring_addr = txr->tx_paddr;
/* Enable Head writeback */
vqpi->txq.headwb_enabled = 1;
- vqpi->txq.dma_headwb_addr = txr->dma.pa +
- (que->num_desc * sizeof(struct i40e_tx_desc));
+ vqpi->txq.dma_headwb_addr = txr->tx_paddr +
+ (sctx->isc_ntxd * sizeof(struct i40e_tx_desc));
vqpi->rxq.vsi_id = vqci->vsi_id;
vqpi->rxq.queue_id = i;
- vqpi->rxq.ring_len = que->num_desc;
- vqpi->rxq.dma_ring_addr = rxr->dma.pa;
+ vqpi->rxq.ring_len = sctx->isc_ntxd;
+ vqpi->rxq.dma_ring_addr = rxr->rx_paddr;
vqpi->rxq.max_pkt_size = vsi->max_frame_size;
vqpi->rxq.databuffer_size = rxr->mbuf_sz;
vqpi->rxq.splithdr_enabled = 0;
@@ -415,7 +417,7 @@
ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES,
(u8 *)vqci, len);
- free(vqci, M_DEVBUF);
+ free(vqci, M_IXL);
}
/*
@@ -471,7 +473,7 @@
len = sizeof(struct i40e_virtchnl_irq_map_info) +
(sc->msix * sizeof(struct i40e_virtchnl_vector_map));
- vm = malloc(len, M_DEVBUF, M_NOWAIT);
+ vm = malloc(len, M_IXL, M_NOWAIT);
if (!vm) {
printf("%s: unable to allocate memory\n", __func__);
ixl_vc_schedule_retry(&sc->vc_mgr);
@@ -499,7 +501,7 @@
ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
(u8 *)vm, len);
- free(vm, M_DEVBUF);
+ free(vm, M_IXL);
}
/*
@@ -537,7 +539,7 @@
return;
}
- v = malloc(len, M_DEVBUF, M_NOWAIT);
+ v = malloc(len, M_IXL, M_NOWAIT);
if (!v) {
device_printf(dev, "%s: unable to allocate memory\n",
__func__);
@@ -567,7 +569,7 @@
}
ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_ADD_VLAN, (u8 *)v, len);
- free(v, M_DEVBUF);
+ free(v, M_IXL);
/* add stats? */
}
@@ -606,7 +608,7 @@
return;
}
- v = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ v = malloc(len, M_IXL, M_NOWAIT | M_ZERO);
if (!v) {
device_printf(dev, "%s: unable to allocate memory\n",
__func__);
@@ -623,7 +625,7 @@
bcopy(&f->vlan, &v->vlan_id[i], sizeof(u16));
i++;
SLIST_REMOVE(sc->vlan_filters, f, ixlv_vlan_filter, next);
- free(f, M_DEVBUF);
+ free(f, M_IXL);
}
if (i == cnt)
break;
@@ -637,7 +639,7 @@
}
ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_DEL_VLAN, (u8 *)v, len);
- free(v, M_DEVBUF);
+ free(v, M_IXL);
/* add stats? */
}
@@ -670,7 +672,7 @@
len = sizeof(struct i40e_virtchnl_ether_addr_list) +
(cnt * sizeof(struct i40e_virtchnl_ether_addr));
- a = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ a = malloc(len, M_IXL, M_NOWAIT | M_ZERO);
if (a == NULL) {
device_printf(dev, "%s: Failed to get memory for "
"virtchnl_ether_addr_list\n", __func__);
@@ -698,7 +700,7 @@
ixlv_send_pf_msg(sc,
I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS, (u8 *)a, len);
/* add stats? */
- free(a, M_DEVBUF);
+ free(a, M_IXL);
return;
}
@@ -730,7 +732,7 @@
len = sizeof(struct i40e_virtchnl_ether_addr_list) +
(cnt * sizeof(struct i40e_virtchnl_ether_addr));
- d = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ d = malloc(len, M_IXL, M_NOWAIT | M_ZERO);
if (d == NULL) {
device_printf(dev, "%s: Failed to get memory for "
"virtchnl_ether_addr_list\n", __func__);
@@ -748,7 +750,7 @@
MAC_FORMAT_ARGS(f->macaddr));
j++;
SLIST_REMOVE(sc->mac_filters, f, ixlv_mac_filter, next);
- free(f, M_DEVBUF);
+ free(f, M_IXL);
}
if (j == cnt)
break;
@@ -756,7 +758,7 @@
ixlv_send_pf_msg(sc,
I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS, (u8 *)d, len);
/* add stats? */
- free(d, M_DEVBUF);
+ free(d, M_IXL);
return;
}
@@ -806,9 +808,10 @@
uint64_t tx_discards;
tx_discards = es->tx_discards;
+#ifdef notyet
for (int i = 0; i < vsi->num_queues; i++)
tx_discards += sc->vsi.queues[i].txr.br->br_drops;
-
+#endif
/* Update ifnet stats */
IXL_SET_IPACKETS(vsi, es->rx_unicast +
es->rx_multicast +
@@ -1001,7 +1004,6 @@
mgr->sc = sc;
mgr->current = NULL;
TAILQ_INIT(&mgr->pending);
- callout_init_mtx(&mgr->callout, &sc->mtx, 0);
}
static void
@@ -1036,7 +1038,6 @@
{
struct ixl_vc_mgr *mgr = (struct ixl_vc_mgr *)arg;
- IXLV_CORE_LOCK_ASSERT(mgr->sc);
ixl_vc_process_completion(mgr, I40E_ERR_TIMEOUT);
}
@@ -1045,7 +1046,6 @@
{
struct ixl_vc_mgr *mgr = (struct ixl_vc_mgr *)arg;
- IXLV_CORE_LOCK_ASSERT(mgr->sc);
ixl_vc_send_current(mgr);
}
@@ -1088,7 +1088,6 @@
ixl_vc_enqueue(struct ixl_vc_mgr *mgr, struct ixl_vc_cmd *cmd,
uint32_t req, ixl_vc_callback_t *callback, void *arg)
{
- IXLV_CORE_LOCK_ASSERT(mgr->sc);
if (cmd->flags & IXLV_VC_CMD_FLAG_BUSY) {
if (mgr->current == cmd)
@@ -1111,7 +1110,6 @@
{
struct ixl_vc_cmd *cmd;
- IXLV_CORE_LOCK_ASSERT(mgr->sc);
KASSERT(TAILQ_EMPTY(&mgr->pending) || mgr->current != NULL,
("ixlv: pending commands waiting but no command in progress"));
Index: sys/modules/ixl/Makefile
===================================================================
--- sys/modules/ixl/Makefile
+++ sys/modules/ixl/Makefile
@@ -3,13 +3,12 @@
.PATH: ${.CURDIR}/../../dev/ixl
KMOD = if_ixl
-SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h opt_bdg.h
+SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h opt_bdg.h ifdi_if.h
SRCS += opt_inet.h opt_inet6.h opt_rss.h
-SRCS += if_ixl.c ixl_txrx.c i40e_osdep.c
+SRCS += if_ixl.c if_ixl_common.c ixl_txrx.c i40e_osdep.c
# Shared source
SRCS += i40e_common.c i40e_nvm.c i40e_adminq.c i40e_lan_hmc.c i40e_hmc.c
-
CFLAGS += -DSMP -DIXL_DEBUG_SYSCTL
# Add Flow Director support
Index: sys/modules/ixlv/Makefile
===================================================================
--- sys/modules/ixlv/Makefile
+++ sys/modules/ixlv/Makefile
@@ -3,9 +3,9 @@
.PATH: ${.CURDIR}/../../dev/ixl
KMOD = if_ixlv
-SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h opt_bdg.h
+SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h opt_bdg.h ifdi_if.h
SRCS += opt_inet.h opt_inet6.h opt_rss.h
-SRCS += if_ixlv.c ixlvc.c ixl_txrx.c i40e_osdep.c
+SRCS += if_ixlv.c ixlvc.c if_ixl_common.c ixl_txrx.c i40e_osdep.c
# Shared source
SRCS += i40e_common.c i40e_nvm.c i40e_adminq.c

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 8, 8:51 PM (15 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29416799
Default Alt Text
D5214.id13967.diff (226 KB)

Event Timeline