161ae650dSJack F Vogel /****************************************************************************** 261ae650dSJack F Vogel 3f4cc2d17SEric Joyner Copyright (c) 2013-2018, Intel Corporation 461ae650dSJack F Vogel All rights reserved. 561ae650dSJack F Vogel 661ae650dSJack F Vogel Redistribution and use in source and binary forms, with or without 761ae650dSJack F Vogel modification, are permitted provided that the following conditions are met: 861ae650dSJack F Vogel 961ae650dSJack F Vogel 1. Redistributions of source code must retain the above copyright notice, 1061ae650dSJack F Vogel this list of conditions and the following disclaimer. 1161ae650dSJack F Vogel 1261ae650dSJack F Vogel 2. Redistributions in binary form must reproduce the above copyright 1361ae650dSJack F Vogel notice, this list of conditions and the following disclaimer in the 1461ae650dSJack F Vogel documentation and/or other materials provided with the distribution. 1561ae650dSJack F Vogel 1661ae650dSJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its 1761ae650dSJack F Vogel contributors may be used to endorse or promote products derived from 1861ae650dSJack F Vogel this software without specific prior written permission. 1961ae650dSJack F Vogel 2061ae650dSJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2161ae650dSJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2261ae650dSJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2361ae650dSJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2461ae650dSJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2561ae650dSJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2661ae650dSJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2761ae650dSJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2861ae650dSJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2961ae650dSJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3061ae650dSJack F Vogel POSSIBILITY OF SUCH DAMAGE. 3161ae650dSJack F Vogel 3261ae650dSJack F Vogel ******************************************************************************/ 3361ae650dSJack F Vogel /*$FreeBSD$*/ 3461ae650dSJack F Vogel 3561ae650dSJack F Vogel #include "ixl.h" 3661ae650dSJack F Vogel #include "ixl_pf.h" 3761ae650dSJack F Vogel 38cb6b8299SEric Joyner #ifdef IXL_IW 39cb6b8299SEric Joyner #include "ixl_iw.h" 40cb6b8299SEric Joyner #include "ixl_iw_int.h" 41cb6b8299SEric Joyner #endif 42cb6b8299SEric Joyner 434294f337SSean Bruno #ifdef PCI_IOV 444294f337SSean Bruno #include "ixl_pf_iov.h" 45dcd7b3b2SJack F Vogel #endif 46dcd7b3b2SJack F Vogel 4761ae650dSJack F Vogel /********************************************************************* 4861ae650dSJack F Vogel * Driver version 4961ae650dSJack F Vogel *********************************************************************/ 50f4cc2d17SEric Joyner #define IXL_DRIVER_VERSION_MAJOR 2 512984a8ddSEric Joyner #define IXL_DRIVER_VERSION_MINOR 3 521d02c6b1SKrzysztof Galazka #define IXL_DRIVER_VERSION_BUILD 3 53ceebc2f3SEric Joyner 541031d839SEric Joyner #define IXL_DRIVER_VERSION_STRING \ 551031d839SEric Joyner __XSTRING(IXL_DRIVER_VERSION_MAJOR) "." \ 561031d839SEric Joyner __XSTRING(IXL_DRIVER_VERSION_MINOR) "." \ 57f4cc2d17SEric Joyner __XSTRING(IXL_DRIVER_VERSION_BUILD) "-k" 5861ae650dSJack F Vogel 5961ae650dSJack F Vogel /********************************************************************* 6061ae650dSJack F Vogel * PCI Device ID Table 6161ae650dSJack F Vogel * 6261ae650dSJack F Vogel * Used by probe to select devices to load on 6361ae650dSJack F Vogel * 641031d839SEric Joyner * ( Vendor ID, Device ID, Branding String ) 6561ae650dSJack F Vogel *********************************************************************/ 6661ae650dSJack F Vogel 671031d839SEric Joyner static pci_vendor_info_t ixl_vendor_info_array[] = 6861ae650dSJack F Vogel { 691031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710, "Intel(R) Ethernet Controller X710 for 10GbE SFP+"), 701031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B, "Intel(R) Ethernet Controller XL710 for 40GbE backplane"), 711031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C, "Intel(R) Ethernet Controller X710 for 10GbE backplane"), 721031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A, "Intel(R) Ethernet Controller XL710 for 40GbE QSFP+"), 731031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B, "Intel(R) Ethernet Controller XL710 for 40GbE QSFP+"), 741031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_C, "Intel(R) Ethernet Controller X710 for 10GbE QSFP+"), 751031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T, "Intel(R) Ethernet Controller X710 for 10GBASE-T"), 761031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T4, "Intel(R) Ethernet Controller X710/X557-AT 10GBASE-T"), 771031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_X722, "Intel(R) Ethernet Connection X722 for 10GbE backplane"), 781031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_X722, "Intel(R) Ethernet Connection X722 for 10GbE QSFP+"), 791031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_X722, "Intel(R) Ethernet Connection X722 for 10GbE SFP+"), 801031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_1G_BASE_T_X722, "Intel(R) Ethernet Connection X722 for 1GbE"), 811031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T_X722, "Intel(R) Ethernet Connection X722 for 10GBASE-T"), 821031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_I_X722, "Intel(R) Ethernet Connection X722 for 10GbE SFP+"), 831031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_B, "Intel(R) Ethernet Controller XXV710 for 25GbE backplane"), 841031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_SFP28, "Intel(R) Ethernet Controller XXV710 for 25GbE SFP28"), 852984a8ddSEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T_BC, "Intel(R) Ethernet Controller X710 for 10GBASE-T"), 862984a8ddSEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_SFP, "Intel(R) Ethernet Controller X710 for 10GbE SFP+"), 872984a8ddSEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_B, "Intel(R) Ethernet Controller X710 for 10GbE backplane"), 882984a8ddSEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_5G_BASE_T_BC, "Intel(R) Ethernet Controller V710 for 5GBASE-T"), 89b7b40e4aSKrzysztof Galazka PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_1G_BASE_T_BC, "Intel(R) Ethernet Controller I710 for 1GBASE-T"), 9061ae650dSJack F Vogel /* required last entry */ 911031d839SEric Joyner PVID_END 9261ae650dSJack F Vogel }; 9361ae650dSJack F Vogel 9461ae650dSJack F Vogel /********************************************************************* 9561ae650dSJack F Vogel * Function prototypes 9661ae650dSJack F Vogel *********************************************************************/ 971031d839SEric Joyner /*** IFLIB interface ***/ 981031d839SEric Joyner static void *ixl_register(device_t dev); 991031d839SEric Joyner static int ixl_if_attach_pre(if_ctx_t ctx); 1001031d839SEric Joyner static int ixl_if_attach_post(if_ctx_t ctx); 1011031d839SEric Joyner static int ixl_if_detach(if_ctx_t ctx); 1021031d839SEric Joyner static int ixl_if_shutdown(if_ctx_t ctx); 1031031d839SEric Joyner static int ixl_if_suspend(if_ctx_t ctx); 1041031d839SEric Joyner static int ixl_if_resume(if_ctx_t ctx); 1051031d839SEric Joyner static int ixl_if_msix_intr_assign(if_ctx_t ctx, int msix); 1061031d839SEric Joyner static void ixl_if_enable_intr(if_ctx_t ctx); 1071031d839SEric Joyner static void ixl_if_disable_intr(if_ctx_t ctx); 1081031d839SEric Joyner static int ixl_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid); 1091031d839SEric Joyner static int ixl_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid); 1101031d839SEric Joyner static int ixl_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs, int ntxqsets); 1111031d839SEric Joyner static int ixl_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nqs, int nqsets); 1121031d839SEric Joyner static void ixl_if_queues_free(if_ctx_t ctx); 1131031d839SEric Joyner static void ixl_if_update_admin_status(if_ctx_t ctx); 1141031d839SEric Joyner static void ixl_if_multi_set(if_ctx_t ctx); 1151031d839SEric Joyner static int ixl_if_mtu_set(if_ctx_t ctx, uint32_t mtu); 1161031d839SEric Joyner static void ixl_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr); 1171031d839SEric Joyner static int ixl_if_media_change(if_ctx_t ctx); 1181031d839SEric Joyner static int ixl_if_promisc_set(if_ctx_t ctx, int flags); 1191031d839SEric Joyner static void ixl_if_timer(if_ctx_t ctx, uint16_t qid); 1201031d839SEric Joyner static void ixl_if_vlan_register(if_ctx_t ctx, u16 vtag); 1211031d839SEric Joyner static void ixl_if_vlan_unregister(if_ctx_t ctx, u16 vtag); 1221031d839SEric Joyner static uint64_t ixl_if_get_counter(if_ctx_t ctx, ift_counter cnt); 1231031d839SEric Joyner static int ixl_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req); 1241031d839SEric Joyner static int ixl_if_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data); 125cf150917SEric Joyner static bool ixl_if_needs_restart(if_ctx_t ctx, enum iflib_restart_event event); 12677c1fcecSEric Joyner #ifdef PCI_IOV 12777c1fcecSEric Joyner static void ixl_if_vflr_handle(if_ctx_t ctx); 12877c1fcecSEric Joyner #endif 1296c426059SEric Joyner 1301031d839SEric Joyner /*** Other ***/ 1311031d839SEric Joyner static void ixl_save_pf_tunables(struct ixl_pf *); 1321031d839SEric Joyner static int ixl_allocate_pci_resources(struct ixl_pf *); 133b4a7ce06SEric Joyner static void ixl_setup_ssctx(struct ixl_pf *pf); 134b4a7ce06SEric Joyner static void ixl_admin_timer(void *arg); 13561ae650dSJack F Vogel 13661ae650dSJack F Vogel /********************************************************************* 13761ae650dSJack F Vogel * FreeBSD Device Interface Entry Points 13861ae650dSJack F Vogel *********************************************************************/ 13961ae650dSJack F Vogel 14061ae650dSJack F Vogel static device_method_t ixl_methods[] = { 14161ae650dSJack F Vogel /* Device interface */ 1421031d839SEric Joyner DEVMETHOD(device_register, ixl_register), 1431031d839SEric Joyner DEVMETHOD(device_probe, iflib_device_probe), 1441031d839SEric Joyner DEVMETHOD(device_attach, iflib_device_attach), 1451031d839SEric Joyner DEVMETHOD(device_detach, iflib_device_detach), 1461031d839SEric Joyner DEVMETHOD(device_shutdown, iflib_device_shutdown), 14756c2c47bSJack F Vogel #ifdef PCI_IOV 14877c1fcecSEric Joyner DEVMETHOD(pci_iov_init, iflib_device_iov_init), 14977c1fcecSEric Joyner DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit), 15077c1fcecSEric Joyner DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf), 15156c2c47bSJack F Vogel #endif 1521031d839SEric Joyner DEVMETHOD_END 15361ae650dSJack F Vogel }; 15461ae650dSJack F Vogel 15561ae650dSJack F Vogel static driver_t ixl_driver = { 15661ae650dSJack F Vogel "ixl", ixl_methods, sizeof(struct ixl_pf), 15761ae650dSJack F Vogel }; 15861ae650dSJack F Vogel 15983c0a9e8SJohn Baldwin DRIVER_MODULE(ixl, pci, ixl_driver, 0, 0); 1600dc34160SWarner Losh IFLIB_PNP_INFO(pci, ixl, ixl_vendor_info_array); 1611031d839SEric Joyner MODULE_VERSION(ixl, 3); 162cb6b8299SEric Joyner 16361ae650dSJack F Vogel MODULE_DEPEND(ixl, pci, 1, 1, 1); 16461ae650dSJack F Vogel MODULE_DEPEND(ixl, ether, 1, 1, 1); 1651031d839SEric Joyner MODULE_DEPEND(ixl, iflib, 1, 1, 1); 1661031d839SEric Joyner 1671031d839SEric Joyner static device_method_t ixl_if_methods[] = { 1681031d839SEric Joyner DEVMETHOD(ifdi_attach_pre, ixl_if_attach_pre), 1691031d839SEric Joyner DEVMETHOD(ifdi_attach_post, ixl_if_attach_post), 1701031d839SEric Joyner DEVMETHOD(ifdi_detach, ixl_if_detach), 1711031d839SEric Joyner DEVMETHOD(ifdi_shutdown, ixl_if_shutdown), 1721031d839SEric Joyner DEVMETHOD(ifdi_suspend, ixl_if_suspend), 1731031d839SEric Joyner DEVMETHOD(ifdi_resume, ixl_if_resume), 1741031d839SEric Joyner DEVMETHOD(ifdi_init, ixl_if_init), 1751031d839SEric Joyner DEVMETHOD(ifdi_stop, ixl_if_stop), 1761031d839SEric Joyner DEVMETHOD(ifdi_msix_intr_assign, ixl_if_msix_intr_assign), 1771031d839SEric Joyner DEVMETHOD(ifdi_intr_enable, ixl_if_enable_intr), 1781031d839SEric Joyner DEVMETHOD(ifdi_intr_disable, ixl_if_disable_intr), 1791031d839SEric Joyner DEVMETHOD(ifdi_rx_queue_intr_enable, ixl_if_rx_queue_intr_enable), 1801031d839SEric Joyner DEVMETHOD(ifdi_tx_queue_intr_enable, ixl_if_tx_queue_intr_enable), 1811031d839SEric Joyner DEVMETHOD(ifdi_tx_queues_alloc, ixl_if_tx_queues_alloc), 1821031d839SEric Joyner DEVMETHOD(ifdi_rx_queues_alloc, ixl_if_rx_queues_alloc), 1831031d839SEric Joyner DEVMETHOD(ifdi_queues_free, ixl_if_queues_free), 1841031d839SEric Joyner DEVMETHOD(ifdi_update_admin_status, ixl_if_update_admin_status), 1851031d839SEric Joyner DEVMETHOD(ifdi_multi_set, ixl_if_multi_set), 1861031d839SEric Joyner DEVMETHOD(ifdi_mtu_set, ixl_if_mtu_set), 1871031d839SEric Joyner DEVMETHOD(ifdi_media_status, ixl_if_media_status), 1881031d839SEric Joyner DEVMETHOD(ifdi_media_change, ixl_if_media_change), 1891031d839SEric Joyner DEVMETHOD(ifdi_promisc_set, ixl_if_promisc_set), 1901031d839SEric Joyner DEVMETHOD(ifdi_timer, ixl_if_timer), 1911031d839SEric Joyner DEVMETHOD(ifdi_vlan_register, ixl_if_vlan_register), 1921031d839SEric Joyner DEVMETHOD(ifdi_vlan_unregister, ixl_if_vlan_unregister), 1931031d839SEric Joyner DEVMETHOD(ifdi_get_counter, ixl_if_get_counter), 1941031d839SEric Joyner DEVMETHOD(ifdi_i2c_req, ixl_if_i2c_req), 1951031d839SEric Joyner DEVMETHOD(ifdi_priv_ioctl, ixl_if_priv_ioctl), 196cf150917SEric Joyner DEVMETHOD(ifdi_needs_restart, ixl_if_needs_restart), 19777c1fcecSEric Joyner #ifdef PCI_IOV 19877c1fcecSEric Joyner DEVMETHOD(ifdi_iov_init, ixl_if_iov_init), 19977c1fcecSEric Joyner DEVMETHOD(ifdi_iov_uninit, ixl_if_iov_uninit), 20077c1fcecSEric Joyner DEVMETHOD(ifdi_iov_vf_add, ixl_if_iov_vf_add), 20177c1fcecSEric Joyner DEVMETHOD(ifdi_vflr_handle, ixl_if_vflr_handle), 20277c1fcecSEric Joyner #endif 2031031d839SEric Joyner // ifdi_led_func 2041031d839SEric Joyner // ifdi_debug 2051031d839SEric Joyner DEVMETHOD_END 2061031d839SEric Joyner }; 2071031d839SEric Joyner 2081031d839SEric Joyner static driver_t ixl_if_driver = { 2091031d839SEric Joyner "ixl_if", ixl_if_methods, sizeof(struct ixl_pf) 2101031d839SEric Joyner }; 21131830672SJack F Vogel 21261ae650dSJack F Vogel /* 21361ae650dSJack F Vogel ** TUNEABLE PARAMETERS: 21461ae650dSJack F Vogel */ 21561ae650dSJack F Vogel 21620b91f0aSPawel Biernacki static SYSCTL_NODE(_hw, OID_AUTO, ixl, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 21777c1fcecSEric Joyner "ixl driver parameters"); 21861ae650dSJack F Vogel 219b4a7ce06SEric Joyner #ifdef IXL_DEBUG_FC 22061ae650dSJack F Vogel /* 221ceebc2f3SEric Joyner * Leave this on unless you need to send flow control 222ceebc2f3SEric Joyner * frames (or other control frames) from software 223ceebc2f3SEric Joyner */ 2244294f337SSean Bruno static int ixl_enable_tx_fc_filter = 1; 2254294f337SSean Bruno TUNABLE_INT("hw.ixl.enable_tx_fc_filter", 2264294f337SSean Bruno &ixl_enable_tx_fc_filter); 2274294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, enable_tx_fc_filter, CTLFLAG_RDTUN, 2284294f337SSean Bruno &ixl_enable_tx_fc_filter, 0, 2294294f337SSean Bruno "Filter out packets with Ethertype 0x8808 from being sent out by non-HW sources"); 230b4a7ce06SEric Joyner #endif 231b4a7ce06SEric Joyner 232b4a7ce06SEric Joyner #ifdef IXL_DEBUG 233b4a7ce06SEric Joyner static int ixl_debug_recovery_mode = 0; 234b4a7ce06SEric Joyner TUNABLE_INT("hw.ixl.debug_recovery_mode", 235b4a7ce06SEric Joyner &ixl_debug_recovery_mode); 236b4a7ce06SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, debug_recovery_mode, CTLFLAG_RDTUN, 237b4a7ce06SEric Joyner &ixl_debug_recovery_mode, 0, 238d7125850SGordon Bergling "Act like when FW entered recovery mode (for debugging)"); 239b4a7ce06SEric Joyner #endif 2404294f337SSean Bruno 2411031d839SEric Joyner static int ixl_i2c_access_method = 0; 2421031d839SEric Joyner TUNABLE_INT("hw.ixl.i2c_access_method", 2431031d839SEric Joyner &ixl_i2c_access_method); 2441031d839SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, i2c_access_method, CTLFLAG_RDTUN, 2451031d839SEric Joyner &ixl_i2c_access_method, 0, 2461031d839SEric Joyner IXL_SYSCTL_HELP_I2C_METHOD); 2471031d839SEric Joyner 24877c1fcecSEric Joyner static int ixl_enable_vf_loopback = 1; 24977c1fcecSEric Joyner TUNABLE_INT("hw.ixl.enable_vf_loopback", 25077c1fcecSEric Joyner &ixl_enable_vf_loopback); 25177c1fcecSEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, enable_vf_loopback, CTLFLAG_RDTUN, 25277c1fcecSEric Joyner &ixl_enable_vf_loopback, 0, 25377c1fcecSEric Joyner IXL_SYSCTL_HELP_VF_LOOPBACK); 25477c1fcecSEric Joyner 255ceebc2f3SEric Joyner /* 256ceebc2f3SEric Joyner * Different method for processing TX descriptor 257ceebc2f3SEric Joyner * completion. 258ceebc2f3SEric Joyner */ 259ceebc2f3SEric Joyner static int ixl_enable_head_writeback = 1; 260ceebc2f3SEric Joyner TUNABLE_INT("hw.ixl.enable_head_writeback", 261ceebc2f3SEric Joyner &ixl_enable_head_writeback); 262ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, enable_head_writeback, CTLFLAG_RDTUN, 263ceebc2f3SEric Joyner &ixl_enable_head_writeback, 0, 264ceebc2f3SEric Joyner "For detecting last completed TX descriptor by hardware, use value written by HW instead of checking descriptors"); 265ceebc2f3SEric Joyner 2664294f337SSean Bruno static int ixl_core_debug_mask = 0; 2674294f337SSean Bruno TUNABLE_INT("hw.ixl.core_debug_mask", 2684294f337SSean Bruno &ixl_core_debug_mask); 2694294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, core_debug_mask, CTLFLAG_RDTUN, 2704294f337SSean Bruno &ixl_core_debug_mask, 0, 2714294f337SSean Bruno "Display debug statements that are printed in non-shared code"); 2724294f337SSean Bruno 2734294f337SSean Bruno static int ixl_shared_debug_mask = 0; 2744294f337SSean Bruno TUNABLE_INT("hw.ixl.shared_debug_mask", 2754294f337SSean Bruno &ixl_shared_debug_mask); 2764294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, shared_debug_mask, CTLFLAG_RDTUN, 2774294f337SSean Bruno &ixl_shared_debug_mask, 0, 2784294f337SSean Bruno "Display debug statements that are printed in shared code"); 2794294f337SSean Bruno 2801031d839SEric Joyner #if 0 28161ae650dSJack F Vogel /* 28261ae650dSJack F Vogel ** Controls for Interrupt Throttling 28361ae650dSJack F Vogel ** - true/false for dynamic adjustment 28461ae650dSJack F Vogel ** - default values for static ITR 28561ae650dSJack F Vogel */ 2861031d839SEric Joyner static int ixl_dynamic_rx_itr = 0; 28761ae650dSJack F Vogel TUNABLE_INT("hw.ixl.dynamic_rx_itr", &ixl_dynamic_rx_itr); 28861ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_rx_itr, CTLFLAG_RDTUN, 28961ae650dSJack F Vogel &ixl_dynamic_rx_itr, 0, "Dynamic RX Interrupt Rate"); 29061ae650dSJack F Vogel 2911031d839SEric Joyner static int ixl_dynamic_tx_itr = 0; 29261ae650dSJack F Vogel TUNABLE_INT("hw.ixl.dynamic_tx_itr", &ixl_dynamic_tx_itr); 29361ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_tx_itr, CTLFLAG_RDTUN, 29461ae650dSJack F Vogel &ixl_dynamic_tx_itr, 0, "Dynamic TX Interrupt Rate"); 2951031d839SEric Joyner #endif 29661ae650dSJack F Vogel 2974294f337SSean Bruno static int ixl_rx_itr = IXL_ITR_8K; 29861ae650dSJack F Vogel TUNABLE_INT("hw.ixl.rx_itr", &ixl_rx_itr); 29961ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, rx_itr, CTLFLAG_RDTUN, 30061ae650dSJack F Vogel &ixl_rx_itr, 0, "RX Interrupt Rate"); 30161ae650dSJack F Vogel 3024294f337SSean Bruno static int ixl_tx_itr = IXL_ITR_4K; 30361ae650dSJack F Vogel TUNABLE_INT("hw.ixl.tx_itr", &ixl_tx_itr); 30461ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, tx_itr, CTLFLAG_RDTUN, 30561ae650dSJack F Vogel &ixl_tx_itr, 0, "TX Interrupt Rate"); 30661ae650dSJack F Vogel 30720a52706SKrzysztof Galazka static int ixl_flow_control = -1; 30820a52706SKrzysztof Galazka SYSCTL_INT(_hw_ixl, OID_AUTO, flow_control, CTLFLAG_RDTUN, 30920a52706SKrzysztof Galazka &ixl_flow_control, 0, "Initial Flow Control setting"); 31020a52706SKrzysztof Galazka 311cb6b8299SEric Joyner #ifdef IXL_IW 312cb6b8299SEric Joyner int ixl_enable_iwarp = 0; 313cb6b8299SEric Joyner TUNABLE_INT("hw.ixl.enable_iwarp", &ixl_enable_iwarp); 314ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, enable_iwarp, CTLFLAG_RDTUN, 315ceebc2f3SEric Joyner &ixl_enable_iwarp, 0, "iWARP enabled"); 316ceebc2f3SEric Joyner 317ceebc2f3SEric Joyner int ixl_limit_iwarp_msix = IXL_IW_MAX_MSIX; 318ceebc2f3SEric Joyner TUNABLE_INT("hw.ixl.limit_iwarp_msix", &ixl_limit_iwarp_msix); 319ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, limit_iwarp_msix, CTLFLAG_RDTUN, 320b97de13aSMarius Strobl &ixl_limit_iwarp_msix, 0, "Limit MSI-X vectors assigned to iWARP"); 321cb6b8299SEric Joyner #endif 322cb6b8299SEric Joyner 3231031d839SEric Joyner extern struct if_txrx ixl_txrx_hwb; 3241031d839SEric Joyner extern struct if_txrx ixl_txrx_dwb; 325e5100ee2SJack F Vogel 3261031d839SEric Joyner static struct if_shared_ctx ixl_sctx_init = { 3271031d839SEric Joyner .isc_magic = IFLIB_MAGIC, 3281031d839SEric Joyner .isc_q_align = PAGE_SIZE, 3297f87c040SMarius Strobl .isc_tx_maxsize = IXL_TSO_SIZE + sizeof(struct ether_vlan_header), 3301031d839SEric Joyner .isc_tx_maxsegsize = IXL_MAX_DMA_SEG_SIZE, 3317f87c040SMarius Strobl .isc_tso_maxsize = IXL_TSO_SIZE + sizeof(struct ether_vlan_header), 3327f87c040SMarius Strobl .isc_tso_maxsegsize = IXL_MAX_DMA_SEG_SIZE, 3331031d839SEric Joyner .isc_rx_maxsize = 16384, 3341031d839SEric Joyner .isc_rx_nsegments = IXL_MAX_RX_SEGS, 3351031d839SEric Joyner .isc_rx_maxsegsize = IXL_MAX_DMA_SEG_SIZE, 3361031d839SEric Joyner .isc_nfl = 1, 3371031d839SEric Joyner .isc_ntxqs = 1, 3381031d839SEric Joyner .isc_nrxqs = 1, 3391031d839SEric Joyner 3401031d839SEric Joyner .isc_admin_intrcnt = 1, 3411031d839SEric Joyner .isc_vendor_info = ixl_vendor_info_array, 3421031d839SEric Joyner .isc_driver_version = IXL_DRIVER_VERSION_STRING, 3431031d839SEric Joyner .isc_driver = &ixl_if_driver, 34437761e2eSEric Joyner .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_NEED_ZERO_CSUM | IFLIB_TSO_INIT_IP | IFLIB_ADMIN_ALWAYS_RUN, 3451031d839SEric Joyner 3461031d839SEric Joyner .isc_nrxd_min = {IXL_MIN_RING}, 3471031d839SEric Joyner .isc_ntxd_min = {IXL_MIN_RING}, 3481031d839SEric Joyner .isc_nrxd_max = {IXL_MAX_RING}, 3491031d839SEric Joyner .isc_ntxd_max = {IXL_MAX_RING}, 3501031d839SEric Joyner .isc_nrxd_default = {IXL_DEFAULT_RING}, 3511031d839SEric Joyner .isc_ntxd_default = {IXL_DEFAULT_RING}, 3521031d839SEric Joyner }; 3531031d839SEric Joyner 3541031d839SEric Joyner /*** Functions ***/ 3551031d839SEric Joyner static void * 3561031d839SEric Joyner ixl_register(device_t dev) 3571031d839SEric Joyner { 358ffe3def9SMark Johnston return (&ixl_sctx_init); 3591031d839SEric Joyner } 36061ae650dSJack F Vogel 36161ae650dSJack F Vogel static int 3621031d839SEric Joyner ixl_allocate_pci_resources(struct ixl_pf *pf) 36361ae650dSJack F Vogel { 3641031d839SEric Joyner device_t dev = iflib_get_dev(pf->vsi.ctx); 36577c1fcecSEric Joyner struct i40e_hw *hw = &pf->hw; 36677c1fcecSEric Joyner int rid; 36761ae650dSJack F Vogel 3681031d839SEric Joyner /* Map BAR0 */ 3691031d839SEric Joyner rid = PCIR_BAR(0); 3701031d839SEric Joyner pf->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 3711031d839SEric Joyner &rid, RF_ACTIVE); 37261ae650dSJack F Vogel 3731031d839SEric Joyner if (!(pf->pci_mem)) { 3741031d839SEric Joyner device_printf(dev, "Unable to allocate bus resource: PCI memory\n"); 37561ae650dSJack F Vogel return (ENXIO); 37661ae650dSJack F Vogel } 37761ae650dSJack F Vogel 3781031d839SEric Joyner /* Save off the PCI information */ 3791031d839SEric Joyner hw->vendor_id = pci_get_vendor(dev); 3801031d839SEric Joyner hw->device_id = pci_get_device(dev); 3811031d839SEric Joyner hw->revision_id = pci_read_config(dev, PCIR_REVID, 1); 3821031d839SEric Joyner hw->subsystem_vendor_id = 3831031d839SEric Joyner pci_read_config(dev, PCIR_SUBVEND_0, 2); 3841031d839SEric Joyner hw->subsystem_device_id = 3851031d839SEric Joyner pci_read_config(dev, PCIR_SUBDEV_0, 2); 3864294f337SSean Bruno 3871031d839SEric Joyner hw->bus.device = pci_get_slot(dev); 3881031d839SEric Joyner hw->bus.func = pci_get_function(dev); 3894294f337SSean Bruno 3901031d839SEric Joyner /* Save off register access information */ 3911031d839SEric Joyner pf->osdep.mem_bus_space_tag = 3921031d839SEric Joyner rman_get_bustag(pf->pci_mem); 3931031d839SEric Joyner pf->osdep.mem_bus_space_handle = 3941031d839SEric Joyner rman_get_bushandle(pf->pci_mem); 3951031d839SEric Joyner pf->osdep.mem_bus_space_size = rman_get_size(pf->pci_mem); 3961031d839SEric Joyner pf->osdep.flush_reg = I40E_GLGEN_STAT; 3971031d839SEric Joyner pf->osdep.dev = dev; 398cb6b8299SEric Joyner 3991031d839SEric Joyner pf->hw.hw_addr = (u8 *) &pf->osdep.mem_bus_space_handle; 4001031d839SEric Joyner pf->hw.back = &pf->osdep; 4014294f337SSean Bruno 4024294f337SSean Bruno return (0); 4034294f337SSean Bruno } 4044294f337SSean Bruno 405b4a7ce06SEric Joyner static void 406b4a7ce06SEric Joyner ixl_setup_ssctx(struct ixl_pf *pf) 407b4a7ce06SEric Joyner { 408b4a7ce06SEric Joyner if_softc_ctx_t scctx = pf->vsi.shared; 409b4a7ce06SEric Joyner struct i40e_hw *hw = &pf->hw; 410b4a7ce06SEric Joyner 411b4a7ce06SEric Joyner if (IXL_PF_IN_RECOVERY_MODE(pf)) { 412b4a7ce06SEric Joyner scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 1; 413b4a7ce06SEric Joyner scctx->isc_ntxqsets = scctx->isc_nrxqsets = 1; 414b4a7ce06SEric Joyner } else if (hw->mac.type == I40E_MAC_X722) 415b4a7ce06SEric Joyner scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 128; 416b4a7ce06SEric Joyner else 417b4a7ce06SEric Joyner scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 64; 418b4a7ce06SEric Joyner 419b4a7ce06SEric Joyner if (pf->vsi.enable_head_writeback) { 420b4a7ce06SEric Joyner scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0] 421b4a7ce06SEric Joyner * sizeof(struct i40e_tx_desc) + sizeof(u32), DBA_ALIGN); 422b4a7ce06SEric Joyner scctx->isc_txrx = &ixl_txrx_hwb; 423b4a7ce06SEric Joyner } else { 424b4a7ce06SEric Joyner scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0] 425b4a7ce06SEric Joyner * sizeof(struct i40e_tx_desc), DBA_ALIGN); 426b4a7ce06SEric Joyner scctx->isc_txrx = &ixl_txrx_dwb; 427b4a7ce06SEric Joyner } 428b4a7ce06SEric Joyner 429b4a7ce06SEric Joyner scctx->isc_txrx->ift_legacy_intr = ixl_intr; 430b4a7ce06SEric Joyner scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0] 431b4a7ce06SEric Joyner * sizeof(union i40e_32byte_rx_desc), DBA_ALIGN); 432b4a7ce06SEric Joyner scctx->isc_msix_bar = PCIR_BAR(IXL_MSIX_BAR); 433b4a7ce06SEric Joyner scctx->isc_tx_nsegments = IXL_MAX_TX_SEGS; 434b4a7ce06SEric Joyner scctx->isc_tx_tso_segments_max = IXL_MAX_TSO_SEGS; 435b4a7ce06SEric Joyner scctx->isc_tx_tso_size_max = IXL_TSO_SIZE; 436b4a7ce06SEric Joyner scctx->isc_tx_tso_segsize_max = IXL_MAX_DMA_SEG_SIZE; 437b4a7ce06SEric Joyner scctx->isc_rss_table_size = pf->hw.func_caps.rss_table_size; 438b4a7ce06SEric Joyner scctx->isc_tx_csum_flags = CSUM_OFFLOAD; 439b4a7ce06SEric Joyner scctx->isc_capabilities = scctx->isc_capenable = IXL_CAPS; 440b4a7ce06SEric Joyner } 441b4a7ce06SEric Joyner 442b4a7ce06SEric Joyner static void 443b4a7ce06SEric Joyner ixl_admin_timer(void *arg) 444b4a7ce06SEric Joyner { 445b4a7ce06SEric Joyner struct ixl_pf *pf = (struct ixl_pf *)arg; 446b4a7ce06SEric Joyner 447*ba2f531fSKrzysztof Galazka if (ixl_test_state(&pf->state, IXL_STATE_LINK_POLLING)) { 448*ba2f531fSKrzysztof Galazka struct i40e_hw *hw = &pf->hw; 449*ba2f531fSKrzysztof Galazka sbintime_t stime; 450*ba2f531fSKrzysztof Galazka enum i40e_status_code status; 451*ba2f531fSKrzysztof Galazka 452*ba2f531fSKrzysztof Galazka hw->phy.get_link_info = TRUE; 453*ba2f531fSKrzysztof Galazka status = i40e_get_link_status(hw, &pf->link_up); 454*ba2f531fSKrzysztof Galazka if (status == I40E_SUCCESS) { 455*ba2f531fSKrzysztof Galazka ixl_clear_state(&pf->state, IXL_STATE_LINK_POLLING); 456*ba2f531fSKrzysztof Galazka /* OS link info is updated in the admin task */ 457*ba2f531fSKrzysztof Galazka } else { 458*ba2f531fSKrzysztof Galazka device_printf(pf->dev, 459*ba2f531fSKrzysztof Galazka "%s: i40e_get_link_status status %s, aq error %s\n", 460*ba2f531fSKrzysztof Galazka __func__, i40e_stat_str(hw, status), 461*ba2f531fSKrzysztof Galazka i40e_aq_str(hw, hw->aq.asq_last_status)); 462*ba2f531fSKrzysztof Galazka stime = getsbinuptime(); 463*ba2f531fSKrzysztof Galazka if (stime - pf->link_poll_start > IXL_PF_MAX_LINK_POLL) { 464*ba2f531fSKrzysztof Galazka device_printf(pf->dev, "Polling link status failed\n"); 465*ba2f531fSKrzysztof Galazka ixl_clear_state(&pf->state, IXL_STATE_LINK_POLLING); 466*ba2f531fSKrzysztof Galazka } 467*ba2f531fSKrzysztof Galazka } 468*ba2f531fSKrzysztof Galazka } 469*ba2f531fSKrzysztof Galazka 470b4a7ce06SEric Joyner /* Fire off the admin task */ 471b4a7ce06SEric Joyner iflib_admin_intr_deferred(pf->vsi.ctx); 472b4a7ce06SEric Joyner 473b4a7ce06SEric Joyner /* Reschedule the admin timer */ 474b4a7ce06SEric Joyner callout_schedule(&pf->admin_timer, hz/2); 475b4a7ce06SEric Joyner } 476b4a7ce06SEric Joyner 477b4a7ce06SEric Joyner static int 478b4a7ce06SEric Joyner ixl_attach_pre_recovery_mode(struct ixl_pf *pf) 479b4a7ce06SEric Joyner { 480b4a7ce06SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 481b4a7ce06SEric Joyner struct i40e_hw *hw = &pf->hw; 482b4a7ce06SEric Joyner device_t dev = pf->dev; 483b4a7ce06SEric Joyner 484b4a7ce06SEric Joyner device_printf(dev, "Firmware recovery mode detected. Limiting functionality. Refer to Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode.\n"); 485b4a7ce06SEric Joyner 486b4a7ce06SEric Joyner i40e_get_mac_addr(hw, hw->mac.addr); 487b4a7ce06SEric Joyner 488b4a7ce06SEric Joyner if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) { 489b4a7ce06SEric Joyner ixl_configure_intr0_msix(pf); 490b4a7ce06SEric Joyner ixl_enable_intr0(hw); 491b4a7ce06SEric Joyner } 492b4a7ce06SEric Joyner 493b4a7ce06SEric Joyner ixl_setup_ssctx(pf); 494b4a7ce06SEric Joyner 495b4a7ce06SEric Joyner return (0); 496b4a7ce06SEric Joyner } 497b4a7ce06SEric Joyner 49861ae650dSJack F Vogel static int 4991031d839SEric Joyner ixl_if_attach_pre(if_ctx_t ctx) 50061ae650dSJack F Vogel { 5011031d839SEric Joyner device_t dev; 50261ae650dSJack F Vogel struct ixl_pf *pf; 50361ae650dSJack F Vogel struct i40e_hw *hw; 50461ae650dSJack F Vogel struct ixl_vsi *vsi; 505b4a7ce06SEric Joyner enum i40e_get_fw_lldp_status_resp lldp_status; 5061031d839SEric Joyner struct i40e_filter_control_settings filter; 5074294f337SSean Bruno enum i40e_status_code status; 50861ae650dSJack F Vogel int error = 0; 50961ae650dSJack F Vogel 5101031d839SEric Joyner dev = iflib_get_dev(ctx); 5111031d839SEric Joyner pf = iflib_get_softc(ctx); 51277c1fcecSEric Joyner 513c65f571cSLeandro Lupori INIT_DBG_DEV(dev, "begin"); 514c65f571cSLeandro Lupori 5151031d839SEric Joyner vsi = &pf->vsi; 5161031d839SEric Joyner vsi->back = pf; 5171031d839SEric Joyner pf->dev = dev; 51861ae650dSJack F Vogel hw = &pf->hw; 51961ae650dSJack F Vogel 52077c1fcecSEric Joyner vsi->dev = dev; 5211031d839SEric Joyner vsi->hw = &pf->hw; 5221031d839SEric Joyner vsi->id = 0; 5231031d839SEric Joyner vsi->num_vlans = 0; 5241031d839SEric Joyner vsi->ctx = ctx; 5251031d839SEric Joyner vsi->media = iflib_get_media(ctx); 526b4a7ce06SEric Joyner vsi->shared = iflib_get_softc_ctx(ctx); 527b4a7ce06SEric Joyner 528b4a7ce06SEric Joyner snprintf(pf->admin_mtx_name, sizeof(pf->admin_mtx_name), 529b4a7ce06SEric Joyner "%s:admin", device_get_nameunit(dev)); 530b4a7ce06SEric Joyner mtx_init(&pf->admin_mtx, pf->admin_mtx_name, NULL, MTX_DEF); 531b4a7ce06SEric Joyner callout_init_mtx(&pf->admin_timer, &pf->admin_mtx, 0); 53261ae650dSJack F Vogel 5334294f337SSean Bruno /* Save tunable values */ 5341031d839SEric Joyner ixl_save_pf_tunables(pf); 53561ae650dSJack F Vogel 53661ae650dSJack F Vogel /* Do PCI setup - map BAR0, etc */ 53761ae650dSJack F Vogel if (ixl_allocate_pci_resources(pf)) { 53861ae650dSJack F Vogel device_printf(dev, "Allocation of PCI resources failed\n"); 53961ae650dSJack F Vogel error = ENXIO; 5401031d839SEric Joyner goto err_pci_res; 54161ae650dSJack F Vogel } 54261ae650dSJack F Vogel 54361ae650dSJack F Vogel /* Establish a clean starting point */ 54461ae650dSJack F Vogel i40e_clear_hw(hw); 545b4a7ce06SEric Joyner i40e_set_mac_type(hw); 546b4a7ce06SEric Joyner 547b4a7ce06SEric Joyner error = ixl_pf_reset(pf); 548b4a7ce06SEric Joyner if (error) 54961ae650dSJack F Vogel goto err_out; 55061ae650dSJack F Vogel 55161ae650dSJack F Vogel /* Initialize the shared code */ 5524294f337SSean Bruno status = i40e_init_shared_code(hw); 5534294f337SSean Bruno if (status) { 5544294f337SSean Bruno device_printf(dev, "Unable to initialize shared code, error %s\n", 5554294f337SSean Bruno i40e_stat_str(hw, status)); 55661ae650dSJack F Vogel error = EIO; 55761ae650dSJack F Vogel goto err_out; 55861ae650dSJack F Vogel } 55961ae650dSJack F Vogel 56061ae650dSJack F Vogel /* Set up the admin queue */ 5614294f337SSean Bruno hw->aq.num_arq_entries = IXL_AQ_LEN; 5624294f337SSean Bruno hw->aq.num_asq_entries = IXL_AQ_LEN; 5634294f337SSean Bruno hw->aq.arq_buf_size = IXL_AQ_BUF_SZ; 5644294f337SSean Bruno hw->aq.asq_buf_size = IXL_AQ_BUF_SZ; 5654294f337SSean Bruno 5664294f337SSean Bruno status = i40e_init_adminq(hw); 5674294f337SSean Bruno if (status != 0 && status != I40E_ERR_FIRMWARE_API_VERSION) { 5684294f337SSean Bruno device_printf(dev, "Unable to initialize Admin Queue, error %s\n", 5694294f337SSean Bruno i40e_stat_str(hw, status)); 570fdb6f38aSEric Joyner error = EIO; 571fdb6f38aSEric Joyner goto err_out; 572fdb6f38aSEric Joyner } 5731d767a8eSEric Joyner ixl_print_nvm_version(pf); 5741d767a8eSEric Joyner 5754294f337SSean Bruno if (status == I40E_ERR_FIRMWARE_API_VERSION) { 57661ae650dSJack F Vogel device_printf(dev, "The driver for the device stopped " 577ceebc2f3SEric Joyner "because the NVM image is newer than expected.\n"); 578ceebc2f3SEric Joyner device_printf(dev, "You must install the most recent version of " 57961ae650dSJack F Vogel "the network driver.\n"); 580fdb6f38aSEric Joyner error = EIO; 58161ae650dSJack F Vogel goto err_out; 58261ae650dSJack F Vogel } 58361ae650dSJack F Vogel 58461ae650dSJack F Vogel if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR && 585ceebc2f3SEric Joyner hw->aq.api_min_ver > I40E_FW_MINOR_VERSION(hw)) { 58661ae650dSJack F Vogel device_printf(dev, "The driver for the device detected " 587ceebc2f3SEric Joyner "a newer version of the NVM image than expected.\n"); 588ceebc2f3SEric Joyner device_printf(dev, "Please install the most recent version " 589ceebc2f3SEric Joyner "of the network driver.\n"); 590ceebc2f3SEric Joyner } else if (hw->aq.api_maj_ver == 1 && hw->aq.api_min_ver < 4) { 59161ae650dSJack F Vogel device_printf(dev, "The driver for the device detected " 592ceebc2f3SEric Joyner "an older version of the NVM image than expected.\n"); 593ceebc2f3SEric Joyner device_printf(dev, "Please update the NVM image.\n"); 594ceebc2f3SEric Joyner } 59561ae650dSJack F Vogel 596b4a7ce06SEric Joyner if (IXL_PF_IN_RECOVERY_MODE(pf)) { 597b4a7ce06SEric Joyner error = ixl_attach_pre_recovery_mode(pf); 598b4a7ce06SEric Joyner if (error) 599b4a7ce06SEric Joyner goto err_out; 600b4a7ce06SEric Joyner return (error); 601b4a7ce06SEric Joyner } 602b4a7ce06SEric Joyner 60361ae650dSJack F Vogel /* Clear PXE mode */ 60461ae650dSJack F Vogel i40e_clear_pxe_mode(hw); 60561ae650dSJack F Vogel 60661ae650dSJack F Vogel /* Get capabilities from the device */ 60761ae650dSJack F Vogel error = ixl_get_hw_capabilities(pf); 60861ae650dSJack F Vogel if (error) { 6091031d839SEric Joyner device_printf(dev, "get_hw_capabilities failed: %d\n", 6101031d839SEric Joyner error); 61161ae650dSJack F Vogel goto err_get_cap; 61261ae650dSJack F Vogel } 61361ae650dSJack F Vogel 61461ae650dSJack F Vogel /* Set up host memory cache */ 615b4a7ce06SEric Joyner error = ixl_setup_hmc(pf); 616b4a7ce06SEric Joyner if (error) 61761ae650dSJack F Vogel goto err_mac_hmc; 61861ae650dSJack F Vogel 619d4683565SEric Joyner /* Disable LLDP from the firmware for certain NVM versions */ 620d4683565SEric Joyner if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 3)) || 621ceebc2f3SEric Joyner (pf->hw.aq.fw_maj_ver < 4)) { 622b4a7ce06SEric Joyner i40e_aq_stop_lldp(hw, true, false, NULL); 623b8f51b8cSPiotr Kubaj ixl_set_state(&pf->state, IXL_STATE_FW_LLDP_DISABLED); 624ceebc2f3SEric Joyner } 62561ae650dSJack F Vogel 6262984a8ddSEric Joyner /* Try enabling Energy Efficient Ethernet (EEE) mode */ 6272984a8ddSEric Joyner if (i40e_enable_eee(hw, true) == I40E_SUCCESS) 628b8f51b8cSPiotr Kubaj ixl_set_state(&pf->state, IXL_STATE_EEE_ENABLED); 6292984a8ddSEric Joyner else 630b8f51b8cSPiotr Kubaj ixl_clear_state(&pf->state, IXL_STATE_EEE_ENABLED); 6312984a8ddSEric Joyner 6324294f337SSean Bruno /* Get MAC addresses from hardware */ 63361ae650dSJack F Vogel i40e_get_mac_addr(hw, hw->mac.addr); 63461ae650dSJack F Vogel error = i40e_validate_mac_addr(hw->mac.addr); 63561ae650dSJack F Vogel if (error) { 63661ae650dSJack F Vogel device_printf(dev, "validate_mac_addr failed: %d\n", error); 63761ae650dSJack F Vogel goto err_mac_hmc; 63861ae650dSJack F Vogel } 63961ae650dSJack F Vogel bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN); 6401031d839SEric Joyner iflib_set_mac(ctx, hw->mac.addr); 64161ae650dSJack F Vogel i40e_get_port_mac_addr(hw, hw->mac.port_addr); 64261ae650dSJack F Vogel 6431031d839SEric Joyner /* Set up the device filtering */ 6441031d839SEric Joyner bzero(&filter, sizeof(filter)); 6451031d839SEric Joyner filter.enable_ethtype = TRUE; 6461031d839SEric Joyner filter.enable_macvlan = TRUE; 6471031d839SEric Joyner filter.enable_fdir = FALSE; 6481031d839SEric Joyner filter.hash_lut_size = I40E_HASH_LUT_SIZE_512; 6491031d839SEric Joyner if (i40e_set_filter_control(hw, &filter)) 6501031d839SEric Joyner device_printf(dev, "i40e_set_filter_control() failed\n"); 6511031d839SEric Joyner 652ceebc2f3SEric Joyner /* Query device FW LLDP status */ 653b4a7ce06SEric Joyner if (i40e_get_fw_lldp_status(hw, &lldp_status) == I40E_SUCCESS) { 654b4a7ce06SEric Joyner if (lldp_status == I40E_GET_FW_LLDP_STATUS_DISABLED) { 655b8f51b8cSPiotr Kubaj ixl_set_state(&pf->state, 656b8f51b8cSPiotr Kubaj IXL_STATE_FW_LLDP_DISABLED); 657b4a7ce06SEric Joyner } else { 658b8f51b8cSPiotr Kubaj ixl_clear_state(&pf->state, 659b8f51b8cSPiotr Kubaj IXL_STATE_FW_LLDP_DISABLED); 660b4a7ce06SEric Joyner } 661b4a7ce06SEric Joyner } 662b4a7ce06SEric Joyner 663ceebc2f3SEric Joyner /* Tell FW to apply DCB config on link up */ 664ceebc2f3SEric Joyner i40e_aq_set_dcb_parameters(hw, true, NULL); 665ceebc2f3SEric Joyner 6661031d839SEric Joyner /* Fill out iflib parameters */ 667b4a7ce06SEric Joyner ixl_setup_ssctx(pf); 6684294f337SSean Bruno 66977c1fcecSEric Joyner INIT_DBG_DEV(dev, "end"); 6701031d839SEric Joyner return (0); 6711031d839SEric Joyner 6721031d839SEric Joyner err_mac_hmc: 673b4a7ce06SEric Joyner ixl_shutdown_hmc(pf); 6741031d839SEric Joyner err_get_cap: 6751031d839SEric Joyner i40e_shutdown_adminq(hw); 6761031d839SEric Joyner err_out: 6771031d839SEric Joyner ixl_free_pci_resources(pf); 6781031d839SEric Joyner err_pci_res: 679b4a7ce06SEric Joyner mtx_lock(&pf->admin_mtx); 680b4a7ce06SEric Joyner callout_stop(&pf->admin_timer); 681b4a7ce06SEric Joyner mtx_unlock(&pf->admin_mtx); 682b4a7ce06SEric Joyner mtx_destroy(&pf->admin_mtx); 6831031d839SEric Joyner return (error); 68461ae650dSJack F Vogel } 68561ae650dSJack F Vogel 6861031d839SEric Joyner static int 6871031d839SEric Joyner ixl_if_attach_post(if_ctx_t ctx) 6881031d839SEric Joyner { 6891031d839SEric Joyner device_t dev; 6901031d839SEric Joyner struct ixl_pf *pf; 6911031d839SEric Joyner struct i40e_hw *hw; 6921031d839SEric Joyner struct ixl_vsi *vsi; 6931031d839SEric Joyner int error = 0; 6941031d839SEric Joyner enum i40e_status_code status; 6951031d839SEric Joyner 6961031d839SEric Joyner dev = iflib_get_dev(ctx); 6971031d839SEric Joyner pf = iflib_get_softc(ctx); 698c65f571cSLeandro Lupori 699c65f571cSLeandro Lupori INIT_DBG_DEV(dev, "begin"); 700c65f571cSLeandro Lupori 7011031d839SEric Joyner vsi = &pf->vsi; 7021031d839SEric Joyner vsi->ifp = iflib_get_ifp(ctx); 7031031d839SEric Joyner hw = &pf->hw; 7041031d839SEric Joyner 70577c1fcecSEric Joyner /* Save off determined number of queues for interface */ 70677c1fcecSEric Joyner vsi->num_rx_queues = vsi->shared->isc_nrxqsets; 70777c1fcecSEric Joyner vsi->num_tx_queues = vsi->shared->isc_ntxqsets; 70877c1fcecSEric Joyner 7094294f337SSean Bruno /* Setup OS network interface / ifnet */ 7101031d839SEric Joyner if (ixl_setup_interface(dev, pf)) { 7114294f337SSean Bruno device_printf(dev, "interface setup failed!\n"); 7124294f337SSean Bruno error = EIO; 7131031d839SEric Joyner goto err; 714223d846dSEric Joyner } 71561ae650dSJack F Vogel 716b4a7ce06SEric Joyner if (IXL_PF_IN_RECOVERY_MODE(pf)) { 717b4a7ce06SEric Joyner /* Keep admin queue interrupts active while driver is loaded */ 718b4a7ce06SEric Joyner if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) { 719b4a7ce06SEric Joyner ixl_configure_intr0_msix(pf); 720b4a7ce06SEric Joyner ixl_enable_intr0(hw); 721b4a7ce06SEric Joyner } 722b4a7ce06SEric Joyner 723b4a7ce06SEric Joyner ixl_add_sysctls_recovery_mode(pf); 724b4a7ce06SEric Joyner 725b4a7ce06SEric Joyner /* Start the admin timer */ 726b4a7ce06SEric Joyner mtx_lock(&pf->admin_mtx); 727b4a7ce06SEric Joyner callout_reset(&pf->admin_timer, hz/2, ixl_admin_timer, pf); 728b4a7ce06SEric Joyner mtx_unlock(&pf->admin_mtx); 729b4a7ce06SEric Joyner return (0); 730b4a7ce06SEric Joyner } 731b4a7ce06SEric Joyner 732b6c8f260SJack F Vogel error = ixl_switch_config(pf); 733b6c8f260SJack F Vogel if (error) { 7346c426059SEric Joyner device_printf(dev, "Initial ixl_switch_config() failed: %d\n", 7356c426059SEric Joyner error); 7361031d839SEric Joyner goto err; 737b6c8f260SJack F Vogel } 738b6c8f260SJack F Vogel 7391031d839SEric Joyner /* Add protocol filters to list */ 7401031d839SEric Joyner ixl_init_filters(vsi); 7411031d839SEric Joyner 7421031d839SEric Joyner /* Init queue allocation manager */ 7431031d839SEric Joyner error = ixl_pf_qmgr_init(&pf->qmgr, hw->func_caps.num_tx_qp); 7441031d839SEric Joyner if (error) { 7451031d839SEric Joyner device_printf(dev, "Failed to init queue manager for PF queues, error %d\n", 7461031d839SEric Joyner error); 7471031d839SEric Joyner goto err; 7481031d839SEric Joyner } 7491031d839SEric Joyner /* reserve a contiguous allocation for the PF's VSI */ 7501031d839SEric Joyner error = ixl_pf_qmgr_alloc_contiguous(&pf->qmgr, 7511031d839SEric Joyner max(vsi->num_rx_queues, vsi->num_tx_queues), &pf->qtag); 7521031d839SEric Joyner if (error) { 7531031d839SEric Joyner device_printf(dev, "Failed to reserve queues for PF LAN VSI, error %d\n", 7541031d839SEric Joyner error); 7551031d839SEric Joyner goto err; 7561031d839SEric Joyner } 7571031d839SEric Joyner device_printf(dev, "Allocating %d queues for PF LAN VSI; %d queues active\n", 7581031d839SEric Joyner pf->qtag.num_allocated, pf->qtag.num_active); 7591031d839SEric Joyner 760*ba2f531fSKrzysztof Galazka /* Determine link state */ 761*ba2f531fSKrzysztof Galazka error = ixl_attach_get_link_status(pf); 762*ba2f531fSKrzysztof Galazka if (error == EINVAL) 763*ba2f531fSKrzysztof Galazka goto err; 764*ba2f531fSKrzysztof Galazka 765223d846dSEric Joyner /* Limit PHY interrupts to link, autoneg, and modules failure */ 7664294f337SSean Bruno status = i40e_aq_set_phy_int_mask(hw, IXL_DEFAULT_PHY_INT_MASK, 767223d846dSEric Joyner NULL); 7684294f337SSean Bruno if (status) { 7694294f337SSean Bruno device_printf(dev, "i40e_aq_set_phy_mask() failed: err %s," 7704294f337SSean Bruno " aq_err %s\n", i40e_stat_str(hw, status), 7714294f337SSean Bruno i40e_aq_str(hw, hw->aq.asq_last_status)); 7721031d839SEric Joyner goto err; 773223d846dSEric Joyner } 774b6c8f260SJack F Vogel 7751031d839SEric Joyner /* Get the bus configuration and set the shared code */ 776cb6b8299SEric Joyner ixl_get_bus_info(pf); 77761ae650dSJack F Vogel 7781031d839SEric Joyner /* Keep admin queue interrupts active while driver is loaded */ 7791031d839SEric Joyner if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) { 7806c426059SEric Joyner ixl_configure_intr0_msix(pf); 781cb6b8299SEric Joyner ixl_enable_intr0(hw); 782cb6b8299SEric Joyner } 783cb6b8299SEric Joyner 784cb6b8299SEric Joyner /* Set initial advertised speed sysctl value */ 785ceebc2f3SEric Joyner ixl_set_initial_advertised_speeds(pf); 786cb6b8299SEric Joyner 787fdb6f38aSEric Joyner /* Initialize statistics & add sysctls */ 788fdb6f38aSEric Joyner ixl_add_device_sysctls(pf); 78961ae650dSJack F Vogel ixl_pf_reset_stats(pf); 79061ae650dSJack F Vogel ixl_update_stats_counters(pf); 79161ae650dSJack F Vogel ixl_add_hw_stats(pf); 79261ae650dSJack F Vogel 79321802a12SKrzysztof Galazka /* 79421802a12SKrzysztof Galazka * Driver may have been reloaded. Ensure that the link state 79521802a12SKrzysztof Galazka * is consistent with current settings. 79621802a12SKrzysztof Galazka */ 797b8f51b8cSPiotr Kubaj ixl_set_link(pf, ixl_test_state(&pf->state, IXL_STATE_LINK_ACTIVE_ON_DOWN)); 79821802a12SKrzysztof Galazka 7991031d839SEric Joyner hw->phy.get_link_info = true; 800*ba2f531fSKrzysztof Galazka status = i40e_get_link_status(hw, &pf->link_up); 801*ba2f531fSKrzysztof Galazka if (status != I40E_SUCCESS) { 802*ba2f531fSKrzysztof Galazka device_printf(dev, 803*ba2f531fSKrzysztof Galazka "%s get link status, status: %s aq_err=%s\n", 804*ba2f531fSKrzysztof Galazka __func__, i40e_stat_str(hw, status), 805*ba2f531fSKrzysztof Galazka i40e_aq_str(hw, hw->aq.asq_last_status)); 806*ba2f531fSKrzysztof Galazka /* 807*ba2f531fSKrzysztof Galazka * Most probably FW has not finished configuring PHY. 808*ba2f531fSKrzysztof Galazka * Retry periodically in a timer callback. 809*ba2f531fSKrzysztof Galazka */ 810*ba2f531fSKrzysztof Galazka ixl_set_state(&pf->state, IXL_STATE_LINK_POLLING); 811*ba2f531fSKrzysztof Galazka pf->link_poll_start = getsbinuptime(); 812*ba2f531fSKrzysztof Galazka } else 8131031d839SEric Joyner ixl_update_link_status(pf); 81461ae650dSJack F Vogel 81556c2c47bSJack F Vogel #ifdef PCI_IOV 8164294f337SSean Bruno ixl_initialize_sriov(pf); 81756c2c47bSJack F Vogel #endif 81856c2c47bSJack F Vogel 819cb6b8299SEric Joyner #ifdef IXL_IW 820cb6b8299SEric Joyner if (hw->func_caps.iwarp && ixl_enable_iwarp) { 821cb6b8299SEric Joyner pf->iw_enabled = (pf->iw_msix > 0) ? true : false; 822cb6b8299SEric Joyner if (pf->iw_enabled) { 823cb6b8299SEric Joyner error = ixl_iw_pf_attach(pf); 824cb6b8299SEric Joyner if (error) { 825cb6b8299SEric Joyner device_printf(dev, 826b97de13aSMarius Strobl "interfacing to iWARP driver failed: %d\n", 827cb6b8299SEric Joyner error); 8281031d839SEric Joyner goto err; 829ceebc2f3SEric Joyner } else 830ceebc2f3SEric Joyner device_printf(dev, "iWARP ready\n"); 831cb6b8299SEric Joyner } else 832b97de13aSMarius Strobl device_printf(dev, "iWARP disabled on this device " 833b97de13aSMarius Strobl "(no MSI-X vectors)\n"); 834cb6b8299SEric Joyner } else { 835cb6b8299SEric Joyner pf->iw_enabled = false; 836cb6b8299SEric Joyner device_printf(dev, "The device is not iWARP enabled\n"); 837cb6b8299SEric Joyner } 838cb6b8299SEric Joyner #endif 839b4a7ce06SEric Joyner /* Start the admin timer */ 840b4a7ce06SEric Joyner mtx_lock(&pf->admin_mtx); 841b4a7ce06SEric Joyner callout_reset(&pf->admin_timer, hz/2, ixl_admin_timer, pf); 842b4a7ce06SEric Joyner mtx_unlock(&pf->admin_mtx); 843cb6b8299SEric Joyner 8441031d839SEric Joyner INIT_DBG_DEV(dev, "end"); 84561ae650dSJack F Vogel return (0); 84661ae650dSJack F Vogel 8471031d839SEric Joyner err: 8481031d839SEric Joyner INIT_DEBUGOUT("end: error %d", error); 8491031d839SEric Joyner /* ixl_if_detach() is called on error from this */ 85061ae650dSJack F Vogel return (error); 85161ae650dSJack F Vogel } 85261ae650dSJack F Vogel 85377c1fcecSEric Joyner /** 85477c1fcecSEric Joyner * XXX: iflib always ignores the return value of detach() 85577c1fcecSEric Joyner * -> This means that this isn't allowed to fail 85677c1fcecSEric Joyner */ 85761ae650dSJack F Vogel static int 8581031d839SEric Joyner ixl_if_detach(if_ctx_t ctx) 85961ae650dSJack F Vogel { 8601031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 86161ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 8621031d839SEric Joyner struct i40e_hw *hw = &pf->hw; 8631031d839SEric Joyner device_t dev = pf->dev; 8646c426059SEric Joyner enum i40e_status_code status; 86577c1fcecSEric Joyner #ifdef IXL_IW 86656c2c47bSJack F Vogel int error; 86756c2c47bSJack F Vogel #endif 86861ae650dSJack F Vogel 8691031d839SEric Joyner INIT_DBG_DEV(dev, "begin"); 870cb6b8299SEric Joyner 871b4a7ce06SEric Joyner /* Stop the admin timer */ 872b4a7ce06SEric Joyner mtx_lock(&pf->admin_mtx); 873b4a7ce06SEric Joyner callout_stop(&pf->admin_timer); 874b4a7ce06SEric Joyner mtx_unlock(&pf->admin_mtx); 875b4a7ce06SEric Joyner mtx_destroy(&pf->admin_mtx); 876b4a7ce06SEric Joyner 877cb6b8299SEric Joyner #ifdef IXL_IW 878cb6b8299SEric Joyner if (ixl_enable_iwarp && pf->iw_enabled) { 879cb6b8299SEric Joyner error = ixl_iw_pf_detach(pf); 880cb6b8299SEric Joyner if (error == EBUSY) { 881cb6b8299SEric Joyner device_printf(dev, "iwarp in use; stop it first.\n"); 88277c1fcecSEric Joyner //return (error); 883cb6b8299SEric Joyner } 884cb6b8299SEric Joyner } 885cb6b8299SEric Joyner #endif 8861031d839SEric Joyner /* Remove all previously allocated media types */ 8871031d839SEric Joyner ifmedia_removeall(vsi->media); 888cb6b8299SEric Joyner 8891031d839SEric Joyner /* Shutdown LAN HMC */ 890b4a7ce06SEric Joyner ixl_shutdown_hmc(pf); 8911031d839SEric Joyner 8921031d839SEric Joyner /* Shutdown admin queue */ 8931031d839SEric Joyner ixl_disable_intr0(hw); 8941031d839SEric Joyner status = i40e_shutdown_adminq(hw); 8951031d839SEric Joyner if (status) 8961031d839SEric Joyner device_printf(dev, 8971031d839SEric Joyner "i40e_shutdown_adminq() failed with status %s\n", 8981031d839SEric Joyner i40e_stat_str(hw, status)); 8991031d839SEric Joyner 9004294f337SSean Bruno ixl_pf_qmgr_destroy(&pf->qmgr); 90161ae650dSJack F Vogel ixl_free_pci_resources(pf); 9027d4dceecSKrzysztof Galazka ixl_free_filters(&vsi->ftl); 9031031d839SEric Joyner INIT_DBG_DEV(dev, "end"); 90461ae650dSJack F Vogel return (0); 90561ae650dSJack F Vogel } 90661ae650dSJack F Vogel 9071031d839SEric Joyner static int 9081031d839SEric Joyner ixl_if_shutdown(if_ctx_t ctx) 9091031d839SEric Joyner { 9101031d839SEric Joyner int error = 0; 9111031d839SEric Joyner 9121031d839SEric Joyner INIT_DEBUGOUT("ixl_if_shutdown: begin"); 9131031d839SEric Joyner 9141031d839SEric Joyner /* TODO: Call ixl_if_stop()? */ 9151031d839SEric Joyner 9161031d839SEric Joyner /* TODO: Then setup low power mode */ 9171031d839SEric Joyner 9181031d839SEric Joyner return (error); 9191031d839SEric Joyner } 92061ae650dSJack F Vogel 92161ae650dSJack F Vogel static int 9221031d839SEric Joyner ixl_if_suspend(if_ctx_t ctx) 92361ae650dSJack F Vogel { 9241031d839SEric Joyner int error = 0; 9251031d839SEric Joyner 9261031d839SEric Joyner INIT_DEBUGOUT("ixl_if_suspend: begin"); 9271031d839SEric Joyner 9281031d839SEric Joyner /* TODO: Call ixl_if_stop()? */ 9291031d839SEric Joyner 9301031d839SEric Joyner /* TODO: Then setup low power mode */ 9311031d839SEric Joyner 9321031d839SEric Joyner return (error); 9331031d839SEric Joyner } 9341031d839SEric Joyner 9351031d839SEric Joyner static int 9361031d839SEric Joyner ixl_if_resume(if_ctx_t ctx) 9371031d839SEric Joyner { 938402810d3SJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 9391031d839SEric Joyner 9401031d839SEric Joyner INIT_DEBUGOUT("ixl_if_resume: begin"); 9411031d839SEric Joyner 9421031d839SEric Joyner /* Read & clear wake-up registers */ 9431031d839SEric Joyner 9441031d839SEric Joyner /* Required after D3->D0 transition */ 945402810d3SJustin Hibbits if (if_getflags(ifp) & IFF_UP) 9461031d839SEric Joyner ixl_if_init(ctx); 9471031d839SEric Joyner 94861ae650dSJack F Vogel return (0); 94961ae650dSJack F Vogel } 95061ae650dSJack F Vogel 9511031d839SEric Joyner void 9521031d839SEric Joyner ixl_if_init(if_ctx_t ctx) 9531031d839SEric Joyner { 9541031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 9551031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 9561031d839SEric Joyner struct i40e_hw *hw = &pf->hw; 957402810d3SJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 9581031d839SEric Joyner device_t dev = iflib_get_dev(ctx); 9591031d839SEric Joyner u8 tmpaddr[ETHER_ADDR_LEN]; 9601031d839SEric Joyner int ret; 9611031d839SEric Joyner 962b4a7ce06SEric Joyner if (IXL_PF_IN_RECOVERY_MODE(pf)) 963b4a7ce06SEric Joyner return; 9641031d839SEric Joyner /* 9651031d839SEric Joyner * If the aq is dead here, it probably means something outside of the driver 9661031d839SEric Joyner * did something to the adapter, like a PF reset. 96777c1fcecSEric Joyner * So, rebuild the driver's state here if that occurs. 9681031d839SEric Joyner */ 9691031d839SEric Joyner if (!i40e_check_asq_alive(&pf->hw)) { 9701031d839SEric Joyner device_printf(dev, "Admin Queue is down; resetting...\n"); 9711031d839SEric Joyner ixl_teardown_hw_structs(pf); 972b4a7ce06SEric Joyner ixl_rebuild_hw_structs_after_reset(pf, false); 9731031d839SEric Joyner } 9741031d839SEric Joyner 9751031d839SEric Joyner /* Get the latest mac address... User might use a LAA */ 976402810d3SJustin Hibbits bcopy(if_getlladdr(vsi->ifp), tmpaddr, ETH_ALEN); 9777d4dceecSKrzysztof Galazka if (!ixl_ether_is_equal(hw->mac.addr, tmpaddr) && 9781031d839SEric Joyner (i40e_validate_mac_addr(tmpaddr) == I40E_SUCCESS)) { 9797d4dceecSKrzysztof Galazka ixl_del_all_vlan_filters(vsi, hw->mac.addr); 9801031d839SEric Joyner bcopy(tmpaddr, hw->mac.addr, ETH_ALEN); 9811031d839SEric Joyner ret = i40e_aq_mac_address_write(hw, 9821031d839SEric Joyner I40E_AQC_WRITE_TYPE_LAA_ONLY, 9831031d839SEric Joyner hw->mac.addr, NULL); 9841031d839SEric Joyner if (ret) { 9851031d839SEric Joyner device_printf(dev, "LLA address change failed!!\n"); 9861031d839SEric Joyner return; 9871031d839SEric Joyner } 9887d4dceecSKrzysztof Galazka /* 9897d4dceecSKrzysztof Galazka * New filters are configured by ixl_reconfigure_filters 9907d4dceecSKrzysztof Galazka * at the end of ixl_init_locked. 9917d4dceecSKrzysztof Galazka */ 9921031d839SEric Joyner } 9931031d839SEric Joyner 9941031d839SEric Joyner iflib_set_mac(ctx, hw->mac.addr); 9951031d839SEric Joyner 9961031d839SEric Joyner /* Prepare the VSI: rings, hmc contexts, etc... */ 9971031d839SEric Joyner if (ixl_initialize_vsi(vsi)) { 9981031d839SEric Joyner device_printf(dev, "initialize vsi failed!!\n"); 9991031d839SEric Joyner return; 10001031d839SEric Joyner } 10011031d839SEric Joyner 100221802a12SKrzysztof Galazka ixl_set_link(pf, true); 100321802a12SKrzysztof Galazka 100477c1fcecSEric Joyner /* Reconfigure multicast filters in HW */ 10051031d839SEric Joyner ixl_if_multi_set(ctx); 10061031d839SEric Joyner 10071031d839SEric Joyner /* Set up RSS */ 10081031d839SEric Joyner ixl_config_rss(pf); 10091031d839SEric Joyner 1010b97de13aSMarius Strobl /* Set up MSI-X routing and the ITR settings */ 10111031d839SEric Joyner if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) { 10121031d839SEric Joyner ixl_configure_queue_intr_msix(pf); 10131031d839SEric Joyner ixl_configure_itr(pf); 10141031d839SEric Joyner } else 10151031d839SEric Joyner ixl_configure_legacy(pf); 10161031d839SEric Joyner 10171031d839SEric Joyner if (vsi->enable_head_writeback) 10181031d839SEric Joyner ixl_init_tx_cidx(vsi); 10191031d839SEric Joyner else 10201031d839SEric Joyner ixl_init_tx_rsqs(vsi); 10211031d839SEric Joyner 10221031d839SEric Joyner ixl_enable_rings(vsi); 10231031d839SEric Joyner 10241031d839SEric Joyner i40e_aq_set_default_vsi(hw, vsi->seid, NULL); 10251031d839SEric Joyner 102677c1fcecSEric Joyner /* Re-add configure filters to HW */ 10271031d839SEric Joyner ixl_reconfigure_filters(vsi); 10281031d839SEric Joyner 102977c1fcecSEric Joyner /* Configure promiscuous mode */ 103077c1fcecSEric Joyner ixl_if_promisc_set(ctx, if_getflags(ifp)); 103177c1fcecSEric Joyner 10321031d839SEric Joyner #ifdef IXL_IW 10331031d839SEric Joyner if (ixl_enable_iwarp && pf->iw_enabled) { 10341031d839SEric Joyner ret = ixl_iw_pf_init(pf); 10351031d839SEric Joyner if (ret) 10361031d839SEric Joyner device_printf(dev, 10371031d839SEric Joyner "initialize iwarp failed, code %d\n", ret); 10381031d839SEric Joyner } 10391031d839SEric Joyner #endif 10401031d839SEric Joyner } 10411031d839SEric Joyner 10421031d839SEric Joyner void 10431031d839SEric Joyner ixl_if_stop(if_ctx_t ctx) 10441031d839SEric Joyner { 10451031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1046402810d3SJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 10471031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 10481031d839SEric Joyner 10491031d839SEric Joyner INIT_DEBUGOUT("ixl_if_stop: begin\n"); 10501031d839SEric Joyner 1051b4a7ce06SEric Joyner if (IXL_PF_IN_RECOVERY_MODE(pf)) 1052b4a7ce06SEric Joyner return; 1053b4a7ce06SEric Joyner 10541031d839SEric Joyner // TODO: This may need to be reworked 10551031d839SEric Joyner #ifdef IXL_IW 10561031d839SEric Joyner /* Stop iWARP device */ 10571031d839SEric Joyner if (ixl_enable_iwarp && pf->iw_enabled) 10581031d839SEric Joyner ixl_iw_pf_stop(pf); 10591031d839SEric Joyner #endif 10601031d839SEric Joyner 10611031d839SEric Joyner ixl_disable_rings_intr(vsi); 106277c1fcecSEric Joyner ixl_disable_rings(pf, vsi, &pf->qtag); 106321802a12SKrzysztof Galazka 106421802a12SKrzysztof Galazka /* 106521802a12SKrzysztof Galazka * Don't set link state if only reconfiguring 106621802a12SKrzysztof Galazka * e.g. on MTU change. 106721802a12SKrzysztof Galazka */ 106821802a12SKrzysztof Galazka if ((if_getflags(ifp) & IFF_UP) == 0 && 1069b8f51b8cSPiotr Kubaj !ixl_test_state(&pf->state, IXL_STATE_LINK_ACTIVE_ON_DOWN)) 107021802a12SKrzysztof Galazka ixl_set_link(pf, false); 10711031d839SEric Joyner } 10721031d839SEric Joyner 10731031d839SEric Joyner static int 10741031d839SEric Joyner ixl_if_msix_intr_assign(if_ctx_t ctx, int msix) 10751031d839SEric Joyner { 10761031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 10771031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 10781031d839SEric Joyner struct ixl_rx_queue *rx_que = vsi->rx_queues; 10791031d839SEric Joyner struct ixl_tx_queue *tx_que = vsi->tx_queues; 10801031d839SEric Joyner int err, i, rid, vector = 0; 10811031d839SEric Joyner char buf[16]; 10821031d839SEric Joyner 108377c1fcecSEric Joyner MPASS(vsi->shared->isc_nrxqsets > 0); 108477c1fcecSEric Joyner MPASS(vsi->shared->isc_ntxqsets > 0); 108577c1fcecSEric Joyner 10861031d839SEric Joyner /* Admin Que must use vector 0*/ 10871031d839SEric Joyner rid = vector + 1; 10881031d839SEric Joyner err = iflib_irq_alloc_generic(ctx, &vsi->irq, rid, IFLIB_INTR_ADMIN, 10891031d839SEric Joyner ixl_msix_adminq, pf, 0, "aq"); 10901031d839SEric Joyner if (err) { 10911031d839SEric Joyner iflib_irq_free(ctx, &vsi->irq); 10921031d839SEric Joyner device_printf(iflib_get_dev(ctx), 109377c1fcecSEric Joyner "Failed to register Admin Que handler"); 10941031d839SEric Joyner return (err); 10951031d839SEric Joyner } 109617859d53SAndrew Gallatin 109717859d53SAndrew Gallatin #ifdef PCI_IOV 109877c1fcecSEric Joyner /* Create soft IRQ for handling VFLRs */ 1099af06fa26SEric Joyner iflib_softirq_alloc_generic(ctx, NULL, IFLIB_INTR_IOV, pf, 0, "iov"); 110017859d53SAndrew Gallatin #endif 11011031d839SEric Joyner 11021031d839SEric Joyner /* Now set up the stations */ 110377c1fcecSEric Joyner for (i = 0, vector = 1; i < vsi->shared->isc_nrxqsets; i++, vector++, rx_que++) { 11041031d839SEric Joyner rid = vector + 1; 11051031d839SEric Joyner 11061031d839SEric Joyner snprintf(buf, sizeof(buf), "rxq%d", i); 11071031d839SEric Joyner err = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid, 110881be6552SMatt Macy IFLIB_INTR_RXTX, ixl_msix_que, rx_que, rx_que->rxr.me, buf); 11091031d839SEric Joyner /* XXX: Does the driver work as expected if there are fewer num_rx_queues than 11101031d839SEric Joyner * what's expected in the iflib context? */ 11111031d839SEric Joyner if (err) { 11121031d839SEric Joyner device_printf(iflib_get_dev(ctx), 111377c1fcecSEric Joyner "Failed to allocate queue RX int vector %d, err: %d\n", i, err); 11141031d839SEric Joyner vsi->num_rx_queues = i + 1; 11151031d839SEric Joyner goto fail; 11161031d839SEric Joyner } 11171031d839SEric Joyner rx_que->msix = vector; 11181031d839SEric Joyner } 11191031d839SEric Joyner 11201031d839SEric Joyner bzero(buf, sizeof(buf)); 11211031d839SEric Joyner 112277c1fcecSEric Joyner for (i = 0; i < vsi->shared->isc_ntxqsets; i++, tx_que++) { 11231031d839SEric Joyner snprintf(buf, sizeof(buf), "txq%d", i); 11241031d839SEric Joyner iflib_softirq_alloc_generic(ctx, 112577c1fcecSEric Joyner &vsi->rx_queues[i % vsi->shared->isc_nrxqsets].que_irq, 11261031d839SEric Joyner IFLIB_INTR_TX, tx_que, tx_que->txr.me, buf); 11271031d839SEric Joyner 11281031d839SEric Joyner /* TODO: Maybe call a strategy function for this to figure out which 11291031d839SEric Joyner * interrupts to map Tx queues to. I don't know if there's an immediately 11301031d839SEric Joyner * better way than this other than a user-supplied map, though. */ 113177c1fcecSEric Joyner tx_que->msix = (i % vsi->shared->isc_nrxqsets) + 1; 11321031d839SEric Joyner } 11331031d839SEric Joyner 11341031d839SEric Joyner return (0); 11351031d839SEric Joyner fail: 11361031d839SEric Joyner iflib_irq_free(ctx, &vsi->irq); 11371031d839SEric Joyner rx_que = vsi->rx_queues; 11381031d839SEric Joyner for (int i = 0; i < vsi->num_rx_queues; i++, rx_que++) 11391031d839SEric Joyner iflib_irq_free(ctx, &rx_que->que_irq); 11401031d839SEric Joyner return (err); 11411031d839SEric Joyner } 11421031d839SEric Joyner 11431031d839SEric Joyner /* 11441031d839SEric Joyner * Enable all interrupts 11451031d839SEric Joyner * 11461031d839SEric Joyner * Called in: 11471031d839SEric Joyner * iflib_init_locked, after ixl_if_init() 11481031d839SEric Joyner */ 11491031d839SEric Joyner static void 11501031d839SEric Joyner ixl_if_enable_intr(if_ctx_t ctx) 11511031d839SEric Joyner { 11521031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 11531031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 11541031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 11551031d839SEric Joyner struct ixl_rx_queue *que = vsi->rx_queues; 11561031d839SEric Joyner 11571031d839SEric Joyner ixl_enable_intr0(hw); 11581031d839SEric Joyner /* Enable queue interrupts */ 11591031d839SEric Joyner for (int i = 0; i < vsi->num_rx_queues; i++, que++) 11601031d839SEric Joyner /* TODO: Queue index parameter is probably wrong */ 11611031d839SEric Joyner ixl_enable_queue(hw, que->rxr.me); 11621031d839SEric Joyner } 11631031d839SEric Joyner 11641031d839SEric Joyner /* 11651031d839SEric Joyner * Disable queue interrupts 11661031d839SEric Joyner * 11671031d839SEric Joyner * Other interrupt causes need to remain active. 11681031d839SEric Joyner */ 11691031d839SEric Joyner static void 11701031d839SEric Joyner ixl_if_disable_intr(if_ctx_t ctx) 11711031d839SEric Joyner { 11721031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 11731031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 11741031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 11751031d839SEric Joyner struct ixl_rx_queue *rx_que = vsi->rx_queues; 11761031d839SEric Joyner 11771031d839SEric Joyner if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) { 11781031d839SEric Joyner for (int i = 0; i < vsi->num_rx_queues; i++, rx_que++) 11791031d839SEric Joyner ixl_disable_queue(hw, rx_que->msix - 1); 11801031d839SEric Joyner } else { 11811031d839SEric Joyner // Set PFINT_LNKLST0 FIRSTQ_INDX to 0x7FF 11821031d839SEric Joyner // stops queues from triggering interrupts 11831031d839SEric Joyner wr32(hw, I40E_PFINT_LNKLST0, 0x7FF); 11841031d839SEric Joyner } 11851031d839SEric Joyner } 11861031d839SEric Joyner 11871031d839SEric Joyner static int 11881031d839SEric Joyner ixl_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid) 11891031d839SEric Joyner { 11901031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 11911031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 11921031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 11931031d839SEric Joyner struct ixl_rx_queue *rx_que = &vsi->rx_queues[rxqid]; 11941031d839SEric Joyner 11951031d839SEric Joyner ixl_enable_queue(hw, rx_que->msix - 1); 11961031d839SEric Joyner return (0); 11971031d839SEric Joyner } 11981031d839SEric Joyner 11991031d839SEric Joyner static int 12001031d839SEric Joyner ixl_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid) 12011031d839SEric Joyner { 12021031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 12031031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 12041031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 12051031d839SEric Joyner struct ixl_tx_queue *tx_que = &vsi->tx_queues[txqid]; 12061031d839SEric Joyner 12071031d839SEric Joyner ixl_enable_queue(hw, tx_que->msix - 1); 12081031d839SEric Joyner return (0); 12091031d839SEric Joyner } 12101031d839SEric Joyner 12111031d839SEric Joyner static int 12121031d839SEric Joyner ixl_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs, int ntxqsets) 12131031d839SEric Joyner { 12141031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 12151031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 12161031d839SEric Joyner if_softc_ctx_t scctx = vsi->shared; 12171031d839SEric Joyner struct ixl_tx_queue *que; 12181031d839SEric Joyner int i, j, error = 0; 12191031d839SEric Joyner 122077c1fcecSEric Joyner MPASS(scctx->isc_ntxqsets > 0); 12211031d839SEric Joyner MPASS(ntxqs == 1); 122277c1fcecSEric Joyner MPASS(scctx->isc_ntxqsets == ntxqsets); 12231031d839SEric Joyner 12241031d839SEric Joyner /* Allocate queue structure memory */ 12251031d839SEric Joyner if (!(vsi->tx_queues = 12261031d839SEric Joyner (struct ixl_tx_queue *) malloc(sizeof(struct ixl_tx_queue) *ntxqsets, M_IXL, M_NOWAIT | M_ZERO))) { 12271031d839SEric Joyner device_printf(iflib_get_dev(ctx), "Unable to allocate TX ring memory\n"); 12281031d839SEric Joyner return (ENOMEM); 12291031d839SEric Joyner } 12301031d839SEric Joyner 12311031d839SEric Joyner for (i = 0, que = vsi->tx_queues; i < ntxqsets; i++, que++) { 12321031d839SEric Joyner struct tx_ring *txr = &que->txr; 12331031d839SEric Joyner 12341031d839SEric Joyner txr->me = i; 12351031d839SEric Joyner que->vsi = vsi; 12361031d839SEric Joyner 12371031d839SEric Joyner if (!vsi->enable_head_writeback) { 12381031d839SEric Joyner /* Allocate report status array */ 12391031d839SEric Joyner if (!(txr->tx_rsq = malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_IXL, M_NOWAIT))) { 12401031d839SEric Joyner device_printf(iflib_get_dev(ctx), "failed to allocate tx_rsq memory\n"); 12411031d839SEric Joyner error = ENOMEM; 12421031d839SEric Joyner goto fail; 12431031d839SEric Joyner } 12441031d839SEric Joyner /* Init report status array */ 12451031d839SEric Joyner for (j = 0; j < scctx->isc_ntxd[0]; j++) 12461031d839SEric Joyner txr->tx_rsq[j] = QIDX_INVALID; 12471031d839SEric Joyner } 12481031d839SEric Joyner /* get the virtual and physical address of the hardware queues */ 12491031d839SEric Joyner txr->tail = I40E_QTX_TAIL(txr->me); 12501031d839SEric Joyner txr->tx_base = (struct i40e_tx_desc *)vaddrs[i * ntxqs]; 12511031d839SEric Joyner txr->tx_paddr = paddrs[i * ntxqs]; 12521031d839SEric Joyner txr->que = que; 12531031d839SEric Joyner } 12541031d839SEric Joyner 12551031d839SEric Joyner return (0); 12561031d839SEric Joyner fail: 12571031d839SEric Joyner ixl_if_queues_free(ctx); 12581031d839SEric Joyner return (error); 12591031d839SEric Joyner } 12601031d839SEric Joyner 12611031d839SEric Joyner static int 12621031d839SEric Joyner ixl_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nrxqs, int nrxqsets) 12631031d839SEric Joyner { 12641031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 12651031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 12661031d839SEric Joyner struct ixl_rx_queue *que; 12671031d839SEric Joyner int i, error = 0; 12681031d839SEric Joyner 126977c1fcecSEric Joyner #ifdef INVARIANTS 127077c1fcecSEric Joyner if_softc_ctx_t scctx = vsi->shared; 127177c1fcecSEric Joyner MPASS(scctx->isc_nrxqsets > 0); 12721031d839SEric Joyner MPASS(nrxqs == 1); 127377c1fcecSEric Joyner MPASS(scctx->isc_nrxqsets == nrxqsets); 127477c1fcecSEric Joyner #endif 12751031d839SEric Joyner 12761031d839SEric Joyner /* Allocate queue structure memory */ 12771031d839SEric Joyner if (!(vsi->rx_queues = 12781031d839SEric Joyner (struct ixl_rx_queue *) malloc(sizeof(struct ixl_rx_queue) * 12791031d839SEric Joyner nrxqsets, M_IXL, M_NOWAIT | M_ZERO))) { 12801031d839SEric Joyner device_printf(iflib_get_dev(ctx), "Unable to allocate RX ring memory\n"); 12811031d839SEric Joyner error = ENOMEM; 12821031d839SEric Joyner goto fail; 12831031d839SEric Joyner } 12841031d839SEric Joyner 12851031d839SEric Joyner for (i = 0, que = vsi->rx_queues; i < nrxqsets; i++, que++) { 12861031d839SEric Joyner struct rx_ring *rxr = &que->rxr; 12871031d839SEric Joyner 12881031d839SEric Joyner rxr->me = i; 12891031d839SEric Joyner que->vsi = vsi; 12901031d839SEric Joyner 12911031d839SEric Joyner /* get the virtual and physical address of the hardware queues */ 12921031d839SEric Joyner rxr->tail = I40E_QRX_TAIL(rxr->me); 12931031d839SEric Joyner rxr->rx_base = (union i40e_rx_desc *)vaddrs[i * nrxqs]; 12941031d839SEric Joyner rxr->rx_paddr = paddrs[i * nrxqs]; 12951031d839SEric Joyner rxr->que = que; 12961031d839SEric Joyner } 12971031d839SEric Joyner 12981031d839SEric Joyner return (0); 12991031d839SEric Joyner fail: 13001031d839SEric Joyner ixl_if_queues_free(ctx); 13011031d839SEric Joyner return (error); 13021031d839SEric Joyner } 13031031d839SEric Joyner 13041031d839SEric Joyner static void 13051031d839SEric Joyner ixl_if_queues_free(if_ctx_t ctx) 13061031d839SEric Joyner { 13071031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 13081031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 13091031d839SEric Joyner 131038bfc6deSSai Rajesh Tallamraju if (vsi->tx_queues != NULL && !vsi->enable_head_writeback) { 13111031d839SEric Joyner struct ixl_tx_queue *que; 13121031d839SEric Joyner int i = 0; 13131031d839SEric Joyner 13141031d839SEric Joyner for (i = 0, que = vsi->tx_queues; i < vsi->num_tx_queues; i++, que++) { 13151031d839SEric Joyner struct tx_ring *txr = &que->txr; 13161031d839SEric Joyner if (txr->tx_rsq != NULL) { 13171031d839SEric Joyner free(txr->tx_rsq, M_IXL); 13181031d839SEric Joyner txr->tx_rsq = NULL; 13191031d839SEric Joyner } 13201031d839SEric Joyner } 13211031d839SEric Joyner } 13221031d839SEric Joyner 13231031d839SEric Joyner if (vsi->tx_queues != NULL) { 13241031d839SEric Joyner free(vsi->tx_queues, M_IXL); 13251031d839SEric Joyner vsi->tx_queues = NULL; 13261031d839SEric Joyner } 13271031d839SEric Joyner if (vsi->rx_queues != NULL) { 13281031d839SEric Joyner free(vsi->rx_queues, M_IXL); 13291031d839SEric Joyner vsi->rx_queues = NULL; 13301031d839SEric Joyner } 1331b4a7ce06SEric Joyner 1332b4a7ce06SEric Joyner if (!IXL_PF_IN_RECOVERY_MODE(pf)) 1333b4a7ce06SEric Joyner sysctl_ctx_free(&vsi->sysctl_ctx); 13341031d839SEric Joyner } 13351031d839SEric Joyner 13361031d839SEric Joyner void 13371031d839SEric Joyner ixl_update_link_status(struct ixl_pf *pf) 13381031d839SEric Joyner { 13391031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1340c9da8d8bSEric Joyner struct i40e_hw *hw = &pf->hw; 13411031d839SEric Joyner u64 baudrate; 13421031d839SEric Joyner 13431031d839SEric Joyner if (pf->link_up) { 13441031d839SEric Joyner if (vsi->link_active == FALSE) { 13451031d839SEric Joyner vsi->link_active = TRUE; 1346c9da8d8bSEric Joyner baudrate = ixl_max_aq_speed_to_value(hw->phy.link_info.link_speed); 13471031d839SEric Joyner iflib_link_state_change(vsi->ctx, LINK_STATE_UP, baudrate); 13481031d839SEric Joyner ixl_link_up_msg(pf); 13491031d839SEric Joyner #ifdef PCI_IOV 13501031d839SEric Joyner ixl_broadcast_link_state(pf); 13511031d839SEric Joyner #endif 13521031d839SEric Joyner } 13531031d839SEric Joyner } else { /* Link down */ 13541031d839SEric Joyner if (vsi->link_active == TRUE) { 13551031d839SEric Joyner vsi->link_active = FALSE; 13561031d839SEric Joyner iflib_link_state_change(vsi->ctx, LINK_STATE_DOWN, 0); 13571031d839SEric Joyner #ifdef PCI_IOV 13581031d839SEric Joyner ixl_broadcast_link_state(pf); 13591031d839SEric Joyner #endif 13601031d839SEric Joyner } 13611031d839SEric Joyner } 13621031d839SEric Joyner } 13631031d839SEric Joyner 136477c1fcecSEric Joyner static void 136577c1fcecSEric Joyner ixl_handle_lan_overflow_event(struct ixl_pf *pf, struct i40e_arq_event_info *e) 136677c1fcecSEric Joyner { 136777c1fcecSEric Joyner device_t dev = pf->dev; 136877c1fcecSEric Joyner u32 rxq_idx, qtx_ctl; 136977c1fcecSEric Joyner 137077c1fcecSEric Joyner rxq_idx = (e->desc.params.external.param0 & I40E_PRTDCB_RUPTQ_RXQNUM_MASK) >> 137177c1fcecSEric Joyner I40E_PRTDCB_RUPTQ_RXQNUM_SHIFT; 137277c1fcecSEric Joyner qtx_ctl = e->desc.params.external.param1; 137377c1fcecSEric Joyner 137477c1fcecSEric Joyner device_printf(dev, "LAN overflow event: global rxq_idx %d\n", rxq_idx); 137577c1fcecSEric Joyner device_printf(dev, "LAN overflow event: QTX_CTL 0x%08x\n", qtx_ctl); 137677c1fcecSEric Joyner } 137777c1fcecSEric Joyner 13781031d839SEric Joyner static int 13791031d839SEric Joyner ixl_process_adminq(struct ixl_pf *pf, u16 *pending) 13801031d839SEric Joyner { 13811031d839SEric Joyner enum i40e_status_code status = I40E_SUCCESS; 13821031d839SEric Joyner struct i40e_arq_event_info event; 13831031d839SEric Joyner struct i40e_hw *hw = &pf->hw; 13841031d839SEric Joyner device_t dev = pf->dev; 13851031d839SEric Joyner u16 opcode; 13861031d839SEric Joyner u32 loop = 0, reg; 13871031d839SEric Joyner 13881031d839SEric Joyner event.buf_len = IXL_AQ_BUF_SZ; 13891031d839SEric Joyner event.msg_buf = malloc(event.buf_len, M_IXL, M_NOWAIT | M_ZERO); 13901031d839SEric Joyner if (!event.msg_buf) { 13911031d839SEric Joyner device_printf(dev, "%s: Unable to allocate memory for Admin" 13921031d839SEric Joyner " Queue event!\n", __func__); 13931031d839SEric Joyner return (ENOMEM); 13941031d839SEric Joyner } 13951031d839SEric Joyner 13961031d839SEric Joyner /* clean and process any events */ 13971031d839SEric Joyner do { 13981031d839SEric Joyner status = i40e_clean_arq_element(hw, &event, pending); 13991031d839SEric Joyner if (status) 14001031d839SEric Joyner break; 14011031d839SEric Joyner opcode = LE16_TO_CPU(event.desc.opcode); 14021031d839SEric Joyner ixl_dbg(pf, IXL_DBG_AQ, 14031031d839SEric Joyner "Admin Queue event: %#06x\n", opcode); 14041031d839SEric Joyner switch (opcode) { 14051031d839SEric Joyner case i40e_aqc_opc_get_link_status: 14061031d839SEric Joyner ixl_link_event(pf, &event); 14071031d839SEric Joyner break; 14081031d839SEric Joyner case i40e_aqc_opc_send_msg_to_pf: 14091031d839SEric Joyner #ifdef PCI_IOV 14101031d839SEric Joyner ixl_handle_vf_msg(pf, &event); 14111031d839SEric Joyner #endif 14121031d839SEric Joyner break; 14131031d839SEric Joyner /* 14141031d839SEric Joyner * This should only occur on no-drop queues, which 14151031d839SEric Joyner * aren't currently configured. 14161031d839SEric Joyner */ 14171031d839SEric Joyner case i40e_aqc_opc_event_lan_overflow: 141877c1fcecSEric Joyner ixl_handle_lan_overflow_event(pf, &event); 14191031d839SEric Joyner break; 14201031d839SEric Joyner default: 14211031d839SEric Joyner break; 14221031d839SEric Joyner } 14231031d839SEric Joyner } while (*pending && (loop++ < IXL_ADM_LIMIT)); 14241031d839SEric Joyner 14251031d839SEric Joyner free(event.msg_buf, M_IXL); 14261031d839SEric Joyner 14271031d839SEric Joyner /* Re-enable admin queue interrupt cause */ 14281031d839SEric Joyner reg = rd32(hw, I40E_PFINT_ICR0_ENA); 14291031d839SEric Joyner reg |= I40E_PFINT_ICR0_ENA_ADMINQ_MASK; 14301031d839SEric Joyner wr32(hw, I40E_PFINT_ICR0_ENA, reg); 14311031d839SEric Joyner 14321031d839SEric Joyner return (status); 14331031d839SEric Joyner } 14341031d839SEric Joyner 14351031d839SEric Joyner static void 14361031d839SEric Joyner ixl_if_update_admin_status(if_ctx_t ctx) 14371031d839SEric Joyner { 14381031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 14391031d839SEric Joyner struct i40e_hw *hw = &pf->hw; 14401031d839SEric Joyner u16 pending; 14411031d839SEric Joyner 14427d4dceecSKrzysztof Galazka if (IXL_PF_IS_RESETTING(pf)) 14431031d839SEric Joyner ixl_handle_empr_reset(pf); 14441031d839SEric Joyner 1445b4a7ce06SEric Joyner /* 1446b4a7ce06SEric Joyner * Admin Queue is shut down while handling reset. 1447b4a7ce06SEric Joyner * Don't proceed if it hasn't been re-initialized 1448b4a7ce06SEric Joyner * e.g due to an issue with new FW. 1449b4a7ce06SEric Joyner */ 1450b4a7ce06SEric Joyner if (!i40e_check_asq_alive(&pf->hw)) 1451b4a7ce06SEric Joyner return; 1452b4a7ce06SEric Joyner 1453b8f51b8cSPiotr Kubaj if (ixl_test_state(&pf->state, IXL_STATE_MDD_PENDING)) 14541031d839SEric Joyner ixl_handle_mdd_event(pf); 14551031d839SEric Joyner 14561031d839SEric Joyner ixl_process_adminq(pf, &pending); 14571031d839SEric Joyner ixl_update_link_status(pf); 14581031d839SEric Joyner 14591031d839SEric Joyner /* 14601031d839SEric Joyner * If there are still messages to process, reschedule ourselves. 14611031d839SEric Joyner * Otherwise, re-enable our interrupt and go to sleep. 14621031d839SEric Joyner */ 14631031d839SEric Joyner if (pending > 0) 14641031d839SEric Joyner iflib_admin_intr_deferred(ctx); 14651031d839SEric Joyner else 14661031d839SEric Joyner ixl_enable_intr0(hw); 14671031d839SEric Joyner } 14681031d839SEric Joyner 14691031d839SEric Joyner static void 14701031d839SEric Joyner ixl_if_multi_set(if_ctx_t ctx) 14711031d839SEric Joyner { 14721031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 14731031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 14741031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 14757d4dceecSKrzysztof Galazka int mcnt; 14761031d839SEric Joyner 14771031d839SEric Joyner IOCTL_DEBUGOUT("ixl_if_multi_set: begin"); 14781031d839SEric Joyner 147977c1fcecSEric Joyner /* Delete filters for removed multicast addresses */ 14807d4dceecSKrzysztof Galazka ixl_del_multi(vsi, false); 14811031d839SEric Joyner 14827d4dceecSKrzysztof Galazka mcnt = min(if_llmaddr_count(iflib_get_ifp(ctx)), MAX_MULTICAST_ADDR); 14831031d839SEric Joyner if (__predict_false(mcnt == MAX_MULTICAST_ADDR)) { 14841031d839SEric Joyner i40e_aq_set_vsi_multicast_promiscuous(hw, 14851031d839SEric Joyner vsi->seid, TRUE, NULL); 14867d4dceecSKrzysztof Galazka ixl_del_multi(vsi, true); 14871031d839SEric Joyner return; 14881031d839SEric Joyner } 14891031d839SEric Joyner 14907d4dceecSKrzysztof Galazka ixl_add_multi(vsi); 14911031d839SEric Joyner IOCTL_DEBUGOUT("ixl_if_multi_set: end"); 14921031d839SEric Joyner } 14931031d839SEric Joyner 14941031d839SEric Joyner static int 14951031d839SEric Joyner ixl_if_mtu_set(if_ctx_t ctx, uint32_t mtu) 14961031d839SEric Joyner { 14971031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 14981031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 14991031d839SEric Joyner 15001031d839SEric Joyner IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)"); 15011031d839SEric Joyner if (mtu > IXL_MAX_FRAME - ETHER_HDR_LEN - ETHER_CRC_LEN - 15021031d839SEric Joyner ETHER_VLAN_ENCAP_LEN) 15031031d839SEric Joyner return (EINVAL); 15041031d839SEric Joyner 15051031d839SEric Joyner vsi->shared->isc_max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + 15061031d839SEric Joyner ETHER_VLAN_ENCAP_LEN; 15071031d839SEric Joyner 15081031d839SEric Joyner return (0); 15091031d839SEric Joyner } 15101031d839SEric Joyner 15111031d839SEric Joyner static void 15121031d839SEric Joyner ixl_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr) 15131031d839SEric Joyner { 15141031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 15151031d839SEric Joyner struct i40e_hw *hw = &pf->hw; 15161031d839SEric Joyner 15171031d839SEric Joyner INIT_DEBUGOUT("ixl_media_status: begin"); 15181031d839SEric Joyner 15191031d839SEric Joyner ifmr->ifm_status = IFM_AVALID; 15201031d839SEric Joyner ifmr->ifm_active = IFM_ETHER; 15211031d839SEric Joyner 15221031d839SEric Joyner if (!pf->link_up) { 15231031d839SEric Joyner return; 15241031d839SEric Joyner } 15251031d839SEric Joyner 15261031d839SEric Joyner ifmr->ifm_status |= IFM_ACTIVE; 15271031d839SEric Joyner /* Hardware is always full-duplex */ 15281031d839SEric Joyner ifmr->ifm_active |= IFM_FDX; 15291031d839SEric Joyner 15301031d839SEric Joyner switch (hw->phy.link_info.phy_type) { 15311031d839SEric Joyner /* 100 M */ 15321031d839SEric Joyner case I40E_PHY_TYPE_100BASE_TX: 15331031d839SEric Joyner ifmr->ifm_active |= IFM_100_TX; 15341031d839SEric Joyner break; 15351031d839SEric Joyner /* 1 G */ 15361031d839SEric Joyner case I40E_PHY_TYPE_1000BASE_T: 15371031d839SEric Joyner ifmr->ifm_active |= IFM_1000_T; 15381031d839SEric Joyner break; 15391031d839SEric Joyner case I40E_PHY_TYPE_1000BASE_SX: 15401031d839SEric Joyner ifmr->ifm_active |= IFM_1000_SX; 15411031d839SEric Joyner break; 15421031d839SEric Joyner case I40E_PHY_TYPE_1000BASE_LX: 15431031d839SEric Joyner ifmr->ifm_active |= IFM_1000_LX; 15441031d839SEric Joyner break; 15451031d839SEric Joyner case I40E_PHY_TYPE_1000BASE_T_OPTICAL: 15461031d839SEric Joyner ifmr->ifm_active |= IFM_1000_T; 15471031d839SEric Joyner break; 15482984a8ddSEric Joyner /* 2.5 G */ 1549abf77452SKrzysztof Galazka case I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS: 15502984a8ddSEric Joyner ifmr->ifm_active |= IFM_2500_T; 15512984a8ddSEric Joyner break; 15522984a8ddSEric Joyner /* 5 G */ 1553abf77452SKrzysztof Galazka case I40E_PHY_TYPE_5GBASE_T_LINK_STATUS: 15542984a8ddSEric Joyner ifmr->ifm_active |= IFM_5000_T; 15552984a8ddSEric Joyner break; 15561031d839SEric Joyner /* 10 G */ 15571031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_SFPP_CU: 15581031d839SEric Joyner ifmr->ifm_active |= IFM_10G_TWINAX; 15591031d839SEric Joyner break; 15601031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_SR: 15611031d839SEric Joyner ifmr->ifm_active |= IFM_10G_SR; 15621031d839SEric Joyner break; 15631031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_LR: 15641031d839SEric Joyner ifmr->ifm_active |= IFM_10G_LR; 15651031d839SEric Joyner break; 15661031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_T: 15671031d839SEric Joyner ifmr->ifm_active |= IFM_10G_T; 15681031d839SEric Joyner break; 15691031d839SEric Joyner case I40E_PHY_TYPE_XAUI: 15701031d839SEric Joyner case I40E_PHY_TYPE_XFI: 15711031d839SEric Joyner ifmr->ifm_active |= IFM_10G_TWINAX; 15721031d839SEric Joyner break; 15731031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_AOC: 15741031d839SEric Joyner ifmr->ifm_active |= IFM_10G_AOC; 15751031d839SEric Joyner break; 15761031d839SEric Joyner /* 25 G */ 15771031d839SEric Joyner case I40E_PHY_TYPE_25GBASE_KR: 15781031d839SEric Joyner ifmr->ifm_active |= IFM_25G_KR; 15791031d839SEric Joyner break; 15801031d839SEric Joyner case I40E_PHY_TYPE_25GBASE_CR: 15811031d839SEric Joyner ifmr->ifm_active |= IFM_25G_CR; 15821031d839SEric Joyner break; 15831031d839SEric Joyner case I40E_PHY_TYPE_25GBASE_SR: 15841031d839SEric Joyner ifmr->ifm_active |= IFM_25G_SR; 15851031d839SEric Joyner break; 15861031d839SEric Joyner case I40E_PHY_TYPE_25GBASE_LR: 15871031d839SEric Joyner ifmr->ifm_active |= IFM_25G_LR; 15881031d839SEric Joyner break; 15891031d839SEric Joyner case I40E_PHY_TYPE_25GBASE_AOC: 15901031d839SEric Joyner ifmr->ifm_active |= IFM_25G_AOC; 15911031d839SEric Joyner break; 15921031d839SEric Joyner case I40E_PHY_TYPE_25GBASE_ACC: 15931031d839SEric Joyner ifmr->ifm_active |= IFM_25G_ACC; 15941031d839SEric Joyner break; 15951031d839SEric Joyner /* 40 G */ 15961031d839SEric Joyner case I40E_PHY_TYPE_40GBASE_CR4: 15971031d839SEric Joyner case I40E_PHY_TYPE_40GBASE_CR4_CU: 15981031d839SEric Joyner ifmr->ifm_active |= IFM_40G_CR4; 15991031d839SEric Joyner break; 16001031d839SEric Joyner case I40E_PHY_TYPE_40GBASE_SR4: 16011031d839SEric Joyner ifmr->ifm_active |= IFM_40G_SR4; 16021031d839SEric Joyner break; 16031031d839SEric Joyner case I40E_PHY_TYPE_40GBASE_LR4: 16041031d839SEric Joyner ifmr->ifm_active |= IFM_40G_LR4; 16051031d839SEric Joyner break; 16061031d839SEric Joyner case I40E_PHY_TYPE_XLAUI: 16071031d839SEric Joyner ifmr->ifm_active |= IFM_OTHER; 16081031d839SEric Joyner break; 16091031d839SEric Joyner case I40E_PHY_TYPE_1000BASE_KX: 16101031d839SEric Joyner ifmr->ifm_active |= IFM_1000_KX; 16111031d839SEric Joyner break; 16121031d839SEric Joyner case I40E_PHY_TYPE_SGMII: 16131031d839SEric Joyner ifmr->ifm_active |= IFM_1000_SGMII; 16141031d839SEric Joyner break; 16151031d839SEric Joyner /* ERJ: What's the difference between these? */ 16161031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_CR1_CU: 16171031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_CR1: 16181031d839SEric Joyner ifmr->ifm_active |= IFM_10G_CR1; 16191031d839SEric Joyner break; 16201031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_KX4: 16211031d839SEric Joyner ifmr->ifm_active |= IFM_10G_KX4; 16221031d839SEric Joyner break; 16231031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_KR: 16241031d839SEric Joyner ifmr->ifm_active |= IFM_10G_KR; 16251031d839SEric Joyner break; 16261031d839SEric Joyner case I40E_PHY_TYPE_SFI: 16271031d839SEric Joyner ifmr->ifm_active |= IFM_10G_SFI; 16281031d839SEric Joyner break; 16291031d839SEric Joyner /* Our single 20G media type */ 16301031d839SEric Joyner case I40E_PHY_TYPE_20GBASE_KR2: 16311031d839SEric Joyner ifmr->ifm_active |= IFM_20G_KR2; 16321031d839SEric Joyner break; 16331031d839SEric Joyner case I40E_PHY_TYPE_40GBASE_KR4: 16341031d839SEric Joyner ifmr->ifm_active |= IFM_40G_KR4; 16351031d839SEric Joyner break; 16361031d839SEric Joyner case I40E_PHY_TYPE_XLPPI: 16371031d839SEric Joyner case I40E_PHY_TYPE_40GBASE_AOC: 16381031d839SEric Joyner ifmr->ifm_active |= IFM_40G_XLPPI; 16391031d839SEric Joyner break; 16401031d839SEric Joyner /* Unknown to driver */ 16411031d839SEric Joyner default: 16421031d839SEric Joyner ifmr->ifm_active |= IFM_UNKNOWN; 16431031d839SEric Joyner break; 16441031d839SEric Joyner } 16451031d839SEric Joyner /* Report flow control status as well */ 16461031d839SEric Joyner if (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX) 16471031d839SEric Joyner ifmr->ifm_active |= IFM_ETH_TXPAUSE; 16481031d839SEric Joyner if (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX) 16491031d839SEric Joyner ifmr->ifm_active |= IFM_ETH_RXPAUSE; 16501031d839SEric Joyner } 16511031d839SEric Joyner 16521031d839SEric Joyner static int 16531031d839SEric Joyner ixl_if_media_change(if_ctx_t ctx) 16541031d839SEric Joyner { 16551031d839SEric Joyner struct ifmedia *ifm = iflib_get_media(ctx); 16561031d839SEric Joyner 16571031d839SEric Joyner INIT_DEBUGOUT("ixl_media_change: begin"); 16581031d839SEric Joyner 16591031d839SEric Joyner if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 16601031d839SEric Joyner return (EINVAL); 16611031d839SEric Joyner 16621031d839SEric Joyner if_printf(iflib_get_ifp(ctx), "Media change is not supported.\n"); 16631031d839SEric Joyner return (ENODEV); 16641031d839SEric Joyner } 16651031d839SEric Joyner 16661031d839SEric Joyner static int 16671031d839SEric Joyner ixl_if_promisc_set(if_ctx_t ctx, int flags) 16681031d839SEric Joyner { 16691031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 16701031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1671402810d3SJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 16721031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 16731031d839SEric Joyner int err; 16741031d839SEric Joyner bool uni = FALSE, multi = FALSE; 16751031d839SEric Joyner 16761031d839SEric Joyner if (flags & IFF_PROMISC) 16771031d839SEric Joyner uni = multi = TRUE; 1678ba76aa63SGleb Smirnoff else if (flags & IFF_ALLMULTI || if_llmaddr_count(ifp) >= 1679ba76aa63SGleb Smirnoff MAX_MULTICAST_ADDR) 16801031d839SEric Joyner multi = TRUE; 16811031d839SEric Joyner 16821031d839SEric Joyner err = i40e_aq_set_vsi_unicast_promiscuous(hw, 16831031d839SEric Joyner vsi->seid, uni, NULL, true); 16841031d839SEric Joyner if (err) 16851031d839SEric Joyner return (err); 16861031d839SEric Joyner err = i40e_aq_set_vsi_multicast_promiscuous(hw, 16871031d839SEric Joyner vsi->seid, multi, NULL); 16881031d839SEric Joyner return (err); 16891031d839SEric Joyner } 16901031d839SEric Joyner 16911031d839SEric Joyner static void 16921031d839SEric Joyner ixl_if_timer(if_ctx_t ctx, uint16_t qid) 16931031d839SEric Joyner { 1694b4a7ce06SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1695b4a7ce06SEric Joyner 16961031d839SEric Joyner if (qid != 0) 16971031d839SEric Joyner return; 16981031d839SEric Joyner 1699b4a7ce06SEric Joyner ixl_update_stats_counters(pf); 17001031d839SEric Joyner } 17011031d839SEric Joyner 17021031d839SEric Joyner static void 17031031d839SEric Joyner ixl_if_vlan_register(if_ctx_t ctx, u16 vtag) 17041031d839SEric Joyner { 17051031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 17061031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 17071031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 17087d4dceecSKrzysztof Galazka if_t ifp = iflib_get_ifp(ctx); 17091031d839SEric Joyner 17101031d839SEric Joyner if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 17111031d839SEric Joyner return; 17121031d839SEric Joyner 17137d4dceecSKrzysztof Galazka /* 17147d4dceecSKrzysztof Galazka * Keep track of registered VLANS to know what 17157d4dceecSKrzysztof Galazka * filters have to be configured when VLAN_HWFILTER 17167d4dceecSKrzysztof Galazka * capability is enabled. 17177d4dceecSKrzysztof Galazka */ 17181031d839SEric Joyner ++vsi->num_vlans; 17197d4dceecSKrzysztof Galazka bit_set(vsi->vlans_map, vtag); 17207d4dceecSKrzysztof Galazka 17217d4dceecSKrzysztof Galazka if ((if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER) == 0) 17227d4dceecSKrzysztof Galazka return; 17237d4dceecSKrzysztof Galazka 17247d4dceecSKrzysztof Galazka if (vsi->num_vlans < IXL_MAX_VLAN_FILTERS) 17251031d839SEric Joyner ixl_add_filter(vsi, hw->mac.addr, vtag); 17267d4dceecSKrzysztof Galazka else if (vsi->num_vlans == IXL_MAX_VLAN_FILTERS) { 17277d4dceecSKrzysztof Galazka /* 17287d4dceecSKrzysztof Galazka * There is not enough HW resources to add filters 17297d4dceecSKrzysztof Galazka * for all registered VLANs. Re-configure filtering 17307d4dceecSKrzysztof Galazka * to allow reception of all expected traffic. 17317d4dceecSKrzysztof Galazka */ 17327d4dceecSKrzysztof Galazka device_printf(vsi->dev, 17337d4dceecSKrzysztof Galazka "Not enough HW filters for all VLANs. VLAN HW filtering disabled"); 17347d4dceecSKrzysztof Galazka ixl_del_all_vlan_filters(vsi, hw->mac.addr); 17357d4dceecSKrzysztof Galazka ixl_add_filter(vsi, hw->mac.addr, IXL_VLAN_ANY); 17367d4dceecSKrzysztof Galazka } 17371031d839SEric Joyner } 17381031d839SEric Joyner 17391031d839SEric Joyner static void 17401031d839SEric Joyner ixl_if_vlan_unregister(if_ctx_t ctx, u16 vtag) 17411031d839SEric Joyner { 17421031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 17431031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 17441031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 17457d4dceecSKrzysztof Galazka if_t ifp = iflib_get_ifp(ctx); 17461031d839SEric Joyner 17471031d839SEric Joyner if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 17481031d839SEric Joyner return; 17491031d839SEric Joyner 17501031d839SEric Joyner --vsi->num_vlans; 17517d4dceecSKrzysztof Galazka bit_clear(vsi->vlans_map, vtag); 17527d4dceecSKrzysztof Galazka 17537d4dceecSKrzysztof Galazka if ((if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER) == 0) 17547d4dceecSKrzysztof Galazka return; 17557d4dceecSKrzysztof Galazka 17561d02c6b1SKrzysztof Galazka /* One filter is used for untagged frames */ 17571d02c6b1SKrzysztof Galazka if (vsi->num_vlans < IXL_MAX_VLAN_FILTERS - 1) 17581031d839SEric Joyner ixl_del_filter(vsi, hw->mac.addr, vtag); 17591d02c6b1SKrzysztof Galazka else if (vsi->num_vlans == IXL_MAX_VLAN_FILTERS - 1) { 17607d4dceecSKrzysztof Galazka ixl_del_filter(vsi, hw->mac.addr, IXL_VLAN_ANY); 17617d4dceecSKrzysztof Galazka ixl_add_vlan_filters(vsi, hw->mac.addr); 17627d4dceecSKrzysztof Galazka } 17631031d839SEric Joyner } 17641031d839SEric Joyner 17651031d839SEric Joyner static uint64_t 17661031d839SEric Joyner ixl_if_get_counter(if_ctx_t ctx, ift_counter cnt) 17671031d839SEric Joyner { 17681031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 17691031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 17701031d839SEric Joyner if_t ifp = iflib_get_ifp(ctx); 17711031d839SEric Joyner 17721031d839SEric Joyner switch (cnt) { 17731031d839SEric Joyner case IFCOUNTER_IPACKETS: 17741031d839SEric Joyner return (vsi->ipackets); 17751031d839SEric Joyner case IFCOUNTER_IERRORS: 17761031d839SEric Joyner return (vsi->ierrors); 17771031d839SEric Joyner case IFCOUNTER_OPACKETS: 17781031d839SEric Joyner return (vsi->opackets); 17791031d839SEric Joyner case IFCOUNTER_OERRORS: 17801031d839SEric Joyner return (vsi->oerrors); 17811031d839SEric Joyner case IFCOUNTER_COLLISIONS: 17821031d839SEric Joyner /* Collisions are by standard impossible in 40G/10G Ethernet */ 17831031d839SEric Joyner return (0); 17841031d839SEric Joyner case IFCOUNTER_IBYTES: 17851031d839SEric Joyner return (vsi->ibytes); 17861031d839SEric Joyner case IFCOUNTER_OBYTES: 17871031d839SEric Joyner return (vsi->obytes); 17881031d839SEric Joyner case IFCOUNTER_IMCASTS: 17891031d839SEric Joyner return (vsi->imcasts); 17901031d839SEric Joyner case IFCOUNTER_OMCASTS: 17911031d839SEric Joyner return (vsi->omcasts); 17921031d839SEric Joyner case IFCOUNTER_IQDROPS: 17931031d839SEric Joyner return (vsi->iqdrops); 17941031d839SEric Joyner case IFCOUNTER_OQDROPS: 17951031d839SEric Joyner return (vsi->oqdrops); 17961031d839SEric Joyner case IFCOUNTER_NOPROTO: 17971031d839SEric Joyner return (vsi->noproto); 17981031d839SEric Joyner default: 17991031d839SEric Joyner return (if_get_counter_default(ifp, cnt)); 18001031d839SEric Joyner } 18011031d839SEric Joyner } 18021031d839SEric Joyner 180377c1fcecSEric Joyner #ifdef PCI_IOV 18041031d839SEric Joyner static void 18051031d839SEric Joyner ixl_if_vflr_handle(if_ctx_t ctx) 18061031d839SEric Joyner { 180777c1fcecSEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 18081031d839SEric Joyner 180977c1fcecSEric Joyner ixl_handle_vflr(pf); 18101031d839SEric Joyner } 181177c1fcecSEric Joyner #endif 18121031d839SEric Joyner 18131031d839SEric Joyner static int 18141031d839SEric Joyner ixl_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req) 18151031d839SEric Joyner { 18161031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 18171031d839SEric Joyner 18181031d839SEric Joyner if (pf->read_i2c_byte == NULL) 18191031d839SEric Joyner return (EINVAL); 18201031d839SEric Joyner 18211031d839SEric Joyner for (int i = 0; i < req->len; i++) 18221031d839SEric Joyner if (pf->read_i2c_byte(pf, req->offset + i, 18231031d839SEric Joyner req->dev_addr, &req->data[i])) 18241031d839SEric Joyner return (EIO); 18251031d839SEric Joyner return (0); 18261031d839SEric Joyner } 18271031d839SEric Joyner 18281031d839SEric Joyner static int 18291031d839SEric Joyner ixl_if_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data) 18301031d839SEric Joyner { 18311031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 18321031d839SEric Joyner struct ifdrv *ifd = (struct ifdrv *)data; 18331031d839SEric Joyner int error = 0; 18341031d839SEric Joyner 1835ab43ce7aSEric Joyner /* 1836ab43ce7aSEric Joyner * The iflib_if_ioctl forwards SIOCxDRVSPEC and SIOGPRIVATE_0 without 1837ab43ce7aSEric Joyner * performing privilege checks. It is important that this function 1838ab43ce7aSEric Joyner * perform the necessary checks for commands which should only be 1839ab43ce7aSEric Joyner * executed by privileged threads. 1840ab43ce7aSEric Joyner */ 1841ab43ce7aSEric Joyner 1842ab43ce7aSEric Joyner switch(command) { 1843ab43ce7aSEric Joyner case SIOCGDRVSPEC: 1844ab43ce7aSEric Joyner case SIOCSDRVSPEC: 18451031d839SEric Joyner /* NVM update command */ 1846ab43ce7aSEric Joyner if (ifd->ifd_cmd == I40E_NVM_ACCESS) { 1847ab43ce7aSEric Joyner error = priv_check(curthread, PRIV_DRIVER); 1848ab43ce7aSEric Joyner if (error) 1849ab43ce7aSEric Joyner break; 18501031d839SEric Joyner error = ixl_handle_nvmupd_cmd(pf, ifd); 1851ab43ce7aSEric Joyner } else { 18521031d839SEric Joyner error = EINVAL; 1853ab43ce7aSEric Joyner } 1854ab43ce7aSEric Joyner break; 1855ab43ce7aSEric Joyner default: 1856ab43ce7aSEric Joyner error = EOPNOTSUPP; 1857ab43ce7aSEric Joyner } 18581031d839SEric Joyner 18591031d839SEric Joyner return (error); 18601031d839SEric Joyner } 18611031d839SEric Joyner 1862cf150917SEric Joyner /* ixl_if_needs_restart - Tell iflib when the driver needs to be reinitialized 1863cf150917SEric Joyner * @ctx: iflib context 1864cf150917SEric Joyner * @event: event code to check 1865cf150917SEric Joyner * 1866cf150917SEric Joyner * Defaults to returning false for every event. 1867cf150917SEric Joyner * 1868cf150917SEric Joyner * @returns true if iflib needs to reinit the interface, false otherwise 1869cf150917SEric Joyner */ 1870cf150917SEric Joyner static bool 1871cf150917SEric Joyner ixl_if_needs_restart(if_ctx_t ctx __unused, enum iflib_restart_event event) 1872cf150917SEric Joyner { 1873cf150917SEric Joyner switch (event) { 1874cf150917SEric Joyner case IFLIB_RESTART_VLAN_CONFIG: 1875cf150917SEric Joyner default: 1876cf150917SEric Joyner return (false); 1877cf150917SEric Joyner } 1878cf150917SEric Joyner } 1879cf150917SEric Joyner 18801031d839SEric Joyner /* 18811031d839SEric Joyner * Sanity check and save off tunable values. 18821031d839SEric Joyner */ 18831031d839SEric Joyner static void 18841031d839SEric Joyner ixl_save_pf_tunables(struct ixl_pf *pf) 18851031d839SEric Joyner { 18861031d839SEric Joyner device_t dev = pf->dev; 18871031d839SEric Joyner 18881031d839SEric Joyner /* Save tunable information */ 1889b4a7ce06SEric Joyner #ifdef IXL_DEBUG_FC 18901031d839SEric Joyner pf->enable_tx_fc_filter = ixl_enable_tx_fc_filter; 1891b4a7ce06SEric Joyner #endif 1892b4a7ce06SEric Joyner #ifdef IXL_DEBUG 1893b4a7ce06SEric Joyner pf->recovery_mode = ixl_debug_recovery_mode; 1894b4a7ce06SEric Joyner #endif 18951031d839SEric Joyner pf->dbg_mask = ixl_core_debug_mask; 18961031d839SEric Joyner pf->hw.debug_mask = ixl_shared_debug_mask; 18971031d839SEric Joyner pf->vsi.enable_head_writeback = !!(ixl_enable_head_writeback); 189877c1fcecSEric Joyner pf->enable_vf_loopback = !!(ixl_enable_vf_loopback); 18991031d839SEric Joyner #if 0 19001031d839SEric Joyner pf->dynamic_rx_itr = ixl_dynamic_rx_itr; 19011031d839SEric Joyner pf->dynamic_tx_itr = ixl_dynamic_tx_itr; 19021031d839SEric Joyner #endif 19031031d839SEric Joyner 19041031d839SEric Joyner if (ixl_i2c_access_method > 3 || ixl_i2c_access_method < 0) 19051031d839SEric Joyner pf->i2c_access_method = 0; 19061031d839SEric Joyner else 19071031d839SEric Joyner pf->i2c_access_method = ixl_i2c_access_method; 19081031d839SEric Joyner 19091031d839SEric Joyner if (ixl_tx_itr < 0 || ixl_tx_itr > IXL_MAX_ITR) { 19101031d839SEric Joyner device_printf(dev, "Invalid tx_itr value of %d set!\n", 19111031d839SEric Joyner ixl_tx_itr); 19121031d839SEric Joyner device_printf(dev, "tx_itr must be between %d and %d, " 19131031d839SEric Joyner "inclusive\n", 19141031d839SEric Joyner 0, IXL_MAX_ITR); 19151031d839SEric Joyner device_printf(dev, "Using default value of %d instead\n", 19161031d839SEric Joyner IXL_ITR_4K); 19171031d839SEric Joyner pf->tx_itr = IXL_ITR_4K; 19181031d839SEric Joyner } else 19191031d839SEric Joyner pf->tx_itr = ixl_tx_itr; 19201031d839SEric Joyner 19211031d839SEric Joyner if (ixl_rx_itr < 0 || ixl_rx_itr > IXL_MAX_ITR) { 19221031d839SEric Joyner device_printf(dev, "Invalid rx_itr value of %d set!\n", 19231031d839SEric Joyner ixl_rx_itr); 19241031d839SEric Joyner device_printf(dev, "rx_itr must be between %d and %d, " 19251031d839SEric Joyner "inclusive\n", 19261031d839SEric Joyner 0, IXL_MAX_ITR); 19271031d839SEric Joyner device_printf(dev, "Using default value of %d instead\n", 19281031d839SEric Joyner IXL_ITR_8K); 19291031d839SEric Joyner pf->rx_itr = IXL_ITR_8K; 19301031d839SEric Joyner } else 19311031d839SEric Joyner pf->rx_itr = ixl_rx_itr; 193220a52706SKrzysztof Galazka 193320a52706SKrzysztof Galazka pf->fc = -1; 193420a52706SKrzysztof Galazka if (ixl_flow_control != -1) { 193520a52706SKrzysztof Galazka if (ixl_flow_control < 0 || ixl_flow_control > 3) { 193620a52706SKrzysztof Galazka device_printf(dev, 193720a52706SKrzysztof Galazka "Invalid flow_control value of %d set!\n", 193820a52706SKrzysztof Galazka ixl_flow_control); 193920a52706SKrzysztof Galazka device_printf(dev, 194020a52706SKrzysztof Galazka "flow_control must be between %d and %d, " 194120a52706SKrzysztof Galazka "inclusive\n", 0, 3); 194220a52706SKrzysztof Galazka device_printf(dev, 194320a52706SKrzysztof Galazka "Using default configuration instead\n"); 194420a52706SKrzysztof Galazka } else 194520a52706SKrzysztof Galazka pf->fc = ixl_flow_control; 194620a52706SKrzysztof Galazka } 19471031d839SEric Joyner } 19481031d839SEric Joyner 1949