Index: sys/dev/ixl/if_ixl.c =================================================================== --- sys/dev/ixl/if_ixl.c +++ sys/dev/ixl/if_ixl.c @@ -45,6 +45,8 @@ #include #endif +#include "ifdi_if.h" + /********************************************************************* * Driver version *********************************************************************/ @@ -55,68 +57,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_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 *); @@ -127,21 +106,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 *); @@ -163,14 +134,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); @@ -205,32 +173,62 @@ #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); +static void ixl_if_queue_intr_disable(if_ctx_t ctx, uint16_t qid); + +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} }; @@ -244,14 +242,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: @@ -321,11 +348,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 -#endif /* DEV_NETMAP */ - static char *ixl_fc_string[6] = { "None", "Rx", @@ -335,68 +357,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*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 = 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; - - u16 pci_vendor_id, pci_device_id; - u16 pci_subvendor_id, pci_subdevice_id; - char device_name[256]; - static bool lock_init = FALSE; + 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); - 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 * @@ -408,37 +416,41 @@ *********************************************************************/ 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); + /* ** 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), @@ -537,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)) { @@ -579,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" @@ -624,46 +638,73 @@ 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_late; +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); @@ -685,12 +726,6 @@ 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) { @@ -711,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); } @@ -743,12 +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; - struct ixl_queue *que = vsi->queues; i40e_status status; #ifdef PCI_IOV int error; @@ -756,82 +780,31 @@ 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); - } - - for (int i = 0; i < vsi->num_queues; i++, que++) { - if (que->tq) { - taskqueue_drain(que->tq, &que->task); - taskqueue_drain(que->tq, &que->tx_task); - taskqueue_free(que->tq); - } - } - /* 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 */ 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 @@ -843,7 +816,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; @@ -851,7 +824,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); } @@ -859,7 +832,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 */ @@ -890,226 +863,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 + * Ioctl mtu entry point * - * ixl_ioctl is called when the user wants to configure the - * interface. - * - * 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; + struct ixl_vsi *vsi = iflib_get_softc(ctx); - 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; - } - - 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 * @@ -1122,22 +896,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)) { @@ -1156,15 +929,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; @@ -1193,9 +957,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); @@ -1213,114 +974,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); @@ -1333,10 +1025,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); } @@ -1345,43 +1034,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); } @@ -1390,7 +1051,7 @@ * MSIX Admin Queue Interrupt Service routine * **********************************************************************/ -static void +int ixl_msix_adminq(void *arg) { struct ixl_pf *pf = arg; @@ -1414,7 +1075,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 @@ -1422,8 +1083,66 @@ 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); +} + +/********************************************************************* + * + * Setup MSIX Interrupt resources and handlers for the VSI + * + **********************************************************************/ +int +ixl_if_msix_intr_assign(if_ctx_t ctx, int msix) +{ + struct ixl_vsi *vsi = iflib_get_softc(ctx); + struct ixl_pf *pf = vsi->back; + struct ixl_queue *que = vsi->queues; + int err, i, rid, vector = 0; + char buf[16]; + + /* Admin Que is vector 0*/ + rid = vector + 1; + + 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); } /********************************************************************* @@ -1435,14 +1154,13 @@ * **********************************************************************/ static void -ixl_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) +ixl_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr) { - struct ixl_vsi *vsi = ifp->if_softc; - struct ixl_pf *pf = vsi->back; + 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"); - IXL_PF_LOCK(pf); hw->phy.get_link_info = TRUE; i40e_get_link_status(hw, &pf->link_up); @@ -1452,7 +1170,6 @@ ifmr->ifm_active = IFM_ETHER; if (!pf->link_up) { - IXL_PF_UNLOCK(pf); return; } @@ -1552,33 +1269,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); } @@ -1590,9 +1280,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; @@ -1606,7 +1297,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; @@ -1614,7 +1305,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; @@ -1636,7 +1327,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 << @@ -1650,44 +1341,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); } /********************************************************************* @@ -1697,92 +1375,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 * @@ -1792,68 +1442,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; -hung: - device_printf(dev, "Local Timer: HANG DETECT - Resetting!!\n"); - ixl_init_locked(pf); + /* Fire off the adminq task */ + iflib_admin_intr_deferred(ctx); + + /* Update stats */ + ixl_update_stats_counters(pf); } /* @@ -1866,8 +1480,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) { @@ -1885,24 +1498,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; } /********************************************************************* @@ -1913,304 +1522,14 @@ **********************************************************************/ 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; + struct ixl_vsi *vsi = iflib_get_softc(ctx); - mtx_assert(&pf->pf_mtx, MA_OWNED); - - INIT_DEBUGOUT("ixl_stop: begin\n"); - if (pf->num_vfs == 0) - ixl_disable_intr(vsi); - else - ixl_disable_rings_intr(vsi); + INIT_DEBUGOUT("ixl_if_stop: begin\n"); 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); -} - - -/********************************************************************* - * - * 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; - /* Tasklet for Admin Queue */ - 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(pf->dev)); - ++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; - 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", device_get_nameunit(dev)); -#endif - } - - 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 sane */ - if ((ixl_max_queues != 0) && (ixl_max_queues <= queues)) - queues = ixl_max_queues; - -#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); -} - - /* * Plumb MSI/X vectors */ @@ -2275,11 +1594,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 @@ -2363,7 +1680,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, @@ -2384,12 +1701,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); } @@ -2398,7 +1709,7 @@ { struct ixl_vsi *vsi = &pf->vsi; struct ixl_queue *que = vsi->queues; - device_t dev = pf->dev; + device_t dev = iflib_get_dev(vsi->ctx); int rid, memrid; memrid = PCIR_BAR(IXL_BAR); @@ -2407,19 +1718,14 @@ 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 */ @@ -2434,18 +1740,10 @@ 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 @@ -2453,79 +1751,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 } @@ -2537,58 +1835,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; - + /* 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; - - /* - * 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; + ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + + ETHER_VLAN_ENCAP_LEN; /* ** Don't turn this on by default, if vlans are @@ -2600,13 +1866,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 */ @@ -2628,10 +1887,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); } @@ -2658,7 +1915,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; @@ -2676,7 +1933,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; @@ -2721,17 +1978,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) { @@ -2769,7 +2029,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; @@ -2801,17 +2061,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) { @@ -2851,8 +2112,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; @@ -2875,68 +2136,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; - } - wr32(vsi->hw, I40E_QRX_TAIL(que->me), 0); -#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) { @@ -2945,11 +2148,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 @@ -2957,127 +2159,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 @@ -3149,7 +2230,6 @@ } rxr->bytes = 0; rxr->packets = 0; - return; } @@ -3223,7 +2303,6 @@ } txr->bytes = 0; txr->packets = 0; - return; } #define QUEUE_NAME_LEN 32 @@ -3236,7 +2315,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"); @@ -3248,8 +2327,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; @@ -3415,8 +2494,6 @@ entry++; } } - - /* ** ixl_config_rss - setup RSS ** - note this is done for the single vsi @@ -3426,6 +2503,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 @@ -3484,6 +2562,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) @@ -3509,57 +2595,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 @@ -3593,7 +2628,6 @@ flags = IXL_FILTER_VLAN; flags |= (IXL_FILTER_ADD | IXL_FILTER_USED); ixl_add_hw_filters(vsi, flags, cnt); - return; } /* @@ -3629,8 +2663,6 @@ f->vlan = IXL_VLAN_ANY; f->flags |= (IXL_FILTER_ADD | IXL_FILTER_USED | IXL_FILTER_MC); - - return; } static void @@ -3641,20 +2673,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) @@ -3674,7 +2740,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); @@ -3689,7 +2755,7 @@ return; } -static void +void ixl_del_filter(struct ixl_vsi *vsi, u8 *macaddr, s16 vlan) { struct ixl_mac_filter *f; @@ -3744,18 +2810,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; @@ -3792,7 +2852,7 @@ else vsi->hw_filters_add += j; } - free(a, M_DEVBUF); + free(a, M_IXL); return; } @@ -3805,20 +2865,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; @@ -3832,7 +2887,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) @@ -3854,7 +2909,7 @@ } else vsi->hw_filters_del += j; } - free(d, M_DEVBUF); + free(d, M_IXL); DEBUGOUT("ixl_del_hw_filters: end\n"); return; @@ -3885,7 +2940,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; } @@ -3902,7 +2957,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; } @@ -3911,6 +2966,59 @@ 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; + struct ixl_queue *que = vsi->queues; + + if (ixl_enable_msix) { + ixl_enable_adminq(hw); + for (int i = 0; i < vsi->num_queues; i++, que++) + ixl_if_queue_intr_enable(vsi->ctx, que->me); + } 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; + struct ixl_queue *que = vsi->queues; + + if (ixl_enable_msix) { + ixl_disable_adminq(hw); + for (int i = 0; i < vsi->num_queues; i++, que++) + ixl_if_queue_intr_disable(ctx, que->me); + } 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); +} + +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); +} + static int ixl_disable_rings(struct ixl_vsi *vsi) { @@ -3937,7 +3045,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; } @@ -3953,7 +3061,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; } @@ -3971,7 +3079,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; @@ -4043,33 +3151,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; @@ -4094,28 +3181,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; @@ -4317,11 +3382,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; @@ -4329,13 +3394,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); @@ -4366,18 +3430,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 @@ -4413,7 +3476,6 @@ 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); @@ -4456,6 +3518,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; @@ -4511,22 +3574,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 + @@ -4641,7 +3700,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; @@ -4729,7 +3788,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; @@ -4777,11 +3839,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); } @@ -4800,7 +3858,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; @@ -5037,7 +4095,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) { @@ -5055,7 +4113,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; } @@ -5075,14 +4133,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); @@ -5123,6 +4181,7 @@ sbuf_cat(buf, "\n"); } + sbuf_trim(buf); error = sbuf_finish(buf); sbuf_delete(buf); @@ -5172,7 +4231,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; @@ -5182,7 +4241,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); @@ -5301,7 +4360,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)); } @@ -5499,7 +4558,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); @@ -5512,7 +4571,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); @@ -6385,7 +5444,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; } @@ -6449,7 +5508,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; @@ -6457,10 +5516,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; @@ -6479,8 +5537,6 @@ icr0 |= I40E_PFINT_ICR0_ENA_VFLR_MASK; wr32(hw, I40E_PFINT_ICR0_ENA, icr0); ixl_flush(hw); - - IXL_PF_UNLOCK(pf); } static int @@ -6538,19 +5594,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); @@ -6575,32 +5632,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); @@ -6611,19 +5667,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++) @@ -6632,19 +5683,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; @@ -6678,7 +5730,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 +#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_DEVBUF); +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); 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); @@ -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); } /* 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. @@ -1136,134 +1090,12 @@ 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; + /* should either fail or be M_WAITOK XXX */ v = malloc(sizeof(struct ixlv_vlan_filter), M_DEVBUF, 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; } /* @@ -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_DYN_CTL01); - reg |= I40E_VFINT_DYN_CTL01_CLEARPBA_MASK; - wr32(hw, I40E_VFINT_DYN_CTL01, reg); + reg = rd32(hw, I40E_VFINT_ICR01); + mask = rd32(hw, I40E_VFINT_ICR0_ENA1); - /* 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; @@ -2969,4 +2405,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 #include -#include -#include #include #include #include @@ -60,6 +58,7 @@ #include #include #include +#include #include #include @@ -85,7 +84,6 @@ #include #include #include -#include #include #include #include @@ -96,12 +94,16 @@ #include #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 + #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], \ @@ -304,16 +306,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 +354,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 +372,21 @@ * 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; + struct i40e_tx_desc *tx_base; + uint64_t tx_paddr; u16 next_avail; u16 next_to_clean; u16 atr_rate; u16 atr_count; u16 itr; u16 latency; - struct ixl_tx_buf *buffers; + struct ixl_tx_buf *tx_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; /* Used for Dynamic ITR calculation */ u32 packets; @@ -425,20 +403,13 @@ * 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; @@ -467,13 +438,11 @@ 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; @@ -486,32 +455,40 @@ 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 +496,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 +526,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 +535,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 +548,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 +586,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 *); + #ifdef IXL_FDIR void ixl_atr(struct ixl_queue *, struct tcphdr *, int); #endif @@ -652,4 +595,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,12 +54,22 @@ /* 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 @@ -73,28 +83,14 @@ 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 +125,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,148 +51,35 @@ #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); -#ifdef DEV_NETMAP -#include -#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 - - /* - ** 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); - - que = &vsi->queues[i]; - txr = &que->txr; - - 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); - - return (0); -} - -int -ixl_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr) -{ - struct ixl_queue *que = txr->que; - struct ixl_vsi *vsi = que->vsi; - struct mbuf *next; - int err = 0; +extern int ixl_intr(void *arg); +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 +}; - if (((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) || - vsi->link_active == 0) - return (ENETDOWN); +extern if_shared_ctx_t ixl_sctx; - /* 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); - 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) - break; - } - - if (txr->avail < IXL_TX_CLEANUP_THRESHOLD) - ixl_txeof(que); - - return (err); -} - -/* - * 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); -} - -/* -** 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); - } - if_qflush(ifp); -} +#ifdef notyet /* ** Find mbuf chains passed to the driver ** that are 'sparse', using more than 8 @@ -219,6 +106,113 @@ return (ret); } +#endif + + +/********************************************************************* + * + * Setup descriptor for hw offloads + * + **********************************************************************/ + +static void +ixl_tx_setup_offload(struct ixl_queue *que, + if_pkt_info_t pi, u32 *cmd, u32 *off) +{ + + + switch (pi->ipi_etype) { +#ifdef INET + case ETHERTYPE_IP: + /* The IP checksum must be recalculated with TSO */ + if (pi->ipi_csum_flags & CSUM_TSO) + *cmd |= I40E_TX_DESC_CMD_IIPT_IPV4_CSUM; + else + *cmd |= I40E_TX_DESC_CMD_IIPT_IPV4; + break; +#endif +#ifdef INET6 + case ETHERTYPE_IPV6: + *cmd |= I40E_TX_DESC_CMD_IIPT_IPV6; + break; +#endif + default: + break; + } + + *off |= (pi->ipi_ehdrlen >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT; + *off |= (pi->ipi_ip_hlen >> 2) << I40E_TX_DESC_LENGTH_IPLEN_SHIFT; + + 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; + + 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; + } + +} + +/********************************************************************** + * + * Setup context for hardware segmentation offload (TSO) + * + **********************************************************************/ +static int +ixl_tso_setup(struct ixl_queue *que, if_pkt_info_t pi) +{ + struct tx_ring *txr = &que->txr; + 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); + + TXD->tunneling_params = htole32(0); + buf->eop_index = -1; + + if (++idx == ixl_sctx->isc_ntxd) + idx = 0; + return (idx); +} + /********************************************************************* @@ -231,37 +225,35 @@ #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; + first = pi->ipi_pidx; + buf = &txr->tx_buffers[first]; + + if (pi->ipi_flags & IPI_TX_INTR) + cmd |= (I40E_TX_DESC_CMD_RS << I40E_TXD_QW1_CMD_SHIFT); +#ifdef notyet + /* add this check to iflib - shouldn't actually happen in practice */ if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { /* Use larger mapping for TSO */ tag = txr->tso_tag; @@ -277,76 +269,27 @@ } } - /* - * 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; +#endif /* 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) + first = ixl_tso_setup(que, 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; + + i = first; 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,128 +298,41 @@ | ((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; + pi->ipi_new_pidx = 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); - /* Set the index of the descriptor that will be marked done */ - buf = &txr->buffers[first]; + /* Set the index of the descriptor that will be marked done */ + buf = &txr->tx_buffers[first]; buf->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); - - ixl_flush(hw); - /* 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. @@ -487,30 +343,12 @@ void ixl_init_tx_ring(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 */ @@ -518,310 +356,15 @@ 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 */ + 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 ** location the HW records its HEAD index @@ -830,7 +373,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); } @@ -841,37 +385,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) { + 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); @@ -882,11 +413,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 @@ -894,74 +423,28 @@ ** '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 (++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; /* 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); } /********************************************************************* @@ -974,468 +457,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); - } +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) - 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; - } - } - - 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; - } + struct ixl_vsi *vsi = arg; + struct rx_ring *rxr = &vsi->queues[rxqid].rxr; + int i; + uint32_t next_pidx; - /* header split is off */ - rxr->hdr_split = FALSE; - - /* 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; + 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; } - - - /* 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; - } -#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) +static void +ixl_isc_rxd_flush(void * arg, uint16_t rxqid, uint8_t flid __unused, uint32_t pidx) { - 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; - } + struct ixl_vsi *vsi = arg; + struct rx_ring *rxr = &vsi->queues[rxqid].rxr; - INIT_DBG_IF(que->vsi->ifp, "queue %d: end", que->me); - return; + wr32(vsi->hw, rxr->tail, pidx); } -static __inline void -ixl_rx_input(struct rx_ring *rxr, struct ifnet *ifp, struct mbuf *m, u8 ptype) -{ - -#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); -} - - -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. @@ -1491,259 +562,85 @@ /* 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]; - qword = le64toh(cur->wb.qword1.status_error_len); - status = (qword & I40E_RXD_QW1_STATUS_MASK) - >> I40E_RXD_QW1_STATUS_SHIFT; - error = (qword & I40E_RXD_QW1_ERROR_MASK) - >> I40E_RXD_QW1_ERROR_SHIFT; - plen = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK) - >> I40E_RXD_QW1_LENGTH_PBUF_SHIFT; - hlen = (qword & I40E_RXD_QW1_LENGTH_HBUF_MASK) - >> I40E_RXD_QW1_LENGTH_HBUF_SHIFT; - ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) + u32 status, error; + u16 hlen, plen, vtag; + u64 qword; + u8 ptype; + bool eop; + + ri->iri_qidx = 0; + cur = &rxr->rx_base[ri->iri_cidx]; + qword = le64toh(cur->wb.qword1.status_error_len); + status = (qword & I40E_RXD_QW1_STATUS_MASK) + >> I40E_RXD_QW1_STATUS_SHIFT; + error = (qword & I40E_RXD_QW1_ERROR_MASK) + >> I40E_RXD_QW1_ERROR_SHIFT; + plen = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK) + >> I40E_RXD_QW1_LENGTH_PBUF_SHIFT; + hlen = (qword & I40E_RXD_QW1_LENGTH_HBUF_MASK) + >> I40E_RXD_QW1_LENGTH_HBUF_SHIFT; + ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >> 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; - - 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); - else - vtag = 0; - - /* - ** Make sure bad packets are discarded, - ** note that only EOP descriptor has valid - ** error results. - */ - if (eop && (error & (1 << I40E_RX_DESC_ERROR_RXE_SHIFT))) { - rxr->discarded++; - ixl_rx_discard(rxr, i); - goto next_desc; - } + /* we should never be called without a valid descriptor */ + MPASS((status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT)) != 0); - /* Prefetch the next buffer */ - if (!eop) { - nextp = i + 1; - if (nextp == que->num_desc) - nextp = 0; - nbuf = &rxr->buffers[nextp]; - prefetch(nbuf); - } + ri->iri_len = plen; + rxr->rx_bytes += plen; - /* - ** 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; + cur->wb.qword1.status_error_len = 0; + 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); + else + vtag = 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; - } - } - - /* 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); + ** Make sure bad packets are discarded, + ** note that only EOP descriptor has valid + ** error results. + */ + if (eop && (error & (1 << I40E_RX_DESC_ERROR_RXE_SHIFT))) { + rxr->discarded++; + return (EBADMSG); } -#endif - IXL_RX_UNLOCK(rxr); - return (FALSE); + /* Prefetch the next buffer */ + if (!eop) { + ri->iri_next_offset = 1; + } else { + 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); + + if (vtag) { + ri->iri_vtag = vtag; + ri->iri_flags |= M_VLANTAG; + } + ri->iri_next_offset = 0; + } + return (0); } @@ -1755,7 +652,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; @@ -1764,7 +661,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; } @@ -1773,19 +670,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 @@ -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; @@ -386,6 +387,7 @@ 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; @@ -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