1758cc3dcSJack F Vogel /****************************************************************************** 2758cc3dcSJack F Vogel 38eb6488eSEric Joyner Copyright (c) 2001-2017, Intel Corporation 4758cc3dcSJack F Vogel All rights reserved. 5758cc3dcSJack F Vogel 6758cc3dcSJack F Vogel Redistribution and use in source and binary forms, with or without 7758cc3dcSJack F Vogel modification, are permitted provided that the following conditions are met: 8758cc3dcSJack F Vogel 9758cc3dcSJack F Vogel 1. Redistributions of source code must retain the above copyright notice, 10758cc3dcSJack F Vogel this list of conditions and the following disclaimer. 11758cc3dcSJack F Vogel 12758cc3dcSJack F Vogel 2. Redistributions in binary form must reproduce the above copyright 13758cc3dcSJack F Vogel notice, this list of conditions and the following disclaimer in the 14758cc3dcSJack F Vogel documentation and/or other materials provided with the distribution. 15758cc3dcSJack F Vogel 16758cc3dcSJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its 17758cc3dcSJack F Vogel contributors may be used to endorse or promote products derived from 18758cc3dcSJack F Vogel this software without specific prior written permission. 19758cc3dcSJack F Vogel 20758cc3dcSJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21758cc3dcSJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22758cc3dcSJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23758cc3dcSJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24758cc3dcSJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25758cc3dcSJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26758cc3dcSJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27758cc3dcSJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28758cc3dcSJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29758cc3dcSJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30758cc3dcSJack F Vogel POSSIBILITY OF SUCH DAMAGE. 31758cc3dcSJack F Vogel 32758cc3dcSJack F Vogel ******************************************************************************/ 33758cc3dcSJack F Vogel /*$FreeBSD$*/ 34758cc3dcSJack F Vogel 35758cc3dcSJack F Vogel 36758cc3dcSJack F Vogel #ifndef IXGBE_STANDALONE_BUILD 37758cc3dcSJack F Vogel #include "opt_inet.h" 38758cc3dcSJack F Vogel #include "opt_inet6.h" 39758cc3dcSJack F Vogel #include "opt_rss.h" 40758cc3dcSJack F Vogel #endif 41758cc3dcSJack F Vogel 42758cc3dcSJack F Vogel #include "ixgbe.h" 43758cc3dcSJack F Vogel 448eb6488eSEric Joyner /************************************************************************ 45758cc3dcSJack F Vogel * Driver version 468eb6488eSEric Joyner ************************************************************************/ 478eb6488eSEric Joyner char ixgbe_driver_version[] = "3.2.12-k"; 48a9ca1c79SSean Bruno 49758cc3dcSJack F Vogel 508eb6488eSEric Joyner /************************************************************************ 51758cc3dcSJack F Vogel * PCI Device ID Table 52758cc3dcSJack F Vogel * 53758cc3dcSJack F Vogel * Used by probe to select devices to load on 54758cc3dcSJack F Vogel * Last field stores an index into ixgbe_strings 55758cc3dcSJack F Vogel * Last entry must be all 0s 56758cc3dcSJack F Vogel * 57758cc3dcSJack F Vogel * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } 588eb6488eSEric Joyner ************************************************************************/ 59758cc3dcSJack F Vogel static ixgbe_vendor_info_t ixgbe_vendor_info_array[] = 60758cc3dcSJack F Vogel { 61758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, 0, 0, 0}, 62758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 0, 0, 0}, 63758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, 0, 0, 0}, 64758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0}, 65758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, 0, 0, 0}, 66758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, 0, 0, 0}, 67758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, 0, 0, 0}, 68758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, 0, 0, 0}, 69758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, 0, 0, 0}, 70758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, 0, 0, 0}, 71758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, 0, 0, 0}, 72758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, 0, 0, 0}, 73758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, 0, 0, 0}, 74758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0}, 75758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, 0, 0, 0}, 76758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 0, 0, 0}, 77758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 0, 0, 0}, 78758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 0, 0, 0}, 79758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, 0, 0, 0}, 80758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF2, 0, 0, 0}, 81758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, 0, 0, 0}, 82758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP, 0, 0, 0}, 83758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF_QP, 0, 0, 0}, 84758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_QSFP_SF_QP, 0, 0, 0}, 85758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, 0, 0, 0}, 86758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, 0, 0, 0}, 87758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, 0, 0, 0}, 88a9ca1c79SSean Bruno {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, 0, 0, 0}, 89758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, 0, 0, 0}, 90758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, 0, 0, 0}, 91758cc3dcSJack F Vogel {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, 0, 0, 0}, 928eb6488eSEric Joyner {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_1G_T, 0, 0, 0}, 93a9ca1c79SSean Bruno {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, 0, 0, 0}, 948eb6488eSEric Joyner {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR, 0, 0, 0}, 958eb6488eSEric Joyner {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR_L, 0, 0, 0}, 968eb6488eSEric Joyner {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP, 0, 0, 0}, 978eb6488eSEric Joyner {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP_N, 0, 0, 0}, 988eb6488eSEric Joyner {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII, 0, 0, 0}, 998eb6488eSEric Joyner {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII_L, 0, 0, 0}, 1008eb6488eSEric Joyner {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_10G_T, 0, 0, 0}, 1018eb6488eSEric Joyner {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T, 0, 0, 0}, 1028eb6488eSEric Joyner {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T_L, 0, 0, 0}, 1038eb6488eSEric Joyner {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_BYPASS, 0, 0, 0}, 1048eb6488eSEric Joyner {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BYPASS, 0, 0, 0}, 105758cc3dcSJack F Vogel /* required last entry */ 106758cc3dcSJack F Vogel {0, 0, 0, 0, 0} 107758cc3dcSJack F Vogel }; 108758cc3dcSJack F Vogel 1098eb6488eSEric Joyner /************************************************************************ 110758cc3dcSJack F Vogel * Table of branding strings 1118eb6488eSEric Joyner ************************************************************************/ 112758cc3dcSJack F Vogel static char *ixgbe_strings[] = { 113758cc3dcSJack F Vogel "Intel(R) PRO/10GbE PCI-Express Network Driver" 114758cc3dcSJack F Vogel }; 115758cc3dcSJack F Vogel 1168eb6488eSEric Joyner /************************************************************************ 117758cc3dcSJack F Vogel * Function prototypes 1188eb6488eSEric Joyner ************************************************************************/ 119758cc3dcSJack F Vogel static int ixgbe_probe(device_t); 120758cc3dcSJack F Vogel static int ixgbe_attach(device_t); 121758cc3dcSJack F Vogel static int ixgbe_detach(device_t); 122758cc3dcSJack F Vogel static int ixgbe_shutdown(device_t); 1236f37f232SEric Joyner static int ixgbe_suspend(device_t); 1246f37f232SEric Joyner static int ixgbe_resume(device_t); 125758cc3dcSJack F Vogel static int ixgbe_ioctl(struct ifnet *, u_long, caddr_t); 126758cc3dcSJack F Vogel static void ixgbe_init(void *); 127758cc3dcSJack F Vogel static void ixgbe_init_locked(struct adapter *); 128758cc3dcSJack F Vogel static void ixgbe_stop(void *); 129758cc3dcSJack F Vogel #if __FreeBSD_version >= 1100036 130758cc3dcSJack F Vogel static uint64_t ixgbe_get_counter(struct ifnet *, ift_counter); 131758cc3dcSJack F Vogel #endif 1328eb6488eSEric Joyner static void ixgbe_init_device_features(struct adapter *); 1338eb6488eSEric Joyner static void ixgbe_check_fan_failure(struct adapter *, u32, bool); 134758cc3dcSJack F Vogel static void ixgbe_add_media_types(struct adapter *); 135758cc3dcSJack F Vogel static void ixgbe_media_status(struct ifnet *, struct ifmediareq *); 136758cc3dcSJack F Vogel static int ixgbe_media_change(struct ifnet *); 137758cc3dcSJack F Vogel static int ixgbe_allocate_pci_resources(struct adapter *); 138a9ca1c79SSean Bruno static void ixgbe_get_slot_info(struct adapter *); 139758cc3dcSJack F Vogel static int ixgbe_allocate_msix(struct adapter *); 140758cc3dcSJack F Vogel static int ixgbe_allocate_legacy(struct adapter *); 1418eb6488eSEric Joyner static int ixgbe_configure_interrupts(struct adapter *); 142758cc3dcSJack F Vogel static void ixgbe_free_pci_resources(struct adapter *); 143758cc3dcSJack F Vogel static void ixgbe_local_timer(void *); 144758cc3dcSJack F Vogel static int ixgbe_setup_interface(device_t, struct adapter *); 14548056c88SJack F Vogel static void ixgbe_config_gpie(struct adapter *); 1466f37f232SEric Joyner static void ixgbe_config_dmac(struct adapter *); 1476f37f232SEric Joyner static void ixgbe_config_delay_values(struct adapter *); 148758cc3dcSJack F Vogel static void ixgbe_config_link(struct adapter *); 1496f37f232SEric Joyner static void ixgbe_check_wol_support(struct adapter *); 1506f37f232SEric Joyner static int ixgbe_setup_low_power_mode(struct adapter *); 151758cc3dcSJack F Vogel static void ixgbe_rearm_queues(struct adapter *, u64); 152758cc3dcSJack F Vogel 153758cc3dcSJack F Vogel static void ixgbe_initialize_transmit_units(struct adapter *); 154758cc3dcSJack F Vogel static void ixgbe_initialize_receive_units(struct adapter *); 155758cc3dcSJack F Vogel static void ixgbe_enable_rx_drop(struct adapter *); 156758cc3dcSJack F Vogel static void ixgbe_disable_rx_drop(struct adapter *); 157a9ca1c79SSean Bruno static void ixgbe_initialize_rss_mapping(struct adapter *); 158758cc3dcSJack F Vogel 159758cc3dcSJack F Vogel static void ixgbe_enable_intr(struct adapter *); 160758cc3dcSJack F Vogel static void ixgbe_disable_intr(struct adapter *); 161758cc3dcSJack F Vogel static void ixgbe_update_stats_counters(struct adapter *); 162758cc3dcSJack F Vogel static void ixgbe_set_promisc(struct adapter *); 163758cc3dcSJack F Vogel static void ixgbe_set_multi(struct adapter *); 164758cc3dcSJack F Vogel static void ixgbe_update_link_status(struct adapter *); 165758cc3dcSJack F Vogel static void ixgbe_set_ivar(struct adapter *, u8, u8, s8); 166758cc3dcSJack F Vogel static void ixgbe_configure_ivars(struct adapter *); 167758cc3dcSJack F Vogel static u8 *ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); 168758cc3dcSJack F Vogel 169758cc3dcSJack F Vogel static void ixgbe_setup_vlan_hw_support(struct adapter *); 170758cc3dcSJack F Vogel static void ixgbe_register_vlan(void *, struct ifnet *, u16); 171758cc3dcSJack F Vogel static void ixgbe_unregister_vlan(void *, struct ifnet *, u16); 172758cc3dcSJack F Vogel 1736f37f232SEric Joyner static void ixgbe_add_device_sysctls(struct adapter *); 1746f37f232SEric Joyner static void ixgbe_add_hw_stats(struct adapter *); 175f2c4db54SSteven Hartland static int ixgbe_set_flowcntl(struct adapter *, int); 176f2c4db54SSteven Hartland static int ixgbe_set_advertise(struct adapter *, int); 1778eb6488eSEric Joyner static int ixgbe_get_advertise(struct adapter *); 1786f37f232SEric Joyner 1796f37f232SEric Joyner /* Sysctl handlers */ 180b0c041f8SSean Bruno static void ixgbe_set_sysctl_value(struct adapter *, const char *, 181b0c041f8SSean Bruno const char *, int *, int); 182f2c4db54SSteven Hartland static int ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS); 183f2c4db54SSteven Hartland static int ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS); 1848eb6488eSEric Joyner static int ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS); 1856f37f232SEric Joyner static int ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS); 1866f37f232SEric Joyner static int ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS); 1876f37f232SEric Joyner static int ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS); 188a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 189a9ca1c79SSean Bruno static int ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS); 190a9ca1c79SSean Bruno static int ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS); 191a9ca1c79SSean Bruno #endif 1928eb6488eSEric Joyner static int ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS); 1938eb6488eSEric Joyner static int ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS); 1948eb6488eSEric Joyner static int ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS); 1958eb6488eSEric Joyner static int ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS); 1968eb6488eSEric Joyner static int ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS); 1976f37f232SEric Joyner static int ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS); 1986f37f232SEric Joyner static int ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS); 199758cc3dcSJack F Vogel 200758cc3dcSJack F Vogel /* Support for pluggable optic modules */ 201758cc3dcSJack F Vogel static bool ixgbe_sfp_probe(struct adapter *); 202758cc3dcSJack F Vogel 2038eb6488eSEric Joyner /* Legacy (single vector) interrupt handler */ 204758cc3dcSJack F Vogel static void ixgbe_legacy_irq(void *); 205758cc3dcSJack F Vogel 2068eb6488eSEric Joyner /* The MSI/MSI-X Interrupt handlers */ 207758cc3dcSJack F Vogel static void ixgbe_msix_que(void *); 208758cc3dcSJack F Vogel static void ixgbe_msix_link(void *); 209758cc3dcSJack F Vogel 210758cc3dcSJack F Vogel /* Deferred interrupt tasklets */ 211758cc3dcSJack F Vogel static void ixgbe_handle_que(void *, int); 212758cc3dcSJack F Vogel static void ixgbe_handle_link(void *, int); 213758cc3dcSJack F Vogel static void ixgbe_handle_msf(void *, int); 214758cc3dcSJack F Vogel static void ixgbe_handle_mod(void *, int); 2156f37f232SEric Joyner static void ixgbe_handle_phy(void *, int); 216758cc3dcSJack F Vogel 217758cc3dcSJack F Vogel 2188eb6488eSEric Joyner /************************************************************************ 219758cc3dcSJack F Vogel * FreeBSD Device Interface Entry Points 2208eb6488eSEric Joyner ************************************************************************/ 221a1edda90SAdrian Chadd static device_method_t ix_methods[] = { 222758cc3dcSJack F Vogel /* Device interface */ 223758cc3dcSJack F Vogel DEVMETHOD(device_probe, ixgbe_probe), 224758cc3dcSJack F Vogel DEVMETHOD(device_attach, ixgbe_attach), 225758cc3dcSJack F Vogel DEVMETHOD(device_detach, ixgbe_detach), 226758cc3dcSJack F Vogel DEVMETHOD(device_shutdown, ixgbe_shutdown), 2276f37f232SEric Joyner DEVMETHOD(device_suspend, ixgbe_suspend), 2286f37f232SEric Joyner DEVMETHOD(device_resume, ixgbe_resume), 22948056c88SJack F Vogel #ifdef PCI_IOV 2309e34aea2SJohn Baldwin DEVMETHOD(pci_iov_init, ixgbe_init_iov), 2319e34aea2SJohn Baldwin DEVMETHOD(pci_iov_uninit, ixgbe_uninit_iov), 2329e34aea2SJohn Baldwin DEVMETHOD(pci_iov_add_vf, ixgbe_add_vf), 23348056c88SJack F Vogel #endif /* PCI_IOV */ 234758cc3dcSJack F Vogel DEVMETHOD_END 235758cc3dcSJack F Vogel }; 236758cc3dcSJack F Vogel 237a1edda90SAdrian Chadd static driver_t ix_driver = { 238a1edda90SAdrian Chadd "ix", ix_methods, sizeof(struct adapter), 239758cc3dcSJack F Vogel }; 240758cc3dcSJack F Vogel 241a1edda90SAdrian Chadd devclass_t ix_devclass; 242a1edda90SAdrian Chadd DRIVER_MODULE(ix, pci, ix_driver, ix_devclass, 0, 0); 243758cc3dcSJack F Vogel 244a1edda90SAdrian Chadd MODULE_DEPEND(ix, pci, 1, 1, 1); 245a1edda90SAdrian Chadd MODULE_DEPEND(ix, ether, 1, 1, 1); 246847bf383SLuigi Rizzo MODULE_DEPEND(ix, netmap, 1, 1, 1); 247758cc3dcSJack F Vogel 248758cc3dcSJack F Vogel /* 2498eb6488eSEric Joyner * TUNEABLE PARAMETERS: 250758cc3dcSJack F Vogel */ 251758cc3dcSJack F Vogel 2528eb6488eSEric Joyner static SYSCTL_NODE(_hw, OID_AUTO, ix, CTLFLAG_RD, 0, "IXGBE driver parameters"); 253758cc3dcSJack F Vogel 254758cc3dcSJack F Vogel /* 2558eb6488eSEric Joyner * AIM: Adaptive Interrupt Moderation 2568eb6488eSEric Joyner * which means that the interrupt rate 2578eb6488eSEric Joyner * is varied over time based on the 2588eb6488eSEric Joyner * traffic for that interrupt vector 259758cc3dcSJack F Vogel */ 260758cc3dcSJack F Vogel static int ixgbe_enable_aim = TRUE; 2618eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_aim, CTLFLAG_RDTUN, &ixgbe_enable_aim, 0, 262758cc3dcSJack F Vogel "Enable adaptive interrupt moderation"); 263758cc3dcSJack F Vogel 264758cc3dcSJack F Vogel static int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY); 265758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN, 266758cc3dcSJack F Vogel &ixgbe_max_interrupt_rate, 0, "Maximum interrupts per second"); 267758cc3dcSJack F Vogel 268758cc3dcSJack F Vogel /* How many packets rxeof tries to clean at a time */ 269758cc3dcSJack F Vogel static int ixgbe_rx_process_limit = 256; 270758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN, 2718eb6488eSEric Joyner &ixgbe_rx_process_limit, 0, "Maximum number of received packets to process at a time, -1 means unlimited"); 272758cc3dcSJack F Vogel 273758cc3dcSJack F Vogel /* How many packets txeof tries to clean at a time */ 274758cc3dcSJack F Vogel static int ixgbe_tx_process_limit = 256; 275758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, tx_process_limit, CTLFLAG_RDTUN, 276758cc3dcSJack F Vogel &ixgbe_tx_process_limit, 0, 2778eb6488eSEric Joyner "Maximum number of sent packets to process at a time, -1 means unlimited"); 278758cc3dcSJack F Vogel 279f2c4db54SSteven Hartland /* Flow control setting, default to full */ 280f2c4db54SSteven Hartland static int ixgbe_flow_control = ixgbe_fc_full; 281f2c4db54SSteven Hartland SYSCTL_INT(_hw_ix, OID_AUTO, flow_control, CTLFLAG_RDTUN, 282f2c4db54SSteven Hartland &ixgbe_flow_control, 0, "Default flow control used for all adapters"); 283f2c4db54SSteven Hartland 284f2c4db54SSteven Hartland /* Advertise Speed, default to 0 (auto) */ 285f2c4db54SSteven Hartland static int ixgbe_advertise_speed = 0; 286f2c4db54SSteven Hartland SYSCTL_INT(_hw_ix, OID_AUTO, advertise_speed, CTLFLAG_RDTUN, 287f2c4db54SSteven Hartland &ixgbe_advertise_speed, 0, "Default advertised speed for all adapters"); 288f2c4db54SSteven Hartland 289758cc3dcSJack F Vogel /* 2908eb6488eSEric Joyner * Smart speed setting, default to on 2918eb6488eSEric Joyner * this only works as a compile option 2928eb6488eSEric Joyner * right now as its during attach, set 2938eb6488eSEric Joyner * this to 'ixgbe_smart_speed_off' to 2948eb6488eSEric Joyner * disable. 295758cc3dcSJack F Vogel */ 296758cc3dcSJack F Vogel static int ixgbe_smart_speed = ixgbe_smart_speed_on; 297758cc3dcSJack F Vogel 298758cc3dcSJack F Vogel /* 2998eb6488eSEric Joyner * MSI-X should be the default for best performance, 300758cc3dcSJack F Vogel * but this allows it to be forced off for testing. 301758cc3dcSJack F Vogel */ 302758cc3dcSJack F Vogel static int ixgbe_enable_msix = 1; 303758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixgbe_enable_msix, 0, 304758cc3dcSJack F Vogel "Enable MSI-X interrupts"); 305758cc3dcSJack F Vogel 306758cc3dcSJack F Vogel /* 307758cc3dcSJack F Vogel * Number of Queues, can be set to 0, 308758cc3dcSJack F Vogel * it then autoconfigures based on the 309758cc3dcSJack F Vogel * number of cpus with a max of 8. This 310758cc3dcSJack F Vogel * can be overriden manually here. 311758cc3dcSJack F Vogel */ 312758cc3dcSJack F Vogel static int ixgbe_num_queues = 0; 313758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, num_queues, CTLFLAG_RDTUN, &ixgbe_num_queues, 0, 314758cc3dcSJack F Vogel "Number of queues to configure, 0 indicates autoconfigure"); 315758cc3dcSJack F Vogel 316758cc3dcSJack F Vogel /* 3178eb6488eSEric Joyner * Number of TX descriptors per ring, 3188eb6488eSEric Joyner * setting higher than RX as this seems 3198eb6488eSEric Joyner * the better performing choice. 320758cc3dcSJack F Vogel */ 321758cc3dcSJack F Vogel static int ixgbe_txd = PERFORM_TXD; 322758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, txd, CTLFLAG_RDTUN, &ixgbe_txd, 0, 323758cc3dcSJack F Vogel "Number of transmit descriptors per queue"); 324758cc3dcSJack F Vogel 325758cc3dcSJack F Vogel /* Number of RX descriptors per ring */ 326758cc3dcSJack F Vogel static int ixgbe_rxd = PERFORM_RXD; 327758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, rxd, CTLFLAG_RDTUN, &ixgbe_rxd, 0, 328758cc3dcSJack F Vogel "Number of receive descriptors per queue"); 329758cc3dcSJack F Vogel 330758cc3dcSJack F Vogel /* 3318eb6488eSEric Joyner * Defining this on will allow the use 3328eb6488eSEric Joyner * of unsupported SFP+ modules, note that 3338eb6488eSEric Joyner * doing so you are on your own :) 334758cc3dcSJack F Vogel */ 335758cc3dcSJack F Vogel static int allow_unsupported_sfp = FALSE; 336*fb6aa95dSSean Bruno SYSCTL_INT(_hw_ix, OID_AUTO, unsupported_sfp, CTLFLAG_RDTUN, 3378eb6488eSEric Joyner &allow_unsupported_sfp, 0, 3388eb6488eSEric Joyner "Allow unsupported SFP modules...use at your own risk"); 3398eb6488eSEric Joyner 3408eb6488eSEric Joyner /* 3418eb6488eSEric Joyner * Not sure if Flow Director is fully baked, 3428eb6488eSEric Joyner * so we'll default to turning it off. 3438eb6488eSEric Joyner */ 3448eb6488eSEric Joyner static int ixgbe_enable_fdir = 0; 3458eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_fdir, CTLFLAG_RDTUN, &ixgbe_enable_fdir, 0, 3468eb6488eSEric Joyner "Enable Flow Director"); 3478eb6488eSEric Joyner 3488eb6488eSEric Joyner /* Legacy Transmit (single queue) */ 3498eb6488eSEric Joyner static int ixgbe_enable_legacy_tx = 0; 3508eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_legacy_tx, CTLFLAG_RDTUN, 3518eb6488eSEric Joyner &ixgbe_enable_legacy_tx, 0, "Enable Legacy TX flow"); 3528eb6488eSEric Joyner 3538eb6488eSEric Joyner /* Receive-Side Scaling */ 3548eb6488eSEric Joyner static int ixgbe_enable_rss = 1; 3558eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_rss, CTLFLAG_RDTUN, &ixgbe_enable_rss, 0, 3568eb6488eSEric Joyner "Enable Receive-Side Scaling (RSS)"); 357758cc3dcSJack F Vogel 358758cc3dcSJack F Vogel /* Keep running tab on them for sanity check */ 359758cc3dcSJack F Vogel static int ixgbe_total_ports; 360758cc3dcSJack F Vogel 3618eb6488eSEric Joyner static int (*ixgbe_start_locked)(struct ifnet *, struct tx_ring *); 3628eb6488eSEric Joyner static int (*ixgbe_ring_empty)(struct ifnet *, struct buf_ring *); 363758cc3dcSJack F Vogel 3648eb6488eSEric Joyner MALLOC_DEFINE(M_IXGBE, "ix", "ix driver allocations"); 365758cc3dcSJack F Vogel 3668eb6488eSEric Joyner /************************************************************************ 3678eb6488eSEric Joyner * ixgbe_initialize_rss_mapping 3688eb6488eSEric Joyner ************************************************************************/ 3698eb6488eSEric Joyner static void 3708eb6488eSEric Joyner ixgbe_initialize_rss_mapping(struct adapter *adapter) 371758cc3dcSJack F Vogel { 3726f37f232SEric Joyner struct ixgbe_hw *hw = &adapter->hw; 3738eb6488eSEric Joyner u32 reta = 0, mrqc, rss_key[10]; 3748eb6488eSEric Joyner int queue_id, table_size, index_mult; 3758eb6488eSEric Joyner int i, j; 3768eb6488eSEric Joyner u32 rss_hash_config; 3776f37f232SEric Joyner 3788eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_RSS) { 3798eb6488eSEric Joyner /* Fetch the configured RSS key */ 3808eb6488eSEric Joyner rss_getkey((uint8_t *)&rss_key); 381758cc3dcSJack F Vogel } else { 3828eb6488eSEric Joyner /* set up random bits */ 3838eb6488eSEric Joyner arc4rand(&rss_key, sizeof(rss_key), 0); 384758cc3dcSJack F Vogel } 385758cc3dcSJack F Vogel 3868eb6488eSEric Joyner /* Set multiplier for RETA setup and table size based on MAC */ 3878eb6488eSEric Joyner index_mult = 0x1; 3888eb6488eSEric Joyner table_size = 128; 3898eb6488eSEric Joyner switch (adapter->hw.mac.type) { 3908eb6488eSEric Joyner case ixgbe_mac_82598EB: 3918eb6488eSEric Joyner index_mult = 0x11; 392758cc3dcSJack F Vogel break; 3938eb6488eSEric Joyner case ixgbe_mac_X550: 3948eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 3958eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 3968eb6488eSEric Joyner table_size = 512; 3978eb6488eSEric Joyner break; 398758cc3dcSJack F Vogel default: 399758cc3dcSJack F Vogel break; 400758cc3dcSJack F Vogel } 401758cc3dcSJack F Vogel 4028eb6488eSEric Joyner /* Set up the redirection table */ 4038eb6488eSEric Joyner for (i = 0, j = 0; i < table_size; i++, j++) { 4048eb6488eSEric Joyner if (j == adapter->num_queues) 4058eb6488eSEric Joyner j = 0; 406758cc3dcSJack F Vogel 4078eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_RSS) { 408a9ca1c79SSean Bruno /* 4098eb6488eSEric Joyner * Fetch the RSS bucket id for the given indirection 4108eb6488eSEric Joyner * entry. Cap it at the number of configured buckets 4118eb6488eSEric Joyner * (which is num_queues.) 412a9ca1c79SSean Bruno */ 4138eb6488eSEric Joyner queue_id = rss_get_indirection_to_bucket(i); 4148eb6488eSEric Joyner queue_id = queue_id % adapter->num_queues; 415758cc3dcSJack F Vogel } else 4168eb6488eSEric Joyner queue_id = (j * index_mult); 4178eb6488eSEric Joyner 4188eb6488eSEric Joyner /* 4198eb6488eSEric Joyner * The low 8 bits are for hash value (n+0); 4208eb6488eSEric Joyner * The next 8 bits are for hash value (n+1), etc. 4218eb6488eSEric Joyner */ 4228eb6488eSEric Joyner reta = reta >> 8; 4238eb6488eSEric Joyner reta = reta | (((uint32_t)queue_id) << 24); 4248eb6488eSEric Joyner if ((i & 3) == 3) { 4258eb6488eSEric Joyner if (i < 128) 4268eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta); 4278eb6488eSEric Joyner else 4288eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32), 4298eb6488eSEric Joyner reta); 4308eb6488eSEric Joyner reta = 0; 4318eb6488eSEric Joyner } 432758cc3dcSJack F Vogel } 433758cc3dcSJack F Vogel 4348eb6488eSEric Joyner /* Now fill our hash function seeds */ 4358eb6488eSEric Joyner for (i = 0; i < 10; i++) 4368eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]); 437758cc3dcSJack F Vogel 4388eb6488eSEric Joyner /* Perform hash on these packet types */ 4398eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_RSS) 4408eb6488eSEric Joyner rss_hash_config = rss_gethashconfig(); 441758cc3dcSJack F Vogel else { 442758cc3dcSJack F Vogel /* 4438eb6488eSEric Joyner * Disable UDP - IP fragments aren't currently being handled 4448eb6488eSEric Joyner * and so we end up with a mix of 2-tuple and 4-tuple 4458eb6488eSEric Joyner * traffic. 446758cc3dcSJack F Vogel */ 4478eb6488eSEric Joyner rss_hash_config = RSS_HASHTYPE_RSS_IPV4 4488eb6488eSEric Joyner | RSS_HASHTYPE_RSS_TCP_IPV4 4498eb6488eSEric Joyner | RSS_HASHTYPE_RSS_IPV6 4508eb6488eSEric Joyner | RSS_HASHTYPE_RSS_TCP_IPV6 4518eb6488eSEric Joyner | RSS_HASHTYPE_RSS_IPV6_EX 4528eb6488eSEric Joyner | RSS_HASHTYPE_RSS_TCP_IPV6_EX; 453758cc3dcSJack F Vogel } 454758cc3dcSJack F Vogel 4558eb6488eSEric Joyner mrqc = IXGBE_MRQC_RSSEN; 4568eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4) 4578eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4; 4588eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4) 4598eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP; 4608eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6) 4618eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6; 4628eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6) 4638eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP; 4648eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX) 4658eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX; 4668eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX) 4678eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP; 4688eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4) 4698eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; 4708eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4_EX) 4718eb6488eSEric Joyner device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_UDP_IPV4_EX defined, but not supported\n", 4728eb6488eSEric Joyner __func__); 4738eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6) 4748eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; 4758eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX) 4768eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP; 4778eb6488eSEric Joyner mrqc |= ixgbe_get_mrqc(adapter->iov_mode); 4788eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); 4798eb6488eSEric Joyner } /* ixgbe_initialize_rss_mapping */ 480758cc3dcSJack F Vogel 4818eb6488eSEric Joyner /************************************************************************ 4828eb6488eSEric Joyner * ixgbe_initialize_receive_units - Setup receive registers and features. 4838eb6488eSEric Joyner ************************************************************************/ 4848eb6488eSEric Joyner #define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1) 485758cc3dcSJack F Vogel 486758cc3dcSJack F Vogel static void 4878eb6488eSEric Joyner ixgbe_initialize_receive_units(struct adapter *adapter) 488758cc3dcSJack F Vogel { 4898eb6488eSEric Joyner struct rx_ring *rxr = adapter->rx_rings; 49048056c88SJack F Vogel struct ixgbe_hw *hw = &adapter->hw; 4918eb6488eSEric Joyner struct ifnet *ifp = adapter->ifp; 4928eb6488eSEric Joyner int i, j; 4938eb6488eSEric Joyner u32 bufsz, fctrl, srrctl, rxcsum; 4948eb6488eSEric Joyner u32 hlreg; 49548056c88SJack F Vogel 49648056c88SJack F Vogel /* 4978eb6488eSEric Joyner * Make sure receives are disabled while 4988eb6488eSEric Joyner * setting up the descriptor ring 49948056c88SJack F Vogel */ 5008eb6488eSEric Joyner ixgbe_disable_rx(hw); 5018eb6488eSEric Joyner 5028eb6488eSEric Joyner /* Enable broadcasts */ 5038eb6488eSEric Joyner fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 5048eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_BAM; 5058eb6488eSEric Joyner if (adapter->hw.mac.type == ixgbe_mac_82598EB) { 5068eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_DPF; 5078eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_PMCF; 50848056c88SJack F Vogel } 5098eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 5108eb6488eSEric Joyner 5118eb6488eSEric Joyner /* Set for Jumbo Frames? */ 5128eb6488eSEric Joyner hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0); 5138eb6488eSEric Joyner if (ifp->if_mtu > ETHERMTU) 5148eb6488eSEric Joyner hlreg |= IXGBE_HLREG0_JUMBOEN; 5158eb6488eSEric Joyner else 5168eb6488eSEric Joyner hlreg &= ~IXGBE_HLREG0_JUMBOEN; 5178eb6488eSEric Joyner 5188eb6488eSEric Joyner #ifdef DEV_NETMAP 5198eb6488eSEric Joyner /* CRC stripping is conditional in Netmap */ 5208eb6488eSEric Joyner if ((adapter->feat_en & IXGBE_FEATURE_NETMAP) && 5218eb6488eSEric Joyner (ifp->if_capenable & IFCAP_NETMAP) && 5228eb6488eSEric Joyner !ix_crcstrip) 5238eb6488eSEric Joyner hlreg &= ~IXGBE_HLREG0_RXCRCSTRP; 5248eb6488eSEric Joyner else 5258eb6488eSEric Joyner #endif /* DEV_NETMAP */ 5268eb6488eSEric Joyner hlreg |= IXGBE_HLREG0_RXCRCSTRP; 5278eb6488eSEric Joyner 5288eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg); 5298eb6488eSEric Joyner 5308eb6488eSEric Joyner bufsz = (adapter->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >> 5318eb6488eSEric Joyner IXGBE_SRRCTL_BSIZEPKT_SHIFT; 5328eb6488eSEric Joyner 5338eb6488eSEric Joyner for (i = 0; i < adapter->num_queues; i++, rxr++) { 5348eb6488eSEric Joyner u64 rdba = rxr->rxdma.dma_paddr; 5358eb6488eSEric Joyner j = rxr->me; 5368eb6488eSEric Joyner 5378eb6488eSEric Joyner /* Setup the Base and Length of the Rx Descriptor Ring */ 5388eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), 5398eb6488eSEric Joyner (rdba & 0x00000000ffffffffULL)); 5408eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32)); 5418eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j), 5428eb6488eSEric Joyner adapter->num_rx_desc * sizeof(union ixgbe_adv_rx_desc)); 5438eb6488eSEric Joyner 5448eb6488eSEric Joyner /* Set up the SRRCTL register */ 5458eb6488eSEric Joyner srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(j)); 5468eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK; 5478eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK; 5488eb6488eSEric Joyner srrctl |= bufsz; 5498eb6488eSEric Joyner srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; 55048056c88SJack F Vogel 55148056c88SJack F Vogel /* 5528eb6488eSEric Joyner * Set DROP_EN iff we have no flow control and >1 queue. 5538eb6488eSEric Joyner * Note that srrctl was cleared shortly before during reset, 5548eb6488eSEric Joyner * so we do not need to clear the bit, but do it just in case 5558eb6488eSEric Joyner * this code is moved elsewhere. 55648056c88SJack F Vogel */ 5578eb6488eSEric Joyner if (adapter->num_queues > 1 && 5588eb6488eSEric Joyner adapter->hw.fc.requested_mode == ixgbe_fc_none) { 5598eb6488eSEric Joyner srrctl |= IXGBE_SRRCTL_DROP_EN; 560758cc3dcSJack F Vogel } else { 5618eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_DROP_EN; 562758cc3dcSJack F Vogel } 563758cc3dcSJack F Vogel 5648eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl); 565758cc3dcSJack F Vogel 5668eb6488eSEric Joyner /* Setup the HW Rx Head and Tail Descriptor Pointers */ 5678eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0); 5688eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0); 569758cc3dcSJack F Vogel 5708eb6488eSEric Joyner /* Set the driver rx tail address */ 5718eb6488eSEric Joyner rxr->tail = IXGBE_RDT(rxr->me); 572a9ca1c79SSean Bruno } 573758cc3dcSJack F Vogel 574758cc3dcSJack F Vogel if (adapter->hw.mac.type != ixgbe_mac_82598EB) { 5758eb6488eSEric Joyner u32 psrtype = IXGBE_PSRTYPE_TCPHDR 5768eb6488eSEric Joyner | IXGBE_PSRTYPE_UDPHDR 5778eb6488eSEric Joyner | IXGBE_PSRTYPE_IPV4HDR 5788eb6488eSEric Joyner | IXGBE_PSRTYPE_IPV6HDR; 5798eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype); 5806f37f232SEric Joyner } 5816f37f232SEric Joyner 5828eb6488eSEric Joyner rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); 5838eb6488eSEric Joyner 5848eb6488eSEric Joyner ixgbe_initialize_rss_mapping(adapter); 5858eb6488eSEric Joyner 5868eb6488eSEric Joyner if (adapter->num_queues > 1) { 5878eb6488eSEric Joyner /* RSS and RX IPP Checksum are mutually exclusive */ 5888eb6488eSEric Joyner rxcsum |= IXGBE_RXCSUM_PCSD; 5896f37f232SEric Joyner } 5906f37f232SEric Joyner 5918eb6488eSEric Joyner if (ifp->if_capenable & IFCAP_RXCSUM) 5928eb6488eSEric Joyner rxcsum |= IXGBE_RXCSUM_PCSD; 593758cc3dcSJack F Vogel 5948eb6488eSEric Joyner /* This is useful for calculating UDP/IP fragment checksums */ 5958eb6488eSEric Joyner if (!(rxcsum & IXGBE_RXCSUM_PCSD)) 5968eb6488eSEric Joyner rxcsum |= IXGBE_RXCSUM_IPPCSE; 597758cc3dcSJack F Vogel 5988eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum); 599758cc3dcSJack F Vogel 600758cc3dcSJack F Vogel return; 6018eb6488eSEric Joyner } /* ixgbe_initialize_receive_units */ 602758cc3dcSJack F Vogel 6038eb6488eSEric Joyner /************************************************************************ 6048eb6488eSEric Joyner * ixgbe_initialize_transmit_units - Enable transmit units. 6058eb6488eSEric Joyner ************************************************************************/ 606758cc3dcSJack F Vogel static void 607758cc3dcSJack F Vogel ixgbe_initialize_transmit_units(struct adapter *adapter) 608758cc3dcSJack F Vogel { 609758cc3dcSJack F Vogel struct tx_ring *txr = adapter->tx_rings; 610758cc3dcSJack F Vogel struct ixgbe_hw *hw = &adapter->hw; 611758cc3dcSJack F Vogel 612758cc3dcSJack F Vogel /* Setup the Base and Length of the Tx Descriptor Ring */ 613758cc3dcSJack F Vogel for (int i = 0; i < adapter->num_queues; i++, txr++) { 614758cc3dcSJack F Vogel u64 tdba = txr->txdma.dma_paddr; 615758cc3dcSJack F Vogel u32 txctrl = 0; 61648056c88SJack F Vogel int j = txr->me; 617758cc3dcSJack F Vogel 61848056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j), 619758cc3dcSJack F Vogel (tdba & 0x00000000ffffffffULL)); 62048056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32)); 62148056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), 622758cc3dcSJack F Vogel adapter->num_tx_desc * sizeof(union ixgbe_adv_tx_desc)); 623758cc3dcSJack F Vogel 624758cc3dcSJack F Vogel /* Setup the HW Tx Head and Tail descriptor pointers */ 62548056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0); 62648056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0); 627758cc3dcSJack F Vogel 628758cc3dcSJack F Vogel /* Cache the tail address */ 62948056c88SJack F Vogel txr->tail = IXGBE_TDT(j); 630758cc3dcSJack F Vogel 631758cc3dcSJack F Vogel /* Disable Head Writeback */ 632a9ca1c79SSean Bruno /* 633a9ca1c79SSean Bruno * Note: for X550 series devices, these registers are actually 634a9ca1c79SSean Bruno * prefixed with TPH_ isntead of DCA_, but the addresses and 635a9ca1c79SSean Bruno * fields remain the same. 636a9ca1c79SSean Bruno */ 637758cc3dcSJack F Vogel switch (hw->mac.type) { 638758cc3dcSJack F Vogel case ixgbe_mac_82598EB: 63948056c88SJack F Vogel txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j)); 640758cc3dcSJack F Vogel break; 641758cc3dcSJack F Vogel default: 64248056c88SJack F Vogel txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j)); 643758cc3dcSJack F Vogel break; 644758cc3dcSJack F Vogel } 645758cc3dcSJack F Vogel txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; 646758cc3dcSJack F Vogel switch (hw->mac.type) { 647758cc3dcSJack F Vogel case ixgbe_mac_82598EB: 64848056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl); 649758cc3dcSJack F Vogel break; 650758cc3dcSJack F Vogel default: 65148056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl); 652758cc3dcSJack F Vogel break; 653758cc3dcSJack F Vogel } 654758cc3dcSJack F Vogel 655758cc3dcSJack F Vogel } 656758cc3dcSJack F Vogel 657758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 658758cc3dcSJack F Vogel u32 dmatxctl, rttdcs; 6598eb6488eSEric Joyner 660758cc3dcSJack F Vogel dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); 661758cc3dcSJack F Vogel dmatxctl |= IXGBE_DMATXCTL_TE; 662758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); 663758cc3dcSJack F Vogel /* Disable arbiter to set MTQC */ 664758cc3dcSJack F Vogel rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); 665758cc3dcSJack F Vogel rttdcs |= IXGBE_RTTDCS_ARBDIS; 666758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); 6678eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_MTQC, 6688eb6488eSEric Joyner ixgbe_get_mtqc(adapter->iov_mode)); 669758cc3dcSJack F Vogel rttdcs &= ~IXGBE_RTTDCS_ARBDIS; 670758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); 671758cc3dcSJack F Vogel } 672758cc3dcSJack F Vogel 673758cc3dcSJack F Vogel return; 6748eb6488eSEric Joyner } /* ixgbe_initialize_transmit_units */ 675758cc3dcSJack F Vogel 6768eb6488eSEric Joyner /************************************************************************ 6778eb6488eSEric Joyner * ixgbe_attach - Device initialization routine 678758cc3dcSJack F Vogel * 6798eb6488eSEric Joyner * Called when the driver is being loaded. 6808eb6488eSEric Joyner * Identifies the type of hardware, allocates all resources 6818eb6488eSEric Joyner * and initializes the hardware. 682758cc3dcSJack F Vogel * 6838eb6488eSEric Joyner * return 0 on success, positive on failure 6848eb6488eSEric Joyner ************************************************************************/ 6858eb6488eSEric Joyner static int 6868eb6488eSEric Joyner ixgbe_attach(device_t dev) 687758cc3dcSJack F Vogel { 6888eb6488eSEric Joyner struct adapter *adapter; 6898eb6488eSEric Joyner struct ixgbe_hw *hw; 6908eb6488eSEric Joyner int error = 0; 6918eb6488eSEric Joyner u32 ctrl_ext; 6928eb6488eSEric Joyner 6938eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_attach: begin"); 6948eb6488eSEric Joyner 6958eb6488eSEric Joyner /* Allocate, clear, and link in our adapter structure */ 6968eb6488eSEric Joyner adapter = device_get_softc(dev); 6978eb6488eSEric Joyner adapter->hw.back = adapter; 6988eb6488eSEric Joyner adapter->dev = dev; 6998eb6488eSEric Joyner hw = &adapter->hw; 7008eb6488eSEric Joyner 7018eb6488eSEric Joyner /* Core Lock Init*/ 7028eb6488eSEric Joyner IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev)); 7038eb6488eSEric Joyner 7048eb6488eSEric Joyner /* Set up the timer callout */ 7058eb6488eSEric Joyner callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0); 7068eb6488eSEric Joyner 7078eb6488eSEric Joyner /* Determine hardware revision */ 7088eb6488eSEric Joyner hw->vendor_id = pci_get_vendor(dev); 7098eb6488eSEric Joyner hw->device_id = pci_get_device(dev); 7108eb6488eSEric Joyner hw->revision_id = pci_get_revid(dev); 7118eb6488eSEric Joyner hw->subsystem_vendor_id = pci_get_subvendor(dev); 7128eb6488eSEric Joyner hw->subsystem_device_id = pci_get_subdevice(dev); 713758cc3dcSJack F Vogel 714758cc3dcSJack F Vogel /* 7158eb6488eSEric Joyner * Make sure BUSMASTER is set 716758cc3dcSJack F Vogel */ 7178eb6488eSEric Joyner pci_enable_busmaster(dev); 718758cc3dcSJack F Vogel 7198eb6488eSEric Joyner /* Do base PCI setup - map BAR0 */ 7208eb6488eSEric Joyner if (ixgbe_allocate_pci_resources(adapter)) { 7218eb6488eSEric Joyner device_printf(dev, "Allocation of PCI resources failed\n"); 7228eb6488eSEric Joyner error = ENXIO; 7238eb6488eSEric Joyner goto err_out; 7246f37f232SEric Joyner } 725758cc3dcSJack F Vogel 7268eb6488eSEric Joyner /* let hardware know driver is loaded */ 7278eb6488eSEric Joyner ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 7288eb6488eSEric Joyner ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD; 7298eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 730758cc3dcSJack F Vogel 731758cc3dcSJack F Vogel /* 7328eb6488eSEric Joyner * Initialize the shared code 733758cc3dcSJack F Vogel */ 7348eb6488eSEric Joyner if (ixgbe_init_shared_code(hw)) { 7358eb6488eSEric Joyner device_printf(dev, "Unable to initialize the shared code\n"); 7368eb6488eSEric Joyner error = ENXIO; 7378eb6488eSEric Joyner goto err_out; 73830126537SJack F Vogel } 739758cc3dcSJack F Vogel 7408eb6488eSEric Joyner if (hw->mbx.ops.init_params) 7418eb6488eSEric Joyner hw->mbx.ops.init_params(hw); 742758cc3dcSJack F Vogel 7438eb6488eSEric Joyner hw->allow_unsupported_sfp = allow_unsupported_sfp; 744758cc3dcSJack F Vogel 7458eb6488eSEric Joyner /* Pick up the 82599 settings */ 746758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 7478eb6488eSEric Joyner hw->phy.smart_speed = ixgbe_smart_speed; 7488eb6488eSEric Joyner adapter->num_segs = IXGBE_82599_SCATTER; 749758cc3dcSJack F Vogel } else 7508eb6488eSEric Joyner adapter->num_segs = IXGBE_82598_SCATTER; 7518eb6488eSEric Joyner 7528eb6488eSEric Joyner ixgbe_init_device_features(adapter); 7538eb6488eSEric Joyner 7548eb6488eSEric Joyner if (ixgbe_configure_interrupts(adapter)) { 7558eb6488eSEric Joyner error = ENXIO; 7568eb6488eSEric Joyner goto err_out; 757758cc3dcSJack F Vogel } 7588eb6488eSEric Joyner 7598eb6488eSEric Joyner /* Allocate multicast array memory. */ 7608eb6488eSEric Joyner adapter->mta = malloc(sizeof(*adapter->mta) * 7618eb6488eSEric Joyner MAX_NUM_MULTICAST_ADDRESSES, M_IXGBE, M_NOWAIT); 7628eb6488eSEric Joyner if (adapter->mta == NULL) { 7638eb6488eSEric Joyner device_printf(dev, "Can not allocate multicast setup array\n"); 7648eb6488eSEric Joyner error = ENOMEM; 7658eb6488eSEric Joyner goto err_out; 766758cc3dcSJack F Vogel } 767758cc3dcSJack F Vogel 7688eb6488eSEric Joyner /* Enable WoL (if supported) */ 7698eb6488eSEric Joyner ixgbe_check_wol_support(adapter); 7708eb6488eSEric Joyner 7718eb6488eSEric Joyner /* Register for VLAN events */ 7728eb6488eSEric Joyner adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, 7738eb6488eSEric Joyner ixgbe_register_vlan, adapter, EVENTHANDLER_PRI_FIRST); 7748eb6488eSEric Joyner adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, 7758eb6488eSEric Joyner ixgbe_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST); 7768eb6488eSEric Joyner 7778eb6488eSEric Joyner /* Verify adapter fan is still functional (if applicable) */ 7788eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) { 7798eb6488eSEric Joyner u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 7808eb6488eSEric Joyner ixgbe_check_fan_failure(adapter, esdp, FALSE); 7818eb6488eSEric Joyner } 7828eb6488eSEric Joyner 7838eb6488eSEric Joyner /* Ensure SW/FW semaphore is free */ 7848eb6488eSEric Joyner ixgbe_init_swfw_semaphore(hw); 7858eb6488eSEric Joyner 7868eb6488eSEric Joyner /* Enable EEE power saving */ 7878eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_EEE) 7888eb6488eSEric Joyner hw->mac.ops.setup_eee(hw, TRUE); 7898eb6488eSEric Joyner 7908eb6488eSEric Joyner /* Set an initial default flow control value */ 7918eb6488eSEric Joyner hw->fc.requested_mode = ixgbe_flow_control; 7928eb6488eSEric Joyner 7938eb6488eSEric Joyner /* Sysctls for limiting the amount of work done in the taskqueues */ 7948eb6488eSEric Joyner ixgbe_set_sysctl_value(adapter, "rx_processing_limit", 7958eb6488eSEric Joyner "max number of rx packets to process", 7968eb6488eSEric Joyner &adapter->rx_process_limit, ixgbe_rx_process_limit); 7978eb6488eSEric Joyner 7988eb6488eSEric Joyner ixgbe_set_sysctl_value(adapter, "tx_processing_limit", 7998eb6488eSEric Joyner "max number of tx packets to process", 8008eb6488eSEric Joyner &adapter->tx_process_limit, ixgbe_tx_process_limit); 8018eb6488eSEric Joyner 8028eb6488eSEric Joyner /* Do descriptor calc and sanity checks */ 8038eb6488eSEric Joyner if (((ixgbe_txd * sizeof(union ixgbe_adv_tx_desc)) % DBA_ALIGN) != 0 || 8048eb6488eSEric Joyner ixgbe_txd < MIN_TXD || ixgbe_txd > MAX_TXD) { 8058eb6488eSEric Joyner device_printf(dev, "TXD config issue, using default!\n"); 8068eb6488eSEric Joyner adapter->num_tx_desc = DEFAULT_TXD; 8078eb6488eSEric Joyner } else 8088eb6488eSEric Joyner adapter->num_tx_desc = ixgbe_txd; 8098eb6488eSEric Joyner 810758cc3dcSJack F Vogel /* 8118eb6488eSEric Joyner * With many RX rings it is easy to exceed the 8128eb6488eSEric Joyner * system mbuf allocation. Tuning nmbclusters 8138eb6488eSEric Joyner * can alleviate this. 814758cc3dcSJack F Vogel */ 8158eb6488eSEric Joyner if (nmbclusters > 0) { 8168eb6488eSEric Joyner int s; 8178eb6488eSEric Joyner s = (ixgbe_rxd * adapter->num_queues) * ixgbe_total_ports; 8188eb6488eSEric Joyner if (s > nmbclusters) { 8198eb6488eSEric Joyner device_printf(dev, "RX Descriptors exceed system mbuf max, using default instead!\n"); 8208eb6488eSEric Joyner ixgbe_rxd = DEFAULT_RXD; 8218eb6488eSEric Joyner } 822758cc3dcSJack F Vogel } 823758cc3dcSJack F Vogel 8248eb6488eSEric Joyner if (((ixgbe_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 || 8258eb6488eSEric Joyner ixgbe_rxd < MIN_RXD || ixgbe_rxd > MAX_RXD) { 8268eb6488eSEric Joyner device_printf(dev, "RXD config issue, using default!\n"); 8278eb6488eSEric Joyner adapter->num_rx_desc = DEFAULT_RXD; 8288eb6488eSEric Joyner } else 8298eb6488eSEric Joyner adapter->num_rx_desc = ixgbe_rxd; 8308eb6488eSEric Joyner 8318eb6488eSEric Joyner /* Allocate our TX/RX Queues */ 8328eb6488eSEric Joyner if (ixgbe_allocate_queues(adapter)) { 8338eb6488eSEric Joyner error = ENOMEM; 8348eb6488eSEric Joyner goto err_out; 8358eb6488eSEric Joyner } 8368eb6488eSEric Joyner 8378eb6488eSEric Joyner hw->phy.reset_if_overtemp = TRUE; 8388eb6488eSEric Joyner error = ixgbe_reset_hw(hw); 8398eb6488eSEric Joyner hw->phy.reset_if_overtemp = FALSE; 8408eb6488eSEric Joyner if (error == IXGBE_ERR_SFP_NOT_PRESENT) { 841758cc3dcSJack F Vogel /* 8428eb6488eSEric Joyner * No optics in this port, set up 8438eb6488eSEric Joyner * so the timer routine will probe 8448eb6488eSEric Joyner * for later insertion. 845758cc3dcSJack F Vogel */ 8468eb6488eSEric Joyner adapter->sfp_probe = TRUE; 8478eb6488eSEric Joyner error = IXGBE_SUCCESS; 8488eb6488eSEric Joyner } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) { 8498eb6488eSEric Joyner device_printf(dev, "Unsupported SFP+ module detected!\n"); 8508eb6488eSEric Joyner error = EIO; 8518eb6488eSEric Joyner goto err_late; 8528eb6488eSEric Joyner } else if (error) { 8538eb6488eSEric Joyner device_printf(dev, "Hardware initialization failed\n"); 8548eb6488eSEric Joyner error = EIO; 8558eb6488eSEric Joyner goto err_late; 85697f9586eSSean Bruno } 85797f9586eSSean Bruno 8588eb6488eSEric Joyner /* Make sure we have a good EEPROM before we read from it */ 8598eb6488eSEric Joyner if (ixgbe_validate_eeprom_checksum(&adapter->hw, NULL) < 0) { 8608eb6488eSEric Joyner device_printf(dev, "The EEPROM Checksum Is Not Valid\n"); 8618eb6488eSEric Joyner error = EIO; 8628eb6488eSEric Joyner goto err_late; 86397f9586eSSean Bruno } 86497f9586eSSean Bruno 8658eb6488eSEric Joyner /* Setup OS specific network interface */ 8668eb6488eSEric Joyner if (ixgbe_setup_interface(dev, adapter) != 0) 8678eb6488eSEric Joyner goto err_late; 86897f9586eSSean Bruno 8698eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_MSIX) 8708eb6488eSEric Joyner error = ixgbe_allocate_msix(adapter); 8718eb6488eSEric Joyner else 8728eb6488eSEric Joyner error = ixgbe_allocate_legacy(adapter); 8738eb6488eSEric Joyner if (error) 8748eb6488eSEric Joyner goto err_late; 87548056c88SJack F Vogel 8768eb6488eSEric Joyner error = ixgbe_start_hw(hw); 8778eb6488eSEric Joyner switch (error) { 8788eb6488eSEric Joyner case IXGBE_ERR_EEPROM_VERSION: 8798eb6488eSEric Joyner device_printf(dev, "This device is a pre-production adapter/LOM. Please be aware there may be issues associated with your hardware.\nIf you are experiencing problems please contact your Intel or hardware representative who provided you with this hardware.\n"); 88097f9586eSSean Bruno break; 8818eb6488eSEric Joyner case IXGBE_ERR_SFP_NOT_SUPPORTED: 8828eb6488eSEric Joyner device_printf(dev, "Unsupported SFP+ Module\n"); 8838eb6488eSEric Joyner error = EIO; 8848eb6488eSEric Joyner goto err_late; 8858eb6488eSEric Joyner case IXGBE_ERR_SFP_NOT_PRESENT: 8868eb6488eSEric Joyner device_printf(dev, "No SFP+ Module found\n"); 8878eb6488eSEric Joyner /* falls thru */ 88897f9586eSSean Bruno default: 88997f9586eSSean Bruno break; 89097f9586eSSean Bruno } 89197f9586eSSean Bruno 8928eb6488eSEric Joyner /* Enable the optics for 82599 SFP+ fiber */ 8938eb6488eSEric Joyner ixgbe_enable_tx_laser(hw); 894758cc3dcSJack F Vogel 8958eb6488eSEric Joyner /* Enable power to the phy. */ 8968eb6488eSEric Joyner ixgbe_set_phy_power(hw, TRUE); 8978eb6488eSEric Joyner 8988eb6488eSEric Joyner /* Initialize statistics */ 8998eb6488eSEric Joyner ixgbe_update_stats_counters(adapter); 9008eb6488eSEric Joyner 9018eb6488eSEric Joyner /* Check PCIE slot type/speed/width */ 9028eb6488eSEric Joyner ixgbe_get_slot_info(adapter); 903758cc3dcSJack F Vogel 904758cc3dcSJack F Vogel /* 9058eb6488eSEric Joyner * Do time init and sysctl init here, but 9068eb6488eSEric Joyner * only on the first port of a bypass adapter. 907758cc3dcSJack F Vogel */ 9088eb6488eSEric Joyner ixgbe_bypass_init(adapter); 909758cc3dcSJack F Vogel 9108eb6488eSEric Joyner /* Set an initial dmac value */ 9118eb6488eSEric Joyner adapter->dmac = 0; 9128eb6488eSEric Joyner /* Set initial advertised speeds (if applicable) */ 9138eb6488eSEric Joyner adapter->advertise = ixgbe_get_advertise(adapter); 914758cc3dcSJack F Vogel 9158eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_SRIOV) 9168eb6488eSEric Joyner ixgbe_define_iov_schemas(dev, &error); 917758cc3dcSJack F Vogel 9188eb6488eSEric Joyner /* Add sysctls */ 9198eb6488eSEric Joyner ixgbe_add_device_sysctls(adapter); 9208eb6488eSEric Joyner ixgbe_add_hw_stats(adapter); 921758cc3dcSJack F Vogel 9228eb6488eSEric Joyner /* For Netmap */ 9238eb6488eSEric Joyner adapter->init_locked = ixgbe_init_locked; 9248eb6488eSEric Joyner adapter->stop_locked = ixgbe_stop; 9256f37f232SEric Joyner 9268eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_NETMAP) 9278eb6488eSEric Joyner ixgbe_netmap_attach(adapter); 9286f37f232SEric Joyner 9298eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_attach: end"); 930758cc3dcSJack F Vogel 9318eb6488eSEric Joyner return (0); 932758cc3dcSJack F Vogel 9338eb6488eSEric Joyner err_late: 9348eb6488eSEric Joyner ixgbe_free_transmit_structures(adapter); 9358eb6488eSEric Joyner ixgbe_free_receive_structures(adapter); 9368eb6488eSEric Joyner free(adapter->queues, M_DEVBUF); 9378eb6488eSEric Joyner err_out: 9388eb6488eSEric Joyner if (adapter->ifp != NULL) 9398eb6488eSEric Joyner if_free(adapter->ifp); 9408eb6488eSEric Joyner ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); 9418eb6488eSEric Joyner ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD; 9428eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext); 9438eb6488eSEric Joyner ixgbe_free_pci_resources(adapter); 9448eb6488eSEric Joyner free(adapter->mta, M_IXGBE); 9458eb6488eSEric Joyner IXGBE_CORE_LOCK_DESTROY(adapter); 9468eb6488eSEric Joyner 9478eb6488eSEric Joyner return (error); 9488eb6488eSEric Joyner } /* ixgbe_attach */ 9498eb6488eSEric Joyner 9508eb6488eSEric Joyner /************************************************************************ 9518eb6488eSEric Joyner * ixgbe_check_wol_support 9526f37f232SEric Joyner * 9536f37f232SEric Joyner * Checks whether the adapter's ports are capable of 9546f37f232SEric Joyner * Wake On LAN by reading the adapter's NVM. 9556f37f232SEric Joyner * 9566f37f232SEric Joyner * Sets each port's hw->wol_enabled value depending 9576f37f232SEric Joyner * on the value read here. 9588eb6488eSEric Joyner ************************************************************************/ 9596f37f232SEric Joyner static void 9606f37f232SEric Joyner ixgbe_check_wol_support(struct adapter *adapter) 9616f37f232SEric Joyner { 9626f37f232SEric Joyner struct ixgbe_hw *hw = &adapter->hw; 9636f37f232SEric Joyner u16 dev_caps = 0; 9646f37f232SEric Joyner 9656f37f232SEric Joyner /* Find out WoL support for port */ 9666f37f232SEric Joyner adapter->wol_support = hw->wol_enabled = 0; 9676f37f232SEric Joyner ixgbe_get_device_caps(hw, &dev_caps); 9686f37f232SEric Joyner if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) || 9696f37f232SEric Joyner ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) && 9706f37f232SEric Joyner hw->bus.func == 0)) 9716f37f232SEric Joyner adapter->wol_support = hw->wol_enabled = 1; 9726f37f232SEric Joyner 9736f37f232SEric Joyner /* Save initial wake up filter configuration */ 9746f37f232SEric Joyner adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC); 9756f37f232SEric Joyner 9766f37f232SEric Joyner return; 9778eb6488eSEric Joyner } /* ixgbe_check_wol_support */ 9786f37f232SEric Joyner 9798eb6488eSEric Joyner /************************************************************************ 9808eb6488eSEric Joyner * ixgbe_setup_interface 9818eb6488eSEric Joyner * 9828eb6488eSEric Joyner * Setup networking device structure and register an interface. 9838eb6488eSEric Joyner ************************************************************************/ 9846f37f232SEric Joyner static int 9858eb6488eSEric Joyner ixgbe_setup_interface(device_t dev, struct adapter *adapter) 9866f37f232SEric Joyner { 9878eb6488eSEric Joyner struct ifnet *ifp; 9886f37f232SEric Joyner 9898eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_setup_interface: begin"); 9906f37f232SEric Joyner 9918eb6488eSEric Joyner ifp = adapter->ifp = if_alloc(IFT_ETHER); 9928eb6488eSEric Joyner if (ifp == NULL) { 9938eb6488eSEric Joyner device_printf(dev, "can not allocate ifnet structure\n"); 9948eb6488eSEric Joyner return (-1); 9958eb6488eSEric Joyner } 9968eb6488eSEric Joyner if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 9978eb6488eSEric Joyner ifp->if_baudrate = IF_Gbps(10); 9988eb6488eSEric Joyner ifp->if_init = ixgbe_init; 9998eb6488eSEric Joyner ifp->if_softc = adapter; 10008eb6488eSEric Joyner ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 10018eb6488eSEric Joyner ifp->if_ioctl = ixgbe_ioctl; 10028eb6488eSEric Joyner #if __FreeBSD_version >= 1100036 10038eb6488eSEric Joyner if_setgetcounterfn(ifp, ixgbe_get_counter); 10048eb6488eSEric Joyner #endif 10058eb6488eSEric Joyner #if __FreeBSD_version >= 1100045 10068eb6488eSEric Joyner /* TSO parameters */ 10078eb6488eSEric Joyner ifp->if_hw_tsomax = 65518; 10088eb6488eSEric Joyner ifp->if_hw_tsomaxsegcount = IXGBE_82599_SCATTER; 10098eb6488eSEric Joyner ifp->if_hw_tsomaxsegsize = 2048; 10108eb6488eSEric Joyner #endif 10118eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_LEGACY_TX) { 10128eb6488eSEric Joyner ifp->if_start = ixgbe_legacy_start; 10138eb6488eSEric Joyner IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 2); 10148eb6488eSEric Joyner ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 2; 10158eb6488eSEric Joyner IFQ_SET_READY(&ifp->if_snd); 10168eb6488eSEric Joyner ixgbe_start_locked = ixgbe_legacy_start_locked; 10178eb6488eSEric Joyner ixgbe_ring_empty = ixgbe_legacy_ring_empty; 10186f37f232SEric Joyner } else { 10198eb6488eSEric Joyner ifp->if_transmit = ixgbe_mq_start; 10208eb6488eSEric Joyner ifp->if_qflush = ixgbe_qflush; 10218eb6488eSEric Joyner ixgbe_start_locked = ixgbe_mq_start_locked; 10228eb6488eSEric Joyner ixgbe_ring_empty = drbr_empty; 10236f37f232SEric Joyner } 10246f37f232SEric Joyner 10258eb6488eSEric Joyner ether_ifattach(ifp, adapter->hw.mac.addr); 10266f37f232SEric Joyner 10278eb6488eSEric Joyner adapter->max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; 1028758cc3dcSJack F Vogel 1029758cc3dcSJack F Vogel /* 10308eb6488eSEric Joyner * Tell the upper layer(s) we support long frames. 1031758cc3dcSJack F Vogel */ 10328eb6488eSEric Joyner ifp->if_hdrlen = sizeof(struct ether_vlan_header); 1033758cc3dcSJack F Vogel 10348eb6488eSEric Joyner /* Set capability flags */ 10358eb6488eSEric Joyner ifp->if_capabilities |= IFCAP_HWCSUM 10368eb6488eSEric Joyner | IFCAP_HWCSUM_IPV6 10378eb6488eSEric Joyner | IFCAP_TSO 10388eb6488eSEric Joyner | IFCAP_LRO 10398eb6488eSEric Joyner | IFCAP_VLAN_HWTAGGING 10408eb6488eSEric Joyner | IFCAP_VLAN_HWTSO 10418eb6488eSEric Joyner | IFCAP_VLAN_HWCSUM 10428eb6488eSEric Joyner | IFCAP_JUMBO_MTU 10438eb6488eSEric Joyner | IFCAP_VLAN_MTU 10448eb6488eSEric Joyner | IFCAP_HWSTATS; 1045758cc3dcSJack F Vogel 10468eb6488eSEric Joyner /* Enable the above capabilities by default */ 10478eb6488eSEric Joyner ifp->if_capenable = ifp->if_capabilities; 1048758cc3dcSJack F Vogel 10498eb6488eSEric Joyner /* 10508eb6488eSEric Joyner * Don't turn this on by default, if vlans are 10518eb6488eSEric Joyner * created on another pseudo device (eg. lagg) 10528eb6488eSEric Joyner * then vlan events are not passed thru, breaking 10538eb6488eSEric Joyner * operation, but with HW FILTER off it works. If 10548eb6488eSEric Joyner * using vlans directly on the ixgbe driver you can 10558eb6488eSEric Joyner * enable this and get full hardware tag filtering. 10568eb6488eSEric Joyner */ 10578eb6488eSEric Joyner ifp->if_capabilities |= IFCAP_VLAN_HWFILTER; 1058758cc3dcSJack F Vogel 10598eb6488eSEric Joyner /* 10608eb6488eSEric Joyner * Specify the media types supported by this adapter and register 10618eb6488eSEric Joyner * callbacks to update media and link information 10628eb6488eSEric Joyner */ 10638eb6488eSEric Joyner ifmedia_init(&adapter->media, IFM_IMASK, ixgbe_media_change, 10648eb6488eSEric Joyner ixgbe_media_status); 1065758cc3dcSJack F Vogel 10668eb6488eSEric Joyner adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw); 10678eb6488eSEric Joyner ixgbe_add_media_types(adapter); 10688eb6488eSEric Joyner 10698eb6488eSEric Joyner /* Set autoselect media by default */ 10708eb6488eSEric Joyner ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); 10718eb6488eSEric Joyner 10728eb6488eSEric Joyner return (0); 10738eb6488eSEric Joyner } /* ixgbe_setup_interface */ 1074758cc3dcSJack F Vogel 1075758cc3dcSJack F Vogel #if __FreeBSD_version >= 1100036 10768eb6488eSEric Joyner /************************************************************************ 10778eb6488eSEric Joyner * ixgbe_get_counter 10788eb6488eSEric Joyner ************************************************************************/ 1079758cc3dcSJack F Vogel static uint64_t 1080758cc3dcSJack F Vogel ixgbe_get_counter(struct ifnet *ifp, ift_counter cnt) 1081758cc3dcSJack F Vogel { 1082758cc3dcSJack F Vogel struct adapter *adapter; 1083625d12c6SJohn Baldwin struct tx_ring *txr; 1084625d12c6SJohn Baldwin uint64_t rv; 1085758cc3dcSJack F Vogel 1086758cc3dcSJack F Vogel adapter = if_getsoftc(ifp); 1087758cc3dcSJack F Vogel 1088758cc3dcSJack F Vogel switch (cnt) { 1089758cc3dcSJack F Vogel case IFCOUNTER_IPACKETS: 1090758cc3dcSJack F Vogel return (adapter->ipackets); 1091758cc3dcSJack F Vogel case IFCOUNTER_OPACKETS: 1092758cc3dcSJack F Vogel return (adapter->opackets); 1093758cc3dcSJack F Vogel case IFCOUNTER_IBYTES: 1094758cc3dcSJack F Vogel return (adapter->ibytes); 1095758cc3dcSJack F Vogel case IFCOUNTER_OBYTES: 1096758cc3dcSJack F Vogel return (adapter->obytes); 1097758cc3dcSJack F Vogel case IFCOUNTER_IMCASTS: 1098758cc3dcSJack F Vogel return (adapter->imcasts); 1099758cc3dcSJack F Vogel case IFCOUNTER_OMCASTS: 1100758cc3dcSJack F Vogel return (adapter->omcasts); 1101758cc3dcSJack F Vogel case IFCOUNTER_COLLISIONS: 1102758cc3dcSJack F Vogel return (0); 1103758cc3dcSJack F Vogel case IFCOUNTER_IQDROPS: 1104758cc3dcSJack F Vogel return (adapter->iqdrops); 1105625d12c6SJohn Baldwin case IFCOUNTER_OQDROPS: 1106625d12c6SJohn Baldwin rv = 0; 1107625d12c6SJohn Baldwin txr = adapter->tx_rings; 1108625d12c6SJohn Baldwin for (int i = 0; i < adapter->num_queues; i++, txr++) 1109625d12c6SJohn Baldwin rv += txr->br->br_drops; 1110625d12c6SJohn Baldwin return (rv); 1111758cc3dcSJack F Vogel case IFCOUNTER_IERRORS: 1112758cc3dcSJack F Vogel return (adapter->ierrors); 1113758cc3dcSJack F Vogel default: 1114758cc3dcSJack F Vogel return (if_get_counter_default(ifp, cnt)); 1115758cc3dcSJack F Vogel } 11168eb6488eSEric Joyner } /* ixgbe_get_counter */ 1117758cc3dcSJack F Vogel #endif 1118758cc3dcSJack F Vogel 11198eb6488eSEric Joyner /************************************************************************ 11208eb6488eSEric Joyner * ixgbe_add_media_types 11218eb6488eSEric Joyner ************************************************************************/ 11228eb6488eSEric Joyner static void 11238eb6488eSEric Joyner ixgbe_add_media_types(struct adapter *adapter) 11248eb6488eSEric Joyner { 11258eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 11268eb6488eSEric Joyner device_t dev = adapter->dev; 11278eb6488eSEric Joyner u64 layer; 11288eb6488eSEric Joyner 11298eb6488eSEric Joyner layer = adapter->phy_layer; 11308eb6488eSEric Joyner 11318eb6488eSEric Joyner /* Media types with matching FreeBSD media defines */ 11328eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) 11338eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_T, 0, NULL); 11348eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) 11358eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL); 11368eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) 11378eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX, 0, NULL); 11388eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T) 11398eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T, 0, NULL); 11408eb6488eSEric Joyner 11418eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || 11428eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) 11438eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_TWINAX, 0, 11448eb6488eSEric Joyner NULL); 11458eb6488eSEric Joyner 11468eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) { 11478eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_LR, 0, NULL); 11488eb6488eSEric Joyner if (hw->phy.multispeed_fiber) 11498eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_LX, 0, 11508eb6488eSEric Joyner NULL); 11518eb6488eSEric Joyner } 11528eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) { 11538eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL); 11548eb6488eSEric Joyner if (hw->phy.multispeed_fiber) 11558eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, 11568eb6488eSEric Joyner NULL); 11578eb6488eSEric Joyner } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) 11588eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL); 11598eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) 11608eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); 11618eb6488eSEric Joyner 11628eb6488eSEric Joyner #ifdef IFM_ETH_XTYPE 11638eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 11648eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KR, 0, NULL); 11658eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) 11668eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KX4, 0, NULL); 11678eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 11688eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_KX, 0, NULL); 11698eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) 11708eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_2500_KX, 0, NULL); 11718eb6488eSEric Joyner #else 11728eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) { 11738eb6488eSEric Joyner device_printf(dev, "Media supported: 10GbaseKR\n"); 11748eb6488eSEric Joyner device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n"); 11758eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL); 11768eb6488eSEric Joyner } 11778eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) { 11788eb6488eSEric Joyner device_printf(dev, "Media supported: 10GbaseKX4\n"); 11798eb6488eSEric Joyner device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n"); 11808eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); 11818eb6488eSEric Joyner } 11828eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) { 11838eb6488eSEric Joyner device_printf(dev, "Media supported: 1000baseKX\n"); 11848eb6488eSEric Joyner device_printf(dev, "1000baseKX mapped to 1000baseCX\n"); 11858eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_CX, 0, NULL); 11868eb6488eSEric Joyner } 11878eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) { 11888eb6488eSEric Joyner device_printf(dev, "Media supported: 2500baseKX\n"); 11898eb6488eSEric Joyner device_printf(dev, "2500baseKX mapped to 2500baseSX\n"); 11908eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_2500_SX, 0, NULL); 11918eb6488eSEric Joyner } 11928eb6488eSEric Joyner #endif 11938eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) 11948eb6488eSEric Joyner device_printf(dev, "Media supported: 1000baseBX\n"); 11958eb6488eSEric Joyner 11968eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_82598AT) { 11978eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 11988eb6488eSEric Joyner 0, NULL); 11998eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL); 12008eb6488eSEric Joyner } 12018eb6488eSEric Joyner 12028eb6488eSEric Joyner ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); 12038eb6488eSEric Joyner } /* ixgbe_add_media_types */ 12048eb6488eSEric Joyner 12058eb6488eSEric Joyner /************************************************************************ 12068eb6488eSEric Joyner * ixgbe_is_sfp 12078eb6488eSEric Joyner ************************************************************************/ 12088eb6488eSEric Joyner static inline bool 12098eb6488eSEric Joyner ixgbe_is_sfp(struct ixgbe_hw *hw) 12108eb6488eSEric Joyner { 12118eb6488eSEric Joyner switch (hw->mac.type) { 12128eb6488eSEric Joyner case ixgbe_mac_82598EB: 12138eb6488eSEric Joyner if (hw->phy.type == ixgbe_phy_nl) 12148eb6488eSEric Joyner return TRUE; 12158eb6488eSEric Joyner return FALSE; 12168eb6488eSEric Joyner case ixgbe_mac_82599EB: 12178eb6488eSEric Joyner switch (hw->mac.ops.get_media_type(hw)) { 12188eb6488eSEric Joyner case ixgbe_media_type_fiber: 12198eb6488eSEric Joyner case ixgbe_media_type_fiber_qsfp: 12208eb6488eSEric Joyner return TRUE; 12218eb6488eSEric Joyner default: 12228eb6488eSEric Joyner return FALSE; 12238eb6488eSEric Joyner } 12248eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 12258eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 12268eb6488eSEric Joyner if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) 12278eb6488eSEric Joyner return TRUE; 12288eb6488eSEric Joyner return FALSE; 12298eb6488eSEric Joyner default: 12308eb6488eSEric Joyner return FALSE; 12318eb6488eSEric Joyner } 12328eb6488eSEric Joyner } /* ixgbe_is_sfp */ 12338eb6488eSEric Joyner 12348eb6488eSEric Joyner /************************************************************************ 12358eb6488eSEric Joyner * ixgbe_config_link 12368eb6488eSEric Joyner ************************************************************************/ 12378eb6488eSEric Joyner static void 12388eb6488eSEric Joyner ixgbe_config_link(struct adapter *adapter) 12398eb6488eSEric Joyner { 12408eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 12418eb6488eSEric Joyner u32 autoneg, err = 0; 12428eb6488eSEric Joyner bool sfp, negotiate; 12438eb6488eSEric Joyner 12448eb6488eSEric Joyner sfp = ixgbe_is_sfp(hw); 12458eb6488eSEric Joyner 12468eb6488eSEric Joyner if (sfp) { 12478eb6488eSEric Joyner if (hw->phy.multispeed_fiber) { 12488eb6488eSEric Joyner hw->mac.ops.setup_sfp(hw); 12498eb6488eSEric Joyner ixgbe_enable_tx_laser(hw); 12508eb6488eSEric Joyner taskqueue_enqueue(adapter->tq, &adapter->msf_task); 12518eb6488eSEric Joyner } else 12528eb6488eSEric Joyner taskqueue_enqueue(adapter->tq, &adapter->mod_task); 12538eb6488eSEric Joyner } else { 12548eb6488eSEric Joyner if (hw->mac.ops.check_link) 12558eb6488eSEric Joyner err = ixgbe_check_link(hw, &adapter->link_speed, 12568eb6488eSEric Joyner &adapter->link_up, FALSE); 12578eb6488eSEric Joyner if (err) 12588eb6488eSEric Joyner goto out; 12598eb6488eSEric Joyner autoneg = hw->phy.autoneg_advertised; 12608eb6488eSEric Joyner if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) 12618eb6488eSEric Joyner err = hw->mac.ops.get_link_capabilities(hw, &autoneg, 12628eb6488eSEric Joyner &negotiate); 12638eb6488eSEric Joyner if (err) 12648eb6488eSEric Joyner goto out; 12658eb6488eSEric Joyner if (hw->mac.ops.setup_link) 12668eb6488eSEric Joyner err = hw->mac.ops.setup_link(hw, autoneg, 12678eb6488eSEric Joyner adapter->link_up); 12688eb6488eSEric Joyner } 12698eb6488eSEric Joyner out: 12708eb6488eSEric Joyner 12718eb6488eSEric Joyner return; 12728eb6488eSEric Joyner } /* ixgbe_config_link */ 12738eb6488eSEric Joyner 12748eb6488eSEric Joyner /************************************************************************ 12758eb6488eSEric Joyner * ixgbe_update_stats_counters - Update board statistics counters. 12768eb6488eSEric Joyner ************************************************************************/ 12778eb6488eSEric Joyner static void 12788eb6488eSEric Joyner ixgbe_update_stats_counters(struct adapter *adapter) 12798eb6488eSEric Joyner { 12808eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 12818eb6488eSEric Joyner struct ixgbe_hw_stats *stats = &adapter->stats.pf; 12828eb6488eSEric Joyner u32 missed_rx = 0, bprc, lxon, lxoff, total; 12838eb6488eSEric Joyner u64 total_missed_rx = 0; 12848eb6488eSEric Joyner 12858eb6488eSEric Joyner stats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); 12868eb6488eSEric Joyner stats->illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC); 12878eb6488eSEric Joyner stats->errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC); 12888eb6488eSEric Joyner stats->mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC); 12898eb6488eSEric Joyner stats->mpc[0] += IXGBE_READ_REG(hw, IXGBE_MPC(0)); 12908eb6488eSEric Joyner 12918eb6488eSEric Joyner for (int i = 0; i < 16; i++) { 12928eb6488eSEric Joyner stats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 12938eb6488eSEric Joyner stats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 12948eb6488eSEric Joyner stats->qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); 12958eb6488eSEric Joyner } 12968eb6488eSEric Joyner stats->mlfc += IXGBE_READ_REG(hw, IXGBE_MLFC); 12978eb6488eSEric Joyner stats->mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC); 12988eb6488eSEric Joyner stats->rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); 12998eb6488eSEric Joyner 13008eb6488eSEric Joyner /* Hardware workaround, gprc counts missed packets */ 13018eb6488eSEric Joyner stats->gprc += IXGBE_READ_REG(hw, IXGBE_GPRC); 13028eb6488eSEric Joyner stats->gprc -= missed_rx; 13038eb6488eSEric Joyner 13048eb6488eSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) { 13058eb6488eSEric Joyner stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL) + 13068eb6488eSEric Joyner ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32); 13078eb6488eSEric Joyner stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL) + 13088eb6488eSEric Joyner ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32); 13098eb6488eSEric Joyner stats->tor += IXGBE_READ_REG(hw, IXGBE_TORL) + 13108eb6488eSEric Joyner ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32); 13118eb6488eSEric Joyner stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 13128eb6488eSEric Joyner stats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 13138eb6488eSEric Joyner } else { 13148eb6488eSEric Joyner stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); 13158eb6488eSEric Joyner stats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 13168eb6488eSEric Joyner /* 82598 only has a counter in the high register */ 13178eb6488eSEric Joyner stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); 13188eb6488eSEric Joyner stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); 13198eb6488eSEric Joyner stats->tor += IXGBE_READ_REG(hw, IXGBE_TORH); 13208eb6488eSEric Joyner } 13218eb6488eSEric Joyner 13228eb6488eSEric Joyner /* 13238eb6488eSEric Joyner * Workaround: mprc hardware is incorrectly counting 13248eb6488eSEric Joyner * broadcasts, so for now we subtract those. 1325758cc3dcSJack F Vogel */ 13268eb6488eSEric Joyner bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); 13278eb6488eSEric Joyner stats->bprc += bprc; 13288eb6488eSEric Joyner stats->mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); 13298eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 13308eb6488eSEric Joyner stats->mprc -= bprc; 13318eb6488eSEric Joyner 13328eb6488eSEric Joyner stats->prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64); 13338eb6488eSEric Joyner stats->prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127); 13348eb6488eSEric Joyner stats->prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255); 13358eb6488eSEric Joyner stats->prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511); 13368eb6488eSEric Joyner stats->prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023); 13378eb6488eSEric Joyner stats->prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522); 13388eb6488eSEric Joyner 13398eb6488eSEric Joyner lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC); 13408eb6488eSEric Joyner stats->lxontxc += lxon; 13418eb6488eSEric Joyner lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 13428eb6488eSEric Joyner stats->lxofftxc += lxoff; 13438eb6488eSEric Joyner total = lxon + lxoff; 13448eb6488eSEric Joyner 13458eb6488eSEric Joyner stats->gptc += IXGBE_READ_REG(hw, IXGBE_GPTC); 13468eb6488eSEric Joyner stats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC); 13478eb6488eSEric Joyner stats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64); 13488eb6488eSEric Joyner stats->gptc -= total; 13498eb6488eSEric Joyner stats->mptc -= total; 13508eb6488eSEric Joyner stats->ptc64 -= total; 13518eb6488eSEric Joyner stats->gotc -= total * ETHER_MIN_LEN; 13528eb6488eSEric Joyner 13538eb6488eSEric Joyner stats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC); 13548eb6488eSEric Joyner stats->rfc += IXGBE_READ_REG(hw, IXGBE_RFC); 13558eb6488eSEric Joyner stats->roc += IXGBE_READ_REG(hw, IXGBE_ROC); 13568eb6488eSEric Joyner stats->rjc += IXGBE_READ_REG(hw, IXGBE_RJC); 13578eb6488eSEric Joyner stats->mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC); 13588eb6488eSEric Joyner stats->mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC); 13598eb6488eSEric Joyner stats->mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC); 13608eb6488eSEric Joyner stats->tpr += IXGBE_READ_REG(hw, IXGBE_TPR); 13618eb6488eSEric Joyner stats->tpt += IXGBE_READ_REG(hw, IXGBE_TPT); 13628eb6488eSEric Joyner stats->ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127); 13638eb6488eSEric Joyner stats->ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255); 13648eb6488eSEric Joyner stats->ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511); 13658eb6488eSEric Joyner stats->ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023); 13668eb6488eSEric Joyner stats->ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522); 13678eb6488eSEric Joyner stats->bptc += IXGBE_READ_REG(hw, IXGBE_BPTC); 13688eb6488eSEric Joyner stats->xec += IXGBE_READ_REG(hw, IXGBE_XEC); 13698eb6488eSEric Joyner stats->fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC); 13708eb6488eSEric Joyner stats->fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST); 13718eb6488eSEric Joyner /* Only read FCOE on 82599 */ 13728eb6488eSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) { 13738eb6488eSEric Joyner stats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC); 13748eb6488eSEric Joyner stats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC); 13758eb6488eSEric Joyner stats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC); 13768eb6488eSEric Joyner stats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC); 13778eb6488eSEric Joyner stats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC); 13788eb6488eSEric Joyner } 13798eb6488eSEric Joyner 13808eb6488eSEric Joyner /* Fill out the OS statistics structure */ 13818eb6488eSEric Joyner IXGBE_SET_IPACKETS(adapter, stats->gprc); 13828eb6488eSEric Joyner IXGBE_SET_OPACKETS(adapter, stats->gptc); 13838eb6488eSEric Joyner IXGBE_SET_IBYTES(adapter, stats->gorc); 13848eb6488eSEric Joyner IXGBE_SET_OBYTES(adapter, stats->gotc); 13858eb6488eSEric Joyner IXGBE_SET_IMCASTS(adapter, stats->mprc); 13868eb6488eSEric Joyner IXGBE_SET_OMCASTS(adapter, stats->mptc); 13878eb6488eSEric Joyner IXGBE_SET_COLLISIONS(adapter, 0); 13888eb6488eSEric Joyner IXGBE_SET_IQDROPS(adapter, total_missed_rx); 13898eb6488eSEric Joyner IXGBE_SET_IERRORS(adapter, stats->crcerrs + stats->rlec); 13908eb6488eSEric Joyner } /* ixgbe_update_stats_counters */ 13918eb6488eSEric Joyner 13928eb6488eSEric Joyner /************************************************************************ 13938eb6488eSEric Joyner * ixgbe_add_hw_stats 13948eb6488eSEric Joyner * 13958eb6488eSEric Joyner * Add sysctl variables, one per statistic, to the system. 13968eb6488eSEric Joyner ************************************************************************/ 13978eb6488eSEric Joyner static void 13988eb6488eSEric Joyner ixgbe_add_hw_stats(struct adapter *adapter) 13998eb6488eSEric Joyner { 14008eb6488eSEric Joyner device_t dev = adapter->dev; 14018eb6488eSEric Joyner struct tx_ring *txr = adapter->tx_rings; 14028eb6488eSEric Joyner struct rx_ring *rxr = adapter->rx_rings; 14038eb6488eSEric Joyner struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 14048eb6488eSEric Joyner struct sysctl_oid *tree = device_get_sysctl_tree(dev); 14058eb6488eSEric Joyner struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); 14068eb6488eSEric Joyner struct ixgbe_hw_stats *stats = &adapter->stats.pf; 14078eb6488eSEric Joyner struct sysctl_oid *stat_node, *queue_node; 14088eb6488eSEric Joyner struct sysctl_oid_list *stat_list, *queue_list; 14098eb6488eSEric Joyner 14108eb6488eSEric Joyner #define QUEUE_NAME_LEN 32 14118eb6488eSEric Joyner char namebuf[QUEUE_NAME_LEN]; 14128eb6488eSEric Joyner 14138eb6488eSEric Joyner /* Driver Statistics */ 14148eb6488eSEric Joyner SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", 14158eb6488eSEric Joyner CTLFLAG_RD, &adapter->dropped_pkts, "Driver dropped packets"); 14168eb6488eSEric Joyner SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_failed", 14178eb6488eSEric Joyner CTLFLAG_RD, &adapter->mbuf_defrag_failed, "m_defrag() failed"); 14188eb6488eSEric Joyner SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events", 14198eb6488eSEric Joyner CTLFLAG_RD, &adapter->watchdog_events, "Watchdog timeouts"); 14208eb6488eSEric Joyner SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq", 14218eb6488eSEric Joyner CTLFLAG_RD, &adapter->link_irq, "Link MSI-X IRQ Handled"); 14228eb6488eSEric Joyner 14238eb6488eSEric Joyner for (int i = 0; i < adapter->num_queues; i++, txr++) { 14248eb6488eSEric Joyner snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); 14258eb6488eSEric Joyner queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, 14268eb6488eSEric Joyner CTLFLAG_RD, NULL, "Queue Name"); 14278eb6488eSEric Joyner queue_list = SYSCTL_CHILDREN(queue_node); 14288eb6488eSEric Joyner 14298eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate", 14308eb6488eSEric Joyner CTLTYPE_UINT | CTLFLAG_RW, &adapter->queues[i], 14318eb6488eSEric Joyner sizeof(&adapter->queues[i]), 14328eb6488eSEric Joyner ixgbe_sysctl_interrupt_rate_handler, "IU", 14338eb6488eSEric Joyner "Interrupt Rate"); 14348eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs", 14358eb6488eSEric Joyner CTLFLAG_RD, &(adapter->queues[i].irqs), 14368eb6488eSEric Joyner "irqs on this queue"); 14378eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head", 14388eb6488eSEric Joyner CTLTYPE_UINT | CTLFLAG_RD, txr, sizeof(txr), 14398eb6488eSEric Joyner ixgbe_sysctl_tdh_handler, "IU", "Transmit Descriptor Head"); 14408eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail", 14418eb6488eSEric Joyner CTLTYPE_UINT | CTLFLAG_RD, txr, sizeof(txr), 14428eb6488eSEric Joyner ixgbe_sysctl_tdt_handler, "IU", "Transmit Descriptor Tail"); 14438eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx", 14448eb6488eSEric Joyner CTLFLAG_RD, &txr->tso_tx, "TSO"); 14458eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "no_tx_dma_setup", 14468eb6488eSEric Joyner CTLFLAG_RD, &txr->no_tx_dma_setup, 14478eb6488eSEric Joyner "Driver tx dma failure in xmit"); 14488eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "no_desc_avail", 14498eb6488eSEric Joyner CTLFLAG_RD, &txr->no_desc_avail, 14508eb6488eSEric Joyner "Queue No Descriptor Available"); 14518eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets", 14528eb6488eSEric Joyner CTLFLAG_RD, &txr->total_packets, 14538eb6488eSEric Joyner "Queue Packets Transmitted"); 14548eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "br_drops", 14558eb6488eSEric Joyner CTLFLAG_RD, &txr->br->br_drops, 14568eb6488eSEric Joyner "Packets dropped in buf_ring"); 14578eb6488eSEric Joyner } 14588eb6488eSEric Joyner 14598eb6488eSEric Joyner for (int i = 0; i < adapter->num_queues; i++, rxr++) { 14608eb6488eSEric Joyner struct lro_ctrl *lro = &rxr->lro; 14618eb6488eSEric Joyner 14628eb6488eSEric Joyner snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); 14638eb6488eSEric Joyner queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, 14648eb6488eSEric Joyner CTLFLAG_RD, NULL, "Queue Name"); 14658eb6488eSEric Joyner queue_list = SYSCTL_CHILDREN(queue_node); 14668eb6488eSEric Joyner 14678eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head", 14688eb6488eSEric Joyner CTLTYPE_UINT | CTLFLAG_RD, rxr, sizeof(rxr), 14698eb6488eSEric Joyner ixgbe_sysctl_rdh_handler, "IU", "Receive Descriptor Head"); 14708eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail", 14718eb6488eSEric Joyner CTLTYPE_UINT | CTLFLAG_RD, rxr, sizeof(rxr), 14728eb6488eSEric Joyner ixgbe_sysctl_rdt_handler, "IU", "Receive Descriptor Tail"); 14738eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets", 14748eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_packets, "Queue Packets Received"); 14758eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes", 14768eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_bytes, "Queue Bytes Received"); 14778eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_copies", 14788eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_copies, "Copied RX Frames"); 14798eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_discarded", 14808eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_discarded, "Discarded RX packets"); 14818eb6488eSEric Joyner SYSCTL_ADD_U64(ctx, queue_list, OID_AUTO, "lro_queued", 14828eb6488eSEric Joyner CTLFLAG_RD, &lro->lro_queued, 0, "LRO Queued"); 14838eb6488eSEric Joyner SYSCTL_ADD_U64(ctx, queue_list, OID_AUTO, "lro_flushed", 14848eb6488eSEric Joyner CTLFLAG_RD, &lro->lro_flushed, 0, "LRO Flushed"); 14858eb6488eSEric Joyner } 14868eb6488eSEric Joyner 14878eb6488eSEric Joyner /* MAC stats get their own sub node */ 14888eb6488eSEric Joyner 14898eb6488eSEric Joyner stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats", 14908eb6488eSEric Joyner CTLFLAG_RD, NULL, "MAC Statistics"); 14918eb6488eSEric Joyner stat_list = SYSCTL_CHILDREN(stat_node); 14928eb6488eSEric Joyner 14938eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs", 14948eb6488eSEric Joyner CTLFLAG_RD, &stats->crcerrs, "CRC Errors"); 14958eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ill_errs", 14968eb6488eSEric Joyner CTLFLAG_RD, &stats->illerrc, "Illegal Byte Errors"); 14978eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "byte_errs", 14988eb6488eSEric Joyner CTLFLAG_RD, &stats->errbc, "Byte Errors"); 14998eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "short_discards", 15008eb6488eSEric Joyner CTLFLAG_RD, &stats->mspdc, "MAC Short Packets Discarded"); 15018eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "local_faults", 15028eb6488eSEric Joyner CTLFLAG_RD, &stats->mlfc, "MAC Local Faults"); 15038eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "remote_faults", 15048eb6488eSEric Joyner CTLFLAG_RD, &stats->mrfc, "MAC Remote Faults"); 15058eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rec_len_errs", 15068eb6488eSEric Joyner CTLFLAG_RD, &stats->rlec, "Receive Length Errors"); 15078eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_missed_packets", 15088eb6488eSEric Joyner CTLFLAG_RD, &stats->mpc[0], "RX Missed Packet Count"); 15098eb6488eSEric Joyner 15108eb6488eSEric Joyner /* Flow Control stats */ 15118eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd", 15128eb6488eSEric Joyner CTLFLAG_RD, &stats->lxontxc, "Link XON Transmitted"); 15138eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd", 15148eb6488eSEric Joyner CTLFLAG_RD, &stats->lxonrxc, "Link XON Received"); 15158eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd", 15168eb6488eSEric Joyner CTLFLAG_RD, &stats->lxofftxc, "Link XOFF Transmitted"); 15178eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd", 15188eb6488eSEric Joyner CTLFLAG_RD, &stats->lxoffrxc, "Link XOFF Received"); 15198eb6488eSEric Joyner 15208eb6488eSEric Joyner /* Packet Reception Stats */ 15218eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_octets_rcvd", 15228eb6488eSEric Joyner CTLFLAG_RD, &stats->tor, "Total Octets Received"); 15238eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd", 15248eb6488eSEric Joyner CTLFLAG_RD, &stats->gorc, "Good Octets Received"); 15258eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_rcvd", 15268eb6488eSEric Joyner CTLFLAG_RD, &stats->tpr, "Total Packets Received"); 15278eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd", 15288eb6488eSEric Joyner CTLFLAG_RD, &stats->gprc, "Good Packets Received"); 15298eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd", 15308eb6488eSEric Joyner CTLFLAG_RD, &stats->mprc, "Multicast Packets Received"); 15318eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_rcvd", 15328eb6488eSEric Joyner CTLFLAG_RD, &stats->bprc, "Broadcast Packets Received"); 15338eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64", 15348eb6488eSEric Joyner CTLFLAG_RD, &stats->prc64, "64 byte frames received "); 15358eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127", 15368eb6488eSEric Joyner CTLFLAG_RD, &stats->prc127, "65-127 byte frames received"); 15378eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255", 15388eb6488eSEric Joyner CTLFLAG_RD, &stats->prc255, "128-255 byte frames received"); 15398eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511", 15408eb6488eSEric Joyner CTLFLAG_RD, &stats->prc511, "256-511 byte frames received"); 15418eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023", 15428eb6488eSEric Joyner CTLFLAG_RD, &stats->prc1023, "512-1023 byte frames received"); 15438eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522", 15448eb6488eSEric Joyner CTLFLAG_RD, &stats->prc1522, "1023-1522 byte frames received"); 15458eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersized", 15468eb6488eSEric Joyner CTLFLAG_RD, &stats->ruc, "Receive Undersized"); 15478eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented", 15488eb6488eSEric Joyner CTLFLAG_RD, &stats->rfc, "Fragmented Packets Received "); 15498eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversized", 15508eb6488eSEric Joyner CTLFLAG_RD, &stats->roc, "Oversized Packets Received"); 15518eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabberd", 15528eb6488eSEric Joyner CTLFLAG_RD, &stats->rjc, "Received Jabber"); 15538eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_rcvd", 15548eb6488eSEric Joyner CTLFLAG_RD, &stats->mngprc, "Management Packets Received"); 15558eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_drpd", 15568eb6488eSEric Joyner CTLFLAG_RD, &stats->mngptc, "Management Packets Dropped"); 15578eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "checksum_errs", 15588eb6488eSEric Joyner CTLFLAG_RD, &stats->xec, "Checksum Errors"); 15598eb6488eSEric Joyner 15608eb6488eSEric Joyner /* Packet Transmission Stats */ 15618eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd", 15628eb6488eSEric Joyner CTLFLAG_RD, &stats->gotc, "Good Octets Transmitted"); 15638eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd", 15648eb6488eSEric Joyner CTLFLAG_RD, &stats->tpt, "Total Packets Transmitted"); 15658eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd", 15668eb6488eSEric Joyner CTLFLAG_RD, &stats->gptc, "Good Packets Transmitted"); 15678eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd", 15688eb6488eSEric Joyner CTLFLAG_RD, &stats->bptc, "Broadcast Packets Transmitted"); 15698eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd", 15708eb6488eSEric Joyner CTLFLAG_RD, &stats->mptc, "Multicast Packets Transmitted"); 15718eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_txd", 15728eb6488eSEric Joyner CTLFLAG_RD, &stats->mngptc, "Management Packets Transmitted"); 15738eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64", 15748eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc64, "64 byte frames transmitted "); 15758eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127", 15768eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc127, "65-127 byte frames transmitted"); 15778eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255", 15788eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc255, "128-255 byte frames transmitted"); 15798eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511", 15808eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc511, "256-511 byte frames transmitted"); 15818eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023", 15828eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc1023, "512-1023 byte frames transmitted"); 15838eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522", 15848eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc1522, "1024-1522 byte frames transmitted"); 15858eb6488eSEric Joyner } /* ixgbe_add_hw_stats */ 15868eb6488eSEric Joyner 15878eb6488eSEric Joyner /************************************************************************ 15888eb6488eSEric Joyner * ixgbe_sysctl_tdh_handler - Transmit Descriptor Head handler function 15898eb6488eSEric Joyner * 15908eb6488eSEric Joyner * Retrieves the TDH value from the hardware 15918eb6488eSEric Joyner ************************************************************************/ 1592758cc3dcSJack F Vogel static int 1593758cc3dcSJack F Vogel ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS) 1594758cc3dcSJack F Vogel { 1595758cc3dcSJack F Vogel struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); 15968eb6488eSEric Joyner int error; 15978eb6488eSEric Joyner unsigned int val; 1598758cc3dcSJack F Vogel 15998eb6488eSEric Joyner if (!txr) 16008eb6488eSEric Joyner return (0); 16018eb6488eSEric Joyner 16028eb6488eSEric Joyner val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me)); 1603758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1604758cc3dcSJack F Vogel if (error || !req->newptr) 1605758cc3dcSJack F Vogel return error; 1606758cc3dcSJack F Vogel 16078eb6488eSEric Joyner return (0); 16088eb6488eSEric Joyner } /* ixgbe_sysctl_tdh_handler */ 16098eb6488eSEric Joyner 16108eb6488eSEric Joyner /************************************************************************ 16118eb6488eSEric Joyner * ixgbe_sysctl_tdt_handler - Transmit Descriptor Tail handler function 16128eb6488eSEric Joyner * 1613758cc3dcSJack F Vogel * Retrieves the TDT value from the hardware 16148eb6488eSEric Joyner ************************************************************************/ 1615758cc3dcSJack F Vogel static int 1616758cc3dcSJack F Vogel ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS) 1617758cc3dcSJack F Vogel { 1618758cc3dcSJack F Vogel struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); 16198eb6488eSEric Joyner int error; 16208eb6488eSEric Joyner unsigned int val; 1621758cc3dcSJack F Vogel 16228eb6488eSEric Joyner if (!txr) 16238eb6488eSEric Joyner return (0); 16248eb6488eSEric Joyner 16258eb6488eSEric Joyner val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me)); 1626758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1627758cc3dcSJack F Vogel if (error || !req->newptr) 1628758cc3dcSJack F Vogel return error; 1629758cc3dcSJack F Vogel 16308eb6488eSEric Joyner return (0); 16318eb6488eSEric Joyner } /* ixgbe_sysctl_tdt_handler */ 16328eb6488eSEric Joyner 16338eb6488eSEric Joyner /************************************************************************ 16348eb6488eSEric Joyner * ixgbe_sysctl_rdh_handler - Receive Descriptor Head handler function 16358eb6488eSEric Joyner * 1636758cc3dcSJack F Vogel * Retrieves the RDH value from the hardware 16378eb6488eSEric Joyner ************************************************************************/ 1638758cc3dcSJack F Vogel static int 1639758cc3dcSJack F Vogel ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS) 1640758cc3dcSJack F Vogel { 1641758cc3dcSJack F Vogel struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); 16428eb6488eSEric Joyner int error; 16438eb6488eSEric Joyner unsigned int val; 1644758cc3dcSJack F Vogel 16458eb6488eSEric Joyner if (!rxr) 16468eb6488eSEric Joyner return (0); 16478eb6488eSEric Joyner 16488eb6488eSEric Joyner val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me)); 1649758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1650758cc3dcSJack F Vogel if (error || !req->newptr) 1651758cc3dcSJack F Vogel return error; 1652758cc3dcSJack F Vogel 16538eb6488eSEric Joyner return (0); 16548eb6488eSEric Joyner } /* ixgbe_sysctl_rdh_handler */ 16558eb6488eSEric Joyner 16568eb6488eSEric Joyner /************************************************************************ 16578eb6488eSEric Joyner * ixgbe_sysctl_rdt_handler - Receive Descriptor Tail handler function 16588eb6488eSEric Joyner * 1659758cc3dcSJack F Vogel * Retrieves the RDT value from the hardware 16608eb6488eSEric Joyner ************************************************************************/ 1661758cc3dcSJack F Vogel static int 1662758cc3dcSJack F Vogel ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS) 1663758cc3dcSJack F Vogel { 1664758cc3dcSJack F Vogel struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); 16658eb6488eSEric Joyner int error; 16668eb6488eSEric Joyner unsigned int val; 1667758cc3dcSJack F Vogel 16688eb6488eSEric Joyner if (!rxr) 16698eb6488eSEric Joyner return (0); 16708eb6488eSEric Joyner 16718eb6488eSEric Joyner val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me)); 1672758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1673758cc3dcSJack F Vogel if (error || !req->newptr) 1674758cc3dcSJack F Vogel return error; 16758eb6488eSEric Joyner 16768eb6488eSEric Joyner return (0); 16778eb6488eSEric Joyner } /* ixgbe_sysctl_rdt_handler */ 16788eb6488eSEric Joyner 16798eb6488eSEric Joyner /************************************************************************ 16808eb6488eSEric Joyner * ixgbe_register_vlan 16818eb6488eSEric Joyner * 16828eb6488eSEric Joyner * Run via vlan config EVENT, it enables us to use the 16838eb6488eSEric Joyner * HW Filter table since we can get the vlan id. This 16848eb6488eSEric Joyner * just creates the entry in the soft version of the 16858eb6488eSEric Joyner * VFTA, init will repopulate the real table. 16868eb6488eSEric Joyner ************************************************************************/ 16878eb6488eSEric Joyner static void 16888eb6488eSEric Joyner ixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) 16898eb6488eSEric Joyner { 16908eb6488eSEric Joyner struct adapter *adapter = ifp->if_softc; 16918eb6488eSEric Joyner u16 index, bit; 16928eb6488eSEric Joyner 16938eb6488eSEric Joyner if (ifp->if_softc != arg) /* Not our event */ 16948eb6488eSEric Joyner return; 16958eb6488eSEric Joyner 16968eb6488eSEric Joyner if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 16978eb6488eSEric Joyner return; 16988eb6488eSEric Joyner 16998eb6488eSEric Joyner IXGBE_CORE_LOCK(adapter); 17008eb6488eSEric Joyner index = (vtag >> 5) & 0x7F; 17018eb6488eSEric Joyner bit = vtag & 0x1F; 17028eb6488eSEric Joyner adapter->shadow_vfta[index] |= (1 << bit); 17038eb6488eSEric Joyner ++adapter->num_vlans; 17048eb6488eSEric Joyner ixgbe_setup_vlan_hw_support(adapter); 17058eb6488eSEric Joyner IXGBE_CORE_UNLOCK(adapter); 17068eb6488eSEric Joyner } /* ixgbe_register_vlan */ 17078eb6488eSEric Joyner 17088eb6488eSEric Joyner /************************************************************************ 17098eb6488eSEric Joyner * ixgbe_unregister_vlan 17108eb6488eSEric Joyner * 17118eb6488eSEric Joyner * Run via vlan unconfig EVENT, remove our entry in the soft vfta. 17128eb6488eSEric Joyner ************************************************************************/ 17138eb6488eSEric Joyner static void 17148eb6488eSEric Joyner ixgbe_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) 17158eb6488eSEric Joyner { 17168eb6488eSEric Joyner struct adapter *adapter = ifp->if_softc; 17178eb6488eSEric Joyner u16 index, bit; 17188eb6488eSEric Joyner 17198eb6488eSEric Joyner if (ifp->if_softc != arg) 17208eb6488eSEric Joyner return; 17218eb6488eSEric Joyner 17228eb6488eSEric Joyner if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 17238eb6488eSEric Joyner return; 17248eb6488eSEric Joyner 17258eb6488eSEric Joyner IXGBE_CORE_LOCK(adapter); 17268eb6488eSEric Joyner index = (vtag >> 5) & 0x7F; 17278eb6488eSEric Joyner bit = vtag & 0x1F; 17288eb6488eSEric Joyner adapter->shadow_vfta[index] &= ~(1 << bit); 17298eb6488eSEric Joyner --adapter->num_vlans; 17308eb6488eSEric Joyner /* Re-init to load the changes */ 17318eb6488eSEric Joyner ixgbe_setup_vlan_hw_support(adapter); 17328eb6488eSEric Joyner IXGBE_CORE_UNLOCK(adapter); 17338eb6488eSEric Joyner } /* ixgbe_unregister_vlan */ 17348eb6488eSEric Joyner 17358eb6488eSEric Joyner /************************************************************************ 17368eb6488eSEric Joyner * ixgbe_setup_vlan_hw_support 17378eb6488eSEric Joyner ************************************************************************/ 17388eb6488eSEric Joyner static void 17398eb6488eSEric Joyner ixgbe_setup_vlan_hw_support(struct adapter *adapter) 17408eb6488eSEric Joyner { 17418eb6488eSEric Joyner struct ifnet *ifp = adapter->ifp; 17428eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 17438eb6488eSEric Joyner struct rx_ring *rxr; 17448eb6488eSEric Joyner int i; 17458eb6488eSEric Joyner u32 ctrl; 17468eb6488eSEric Joyner 17478eb6488eSEric Joyner 17488eb6488eSEric Joyner /* 17498eb6488eSEric Joyner * We get here thru init_locked, meaning 17508eb6488eSEric Joyner * a soft reset, this has already cleared 17518eb6488eSEric Joyner * the VFTA and other state, so if there 17528eb6488eSEric Joyner * have been no vlan's registered do nothing. 17538eb6488eSEric Joyner */ 17548eb6488eSEric Joyner if (adapter->num_vlans == 0) 17558eb6488eSEric Joyner return; 17568eb6488eSEric Joyner 17578eb6488eSEric Joyner /* Setup the queues for vlans */ 17588eb6488eSEric Joyner for (i = 0; i < adapter->num_queues; i++) { 17598eb6488eSEric Joyner rxr = &adapter->rx_rings[i]; 17608eb6488eSEric Joyner /* On 82599 the VLAN enable is per/queue in RXDCTL */ 17618eb6488eSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) { 17628eb6488eSEric Joyner ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); 17638eb6488eSEric Joyner ctrl |= IXGBE_RXDCTL_VME; 17648eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl); 17658eb6488eSEric Joyner } 17668eb6488eSEric Joyner rxr->vtag_strip = TRUE; 1767758cc3dcSJack F Vogel } 1768758cc3dcSJack F Vogel 17698eb6488eSEric Joyner if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0) 17708eb6488eSEric Joyner return; 17718eb6488eSEric Joyner /* 17728eb6488eSEric Joyner * A soft reset zero's out the VFTA, so 17738eb6488eSEric Joyner * we need to repopulate it now. 17748eb6488eSEric Joyner */ 17758eb6488eSEric Joyner for (i = 0; i < IXGBE_VFTA_SIZE; i++) 17768eb6488eSEric Joyner if (adapter->shadow_vfta[i] != 0) 17778eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), 17788eb6488eSEric Joyner adapter->shadow_vfta[i]); 17798eb6488eSEric Joyner 17808eb6488eSEric Joyner ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); 17818eb6488eSEric Joyner /* Enable the Filter Table if enabled */ 17828eb6488eSEric Joyner if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) { 17838eb6488eSEric Joyner ctrl &= ~IXGBE_VLNCTRL_CFIEN; 17848eb6488eSEric Joyner ctrl |= IXGBE_VLNCTRL_VFE; 17858eb6488eSEric Joyner } 17868eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 17878eb6488eSEric Joyner ctrl |= IXGBE_VLNCTRL_VME; 17888eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); 17898eb6488eSEric Joyner } /* ixgbe_setup_vlan_hw_support */ 17908eb6488eSEric Joyner 17918eb6488eSEric Joyner /************************************************************************ 17928eb6488eSEric Joyner * ixgbe_get_slot_info 17938eb6488eSEric Joyner * 17948eb6488eSEric Joyner * Get the width and transaction speed of 17958eb6488eSEric Joyner * the slot this adapter is plugged into. 17968eb6488eSEric Joyner ************************************************************************/ 17978eb6488eSEric Joyner static void 17988eb6488eSEric Joyner ixgbe_get_slot_info(struct adapter *adapter) 17998eb6488eSEric Joyner { 18008eb6488eSEric Joyner device_t dev = adapter->dev; 18018eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 18028eb6488eSEric Joyner u32 offset; 18038eb6488eSEric Joyner u16 link; 18048eb6488eSEric Joyner int bus_info_valid = TRUE; 18058eb6488eSEric Joyner 18068eb6488eSEric Joyner /* Some devices are behind an internal bridge */ 18078eb6488eSEric Joyner switch (hw->device_id) { 18088eb6488eSEric Joyner case IXGBE_DEV_ID_82599_SFP_SF_QP: 18098eb6488eSEric Joyner case IXGBE_DEV_ID_82599_QSFP_SF_QP: 18108eb6488eSEric Joyner goto get_parent_info; 18118eb6488eSEric Joyner default: 18128eb6488eSEric Joyner break; 18138eb6488eSEric Joyner } 18148eb6488eSEric Joyner 18158eb6488eSEric Joyner ixgbe_get_bus_info(hw); 18168eb6488eSEric Joyner 18178eb6488eSEric Joyner /* 18188eb6488eSEric Joyner * Some devices don't use PCI-E, but there is no need 18198eb6488eSEric Joyner * to display "Unknown" for bus speed and width. 18208eb6488eSEric Joyner */ 18218eb6488eSEric Joyner switch (hw->mac.type) { 18228eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 18238eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 18248eb6488eSEric Joyner return; 18258eb6488eSEric Joyner default: 18268eb6488eSEric Joyner goto display; 18278eb6488eSEric Joyner } 18288eb6488eSEric Joyner 18298eb6488eSEric Joyner get_parent_info: 18308eb6488eSEric Joyner /* 18318eb6488eSEric Joyner * For the Quad port adapter we need to parse back 18328eb6488eSEric Joyner * up the PCI tree to find the speed of the expansion 18338eb6488eSEric Joyner * slot into which this adapter is plugged. A bit more work. 18348eb6488eSEric Joyner */ 18358eb6488eSEric Joyner dev = device_get_parent(device_get_parent(dev)); 18368eb6488eSEric Joyner #ifdef IXGBE_DEBUG 18378eb6488eSEric Joyner device_printf(dev, "parent pcib = %x,%x,%x\n", pci_get_bus(dev), 18388eb6488eSEric Joyner pci_get_slot(dev), pci_get_function(dev)); 18398eb6488eSEric Joyner #endif 18408eb6488eSEric Joyner dev = device_get_parent(device_get_parent(dev)); 18418eb6488eSEric Joyner #ifdef IXGBE_DEBUG 18428eb6488eSEric Joyner device_printf(dev, "slot pcib = %x,%x,%x\n", pci_get_bus(dev), 18438eb6488eSEric Joyner pci_get_slot(dev), pci_get_function(dev)); 18448eb6488eSEric Joyner #endif 18458eb6488eSEric Joyner /* Now get the PCI Express Capabilities offset */ 18468eb6488eSEric Joyner if (pci_find_cap(dev, PCIY_EXPRESS, &offset)) { 18478eb6488eSEric Joyner /* 18488eb6488eSEric Joyner * Hmm...can't get PCI-Express capabilities. 18498eb6488eSEric Joyner * Falling back to default method. 18508eb6488eSEric Joyner */ 18518eb6488eSEric Joyner bus_info_valid = FALSE; 18528eb6488eSEric Joyner ixgbe_get_bus_info(hw); 18538eb6488eSEric Joyner goto display; 18548eb6488eSEric Joyner } 18558eb6488eSEric Joyner /* ...and read the Link Status Register */ 18568eb6488eSEric Joyner link = pci_read_config(dev, offset + PCIER_LINK_STA, 2); 18578eb6488eSEric Joyner ixgbe_set_pci_config_data_generic(hw, link); 18588eb6488eSEric Joyner 18598eb6488eSEric Joyner display: 18608eb6488eSEric Joyner device_printf(dev, "PCI Express Bus: Speed %s %s\n", 18618eb6488eSEric Joyner ((hw->bus.speed == ixgbe_bus_speed_8000) ? "8.0GT/s" : 18628eb6488eSEric Joyner (hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0GT/s" : 18638eb6488eSEric Joyner (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5GT/s" : 18648eb6488eSEric Joyner "Unknown"), 18658eb6488eSEric Joyner ((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" : 18668eb6488eSEric Joyner (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" : 18678eb6488eSEric Joyner (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" : 18688eb6488eSEric Joyner "Unknown")); 18698eb6488eSEric Joyner 18708eb6488eSEric Joyner if (bus_info_valid) { 18718eb6488eSEric Joyner if ((hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) && 18728eb6488eSEric Joyner ((hw->bus.width <= ixgbe_bus_width_pcie_x4) && 18738eb6488eSEric Joyner (hw->bus.speed == ixgbe_bus_speed_2500))) { 18748eb6488eSEric Joyner device_printf(dev, "PCI-Express bandwidth available for this card\n is not sufficient for optimal performance.\n"); 18758eb6488eSEric Joyner device_printf(dev, "For optimal performance a x8 PCIE, or x4 PCIE Gen2 slot is required.\n"); 18768eb6488eSEric Joyner } 18778eb6488eSEric Joyner if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) && 18788eb6488eSEric Joyner ((hw->bus.width <= ixgbe_bus_width_pcie_x8) && 18798eb6488eSEric Joyner (hw->bus.speed < ixgbe_bus_speed_8000))) { 18808eb6488eSEric Joyner device_printf(dev, "PCI-Express bandwidth available for this card\n is not sufficient for optimal performance.\n"); 18818eb6488eSEric Joyner device_printf(dev, "For optimal performance a x8 PCIE Gen3 slot is required.\n"); 18828eb6488eSEric Joyner } 18838eb6488eSEric Joyner } else 18848eb6488eSEric Joyner device_printf(dev, "Unable to determine slot speed/width. The speed/width reported are that of the internal switch.\n"); 18858eb6488eSEric Joyner 18868eb6488eSEric Joyner return; 18878eb6488eSEric Joyner } /* ixgbe_get_slot_info */ 18888eb6488eSEric Joyner 18898eb6488eSEric Joyner /************************************************************************ 18908eb6488eSEric Joyner * ixgbe_enable_queue - MSI-X Interrupt Handlers and Tasklets 18918eb6488eSEric Joyner ************************************************************************/ 18928eb6488eSEric Joyner static inline void 18938eb6488eSEric Joyner ixgbe_enable_queue(struct adapter *adapter, u32 vector) 18948eb6488eSEric Joyner { 18958eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 18968eb6488eSEric Joyner u64 queue = (u64)(1 << vector); 18978eb6488eSEric Joyner u32 mask; 18988eb6488eSEric Joyner 18998eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) { 19008eb6488eSEric Joyner mask = (IXGBE_EIMS_RTX_QUEUE & queue); 19018eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); 19028eb6488eSEric Joyner } else { 19038eb6488eSEric Joyner mask = (queue & 0xFFFFFFFF); 19048eb6488eSEric Joyner if (mask) 19058eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); 19068eb6488eSEric Joyner mask = (queue >> 32); 19078eb6488eSEric Joyner if (mask) 19088eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask); 19098eb6488eSEric Joyner } 19108eb6488eSEric Joyner } /* ixgbe_enable_queue */ 19118eb6488eSEric Joyner 19128eb6488eSEric Joyner /************************************************************************ 19138eb6488eSEric Joyner * ixgbe_disable_queue 19148eb6488eSEric Joyner ************************************************************************/ 19158eb6488eSEric Joyner static inline void 19168eb6488eSEric Joyner ixgbe_disable_queue(struct adapter *adapter, u32 vector) 19178eb6488eSEric Joyner { 19188eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 19198eb6488eSEric Joyner u64 queue = (u64)(1 << vector); 19208eb6488eSEric Joyner u32 mask; 19218eb6488eSEric Joyner 19228eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) { 19238eb6488eSEric Joyner mask = (IXGBE_EIMS_RTX_QUEUE & queue); 19248eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask); 19258eb6488eSEric Joyner } else { 19268eb6488eSEric Joyner mask = (queue & 0xFFFFFFFF); 19278eb6488eSEric Joyner if (mask) 19288eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask); 19298eb6488eSEric Joyner mask = (queue >> 32); 19308eb6488eSEric Joyner if (mask) 19318eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask); 19328eb6488eSEric Joyner } 19338eb6488eSEric Joyner } /* ixgbe_disable_queue */ 19348eb6488eSEric Joyner 19358eb6488eSEric Joyner /************************************************************************ 19368eb6488eSEric Joyner * ixgbe_msix_que - MSI-X Queue Interrupt Service routine 19378eb6488eSEric Joyner ************************************************************************/ 19388eb6488eSEric Joyner void 19398eb6488eSEric Joyner ixgbe_msix_que(void *arg) 19408eb6488eSEric Joyner { 19418eb6488eSEric Joyner struct ix_queue *que = arg; 19428eb6488eSEric Joyner struct adapter *adapter = que->adapter; 19438eb6488eSEric Joyner struct ifnet *ifp = adapter->ifp; 19448eb6488eSEric Joyner struct tx_ring *txr = que->txr; 19458eb6488eSEric Joyner struct rx_ring *rxr = que->rxr; 19468eb6488eSEric Joyner bool more; 19478eb6488eSEric Joyner u32 newitr = 0; 19488eb6488eSEric Joyner 19498eb6488eSEric Joyner 19508eb6488eSEric Joyner /* Protect against spurious interrupts */ 19518eb6488eSEric Joyner if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 19528eb6488eSEric Joyner return; 19538eb6488eSEric Joyner 19548eb6488eSEric Joyner ixgbe_disable_queue(adapter, que->msix); 19558eb6488eSEric Joyner ++que->irqs; 19568eb6488eSEric Joyner 19578eb6488eSEric Joyner more = ixgbe_rxeof(que); 19588eb6488eSEric Joyner 19598eb6488eSEric Joyner IXGBE_TX_LOCK(txr); 19608eb6488eSEric Joyner ixgbe_txeof(txr); 19618eb6488eSEric Joyner if (!ixgbe_ring_empty(ifp, txr->br)) 19628eb6488eSEric Joyner ixgbe_start_locked(ifp, txr); 19638eb6488eSEric Joyner IXGBE_TX_UNLOCK(txr); 19648eb6488eSEric Joyner 19658eb6488eSEric Joyner /* Do AIM now? */ 19668eb6488eSEric Joyner 19678eb6488eSEric Joyner if (adapter->enable_aim == FALSE) 19688eb6488eSEric Joyner goto no_calc; 19698eb6488eSEric Joyner /* 19708eb6488eSEric Joyner * Do Adaptive Interrupt Moderation: 19718eb6488eSEric Joyner * - Write out last calculated setting 19728eb6488eSEric Joyner * - Calculate based on average size over 19738eb6488eSEric Joyner * the last interval. 19748eb6488eSEric Joyner */ 19758eb6488eSEric Joyner if (que->eitr_setting) 19768eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(que->msix), 19778eb6488eSEric Joyner que->eitr_setting); 19788eb6488eSEric Joyner 19798eb6488eSEric Joyner que->eitr_setting = 0; 19808eb6488eSEric Joyner 19818eb6488eSEric Joyner /* Idle, do nothing */ 19828eb6488eSEric Joyner if ((txr->bytes == 0) && (rxr->bytes == 0)) 19838eb6488eSEric Joyner goto no_calc; 19848eb6488eSEric Joyner 19858eb6488eSEric Joyner if ((txr->bytes) && (txr->packets)) 19868eb6488eSEric Joyner newitr = txr->bytes/txr->packets; 19878eb6488eSEric Joyner if ((rxr->bytes) && (rxr->packets)) 19888eb6488eSEric Joyner newitr = max(newitr, (rxr->bytes / rxr->packets)); 19898eb6488eSEric Joyner newitr += 24; /* account for hardware frame, crc */ 19908eb6488eSEric Joyner 19918eb6488eSEric Joyner /* set an upper boundary */ 19928eb6488eSEric Joyner newitr = min(newitr, 3000); 19938eb6488eSEric Joyner 19948eb6488eSEric Joyner /* Be nice to the mid range */ 19958eb6488eSEric Joyner if ((newitr > 300) && (newitr < 1200)) 19968eb6488eSEric Joyner newitr = (newitr / 3); 19978eb6488eSEric Joyner else 19988eb6488eSEric Joyner newitr = (newitr / 2); 19998eb6488eSEric Joyner 20008eb6488eSEric Joyner if (adapter->hw.mac.type == ixgbe_mac_82598EB) 20018eb6488eSEric Joyner newitr |= newitr << 16; 20028eb6488eSEric Joyner else 20038eb6488eSEric Joyner newitr |= IXGBE_EITR_CNT_WDIS; 20048eb6488eSEric Joyner 20058eb6488eSEric Joyner /* save for next interrupt */ 20068eb6488eSEric Joyner que->eitr_setting = newitr; 20078eb6488eSEric Joyner 20088eb6488eSEric Joyner /* Reset state */ 20098eb6488eSEric Joyner txr->bytes = 0; 20108eb6488eSEric Joyner txr->packets = 0; 20118eb6488eSEric Joyner rxr->bytes = 0; 20128eb6488eSEric Joyner rxr->packets = 0; 20138eb6488eSEric Joyner 20148eb6488eSEric Joyner no_calc: 20158eb6488eSEric Joyner if (more) 20168eb6488eSEric Joyner taskqueue_enqueue(que->tq, &que->que_task); 20178eb6488eSEric Joyner else 20188eb6488eSEric Joyner ixgbe_enable_queue(adapter, que->msix); 20198eb6488eSEric Joyner 20208eb6488eSEric Joyner return; 20218eb6488eSEric Joyner } /* ixgbe_msix_que */ 20228eb6488eSEric Joyner 20238eb6488eSEric Joyner /************************************************************************ 20248eb6488eSEric Joyner * ixgbe_media_status - Media Ioctl callback 20258eb6488eSEric Joyner * 20268eb6488eSEric Joyner * Called whenever the user queries the status of 20278eb6488eSEric Joyner * the interface using ifconfig. 20288eb6488eSEric Joyner ************************************************************************/ 20298eb6488eSEric Joyner static void 20308eb6488eSEric Joyner ixgbe_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) 20318eb6488eSEric Joyner { 20328eb6488eSEric Joyner struct adapter *adapter = ifp->if_softc; 20338eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 20348eb6488eSEric Joyner int layer; 20358eb6488eSEric Joyner 20368eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_media_status: begin"); 20378eb6488eSEric Joyner IXGBE_CORE_LOCK(adapter); 20388eb6488eSEric Joyner ixgbe_update_link_status(adapter); 20398eb6488eSEric Joyner 20408eb6488eSEric Joyner ifmr->ifm_status = IFM_AVALID; 20418eb6488eSEric Joyner ifmr->ifm_active = IFM_ETHER; 20428eb6488eSEric Joyner 20438eb6488eSEric Joyner if (!adapter->link_active) { 20448eb6488eSEric Joyner IXGBE_CORE_UNLOCK(adapter); 20458eb6488eSEric Joyner return; 20468eb6488eSEric Joyner } 20478eb6488eSEric Joyner 20488eb6488eSEric Joyner ifmr->ifm_status |= IFM_ACTIVE; 20498eb6488eSEric Joyner layer = adapter->phy_layer; 20508eb6488eSEric Joyner 20518eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T || 20528eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_T || 20538eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_100BASE_TX || 20548eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_10BASE_T) 20558eb6488eSEric Joyner switch (adapter->link_speed) { 20568eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 20578eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_T | IFM_FDX; 20588eb6488eSEric Joyner break; 20598eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 20608eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_T | IFM_FDX; 20618eb6488eSEric Joyner break; 20628eb6488eSEric Joyner case IXGBE_LINK_SPEED_100_FULL: 20638eb6488eSEric Joyner ifmr->ifm_active |= IFM_100_TX | IFM_FDX; 20648eb6488eSEric Joyner break; 20658eb6488eSEric Joyner case IXGBE_LINK_SPEED_10_FULL: 20668eb6488eSEric Joyner ifmr->ifm_active |= IFM_10_T | IFM_FDX; 20678eb6488eSEric Joyner break; 20688eb6488eSEric Joyner } 20698eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || 20708eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) 20718eb6488eSEric Joyner switch (adapter->link_speed) { 20728eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 20738eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX; 20748eb6488eSEric Joyner break; 20758eb6488eSEric Joyner } 20768eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) 20778eb6488eSEric Joyner switch (adapter->link_speed) { 20788eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 20798eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_LR | IFM_FDX; 20808eb6488eSEric Joyner break; 20818eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 20828eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; 20838eb6488eSEric Joyner break; 20848eb6488eSEric Joyner } 20858eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM) 20868eb6488eSEric Joyner switch (adapter->link_speed) { 20878eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 20888eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX; 20898eb6488eSEric Joyner break; 20908eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 20918eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; 20928eb6488eSEric Joyner break; 20938eb6488eSEric Joyner } 20948eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR || 20958eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) 20968eb6488eSEric Joyner switch (adapter->link_speed) { 20978eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 20988eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; 20998eb6488eSEric Joyner break; 21008eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 21018eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_SX | IFM_FDX; 21028eb6488eSEric Joyner break; 21038eb6488eSEric Joyner } 21048eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) 21058eb6488eSEric Joyner switch (adapter->link_speed) { 21068eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 21078eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; 21088eb6488eSEric Joyner break; 21098eb6488eSEric Joyner } 21108eb6488eSEric Joyner /* 21118eb6488eSEric Joyner * XXX: These need to use the proper media types once 21128eb6488eSEric Joyner * they're added. 21138eb6488eSEric Joyner */ 21148eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE 21158eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 21168eb6488eSEric Joyner switch (adapter->link_speed) { 21178eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 21188eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; 21198eb6488eSEric Joyner break; 21208eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 21218eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; 21228eb6488eSEric Joyner break; 21238eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 21248eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; 21258eb6488eSEric Joyner break; 21268eb6488eSEric Joyner } 21278eb6488eSEric Joyner else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 || 21288eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX || 21298eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 21308eb6488eSEric Joyner switch (adapter->link_speed) { 21318eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 21328eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; 21338eb6488eSEric Joyner break; 21348eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 21358eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; 21368eb6488eSEric Joyner break; 21378eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 21388eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; 21398eb6488eSEric Joyner break; 21408eb6488eSEric Joyner } 21418eb6488eSEric Joyner #else 21428eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 21438eb6488eSEric Joyner switch (adapter->link_speed) { 21448eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 21458eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_KR | IFM_FDX; 21468eb6488eSEric Joyner break; 21478eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 21488eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; 21498eb6488eSEric Joyner break; 21508eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 21518eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; 21528eb6488eSEric Joyner break; 21538eb6488eSEric Joyner } 21548eb6488eSEric Joyner else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 || 21558eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX || 21568eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 21578eb6488eSEric Joyner switch (adapter->link_speed) { 21588eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 21598eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX; 21608eb6488eSEric Joyner break; 21618eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 21628eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; 21638eb6488eSEric Joyner break; 21648eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 21658eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; 21668eb6488eSEric Joyner break; 21678eb6488eSEric Joyner } 21688eb6488eSEric Joyner #endif 21698eb6488eSEric Joyner 21708eb6488eSEric Joyner /* If nothing is recognized... */ 21718eb6488eSEric Joyner if (IFM_SUBTYPE(ifmr->ifm_active) == 0) 21728eb6488eSEric Joyner ifmr->ifm_active |= IFM_UNKNOWN; 21738eb6488eSEric Joyner 21748eb6488eSEric Joyner #if __FreeBSD_version >= 900025 21758eb6488eSEric Joyner /* Display current flow control setting used on link */ 21768eb6488eSEric Joyner if (hw->fc.current_mode == ixgbe_fc_rx_pause || 21778eb6488eSEric Joyner hw->fc.current_mode == ixgbe_fc_full) 21788eb6488eSEric Joyner ifmr->ifm_active |= IFM_ETH_RXPAUSE; 21798eb6488eSEric Joyner if (hw->fc.current_mode == ixgbe_fc_tx_pause || 21808eb6488eSEric Joyner hw->fc.current_mode == ixgbe_fc_full) 21818eb6488eSEric Joyner ifmr->ifm_active |= IFM_ETH_TXPAUSE; 21828eb6488eSEric Joyner #endif 21838eb6488eSEric Joyner 21848eb6488eSEric Joyner IXGBE_CORE_UNLOCK(adapter); 21858eb6488eSEric Joyner 21868eb6488eSEric Joyner return; 21878eb6488eSEric Joyner } /* ixgbe_media_status */ 21888eb6488eSEric Joyner 21898eb6488eSEric Joyner /************************************************************************ 21908eb6488eSEric Joyner * ixgbe_media_change - Media Ioctl callback 21918eb6488eSEric Joyner * 21928eb6488eSEric Joyner * Called when the user changes speed/duplex using 21938eb6488eSEric Joyner * media/mediopt option with ifconfig. 21948eb6488eSEric Joyner ************************************************************************/ 21958eb6488eSEric Joyner static int 21968eb6488eSEric Joyner ixgbe_media_change(struct ifnet *ifp) 21978eb6488eSEric Joyner { 21988eb6488eSEric Joyner struct adapter *adapter = ifp->if_softc; 21998eb6488eSEric Joyner struct ifmedia *ifm = &adapter->media; 22008eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 22018eb6488eSEric Joyner ixgbe_link_speed speed = 0; 22028eb6488eSEric Joyner 22038eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_media_change: begin"); 22048eb6488eSEric Joyner 22058eb6488eSEric Joyner if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 22068eb6488eSEric Joyner return (EINVAL); 22078eb6488eSEric Joyner 22088eb6488eSEric Joyner if (hw->phy.media_type == ixgbe_media_type_backplane) 22098eb6488eSEric Joyner return (ENODEV); 22108eb6488eSEric Joyner 22118eb6488eSEric Joyner /* 22128eb6488eSEric Joyner * We don't actually need to check against the supported 22138eb6488eSEric Joyner * media types of the adapter; ifmedia will take care of 22148eb6488eSEric Joyner * that for us. 22158eb6488eSEric Joyner */ 22168eb6488eSEric Joyner switch (IFM_SUBTYPE(ifm->ifm_media)) { 22178eb6488eSEric Joyner case IFM_AUTO: 22188eb6488eSEric Joyner case IFM_10G_T: 22198eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_100_FULL; 22208eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 22218eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10GB_FULL; 22228eb6488eSEric Joyner break; 22238eb6488eSEric Joyner case IFM_10G_LRM: 22248eb6488eSEric Joyner case IFM_10G_LR: 22258eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE 22268eb6488eSEric Joyner case IFM_10G_SR: /* KR, too */ 22278eb6488eSEric Joyner case IFM_10G_CX4: /* KX4 */ 22288eb6488eSEric Joyner #else 22298eb6488eSEric Joyner case IFM_10G_KR: 22308eb6488eSEric Joyner case IFM_10G_KX4: 22318eb6488eSEric Joyner #endif 22328eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 22338eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10GB_FULL; 22348eb6488eSEric Joyner break; 22358eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE 22368eb6488eSEric Joyner case IFM_1000_CX: /* KX */ 22378eb6488eSEric Joyner #else 22388eb6488eSEric Joyner case IFM_1000_KX: 22398eb6488eSEric Joyner #endif 22408eb6488eSEric Joyner case IFM_1000_LX: 22418eb6488eSEric Joyner case IFM_1000_SX: 22428eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 22438eb6488eSEric Joyner break; 22448eb6488eSEric Joyner case IFM_1000_T: 22458eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_100_FULL; 22468eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 22478eb6488eSEric Joyner break; 22488eb6488eSEric Joyner case IFM_10G_TWINAX: 22498eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10GB_FULL; 22508eb6488eSEric Joyner break; 22518eb6488eSEric Joyner case IFM_100_TX: 22528eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_100_FULL; 22538eb6488eSEric Joyner break; 22548eb6488eSEric Joyner case IFM_10_T: 22558eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10_FULL; 22568eb6488eSEric Joyner break; 22578eb6488eSEric Joyner default: 22588eb6488eSEric Joyner goto invalid; 22598eb6488eSEric Joyner } 22608eb6488eSEric Joyner 22618eb6488eSEric Joyner hw->mac.autotry_restart = TRUE; 22628eb6488eSEric Joyner hw->mac.ops.setup_link(hw, speed, TRUE); 22638eb6488eSEric Joyner adapter->advertise = 22648eb6488eSEric Joyner ((speed & IXGBE_LINK_SPEED_10GB_FULL) ? 4 : 0) | 22658eb6488eSEric Joyner ((speed & IXGBE_LINK_SPEED_1GB_FULL) ? 2 : 0) | 22668eb6488eSEric Joyner ((speed & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0) | 22678eb6488eSEric Joyner ((speed & IXGBE_LINK_SPEED_10_FULL) ? 8 : 0); 22688eb6488eSEric Joyner 22698eb6488eSEric Joyner return (0); 22708eb6488eSEric Joyner 22718eb6488eSEric Joyner invalid: 22728eb6488eSEric Joyner device_printf(adapter->dev, "Invalid media type!\n"); 22738eb6488eSEric Joyner 22748eb6488eSEric Joyner return (EINVAL); 22758eb6488eSEric Joyner } /* ixgbe_media_change */ 22768eb6488eSEric Joyner 22778eb6488eSEric Joyner /************************************************************************ 22788eb6488eSEric Joyner * ixgbe_set_promisc 22798eb6488eSEric Joyner ************************************************************************/ 22808eb6488eSEric Joyner static void 22818eb6488eSEric Joyner ixgbe_set_promisc(struct adapter *adapter) 22828eb6488eSEric Joyner { 22838eb6488eSEric Joyner struct ifnet *ifp = adapter->ifp; 22848eb6488eSEric Joyner int mcnt = 0; 22858eb6488eSEric Joyner u32 rctl; 22868eb6488eSEric Joyner 22878eb6488eSEric Joyner rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); 22888eb6488eSEric Joyner rctl &= (~IXGBE_FCTRL_UPE); 22898eb6488eSEric Joyner if (ifp->if_flags & IFF_ALLMULTI) 22908eb6488eSEric Joyner mcnt = MAX_NUM_MULTICAST_ADDRESSES; 22918eb6488eSEric Joyner else { 22928eb6488eSEric Joyner struct ifmultiaddr *ifma; 22938eb6488eSEric Joyner #if __FreeBSD_version < 800000 22948eb6488eSEric Joyner IF_ADDR_LOCK(ifp); 22958eb6488eSEric Joyner #else 22968eb6488eSEric Joyner if_maddr_rlock(ifp); 22978eb6488eSEric Joyner #endif 22988eb6488eSEric Joyner TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 22998eb6488eSEric Joyner if (ifma->ifma_addr->sa_family != AF_LINK) 23008eb6488eSEric Joyner continue; 23018eb6488eSEric Joyner if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) 23028eb6488eSEric Joyner break; 23038eb6488eSEric Joyner mcnt++; 23048eb6488eSEric Joyner } 23058eb6488eSEric Joyner #if __FreeBSD_version < 800000 23068eb6488eSEric Joyner IF_ADDR_UNLOCK(ifp); 23078eb6488eSEric Joyner #else 23088eb6488eSEric Joyner if_maddr_runlock(ifp); 23098eb6488eSEric Joyner #endif 23108eb6488eSEric Joyner } 23118eb6488eSEric Joyner if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) 23128eb6488eSEric Joyner rctl &= (~IXGBE_FCTRL_MPE); 23138eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl); 23148eb6488eSEric Joyner 23158eb6488eSEric Joyner if (ifp->if_flags & IFF_PROMISC) { 23168eb6488eSEric Joyner rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 23178eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl); 23188eb6488eSEric Joyner } else if (ifp->if_flags & IFF_ALLMULTI) { 23198eb6488eSEric Joyner rctl |= IXGBE_FCTRL_MPE; 23208eb6488eSEric Joyner rctl &= ~IXGBE_FCTRL_UPE; 23218eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl); 23228eb6488eSEric Joyner } 23238eb6488eSEric Joyner } /* ixgbe_set_promisc */ 23248eb6488eSEric Joyner 23258eb6488eSEric Joyner /************************************************************************ 23268eb6488eSEric Joyner * ixgbe_msix_link - Link status change ISR (MSI/MSI-X) 23278eb6488eSEric Joyner ************************************************************************/ 23288eb6488eSEric Joyner static void 23298eb6488eSEric Joyner ixgbe_msix_link(void *arg) 23308eb6488eSEric Joyner { 23318eb6488eSEric Joyner struct adapter *adapter = arg; 23328eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 23338eb6488eSEric Joyner u32 eicr, eicr_mask; 23348eb6488eSEric Joyner s32 retval; 23358eb6488eSEric Joyner 23368eb6488eSEric Joyner ++adapter->link_irq; 23378eb6488eSEric Joyner 23388eb6488eSEric Joyner /* Pause other interrupts */ 23398eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER); 23408eb6488eSEric Joyner 23418eb6488eSEric Joyner /* First get the cause */ 23428eb6488eSEric Joyner eicr = IXGBE_READ_REG(hw, IXGBE_EICS); 23438eb6488eSEric Joyner /* Be sure the queue bits are not cleared */ 23448eb6488eSEric Joyner eicr &= ~IXGBE_EICR_RTX_QUEUE; 23458eb6488eSEric Joyner /* Clear interrupt with write */ 23468eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr); 23478eb6488eSEric Joyner 23488eb6488eSEric Joyner /* Link status change */ 23498eb6488eSEric Joyner if (eicr & IXGBE_EICR_LSC) { 23508eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); 23518eb6488eSEric Joyner taskqueue_enqueue(adapter->tq, &adapter->link_task); 23528eb6488eSEric Joyner } 23538eb6488eSEric Joyner 23548eb6488eSEric Joyner if (adapter->hw.mac.type != ixgbe_mac_82598EB) { 23558eb6488eSEric Joyner if ((adapter->feat_en & IXGBE_FEATURE_FDIR) && 23568eb6488eSEric Joyner (eicr & IXGBE_EICR_FLOW_DIR)) { 23578eb6488eSEric Joyner /* This is probably overkill :) */ 23588eb6488eSEric Joyner if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1)) 23598eb6488eSEric Joyner return; 23608eb6488eSEric Joyner /* Disable the interrupt */ 23618eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR); 23628eb6488eSEric Joyner taskqueue_enqueue(adapter->tq, &adapter->fdir_task); 23638eb6488eSEric Joyner } 23648eb6488eSEric Joyner 23658eb6488eSEric Joyner if (eicr & IXGBE_EICR_ECC) { 23668eb6488eSEric Joyner device_printf(adapter->dev, 23678eb6488eSEric Joyner "CRITICAL: ECC ERROR!! Please Reboot!!\n"); 23688eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC); 23698eb6488eSEric Joyner } 23708eb6488eSEric Joyner 23718eb6488eSEric Joyner /* Check for over temp condition */ 23728eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR) { 23738eb6488eSEric Joyner switch (adapter->hw.mac.type) { 23748eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 23758eb6488eSEric Joyner if (!(eicr & IXGBE_EICR_GPI_SDP0_X550EM_a)) 23768eb6488eSEric Joyner break; 23778eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, 23788eb6488eSEric Joyner IXGBE_EICR_GPI_SDP0_X550EM_a); 23798eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, 23808eb6488eSEric Joyner IXGBE_EICR_GPI_SDP0_X550EM_a); 23818eb6488eSEric Joyner retval = hw->phy.ops.check_overtemp(hw); 23828eb6488eSEric Joyner if (retval != IXGBE_ERR_OVERTEMP) 23838eb6488eSEric Joyner break; 23848eb6488eSEric Joyner device_printf(adapter->dev, "CRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n"); 23858eb6488eSEric Joyner device_printf(adapter->dev, "System shutdown required!\n"); 23868eb6488eSEric Joyner break; 23878eb6488eSEric Joyner default: 23888eb6488eSEric Joyner if (!(eicr & IXGBE_EICR_TS)) 23898eb6488eSEric Joyner break; 23908eb6488eSEric Joyner retval = hw->phy.ops.check_overtemp(hw); 23918eb6488eSEric Joyner if (retval != IXGBE_ERR_OVERTEMP) 23928eb6488eSEric Joyner break; 23938eb6488eSEric Joyner device_printf(adapter->dev, "CRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n"); 23948eb6488eSEric Joyner device_printf(adapter->dev, "System shutdown required!\n"); 23958eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS); 23968eb6488eSEric Joyner break; 23978eb6488eSEric Joyner } 23988eb6488eSEric Joyner } 23998eb6488eSEric Joyner 24008eb6488eSEric Joyner /* Check for VF message */ 24018eb6488eSEric Joyner if ((adapter->feat_en & IXGBE_FEATURE_SRIOV) && 24028eb6488eSEric Joyner (eicr & IXGBE_EICR_MAILBOX)) 24038eb6488eSEric Joyner taskqueue_enqueue(adapter->tq, &adapter->mbx_task); 24048eb6488eSEric Joyner } 24058eb6488eSEric Joyner 24068eb6488eSEric Joyner if (ixgbe_is_sfp(hw)) { 24078eb6488eSEric Joyner /* Pluggable optics-related interrupt */ 24088eb6488eSEric Joyner if (hw->mac.type >= ixgbe_mac_X540) 24098eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP0_X540; 24108eb6488eSEric Joyner else 24118eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); 24128eb6488eSEric Joyner 24138eb6488eSEric Joyner if (eicr & eicr_mask) { 24148eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); 24158eb6488eSEric Joyner taskqueue_enqueue(adapter->tq, &adapter->mod_task); 24168eb6488eSEric Joyner } 24178eb6488eSEric Joyner 24188eb6488eSEric Joyner if ((hw->mac.type == ixgbe_mac_82599EB) && 24198eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { 24208eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, 24218eb6488eSEric Joyner IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 24228eb6488eSEric Joyner taskqueue_enqueue(adapter->tq, &adapter->msf_task); 24238eb6488eSEric Joyner } 24248eb6488eSEric Joyner } 24258eb6488eSEric Joyner 24268eb6488eSEric Joyner /* Check for fan failure */ 24278eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) { 24288eb6488eSEric Joyner ixgbe_check_fan_failure(adapter, eicr, TRUE); 24298eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 24308eb6488eSEric Joyner } 24318eb6488eSEric Joyner 24328eb6488eSEric Joyner /* External PHY interrupt */ 24338eb6488eSEric Joyner if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && 24348eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP0_X540)) { 24358eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540); 24368eb6488eSEric Joyner taskqueue_enqueue(adapter->tq, &adapter->phy_task); 24378eb6488eSEric Joyner } 24388eb6488eSEric Joyner 24398eb6488eSEric Joyner /* Re-enable other interrupts */ 24408eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); 24418eb6488eSEric Joyner } /* ixgbe_msix_link */ 24428eb6488eSEric Joyner 24438eb6488eSEric Joyner /************************************************************************ 24448eb6488eSEric Joyner * ixgbe_sysctl_interrupt_rate_handler 24458eb6488eSEric Joyner ************************************************************************/ 2446758cc3dcSJack F Vogel static int 2447758cc3dcSJack F Vogel ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS) 2448758cc3dcSJack F Vogel { 2449758cc3dcSJack F Vogel struct ix_queue *que = ((struct ix_queue *)oidp->oid_arg1); 24508eb6488eSEric Joyner int error; 2451758cc3dcSJack F Vogel unsigned int reg, usec, rate; 2452758cc3dcSJack F Vogel 2453758cc3dcSJack F Vogel reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix)); 2454758cc3dcSJack F Vogel usec = ((reg & 0x0FF8) >> 3); 2455758cc3dcSJack F Vogel if (usec > 0) 2456758cc3dcSJack F Vogel rate = 500000 / usec; 2457758cc3dcSJack F Vogel else 2458758cc3dcSJack F Vogel rate = 0; 2459758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &rate, 0, req); 2460758cc3dcSJack F Vogel if (error || !req->newptr) 2461758cc3dcSJack F Vogel return error; 2462758cc3dcSJack F Vogel reg &= ~0xfff; /* default, no limitation */ 2463758cc3dcSJack F Vogel ixgbe_max_interrupt_rate = 0; 2464758cc3dcSJack F Vogel if (rate > 0 && rate < 500000) { 2465758cc3dcSJack F Vogel if (rate < 1000) 2466758cc3dcSJack F Vogel rate = 1000; 2467758cc3dcSJack F Vogel ixgbe_max_interrupt_rate = rate; 2468758cc3dcSJack F Vogel reg |= ((4000000/rate) & 0xff8); 2469758cc3dcSJack F Vogel } 2470758cc3dcSJack F Vogel IXGBE_WRITE_REG(&que->adapter->hw, IXGBE_EITR(que->msix), reg); 2471758cc3dcSJack F Vogel 24728eb6488eSEric Joyner return (0); 24738eb6488eSEric Joyner } /* ixgbe_sysctl_interrupt_rate_handler */ 24748eb6488eSEric Joyner 24758eb6488eSEric Joyner /************************************************************************ 24768eb6488eSEric Joyner * ixgbe_add_device_sysctls 24778eb6488eSEric Joyner ************************************************************************/ 24786f37f232SEric Joyner static void 24796f37f232SEric Joyner ixgbe_add_device_sysctls(struct adapter *adapter) 24806f37f232SEric Joyner { 24816f37f232SEric Joyner device_t dev = adapter->dev; 24826f37f232SEric Joyner struct ixgbe_hw *hw = &adapter->hw; 24836f37f232SEric Joyner struct sysctl_oid_list *child; 24846f37f232SEric Joyner struct sysctl_ctx_list *ctx; 24856f37f232SEric Joyner 24866f37f232SEric Joyner ctx = device_get_sysctl_ctx(dev); 24876f37f232SEric Joyner child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); 24886f37f232SEric Joyner 24896f37f232SEric Joyner /* Sysctls for all devices */ 24908eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fc", CTLTYPE_INT | CTLFLAG_RW, 24918eb6488eSEric Joyner adapter, 0, ixgbe_sysctl_flowcntl, "I", IXGBE_SYSCTL_DESC_SET_FC); 24926f37f232SEric Joyner 24938eb6488eSEric Joyner adapter->enable_aim = ixgbe_enable_aim; 24948eb6488eSEric Joyner SYSCTL_ADD_INT(ctx, child, OID_AUTO, "enable_aim", CTLFLAG_RW, 24958eb6488eSEric Joyner &adapter->enable_aim, 1, "Interrupt Moderation"); 24966f37f232SEric Joyner 24976f37f232SEric Joyner SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "advertise_speed", 24988eb6488eSEric Joyner CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_advertise, "I", 24998eb6488eSEric Joyner IXGBE_SYSCTL_DESC_ADV_SPEED); 25006f37f232SEric Joyner 2501a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 2502a9ca1c79SSean Bruno /* testing sysctls (for all devices) */ 2503a9ca1c79SSean Bruno SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "power_state", 25048eb6488eSEric Joyner CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_power_state, 25058eb6488eSEric Joyner "I", "PCI Power State"); 2506a9ca1c79SSean Bruno 2507a9ca1c79SSean Bruno SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "print_rss_config", 2508a9ca1c79SSean Bruno CTLTYPE_STRING | CTLFLAG_RD, adapter, 0, 2509a9ca1c79SSean Bruno ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration"); 2510a9ca1c79SSean Bruno #endif 2511a9ca1c79SSean Bruno /* for X550 series devices */ 25126f37f232SEric Joyner if (hw->mac.type >= ixgbe_mac_X550) 25136f37f232SEric Joyner SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "dmac", 25148eb6488eSEric Joyner CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_dmac, 25158eb6488eSEric Joyner "I", "DMA Coalesce"); 25166f37f232SEric Joyner 2517a9ca1c79SSean Bruno /* for WoL-capable devices */ 2518a9ca1c79SSean Bruno if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { 25196f37f232SEric Joyner SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "wol_enable", 25206f37f232SEric Joyner CTLTYPE_INT | CTLFLAG_RW, adapter, 0, 25218eb6488eSEric Joyner ixgbe_sysctl_wol_enable, "I", "Enable/Disable Wake on LAN"); 25226f37f232SEric Joyner 25236f37f232SEric Joyner SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "wufc", 25248eb6488eSEric Joyner CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_wufc, 25258eb6488eSEric Joyner "I", "Enable/Disable Wake Up Filters"); 25266f37f232SEric Joyner } 25276f37f232SEric Joyner 2528a9ca1c79SSean Bruno /* for X552/X557-AT devices */ 25296f37f232SEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { 25306f37f232SEric Joyner struct sysctl_oid *phy_node; 25316f37f232SEric Joyner struct sysctl_oid_list *phy_list; 25326f37f232SEric Joyner 25336f37f232SEric Joyner phy_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "phy", 25348eb6488eSEric Joyner CTLFLAG_RD, NULL, "External PHY sysctls"); 25356f37f232SEric Joyner phy_list = SYSCTL_CHILDREN(phy_node); 25366f37f232SEric Joyner 25376f37f232SEric Joyner SYSCTL_ADD_PROC(ctx, phy_list, OID_AUTO, "temp", 25388eb6488eSEric Joyner CTLTYPE_INT | CTLFLAG_RD, adapter, 0, ixgbe_sysctl_phy_temp, 25398eb6488eSEric Joyner "I", "Current External PHY Temperature (Celsius)"); 25406f37f232SEric Joyner 25416f37f232SEric Joyner SYSCTL_ADD_PROC(ctx, phy_list, OID_AUTO, "overtemp_occurred", 25426f37f232SEric Joyner CTLTYPE_INT | CTLFLAG_RD, adapter, 0, 25436f37f232SEric Joyner ixgbe_sysctl_phy_overtemp_occurred, "I", 25446f37f232SEric Joyner "External PHY High Temperature Event Occurred"); 25456f37f232SEric Joyner } 25468eb6488eSEric Joyner 25478eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_EEE) { 25488eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "eee_state", 25498eb6488eSEric Joyner CTLTYPE_INT | CTLFLAG_RW, adapter, 0, 25508eb6488eSEric Joyner ixgbe_sysctl_eee_state, "I", "EEE Power Save State"); 25518eb6488eSEric Joyner } 25528eb6488eSEric Joyner } /* ixgbe_add_device_sysctls */ 25538eb6488eSEric Joyner 25548eb6488eSEric Joyner /************************************************************************ 25558eb6488eSEric Joyner * ixgbe_allocate_pci_resources 25568eb6488eSEric Joyner ************************************************************************/ 25578eb6488eSEric Joyner static int 25588eb6488eSEric Joyner ixgbe_allocate_pci_resources(struct adapter *adapter) 25598eb6488eSEric Joyner { 25608eb6488eSEric Joyner device_t dev = adapter->dev; 25618eb6488eSEric Joyner int rid; 25628eb6488eSEric Joyner 25638eb6488eSEric Joyner rid = PCIR_BAR(0); 25648eb6488eSEric Joyner adapter->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 25658eb6488eSEric Joyner RF_ACTIVE); 25668eb6488eSEric Joyner 25678eb6488eSEric Joyner if (!(adapter->pci_mem)) { 25688eb6488eSEric Joyner device_printf(dev, "Unable to allocate bus resource: memory\n"); 25698eb6488eSEric Joyner return (ENXIO); 25708eb6488eSEric Joyner } 25718eb6488eSEric Joyner 25728eb6488eSEric Joyner /* Save bus_space values for READ/WRITE_REG macros */ 25738eb6488eSEric Joyner adapter->osdep.mem_bus_space_tag = rman_get_bustag(adapter->pci_mem); 25748eb6488eSEric Joyner adapter->osdep.mem_bus_space_handle = 25758eb6488eSEric Joyner rman_get_bushandle(adapter->pci_mem); 25768eb6488eSEric Joyner /* Set hw values for shared code */ 25778eb6488eSEric Joyner adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle; 25788eb6488eSEric Joyner 25798eb6488eSEric Joyner return (0); 25808eb6488eSEric Joyner } /* ixgbe_allocate_pci_resources */ 25818eb6488eSEric Joyner 25828eb6488eSEric Joyner /************************************************************************ 25838eb6488eSEric Joyner * ixgbe_detach - Device removal routine 25848eb6488eSEric Joyner * 25858eb6488eSEric Joyner * Called when the driver is being removed. 25868eb6488eSEric Joyner * Stops the adapter and deallocates all the resources 25878eb6488eSEric Joyner * that were allocated for driver operation. 25888eb6488eSEric Joyner * 25898eb6488eSEric Joyner * return 0 on success, positive on failure 25908eb6488eSEric Joyner ************************************************************************/ 25918eb6488eSEric Joyner static int 25928eb6488eSEric Joyner ixgbe_detach(device_t dev) 25938eb6488eSEric Joyner { 25948eb6488eSEric Joyner struct adapter *adapter = device_get_softc(dev); 25958eb6488eSEric Joyner struct ix_queue *que = adapter->queues; 25968eb6488eSEric Joyner struct tx_ring *txr = adapter->tx_rings; 25978eb6488eSEric Joyner u32 ctrl_ext; 25988eb6488eSEric Joyner 25998eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_detach: begin"); 26008eb6488eSEric Joyner 26018eb6488eSEric Joyner /* Make sure VLANS are not using driver */ 26028eb6488eSEric Joyner if (adapter->ifp->if_vlantrunk != NULL) { 26038eb6488eSEric Joyner device_printf(dev, "Vlan in use, detach first\n"); 26048eb6488eSEric Joyner return (EBUSY); 26058eb6488eSEric Joyner } 26068eb6488eSEric Joyner 26078eb6488eSEric Joyner if (ixgbe_pci_iov_detach(dev) != 0) { 26088eb6488eSEric Joyner device_printf(dev, "SR-IOV in use; detach first.\n"); 26098eb6488eSEric Joyner return (EBUSY); 26108eb6488eSEric Joyner } 26118eb6488eSEric Joyner 26128eb6488eSEric Joyner ether_ifdetach(adapter->ifp); 26138eb6488eSEric Joyner /* Stop the adapter */ 26148eb6488eSEric Joyner IXGBE_CORE_LOCK(adapter); 26158eb6488eSEric Joyner ixgbe_setup_low_power_mode(adapter); 26168eb6488eSEric Joyner IXGBE_CORE_UNLOCK(adapter); 26178eb6488eSEric Joyner 26188eb6488eSEric Joyner for (int i = 0; i < adapter->num_queues; i++, que++, txr++) { 26198eb6488eSEric Joyner if (que->tq) { 26208eb6488eSEric Joyner if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX)) 26218eb6488eSEric Joyner taskqueue_drain(que->tq, &txr->txq_task); 26228eb6488eSEric Joyner taskqueue_drain(que->tq, &que->que_task); 26238eb6488eSEric Joyner taskqueue_free(que->tq); 26248eb6488eSEric Joyner } 26258eb6488eSEric Joyner } 26268eb6488eSEric Joyner 26278eb6488eSEric Joyner /* Drain the Link queue */ 26288eb6488eSEric Joyner if (adapter->tq) { 26298eb6488eSEric Joyner taskqueue_drain(adapter->tq, &adapter->link_task); 26308eb6488eSEric Joyner taskqueue_drain(adapter->tq, &adapter->mod_task); 26318eb6488eSEric Joyner taskqueue_drain(adapter->tq, &adapter->msf_task); 26328eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_SRIOV) 26338eb6488eSEric Joyner taskqueue_drain(adapter->tq, &adapter->mbx_task); 26348eb6488eSEric Joyner taskqueue_drain(adapter->tq, &adapter->phy_task); 26358eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FDIR) 26368eb6488eSEric Joyner taskqueue_drain(adapter->tq, &adapter->fdir_task); 26378eb6488eSEric Joyner taskqueue_free(adapter->tq); 26388eb6488eSEric Joyner } 26398eb6488eSEric Joyner 26408eb6488eSEric Joyner /* let hardware know driver is unloading */ 26418eb6488eSEric Joyner ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); 26428eb6488eSEric Joyner ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD; 26438eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext); 26448eb6488eSEric Joyner 26458eb6488eSEric Joyner /* Unregister VLAN events */ 26468eb6488eSEric Joyner if (adapter->vlan_attach != NULL) 26478eb6488eSEric Joyner EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach); 26488eb6488eSEric Joyner if (adapter->vlan_detach != NULL) 26498eb6488eSEric Joyner EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach); 26508eb6488eSEric Joyner 26518eb6488eSEric Joyner callout_drain(&adapter->timer); 26528eb6488eSEric Joyner 26538eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_NETMAP) 26548eb6488eSEric Joyner netmap_detach(adapter->ifp); 26558eb6488eSEric Joyner 26568eb6488eSEric Joyner ixgbe_free_pci_resources(adapter); 26578eb6488eSEric Joyner bus_generic_detach(dev); 26588eb6488eSEric Joyner if_free(adapter->ifp); 26598eb6488eSEric Joyner 26608eb6488eSEric Joyner ixgbe_free_transmit_structures(adapter); 26618eb6488eSEric Joyner ixgbe_free_receive_structures(adapter); 26628eb6488eSEric Joyner free(adapter->queues, M_DEVBUF); 26638eb6488eSEric Joyner free(adapter->mta, M_IXGBE); 26648eb6488eSEric Joyner 26658eb6488eSEric Joyner IXGBE_CORE_LOCK_DESTROY(adapter); 26668eb6488eSEric Joyner 26678eb6488eSEric Joyner return (0); 26688eb6488eSEric Joyner } /* ixgbe_detach */ 26698eb6488eSEric Joyner 26708eb6488eSEric Joyner /************************************************************************ 26718eb6488eSEric Joyner * ixgbe_setup_low_power_mode - LPLU/WoL preparation 26728eb6488eSEric Joyner * 26738eb6488eSEric Joyner * Prepare the adapter/port for LPLU and/or WoL 26748eb6488eSEric Joyner ************************************************************************/ 26758eb6488eSEric Joyner static int 26768eb6488eSEric Joyner ixgbe_setup_low_power_mode(struct adapter *adapter) 26778eb6488eSEric Joyner { 26788eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 26798eb6488eSEric Joyner device_t dev = adapter->dev; 26808eb6488eSEric Joyner s32 error = 0; 26818eb6488eSEric Joyner 26828eb6488eSEric Joyner mtx_assert(&adapter->core_mtx, MA_OWNED); 26838eb6488eSEric Joyner 26848eb6488eSEric Joyner /* Limit power management flow to X550EM baseT */ 26858eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T && 26868eb6488eSEric Joyner hw->phy.ops.enter_lplu) { 26878eb6488eSEric Joyner /* Turn off support for APM wakeup. (Using ACPI instead) */ 26888eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_GRC, 26898eb6488eSEric Joyner IXGBE_READ_REG(hw, IXGBE_GRC) & ~(u32)2); 26908eb6488eSEric Joyner 26918eb6488eSEric Joyner /* 26928eb6488eSEric Joyner * Clear Wake Up Status register to prevent any previous wakeup 26938eb6488eSEric Joyner * events from waking us up immediately after we suspend. 26948eb6488eSEric Joyner */ 26958eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff); 26968eb6488eSEric Joyner 26978eb6488eSEric Joyner /* 26988eb6488eSEric Joyner * Program the Wakeup Filter Control register with user filter 26998eb6488eSEric Joyner * settings 27008eb6488eSEric Joyner */ 27018eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUFC, adapter->wufc); 27028eb6488eSEric Joyner 27038eb6488eSEric Joyner /* Enable wakeups and power management in Wakeup Control */ 27048eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUC, 27058eb6488eSEric Joyner IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN); 27068eb6488eSEric Joyner 27078eb6488eSEric Joyner /* X550EM baseT adapters need a special LPLU flow */ 27088eb6488eSEric Joyner hw->phy.reset_disable = true; 27098eb6488eSEric Joyner ixgbe_stop(adapter); 27108eb6488eSEric Joyner error = hw->phy.ops.enter_lplu(hw); 27118eb6488eSEric Joyner if (error) 27128eb6488eSEric Joyner device_printf(dev, "Error entering LPLU: %d\n", error); 27138eb6488eSEric Joyner hw->phy.reset_disable = false; 27148eb6488eSEric Joyner } else { 27158eb6488eSEric Joyner /* Just stop for other adapters */ 27168eb6488eSEric Joyner ixgbe_stop(adapter); 27178eb6488eSEric Joyner } 27188eb6488eSEric Joyner 27198eb6488eSEric Joyner return error; 27208eb6488eSEric Joyner } /* ixgbe_setup_low_power_mode */ 27218eb6488eSEric Joyner 27228eb6488eSEric Joyner /************************************************************************ 27238eb6488eSEric Joyner * ixgbe_shutdown - Shutdown entry point 27248eb6488eSEric Joyner ************************************************************************/ 27258eb6488eSEric Joyner static int 27268eb6488eSEric Joyner ixgbe_shutdown(device_t dev) 27278eb6488eSEric Joyner { 27288eb6488eSEric Joyner struct adapter *adapter = device_get_softc(dev); 27298eb6488eSEric Joyner int error = 0; 27308eb6488eSEric Joyner 27318eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_shutdown: begin"); 27328eb6488eSEric Joyner 27338eb6488eSEric Joyner IXGBE_CORE_LOCK(adapter); 27348eb6488eSEric Joyner error = ixgbe_setup_low_power_mode(adapter); 27358eb6488eSEric Joyner IXGBE_CORE_UNLOCK(adapter); 27368eb6488eSEric Joyner 27378eb6488eSEric Joyner return (error); 27388eb6488eSEric Joyner } /* ixgbe_shutdown */ 27398eb6488eSEric Joyner 27408eb6488eSEric Joyner /************************************************************************ 27418eb6488eSEric Joyner * ixgbe_suspend 27428eb6488eSEric Joyner * 27438eb6488eSEric Joyner * From D0 to D3 27448eb6488eSEric Joyner ************************************************************************/ 27458eb6488eSEric Joyner static int 27468eb6488eSEric Joyner ixgbe_suspend(device_t dev) 27478eb6488eSEric Joyner { 27488eb6488eSEric Joyner struct adapter *adapter = device_get_softc(dev); 27498eb6488eSEric Joyner int error = 0; 27508eb6488eSEric Joyner 27518eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_suspend: begin"); 27528eb6488eSEric Joyner 27538eb6488eSEric Joyner IXGBE_CORE_LOCK(adapter); 27548eb6488eSEric Joyner 27558eb6488eSEric Joyner error = ixgbe_setup_low_power_mode(adapter); 27568eb6488eSEric Joyner 27578eb6488eSEric Joyner IXGBE_CORE_UNLOCK(adapter); 27588eb6488eSEric Joyner 27598eb6488eSEric Joyner return (error); 27608eb6488eSEric Joyner } /* ixgbe_suspend */ 27618eb6488eSEric Joyner 27628eb6488eSEric Joyner /************************************************************************ 27638eb6488eSEric Joyner * ixgbe_resume 27648eb6488eSEric Joyner * 27658eb6488eSEric Joyner * From D3 to D0 27668eb6488eSEric Joyner ************************************************************************/ 27678eb6488eSEric Joyner static int 27688eb6488eSEric Joyner ixgbe_resume(device_t dev) 27698eb6488eSEric Joyner { 27708eb6488eSEric Joyner struct adapter *adapter = device_get_softc(dev); 27718eb6488eSEric Joyner struct ifnet *ifp = adapter->ifp; 27728eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 27738eb6488eSEric Joyner u32 wus; 27748eb6488eSEric Joyner 27758eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_resume: begin"); 27768eb6488eSEric Joyner 27778eb6488eSEric Joyner IXGBE_CORE_LOCK(adapter); 27788eb6488eSEric Joyner 27798eb6488eSEric Joyner /* Read & clear WUS register */ 27808eb6488eSEric Joyner wus = IXGBE_READ_REG(hw, IXGBE_WUS); 27818eb6488eSEric Joyner if (wus) 27828eb6488eSEric Joyner device_printf(dev, "Woken up by (WUS): %#010x\n", 27838eb6488eSEric Joyner IXGBE_READ_REG(hw, IXGBE_WUS)); 27848eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff); 27858eb6488eSEric Joyner /* And clear WUFC until next low-power transition */ 27868eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0); 27878eb6488eSEric Joyner 27888eb6488eSEric Joyner /* 27898eb6488eSEric Joyner * Required after D3->D0 transition; 27908eb6488eSEric Joyner * will re-advertise all previous advertised speeds 27918eb6488eSEric Joyner */ 27928eb6488eSEric Joyner if (ifp->if_flags & IFF_UP) 27938eb6488eSEric Joyner ixgbe_init_locked(adapter); 27948eb6488eSEric Joyner 27958eb6488eSEric Joyner IXGBE_CORE_UNLOCK(adapter); 27968eb6488eSEric Joyner 27978eb6488eSEric Joyner return (0); 27988eb6488eSEric Joyner } /* ixgbe_resume */ 27998eb6488eSEric Joyner 28008eb6488eSEric Joyner /************************************************************************ 28018eb6488eSEric Joyner * ixgbe_set_if_hwassist - Set the various hardware offload abilities. 28028eb6488eSEric Joyner * 28038eb6488eSEric Joyner * Takes the ifnet's if_capenable flags (e.g. set by the user using 28048eb6488eSEric Joyner * ifconfig) and indicates to the OS via the ifnet's if_hwassist 28058eb6488eSEric Joyner * field what mbuf offload flags the driver will understand. 28068eb6488eSEric Joyner ************************************************************************/ 28078eb6488eSEric Joyner static void 28088eb6488eSEric Joyner ixgbe_set_if_hwassist(struct adapter *adapter) 28098eb6488eSEric Joyner { 28108eb6488eSEric Joyner struct ifnet *ifp = adapter->ifp; 28118eb6488eSEric Joyner 28128eb6488eSEric Joyner ifp->if_hwassist = 0; 28138eb6488eSEric Joyner #if __FreeBSD_version >= 1000000 28148eb6488eSEric Joyner if (ifp->if_capenable & IFCAP_TSO4) 28158eb6488eSEric Joyner ifp->if_hwassist |= CSUM_IP_TSO; 28168eb6488eSEric Joyner if (ifp->if_capenable & IFCAP_TSO6) 28178eb6488eSEric Joyner ifp->if_hwassist |= CSUM_IP6_TSO; 28188eb6488eSEric Joyner if (ifp->if_capenable & IFCAP_TXCSUM) { 28198eb6488eSEric Joyner ifp->if_hwassist |= (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP); 28208eb6488eSEric Joyner if (adapter->hw.mac.type != ixgbe_mac_82598EB) 28218eb6488eSEric Joyner ifp->if_hwassist |= CSUM_IP_SCTP; 28228eb6488eSEric Joyner } 28238eb6488eSEric Joyner if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) { 28248eb6488eSEric Joyner ifp->if_hwassist |= (CSUM_IP6_UDP | CSUM_IP6_TCP); 28258eb6488eSEric Joyner if (adapter->hw.mac.type != ixgbe_mac_82598EB) 28268eb6488eSEric Joyner ifp->if_hwassist |= CSUM_IP6_SCTP; 28278eb6488eSEric Joyner } 28288eb6488eSEric Joyner #else 28298eb6488eSEric Joyner if (ifp->if_capenable & IFCAP_TSO) 28308eb6488eSEric Joyner ifp->if_hwassist |= CSUM_TSO; 28318eb6488eSEric Joyner if (ifp->if_capenable & IFCAP_TXCSUM) { 28328eb6488eSEric Joyner ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); 28338eb6488eSEric Joyner if (adapter->hw.mac.type != ixgbe_mac_82598EB) 28348eb6488eSEric Joyner ifp->if_hwassist |= CSUM_SCTP; 28358eb6488eSEric Joyner } 28368eb6488eSEric Joyner #endif 28378eb6488eSEric Joyner } /* ixgbe_set_if_hwassist */ 28388eb6488eSEric Joyner 28398eb6488eSEric Joyner /************************************************************************ 28408eb6488eSEric Joyner * ixgbe_init_locked - Init entry point 28418eb6488eSEric Joyner * 28428eb6488eSEric Joyner * Used in two ways: It is used by the stack as an init 28438eb6488eSEric Joyner * entry point in network interface structure. It is also 28448eb6488eSEric Joyner * used by the driver as a hw/sw initialization routine to 28458eb6488eSEric Joyner * get to a consistent state. 28468eb6488eSEric Joyner * 28478eb6488eSEric Joyner * return 0 on success, positive on failure 28488eb6488eSEric Joyner ************************************************************************/ 28498eb6488eSEric Joyner void 28508eb6488eSEric Joyner ixgbe_init_locked(struct adapter *adapter) 28518eb6488eSEric Joyner { 28528eb6488eSEric Joyner struct ifnet *ifp = adapter->ifp; 28538eb6488eSEric Joyner device_t dev = adapter->dev; 28548eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 28558eb6488eSEric Joyner struct tx_ring *txr; 28568eb6488eSEric Joyner struct rx_ring *rxr; 28578eb6488eSEric Joyner u32 txdctl, mhadd; 28588eb6488eSEric Joyner u32 rxdctl, rxctrl; 28598eb6488eSEric Joyner u32 ctrl_ext; 28608eb6488eSEric Joyner int err = 0; 28618eb6488eSEric Joyner 28628eb6488eSEric Joyner mtx_assert(&adapter->core_mtx, MA_OWNED); 28638eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_init_locked: begin"); 28648eb6488eSEric Joyner 28658eb6488eSEric Joyner hw->adapter_stopped = FALSE; 28668eb6488eSEric Joyner ixgbe_stop_adapter(hw); 28678eb6488eSEric Joyner callout_stop(&adapter->timer); 28688eb6488eSEric Joyner 28698eb6488eSEric Joyner /* Queue indices may change with IOV mode */ 28708eb6488eSEric Joyner ixgbe_align_all_queue_indices(adapter); 28718eb6488eSEric Joyner 28728eb6488eSEric Joyner /* reprogram the RAR[0] in case user changed it. */ 28738eb6488eSEric Joyner ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, IXGBE_RAH_AV); 28748eb6488eSEric Joyner 28758eb6488eSEric Joyner /* Get the latest mac address, User can use a LAA */ 28768eb6488eSEric Joyner bcopy(IF_LLADDR(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS); 28778eb6488eSEric Joyner ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1); 28788eb6488eSEric Joyner hw->addr_ctrl.rar_used_count = 1; 28798eb6488eSEric Joyner 28808eb6488eSEric Joyner /* Set hardware offload abilities from ifnet flags */ 28818eb6488eSEric Joyner ixgbe_set_if_hwassist(adapter); 28828eb6488eSEric Joyner 28838eb6488eSEric Joyner /* Prepare transmit descriptors and buffers */ 28848eb6488eSEric Joyner if (ixgbe_setup_transmit_structures(adapter)) { 28858eb6488eSEric Joyner device_printf(dev, "Could not setup transmit structures\n"); 28868eb6488eSEric Joyner ixgbe_stop(adapter); 28878eb6488eSEric Joyner return; 28888eb6488eSEric Joyner } 28898eb6488eSEric Joyner 28908eb6488eSEric Joyner ixgbe_init_hw(hw); 28918eb6488eSEric Joyner ixgbe_initialize_iov(adapter); 28928eb6488eSEric Joyner ixgbe_initialize_transmit_units(adapter); 28938eb6488eSEric Joyner 28948eb6488eSEric Joyner /* Setup Multicast table */ 28958eb6488eSEric Joyner ixgbe_set_multi(adapter); 28968eb6488eSEric Joyner 28978eb6488eSEric Joyner /* Determine the correct mbuf pool, based on frame size */ 28988eb6488eSEric Joyner if (adapter->max_frame_size <= MCLBYTES) 28998eb6488eSEric Joyner adapter->rx_mbuf_sz = MCLBYTES; 29008eb6488eSEric Joyner else 29018eb6488eSEric Joyner adapter->rx_mbuf_sz = MJUMPAGESIZE; 29028eb6488eSEric Joyner 29038eb6488eSEric Joyner /* Prepare receive descriptors and buffers */ 29048eb6488eSEric Joyner if (ixgbe_setup_receive_structures(adapter)) { 29058eb6488eSEric Joyner device_printf(dev, "Could not setup receive structures\n"); 29068eb6488eSEric Joyner ixgbe_stop(adapter); 29078eb6488eSEric Joyner return; 29088eb6488eSEric Joyner } 29098eb6488eSEric Joyner 29108eb6488eSEric Joyner /* Configure RX settings */ 29118eb6488eSEric Joyner ixgbe_initialize_receive_units(adapter); 29128eb6488eSEric Joyner 29138eb6488eSEric Joyner /* Enable SDP & MSI-X interrupts based on adapter */ 29148eb6488eSEric Joyner ixgbe_config_gpie(adapter); 29158eb6488eSEric Joyner 29168eb6488eSEric Joyner /* Set MTU size */ 29178eb6488eSEric Joyner if (ifp->if_mtu > ETHERMTU) { 29188eb6488eSEric Joyner /* aka IXGBE_MAXFRS on 82599 and newer */ 29198eb6488eSEric Joyner mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); 29208eb6488eSEric Joyner mhadd &= ~IXGBE_MHADD_MFS_MASK; 29218eb6488eSEric Joyner mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT; 29228eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); 29238eb6488eSEric Joyner } 29248eb6488eSEric Joyner 29258eb6488eSEric Joyner /* Now enable all the queues */ 29268eb6488eSEric Joyner for (int i = 0; i < adapter->num_queues; i++) { 29278eb6488eSEric Joyner txr = &adapter->tx_rings[i]; 29288eb6488eSEric Joyner txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me)); 29298eb6488eSEric Joyner txdctl |= IXGBE_TXDCTL_ENABLE; 29308eb6488eSEric Joyner /* Set WTHRESH to 8, burst writeback */ 29318eb6488eSEric Joyner txdctl |= (8 << 16); 29328eb6488eSEric Joyner /* 29338eb6488eSEric Joyner * When the internal queue falls below PTHRESH (32), 29348eb6488eSEric Joyner * start prefetching as long as there are at least 29358eb6488eSEric Joyner * HTHRESH (1) buffers ready. The values are taken 29368eb6488eSEric Joyner * from the Intel linux driver 3.8.21. 29378eb6488eSEric Joyner * Prefetching enables tx line rate even with 1 queue. 29388eb6488eSEric Joyner */ 29398eb6488eSEric Joyner txdctl |= (32 << 0) | (1 << 8); 29408eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl); 29418eb6488eSEric Joyner } 29428eb6488eSEric Joyner 29438eb6488eSEric Joyner for (int i = 0, j = 0; i < adapter->num_queues; i++) { 29448eb6488eSEric Joyner rxr = &adapter->rx_rings[i]; 29458eb6488eSEric Joyner rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); 29468eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) { 29478eb6488eSEric Joyner /* 29488eb6488eSEric Joyner * PTHRESH = 21 29498eb6488eSEric Joyner * HTHRESH = 4 29508eb6488eSEric Joyner * WTHRESH = 8 29518eb6488eSEric Joyner */ 29528eb6488eSEric Joyner rxdctl &= ~0x3FFFFF; 29538eb6488eSEric Joyner rxdctl |= 0x080420; 29548eb6488eSEric Joyner } 29558eb6488eSEric Joyner rxdctl |= IXGBE_RXDCTL_ENABLE; 29568eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), rxdctl); 29578eb6488eSEric Joyner for (; j < 10; j++) { 29588eb6488eSEric Joyner if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)) & 29598eb6488eSEric Joyner IXGBE_RXDCTL_ENABLE) 29608eb6488eSEric Joyner break; 29618eb6488eSEric Joyner else 29628eb6488eSEric Joyner msec_delay(1); 29638eb6488eSEric Joyner } 29648eb6488eSEric Joyner wmb(); 29658eb6488eSEric Joyner 29668eb6488eSEric Joyner /* 29678eb6488eSEric Joyner * In netmap mode, we must preserve the buffers made 29688eb6488eSEric Joyner * available to userspace before the if_init() 29698eb6488eSEric Joyner * (this is true by default on the TX side, because 29708eb6488eSEric Joyner * init makes all buffers available to userspace). 29718eb6488eSEric Joyner * 29728eb6488eSEric Joyner * netmap_reset() and the device specific routines 29738eb6488eSEric Joyner * (e.g. ixgbe_setup_receive_rings()) map these 29748eb6488eSEric Joyner * buffers at the end of the NIC ring, so here we 29758eb6488eSEric Joyner * must set the RDT (tail) register to make sure 29768eb6488eSEric Joyner * they are not overwritten. 29778eb6488eSEric Joyner * 29788eb6488eSEric Joyner * In this driver the NIC ring starts at RDH = 0, 29798eb6488eSEric Joyner * RDT points to the last slot available for reception (?), 29808eb6488eSEric Joyner * so RDT = num_rx_desc - 1 means the whole ring is available. 29818eb6488eSEric Joyner */ 29828eb6488eSEric Joyner #ifdef DEV_NETMAP 29838eb6488eSEric Joyner if ((adapter->feat_en & IXGBE_FEATURE_NETMAP) && 29848eb6488eSEric Joyner (ifp->if_capenable & IFCAP_NETMAP)) { 29858eb6488eSEric Joyner struct netmap_adapter *na = NA(adapter->ifp); 29868eb6488eSEric Joyner struct netmap_kring *kring = &na->rx_rings[i]; 29878eb6488eSEric Joyner int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring); 29888eb6488eSEric Joyner 29898eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me), t); 29908eb6488eSEric Joyner } else 29918eb6488eSEric Joyner #endif /* DEV_NETMAP */ 29928eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me), 29938eb6488eSEric Joyner adapter->num_rx_desc - 1); 29948eb6488eSEric Joyner } 29958eb6488eSEric Joyner 29968eb6488eSEric Joyner /* Enable Receive engine */ 29978eb6488eSEric Joyner rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 29988eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 29998eb6488eSEric Joyner rxctrl |= IXGBE_RXCTRL_DMBYPS; 30008eb6488eSEric Joyner rxctrl |= IXGBE_RXCTRL_RXEN; 30018eb6488eSEric Joyner ixgbe_enable_rx_dma(hw, rxctrl); 30028eb6488eSEric Joyner 30038eb6488eSEric Joyner callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter); 30048eb6488eSEric Joyner 30058eb6488eSEric Joyner /* Set up MSI-X routing */ 30068eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_MSIX) { 30078eb6488eSEric Joyner ixgbe_configure_ivars(adapter); 30088eb6488eSEric Joyner /* Set up auto-mask */ 30098eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 30108eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); 30118eb6488eSEric Joyner else { 30128eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF); 30138eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF); 30148eb6488eSEric Joyner } 30158eb6488eSEric Joyner } else { /* Simple settings for Legacy/MSI */ 30168eb6488eSEric Joyner ixgbe_set_ivar(adapter, 0, 0, 0); 30178eb6488eSEric Joyner ixgbe_set_ivar(adapter, 0, 0, 1); 30188eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); 30198eb6488eSEric Joyner } 30208eb6488eSEric Joyner 30218eb6488eSEric Joyner ixgbe_init_fdir(adapter); 30228eb6488eSEric Joyner 30238eb6488eSEric Joyner /* 30248eb6488eSEric Joyner * Check on any SFP devices that 30258eb6488eSEric Joyner * need to be kick-started 30268eb6488eSEric Joyner */ 30278eb6488eSEric Joyner if (hw->phy.type == ixgbe_phy_none) { 30288eb6488eSEric Joyner err = hw->phy.ops.identify(hw); 30298eb6488eSEric Joyner if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 30308eb6488eSEric Joyner device_printf(dev, 30318eb6488eSEric Joyner "Unsupported SFP+ module type was detected.\n"); 30328eb6488eSEric Joyner return; 30338eb6488eSEric Joyner } 30348eb6488eSEric Joyner } 30358eb6488eSEric Joyner 30368eb6488eSEric Joyner /* Set moderation on the Link interrupt */ 30378eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR); 30388eb6488eSEric Joyner 30398eb6488eSEric Joyner /* Config/Enable Link */ 30408eb6488eSEric Joyner ixgbe_config_link(adapter); 30418eb6488eSEric Joyner 30428eb6488eSEric Joyner /* Hardware Packet Buffer & Flow Control setup */ 30438eb6488eSEric Joyner ixgbe_config_delay_values(adapter); 30448eb6488eSEric Joyner 30458eb6488eSEric Joyner /* Initialize the FC settings */ 30468eb6488eSEric Joyner ixgbe_start_hw(hw); 30478eb6488eSEric Joyner 30488eb6488eSEric Joyner /* Set up VLAN support and filter */ 30498eb6488eSEric Joyner ixgbe_setup_vlan_hw_support(adapter); 30508eb6488eSEric Joyner 30518eb6488eSEric Joyner /* Setup DMA Coalescing */ 30528eb6488eSEric Joyner ixgbe_config_dmac(adapter); 30538eb6488eSEric Joyner 30548eb6488eSEric Joyner /* And now turn on interrupts */ 30558eb6488eSEric Joyner ixgbe_enable_intr(adapter); 30568eb6488eSEric Joyner 30578eb6488eSEric Joyner /* Enable the use of the MBX by the VF's */ 30588eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_SRIOV) { 30598eb6488eSEric Joyner ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 30608eb6488eSEric Joyner ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD; 30618eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 30628eb6488eSEric Joyner } 30638eb6488eSEric Joyner 30648eb6488eSEric Joyner /* Now inform the stack we're ready */ 30658eb6488eSEric Joyner ifp->if_drv_flags |= IFF_DRV_RUNNING; 30668eb6488eSEric Joyner 30678eb6488eSEric Joyner return; 30688eb6488eSEric Joyner } /* ixgbe_init_locked */ 30698eb6488eSEric Joyner 30708eb6488eSEric Joyner /************************************************************************ 30718eb6488eSEric Joyner * ixgbe_init 30728eb6488eSEric Joyner ************************************************************************/ 30738eb6488eSEric Joyner static void 30748eb6488eSEric Joyner ixgbe_init(void *arg) 30758eb6488eSEric Joyner { 30768eb6488eSEric Joyner struct adapter *adapter = arg; 30778eb6488eSEric Joyner 30788eb6488eSEric Joyner IXGBE_CORE_LOCK(adapter); 30798eb6488eSEric Joyner ixgbe_init_locked(adapter); 30808eb6488eSEric Joyner IXGBE_CORE_UNLOCK(adapter); 30818eb6488eSEric Joyner 30828eb6488eSEric Joyner return; 30838eb6488eSEric Joyner } /* ixgbe_init */ 30848eb6488eSEric Joyner 30858eb6488eSEric Joyner /************************************************************************ 30868eb6488eSEric Joyner * ixgbe_set_ivar 30878eb6488eSEric Joyner * 30888eb6488eSEric Joyner * Setup the correct IVAR register for a particular MSI-X interrupt 30898eb6488eSEric Joyner * (yes this is all very magic and confusing :) 30908eb6488eSEric Joyner * - entry is the register array entry 30918eb6488eSEric Joyner * - vector is the MSI-X vector for this queue 30928eb6488eSEric Joyner * - type is RX/TX/MISC 30938eb6488eSEric Joyner ************************************************************************/ 30948eb6488eSEric Joyner static void 30958eb6488eSEric Joyner ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type) 30968eb6488eSEric Joyner { 30978eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 30988eb6488eSEric Joyner u32 ivar, index; 30998eb6488eSEric Joyner 31008eb6488eSEric Joyner vector |= IXGBE_IVAR_ALLOC_VAL; 31018eb6488eSEric Joyner 31028eb6488eSEric Joyner switch (hw->mac.type) { 31038eb6488eSEric Joyner 31048eb6488eSEric Joyner case ixgbe_mac_82598EB: 31058eb6488eSEric Joyner if (type == -1) 31068eb6488eSEric Joyner entry = IXGBE_IVAR_OTHER_CAUSES_INDEX; 31078eb6488eSEric Joyner else 31088eb6488eSEric Joyner entry += (type * 64); 31098eb6488eSEric Joyner index = (entry >> 2) & 0x1F; 31108eb6488eSEric Joyner ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index)); 31118eb6488eSEric Joyner ivar &= ~(0xFF << (8 * (entry & 0x3))); 31128eb6488eSEric Joyner ivar |= (vector << (8 * (entry & 0x3))); 31138eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR(index), ivar); 31148eb6488eSEric Joyner break; 31158eb6488eSEric Joyner 31168eb6488eSEric Joyner case ixgbe_mac_82599EB: 31178eb6488eSEric Joyner case ixgbe_mac_X540: 31188eb6488eSEric Joyner case ixgbe_mac_X550: 31198eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 31208eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 31218eb6488eSEric Joyner if (type == -1) { /* MISC IVAR */ 31228eb6488eSEric Joyner index = (entry & 1) * 8; 31238eb6488eSEric Joyner ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC); 31248eb6488eSEric Joyner ivar &= ~(0xFF << index); 31258eb6488eSEric Joyner ivar |= (vector << index); 31268eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar); 31278eb6488eSEric Joyner } else { /* RX/TX IVARS */ 31288eb6488eSEric Joyner index = (16 * (entry & 1)) + (8 * type); 31298eb6488eSEric Joyner ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1)); 31308eb6488eSEric Joyner ivar &= ~(0xFF << index); 31318eb6488eSEric Joyner ivar |= (vector << index); 31328eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar); 31338eb6488eSEric Joyner } 31348eb6488eSEric Joyner 31358eb6488eSEric Joyner default: 31368eb6488eSEric Joyner break; 31378eb6488eSEric Joyner } 31388eb6488eSEric Joyner } /* ixgbe_set_ivar */ 31398eb6488eSEric Joyner 31408eb6488eSEric Joyner /************************************************************************ 31418eb6488eSEric Joyner * ixgbe_configure_ivars 31428eb6488eSEric Joyner ************************************************************************/ 31438eb6488eSEric Joyner static void 31448eb6488eSEric Joyner ixgbe_configure_ivars(struct adapter *adapter) 31458eb6488eSEric Joyner { 31468eb6488eSEric Joyner struct ix_queue *que = adapter->queues; 31478eb6488eSEric Joyner u32 newitr; 31488eb6488eSEric Joyner 31498eb6488eSEric Joyner if (ixgbe_max_interrupt_rate > 0) 31508eb6488eSEric Joyner newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8; 31518eb6488eSEric Joyner else { 31528eb6488eSEric Joyner /* 31538eb6488eSEric Joyner * Disable DMA coalescing if interrupt moderation is 31548eb6488eSEric Joyner * disabled. 31558eb6488eSEric Joyner */ 31568eb6488eSEric Joyner adapter->dmac = 0; 31578eb6488eSEric Joyner newitr = 0; 31588eb6488eSEric Joyner } 31598eb6488eSEric Joyner 31608eb6488eSEric Joyner for (int i = 0; i < adapter->num_queues; i++, que++) { 31618eb6488eSEric Joyner struct rx_ring *rxr = &adapter->rx_rings[i]; 31628eb6488eSEric Joyner struct tx_ring *txr = &adapter->tx_rings[i]; 31638eb6488eSEric Joyner /* First the RX queue entry */ 31648eb6488eSEric Joyner ixgbe_set_ivar(adapter, rxr->me, que->msix, 0); 31658eb6488eSEric Joyner /* ... and the TX */ 31668eb6488eSEric Joyner ixgbe_set_ivar(adapter, txr->me, que->msix, 1); 31678eb6488eSEric Joyner /* Set an Initial EITR value */ 31688eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(que->msix), newitr); 31698eb6488eSEric Joyner } 31708eb6488eSEric Joyner 31718eb6488eSEric Joyner /* For the Link interrupt */ 31728eb6488eSEric Joyner ixgbe_set_ivar(adapter, 1, adapter->vector, -1); 31738eb6488eSEric Joyner } /* ixgbe_configure_ivars */ 31748eb6488eSEric Joyner 31758eb6488eSEric Joyner /************************************************************************ 31768eb6488eSEric Joyner * ixgbe_config_gpie 31778eb6488eSEric Joyner ************************************************************************/ 31788eb6488eSEric Joyner static void 31798eb6488eSEric Joyner ixgbe_config_gpie(struct adapter *adapter) 31808eb6488eSEric Joyner { 31818eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 31828eb6488eSEric Joyner u32 gpie; 31838eb6488eSEric Joyner 31848eb6488eSEric Joyner gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); 31858eb6488eSEric Joyner 31868eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_MSIX) { 31878eb6488eSEric Joyner /* Enable Enhanced MSI-X mode */ 31888eb6488eSEric Joyner gpie |= IXGBE_GPIE_MSIX_MODE 31898eb6488eSEric Joyner | IXGBE_GPIE_EIAME 31908eb6488eSEric Joyner | IXGBE_GPIE_PBA_SUPPORT 31918eb6488eSEric Joyner | IXGBE_GPIE_OCD; 31928eb6488eSEric Joyner } 31938eb6488eSEric Joyner 31948eb6488eSEric Joyner /* Fan Failure Interrupt */ 31958eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) 31968eb6488eSEric Joyner gpie |= IXGBE_SDP1_GPIEN; 31978eb6488eSEric Joyner 31988eb6488eSEric Joyner /* Thermal Sensor Interrupt */ 31998eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR) 32008eb6488eSEric Joyner gpie |= IXGBE_SDP0_GPIEN_X540; 32018eb6488eSEric Joyner 32028eb6488eSEric Joyner /* Link detection */ 32038eb6488eSEric Joyner switch (hw->mac.type) { 32048eb6488eSEric Joyner case ixgbe_mac_82599EB: 32058eb6488eSEric Joyner gpie |= IXGBE_SDP1_GPIEN | IXGBE_SDP2_GPIEN; 32068eb6488eSEric Joyner break; 32078eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 32088eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 32098eb6488eSEric Joyner gpie |= IXGBE_SDP0_GPIEN_X540; 32108eb6488eSEric Joyner break; 32118eb6488eSEric Joyner default: 32128eb6488eSEric Joyner break; 32138eb6488eSEric Joyner } 32148eb6488eSEric Joyner 32158eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); 32168eb6488eSEric Joyner 32178eb6488eSEric Joyner return; 32188eb6488eSEric Joyner } /* ixgbe_config_gpie */ 32198eb6488eSEric Joyner 32208eb6488eSEric Joyner /************************************************************************ 32218eb6488eSEric Joyner * ixgbe_config_delay_values 32228eb6488eSEric Joyner * 32238eb6488eSEric Joyner * Requires adapter->max_frame_size to be set. 32248eb6488eSEric Joyner ************************************************************************/ 32258eb6488eSEric Joyner static void 32268eb6488eSEric Joyner ixgbe_config_delay_values(struct adapter *adapter) 32278eb6488eSEric Joyner { 32288eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 32298eb6488eSEric Joyner u32 rxpb, frame, size, tmp; 32308eb6488eSEric Joyner 32318eb6488eSEric Joyner frame = adapter->max_frame_size; 32328eb6488eSEric Joyner 32338eb6488eSEric Joyner /* Calculate High Water */ 32348eb6488eSEric Joyner switch (hw->mac.type) { 32358eb6488eSEric Joyner case ixgbe_mac_X540: 32368eb6488eSEric Joyner case ixgbe_mac_X550: 32378eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 32388eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 32398eb6488eSEric Joyner tmp = IXGBE_DV_X540(frame, frame); 32408eb6488eSEric Joyner break; 32418eb6488eSEric Joyner default: 32428eb6488eSEric Joyner tmp = IXGBE_DV(frame, frame); 32438eb6488eSEric Joyner break; 32448eb6488eSEric Joyner } 32458eb6488eSEric Joyner size = IXGBE_BT2KB(tmp); 32468eb6488eSEric Joyner rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10; 32478eb6488eSEric Joyner hw->fc.high_water[0] = rxpb - size; 32488eb6488eSEric Joyner 32498eb6488eSEric Joyner /* Now calculate Low Water */ 32508eb6488eSEric Joyner switch (hw->mac.type) { 32518eb6488eSEric Joyner case ixgbe_mac_X540: 32528eb6488eSEric Joyner case ixgbe_mac_X550: 32538eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 32548eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 32558eb6488eSEric Joyner tmp = IXGBE_LOW_DV_X540(frame); 32568eb6488eSEric Joyner break; 32578eb6488eSEric Joyner default: 32588eb6488eSEric Joyner tmp = IXGBE_LOW_DV(frame); 32598eb6488eSEric Joyner break; 32608eb6488eSEric Joyner } 32618eb6488eSEric Joyner hw->fc.low_water[0] = IXGBE_BT2KB(tmp); 32628eb6488eSEric Joyner 32638eb6488eSEric Joyner hw->fc.pause_time = IXGBE_FC_PAUSE; 32648eb6488eSEric Joyner hw->fc.send_xon = TRUE; 32658eb6488eSEric Joyner } /* ixgbe_config_delay_values */ 32668eb6488eSEric Joyner 32678eb6488eSEric Joyner /************************************************************************ 32688eb6488eSEric Joyner * ixgbe_set_multi - Multicast Update 32698eb6488eSEric Joyner * 32708eb6488eSEric Joyner * Called whenever multicast address list is updated. 32718eb6488eSEric Joyner ************************************************************************/ 32728eb6488eSEric Joyner static void 32738eb6488eSEric Joyner ixgbe_set_multi(struct adapter *adapter) 32748eb6488eSEric Joyner { 32758eb6488eSEric Joyner struct ifmultiaddr *ifma; 32768eb6488eSEric Joyner struct ixgbe_mc_addr *mta; 32778eb6488eSEric Joyner struct ifnet *ifp = adapter->ifp; 32788eb6488eSEric Joyner u8 *update_ptr; 32798eb6488eSEric Joyner int mcnt = 0; 32808eb6488eSEric Joyner u32 fctrl; 32818eb6488eSEric Joyner 32828eb6488eSEric Joyner IOCTL_DEBUGOUT("ixgbe_set_multi: begin"); 32838eb6488eSEric Joyner 32848eb6488eSEric Joyner mta = adapter->mta; 32858eb6488eSEric Joyner bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES); 32868eb6488eSEric Joyner 32878eb6488eSEric Joyner #if __FreeBSD_version < 800000 32888eb6488eSEric Joyner IF_ADDR_LOCK(ifp); 32898eb6488eSEric Joyner #else 32908eb6488eSEric Joyner if_maddr_rlock(ifp); 32918eb6488eSEric Joyner #endif 32928eb6488eSEric Joyner TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 32938eb6488eSEric Joyner if (ifma->ifma_addr->sa_family != AF_LINK) 32948eb6488eSEric Joyner continue; 32958eb6488eSEric Joyner if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) 32968eb6488eSEric Joyner break; 32978eb6488eSEric Joyner bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr), 32988eb6488eSEric Joyner mta[mcnt].addr, IXGBE_ETH_LENGTH_OF_ADDRESS); 32998eb6488eSEric Joyner mta[mcnt].vmdq = adapter->pool; 33008eb6488eSEric Joyner mcnt++; 33018eb6488eSEric Joyner } 33028eb6488eSEric Joyner #if __FreeBSD_version < 800000 33038eb6488eSEric Joyner IF_ADDR_UNLOCK(ifp); 33048eb6488eSEric Joyner #else 33058eb6488eSEric Joyner if_maddr_runlock(ifp); 33068eb6488eSEric Joyner #endif 33078eb6488eSEric Joyner 33088eb6488eSEric Joyner fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); 33098eb6488eSEric Joyner fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 33108eb6488eSEric Joyner if (ifp->if_flags & IFF_PROMISC) 33118eb6488eSEric Joyner fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 33128eb6488eSEric Joyner else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES || 33138eb6488eSEric Joyner ifp->if_flags & IFF_ALLMULTI) { 33148eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_MPE; 33158eb6488eSEric Joyner fctrl &= ~IXGBE_FCTRL_UPE; 33168eb6488eSEric Joyner } else 33178eb6488eSEric Joyner fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 33188eb6488eSEric Joyner 33198eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl); 33208eb6488eSEric Joyner 33218eb6488eSEric Joyner if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) { 33228eb6488eSEric Joyner update_ptr = (u8 *)mta; 33238eb6488eSEric Joyner ixgbe_update_mc_addr_list(&adapter->hw, update_ptr, mcnt, 33248eb6488eSEric Joyner ixgbe_mc_array_itr, TRUE); 33258eb6488eSEric Joyner } 33268eb6488eSEric Joyner 33278eb6488eSEric Joyner return; 33288eb6488eSEric Joyner } /* ixgbe_set_multi */ 33298eb6488eSEric Joyner 33308eb6488eSEric Joyner /************************************************************************ 33318eb6488eSEric Joyner * ixgbe_mc_array_itr 33328eb6488eSEric Joyner * 33338eb6488eSEric Joyner * An iterator function needed by the multicast shared code. 33348eb6488eSEric Joyner * It feeds the shared code routine the addresses in the 33358eb6488eSEric Joyner * array of ixgbe_set_multi() one by one. 33368eb6488eSEric Joyner ************************************************************************/ 33378eb6488eSEric Joyner static u8 * 33388eb6488eSEric Joyner ixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq) 33398eb6488eSEric Joyner { 33408eb6488eSEric Joyner struct ixgbe_mc_addr *mta; 33418eb6488eSEric Joyner 33428eb6488eSEric Joyner mta = (struct ixgbe_mc_addr *)*update_ptr; 33438eb6488eSEric Joyner *vmdq = mta->vmdq; 33448eb6488eSEric Joyner 33458eb6488eSEric Joyner *update_ptr = (u8*)(mta + 1); 33468eb6488eSEric Joyner 33478eb6488eSEric Joyner return (mta->addr); 33488eb6488eSEric Joyner } /* ixgbe_mc_array_itr */ 33498eb6488eSEric Joyner 33508eb6488eSEric Joyner /************************************************************************ 33518eb6488eSEric Joyner * ixgbe_local_timer - Timer routine 33528eb6488eSEric Joyner * 33538eb6488eSEric Joyner * Checks for link status, updates statistics, 33548eb6488eSEric Joyner * and runs the watchdog check. 33558eb6488eSEric Joyner ************************************************************************/ 33568eb6488eSEric Joyner static void 33578eb6488eSEric Joyner ixgbe_local_timer(void *arg) 33588eb6488eSEric Joyner { 33598eb6488eSEric Joyner struct adapter *adapter = arg; 33608eb6488eSEric Joyner device_t dev = adapter->dev; 33618eb6488eSEric Joyner struct ix_queue *que = adapter->queues; 33628eb6488eSEric Joyner u64 queues = 0; 33638eb6488eSEric Joyner int hung = 0; 33648eb6488eSEric Joyner 33658eb6488eSEric Joyner mtx_assert(&adapter->core_mtx, MA_OWNED); 33668eb6488eSEric Joyner 33678eb6488eSEric Joyner /* Check for pluggable optics */ 33688eb6488eSEric Joyner if (adapter->sfp_probe) 33698eb6488eSEric Joyner if (!ixgbe_sfp_probe(adapter)) 33708eb6488eSEric Joyner goto out; /* Nothing to do */ 33718eb6488eSEric Joyner 33728eb6488eSEric Joyner ixgbe_update_link_status(adapter); 33738eb6488eSEric Joyner ixgbe_update_stats_counters(adapter); 33748eb6488eSEric Joyner 33758eb6488eSEric Joyner /* 33768eb6488eSEric Joyner * Check the TX queues status 33778eb6488eSEric Joyner * - mark hung queues so we don't schedule on them 33788eb6488eSEric Joyner * - watchdog only if all queues show hung 33798eb6488eSEric Joyner */ 33808eb6488eSEric Joyner for (int i = 0; i < adapter->num_queues; i++, que++) { 33818eb6488eSEric Joyner /* Keep track of queues with work for soft irq */ 33828eb6488eSEric Joyner if (que->txr->busy) 33838eb6488eSEric Joyner queues |= ((u64)1 << que->me); 33848eb6488eSEric Joyner /* 33858eb6488eSEric Joyner * Each time txeof runs without cleaning, but there 33868eb6488eSEric Joyner * are uncleaned descriptors it increments busy. If 33878eb6488eSEric Joyner * we get to the MAX we declare it hung. 33888eb6488eSEric Joyner */ 33898eb6488eSEric Joyner if (que->busy == IXGBE_QUEUE_HUNG) { 33908eb6488eSEric Joyner ++hung; 33918eb6488eSEric Joyner /* Mark the queue as inactive */ 33928eb6488eSEric Joyner adapter->active_queues &= ~((u64)1 << que->me); 33938eb6488eSEric Joyner continue; 33948eb6488eSEric Joyner } else { 33958eb6488eSEric Joyner /* Check if we've come back from hung */ 33968eb6488eSEric Joyner if ((adapter->active_queues & ((u64)1 << que->me)) == 0) 33978eb6488eSEric Joyner adapter->active_queues |= ((u64)1 << que->me); 33988eb6488eSEric Joyner } 33998eb6488eSEric Joyner if (que->busy >= IXGBE_MAX_TX_BUSY) { 34008eb6488eSEric Joyner device_printf(dev, 34018eb6488eSEric Joyner "Warning queue %d appears to be hung!\n", i); 34028eb6488eSEric Joyner que->txr->busy = IXGBE_QUEUE_HUNG; 34038eb6488eSEric Joyner ++hung; 34048eb6488eSEric Joyner } 34058eb6488eSEric Joyner } 34068eb6488eSEric Joyner 34078eb6488eSEric Joyner /* Only truly watchdog if all queues show hung */ 34088eb6488eSEric Joyner if (hung == adapter->num_queues) 34098eb6488eSEric Joyner goto watchdog; 34108eb6488eSEric Joyner else if (queues != 0) { /* Force an IRQ on queues with work */ 34118eb6488eSEric Joyner ixgbe_rearm_queues(adapter, queues); 34128eb6488eSEric Joyner } 34138eb6488eSEric Joyner 34148eb6488eSEric Joyner out: 34158eb6488eSEric Joyner callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter); 34168eb6488eSEric Joyner return; 34178eb6488eSEric Joyner 34188eb6488eSEric Joyner watchdog: 34198eb6488eSEric Joyner device_printf(adapter->dev, "Watchdog timeout -- resetting\n"); 34208eb6488eSEric Joyner adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 34218eb6488eSEric Joyner adapter->watchdog_events++; 34228eb6488eSEric Joyner ixgbe_init_locked(adapter); 34238eb6488eSEric Joyner } /* ixgbe_local_timer */ 34248eb6488eSEric Joyner 34258eb6488eSEric Joyner /************************************************************************ 34268eb6488eSEric Joyner * ixgbe_sfp_probe 34278eb6488eSEric Joyner * 34288eb6488eSEric Joyner * Determine if a port had optics inserted. 34298eb6488eSEric Joyner ************************************************************************/ 34308eb6488eSEric Joyner static bool 34318eb6488eSEric Joyner ixgbe_sfp_probe(struct adapter *adapter) 34328eb6488eSEric Joyner { 34338eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 34348eb6488eSEric Joyner device_t dev = adapter->dev; 34358eb6488eSEric Joyner bool result = FALSE; 34368eb6488eSEric Joyner 34378eb6488eSEric Joyner if ((hw->phy.type == ixgbe_phy_nl) && 34388eb6488eSEric Joyner (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) { 34398eb6488eSEric Joyner s32 ret = hw->phy.ops.identify_sfp(hw); 34408eb6488eSEric Joyner if (ret) 34418eb6488eSEric Joyner goto out; 34428eb6488eSEric Joyner ret = hw->phy.ops.reset(hw); 34438eb6488eSEric Joyner adapter->sfp_probe = FALSE; 34448eb6488eSEric Joyner if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { 34458eb6488eSEric Joyner device_printf(dev, "Unsupported SFP+ module detected!"); 34468eb6488eSEric Joyner device_printf(dev, 34478eb6488eSEric Joyner "Reload driver with supported module.\n"); 34488eb6488eSEric Joyner goto out; 34498eb6488eSEric Joyner } else 34508eb6488eSEric Joyner device_printf(dev, "SFP+ module detected!\n"); 34518eb6488eSEric Joyner /* We now have supported optics */ 34528eb6488eSEric Joyner result = TRUE; 34538eb6488eSEric Joyner } 34548eb6488eSEric Joyner out: 34558eb6488eSEric Joyner 34568eb6488eSEric Joyner return (result); 34578eb6488eSEric Joyner } /* ixgbe_sfp_probe */ 34588eb6488eSEric Joyner 34598eb6488eSEric Joyner /************************************************************************ 34608eb6488eSEric Joyner * ixgbe_handle_mod - Tasklet for SFP module interrupts 34618eb6488eSEric Joyner ************************************************************************/ 34628eb6488eSEric Joyner static void 34638eb6488eSEric Joyner ixgbe_handle_mod(void *context, int pending) 34648eb6488eSEric Joyner { 34658eb6488eSEric Joyner struct adapter *adapter = context; 34668eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 34678eb6488eSEric Joyner device_t dev = adapter->dev; 34688eb6488eSEric Joyner u32 err, cage_full = 0; 34698eb6488eSEric Joyner 34708eb6488eSEric Joyner if (adapter->hw.need_crosstalk_fix) { 34718eb6488eSEric Joyner switch (hw->mac.type) { 34728eb6488eSEric Joyner case ixgbe_mac_82599EB: 34738eb6488eSEric Joyner cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 34748eb6488eSEric Joyner IXGBE_ESDP_SDP2; 34758eb6488eSEric Joyner break; 34768eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 34778eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 34788eb6488eSEric Joyner cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 34798eb6488eSEric Joyner IXGBE_ESDP_SDP0; 34808eb6488eSEric Joyner break; 34818eb6488eSEric Joyner default: 34828eb6488eSEric Joyner break; 34838eb6488eSEric Joyner } 34848eb6488eSEric Joyner 34858eb6488eSEric Joyner if (!cage_full) 34868eb6488eSEric Joyner return; 34878eb6488eSEric Joyner } 34888eb6488eSEric Joyner 34898eb6488eSEric Joyner err = hw->phy.ops.identify_sfp(hw); 34908eb6488eSEric Joyner if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 34918eb6488eSEric Joyner device_printf(dev, 34928eb6488eSEric Joyner "Unsupported SFP+ module type was detected.\n"); 34938eb6488eSEric Joyner return; 34948eb6488eSEric Joyner } 34958eb6488eSEric Joyner 34968eb6488eSEric Joyner err = hw->mac.ops.setup_sfp(hw); 34978eb6488eSEric Joyner if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 34988eb6488eSEric Joyner device_printf(dev, 34998eb6488eSEric Joyner "Setup failure - unsupported SFP+ module type.\n"); 35008eb6488eSEric Joyner return; 35018eb6488eSEric Joyner } 35028eb6488eSEric Joyner taskqueue_enqueue(adapter->tq, &adapter->msf_task); 35038eb6488eSEric Joyner } /* ixgbe_handle_mod */ 35048eb6488eSEric Joyner 35058eb6488eSEric Joyner 35068eb6488eSEric Joyner /************************************************************************ 35078eb6488eSEric Joyner * ixgbe_handle_msf - Tasklet for MSF (multispeed fiber) interrupts 35088eb6488eSEric Joyner ************************************************************************/ 35098eb6488eSEric Joyner static void 35108eb6488eSEric Joyner ixgbe_handle_msf(void *context, int pending) 35118eb6488eSEric Joyner { 35128eb6488eSEric Joyner struct adapter *adapter = context; 35138eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 35148eb6488eSEric Joyner u32 autoneg; 35158eb6488eSEric Joyner bool negotiate; 35168eb6488eSEric Joyner 35178eb6488eSEric Joyner /* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */ 35188eb6488eSEric Joyner adapter->phy_layer = ixgbe_get_supported_physical_layer(hw); 35198eb6488eSEric Joyner 35208eb6488eSEric Joyner autoneg = hw->phy.autoneg_advertised; 35218eb6488eSEric Joyner if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) 35228eb6488eSEric Joyner hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate); 35238eb6488eSEric Joyner if (hw->mac.ops.setup_link) 35248eb6488eSEric Joyner hw->mac.ops.setup_link(hw, autoneg, TRUE); 35258eb6488eSEric Joyner 35268eb6488eSEric Joyner /* Adjust media types shown in ifconfig */ 35278eb6488eSEric Joyner ifmedia_removeall(&adapter->media); 35288eb6488eSEric Joyner ixgbe_add_media_types(adapter); 35298eb6488eSEric Joyner ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); 35308eb6488eSEric Joyner } /* ixgbe_handle_msf */ 35318eb6488eSEric Joyner 35328eb6488eSEric Joyner /************************************************************************ 35338eb6488eSEric Joyner * ixgbe_handle_phy - Tasklet for external PHY interrupts 35348eb6488eSEric Joyner ************************************************************************/ 35358eb6488eSEric Joyner static void 35368eb6488eSEric Joyner ixgbe_handle_phy(void *context, int pending) 35378eb6488eSEric Joyner { 35388eb6488eSEric Joyner struct adapter *adapter = context; 35398eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 35408eb6488eSEric Joyner int error; 35418eb6488eSEric Joyner 35428eb6488eSEric Joyner error = hw->phy.ops.handle_lasi(hw); 35438eb6488eSEric Joyner if (error == IXGBE_ERR_OVERTEMP) 35448eb6488eSEric Joyner device_printf(adapter->dev, "CRITICAL: EXTERNAL PHY OVER TEMP!! PHY will downshift to lower power state!\n"); 35458eb6488eSEric Joyner else if (error) 35468eb6488eSEric Joyner device_printf(adapter->dev, 35478eb6488eSEric Joyner "Error handling LASI interrupt: %d\n", error); 35488eb6488eSEric Joyner } /* ixgbe_handle_phy */ 35498eb6488eSEric Joyner 35508eb6488eSEric Joyner /************************************************************************ 35518eb6488eSEric Joyner * ixgbe_stop - Stop the hardware 35528eb6488eSEric Joyner * 35538eb6488eSEric Joyner * Disables all traffic on the adapter by issuing a 35548eb6488eSEric Joyner * global reset on the MAC and deallocates TX/RX buffers. 35558eb6488eSEric Joyner ************************************************************************/ 35568eb6488eSEric Joyner static void 35578eb6488eSEric Joyner ixgbe_stop(void *arg) 35588eb6488eSEric Joyner { 35598eb6488eSEric Joyner struct ifnet *ifp; 35608eb6488eSEric Joyner struct adapter *adapter = arg; 35618eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 35628eb6488eSEric Joyner 35638eb6488eSEric Joyner ifp = adapter->ifp; 35648eb6488eSEric Joyner 35658eb6488eSEric Joyner mtx_assert(&adapter->core_mtx, MA_OWNED); 35668eb6488eSEric Joyner 35678eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_stop: begin\n"); 35688eb6488eSEric Joyner ixgbe_disable_intr(adapter); 35698eb6488eSEric Joyner callout_stop(&adapter->timer); 35708eb6488eSEric Joyner 35718eb6488eSEric Joyner /* Let the stack know...*/ 35728eb6488eSEric Joyner ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 35738eb6488eSEric Joyner 35748eb6488eSEric Joyner ixgbe_reset_hw(hw); 35758eb6488eSEric Joyner hw->adapter_stopped = FALSE; 35768eb6488eSEric Joyner ixgbe_stop_adapter(hw); 35778eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82599EB) 35788eb6488eSEric Joyner ixgbe_stop_mac_link_on_d3_82599(hw); 35798eb6488eSEric Joyner /* Turn off the laser - noop with no optics */ 35808eb6488eSEric Joyner ixgbe_disable_tx_laser(hw); 35818eb6488eSEric Joyner 35828eb6488eSEric Joyner /* Update the stack */ 35838eb6488eSEric Joyner adapter->link_up = FALSE; 35848eb6488eSEric Joyner ixgbe_update_link_status(adapter); 35858eb6488eSEric Joyner 35868eb6488eSEric Joyner /* reprogram the RAR[0] in case user changed it. */ 35878eb6488eSEric Joyner ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV); 35888eb6488eSEric Joyner 35898eb6488eSEric Joyner return; 35908eb6488eSEric Joyner } /* ixgbe_stop */ 35918eb6488eSEric Joyner 35928eb6488eSEric Joyner /************************************************************************ 35938eb6488eSEric Joyner * ixgbe_update_link_status - Update OS on link state 35948eb6488eSEric Joyner * 35958eb6488eSEric Joyner * Note: Only updates the OS on the cached link state. 35968eb6488eSEric Joyner * The real check of the hardware only happens with 35978eb6488eSEric Joyner * a link interrupt. 35988eb6488eSEric Joyner ************************************************************************/ 35998eb6488eSEric Joyner static void 36008eb6488eSEric Joyner ixgbe_update_link_status(struct adapter *adapter) 36018eb6488eSEric Joyner { 36028eb6488eSEric Joyner struct ifnet *ifp = adapter->ifp; 36038eb6488eSEric Joyner device_t dev = adapter->dev; 36048eb6488eSEric Joyner 36058eb6488eSEric Joyner if (adapter->link_up) { 36068eb6488eSEric Joyner if (adapter->link_active == FALSE) { 36078eb6488eSEric Joyner if (bootverbose) 36088eb6488eSEric Joyner device_printf(dev, "Link is up %d Gbps %s \n", 36098eb6488eSEric Joyner ((adapter->link_speed == 128) ? 10 : 1), 36108eb6488eSEric Joyner "Full Duplex"); 36118eb6488eSEric Joyner adapter->link_active = TRUE; 36128eb6488eSEric Joyner /* Update any Flow Control changes */ 36138eb6488eSEric Joyner ixgbe_fc_enable(&adapter->hw); 36148eb6488eSEric Joyner /* Update DMA coalescing config */ 36158eb6488eSEric Joyner ixgbe_config_dmac(adapter); 36168eb6488eSEric Joyner if_link_state_change(ifp, LINK_STATE_UP); 36178eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_SRIOV) 36188eb6488eSEric Joyner ixgbe_ping_all_vfs(adapter); 36198eb6488eSEric Joyner } 36208eb6488eSEric Joyner } else { /* Link down */ 36218eb6488eSEric Joyner if (adapter->link_active == TRUE) { 36228eb6488eSEric Joyner if (bootverbose) 36238eb6488eSEric Joyner device_printf(dev, "Link is Down\n"); 36248eb6488eSEric Joyner if_link_state_change(ifp, LINK_STATE_DOWN); 36258eb6488eSEric Joyner adapter->link_active = FALSE; 36268eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_SRIOV) 36278eb6488eSEric Joyner ixgbe_ping_all_vfs(adapter); 36288eb6488eSEric Joyner } 36298eb6488eSEric Joyner } 36308eb6488eSEric Joyner 36318eb6488eSEric Joyner return; 36328eb6488eSEric Joyner } /* ixgbe_update_link_status */ 36338eb6488eSEric Joyner 36348eb6488eSEric Joyner /************************************************************************ 36358eb6488eSEric Joyner * ixgbe_config_dmac - Configure DMA Coalescing 36368eb6488eSEric Joyner ************************************************************************/ 36378eb6488eSEric Joyner static void 36388eb6488eSEric Joyner ixgbe_config_dmac(struct adapter *adapter) 36398eb6488eSEric Joyner { 36408eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 36418eb6488eSEric Joyner struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config; 36428eb6488eSEric Joyner 36438eb6488eSEric Joyner if (hw->mac.type < ixgbe_mac_X550 || !hw->mac.ops.dmac_config) 36448eb6488eSEric Joyner return; 36458eb6488eSEric Joyner 36468eb6488eSEric Joyner if (dcfg->watchdog_timer ^ adapter->dmac || 36478eb6488eSEric Joyner dcfg->link_speed ^ adapter->link_speed) { 36488eb6488eSEric Joyner dcfg->watchdog_timer = adapter->dmac; 36498eb6488eSEric Joyner dcfg->fcoe_en = false; 36508eb6488eSEric Joyner dcfg->link_speed = adapter->link_speed; 36518eb6488eSEric Joyner dcfg->num_tcs = 1; 36528eb6488eSEric Joyner 36538eb6488eSEric Joyner INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n", 36548eb6488eSEric Joyner dcfg->watchdog_timer, dcfg->link_speed); 36558eb6488eSEric Joyner 36568eb6488eSEric Joyner hw->mac.ops.dmac_config(hw); 36578eb6488eSEric Joyner } 36588eb6488eSEric Joyner } /* ixgbe_config_dmac */ 36598eb6488eSEric Joyner 36608eb6488eSEric Joyner /************************************************************************ 36618eb6488eSEric Joyner * ixgbe_enable_intr 36628eb6488eSEric Joyner ************************************************************************/ 36638eb6488eSEric Joyner static void 36648eb6488eSEric Joyner ixgbe_enable_intr(struct adapter *adapter) 36658eb6488eSEric Joyner { 36668eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 36678eb6488eSEric Joyner struct ix_queue *que = adapter->queues; 36688eb6488eSEric Joyner u32 mask, fwsm; 36698eb6488eSEric Joyner 36708eb6488eSEric Joyner mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); 36718eb6488eSEric Joyner 36728eb6488eSEric Joyner switch (adapter->hw.mac.type) { 36738eb6488eSEric Joyner case ixgbe_mac_82599EB: 36748eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 36758eb6488eSEric Joyner /* Temperature sensor on some adapters */ 36768eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP0; 36778eb6488eSEric Joyner /* SFP+ (RX_LOS_N & MOD_ABS_N) */ 36788eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP1; 36798eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP2; 36808eb6488eSEric Joyner break; 36818eb6488eSEric Joyner case ixgbe_mac_X540: 36828eb6488eSEric Joyner /* Detect if Thermal Sensor is enabled */ 36838eb6488eSEric Joyner fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); 36848eb6488eSEric Joyner if (fwsm & IXGBE_FWSM_TS_ENABLED) 36858eb6488eSEric Joyner mask |= IXGBE_EIMS_TS; 36868eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 36878eb6488eSEric Joyner break; 36888eb6488eSEric Joyner case ixgbe_mac_X550: 36898eb6488eSEric Joyner /* MAC thermal sensor is automatically enabled */ 36908eb6488eSEric Joyner mask |= IXGBE_EIMS_TS; 36918eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 36928eb6488eSEric Joyner break; 36938eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 36948eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 36958eb6488eSEric Joyner /* Some devices use SDP0 for important information */ 36968eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP || 36978eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP || 36988eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N || 36998eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) 37008eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw); 37018eb6488eSEric Joyner if (hw->phy.type == ixgbe_phy_x550em_ext_t) 37028eb6488eSEric Joyner mask |= IXGBE_EICR_GPI_SDP0_X540; 37038eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 37048eb6488eSEric Joyner break; 37058eb6488eSEric Joyner default: 37068eb6488eSEric Joyner break; 37078eb6488eSEric Joyner } 37088eb6488eSEric Joyner 37098eb6488eSEric Joyner /* Enable Fan Failure detection */ 37108eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) 37118eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP1; 37128eb6488eSEric Joyner /* Enable SR-IOV */ 37138eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_SRIOV) 37148eb6488eSEric Joyner mask |= IXGBE_EIMS_MAILBOX; 37158eb6488eSEric Joyner /* Enable Flow Director */ 37168eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FDIR) 37178eb6488eSEric Joyner mask |= IXGBE_EIMS_FLOW_DIR; 37188eb6488eSEric Joyner 37198eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); 37208eb6488eSEric Joyner 37218eb6488eSEric Joyner /* With MSI-X we use auto clear */ 37228eb6488eSEric Joyner if (adapter->msix_mem) { 37238eb6488eSEric Joyner mask = IXGBE_EIMS_ENABLE_MASK; 37248eb6488eSEric Joyner /* Don't autoclear Link */ 37258eb6488eSEric Joyner mask &= ~IXGBE_EIMS_OTHER; 37268eb6488eSEric Joyner mask &= ~IXGBE_EIMS_LSC; 37278eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_SRIOV) 37288eb6488eSEric Joyner mask &= ~IXGBE_EIMS_MAILBOX; 37298eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask); 37306f37f232SEric Joyner } 37316f37f232SEric Joyner 3732758cc3dcSJack F Vogel /* 37338eb6488eSEric Joyner * Now enable all queues, this is done separately to 37348eb6488eSEric Joyner * allow for handling the extended (beyond 32) MSI-X 37358eb6488eSEric Joyner * vectors that can be used by 82599 3736758cc3dcSJack F Vogel */ 37378eb6488eSEric Joyner for (int i = 0; i < adapter->num_queues; i++, que++) 37388eb6488eSEric Joyner ixgbe_enable_queue(adapter, que->msix); 37398eb6488eSEric Joyner 37408eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 37418eb6488eSEric Joyner 37428eb6488eSEric Joyner return; 37438eb6488eSEric Joyner } /* ixgbe_enable_intr */ 37448eb6488eSEric Joyner 37458eb6488eSEric Joyner /************************************************************************ 37468eb6488eSEric Joyner * ixgbe_disable_intr 37478eb6488eSEric Joyner ************************************************************************/ 3748758cc3dcSJack F Vogel static void 37498eb6488eSEric Joyner ixgbe_disable_intr(struct adapter *adapter) 3750758cc3dcSJack F Vogel { 37518eb6488eSEric Joyner if (adapter->msix_mem) 37528eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 0); 37538eb6488eSEric Joyner if (adapter->hw.mac.type == ixgbe_mac_82598EB) { 37548eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); 37558eb6488eSEric Joyner } else { 37568eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000); 37578eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0); 37588eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); 37598eb6488eSEric Joyner } 37608eb6488eSEric Joyner IXGBE_WRITE_FLUSH(&adapter->hw); 3761758cc3dcSJack F Vogel 37628eb6488eSEric Joyner return; 37638eb6488eSEric Joyner } /* ixgbe_disable_intr */ 37648eb6488eSEric Joyner 37658eb6488eSEric Joyner /************************************************************************ 37668eb6488eSEric Joyner * ixgbe_legacy_irq - Legacy Interrupt Service routine 37678eb6488eSEric Joyner ************************************************************************/ 37688eb6488eSEric Joyner static void 37698eb6488eSEric Joyner ixgbe_legacy_irq(void *arg) 37708eb6488eSEric Joyner { 37718eb6488eSEric Joyner struct ix_queue *que = arg; 37728eb6488eSEric Joyner struct adapter *adapter = que->adapter; 37738eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 37748eb6488eSEric Joyner struct ifnet *ifp = adapter->ifp; 3775758cc3dcSJack F Vogel struct tx_ring *txr = adapter->tx_rings; 37768eb6488eSEric Joyner bool more = false; 37778eb6488eSEric Joyner u32 eicr, eicr_mask; 3778758cc3dcSJack F Vogel 37798eb6488eSEric Joyner /* Silicon errata #26 on 82598 */ 37808eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); 3781758cc3dcSJack F Vogel 37828eb6488eSEric Joyner eicr = IXGBE_READ_REG(hw, IXGBE_EICR); 3783758cc3dcSJack F Vogel 37848eb6488eSEric Joyner ++que->irqs; 37858eb6488eSEric Joyner if (eicr == 0) { 37868eb6488eSEric Joyner ixgbe_enable_intr(adapter); 37878eb6488eSEric Joyner return; 3788758cc3dcSJack F Vogel } 3789758cc3dcSJack F Vogel 37908eb6488eSEric Joyner if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 37918eb6488eSEric Joyner more = ixgbe_rxeof(que); 3792758cc3dcSJack F Vogel 37938eb6488eSEric Joyner IXGBE_TX_LOCK(txr); 37948eb6488eSEric Joyner ixgbe_txeof(txr); 37958eb6488eSEric Joyner if (!ixgbe_ring_empty(ifp, txr->br)) 37968eb6488eSEric Joyner ixgbe_start_locked(ifp, txr); 37978eb6488eSEric Joyner IXGBE_TX_UNLOCK(txr); 3798758cc3dcSJack F Vogel } 3799758cc3dcSJack F Vogel 38008eb6488eSEric Joyner /* Check for fan failure */ 38018eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) { 38028eb6488eSEric Joyner ixgbe_check_fan_failure(adapter, eicr, true); 38038eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 3804758cc3dcSJack F Vogel } 3805758cc3dcSJack F Vogel 38068eb6488eSEric Joyner /* Link status change */ 38078eb6488eSEric Joyner if (eicr & IXGBE_EICR_LSC) 38088eb6488eSEric Joyner taskqueue_enqueue(adapter->tq, &adapter->link_task); 38098eb6488eSEric Joyner 38108eb6488eSEric Joyner if (ixgbe_is_sfp(hw)) { 38118eb6488eSEric Joyner /* Pluggable optics-related interrupt */ 38128eb6488eSEric Joyner if (hw->mac.type >= ixgbe_mac_X540) 38138eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP0_X540; 38148eb6488eSEric Joyner else 38158eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); 38168eb6488eSEric Joyner 38178eb6488eSEric Joyner if (eicr & eicr_mask) { 38188eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); 38198eb6488eSEric Joyner taskqueue_enqueue(adapter->tq, &adapter->mod_task); 38208eb6488eSEric Joyner } 38218eb6488eSEric Joyner 38228eb6488eSEric Joyner if ((hw->mac.type == ixgbe_mac_82599EB) && 38238eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { 38248eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, 38258eb6488eSEric Joyner IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 38268eb6488eSEric Joyner taskqueue_enqueue(adapter->tq, &adapter->msf_task); 38278eb6488eSEric Joyner } 38288eb6488eSEric Joyner } 38298eb6488eSEric Joyner 38308eb6488eSEric Joyner /* External PHY interrupt */ 38318eb6488eSEric Joyner if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && 38328eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP0_X540)) 38338eb6488eSEric Joyner taskqueue_enqueue(adapter->tq, &adapter->phy_task); 38348eb6488eSEric Joyner 38358eb6488eSEric Joyner if (more) 38368eb6488eSEric Joyner taskqueue_enqueue(que->tq, &que->que_task); 38378eb6488eSEric Joyner else 38388eb6488eSEric Joyner ixgbe_enable_intr(adapter); 38398eb6488eSEric Joyner 38408eb6488eSEric Joyner return; 38418eb6488eSEric Joyner } /* ixgbe_legacy_irq */ 38428eb6488eSEric Joyner 38438eb6488eSEric Joyner /************************************************************************ 38448eb6488eSEric Joyner * ixgbe_free_pci_resources 38458eb6488eSEric Joyner ************************************************************************/ 38468eb6488eSEric Joyner static void 38478eb6488eSEric Joyner ixgbe_free_pci_resources(struct adapter *adapter) 38488eb6488eSEric Joyner { 38498eb6488eSEric Joyner struct ix_queue *que = adapter->queues; 38508eb6488eSEric Joyner device_t dev = adapter->dev; 38518eb6488eSEric Joyner int rid, memrid; 38528eb6488eSEric Joyner 38538eb6488eSEric Joyner if (adapter->hw.mac.type == ixgbe_mac_82598EB) 38548eb6488eSEric Joyner memrid = PCIR_BAR(MSIX_82598_BAR); 38558eb6488eSEric Joyner else 38568eb6488eSEric Joyner memrid = PCIR_BAR(MSIX_82599_BAR); 38578eb6488eSEric Joyner 38588eb6488eSEric Joyner /* 38598eb6488eSEric Joyner * There is a slight possibility of a failure mode 38608eb6488eSEric Joyner * in attach that will result in entering this function 38618eb6488eSEric Joyner * before interrupt resources have been initialized, and 38628eb6488eSEric Joyner * in that case we do not want to execute the loops below 38638eb6488eSEric Joyner * We can detect this reliably by the state of the adapter 38648eb6488eSEric Joyner * res pointer. 38658eb6488eSEric Joyner */ 38668eb6488eSEric Joyner if (adapter->res == NULL) 38678eb6488eSEric Joyner goto mem; 38688eb6488eSEric Joyner 38698eb6488eSEric Joyner /* 38708eb6488eSEric Joyner * Release all msix queue resources: 38718eb6488eSEric Joyner */ 38728eb6488eSEric Joyner for (int i = 0; i < adapter->num_queues; i++, que++) { 38738eb6488eSEric Joyner rid = que->msix + 1; 38748eb6488eSEric Joyner if (que->tag != NULL) { 38758eb6488eSEric Joyner bus_teardown_intr(dev, que->res, que->tag); 38768eb6488eSEric Joyner que->tag = NULL; 38778eb6488eSEric Joyner } 38788eb6488eSEric Joyner if (que->res != NULL) 38798eb6488eSEric Joyner bus_release_resource(dev, SYS_RES_IRQ, rid, que->res); 38808eb6488eSEric Joyner } 38818eb6488eSEric Joyner 38828eb6488eSEric Joyner 38838eb6488eSEric Joyner if (adapter->tag != NULL) { 38848eb6488eSEric Joyner bus_teardown_intr(dev, adapter->res, adapter->tag); 38858eb6488eSEric Joyner adapter->tag = NULL; 38868eb6488eSEric Joyner } 38878eb6488eSEric Joyner 38888eb6488eSEric Joyner /* Clean the Legacy or Link interrupt last */ 38898eb6488eSEric Joyner if (adapter->res != NULL) 38908eb6488eSEric Joyner bus_release_resource(dev, SYS_RES_IRQ, adapter->link_rid, 38918eb6488eSEric Joyner adapter->res); 38928eb6488eSEric Joyner 38938eb6488eSEric Joyner mem: 38948eb6488eSEric Joyner if ((adapter->feat_en & IXGBE_FEATURE_MSI) || 38958eb6488eSEric Joyner (adapter->feat_en & IXGBE_FEATURE_MSIX)) 38968eb6488eSEric Joyner pci_release_msi(dev); 38978eb6488eSEric Joyner 38988eb6488eSEric Joyner if (adapter->msix_mem != NULL) 38998eb6488eSEric Joyner bus_release_resource(dev, SYS_RES_MEMORY, memrid, 39008eb6488eSEric Joyner adapter->msix_mem); 39018eb6488eSEric Joyner 39028eb6488eSEric Joyner if (adapter->pci_mem != NULL) 39038eb6488eSEric Joyner bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), 39048eb6488eSEric Joyner adapter->pci_mem); 39058eb6488eSEric Joyner 39068eb6488eSEric Joyner return; 39078eb6488eSEric Joyner } /* ixgbe_free_pci_resources */ 39088eb6488eSEric Joyner 39098eb6488eSEric Joyner /************************************************************************ 39108eb6488eSEric Joyner * ixgbe_set_sysctl_value 39118eb6488eSEric Joyner ************************************************************************/ 3912b0c041f8SSean Bruno static void 3913b0c041f8SSean Bruno ixgbe_set_sysctl_value(struct adapter *adapter, const char *name, 3914b0c041f8SSean Bruno const char *description, int *limit, int value) 3915b0c041f8SSean Bruno { 3916b0c041f8SSean Bruno *limit = value; 3917b0c041f8SSean Bruno SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev), 3918b0c041f8SSean Bruno SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 3919b0c041f8SSean Bruno OID_AUTO, name, CTLFLAG_RW, limit, value, description); 39208eb6488eSEric Joyner } /* ixgbe_set_sysctl_value */ 3921b0c041f8SSean Bruno 39228eb6488eSEric Joyner /************************************************************************ 39238eb6488eSEric Joyner * ixgbe_sysctl_flowcntl 39248eb6488eSEric Joyner * 39258eb6488eSEric Joyner * SYSCTL wrapper around setting Flow Control 39268eb6488eSEric Joyner ************************************************************************/ 3927758cc3dcSJack F Vogel static int 3928f2c4db54SSteven Hartland ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS) 3929758cc3dcSJack F Vogel { 3930f2c4db54SSteven Hartland struct adapter *adapter; 39318eb6488eSEric Joyner int error, fc; 3932758cc3dcSJack F Vogel 3933f2c4db54SSteven Hartland adapter = (struct adapter *)arg1; 39348eb6488eSEric Joyner fc = adapter->hw.fc.current_mode; 3935f2c4db54SSteven Hartland 3936f2c4db54SSteven Hartland error = sysctl_handle_int(oidp, &fc, 0, req); 3937758cc3dcSJack F Vogel if ((error) || (req->newptr == NULL)) 3938758cc3dcSJack F Vogel return (error); 3939758cc3dcSJack F Vogel 3940758cc3dcSJack F Vogel /* Don't bother if it's not changed */ 39418eb6488eSEric Joyner if (fc == adapter->hw.fc.current_mode) 3942758cc3dcSJack F Vogel return (0); 3943758cc3dcSJack F Vogel 3944f2c4db54SSteven Hartland return ixgbe_set_flowcntl(adapter, fc); 39458eb6488eSEric Joyner } /* ixgbe_sysctl_flowcntl */ 3946f2c4db54SSteven Hartland 39478eb6488eSEric Joyner /************************************************************************ 39488eb6488eSEric Joyner * ixgbe_set_flowcntl - Set flow control 39498eb6488eSEric Joyner * 39508eb6488eSEric Joyner * Flow control values: 39518eb6488eSEric Joyner * 0 - off 39528eb6488eSEric Joyner * 1 - rx pause 39538eb6488eSEric Joyner * 2 - tx pause 39548eb6488eSEric Joyner * 3 - full 39558eb6488eSEric Joyner ************************************************************************/ 3956f2c4db54SSteven Hartland static int 3957f2c4db54SSteven Hartland ixgbe_set_flowcntl(struct adapter *adapter, int fc) 3958f2c4db54SSteven Hartland { 3959f2c4db54SSteven Hartland switch (fc) { 3960758cc3dcSJack F Vogel case ixgbe_fc_rx_pause: 3961758cc3dcSJack F Vogel case ixgbe_fc_tx_pause: 3962758cc3dcSJack F Vogel case ixgbe_fc_full: 39638eb6488eSEric Joyner adapter->hw.fc.requested_mode = fc; 3964758cc3dcSJack F Vogel if (adapter->num_queues > 1) 3965758cc3dcSJack F Vogel ixgbe_disable_rx_drop(adapter); 3966758cc3dcSJack F Vogel break; 3967758cc3dcSJack F Vogel case ixgbe_fc_none: 3968758cc3dcSJack F Vogel adapter->hw.fc.requested_mode = ixgbe_fc_none; 3969758cc3dcSJack F Vogel if (adapter->num_queues > 1) 3970758cc3dcSJack F Vogel ixgbe_enable_rx_drop(adapter); 3971758cc3dcSJack F Vogel break; 3972758cc3dcSJack F Vogel default: 3973758cc3dcSJack F Vogel return (EINVAL); 3974758cc3dcSJack F Vogel } 39758eb6488eSEric Joyner 3976758cc3dcSJack F Vogel /* Don't autoneg if forcing a value */ 3977758cc3dcSJack F Vogel adapter->hw.fc.disable_fc_autoneg = TRUE; 3978758cc3dcSJack F Vogel ixgbe_fc_enable(&adapter->hw); 39798eb6488eSEric Joyner 3980f2c4db54SSteven Hartland return (0); 39818eb6488eSEric Joyner } /* ixgbe_set_flowcntl */ 39828eb6488eSEric Joyner 39838eb6488eSEric Joyner /************************************************************************ 39848eb6488eSEric Joyner * ixgbe_enable_rx_drop 39858eb6488eSEric Joyner * 39868eb6488eSEric Joyner * Enable the hardware to drop packets when the buffer is 39878eb6488eSEric Joyner * full. This is useful with multiqueue, so that no single 39888eb6488eSEric Joyner * queue being full stalls the entire RX engine. We only 39898eb6488eSEric Joyner * enable this when Multiqueue is enabled AND Flow Control 39908eb6488eSEric Joyner * is disabled. 39918eb6488eSEric Joyner ************************************************************************/ 39928eb6488eSEric Joyner static void 39938eb6488eSEric Joyner ixgbe_enable_rx_drop(struct adapter *adapter) 39948eb6488eSEric Joyner { 39958eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 39968eb6488eSEric Joyner struct rx_ring *rxr; 39978eb6488eSEric Joyner u32 srrctl; 39988eb6488eSEric Joyner 39998eb6488eSEric Joyner for (int i = 0; i < adapter->num_queues; i++) { 40008eb6488eSEric Joyner rxr = &adapter->rx_rings[i]; 40018eb6488eSEric Joyner srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); 40028eb6488eSEric Joyner srrctl |= IXGBE_SRRCTL_DROP_EN; 40038eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); 4004758cc3dcSJack F Vogel } 4005758cc3dcSJack F Vogel 40068eb6488eSEric Joyner /* enable drop for each vf */ 40078eb6488eSEric Joyner for (int i = 0; i < adapter->num_vfs; i++) { 40088eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_QDE, 40098eb6488eSEric Joyner (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT) | 40108eb6488eSEric Joyner IXGBE_QDE_ENABLE)); 40118eb6488eSEric Joyner } 40128eb6488eSEric Joyner } /* ixgbe_enable_rx_drop */ 40138eb6488eSEric Joyner 40148eb6488eSEric Joyner /************************************************************************ 40158eb6488eSEric Joyner * ixgbe_disable_rx_drop 40168eb6488eSEric Joyner ************************************************************************/ 40178eb6488eSEric Joyner static void 40188eb6488eSEric Joyner ixgbe_disable_rx_drop(struct adapter *adapter) 40198eb6488eSEric Joyner { 40208eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 40218eb6488eSEric Joyner struct rx_ring *rxr; 40228eb6488eSEric Joyner u32 srrctl; 40238eb6488eSEric Joyner 40248eb6488eSEric Joyner for (int i = 0; i < adapter->num_queues; i++) { 40258eb6488eSEric Joyner rxr = &adapter->rx_rings[i]; 40268eb6488eSEric Joyner srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); 40278eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_DROP_EN; 40288eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); 40298eb6488eSEric Joyner } 40308eb6488eSEric Joyner 40318eb6488eSEric Joyner /* disable drop for each vf */ 40328eb6488eSEric Joyner for (int i = 0; i < adapter->num_vfs; i++) { 40338eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_QDE, 40348eb6488eSEric Joyner (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT))); 40358eb6488eSEric Joyner } 40368eb6488eSEric Joyner } /* ixgbe_disable_rx_drop */ 40378eb6488eSEric Joyner 40388eb6488eSEric Joyner /************************************************************************ 40398eb6488eSEric Joyner * ixgbe_sysctl_advertise 40408eb6488eSEric Joyner * 40418eb6488eSEric Joyner * SYSCTL wrapper around setting advertised speed 40428eb6488eSEric Joyner ************************************************************************/ 4043758cc3dcSJack F Vogel static int 4044f2c4db54SSteven Hartland ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS) 4045758cc3dcSJack F Vogel { 4046758cc3dcSJack F Vogel struct adapter *adapter; 40478eb6488eSEric Joyner int error, advertise; 4048758cc3dcSJack F Vogel 4049758cc3dcSJack F Vogel adapter = (struct adapter *)arg1; 4050f2c4db54SSteven Hartland advertise = adapter->advertise; 4051758cc3dcSJack F Vogel 4052f2c4db54SSteven Hartland error = sysctl_handle_int(oidp, &advertise, 0, req); 4053758cc3dcSJack F Vogel if ((error) || (req->newptr == NULL)) 4054758cc3dcSJack F Vogel return (error); 4055758cc3dcSJack F Vogel 4056f2c4db54SSteven Hartland return ixgbe_set_advertise(adapter, advertise); 40578eb6488eSEric Joyner } /* ixgbe_sysctl_advertise */ 4058f2c4db54SSteven Hartland 40598eb6488eSEric Joyner /************************************************************************ 40608eb6488eSEric Joyner * ixgbe_set_advertise - Control advertised link speed 40618eb6488eSEric Joyner * 40628eb6488eSEric Joyner * Flags: 40638eb6488eSEric Joyner * 0x1 - advertise 100 Mb 40648eb6488eSEric Joyner * 0x2 - advertise 1G 40658eb6488eSEric Joyner * 0x4 - advertise 10G 40668eb6488eSEric Joyner * 0x8 - advertise 10 Mb (yes, Mb) 40678eb6488eSEric Joyner ************************************************************************/ 4068f2c4db54SSteven Hartland static int 4069f2c4db54SSteven Hartland ixgbe_set_advertise(struct adapter *adapter, int advertise) 4070f2c4db54SSteven Hartland { 4071f2c4db54SSteven Hartland device_t dev; 4072f2c4db54SSteven Hartland struct ixgbe_hw *hw; 40738eb6488eSEric Joyner ixgbe_link_speed speed = 0; 40748eb6488eSEric Joyner ixgbe_link_speed link_caps = 0; 40758eb6488eSEric Joyner s32 err = IXGBE_NOT_IMPLEMENTED; 40768eb6488eSEric Joyner bool negotiate = FALSE; 4077f2c4db54SSteven Hartland 4078d775d23aSSteven Hartland /* Checks to validate new value */ 4079d775d23aSSteven Hartland if (adapter->advertise == advertise) /* no change */ 4080d775d23aSSteven Hartland return (0); 4081d775d23aSSteven Hartland 4082f2c4db54SSteven Hartland dev = adapter->dev; 40838eb6488eSEric Joyner hw = &adapter->hw; 4084f2c4db54SSteven Hartland 4085a9ca1c79SSean Bruno /* No speed changes for backplane media */ 4086a9ca1c79SSean Bruno if (hw->phy.media_type == ixgbe_media_type_backplane) 4087a9ca1c79SSean Bruno return (ENODEV); 4088a9ca1c79SSean Bruno 4089758cc3dcSJack F Vogel if (!((hw->phy.media_type == ixgbe_media_type_copper) || 4090758cc3dcSJack F Vogel (hw->phy.multispeed_fiber))) { 40918eb6488eSEric Joyner device_printf(dev, "Advertised speed can only be set on copper or multispeed fiber media types.\n"); 4092758cc3dcSJack F Vogel return (EINVAL); 4093758cc3dcSJack F Vogel } 4094758cc3dcSJack F Vogel 40958eb6488eSEric Joyner if (advertise < 0x1 || advertise > 0xF) { 40968eb6488eSEric Joyner device_printf(dev, "Invalid advertised speed; valid modes are 0x1 through 0xF\n"); 4097758cc3dcSJack F Vogel return (EINVAL); 4098758cc3dcSJack F Vogel } 4099758cc3dcSJack F Vogel 41008eb6488eSEric Joyner if (hw->mac.ops.get_link_capabilities) { 41018eb6488eSEric Joyner err = hw->mac.ops.get_link_capabilities(hw, &link_caps, 41028eb6488eSEric Joyner &negotiate); 41038eb6488eSEric Joyner if (err != IXGBE_SUCCESS) { 41048eb6488eSEric Joyner device_printf(dev, "Unable to determine supported advertise speeds\n"); 41058eb6488eSEric Joyner return (ENODEV); 41068eb6488eSEric Joyner } 4107758cc3dcSJack F Vogel } 4108758cc3dcSJack F Vogel 4109758cc3dcSJack F Vogel /* Set new value and report new advertised mode */ 41108eb6488eSEric Joyner if (advertise & 0x1) { 41118eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_100_FULL)) { 41128eb6488eSEric Joyner device_printf(dev, "Interface does not support 100Mb advertised speed\n"); 41138eb6488eSEric Joyner return (EINVAL); 41148eb6488eSEric Joyner } 4115758cc3dcSJack F Vogel speed |= IXGBE_LINK_SPEED_100_FULL; 41168eb6488eSEric Joyner } 41178eb6488eSEric Joyner if (advertise & 0x2) { 41188eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_1GB_FULL)) { 41198eb6488eSEric Joyner device_printf(dev, "Interface does not support 1Gb advertised speed\n"); 41208eb6488eSEric Joyner return (EINVAL); 41218eb6488eSEric Joyner } 4122758cc3dcSJack F Vogel speed |= IXGBE_LINK_SPEED_1GB_FULL; 41238eb6488eSEric Joyner } 41248eb6488eSEric Joyner if (advertise & 0x4) { 41258eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_10GB_FULL)) { 41268eb6488eSEric Joyner device_printf(dev, "Interface does not support 10Gb advertised speed\n"); 41278eb6488eSEric Joyner return (EINVAL); 41288eb6488eSEric Joyner } 4129758cc3dcSJack F Vogel speed |= IXGBE_LINK_SPEED_10GB_FULL; 41308eb6488eSEric Joyner } 41318eb6488eSEric Joyner if (advertise & 0x8) { 41328eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_10_FULL)) { 41338eb6488eSEric Joyner device_printf(dev, "Interface does not support 10Mb advertised speed\n"); 41348eb6488eSEric Joyner return (EINVAL); 41358eb6488eSEric Joyner } 41368eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10_FULL; 41378eb6488eSEric Joyner } 4138758cc3dcSJack F Vogel 4139758cc3dcSJack F Vogel hw->mac.autotry_restart = TRUE; 4140758cc3dcSJack F Vogel hw->mac.ops.setup_link(hw, speed, TRUE); 41418eb6488eSEric Joyner adapter->advertise = advertise; 4142758cc3dcSJack F Vogel 4143f2c4db54SSteven Hartland return (0); 41448eb6488eSEric Joyner } /* ixgbe_set_advertise */ 41458eb6488eSEric Joyner 41468eb6488eSEric Joyner /************************************************************************ 41478eb6488eSEric Joyner * ixgbe_get_advertise - Get current advertised speed settings 41488eb6488eSEric Joyner * 41498eb6488eSEric Joyner * Formatted for sysctl usage. 41508eb6488eSEric Joyner * Flags: 41518eb6488eSEric Joyner * 0x1 - advertise 100 Mb 41528eb6488eSEric Joyner * 0x2 - advertise 1G 41538eb6488eSEric Joyner * 0x4 - advertise 10G 41548eb6488eSEric Joyner * 0x8 - advertise 10 Mb (yes, Mb) 41558eb6488eSEric Joyner ************************************************************************/ 41568eb6488eSEric Joyner static int 41578eb6488eSEric Joyner ixgbe_get_advertise(struct adapter *adapter) 41588eb6488eSEric Joyner { 41598eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 41608eb6488eSEric Joyner int speed; 41618eb6488eSEric Joyner ixgbe_link_speed link_caps = 0; 41628eb6488eSEric Joyner s32 err; 41638eb6488eSEric Joyner bool negotiate = FALSE; 4164758cc3dcSJack F Vogel 4165758cc3dcSJack F Vogel /* 41668eb6488eSEric Joyner * Advertised speed means nothing unless it's copper or 41678eb6488eSEric Joyner * multi-speed fiber 4168758cc3dcSJack F Vogel */ 41698eb6488eSEric Joyner if (!(hw->phy.media_type == ixgbe_media_type_copper) && 41708eb6488eSEric Joyner !(hw->phy.multispeed_fiber)) 4171758cc3dcSJack F Vogel return (0); 4172758cc3dcSJack F Vogel 41738eb6488eSEric Joyner err = hw->mac.ops.get_link_capabilities(hw, &link_caps, &negotiate); 41748eb6488eSEric Joyner if (err != IXGBE_SUCCESS) 41758eb6488eSEric Joyner return (0); 41768eb6488eSEric Joyner 41778eb6488eSEric Joyner speed = 41788eb6488eSEric Joyner ((link_caps & IXGBE_LINK_SPEED_10GB_FULL) ? 4 : 0) | 41798eb6488eSEric Joyner ((link_caps & IXGBE_LINK_SPEED_1GB_FULL) ? 2 : 0) | 41808eb6488eSEric Joyner ((link_caps & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0) | 41818eb6488eSEric Joyner ((link_caps & IXGBE_LINK_SPEED_10_FULL) ? 8 : 0); 41828eb6488eSEric Joyner 41838eb6488eSEric Joyner return speed; 41848eb6488eSEric Joyner } /* ixgbe_get_advertise */ 41858eb6488eSEric Joyner 41868eb6488eSEric Joyner /************************************************************************ 41878eb6488eSEric Joyner * ixgbe_sysctl_dmac - Manage DMA Coalescing 41888eb6488eSEric Joyner * 41898eb6488eSEric Joyner * Control values: 41908eb6488eSEric Joyner * 0/1 - off / on (use default value of 1000) 41918eb6488eSEric Joyner * 41928eb6488eSEric Joyner * Legal timer values are: 41938eb6488eSEric Joyner * 50,100,250,500,1000,2000,5000,10000 41948eb6488eSEric Joyner * 41958eb6488eSEric Joyner * Turning off interrupt moderation will also turn this off. 41968eb6488eSEric Joyner ************************************************************************/ 41976f37f232SEric Joyner static int 41986f37f232SEric Joyner ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS) 41996f37f232SEric Joyner { 42006f37f232SEric Joyner struct adapter *adapter = (struct adapter *)arg1; 42016f37f232SEric Joyner struct ifnet *ifp = adapter->ifp; 42026f37f232SEric Joyner int error; 4203a9ca1c79SSean Bruno u32 newval; 42046f37f232SEric Joyner 4205a9ca1c79SSean Bruno newval = adapter->dmac; 4206a9ca1c79SSean Bruno error = sysctl_handle_int(oidp, &newval, 0, req); 42076f37f232SEric Joyner if ((error) || (req->newptr == NULL)) 42086f37f232SEric Joyner return (error); 42096f37f232SEric Joyner 4210a9ca1c79SSean Bruno switch (newval) { 42116f37f232SEric Joyner case 0: 42126f37f232SEric Joyner /* Disabled */ 4213a9ca1c79SSean Bruno adapter->dmac = 0; 42146f37f232SEric Joyner break; 4215a9ca1c79SSean Bruno case 1: 4216a9ca1c79SSean Bruno /* Enable and use default */ 42176f37f232SEric Joyner adapter->dmac = 1000; 42186f37f232SEric Joyner break; 42196f37f232SEric Joyner case 50: 42206f37f232SEric Joyner case 100: 42216f37f232SEric Joyner case 250: 42226f37f232SEric Joyner case 500: 42236f37f232SEric Joyner case 1000: 42246f37f232SEric Joyner case 2000: 42256f37f232SEric Joyner case 5000: 42266f37f232SEric Joyner case 10000: 42276f37f232SEric Joyner /* Legal values - allow */ 4228a9ca1c79SSean Bruno adapter->dmac = newval; 42296f37f232SEric Joyner break; 42306f37f232SEric Joyner default: 42316f37f232SEric Joyner /* Do nothing, illegal value */ 42326f37f232SEric Joyner return (EINVAL); 42336f37f232SEric Joyner } 42346f37f232SEric Joyner 42356f37f232SEric Joyner /* Re-initialize hardware if it's already running */ 42366f37f232SEric Joyner if (ifp->if_drv_flags & IFF_DRV_RUNNING) 42376f37f232SEric Joyner ixgbe_init(adapter); 42386f37f232SEric Joyner 42396f37f232SEric Joyner return (0); 42408eb6488eSEric Joyner } /* ixgbe_sysctl_dmac */ 42416f37f232SEric Joyner 4242a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 42438eb6488eSEric Joyner /************************************************************************ 42448eb6488eSEric Joyner * ixgbe_sysctl_power_state 42458eb6488eSEric Joyner * 4246a9ca1c79SSean Bruno * Sysctl to test power states 4247a9ca1c79SSean Bruno * Values: 4248a9ca1c79SSean Bruno * 0 - set device to D0 4249a9ca1c79SSean Bruno * 3 - set device to D3 4250a9ca1c79SSean Bruno * (none) - get current device power state 42518eb6488eSEric Joyner ************************************************************************/ 4252a9ca1c79SSean Bruno static int 4253a9ca1c79SSean Bruno ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS) 4254a9ca1c79SSean Bruno { 4255a9ca1c79SSean Bruno struct adapter *adapter = (struct adapter *)arg1; 4256a9ca1c79SSean Bruno device_t dev = adapter->dev; 4257a9ca1c79SSean Bruno int curr_ps, new_ps, error = 0; 4258a9ca1c79SSean Bruno 4259a9ca1c79SSean Bruno curr_ps = new_ps = pci_get_powerstate(dev); 4260a9ca1c79SSean Bruno 4261a9ca1c79SSean Bruno error = sysctl_handle_int(oidp, &new_ps, 0, req); 4262a9ca1c79SSean Bruno if ((error) || (req->newptr == NULL)) 4263a9ca1c79SSean Bruno return (error); 4264a9ca1c79SSean Bruno 4265a9ca1c79SSean Bruno if (new_ps == curr_ps) 4266a9ca1c79SSean Bruno return (0); 4267a9ca1c79SSean Bruno 4268a9ca1c79SSean Bruno if (new_ps == 3 && curr_ps == 0) 4269a9ca1c79SSean Bruno error = DEVICE_SUSPEND(dev); 4270a9ca1c79SSean Bruno else if (new_ps == 0 && curr_ps == 3) 4271a9ca1c79SSean Bruno error = DEVICE_RESUME(dev); 4272a9ca1c79SSean Bruno else 4273a9ca1c79SSean Bruno return (EINVAL); 4274a9ca1c79SSean Bruno 4275a9ca1c79SSean Bruno device_printf(dev, "New state: %d\n", pci_get_powerstate(dev)); 4276a9ca1c79SSean Bruno 4277a9ca1c79SSean Bruno return (error); 42788eb6488eSEric Joyner } /* ixgbe_sysctl_power_state */ 4279a9ca1c79SSean Bruno #endif 42808eb6488eSEric Joyner 42818eb6488eSEric Joyner /************************************************************************ 42828eb6488eSEric Joyner * ixgbe_sysctl_wol_enable 42838eb6488eSEric Joyner * 42848eb6488eSEric Joyner * Sysctl to enable/disable the WoL capability, 42858eb6488eSEric Joyner * if supported by the adapter. 42868eb6488eSEric Joyner * 42876f37f232SEric Joyner * Values: 42886f37f232SEric Joyner * 0 - disabled 42896f37f232SEric Joyner * 1 - enabled 42908eb6488eSEric Joyner ************************************************************************/ 42916f37f232SEric Joyner static int 42926f37f232SEric Joyner ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS) 42936f37f232SEric Joyner { 42946f37f232SEric Joyner struct adapter *adapter = (struct adapter *)arg1; 42956f37f232SEric Joyner struct ixgbe_hw *hw = &adapter->hw; 42966f37f232SEric Joyner int new_wol_enabled; 42976f37f232SEric Joyner int error = 0; 42986f37f232SEric Joyner 42996f37f232SEric Joyner new_wol_enabled = hw->wol_enabled; 43006f37f232SEric Joyner error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req); 43016f37f232SEric Joyner if ((error) || (req->newptr == NULL)) 43026f37f232SEric Joyner return (error); 4303a9ca1c79SSean Bruno new_wol_enabled = !!(new_wol_enabled); 43046f37f232SEric Joyner if (new_wol_enabled == hw->wol_enabled) 43056f37f232SEric Joyner return (0); 43066f37f232SEric Joyner 43076f37f232SEric Joyner if (new_wol_enabled > 0 && !adapter->wol_support) 43086f37f232SEric Joyner return (ENODEV); 43096f37f232SEric Joyner else 4310a9ca1c79SSean Bruno hw->wol_enabled = new_wol_enabled; 43116f37f232SEric Joyner 43126f37f232SEric Joyner return (0); 43138eb6488eSEric Joyner } /* ixgbe_sysctl_wol_enable */ 43146f37f232SEric Joyner 43158eb6488eSEric Joyner /************************************************************************ 43168eb6488eSEric Joyner * ixgbe_sysctl_wufc - Wake Up Filter Control 43178eb6488eSEric Joyner * 43186f37f232SEric Joyner * Sysctl to enable/disable the types of packets that the 43196f37f232SEric Joyner * adapter will wake up on upon receipt. 43206f37f232SEric Joyner * Flags: 43216f37f232SEric Joyner * 0x1 - Link Status Change 43226f37f232SEric Joyner * 0x2 - Magic Packet 43236f37f232SEric Joyner * 0x4 - Direct Exact 43246f37f232SEric Joyner * 0x8 - Directed Multicast 43256f37f232SEric Joyner * 0x10 - Broadcast 43266f37f232SEric Joyner * 0x20 - ARP/IPv4 Request Packet 43276f37f232SEric Joyner * 0x40 - Direct IPv4 Packet 43286f37f232SEric Joyner * 0x80 - Direct IPv6 Packet 43296f37f232SEric Joyner * 43308eb6488eSEric Joyner * Settings not listed above will cause the sysctl to return an error. 43318eb6488eSEric Joyner ************************************************************************/ 43326f37f232SEric Joyner static int 43336f37f232SEric Joyner ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS) 43346f37f232SEric Joyner { 43356f37f232SEric Joyner struct adapter *adapter = (struct adapter *)arg1; 43366f37f232SEric Joyner int error = 0; 43376f37f232SEric Joyner u32 new_wufc; 43386f37f232SEric Joyner 43396f37f232SEric Joyner new_wufc = adapter->wufc; 43406f37f232SEric Joyner 43416f37f232SEric Joyner error = sysctl_handle_int(oidp, &new_wufc, 0, req); 43426f37f232SEric Joyner if ((error) || (req->newptr == NULL)) 43436f37f232SEric Joyner return (error); 43446f37f232SEric Joyner if (new_wufc == adapter->wufc) 43456f37f232SEric Joyner return (0); 43466f37f232SEric Joyner 43476f37f232SEric Joyner if (new_wufc & 0xffffff00) 43486f37f232SEric Joyner return (EINVAL); 43498eb6488eSEric Joyner 43506f37f232SEric Joyner new_wufc &= 0xff; 43516f37f232SEric Joyner new_wufc |= (0xffffff & adapter->wufc); 43526f37f232SEric Joyner adapter->wufc = new_wufc; 43536f37f232SEric Joyner 43546f37f232SEric Joyner return (0); 43558eb6488eSEric Joyner } /* ixgbe_sysctl_wufc */ 43566f37f232SEric Joyner 4357a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 43588eb6488eSEric Joyner /************************************************************************ 43598eb6488eSEric Joyner * ixgbe_sysctl_print_rss_config 43608eb6488eSEric Joyner ************************************************************************/ 4361a9ca1c79SSean Bruno static int 4362a9ca1c79SSean Bruno ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS) 4363a9ca1c79SSean Bruno { 4364a9ca1c79SSean Bruno struct adapter *adapter = (struct adapter *)arg1; 4365a9ca1c79SSean Bruno struct ixgbe_hw *hw = &adapter->hw; 4366a9ca1c79SSean Bruno device_t dev = adapter->dev; 4367a9ca1c79SSean Bruno struct sbuf *buf; 43688eb6488eSEric Joyner int error = 0, reta_size; 4369a9ca1c79SSean Bruno u32 reg; 4370a9ca1c79SSean Bruno 4371a9ca1c79SSean Bruno buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); 4372a9ca1c79SSean Bruno if (!buf) { 4373a9ca1c79SSean Bruno device_printf(dev, "Could not allocate sbuf for output.\n"); 4374a9ca1c79SSean Bruno return (ENOMEM); 4375a9ca1c79SSean Bruno } 4376a9ca1c79SSean Bruno 4377a9ca1c79SSean Bruno // TODO: use sbufs to make a string to print out 4378a9ca1c79SSean Bruno /* Set multiplier for RETA setup and table size based on MAC */ 4379a9ca1c79SSean Bruno switch (adapter->hw.mac.type) { 4380a9ca1c79SSean Bruno case ixgbe_mac_X550: 4381a9ca1c79SSean Bruno case ixgbe_mac_X550EM_x: 43828eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 4383a9ca1c79SSean Bruno reta_size = 128; 4384a9ca1c79SSean Bruno break; 4385a9ca1c79SSean Bruno default: 4386a9ca1c79SSean Bruno reta_size = 32; 4387a9ca1c79SSean Bruno break; 4388a9ca1c79SSean Bruno } 4389a9ca1c79SSean Bruno 4390a9ca1c79SSean Bruno /* Print out the redirection table */ 4391a9ca1c79SSean Bruno sbuf_cat(buf, "\n"); 4392a9ca1c79SSean Bruno for (int i = 0; i < reta_size; i++) { 4393a9ca1c79SSean Bruno if (i < 32) { 4394a9ca1c79SSean Bruno reg = IXGBE_READ_REG(hw, IXGBE_RETA(i)); 4395a9ca1c79SSean Bruno sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg); 4396a9ca1c79SSean Bruno } else { 4397a9ca1c79SSean Bruno reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32)); 4398a9ca1c79SSean Bruno sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg); 4399a9ca1c79SSean Bruno } 4400a9ca1c79SSean Bruno } 4401a9ca1c79SSean Bruno 4402a9ca1c79SSean Bruno // TODO: print more config 4403a9ca1c79SSean Bruno 4404a9ca1c79SSean Bruno error = sbuf_finish(buf); 4405a9ca1c79SSean Bruno if (error) 4406a9ca1c79SSean Bruno device_printf(dev, "Error finishing sbuf: %d\n", error); 4407a9ca1c79SSean Bruno 4408a9ca1c79SSean Bruno sbuf_delete(buf); 44098eb6488eSEric Joyner 4410a9ca1c79SSean Bruno return (0); 44118eb6488eSEric Joyner } /* ixgbe_sysctl_print_rss_config */ 4412a9ca1c79SSean Bruno #endif /* IXGBE_DEBUG */ 4413a9ca1c79SSean Bruno 44148eb6488eSEric Joyner /************************************************************************ 44158eb6488eSEric Joyner * ixgbe_sysctl_phy_temp - Retrieve temperature of PHY 44168eb6488eSEric Joyner * 44178eb6488eSEric Joyner * For X552/X557-AT devices using an external PHY 44188eb6488eSEric Joyner ************************************************************************/ 44198eb6488eSEric Joyner static int 44208eb6488eSEric Joyner ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS) 44218eb6488eSEric Joyner { 44228eb6488eSEric Joyner struct adapter *adapter = (struct adapter *)arg1; 44238eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 44248eb6488eSEric Joyner u16 reg; 44258eb6488eSEric Joyner 44268eb6488eSEric Joyner if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { 44278eb6488eSEric Joyner device_printf(adapter->dev, 44288eb6488eSEric Joyner "Device has no supported external thermal sensor.\n"); 44298eb6488eSEric Joyner return (ENODEV); 44308eb6488eSEric Joyner } 44318eb6488eSEric Joyner 44328eb6488eSEric Joyner if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP, 44338eb6488eSEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) { 44348eb6488eSEric Joyner device_printf(adapter->dev, 44358eb6488eSEric Joyner "Error reading from PHY's current temperature register\n"); 44368eb6488eSEric Joyner return (EAGAIN); 44378eb6488eSEric Joyner } 44388eb6488eSEric Joyner 44398eb6488eSEric Joyner /* Shift temp for output */ 44408eb6488eSEric Joyner reg = reg >> 8; 44418eb6488eSEric Joyner 44428eb6488eSEric Joyner return (sysctl_handle_int(oidp, NULL, reg, req)); 44438eb6488eSEric Joyner } /* ixgbe_sysctl_phy_temp */ 44448eb6488eSEric Joyner 44458eb6488eSEric Joyner /************************************************************************ 44468eb6488eSEric Joyner * ixgbe_sysctl_phy_overtemp_occurred 44478eb6488eSEric Joyner * 44488eb6488eSEric Joyner * Reports (directly from the PHY) whether the current PHY 44498eb6488eSEric Joyner * temperature is over the overtemp threshold. 44508eb6488eSEric Joyner ************************************************************************/ 44518eb6488eSEric Joyner static int 44528eb6488eSEric Joyner ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS) 44538eb6488eSEric Joyner { 44548eb6488eSEric Joyner struct adapter *adapter = (struct adapter *)arg1; 44558eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 44568eb6488eSEric Joyner u16 reg; 44578eb6488eSEric Joyner 44588eb6488eSEric Joyner if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { 44598eb6488eSEric Joyner device_printf(adapter->dev, 44608eb6488eSEric Joyner "Device has no supported external thermal sensor.\n"); 44618eb6488eSEric Joyner return (ENODEV); 44628eb6488eSEric Joyner } 44638eb6488eSEric Joyner 44648eb6488eSEric Joyner if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS, 44658eb6488eSEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) { 44668eb6488eSEric Joyner device_printf(adapter->dev, 44678eb6488eSEric Joyner "Error reading from PHY's temperature status register\n"); 44688eb6488eSEric Joyner return (EAGAIN); 44698eb6488eSEric Joyner } 44708eb6488eSEric Joyner 44718eb6488eSEric Joyner /* Get occurrence bit */ 44728eb6488eSEric Joyner reg = !!(reg & 0x4000); 44738eb6488eSEric Joyner 44748eb6488eSEric Joyner return (sysctl_handle_int(oidp, 0, reg, req)); 44758eb6488eSEric Joyner } /* ixgbe_sysctl_phy_overtemp_occurred */ 44768eb6488eSEric Joyner 44778eb6488eSEric Joyner /************************************************************************ 44788eb6488eSEric Joyner * ixgbe_sysctl_eee_state 44798eb6488eSEric Joyner * 44808eb6488eSEric Joyner * Sysctl to set EEE power saving feature 44818eb6488eSEric Joyner * Values: 44828eb6488eSEric Joyner * 0 - disable EEE 44838eb6488eSEric Joyner * 1 - enable EEE 44848eb6488eSEric Joyner * (none) - get current device EEE state 44858eb6488eSEric Joyner ************************************************************************/ 44868eb6488eSEric Joyner static int 44878eb6488eSEric Joyner ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS) 44888eb6488eSEric Joyner { 44898eb6488eSEric Joyner struct adapter *adapter = (struct adapter *)arg1; 44908eb6488eSEric Joyner device_t dev = adapter->dev; 44918eb6488eSEric Joyner int curr_eee, new_eee, error = 0; 44928eb6488eSEric Joyner s32 retval; 44938eb6488eSEric Joyner 44948eb6488eSEric Joyner curr_eee = new_eee = !!(adapter->feat_en & IXGBE_FEATURE_EEE); 44958eb6488eSEric Joyner 44968eb6488eSEric Joyner error = sysctl_handle_int(oidp, &new_eee, 0, req); 44978eb6488eSEric Joyner if ((error) || (req->newptr == NULL)) 44988eb6488eSEric Joyner return (error); 44998eb6488eSEric Joyner 45008eb6488eSEric Joyner /* Nothing to do */ 45018eb6488eSEric Joyner if (new_eee == curr_eee) 45028eb6488eSEric Joyner return (0); 45038eb6488eSEric Joyner 45048eb6488eSEric Joyner /* Not supported */ 45058eb6488eSEric Joyner if (!(adapter->feat_cap & IXGBE_FEATURE_EEE)) 45068eb6488eSEric Joyner return (EINVAL); 45078eb6488eSEric Joyner 45088eb6488eSEric Joyner /* Bounds checking */ 45098eb6488eSEric Joyner if ((new_eee < 0) || (new_eee > 1)) 45108eb6488eSEric Joyner return (EINVAL); 45118eb6488eSEric Joyner 45128eb6488eSEric Joyner retval = adapter->hw.mac.ops.setup_eee(&adapter->hw, new_eee); 45138eb6488eSEric Joyner if (retval) { 45148eb6488eSEric Joyner device_printf(dev, "Error in EEE setup: 0x%08X\n", retval); 45158eb6488eSEric Joyner return (EINVAL); 45168eb6488eSEric Joyner } 45178eb6488eSEric Joyner 45188eb6488eSEric Joyner /* Restart auto-neg */ 45198eb6488eSEric Joyner ixgbe_init(adapter); 45208eb6488eSEric Joyner 45218eb6488eSEric Joyner device_printf(dev, "New EEE state: %d\n", new_eee); 45228eb6488eSEric Joyner 45238eb6488eSEric Joyner /* Cache new value */ 45248eb6488eSEric Joyner if (new_eee) 45258eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_EEE; 45268eb6488eSEric Joyner else 45278eb6488eSEric Joyner adapter->feat_en &= ~IXGBE_FEATURE_EEE; 45288eb6488eSEric Joyner 45298eb6488eSEric Joyner return (error); 45308eb6488eSEric Joyner } /* ixgbe_sysctl_eee_state */ 45318eb6488eSEric Joyner 45328eb6488eSEric Joyner /************************************************************************ 45338eb6488eSEric Joyner * ixgbe_init_device_features 45348eb6488eSEric Joyner ************************************************************************/ 45358eb6488eSEric Joyner static void 45368eb6488eSEric Joyner ixgbe_init_device_features(struct adapter *adapter) 45378eb6488eSEric Joyner { 45388eb6488eSEric Joyner adapter->feat_cap = IXGBE_FEATURE_NETMAP 45398eb6488eSEric Joyner | IXGBE_FEATURE_RSS 45408eb6488eSEric Joyner | IXGBE_FEATURE_MSI 45418eb6488eSEric Joyner | IXGBE_FEATURE_MSIX 45428eb6488eSEric Joyner | IXGBE_FEATURE_LEGACY_IRQ 45438eb6488eSEric Joyner | IXGBE_FEATURE_LEGACY_TX; 45448eb6488eSEric Joyner 45458eb6488eSEric Joyner /* Set capabilities first... */ 45468eb6488eSEric Joyner switch (adapter->hw.mac.type) { 45478eb6488eSEric Joyner case ixgbe_mac_82598EB: 45488eb6488eSEric Joyner if (adapter->hw.device_id == IXGBE_DEV_ID_82598AT) 45498eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_FAN_FAIL; 45508eb6488eSEric Joyner break; 45518eb6488eSEric Joyner case ixgbe_mac_X540: 45528eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_SRIOV; 45538eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_FDIR; 45548eb6488eSEric Joyner if ((adapter->hw.device_id == IXGBE_DEV_ID_X540_BYPASS) && 45558eb6488eSEric Joyner (adapter->hw.bus.func == 0)) 45568eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_BYPASS; 45578eb6488eSEric Joyner break; 45588eb6488eSEric Joyner case ixgbe_mac_X550: 45598eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR; 45608eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_SRIOV; 45618eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_FDIR; 45628eb6488eSEric Joyner break; 45638eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 45648eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_SRIOV; 45658eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_FDIR; 45668eb6488eSEric Joyner if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_X_KR) 45678eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_EEE; 45688eb6488eSEric Joyner break; 45698eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 45708eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_SRIOV; 45718eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_FDIR; 45728eb6488eSEric Joyner adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ; 45738eb6488eSEric Joyner if ((adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T) || 45748eb6488eSEric Joyner (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) { 45758eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR; 45768eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_EEE; 45778eb6488eSEric Joyner } 45788eb6488eSEric Joyner break; 45798eb6488eSEric Joyner case ixgbe_mac_82599EB: 45808eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_SRIOV; 45818eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_FDIR; 45828eb6488eSEric Joyner if ((adapter->hw.device_id == IXGBE_DEV_ID_82599_BYPASS) && 45838eb6488eSEric Joyner (adapter->hw.bus.func == 0)) 45848eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_BYPASS; 45858eb6488eSEric Joyner if (adapter->hw.device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) 45868eb6488eSEric Joyner adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ; 45878eb6488eSEric Joyner break; 45888eb6488eSEric Joyner default: 45898eb6488eSEric Joyner break; 45908eb6488eSEric Joyner } 45918eb6488eSEric Joyner 45928eb6488eSEric Joyner /* Enabled by default... */ 45938eb6488eSEric Joyner /* Fan failure detection */ 45948eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_FAN_FAIL) 45958eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_FAN_FAIL; 45968eb6488eSEric Joyner /* Netmap */ 45978eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_NETMAP) 45988eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_NETMAP; 45998eb6488eSEric Joyner /* EEE */ 46008eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_EEE) 46018eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_EEE; 46028eb6488eSEric Joyner /* Thermal Sensor */ 46038eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_TEMP_SENSOR) 46048eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_TEMP_SENSOR; 46058eb6488eSEric Joyner 46068eb6488eSEric Joyner /* Enabled via global sysctl... */ 46078eb6488eSEric Joyner /* Flow Director */ 46088eb6488eSEric Joyner if (ixgbe_enable_fdir) { 46098eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_FDIR) 46108eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_FDIR; 46118eb6488eSEric Joyner else 46128eb6488eSEric Joyner device_printf(adapter->dev, "Device does not support Flow Director. Leaving disabled."); 46138eb6488eSEric Joyner } 46148eb6488eSEric Joyner /* Legacy (single queue) transmit */ 46158eb6488eSEric Joyner if ((adapter->feat_cap & IXGBE_FEATURE_LEGACY_TX) && 46168eb6488eSEric Joyner ixgbe_enable_legacy_tx) 46178eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_LEGACY_TX; 46186f37f232SEric Joyner /* 46198eb6488eSEric Joyner * Message Signal Interrupts - Extended (MSI-X) 46208eb6488eSEric Joyner * Normal MSI is only enabled if MSI-X calls fail. 4621758cc3dcSJack F Vogel */ 46228eb6488eSEric Joyner if (!ixgbe_enable_msix) 46238eb6488eSEric Joyner adapter->feat_cap &= ~IXGBE_FEATURE_MSIX; 46248eb6488eSEric Joyner /* Receive-Side Scaling (RSS) */ 46258eb6488eSEric Joyner if ((adapter->feat_cap & IXGBE_FEATURE_RSS) && ixgbe_enable_rss) 46268eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_RSS; 46278eb6488eSEric Joyner 46288eb6488eSEric Joyner /* Disable features with unmet dependencies... */ 46298eb6488eSEric Joyner /* No MSI-X */ 46308eb6488eSEric Joyner if (!(adapter->feat_cap & IXGBE_FEATURE_MSIX)) { 46318eb6488eSEric Joyner adapter->feat_cap &= ~IXGBE_FEATURE_RSS; 46328eb6488eSEric Joyner adapter->feat_cap &= ~IXGBE_FEATURE_SRIOV; 46338eb6488eSEric Joyner adapter->feat_en &= ~IXGBE_FEATURE_RSS; 46348eb6488eSEric Joyner adapter->feat_en &= ~IXGBE_FEATURE_SRIOV; 46358eb6488eSEric Joyner } 46368eb6488eSEric Joyner } /* ixgbe_init_device_features */ 46378eb6488eSEric Joyner 46388eb6488eSEric Joyner /************************************************************************ 46398eb6488eSEric Joyner * ixgbe_probe - Device identification routine 46408eb6488eSEric Joyner * 46418eb6488eSEric Joyner * Determines if the driver should be loaded on 46428eb6488eSEric Joyner * adapter based on its PCI vendor/device ID. 46438eb6488eSEric Joyner * 46448eb6488eSEric Joyner * return BUS_PROBE_DEFAULT on success, positive on failure 46458eb6488eSEric Joyner ************************************************************************/ 46468eb6488eSEric Joyner static int 46478eb6488eSEric Joyner ixgbe_probe(device_t dev) 46488eb6488eSEric Joyner { 46498eb6488eSEric Joyner ixgbe_vendor_info_t *ent; 46508eb6488eSEric Joyner 46518eb6488eSEric Joyner u16 pci_vendor_id = 0; 46528eb6488eSEric Joyner u16 pci_device_id = 0; 46538eb6488eSEric Joyner u16 pci_subvendor_id = 0; 46548eb6488eSEric Joyner u16 pci_subdevice_id = 0; 46558eb6488eSEric Joyner char adapter_name[256]; 46568eb6488eSEric Joyner 46578eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_probe: begin"); 46588eb6488eSEric Joyner 46598eb6488eSEric Joyner pci_vendor_id = pci_get_vendor(dev); 46608eb6488eSEric Joyner if (pci_vendor_id != IXGBE_INTEL_VENDOR_ID) 46618eb6488eSEric Joyner return (ENXIO); 46628eb6488eSEric Joyner 46638eb6488eSEric Joyner pci_device_id = pci_get_device(dev); 46648eb6488eSEric Joyner pci_subvendor_id = pci_get_subvendor(dev); 46658eb6488eSEric Joyner pci_subdevice_id = pci_get_subdevice(dev); 46668eb6488eSEric Joyner 46678eb6488eSEric Joyner ent = ixgbe_vendor_info_array; 46688eb6488eSEric Joyner while (ent->vendor_id != 0) { 46698eb6488eSEric Joyner if ((pci_vendor_id == ent->vendor_id) && 46708eb6488eSEric Joyner (pci_device_id == ent->device_id) && 46718eb6488eSEric Joyner ((pci_subvendor_id == ent->subvendor_id) || 46728eb6488eSEric Joyner (ent->subvendor_id == 0)) && 46738eb6488eSEric Joyner ((pci_subdevice_id == ent->subdevice_id) || 46748eb6488eSEric Joyner (ent->subdevice_id == 0))) { 46758eb6488eSEric Joyner sprintf(adapter_name, "%s, Version - %s", 46768eb6488eSEric Joyner ixgbe_strings[ent->index], 46778eb6488eSEric Joyner ixgbe_driver_version); 46788eb6488eSEric Joyner device_set_desc_copy(dev, adapter_name); 46798eb6488eSEric Joyner ++ixgbe_total_ports; 46808eb6488eSEric Joyner return (BUS_PROBE_DEFAULT); 46818eb6488eSEric Joyner } 46828eb6488eSEric Joyner ent++; 46838eb6488eSEric Joyner } 46848eb6488eSEric Joyner 46858eb6488eSEric Joyner return (ENXIO); 46868eb6488eSEric Joyner } /* ixgbe_probe */ 46878eb6488eSEric Joyner 46888eb6488eSEric Joyner 46898eb6488eSEric Joyner /************************************************************************ 46908eb6488eSEric Joyner * ixgbe_ioctl - Ioctl entry point 46918eb6488eSEric Joyner * 46928eb6488eSEric Joyner * Called when the user wants to configure the interface. 46938eb6488eSEric Joyner * 46948eb6488eSEric Joyner * return 0 on success, positive on failure 46958eb6488eSEric Joyner ************************************************************************/ 46968eb6488eSEric Joyner static int 46978eb6488eSEric Joyner ixgbe_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 46988eb6488eSEric Joyner { 46998eb6488eSEric Joyner struct adapter *adapter = ifp->if_softc; 47008eb6488eSEric Joyner struct ifreq *ifr = (struct ifreq *) data; 47018eb6488eSEric Joyner #if defined(INET) || defined(INET6) 47028eb6488eSEric Joyner struct ifaddr *ifa = (struct ifaddr *)data; 47038eb6488eSEric Joyner #endif 47048eb6488eSEric Joyner int error = 0; 47058eb6488eSEric Joyner bool avoid_reset = FALSE; 47068eb6488eSEric Joyner 47078eb6488eSEric Joyner switch (command) { 47088eb6488eSEric Joyner case SIOCSIFADDR: 47098eb6488eSEric Joyner #ifdef INET 47108eb6488eSEric Joyner if (ifa->ifa_addr->sa_family == AF_INET) 47118eb6488eSEric Joyner avoid_reset = TRUE; 47128eb6488eSEric Joyner #endif 47138eb6488eSEric Joyner #ifdef INET6 47148eb6488eSEric Joyner if (ifa->ifa_addr->sa_family == AF_INET6) 47158eb6488eSEric Joyner avoid_reset = TRUE; 47168eb6488eSEric Joyner #endif 47178eb6488eSEric Joyner /* 47188eb6488eSEric Joyner * Calling init results in link renegotiation, 47198eb6488eSEric Joyner * so we avoid doing it when possible. 47208eb6488eSEric Joyner */ 47218eb6488eSEric Joyner if (avoid_reset) { 47228eb6488eSEric Joyner ifp->if_flags |= IFF_UP; 47238eb6488eSEric Joyner if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 47248eb6488eSEric Joyner ixgbe_init(adapter); 47258eb6488eSEric Joyner #ifdef INET 47268eb6488eSEric Joyner if (!(ifp->if_flags & IFF_NOARP)) 47278eb6488eSEric Joyner arp_ifinit(ifp, ifa); 47288eb6488eSEric Joyner #endif 47298eb6488eSEric Joyner } else 47308eb6488eSEric Joyner error = ether_ioctl(ifp, command, data); 47318eb6488eSEric Joyner break; 47328eb6488eSEric Joyner case SIOCSIFMTU: 47338eb6488eSEric Joyner IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)"); 47348eb6488eSEric Joyner if (ifr->ifr_mtu > IXGBE_MAX_MTU) { 47358eb6488eSEric Joyner error = EINVAL; 47368eb6488eSEric Joyner } else { 47378eb6488eSEric Joyner IXGBE_CORE_LOCK(adapter); 47388eb6488eSEric Joyner ifp->if_mtu = ifr->ifr_mtu; 47398eb6488eSEric Joyner adapter->max_frame_size = ifp->if_mtu + IXGBE_MTU_HDR; 47408eb6488eSEric Joyner if (ifp->if_drv_flags & IFF_DRV_RUNNING) 47418eb6488eSEric Joyner ixgbe_init_locked(adapter); 47428eb6488eSEric Joyner ixgbe_recalculate_max_frame(adapter); 47438eb6488eSEric Joyner IXGBE_CORE_UNLOCK(adapter); 47448eb6488eSEric Joyner } 47458eb6488eSEric Joyner break; 47468eb6488eSEric Joyner case SIOCSIFFLAGS: 47478eb6488eSEric Joyner IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)"); 47488eb6488eSEric Joyner IXGBE_CORE_LOCK(adapter); 47498eb6488eSEric Joyner if (ifp->if_flags & IFF_UP) { 47508eb6488eSEric Joyner if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) { 47518eb6488eSEric Joyner if ((ifp->if_flags ^ adapter->if_flags) & 47528eb6488eSEric Joyner (IFF_PROMISC | IFF_ALLMULTI)) { 47538eb6488eSEric Joyner ixgbe_set_promisc(adapter); 47548eb6488eSEric Joyner } 47558eb6488eSEric Joyner } else 47568eb6488eSEric Joyner ixgbe_init_locked(adapter); 47578eb6488eSEric Joyner } else 47588eb6488eSEric Joyner if (ifp->if_drv_flags & IFF_DRV_RUNNING) 47598eb6488eSEric Joyner ixgbe_stop(adapter); 47608eb6488eSEric Joyner adapter->if_flags = ifp->if_flags; 47618eb6488eSEric Joyner IXGBE_CORE_UNLOCK(adapter); 47628eb6488eSEric Joyner break; 47638eb6488eSEric Joyner case SIOCADDMULTI: 47648eb6488eSEric Joyner case SIOCDELMULTI: 47658eb6488eSEric Joyner IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI"); 47668eb6488eSEric Joyner if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 47678eb6488eSEric Joyner IXGBE_CORE_LOCK(adapter); 47688eb6488eSEric Joyner ixgbe_disable_intr(adapter); 47698eb6488eSEric Joyner ixgbe_set_multi(adapter); 47708eb6488eSEric Joyner ixgbe_enable_intr(adapter); 47718eb6488eSEric Joyner IXGBE_CORE_UNLOCK(adapter); 47728eb6488eSEric Joyner } 47738eb6488eSEric Joyner break; 47748eb6488eSEric Joyner case SIOCSIFMEDIA: 47758eb6488eSEric Joyner case SIOCGIFMEDIA: 47768eb6488eSEric Joyner IOCTL_DEBUGOUT("ioctl: SIOCxIFMEDIA (Get/Set Interface Media)"); 47778eb6488eSEric Joyner error = ifmedia_ioctl(ifp, ifr, &adapter->media, command); 47788eb6488eSEric Joyner break; 47798eb6488eSEric Joyner case SIOCSIFCAP: 47808eb6488eSEric Joyner { 47818eb6488eSEric Joyner IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)"); 47828eb6488eSEric Joyner 47838eb6488eSEric Joyner int mask = ifr->ifr_reqcap ^ ifp->if_capenable; 47848eb6488eSEric Joyner 47858eb6488eSEric Joyner if (!mask) 47868eb6488eSEric Joyner break; 47878eb6488eSEric Joyner 47888eb6488eSEric Joyner /* HW cannot turn these on/off separately */ 47898eb6488eSEric Joyner if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) { 47908eb6488eSEric Joyner ifp->if_capenable ^= IFCAP_RXCSUM; 47918eb6488eSEric Joyner ifp->if_capenable ^= IFCAP_RXCSUM_IPV6; 47928eb6488eSEric Joyner } 47938eb6488eSEric Joyner if (mask & IFCAP_TXCSUM) 47948eb6488eSEric Joyner ifp->if_capenable ^= IFCAP_TXCSUM; 47958eb6488eSEric Joyner if (mask & IFCAP_TXCSUM_IPV6) 47968eb6488eSEric Joyner ifp->if_capenable ^= IFCAP_TXCSUM_IPV6; 47978eb6488eSEric Joyner if (mask & IFCAP_TSO4) 47988eb6488eSEric Joyner ifp->if_capenable ^= IFCAP_TSO4; 47998eb6488eSEric Joyner if (mask & IFCAP_TSO6) 48008eb6488eSEric Joyner ifp->if_capenable ^= IFCAP_TSO6; 48018eb6488eSEric Joyner if (mask & IFCAP_LRO) 48028eb6488eSEric Joyner ifp->if_capenable ^= IFCAP_LRO; 48038eb6488eSEric Joyner if (mask & IFCAP_VLAN_HWTAGGING) 48048eb6488eSEric Joyner ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 48058eb6488eSEric Joyner if (mask & IFCAP_VLAN_HWFILTER) 48068eb6488eSEric Joyner ifp->if_capenable ^= IFCAP_VLAN_HWFILTER; 48078eb6488eSEric Joyner if (mask & IFCAP_VLAN_HWTSO) 48088eb6488eSEric Joyner ifp->if_capenable ^= IFCAP_VLAN_HWTSO; 48098eb6488eSEric Joyner 48108eb6488eSEric Joyner if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 48118eb6488eSEric Joyner IXGBE_CORE_LOCK(adapter); 48128eb6488eSEric Joyner ixgbe_init_locked(adapter); 48138eb6488eSEric Joyner IXGBE_CORE_UNLOCK(adapter); 48148eb6488eSEric Joyner } 48158eb6488eSEric Joyner VLAN_CAPABILITIES(ifp); 48168eb6488eSEric Joyner break; 48178eb6488eSEric Joyner } 48188eb6488eSEric Joyner #if __FreeBSD_version >= 1100036 48198eb6488eSEric Joyner case SIOCGI2C: 4820758cc3dcSJack F Vogel { 4821758cc3dcSJack F Vogel struct ixgbe_hw *hw = &adapter->hw; 48228eb6488eSEric Joyner struct ifi2creq i2c; 48238eb6488eSEric Joyner int i; 4824758cc3dcSJack F Vogel 48258eb6488eSEric Joyner IOCTL_DEBUGOUT("ioctl: SIOCGI2C (Get I2C Data)"); 48268eb6488eSEric Joyner error = copyin(ifr->ifr_data, &i2c, sizeof(i2c)); 48278eb6488eSEric Joyner if (error != 0) 48288eb6488eSEric Joyner break; 48298eb6488eSEric Joyner if (i2c.dev_addr != 0xA0 && i2c.dev_addr != 0xA2) { 48308eb6488eSEric Joyner error = EINVAL; 48318eb6488eSEric Joyner break; 4832758cc3dcSJack F Vogel } 48338eb6488eSEric Joyner if (i2c.len > sizeof(i2c.data)) { 48348eb6488eSEric Joyner error = EINVAL; 48358eb6488eSEric Joyner break; 483648056c88SJack F Vogel } 48378eb6488eSEric Joyner 48388eb6488eSEric Joyner for (i = 0; i < i2c.len; i++) 48398eb6488eSEric Joyner hw->phy.ops.read_i2c_byte(hw, i2c.offset + i, 48408eb6488eSEric Joyner i2c.dev_addr, &i2c.data[i]); 48418eb6488eSEric Joyner error = copyout(&i2c, ifr->ifr_data, sizeof(i2c)); 48428eb6488eSEric Joyner break; 48438eb6488eSEric Joyner } 48448eb6488eSEric Joyner #endif 48458eb6488eSEric Joyner default: 48468eb6488eSEric Joyner IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command); 48478eb6488eSEric Joyner error = ether_ioctl(ifp, command, data); 48488eb6488eSEric Joyner break; 48498eb6488eSEric Joyner } 48508eb6488eSEric Joyner 48518eb6488eSEric Joyner return (error); 48528eb6488eSEric Joyner } /* ixgbe_ioctl */ 48538eb6488eSEric Joyner 48548eb6488eSEric Joyner /************************************************************************ 48558eb6488eSEric Joyner * ixgbe_check_fan_failure 48568eb6488eSEric Joyner ************************************************************************/ 48578eb6488eSEric Joyner static void 48588eb6488eSEric Joyner ixgbe_check_fan_failure(struct adapter *adapter, u32 reg, bool in_interrupt) 48598eb6488eSEric Joyner { 48608eb6488eSEric Joyner u32 mask; 48618eb6488eSEric Joyner 48628eb6488eSEric Joyner mask = (in_interrupt) ? IXGBE_EICR_GPI_SDP1_BY_MAC(&adapter->hw) : 48638eb6488eSEric Joyner IXGBE_ESDP_SDP1; 48648eb6488eSEric Joyner 48658eb6488eSEric Joyner if (reg & mask) 48668eb6488eSEric Joyner device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n"); 48678eb6488eSEric Joyner } /* ixgbe_check_fan_failure */ 48688eb6488eSEric Joyner 48698eb6488eSEric Joyner /************************************************************************ 48708eb6488eSEric Joyner * ixgbe_handle_que 48718eb6488eSEric Joyner ************************************************************************/ 48728eb6488eSEric Joyner static void 48738eb6488eSEric Joyner ixgbe_handle_que(void *context, int pending) 48748eb6488eSEric Joyner { 48758eb6488eSEric Joyner struct ix_queue *que = context; 48768eb6488eSEric Joyner struct adapter *adapter = que->adapter; 48778eb6488eSEric Joyner struct tx_ring *txr = que->txr; 48788eb6488eSEric Joyner struct ifnet *ifp = adapter->ifp; 48798eb6488eSEric Joyner 48808eb6488eSEric Joyner if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 48818eb6488eSEric Joyner ixgbe_rxeof(que); 48828eb6488eSEric Joyner IXGBE_TX_LOCK(txr); 48838eb6488eSEric Joyner ixgbe_txeof(txr); 48848eb6488eSEric Joyner if (!ixgbe_ring_empty(ifp, txr->br)) 48858eb6488eSEric Joyner ixgbe_start_locked(ifp, txr); 48868eb6488eSEric Joyner IXGBE_TX_UNLOCK(txr); 48878eb6488eSEric Joyner } 48888eb6488eSEric Joyner 48898eb6488eSEric Joyner /* Re-enable this interrupt */ 48908eb6488eSEric Joyner if (que->res != NULL) 48918eb6488eSEric Joyner ixgbe_enable_queue(adapter, que->msix); 48928eb6488eSEric Joyner else 48938eb6488eSEric Joyner ixgbe_enable_intr(adapter); 48948eb6488eSEric Joyner 48958eb6488eSEric Joyner return; 48968eb6488eSEric Joyner } /* ixgbe_handle_que */ 48978eb6488eSEric Joyner 48988eb6488eSEric Joyner 48998eb6488eSEric Joyner 49008eb6488eSEric Joyner /************************************************************************ 49018eb6488eSEric Joyner * ixgbe_allocate_legacy - Setup the Legacy or MSI Interrupt handler 49028eb6488eSEric Joyner ************************************************************************/ 49038eb6488eSEric Joyner static int 49048eb6488eSEric Joyner ixgbe_allocate_legacy(struct adapter *adapter) 49058eb6488eSEric Joyner { 49068eb6488eSEric Joyner device_t dev = adapter->dev; 49078eb6488eSEric Joyner struct ix_queue *que = adapter->queues; 49088eb6488eSEric Joyner struct tx_ring *txr = adapter->tx_rings; 49098eb6488eSEric Joyner int error; 49108eb6488eSEric Joyner 49118eb6488eSEric Joyner /* We allocate a single interrupt resource */ 49128eb6488eSEric Joyner adapter->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 49138eb6488eSEric Joyner &adapter->link_rid, RF_SHAREABLE | RF_ACTIVE); 49148eb6488eSEric Joyner if (adapter->res == NULL) { 49158eb6488eSEric Joyner device_printf(dev, 49168eb6488eSEric Joyner "Unable to allocate bus resource: interrupt\n"); 49178eb6488eSEric Joyner return (ENXIO); 49188eb6488eSEric Joyner } 49198eb6488eSEric Joyner 49208eb6488eSEric Joyner /* 49218eb6488eSEric Joyner * Try allocating a fast interrupt and the associated deferred 49228eb6488eSEric Joyner * processing contexts. 49238eb6488eSEric Joyner */ 49248eb6488eSEric Joyner if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX)) 49258eb6488eSEric Joyner TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr); 49268eb6488eSEric Joyner TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que); 49278eb6488eSEric Joyner que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT, 49288eb6488eSEric Joyner taskqueue_thread_enqueue, &que->tq); 49298eb6488eSEric Joyner taskqueue_start_threads(&que->tq, 1, PI_NET, "%s ixq", 49308eb6488eSEric Joyner device_get_nameunit(adapter->dev)); 49318eb6488eSEric Joyner 49328eb6488eSEric Joyner /* Tasklets for Link, SFP and Multispeed Fiber */ 49338eb6488eSEric Joyner TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter); 49348eb6488eSEric Joyner TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter); 49358eb6488eSEric Joyner TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter); 49368eb6488eSEric Joyner TASK_INIT(&adapter->phy_task, 0, ixgbe_handle_phy, adapter); 49378eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FDIR) 49388eb6488eSEric Joyner TASK_INIT(&adapter->fdir_task, 0, ixgbe_reinit_fdir, adapter); 49398eb6488eSEric Joyner adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT, 49408eb6488eSEric Joyner taskqueue_thread_enqueue, &adapter->tq); 49418eb6488eSEric Joyner taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq", 49428eb6488eSEric Joyner device_get_nameunit(adapter->dev)); 49438eb6488eSEric Joyner 49448eb6488eSEric Joyner if ((error = bus_setup_intr(dev, adapter->res, 49458eb6488eSEric Joyner INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_legacy_irq, que, 49468eb6488eSEric Joyner &adapter->tag)) != 0) { 49478eb6488eSEric Joyner device_printf(dev, 49488eb6488eSEric Joyner "Failed to register fast interrupt handler: %d\n", error); 49498eb6488eSEric Joyner taskqueue_free(que->tq); 49508eb6488eSEric Joyner taskqueue_free(adapter->tq); 49518eb6488eSEric Joyner que->tq = NULL; 49528eb6488eSEric Joyner adapter->tq = NULL; 49538eb6488eSEric Joyner 49548eb6488eSEric Joyner return (error); 49558eb6488eSEric Joyner } 49568eb6488eSEric Joyner /* For simplicity in the handlers */ 49578eb6488eSEric Joyner adapter->active_queues = IXGBE_EIMS_ENABLE_MASK; 49588eb6488eSEric Joyner 49598eb6488eSEric Joyner return (0); 49608eb6488eSEric Joyner } /* ixgbe_allocate_legacy */ 49618eb6488eSEric Joyner 49628eb6488eSEric Joyner 49638eb6488eSEric Joyner /************************************************************************ 49648eb6488eSEric Joyner * ixgbe_allocate_msix - Setup MSI-X Interrupt resources and handlers 49658eb6488eSEric Joyner ************************************************************************/ 49668eb6488eSEric Joyner static int 49678eb6488eSEric Joyner ixgbe_allocate_msix(struct adapter *adapter) 49688eb6488eSEric Joyner { 49698eb6488eSEric Joyner device_t dev = adapter->dev; 49708eb6488eSEric Joyner struct ix_queue *que = adapter->queues; 49718eb6488eSEric Joyner struct tx_ring *txr = adapter->tx_rings; 49728eb6488eSEric Joyner int error, rid, vector = 0; 49738eb6488eSEric Joyner int cpu_id = 0; 49748eb6488eSEric Joyner unsigned int rss_buckets = 0; 49758eb6488eSEric Joyner cpuset_t cpu_mask; 49768eb6488eSEric Joyner 49778eb6488eSEric Joyner /* 49788eb6488eSEric Joyner * If we're doing RSS, the number of queues needs to 49798eb6488eSEric Joyner * match the number of RSS buckets that are configured. 49808eb6488eSEric Joyner * 49818eb6488eSEric Joyner * + If there's more queues than RSS buckets, we'll end 49828eb6488eSEric Joyner * up with queues that get no traffic. 49838eb6488eSEric Joyner * 49848eb6488eSEric Joyner * + If there's more RSS buckets than queues, we'll end 49858eb6488eSEric Joyner * up having multiple RSS buckets map to the same queue, 49868eb6488eSEric Joyner * so there'll be some contention. 49878eb6488eSEric Joyner */ 49888eb6488eSEric Joyner rss_buckets = rss_getnumbuckets(); 49898eb6488eSEric Joyner if ((adapter->feat_en & IXGBE_FEATURE_RSS) && 49908eb6488eSEric Joyner (adapter->num_queues != rss_buckets)) { 49918eb6488eSEric Joyner device_printf(dev, "%s: number of queues (%d) != number of RSS buckets (%d); performance will be impacted.\n", 49928eb6488eSEric Joyner __func__, adapter->num_queues, rss_buckets); 49938eb6488eSEric Joyner } 49948eb6488eSEric Joyner 49958eb6488eSEric Joyner for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) { 49968eb6488eSEric Joyner rid = vector + 1; 49978eb6488eSEric Joyner que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 49988eb6488eSEric Joyner RF_SHAREABLE | RF_ACTIVE); 49998eb6488eSEric Joyner if (que->res == NULL) { 50008eb6488eSEric Joyner device_printf(dev, "Unable to allocate bus resource: que interrupt [%d]\n", 50018eb6488eSEric Joyner vector); 50028eb6488eSEric Joyner return (ENXIO); 50038eb6488eSEric Joyner } 50048eb6488eSEric Joyner /* Set the handler function */ 50058eb6488eSEric Joyner error = bus_setup_intr(dev, que->res, 50068eb6488eSEric Joyner INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_msix_que, que, 50078eb6488eSEric Joyner &que->tag); 50088eb6488eSEric Joyner if (error) { 50098eb6488eSEric Joyner que->res = NULL; 50108eb6488eSEric Joyner device_printf(dev, "Failed to register QUE handler"); 50118eb6488eSEric Joyner return (error); 50128eb6488eSEric Joyner } 50138eb6488eSEric Joyner #if __FreeBSD_version >= 800504 50148eb6488eSEric Joyner bus_describe_intr(dev, que->res, que->tag, "q%d", i); 50158eb6488eSEric Joyner #endif 50168eb6488eSEric Joyner que->msix = vector; 50178eb6488eSEric Joyner adapter->active_queues |= (u64)(1 << que->msix); 50188eb6488eSEric Joyner 50198eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_RSS) { 50208eb6488eSEric Joyner /* 50218eb6488eSEric Joyner * The queue ID is used as the RSS layer bucket ID. 50228eb6488eSEric Joyner * We look up the queue ID -> RSS CPU ID and select 50238eb6488eSEric Joyner * that. 50248eb6488eSEric Joyner */ 50258eb6488eSEric Joyner cpu_id = rss_getcpu(i % rss_buckets); 50268eb6488eSEric Joyner CPU_SETOF(cpu_id, &cpu_mask); 50278eb6488eSEric Joyner } else { 50288eb6488eSEric Joyner /* 50298eb6488eSEric Joyner * Bind the MSI-X vector, and thus the 50308eb6488eSEric Joyner * rings to the corresponding CPU. 50318eb6488eSEric Joyner * 50328eb6488eSEric Joyner * This just happens to match the default RSS 50338eb6488eSEric Joyner * round-robin bucket -> queue -> CPU allocation. 50348eb6488eSEric Joyner */ 50358eb6488eSEric Joyner if (adapter->num_queues > 1) 50368eb6488eSEric Joyner cpu_id = i; 50378eb6488eSEric Joyner } 50388eb6488eSEric Joyner if (adapter->num_queues > 1) 50398eb6488eSEric Joyner bus_bind_intr(dev, que->res, cpu_id); 50408eb6488eSEric Joyner #ifdef IXGBE_DEBUG 50418eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_RSS) 50428eb6488eSEric Joyner device_printf(dev, "Bound RSS bucket %d to CPU %d\n", i, 50438eb6488eSEric Joyner cpu_id); 50448eb6488eSEric Joyner else 50458eb6488eSEric Joyner device_printf(dev, "Bound queue %d to cpu %d\n", i, 50468eb6488eSEric Joyner cpu_id); 50478eb6488eSEric Joyner #endif /* IXGBE_DEBUG */ 50488eb6488eSEric Joyner 50498eb6488eSEric Joyner 50508eb6488eSEric Joyner if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX)) 50518eb6488eSEric Joyner TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, 50528eb6488eSEric Joyner txr); 50538eb6488eSEric Joyner TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que); 50548eb6488eSEric Joyner que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT, 50558eb6488eSEric Joyner taskqueue_thread_enqueue, &que->tq); 50568eb6488eSEric Joyner #if __FreeBSD_version < 1100000 50578eb6488eSEric Joyner taskqueue_start_threads(&que->tq, 1, PI_NET, "%s:q%d", 50588eb6488eSEric Joyner device_get_nameunit(adapter->dev), i); 50598eb6488eSEric Joyner #else 50608eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_RSS) 50618eb6488eSEric Joyner taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET, 50628eb6488eSEric Joyner &cpu_mask, "%s (bucket %d)", 50638eb6488eSEric Joyner device_get_nameunit(adapter->dev), cpu_id); 50648eb6488eSEric Joyner else 50658eb6488eSEric Joyner taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET, 50668eb6488eSEric Joyner NULL, "%s:q%d", device_get_nameunit(adapter->dev), 50678eb6488eSEric Joyner i); 506848056c88SJack F Vogel #endif 5069758cc3dcSJack F Vogel } 5070758cc3dcSJack F Vogel 50718eb6488eSEric Joyner /* and Link */ 50728eb6488eSEric Joyner adapter->link_rid = vector + 1; 50738eb6488eSEric Joyner adapter->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 50748eb6488eSEric Joyner &adapter->link_rid, RF_SHAREABLE | RF_ACTIVE); 50758eb6488eSEric Joyner if (!adapter->res) { 50768eb6488eSEric Joyner device_printf(dev, 50778eb6488eSEric Joyner "Unable to allocate bus resource: Link interrupt [%d]\n", 50788eb6488eSEric Joyner adapter->link_rid); 50798eb6488eSEric Joyner return (ENXIO); 50808eb6488eSEric Joyner } 50818eb6488eSEric Joyner /* Set the link handler function */ 50828eb6488eSEric Joyner error = bus_setup_intr(dev, adapter->res, INTR_TYPE_NET | INTR_MPSAFE, 50838eb6488eSEric Joyner NULL, ixgbe_msix_link, adapter, &adapter->tag); 50848eb6488eSEric Joyner if (error) { 50858eb6488eSEric Joyner adapter->res = NULL; 50868eb6488eSEric Joyner device_printf(dev, "Failed to register LINK handler"); 50878eb6488eSEric Joyner return (error); 50888eb6488eSEric Joyner } 50898eb6488eSEric Joyner #if __FreeBSD_version >= 800504 50908eb6488eSEric Joyner bus_describe_intr(dev, adapter->res, adapter->tag, "link"); 50918eb6488eSEric Joyner #endif 50928eb6488eSEric Joyner adapter->vector = vector; 50938eb6488eSEric Joyner /* Tasklets for Link, SFP and Multispeed Fiber */ 50948eb6488eSEric Joyner TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter); 50958eb6488eSEric Joyner TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter); 50968eb6488eSEric Joyner TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter); 50978eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_SRIOV) 50988eb6488eSEric Joyner TASK_INIT(&adapter->mbx_task, 0, ixgbe_handle_mbx, adapter); 50998eb6488eSEric Joyner TASK_INIT(&adapter->phy_task, 0, ixgbe_handle_phy, adapter); 51008eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FDIR) 51018eb6488eSEric Joyner TASK_INIT(&adapter->fdir_task, 0, ixgbe_reinit_fdir, adapter); 51028eb6488eSEric Joyner adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT, 51038eb6488eSEric Joyner taskqueue_thread_enqueue, &adapter->tq); 51048eb6488eSEric Joyner taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq", 51058eb6488eSEric Joyner device_get_nameunit(adapter->dev)); 51068eb6488eSEric Joyner 51078eb6488eSEric Joyner return (0); 51088eb6488eSEric Joyner } /* ixgbe_allocate_msix */ 51098eb6488eSEric Joyner 51108eb6488eSEric Joyner /************************************************************************ 51118eb6488eSEric Joyner * ixgbe_configure_interrupts 51128eb6488eSEric Joyner * 51138eb6488eSEric Joyner * Setup MSI-X, MSI, or legacy interrupts (in that order). 51148eb6488eSEric Joyner * This will also depend on user settings. 51158eb6488eSEric Joyner ************************************************************************/ 51168eb6488eSEric Joyner static int 51178eb6488eSEric Joyner ixgbe_configure_interrupts(struct adapter *adapter) 5118758cc3dcSJack F Vogel { 51198eb6488eSEric Joyner device_t dev = adapter->dev; 51208eb6488eSEric Joyner int rid, want, queues, msgs; 51218eb6488eSEric Joyner 51228eb6488eSEric Joyner /* Default to 1 queue if MSI-X setup fails */ 51238eb6488eSEric Joyner adapter->num_queues = 1; 51248eb6488eSEric Joyner 51258eb6488eSEric Joyner /* Override by tuneable */ 51268eb6488eSEric Joyner if (!(adapter->feat_cap & IXGBE_FEATURE_MSIX)) 51278eb6488eSEric Joyner goto msi; 51288eb6488eSEric Joyner 51298eb6488eSEric Joyner /* First try MSI-X */ 51308eb6488eSEric Joyner msgs = pci_msix_count(dev); 51318eb6488eSEric Joyner if (msgs == 0) 51328eb6488eSEric Joyner goto msi; 51338eb6488eSEric Joyner rid = PCIR_BAR(MSIX_82598_BAR); 51348eb6488eSEric Joyner adapter->msix_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 51358eb6488eSEric Joyner RF_ACTIVE); 51368eb6488eSEric Joyner if (adapter->msix_mem == NULL) { 51378eb6488eSEric Joyner rid += 4; /* 82599 maps in higher BAR */ 51388eb6488eSEric Joyner adapter->msix_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 51398eb6488eSEric Joyner &rid, RF_ACTIVE); 51408eb6488eSEric Joyner } 51418eb6488eSEric Joyner if (adapter->msix_mem == NULL) { 51428eb6488eSEric Joyner /* May not be enabled */ 51438eb6488eSEric Joyner device_printf(adapter->dev, "Unable to map MSI-X table.\n"); 51448eb6488eSEric Joyner goto msi; 51458eb6488eSEric Joyner } 51468eb6488eSEric Joyner 51478eb6488eSEric Joyner /* Figure out a reasonable auto config value */ 51488eb6488eSEric Joyner queues = min(mp_ncpus, msgs - 1); 51498eb6488eSEric Joyner /* If we're doing RSS, clamp at the number of RSS buckets */ 51508eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_RSS) 51518eb6488eSEric Joyner queues = min(queues, rss_getnumbuckets()); 51528eb6488eSEric Joyner if (ixgbe_num_queues > queues) { 51538eb6488eSEric Joyner device_printf(adapter->dev, "ixgbe_num_queues (%d) is too large, using reduced amount (%d).\n", ixgbe_num_queues, queues); 51548eb6488eSEric Joyner ixgbe_num_queues = queues; 51558eb6488eSEric Joyner } 51568eb6488eSEric Joyner 51578eb6488eSEric Joyner if (ixgbe_num_queues != 0) 51588eb6488eSEric Joyner queues = ixgbe_num_queues; 51598eb6488eSEric Joyner /* Set max queues to 8 when autoconfiguring */ 51608eb6488eSEric Joyner else 51618eb6488eSEric Joyner queues = min(queues, 8); 51628eb6488eSEric Joyner 51638eb6488eSEric Joyner /* reflect correct sysctl value */ 51648eb6488eSEric Joyner ixgbe_num_queues = queues; 51658eb6488eSEric Joyner 51668eb6488eSEric Joyner /* 51678eb6488eSEric Joyner * Want one vector (RX/TX pair) per queue 51688eb6488eSEric Joyner * plus an additional for Link. 51698eb6488eSEric Joyner */ 51708eb6488eSEric Joyner want = queues + 1; 51718eb6488eSEric Joyner if (msgs >= want) 51728eb6488eSEric Joyner msgs = want; 51738eb6488eSEric Joyner else { 51748eb6488eSEric Joyner device_printf(adapter->dev, "MSI-X Configuration Problem, %d vectors but %d queues wanted!\n", 51758eb6488eSEric Joyner msgs, want); 51768eb6488eSEric Joyner goto msi; 51778eb6488eSEric Joyner } 51788eb6488eSEric Joyner if ((pci_alloc_msix(dev, &msgs) == 0) && (msgs == want)) { 51798eb6488eSEric Joyner device_printf(adapter->dev, 51808eb6488eSEric Joyner "Using MSI-X interrupts with %d vectors\n", msgs); 51818eb6488eSEric Joyner adapter->num_queues = queues; 51828eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_MSIX; 51838eb6488eSEric Joyner return (0); 51848eb6488eSEric Joyner } 51858eb6488eSEric Joyner /* 51868eb6488eSEric Joyner * MSI-X allocation failed or provided us with 51878eb6488eSEric Joyner * less vectors than needed. Free MSI-X resources 51888eb6488eSEric Joyner * and we'll try enabling MSI. 51898eb6488eSEric Joyner */ 51908eb6488eSEric Joyner pci_release_msi(dev); 51918eb6488eSEric Joyner 51928eb6488eSEric Joyner msi: 51938eb6488eSEric Joyner /* Without MSI-X, some features are no longer supported */ 51948eb6488eSEric Joyner adapter->feat_cap &= ~IXGBE_FEATURE_RSS; 51958eb6488eSEric Joyner adapter->feat_en &= ~IXGBE_FEATURE_RSS; 51968eb6488eSEric Joyner adapter->feat_cap &= ~IXGBE_FEATURE_SRIOV; 51978eb6488eSEric Joyner adapter->feat_en &= ~IXGBE_FEATURE_SRIOV; 51988eb6488eSEric Joyner 51998eb6488eSEric Joyner if (adapter->msix_mem != NULL) { 52008eb6488eSEric Joyner bus_release_resource(dev, SYS_RES_MEMORY, rid, 52018eb6488eSEric Joyner adapter->msix_mem); 52028eb6488eSEric Joyner adapter->msix_mem = NULL; 52038eb6488eSEric Joyner } 52048eb6488eSEric Joyner msgs = 1; 52058eb6488eSEric Joyner if (pci_alloc_msi(dev, &msgs) == 0) { 52068eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_MSI; 52078eb6488eSEric Joyner adapter->link_rid = 1; 52088eb6488eSEric Joyner device_printf(adapter->dev, "Using an MSI interrupt\n"); 52098eb6488eSEric Joyner return (0); 52108eb6488eSEric Joyner } 52118eb6488eSEric Joyner 52128eb6488eSEric Joyner if (!(adapter->feat_cap & IXGBE_FEATURE_LEGACY_IRQ)) { 52138eb6488eSEric Joyner device_printf(adapter->dev, 52148eb6488eSEric Joyner "Device does not support legacy interrupts.\n"); 52158eb6488eSEric Joyner return 1; 52168eb6488eSEric Joyner } 52178eb6488eSEric Joyner 52188eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_LEGACY_IRQ; 52198eb6488eSEric Joyner adapter->link_rid = 0; 52208eb6488eSEric Joyner device_printf(adapter->dev, "Using a Legacy interrupt\n"); 52218eb6488eSEric Joyner 52228eb6488eSEric Joyner return (0); 52238eb6488eSEric Joyner } /* ixgbe_configure_interrupts */ 52248eb6488eSEric Joyner 52258eb6488eSEric Joyner 52268eb6488eSEric Joyner /************************************************************************ 52278eb6488eSEric Joyner * ixgbe_handle_link - Tasklet for MSI-X Link interrupts 52288eb6488eSEric Joyner * 52298eb6488eSEric Joyner * Done outside of interrupt context since the driver might sleep 52308eb6488eSEric Joyner ************************************************************************/ 52318eb6488eSEric Joyner static void 52328eb6488eSEric Joyner ixgbe_handle_link(void *context, int pending) 52338eb6488eSEric Joyner { 52348eb6488eSEric Joyner struct adapter *adapter = context; 5235758cc3dcSJack F Vogel struct ixgbe_hw *hw = &adapter->hw; 5236758cc3dcSJack F Vogel 52378eb6488eSEric Joyner ixgbe_check_link(hw, &adapter->link_speed, &adapter->link_up, 0); 52388eb6488eSEric Joyner ixgbe_update_link_status(adapter); 5239758cc3dcSJack F Vogel 52408eb6488eSEric Joyner /* Re-enable link interrupts */ 52418eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_LSC); 52428eb6488eSEric Joyner } /* ixgbe_handle_link */ 52438eb6488eSEric Joyner 52448eb6488eSEric Joyner /************************************************************************ 52458eb6488eSEric Joyner * ixgbe_rearm_queues 52468eb6488eSEric Joyner ************************************************************************/ 5247758cc3dcSJack F Vogel static void 5248758cc3dcSJack F Vogel ixgbe_rearm_queues(struct adapter *adapter, u64 queues) 5249758cc3dcSJack F Vogel { 5250758cc3dcSJack F Vogel u32 mask; 5251758cc3dcSJack F Vogel 5252758cc3dcSJack F Vogel switch (adapter->hw.mac.type) { 5253758cc3dcSJack F Vogel case ixgbe_mac_82598EB: 5254758cc3dcSJack F Vogel mask = (IXGBE_EIMS_RTX_QUEUE & queues); 5255758cc3dcSJack F Vogel IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask); 5256758cc3dcSJack F Vogel break; 5257758cc3dcSJack F Vogel case ixgbe_mac_82599EB: 5258758cc3dcSJack F Vogel case ixgbe_mac_X540: 5259758cc3dcSJack F Vogel case ixgbe_mac_X550: 52606f37f232SEric Joyner case ixgbe_mac_X550EM_x: 52618eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 5262758cc3dcSJack F Vogel mask = (queues & 0xFFFFFFFF); 5263758cc3dcSJack F Vogel IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask); 5264758cc3dcSJack F Vogel mask = (queues >> 32); 5265758cc3dcSJack F Vogel IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), mask); 5266758cc3dcSJack F Vogel break; 5267758cc3dcSJack F Vogel default: 5268758cc3dcSJack F Vogel break; 5269758cc3dcSJack F Vogel } 52708eb6488eSEric Joyner } /* ixgbe_rearm_queues */ 5271758cc3dcSJack F Vogel 5272