161ae650dSJack F Vogel /****************************************************************************** 261ae650dSJack F Vogel 3ceebc2f3SEric Joyner Copyright (c) 2013-2017, 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 *********************************************************************/ 50ceebc2f3SEric Joyner #define IXL_DRIVER_VERSION_MAJOR 1 51ceebc2f3SEric Joyner #define IXL_DRIVER_VERSION_MINOR 9 52ceebc2f3SEric Joyner #define IXL_DRIVER_VERSION_BUILD 9 53ceebc2f3SEric Joyner 54*1031d839SEric Joyner #define IXL_DRIVER_VERSION_STRING \ 55*1031d839SEric Joyner __XSTRING(IXL_DRIVER_VERSION_MAJOR) "." \ 56*1031d839SEric Joyner __XSTRING(IXL_DRIVER_VERSION_MINOR) "." \ 57*1031d839SEric Joyner __XSTRING(IXL_DRIVER_VERSION_BUILD) "-iflib-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 * 64*1031d839SEric Joyner * ( Vendor ID, Device ID, Branding String ) 6561ae650dSJack F Vogel *********************************************************************/ 6661ae650dSJack F Vogel 67*1031d839SEric Joyner static pci_vendor_info_t ixl_vendor_info_array[] = 6861ae650dSJack F Vogel { 69*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710, "Intel(R) Ethernet Controller X710 for 10GbE SFP+"), 70*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B, "Intel(R) Ethernet Controller XL710 for 40GbE backplane"), 71*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C, "Intel(R) Ethernet Controller X710 for 10GbE backplane"), 72*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A, "Intel(R) Ethernet Controller XL710 for 40GbE QSFP+"), 73*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B, "Intel(R) Ethernet Controller XL710 for 40GbE QSFP+"), 74*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_C, "Intel(R) Ethernet Controller X710 for 10GbE QSFP+"), 75*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T, "Intel(R) Ethernet Controller X710 for 10GBASE-T"), 76*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T4, "Intel(R) Ethernet Controller X710/X557-AT 10GBASE-T"), 77*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_X722, "Intel(R) Ethernet Connection X722 for 10GbE backplane"), 78*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_X722, "Intel(R) Ethernet Connection X722 for 10GbE QSFP+"), 79*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_X722, "Intel(R) Ethernet Connection X722 for 10GbE SFP+"), 80*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_1G_BASE_T_X722, "Intel(R) Ethernet Connection X722 for 1GbE"), 81*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T_X722, "Intel(R) Ethernet Connection X722 for 10GBASE-T"), 82*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_I_X722, "Intel(R) Ethernet Connection X722 for 10GbE SFP+"), 83*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_B, "Intel(R) Ethernet Controller XXV710 for 25GbE backplane"), 84*1031d839SEric Joyner PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_SFP28, "Intel(R) Ethernet Controller XXV710 for 25GbE SFP28"), 8561ae650dSJack F Vogel /* required last entry */ 86*1031d839SEric Joyner PVID_END 8761ae650dSJack F Vogel }; 8861ae650dSJack F Vogel 8961ae650dSJack F Vogel /********************************************************************* 9061ae650dSJack F Vogel * Function prototypes 9161ae650dSJack F Vogel *********************************************************************/ 92*1031d839SEric Joyner /*** IFLIB interface ***/ 93*1031d839SEric Joyner static void *ixl_register(device_t dev); 94*1031d839SEric Joyner static int ixl_if_attach_pre(if_ctx_t ctx); 95*1031d839SEric Joyner static int ixl_if_attach_post(if_ctx_t ctx); 96*1031d839SEric Joyner static int ixl_if_detach(if_ctx_t ctx); 97*1031d839SEric Joyner static int ixl_if_shutdown(if_ctx_t ctx); 98*1031d839SEric Joyner static int ixl_if_suspend(if_ctx_t ctx); 99*1031d839SEric Joyner static int ixl_if_resume(if_ctx_t ctx); 100*1031d839SEric Joyner static int ixl_if_msix_intr_assign(if_ctx_t ctx, int msix); 101*1031d839SEric Joyner static void ixl_if_enable_intr(if_ctx_t ctx); 102*1031d839SEric Joyner static void ixl_if_disable_intr(if_ctx_t ctx); 103*1031d839SEric Joyner static int ixl_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid); 104*1031d839SEric Joyner static int ixl_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid); 105*1031d839SEric Joyner static int ixl_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs, int ntxqsets); 106*1031d839SEric Joyner static int ixl_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nqs, int nqsets); 107*1031d839SEric Joyner static void ixl_if_queues_free(if_ctx_t ctx); 108*1031d839SEric Joyner static void ixl_if_update_admin_status(if_ctx_t ctx); 109*1031d839SEric Joyner static void ixl_if_multi_set(if_ctx_t ctx); 110*1031d839SEric Joyner static int ixl_if_mtu_set(if_ctx_t ctx, uint32_t mtu); 111*1031d839SEric Joyner static void ixl_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr); 112*1031d839SEric Joyner static int ixl_if_media_change(if_ctx_t ctx); 113*1031d839SEric Joyner static int ixl_if_promisc_set(if_ctx_t ctx, int flags); 114*1031d839SEric Joyner static void ixl_if_timer(if_ctx_t ctx, uint16_t qid); 115*1031d839SEric Joyner static void ixl_if_vlan_register(if_ctx_t ctx, u16 vtag); 116*1031d839SEric Joyner static void ixl_if_vlan_unregister(if_ctx_t ctx, u16 vtag); 117*1031d839SEric Joyner static uint64_t ixl_if_get_counter(if_ctx_t ctx, ift_counter cnt); 118*1031d839SEric Joyner static void ixl_if_vflr_handle(if_ctx_t ctx); 119*1031d839SEric Joyner // static void ixl_if_link_intr_enable(if_ctx_t ctx); 120*1031d839SEric Joyner static int ixl_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req); 121*1031d839SEric Joyner static int ixl_if_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data); 1226c426059SEric Joyner 123*1031d839SEric Joyner /*** Other ***/ 124*1031d839SEric Joyner static int ixl_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int); 125*1031d839SEric Joyner static void ixl_save_pf_tunables(struct ixl_pf *); 126*1031d839SEric Joyner static int ixl_allocate_pci_resources(struct ixl_pf *); 12761ae650dSJack F Vogel 12861ae650dSJack F Vogel /********************************************************************* 12961ae650dSJack F Vogel * FreeBSD Device Interface Entry Points 13061ae650dSJack F Vogel *********************************************************************/ 13161ae650dSJack F Vogel 13261ae650dSJack F Vogel static device_method_t ixl_methods[] = { 13361ae650dSJack F Vogel /* Device interface */ 134*1031d839SEric Joyner DEVMETHOD(device_register, ixl_register), 135*1031d839SEric Joyner DEVMETHOD(device_probe, iflib_device_probe), 136*1031d839SEric Joyner DEVMETHOD(device_attach, iflib_device_attach), 137*1031d839SEric Joyner DEVMETHOD(device_detach, iflib_device_detach), 138*1031d839SEric Joyner DEVMETHOD(device_shutdown, iflib_device_shutdown), 13956c2c47bSJack F Vogel #ifdef PCI_IOV 140a48d00d2SEric Joyner DEVMETHOD(pci_iov_init, ixl_iov_init), 141a48d00d2SEric Joyner DEVMETHOD(pci_iov_uninit, ixl_iov_uninit), 142a48d00d2SEric Joyner DEVMETHOD(pci_iov_add_vf, ixl_add_vf), 14356c2c47bSJack F Vogel #endif 144*1031d839SEric Joyner DEVMETHOD_END 14561ae650dSJack F Vogel }; 14661ae650dSJack F Vogel 14761ae650dSJack F Vogel static driver_t ixl_driver = { 14861ae650dSJack F Vogel "ixl", ixl_methods, sizeof(struct ixl_pf), 14961ae650dSJack F Vogel }; 15061ae650dSJack F Vogel 15161ae650dSJack F Vogel devclass_t ixl_devclass; 15261ae650dSJack F Vogel DRIVER_MODULE(ixl, pci, ixl_driver, ixl_devclass, 0, 0); 153*1031d839SEric Joyner MODULE_VERSION(ixl, 3); 154cb6b8299SEric Joyner 15561ae650dSJack F Vogel MODULE_DEPEND(ixl, pci, 1, 1, 1); 15661ae650dSJack F Vogel MODULE_DEPEND(ixl, ether, 1, 1, 1); 157*1031d839SEric Joyner MODULE_DEPEND(ixl, iflib, 1, 1, 1); 158*1031d839SEric Joyner 159*1031d839SEric Joyner static device_method_t ixl_if_methods[] = { 160*1031d839SEric Joyner DEVMETHOD(ifdi_attach_pre, ixl_if_attach_pre), 161*1031d839SEric Joyner DEVMETHOD(ifdi_attach_post, ixl_if_attach_post), 162*1031d839SEric Joyner DEVMETHOD(ifdi_detach, ixl_if_detach), 163*1031d839SEric Joyner DEVMETHOD(ifdi_shutdown, ixl_if_shutdown), 164*1031d839SEric Joyner DEVMETHOD(ifdi_suspend, ixl_if_suspend), 165*1031d839SEric Joyner DEVMETHOD(ifdi_resume, ixl_if_resume), 166*1031d839SEric Joyner DEVMETHOD(ifdi_init, ixl_if_init), 167*1031d839SEric Joyner DEVMETHOD(ifdi_stop, ixl_if_stop), 168*1031d839SEric Joyner DEVMETHOD(ifdi_msix_intr_assign, ixl_if_msix_intr_assign), 169*1031d839SEric Joyner DEVMETHOD(ifdi_intr_enable, ixl_if_enable_intr), 170*1031d839SEric Joyner DEVMETHOD(ifdi_intr_disable, ixl_if_disable_intr), 171*1031d839SEric Joyner //DEVMETHOD(ifdi_link_intr_enable, ixl_if_link_intr_enable), 172*1031d839SEric Joyner DEVMETHOD(ifdi_rx_queue_intr_enable, ixl_if_rx_queue_intr_enable), 173*1031d839SEric Joyner DEVMETHOD(ifdi_tx_queue_intr_enable, ixl_if_tx_queue_intr_enable), 174*1031d839SEric Joyner DEVMETHOD(ifdi_tx_queues_alloc, ixl_if_tx_queues_alloc), 175*1031d839SEric Joyner DEVMETHOD(ifdi_rx_queues_alloc, ixl_if_rx_queues_alloc), 176*1031d839SEric Joyner DEVMETHOD(ifdi_queues_free, ixl_if_queues_free), 177*1031d839SEric Joyner DEVMETHOD(ifdi_update_admin_status, ixl_if_update_admin_status), 178*1031d839SEric Joyner DEVMETHOD(ifdi_multi_set, ixl_if_multi_set), 179*1031d839SEric Joyner DEVMETHOD(ifdi_mtu_set, ixl_if_mtu_set), 180*1031d839SEric Joyner DEVMETHOD(ifdi_media_status, ixl_if_media_status), 181*1031d839SEric Joyner DEVMETHOD(ifdi_media_change, ixl_if_media_change), 182*1031d839SEric Joyner DEVMETHOD(ifdi_promisc_set, ixl_if_promisc_set), 183*1031d839SEric Joyner DEVMETHOD(ifdi_timer, ixl_if_timer), 184*1031d839SEric Joyner DEVMETHOD(ifdi_vlan_register, ixl_if_vlan_register), 185*1031d839SEric Joyner DEVMETHOD(ifdi_vlan_unregister, ixl_if_vlan_unregister), 186*1031d839SEric Joyner DEVMETHOD(ifdi_get_counter, ixl_if_get_counter), 187*1031d839SEric Joyner DEVMETHOD(ifdi_vflr_handle, ixl_if_vflr_handle), 188*1031d839SEric Joyner DEVMETHOD(ifdi_i2c_req, ixl_if_i2c_req), 189*1031d839SEric Joyner DEVMETHOD(ifdi_priv_ioctl, ixl_if_priv_ioctl), 190*1031d839SEric Joyner // ifdi_led_func 191*1031d839SEric Joyner // ifdi_debug 192*1031d839SEric Joyner DEVMETHOD_END 193*1031d839SEric Joyner }; 194*1031d839SEric Joyner 195*1031d839SEric Joyner static driver_t ixl_if_driver = { 196*1031d839SEric Joyner "ixl_if", ixl_if_methods, sizeof(struct ixl_pf) 197*1031d839SEric Joyner }; 19831830672SJack F Vogel 19961ae650dSJack F Vogel /* 20061ae650dSJack F Vogel ** TUNEABLE PARAMETERS: 20161ae650dSJack F Vogel */ 20261ae650dSJack F Vogel 20361ae650dSJack F Vogel static SYSCTL_NODE(_hw, OID_AUTO, ixl, CTLFLAG_RD, 0, 20461ae650dSJack F Vogel "IXL driver parameters"); 20561ae650dSJack F Vogel 20661ae650dSJack F Vogel /* 207ceebc2f3SEric Joyner * Leave this on unless you need to send flow control 208ceebc2f3SEric Joyner * frames (or other control frames) from software 209ceebc2f3SEric Joyner */ 2104294f337SSean Bruno static int ixl_enable_tx_fc_filter = 1; 2114294f337SSean Bruno TUNABLE_INT("hw.ixl.enable_tx_fc_filter", 2124294f337SSean Bruno &ixl_enable_tx_fc_filter); 2134294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, enable_tx_fc_filter, CTLFLAG_RDTUN, 2144294f337SSean Bruno &ixl_enable_tx_fc_filter, 0, 2154294f337SSean Bruno "Filter out packets with Ethertype 0x8808 from being sent out by non-HW sources"); 2164294f337SSean Bruno 217*1031d839SEric Joyner static int ixl_i2c_access_method = 0; 218*1031d839SEric Joyner TUNABLE_INT("hw.ixl.i2c_access_method", 219*1031d839SEric Joyner &ixl_i2c_access_method); 220*1031d839SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, i2c_access_method, CTLFLAG_RDTUN, 221*1031d839SEric Joyner &ixl_i2c_access_method, 0, 222*1031d839SEric Joyner IXL_SYSCTL_HELP_I2C_METHOD); 223*1031d839SEric Joyner 224ceebc2f3SEric Joyner /* 225ceebc2f3SEric Joyner * Different method for processing TX descriptor 226ceebc2f3SEric Joyner * completion. 227ceebc2f3SEric Joyner */ 228ceebc2f3SEric Joyner static int ixl_enable_head_writeback = 1; 229ceebc2f3SEric Joyner TUNABLE_INT("hw.ixl.enable_head_writeback", 230ceebc2f3SEric Joyner &ixl_enable_head_writeback); 231ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, enable_head_writeback, CTLFLAG_RDTUN, 232ceebc2f3SEric Joyner &ixl_enable_head_writeback, 0, 233ceebc2f3SEric Joyner "For detecting last completed TX descriptor by hardware, use value written by HW instead of checking descriptors"); 234ceebc2f3SEric Joyner 2354294f337SSean Bruno static int ixl_core_debug_mask = 0; 2364294f337SSean Bruno TUNABLE_INT("hw.ixl.core_debug_mask", 2374294f337SSean Bruno &ixl_core_debug_mask); 2384294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, core_debug_mask, CTLFLAG_RDTUN, 2394294f337SSean Bruno &ixl_core_debug_mask, 0, 2404294f337SSean Bruno "Display debug statements that are printed in non-shared code"); 2414294f337SSean Bruno 2424294f337SSean Bruno static int ixl_shared_debug_mask = 0; 2434294f337SSean Bruno TUNABLE_INT("hw.ixl.shared_debug_mask", 2444294f337SSean Bruno &ixl_shared_debug_mask); 2454294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, shared_debug_mask, CTLFLAG_RDTUN, 2464294f337SSean Bruno &ixl_shared_debug_mask, 0, 2474294f337SSean Bruno "Display debug statements that are printed in shared code"); 2484294f337SSean Bruno 249*1031d839SEric Joyner #if 0 25061ae650dSJack F Vogel /* 25161ae650dSJack F Vogel ** Controls for Interrupt Throttling 25261ae650dSJack F Vogel ** - true/false for dynamic adjustment 25361ae650dSJack F Vogel ** - default values for static ITR 25461ae650dSJack F Vogel */ 255*1031d839SEric Joyner static int ixl_dynamic_rx_itr = 0; 25661ae650dSJack F Vogel TUNABLE_INT("hw.ixl.dynamic_rx_itr", &ixl_dynamic_rx_itr); 25761ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_rx_itr, CTLFLAG_RDTUN, 25861ae650dSJack F Vogel &ixl_dynamic_rx_itr, 0, "Dynamic RX Interrupt Rate"); 25961ae650dSJack F Vogel 260*1031d839SEric Joyner static int ixl_dynamic_tx_itr = 0; 26161ae650dSJack F Vogel TUNABLE_INT("hw.ixl.dynamic_tx_itr", &ixl_dynamic_tx_itr); 26261ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_tx_itr, CTLFLAG_RDTUN, 26361ae650dSJack F Vogel &ixl_dynamic_tx_itr, 0, "Dynamic TX Interrupt Rate"); 264*1031d839SEric Joyner #endif 26561ae650dSJack F Vogel 2664294f337SSean Bruno static int ixl_rx_itr = IXL_ITR_8K; 26761ae650dSJack F Vogel TUNABLE_INT("hw.ixl.rx_itr", &ixl_rx_itr); 26861ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, rx_itr, CTLFLAG_RDTUN, 26961ae650dSJack F Vogel &ixl_rx_itr, 0, "RX Interrupt Rate"); 27061ae650dSJack F Vogel 2714294f337SSean Bruno static int ixl_tx_itr = IXL_ITR_4K; 27261ae650dSJack F Vogel TUNABLE_INT("hw.ixl.tx_itr", &ixl_tx_itr); 27361ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, tx_itr, CTLFLAG_RDTUN, 27461ae650dSJack F Vogel &ixl_tx_itr, 0, "TX Interrupt Rate"); 27561ae650dSJack F Vogel 276cb6b8299SEric Joyner #ifdef IXL_IW 277cb6b8299SEric Joyner int ixl_enable_iwarp = 0; 278cb6b8299SEric Joyner TUNABLE_INT("hw.ixl.enable_iwarp", &ixl_enable_iwarp); 279ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, enable_iwarp, CTLFLAG_RDTUN, 280ceebc2f3SEric Joyner &ixl_enable_iwarp, 0, "iWARP enabled"); 281ceebc2f3SEric Joyner 282ceebc2f3SEric Joyner #if __FreeBSD_version < 1100000 283ceebc2f3SEric Joyner int ixl_limit_iwarp_msix = 1; 284ceebc2f3SEric Joyner #else 285ceebc2f3SEric Joyner int ixl_limit_iwarp_msix = IXL_IW_MAX_MSIX; 286ceebc2f3SEric Joyner #endif 287ceebc2f3SEric Joyner TUNABLE_INT("hw.ixl.limit_iwarp_msix", &ixl_limit_iwarp_msix); 288ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, limit_iwarp_msix, CTLFLAG_RDTUN, 289ceebc2f3SEric Joyner &ixl_limit_iwarp_msix, 0, "Limit MSIX vectors assigned to iWARP"); 290cb6b8299SEric Joyner #endif 291cb6b8299SEric Joyner 292*1031d839SEric Joyner extern struct if_txrx ixl_txrx_hwb; 293*1031d839SEric Joyner extern struct if_txrx ixl_txrx_dwb; 294e5100ee2SJack F Vogel 295*1031d839SEric Joyner static struct if_shared_ctx ixl_sctx_init = { 296*1031d839SEric Joyner .isc_magic = IFLIB_MAGIC, 297*1031d839SEric Joyner .isc_q_align = PAGE_SIZE, 298*1031d839SEric Joyner .isc_tx_maxsize = IXL_TSO_SIZE, 299*1031d839SEric Joyner .isc_tx_maxsegsize = IXL_MAX_DMA_SEG_SIZE, 300*1031d839SEric Joyner 301*1031d839SEric Joyner .isc_rx_maxsize = 16384, 302*1031d839SEric Joyner .isc_rx_nsegments = IXL_MAX_RX_SEGS, 303*1031d839SEric Joyner .isc_rx_maxsegsize = IXL_MAX_DMA_SEG_SIZE, 304*1031d839SEric Joyner .isc_nfl = 1, 305*1031d839SEric Joyner .isc_ntxqs = 1, 306*1031d839SEric Joyner .isc_nrxqs = 1, 307*1031d839SEric Joyner 308*1031d839SEric Joyner .isc_admin_intrcnt = 1, 309*1031d839SEric Joyner .isc_vendor_info = ixl_vendor_info_array, 310*1031d839SEric Joyner .isc_driver_version = IXL_DRIVER_VERSION_STRING, 311*1031d839SEric Joyner .isc_driver = &ixl_if_driver, 312*1031d839SEric Joyner .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_NEED_ZERO_CSUM | IFLIB_ADMIN_ALWAYS_RUN, 313*1031d839SEric Joyner 314*1031d839SEric Joyner .isc_nrxd_min = {IXL_MIN_RING}, 315*1031d839SEric Joyner .isc_ntxd_min = {IXL_MIN_RING}, 316*1031d839SEric Joyner .isc_nrxd_max = {IXL_MAX_RING}, 317*1031d839SEric Joyner .isc_ntxd_max = {IXL_MAX_RING}, 318*1031d839SEric Joyner .isc_nrxd_default = {IXL_DEFAULT_RING}, 319*1031d839SEric Joyner .isc_ntxd_default = {IXL_DEFAULT_RING}, 320*1031d839SEric Joyner }; 321*1031d839SEric Joyner 322*1031d839SEric Joyner if_shared_ctx_t ixl_sctx = &ixl_sctx_init; 323*1031d839SEric Joyner 324*1031d839SEric Joyner /*** Functions ***/ 325*1031d839SEric Joyner static void * 326*1031d839SEric Joyner ixl_register(device_t dev) 327*1031d839SEric Joyner { 328*1031d839SEric Joyner return (ixl_sctx); 329*1031d839SEric Joyner } 33061ae650dSJack F Vogel 33161ae650dSJack F Vogel static int 332*1031d839SEric Joyner ixl_allocate_pci_resources(struct ixl_pf *pf) 33361ae650dSJack F Vogel { 334*1031d839SEric Joyner int rid; 335*1031d839SEric Joyner struct i40e_hw *hw = &pf->hw; 336*1031d839SEric Joyner device_t dev = iflib_get_dev(pf->vsi.ctx); 33761ae650dSJack F Vogel 338*1031d839SEric Joyner /* Map BAR0 */ 339*1031d839SEric Joyner rid = PCIR_BAR(0); 340*1031d839SEric Joyner pf->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 341*1031d839SEric Joyner &rid, RF_ACTIVE); 34261ae650dSJack F Vogel 343*1031d839SEric Joyner if (!(pf->pci_mem)) { 344*1031d839SEric Joyner device_printf(dev, "Unable to allocate bus resource: PCI memory\n"); 34561ae650dSJack F Vogel return (ENXIO); 34661ae650dSJack F Vogel } 34761ae650dSJack F Vogel 348*1031d839SEric Joyner /* Save off the PCI information */ 349*1031d839SEric Joyner hw->vendor_id = pci_get_vendor(dev); 350*1031d839SEric Joyner hw->device_id = pci_get_device(dev); 351*1031d839SEric Joyner hw->revision_id = pci_read_config(dev, PCIR_REVID, 1); 352*1031d839SEric Joyner hw->subsystem_vendor_id = 353*1031d839SEric Joyner pci_read_config(dev, PCIR_SUBVEND_0, 2); 354*1031d839SEric Joyner hw->subsystem_device_id = 355*1031d839SEric Joyner pci_read_config(dev, PCIR_SUBDEV_0, 2); 3564294f337SSean Bruno 357*1031d839SEric Joyner hw->bus.device = pci_get_slot(dev); 358*1031d839SEric Joyner hw->bus.func = pci_get_function(dev); 3594294f337SSean Bruno 360*1031d839SEric Joyner /* Save off register access information */ 361*1031d839SEric Joyner pf->osdep.mem_bus_space_tag = 362*1031d839SEric Joyner rman_get_bustag(pf->pci_mem); 363*1031d839SEric Joyner pf->osdep.mem_bus_space_handle = 364*1031d839SEric Joyner rman_get_bushandle(pf->pci_mem); 365*1031d839SEric Joyner pf->osdep.mem_bus_space_size = rman_get_size(pf->pci_mem); 366*1031d839SEric Joyner pf->osdep.flush_reg = I40E_GLGEN_STAT; 367*1031d839SEric Joyner pf->osdep.dev = dev; 368cb6b8299SEric Joyner 369*1031d839SEric Joyner pf->hw.hw_addr = (u8 *) &pf->osdep.mem_bus_space_handle; 370*1031d839SEric Joyner pf->hw.back = &pf->osdep; 3714294f337SSean Bruno 3724294f337SSean Bruno return (0); 3734294f337SSean Bruno } 3744294f337SSean Bruno 37561ae650dSJack F Vogel static int 376*1031d839SEric Joyner ixl_if_attach_pre(if_ctx_t ctx) 37761ae650dSJack F Vogel { 378*1031d839SEric Joyner device_t dev; 37961ae650dSJack F Vogel struct ixl_pf *pf; 38061ae650dSJack F Vogel struct i40e_hw *hw; 38161ae650dSJack F Vogel struct ixl_vsi *vsi; 382*1031d839SEric Joyner if_softc_ctx_t scctx; 383*1031d839SEric Joyner struct i40e_filter_control_settings filter; 3844294f337SSean Bruno enum i40e_status_code status; 38561ae650dSJack F Vogel int error = 0; 38661ae650dSJack F Vogel 387*1031d839SEric Joyner INIT_DEBUGOUT("ixl_if_attach_pre: begin"); 38861ae650dSJack F Vogel 38961ae650dSJack F Vogel /* Allocate, clear, and link in our primary soft structure */ 390*1031d839SEric Joyner dev = iflib_get_dev(ctx); 391*1031d839SEric Joyner pf = iflib_get_softc(ctx); 392*1031d839SEric Joyner vsi = &pf->vsi; 393*1031d839SEric Joyner vsi->back = pf; 394*1031d839SEric Joyner pf->dev = dev; 39561ae650dSJack F Vogel hw = &pf->hw; 39661ae650dSJack F Vogel 39761ae650dSJack F Vogel /* 39861ae650dSJack F Vogel ** Note this assumes we have a single embedded VSI, 39961ae650dSJack F Vogel ** this could be enhanced later to allocate multiple 40061ae650dSJack F Vogel */ 401*1031d839SEric Joyner //vsi->dev = pf->dev; 402*1031d839SEric Joyner vsi->hw = &pf->hw; 403*1031d839SEric Joyner vsi->id = 0; 404*1031d839SEric Joyner vsi->num_vlans = 0; 405*1031d839SEric Joyner vsi->ctx = ctx; 406*1031d839SEric Joyner vsi->media = iflib_get_media(ctx); 407*1031d839SEric Joyner vsi->shared = scctx = iflib_get_softc_ctx(ctx); 40861ae650dSJack F Vogel 4094294f337SSean Bruno /* Save tunable values */ 410*1031d839SEric Joyner ixl_save_pf_tunables(pf); 41161ae650dSJack F Vogel 41261ae650dSJack F Vogel /* Do PCI setup - map BAR0, etc */ 41361ae650dSJack F Vogel if (ixl_allocate_pci_resources(pf)) { 41461ae650dSJack F Vogel device_printf(dev, "Allocation of PCI resources failed\n"); 41561ae650dSJack F Vogel error = ENXIO; 416*1031d839SEric Joyner goto err_pci_res; 41761ae650dSJack F Vogel } 41861ae650dSJack F Vogel 41961ae650dSJack F Vogel /* Establish a clean starting point */ 42061ae650dSJack F Vogel i40e_clear_hw(hw); 4214294f337SSean Bruno status = i40e_pf_reset(hw); 4224294f337SSean Bruno if (status) { 4234294f337SSean Bruno device_printf(dev, "PF reset failure %s\n", 4244294f337SSean Bruno i40e_stat_str(hw, status)); 42561ae650dSJack F Vogel error = EIO; 42661ae650dSJack F Vogel goto err_out; 42761ae650dSJack F Vogel } 42861ae650dSJack F Vogel 42961ae650dSJack F Vogel /* Initialize the shared code */ 4304294f337SSean Bruno status = i40e_init_shared_code(hw); 4314294f337SSean Bruno if (status) { 4324294f337SSean Bruno device_printf(dev, "Unable to initialize shared code, error %s\n", 4334294f337SSean Bruno i40e_stat_str(hw, status)); 43461ae650dSJack F Vogel error = EIO; 43561ae650dSJack F Vogel goto err_out; 43661ae650dSJack F Vogel } 43761ae650dSJack F Vogel 43861ae650dSJack F Vogel /* Set up the admin queue */ 4394294f337SSean Bruno hw->aq.num_arq_entries = IXL_AQ_LEN; 4404294f337SSean Bruno hw->aq.num_asq_entries = IXL_AQ_LEN; 4414294f337SSean Bruno hw->aq.arq_buf_size = IXL_AQ_BUF_SZ; 4424294f337SSean Bruno hw->aq.asq_buf_size = IXL_AQ_BUF_SZ; 4434294f337SSean Bruno 4444294f337SSean Bruno status = i40e_init_adminq(hw); 4454294f337SSean Bruno if (status != 0 && status != I40E_ERR_FIRMWARE_API_VERSION) { 4464294f337SSean Bruno device_printf(dev, "Unable to initialize Admin Queue, error %s\n", 4474294f337SSean Bruno i40e_stat_str(hw, status)); 448fdb6f38aSEric Joyner error = EIO; 449fdb6f38aSEric Joyner goto err_out; 450fdb6f38aSEric Joyner } 4511d767a8eSEric Joyner ixl_print_nvm_version(pf); 4521d767a8eSEric Joyner 4534294f337SSean Bruno if (status == I40E_ERR_FIRMWARE_API_VERSION) { 45461ae650dSJack F Vogel device_printf(dev, "The driver for the device stopped " 455ceebc2f3SEric Joyner "because the NVM image is newer than expected.\n"); 456ceebc2f3SEric Joyner device_printf(dev, "You must install the most recent version of " 45761ae650dSJack F Vogel "the network driver.\n"); 458fdb6f38aSEric Joyner error = EIO; 45961ae650dSJack F Vogel goto err_out; 46061ae650dSJack F Vogel } 46161ae650dSJack F Vogel 46261ae650dSJack F Vogel if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR && 463ceebc2f3SEric Joyner hw->aq.api_min_ver > I40E_FW_MINOR_VERSION(hw)) { 46461ae650dSJack F Vogel device_printf(dev, "The driver for the device detected " 465ceebc2f3SEric Joyner "a newer version of the NVM image than expected.\n"); 466ceebc2f3SEric Joyner device_printf(dev, "Please install the most recent version " 467ceebc2f3SEric Joyner "of the network driver.\n"); 468ceebc2f3SEric Joyner } else if (hw->aq.api_maj_ver == 1 && hw->aq.api_min_ver < 4) { 46961ae650dSJack F Vogel device_printf(dev, "The driver for the device detected " 470ceebc2f3SEric Joyner "an older version of the NVM image than expected.\n"); 471ceebc2f3SEric Joyner device_printf(dev, "Please update the NVM image.\n"); 472ceebc2f3SEric Joyner } 47361ae650dSJack F Vogel 47461ae650dSJack F Vogel /* Clear PXE mode */ 47561ae650dSJack F Vogel i40e_clear_pxe_mode(hw); 47661ae650dSJack F Vogel 47761ae650dSJack F Vogel /* Get capabilities from the device */ 47861ae650dSJack F Vogel error = ixl_get_hw_capabilities(pf); 47961ae650dSJack F Vogel if (error) { 480*1031d839SEric Joyner device_printf(dev, "get_hw_capabilities failed: %d\n", 481*1031d839SEric Joyner error); 48261ae650dSJack F Vogel goto err_get_cap; 48361ae650dSJack F Vogel } 48461ae650dSJack F Vogel 48561ae650dSJack F Vogel /* Set up host memory cache */ 4864294f337SSean Bruno status = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp, 48756c2c47bSJack F Vogel hw->func_caps.num_rx_qp, 0, 0); 4884294f337SSean Bruno if (status) { 4894294f337SSean Bruno device_printf(dev, "init_lan_hmc failed: %s\n", 4904294f337SSean Bruno i40e_stat_str(hw, status)); 49161ae650dSJack F Vogel goto err_get_cap; 49261ae650dSJack F Vogel } 4934294f337SSean Bruno status = i40e_configure_lan_hmc(hw, I40E_HMC_MODEL_DIRECT_ONLY); 4944294f337SSean Bruno if (status) { 4954294f337SSean Bruno device_printf(dev, "configure_lan_hmc failed: %s\n", 4964294f337SSean Bruno i40e_stat_str(hw, status)); 49761ae650dSJack F Vogel goto err_mac_hmc; 49861ae650dSJack F Vogel } 49961ae650dSJack F Vogel 500d4683565SEric Joyner /* Disable LLDP from the firmware for certain NVM versions */ 501d4683565SEric Joyner if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 3)) || 502ceebc2f3SEric Joyner (pf->hw.aq.fw_maj_ver < 4)) { 50361ae650dSJack F Vogel i40e_aq_stop_lldp(hw, TRUE, NULL); 504ceebc2f3SEric Joyner pf->state |= IXL_PF_STATE_FW_LLDP_DISABLED; 505ceebc2f3SEric Joyner } 50661ae650dSJack F Vogel 5074294f337SSean Bruno /* Get MAC addresses from hardware */ 50861ae650dSJack F Vogel i40e_get_mac_addr(hw, hw->mac.addr); 50961ae650dSJack F Vogel error = i40e_validate_mac_addr(hw->mac.addr); 51061ae650dSJack F Vogel if (error) { 51161ae650dSJack F Vogel device_printf(dev, "validate_mac_addr failed: %d\n", error); 51261ae650dSJack F Vogel goto err_mac_hmc; 51361ae650dSJack F Vogel } 51461ae650dSJack F Vogel bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN); 515*1031d839SEric Joyner iflib_set_mac(ctx, hw->mac.addr); 51661ae650dSJack F Vogel i40e_get_port_mac_addr(hw, hw->mac.port_addr); 51761ae650dSJack F Vogel 518*1031d839SEric Joyner /* Set up the device filtering */ 519*1031d839SEric Joyner bzero(&filter, sizeof(filter)); 520*1031d839SEric Joyner filter.enable_ethtype = TRUE; 521*1031d839SEric Joyner filter.enable_macvlan = TRUE; 522*1031d839SEric Joyner filter.enable_fdir = FALSE; 523*1031d839SEric Joyner filter.hash_lut_size = I40E_HASH_LUT_SIZE_512; 524*1031d839SEric Joyner if (i40e_set_filter_control(hw, &filter)) 525*1031d839SEric Joyner device_printf(dev, "i40e_set_filter_control() failed\n"); 526*1031d839SEric Joyner 527ceebc2f3SEric Joyner /* Query device FW LLDP status */ 528ceebc2f3SEric Joyner ixl_get_fw_lldp_status(pf); 529ceebc2f3SEric Joyner /* Tell FW to apply DCB config on link up */ 530ceebc2f3SEric Joyner i40e_aq_set_dcb_parameters(hw, true, NULL); 531ceebc2f3SEric Joyner 532*1031d839SEric Joyner /* Fill out iflib parameters */ 533*1031d839SEric Joyner if (hw->mac.type == I40E_MAC_X722) 534*1031d839SEric Joyner scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 128; 535*1031d839SEric Joyner else 536*1031d839SEric Joyner scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 64; 537*1031d839SEric Joyner if (vsi->enable_head_writeback) { 538*1031d839SEric Joyner scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0] 539*1031d839SEric Joyner * sizeof(struct i40e_tx_desc) + sizeof(u32), DBA_ALIGN); 540*1031d839SEric Joyner scctx->isc_txrx = &ixl_txrx_hwb; 541*1031d839SEric Joyner } else { 542*1031d839SEric Joyner scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0] 543*1031d839SEric Joyner * sizeof(struct i40e_tx_desc), DBA_ALIGN); 544*1031d839SEric Joyner scctx->isc_txrx = &ixl_txrx_dwb; 545*1031d839SEric Joyner } 546*1031d839SEric Joyner scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0] 547*1031d839SEric Joyner * sizeof(union i40e_32byte_rx_desc), DBA_ALIGN); 548*1031d839SEric Joyner scctx->isc_msix_bar = PCIR_BAR(IXL_MSIX_BAR); 549*1031d839SEric Joyner scctx->isc_tx_nsegments = IXL_MAX_TX_SEGS; 550*1031d839SEric Joyner scctx->isc_tx_tso_segments_max = IXL_MAX_TSO_SEGS; 551*1031d839SEric Joyner scctx->isc_tx_tso_size_max = IXL_TSO_SIZE; 552*1031d839SEric Joyner scctx->isc_tx_tso_segsize_max = IXL_MAX_DMA_SEG_SIZE; 553*1031d839SEric Joyner scctx->isc_rss_table_size = pf->hw.func_caps.rss_table_size; 554*1031d839SEric Joyner scctx->isc_tx_csum_flags = CSUM_OFFLOAD; 555*1031d839SEric Joyner scctx->isc_capenable = IXL_CAPS; 5564294f337SSean Bruno 557*1031d839SEric Joyner INIT_DEBUGOUT("ixl_if_attach_pre: end"); 558*1031d839SEric Joyner return (0); 559*1031d839SEric Joyner 560*1031d839SEric Joyner err_mac_hmc: 561*1031d839SEric Joyner i40e_shutdown_lan_hmc(hw); 562*1031d839SEric Joyner err_get_cap: 563*1031d839SEric Joyner i40e_shutdown_adminq(hw); 564*1031d839SEric Joyner err_out: 565*1031d839SEric Joyner ixl_free_pci_resources(pf); 566*1031d839SEric Joyner err_pci_res: 567*1031d839SEric Joyner return (error); 56861ae650dSJack F Vogel } 56961ae650dSJack F Vogel 570*1031d839SEric Joyner static int 571*1031d839SEric Joyner ixl_if_attach_post(if_ctx_t ctx) 572*1031d839SEric Joyner { 573*1031d839SEric Joyner device_t dev; 574*1031d839SEric Joyner struct ixl_pf *pf; 575*1031d839SEric Joyner struct i40e_hw *hw; 576*1031d839SEric Joyner struct ixl_vsi *vsi; 577*1031d839SEric Joyner int error = 0; 578*1031d839SEric Joyner enum i40e_status_code status; 579*1031d839SEric Joyner 580*1031d839SEric Joyner INIT_DEBUGOUT("ixl_if_attach_post: begin"); 581*1031d839SEric Joyner 582*1031d839SEric Joyner dev = iflib_get_dev(ctx); 583*1031d839SEric Joyner pf = iflib_get_softc(ctx); 584*1031d839SEric Joyner vsi = &pf->vsi; 585*1031d839SEric Joyner vsi->ifp = iflib_get_ifp(ctx); 586*1031d839SEric Joyner hw = &pf->hw; 587*1031d839SEric Joyner 5884294f337SSean Bruno /* Setup OS network interface / ifnet */ 589*1031d839SEric Joyner if (ixl_setup_interface(dev, pf)) { 5904294f337SSean Bruno device_printf(dev, "interface setup failed!\n"); 5914294f337SSean Bruno error = EIO; 592*1031d839SEric Joyner goto err; 593223d846dSEric Joyner } 59461ae650dSJack F Vogel 59561ae650dSJack F Vogel /* Determine link state */ 5964294f337SSean Bruno if (ixl_attach_get_link_status(pf)) { 5974294f337SSean Bruno error = EINVAL; 598*1031d839SEric Joyner goto err; 599e5100ee2SJack F Vogel } 60061ae650dSJack F Vogel 601b6c8f260SJack F Vogel error = ixl_switch_config(pf); 602b6c8f260SJack F Vogel if (error) { 6036c426059SEric Joyner device_printf(dev, "Initial ixl_switch_config() failed: %d\n", 6046c426059SEric Joyner error); 605*1031d839SEric Joyner goto err; 606b6c8f260SJack F Vogel } 607b6c8f260SJack F Vogel 608*1031d839SEric Joyner /* Add protocol filters to list */ 609*1031d839SEric Joyner ixl_init_filters(vsi); 610*1031d839SEric Joyner 611*1031d839SEric Joyner /* Init queue allocation manager */ 612*1031d839SEric Joyner error = ixl_pf_qmgr_init(&pf->qmgr, hw->func_caps.num_tx_qp); 613*1031d839SEric Joyner if (error) { 614*1031d839SEric Joyner device_printf(dev, "Failed to init queue manager for PF queues, error %d\n", 615*1031d839SEric Joyner error); 616*1031d839SEric Joyner goto err; 617*1031d839SEric Joyner } 618*1031d839SEric Joyner /* reserve a contiguous allocation for the PF's VSI */ 619*1031d839SEric Joyner error = ixl_pf_qmgr_alloc_contiguous(&pf->qmgr, 620*1031d839SEric Joyner max(vsi->num_rx_queues, vsi->num_tx_queues), &pf->qtag); 621*1031d839SEric Joyner if (error) { 622*1031d839SEric Joyner device_printf(dev, "Failed to reserve queues for PF LAN VSI, error %d\n", 623*1031d839SEric Joyner error); 624*1031d839SEric Joyner goto err; 625*1031d839SEric Joyner } 626*1031d839SEric Joyner device_printf(dev, "Allocating %d queues for PF LAN VSI; %d queues active\n", 627*1031d839SEric Joyner pf->qtag.num_allocated, pf->qtag.num_active); 628*1031d839SEric Joyner 629223d846dSEric Joyner /* Limit PHY interrupts to link, autoneg, and modules failure */ 6304294f337SSean Bruno status = i40e_aq_set_phy_int_mask(hw, IXL_DEFAULT_PHY_INT_MASK, 631223d846dSEric Joyner NULL); 6324294f337SSean Bruno if (status) { 6334294f337SSean Bruno device_printf(dev, "i40e_aq_set_phy_mask() failed: err %s," 6344294f337SSean Bruno " aq_err %s\n", i40e_stat_str(hw, status), 6354294f337SSean Bruno i40e_aq_str(hw, hw->aq.asq_last_status)); 636*1031d839SEric Joyner goto err; 637223d846dSEric Joyner } 638b6c8f260SJack F Vogel 639*1031d839SEric Joyner /* Get the bus configuration and set the shared code */ 640cb6b8299SEric Joyner ixl_get_bus_info(pf); 64161ae650dSJack F Vogel 642*1031d839SEric Joyner /* Keep admin queue interrupts active while driver is loaded */ 643*1031d839SEric Joyner if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) { 6446c426059SEric Joyner ixl_configure_intr0_msix(pf); 645cb6b8299SEric Joyner ixl_enable_intr0(hw); 646cb6b8299SEric Joyner } 647cb6b8299SEric Joyner 648cb6b8299SEric Joyner /* Set initial advertised speed sysctl value */ 649ceebc2f3SEric Joyner ixl_set_initial_advertised_speeds(pf); 650cb6b8299SEric Joyner 651fdb6f38aSEric Joyner /* Initialize statistics & add sysctls */ 652fdb6f38aSEric Joyner ixl_add_device_sysctls(pf); 65361ae650dSJack F Vogel ixl_pf_reset_stats(pf); 65461ae650dSJack F Vogel ixl_update_stats_counters(pf); 65561ae650dSJack F Vogel ixl_add_hw_stats(pf); 65661ae650dSJack F Vogel 657*1031d839SEric Joyner hw->phy.get_link_info = true; 658*1031d839SEric Joyner i40e_get_link_status(hw, &pf->link_up); 659*1031d839SEric Joyner ixl_update_link_status(pf); 66061ae650dSJack F Vogel 66156c2c47bSJack F Vogel #ifdef PCI_IOV 6624294f337SSean Bruno ixl_initialize_sriov(pf); 66356c2c47bSJack F Vogel #endif 66456c2c47bSJack F Vogel 665cb6b8299SEric Joyner #ifdef IXL_IW 666cb6b8299SEric Joyner if (hw->func_caps.iwarp && ixl_enable_iwarp) { 667cb6b8299SEric Joyner pf->iw_enabled = (pf->iw_msix > 0) ? true : false; 668cb6b8299SEric Joyner if (pf->iw_enabled) { 669cb6b8299SEric Joyner error = ixl_iw_pf_attach(pf); 670cb6b8299SEric Joyner if (error) { 671cb6b8299SEric Joyner device_printf(dev, 672cb6b8299SEric Joyner "interfacing to iwarp driver failed: %d\n", 673cb6b8299SEric Joyner error); 674*1031d839SEric Joyner goto err; 675ceebc2f3SEric Joyner } else 676ceebc2f3SEric Joyner device_printf(dev, "iWARP ready\n"); 677cb6b8299SEric Joyner } else 678cb6b8299SEric Joyner device_printf(dev, 679cb6b8299SEric Joyner "iwarp disabled on this device (no msix vectors)\n"); 680cb6b8299SEric Joyner } else { 681cb6b8299SEric Joyner pf->iw_enabled = false; 682cb6b8299SEric Joyner device_printf(dev, "The device is not iWARP enabled\n"); 683cb6b8299SEric Joyner } 684cb6b8299SEric Joyner #endif 685cb6b8299SEric Joyner 686*1031d839SEric Joyner INIT_DBG_DEV(dev, "end"); 68761ae650dSJack F Vogel return (0); 68861ae650dSJack F Vogel 689*1031d839SEric Joyner err: 690*1031d839SEric Joyner INIT_DEBUGOUT("end: error %d", error); 691*1031d839SEric Joyner /* ixl_if_detach() is called on error from this */ 69261ae650dSJack F Vogel return (error); 69361ae650dSJack F Vogel } 69461ae650dSJack F Vogel 69561ae650dSJack F Vogel static int 696*1031d839SEric Joyner ixl_if_detach(if_ctx_t ctx) 69761ae650dSJack F Vogel { 698*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 69961ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 700*1031d839SEric Joyner struct i40e_hw *hw = &pf->hw; 701*1031d839SEric Joyner device_t dev = pf->dev; 7026c426059SEric Joyner enum i40e_status_code status; 703cb6b8299SEric Joyner #if defined(PCI_IOV) || defined(IXL_IW) 70456c2c47bSJack F Vogel int error; 70556c2c47bSJack F Vogel #endif 70661ae650dSJack F Vogel 707*1031d839SEric Joyner INIT_DBG_DEV(dev, "begin"); 708cb6b8299SEric Joyner 709cb6b8299SEric Joyner #ifdef IXL_IW 710cb6b8299SEric Joyner if (ixl_enable_iwarp && pf->iw_enabled) { 711cb6b8299SEric Joyner error = ixl_iw_pf_detach(pf); 712cb6b8299SEric Joyner if (error == EBUSY) { 713cb6b8299SEric Joyner device_printf(dev, "iwarp in use; stop it first.\n"); 714cb6b8299SEric Joyner return (error); 715cb6b8299SEric Joyner } 716cb6b8299SEric Joyner } 717cb6b8299SEric Joyner #endif 718*1031d839SEric Joyner #ifdef PCI_IOV 719*1031d839SEric Joyner error = pci_iov_detach(dev); 720*1031d839SEric Joyner if (error != 0) { 721*1031d839SEric Joyner device_printf(dev, "SR-IOV in use; detach first.\n"); 722*1031d839SEric Joyner return (error); 723*1031d839SEric Joyner } 724*1031d839SEric Joyner #endif 725*1031d839SEric Joyner /* Remove all previously allocated media types */ 726*1031d839SEric Joyner ifmedia_removeall(vsi->media); 727cb6b8299SEric Joyner 728*1031d839SEric Joyner /* Shutdown LAN HMC */ 729*1031d839SEric Joyner if (hw->hmc.hmc_obj) { 730*1031d839SEric Joyner status = i40e_shutdown_lan_hmc(hw); 731*1031d839SEric Joyner if (status) 732*1031d839SEric Joyner device_printf(dev, 733*1031d839SEric Joyner "i40e_shutdown_lan_hmc() failed with status %s\n", 734*1031d839SEric Joyner i40e_stat_str(hw, status)); 735*1031d839SEric Joyner } 736*1031d839SEric Joyner 737*1031d839SEric Joyner /* Shutdown admin queue */ 738*1031d839SEric Joyner ixl_disable_intr0(hw); 739*1031d839SEric Joyner status = i40e_shutdown_adminq(hw); 740*1031d839SEric Joyner if (status) 741*1031d839SEric Joyner device_printf(dev, 742*1031d839SEric Joyner "i40e_shutdown_adminq() failed with status %s\n", 743*1031d839SEric Joyner i40e_stat_str(hw, status)); 744*1031d839SEric Joyner 7454294f337SSean Bruno ixl_pf_qmgr_destroy(&pf->qmgr); 74661ae650dSJack F Vogel ixl_free_pci_resources(pf); 747*1031d839SEric Joyner ixl_free_mac_filters(vsi); 748*1031d839SEric Joyner INIT_DBG_DEV(dev, "end"); 74961ae650dSJack F Vogel return (0); 75061ae650dSJack F Vogel } 75161ae650dSJack F Vogel 752*1031d839SEric Joyner /* TODO: Do shutdown-specific stuff here */ 753*1031d839SEric Joyner static int 754*1031d839SEric Joyner ixl_if_shutdown(if_ctx_t ctx) 755*1031d839SEric Joyner { 756*1031d839SEric Joyner int error = 0; 757*1031d839SEric Joyner 758*1031d839SEric Joyner INIT_DEBUGOUT("ixl_if_shutdown: begin"); 759*1031d839SEric Joyner 760*1031d839SEric Joyner /* TODO: Call ixl_if_stop()? */ 761*1031d839SEric Joyner 762*1031d839SEric Joyner /* TODO: Then setup low power mode */ 763*1031d839SEric Joyner 764*1031d839SEric Joyner return (error); 765*1031d839SEric Joyner } 76661ae650dSJack F Vogel 76761ae650dSJack F Vogel static int 768*1031d839SEric Joyner ixl_if_suspend(if_ctx_t ctx) 76961ae650dSJack F Vogel { 770*1031d839SEric Joyner int error = 0; 771*1031d839SEric Joyner 772*1031d839SEric Joyner INIT_DEBUGOUT("ixl_if_suspend: begin"); 773*1031d839SEric Joyner 774*1031d839SEric Joyner /* TODO: Call ixl_if_stop()? */ 775*1031d839SEric Joyner 776*1031d839SEric Joyner /* TODO: Then setup low power mode */ 777*1031d839SEric Joyner 778*1031d839SEric Joyner return (error); 779*1031d839SEric Joyner } 780*1031d839SEric Joyner 781*1031d839SEric Joyner static int 782*1031d839SEric Joyner ixl_if_resume(if_ctx_t ctx) 783*1031d839SEric Joyner { 784*1031d839SEric Joyner struct ifnet *ifp = iflib_get_ifp(ctx); 785*1031d839SEric Joyner 786*1031d839SEric Joyner INIT_DEBUGOUT("ixl_if_resume: begin"); 787*1031d839SEric Joyner 788*1031d839SEric Joyner /* Read & clear wake-up registers */ 789*1031d839SEric Joyner 790*1031d839SEric Joyner /* Required after D3->D0 transition */ 791*1031d839SEric Joyner if (ifp->if_flags & IFF_UP) 792*1031d839SEric Joyner ixl_if_init(ctx); 793*1031d839SEric Joyner 79461ae650dSJack F Vogel return (0); 79561ae650dSJack F Vogel } 79661ae650dSJack F Vogel 797*1031d839SEric Joyner /* Set Report Status queue fields to 0 */ 798*1031d839SEric Joyner static void 799*1031d839SEric Joyner ixl_init_tx_rsqs(struct ixl_vsi *vsi) 800*1031d839SEric Joyner { 801*1031d839SEric Joyner if_softc_ctx_t scctx = vsi->shared; 802*1031d839SEric Joyner struct ixl_tx_queue *tx_que; 803*1031d839SEric Joyner int i, j; 804*1031d839SEric Joyner 805*1031d839SEric Joyner for (i = 0, tx_que = vsi->tx_queues; i < vsi->num_tx_queues; i++, tx_que++) { 806*1031d839SEric Joyner struct tx_ring *txr = &tx_que->txr; 807*1031d839SEric Joyner 808*1031d839SEric Joyner txr->tx_rs_cidx = txr->tx_rs_pidx = txr->tx_cidx_processed = 0; 809*1031d839SEric Joyner 810*1031d839SEric Joyner for (j = 0; j < scctx->isc_ntxd[0]; j++) 811*1031d839SEric Joyner txr->tx_rsq[j] = QIDX_INVALID; 812*1031d839SEric Joyner } 813*1031d839SEric Joyner } 814*1031d839SEric Joyner 815*1031d839SEric Joyner static void 816*1031d839SEric Joyner ixl_init_tx_cidx(struct ixl_vsi *vsi) 817*1031d839SEric Joyner { 818*1031d839SEric Joyner struct ixl_tx_queue *tx_que; 819*1031d839SEric Joyner int i; 820*1031d839SEric Joyner 821*1031d839SEric Joyner for (i = 0, tx_que = vsi->tx_queues; i < vsi->num_tx_queues; i++, tx_que++) { 822*1031d839SEric Joyner struct tx_ring *txr = &tx_que->txr; 823*1031d839SEric Joyner 824*1031d839SEric Joyner txr->tx_cidx_processed = 0; 825*1031d839SEric Joyner } 826*1031d839SEric Joyner } 827*1031d839SEric Joyner 828*1031d839SEric Joyner void 829*1031d839SEric Joyner ixl_if_init(if_ctx_t ctx) 830*1031d839SEric Joyner { 831*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 832*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 833*1031d839SEric Joyner struct i40e_hw *hw = &pf->hw; 834*1031d839SEric Joyner device_t dev = iflib_get_dev(ctx); 835*1031d839SEric Joyner u8 tmpaddr[ETHER_ADDR_LEN]; 836*1031d839SEric Joyner int ret; 837*1031d839SEric Joyner 838*1031d839SEric Joyner /* 839*1031d839SEric Joyner * If the aq is dead here, it probably means something outside of the driver 840*1031d839SEric Joyner * did something to the adapter, like a PF reset. 841*1031d839SEric Joyner * So rebuild the driver's state here if that occurs. 842*1031d839SEric Joyner */ 843*1031d839SEric Joyner if (!i40e_check_asq_alive(&pf->hw)) { 844*1031d839SEric Joyner device_printf(dev, "Admin Queue is down; resetting...\n"); 845*1031d839SEric Joyner ixl_teardown_hw_structs(pf); 846*1031d839SEric Joyner ixl_reset(pf); 847*1031d839SEric Joyner } 848*1031d839SEric Joyner 849*1031d839SEric Joyner /* Get the latest mac address... User might use a LAA */ 850*1031d839SEric Joyner bcopy(IF_LLADDR(vsi->ifp), tmpaddr, ETH_ALEN); 851*1031d839SEric Joyner if (!cmp_etheraddr(hw->mac.addr, tmpaddr) && 852*1031d839SEric Joyner (i40e_validate_mac_addr(tmpaddr) == I40E_SUCCESS)) { 853*1031d839SEric Joyner ixl_del_filter(vsi, hw->mac.addr, IXL_VLAN_ANY); 854*1031d839SEric Joyner bcopy(tmpaddr, hw->mac.addr, ETH_ALEN); 855*1031d839SEric Joyner ret = i40e_aq_mac_address_write(hw, 856*1031d839SEric Joyner I40E_AQC_WRITE_TYPE_LAA_ONLY, 857*1031d839SEric Joyner hw->mac.addr, NULL); 858*1031d839SEric Joyner if (ret) { 859*1031d839SEric Joyner device_printf(dev, "LLA address change failed!!\n"); 860*1031d839SEric Joyner return; 861*1031d839SEric Joyner } 862*1031d839SEric Joyner ixl_add_filter(vsi, hw->mac.addr, IXL_VLAN_ANY); 863*1031d839SEric Joyner } 864*1031d839SEric Joyner 865*1031d839SEric Joyner iflib_set_mac(ctx, hw->mac.addr); 866*1031d839SEric Joyner 867*1031d839SEric Joyner /* Prepare the VSI: rings, hmc contexts, etc... */ 868*1031d839SEric Joyner if (ixl_initialize_vsi(vsi)) { 869*1031d839SEric Joyner device_printf(dev, "initialize vsi failed!!\n"); 870*1031d839SEric Joyner return; 871*1031d839SEric Joyner } 872*1031d839SEric Joyner 873*1031d839SEric Joyner // TODO: Call iflib setup multicast filters here? 874*1031d839SEric Joyner // It's called in ixgbe in D5213 875*1031d839SEric Joyner ixl_if_multi_set(ctx); 876*1031d839SEric Joyner 877*1031d839SEric Joyner /* Set up RSS */ 878*1031d839SEric Joyner ixl_config_rss(pf); 879*1031d839SEric Joyner 880*1031d839SEric Joyner /* Set up MSI/X routing and the ITR settings */ 881*1031d839SEric Joyner if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) { 882*1031d839SEric Joyner ixl_configure_queue_intr_msix(pf); 883*1031d839SEric Joyner ixl_configure_itr(pf); 884*1031d839SEric Joyner } else 885*1031d839SEric Joyner ixl_configure_legacy(pf); 886*1031d839SEric Joyner 887*1031d839SEric Joyner if (vsi->enable_head_writeback) 888*1031d839SEric Joyner ixl_init_tx_cidx(vsi); 889*1031d839SEric Joyner else 890*1031d839SEric Joyner ixl_init_tx_rsqs(vsi); 891*1031d839SEric Joyner 892*1031d839SEric Joyner ixl_enable_rings(vsi); 893*1031d839SEric Joyner 894*1031d839SEric Joyner i40e_aq_set_default_vsi(hw, vsi->seid, NULL); 895*1031d839SEric Joyner 896*1031d839SEric Joyner ixl_reconfigure_filters(vsi); 897*1031d839SEric Joyner 898*1031d839SEric Joyner #ifdef IXL_IW 899*1031d839SEric Joyner if (ixl_enable_iwarp && pf->iw_enabled) { 900*1031d839SEric Joyner ret = ixl_iw_pf_init(pf); 901*1031d839SEric Joyner if (ret) 902*1031d839SEric Joyner device_printf(dev, 903*1031d839SEric Joyner "initialize iwarp failed, code %d\n", ret); 904*1031d839SEric Joyner } 905*1031d839SEric Joyner #endif 906*1031d839SEric Joyner } 907*1031d839SEric Joyner 908*1031d839SEric Joyner void 909*1031d839SEric Joyner ixl_if_stop(if_ctx_t ctx) 910*1031d839SEric Joyner { 911*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 912*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 913*1031d839SEric Joyner 914*1031d839SEric Joyner INIT_DEBUGOUT("ixl_if_stop: begin\n"); 915*1031d839SEric Joyner 916*1031d839SEric Joyner // TODO: This may need to be reworked 917*1031d839SEric Joyner #ifdef IXL_IW 918*1031d839SEric Joyner /* Stop iWARP device */ 919*1031d839SEric Joyner if (ixl_enable_iwarp && pf->iw_enabled) 920*1031d839SEric Joyner ixl_iw_pf_stop(pf); 921*1031d839SEric Joyner #endif 922*1031d839SEric Joyner 923*1031d839SEric Joyner ixl_disable_rings_intr(vsi); 924*1031d839SEric Joyner ixl_disable_rings(vsi); 925*1031d839SEric Joyner } 926*1031d839SEric Joyner 927*1031d839SEric Joyner static int 928*1031d839SEric Joyner ixl_if_msix_intr_assign(if_ctx_t ctx, int msix) 929*1031d839SEric Joyner { 930*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 931*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 932*1031d839SEric Joyner struct ixl_rx_queue *rx_que = vsi->rx_queues; 933*1031d839SEric Joyner struct ixl_tx_queue *tx_que = vsi->tx_queues; 934*1031d839SEric Joyner int err, i, rid, vector = 0; 935*1031d839SEric Joyner char buf[16]; 936*1031d839SEric Joyner 937*1031d839SEric Joyner /* Admin Que must use vector 0*/ 938*1031d839SEric Joyner rid = vector + 1; 939*1031d839SEric Joyner err = iflib_irq_alloc_generic(ctx, &vsi->irq, rid, IFLIB_INTR_ADMIN, 940*1031d839SEric Joyner ixl_msix_adminq, pf, 0, "aq"); 941*1031d839SEric Joyner if (err) { 942*1031d839SEric Joyner iflib_irq_free(ctx, &vsi->irq); 943*1031d839SEric Joyner device_printf(iflib_get_dev(ctx), 944*1031d839SEric Joyner "Failed to register Admin que handler"); 945*1031d839SEric Joyner return (err); 946*1031d839SEric Joyner } 947*1031d839SEric Joyner // TODO: Re-enable this at some point 948*1031d839SEric Joyner // iflib_softirq_alloc_generic(ctx, rid, IFLIB_INTR_IOV, pf, 0, "ixl_iov"); 949*1031d839SEric Joyner 950*1031d839SEric Joyner /* Now set up the stations */ 951*1031d839SEric Joyner for (i = 0, vector = 1; i < vsi->num_rx_queues; i++, vector++, rx_que++) { 952*1031d839SEric Joyner rid = vector + 1; 953*1031d839SEric Joyner 954*1031d839SEric Joyner snprintf(buf, sizeof(buf), "rxq%d", i); 955*1031d839SEric Joyner err = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid, 956*1031d839SEric Joyner IFLIB_INTR_RX, ixl_msix_que, rx_que, rx_que->rxr.me, buf); 957*1031d839SEric Joyner /* XXX: Does the driver work as expected if there are fewer num_rx_queues than 958*1031d839SEric Joyner * what's expected in the iflib context? */ 959*1031d839SEric Joyner if (err) { 960*1031d839SEric Joyner device_printf(iflib_get_dev(ctx), 961*1031d839SEric Joyner "Failed to allocate q int %d err: %d", i, err); 962*1031d839SEric Joyner vsi->num_rx_queues = i + 1; 963*1031d839SEric Joyner goto fail; 964*1031d839SEric Joyner } 965*1031d839SEric Joyner rx_que->msix = vector; 966*1031d839SEric Joyner } 967*1031d839SEric Joyner 968*1031d839SEric Joyner bzero(buf, sizeof(buf)); 969*1031d839SEric Joyner 970*1031d839SEric Joyner for (i = 0; i < vsi->num_tx_queues; i++, tx_que++) { 971*1031d839SEric Joyner snprintf(buf, sizeof(buf), "txq%d", i); 972*1031d839SEric Joyner iflib_softirq_alloc_generic(ctx, 973*1031d839SEric Joyner &vsi->rx_queues[i % vsi->num_rx_queues].que_irq, 974*1031d839SEric Joyner IFLIB_INTR_TX, tx_que, tx_que->txr.me, buf); 975*1031d839SEric Joyner 976*1031d839SEric Joyner /* TODO: Maybe call a strategy function for this to figure out which 977*1031d839SEric Joyner * interrupts to map Tx queues to. I don't know if there's an immediately 978*1031d839SEric Joyner * better way than this other than a user-supplied map, though. */ 979*1031d839SEric Joyner tx_que->msix = (i % vsi->num_rx_queues) + 1; 980*1031d839SEric Joyner } 981*1031d839SEric Joyner 982*1031d839SEric Joyner return (0); 983*1031d839SEric Joyner fail: 984*1031d839SEric Joyner iflib_irq_free(ctx, &vsi->irq); 985*1031d839SEric Joyner rx_que = vsi->rx_queues; 986*1031d839SEric Joyner for (int i = 0; i < vsi->num_rx_queues; i++, rx_que++) 987*1031d839SEric Joyner iflib_irq_free(ctx, &rx_que->que_irq); 988*1031d839SEric Joyner return (err); 989*1031d839SEric Joyner } 990*1031d839SEric Joyner 991*1031d839SEric Joyner /* 992*1031d839SEric Joyner * Enable all interrupts 993*1031d839SEric Joyner * 994*1031d839SEric Joyner * Called in: 995*1031d839SEric Joyner * iflib_init_locked, after ixl_if_init() 996*1031d839SEric Joyner */ 997*1031d839SEric Joyner static void 998*1031d839SEric Joyner ixl_if_enable_intr(if_ctx_t ctx) 999*1031d839SEric Joyner { 1000*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1001*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1002*1031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 1003*1031d839SEric Joyner struct ixl_rx_queue *que = vsi->rx_queues; 1004*1031d839SEric Joyner 1005*1031d839SEric Joyner ixl_enable_intr0(hw); 1006*1031d839SEric Joyner /* Enable queue interrupts */ 1007*1031d839SEric Joyner for (int i = 0; i < vsi->num_rx_queues; i++, que++) 1008*1031d839SEric Joyner /* TODO: Queue index parameter is probably wrong */ 1009*1031d839SEric Joyner ixl_enable_queue(hw, que->rxr.me); 1010*1031d839SEric Joyner } 1011*1031d839SEric Joyner 1012*1031d839SEric Joyner /* 1013*1031d839SEric Joyner * Disable queue interrupts 1014*1031d839SEric Joyner * 1015*1031d839SEric Joyner * Other interrupt causes need to remain active. 1016*1031d839SEric Joyner */ 1017*1031d839SEric Joyner static void 1018*1031d839SEric Joyner ixl_if_disable_intr(if_ctx_t ctx) 1019*1031d839SEric Joyner { 1020*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1021*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1022*1031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 1023*1031d839SEric Joyner struct ixl_rx_queue *rx_que = vsi->rx_queues; 1024*1031d839SEric Joyner 1025*1031d839SEric Joyner if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) { 1026*1031d839SEric Joyner for (int i = 0; i < vsi->num_rx_queues; i++, rx_que++) 1027*1031d839SEric Joyner ixl_disable_queue(hw, rx_que->msix - 1); 1028*1031d839SEric Joyner } else { 1029*1031d839SEric Joyner // Set PFINT_LNKLST0 FIRSTQ_INDX to 0x7FF 1030*1031d839SEric Joyner // stops queues from triggering interrupts 1031*1031d839SEric Joyner wr32(hw, I40E_PFINT_LNKLST0, 0x7FF); 1032*1031d839SEric Joyner } 1033*1031d839SEric Joyner } 1034*1031d839SEric Joyner 1035*1031d839SEric Joyner static int 1036*1031d839SEric Joyner ixl_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid) 1037*1031d839SEric Joyner { 1038*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1039*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1040*1031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 1041*1031d839SEric Joyner struct ixl_rx_queue *rx_que = &vsi->rx_queues[rxqid]; 1042*1031d839SEric Joyner 1043*1031d839SEric Joyner ixl_enable_queue(hw, rx_que->msix - 1); 1044*1031d839SEric Joyner return (0); 1045*1031d839SEric Joyner } 1046*1031d839SEric Joyner 1047*1031d839SEric Joyner static int 1048*1031d839SEric Joyner ixl_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid) 1049*1031d839SEric Joyner { 1050*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1051*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1052*1031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 1053*1031d839SEric Joyner struct ixl_tx_queue *tx_que = &vsi->tx_queues[txqid]; 1054*1031d839SEric Joyner 1055*1031d839SEric Joyner ixl_enable_queue(hw, tx_que->msix - 1); 1056*1031d839SEric Joyner 1057*1031d839SEric Joyner return (0); 1058*1031d839SEric Joyner } 1059*1031d839SEric Joyner 1060*1031d839SEric Joyner static int 1061*1031d839SEric Joyner ixl_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs, int ntxqsets) 1062*1031d839SEric Joyner { 1063*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1064*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1065*1031d839SEric Joyner if_softc_ctx_t scctx = vsi->shared; 1066*1031d839SEric Joyner struct ixl_tx_queue *que; 1067*1031d839SEric Joyner // int i; 1068*1031d839SEric Joyner int i, j, error = 0; 1069*1031d839SEric Joyner 1070*1031d839SEric Joyner MPASS(vsi->num_tx_queues > 0); 1071*1031d839SEric Joyner MPASS(ntxqs == 1); 1072*1031d839SEric Joyner MPASS(vsi->num_tx_queues == ntxqsets); 1073*1031d839SEric Joyner 1074*1031d839SEric Joyner /* Allocate queue structure memory */ 1075*1031d839SEric Joyner if (!(vsi->tx_queues = 1076*1031d839SEric Joyner (struct ixl_tx_queue *) malloc(sizeof(struct ixl_tx_queue) *ntxqsets, M_IXL, M_NOWAIT | M_ZERO))) { 1077*1031d839SEric Joyner device_printf(iflib_get_dev(ctx), "Unable to allocate TX ring memory\n"); 1078*1031d839SEric Joyner return (ENOMEM); 1079*1031d839SEric Joyner } 1080*1031d839SEric Joyner 1081*1031d839SEric Joyner for (i = 0, que = vsi->tx_queues; i < ntxqsets; i++, que++) { 1082*1031d839SEric Joyner struct tx_ring *txr = &que->txr; 1083*1031d839SEric Joyner 1084*1031d839SEric Joyner txr->me = i; 1085*1031d839SEric Joyner que->vsi = vsi; 1086*1031d839SEric Joyner 1087*1031d839SEric Joyner if (!vsi->enable_head_writeback) { 1088*1031d839SEric Joyner /* Allocate report status array */ 1089*1031d839SEric Joyner if (!(txr->tx_rsq = malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_IXL, M_NOWAIT))) { 1090*1031d839SEric Joyner device_printf(iflib_get_dev(ctx), "failed to allocate tx_rsq memory\n"); 1091*1031d839SEric Joyner error = ENOMEM; 1092*1031d839SEric Joyner goto fail; 1093*1031d839SEric Joyner } 1094*1031d839SEric Joyner /* Init report status array */ 1095*1031d839SEric Joyner for (j = 0; j < scctx->isc_ntxd[0]; j++) 1096*1031d839SEric Joyner txr->tx_rsq[j] = QIDX_INVALID; 1097*1031d839SEric Joyner } 1098*1031d839SEric Joyner /* get the virtual and physical address of the hardware queues */ 1099*1031d839SEric Joyner txr->tail = I40E_QTX_TAIL(txr->me); 1100*1031d839SEric Joyner txr->tx_base = (struct i40e_tx_desc *)vaddrs[i * ntxqs]; 1101*1031d839SEric Joyner txr->tx_paddr = paddrs[i * ntxqs]; 1102*1031d839SEric Joyner txr->que = que; 1103*1031d839SEric Joyner } 1104*1031d839SEric Joyner 1105*1031d839SEric Joyner return (0); 1106*1031d839SEric Joyner fail: 1107*1031d839SEric Joyner ixl_if_queues_free(ctx); 1108*1031d839SEric Joyner return (error); 1109*1031d839SEric Joyner } 1110*1031d839SEric Joyner 1111*1031d839SEric Joyner static int 1112*1031d839SEric Joyner ixl_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nrxqs, int nrxqsets) 1113*1031d839SEric Joyner { 1114*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1115*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1116*1031d839SEric Joyner struct ixl_rx_queue *que; 1117*1031d839SEric Joyner int i, error = 0; 1118*1031d839SEric Joyner 1119*1031d839SEric Joyner MPASS(vsi->num_rx_queues > 0); 1120*1031d839SEric Joyner MPASS(nrxqs == 1); 1121*1031d839SEric Joyner MPASS(vsi->num_rx_queues == nrxqsets); 1122*1031d839SEric Joyner 1123*1031d839SEric Joyner /* Allocate queue structure memory */ 1124*1031d839SEric Joyner if (!(vsi->rx_queues = 1125*1031d839SEric Joyner (struct ixl_rx_queue *) malloc(sizeof(struct ixl_rx_queue) * 1126*1031d839SEric Joyner nrxqsets, M_IXL, M_NOWAIT | M_ZERO))) { 1127*1031d839SEric Joyner device_printf(iflib_get_dev(ctx), "Unable to allocate RX ring memory\n"); 1128*1031d839SEric Joyner error = ENOMEM; 1129*1031d839SEric Joyner goto fail; 1130*1031d839SEric Joyner } 1131*1031d839SEric Joyner 1132*1031d839SEric Joyner for (i = 0, que = vsi->rx_queues; i < nrxqsets; i++, que++) { 1133*1031d839SEric Joyner struct rx_ring *rxr = &que->rxr; 1134*1031d839SEric Joyner 1135*1031d839SEric Joyner rxr->me = i; 1136*1031d839SEric Joyner que->vsi = vsi; 1137*1031d839SEric Joyner 1138*1031d839SEric Joyner /* get the virtual and physical address of the hardware queues */ 1139*1031d839SEric Joyner rxr->tail = I40E_QRX_TAIL(rxr->me); 1140*1031d839SEric Joyner rxr->rx_base = (union i40e_rx_desc *)vaddrs[i * nrxqs]; 1141*1031d839SEric Joyner rxr->rx_paddr = paddrs[i * nrxqs]; 1142*1031d839SEric Joyner rxr->que = que; 1143*1031d839SEric Joyner } 1144*1031d839SEric Joyner 1145*1031d839SEric Joyner return (0); 1146*1031d839SEric Joyner fail: 1147*1031d839SEric Joyner ixl_if_queues_free(ctx); 1148*1031d839SEric Joyner return (error); 1149*1031d839SEric Joyner } 1150*1031d839SEric Joyner 1151*1031d839SEric Joyner static void 1152*1031d839SEric Joyner ixl_if_queues_free(if_ctx_t ctx) 1153*1031d839SEric Joyner { 1154*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1155*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1156*1031d839SEric Joyner 1157*1031d839SEric Joyner if (vsi->enable_head_writeback) { 1158*1031d839SEric Joyner struct ixl_tx_queue *que; 1159*1031d839SEric Joyner int i = 0; 1160*1031d839SEric Joyner 1161*1031d839SEric Joyner for (i = 0, que = vsi->tx_queues; i < vsi->num_tx_queues; i++, que++) { 1162*1031d839SEric Joyner struct tx_ring *txr = &que->txr; 1163*1031d839SEric Joyner if (txr->tx_rsq != NULL) { 1164*1031d839SEric Joyner free(txr->tx_rsq, M_IXL); 1165*1031d839SEric Joyner txr->tx_rsq = NULL; 1166*1031d839SEric Joyner } 1167*1031d839SEric Joyner } 1168*1031d839SEric Joyner } 1169*1031d839SEric Joyner 1170*1031d839SEric Joyner if (vsi->tx_queues != NULL) { 1171*1031d839SEric Joyner free(vsi->tx_queues, M_IXL); 1172*1031d839SEric Joyner vsi->tx_queues = NULL; 1173*1031d839SEric Joyner } 1174*1031d839SEric Joyner if (vsi->rx_queues != NULL) { 1175*1031d839SEric Joyner free(vsi->rx_queues, M_IXL); 1176*1031d839SEric Joyner vsi->rx_queues = NULL; 1177*1031d839SEric Joyner } 1178*1031d839SEric Joyner } 1179*1031d839SEric Joyner 1180*1031d839SEric Joyner void 1181*1031d839SEric Joyner ixl_update_link_status(struct ixl_pf *pf) 1182*1031d839SEric Joyner { 1183*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1184*1031d839SEric Joyner u64 baudrate; 1185*1031d839SEric Joyner 1186*1031d839SEric Joyner if (pf->link_up) { 1187*1031d839SEric Joyner if (vsi->link_active == FALSE) { 1188*1031d839SEric Joyner vsi->link_active = TRUE; 1189*1031d839SEric Joyner baudrate = ixl_max_aq_speed_to_value(pf->link_speed); 1190*1031d839SEric Joyner iflib_link_state_change(vsi->ctx, LINK_STATE_UP, baudrate); 1191*1031d839SEric Joyner ixl_link_up_msg(pf); 1192*1031d839SEric Joyner #ifdef PCI_IOV 1193*1031d839SEric Joyner ixl_broadcast_link_state(pf); 1194*1031d839SEric Joyner #endif 1195*1031d839SEric Joyner 1196*1031d839SEric Joyner } 1197*1031d839SEric Joyner } else { /* Link down */ 1198*1031d839SEric Joyner if (vsi->link_active == TRUE) { 1199*1031d839SEric Joyner vsi->link_active = FALSE; 1200*1031d839SEric Joyner iflib_link_state_change(vsi->ctx, LINK_STATE_DOWN, 0); 1201*1031d839SEric Joyner #ifdef PCI_IOV 1202*1031d839SEric Joyner ixl_broadcast_link_state(pf); 1203*1031d839SEric Joyner #endif 1204*1031d839SEric Joyner } 1205*1031d839SEric Joyner } 1206*1031d839SEric Joyner } 1207*1031d839SEric Joyner 1208*1031d839SEric Joyner static int 1209*1031d839SEric Joyner ixl_process_adminq(struct ixl_pf *pf, u16 *pending) 1210*1031d839SEric Joyner { 1211*1031d839SEric Joyner enum i40e_status_code status = I40E_SUCCESS; 1212*1031d839SEric Joyner struct i40e_arq_event_info event; 1213*1031d839SEric Joyner struct i40e_hw *hw = &pf->hw; 1214*1031d839SEric Joyner device_t dev = pf->dev; 1215*1031d839SEric Joyner u16 opcode; 1216*1031d839SEric Joyner u32 loop = 0, reg; 1217*1031d839SEric Joyner 1218*1031d839SEric Joyner event.buf_len = IXL_AQ_BUF_SZ; 1219*1031d839SEric Joyner event.msg_buf = malloc(event.buf_len, M_IXL, M_NOWAIT | M_ZERO); 1220*1031d839SEric Joyner if (!event.msg_buf) { 1221*1031d839SEric Joyner device_printf(dev, "%s: Unable to allocate memory for Admin" 1222*1031d839SEric Joyner " Queue event!\n", __func__); 1223*1031d839SEric Joyner return (ENOMEM); 1224*1031d839SEric Joyner } 1225*1031d839SEric Joyner 1226*1031d839SEric Joyner /* clean and process any events */ 1227*1031d839SEric Joyner do { 1228*1031d839SEric Joyner status = i40e_clean_arq_element(hw, &event, pending); 1229*1031d839SEric Joyner if (status) 1230*1031d839SEric Joyner break; 1231*1031d839SEric Joyner opcode = LE16_TO_CPU(event.desc.opcode); 1232*1031d839SEric Joyner ixl_dbg(pf, IXL_DBG_AQ, 1233*1031d839SEric Joyner "Admin Queue event: %#06x\n", opcode); 1234*1031d839SEric Joyner switch (opcode) { 1235*1031d839SEric Joyner case i40e_aqc_opc_get_link_status: 1236*1031d839SEric Joyner ixl_link_event(pf, &event); 1237*1031d839SEric Joyner break; 1238*1031d839SEric Joyner case i40e_aqc_opc_send_msg_to_pf: 1239*1031d839SEric Joyner #ifdef PCI_IOV 1240*1031d839SEric Joyner ixl_handle_vf_msg(pf, &event); 1241*1031d839SEric Joyner #endif 1242*1031d839SEric Joyner break; 1243*1031d839SEric Joyner /* 1244*1031d839SEric Joyner * This should only occur on no-drop queues, which 1245*1031d839SEric Joyner * aren't currently configured. 1246*1031d839SEric Joyner */ 1247*1031d839SEric Joyner case i40e_aqc_opc_event_lan_overflow: 1248*1031d839SEric Joyner device_printf(dev, "LAN overflow event\n"); 1249*1031d839SEric Joyner break; 1250*1031d839SEric Joyner default: 1251*1031d839SEric Joyner break; 1252*1031d839SEric Joyner } 1253*1031d839SEric Joyner } while (*pending && (loop++ < IXL_ADM_LIMIT)); 1254*1031d839SEric Joyner 1255*1031d839SEric Joyner free(event.msg_buf, M_IXL); 1256*1031d839SEric Joyner 1257*1031d839SEric Joyner /* Re-enable admin queue interrupt cause */ 1258*1031d839SEric Joyner reg = rd32(hw, I40E_PFINT_ICR0_ENA); 1259*1031d839SEric Joyner reg |= I40E_PFINT_ICR0_ENA_ADMINQ_MASK; 1260*1031d839SEric Joyner wr32(hw, I40E_PFINT_ICR0_ENA, reg); 1261*1031d839SEric Joyner 1262*1031d839SEric Joyner return (status); 1263*1031d839SEric Joyner } 1264*1031d839SEric Joyner 1265*1031d839SEric Joyner static void 1266*1031d839SEric Joyner ixl_if_update_admin_status(if_ctx_t ctx) 1267*1031d839SEric Joyner { 1268*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1269*1031d839SEric Joyner struct i40e_hw *hw = &pf->hw; 1270*1031d839SEric Joyner u16 pending; 1271*1031d839SEric Joyner 1272*1031d839SEric Joyner if (pf->state & IXL_PF_STATE_ADAPTER_RESETTING) 1273*1031d839SEric Joyner ixl_handle_empr_reset(pf); 1274*1031d839SEric Joyner 1275*1031d839SEric Joyner if (pf->state & IXL_PF_STATE_MDD_PENDING) 1276*1031d839SEric Joyner ixl_handle_mdd_event(pf); 1277*1031d839SEric Joyner 1278*1031d839SEric Joyner #ifdef PCI_IOV 1279*1031d839SEric Joyner if (pf->state & IXL_PF_STATE_VF_RESET_REQ) 1280*1031d839SEric Joyner iflib_iov_intr_deferred(ctx); 1281*1031d839SEric Joyner #endif 1282*1031d839SEric Joyner 1283*1031d839SEric Joyner ixl_process_adminq(pf, &pending); 1284*1031d839SEric Joyner ixl_update_link_status(pf); 1285*1031d839SEric Joyner 1286*1031d839SEric Joyner /* 1287*1031d839SEric Joyner * If there are still messages to process, reschedule ourselves. 1288*1031d839SEric Joyner * Otherwise, re-enable our interrupt and go to sleep. 1289*1031d839SEric Joyner */ 1290*1031d839SEric Joyner if (pending > 0) 1291*1031d839SEric Joyner iflib_admin_intr_deferred(ctx); 1292*1031d839SEric Joyner else 1293*1031d839SEric Joyner ixl_enable_intr0(hw); 1294*1031d839SEric Joyner } 1295*1031d839SEric Joyner 1296*1031d839SEric Joyner static void 1297*1031d839SEric Joyner ixl_if_multi_set(if_ctx_t ctx) 1298*1031d839SEric Joyner { 1299*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1300*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1301*1031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 1302*1031d839SEric Joyner int mcnt = 0, flags; 1303*1031d839SEric Joyner 1304*1031d839SEric Joyner IOCTL_DEBUGOUT("ixl_if_multi_set: begin"); 1305*1031d839SEric Joyner 1306*1031d839SEric Joyner mcnt = if_multiaddr_count(iflib_get_ifp(ctx), MAX_MULTICAST_ADDR); 1307*1031d839SEric Joyner /* delete existing MC filters */ 1308*1031d839SEric Joyner ixl_del_multi(vsi); 1309*1031d839SEric Joyner 1310*1031d839SEric Joyner if (__predict_false(mcnt == MAX_MULTICAST_ADDR)) { 1311*1031d839SEric Joyner i40e_aq_set_vsi_multicast_promiscuous(hw, 1312*1031d839SEric Joyner vsi->seid, TRUE, NULL); 1313*1031d839SEric Joyner return; 1314*1031d839SEric Joyner } 1315*1031d839SEric Joyner /* (re-)install filters for all mcast addresses */ 1316*1031d839SEric Joyner mcnt = if_multi_apply(iflib_get_ifp(ctx), ixl_mc_filter_apply, vsi); 1317*1031d839SEric Joyner 1318*1031d839SEric Joyner if (mcnt > 0) { 1319*1031d839SEric Joyner flags = (IXL_FILTER_ADD | IXL_FILTER_USED | IXL_FILTER_MC); 1320*1031d839SEric Joyner ixl_add_hw_filters(vsi, flags, mcnt); 1321*1031d839SEric Joyner } 1322*1031d839SEric Joyner 1323*1031d839SEric Joyner IOCTL_DEBUGOUT("ixl_if_multi_set: end"); 1324*1031d839SEric Joyner } 1325*1031d839SEric Joyner 1326*1031d839SEric Joyner static int 1327*1031d839SEric Joyner ixl_if_mtu_set(if_ctx_t ctx, uint32_t mtu) 1328*1031d839SEric Joyner { 1329*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1330*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1331*1031d839SEric Joyner 1332*1031d839SEric Joyner IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)"); 1333*1031d839SEric Joyner if (mtu > IXL_MAX_FRAME - ETHER_HDR_LEN - ETHER_CRC_LEN - 1334*1031d839SEric Joyner ETHER_VLAN_ENCAP_LEN) 1335*1031d839SEric Joyner return (EINVAL); 1336*1031d839SEric Joyner 1337*1031d839SEric Joyner vsi->shared->isc_max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + 1338*1031d839SEric Joyner ETHER_VLAN_ENCAP_LEN; 1339*1031d839SEric Joyner 1340*1031d839SEric Joyner return (0); 1341*1031d839SEric Joyner } 1342*1031d839SEric Joyner 1343*1031d839SEric Joyner static void 1344*1031d839SEric Joyner ixl_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr) 1345*1031d839SEric Joyner { 1346*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1347*1031d839SEric Joyner struct i40e_hw *hw = &pf->hw; 1348*1031d839SEric Joyner 1349*1031d839SEric Joyner INIT_DEBUGOUT("ixl_media_status: begin"); 1350*1031d839SEric Joyner 1351*1031d839SEric Joyner ifmr->ifm_status = IFM_AVALID; 1352*1031d839SEric Joyner ifmr->ifm_active = IFM_ETHER; 1353*1031d839SEric Joyner 1354*1031d839SEric Joyner if (!pf->link_up) { 1355*1031d839SEric Joyner return; 1356*1031d839SEric Joyner } 1357*1031d839SEric Joyner 1358*1031d839SEric Joyner ifmr->ifm_status |= IFM_ACTIVE; 1359*1031d839SEric Joyner /* Hardware is always full-duplex */ 1360*1031d839SEric Joyner ifmr->ifm_active |= IFM_FDX; 1361*1031d839SEric Joyner 1362*1031d839SEric Joyner switch (hw->phy.link_info.phy_type) { 1363*1031d839SEric Joyner /* 100 M */ 1364*1031d839SEric Joyner case I40E_PHY_TYPE_100BASE_TX: 1365*1031d839SEric Joyner ifmr->ifm_active |= IFM_100_TX; 1366*1031d839SEric Joyner break; 1367*1031d839SEric Joyner /* 1 G */ 1368*1031d839SEric Joyner case I40E_PHY_TYPE_1000BASE_T: 1369*1031d839SEric Joyner ifmr->ifm_active |= IFM_1000_T; 1370*1031d839SEric Joyner break; 1371*1031d839SEric Joyner case I40E_PHY_TYPE_1000BASE_SX: 1372*1031d839SEric Joyner ifmr->ifm_active |= IFM_1000_SX; 1373*1031d839SEric Joyner break; 1374*1031d839SEric Joyner case I40E_PHY_TYPE_1000BASE_LX: 1375*1031d839SEric Joyner ifmr->ifm_active |= IFM_1000_LX; 1376*1031d839SEric Joyner break; 1377*1031d839SEric Joyner case I40E_PHY_TYPE_1000BASE_T_OPTICAL: 1378*1031d839SEric Joyner ifmr->ifm_active |= IFM_1000_T; 1379*1031d839SEric Joyner break; 1380*1031d839SEric Joyner /* 10 G */ 1381*1031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_SFPP_CU: 1382*1031d839SEric Joyner ifmr->ifm_active |= IFM_10G_TWINAX; 1383*1031d839SEric Joyner break; 1384*1031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_SR: 1385*1031d839SEric Joyner ifmr->ifm_active |= IFM_10G_SR; 1386*1031d839SEric Joyner break; 1387*1031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_LR: 1388*1031d839SEric Joyner ifmr->ifm_active |= IFM_10G_LR; 1389*1031d839SEric Joyner break; 1390*1031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_T: 1391*1031d839SEric Joyner ifmr->ifm_active |= IFM_10G_T; 1392*1031d839SEric Joyner break; 1393*1031d839SEric Joyner case I40E_PHY_TYPE_XAUI: 1394*1031d839SEric Joyner case I40E_PHY_TYPE_XFI: 1395*1031d839SEric Joyner ifmr->ifm_active |= IFM_10G_TWINAX; 1396*1031d839SEric Joyner break; 1397*1031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_AOC: 1398*1031d839SEric Joyner ifmr->ifm_active |= IFM_10G_AOC; 1399*1031d839SEric Joyner break; 1400*1031d839SEric Joyner /* 25 G */ 1401*1031d839SEric Joyner case I40E_PHY_TYPE_25GBASE_KR: 1402*1031d839SEric Joyner ifmr->ifm_active |= IFM_25G_KR; 1403*1031d839SEric Joyner break; 1404*1031d839SEric Joyner case I40E_PHY_TYPE_25GBASE_CR: 1405*1031d839SEric Joyner ifmr->ifm_active |= IFM_25G_CR; 1406*1031d839SEric Joyner break; 1407*1031d839SEric Joyner case I40E_PHY_TYPE_25GBASE_SR: 1408*1031d839SEric Joyner ifmr->ifm_active |= IFM_25G_SR; 1409*1031d839SEric Joyner break; 1410*1031d839SEric Joyner case I40E_PHY_TYPE_25GBASE_LR: 1411*1031d839SEric Joyner ifmr->ifm_active |= IFM_25G_LR; 1412*1031d839SEric Joyner break; 1413*1031d839SEric Joyner case I40E_PHY_TYPE_25GBASE_AOC: 1414*1031d839SEric Joyner ifmr->ifm_active |= IFM_25G_AOC; 1415*1031d839SEric Joyner break; 1416*1031d839SEric Joyner case I40E_PHY_TYPE_25GBASE_ACC: 1417*1031d839SEric Joyner ifmr->ifm_active |= IFM_25G_ACC; 1418*1031d839SEric Joyner break; 1419*1031d839SEric Joyner /* 40 G */ 1420*1031d839SEric Joyner case I40E_PHY_TYPE_40GBASE_CR4: 1421*1031d839SEric Joyner case I40E_PHY_TYPE_40GBASE_CR4_CU: 1422*1031d839SEric Joyner ifmr->ifm_active |= IFM_40G_CR4; 1423*1031d839SEric Joyner break; 1424*1031d839SEric Joyner case I40E_PHY_TYPE_40GBASE_SR4: 1425*1031d839SEric Joyner ifmr->ifm_active |= IFM_40G_SR4; 1426*1031d839SEric Joyner break; 1427*1031d839SEric Joyner case I40E_PHY_TYPE_40GBASE_LR4: 1428*1031d839SEric Joyner ifmr->ifm_active |= IFM_40G_LR4; 1429*1031d839SEric Joyner break; 1430*1031d839SEric Joyner case I40E_PHY_TYPE_XLAUI: 1431*1031d839SEric Joyner ifmr->ifm_active |= IFM_OTHER; 1432*1031d839SEric Joyner break; 1433*1031d839SEric Joyner case I40E_PHY_TYPE_1000BASE_KX: 1434*1031d839SEric Joyner ifmr->ifm_active |= IFM_1000_KX; 1435*1031d839SEric Joyner break; 1436*1031d839SEric Joyner case I40E_PHY_TYPE_SGMII: 1437*1031d839SEric Joyner ifmr->ifm_active |= IFM_1000_SGMII; 1438*1031d839SEric Joyner break; 1439*1031d839SEric Joyner /* ERJ: What's the difference between these? */ 1440*1031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_CR1_CU: 1441*1031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_CR1: 1442*1031d839SEric Joyner ifmr->ifm_active |= IFM_10G_CR1; 1443*1031d839SEric Joyner break; 1444*1031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_KX4: 1445*1031d839SEric Joyner ifmr->ifm_active |= IFM_10G_KX4; 1446*1031d839SEric Joyner break; 1447*1031d839SEric Joyner case I40E_PHY_TYPE_10GBASE_KR: 1448*1031d839SEric Joyner ifmr->ifm_active |= IFM_10G_KR; 1449*1031d839SEric Joyner break; 1450*1031d839SEric Joyner case I40E_PHY_TYPE_SFI: 1451*1031d839SEric Joyner ifmr->ifm_active |= IFM_10G_SFI; 1452*1031d839SEric Joyner break; 1453*1031d839SEric Joyner /* Our single 20G media type */ 1454*1031d839SEric Joyner case I40E_PHY_TYPE_20GBASE_KR2: 1455*1031d839SEric Joyner ifmr->ifm_active |= IFM_20G_KR2; 1456*1031d839SEric Joyner break; 1457*1031d839SEric Joyner case I40E_PHY_TYPE_40GBASE_KR4: 1458*1031d839SEric Joyner ifmr->ifm_active |= IFM_40G_KR4; 1459*1031d839SEric Joyner break; 1460*1031d839SEric Joyner case I40E_PHY_TYPE_XLPPI: 1461*1031d839SEric Joyner case I40E_PHY_TYPE_40GBASE_AOC: 1462*1031d839SEric Joyner ifmr->ifm_active |= IFM_40G_XLPPI; 1463*1031d839SEric Joyner break; 1464*1031d839SEric Joyner /* Unknown to driver */ 1465*1031d839SEric Joyner default: 1466*1031d839SEric Joyner ifmr->ifm_active |= IFM_UNKNOWN; 1467*1031d839SEric Joyner break; 1468*1031d839SEric Joyner } 1469*1031d839SEric Joyner /* Report flow control status as well */ 1470*1031d839SEric Joyner if (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX) 1471*1031d839SEric Joyner ifmr->ifm_active |= IFM_ETH_TXPAUSE; 1472*1031d839SEric Joyner if (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX) 1473*1031d839SEric Joyner ifmr->ifm_active |= IFM_ETH_RXPAUSE; 1474*1031d839SEric Joyner } 1475*1031d839SEric Joyner 1476*1031d839SEric Joyner static int 1477*1031d839SEric Joyner ixl_if_media_change(if_ctx_t ctx) 1478*1031d839SEric Joyner { 1479*1031d839SEric Joyner struct ifmedia *ifm = iflib_get_media(ctx); 1480*1031d839SEric Joyner 1481*1031d839SEric Joyner INIT_DEBUGOUT("ixl_media_change: begin"); 1482*1031d839SEric Joyner 1483*1031d839SEric Joyner if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 1484*1031d839SEric Joyner return (EINVAL); 1485*1031d839SEric Joyner 1486*1031d839SEric Joyner if_printf(iflib_get_ifp(ctx), "Media change is not supported.\n"); 1487*1031d839SEric Joyner return (ENODEV); 1488*1031d839SEric Joyner } 1489*1031d839SEric Joyner 1490*1031d839SEric Joyner static int 1491*1031d839SEric Joyner ixl_if_promisc_set(if_ctx_t ctx, int flags) 1492*1031d839SEric Joyner { 1493*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1494*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1495*1031d839SEric Joyner struct ifnet *ifp = iflib_get_ifp(ctx); 1496*1031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 1497*1031d839SEric Joyner int err; 1498*1031d839SEric Joyner bool uni = FALSE, multi = FALSE; 1499*1031d839SEric Joyner 1500*1031d839SEric Joyner if (flags & IFF_PROMISC) 1501*1031d839SEric Joyner uni = multi = TRUE; 1502*1031d839SEric Joyner else if (flags & IFF_ALLMULTI || 1503*1031d839SEric Joyner if_multiaddr_count(ifp, MAX_MULTICAST_ADDR) == MAX_MULTICAST_ADDR) 1504*1031d839SEric Joyner multi = TRUE; 1505*1031d839SEric Joyner 1506*1031d839SEric Joyner err = i40e_aq_set_vsi_unicast_promiscuous(hw, 1507*1031d839SEric Joyner vsi->seid, uni, NULL, true); 1508*1031d839SEric Joyner if (err) 1509*1031d839SEric Joyner return (err); 1510*1031d839SEric Joyner err = i40e_aq_set_vsi_multicast_promiscuous(hw, 1511*1031d839SEric Joyner vsi->seid, multi, NULL); 1512*1031d839SEric Joyner return (err); 1513*1031d839SEric Joyner } 1514*1031d839SEric Joyner 1515*1031d839SEric Joyner static void 1516*1031d839SEric Joyner ixl_if_timer(if_ctx_t ctx, uint16_t qid) 1517*1031d839SEric Joyner { 1518*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1519*1031d839SEric Joyner //struct i40e_hw *hw = &pf->hw; 1520*1031d839SEric Joyner //struct ixl_tx_queue *que = &vsi->tx_queues[qid]; 1521*1031d839SEric Joyner #if 0 1522*1031d839SEric Joyner u32 mask; 1523*1031d839SEric Joyner 1524*1031d839SEric Joyner /* 1525*1031d839SEric Joyner ** Check status of the queues 1526*1031d839SEric Joyner */ 1527*1031d839SEric Joyner mask = (I40E_PFINT_DYN_CTLN_INTENA_MASK | 1528*1031d839SEric Joyner I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK); 1529*1031d839SEric Joyner 1530*1031d839SEric Joyner /* If queue param has outstanding work, trigger sw irq */ 1531*1031d839SEric Joyner // TODO: TX queues in iflib don't use HW interrupts; does this do anything? 1532*1031d839SEric Joyner if (que->busy) 1533*1031d839SEric Joyner wr32(hw, I40E_PFINT_DYN_CTLN(que->txr.me), mask); 1534*1031d839SEric Joyner #endif 1535*1031d839SEric Joyner 1536*1031d839SEric Joyner if (qid != 0) 1537*1031d839SEric Joyner return; 1538*1031d839SEric Joyner 1539*1031d839SEric Joyner /* Fire off the adminq task */ 1540*1031d839SEric Joyner iflib_admin_intr_deferred(ctx); 1541*1031d839SEric Joyner 1542*1031d839SEric Joyner /* Update stats */ 1543*1031d839SEric Joyner ixl_update_stats_counters(pf); 1544*1031d839SEric Joyner } 1545*1031d839SEric Joyner 1546*1031d839SEric Joyner static void 1547*1031d839SEric Joyner ixl_if_vlan_register(if_ctx_t ctx, u16 vtag) 1548*1031d839SEric Joyner { 1549*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1550*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1551*1031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 1552*1031d839SEric Joyner 1553*1031d839SEric Joyner if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 1554*1031d839SEric Joyner return; 1555*1031d839SEric Joyner 1556*1031d839SEric Joyner ++vsi->num_vlans; 1557*1031d839SEric Joyner ixl_add_filter(vsi, hw->mac.addr, vtag); 1558*1031d839SEric Joyner } 1559*1031d839SEric Joyner 1560*1031d839SEric Joyner static void 1561*1031d839SEric Joyner ixl_if_vlan_unregister(if_ctx_t ctx, u16 vtag) 1562*1031d839SEric Joyner { 1563*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1564*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1565*1031d839SEric Joyner struct i40e_hw *hw = vsi->hw; 1566*1031d839SEric Joyner 1567*1031d839SEric Joyner if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 1568*1031d839SEric Joyner return; 1569*1031d839SEric Joyner 1570*1031d839SEric Joyner --vsi->num_vlans; 1571*1031d839SEric Joyner ixl_del_filter(vsi, hw->mac.addr, vtag); 1572*1031d839SEric Joyner } 1573*1031d839SEric Joyner 1574*1031d839SEric Joyner static uint64_t 1575*1031d839SEric Joyner ixl_if_get_counter(if_ctx_t ctx, ift_counter cnt) 1576*1031d839SEric Joyner { 1577*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1578*1031d839SEric Joyner struct ixl_vsi *vsi = &pf->vsi; 1579*1031d839SEric Joyner if_t ifp = iflib_get_ifp(ctx); 1580*1031d839SEric Joyner 1581*1031d839SEric Joyner switch (cnt) { 1582*1031d839SEric Joyner case IFCOUNTER_IPACKETS: 1583*1031d839SEric Joyner return (vsi->ipackets); 1584*1031d839SEric Joyner case IFCOUNTER_IERRORS: 1585*1031d839SEric Joyner return (vsi->ierrors); 1586*1031d839SEric Joyner case IFCOUNTER_OPACKETS: 1587*1031d839SEric Joyner return (vsi->opackets); 1588*1031d839SEric Joyner case IFCOUNTER_OERRORS: 1589*1031d839SEric Joyner return (vsi->oerrors); 1590*1031d839SEric Joyner case IFCOUNTER_COLLISIONS: 1591*1031d839SEric Joyner /* Collisions are by standard impossible in 40G/10G Ethernet */ 1592*1031d839SEric Joyner return (0); 1593*1031d839SEric Joyner case IFCOUNTER_IBYTES: 1594*1031d839SEric Joyner return (vsi->ibytes); 1595*1031d839SEric Joyner case IFCOUNTER_OBYTES: 1596*1031d839SEric Joyner return (vsi->obytes); 1597*1031d839SEric Joyner case IFCOUNTER_IMCASTS: 1598*1031d839SEric Joyner return (vsi->imcasts); 1599*1031d839SEric Joyner case IFCOUNTER_OMCASTS: 1600*1031d839SEric Joyner return (vsi->omcasts); 1601*1031d839SEric Joyner case IFCOUNTER_IQDROPS: 1602*1031d839SEric Joyner return (vsi->iqdrops); 1603*1031d839SEric Joyner case IFCOUNTER_OQDROPS: 1604*1031d839SEric Joyner return (vsi->oqdrops); 1605*1031d839SEric Joyner case IFCOUNTER_NOPROTO: 1606*1031d839SEric Joyner return (vsi->noproto); 1607*1031d839SEric Joyner default: 1608*1031d839SEric Joyner return (if_get_counter_default(ifp, cnt)); 1609*1031d839SEric Joyner } 1610*1031d839SEric Joyner } 1611*1031d839SEric Joyner 1612*1031d839SEric Joyner static void 1613*1031d839SEric Joyner ixl_if_vflr_handle(if_ctx_t ctx) 1614*1031d839SEric Joyner { 1615*1031d839SEric Joyner IXL_DEV_ERR(iflib_get_dev(ctx), ""); 1616*1031d839SEric Joyner 1617*1031d839SEric Joyner // TODO: call ixl_handle_vflr() 1618*1031d839SEric Joyner } 1619*1031d839SEric Joyner 1620*1031d839SEric Joyner static int 1621*1031d839SEric Joyner ixl_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req) 1622*1031d839SEric Joyner { 1623*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1624*1031d839SEric Joyner 1625*1031d839SEric Joyner if (pf->read_i2c_byte == NULL) 1626*1031d839SEric Joyner return (EINVAL); 1627*1031d839SEric Joyner 1628*1031d839SEric Joyner for (int i = 0; i < req->len; i++) 1629*1031d839SEric Joyner if (pf->read_i2c_byte(pf, req->offset + i, 1630*1031d839SEric Joyner req->dev_addr, &req->data[i])) 1631*1031d839SEric Joyner return (EIO); 1632*1031d839SEric Joyner return (0); 1633*1031d839SEric Joyner } 1634*1031d839SEric Joyner 1635*1031d839SEric Joyner static int 1636*1031d839SEric Joyner ixl_if_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data) 1637*1031d839SEric Joyner { 1638*1031d839SEric Joyner struct ixl_pf *pf = iflib_get_softc(ctx); 1639*1031d839SEric Joyner struct ifdrv *ifd = (struct ifdrv *)data; 1640*1031d839SEric Joyner int error = 0; 1641*1031d839SEric Joyner 1642*1031d839SEric Joyner /* NVM update command */ 1643*1031d839SEric Joyner if (ifd->ifd_cmd == I40E_NVM_ACCESS) 1644*1031d839SEric Joyner error = ixl_handle_nvmupd_cmd(pf, ifd); 1645*1031d839SEric Joyner else 1646*1031d839SEric Joyner error = EINVAL; 1647*1031d839SEric Joyner 1648*1031d839SEric Joyner return (error); 1649*1031d839SEric Joyner } 1650*1031d839SEric Joyner 1651*1031d839SEric Joyner static int 1652*1031d839SEric Joyner ixl_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int count __unused) 1653*1031d839SEric Joyner { 1654*1031d839SEric Joyner struct ixl_vsi *vsi = arg; 1655*1031d839SEric Joyner 1656*1031d839SEric Joyner if (ifma->ifma_addr->sa_family != AF_LINK) 1657*1031d839SEric Joyner return (0); 1658*1031d839SEric Joyner ixl_add_mc_filter(vsi, 1659*1031d839SEric Joyner (u8*)LLADDR((struct sockaddr_dl *) ifma->ifma_addr)); 1660*1031d839SEric Joyner return (1); 1661*1031d839SEric Joyner } 1662*1031d839SEric Joyner 1663*1031d839SEric Joyner /* 1664*1031d839SEric Joyner * Sanity check and save off tunable values. 1665*1031d839SEric Joyner */ 1666*1031d839SEric Joyner static void 1667*1031d839SEric Joyner ixl_save_pf_tunables(struct ixl_pf *pf) 1668*1031d839SEric Joyner { 1669*1031d839SEric Joyner device_t dev = pf->dev; 1670*1031d839SEric Joyner 1671*1031d839SEric Joyner /* Save tunable information */ 1672*1031d839SEric Joyner pf->enable_tx_fc_filter = ixl_enable_tx_fc_filter; 1673*1031d839SEric Joyner pf->dbg_mask = ixl_core_debug_mask; 1674*1031d839SEric Joyner pf->hw.debug_mask = ixl_shared_debug_mask; 1675*1031d839SEric Joyner pf->vsi.enable_head_writeback = !!(ixl_enable_head_writeback); 1676*1031d839SEric Joyner #if 0 1677*1031d839SEric Joyner pf->dynamic_rx_itr = ixl_dynamic_rx_itr; 1678*1031d839SEric Joyner pf->dynamic_tx_itr = ixl_dynamic_tx_itr; 1679*1031d839SEric Joyner #endif 1680*1031d839SEric Joyner 1681*1031d839SEric Joyner if (ixl_i2c_access_method > 3 || ixl_i2c_access_method < 0) 1682*1031d839SEric Joyner pf->i2c_access_method = 0; 1683*1031d839SEric Joyner else 1684*1031d839SEric Joyner pf->i2c_access_method = ixl_i2c_access_method; 1685*1031d839SEric Joyner 1686*1031d839SEric Joyner if (ixl_tx_itr < 0 || ixl_tx_itr > IXL_MAX_ITR) { 1687*1031d839SEric Joyner device_printf(dev, "Invalid tx_itr value of %d set!\n", 1688*1031d839SEric Joyner ixl_tx_itr); 1689*1031d839SEric Joyner device_printf(dev, "tx_itr must be between %d and %d, " 1690*1031d839SEric Joyner "inclusive\n", 1691*1031d839SEric Joyner 0, IXL_MAX_ITR); 1692*1031d839SEric Joyner device_printf(dev, "Using default value of %d instead\n", 1693*1031d839SEric Joyner IXL_ITR_4K); 1694*1031d839SEric Joyner pf->tx_itr = IXL_ITR_4K; 1695*1031d839SEric Joyner } else 1696*1031d839SEric Joyner pf->tx_itr = ixl_tx_itr; 1697*1031d839SEric Joyner 1698*1031d839SEric Joyner if (ixl_rx_itr < 0 || ixl_rx_itr > IXL_MAX_ITR) { 1699*1031d839SEric Joyner device_printf(dev, "Invalid rx_itr value of %d set!\n", 1700*1031d839SEric Joyner ixl_rx_itr); 1701*1031d839SEric Joyner device_printf(dev, "rx_itr must be between %d and %d, " 1702*1031d839SEric Joyner "inclusive\n", 1703*1031d839SEric Joyner 0, IXL_MAX_ITR); 1704*1031d839SEric Joyner device_printf(dev, "Using default value of %d instead\n", 1705*1031d839SEric Joyner IXL_ITR_8K); 1706*1031d839SEric Joyner pf->rx_itr = IXL_ITR_8K; 1707*1031d839SEric Joyner } else 1708*1031d839SEric Joyner pf->rx_itr = ixl_rx_itr; 1709*1031d839SEric Joyner } 1710*1031d839SEric Joyner 1711