1*c58d34ddSKevin Bowling /***************************************************************************** 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 32*c58d34ddSKevin Bowling *****************************************************************************/ 33758cc3dcSJack F Vogel 34758cc3dcSJack F Vogel #include "opt_inet.h" 35758cc3dcSJack F Vogel #include "opt_inet6.h" 36758cc3dcSJack F Vogel #include "opt_rss.h" 37758cc3dcSJack F Vogel 38758cc3dcSJack F Vogel #include "ixgbe.h" 39c19c7afeSEric Joyner #include "ixgbe_sriov.h" 40c19c7afeSEric Joyner #include "ifdi_if.h" 41c19c7afeSEric Joyner 42c19c7afeSEric Joyner #include <net/netmap.h> 43c19c7afeSEric Joyner #include <dev/netmap/netmap_kern.h> 44758cc3dcSJack F Vogel 458eb6488eSEric Joyner /************************************************************************ 46758cc3dcSJack F Vogel * Driver version 478eb6488eSEric Joyner ************************************************************************/ 4851e23514SMarius Strobl static const char ixgbe_driver_version[] = "4.0.1-k"; 49a9ca1c79SSean Bruno 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 ************************************************************************/ 5951e23514SMarius Strobl static const pci_vendor_info_t ixgbe_vendor_info_array[] = 60758cc3dcSJack F Vogel { 61*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, 62*c58d34ddSKevin Bowling "Intel(R) 82598EB AF (Dual Fiber)"), 63*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 64*c58d34ddSKevin Bowling "Intel(R) 82598EB AF (Fiber)"), 65*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, 66*c58d34ddSKevin Bowling "Intel(R) 82598EB AT (CX4)"), 67*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 68*c58d34ddSKevin Bowling "Intel(R) 82598EB AT"), 69*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, 70*c58d34ddSKevin Bowling "Intel(R) 82598EB AT2"), 71fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, "Intel(R) 82598"), 72*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, 73*c58d34ddSKevin Bowling "Intel(R) 82598EB AF DA (Dual Fiber)"), 74*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, 75*c58d34ddSKevin Bowling "Intel(R) 82598EB AT (Dual CX4)"), 76*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, 77*c58d34ddSKevin Bowling "Intel(R) 82598EB AF (Dual Fiber LR)"), 78*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, 79*c58d34ddSKevin Bowling "Intel(R) 82598EB AF (Dual Fiber SR)"), 80*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, 81*c58d34ddSKevin Bowling "Intel(R) 82598EB LOM"), 82*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, 83*c58d34ddSKevin Bowling "Intel(R) X520 82599 (KX4)"), 84*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, 85*c58d34ddSKevin Bowling "Intel(R) X520 82599 (KX4 Mezzanine)"), 86*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 87*c58d34ddSKevin Bowling "Intel(R) X520 82599ES (SFI/SFP+)"), 88*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, 89*c58d34ddSKevin Bowling "Intel(R) X520 82599 (XAUI/BX4)"), 90*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 91*c58d34ddSKevin Bowling "Intel(R) X520 82599 (Dual CX4)"), 92*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 93*c58d34ddSKevin Bowling "Intel(R) X520-T 82599 LOM"), 94*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_LS, 95*c58d34ddSKevin Bowling "Intel(R) X520 82599 LS"), 96*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 97*c58d34ddSKevin Bowling "Intel(R) X520 82599 (Combined Backplane)"), 98*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, 99*c58d34ddSKevin Bowling "Intel(R) X520 82599 (Backplane w/FCoE)"), 100*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF2, 101*c58d34ddSKevin Bowling "Intel(R) X520 82599 (Dual SFP+)"), 102*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, 103*c58d34ddSKevin Bowling "Intel(R) X520 82599 (Dual SFP+ w/FCoE)"), 104*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP, 105*c58d34ddSKevin Bowling "Intel(R) X520-1 82599EN (SFP+)"), 106*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF_QP, 107*c58d34ddSKevin Bowling "Intel(R) X520-4 82599 (Quad SFP+)"), 108*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_QSFP_SF_QP, 109*c58d34ddSKevin Bowling "Intel(R) X520-Q1 82599 (QSFP+)"), 110*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, 111*c58d34ddSKevin Bowling "Intel(R) X540-AT2"), 112fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, "Intel(R) X540-T1"), 113fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, "Intel(R) X550-T2"), 114fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, "Intel(R) X550-T1"), 115*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, 116*c58d34ddSKevin Bowling "Intel(R) X552 (KR Backplane)"), 117*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, 118*c58d34ddSKevin Bowling "Intel(R) X552 (KX4 Backplane)"), 119*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, 120*c58d34ddSKevin Bowling "Intel(R) X552/X557-AT (10GBASE-T)"), 121*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_1G_T, 122*c58d34ddSKevin Bowling "Intel(R) X552 (1000BASE-T)"), 123*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, 124*c58d34ddSKevin Bowling "Intel(R) X552 (SFP+)"), 125*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR, 126*c58d34ddSKevin Bowling "Intel(R) X553 (KR Backplane)"), 127*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR_L, 128*c58d34ddSKevin Bowling "Intel(R) X553 L (KR Backplane)"), 129*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP, 130*c58d34ddSKevin Bowling "Intel(R) X553 (SFP+)"), 131*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP_N, 132*c58d34ddSKevin Bowling "Intel(R) X553 N (SFP+)"), 133*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII, 134*c58d34ddSKevin Bowling "Intel(R) X553 (1GbE SGMII)"), 135*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII_L, 136*c58d34ddSKevin Bowling "Intel(R) X553 L (1GbE SGMII)"), 137*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_10G_T, 138*c58d34ddSKevin Bowling "Intel(R) X553/X557-AT (10GBASE-T)"), 139*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T, 140*c58d34ddSKevin Bowling "Intel(R) X553 (1GbE)"), 141*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T_L, 142*c58d34ddSKevin Bowling "Intel(R) X553 L (1GbE)"), 143*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_BYPASS, 144*c58d34ddSKevin Bowling "Intel(R) X540-T2 (Bypass)"), 145*c58d34ddSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BYPASS, 146*c58d34ddSKevin Bowling "Intel(R) X520 82599 (Bypass)"), 147758cc3dcSJack F Vogel /* required last entry */ 148c19c7afeSEric Joyner PVID_END 149758cc3dcSJack F Vogel }; 150758cc3dcSJack F Vogel 151b1d5caf3SKevin Bowling static void *ixgbe_register(device_t); 152b1d5caf3SKevin Bowling static int ixgbe_if_attach_pre(if_ctx_t); 153b1d5caf3SKevin Bowling static int ixgbe_if_attach_post(if_ctx_t); 154b1d5caf3SKevin Bowling static int ixgbe_if_detach(if_ctx_t); 155b1d5caf3SKevin Bowling static int ixgbe_if_shutdown(if_ctx_t); 156b1d5caf3SKevin Bowling static int ixgbe_if_suspend(if_ctx_t); 157b1d5caf3SKevin Bowling static int ixgbe_if_resume(if_ctx_t); 158c19c7afeSEric Joyner 159b1d5caf3SKevin Bowling static void ixgbe_if_stop(if_ctx_t); 160b1d5caf3SKevin Bowling void ixgbe_if_enable_intr(if_ctx_t); 161b1d5caf3SKevin Bowling static void ixgbe_if_disable_intr(if_ctx_t); 162b1d5caf3SKevin Bowling static void ixgbe_link_intr_enable(if_ctx_t); 163b1d5caf3SKevin Bowling static int ixgbe_if_rx_queue_intr_enable(if_ctx_t, uint16_t); 164b1d5caf3SKevin Bowling static void ixgbe_if_media_status(if_ctx_t, struct ifmediareq *); 165b1d5caf3SKevin Bowling static int ixgbe_if_media_change(if_ctx_t); 166c19c7afeSEric Joyner static int ixgbe_if_msix_intr_assign(if_ctx_t, int); 167b1d5caf3SKevin Bowling static int ixgbe_if_mtu_set(if_ctx_t, uint32_t); 168b1d5caf3SKevin Bowling static void ixgbe_if_crcstrip_set(if_ctx_t, int, int); 169b1d5caf3SKevin Bowling static void ixgbe_if_multi_set(if_ctx_t); 170b1d5caf3SKevin Bowling static int ixgbe_if_promisc_set(if_ctx_t, int); 171*c58d34ddSKevin Bowling static int ixgbe_if_tx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int, 172*c58d34ddSKevin Bowling int); 173*c58d34ddSKevin Bowling static int ixgbe_if_rx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int, 174*c58d34ddSKevin Bowling int); 175b1d5caf3SKevin Bowling static void ixgbe_if_queues_free(if_ctx_t); 176b1d5caf3SKevin Bowling static void ixgbe_if_timer(if_ctx_t, uint16_t); 177b1d5caf3SKevin Bowling static void ixgbe_if_update_admin_status(if_ctx_t); 178b1d5caf3SKevin Bowling static void ixgbe_if_vlan_register(if_ctx_t, u16); 179b1d5caf3SKevin Bowling static void ixgbe_if_vlan_unregister(if_ctx_t, u16); 180b1d5caf3SKevin Bowling static int ixgbe_if_i2c_req(if_ctx_t, struct ifi2creq *); 181b1d5caf3SKevin Bowling static bool ixgbe_if_needs_restart(if_ctx_t, enum iflib_restart_event); 182b1d5caf3SKevin Bowling int ixgbe_intr(void *); 183758cc3dcSJack F Vogel 1848eb6488eSEric Joyner /************************************************************************ 185758cc3dcSJack F Vogel * Function prototypes 1868eb6488eSEric Joyner ************************************************************************/ 187c19c7afeSEric Joyner static uint64_t ixgbe_if_get_counter(if_ctx_t, ift_counter); 188758cc3dcSJack F Vogel 189b1d5caf3SKevin Bowling static void ixgbe_enable_queue(struct ixgbe_softc *, u32); 190b1d5caf3SKevin Bowling static void ixgbe_disable_queue(struct ixgbe_softc *, u32); 191b1d5caf3SKevin Bowling static void ixgbe_add_device_sysctls(if_ctx_t); 192b1d5caf3SKevin Bowling static int ixgbe_allocate_pci_resources(if_ctx_t); 193b1d5caf3SKevin Bowling static int ixgbe_setup_low_power_mode(if_ctx_t); 194c19c7afeSEric Joyner 195b1d5caf3SKevin Bowling static void ixgbe_config_dmac(struct ixgbe_softc *); 196b1d5caf3SKevin Bowling static void ixgbe_configure_ivars(struct ixgbe_softc *); 197b1d5caf3SKevin Bowling static void ixgbe_set_ivar(struct ixgbe_softc *, u8, u8, s8); 198c19c7afeSEric Joyner static u8 *ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); 199b1d5caf3SKevin Bowling static bool ixgbe_sfp_probe(if_ctx_t); 200c19c7afeSEric Joyner 201b1d5caf3SKevin Bowling static void ixgbe_free_pci_resources(if_ctx_t); 202c19c7afeSEric Joyner 203b1d5caf3SKevin Bowling static int ixgbe_msix_link(void *); 204b1d5caf3SKevin Bowling static int ixgbe_msix_que(void *); 205b1d5caf3SKevin Bowling static void ixgbe_initialize_rss_mapping(struct ixgbe_softc *); 206b1d5caf3SKevin Bowling static void ixgbe_initialize_receive_units(if_ctx_t); 207b1d5caf3SKevin Bowling static void ixgbe_initialize_transmit_units(if_ctx_t); 208c19c7afeSEric Joyner 209b1d5caf3SKevin Bowling static int ixgbe_setup_interface(if_ctx_t); 210b1d5caf3SKevin Bowling static void ixgbe_init_device_features(struct ixgbe_softc *); 211b1d5caf3SKevin Bowling static void ixgbe_check_fan_failure(struct ixgbe_softc *, u32, bool); 2127660e4eaSKevin Bowling static void ixgbe_sbuf_fw_version(struct ixgbe_hw *, struct sbuf *); 213b1d5caf3SKevin Bowling static void ixgbe_print_fw_version(if_ctx_t); 214b1d5caf3SKevin Bowling static void ixgbe_add_media_types(if_ctx_t); 215b1d5caf3SKevin Bowling static void ixgbe_update_stats_counters(struct ixgbe_softc *); 216b1d5caf3SKevin Bowling static void ixgbe_config_link(if_ctx_t); 217b1d5caf3SKevin Bowling static void ixgbe_get_slot_info(struct ixgbe_softc *); 218f72de14eSKevin Bowling static void ixgbe_fw_mode_timer(void *); 219b1d5caf3SKevin Bowling static void ixgbe_check_wol_support(struct ixgbe_softc *); 220b1d5caf3SKevin Bowling static void ixgbe_enable_rx_drop(struct ixgbe_softc *); 221b1d5caf3SKevin Bowling static void ixgbe_disable_rx_drop(struct ixgbe_softc *); 222758cc3dcSJack F Vogel 223b1d5caf3SKevin Bowling static void ixgbe_add_hw_stats(struct ixgbe_softc *); 224b1d5caf3SKevin Bowling static int ixgbe_set_flowcntl(struct ixgbe_softc *, int); 225b1d5caf3SKevin Bowling static int ixgbe_set_advertise(struct ixgbe_softc *, int); 226d381c807SPiotr Pietruszewski static int ixgbe_get_default_advertise(struct ixgbe_softc *); 227b1d5caf3SKevin Bowling static void ixgbe_setup_vlan_hw_support(if_ctx_t); 228b1d5caf3SKevin Bowling static void ixgbe_config_gpie(struct ixgbe_softc *); 229b1d5caf3SKevin Bowling static void ixgbe_config_delay_values(struct ixgbe_softc *); 2306f37f232SEric Joyner 2316f37f232SEric Joyner /* Sysctl handlers */ 232f2c4db54SSteven Hartland static int ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS); 233f2c4db54SSteven Hartland static int ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS); 2348eb6488eSEric Joyner static int ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS); 2356f37f232SEric Joyner static int ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS); 2366f37f232SEric Joyner static int ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS); 2376f37f232SEric Joyner static int ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS); 2387660e4eaSKevin Bowling static int ixgbe_sysctl_print_fw_version(SYSCTL_HANDLER_ARGS); 239a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 240a9ca1c79SSean Bruno static int ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS); 241a9ca1c79SSean Bruno static int ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS); 242a9ca1c79SSean Bruno #endif 2438eb6488eSEric Joyner static int ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS); 2448eb6488eSEric Joyner static int ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS); 2458eb6488eSEric Joyner static int ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS); 2468eb6488eSEric Joyner static int ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS); 2478eb6488eSEric Joyner static int ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS); 2486f37f232SEric Joyner static int ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS); 2496f37f232SEric Joyner static int ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS); 250eea2e089SMichael Tuexen static int ixgbe_sysctl_tso_tcp_flags_mask(SYSCTL_HANDLER_ARGS); 251758cc3dcSJack F Vogel 252758cc3dcSJack F Vogel /* Deferred interrupt tasklets */ 253c19c7afeSEric Joyner static void ixgbe_handle_msf(void *); 254c19c7afeSEric Joyner static void ixgbe_handle_mod(void *); 255c19c7afeSEric Joyner static void ixgbe_handle_phy(void *); 256758cc3dcSJack F Vogel 2578eb6488eSEric Joyner /************************************************************************ 258758cc3dcSJack F Vogel * FreeBSD Device Interface Entry Points 2598eb6488eSEric Joyner ************************************************************************/ 260a1edda90SAdrian Chadd static device_method_t ix_methods[] = { 261758cc3dcSJack F Vogel /* Device interface */ 262c19c7afeSEric Joyner DEVMETHOD(device_register, ixgbe_register), 263c19c7afeSEric Joyner DEVMETHOD(device_probe, iflib_device_probe), 264c19c7afeSEric Joyner DEVMETHOD(device_attach, iflib_device_attach), 265c19c7afeSEric Joyner DEVMETHOD(device_detach, iflib_device_detach), 266c19c7afeSEric Joyner DEVMETHOD(device_shutdown, iflib_device_shutdown), 267c19c7afeSEric Joyner DEVMETHOD(device_suspend, iflib_device_suspend), 268c19c7afeSEric Joyner DEVMETHOD(device_resume, iflib_device_resume), 26948056c88SJack F Vogel #ifdef PCI_IOV 270c19c7afeSEric Joyner DEVMETHOD(pci_iov_init, iflib_device_iov_init), 271c19c7afeSEric Joyner DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit), 272c19c7afeSEric Joyner DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf), 27348056c88SJack F Vogel #endif /* PCI_IOV */ 274758cc3dcSJack F Vogel DEVMETHOD_END 275758cc3dcSJack F Vogel }; 276758cc3dcSJack F Vogel 277a1edda90SAdrian Chadd static driver_t ix_driver = { 278b1d5caf3SKevin Bowling "ix", ix_methods, sizeof(struct ixgbe_softc), 279758cc3dcSJack F Vogel }; 280758cc3dcSJack F Vogel 281964c2b3aSJohn Baldwin DRIVER_MODULE(ix, pci, ix_driver, 0, 0); 282937b0f25SYuri Pankov IFLIB_PNP_INFO(pci, ix_driver, ixgbe_vendor_info_array); 283a1edda90SAdrian Chadd MODULE_DEPEND(ix, pci, 1, 1, 1); 284a1edda90SAdrian Chadd MODULE_DEPEND(ix, ether, 1, 1, 1); 285c19c7afeSEric Joyner MODULE_DEPEND(ix, iflib, 1, 1, 1); 286c19c7afeSEric Joyner 287c19c7afeSEric Joyner static device_method_t ixgbe_if_methods[] = { 288c19c7afeSEric Joyner DEVMETHOD(ifdi_attach_pre, ixgbe_if_attach_pre), 289c19c7afeSEric Joyner DEVMETHOD(ifdi_attach_post, ixgbe_if_attach_post), 290c19c7afeSEric Joyner DEVMETHOD(ifdi_detach, ixgbe_if_detach), 291c19c7afeSEric Joyner DEVMETHOD(ifdi_shutdown, ixgbe_if_shutdown), 292c19c7afeSEric Joyner DEVMETHOD(ifdi_suspend, ixgbe_if_suspend), 293c19c7afeSEric Joyner DEVMETHOD(ifdi_resume, ixgbe_if_resume), 294c19c7afeSEric Joyner DEVMETHOD(ifdi_init, ixgbe_if_init), 295c19c7afeSEric Joyner DEVMETHOD(ifdi_stop, ixgbe_if_stop), 296c19c7afeSEric Joyner DEVMETHOD(ifdi_msix_intr_assign, ixgbe_if_msix_intr_assign), 297c19c7afeSEric Joyner DEVMETHOD(ifdi_intr_enable, ixgbe_if_enable_intr), 298c19c7afeSEric Joyner DEVMETHOD(ifdi_intr_disable, ixgbe_if_disable_intr), 299b2c1e8e6SEric Joyner DEVMETHOD(ifdi_link_intr_enable, ixgbe_link_intr_enable), 300c19c7afeSEric Joyner DEVMETHOD(ifdi_tx_queue_intr_enable, ixgbe_if_rx_queue_intr_enable), 301c19c7afeSEric Joyner DEVMETHOD(ifdi_rx_queue_intr_enable, ixgbe_if_rx_queue_intr_enable), 302c19c7afeSEric Joyner DEVMETHOD(ifdi_tx_queues_alloc, ixgbe_if_tx_queues_alloc), 303c19c7afeSEric Joyner DEVMETHOD(ifdi_rx_queues_alloc, ixgbe_if_rx_queues_alloc), 304c19c7afeSEric Joyner DEVMETHOD(ifdi_queues_free, ixgbe_if_queues_free), 305c19c7afeSEric Joyner DEVMETHOD(ifdi_update_admin_status, ixgbe_if_update_admin_status), 306c19c7afeSEric Joyner DEVMETHOD(ifdi_multi_set, ixgbe_if_multi_set), 307c19c7afeSEric Joyner DEVMETHOD(ifdi_mtu_set, ixgbe_if_mtu_set), 308c19c7afeSEric Joyner DEVMETHOD(ifdi_crcstrip_set, ixgbe_if_crcstrip_set), 309c19c7afeSEric Joyner DEVMETHOD(ifdi_media_status, ixgbe_if_media_status), 310c19c7afeSEric Joyner DEVMETHOD(ifdi_media_change, ixgbe_if_media_change), 311c19c7afeSEric Joyner DEVMETHOD(ifdi_promisc_set, ixgbe_if_promisc_set), 312c19c7afeSEric Joyner DEVMETHOD(ifdi_timer, ixgbe_if_timer), 313c19c7afeSEric Joyner DEVMETHOD(ifdi_vlan_register, ixgbe_if_vlan_register), 314c19c7afeSEric Joyner DEVMETHOD(ifdi_vlan_unregister, ixgbe_if_vlan_unregister), 315c19c7afeSEric Joyner DEVMETHOD(ifdi_get_counter, ixgbe_if_get_counter), 316bca38080SAndrew Gallatin DEVMETHOD(ifdi_i2c_req, ixgbe_if_i2c_req), 317cf150917SEric Joyner DEVMETHOD(ifdi_needs_restart, ixgbe_if_needs_restart), 318c19c7afeSEric Joyner #ifdef PCI_IOV 319c19c7afeSEric Joyner DEVMETHOD(ifdi_iov_init, ixgbe_if_iov_init), 320c19c7afeSEric Joyner DEVMETHOD(ifdi_iov_uninit, ixgbe_if_iov_uninit), 321c19c7afeSEric Joyner DEVMETHOD(ifdi_iov_vf_add, ixgbe_if_iov_vf_add), 322c19c7afeSEric Joyner #endif /* PCI_IOV */ 323c19c7afeSEric Joyner DEVMETHOD_END 324c19c7afeSEric Joyner }; 325758cc3dcSJack F Vogel 326758cc3dcSJack F Vogel /* 3278eb6488eSEric Joyner * TUNEABLE PARAMETERS: 328758cc3dcSJack F Vogel */ 329758cc3dcSJack F Vogel 33020b91f0aSPawel Biernacki static SYSCTL_NODE(_hw, OID_AUTO, ix, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 33120b91f0aSPawel Biernacki "IXGBE driver parameters"); 332c19c7afeSEric Joyner static driver_t ixgbe_if_driver = { 333b1d5caf3SKevin Bowling "ixgbe_if", ixgbe_if_methods, sizeof(struct ixgbe_softc) 334c19c7afeSEric Joyner }; 335758cc3dcSJack F Vogel 336758cc3dcSJack F Vogel static int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY); 337758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN, 338758cc3dcSJack F Vogel &ixgbe_max_interrupt_rate, 0, "Maximum interrupts per second"); 339758cc3dcSJack F Vogel 340f2c4db54SSteven Hartland /* Flow control setting, default to full */ 341f2c4db54SSteven Hartland static int ixgbe_flow_control = ixgbe_fc_full; 342f2c4db54SSteven Hartland SYSCTL_INT(_hw_ix, OID_AUTO, flow_control, CTLFLAG_RDTUN, 343f2c4db54SSteven Hartland &ixgbe_flow_control, 0, "Default flow control used for all adapters"); 344f2c4db54SSteven Hartland 345f2c4db54SSteven Hartland /* Advertise Speed, default to 0 (auto) */ 346f2c4db54SSteven Hartland static int ixgbe_advertise_speed = 0; 347f2c4db54SSteven Hartland SYSCTL_INT(_hw_ix, OID_AUTO, advertise_speed, CTLFLAG_RDTUN, 348f2c4db54SSteven Hartland &ixgbe_advertise_speed, 0, "Default advertised speed for all adapters"); 349f2c4db54SSteven Hartland 350758cc3dcSJack F Vogel /* 3518eb6488eSEric Joyner * Smart speed setting, default to on 3528eb6488eSEric Joyner * this only works as a compile option 3538eb6488eSEric Joyner * right now as its during attach, set 3548eb6488eSEric Joyner * this to 'ixgbe_smart_speed_off' to 3558eb6488eSEric Joyner * disable. 356758cc3dcSJack F Vogel */ 357758cc3dcSJack F Vogel static int ixgbe_smart_speed = ixgbe_smart_speed_on; 358758cc3dcSJack F Vogel 359758cc3dcSJack F Vogel /* 3608eb6488eSEric Joyner * MSI-X should be the default for best performance, 361758cc3dcSJack F Vogel * but this allows it to be forced off for testing. 362758cc3dcSJack F Vogel */ 363758cc3dcSJack F Vogel static int ixgbe_enable_msix = 1; 364*c58d34ddSKevin Bowling SYSCTL_INT(_hw_ix, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixgbe_enable_msix, 365*c58d34ddSKevin Bowling 0, 366758cc3dcSJack F Vogel "Enable MSI-X interrupts"); 367758cc3dcSJack F Vogel 368758cc3dcSJack F Vogel /* 3698eb6488eSEric Joyner * Defining this on will allow the use 3708eb6488eSEric Joyner * of unsupported SFP+ modules, note that 3718eb6488eSEric Joyner * doing so you are on your own :) 372758cc3dcSJack F Vogel */ 37379b36ec9SKevin Bowling static int allow_unsupported_sfp = false; 374fb6aa95dSSean Bruno SYSCTL_INT(_hw_ix, OID_AUTO, unsupported_sfp, CTLFLAG_RDTUN, 3758eb6488eSEric Joyner &allow_unsupported_sfp, 0, 3768eb6488eSEric Joyner "Allow unsupported SFP modules...use at your own risk"); 3778eb6488eSEric Joyner 3788eb6488eSEric Joyner /* 3798eb6488eSEric Joyner * Not sure if Flow Director is fully baked, 3808eb6488eSEric Joyner * so we'll default to turning it off. 3818eb6488eSEric Joyner */ 3828eb6488eSEric Joyner static int ixgbe_enable_fdir = 0; 383*c58d34ddSKevin Bowling SYSCTL_INT(_hw_ix, OID_AUTO, enable_fdir, CTLFLAG_RDTUN, &ixgbe_enable_fdir, 384*c58d34ddSKevin Bowling 0, 3858eb6488eSEric Joyner "Enable Flow Director"); 3868eb6488eSEric Joyner 3878eb6488eSEric Joyner /* Receive-Side Scaling */ 3888eb6488eSEric Joyner static int ixgbe_enable_rss = 1; 389*c58d34ddSKevin Bowling SYSCTL_INT(_hw_ix, OID_AUTO, enable_rss, CTLFLAG_RDTUN, &ixgbe_enable_rss, 390*c58d34ddSKevin Bowling 0, 3918eb6488eSEric Joyner "Enable Receive-Side Scaling (RSS)"); 392758cc3dcSJack F Vogel 39364881da4SSai Rajesh Tallamraju /* 39464881da4SSai Rajesh Tallamraju * AIM: Adaptive Interrupt Moderation 39564881da4SSai Rajesh Tallamraju * which means that the interrupt rate 39664881da4SSai Rajesh Tallamraju * is varied over time based on the 39764881da4SSai Rajesh Tallamraju * traffic for that interrupt vector 39864881da4SSai Rajesh Tallamraju */ 39979b36ec9SKevin Bowling static int ixgbe_enable_aim = false; 400*c58d34ddSKevin Bowling SYSCTL_INT(_hw_ix, OID_AUTO, enable_aim, CTLFLAG_RWTUN, &ixgbe_enable_aim, 401*c58d34ddSKevin Bowling 0, 40264881da4SSai Rajesh Tallamraju "Enable adaptive interrupt moderation"); 40364881da4SSai Rajesh Tallamraju 404c19c7afeSEric Joyner #if 0 405758cc3dcSJack F Vogel /* Keep running tab on them for sanity check */ 406758cc3dcSJack F Vogel static int ixgbe_total_ports; 407c19c7afeSEric Joyner #endif 408758cc3dcSJack F Vogel 4098eb6488eSEric Joyner MALLOC_DEFINE(M_IXGBE, "ix", "ix driver allocations"); 410758cc3dcSJack F Vogel 411c19c7afeSEric Joyner /* 412c19c7afeSEric Joyner * For Flow Director: this is the number of TX packets we sample 413c19c7afeSEric Joyner * for the filter pool, this means every 20th packet will be probed. 414c19c7afeSEric Joyner * 415c19c7afeSEric Joyner * This feature can be disabled by setting this to 0. 416c19c7afeSEric Joyner */ 417c19c7afeSEric Joyner static int atr_sample_rate = 20; 418c19c7afeSEric Joyner 419c19c7afeSEric Joyner extern struct if_txrx ixgbe_txrx; 420c19c7afeSEric Joyner 421c19c7afeSEric Joyner static struct if_shared_ctx ixgbe_sctx_init = { 422c19c7afeSEric Joyner .isc_magic = IFLIB_MAGIC, 423c19c7afeSEric Joyner .isc_q_align = PAGE_SIZE,/* max(DBA_ALIGN, PAGE_SIZE) */ 4247f87c040SMarius Strobl .isc_tx_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header), 425c19c7afeSEric Joyner .isc_tx_maxsegsize = PAGE_SIZE, 4267f87c040SMarius Strobl .isc_tso_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header), 4277f87c040SMarius Strobl .isc_tso_maxsegsize = PAGE_SIZE, 428c19c7afeSEric Joyner .isc_rx_maxsize = PAGE_SIZE*4, 429c19c7afeSEric Joyner .isc_rx_nsegments = 1, 430c19c7afeSEric Joyner .isc_rx_maxsegsize = PAGE_SIZE*4, 431c19c7afeSEric Joyner .isc_nfl = 1, 432c19c7afeSEric Joyner .isc_ntxqs = 1, 433c19c7afeSEric Joyner .isc_nrxqs = 1, 434c19c7afeSEric Joyner 435c19c7afeSEric Joyner .isc_admin_intrcnt = 1, 436c19c7afeSEric Joyner .isc_vendor_info = ixgbe_vendor_info_array, 437c19c7afeSEric Joyner .isc_driver_version = ixgbe_driver_version, 438c19c7afeSEric Joyner .isc_driver = &ixgbe_if_driver, 4397aad1f4eSEric Joyner .isc_flags = IFLIB_TSO_INIT_IP, 440c19c7afeSEric Joyner 441c19c7afeSEric Joyner .isc_nrxd_min = {MIN_RXD}, 442c19c7afeSEric Joyner .isc_ntxd_min = {MIN_TXD}, 443c19c7afeSEric Joyner .isc_nrxd_max = {MAX_RXD}, 444c19c7afeSEric Joyner .isc_ntxd_max = {MAX_TXD}, 445c19c7afeSEric Joyner .isc_nrxd_default = {DEFAULT_RXD}, 446c19c7afeSEric Joyner .isc_ntxd_default = {DEFAULT_TXD}, 447c19c7afeSEric Joyner }; 448c19c7afeSEric Joyner 449c19c7afeSEric Joyner /************************************************************************ 450c19c7afeSEric Joyner * ixgbe_if_tx_queues_alloc 451c19c7afeSEric Joyner ************************************************************************/ 452c19c7afeSEric Joyner static int 453c19c7afeSEric Joyner ixgbe_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, 454c19c7afeSEric Joyner int ntxqs, int ntxqsets) 455c19c7afeSEric Joyner { 456b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 457b1d5caf3SKevin Bowling if_softc_ctx_t scctx = sc->shared; 458c19c7afeSEric Joyner struct ix_tx_queue *que; 459c19c7afeSEric Joyner int i, j, error; 460c19c7afeSEric Joyner 461b1d5caf3SKevin Bowling MPASS(sc->num_tx_queues > 0); 462b1d5caf3SKevin Bowling MPASS(sc->num_tx_queues == ntxqsets); 463c19c7afeSEric Joyner MPASS(ntxqs == 1); 464c19c7afeSEric Joyner 465c19c7afeSEric Joyner /* Allocate queue structure memory */ 466b1d5caf3SKevin Bowling sc->tx_queues = 467*c58d34ddSKevin Bowling (struct ix_tx_queue *)malloc(sizeof(struct ix_tx_queue) * 468*c58d34ddSKevin Bowling ntxqsets, M_IXGBE, M_NOWAIT | M_ZERO); 469b1d5caf3SKevin Bowling if (!sc->tx_queues) { 470c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), 471c19c7afeSEric Joyner "Unable to allocate TX ring memory\n"); 472c19c7afeSEric Joyner return (ENOMEM); 473c19c7afeSEric Joyner } 474c19c7afeSEric Joyner 475b1d5caf3SKevin Bowling for (i = 0, que = sc->tx_queues; i < ntxqsets; i++, que++) { 476c19c7afeSEric Joyner struct tx_ring *txr = &que->txr; 477c19c7afeSEric Joyner 478c19c7afeSEric Joyner /* In case SR-IOV is enabled, align the index properly */ 479*c58d34ddSKevin Bowling txr->me = ixgbe_vf_que_index(sc->iov_mode, sc->pool, i); 480c19c7afeSEric Joyner 481b1d5caf3SKevin Bowling txr->sc = que->sc = sc; 482c19c7afeSEric Joyner 483c19c7afeSEric Joyner /* Allocate report status array */ 484*c58d34ddSKevin Bowling txr->tx_rsq = (qidx_t *)malloc(sizeof(qidx_t) * 485*c58d34ddSKevin Bowling scctx->isc_ntxd[0], M_IXGBE, M_NOWAIT | M_ZERO); 486c19c7afeSEric Joyner if (txr->tx_rsq == NULL) { 487c19c7afeSEric Joyner error = ENOMEM; 488c19c7afeSEric Joyner goto fail; 489c19c7afeSEric Joyner } 490c19c7afeSEric Joyner for (j = 0; j < scctx->isc_ntxd[0]; j++) 491c19c7afeSEric Joyner txr->tx_rsq[j] = QIDX_INVALID; 492*c58d34ddSKevin Bowling /* get virtual and physical address of the hardware queues */ 493c19c7afeSEric Joyner txr->tail = IXGBE_TDT(txr->me); 494c19c7afeSEric Joyner txr->tx_base = (union ixgbe_adv_tx_desc *)vaddrs[i]; 495c19c7afeSEric Joyner txr->tx_paddr = paddrs[i]; 496c19c7afeSEric Joyner 497c19c7afeSEric Joyner txr->bytes = 0; 498c19c7afeSEric Joyner txr->total_packets = 0; 499c19c7afeSEric Joyner 500c19c7afeSEric Joyner /* Set the rate at which we sample packets */ 501b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_FDIR) 502c19c7afeSEric Joyner txr->atr_sample = atr_sample_rate; 503c19c7afeSEric Joyner 504c19c7afeSEric Joyner } 505c19c7afeSEric Joyner 506c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), "allocated for %d queues\n", 507b1d5caf3SKevin Bowling sc->num_tx_queues); 508c19c7afeSEric Joyner 509c19c7afeSEric Joyner return (0); 510c19c7afeSEric Joyner 511c19c7afeSEric Joyner fail: 512c19c7afeSEric Joyner ixgbe_if_queues_free(ctx); 513c19c7afeSEric Joyner 514c19c7afeSEric Joyner return (error); 515c19c7afeSEric Joyner } /* ixgbe_if_tx_queues_alloc */ 516c19c7afeSEric Joyner 517c19c7afeSEric Joyner /************************************************************************ 518c19c7afeSEric Joyner * ixgbe_if_rx_queues_alloc 519c19c7afeSEric Joyner ************************************************************************/ 520c19c7afeSEric Joyner static int 521c19c7afeSEric Joyner ixgbe_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, 522c19c7afeSEric Joyner int nrxqs, int nrxqsets) 523c19c7afeSEric Joyner { 524b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 525c19c7afeSEric Joyner struct ix_rx_queue *que; 526c19c7afeSEric Joyner int i; 527c19c7afeSEric Joyner 528b1d5caf3SKevin Bowling MPASS(sc->num_rx_queues > 0); 529b1d5caf3SKevin Bowling MPASS(sc->num_rx_queues == nrxqsets); 530c19c7afeSEric Joyner MPASS(nrxqs == 1); 531c19c7afeSEric Joyner 532c19c7afeSEric Joyner /* Allocate queue structure memory */ 533b1d5caf3SKevin Bowling sc->rx_queues = 534c19c7afeSEric Joyner (struct ix_rx_queue *)malloc(sizeof(struct ix_rx_queue)*nrxqsets, 535c19c7afeSEric Joyner M_IXGBE, M_NOWAIT | M_ZERO); 536b1d5caf3SKevin Bowling if (!sc->rx_queues) { 537c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), 538c19c7afeSEric Joyner "Unable to allocate TX ring memory\n"); 539c19c7afeSEric Joyner return (ENOMEM); 540c19c7afeSEric Joyner } 541c19c7afeSEric Joyner 542b1d5caf3SKevin Bowling for (i = 0, que = sc->rx_queues; i < nrxqsets; i++, que++) { 543c19c7afeSEric Joyner struct rx_ring *rxr = &que->rxr; 544c19c7afeSEric Joyner 545c19c7afeSEric Joyner /* In case SR-IOV is enabled, align the index properly */ 546*c58d34ddSKevin Bowling rxr->me = ixgbe_vf_que_index(sc->iov_mode, sc->pool, i); 547c19c7afeSEric Joyner 548b1d5caf3SKevin Bowling rxr->sc = que->sc = sc; 549c19c7afeSEric Joyner 550c19c7afeSEric Joyner /* get the virtual and physical address of the hw queues */ 551c19c7afeSEric Joyner rxr->tail = IXGBE_RDT(rxr->me); 552c19c7afeSEric Joyner rxr->rx_base = (union ixgbe_adv_rx_desc *)vaddrs[i]; 553c19c7afeSEric Joyner rxr->rx_paddr = paddrs[i]; 554c19c7afeSEric Joyner rxr->bytes = 0; 555c19c7afeSEric Joyner rxr->que = que; 556c19c7afeSEric Joyner } 557c19c7afeSEric Joyner 558c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), "allocated for %d rx queues\n", 559b1d5caf3SKevin Bowling sc->num_rx_queues); 560c19c7afeSEric Joyner 561c19c7afeSEric Joyner return (0); 562c19c7afeSEric Joyner } /* ixgbe_if_rx_queues_alloc */ 563c19c7afeSEric Joyner 564c19c7afeSEric Joyner /************************************************************************ 565c19c7afeSEric Joyner * ixgbe_if_queues_free 566c19c7afeSEric Joyner ************************************************************************/ 567c19c7afeSEric Joyner static void 568c19c7afeSEric Joyner ixgbe_if_queues_free(if_ctx_t ctx) 569c19c7afeSEric Joyner { 570b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 571b1d5caf3SKevin Bowling struct ix_tx_queue *tx_que = sc->tx_queues; 572b1d5caf3SKevin Bowling struct ix_rx_queue *rx_que = sc->rx_queues; 573c19c7afeSEric Joyner int i; 574c19c7afeSEric Joyner 575c19c7afeSEric Joyner if (tx_que != NULL) { 576b1d5caf3SKevin Bowling for (i = 0; i < sc->num_tx_queues; i++, tx_que++) { 577c19c7afeSEric Joyner struct tx_ring *txr = &tx_que->txr; 578c19c7afeSEric Joyner if (txr->tx_rsq == NULL) 579c19c7afeSEric Joyner break; 580c19c7afeSEric Joyner 581c19c7afeSEric Joyner free(txr->tx_rsq, M_IXGBE); 582c19c7afeSEric Joyner txr->tx_rsq = NULL; 583c19c7afeSEric Joyner } 584c19c7afeSEric Joyner 585b1d5caf3SKevin Bowling free(sc->tx_queues, M_IXGBE); 586b1d5caf3SKevin Bowling sc->tx_queues = NULL; 587c19c7afeSEric Joyner } 588c19c7afeSEric Joyner if (rx_que != NULL) { 589b1d5caf3SKevin Bowling free(sc->rx_queues, M_IXGBE); 590b1d5caf3SKevin Bowling sc->rx_queues = NULL; 591c19c7afeSEric Joyner } 592c19c7afeSEric Joyner } /* ixgbe_if_queues_free */ 593c19c7afeSEric Joyner 5948eb6488eSEric Joyner /************************************************************************ 5958eb6488eSEric Joyner * ixgbe_initialize_rss_mapping 5968eb6488eSEric Joyner ************************************************************************/ 5978eb6488eSEric Joyner static void 598b1d5caf3SKevin Bowling ixgbe_initialize_rss_mapping(struct ixgbe_softc *sc) 599758cc3dcSJack F Vogel { 600b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 6018eb6488eSEric Joyner u32 reta = 0, mrqc, rss_key[10]; 6028eb6488eSEric Joyner int queue_id, table_size, index_mult; 6038eb6488eSEric Joyner int i, j; 6048eb6488eSEric Joyner u32 rss_hash_config; 6056f37f232SEric Joyner 606b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_RSS) { 6078eb6488eSEric Joyner /* Fetch the configured RSS key */ 6088eb6488eSEric Joyner rss_getkey((uint8_t *)&rss_key); 609758cc3dcSJack F Vogel } else { 6108eb6488eSEric Joyner /* set up random bits */ 6118eb6488eSEric Joyner arc4rand(&rss_key, sizeof(rss_key), 0); 612758cc3dcSJack F Vogel } 613758cc3dcSJack F Vogel 6148eb6488eSEric Joyner /* Set multiplier for RETA setup and table size based on MAC */ 6158eb6488eSEric Joyner index_mult = 0x1; 6168eb6488eSEric Joyner table_size = 128; 617b1d5caf3SKevin Bowling switch (sc->hw.mac.type) { 6188eb6488eSEric Joyner case ixgbe_mac_82598EB: 6198eb6488eSEric Joyner index_mult = 0x11; 620758cc3dcSJack F Vogel break; 6218eb6488eSEric Joyner case ixgbe_mac_X550: 6228eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 6238eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 6248eb6488eSEric Joyner table_size = 512; 6258eb6488eSEric Joyner break; 626758cc3dcSJack F Vogel default: 627758cc3dcSJack F Vogel break; 628758cc3dcSJack F Vogel } 629758cc3dcSJack F Vogel 6308eb6488eSEric Joyner /* Set up the redirection table */ 6318eb6488eSEric Joyner for (i = 0, j = 0; i < table_size; i++, j++) { 632b1d5caf3SKevin Bowling if (j == sc->num_rx_queues) 6338eb6488eSEric Joyner j = 0; 634758cc3dcSJack F Vogel 635b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_RSS) { 636a9ca1c79SSean Bruno /* 6378eb6488eSEric Joyner * Fetch the RSS bucket id for the given indirection 6388eb6488eSEric Joyner * entry. Cap it at the number of configured buckets 639c19c7afeSEric Joyner * (which is num_rx_queues.) 640a9ca1c79SSean Bruno */ 6418eb6488eSEric Joyner queue_id = rss_get_indirection_to_bucket(i); 642b1d5caf3SKevin Bowling queue_id = queue_id % sc->num_rx_queues; 643758cc3dcSJack F Vogel } else 6448eb6488eSEric Joyner queue_id = (j * index_mult); 6458eb6488eSEric Joyner 6468eb6488eSEric Joyner /* 6478eb6488eSEric Joyner * The low 8 bits are for hash value (n+0); 6488eb6488eSEric Joyner * The next 8 bits are for hash value (n+1), etc. 6498eb6488eSEric Joyner */ 6508eb6488eSEric Joyner reta = reta >> 8; 6518eb6488eSEric Joyner reta = reta | (((uint32_t)queue_id) << 24); 6528eb6488eSEric Joyner if ((i & 3) == 3) { 6538eb6488eSEric Joyner if (i < 128) 6548eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta); 6558eb6488eSEric Joyner else 656*c58d34ddSKevin Bowling IXGBE_WRITE_REG(hw, 657*c58d34ddSKevin Bowling IXGBE_ERETA((i >> 2) - 32), reta); 6588eb6488eSEric Joyner reta = 0; 6598eb6488eSEric Joyner } 660758cc3dcSJack F Vogel } 661758cc3dcSJack F Vogel 6628eb6488eSEric Joyner /* Now fill our hash function seeds */ 6638eb6488eSEric Joyner for (i = 0; i < 10; i++) 6648eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]); 665758cc3dcSJack F Vogel 6668eb6488eSEric Joyner /* Perform hash on these packet types */ 667b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_RSS) 6688eb6488eSEric Joyner rss_hash_config = rss_gethashconfig(); 669758cc3dcSJack F Vogel else { 670758cc3dcSJack F Vogel /* 6718eb6488eSEric Joyner * Disable UDP - IP fragments aren't currently being handled 6728eb6488eSEric Joyner * and so we end up with a mix of 2-tuple and 4-tuple 6738eb6488eSEric Joyner * traffic. 674758cc3dcSJack F Vogel */ 675*c58d34ddSKevin Bowling rss_hash_config = RSS_HASHTYPE_RSS_IPV4 | 676*c58d34ddSKevin Bowling RSS_HASHTYPE_RSS_TCP_IPV4 | 677*c58d34ddSKevin Bowling RSS_HASHTYPE_RSS_IPV6 | 678*c58d34ddSKevin Bowling RSS_HASHTYPE_RSS_TCP_IPV6 | 679*c58d34ddSKevin Bowling RSS_HASHTYPE_RSS_IPV6_EX | 680*c58d34ddSKevin Bowling RSS_HASHTYPE_RSS_TCP_IPV6_EX; 681758cc3dcSJack F Vogel } 682758cc3dcSJack F Vogel 6838eb6488eSEric Joyner mrqc = IXGBE_MRQC_RSSEN; 6848eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4) 6858eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4; 6868eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4) 6878eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP; 6888eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6) 6898eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6; 6908eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6) 6918eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP; 6928eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX) 6938eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX; 6948eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX) 6958eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP; 6968eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4) 6978eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; 6988eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6) 6998eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; 7008eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX) 7018eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP; 702b1d5caf3SKevin Bowling mrqc |= ixgbe_get_mrqc(sc->iov_mode); 7038eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); 7048eb6488eSEric Joyner } /* ixgbe_initialize_rss_mapping */ 705758cc3dcSJack F Vogel 7068eb6488eSEric Joyner /************************************************************************ 7078eb6488eSEric Joyner * ixgbe_initialize_receive_units - Setup receive registers and features. 7088eb6488eSEric Joyner ************************************************************************/ 7098eb6488eSEric Joyner #define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1) 710758cc3dcSJack F Vogel 711758cc3dcSJack F Vogel static void 712c19c7afeSEric Joyner ixgbe_initialize_receive_units(if_ctx_t ctx) 713758cc3dcSJack F Vogel { 714b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 715b1d5caf3SKevin Bowling if_softc_ctx_t scctx = sc->shared; 716b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 717ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 718c19c7afeSEric Joyner struct ix_rx_queue *que; 7198eb6488eSEric Joyner int i, j; 7208eb6488eSEric Joyner u32 bufsz, fctrl, srrctl, rxcsum; 7218eb6488eSEric Joyner u32 hlreg; 72248056c88SJack F Vogel 72348056c88SJack F Vogel /* 7248eb6488eSEric Joyner * Make sure receives are disabled while 7258eb6488eSEric Joyner * setting up the descriptor ring 72648056c88SJack F Vogel */ 7278eb6488eSEric Joyner ixgbe_disable_rx(hw); 7288eb6488eSEric Joyner 7298eb6488eSEric Joyner /* Enable broadcasts */ 7308eb6488eSEric Joyner fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 7318eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_BAM; 732b1d5caf3SKevin Bowling if (sc->hw.mac.type == ixgbe_mac_82598EB) { 7338eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_DPF; 7348eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_PMCF; 73548056c88SJack F Vogel } 7368eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 7378eb6488eSEric Joyner 7388eb6488eSEric Joyner /* Set for Jumbo Frames? */ 7398eb6488eSEric Joyner hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0); 740ff06a8dbSJustin Hibbits if (if_getmtu(ifp) > ETHERMTU) 7418eb6488eSEric Joyner hlreg |= IXGBE_HLREG0_JUMBOEN; 7428eb6488eSEric Joyner else 7438eb6488eSEric Joyner hlreg &= ~IXGBE_HLREG0_JUMBOEN; 7448eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg); 7458eb6488eSEric Joyner 746b1d5caf3SKevin Bowling bufsz = (sc->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >> 7478eb6488eSEric Joyner IXGBE_SRRCTL_BSIZEPKT_SHIFT; 7488eb6488eSEric Joyner 749c19c7afeSEric Joyner /* Setup the Base and Length of the Rx Descriptor Ring */ 750b1d5caf3SKevin Bowling for (i = 0, que = sc->rx_queues; i < sc->num_rx_queues; i++, que++) { 751c19c7afeSEric Joyner struct rx_ring *rxr = &que->rxr; 752c19c7afeSEric Joyner u64 rdba = rxr->rx_paddr; 753c19c7afeSEric Joyner 7548eb6488eSEric Joyner j = rxr->me; 7558eb6488eSEric Joyner 7568eb6488eSEric Joyner /* Setup the Base and Length of the Rx Descriptor Ring */ 7578eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), 7588eb6488eSEric Joyner (rdba & 0x00000000ffffffffULL)); 7598eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32)); 7608eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j), 761c19c7afeSEric Joyner scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc)); 7628eb6488eSEric Joyner 7638eb6488eSEric Joyner /* Set up the SRRCTL register */ 7648eb6488eSEric Joyner srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(j)); 7658eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK; 7668eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK; 7678eb6488eSEric Joyner srrctl |= bufsz; 7688eb6488eSEric Joyner srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; 76948056c88SJack F Vogel 77048056c88SJack F Vogel /* 7718eb6488eSEric Joyner * Set DROP_EN iff we have no flow control and >1 queue. 7728eb6488eSEric Joyner * Note that srrctl was cleared shortly before during reset, 7738eb6488eSEric Joyner * so we do not need to clear the bit, but do it just in case 7748eb6488eSEric Joyner * this code is moved elsewhere. 77548056c88SJack F Vogel */ 776b1d5caf3SKevin Bowling if (sc->num_rx_queues > 1 && 777b1d5caf3SKevin Bowling sc->hw.fc.requested_mode == ixgbe_fc_none) { 7788eb6488eSEric Joyner srrctl |= IXGBE_SRRCTL_DROP_EN; 779758cc3dcSJack F Vogel } else { 7808eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_DROP_EN; 781758cc3dcSJack F Vogel } 782758cc3dcSJack F Vogel 7838eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl); 784758cc3dcSJack F Vogel 7858eb6488eSEric Joyner /* Setup the HW Rx Head and Tail Descriptor Pointers */ 7868eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0); 7878eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0); 788758cc3dcSJack F Vogel 7898eb6488eSEric Joyner /* Set the driver rx tail address */ 7908eb6488eSEric Joyner rxr->tail = IXGBE_RDT(rxr->me); 791a9ca1c79SSean Bruno } 792758cc3dcSJack F Vogel 793b1d5caf3SKevin Bowling if (sc->hw.mac.type != ixgbe_mac_82598EB) { 794*c58d34ddSKevin Bowling u32 psrtype = IXGBE_PSRTYPE_TCPHDR | 795*c58d34ddSKevin Bowling IXGBE_PSRTYPE_UDPHDR | 796*c58d34ddSKevin Bowling IXGBE_PSRTYPE_IPV4HDR | 797*c58d34ddSKevin Bowling IXGBE_PSRTYPE_IPV6HDR; 7988eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype); 7996f37f232SEric Joyner } 8006f37f232SEric Joyner 8018eb6488eSEric Joyner rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); 8028eb6488eSEric Joyner 803b1d5caf3SKevin Bowling ixgbe_initialize_rss_mapping(sc); 8048eb6488eSEric Joyner 805156424fcSPrzemyslaw Lewandowski if (sc->feat_en & IXGBE_FEATURE_RSS) { 8068eb6488eSEric Joyner /* RSS and RX IPP Checksum are mutually exclusive */ 8078eb6488eSEric Joyner rxcsum |= IXGBE_RXCSUM_PCSD; 8086f37f232SEric Joyner } 8096f37f232SEric Joyner 810ff06a8dbSJustin Hibbits if (if_getcapenable(ifp) & IFCAP_RXCSUM) 8118eb6488eSEric Joyner rxcsum |= IXGBE_RXCSUM_PCSD; 812758cc3dcSJack F Vogel 8138eb6488eSEric Joyner /* This is useful for calculating UDP/IP fragment checksums */ 8148eb6488eSEric Joyner if (!(rxcsum & IXGBE_RXCSUM_PCSD)) 8158eb6488eSEric Joyner rxcsum |= IXGBE_RXCSUM_IPPCSE; 816758cc3dcSJack F Vogel 8178eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum); 818758cc3dcSJack F Vogel 8198eb6488eSEric Joyner } /* ixgbe_initialize_receive_units */ 820758cc3dcSJack F Vogel 8218eb6488eSEric Joyner /************************************************************************ 8228eb6488eSEric Joyner * ixgbe_initialize_transmit_units - Enable transmit units. 8238eb6488eSEric Joyner ************************************************************************/ 824758cc3dcSJack F Vogel static void 825c19c7afeSEric Joyner ixgbe_initialize_transmit_units(if_ctx_t ctx) 826758cc3dcSJack F Vogel { 827b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 828b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 829b1d5caf3SKevin Bowling if_softc_ctx_t scctx = sc->shared; 830c19c7afeSEric Joyner struct ix_tx_queue *que; 831c19c7afeSEric Joyner int i; 832758cc3dcSJack F Vogel 833758cc3dcSJack F Vogel /* Setup the Base and Length of the Tx Descriptor Ring */ 834b1d5caf3SKevin Bowling for (i = 0, que = sc->tx_queues; i < sc->num_tx_queues; 835c19c7afeSEric Joyner i++, que++) { 836c19c7afeSEric Joyner struct tx_ring *txr = &que->txr; 837c19c7afeSEric Joyner u64 tdba = txr->tx_paddr; 838758cc3dcSJack F Vogel u32 txctrl = 0; 83948056c88SJack F Vogel int j = txr->me; 840758cc3dcSJack F Vogel 84148056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j), 842758cc3dcSJack F Vogel (tdba & 0x00000000ffffffffULL)); 84348056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32)); 84448056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), 845c19c7afeSEric Joyner scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc)); 846758cc3dcSJack F Vogel 847758cc3dcSJack F Vogel /* Setup the HW Tx Head and Tail descriptor pointers */ 84848056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0); 84948056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0); 850758cc3dcSJack F Vogel 851758cc3dcSJack F Vogel /* Cache the tail address */ 8522dc2d580SEric Joyner txr->tail = IXGBE_TDT(txr->me); 8532dc2d580SEric Joyner 854088a0b27SEric Joyner txr->tx_rs_cidx = txr->tx_rs_pidx; 855088a0b27SEric Joyner txr->tx_cidx_processed = scctx->isc_ntxd[0] - 1; 856c19c7afeSEric Joyner for (int k = 0; k < scctx->isc_ntxd[0]; k++) 857c19c7afeSEric Joyner txr->tx_rsq[k] = QIDX_INVALID; 858758cc3dcSJack F Vogel 859758cc3dcSJack F Vogel /* Disable Head Writeback */ 860a9ca1c79SSean Bruno /* 861a9ca1c79SSean Bruno * Note: for X550 series devices, these registers are actually 862a9ca1c79SSean Bruno * prefixed with TPH_ isntead of DCA_, but the addresses and 863a9ca1c79SSean Bruno * fields remain the same. 864a9ca1c79SSean Bruno */ 865758cc3dcSJack F Vogel switch (hw->mac.type) { 866758cc3dcSJack F Vogel case ixgbe_mac_82598EB: 86748056c88SJack F Vogel txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j)); 868758cc3dcSJack F Vogel break; 869758cc3dcSJack F Vogel default: 870*c58d34ddSKevin Bowling txctrl = 871*c58d34ddSKevin Bowling IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j)); 872758cc3dcSJack F Vogel break; 873758cc3dcSJack F Vogel } 874758cc3dcSJack F Vogel txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; 875758cc3dcSJack F Vogel switch (hw->mac.type) { 876758cc3dcSJack F Vogel case ixgbe_mac_82598EB: 87748056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl); 878758cc3dcSJack F Vogel break; 879758cc3dcSJack F Vogel default: 880*c58d34ddSKevin Bowling IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), 881*c58d34ddSKevin Bowling txctrl); 882758cc3dcSJack F Vogel break; 883758cc3dcSJack F Vogel } 884758cc3dcSJack F Vogel 885758cc3dcSJack F Vogel } 886758cc3dcSJack F Vogel 887758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 888758cc3dcSJack F Vogel u32 dmatxctl, rttdcs; 8898eb6488eSEric Joyner 890758cc3dcSJack F Vogel dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); 891758cc3dcSJack F Vogel dmatxctl |= IXGBE_DMATXCTL_TE; 892758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); 893758cc3dcSJack F Vogel /* Disable arbiter to set MTQC */ 894758cc3dcSJack F Vogel rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); 895758cc3dcSJack F Vogel rttdcs |= IXGBE_RTTDCS_ARBDIS; 896758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); 8978eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_MTQC, 898b1d5caf3SKevin Bowling ixgbe_get_mtqc(sc->iov_mode)); 899758cc3dcSJack F Vogel rttdcs &= ~IXGBE_RTTDCS_ARBDIS; 900758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); 901758cc3dcSJack F Vogel } 902758cc3dcSJack F Vogel 9038eb6488eSEric Joyner } /* ixgbe_initialize_transmit_units */ 904758cc3dcSJack F Vogel 9058eb6488eSEric Joyner /************************************************************************ 906c19c7afeSEric Joyner * ixgbe_register 907c19c7afeSEric Joyner ************************************************************************/ 908c19c7afeSEric Joyner static void * 909c19c7afeSEric Joyner ixgbe_register(device_t dev) 910c19c7afeSEric Joyner { 911ffe3def9SMark Johnston return (&ixgbe_sctx_init); 912c19c7afeSEric Joyner } /* ixgbe_register */ 913c19c7afeSEric Joyner 914c19c7afeSEric Joyner /************************************************************************ 915c19c7afeSEric Joyner * ixgbe_if_attach_pre - Device initialization routine, part 1 916758cc3dcSJack F Vogel * 9178eb6488eSEric Joyner * Called when the driver is being loaded. 918c19c7afeSEric Joyner * Identifies the type of hardware, initializes the hardware, 919c19c7afeSEric Joyner * and initializes iflib structures. 920758cc3dcSJack F Vogel * 9218eb6488eSEric Joyner * return 0 on success, positive on failure 9228eb6488eSEric Joyner ************************************************************************/ 9238eb6488eSEric Joyner static int 924c19c7afeSEric Joyner ixgbe_if_attach_pre(if_ctx_t ctx) 925758cc3dcSJack F Vogel { 926b1d5caf3SKevin Bowling struct ixgbe_softc *sc; 927c19c7afeSEric Joyner device_t dev; 928c19c7afeSEric Joyner if_softc_ctx_t scctx; 9298eb6488eSEric Joyner struct ixgbe_hw *hw; 9308eb6488eSEric Joyner int error = 0; 9318eb6488eSEric Joyner u32 ctrl_ext; 9327234c309SJakub Chylkowski size_t i; 9338eb6488eSEric Joyner 9348eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_attach: begin"); 9358eb6488eSEric Joyner 9368eb6488eSEric Joyner /* Allocate, clear, and link in our adapter structure */ 937c19c7afeSEric Joyner dev = iflib_get_dev(ctx); 938b1d5caf3SKevin Bowling sc = iflib_get_softc(ctx); 939b1d5caf3SKevin Bowling sc->hw.back = sc; 940b1d5caf3SKevin Bowling sc->ctx = ctx; 941b1d5caf3SKevin Bowling sc->dev = dev; 942b1d5caf3SKevin Bowling scctx = sc->shared = iflib_get_softc_ctx(ctx); 943b1d5caf3SKevin Bowling sc->media = iflib_get_media(ctx); 944b1d5caf3SKevin Bowling hw = &sc->hw; 9458eb6488eSEric Joyner 9468eb6488eSEric Joyner /* Determine hardware revision */ 9478eb6488eSEric Joyner hw->vendor_id = pci_get_vendor(dev); 9488eb6488eSEric Joyner hw->device_id = pci_get_device(dev); 9498eb6488eSEric Joyner hw->revision_id = pci_get_revid(dev); 9508eb6488eSEric Joyner hw->subsystem_vendor_id = pci_get_subvendor(dev); 9518eb6488eSEric Joyner hw->subsystem_device_id = pci_get_subdevice(dev); 952758cc3dcSJack F Vogel 9538eb6488eSEric Joyner /* Do base PCI setup - map BAR0 */ 954c19c7afeSEric Joyner if (ixgbe_allocate_pci_resources(ctx)) { 9558eb6488eSEric Joyner device_printf(dev, "Allocation of PCI resources failed\n"); 956c19c7afeSEric Joyner return (ENXIO); 9576f37f232SEric Joyner } 958758cc3dcSJack F Vogel 9598eb6488eSEric Joyner /* let hardware know driver is loaded */ 9608eb6488eSEric Joyner ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 9618eb6488eSEric Joyner ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD; 9628eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 963758cc3dcSJack F Vogel 964758cc3dcSJack F Vogel /* 9658eb6488eSEric Joyner * Initialize the shared code 966758cc3dcSJack F Vogel */ 967c19c7afeSEric Joyner if (ixgbe_init_shared_code(hw) != 0) { 9688eb6488eSEric Joyner device_printf(dev, "Unable to initialize the shared code\n"); 9698eb6488eSEric Joyner error = ENXIO; 970c19c7afeSEric Joyner goto err_pci; 97130126537SJack F Vogel } 972758cc3dcSJack F Vogel 973*c58d34ddSKevin Bowling if (hw->mac.ops.fw_recovery_mode && 974*c58d34ddSKevin Bowling hw->mac.ops.fw_recovery_mode(hw)) { 975*c58d34ddSKevin Bowling device_printf(dev, 976*c58d34ddSKevin Bowling "Firmware recovery mode detected. Limiting " 9778b4a3fbdSKevin Bowling "functionality.\nRefer to the Intel(R) Ethernet Adapters " 9788b4a3fbdSKevin Bowling "and Devices User Guide for details on firmware recovery " 9798b4a3fbdSKevin Bowling "mode."); 9808b4a3fbdSKevin Bowling error = ENOSYS; 9818b4a3fbdSKevin Bowling goto err_pci; 9828b4a3fbdSKevin Bowling } 9838b4a3fbdSKevin Bowling 9847234c309SJakub Chylkowski /* 82598 Does not support SR-IOV, initialize everything else */ 9857234c309SJakub Chylkowski if (hw->mac.type >= ixgbe_mac_82599_vf) { 9867234c309SJakub Chylkowski for (i = 0; i < sc->num_vfs; i++) 9877234c309SJakub Chylkowski hw->mbx.ops[i].init_params(hw); 9887234c309SJakub Chylkowski } 989758cc3dcSJack F Vogel 9908eb6488eSEric Joyner hw->allow_unsupported_sfp = allow_unsupported_sfp; 991758cc3dcSJack F Vogel 992c19c7afeSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) 9938eb6488eSEric Joyner hw->phy.smart_speed = ixgbe_smart_speed; 9948eb6488eSEric Joyner 995b1d5caf3SKevin Bowling ixgbe_init_device_features(sc); 9968eb6488eSEric Joyner 9978eb6488eSEric Joyner /* Enable WoL (if supported) */ 998b1d5caf3SKevin Bowling ixgbe_check_wol_support(sc); 9998eb6488eSEric Joyner 10008eb6488eSEric Joyner /* Verify adapter fan is still functional (if applicable) */ 1001b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_FAN_FAIL) { 10028eb6488eSEric Joyner u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 1003b1d5caf3SKevin Bowling ixgbe_check_fan_failure(sc, esdp, false); 10048eb6488eSEric Joyner } 10058eb6488eSEric Joyner 10068eb6488eSEric Joyner /* Ensure SW/FW semaphore is free */ 10078eb6488eSEric Joyner ixgbe_init_swfw_semaphore(hw); 10088eb6488eSEric Joyner 10098eb6488eSEric Joyner /* Set an initial default flow control value */ 10108eb6488eSEric Joyner hw->fc.requested_mode = ixgbe_flow_control; 10118eb6488eSEric Joyner 101279b36ec9SKevin Bowling hw->phy.reset_if_overtemp = true; 10138eb6488eSEric Joyner error = ixgbe_reset_hw(hw); 101479b36ec9SKevin Bowling hw->phy.reset_if_overtemp = false; 10158eb6488eSEric Joyner if (error == IXGBE_ERR_SFP_NOT_PRESENT) { 1016758cc3dcSJack F Vogel /* 10178eb6488eSEric Joyner * No optics in this port, set up 10188eb6488eSEric Joyner * so the timer routine will probe 10198eb6488eSEric Joyner * for later insertion. 1020758cc3dcSJack F Vogel */ 1021b1d5caf3SKevin Bowling sc->sfp_probe = true; 1022c19c7afeSEric Joyner error = 0; 10238eb6488eSEric Joyner } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) { 10248eb6488eSEric Joyner device_printf(dev, "Unsupported SFP+ module detected!\n"); 10258eb6488eSEric Joyner error = EIO; 1026c19c7afeSEric Joyner goto err_pci; 10278eb6488eSEric Joyner } else if (error) { 10288eb6488eSEric Joyner device_printf(dev, "Hardware initialization failed\n"); 10298eb6488eSEric Joyner error = EIO; 1030c19c7afeSEric Joyner goto err_pci; 103197f9586eSSean Bruno } 103297f9586eSSean Bruno 10338eb6488eSEric Joyner /* Make sure we have a good EEPROM before we read from it */ 1034b1d5caf3SKevin Bowling if (ixgbe_validate_eeprom_checksum(&sc->hw, NULL) < 0) { 10358eb6488eSEric Joyner device_printf(dev, "The EEPROM Checksum Is Not Valid\n"); 10368eb6488eSEric Joyner error = EIO; 1037c19c7afeSEric Joyner goto err_pci; 103897f9586eSSean Bruno } 103997f9586eSSean Bruno 10408eb6488eSEric Joyner error = ixgbe_start_hw(hw); 10418eb6488eSEric Joyner switch (error) { 10428eb6488eSEric Joyner case IXGBE_ERR_EEPROM_VERSION: 1043*c58d34ddSKevin Bowling device_printf(dev, 1044*c58d34ddSKevin Bowling "This device is a pre-production adapter/LOM. Please be" 1045*c58d34ddSKevin Bowling " aware there may be issues associated with your" 1046*c58d34ddSKevin Bowling " hardware.\nIf you are experiencing problems please" 1047*c58d34ddSKevin Bowling " contact your Intel or hardware representative who" 1048*c58d34ddSKevin Bowling " provided you with this hardware.\n"); 104997f9586eSSean Bruno break; 10508eb6488eSEric Joyner case IXGBE_ERR_SFP_NOT_SUPPORTED: 10518eb6488eSEric Joyner device_printf(dev, "Unsupported SFP+ Module\n"); 10528eb6488eSEric Joyner error = EIO; 1053c19c7afeSEric Joyner goto err_pci; 10548eb6488eSEric Joyner case IXGBE_ERR_SFP_NOT_PRESENT: 10558eb6488eSEric Joyner device_printf(dev, "No SFP+ Module found\n"); 10568eb6488eSEric Joyner /* falls thru */ 105797f9586eSSean Bruno default: 105897f9586eSSean Bruno break; 105997f9586eSSean Bruno } 106097f9586eSSean Bruno 1061c19c7afeSEric Joyner /* Most of the iflib initialization... */ 1062c19c7afeSEric Joyner 1063c19c7afeSEric Joyner iflib_set_mac(ctx, hw->mac.addr); 1064b1d5caf3SKevin Bowling switch (sc->hw.mac.type) { 1065c19c7afeSEric Joyner case ixgbe_mac_X550: 1066c19c7afeSEric Joyner case ixgbe_mac_X550EM_x: 1067c19c7afeSEric Joyner case ixgbe_mac_X550EM_a: 1068c19c7afeSEric Joyner scctx->isc_rss_table_size = 512; 1069c19c7afeSEric Joyner scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 64; 1070c19c7afeSEric Joyner break; 1071c19c7afeSEric Joyner default: 1072c19c7afeSEric Joyner scctx->isc_rss_table_size = 128; 1073c19c7afeSEric Joyner scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 16; 1074c19c7afeSEric Joyner } 1075c19c7afeSEric Joyner 1076c19c7afeSEric Joyner /* Allow legacy interrupts */ 1077c19c7afeSEric Joyner ixgbe_txrx.ift_legacy_intr = ixgbe_intr; 1078c19c7afeSEric Joyner 1079c19c7afeSEric Joyner scctx->isc_txqsizes[0] = 1080c19c7afeSEric Joyner roundup2(scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc) + 1081c19c7afeSEric Joyner sizeof(u32), DBA_ALIGN), 1082c19c7afeSEric Joyner scctx->isc_rxqsizes[0] = 1083c19c7afeSEric Joyner roundup2(scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc), 1084c19c7afeSEric Joyner DBA_ALIGN); 1085c19c7afeSEric Joyner 1086c19c7afeSEric Joyner /* XXX */ 1087c19c7afeSEric Joyner scctx->isc_tx_csum_flags = CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO | 1088c19c7afeSEric Joyner CSUM_IP6_TCP | CSUM_IP6_UDP | CSUM_IP6_TSO; 1089b1d5caf3SKevin Bowling if (sc->hw.mac.type == ixgbe_mac_82598EB) { 1090c19c7afeSEric Joyner scctx->isc_tx_nsegments = IXGBE_82598_SCATTER; 1091c19c7afeSEric Joyner } else { 1092c19c7afeSEric Joyner scctx->isc_tx_csum_flags |= CSUM_SCTP |CSUM_IP6_SCTP; 1093c19c7afeSEric Joyner scctx->isc_tx_nsegments = IXGBE_82599_SCATTER; 1094c19c7afeSEric Joyner } 1095749597dcSEric Joyner 1096749597dcSEric Joyner scctx->isc_msix_bar = pci_msix_table_bar(dev); 1097749597dcSEric Joyner 1098c19c7afeSEric Joyner scctx->isc_tx_tso_segments_max = scctx->isc_tx_nsegments; 1099c19c7afeSEric Joyner scctx->isc_tx_tso_size_max = IXGBE_TSO_SIZE; 1100c19c7afeSEric Joyner scctx->isc_tx_tso_segsize_max = PAGE_SIZE; 1101c19c7afeSEric Joyner 1102c19c7afeSEric Joyner scctx->isc_txrx = &ixgbe_txrx; 1103c19c7afeSEric Joyner 11047f87c040SMarius Strobl scctx->isc_capabilities = scctx->isc_capenable = IXGBE_CAPS; 1105c19c7afeSEric Joyner 1106c19c7afeSEric Joyner return (0); 1107c19c7afeSEric Joyner 1108c19c7afeSEric Joyner err_pci: 1109b1d5caf3SKevin Bowling ctrl_ext = IXGBE_READ_REG(&sc->hw, IXGBE_CTRL_EXT); 1110c19c7afeSEric Joyner ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD; 1111b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_CTRL_EXT, ctrl_ext); 1112c19c7afeSEric Joyner ixgbe_free_pci_resources(ctx); 1113c19c7afeSEric Joyner 1114c19c7afeSEric Joyner return (error); 1115c19c7afeSEric Joyner } /* ixgbe_if_attach_pre */ 1116c19c7afeSEric Joyner 1117c19c7afeSEric Joyner /********************************************************************* 1118c19c7afeSEric Joyner * ixgbe_if_attach_post - Device initialization routine, part 2 1119c19c7afeSEric Joyner * 1120c19c7afeSEric Joyner * Called during driver load, but after interrupts and 1121c19c7afeSEric Joyner * resources have been allocated and configured. 1122c19c7afeSEric Joyner * Sets up some data structures not relevant to iflib. 1123c19c7afeSEric Joyner * 1124c19c7afeSEric Joyner * return 0 on success, positive on failure 1125c19c7afeSEric Joyner *********************************************************************/ 1126c19c7afeSEric Joyner static int 1127c19c7afeSEric Joyner ixgbe_if_attach_post(if_ctx_t ctx) 1128c19c7afeSEric Joyner { 1129c19c7afeSEric Joyner device_t dev; 1130b1d5caf3SKevin Bowling struct ixgbe_softc *sc; 1131c19c7afeSEric Joyner struct ixgbe_hw *hw; 1132c19c7afeSEric Joyner int error = 0; 1133c19c7afeSEric Joyner 1134c19c7afeSEric Joyner dev = iflib_get_dev(ctx); 1135b1d5caf3SKevin Bowling sc = iflib_get_softc(ctx); 1136b1d5caf3SKevin Bowling hw = &sc->hw; 1137c19c7afeSEric Joyner 1138b1d5caf3SKevin Bowling if (sc->intr_type == IFLIB_INTR_LEGACY && 1139b1d5caf3SKevin Bowling (sc->feat_cap & IXGBE_FEATURE_LEGACY_IRQ) == 0) { 1140c19c7afeSEric Joyner device_printf(dev, "Device does not support legacy interrupts"); 1141c19c7afeSEric Joyner error = ENXIO; 1142c19c7afeSEric Joyner goto err; 1143c19c7afeSEric Joyner } 1144c19c7afeSEric Joyner 1145c19c7afeSEric Joyner /* Allocate multicast array memory. */ 1146*c58d34ddSKevin Bowling sc->mta = malloc(sizeof(*sc->mta) * MAX_NUM_MULTICAST_ADDRESSES, 1147*c58d34ddSKevin Bowling M_IXGBE, M_NOWAIT); 1148b1d5caf3SKevin Bowling if (sc->mta == NULL) { 1149*c58d34ddSKevin Bowling device_printf(dev, 1150*c58d34ddSKevin Bowling "Can not allocate multicast setup array\n"); 1151c19c7afeSEric Joyner error = ENOMEM; 1152c19c7afeSEric Joyner goto err; 1153c19c7afeSEric Joyner } 1154c19c7afeSEric Joyner 1155c19c7afeSEric Joyner /* hw.ix defaults init */ 1156b1d5caf3SKevin Bowling ixgbe_set_advertise(sc, ixgbe_advertise_speed); 1157c19c7afeSEric Joyner 11588eb6488eSEric Joyner /* Enable the optics for 82599 SFP+ fiber */ 11598eb6488eSEric Joyner ixgbe_enable_tx_laser(hw); 1160758cc3dcSJack F Vogel 11618eb6488eSEric Joyner /* Enable power to the phy. */ 116279b36ec9SKevin Bowling ixgbe_set_phy_power(hw, true); 11638eb6488eSEric Joyner 1164b1d5caf3SKevin Bowling ixgbe_initialize_iov(sc); 1165c19c7afeSEric Joyner 1166c19c7afeSEric Joyner error = ixgbe_setup_interface(ctx); 1167c19c7afeSEric Joyner if (error) { 1168c19c7afeSEric Joyner device_printf(dev, "Interface setup failed: %d\n", error); 1169c19c7afeSEric Joyner goto err; 1170c19c7afeSEric Joyner } 1171c19c7afeSEric Joyner 1172c19c7afeSEric Joyner ixgbe_if_update_admin_status(ctx); 1173c19c7afeSEric Joyner 11748eb6488eSEric Joyner /* Initialize statistics */ 1175b1d5caf3SKevin Bowling ixgbe_update_stats_counters(sc); 1176b1d5caf3SKevin Bowling ixgbe_add_hw_stats(sc); 11778eb6488eSEric Joyner 11788eb6488eSEric Joyner /* Check PCIE slot type/speed/width */ 1179b1d5caf3SKevin Bowling ixgbe_get_slot_info(sc); 1180758cc3dcSJack F Vogel 1181758cc3dcSJack F Vogel /* 11828eb6488eSEric Joyner * Do time init and sysctl init here, but 1183b1d5caf3SKevin Bowling * only on the first port of a bypass sc. 1184758cc3dcSJack F Vogel */ 1185b1d5caf3SKevin Bowling ixgbe_bypass_init(sc); 1186758cc3dcSJack F Vogel 11877660e4eaSKevin Bowling /* Display NVM and Option ROM versions */ 11887660e4eaSKevin Bowling ixgbe_print_fw_version(ctx); 11897660e4eaSKevin Bowling 11908eb6488eSEric Joyner /* Set an initial dmac value */ 1191b1d5caf3SKevin Bowling sc->dmac = 0; 11928eb6488eSEric Joyner /* Set initial advertised speeds (if applicable) */ 1193d381c807SPiotr Pietruszewski sc->advertise = ixgbe_get_default_advertise(sc); 1194758cc3dcSJack F Vogel 1195b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_SRIOV) 11968eb6488eSEric Joyner ixgbe_define_iov_schemas(dev, &error); 1197758cc3dcSJack F Vogel 11988eb6488eSEric Joyner /* Add sysctls */ 1199c19c7afeSEric Joyner ixgbe_add_device_sysctls(ctx); 1200758cc3dcSJack F Vogel 1201f72de14eSKevin Bowling /* Init recovery mode timer and state variable */ 1202f72de14eSKevin Bowling if (sc->feat_en & IXGBE_FEATURE_RECOVERY_MODE) { 1203f72de14eSKevin Bowling sc->recovery_mode = 0; 1204f72de14eSKevin Bowling 1205f72de14eSKevin Bowling /* Set up the timer callout */ 1206f72de14eSKevin Bowling callout_init(&sc->fw_mode_timer, true); 1207f72de14eSKevin Bowling 1208f72de14eSKevin Bowling /* Start the task */ 1209a924b5eeSKevin Bowling callout_reset(&sc->fw_mode_timer, hz, ixgbe_fw_mode_timer, sc); 1210f72de14eSKevin Bowling } 1211f72de14eSKevin Bowling 12128eb6488eSEric Joyner return (0); 1213c19c7afeSEric Joyner err: 12148eb6488eSEric Joyner return (error); 1215c19c7afeSEric Joyner } /* ixgbe_if_attach_post */ 12168eb6488eSEric Joyner 12178eb6488eSEric Joyner /************************************************************************ 12188eb6488eSEric Joyner * ixgbe_check_wol_support 12196f37f232SEric Joyner * 12206f37f232SEric Joyner * Checks whether the adapter's ports are capable of 12216f37f232SEric Joyner * Wake On LAN by reading the adapter's NVM. 12226f37f232SEric Joyner * 12236f37f232SEric Joyner * Sets each port's hw->wol_enabled value depending 12246f37f232SEric Joyner * on the value read here. 12258eb6488eSEric Joyner ************************************************************************/ 12266f37f232SEric Joyner static void 1227b1d5caf3SKevin Bowling ixgbe_check_wol_support(struct ixgbe_softc *sc) 12286f37f232SEric Joyner { 1229b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 12306f37f232SEric Joyner u16 dev_caps = 0; 12316f37f232SEric Joyner 12326f37f232SEric Joyner /* Find out WoL support for port */ 1233b1d5caf3SKevin Bowling sc->wol_support = hw->wol_enabled = 0; 12346f37f232SEric Joyner ixgbe_get_device_caps(hw, &dev_caps); 12356f37f232SEric Joyner if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) || 12366f37f232SEric Joyner ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) && 12376f37f232SEric Joyner hw->bus.func == 0)) 1238b1d5caf3SKevin Bowling sc->wol_support = hw->wol_enabled = 1; 12396f37f232SEric Joyner 12406f37f232SEric Joyner /* Save initial wake up filter configuration */ 1241b1d5caf3SKevin Bowling sc->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC); 12426f37f232SEric Joyner 12436f37f232SEric Joyner return; 12448eb6488eSEric Joyner } /* ixgbe_check_wol_support */ 12456f37f232SEric Joyner 12468eb6488eSEric Joyner /************************************************************************ 12478eb6488eSEric Joyner * ixgbe_setup_interface 12488eb6488eSEric Joyner * 12498eb6488eSEric Joyner * Setup networking device structure and register an interface. 12508eb6488eSEric Joyner ************************************************************************/ 12516f37f232SEric Joyner static int 1252c19c7afeSEric Joyner ixgbe_setup_interface(if_ctx_t ctx) 12536f37f232SEric Joyner { 1254ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 1255b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 12566f37f232SEric Joyner 12578eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_setup_interface: begin"); 12586f37f232SEric Joyner 1259c19c7afeSEric Joyner if_setbaudrate(ifp, IF_Gbps(10)); 12606f37f232SEric Joyner 1261ff06a8dbSJustin Hibbits sc->max_frame_size = if_getmtu(ifp) + ETHER_HDR_LEN + ETHER_CRC_LEN; 1262758cc3dcSJack F Vogel 1263b1d5caf3SKevin Bowling sc->phy_layer = ixgbe_get_supported_physical_layer(&sc->hw); 12648eb6488eSEric Joyner 1265c19c7afeSEric Joyner ixgbe_add_media_types(ctx); 1266c19c7afeSEric Joyner 1267c19c7afeSEric Joyner /* Autoselect media by default */ 1268b1d5caf3SKevin Bowling ifmedia_set(sc->media, IFM_ETHER | IFM_AUTO); 12698eb6488eSEric Joyner 12708eb6488eSEric Joyner return (0); 12718eb6488eSEric Joyner } /* ixgbe_setup_interface */ 1272758cc3dcSJack F Vogel 12738eb6488eSEric Joyner /************************************************************************ 1274c19c7afeSEric Joyner * ixgbe_if_get_counter 12758eb6488eSEric Joyner ************************************************************************/ 1276758cc3dcSJack F Vogel static uint64_t 1277c19c7afeSEric Joyner ixgbe_if_get_counter(if_ctx_t ctx, ift_counter cnt) 1278758cc3dcSJack F Vogel { 1279b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 1280c19c7afeSEric Joyner if_t ifp = iflib_get_ifp(ctx); 1281758cc3dcSJack F Vogel 1282758cc3dcSJack F Vogel switch (cnt) { 1283758cc3dcSJack F Vogel case IFCOUNTER_IPACKETS: 1284b1d5caf3SKevin Bowling return (sc->ipackets); 1285758cc3dcSJack F Vogel case IFCOUNTER_OPACKETS: 1286b1d5caf3SKevin Bowling return (sc->opackets); 1287758cc3dcSJack F Vogel case IFCOUNTER_IBYTES: 1288b1d5caf3SKevin Bowling return (sc->ibytes); 1289758cc3dcSJack F Vogel case IFCOUNTER_OBYTES: 1290b1d5caf3SKevin Bowling return (sc->obytes); 1291758cc3dcSJack F Vogel case IFCOUNTER_IMCASTS: 1292b1d5caf3SKevin Bowling return (sc->imcasts); 1293758cc3dcSJack F Vogel case IFCOUNTER_OMCASTS: 1294b1d5caf3SKevin Bowling return (sc->omcasts); 1295758cc3dcSJack F Vogel case IFCOUNTER_COLLISIONS: 1296758cc3dcSJack F Vogel return (0); 1297758cc3dcSJack F Vogel case IFCOUNTER_IQDROPS: 1298b1d5caf3SKevin Bowling return (sc->iqdrops); 1299625d12c6SJohn Baldwin case IFCOUNTER_OQDROPS: 1300c19c7afeSEric Joyner return (0); 1301758cc3dcSJack F Vogel case IFCOUNTER_IERRORS: 1302b1d5caf3SKevin Bowling return (sc->ierrors); 1303758cc3dcSJack F Vogel default: 1304758cc3dcSJack F Vogel return (if_get_counter_default(ifp, cnt)); 1305758cc3dcSJack F Vogel } 1306c19c7afeSEric Joyner } /* ixgbe_if_get_counter */ 1307758cc3dcSJack F Vogel 13088eb6488eSEric Joyner /************************************************************************ 1309bca38080SAndrew Gallatin * ixgbe_if_i2c_req 1310bca38080SAndrew Gallatin ************************************************************************/ 1311bca38080SAndrew Gallatin static int 1312bca38080SAndrew Gallatin ixgbe_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req) 1313bca38080SAndrew Gallatin { 1314b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 1315b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 1316bca38080SAndrew Gallatin int i; 1317bca38080SAndrew Gallatin 1318bca38080SAndrew Gallatin if (hw->phy.ops.read_i2c_byte == NULL) 1319bca38080SAndrew Gallatin return (ENXIO); 1320bca38080SAndrew Gallatin for (i = 0; i < req->len; i++) 1321bca38080SAndrew Gallatin hw->phy.ops.read_i2c_byte(hw, req->offset + i, 1322bca38080SAndrew Gallatin req->dev_addr, &req->data[i]); 1323bca38080SAndrew Gallatin return (0); 1324bca38080SAndrew Gallatin } /* ixgbe_if_i2c_req */ 1325bca38080SAndrew Gallatin 1326*c58d34ddSKevin Bowling /* ixgbe_if_needs_restart - Tell iflib when the driver needs to be 1327*c58d34ddSKevin Bowling * reinitialized 1328cf150917SEric Joyner * @ctx: iflib context 1329cf150917SEric Joyner * @event: event code to check 1330cf150917SEric Joyner * 1331725e4008SKevin Bowling * Defaults to returning false for unknown events. 1332cf150917SEric Joyner * 1333cf150917SEric Joyner * @returns true if iflib needs to reinit the interface 1334cf150917SEric Joyner */ 1335cf150917SEric Joyner static bool 1336cf150917SEric Joyner ixgbe_if_needs_restart(if_ctx_t ctx __unused, enum iflib_restart_event event) 1337cf150917SEric Joyner { 1338cf150917SEric Joyner switch (event) { 1339cf150917SEric Joyner case IFLIB_RESTART_VLAN_CONFIG: 1340cf150917SEric Joyner default: 1341725e4008SKevin Bowling return (false); 1342cf150917SEric Joyner } 1343cf150917SEric Joyner } 1344cf150917SEric Joyner 1345bca38080SAndrew Gallatin /************************************************************************ 13468eb6488eSEric Joyner * ixgbe_add_media_types 13478eb6488eSEric Joyner ************************************************************************/ 13488eb6488eSEric Joyner static void 1349c19c7afeSEric Joyner ixgbe_add_media_types(if_ctx_t ctx) 13508eb6488eSEric Joyner { 1351b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 1352b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 1353c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 13548eb6488eSEric Joyner u64 layer; 13558eb6488eSEric Joyner 1356b1d5caf3SKevin Bowling layer = sc->phy_layer = ixgbe_get_supported_physical_layer(hw); 13578eb6488eSEric Joyner 13588eb6488eSEric Joyner /* Media types with matching FreeBSD media defines */ 13598eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) 1360b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_T, 0, NULL); 13618eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) 1362b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_T, 0, NULL); 13638eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) 1364b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_100_TX, 0, NULL); 13658eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T) 1366b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10_T, 0, NULL); 13678eb6488eSEric Joyner 1368d381c807SPiotr Pietruszewski if (hw->mac.type == ixgbe_mac_X550) { 1369d381c807SPiotr Pietruszewski ifmedia_add(sc->media, IFM_ETHER | IFM_2500_T, 0, NULL); 1370d381c807SPiotr Pietruszewski ifmedia_add(sc->media, IFM_ETHER | IFM_5000_T, 0, NULL); 1371d381c807SPiotr Pietruszewski } 1372d381c807SPiotr Pietruszewski 13738eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || 137448ddd1b9SKevin Bowling layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) { 1375b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_TWINAX, 0, 13768eb6488eSEric Joyner NULL); 137748ddd1b9SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_KX, 0, NULL); 137848ddd1b9SKevin Bowling } 13798eb6488eSEric Joyner 13808eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) { 1381b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_LR, 0, NULL); 13828eb6488eSEric Joyner if (hw->phy.multispeed_fiber) 1383b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_LX, 0, 13848eb6488eSEric Joyner NULL); 13858eb6488eSEric Joyner } 13868eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) { 1387b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_SR, 0, NULL); 13888eb6488eSEric Joyner if (hw->phy.multispeed_fiber) 1389b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_SX, 0, 13908eb6488eSEric Joyner NULL); 13918eb6488eSEric Joyner } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) 1392b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_SX, 0, NULL); 13938eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) 1394b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); 13958eb6488eSEric Joyner 13968eb6488eSEric Joyner #ifdef IFM_ETH_XTYPE 13978eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 1398b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_KR, 0, NULL); 13998eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) 1400b1d5caf3SKevin Bowling ifmedia_add( sc->media, IFM_ETHER | IFM_10G_KX4, 0, NULL); 14018eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 1402b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_KX, 0, NULL); 14038eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) 1404b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_2500_KX, 0, NULL); 14058eb6488eSEric Joyner #else 14068eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) { 14078eb6488eSEric Joyner device_printf(dev, "Media supported: 10GbaseKR\n"); 14088eb6488eSEric Joyner device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n"); 1409b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_SR, 0, NULL); 14108eb6488eSEric Joyner } 14118eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) { 14128eb6488eSEric Joyner device_printf(dev, "Media supported: 10GbaseKX4\n"); 14138eb6488eSEric Joyner device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n"); 1414b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); 14158eb6488eSEric Joyner } 14168eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) { 14178eb6488eSEric Joyner device_printf(dev, "Media supported: 1000baseKX\n"); 14188eb6488eSEric Joyner device_printf(dev, "1000baseKX mapped to 1000baseCX\n"); 1419b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_CX, 0, NULL); 14208eb6488eSEric Joyner } 14218eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) { 14228eb6488eSEric Joyner device_printf(dev, "Media supported: 2500baseKX\n"); 14238eb6488eSEric Joyner device_printf(dev, "2500baseKX mapped to 2500baseSX\n"); 1424b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_2500_SX, 0, NULL); 14258eb6488eSEric Joyner } 14268eb6488eSEric Joyner #endif 14278eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) 14288eb6488eSEric Joyner device_printf(dev, "Media supported: 1000baseBX\n"); 14298eb6488eSEric Joyner 14308eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_82598AT) { 1431b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 14328eb6488eSEric Joyner 0, NULL); 1433b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_T, 0, NULL); 14348eb6488eSEric Joyner } 14358eb6488eSEric Joyner 1436b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); 14378eb6488eSEric Joyner } /* ixgbe_add_media_types */ 14388eb6488eSEric Joyner 14398eb6488eSEric Joyner /************************************************************************ 14408eb6488eSEric Joyner * ixgbe_is_sfp 14418eb6488eSEric Joyner ************************************************************************/ 14428eb6488eSEric Joyner static inline bool 14438eb6488eSEric Joyner ixgbe_is_sfp(struct ixgbe_hw *hw) 14448eb6488eSEric Joyner { 14458eb6488eSEric Joyner switch (hw->mac.type) { 14468eb6488eSEric Joyner case ixgbe_mac_82598EB: 14478eb6488eSEric Joyner if (hw->phy.type == ixgbe_phy_nl) 144879b36ec9SKevin Bowling return (true); 144979b36ec9SKevin Bowling return (false); 14508eb6488eSEric Joyner case ixgbe_mac_82599EB: 14518eb6488eSEric Joyner switch (hw->mac.ops.get_media_type(hw)) { 14528eb6488eSEric Joyner case ixgbe_media_type_fiber: 14538eb6488eSEric Joyner case ixgbe_media_type_fiber_qsfp: 145479b36ec9SKevin Bowling return (true); 14558eb6488eSEric Joyner default: 145679b36ec9SKevin Bowling return (false); 14578eb6488eSEric Joyner } 14588eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 14598eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 14608eb6488eSEric Joyner if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) 146179b36ec9SKevin Bowling return (true); 146279b36ec9SKevin Bowling return (false); 14638eb6488eSEric Joyner default: 146479b36ec9SKevin Bowling return (false); 14658eb6488eSEric Joyner } 14668eb6488eSEric Joyner } /* ixgbe_is_sfp */ 14678eb6488eSEric Joyner 14688eb6488eSEric Joyner /************************************************************************ 14698eb6488eSEric Joyner * ixgbe_config_link 14708eb6488eSEric Joyner ************************************************************************/ 14718eb6488eSEric Joyner static void 1472b2c1e8e6SEric Joyner ixgbe_config_link(if_ctx_t ctx) 14738eb6488eSEric Joyner { 1474b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 1475b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 14768eb6488eSEric Joyner u32 autoneg, err = 0; 14778eb6488eSEric Joyner bool sfp, negotiate; 14788eb6488eSEric Joyner 14798eb6488eSEric Joyner sfp = ixgbe_is_sfp(hw); 14808eb6488eSEric Joyner 14818eb6488eSEric Joyner if (sfp) { 1482b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MOD; 1483b2c1e8e6SEric Joyner iflib_admin_intr_deferred(ctx); 14848eb6488eSEric Joyner } else { 14858eb6488eSEric Joyner if (hw->mac.ops.check_link) 1486b1d5caf3SKevin Bowling err = ixgbe_check_link(hw, &sc->link_speed, 1487b1d5caf3SKevin Bowling &sc->link_up, false); 14888eb6488eSEric Joyner if (err) 1489c19c7afeSEric Joyner return; 14908eb6488eSEric Joyner autoneg = hw->phy.autoneg_advertised; 14918eb6488eSEric Joyner if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) 14928eb6488eSEric Joyner err = hw->mac.ops.get_link_capabilities(hw, &autoneg, 14938eb6488eSEric Joyner &negotiate); 14948eb6488eSEric Joyner if (err) 1495c19c7afeSEric Joyner return; 1496d381c807SPiotr Pietruszewski 1497d381c807SPiotr Pietruszewski if (hw->mac.type == ixgbe_mac_X550 && 1498d381c807SPiotr Pietruszewski hw->phy.autoneg_advertised == 0) { 1499d381c807SPiotr Pietruszewski /* 1500d381c807SPiotr Pietruszewski * 2.5G and 5G autonegotiation speeds on X550 1501d381c807SPiotr Pietruszewski * are disabled by default due to reported 1502d381c807SPiotr Pietruszewski * interoperability issues with some switches. 1503d381c807SPiotr Pietruszewski * 1504d381c807SPiotr Pietruszewski * The second condition checks if any operations 1505d381c807SPiotr Pietruszewski * involving setting autonegotiation speeds have 1506d381c807SPiotr Pietruszewski * been performed prior to this ixgbe_config_link() 1507d381c807SPiotr Pietruszewski * call. 1508d381c807SPiotr Pietruszewski * 1509d381c807SPiotr Pietruszewski * If hw->phy.autoneg_advertised does not 1510d381c807SPiotr Pietruszewski * equal 0, this means that the user might have 1511d381c807SPiotr Pietruszewski * set autonegotiation speeds via the sysctl 1512d381c807SPiotr Pietruszewski * before bringing the interface up. In this 1513d381c807SPiotr Pietruszewski * case, we should not disable 2.5G and 5G 1514d381c807SPiotr Pietruszewski * since that speeds might be selected by the 1515d381c807SPiotr Pietruszewski * user. 1516d381c807SPiotr Pietruszewski * 1517d381c807SPiotr Pietruszewski * Otherwise (i.e. if hw->phy.autoneg_advertised 1518d381c807SPiotr Pietruszewski * is set to 0), it is the first time we set 1519d381c807SPiotr Pietruszewski * autonegotiation preferences and the default 1520d381c807SPiotr Pietruszewski * set of speeds should exclude 2.5G and 5G. 1521d381c807SPiotr Pietruszewski */ 1522d381c807SPiotr Pietruszewski autoneg &= ~(IXGBE_LINK_SPEED_2_5GB_FULL | 1523d381c807SPiotr Pietruszewski IXGBE_LINK_SPEED_5GB_FULL); 1524d381c807SPiotr Pietruszewski } 1525d381c807SPiotr Pietruszewski 15268eb6488eSEric Joyner if (hw->mac.ops.setup_link) 15278eb6488eSEric Joyner err = hw->mac.ops.setup_link(hw, autoneg, 1528b1d5caf3SKevin Bowling sc->link_up); 15298eb6488eSEric Joyner } 15308eb6488eSEric Joyner } /* ixgbe_config_link */ 15318eb6488eSEric Joyner 15328eb6488eSEric Joyner /************************************************************************ 15338eb6488eSEric Joyner * ixgbe_update_stats_counters - Update board statistics counters. 15348eb6488eSEric Joyner ************************************************************************/ 15358eb6488eSEric Joyner static void 1536b1d5caf3SKevin Bowling ixgbe_update_stats_counters(struct ixgbe_softc *sc) 15378eb6488eSEric Joyner { 1538b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 1539b1d5caf3SKevin Bowling struct ixgbe_hw_stats *stats = &sc->stats.pf; 15408eb6488eSEric Joyner u32 missed_rx = 0, bprc, lxon, lxoff, total; 1541e37d3dc1SEric Joyner u32 lxoffrxc; 15428eb6488eSEric Joyner u64 total_missed_rx = 0; 15438eb6488eSEric Joyner 15448eb6488eSEric Joyner stats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); 15458eb6488eSEric Joyner stats->illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC); 15468eb6488eSEric Joyner stats->errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC); 15478eb6488eSEric Joyner stats->mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC); 15488eb6488eSEric Joyner stats->mpc[0] += IXGBE_READ_REG(hw, IXGBE_MPC(0)); 15498eb6488eSEric Joyner 15508eb6488eSEric Joyner for (int i = 0; i < 16; i++) { 15518eb6488eSEric Joyner stats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 15528eb6488eSEric Joyner stats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 15538eb6488eSEric Joyner stats->qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); 15548eb6488eSEric Joyner } 15558eb6488eSEric Joyner stats->mlfc += IXGBE_READ_REG(hw, IXGBE_MLFC); 15568eb6488eSEric Joyner stats->mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC); 15578eb6488eSEric Joyner stats->rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); 15588eb6488eSEric Joyner 15598eb6488eSEric Joyner /* Hardware workaround, gprc counts missed packets */ 15608eb6488eSEric Joyner stats->gprc += IXGBE_READ_REG(hw, IXGBE_GPRC); 15618eb6488eSEric Joyner stats->gprc -= missed_rx; 15628eb6488eSEric Joyner 15638eb6488eSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) { 15648eb6488eSEric Joyner stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL) + 15658eb6488eSEric Joyner ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32); 15668eb6488eSEric Joyner stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL) + 15678eb6488eSEric Joyner ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32); 15688eb6488eSEric Joyner stats->tor += IXGBE_READ_REG(hw, IXGBE_TORL) + 15698eb6488eSEric Joyner ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32); 15708eb6488eSEric Joyner stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 1571e37d3dc1SEric Joyner lxoffrxc = IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 1572e37d3dc1SEric Joyner stats->lxoffrxc += lxoffrxc; 15738eb6488eSEric Joyner } else { 15748eb6488eSEric Joyner stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); 1575e37d3dc1SEric Joyner lxoffrxc = IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 1576e37d3dc1SEric Joyner stats->lxoffrxc += lxoffrxc; 15778eb6488eSEric Joyner /* 82598 only has a counter in the high register */ 15788eb6488eSEric Joyner stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); 15798eb6488eSEric Joyner stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); 15808eb6488eSEric Joyner stats->tor += IXGBE_READ_REG(hw, IXGBE_TORH); 15818eb6488eSEric Joyner } 15828eb6488eSEric Joyner 15838eb6488eSEric Joyner /* 1584e37d3dc1SEric Joyner * For watchdog management we need to know if we have been paused 1585e37d3dc1SEric Joyner * during the last interval, so capture that here. 1586e37d3dc1SEric Joyner */ 1587e37d3dc1SEric Joyner if (lxoffrxc) 1588b1d5caf3SKevin Bowling sc->shared->isc_pause_frames = 1; 1589e37d3dc1SEric Joyner 1590e37d3dc1SEric Joyner /* 15918eb6488eSEric Joyner * Workaround: mprc hardware is incorrectly counting 15928eb6488eSEric Joyner * broadcasts, so for now we subtract those. 1593758cc3dcSJack F Vogel */ 15948eb6488eSEric Joyner bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); 15958eb6488eSEric Joyner stats->bprc += bprc; 15968eb6488eSEric Joyner stats->mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); 15978eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 15988eb6488eSEric Joyner stats->mprc -= bprc; 15998eb6488eSEric Joyner 16008eb6488eSEric Joyner stats->prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64); 16018eb6488eSEric Joyner stats->prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127); 16028eb6488eSEric Joyner stats->prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255); 16038eb6488eSEric Joyner stats->prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511); 16048eb6488eSEric Joyner stats->prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023); 16058eb6488eSEric Joyner stats->prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522); 16068eb6488eSEric Joyner 16078eb6488eSEric Joyner lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC); 16088eb6488eSEric Joyner stats->lxontxc += lxon; 16098eb6488eSEric Joyner lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 16108eb6488eSEric Joyner stats->lxofftxc += lxoff; 16118eb6488eSEric Joyner total = lxon + lxoff; 16128eb6488eSEric Joyner 16138eb6488eSEric Joyner stats->gptc += IXGBE_READ_REG(hw, IXGBE_GPTC); 16148eb6488eSEric Joyner stats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC); 16158eb6488eSEric Joyner stats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64); 16168eb6488eSEric Joyner stats->gptc -= total; 16178eb6488eSEric Joyner stats->mptc -= total; 16188eb6488eSEric Joyner stats->ptc64 -= total; 16198eb6488eSEric Joyner stats->gotc -= total * ETHER_MIN_LEN; 16208eb6488eSEric Joyner 16218eb6488eSEric Joyner stats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC); 16228eb6488eSEric Joyner stats->rfc += IXGBE_READ_REG(hw, IXGBE_RFC); 16238eb6488eSEric Joyner stats->roc += IXGBE_READ_REG(hw, IXGBE_ROC); 16248eb6488eSEric Joyner stats->rjc += IXGBE_READ_REG(hw, IXGBE_RJC); 16258eb6488eSEric Joyner stats->mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC); 16268eb6488eSEric Joyner stats->mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC); 16278eb6488eSEric Joyner stats->mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC); 16288eb6488eSEric Joyner stats->tpr += IXGBE_READ_REG(hw, IXGBE_TPR); 16298eb6488eSEric Joyner stats->tpt += IXGBE_READ_REG(hw, IXGBE_TPT); 16308eb6488eSEric Joyner stats->ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127); 16318eb6488eSEric Joyner stats->ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255); 16328eb6488eSEric Joyner stats->ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511); 16338eb6488eSEric Joyner stats->ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023); 16348eb6488eSEric Joyner stats->ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522); 16358eb6488eSEric Joyner stats->bptc += IXGBE_READ_REG(hw, IXGBE_BPTC); 16368eb6488eSEric Joyner stats->xec += IXGBE_READ_REG(hw, IXGBE_XEC); 16378eb6488eSEric Joyner stats->fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC); 16388eb6488eSEric Joyner stats->fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST); 16398eb6488eSEric Joyner /* Only read FCOE on 82599 */ 16408eb6488eSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) { 16418eb6488eSEric Joyner stats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC); 16428eb6488eSEric Joyner stats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC); 16438eb6488eSEric Joyner stats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC); 16448eb6488eSEric Joyner stats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC); 16458eb6488eSEric Joyner stats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC); 16468eb6488eSEric Joyner } 16478eb6488eSEric Joyner 16488eb6488eSEric Joyner /* Fill out the OS statistics structure */ 1649b1d5caf3SKevin Bowling IXGBE_SET_IPACKETS(sc, stats->gprc); 1650b1d5caf3SKevin Bowling IXGBE_SET_OPACKETS(sc, stats->gptc); 1651b1d5caf3SKevin Bowling IXGBE_SET_IBYTES(sc, stats->gorc); 1652b1d5caf3SKevin Bowling IXGBE_SET_OBYTES(sc, stats->gotc); 1653b1d5caf3SKevin Bowling IXGBE_SET_IMCASTS(sc, stats->mprc); 1654b1d5caf3SKevin Bowling IXGBE_SET_OMCASTS(sc, stats->mptc); 1655b1d5caf3SKevin Bowling IXGBE_SET_COLLISIONS(sc, 0); 1656b1d5caf3SKevin Bowling IXGBE_SET_IQDROPS(sc, total_missed_rx); 1657afb1aa4eSPiotr Pietruszewski 1658afb1aa4eSPiotr Pietruszewski /* 1659afb1aa4eSPiotr Pietruszewski * Aggregate following types of errors as RX errors: 1660afb1aa4eSPiotr Pietruszewski * - CRC error count, 1661afb1aa4eSPiotr Pietruszewski * - illegal byte error count, 1662afb1aa4eSPiotr Pietruszewski * - missed packets count, 1663afb1aa4eSPiotr Pietruszewski * - length error count, 1664afb1aa4eSPiotr Pietruszewski * - undersized packets count, 1665afb1aa4eSPiotr Pietruszewski * - fragmented packets count, 1666afb1aa4eSPiotr Pietruszewski * - oversized packets count, 1667afb1aa4eSPiotr Pietruszewski * - jabber count. 1668afb1aa4eSPiotr Pietruszewski */ 16698526120aSAndrey V. Elsukov IXGBE_SET_IERRORS(sc, stats->crcerrs + stats->illerrc + 1670*c58d34ddSKevin Bowling stats->mpc[0] + stats->rlec + stats->ruc + stats->rfc + 1671*c58d34ddSKevin Bowling stats->roc + stats->rjc); 16728eb6488eSEric Joyner } /* ixgbe_update_stats_counters */ 16738eb6488eSEric Joyner 16748eb6488eSEric Joyner /************************************************************************ 16758eb6488eSEric Joyner * ixgbe_add_hw_stats 16768eb6488eSEric Joyner * 16778eb6488eSEric Joyner * Add sysctl variables, one per statistic, to the system. 16788eb6488eSEric Joyner ************************************************************************/ 16798eb6488eSEric Joyner static void 1680b1d5caf3SKevin Bowling ixgbe_add_hw_stats(struct ixgbe_softc *sc) 16818eb6488eSEric Joyner { 1682b1d5caf3SKevin Bowling device_t dev = iflib_get_dev(sc->ctx); 1683c19c7afeSEric Joyner struct ix_rx_queue *rx_que; 1684c19c7afeSEric Joyner struct ix_tx_queue *tx_que; 16858eb6488eSEric Joyner struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 16868eb6488eSEric Joyner struct sysctl_oid *tree = device_get_sysctl_tree(dev); 16878eb6488eSEric Joyner struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); 1688b1d5caf3SKevin Bowling struct ixgbe_hw_stats *stats = &sc->stats.pf; 16898eb6488eSEric Joyner struct sysctl_oid *stat_node, *queue_node; 16908eb6488eSEric Joyner struct sysctl_oid_list *stat_list, *queue_list; 1691c19c7afeSEric Joyner int i; 16928eb6488eSEric Joyner 16938eb6488eSEric Joyner #define QUEUE_NAME_LEN 32 16948eb6488eSEric Joyner char namebuf[QUEUE_NAME_LEN]; 16958eb6488eSEric Joyner 16968eb6488eSEric Joyner /* Driver Statistics */ 16978eb6488eSEric Joyner SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", 1698b1d5caf3SKevin Bowling CTLFLAG_RD, &sc->dropped_pkts, "Driver dropped packets"); 16998eb6488eSEric Joyner SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events", 1700b1d5caf3SKevin Bowling CTLFLAG_RD, &sc->watchdog_events, "Watchdog timeouts"); 17018eb6488eSEric Joyner SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq", 1702b1d5caf3SKevin Bowling CTLFLAG_RD, &sc->link_irq, "Link MSI-X IRQ Handled"); 17038eb6488eSEric Joyner 1704*c58d34ddSKevin Bowling for (i = 0, tx_que = sc->tx_queues; i < sc->num_tx_queues; 1705*c58d34ddSKevin Bowling i++, tx_que++) { 1706c19c7afeSEric Joyner struct tx_ring *txr = &tx_que->txr; 17078eb6488eSEric Joyner snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); 17088eb6488eSEric Joyner queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, 170920b91f0aSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name"); 17108eb6488eSEric Joyner queue_list = SYSCTL_CHILDREN(queue_node); 17118eb6488eSEric Joyner 17128eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head", 1713f72de14eSKevin Bowling CTLTYPE_UINT | CTLFLAG_RD, txr, 0, 1714*c58d34ddSKevin Bowling ixgbe_sysctl_tdh_handler, "IU", 1715*c58d34ddSKevin Bowling "Transmit Descriptor Head"); 17168eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail", 1717f72de14eSKevin Bowling CTLTYPE_UINT | CTLFLAG_RD, txr, 0, 1718*c58d34ddSKevin Bowling ixgbe_sysctl_tdt_handler, "IU", 1719*c58d34ddSKevin Bowling "Transmit Descriptor Tail"); 17208eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx", 17218eb6488eSEric Joyner CTLFLAG_RD, &txr->tso_tx, "TSO"); 17228eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets", 17238eb6488eSEric Joyner CTLFLAG_RD, &txr->total_packets, 17248eb6488eSEric Joyner "Queue Packets Transmitted"); 17258eb6488eSEric Joyner } 17268eb6488eSEric Joyner 1727*c58d34ddSKevin Bowling for (i = 0, rx_que = sc->rx_queues; i < sc->num_rx_queues; 1728*c58d34ddSKevin Bowling i++, rx_que++) { 1729c19c7afeSEric Joyner struct rx_ring *rxr = &rx_que->rxr; 17308eb6488eSEric Joyner snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); 17318eb6488eSEric Joyner queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, 173220b91f0aSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name"); 17338eb6488eSEric Joyner queue_list = SYSCTL_CHILDREN(queue_node); 17348eb6488eSEric Joyner 1735c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate", 1736f72de14eSKevin Bowling CTLTYPE_UINT | CTLFLAG_RW, 1737b1d5caf3SKevin Bowling &sc->rx_queues[i], 0, 1738c19c7afeSEric Joyner ixgbe_sysctl_interrupt_rate_handler, "IU", 1739c19c7afeSEric Joyner "Interrupt Rate"); 1740c19c7afeSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs", 1741b1d5caf3SKevin Bowling CTLFLAG_RD, &(sc->rx_queues[i].irqs), 1742c19c7afeSEric Joyner "irqs on this queue"); 17438eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head", 1744f72de14eSKevin Bowling CTLTYPE_UINT | CTLFLAG_RD, rxr, 0, 1745*c58d34ddSKevin Bowling ixgbe_sysctl_rdh_handler, "IU", 1746*c58d34ddSKevin Bowling "Receive Descriptor Head"); 17478eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail", 1748f72de14eSKevin Bowling CTLTYPE_UINT | CTLFLAG_RD, rxr, 0, 1749*c58d34ddSKevin Bowling ixgbe_sysctl_rdt_handler, "IU", 1750*c58d34ddSKevin Bowling "Receive Descriptor Tail"); 17518eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets", 17528eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_packets, "Queue Packets Received"); 17538eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes", 17548eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_bytes, "Queue Bytes Received"); 17558eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_copies", 17568eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_copies, "Copied RX Frames"); 17578eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_discarded", 17588eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_discarded, "Discarded RX packets"); 17598eb6488eSEric Joyner } 17608eb6488eSEric Joyner 17618eb6488eSEric Joyner /* MAC stats get their own sub node */ 17628eb6488eSEric Joyner stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats", 176320b91f0aSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "MAC Statistics"); 17648eb6488eSEric Joyner stat_list = SYSCTL_CHILDREN(stat_node); 17658eb6488eSEric Joyner 1766afb1aa4eSPiotr Pietruszewski SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_errs", 1767b1d5caf3SKevin Bowling CTLFLAG_RD, &sc->ierrors, IXGBE_SYSCTL_DESC_RX_ERRS); 17688eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs", 17698eb6488eSEric Joyner CTLFLAG_RD, &stats->crcerrs, "CRC Errors"); 17708eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ill_errs", 17718eb6488eSEric Joyner CTLFLAG_RD, &stats->illerrc, "Illegal Byte Errors"); 17728eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "byte_errs", 17738eb6488eSEric Joyner CTLFLAG_RD, &stats->errbc, "Byte Errors"); 17748eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "short_discards", 17758eb6488eSEric Joyner CTLFLAG_RD, &stats->mspdc, "MAC Short Packets Discarded"); 17768eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "local_faults", 17778eb6488eSEric Joyner CTLFLAG_RD, &stats->mlfc, "MAC Local Faults"); 17788eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "remote_faults", 17798eb6488eSEric Joyner CTLFLAG_RD, &stats->mrfc, "MAC Remote Faults"); 17808eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rec_len_errs", 17818eb6488eSEric Joyner CTLFLAG_RD, &stats->rlec, "Receive Length Errors"); 17828eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_missed_packets", 17838eb6488eSEric Joyner CTLFLAG_RD, &stats->mpc[0], "RX Missed Packet Count"); 17848eb6488eSEric Joyner 17858eb6488eSEric Joyner /* Flow Control stats */ 17868eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd", 17878eb6488eSEric Joyner CTLFLAG_RD, &stats->lxontxc, "Link XON Transmitted"); 17888eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd", 17898eb6488eSEric Joyner CTLFLAG_RD, &stats->lxonrxc, "Link XON Received"); 17908eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd", 17918eb6488eSEric Joyner CTLFLAG_RD, &stats->lxofftxc, "Link XOFF Transmitted"); 17928eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd", 17938eb6488eSEric Joyner CTLFLAG_RD, &stats->lxoffrxc, "Link XOFF Received"); 17948eb6488eSEric Joyner 17958eb6488eSEric Joyner /* Packet Reception Stats */ 17968eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_octets_rcvd", 17978eb6488eSEric Joyner CTLFLAG_RD, &stats->tor, "Total Octets Received"); 17988eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd", 17998eb6488eSEric Joyner CTLFLAG_RD, &stats->gorc, "Good Octets Received"); 18008eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_rcvd", 18018eb6488eSEric Joyner CTLFLAG_RD, &stats->tpr, "Total Packets Received"); 18028eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd", 18038eb6488eSEric Joyner CTLFLAG_RD, &stats->gprc, "Good Packets Received"); 18048eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd", 18058eb6488eSEric Joyner CTLFLAG_RD, &stats->mprc, "Multicast Packets Received"); 18068eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_rcvd", 18078eb6488eSEric Joyner CTLFLAG_RD, &stats->bprc, "Broadcast Packets Received"); 18088eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64", 18098eb6488eSEric Joyner CTLFLAG_RD, &stats->prc64, "64 byte frames received "); 18108eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127", 18118eb6488eSEric Joyner CTLFLAG_RD, &stats->prc127, "65-127 byte frames received"); 18128eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255", 18138eb6488eSEric Joyner CTLFLAG_RD, &stats->prc255, "128-255 byte frames received"); 18148eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511", 18158eb6488eSEric Joyner CTLFLAG_RD, &stats->prc511, "256-511 byte frames received"); 18168eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023", 18178eb6488eSEric Joyner CTLFLAG_RD, &stats->prc1023, "512-1023 byte frames received"); 18188eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522", 18198eb6488eSEric Joyner CTLFLAG_RD, &stats->prc1522, "1023-1522 byte frames received"); 18208eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersized", 18218eb6488eSEric Joyner CTLFLAG_RD, &stats->ruc, "Receive Undersized"); 18228eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented", 18238eb6488eSEric Joyner CTLFLAG_RD, &stats->rfc, "Fragmented Packets Received "); 18248eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversized", 18258eb6488eSEric Joyner CTLFLAG_RD, &stats->roc, "Oversized Packets Received"); 18268eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabberd", 18278eb6488eSEric Joyner CTLFLAG_RD, &stats->rjc, "Received Jabber"); 18288eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_rcvd", 18298eb6488eSEric Joyner CTLFLAG_RD, &stats->mngprc, "Management Packets Received"); 18308eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_drpd", 18318eb6488eSEric Joyner CTLFLAG_RD, &stats->mngptc, "Management Packets Dropped"); 18328eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "checksum_errs", 18338eb6488eSEric Joyner CTLFLAG_RD, &stats->xec, "Checksum Errors"); 18348eb6488eSEric Joyner 18358eb6488eSEric Joyner /* Packet Transmission Stats */ 18368eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd", 18378eb6488eSEric Joyner CTLFLAG_RD, &stats->gotc, "Good Octets Transmitted"); 18388eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd", 18398eb6488eSEric Joyner CTLFLAG_RD, &stats->tpt, "Total Packets Transmitted"); 18408eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd", 18418eb6488eSEric Joyner CTLFLAG_RD, &stats->gptc, "Good Packets Transmitted"); 18428eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd", 18438eb6488eSEric Joyner CTLFLAG_RD, &stats->bptc, "Broadcast Packets Transmitted"); 18448eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd", 18458eb6488eSEric Joyner CTLFLAG_RD, &stats->mptc, "Multicast Packets Transmitted"); 18468eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_txd", 18478eb6488eSEric Joyner CTLFLAG_RD, &stats->mngptc, "Management Packets Transmitted"); 18488eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64", 18498eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc64, "64 byte frames transmitted "); 18508eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127", 18518eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc127, "65-127 byte frames transmitted"); 18528eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255", 18538eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc255, "128-255 byte frames transmitted"); 18548eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511", 18558eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc511, "256-511 byte frames transmitted"); 18568eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023", 18578eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc1023, "512-1023 byte frames transmitted"); 18588eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522", 18598eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc1522, "1024-1522 byte frames transmitted"); 18608eb6488eSEric Joyner } /* ixgbe_add_hw_stats */ 18618eb6488eSEric Joyner 18628eb6488eSEric Joyner /************************************************************************ 18638eb6488eSEric Joyner * ixgbe_sysctl_tdh_handler - Transmit Descriptor Head handler function 18648eb6488eSEric Joyner * 18658eb6488eSEric Joyner * Retrieves the TDH value from the hardware 18668eb6488eSEric Joyner ************************************************************************/ 1867758cc3dcSJack F Vogel static int 1868758cc3dcSJack F Vogel ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS) 1869758cc3dcSJack F Vogel { 1870758cc3dcSJack F Vogel struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); 18718eb6488eSEric Joyner int error; 18728eb6488eSEric Joyner unsigned int val; 1873758cc3dcSJack F Vogel 18748eb6488eSEric Joyner if (!txr) 18758eb6488eSEric Joyner return (0); 18768eb6488eSEric Joyner 1877f72de14eSKevin Bowling 1878f72de14eSKevin Bowling if (atomic_load_acq_int(&txr->sc->recovery_mode)) 1879f72de14eSKevin Bowling return (EPERM); 1880f72de14eSKevin Bowling 1881b1d5caf3SKevin Bowling val = IXGBE_READ_REG(&txr->sc->hw, IXGBE_TDH(txr->me)); 1882758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1883758cc3dcSJack F Vogel if (error || !req->newptr) 1884758cc3dcSJack F Vogel return error; 1885758cc3dcSJack F Vogel 18868eb6488eSEric Joyner return (0); 18878eb6488eSEric Joyner } /* ixgbe_sysctl_tdh_handler */ 18888eb6488eSEric Joyner 18898eb6488eSEric Joyner /************************************************************************ 18908eb6488eSEric Joyner * ixgbe_sysctl_tdt_handler - Transmit Descriptor Tail handler function 18918eb6488eSEric Joyner * 1892758cc3dcSJack F Vogel * Retrieves the TDT value from the hardware 18938eb6488eSEric Joyner ************************************************************************/ 1894758cc3dcSJack F Vogel static int 1895758cc3dcSJack F Vogel ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS) 1896758cc3dcSJack F Vogel { 1897758cc3dcSJack F Vogel struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); 18988eb6488eSEric Joyner int error; 18998eb6488eSEric Joyner unsigned int val; 1900758cc3dcSJack F Vogel 19018eb6488eSEric Joyner if (!txr) 19028eb6488eSEric Joyner return (0); 19038eb6488eSEric Joyner 1904f72de14eSKevin Bowling if (atomic_load_acq_int(&txr->sc->recovery_mode)) 1905f72de14eSKevin Bowling return (EPERM); 1906f72de14eSKevin Bowling 1907b1d5caf3SKevin Bowling val = IXGBE_READ_REG(&txr->sc->hw, IXGBE_TDT(txr->me)); 1908758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1909758cc3dcSJack F Vogel if (error || !req->newptr) 1910758cc3dcSJack F Vogel return error; 1911758cc3dcSJack F Vogel 19128eb6488eSEric Joyner return (0); 19138eb6488eSEric Joyner } /* ixgbe_sysctl_tdt_handler */ 19148eb6488eSEric Joyner 19158eb6488eSEric Joyner /************************************************************************ 19168eb6488eSEric Joyner * ixgbe_sysctl_rdh_handler - Receive Descriptor Head handler function 19178eb6488eSEric Joyner * 1918758cc3dcSJack F Vogel * Retrieves the RDH value from the hardware 19198eb6488eSEric Joyner ************************************************************************/ 1920758cc3dcSJack F Vogel static int 1921758cc3dcSJack F Vogel ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS) 1922758cc3dcSJack F Vogel { 1923758cc3dcSJack F Vogel struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); 19248eb6488eSEric Joyner int error; 19258eb6488eSEric Joyner unsigned int val; 1926758cc3dcSJack F Vogel 19278eb6488eSEric Joyner if (!rxr) 19288eb6488eSEric Joyner return (0); 19298eb6488eSEric Joyner 1930f72de14eSKevin Bowling if (atomic_load_acq_int(&rxr->sc->recovery_mode)) 1931f72de14eSKevin Bowling return (EPERM); 1932f72de14eSKevin Bowling 1933b1d5caf3SKevin Bowling val = IXGBE_READ_REG(&rxr->sc->hw, IXGBE_RDH(rxr->me)); 1934758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1935758cc3dcSJack F Vogel if (error || !req->newptr) 1936758cc3dcSJack F Vogel return error; 1937758cc3dcSJack F Vogel 19388eb6488eSEric Joyner return (0); 19398eb6488eSEric Joyner } /* ixgbe_sysctl_rdh_handler */ 19408eb6488eSEric Joyner 19418eb6488eSEric Joyner /************************************************************************ 19428eb6488eSEric Joyner * ixgbe_sysctl_rdt_handler - Receive Descriptor Tail handler function 19438eb6488eSEric Joyner * 1944758cc3dcSJack F Vogel * Retrieves the RDT value from the hardware 19458eb6488eSEric Joyner ************************************************************************/ 1946758cc3dcSJack F Vogel static int 1947758cc3dcSJack F Vogel ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS) 1948758cc3dcSJack F Vogel { 1949758cc3dcSJack F Vogel struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); 19508eb6488eSEric Joyner int error; 19518eb6488eSEric Joyner unsigned int val; 1952758cc3dcSJack F Vogel 19538eb6488eSEric Joyner if (!rxr) 19548eb6488eSEric Joyner return (0); 19558eb6488eSEric Joyner 1956f72de14eSKevin Bowling if (atomic_load_acq_int(&rxr->sc->recovery_mode)) 1957f72de14eSKevin Bowling return (EPERM); 1958f72de14eSKevin Bowling 1959b1d5caf3SKevin Bowling val = IXGBE_READ_REG(&rxr->sc->hw, IXGBE_RDT(rxr->me)); 1960758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1961758cc3dcSJack F Vogel if (error || !req->newptr) 1962758cc3dcSJack F Vogel return error; 19638eb6488eSEric Joyner 19648eb6488eSEric Joyner return (0); 19658eb6488eSEric Joyner } /* ixgbe_sysctl_rdt_handler */ 19668eb6488eSEric Joyner 19678eb6488eSEric Joyner /************************************************************************ 1968c19c7afeSEric Joyner * ixgbe_if_vlan_register 19698eb6488eSEric Joyner * 19708eb6488eSEric Joyner * Run via vlan config EVENT, it enables us to use the 19718eb6488eSEric Joyner * HW Filter table since we can get the vlan id. This 19728eb6488eSEric Joyner * just creates the entry in the soft version of the 19738eb6488eSEric Joyner * VFTA, init will repopulate the real table. 19748eb6488eSEric Joyner ************************************************************************/ 19758eb6488eSEric Joyner static void 1976c19c7afeSEric Joyner ixgbe_if_vlan_register(if_ctx_t ctx, u16 vtag) 19778eb6488eSEric Joyner { 1978b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 19798eb6488eSEric Joyner u16 index, bit; 19808eb6488eSEric Joyner 19818eb6488eSEric Joyner index = (vtag >> 5) & 0x7F; 19828eb6488eSEric Joyner bit = vtag & 0x1F; 1983b1d5caf3SKevin Bowling sc->shadow_vfta[index] |= (1 << bit); 1984b1d5caf3SKevin Bowling ++sc->num_vlans; 1985c19c7afeSEric Joyner ixgbe_setup_vlan_hw_support(ctx); 1986c19c7afeSEric Joyner } /* ixgbe_if_vlan_register */ 19878eb6488eSEric Joyner 19888eb6488eSEric Joyner /************************************************************************ 1989c19c7afeSEric Joyner * ixgbe_if_vlan_unregister 19908eb6488eSEric Joyner * 19918eb6488eSEric Joyner * Run via vlan unconfig EVENT, remove our entry in the soft vfta. 19928eb6488eSEric Joyner ************************************************************************/ 19938eb6488eSEric Joyner static void 1994c19c7afeSEric Joyner ixgbe_if_vlan_unregister(if_ctx_t ctx, u16 vtag) 19958eb6488eSEric Joyner { 1996b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 19978eb6488eSEric Joyner u16 index, bit; 19988eb6488eSEric Joyner 19998eb6488eSEric Joyner index = (vtag >> 5) & 0x7F; 20008eb6488eSEric Joyner bit = vtag & 0x1F; 2001b1d5caf3SKevin Bowling sc->shadow_vfta[index] &= ~(1 << bit); 2002b1d5caf3SKevin Bowling --sc->num_vlans; 20038eb6488eSEric Joyner /* Re-init to load the changes */ 2004c19c7afeSEric Joyner ixgbe_setup_vlan_hw_support(ctx); 2005c19c7afeSEric Joyner } /* ixgbe_if_vlan_unregister */ 20068eb6488eSEric Joyner 20078eb6488eSEric Joyner /************************************************************************ 20088eb6488eSEric Joyner * ixgbe_setup_vlan_hw_support 20098eb6488eSEric Joyner ************************************************************************/ 20108eb6488eSEric Joyner static void 2011c19c7afeSEric Joyner ixgbe_setup_vlan_hw_support(if_ctx_t ctx) 20128eb6488eSEric Joyner { 2013ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 2014b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2015b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 20168eb6488eSEric Joyner struct rx_ring *rxr; 20178eb6488eSEric Joyner int i; 20188eb6488eSEric Joyner u32 ctrl; 20198eb6488eSEric Joyner 20208eb6488eSEric Joyner 20218eb6488eSEric Joyner /* 20228eb6488eSEric Joyner * We get here thru init_locked, meaning 20238eb6488eSEric Joyner * a soft reset, this has already cleared 20248eb6488eSEric Joyner * the VFTA and other state, so if there 20258eb6488eSEric Joyner * have been no vlan's registered do nothing. 20268eb6488eSEric Joyner */ 2027*c58d34ddSKevin Bowling if (sc->num_vlans == 0 || 2028*c58d34ddSKevin Bowling (if_getcapenable(ifp) & IFCAP_VLAN_HWTAGGING) == 0) { 2029e7abb897SKristof Provost /* Clear the vlan hw flag */ 2030e7abb897SKristof Provost for (i = 0; i < sc->num_rx_queues; i++) { 2031e7abb897SKristof Provost rxr = &sc->rx_queues[i].rxr; 2032e7abb897SKristof Provost /* On 82599 the VLAN enable is per/queue in RXDCTL */ 2033e7abb897SKristof Provost if (hw->mac.type != ixgbe_mac_82598EB) { 2034*c58d34ddSKevin Bowling ctrl = IXGBE_READ_REG(hw, 2035*c58d34ddSKevin Bowling IXGBE_RXDCTL(rxr->me)); 2036e7abb897SKristof Provost ctrl &= ~IXGBE_RXDCTL_VME; 2037*c58d34ddSKevin Bowling IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), 2038*c58d34ddSKevin Bowling ctrl); 2039e7abb897SKristof Provost } 2040e7abb897SKristof Provost rxr->vtag_strip = false; 2041e7abb897SKristof Provost } 2042e7abb897SKristof Provost ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); 2043e7abb897SKristof Provost /* Enable the Filter Table if enabled */ 2044e7abb897SKristof Provost ctrl |= IXGBE_VLNCTRL_CFIEN; 2045e7abb897SKristof Provost ctrl &= ~IXGBE_VLNCTRL_VFE; 2046e7abb897SKristof Provost if (hw->mac.type == ixgbe_mac_82598EB) 2047e7abb897SKristof Provost ctrl &= ~IXGBE_VLNCTRL_VME; 2048e7abb897SKristof Provost IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); 20498eb6488eSEric Joyner return; 2050e7abb897SKristof Provost } 20518eb6488eSEric Joyner 20528eb6488eSEric Joyner /* Setup the queues for vlans */ 2053ff06a8dbSJustin Hibbits if (if_getcapenable(ifp) & IFCAP_VLAN_HWTAGGING) { 2054b1d5caf3SKevin Bowling for (i = 0; i < sc->num_rx_queues; i++) { 2055b1d5caf3SKevin Bowling rxr = &sc->rx_queues[i].rxr; 20568eb6488eSEric Joyner /* On 82599 the VLAN enable is per/queue in RXDCTL */ 20578eb6488eSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) { 2058*c58d34ddSKevin Bowling ctrl = IXGBE_READ_REG(hw, 2059*c58d34ddSKevin Bowling IXGBE_RXDCTL(rxr->me)); 20608eb6488eSEric Joyner ctrl |= IXGBE_RXDCTL_VME; 2061*c58d34ddSKevin Bowling IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), 2062*c58d34ddSKevin Bowling ctrl); 20638eb6488eSEric Joyner } 206479b36ec9SKevin Bowling rxr->vtag_strip = true; 2065758cc3dcSJack F Vogel } 20669c92bb71SSean Bruno } 2067758cc3dcSJack F Vogel 2068ff06a8dbSJustin Hibbits if ((if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER) == 0) 20698eb6488eSEric Joyner return; 20708eb6488eSEric Joyner /* 20718eb6488eSEric Joyner * A soft reset zero's out the VFTA, so 20728eb6488eSEric Joyner * we need to repopulate it now. 20738eb6488eSEric Joyner */ 20748eb6488eSEric Joyner for (i = 0; i < IXGBE_VFTA_SIZE; i++) 2075b1d5caf3SKevin Bowling if (sc->shadow_vfta[i] != 0) 20768eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), 2077b1d5caf3SKevin Bowling sc->shadow_vfta[i]); 20788eb6488eSEric Joyner 20798eb6488eSEric Joyner ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); 20808eb6488eSEric Joyner /* Enable the Filter Table if enabled */ 2081ff06a8dbSJustin Hibbits if (if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER) { 20828eb6488eSEric Joyner ctrl &= ~IXGBE_VLNCTRL_CFIEN; 20838eb6488eSEric Joyner ctrl |= IXGBE_VLNCTRL_VFE; 20848eb6488eSEric Joyner } 20858eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 20868eb6488eSEric Joyner ctrl |= IXGBE_VLNCTRL_VME; 20878eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); 20888eb6488eSEric Joyner } /* ixgbe_setup_vlan_hw_support */ 20898eb6488eSEric Joyner 20908eb6488eSEric Joyner /************************************************************************ 20918eb6488eSEric Joyner * ixgbe_get_slot_info 20928eb6488eSEric Joyner * 20938eb6488eSEric Joyner * Get the width and transaction speed of 20948eb6488eSEric Joyner * the slot this adapter is plugged into. 20958eb6488eSEric Joyner ************************************************************************/ 20968eb6488eSEric Joyner static void 2097b1d5caf3SKevin Bowling ixgbe_get_slot_info(struct ixgbe_softc *sc) 20988eb6488eSEric Joyner { 2099b1d5caf3SKevin Bowling device_t dev = iflib_get_dev(sc->ctx); 2100b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 210179b36ec9SKevin Bowling int bus_info_valid = true; 21028eb6488eSEric Joyner u32 offset; 21038eb6488eSEric Joyner u16 link; 21048eb6488eSEric Joyner 21058eb6488eSEric Joyner /* Some devices are behind an internal bridge */ 21068eb6488eSEric Joyner switch (hw->device_id) { 21078eb6488eSEric Joyner case IXGBE_DEV_ID_82599_SFP_SF_QP: 21088eb6488eSEric Joyner case IXGBE_DEV_ID_82599_QSFP_SF_QP: 21098eb6488eSEric Joyner goto get_parent_info; 21108eb6488eSEric Joyner default: 21118eb6488eSEric Joyner break; 21128eb6488eSEric Joyner } 21138eb6488eSEric Joyner 21148eb6488eSEric Joyner ixgbe_get_bus_info(hw); 21158eb6488eSEric Joyner 21168eb6488eSEric Joyner /* 21178eb6488eSEric Joyner * Some devices don't use PCI-E, but there is no need 21188eb6488eSEric Joyner * to display "Unknown" for bus speed and width. 21198eb6488eSEric Joyner */ 21208eb6488eSEric Joyner switch (hw->mac.type) { 21218eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 21228eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 21238eb6488eSEric Joyner return; 21248eb6488eSEric Joyner default: 21258eb6488eSEric Joyner goto display; 21268eb6488eSEric Joyner } 21278eb6488eSEric Joyner 21288eb6488eSEric Joyner get_parent_info: 21298eb6488eSEric Joyner /* 21308eb6488eSEric Joyner * For the Quad port adapter we need to parse back 21318eb6488eSEric Joyner * up the PCI tree to find the speed of the expansion 21328eb6488eSEric Joyner * slot into which this adapter is plugged. A bit more work. 21338eb6488eSEric Joyner */ 21348eb6488eSEric Joyner dev = device_get_parent(device_get_parent(dev)); 21358eb6488eSEric Joyner #ifdef IXGBE_DEBUG 21368eb6488eSEric Joyner device_printf(dev, "parent pcib = %x,%x,%x\n", pci_get_bus(dev), 21378eb6488eSEric Joyner pci_get_slot(dev), pci_get_function(dev)); 21388eb6488eSEric Joyner #endif 21398eb6488eSEric Joyner dev = device_get_parent(device_get_parent(dev)); 21408eb6488eSEric Joyner #ifdef IXGBE_DEBUG 21418eb6488eSEric Joyner device_printf(dev, "slot pcib = %x,%x,%x\n", pci_get_bus(dev), 21428eb6488eSEric Joyner pci_get_slot(dev), pci_get_function(dev)); 21438eb6488eSEric Joyner #endif 21448eb6488eSEric Joyner /* Now get the PCI Express Capabilities offset */ 21458eb6488eSEric Joyner if (pci_find_cap(dev, PCIY_EXPRESS, &offset)) { 21468eb6488eSEric Joyner /* 21478eb6488eSEric Joyner * Hmm...can't get PCI-Express capabilities. 21488eb6488eSEric Joyner * Falling back to default method. 21498eb6488eSEric Joyner */ 215079b36ec9SKevin Bowling bus_info_valid = false; 21518eb6488eSEric Joyner ixgbe_get_bus_info(hw); 21528eb6488eSEric Joyner goto display; 21538eb6488eSEric Joyner } 21548eb6488eSEric Joyner /* ...and read the Link Status Register */ 21558eb6488eSEric Joyner link = pci_read_config(dev, offset + PCIER_LINK_STA, 2); 21568eb6488eSEric Joyner ixgbe_set_pci_config_data_generic(hw, link); 21578eb6488eSEric Joyner 21588eb6488eSEric Joyner display: 21598eb6488eSEric Joyner device_printf(dev, "PCI Express Bus: Speed %s %s\n", 21608eb6488eSEric Joyner ((hw->bus.speed == ixgbe_bus_speed_8000) ? "8.0GT/s" : 21618eb6488eSEric Joyner (hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0GT/s" : 21628eb6488eSEric Joyner (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5GT/s" : 21638eb6488eSEric Joyner "Unknown"), 21648eb6488eSEric Joyner ((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" : 21658eb6488eSEric Joyner (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" : 21668eb6488eSEric Joyner (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" : 21678eb6488eSEric Joyner "Unknown")); 21688eb6488eSEric Joyner 21698eb6488eSEric Joyner if (bus_info_valid) { 21708eb6488eSEric Joyner if ((hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) && 21718eb6488eSEric Joyner ((hw->bus.width <= ixgbe_bus_width_pcie_x4) && 21728eb6488eSEric Joyner (hw->bus.speed == ixgbe_bus_speed_2500))) { 2173*c58d34ddSKevin Bowling device_printf(dev, 2174*c58d34ddSKevin Bowling "PCI-Express bandwidth available for this card" 2175*c58d34ddSKevin Bowling " is not sufficient for optimal performance.\n"); 2176*c58d34ddSKevin Bowling device_printf(dev, 2177*c58d34ddSKevin Bowling "For optimal performance a x8 PCIE, or x4 PCIE" 2178*c58d34ddSKevin Bowling " Gen2 slot is required.\n"); 21798eb6488eSEric Joyner } 21808eb6488eSEric Joyner if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) && 21818eb6488eSEric Joyner ((hw->bus.width <= ixgbe_bus_width_pcie_x8) && 21828eb6488eSEric Joyner (hw->bus.speed < ixgbe_bus_speed_8000))) { 2183*c58d34ddSKevin Bowling device_printf(dev, 2184*c58d34ddSKevin Bowling "PCI-Express bandwidth available for this card" 2185*c58d34ddSKevin Bowling " is not sufficient for optimal performance.\n"); 2186*c58d34ddSKevin Bowling device_printf(dev, 2187*c58d34ddSKevin Bowling "For optimal performance a x8 PCIE Gen3 slot is" 2188*c58d34ddSKevin Bowling " required.\n"); 21898eb6488eSEric Joyner } 21908eb6488eSEric Joyner } else 2191*c58d34ddSKevin Bowling device_printf(dev, 2192*c58d34ddSKevin Bowling "Unable to determine slot speed/width. The speed/width" 2193*c58d34ddSKevin Bowling " reported are that of the internal switch.\n"); 21948eb6488eSEric Joyner 21958eb6488eSEric Joyner return; 21968eb6488eSEric Joyner } /* ixgbe_get_slot_info */ 21978eb6488eSEric Joyner 21988eb6488eSEric Joyner /************************************************************************ 2199c19c7afeSEric Joyner * ixgbe_if_msix_intr_assign 2200c19c7afeSEric Joyner * 2201c19c7afeSEric Joyner * Setup MSI-X Interrupt resources and handlers 22028eb6488eSEric Joyner ************************************************************************/ 2203c19c7afeSEric Joyner static int 2204c19c7afeSEric Joyner ixgbe_if_msix_intr_assign(if_ctx_t ctx, int msix) 22058eb6488eSEric Joyner { 2206b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2207b1d5caf3SKevin Bowling struct ix_rx_queue *rx_que = sc->rx_queues; 2208c19c7afeSEric Joyner struct ix_tx_queue *tx_que; 2209c19c7afeSEric Joyner int error, rid, vector = 0; 2210c19c7afeSEric Joyner char buf[16]; 22118eb6488eSEric Joyner 2212c19c7afeSEric Joyner /* Admin Que is vector 0*/ 2213c19c7afeSEric Joyner rid = vector + 1; 2214b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++, vector++, rx_que++) { 2215c19c7afeSEric Joyner rid = vector + 1; 2216c19c7afeSEric Joyner 2217c19c7afeSEric Joyner snprintf(buf, sizeof(buf), "rxq%d", i); 2218c19c7afeSEric Joyner error = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid, 2219*c58d34ddSKevin Bowling IFLIB_INTR_RXTX, ixgbe_msix_que, rx_que, rx_que->rxr.me, 2220*c58d34ddSKevin Bowling buf); 2221c19c7afeSEric Joyner 2222c19c7afeSEric Joyner if (error) { 2223c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), 2224*c58d34ddSKevin Bowling "Failed to allocate que int %d err: %d", 2225*c58d34ddSKevin Bowling i,error); 2226b1d5caf3SKevin Bowling sc->num_rx_queues = i + 1; 2227c19c7afeSEric Joyner goto fail; 22288eb6488eSEric Joyner } 22298eb6488eSEric Joyner 2230c19c7afeSEric Joyner rx_que->msix = vector; 2231c19c7afeSEric Joyner } 2232b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_tx_queues; i++) { 2233c19c7afeSEric Joyner snprintf(buf, sizeof(buf), "txq%d", i); 2234b1d5caf3SKevin Bowling tx_que = &sc->tx_queues[i]; 2235b1d5caf3SKevin Bowling tx_que->msix = i % sc->num_rx_queues; 2236c19c7afeSEric Joyner iflib_softirq_alloc_generic(ctx, 2237b1d5caf3SKevin Bowling &sc->rx_queues[tx_que->msix].que_irq, 2238c19c7afeSEric Joyner IFLIB_INTR_TX, tx_que, tx_que->txr.me, buf); 2239c19c7afeSEric Joyner } 2240c19c7afeSEric Joyner rid = vector + 1; 2241b1d5caf3SKevin Bowling error = iflib_irq_alloc_generic(ctx, &sc->irq, rid, 2242b1d5caf3SKevin Bowling IFLIB_INTR_ADMIN, ixgbe_msix_link, sc, 0, "aq"); 2243c19c7afeSEric Joyner if (error) { 2244c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), 2245c19c7afeSEric Joyner "Failed to register admin handler"); 2246c19c7afeSEric Joyner return (error); 2247c19c7afeSEric Joyner } 2248c19c7afeSEric Joyner 2249b1d5caf3SKevin Bowling sc->vector = vector; 2250c19c7afeSEric Joyner 2251c19c7afeSEric Joyner return (0); 2252c19c7afeSEric Joyner fail: 2253b1d5caf3SKevin Bowling iflib_irq_free(ctx, &sc->irq); 2254b1d5caf3SKevin Bowling rx_que = sc->rx_queues; 2255b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++, rx_que++) 2256c19c7afeSEric Joyner iflib_irq_free(ctx, &rx_que->que_irq); 2257c19c7afeSEric Joyner 2258c19c7afeSEric Joyner return (error); 2259c19c7afeSEric Joyner } /* ixgbe_if_msix_intr_assign */ 2260c19c7afeSEric Joyner 226164881da4SSai Rajesh Tallamraju static inline void 2262b1d5caf3SKevin Bowling ixgbe_perform_aim(struct ixgbe_softc *sc, struct ix_rx_queue *que) 226364881da4SSai Rajesh Tallamraju { 226464881da4SSai Rajesh Tallamraju uint32_t newitr = 0; 226564881da4SSai Rajesh Tallamraju struct rx_ring *rxr = &que->rxr; 2266f72de14eSKevin Bowling /* FIXME struct tx_ring *txr = ... ->txr; */ 226764881da4SSai Rajesh Tallamraju 226864881da4SSai Rajesh Tallamraju /* 226964881da4SSai Rajesh Tallamraju * Do Adaptive Interrupt Moderation: 227064881da4SSai Rajesh Tallamraju * - Write out last calculated setting 227164881da4SSai Rajesh Tallamraju * - Calculate based on average size over 227264881da4SSai Rajesh Tallamraju * the last interval. 227364881da4SSai Rajesh Tallamraju */ 227464881da4SSai Rajesh Tallamraju if (que->eitr_setting) { 2275b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(que->msix), 227664881da4SSai Rajesh Tallamraju que->eitr_setting); 227764881da4SSai Rajesh Tallamraju } 227864881da4SSai Rajesh Tallamraju 227964881da4SSai Rajesh Tallamraju que->eitr_setting = 0; 228064881da4SSai Rajesh Tallamraju /* Idle, do nothing */ 228164881da4SSai Rajesh Tallamraju if (rxr->bytes == 0) { 2282f72de14eSKevin Bowling /* FIXME && txr->bytes == 0 */ 228364881da4SSai Rajesh Tallamraju return; 228464881da4SSai Rajesh Tallamraju } 228564881da4SSai Rajesh Tallamraju 2286f72de14eSKevin Bowling if ((rxr->bytes) && (rxr->packets)) 2287f72de14eSKevin Bowling newitr = rxr->bytes / rxr->packets; 2288f72de14eSKevin Bowling /* FIXME for transmit accounting 2289f72de14eSKevin Bowling * if ((txr->bytes) && (txr->packets)) 2290f72de14eSKevin Bowling * newitr = txr->bytes/txr->packets; 2291f72de14eSKevin Bowling * if ((rxr->bytes) && (rxr->packets)) 2292f72de14eSKevin Bowling * newitr = max(newitr, (rxr->bytes / rxr->packets)); 2293f72de14eSKevin Bowling */ 229464881da4SSai Rajesh Tallamraju 229564881da4SSai Rajesh Tallamraju newitr += 24; /* account for hardware frame, crc */ 229664881da4SSai Rajesh Tallamraju /* set an upper boundary */ 229764881da4SSai Rajesh Tallamraju newitr = min(newitr, 3000); 229864881da4SSai Rajesh Tallamraju 229964881da4SSai Rajesh Tallamraju /* Be nice to the mid range */ 230064881da4SSai Rajesh Tallamraju if ((newitr > 300) && (newitr < 1200)) { 230164881da4SSai Rajesh Tallamraju newitr = (newitr / 3); 230264881da4SSai Rajesh Tallamraju } else { 230364881da4SSai Rajesh Tallamraju newitr = (newitr / 2); 230464881da4SSai Rajesh Tallamraju } 230564881da4SSai Rajesh Tallamraju 2306b1d5caf3SKevin Bowling if (sc->hw.mac.type == ixgbe_mac_82598EB) { 230764881da4SSai Rajesh Tallamraju newitr |= newitr << 16; 230864881da4SSai Rajesh Tallamraju } else { 230964881da4SSai Rajesh Tallamraju newitr |= IXGBE_EITR_CNT_WDIS; 231064881da4SSai Rajesh Tallamraju } 231164881da4SSai Rajesh Tallamraju 231264881da4SSai Rajesh Tallamraju /* save for next interrupt */ 231364881da4SSai Rajesh Tallamraju que->eitr_setting = newitr; 231464881da4SSai Rajesh Tallamraju 231564881da4SSai Rajesh Tallamraju /* Reset state */ 2316f72de14eSKevin Bowling /* FIXME txr->bytes = 0; */ 2317f72de14eSKevin Bowling /* FIXME txr->packets = 0; */ 231864881da4SSai Rajesh Tallamraju rxr->bytes = 0; 231964881da4SSai Rajesh Tallamraju rxr->packets = 0; 232064881da4SSai Rajesh Tallamraju 232164881da4SSai Rajesh Tallamraju return; 232264881da4SSai Rajesh Tallamraju } 232364881da4SSai Rajesh Tallamraju 2324c19c7afeSEric Joyner /********************************************************************* 23258eb6488eSEric Joyner * ixgbe_msix_que - MSI-X Queue Interrupt Service routine 2326c19c7afeSEric Joyner **********************************************************************/ 2327c19c7afeSEric Joyner static int 23288eb6488eSEric Joyner ixgbe_msix_que(void *arg) 23298eb6488eSEric Joyner { 2330c19c7afeSEric Joyner struct ix_rx_queue *que = arg; 2331b1d5caf3SKevin Bowling struct ixgbe_softc *sc = que->sc; 2332ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(que->sc->ctx); 23338eb6488eSEric Joyner 23348eb6488eSEric Joyner /* Protect against spurious interrupts */ 2335ff06a8dbSJustin Hibbits if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) 23366c351041SEric Joyner return (FILTER_HANDLED); 23378eb6488eSEric Joyner 2338b1d5caf3SKevin Bowling ixgbe_disable_queue(sc, que->msix); 23398eb6488eSEric Joyner ++que->irqs; 23408eb6488eSEric Joyner 234164881da4SSai Rajesh Tallamraju /* Check for AIM */ 2342b1d5caf3SKevin Bowling if (sc->enable_aim) { 2343b1d5caf3SKevin Bowling ixgbe_perform_aim(sc, que); 234464881da4SSai Rajesh Tallamraju } 234564881da4SSai Rajesh Tallamraju 2346c19c7afeSEric Joyner return (FILTER_SCHEDULE_THREAD); 23478eb6488eSEric Joyner } /* ixgbe_msix_que */ 23488eb6488eSEric Joyner 23498eb6488eSEric Joyner /************************************************************************ 23508eb6488eSEric Joyner * ixgbe_media_status - Media Ioctl callback 23518eb6488eSEric Joyner * 23528eb6488eSEric Joyner * Called whenever the user queries the status of 23538eb6488eSEric Joyner * the interface using ifconfig. 23548eb6488eSEric Joyner ************************************************************************/ 23558eb6488eSEric Joyner static void 2356c19c7afeSEric Joyner ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr) 23578eb6488eSEric Joyner { 2358b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2359b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 23608eb6488eSEric Joyner int layer; 23618eb6488eSEric Joyner 2362c19c7afeSEric Joyner INIT_DEBUGOUT("ixgbe_if_media_status: begin"); 2363c19c7afeSEric Joyner 23648eb6488eSEric Joyner ifmr->ifm_status = IFM_AVALID; 23658eb6488eSEric Joyner ifmr->ifm_active = IFM_ETHER; 23668eb6488eSEric Joyner 2367b1d5caf3SKevin Bowling if (!sc->link_active) 23688eb6488eSEric Joyner return; 23698eb6488eSEric Joyner 23708eb6488eSEric Joyner ifmr->ifm_status |= IFM_ACTIVE; 2371b1d5caf3SKevin Bowling layer = sc->phy_layer; 23728eb6488eSEric Joyner 23738eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T || 23748eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_T || 23758eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_100BASE_TX || 23768eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_10BASE_T) 2377b1d5caf3SKevin Bowling switch (sc->link_speed) { 23788eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 23798eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_T | IFM_FDX; 23808eb6488eSEric Joyner break; 23818eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 23828eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_T | IFM_FDX; 23838eb6488eSEric Joyner break; 23848eb6488eSEric Joyner case IXGBE_LINK_SPEED_100_FULL: 23858eb6488eSEric Joyner ifmr->ifm_active |= IFM_100_TX | IFM_FDX; 23868eb6488eSEric Joyner break; 23878eb6488eSEric Joyner case IXGBE_LINK_SPEED_10_FULL: 23888eb6488eSEric Joyner ifmr->ifm_active |= IFM_10_T | IFM_FDX; 23898eb6488eSEric Joyner break; 23908eb6488eSEric Joyner } 2391d381c807SPiotr Pietruszewski if (hw->mac.type == ixgbe_mac_X550) 2392d381c807SPiotr Pietruszewski switch (sc->link_speed) { 2393d381c807SPiotr Pietruszewski case IXGBE_LINK_SPEED_5GB_FULL: 2394d381c807SPiotr Pietruszewski ifmr->ifm_active |= IFM_5000_T | IFM_FDX; 2395d381c807SPiotr Pietruszewski break; 2396d381c807SPiotr Pietruszewski case IXGBE_LINK_SPEED_2_5GB_FULL: 2397d381c807SPiotr Pietruszewski ifmr->ifm_active |= IFM_2500_T | IFM_FDX; 2398d381c807SPiotr Pietruszewski break; 2399d381c807SPiotr Pietruszewski } 24008eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || 24018eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) 2402b1d5caf3SKevin Bowling switch (sc->link_speed) { 24038eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 24048eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX; 24058eb6488eSEric Joyner break; 240648ddd1b9SKevin Bowling case IXGBE_LINK_SPEED_1GB_FULL: 240748ddd1b9SKevin Bowling ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; 240848ddd1b9SKevin Bowling break; 24098eb6488eSEric Joyner } 24108eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) 2411b1d5caf3SKevin Bowling switch (sc->link_speed) { 24128eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 24138eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_LR | IFM_FDX; 24148eb6488eSEric Joyner break; 24158eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 24168eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; 24178eb6488eSEric Joyner break; 24188eb6488eSEric Joyner } 24198eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM) 2420b1d5caf3SKevin Bowling switch (sc->link_speed) { 24218eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 24228eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX; 24238eb6488eSEric Joyner break; 24248eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 24258eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; 24268eb6488eSEric Joyner break; 24278eb6488eSEric Joyner } 24288eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR || 24298eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) 2430b1d5caf3SKevin Bowling switch (sc->link_speed) { 24318eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 24328eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; 24338eb6488eSEric Joyner break; 24348eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 24358eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_SX | IFM_FDX; 24368eb6488eSEric Joyner break; 24378eb6488eSEric Joyner } 24388eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) 2439b1d5caf3SKevin Bowling switch (sc->link_speed) { 24408eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 24418eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; 24428eb6488eSEric Joyner break; 24438eb6488eSEric Joyner } 24448eb6488eSEric Joyner /* 24458eb6488eSEric Joyner * XXX: These need to use the proper media types once 24468eb6488eSEric Joyner * they're added. 24478eb6488eSEric Joyner */ 24488eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE 24498eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 2450b1d5caf3SKevin Bowling switch (sc->link_speed) { 24518eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 24528eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; 24538eb6488eSEric Joyner break; 24548eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 24558eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; 24568eb6488eSEric Joyner break; 24578eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 24588eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; 24598eb6488eSEric Joyner break; 24608eb6488eSEric Joyner } 24618eb6488eSEric Joyner else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 || 24628eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX || 24638eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 2464b1d5caf3SKevin Bowling switch (sc->link_speed) { 24658eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 24668eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; 24678eb6488eSEric Joyner break; 24688eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 24698eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; 24708eb6488eSEric Joyner break; 24718eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 24728eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; 24738eb6488eSEric Joyner break; 24748eb6488eSEric Joyner } 24758eb6488eSEric Joyner #else 24768eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 2477b1d5caf3SKevin Bowling switch (sc->link_speed) { 24788eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 24798eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_KR | IFM_FDX; 24808eb6488eSEric Joyner break; 24818eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 24828eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; 24838eb6488eSEric Joyner break; 24848eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 24858eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; 24868eb6488eSEric Joyner break; 24878eb6488eSEric Joyner } 24888eb6488eSEric Joyner else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 || 24898eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX || 24908eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 2491b1d5caf3SKevin Bowling switch (sc->link_speed) { 24928eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 24938eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX; 24948eb6488eSEric Joyner break; 24958eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 24968eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; 24978eb6488eSEric Joyner break; 24988eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 24998eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; 25008eb6488eSEric Joyner break; 25018eb6488eSEric Joyner } 25028eb6488eSEric Joyner #endif 25038eb6488eSEric Joyner 25048eb6488eSEric Joyner /* If nothing is recognized... */ 25058eb6488eSEric Joyner if (IFM_SUBTYPE(ifmr->ifm_active) == 0) 25068eb6488eSEric Joyner ifmr->ifm_active |= IFM_UNKNOWN; 25078eb6488eSEric Joyner 25088eb6488eSEric Joyner /* Display current flow control setting used on link */ 25098eb6488eSEric Joyner if (hw->fc.current_mode == ixgbe_fc_rx_pause || 25108eb6488eSEric Joyner hw->fc.current_mode == ixgbe_fc_full) 25118eb6488eSEric Joyner ifmr->ifm_active |= IFM_ETH_RXPAUSE; 25128eb6488eSEric Joyner if (hw->fc.current_mode == ixgbe_fc_tx_pause || 25138eb6488eSEric Joyner hw->fc.current_mode == ixgbe_fc_full) 25148eb6488eSEric Joyner ifmr->ifm_active |= IFM_ETH_TXPAUSE; 25158eb6488eSEric Joyner } /* ixgbe_media_status */ 25168eb6488eSEric Joyner 25178eb6488eSEric Joyner /************************************************************************ 25188eb6488eSEric Joyner * ixgbe_media_change - Media Ioctl callback 25198eb6488eSEric Joyner * 25208eb6488eSEric Joyner * Called when the user changes speed/duplex using 25218eb6488eSEric Joyner * media/mediopt option with ifconfig. 25228eb6488eSEric Joyner ************************************************************************/ 25238eb6488eSEric Joyner static int 2524c19c7afeSEric Joyner ixgbe_if_media_change(if_ctx_t ctx) 25258eb6488eSEric Joyner { 2526b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2527c19c7afeSEric Joyner struct ifmedia *ifm = iflib_get_media(ctx); 2528b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 25298eb6488eSEric Joyner ixgbe_link_speed speed = 0; 25308eb6488eSEric Joyner 2531c19c7afeSEric Joyner INIT_DEBUGOUT("ixgbe_if_media_change: begin"); 25328eb6488eSEric Joyner 25338eb6488eSEric Joyner if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 25348eb6488eSEric Joyner return (EINVAL); 25358eb6488eSEric Joyner 25368eb6488eSEric Joyner if (hw->phy.media_type == ixgbe_media_type_backplane) 2537c19c7afeSEric Joyner return (EPERM); 25388eb6488eSEric Joyner 25398eb6488eSEric Joyner /* 25408eb6488eSEric Joyner * We don't actually need to check against the supported 25418eb6488eSEric Joyner * media types of the adapter; ifmedia will take care of 25428eb6488eSEric Joyner * that for us. 25438eb6488eSEric Joyner */ 25448eb6488eSEric Joyner switch (IFM_SUBTYPE(ifm->ifm_media)) { 25458eb6488eSEric Joyner case IFM_AUTO: 25468eb6488eSEric Joyner case IFM_10G_T: 25478eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_100_FULL; 25488eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 25498eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10GB_FULL; 25508eb6488eSEric Joyner break; 25518eb6488eSEric Joyner case IFM_10G_LRM: 25528eb6488eSEric Joyner case IFM_10G_LR: 25538eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE 25548eb6488eSEric Joyner case IFM_10G_SR: /* KR, too */ 25558eb6488eSEric Joyner case IFM_10G_CX4: /* KX4 */ 25568eb6488eSEric Joyner #else 25578eb6488eSEric Joyner case IFM_10G_KR: 25588eb6488eSEric Joyner case IFM_10G_KX4: 25598eb6488eSEric Joyner #endif 25608eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 25618eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10GB_FULL; 25628eb6488eSEric Joyner break; 25638eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE 25648eb6488eSEric Joyner case IFM_1000_CX: /* KX */ 25658eb6488eSEric Joyner #else 25668eb6488eSEric Joyner case IFM_1000_KX: 25678eb6488eSEric Joyner #endif 25688eb6488eSEric Joyner case IFM_1000_LX: 25698eb6488eSEric Joyner case IFM_1000_SX: 25708eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 25718eb6488eSEric Joyner break; 25728eb6488eSEric Joyner case IFM_1000_T: 25738eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_100_FULL; 25748eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 25758eb6488eSEric Joyner break; 25768eb6488eSEric Joyner case IFM_10G_TWINAX: 25778eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10GB_FULL; 25788eb6488eSEric Joyner break; 2579d381c807SPiotr Pietruszewski case IFM_5000_T: 2580d381c807SPiotr Pietruszewski speed |= IXGBE_LINK_SPEED_5GB_FULL; 2581d381c807SPiotr Pietruszewski break; 2582d381c807SPiotr Pietruszewski case IFM_2500_T: 2583d381c807SPiotr Pietruszewski speed |= IXGBE_LINK_SPEED_2_5GB_FULL; 2584d381c807SPiotr Pietruszewski break; 25858eb6488eSEric Joyner case IFM_100_TX: 25868eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_100_FULL; 25878eb6488eSEric Joyner break; 25888eb6488eSEric Joyner case IFM_10_T: 25898eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10_FULL; 25908eb6488eSEric Joyner break; 25918eb6488eSEric Joyner default: 25928eb6488eSEric Joyner goto invalid; 25938eb6488eSEric Joyner } 25948eb6488eSEric Joyner 259579b36ec9SKevin Bowling hw->mac.autotry_restart = true; 259679b36ec9SKevin Bowling hw->mac.ops.setup_link(hw, speed, true); 2597b1d5caf3SKevin Bowling sc->advertise = 2598d381c807SPiotr Pietruszewski ((speed & IXGBE_LINK_SPEED_10GB_FULL) ? 0x4 : 0) | 2599d381c807SPiotr Pietruszewski ((speed & IXGBE_LINK_SPEED_5GB_FULL) ? 0x20 : 0) | 2600d381c807SPiotr Pietruszewski ((speed & IXGBE_LINK_SPEED_2_5GB_FULL) ? 0x10 : 0) | 2601d381c807SPiotr Pietruszewski ((speed & IXGBE_LINK_SPEED_1GB_FULL) ? 0x2 : 0) | 2602d381c807SPiotr Pietruszewski ((speed & IXGBE_LINK_SPEED_100_FULL) ? 0x1 : 0) | 2603d381c807SPiotr Pietruszewski ((speed & IXGBE_LINK_SPEED_10_FULL) ? 0x8 : 0); 26048eb6488eSEric Joyner 26058eb6488eSEric Joyner return (0); 26068eb6488eSEric Joyner 26078eb6488eSEric Joyner invalid: 2608c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), "Invalid media type!\n"); 26098eb6488eSEric Joyner 26108eb6488eSEric Joyner return (EINVAL); 2611c19c7afeSEric Joyner } /* ixgbe_if_media_change */ 26128eb6488eSEric Joyner 26138eb6488eSEric Joyner /************************************************************************ 26148eb6488eSEric Joyner * ixgbe_set_promisc 26158eb6488eSEric Joyner ************************************************************************/ 2616c19c7afeSEric Joyner static int 2617c19c7afeSEric Joyner ixgbe_if_promisc_set(if_ctx_t ctx, int flags) 26188eb6488eSEric Joyner { 2619b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2620ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 26218eb6488eSEric Joyner u32 rctl; 2622c19c7afeSEric Joyner int mcnt = 0; 26238eb6488eSEric Joyner 2624b1d5caf3SKevin Bowling rctl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL); 26258eb6488eSEric Joyner rctl &= (~IXGBE_FCTRL_UPE); 2626ff06a8dbSJustin Hibbits if (if_getflags(ifp) & IFF_ALLMULTI) 26278eb6488eSEric Joyner mcnt = MAX_NUM_MULTICAST_ADDRESSES; 26288eb6488eSEric Joyner else { 2629*c58d34ddSKevin Bowling mcnt = min(if_llmaddr_count(ifp), 2630*c58d34ddSKevin Bowling MAX_NUM_MULTICAST_ADDRESSES); 26318eb6488eSEric Joyner } 26328eb6488eSEric Joyner if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) 26338eb6488eSEric Joyner rctl &= (~IXGBE_FCTRL_MPE); 2634b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, rctl); 26358eb6488eSEric Joyner 2636ff06a8dbSJustin Hibbits if (if_getflags(ifp) & IFF_PROMISC) { 26378eb6488eSEric Joyner rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 2638b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, rctl); 2639ff06a8dbSJustin Hibbits } else if (if_getflags(ifp) & IFF_ALLMULTI) { 26408eb6488eSEric Joyner rctl |= IXGBE_FCTRL_MPE; 26418eb6488eSEric Joyner rctl &= ~IXGBE_FCTRL_UPE; 2642b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, rctl); 26438eb6488eSEric Joyner } 2644c19c7afeSEric Joyner return (0); 2645c19c7afeSEric Joyner } /* ixgbe_if_promisc_set */ 26468eb6488eSEric Joyner 26478eb6488eSEric Joyner /************************************************************************ 26488eb6488eSEric Joyner * ixgbe_msix_link - Link status change ISR (MSI/MSI-X) 26498eb6488eSEric Joyner ************************************************************************/ 2650c19c7afeSEric Joyner static int 26518eb6488eSEric Joyner ixgbe_msix_link(void *arg) 26528eb6488eSEric Joyner { 2653b1d5caf3SKevin Bowling struct ixgbe_softc *sc = arg; 2654b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 26558eb6488eSEric Joyner u32 eicr, eicr_mask; 26568eb6488eSEric Joyner s32 retval; 26578eb6488eSEric Joyner 2658b1d5caf3SKevin Bowling ++sc->link_irq; 26598eb6488eSEric Joyner 26608eb6488eSEric Joyner /* Pause other interrupts */ 26618eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER); 26628eb6488eSEric Joyner 26638eb6488eSEric Joyner /* First get the cause */ 26648eb6488eSEric Joyner eicr = IXGBE_READ_REG(hw, IXGBE_EICS); 26658eb6488eSEric Joyner /* Be sure the queue bits are not cleared */ 26668eb6488eSEric Joyner eicr &= ~IXGBE_EICR_RTX_QUEUE; 26678eb6488eSEric Joyner /* Clear interrupt with write */ 26688eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr); 26698eb6488eSEric Joyner 26708eb6488eSEric Joyner /* Link status change */ 26718eb6488eSEric Joyner if (eicr & IXGBE_EICR_LSC) { 26728eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); 2673b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_LSC; 26748eb6488eSEric Joyner } 26758eb6488eSEric Joyner 2676b1d5caf3SKevin Bowling if (sc->hw.mac.type != ixgbe_mac_82598EB) { 2677b1d5caf3SKevin Bowling if ((sc->feat_en & IXGBE_FEATURE_FDIR) && 26788eb6488eSEric Joyner (eicr & IXGBE_EICR_FLOW_DIR)) { 26798eb6488eSEric Joyner /* This is probably overkill :) */ 2680b1d5caf3SKevin Bowling if (!atomic_cmpset_int(&sc->fdir_reinit, 0, 1)) 2681c19c7afeSEric Joyner return (FILTER_HANDLED); 26828eb6488eSEric Joyner /* Disable the interrupt */ 2683c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR); 2684b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_FDIR; 2685c19c7afeSEric Joyner } else 26868eb6488eSEric Joyner if (eicr & IXGBE_EICR_ECC) { 2687b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 26884f1d91e4SNeel Chauhan "Received ECC Err, initiating reset\n"); 2689*c58d34ddSKevin Bowling hw->mac.flags |= 2690*c58d34ddSKevin Bowling ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 26914f1d91e4SNeel Chauhan ixgbe_reset_hw(hw); 2692*c58d34ddSKevin Bowling IXGBE_WRITE_REG(hw, IXGBE_EICR, 2693*c58d34ddSKevin Bowling IXGBE_EICR_ECC); 26948eb6488eSEric Joyner } 26958eb6488eSEric Joyner 26968eb6488eSEric Joyner /* Check for over temp condition */ 2697b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_TEMP_SENSOR) { 2698b1d5caf3SKevin Bowling switch (sc->hw.mac.type) { 26998eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 27008eb6488eSEric Joyner if (!(eicr & IXGBE_EICR_GPI_SDP0_X550EM_a)) 27018eb6488eSEric Joyner break; 27028eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, 27038eb6488eSEric Joyner IXGBE_EICR_GPI_SDP0_X550EM_a); 27048eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, 27058eb6488eSEric Joyner IXGBE_EICR_GPI_SDP0_X550EM_a); 27068eb6488eSEric Joyner retval = hw->phy.ops.check_overtemp(hw); 27078eb6488eSEric Joyner if (retval != IXGBE_ERR_OVERTEMP) 27088eb6488eSEric Joyner break; 2709b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 2710*c58d34ddSKevin Bowling "\nCRITICAL: OVER TEMP!!" 2711*c58d34ddSKevin Bowling " PHY IS SHUT DOWN!!\n"); 2712b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 2713c19c7afeSEric Joyner "System shutdown required!\n"); 27148eb6488eSEric Joyner break; 27158eb6488eSEric Joyner default: 27168eb6488eSEric Joyner if (!(eicr & IXGBE_EICR_TS)) 27178eb6488eSEric Joyner break; 27188eb6488eSEric Joyner retval = hw->phy.ops.check_overtemp(hw); 27198eb6488eSEric Joyner if (retval != IXGBE_ERR_OVERTEMP) 27208eb6488eSEric Joyner break; 2721b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 2722*c58d34ddSKevin Bowling "\nCRITICAL: OVER TEMP!!" 2723*c58d34ddSKevin Bowling " PHY IS SHUT DOWN!!\n"); 2724b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 2725c19c7afeSEric Joyner "System shutdown required!\n"); 2726*c58d34ddSKevin Bowling IXGBE_WRITE_REG(hw, IXGBE_EICR, 2727*c58d34ddSKevin Bowling IXGBE_EICR_TS); 27288eb6488eSEric Joyner break; 27298eb6488eSEric Joyner } 27308eb6488eSEric Joyner } 27318eb6488eSEric Joyner 27328eb6488eSEric Joyner /* Check for VF message */ 2733b1d5caf3SKevin Bowling if ((sc->feat_en & IXGBE_FEATURE_SRIOV) && 27348eb6488eSEric Joyner (eicr & IXGBE_EICR_MAILBOX)) 2735b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MBX; 27368eb6488eSEric Joyner } 27378eb6488eSEric Joyner 27388eb6488eSEric Joyner if (ixgbe_is_sfp(hw)) { 27398eb6488eSEric Joyner /* Pluggable optics-related interrupt */ 27408eb6488eSEric Joyner if (hw->mac.type >= ixgbe_mac_X540) 27418eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP0_X540; 27428eb6488eSEric Joyner else 27438eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); 27448eb6488eSEric Joyner 27458eb6488eSEric Joyner if (eicr & eicr_mask) { 27468eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); 2747b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MOD; 27488eb6488eSEric Joyner } 27498eb6488eSEric Joyner 27508eb6488eSEric Joyner if ((hw->mac.type == ixgbe_mac_82599EB) && 27518eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { 27528eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, 27538eb6488eSEric Joyner IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 2754b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MSF; 27558eb6488eSEric Joyner } 27568eb6488eSEric Joyner } 27578eb6488eSEric Joyner 27588eb6488eSEric Joyner /* Check for fan failure */ 2759b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_FAN_FAIL) { 2760b1d5caf3SKevin Bowling ixgbe_check_fan_failure(sc, eicr, true); 2761*c58d34ddSKevin Bowling IXGBE_WRITE_REG(hw, IXGBE_EICR, 2762*c58d34ddSKevin Bowling IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 27638eb6488eSEric Joyner } 27648eb6488eSEric Joyner 27658eb6488eSEric Joyner /* External PHY interrupt */ 27668eb6488eSEric Joyner if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && 27678eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP0_X540)) { 27688eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540); 2769b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_PHY; 27708eb6488eSEric Joyner } 27718eb6488eSEric Joyner 2772*c58d34ddSKevin Bowling return (sc->task_requests != 0) ? 2773*c58d34ddSKevin Bowling FILTER_SCHEDULE_THREAD : FILTER_HANDLED; 27748eb6488eSEric Joyner } /* ixgbe_msix_link */ 27758eb6488eSEric Joyner 27768eb6488eSEric Joyner /************************************************************************ 27778eb6488eSEric Joyner * ixgbe_sysctl_interrupt_rate_handler 27788eb6488eSEric Joyner ************************************************************************/ 2779758cc3dcSJack F Vogel static int 2780758cc3dcSJack F Vogel ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS) 2781758cc3dcSJack F Vogel { 2782c19c7afeSEric Joyner struct ix_rx_queue *que = ((struct ix_rx_queue *)oidp->oid_arg1); 27838eb6488eSEric Joyner int error; 2784758cc3dcSJack F Vogel unsigned int reg, usec, rate; 2785758cc3dcSJack F Vogel 2786f72de14eSKevin Bowling if (atomic_load_acq_int(&que->sc->recovery_mode)) 2787f72de14eSKevin Bowling return (EPERM); 2788f72de14eSKevin Bowling 2789b1d5caf3SKevin Bowling reg = IXGBE_READ_REG(&que->sc->hw, IXGBE_EITR(que->msix)); 2790758cc3dcSJack F Vogel usec = ((reg & 0x0FF8) >> 3); 2791758cc3dcSJack F Vogel if (usec > 0) 2792758cc3dcSJack F Vogel rate = 500000 / usec; 2793758cc3dcSJack F Vogel else 2794758cc3dcSJack F Vogel rate = 0; 2795758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &rate, 0, req); 2796758cc3dcSJack F Vogel if (error || !req->newptr) 2797758cc3dcSJack F Vogel return error; 2798758cc3dcSJack F Vogel reg &= ~0xfff; /* default, no limitation */ 2799758cc3dcSJack F Vogel ixgbe_max_interrupt_rate = 0; 2800758cc3dcSJack F Vogel if (rate > 0 && rate < 500000) { 2801758cc3dcSJack F Vogel if (rate < 1000) 2802758cc3dcSJack F Vogel rate = 1000; 2803758cc3dcSJack F Vogel ixgbe_max_interrupt_rate = rate; 2804758cc3dcSJack F Vogel reg |= ((4000000/rate) & 0xff8); 2805758cc3dcSJack F Vogel } 2806b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&que->sc->hw, IXGBE_EITR(que->msix), reg); 2807758cc3dcSJack F Vogel 28088eb6488eSEric Joyner return (0); 28098eb6488eSEric Joyner } /* ixgbe_sysctl_interrupt_rate_handler */ 28108eb6488eSEric Joyner 28118eb6488eSEric Joyner /************************************************************************ 28128eb6488eSEric Joyner * ixgbe_add_device_sysctls 28138eb6488eSEric Joyner ************************************************************************/ 28146f37f232SEric Joyner static void 2815c19c7afeSEric Joyner ixgbe_add_device_sysctls(if_ctx_t ctx) 28166f37f232SEric Joyner { 2817b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2818c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 2819b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 28206f37f232SEric Joyner struct sysctl_oid_list *child; 2821c19c7afeSEric Joyner struct sysctl_ctx_list *ctx_list; 28226f37f232SEric Joyner 2823c19c7afeSEric Joyner ctx_list = device_get_sysctl_ctx(dev); 28246f37f232SEric Joyner child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); 28256f37f232SEric Joyner 28266f37f232SEric Joyner /* Sysctls for all devices */ 2827c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "fc", 2828f72de14eSKevin Bowling CTLTYPE_INT | CTLFLAG_RW, 2829b1d5caf3SKevin Bowling sc, 0, ixgbe_sysctl_flowcntl, "I", 2830c19c7afeSEric Joyner IXGBE_SYSCTL_DESC_SET_FC); 28316f37f232SEric Joyner 2832c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "advertise_speed", 2833f72de14eSKevin Bowling CTLTYPE_INT | CTLFLAG_RW, 2834b1d5caf3SKevin Bowling sc, 0, ixgbe_sysctl_advertise, "I", 28358eb6488eSEric Joyner IXGBE_SYSCTL_DESC_ADV_SPEED); 28366f37f232SEric Joyner 2837b1d5caf3SKevin Bowling sc->enable_aim = ixgbe_enable_aim; 283864881da4SSai Rajesh Tallamraju SYSCTL_ADD_INT(ctx_list, child, OID_AUTO, "enable_aim", CTLFLAG_RW, 2839b1d5caf3SKevin Bowling &sc->enable_aim, 0, "Interrupt Moderation"); 284064881da4SSai Rajesh Tallamraju 28417660e4eaSKevin Bowling SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "fw_version", 2842f72de14eSKevin Bowling CTLTYPE_STRING | CTLFLAG_RD, sc, 0, 28437660e4eaSKevin Bowling ixgbe_sysctl_print_fw_version, "A", "Prints FW/NVM Versions"); 28447660e4eaSKevin Bowling 2845eea2e089SMichael Tuexen SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, 2846eea2e089SMichael Tuexen "tso_tcp_flags_mask_first_segment", 2847eea2e089SMichael Tuexen CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 2848eea2e089SMichael Tuexen sc, 0, ixgbe_sysctl_tso_tcp_flags_mask, "IU", 2849eea2e089SMichael Tuexen "TSO TCP flags mask for first segment"); 2850eea2e089SMichael Tuexen 2851eea2e089SMichael Tuexen SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, 2852eea2e089SMichael Tuexen "tso_tcp_flags_mask_middle_segment", 2853eea2e089SMichael Tuexen CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 2854eea2e089SMichael Tuexen sc, 1, ixgbe_sysctl_tso_tcp_flags_mask, "IU", 2855eea2e089SMichael Tuexen "TSO TCP flags mask for middle segment"); 2856eea2e089SMichael Tuexen 2857eea2e089SMichael Tuexen SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, 2858eea2e089SMichael Tuexen "tso_tcp_flags_mask_last_segment", 2859eea2e089SMichael Tuexen CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 2860eea2e089SMichael Tuexen sc, 2, ixgbe_sysctl_tso_tcp_flags_mask, "IU", 2861eea2e089SMichael Tuexen "TSO TCP flags mask for last segment"); 2862eea2e089SMichael Tuexen 2863a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 2864a9ca1c79SSean Bruno /* testing sysctls (for all devices) */ 2865c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "power_state", 2866f72de14eSKevin Bowling CTLTYPE_INT | CTLFLAG_RW, 2867b1d5caf3SKevin Bowling sc, 0, ixgbe_sysctl_power_state, 28688eb6488eSEric Joyner "I", "PCI Power State"); 2869a9ca1c79SSean Bruno 2870c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "print_rss_config", 2871f72de14eSKevin Bowling CTLTYPE_STRING | CTLFLAG_RD, sc, 0, 2872a9ca1c79SSean Bruno ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration"); 2873a9ca1c79SSean Bruno #endif 2874a9ca1c79SSean Bruno /* for X550 series devices */ 28756f37f232SEric Joyner if (hw->mac.type >= ixgbe_mac_X550) 2876c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "dmac", 2877f72de14eSKevin Bowling CTLTYPE_U16 | CTLFLAG_RW, 2878b1d5caf3SKevin Bowling sc, 0, ixgbe_sysctl_dmac, 28798eb6488eSEric Joyner "I", "DMA Coalesce"); 28806f37f232SEric Joyner 2881a9ca1c79SSean Bruno /* for WoL-capable devices */ 2882a9ca1c79SSean Bruno if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { 2883c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wol_enable", 2884f72de14eSKevin Bowling CTLTYPE_INT | CTLFLAG_RW, sc, 0, 2885*c58d34ddSKevin Bowling ixgbe_sysctl_wol_enable, "I", 2886*c58d34ddSKevin Bowling "Enable/Disable Wake on LAN"); 28876f37f232SEric Joyner 2888c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wufc", 2889f72de14eSKevin Bowling CTLTYPE_U32 | CTLFLAG_RW, 2890b1d5caf3SKevin Bowling sc, 0, ixgbe_sysctl_wufc, 28918eb6488eSEric Joyner "I", "Enable/Disable Wake Up Filters"); 28926f37f232SEric Joyner } 28936f37f232SEric Joyner 2894a9ca1c79SSean Bruno /* for X552/X557-AT devices */ 28956f37f232SEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { 28966f37f232SEric Joyner struct sysctl_oid *phy_node; 28976f37f232SEric Joyner struct sysctl_oid_list *phy_list; 28986f37f232SEric Joyner 2899c19c7afeSEric Joyner phy_node = SYSCTL_ADD_NODE(ctx_list, child, OID_AUTO, "phy", 2900*c58d34ddSKevin Bowling CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 2901*c58d34ddSKevin Bowling "External PHY sysctls"); 29026f37f232SEric Joyner phy_list = SYSCTL_CHILDREN(phy_node); 29036f37f232SEric Joyner 2904c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO, "temp", 2905f72de14eSKevin Bowling CTLTYPE_U16 | CTLFLAG_RD, 2906b1d5caf3SKevin Bowling sc, 0, ixgbe_sysctl_phy_temp, 29078eb6488eSEric Joyner "I", "Current External PHY Temperature (Celsius)"); 29086f37f232SEric Joyner 2909c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO, 291020b91f0aSPawel Biernacki "overtemp_occurred", 2911f72de14eSKevin Bowling CTLTYPE_U16 | CTLFLAG_RD, sc, 0, 29126f37f232SEric Joyner ixgbe_sysctl_phy_overtemp_occurred, "I", 29136f37f232SEric Joyner "External PHY High Temperature Event Occurred"); 29146f37f232SEric Joyner } 29158eb6488eSEric Joyner 2916b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_EEE) { 2917c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "eee_state", 2918f72de14eSKevin Bowling CTLTYPE_INT | CTLFLAG_RW, sc, 0, 29198eb6488eSEric Joyner ixgbe_sysctl_eee_state, "I", "EEE Power Save State"); 29208eb6488eSEric Joyner } 29218eb6488eSEric Joyner } /* ixgbe_add_device_sysctls */ 29228eb6488eSEric Joyner 29238eb6488eSEric Joyner /************************************************************************ 29248eb6488eSEric Joyner * ixgbe_allocate_pci_resources 29258eb6488eSEric Joyner ************************************************************************/ 29268eb6488eSEric Joyner static int 2927c19c7afeSEric Joyner ixgbe_allocate_pci_resources(if_ctx_t ctx) 29288eb6488eSEric Joyner { 2929b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2930c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 29318eb6488eSEric Joyner int rid; 29328eb6488eSEric Joyner 29338eb6488eSEric Joyner rid = PCIR_BAR(0); 2934b1d5caf3SKevin Bowling sc->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 29358eb6488eSEric Joyner RF_ACTIVE); 29368eb6488eSEric Joyner 2937b1d5caf3SKevin Bowling if (!(sc->pci_mem)) { 2938*c58d34ddSKevin Bowling device_printf(dev, 2939*c58d34ddSKevin Bowling "Unable to allocate bus resource: memory\n"); 29408eb6488eSEric Joyner return (ENXIO); 29418eb6488eSEric Joyner } 29428eb6488eSEric Joyner 29438eb6488eSEric Joyner /* Save bus_space values for READ/WRITE_REG macros */ 2944b1d5caf3SKevin Bowling sc->osdep.mem_bus_space_tag = rman_get_bustag(sc->pci_mem); 2945b1d5caf3SKevin Bowling sc->osdep.mem_bus_space_handle = 2946b1d5caf3SKevin Bowling rman_get_bushandle(sc->pci_mem); 29478eb6488eSEric Joyner /* Set hw values for shared code */ 2948b1d5caf3SKevin Bowling sc->hw.hw_addr = (u8 *)&sc->osdep.mem_bus_space_handle; 29498eb6488eSEric Joyner 29508eb6488eSEric Joyner return (0); 29518eb6488eSEric Joyner } /* ixgbe_allocate_pci_resources */ 29528eb6488eSEric Joyner 29538eb6488eSEric Joyner /************************************************************************ 29548eb6488eSEric Joyner * ixgbe_detach - Device removal routine 29558eb6488eSEric Joyner * 29568eb6488eSEric Joyner * Called when the driver is being removed. 29578eb6488eSEric Joyner * Stops the adapter and deallocates all the resources 29588eb6488eSEric Joyner * that were allocated for driver operation. 29598eb6488eSEric Joyner * 29608eb6488eSEric Joyner * return 0 on success, positive on failure 29618eb6488eSEric Joyner ************************************************************************/ 29628eb6488eSEric Joyner static int 2963c19c7afeSEric Joyner ixgbe_if_detach(if_ctx_t ctx) 29648eb6488eSEric Joyner { 2965b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2966c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 29678eb6488eSEric Joyner u32 ctrl_ext; 29688eb6488eSEric Joyner 29698eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_detach: begin"); 29708eb6488eSEric Joyner 29718eb6488eSEric Joyner if (ixgbe_pci_iov_detach(dev) != 0) { 29728eb6488eSEric Joyner device_printf(dev, "SR-IOV in use; detach first.\n"); 29738eb6488eSEric Joyner return (EBUSY); 29748eb6488eSEric Joyner } 29758eb6488eSEric Joyner 2976c19c7afeSEric Joyner ixgbe_setup_low_power_mode(ctx); 29778eb6488eSEric Joyner 29788eb6488eSEric Joyner /* let hardware know driver is unloading */ 2979b1d5caf3SKevin Bowling ctrl_ext = IXGBE_READ_REG(&sc->hw, IXGBE_CTRL_EXT); 29808eb6488eSEric Joyner ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD; 2981b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_CTRL_EXT, ctrl_ext); 29828eb6488eSEric Joyner 2983f72de14eSKevin Bowling callout_drain(&sc->fw_mode_timer); 2984f72de14eSKevin Bowling 2985c19c7afeSEric Joyner ixgbe_free_pci_resources(ctx); 2986b1d5caf3SKevin Bowling free(sc->mta, M_IXGBE); 29878eb6488eSEric Joyner 29888eb6488eSEric Joyner return (0); 2989c19c7afeSEric Joyner } /* ixgbe_if_detach */ 29908eb6488eSEric Joyner 29918eb6488eSEric Joyner /************************************************************************ 29928eb6488eSEric Joyner * ixgbe_setup_low_power_mode - LPLU/WoL preparation 29938eb6488eSEric Joyner * 29948eb6488eSEric Joyner * Prepare the adapter/port for LPLU and/or WoL 29958eb6488eSEric Joyner ************************************************************************/ 29968eb6488eSEric Joyner static int 2997c19c7afeSEric Joyner ixgbe_setup_low_power_mode(if_ctx_t ctx) 29988eb6488eSEric Joyner { 2999b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3000b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 3001c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 30028eb6488eSEric Joyner s32 error = 0; 30038eb6488eSEric Joyner 3004c19c7afeSEric Joyner if (!hw->wol_enabled) 300579b36ec9SKevin Bowling ixgbe_set_phy_power(hw, false); 30068eb6488eSEric Joyner 30078eb6488eSEric Joyner /* Limit power management flow to X550EM baseT */ 30088eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T && 30098eb6488eSEric Joyner hw->phy.ops.enter_lplu) { 30108eb6488eSEric Joyner /* Turn off support for APM wakeup. (Using ACPI instead) */ 301173fa89e0SPiotr Pietruszewski IXGBE_WRITE_REG(hw, IXGBE_GRC_BY_MAC(hw), 301273fa89e0SPiotr Pietruszewski IXGBE_READ_REG(hw, IXGBE_GRC_BY_MAC(hw)) & ~(u32)2); 30138eb6488eSEric Joyner 30148eb6488eSEric Joyner /* 3015*c58d34ddSKevin Bowling * Clear Wake Up Status register to prevent any previous 3016*c58d34ddSKevin Bowling * wakeup events from waking us up immediately after we 3017*c58d34ddSKevin Bowling * suspend. 30188eb6488eSEric Joyner */ 30198eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff); 30208eb6488eSEric Joyner 30218eb6488eSEric Joyner /* 30228eb6488eSEric Joyner * Program the Wakeup Filter Control register with user filter 30238eb6488eSEric Joyner * settings 30248eb6488eSEric Joyner */ 3025b1d5caf3SKevin Bowling IXGBE_WRITE_REG(hw, IXGBE_WUFC, sc->wufc); 30268eb6488eSEric Joyner 30278eb6488eSEric Joyner /* Enable wakeups and power management in Wakeup Control */ 30288eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUC, 30298eb6488eSEric Joyner IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN); 30308eb6488eSEric Joyner 30318eb6488eSEric Joyner /* X550EM baseT adapters need a special LPLU flow */ 303279b36ec9SKevin Bowling hw->phy.reset_disable = true; 3033c19c7afeSEric Joyner ixgbe_if_stop(ctx); 30348eb6488eSEric Joyner error = hw->phy.ops.enter_lplu(hw); 30358eb6488eSEric Joyner if (error) 3036*c58d34ddSKevin Bowling device_printf(dev, "Error entering LPLU: %d\n", 3037*c58d34ddSKevin Bowling error); 303879b36ec9SKevin Bowling hw->phy.reset_disable = false; 30398eb6488eSEric Joyner } else { 30408eb6488eSEric Joyner /* Just stop for other adapters */ 3041c19c7afeSEric Joyner ixgbe_if_stop(ctx); 30428eb6488eSEric Joyner } 30438eb6488eSEric Joyner 30448eb6488eSEric Joyner return error; 30458eb6488eSEric Joyner } /* ixgbe_setup_low_power_mode */ 30468eb6488eSEric Joyner 30478eb6488eSEric Joyner /************************************************************************ 30488eb6488eSEric Joyner * ixgbe_shutdown - Shutdown entry point 30498eb6488eSEric Joyner ************************************************************************/ 30508eb6488eSEric Joyner static int 3051c19c7afeSEric Joyner ixgbe_if_shutdown(if_ctx_t ctx) 30528eb6488eSEric Joyner { 30538eb6488eSEric Joyner int error = 0; 30548eb6488eSEric Joyner 30558eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_shutdown: begin"); 30568eb6488eSEric Joyner 3057c19c7afeSEric Joyner error = ixgbe_setup_low_power_mode(ctx); 30588eb6488eSEric Joyner 30598eb6488eSEric Joyner return (error); 3060c19c7afeSEric Joyner } /* ixgbe_if_shutdown */ 30618eb6488eSEric Joyner 30628eb6488eSEric Joyner /************************************************************************ 30638eb6488eSEric Joyner * ixgbe_suspend 30648eb6488eSEric Joyner * 30658eb6488eSEric Joyner * From D0 to D3 30668eb6488eSEric Joyner ************************************************************************/ 30678eb6488eSEric Joyner static int 3068c19c7afeSEric Joyner ixgbe_if_suspend(if_ctx_t ctx) 30698eb6488eSEric Joyner { 30708eb6488eSEric Joyner int error = 0; 30718eb6488eSEric Joyner 30728eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_suspend: begin"); 30738eb6488eSEric Joyner 3074c19c7afeSEric Joyner error = ixgbe_setup_low_power_mode(ctx); 30758eb6488eSEric Joyner 30768eb6488eSEric Joyner return (error); 3077c19c7afeSEric Joyner } /* ixgbe_if_suspend */ 30788eb6488eSEric Joyner 30798eb6488eSEric Joyner /************************************************************************ 30808eb6488eSEric Joyner * ixgbe_resume 30818eb6488eSEric Joyner * 30828eb6488eSEric Joyner * From D3 to D0 30838eb6488eSEric Joyner ************************************************************************/ 30848eb6488eSEric Joyner static int 3085c19c7afeSEric Joyner ixgbe_if_resume(if_ctx_t ctx) 30868eb6488eSEric Joyner { 3087b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3088c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 3089ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 3090b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 30918eb6488eSEric Joyner u32 wus; 30928eb6488eSEric Joyner 30938eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_resume: begin"); 30948eb6488eSEric Joyner 30958eb6488eSEric Joyner /* Read & clear WUS register */ 30968eb6488eSEric Joyner wus = IXGBE_READ_REG(hw, IXGBE_WUS); 30978eb6488eSEric Joyner if (wus) 30988eb6488eSEric Joyner device_printf(dev, "Woken up by (WUS): %#010x\n", 30998eb6488eSEric Joyner IXGBE_READ_REG(hw, IXGBE_WUS)); 31008eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff); 31018eb6488eSEric Joyner /* And clear WUFC until next low-power transition */ 31028eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0); 31038eb6488eSEric Joyner 31048eb6488eSEric Joyner /* 31058eb6488eSEric Joyner * Required after D3->D0 transition; 31068eb6488eSEric Joyner * will re-advertise all previous advertised speeds 31078eb6488eSEric Joyner */ 3108ff06a8dbSJustin Hibbits if (if_getflags(ifp) & IFF_UP) 3109c19c7afeSEric Joyner ixgbe_if_init(ctx); 31108eb6488eSEric Joyner 31118eb6488eSEric Joyner return (0); 3112c19c7afeSEric Joyner } /* ixgbe_if_resume */ 31138eb6488eSEric Joyner 31148eb6488eSEric Joyner /************************************************************************ 3115c19c7afeSEric Joyner * ixgbe_if_mtu_set - Ioctl mtu entry point 31168eb6488eSEric Joyner * 3117c19c7afeSEric Joyner * Return 0 on success, EINVAL on failure 3118c19c7afeSEric Joyner ************************************************************************/ 3119c19c7afeSEric Joyner static int 3120c19c7afeSEric Joyner ixgbe_if_mtu_set(if_ctx_t ctx, uint32_t mtu) 3121c19c7afeSEric Joyner { 3122b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3123c19c7afeSEric Joyner int error = 0; 3124c19c7afeSEric Joyner 3125c19c7afeSEric Joyner IOCTL_DEBUGOUT("ioctl: SIOCIFMTU (Set Interface MTU)"); 3126c19c7afeSEric Joyner 3127c19c7afeSEric Joyner if (mtu > IXGBE_MAX_MTU) { 3128c19c7afeSEric Joyner error = EINVAL; 3129c19c7afeSEric Joyner } else { 3130b1d5caf3SKevin Bowling sc->max_frame_size = mtu + IXGBE_MTU_HDR; 3131c19c7afeSEric Joyner } 3132c19c7afeSEric Joyner 3133c19c7afeSEric Joyner return error; 3134c19c7afeSEric Joyner } /* ixgbe_if_mtu_set */ 3135c19c7afeSEric Joyner 3136c19c7afeSEric Joyner /************************************************************************ 3137c19c7afeSEric Joyner * ixgbe_if_crcstrip_set 31388eb6488eSEric Joyner ************************************************************************/ 31398eb6488eSEric Joyner static void 3140c19c7afeSEric Joyner ixgbe_if_crcstrip_set(if_ctx_t ctx, int onoff, int crcstrip) 31418eb6488eSEric Joyner { 3142b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3143c19c7afeSEric Joyner struct ixgbe_hw *hw = &sc->hw; 3144c19c7afeSEric Joyner /* crc stripping is set in two places: 3145c19c7afeSEric Joyner * IXGBE_HLREG0 (modified on init_locked and hw reset) 3146c19c7afeSEric Joyner * IXGBE_RDRXCTL (set by the original driver in 3147c19c7afeSEric Joyner * ixgbe_setup_hw_rsc() called in init_locked. 3148c19c7afeSEric Joyner * We disable the setting when netmap is compiled in). 3149c19c7afeSEric Joyner * We update the values here, but also in ixgbe.c because 3150c19c7afeSEric Joyner * init_locked sometimes is called outside our control. 3151c19c7afeSEric Joyner */ 3152c19c7afeSEric Joyner uint32_t hl, rxc; 31538eb6488eSEric Joyner 3154c19c7afeSEric Joyner hl = IXGBE_READ_REG(hw, IXGBE_HLREG0); 3155c19c7afeSEric Joyner rxc = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); 3156c19c7afeSEric Joyner #ifdef NETMAP 3157c19c7afeSEric Joyner if (netmap_verbose) 3158c19c7afeSEric Joyner D("%s read HLREG 0x%x rxc 0x%x", 3159c19c7afeSEric Joyner onoff ? "enter" : "exit", hl, rxc); 31608eb6488eSEric Joyner #endif 3161c19c7afeSEric Joyner /* hw requirements ... */ 3162c19c7afeSEric Joyner rxc &= ~IXGBE_RDRXCTL_RSCFRSTSIZE; 3163c19c7afeSEric Joyner rxc |= IXGBE_RDRXCTL_RSCACKC; 3164c19c7afeSEric Joyner if (onoff && !crcstrip) { 3165c19c7afeSEric Joyner /* keep the crc. Fast rx */ 3166c19c7afeSEric Joyner hl &= ~IXGBE_HLREG0_RXCRCSTRP; 3167c19c7afeSEric Joyner rxc &= ~IXGBE_RDRXCTL_CRCSTRIP; 3168c19c7afeSEric Joyner } else { 3169c19c7afeSEric Joyner /* reset default mode */ 3170c19c7afeSEric Joyner hl |= IXGBE_HLREG0_RXCRCSTRP; 3171c19c7afeSEric Joyner rxc |= IXGBE_RDRXCTL_CRCSTRIP; 3172c19c7afeSEric Joyner } 3173c19c7afeSEric Joyner #ifdef NETMAP 3174c19c7afeSEric Joyner if (netmap_verbose) 3175c19c7afeSEric Joyner D("%s write HLREG 0x%x rxc 0x%x", 3176c19c7afeSEric Joyner onoff ? "enter" : "exit", hl, rxc); 3177c19c7afeSEric Joyner #endif 3178c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hl); 3179c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rxc); 3180c19c7afeSEric Joyner } /* ixgbe_if_crcstrip_set */ 31818eb6488eSEric Joyner 3182c19c7afeSEric Joyner /********************************************************************* 3183c19c7afeSEric Joyner * ixgbe_if_init - Init entry point 31848eb6488eSEric Joyner * 31858eb6488eSEric Joyner * Used in two ways: It is used by the stack as an init 31868eb6488eSEric Joyner * entry point in network interface structure. It is also 31878eb6488eSEric Joyner * used by the driver as a hw/sw initialization routine to 31888eb6488eSEric Joyner * get to a consistent state. 31898eb6488eSEric Joyner * 3190c19c7afeSEric Joyner * Return 0 on success, positive on failure 3191c19c7afeSEric Joyner **********************************************************************/ 31928eb6488eSEric Joyner void 3193c19c7afeSEric Joyner ixgbe_if_init(if_ctx_t ctx) 31948eb6488eSEric Joyner { 3195b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3196ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 3197c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 3198b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 3199c19c7afeSEric Joyner struct ix_rx_queue *rx_que; 3200c19c7afeSEric Joyner struct ix_tx_queue *tx_que; 32018eb6488eSEric Joyner u32 txdctl, mhadd; 32028eb6488eSEric Joyner u32 rxdctl, rxctrl; 32038eb6488eSEric Joyner u32 ctrl_ext; 32048eb6488eSEric Joyner 3205c19c7afeSEric Joyner int i, j, err; 32068eb6488eSEric Joyner 3207c19c7afeSEric Joyner INIT_DEBUGOUT("ixgbe_if_init: begin"); 32088eb6488eSEric Joyner 32098eb6488eSEric Joyner /* Queue indices may change with IOV mode */ 3210b1d5caf3SKevin Bowling ixgbe_align_all_queue_indices(sc); 32118eb6488eSEric Joyner 32128eb6488eSEric Joyner /* reprogram the RAR[0] in case user changed it. */ 3213b1d5caf3SKevin Bowling ixgbe_set_rar(hw, 0, hw->mac.addr, sc->pool, IXGBE_RAH_AV); 32148eb6488eSEric Joyner 32158eb6488eSEric Joyner /* Get the latest mac address, User can use a LAA */ 3216ff06a8dbSJustin Hibbits bcopy(if_getlladdr(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS); 3217b1d5caf3SKevin Bowling ixgbe_set_rar(hw, 0, hw->mac.addr, sc->pool, 1); 32188eb6488eSEric Joyner hw->addr_ctrl.rar_used_count = 1; 32198eb6488eSEric Joyner 32208eb6488eSEric Joyner ixgbe_init_hw(hw); 3221c19c7afeSEric Joyner 3222b1d5caf3SKevin Bowling ixgbe_initialize_iov(sc); 3223c19c7afeSEric Joyner 3224c19c7afeSEric Joyner ixgbe_initialize_transmit_units(ctx); 32258eb6488eSEric Joyner 32268eb6488eSEric Joyner /* Setup Multicast table */ 3227c19c7afeSEric Joyner ixgbe_if_multi_set(ctx); 32288eb6488eSEric Joyner 32298eb6488eSEric Joyner /* Determine the correct mbuf pool, based on frame size */ 3230b1d5caf3SKevin Bowling sc->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx); 32318eb6488eSEric Joyner 32328eb6488eSEric Joyner /* Configure RX settings */ 3233c19c7afeSEric Joyner ixgbe_initialize_receive_units(ctx); 32348eb6488eSEric Joyner 3235b2c1e8e6SEric Joyner /* 3236b2c1e8e6SEric Joyner * Initialize variable holding task enqueue requests 3237b2c1e8e6SEric Joyner * from MSI-X interrupts 3238b2c1e8e6SEric Joyner */ 3239b1d5caf3SKevin Bowling sc->task_requests = 0; 3240b2c1e8e6SEric Joyner 32418eb6488eSEric Joyner /* Enable SDP & MSI-X interrupts based on adapter */ 3242b1d5caf3SKevin Bowling ixgbe_config_gpie(sc); 32438eb6488eSEric Joyner 32448eb6488eSEric Joyner /* Set MTU size */ 3245ff06a8dbSJustin Hibbits if (if_getmtu(ifp) > ETHERMTU) { 32468eb6488eSEric Joyner /* aka IXGBE_MAXFRS on 82599 and newer */ 32478eb6488eSEric Joyner mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); 32488eb6488eSEric Joyner mhadd &= ~IXGBE_MHADD_MFS_MASK; 3249b1d5caf3SKevin Bowling mhadd |= sc->max_frame_size << IXGBE_MHADD_MFS_SHIFT; 32508eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); 32518eb6488eSEric Joyner } 32528eb6488eSEric Joyner 32538eb6488eSEric Joyner /* Now enable all the queues */ 3254*c58d34ddSKevin Bowling for (i = 0, tx_que = sc->tx_queues; i < sc->num_tx_queues; 3255*c58d34ddSKevin Bowling i++, tx_que++) { 3256c19c7afeSEric Joyner struct tx_ring *txr = &tx_que->txr; 3257c19c7afeSEric Joyner 32588eb6488eSEric Joyner txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me)); 32598eb6488eSEric Joyner txdctl |= IXGBE_TXDCTL_ENABLE; 32608eb6488eSEric Joyner /* Set WTHRESH to 8, burst writeback */ 32618eb6488eSEric Joyner txdctl |= (8 << 16); 32628eb6488eSEric Joyner /* 32638eb6488eSEric Joyner * When the internal queue falls below PTHRESH (32), 32648eb6488eSEric Joyner * start prefetching as long as there are at least 32658eb6488eSEric Joyner * HTHRESH (1) buffers ready. The values are taken 32668eb6488eSEric Joyner * from the Intel linux driver 3.8.21. 32678eb6488eSEric Joyner * Prefetching enables tx line rate even with 1 queue. 32688eb6488eSEric Joyner */ 32698eb6488eSEric Joyner txdctl |= (32 << 0) | (1 << 8); 32708eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl); 32718eb6488eSEric Joyner } 32728eb6488eSEric Joyner 3273*c58d34ddSKevin Bowling for (i = 0, rx_que = sc->rx_queues; i < sc->num_rx_queues; 3274*c58d34ddSKevin Bowling i++, rx_que++) { 3275c19c7afeSEric Joyner struct rx_ring *rxr = &rx_que->rxr; 3276c19c7afeSEric Joyner 32778eb6488eSEric Joyner rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); 32788eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) { 32798eb6488eSEric Joyner /* 32808eb6488eSEric Joyner * PTHRESH = 21 32818eb6488eSEric Joyner * HTHRESH = 4 32828eb6488eSEric Joyner * WTHRESH = 8 32838eb6488eSEric Joyner */ 32848eb6488eSEric Joyner rxdctl &= ~0x3FFFFF; 32858eb6488eSEric Joyner rxdctl |= 0x080420; 32868eb6488eSEric Joyner } 32878eb6488eSEric Joyner rxdctl |= IXGBE_RXDCTL_ENABLE; 32888eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), rxdctl); 3289c19c7afeSEric Joyner for (j = 0; j < 10; j++) { 32908eb6488eSEric Joyner if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)) & 32918eb6488eSEric Joyner IXGBE_RXDCTL_ENABLE) 32928eb6488eSEric Joyner break; 32938eb6488eSEric Joyner else 32948eb6488eSEric Joyner msec_delay(1); 32958eb6488eSEric Joyner } 32968eb6488eSEric Joyner wmb(); 32978eb6488eSEric Joyner } 32988eb6488eSEric Joyner 32998eb6488eSEric Joyner /* Enable Receive engine */ 33008eb6488eSEric Joyner rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 33018eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 33028eb6488eSEric Joyner rxctrl |= IXGBE_RXCTRL_DMBYPS; 33038eb6488eSEric Joyner rxctrl |= IXGBE_RXCTRL_RXEN; 33048eb6488eSEric Joyner ixgbe_enable_rx_dma(hw, rxctrl); 33058eb6488eSEric Joyner 3306c19c7afeSEric Joyner /* Set up MSI/MSI-X routing */ 3307c19c7afeSEric Joyner if (ixgbe_enable_msix) { 3308b1d5caf3SKevin Bowling ixgbe_configure_ivars(sc); 33098eb6488eSEric Joyner /* Set up auto-mask */ 33108eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 33118eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); 33128eb6488eSEric Joyner else { 33138eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF); 33148eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF); 33158eb6488eSEric Joyner } 33168eb6488eSEric Joyner } else { /* Simple settings for Legacy/MSI */ 3317b1d5caf3SKevin Bowling ixgbe_set_ivar(sc, 0, 0, 0); 3318b1d5caf3SKevin Bowling ixgbe_set_ivar(sc, 0, 0, 1); 33198eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); 33208eb6488eSEric Joyner } 33218eb6488eSEric Joyner 3322b1d5caf3SKevin Bowling ixgbe_init_fdir(sc); 33238eb6488eSEric Joyner 33248eb6488eSEric Joyner /* 33258eb6488eSEric Joyner * Check on any SFP devices that 33268eb6488eSEric Joyner * need to be kick-started 33278eb6488eSEric Joyner */ 33288eb6488eSEric Joyner if (hw->phy.type == ixgbe_phy_none) { 33298eb6488eSEric Joyner err = hw->phy.ops.identify(hw); 33308eb6488eSEric Joyner if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 33318eb6488eSEric Joyner device_printf(dev, 33328eb6488eSEric Joyner "Unsupported SFP+ module type was detected.\n"); 33338eb6488eSEric Joyner return; 33348eb6488eSEric Joyner } 33358eb6488eSEric Joyner } 33368eb6488eSEric Joyner 33378eb6488eSEric Joyner /* Set moderation on the Link interrupt */ 3338b1d5caf3SKevin Bowling IXGBE_WRITE_REG(hw, IXGBE_EITR(sc->vector), IXGBE_LINK_ITR); 33398eb6488eSEric Joyner 3340c19c7afeSEric Joyner /* Enable power to the phy. */ 334179b36ec9SKevin Bowling ixgbe_set_phy_power(hw, true); 3342c19c7afeSEric Joyner 33438eb6488eSEric Joyner /* Config/Enable Link */ 3344b2c1e8e6SEric Joyner ixgbe_config_link(ctx); 33458eb6488eSEric Joyner 33468eb6488eSEric Joyner /* Hardware Packet Buffer & Flow Control setup */ 3347b1d5caf3SKevin Bowling ixgbe_config_delay_values(sc); 33488eb6488eSEric Joyner 33498eb6488eSEric Joyner /* Initialize the FC settings */ 33508eb6488eSEric Joyner ixgbe_start_hw(hw); 33518eb6488eSEric Joyner 33528eb6488eSEric Joyner /* Set up VLAN support and filter */ 3353c19c7afeSEric Joyner ixgbe_setup_vlan_hw_support(ctx); 33548eb6488eSEric Joyner 33558eb6488eSEric Joyner /* Setup DMA Coalescing */ 3356b1d5caf3SKevin Bowling ixgbe_config_dmac(sc); 33578eb6488eSEric Joyner 33588eb6488eSEric Joyner /* And now turn on interrupts */ 3359c19c7afeSEric Joyner ixgbe_if_enable_intr(ctx); 33608eb6488eSEric Joyner 33618eb6488eSEric Joyner /* Enable the use of the MBX by the VF's */ 3362b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_SRIOV) { 33638eb6488eSEric Joyner ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 33648eb6488eSEric Joyner ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD; 33658eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 33668eb6488eSEric Joyner } 33678eb6488eSEric Joyner 33688eb6488eSEric Joyner } /* ixgbe_init_locked */ 33698eb6488eSEric Joyner 33708eb6488eSEric Joyner /************************************************************************ 33718eb6488eSEric Joyner * ixgbe_set_ivar 33728eb6488eSEric Joyner * 33738eb6488eSEric Joyner * Setup the correct IVAR register for a particular MSI-X interrupt 33748eb6488eSEric Joyner * (yes this is all very magic and confusing :) 33758eb6488eSEric Joyner * - entry is the register array entry 33768eb6488eSEric Joyner * - vector is the MSI-X vector for this queue 33778eb6488eSEric Joyner * - type is RX/TX/MISC 33788eb6488eSEric Joyner ************************************************************************/ 33798eb6488eSEric Joyner static void 3380b1d5caf3SKevin Bowling ixgbe_set_ivar(struct ixgbe_softc *sc, u8 entry, u8 vector, s8 type) 33818eb6488eSEric Joyner { 3382b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 33838eb6488eSEric Joyner u32 ivar, index; 33848eb6488eSEric Joyner 33858eb6488eSEric Joyner vector |= IXGBE_IVAR_ALLOC_VAL; 33868eb6488eSEric Joyner 33878eb6488eSEric Joyner switch (hw->mac.type) { 33888eb6488eSEric Joyner case ixgbe_mac_82598EB: 33898eb6488eSEric Joyner if (type == -1) 33908eb6488eSEric Joyner entry = IXGBE_IVAR_OTHER_CAUSES_INDEX; 33918eb6488eSEric Joyner else 33928eb6488eSEric Joyner entry += (type * 64); 33938eb6488eSEric Joyner index = (entry >> 2) & 0x1F; 33948eb6488eSEric Joyner ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index)); 33958eb6488eSEric Joyner ivar &= ~(0xFF << (8 * (entry & 0x3))); 33968eb6488eSEric Joyner ivar |= (vector << (8 * (entry & 0x3))); 3397b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_IVAR(index), ivar); 33988eb6488eSEric Joyner break; 33998eb6488eSEric Joyner case ixgbe_mac_82599EB: 34008eb6488eSEric Joyner case ixgbe_mac_X540: 34018eb6488eSEric Joyner case ixgbe_mac_X550: 34028eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 34038eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 34048eb6488eSEric Joyner if (type == -1) { /* MISC IVAR */ 34058eb6488eSEric Joyner index = (entry & 1) * 8; 34068eb6488eSEric Joyner ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC); 34078eb6488eSEric Joyner ivar &= ~(0xFF << index); 34088eb6488eSEric Joyner ivar |= (vector << index); 34098eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar); 34108eb6488eSEric Joyner } else { /* RX/TX IVARS */ 34118eb6488eSEric Joyner index = (16 * (entry & 1)) + (8 * type); 34128eb6488eSEric Joyner ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1)); 34138eb6488eSEric Joyner ivar &= ~(0xFF << index); 34148eb6488eSEric Joyner ivar |= (vector << index); 34158eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar); 34168eb6488eSEric Joyner } 34178eb6488eSEric Joyner default: 34188eb6488eSEric Joyner break; 34198eb6488eSEric Joyner } 34208eb6488eSEric Joyner } /* ixgbe_set_ivar */ 34218eb6488eSEric Joyner 34228eb6488eSEric Joyner /************************************************************************ 34238eb6488eSEric Joyner * ixgbe_configure_ivars 34248eb6488eSEric Joyner ************************************************************************/ 34258eb6488eSEric Joyner static void 3426b1d5caf3SKevin Bowling ixgbe_configure_ivars(struct ixgbe_softc *sc) 34278eb6488eSEric Joyner { 3428b1d5caf3SKevin Bowling struct ix_rx_queue *rx_que = sc->rx_queues; 3429b1d5caf3SKevin Bowling struct ix_tx_queue *tx_que = sc->tx_queues; 34308eb6488eSEric Joyner u32 newitr; 34318eb6488eSEric Joyner 34328eb6488eSEric Joyner if (ixgbe_max_interrupt_rate > 0) 34338eb6488eSEric Joyner newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8; 34348eb6488eSEric Joyner else { 34358eb6488eSEric Joyner /* 34368eb6488eSEric Joyner * Disable DMA coalescing if interrupt moderation is 34378eb6488eSEric Joyner * disabled. 34388eb6488eSEric Joyner */ 3439b1d5caf3SKevin Bowling sc->dmac = 0; 34408eb6488eSEric Joyner newitr = 0; 34418eb6488eSEric Joyner } 34428eb6488eSEric Joyner 3443b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++, rx_que++) { 3444c19c7afeSEric Joyner struct rx_ring *rxr = &rx_que->rxr; 34458eb6488eSEric Joyner 3446c19c7afeSEric Joyner /* First the RX queue entry */ 3447b1d5caf3SKevin Bowling ixgbe_set_ivar(sc, rxr->me, rx_que->msix, 0); 3448c19c7afeSEric Joyner 3449c19c7afeSEric Joyner /* Set an Initial EITR value */ 3450b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(rx_que->msix), newitr); 3451c19c7afeSEric Joyner } 3452b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_tx_queues; i++, tx_que++) { 3453c19c7afeSEric Joyner struct tx_ring *txr = &tx_que->txr; 3454c19c7afeSEric Joyner 3455c19c7afeSEric Joyner /* ... and the TX */ 3456b1d5caf3SKevin Bowling ixgbe_set_ivar(sc, txr->me, tx_que->msix, 1); 3457c19c7afeSEric Joyner } 34588eb6488eSEric Joyner /* For the Link interrupt */ 3459b1d5caf3SKevin Bowling ixgbe_set_ivar(sc, 1, sc->vector, -1); 34608eb6488eSEric Joyner } /* ixgbe_configure_ivars */ 34618eb6488eSEric Joyner 34628eb6488eSEric Joyner /************************************************************************ 34638eb6488eSEric Joyner * ixgbe_config_gpie 34648eb6488eSEric Joyner ************************************************************************/ 34658eb6488eSEric Joyner static void 3466b1d5caf3SKevin Bowling ixgbe_config_gpie(struct ixgbe_softc *sc) 34678eb6488eSEric Joyner { 3468b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 34698eb6488eSEric Joyner u32 gpie; 34708eb6488eSEric Joyner 34718eb6488eSEric Joyner gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); 34728eb6488eSEric Joyner 3473b1d5caf3SKevin Bowling if (sc->intr_type == IFLIB_INTR_MSIX) { 34748eb6488eSEric Joyner /* Enable Enhanced MSI-X mode */ 3475*c58d34ddSKevin Bowling gpie |= IXGBE_GPIE_MSIX_MODE | 3476*c58d34ddSKevin Bowling IXGBE_GPIE_EIAME | 3477*c58d34ddSKevin Bowling IXGBE_GPIE_PBA_SUPPORT | 3478*c58d34ddSKevin Bowling IXGBE_GPIE_OCD; 34798eb6488eSEric Joyner } 34808eb6488eSEric Joyner 34818eb6488eSEric Joyner /* Fan Failure Interrupt */ 3482b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_FAN_FAIL) 34838eb6488eSEric Joyner gpie |= IXGBE_SDP1_GPIEN; 34848eb6488eSEric Joyner 34858eb6488eSEric Joyner /* Thermal Sensor Interrupt */ 3486b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_TEMP_SENSOR) 34878eb6488eSEric Joyner gpie |= IXGBE_SDP0_GPIEN_X540; 34888eb6488eSEric Joyner 34898eb6488eSEric Joyner /* Link detection */ 34908eb6488eSEric Joyner switch (hw->mac.type) { 34918eb6488eSEric Joyner case ixgbe_mac_82599EB: 34928eb6488eSEric Joyner gpie |= IXGBE_SDP1_GPIEN | IXGBE_SDP2_GPIEN; 34938eb6488eSEric Joyner break; 34948eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 34958eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 34968eb6488eSEric Joyner gpie |= IXGBE_SDP0_GPIEN_X540; 34978eb6488eSEric Joyner break; 34988eb6488eSEric Joyner default: 34998eb6488eSEric Joyner break; 35008eb6488eSEric Joyner } 35018eb6488eSEric Joyner 35028eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); 35038eb6488eSEric Joyner 35048eb6488eSEric Joyner } /* ixgbe_config_gpie */ 35058eb6488eSEric Joyner 35068eb6488eSEric Joyner /************************************************************************ 35078eb6488eSEric Joyner * ixgbe_config_delay_values 35088eb6488eSEric Joyner * 3509b1d5caf3SKevin Bowling * Requires sc->max_frame_size to be set. 35108eb6488eSEric Joyner ************************************************************************/ 35118eb6488eSEric Joyner static void 3512b1d5caf3SKevin Bowling ixgbe_config_delay_values(struct ixgbe_softc *sc) 35138eb6488eSEric Joyner { 3514b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 35158eb6488eSEric Joyner u32 rxpb, frame, size, tmp; 35168eb6488eSEric Joyner 3517b1d5caf3SKevin Bowling frame = sc->max_frame_size; 35188eb6488eSEric Joyner 35198eb6488eSEric Joyner /* Calculate High Water */ 35208eb6488eSEric Joyner switch (hw->mac.type) { 35218eb6488eSEric Joyner case ixgbe_mac_X540: 35228eb6488eSEric Joyner case ixgbe_mac_X550: 35238eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 35248eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 35258eb6488eSEric Joyner tmp = IXGBE_DV_X540(frame, frame); 35268eb6488eSEric Joyner break; 35278eb6488eSEric Joyner default: 35288eb6488eSEric Joyner tmp = IXGBE_DV(frame, frame); 35298eb6488eSEric Joyner break; 35308eb6488eSEric Joyner } 35318eb6488eSEric Joyner size = IXGBE_BT2KB(tmp); 35328eb6488eSEric Joyner rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10; 35338eb6488eSEric Joyner hw->fc.high_water[0] = rxpb - size; 35348eb6488eSEric Joyner 35358eb6488eSEric Joyner /* Now calculate Low Water */ 35368eb6488eSEric Joyner switch (hw->mac.type) { 35378eb6488eSEric Joyner case ixgbe_mac_X540: 35388eb6488eSEric Joyner case ixgbe_mac_X550: 35398eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 35408eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 35418eb6488eSEric Joyner tmp = IXGBE_LOW_DV_X540(frame); 35428eb6488eSEric Joyner break; 35438eb6488eSEric Joyner default: 35448eb6488eSEric Joyner tmp = IXGBE_LOW_DV(frame); 35458eb6488eSEric Joyner break; 35468eb6488eSEric Joyner } 35478eb6488eSEric Joyner hw->fc.low_water[0] = IXGBE_BT2KB(tmp); 35488eb6488eSEric Joyner 35498eb6488eSEric Joyner hw->fc.pause_time = IXGBE_FC_PAUSE; 355079b36ec9SKevin Bowling hw->fc.send_xon = true; 35518eb6488eSEric Joyner } /* ixgbe_config_delay_values */ 35528eb6488eSEric Joyner 35538eb6488eSEric Joyner /************************************************************************ 35548eb6488eSEric Joyner * ixgbe_set_multi - Multicast Update 35558eb6488eSEric Joyner * 35568eb6488eSEric Joyner * Called whenever multicast address list is updated. 35578eb6488eSEric Joyner ************************************************************************/ 3558ba76aa63SGleb Smirnoff static u_int 355921afed4bSKevin Bowling ixgbe_mc_filter_apply(void *arg, struct sockaddr_dl *sdl, u_int idx) 35608eb6488eSEric Joyner { 3561b1d5caf3SKevin Bowling struct ixgbe_softc *sc = arg; 3562b1d5caf3SKevin Bowling struct ixgbe_mc_addr *mta = sc->mta; 3563c19c7afeSEric Joyner 356421afed4bSKevin Bowling if (idx == MAX_NUM_MULTICAST_ADDRESSES) 3565c19c7afeSEric Joyner return (0); 356621afed4bSKevin Bowling bcopy(LLADDR(sdl), mta[idx].addr, IXGBE_ETH_LENGTH_OF_ADDRESS); 3567b1d5caf3SKevin Bowling mta[idx].vmdq = sc->pool; 3568c19c7afeSEric Joyner 3569c19c7afeSEric Joyner return (1); 3570c19c7afeSEric Joyner } /* ixgbe_mc_filter_apply */ 3571c19c7afeSEric Joyner 3572c19c7afeSEric Joyner static void 3573c19c7afeSEric Joyner ixgbe_if_multi_set(if_ctx_t ctx) 3574c19c7afeSEric Joyner { 3575b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 35768eb6488eSEric Joyner struct ixgbe_mc_addr *mta; 3577ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 35788eb6488eSEric Joyner u8 *update_ptr; 35798eb6488eSEric Joyner u32 fctrl; 3580ba76aa63SGleb Smirnoff u_int mcnt; 35818eb6488eSEric Joyner 3582c19c7afeSEric Joyner IOCTL_DEBUGOUT("ixgbe_if_multi_set: begin"); 35838eb6488eSEric Joyner 3584b1d5caf3SKevin Bowling mta = sc->mta; 35858eb6488eSEric Joyner bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES); 35868eb6488eSEric Joyner 3587*c58d34ddSKevin Bowling mcnt = if_foreach_llmaddr(iflib_get_ifp(ctx), ixgbe_mc_filter_apply, 3588*c58d34ddSKevin Bowling sc); 35898eb6488eSEric Joyner 3590395cc55dSKevin Bowling if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) { 3591395cc55dSKevin Bowling update_ptr = (u8 *)mta; 3592395cc55dSKevin Bowling ixgbe_update_mc_addr_list(&sc->hw, update_ptr, mcnt, 3593395cc55dSKevin Bowling ixgbe_mc_array_itr, true); 3594395cc55dSKevin Bowling } 3595395cc55dSKevin Bowling 3596b1d5caf3SKevin Bowling fctrl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL); 3597deecaa14SKevin Bowling 3598ff06a8dbSJustin Hibbits if (if_getflags(ifp) & IFF_PROMISC) 35998eb6488eSEric Joyner fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 36008eb6488eSEric Joyner else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES || 3601ff06a8dbSJustin Hibbits if_getflags(ifp) & IFF_ALLMULTI) { 36028eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_MPE; 36038eb6488eSEric Joyner fctrl &= ~IXGBE_FCTRL_UPE; 36048eb6488eSEric Joyner } else 36058eb6488eSEric Joyner fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 36068eb6488eSEric Joyner 3607b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, fctrl); 3608c19c7afeSEric Joyner } /* ixgbe_if_multi_set */ 36098eb6488eSEric Joyner 36108eb6488eSEric Joyner /************************************************************************ 36118eb6488eSEric Joyner * ixgbe_mc_array_itr 36128eb6488eSEric Joyner * 36138eb6488eSEric Joyner * An iterator function needed by the multicast shared code. 36148eb6488eSEric Joyner * It feeds the shared code routine the addresses in the 36158eb6488eSEric Joyner * array of ixgbe_set_multi() one by one. 36168eb6488eSEric Joyner ************************************************************************/ 36178eb6488eSEric Joyner static u8 * 36188eb6488eSEric Joyner ixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq) 36198eb6488eSEric Joyner { 36208eb6488eSEric Joyner struct ixgbe_mc_addr *mta; 36218eb6488eSEric Joyner 36228eb6488eSEric Joyner mta = (struct ixgbe_mc_addr *)*update_ptr; 36238eb6488eSEric Joyner *vmdq = mta->vmdq; 36248eb6488eSEric Joyner 36258eb6488eSEric Joyner *update_ptr = (u8*)(mta + 1); 36268eb6488eSEric Joyner 36278eb6488eSEric Joyner return (mta->addr); 36288eb6488eSEric Joyner } /* ixgbe_mc_array_itr */ 36298eb6488eSEric Joyner 36308eb6488eSEric Joyner /************************************************************************ 36318eb6488eSEric Joyner * ixgbe_local_timer - Timer routine 36328eb6488eSEric Joyner * 36338eb6488eSEric Joyner * Checks for link status, updates statistics, 36348eb6488eSEric Joyner * and runs the watchdog check. 36358eb6488eSEric Joyner ************************************************************************/ 36368eb6488eSEric Joyner static void 3637c19c7afeSEric Joyner ixgbe_if_timer(if_ctx_t ctx, uint16_t qid) 36388eb6488eSEric Joyner { 3639b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 36408eb6488eSEric Joyner 3641c19c7afeSEric Joyner if (qid != 0) 3642c19c7afeSEric Joyner return; 36438eb6488eSEric Joyner 36448eb6488eSEric Joyner /* Check for pluggable optics */ 3645b1d5caf3SKevin Bowling if (sc->sfp_probe) 3646c19c7afeSEric Joyner if (!ixgbe_sfp_probe(ctx)) 3647c19c7afeSEric Joyner return; /* Nothing to do */ 36488eb6488eSEric Joyner 3649b1d5caf3SKevin Bowling ixgbe_check_link(&sc->hw, &sc->link_speed, &sc->link_up, 0); 36508eb6488eSEric Joyner 3651c19c7afeSEric Joyner /* Fire off the adminq task */ 3652c19c7afeSEric Joyner iflib_admin_intr_deferred(ctx); 36538eb6488eSEric Joyner 3654c19c7afeSEric Joyner } /* ixgbe_if_timer */ 36558eb6488eSEric Joyner 36568eb6488eSEric Joyner /************************************************************************ 3657f72de14eSKevin Bowling * ixgbe_fw_mode_timer - FW mode timer routine 3658f72de14eSKevin Bowling ************************************************************************/ 3659f72de14eSKevin Bowling static void 3660f72de14eSKevin Bowling ixgbe_fw_mode_timer(void *arg) 3661f72de14eSKevin Bowling { 3662f72de14eSKevin Bowling struct ixgbe_softc *sc = arg; 3663f72de14eSKevin Bowling struct ixgbe_hw *hw = &sc->hw; 3664f72de14eSKevin Bowling 3665f72de14eSKevin Bowling if (ixgbe_fw_recovery_mode(hw)) { 3666f72de14eSKevin Bowling if (atomic_cmpset_acq_int(&sc->recovery_mode, 0, 1)) { 3667f72de14eSKevin Bowling /* Firmware error detected, entering recovery mode */ 3668*c58d34ddSKevin Bowling device_printf(sc->dev, 3669*c58d34ddSKevin Bowling "Firmware recovery mode detected. Limiting" 3670*c58d34ddSKevin Bowling " functionality. Refer to the Intel(R) Ethernet" 3671*c58d34ddSKevin Bowling " Adapters and Devices User Guide for details on" 3672*c58d34ddSKevin Bowling " firmware recovery mode.\n"); 3673f72de14eSKevin Bowling 3674f72de14eSKevin Bowling if (hw->adapter_stopped == FALSE) 3675f72de14eSKevin Bowling ixgbe_if_stop(sc->ctx); 3676f72de14eSKevin Bowling } 3677f72de14eSKevin Bowling } else 3678f72de14eSKevin Bowling atomic_cmpset_acq_int(&sc->recovery_mode, 1, 0); 3679f72de14eSKevin Bowling 3680f72de14eSKevin Bowling 3681f72de14eSKevin Bowling callout_reset(&sc->fw_mode_timer, hz, 3682f72de14eSKevin Bowling ixgbe_fw_mode_timer, sc); 3683f72de14eSKevin Bowling } /* ixgbe_fw_mode_timer */ 3684f72de14eSKevin Bowling 3685f72de14eSKevin Bowling /************************************************************************ 36868eb6488eSEric Joyner * ixgbe_sfp_probe 36878eb6488eSEric Joyner * 36888eb6488eSEric Joyner * Determine if a port had optics inserted. 36898eb6488eSEric Joyner ************************************************************************/ 36908eb6488eSEric Joyner static bool 3691c19c7afeSEric Joyner ixgbe_sfp_probe(if_ctx_t ctx) 36928eb6488eSEric Joyner { 3693b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3694b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 3695c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 369679b36ec9SKevin Bowling bool result = false; 36978eb6488eSEric Joyner 36988eb6488eSEric Joyner if ((hw->phy.type == ixgbe_phy_nl) && 36998eb6488eSEric Joyner (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) { 37008eb6488eSEric Joyner s32 ret = hw->phy.ops.identify_sfp(hw); 37018eb6488eSEric Joyner if (ret) 37028eb6488eSEric Joyner goto out; 37038eb6488eSEric Joyner ret = hw->phy.ops.reset(hw); 3704b1d5caf3SKevin Bowling sc->sfp_probe = false; 37058eb6488eSEric Joyner if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { 3706*c58d34ddSKevin Bowling device_printf(dev, 3707*c58d34ddSKevin Bowling "Unsupported SFP+ module detected!"); 37088eb6488eSEric Joyner device_printf(dev, 37098eb6488eSEric Joyner "Reload driver with supported module.\n"); 37108eb6488eSEric Joyner goto out; 37118eb6488eSEric Joyner } else 37128eb6488eSEric Joyner device_printf(dev, "SFP+ module detected!\n"); 37138eb6488eSEric Joyner /* We now have supported optics */ 371479b36ec9SKevin Bowling result = true; 37158eb6488eSEric Joyner } 37168eb6488eSEric Joyner out: 37178eb6488eSEric Joyner 37188eb6488eSEric Joyner return (result); 37198eb6488eSEric Joyner } /* ixgbe_sfp_probe */ 37208eb6488eSEric Joyner 37218eb6488eSEric Joyner /************************************************************************ 37228eb6488eSEric Joyner * ixgbe_handle_mod - Tasklet for SFP module interrupts 37238eb6488eSEric Joyner ************************************************************************/ 37248eb6488eSEric Joyner static void 3725c19c7afeSEric Joyner ixgbe_handle_mod(void *context) 37268eb6488eSEric Joyner { 3727c19c7afeSEric Joyner if_ctx_t ctx = context; 3728b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3729b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 3730c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 37318eb6488eSEric Joyner u32 err, cage_full = 0; 37328eb6488eSEric Joyner 3733b1d5caf3SKevin Bowling if (sc->hw.need_crosstalk_fix) { 37348eb6488eSEric Joyner switch (hw->mac.type) { 37358eb6488eSEric Joyner case ixgbe_mac_82599EB: 37368eb6488eSEric Joyner cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 37378eb6488eSEric Joyner IXGBE_ESDP_SDP2; 37388eb6488eSEric Joyner break; 37398eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 37408eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 37418eb6488eSEric Joyner cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 37428eb6488eSEric Joyner IXGBE_ESDP_SDP0; 37438eb6488eSEric Joyner break; 37448eb6488eSEric Joyner default: 37458eb6488eSEric Joyner break; 37468eb6488eSEric Joyner } 37478eb6488eSEric Joyner 37488eb6488eSEric Joyner if (!cage_full) 3749c19c7afeSEric Joyner goto handle_mod_out; 37508eb6488eSEric Joyner } 37518eb6488eSEric Joyner 37528eb6488eSEric Joyner err = hw->phy.ops.identify_sfp(hw); 37538eb6488eSEric Joyner if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 37548eb6488eSEric Joyner device_printf(dev, 37558eb6488eSEric Joyner "Unsupported SFP+ module type was detected.\n"); 3756c19c7afeSEric Joyner goto handle_mod_out; 37578eb6488eSEric Joyner } 37588eb6488eSEric Joyner 3759c19c7afeSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 3760c19c7afeSEric Joyner err = hw->phy.ops.reset(hw); 3761c19c7afeSEric Joyner else 37628eb6488eSEric Joyner err = hw->mac.ops.setup_sfp(hw); 3763c19c7afeSEric Joyner 37648eb6488eSEric Joyner if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 37658eb6488eSEric Joyner device_printf(dev, 37668eb6488eSEric Joyner "Setup failure - unsupported SFP+ module type.\n"); 3767c19c7afeSEric Joyner goto handle_mod_out; 37688eb6488eSEric Joyner } 3769b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MSF; 3770c19c7afeSEric Joyner return; 3771c19c7afeSEric Joyner 3772c19c7afeSEric Joyner handle_mod_out: 3773b1d5caf3SKevin Bowling sc->task_requests &= ~(IXGBE_REQUEST_TASK_MSF); 37748eb6488eSEric Joyner } /* ixgbe_handle_mod */ 37758eb6488eSEric Joyner 37768eb6488eSEric Joyner 37778eb6488eSEric Joyner /************************************************************************ 37788eb6488eSEric Joyner * ixgbe_handle_msf - Tasklet for MSF (multispeed fiber) interrupts 37798eb6488eSEric Joyner ************************************************************************/ 37808eb6488eSEric Joyner static void 3781c19c7afeSEric Joyner ixgbe_handle_msf(void *context) 37828eb6488eSEric Joyner { 3783c19c7afeSEric Joyner if_ctx_t ctx = context; 3784b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3785b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 37868eb6488eSEric Joyner u32 autoneg; 37878eb6488eSEric Joyner bool negotiate; 37888eb6488eSEric Joyner 37898eb6488eSEric Joyner /* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */ 3790b1d5caf3SKevin Bowling sc->phy_layer = ixgbe_get_supported_physical_layer(hw); 37918eb6488eSEric Joyner 37928eb6488eSEric Joyner autoneg = hw->phy.autoneg_advertised; 37938eb6488eSEric Joyner if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) 37948eb6488eSEric Joyner hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate); 37958eb6488eSEric Joyner if (hw->mac.ops.setup_link) 379679b36ec9SKevin Bowling hw->mac.ops.setup_link(hw, autoneg, true); 37978eb6488eSEric Joyner 37988eb6488eSEric Joyner /* Adjust media types shown in ifconfig */ 3799b1d5caf3SKevin Bowling ifmedia_removeall(sc->media); 3800b1d5caf3SKevin Bowling ixgbe_add_media_types(sc->ctx); 3801b1d5caf3SKevin Bowling ifmedia_set(sc->media, IFM_ETHER | IFM_AUTO); 38028eb6488eSEric Joyner } /* ixgbe_handle_msf */ 38038eb6488eSEric Joyner 38048eb6488eSEric Joyner /************************************************************************ 38058eb6488eSEric Joyner * ixgbe_handle_phy - Tasklet for external PHY interrupts 38068eb6488eSEric Joyner ************************************************************************/ 38078eb6488eSEric Joyner static void 3808c19c7afeSEric Joyner ixgbe_handle_phy(void *context) 38098eb6488eSEric Joyner { 3810c19c7afeSEric Joyner if_ctx_t ctx = context; 3811b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3812b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 38138eb6488eSEric Joyner int error; 38148eb6488eSEric Joyner 38158eb6488eSEric Joyner error = hw->phy.ops.handle_lasi(hw); 38168eb6488eSEric Joyner if (error == IXGBE_ERR_OVERTEMP) 3817*c58d34ddSKevin Bowling device_printf(sc->dev, 3818*c58d34ddSKevin Bowling "CRITICAL: EXTERNAL PHY OVER TEMP!!" 3819*c58d34ddSKevin Bowling " PHY will downshift to lower power state!\n"); 38208eb6488eSEric Joyner else if (error) 3821b1d5caf3SKevin Bowling device_printf(sc->dev, 38228eb6488eSEric Joyner "Error handling LASI interrupt: %d\n", error); 38238eb6488eSEric Joyner } /* ixgbe_handle_phy */ 38248eb6488eSEric Joyner 38258eb6488eSEric Joyner /************************************************************************ 3826c19c7afeSEric Joyner * ixgbe_if_stop - Stop the hardware 38278eb6488eSEric Joyner * 38288eb6488eSEric Joyner * Disables all traffic on the adapter by issuing a 38298eb6488eSEric Joyner * global reset on the MAC and deallocates TX/RX buffers. 38308eb6488eSEric Joyner ************************************************************************/ 38318eb6488eSEric Joyner static void 3832c19c7afeSEric Joyner ixgbe_if_stop(if_ctx_t ctx) 38338eb6488eSEric Joyner { 3834b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3835b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 38368eb6488eSEric Joyner 3837c19c7afeSEric Joyner INIT_DEBUGOUT("ixgbe_if_stop: begin\n"); 38388eb6488eSEric Joyner 38398eb6488eSEric Joyner ixgbe_reset_hw(hw); 384079b36ec9SKevin Bowling hw->adapter_stopped = false; 38418eb6488eSEric Joyner ixgbe_stop_adapter(hw); 38428eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82599EB) 38438eb6488eSEric Joyner ixgbe_stop_mac_link_on_d3_82599(hw); 38448eb6488eSEric Joyner /* Turn off the laser - noop with no optics */ 38458eb6488eSEric Joyner ixgbe_disable_tx_laser(hw); 38468eb6488eSEric Joyner 38478eb6488eSEric Joyner /* Update the stack */ 3848b1d5caf3SKevin Bowling sc->link_up = false; 3849c19c7afeSEric Joyner ixgbe_if_update_admin_status(ctx); 38508eb6488eSEric Joyner 38518eb6488eSEric Joyner /* reprogram the RAR[0] in case user changed it. */ 3852b1d5caf3SKevin Bowling ixgbe_set_rar(&sc->hw, 0, sc->hw.mac.addr, 0, IXGBE_RAH_AV); 38538eb6488eSEric Joyner 38548eb6488eSEric Joyner return; 3855c19c7afeSEric Joyner } /* ixgbe_if_stop */ 38568eb6488eSEric Joyner 38578eb6488eSEric Joyner /************************************************************************ 38588eb6488eSEric Joyner * ixgbe_update_link_status - Update OS on link state 38598eb6488eSEric Joyner * 38608eb6488eSEric Joyner * Note: Only updates the OS on the cached link state. 38618eb6488eSEric Joyner * The real check of the hardware only happens with 38628eb6488eSEric Joyner * a link interrupt. 38638eb6488eSEric Joyner ************************************************************************/ 38648eb6488eSEric Joyner static void 3865c19c7afeSEric Joyner ixgbe_if_update_admin_status(if_ctx_t ctx) 38668eb6488eSEric Joyner { 3867b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3868c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 38698eb6488eSEric Joyner 3870b1d5caf3SKevin Bowling if (sc->link_up) { 3871b1d5caf3SKevin Bowling if (sc->link_active == false) { 38728eb6488eSEric Joyner if (bootverbose) 38738eb6488eSEric Joyner device_printf(dev, "Link is up %d Gbps %s \n", 3874b1d5caf3SKevin Bowling ((sc->link_speed == 128) ? 10 : 1), 38758eb6488eSEric Joyner "Full Duplex"); 3876b1d5caf3SKevin Bowling sc->link_active = true; 38778eb6488eSEric Joyner /* Update any Flow Control changes */ 3878b1d5caf3SKevin Bowling ixgbe_fc_enable(&sc->hw); 38798eb6488eSEric Joyner /* Update DMA coalescing config */ 3880b1d5caf3SKevin Bowling ixgbe_config_dmac(sc); 3881a0302c92SPiotr Pietruszewski iflib_link_state_change(ctx, LINK_STATE_UP, 38825ddb1aa3SPiotr Kubaj ixgbe_link_speed_to_baudrate(sc->link_speed)); 3883c19c7afeSEric Joyner 3884b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_SRIOV) 3885b1d5caf3SKevin Bowling ixgbe_ping_all_vfs(sc); 38868eb6488eSEric Joyner } 38878eb6488eSEric Joyner } else { /* Link down */ 3888b1d5caf3SKevin Bowling if (sc->link_active == true) { 38898eb6488eSEric Joyner if (bootverbose) 38908eb6488eSEric Joyner device_printf(dev, "Link is Down\n"); 3891c19c7afeSEric Joyner iflib_link_state_change(ctx, LINK_STATE_DOWN, 0); 3892b1d5caf3SKevin Bowling sc->link_active = false; 3893b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_SRIOV) 3894b1d5caf3SKevin Bowling ixgbe_ping_all_vfs(sc); 38958eb6488eSEric Joyner } 38968eb6488eSEric Joyner } 38978eb6488eSEric Joyner 3898b2c1e8e6SEric Joyner /* Handle task requests from msix_link() */ 3899b1d5caf3SKevin Bowling if (sc->task_requests & IXGBE_REQUEST_TASK_MOD) 3900b2c1e8e6SEric Joyner ixgbe_handle_mod(ctx); 3901b1d5caf3SKevin Bowling if (sc->task_requests & IXGBE_REQUEST_TASK_MSF) 3902b2c1e8e6SEric Joyner ixgbe_handle_msf(ctx); 3903b1d5caf3SKevin Bowling if (sc->task_requests & IXGBE_REQUEST_TASK_MBX) 3904b2c1e8e6SEric Joyner ixgbe_handle_mbx(ctx); 3905b1d5caf3SKevin Bowling if (sc->task_requests & IXGBE_REQUEST_TASK_FDIR) 3906b2c1e8e6SEric Joyner ixgbe_reinit_fdir(ctx); 3907b1d5caf3SKevin Bowling if (sc->task_requests & IXGBE_REQUEST_TASK_PHY) 3908b2c1e8e6SEric Joyner ixgbe_handle_phy(ctx); 3909b1d5caf3SKevin Bowling sc->task_requests = 0; 3910c19c7afeSEric Joyner 3911b1d5caf3SKevin Bowling ixgbe_update_stats_counters(sc); 3912c19c7afeSEric Joyner } /* ixgbe_if_update_admin_status */ 39138eb6488eSEric Joyner 39148eb6488eSEric Joyner /************************************************************************ 39158eb6488eSEric Joyner * ixgbe_config_dmac - Configure DMA Coalescing 39168eb6488eSEric Joyner ************************************************************************/ 39178eb6488eSEric Joyner static void 3918b1d5caf3SKevin Bowling ixgbe_config_dmac(struct ixgbe_softc *sc) 39198eb6488eSEric Joyner { 3920b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 39218eb6488eSEric Joyner struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config; 39228eb6488eSEric Joyner 39238eb6488eSEric Joyner if (hw->mac.type < ixgbe_mac_X550 || !hw->mac.ops.dmac_config) 39248eb6488eSEric Joyner return; 39258eb6488eSEric Joyner 3926b1d5caf3SKevin Bowling if (dcfg->watchdog_timer ^ sc->dmac || 3927b1d5caf3SKevin Bowling dcfg->link_speed ^ sc->link_speed) { 3928b1d5caf3SKevin Bowling dcfg->watchdog_timer = sc->dmac; 392979b36ec9SKevin Bowling dcfg->fcoe_en = false; 3930b1d5caf3SKevin Bowling dcfg->link_speed = sc->link_speed; 39318eb6488eSEric Joyner dcfg->num_tcs = 1; 39328eb6488eSEric Joyner 39338eb6488eSEric Joyner INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n", 39348eb6488eSEric Joyner dcfg->watchdog_timer, dcfg->link_speed); 39358eb6488eSEric Joyner 39368eb6488eSEric Joyner hw->mac.ops.dmac_config(hw); 39378eb6488eSEric Joyner } 39388eb6488eSEric Joyner } /* ixgbe_config_dmac */ 39398eb6488eSEric Joyner 39408eb6488eSEric Joyner /************************************************************************ 3941c19c7afeSEric Joyner * ixgbe_if_enable_intr 39428eb6488eSEric Joyner ************************************************************************/ 3943c19c7afeSEric Joyner void 3944c19c7afeSEric Joyner ixgbe_if_enable_intr(if_ctx_t ctx) 39458eb6488eSEric Joyner { 3946b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3947b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 3948b1d5caf3SKevin Bowling struct ix_rx_queue *que = sc->rx_queues; 39498eb6488eSEric Joyner u32 mask, fwsm; 39508eb6488eSEric Joyner 39518eb6488eSEric Joyner mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); 39528eb6488eSEric Joyner 3953b1d5caf3SKevin Bowling switch (sc->hw.mac.type) { 39548eb6488eSEric Joyner case ixgbe_mac_82599EB: 39558eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 3956b1d5caf3SKevin Bowling /* Temperature sensor on some scs */ 39578eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP0; 39588eb6488eSEric Joyner /* SFP+ (RX_LOS_N & MOD_ABS_N) */ 39598eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP1; 39608eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP2; 39618eb6488eSEric Joyner break; 39628eb6488eSEric Joyner case ixgbe_mac_X540: 39638eb6488eSEric Joyner /* Detect if Thermal Sensor is enabled */ 39648eb6488eSEric Joyner fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); 39658eb6488eSEric Joyner if (fwsm & IXGBE_FWSM_TS_ENABLED) 39668eb6488eSEric Joyner mask |= IXGBE_EIMS_TS; 39678eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 39688eb6488eSEric Joyner break; 39698eb6488eSEric Joyner case ixgbe_mac_X550: 39708eb6488eSEric Joyner /* MAC thermal sensor is automatically enabled */ 39718eb6488eSEric Joyner mask |= IXGBE_EIMS_TS; 39728eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 39738eb6488eSEric Joyner break; 39748eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 39758eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 39768eb6488eSEric Joyner /* Some devices use SDP0 for important information */ 39778eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP || 39788eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP || 39798eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N || 39808eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) 39818eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw); 39828eb6488eSEric Joyner if (hw->phy.type == ixgbe_phy_x550em_ext_t) 39838eb6488eSEric Joyner mask |= IXGBE_EICR_GPI_SDP0_X540; 39848eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 39858eb6488eSEric Joyner break; 39868eb6488eSEric Joyner default: 39878eb6488eSEric Joyner break; 39888eb6488eSEric Joyner } 39898eb6488eSEric Joyner 39908eb6488eSEric Joyner /* Enable Fan Failure detection */ 3991b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_FAN_FAIL) 39928eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP1; 39938eb6488eSEric Joyner /* Enable SR-IOV */ 3994b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_SRIOV) 39958eb6488eSEric Joyner mask |= IXGBE_EIMS_MAILBOX; 39968eb6488eSEric Joyner /* Enable Flow Director */ 3997b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_FDIR) 39988eb6488eSEric Joyner mask |= IXGBE_EIMS_FLOW_DIR; 39998eb6488eSEric Joyner 40008eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); 40018eb6488eSEric Joyner 40028eb6488eSEric Joyner /* With MSI-X we use auto clear */ 4003b1d5caf3SKevin Bowling if (sc->intr_type == IFLIB_INTR_MSIX) { 40048eb6488eSEric Joyner mask = IXGBE_EIMS_ENABLE_MASK; 40058eb6488eSEric Joyner /* Don't autoclear Link */ 40068eb6488eSEric Joyner mask &= ~IXGBE_EIMS_OTHER; 40078eb6488eSEric Joyner mask &= ~IXGBE_EIMS_LSC; 4008b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_SRIOV) 40098eb6488eSEric Joyner mask &= ~IXGBE_EIMS_MAILBOX; 40108eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask); 40116f37f232SEric Joyner } 40126f37f232SEric Joyner 4013758cc3dcSJack F Vogel /* 40148eb6488eSEric Joyner * Now enable all queues, this is done separately to 40158eb6488eSEric Joyner * allow for handling the extended (beyond 32) MSI-X 40168eb6488eSEric Joyner * vectors that can be used by 82599 4017758cc3dcSJack F Vogel */ 4018b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++, que++) 4019b1d5caf3SKevin Bowling ixgbe_enable_queue(sc, que->msix); 40208eb6488eSEric Joyner 40218eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 40228eb6488eSEric Joyner 4023c19c7afeSEric Joyner } /* ixgbe_if_enable_intr */ 40248eb6488eSEric Joyner 40258eb6488eSEric Joyner /************************************************************************ 40268eb6488eSEric Joyner * ixgbe_disable_intr 40278eb6488eSEric Joyner ************************************************************************/ 4028758cc3dcSJack F Vogel static void 4029c19c7afeSEric Joyner ixgbe_if_disable_intr(if_ctx_t ctx) 4030758cc3dcSJack F Vogel { 4031b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 4032c19c7afeSEric Joyner 4033b1d5caf3SKevin Bowling if (sc->intr_type == IFLIB_INTR_MSIX) 4034b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAC, 0); 4035b1d5caf3SKevin Bowling if (sc->hw.mac.type == ixgbe_mac_82598EB) { 4036b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC, ~0); 40378eb6488eSEric Joyner } else { 4038b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC, 0xFFFF0000); 4039b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC_EX(0), ~0); 4040b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC_EX(1), ~0); 40418eb6488eSEric Joyner } 4042b1d5caf3SKevin Bowling IXGBE_WRITE_FLUSH(&sc->hw); 4043758cc3dcSJack F Vogel 4044c19c7afeSEric Joyner } /* ixgbe_if_disable_intr */ 40458eb6488eSEric Joyner 40468eb6488eSEric Joyner /************************************************************************ 4047b2c1e8e6SEric Joyner * ixgbe_link_intr_enable 4048b2c1e8e6SEric Joyner ************************************************************************/ 4049b2c1e8e6SEric Joyner static void 4050b2c1e8e6SEric Joyner ixgbe_link_intr_enable(if_ctx_t ctx) 4051b2c1e8e6SEric Joyner { 4052*c58d34ddSKevin Bowling struct ixgbe_hw *hw = 4053*c58d34ddSKevin Bowling &((struct ixgbe_softc *)iflib_get_softc(ctx))->hw; 4054b2c1e8e6SEric Joyner 4055b2c1e8e6SEric Joyner /* Re-enable other interrupts */ 4056b2c1e8e6SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC); 4057b2c1e8e6SEric Joyner } /* ixgbe_link_intr_enable */ 4058b2c1e8e6SEric Joyner 4059b2c1e8e6SEric Joyner /************************************************************************ 4060c19c7afeSEric Joyner * ixgbe_if_rx_queue_intr_enable 4061c19c7afeSEric Joyner ************************************************************************/ 4062c19c7afeSEric Joyner static int 4063c19c7afeSEric Joyner ixgbe_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid) 4064c19c7afeSEric Joyner { 4065b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 4066b1d5caf3SKevin Bowling struct ix_rx_queue *que = &sc->rx_queues[rxqid]; 4067c19c7afeSEric Joyner 4068b1d5caf3SKevin Bowling ixgbe_enable_queue(sc, que->msix); 4069c19c7afeSEric Joyner 4070c19c7afeSEric Joyner return (0); 4071c19c7afeSEric Joyner } /* ixgbe_if_rx_queue_intr_enable */ 4072c19c7afeSEric Joyner 4073c19c7afeSEric Joyner /************************************************************************ 4074c19c7afeSEric Joyner * ixgbe_enable_queue 40758eb6488eSEric Joyner ************************************************************************/ 40768eb6488eSEric Joyner static void 4077b1d5caf3SKevin Bowling ixgbe_enable_queue(struct ixgbe_softc *sc, u32 vector) 40788eb6488eSEric Joyner { 4079b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 40802dc2d580SEric Joyner u64 queue = 1ULL << vector; 4081c19c7afeSEric Joyner u32 mask; 4082758cc3dcSJack F Vogel 4083c19c7afeSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) { 4084c19c7afeSEric Joyner mask = (IXGBE_EIMS_RTX_QUEUE & queue); 4085c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); 4086c19c7afeSEric Joyner } else { 4087c19c7afeSEric Joyner mask = (queue & 0xFFFFFFFF); 4088c19c7afeSEric Joyner if (mask) 4089c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); 4090c19c7afeSEric Joyner mask = (queue >> 32); 4091c19c7afeSEric Joyner if (mask) 4092c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask); 4093c19c7afeSEric Joyner } 4094c19c7afeSEric Joyner } /* ixgbe_enable_queue */ 4095c19c7afeSEric Joyner 4096c19c7afeSEric Joyner /************************************************************************ 4097c19c7afeSEric Joyner * ixgbe_disable_queue 4098c19c7afeSEric Joyner ************************************************************************/ 4099c19c7afeSEric Joyner static void 4100b1d5caf3SKevin Bowling ixgbe_disable_queue(struct ixgbe_softc *sc, u32 vector) 4101c19c7afeSEric Joyner { 4102b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 41032dc2d580SEric Joyner u64 queue = 1ULL << vector; 4104c19c7afeSEric Joyner u32 mask; 4105c19c7afeSEric Joyner 4106c19c7afeSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) { 4107c19c7afeSEric Joyner mask = (IXGBE_EIMS_RTX_QUEUE & queue); 4108c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask); 4109c19c7afeSEric Joyner } else { 4110c19c7afeSEric Joyner mask = (queue & 0xFFFFFFFF); 4111c19c7afeSEric Joyner if (mask) 4112c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask); 4113c19c7afeSEric Joyner mask = (queue >> 32); 4114c19c7afeSEric Joyner if (mask) 4115c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask); 4116c19c7afeSEric Joyner } 4117c19c7afeSEric Joyner } /* ixgbe_disable_queue */ 4118c19c7afeSEric Joyner 4119c19c7afeSEric Joyner /************************************************************************ 4120c19c7afeSEric Joyner * ixgbe_intr - Legacy Interrupt Service Routine 4121c19c7afeSEric Joyner ************************************************************************/ 4122c19c7afeSEric Joyner int 4123c19c7afeSEric Joyner ixgbe_intr(void *arg) 4124c19c7afeSEric Joyner { 4125b1d5caf3SKevin Bowling struct ixgbe_softc *sc = arg; 4126b1d5caf3SKevin Bowling struct ix_rx_queue *que = sc->rx_queues; 4127b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 4128b1d5caf3SKevin Bowling if_ctx_t ctx = sc->ctx; 4129c19c7afeSEric Joyner u32 eicr, eicr_mask; 4130758cc3dcSJack F Vogel 41318eb6488eSEric Joyner eicr = IXGBE_READ_REG(hw, IXGBE_EICR); 4132758cc3dcSJack F Vogel 41338eb6488eSEric Joyner ++que->irqs; 41348eb6488eSEric Joyner if (eicr == 0) { 4135c19c7afeSEric Joyner ixgbe_if_enable_intr(ctx); 4136c19c7afeSEric Joyner return (FILTER_HANDLED); 4137758cc3dcSJack F Vogel } 4138758cc3dcSJack F Vogel 41398eb6488eSEric Joyner /* Check for fan failure */ 4140f72de14eSKevin Bowling if ((sc->feat_en & IXGBE_FEATURE_FAN_FAIL) && 4141c19c7afeSEric Joyner (eicr & IXGBE_EICR_GPI_SDP1)) { 4142b1d5caf3SKevin Bowling device_printf(sc->dev, 4143c19c7afeSEric Joyner "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n"); 4144*c58d34ddSKevin Bowling IXGBE_WRITE_REG(hw, IXGBE_EIMS, 4145*c58d34ddSKevin Bowling IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 4146758cc3dcSJack F Vogel } 4147758cc3dcSJack F Vogel 41488eb6488eSEric Joyner /* Link status change */ 4149c19c7afeSEric Joyner if (eicr & IXGBE_EICR_LSC) { 4150c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); 4151c19c7afeSEric Joyner iflib_admin_intr_deferred(ctx); 4152c19c7afeSEric Joyner } 41538eb6488eSEric Joyner 41548eb6488eSEric Joyner if (ixgbe_is_sfp(hw)) { 41558eb6488eSEric Joyner /* Pluggable optics-related interrupt */ 41568eb6488eSEric Joyner if (hw->mac.type >= ixgbe_mac_X540) 41578eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP0_X540; 41588eb6488eSEric Joyner else 41598eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); 41608eb6488eSEric Joyner 41618eb6488eSEric Joyner if (eicr & eicr_mask) { 41628eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); 4163b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MOD; 41648eb6488eSEric Joyner } 41658eb6488eSEric Joyner 41668eb6488eSEric Joyner if ((hw->mac.type == ixgbe_mac_82599EB) && 41678eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { 41688eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, 41698eb6488eSEric Joyner IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 4170b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MSF; 41718eb6488eSEric Joyner } 41728eb6488eSEric Joyner } 41738eb6488eSEric Joyner 41748eb6488eSEric Joyner /* External PHY interrupt */ 41758eb6488eSEric Joyner if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && 41768eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP0_X540)) 4177b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_PHY; 41788eb6488eSEric Joyner 4179c19c7afeSEric Joyner return (FILTER_SCHEDULE_THREAD); 4180c19c7afeSEric Joyner } /* ixgbe_intr */ 41818eb6488eSEric Joyner 41828eb6488eSEric Joyner /************************************************************************ 41838eb6488eSEric Joyner * ixgbe_free_pci_resources 41848eb6488eSEric Joyner ************************************************************************/ 41858eb6488eSEric Joyner static void 4186c19c7afeSEric Joyner ixgbe_free_pci_resources(if_ctx_t ctx) 41878eb6488eSEric Joyner { 4188b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 4189b1d5caf3SKevin Bowling struct ix_rx_queue *que = sc->rx_queues; 4190c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 41918eb6488eSEric Joyner 4192b97de13aSMarius Strobl /* Release all MSI-X queue resources */ 4193b1d5caf3SKevin Bowling if (sc->intr_type == IFLIB_INTR_MSIX) 4194b1d5caf3SKevin Bowling iflib_irq_free(ctx, &sc->irq); 4195c19c7afeSEric Joyner 4196c19c7afeSEric Joyner if (que != NULL) { 4197b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++, que++) { 4198c19c7afeSEric Joyner iflib_irq_free(ctx, &que->que_irq); 4199c19c7afeSEric Joyner } 4200c19c7afeSEric Joyner } 42018eb6488eSEric Joyner 4202b1d5caf3SKevin Bowling if (sc->pci_mem != NULL) 4203c19c7afeSEric Joyner bus_release_resource(dev, SYS_RES_MEMORY, 4204b1d5caf3SKevin Bowling rman_get_rid(sc->pci_mem), sc->pci_mem); 42058eb6488eSEric Joyner } /* ixgbe_free_pci_resources */ 42068eb6488eSEric Joyner 42078eb6488eSEric Joyner /************************************************************************ 42088eb6488eSEric Joyner * ixgbe_sysctl_flowcntl 42098eb6488eSEric Joyner * 42108eb6488eSEric Joyner * SYSCTL wrapper around setting Flow Control 42118eb6488eSEric Joyner ************************************************************************/ 4212758cc3dcSJack F Vogel static int 4213f2c4db54SSteven Hartland ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS) 4214758cc3dcSJack F Vogel { 4215b1d5caf3SKevin Bowling struct ixgbe_softc *sc; 42168eb6488eSEric Joyner int error, fc; 4217758cc3dcSJack F Vogel 4218b1d5caf3SKevin Bowling sc = (struct ixgbe_softc *)arg1; 4219b1d5caf3SKevin Bowling fc = sc->hw.fc.current_mode; 4220f2c4db54SSteven Hartland 4221f2c4db54SSteven Hartland error = sysctl_handle_int(oidp, &fc, 0, req); 4222758cc3dcSJack F Vogel if ((error) || (req->newptr == NULL)) 4223758cc3dcSJack F Vogel return (error); 4224758cc3dcSJack F Vogel 4225758cc3dcSJack F Vogel /* Don't bother if it's not changed */ 4226b1d5caf3SKevin Bowling if (fc == sc->hw.fc.current_mode) 4227758cc3dcSJack F Vogel return (0); 4228758cc3dcSJack F Vogel 4229b1d5caf3SKevin Bowling return ixgbe_set_flowcntl(sc, fc); 42308eb6488eSEric Joyner } /* ixgbe_sysctl_flowcntl */ 4231f2c4db54SSteven Hartland 42328eb6488eSEric Joyner /************************************************************************ 42338eb6488eSEric Joyner * ixgbe_set_flowcntl - Set flow control 42348eb6488eSEric Joyner * 42358eb6488eSEric Joyner * Flow control values: 42368eb6488eSEric Joyner * 0 - off 42378eb6488eSEric Joyner * 1 - rx pause 42388eb6488eSEric Joyner * 2 - tx pause 42398eb6488eSEric Joyner * 3 - full 42408eb6488eSEric Joyner ************************************************************************/ 4241f2c4db54SSteven Hartland static int 4242b1d5caf3SKevin Bowling ixgbe_set_flowcntl(struct ixgbe_softc *sc, int fc) 4243f2c4db54SSteven Hartland { 4244f2c4db54SSteven Hartland switch (fc) { 4245758cc3dcSJack F Vogel case ixgbe_fc_rx_pause: 4246758cc3dcSJack F Vogel case ixgbe_fc_tx_pause: 4247758cc3dcSJack F Vogel case ixgbe_fc_full: 4248b1d5caf3SKevin Bowling sc->hw.fc.requested_mode = fc; 4249b1d5caf3SKevin Bowling if (sc->num_rx_queues > 1) 4250b1d5caf3SKevin Bowling ixgbe_disable_rx_drop(sc); 4251758cc3dcSJack F Vogel break; 4252758cc3dcSJack F Vogel case ixgbe_fc_none: 4253b1d5caf3SKevin Bowling sc->hw.fc.requested_mode = ixgbe_fc_none; 4254b1d5caf3SKevin Bowling if (sc->num_rx_queues > 1) 4255b1d5caf3SKevin Bowling ixgbe_enable_rx_drop(sc); 4256758cc3dcSJack F Vogel break; 4257758cc3dcSJack F Vogel default: 4258758cc3dcSJack F Vogel return (EINVAL); 4259758cc3dcSJack F Vogel } 42608eb6488eSEric Joyner 4261758cc3dcSJack F Vogel /* Don't autoneg if forcing a value */ 4262b1d5caf3SKevin Bowling sc->hw.fc.disable_fc_autoneg = true; 4263b1d5caf3SKevin Bowling ixgbe_fc_enable(&sc->hw); 42648eb6488eSEric Joyner 4265f2c4db54SSteven Hartland return (0); 42668eb6488eSEric Joyner } /* ixgbe_set_flowcntl */ 42678eb6488eSEric Joyner 42688eb6488eSEric Joyner /************************************************************************ 42698eb6488eSEric Joyner * ixgbe_enable_rx_drop 42708eb6488eSEric Joyner * 42718eb6488eSEric Joyner * Enable the hardware to drop packets when the buffer is 42728eb6488eSEric Joyner * full. This is useful with multiqueue, so that no single 42738eb6488eSEric Joyner * queue being full stalls the entire RX engine. We only 42748eb6488eSEric Joyner * enable this when Multiqueue is enabled AND Flow Control 42758eb6488eSEric Joyner * is disabled. 42768eb6488eSEric Joyner ************************************************************************/ 42778eb6488eSEric Joyner static void 4278b1d5caf3SKevin Bowling ixgbe_enable_rx_drop(struct ixgbe_softc *sc) 42798eb6488eSEric Joyner { 4280b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 42818eb6488eSEric Joyner struct rx_ring *rxr; 42828eb6488eSEric Joyner u32 srrctl; 42838eb6488eSEric Joyner 4284b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++) { 4285b1d5caf3SKevin Bowling rxr = &sc->rx_queues[i].rxr; 42868eb6488eSEric Joyner srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); 42878eb6488eSEric Joyner srrctl |= IXGBE_SRRCTL_DROP_EN; 42888eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); 4289758cc3dcSJack F Vogel } 4290758cc3dcSJack F Vogel 42918eb6488eSEric Joyner /* enable drop for each vf */ 4292b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_vfs; i++) { 42938eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_QDE, 4294*c58d34ddSKevin Bowling (IXGBE_QDE_WRITE | 4295*c58d34ddSKevin Bowling (i << IXGBE_QDE_IDX_SHIFT) | 42968eb6488eSEric Joyner IXGBE_QDE_ENABLE)); 42978eb6488eSEric Joyner } 42988eb6488eSEric Joyner } /* ixgbe_enable_rx_drop */ 42998eb6488eSEric Joyner 43008eb6488eSEric Joyner /************************************************************************ 43018eb6488eSEric Joyner * ixgbe_disable_rx_drop 43028eb6488eSEric Joyner ************************************************************************/ 43038eb6488eSEric Joyner static void 4304b1d5caf3SKevin Bowling ixgbe_disable_rx_drop(struct ixgbe_softc *sc) 43058eb6488eSEric Joyner { 4306b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 43078eb6488eSEric Joyner struct rx_ring *rxr; 43088eb6488eSEric Joyner u32 srrctl; 43098eb6488eSEric Joyner 4310b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++) { 4311b1d5caf3SKevin Bowling rxr = &sc->rx_queues[i].rxr; 43128eb6488eSEric Joyner srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); 43138eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_DROP_EN; 43148eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); 43158eb6488eSEric Joyner } 43168eb6488eSEric Joyner 43178eb6488eSEric Joyner /* disable drop for each vf */ 4318b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_vfs; i++) { 43198eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_QDE, 43208eb6488eSEric Joyner (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT))); 43218eb6488eSEric Joyner } 43228eb6488eSEric Joyner } /* ixgbe_disable_rx_drop */ 43238eb6488eSEric Joyner 43248eb6488eSEric Joyner /************************************************************************ 43258eb6488eSEric Joyner * ixgbe_sysctl_advertise 43268eb6488eSEric Joyner * 43278eb6488eSEric Joyner * SYSCTL wrapper around setting advertised speed 43288eb6488eSEric Joyner ************************************************************************/ 4329758cc3dcSJack F Vogel static int 4330f2c4db54SSteven Hartland ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS) 4331758cc3dcSJack F Vogel { 4332b1d5caf3SKevin Bowling struct ixgbe_softc *sc; 43338eb6488eSEric Joyner int error, advertise; 4334758cc3dcSJack F Vogel 4335b1d5caf3SKevin Bowling sc = (struct ixgbe_softc *)arg1; 4336f72de14eSKevin Bowling if (atomic_load_acq_int(&sc->recovery_mode)) 4337f72de14eSKevin Bowling return (EPERM); 4338f72de14eSKevin Bowling 4339b1d5caf3SKevin Bowling advertise = sc->advertise; 4340758cc3dcSJack F Vogel 4341f2c4db54SSteven Hartland error = sysctl_handle_int(oidp, &advertise, 0, req); 4342758cc3dcSJack F Vogel if ((error) || (req->newptr == NULL)) 4343758cc3dcSJack F Vogel return (error); 4344758cc3dcSJack F Vogel 4345b1d5caf3SKevin Bowling return ixgbe_set_advertise(sc, advertise); 43468eb6488eSEric Joyner } /* ixgbe_sysctl_advertise */ 4347f2c4db54SSteven Hartland 43488eb6488eSEric Joyner /************************************************************************ 43498eb6488eSEric Joyner * ixgbe_set_advertise - Control advertised link speed 43508eb6488eSEric Joyner * 43518eb6488eSEric Joyner * Flags: 43528eb6488eSEric Joyner * 0x1 - advertise 100 Mb 43538eb6488eSEric Joyner * 0x2 - advertise 1G 43548eb6488eSEric Joyner * 0x4 - advertise 10G 43558eb6488eSEric Joyner * 0x8 - advertise 10 Mb (yes, Mb) 4356d381c807SPiotr Pietruszewski * 0x10 - advertise 2.5G (disabled by default) 4357d381c807SPiotr Pietruszewski * 0x20 - advertise 5G (disabled by default) 4358d381c807SPiotr Pietruszewski * 43598eb6488eSEric Joyner ************************************************************************/ 4360f2c4db54SSteven Hartland static int 4361b1d5caf3SKevin Bowling ixgbe_set_advertise(struct ixgbe_softc *sc, int advertise) 4362f2c4db54SSteven Hartland { 4363b1d5caf3SKevin Bowling device_t dev = iflib_get_dev(sc->ctx); 4364f2c4db54SSteven Hartland struct ixgbe_hw *hw; 43658eb6488eSEric Joyner ixgbe_link_speed speed = 0; 43668eb6488eSEric Joyner ixgbe_link_speed link_caps = 0; 43678eb6488eSEric Joyner s32 err = IXGBE_NOT_IMPLEMENTED; 436879b36ec9SKevin Bowling bool negotiate = false; 4369f2c4db54SSteven Hartland 4370d775d23aSSteven Hartland /* Checks to validate new value */ 4371b1d5caf3SKevin Bowling if (sc->advertise == advertise) /* no change */ 4372d775d23aSSteven Hartland return (0); 4373d775d23aSSteven Hartland 4374b1d5caf3SKevin Bowling hw = &sc->hw; 4375f2c4db54SSteven Hartland 4376a9ca1c79SSean Bruno /* No speed changes for backplane media */ 4377a9ca1c79SSean Bruno if (hw->phy.media_type == ixgbe_media_type_backplane) 4378a9ca1c79SSean Bruno return (ENODEV); 4379a9ca1c79SSean Bruno 4380758cc3dcSJack F Vogel if (!((hw->phy.media_type == ixgbe_media_type_copper) || 4381758cc3dcSJack F Vogel (hw->phy.multispeed_fiber))) { 4382*c58d34ddSKevin Bowling device_printf(dev, 4383*c58d34ddSKevin Bowling "Advertised speed can only be set on copper or multispeed" 4384*c58d34ddSKevin Bowling " fiber media types.\n"); 4385758cc3dcSJack F Vogel return (EINVAL); 4386758cc3dcSJack F Vogel } 4387758cc3dcSJack F Vogel 4388d381c807SPiotr Pietruszewski if (advertise < 0x1 || advertise > 0x3F) { 4389*c58d34ddSKevin Bowling device_printf(dev, 4390*c58d34ddSKevin Bowling "Invalid advertised speed; valid modes are 0x1 through" 4391*c58d34ddSKevin Bowling " 0x3F\n"); 4392758cc3dcSJack F Vogel return (EINVAL); 4393758cc3dcSJack F Vogel } 4394758cc3dcSJack F Vogel 43958eb6488eSEric Joyner if (hw->mac.ops.get_link_capabilities) { 43968eb6488eSEric Joyner err = hw->mac.ops.get_link_capabilities(hw, &link_caps, 43978eb6488eSEric Joyner &negotiate); 43988eb6488eSEric Joyner if (err != IXGBE_SUCCESS) { 4399*c58d34ddSKevin Bowling device_printf(dev, 4400*c58d34ddSKevin Bowling "Unable to determine supported advertise speeds" 4401*c58d34ddSKevin Bowling "\n"); 44028eb6488eSEric Joyner return (ENODEV); 44038eb6488eSEric Joyner } 4404758cc3dcSJack F Vogel } 4405758cc3dcSJack F Vogel 4406758cc3dcSJack F Vogel /* Set new value and report new advertised mode */ 44078eb6488eSEric Joyner if (advertise & 0x1) { 44088eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_100_FULL)) { 4409*c58d34ddSKevin Bowling device_printf(dev, 4410*c58d34ddSKevin Bowling "Interface does not support 100Mb advertised" 4411*c58d34ddSKevin Bowling " speed\n"); 44128eb6488eSEric Joyner return (EINVAL); 44138eb6488eSEric Joyner } 4414758cc3dcSJack F Vogel speed |= IXGBE_LINK_SPEED_100_FULL; 44158eb6488eSEric Joyner } 44168eb6488eSEric Joyner if (advertise & 0x2) { 44178eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_1GB_FULL)) { 4418*c58d34ddSKevin Bowling device_printf(dev, 4419*c58d34ddSKevin Bowling "Interface does not support 1Gb advertised speed" 4420*c58d34ddSKevin Bowling "\n"); 44218eb6488eSEric Joyner return (EINVAL); 44228eb6488eSEric Joyner } 4423758cc3dcSJack F Vogel speed |= IXGBE_LINK_SPEED_1GB_FULL; 44248eb6488eSEric Joyner } 44258eb6488eSEric Joyner if (advertise & 0x4) { 44268eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_10GB_FULL)) { 4427*c58d34ddSKevin Bowling device_printf(dev, 4428*c58d34ddSKevin Bowling "Interface does not support 10Gb advertised speed" 4429*c58d34ddSKevin Bowling "\n"); 44308eb6488eSEric Joyner return (EINVAL); 44318eb6488eSEric Joyner } 4432758cc3dcSJack F Vogel speed |= IXGBE_LINK_SPEED_10GB_FULL; 44338eb6488eSEric Joyner } 44348eb6488eSEric Joyner if (advertise & 0x8) { 44358eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_10_FULL)) { 4436*c58d34ddSKevin Bowling device_printf(dev, 4437*c58d34ddSKevin Bowling "Interface does not support 10Mb advertised speed" 4438*c58d34ddSKevin Bowling "\n"); 44398eb6488eSEric Joyner return (EINVAL); 44408eb6488eSEric Joyner } 44418eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10_FULL; 44428eb6488eSEric Joyner } 4443d381c807SPiotr Pietruszewski if (advertise & 0x10) { 4444d381c807SPiotr Pietruszewski if (!(link_caps & IXGBE_LINK_SPEED_2_5GB_FULL)) { 4445*c58d34ddSKevin Bowling device_printf(dev, 4446*c58d34ddSKevin Bowling "Interface does not support 2.5G advertised speed" 4447*c58d34ddSKevin Bowling "\n"); 4448d381c807SPiotr Pietruszewski return (EINVAL); 4449d381c807SPiotr Pietruszewski } 4450d381c807SPiotr Pietruszewski speed |= IXGBE_LINK_SPEED_2_5GB_FULL; 4451d381c807SPiotr Pietruszewski } 4452d381c807SPiotr Pietruszewski if (advertise & 0x20) { 4453d381c807SPiotr Pietruszewski if (!(link_caps & IXGBE_LINK_SPEED_5GB_FULL)) { 4454*c58d34ddSKevin Bowling device_printf(dev, 4455*c58d34ddSKevin Bowling "Interface does not support 5G advertised speed" 4456*c58d34ddSKevin Bowling "\n"); 4457d381c807SPiotr Pietruszewski return (EINVAL); 4458d381c807SPiotr Pietruszewski } 4459d381c807SPiotr Pietruszewski speed |= IXGBE_LINK_SPEED_5GB_FULL; 4460d381c807SPiotr Pietruszewski } 4461758cc3dcSJack F Vogel 446279b36ec9SKevin Bowling hw->mac.autotry_restart = true; 446379b36ec9SKevin Bowling hw->mac.ops.setup_link(hw, speed, true); 4464b1d5caf3SKevin Bowling sc->advertise = advertise; 4465758cc3dcSJack F Vogel 4466f2c4db54SSteven Hartland return (0); 44678eb6488eSEric Joyner } /* ixgbe_set_advertise */ 44688eb6488eSEric Joyner 44698eb6488eSEric Joyner /************************************************************************ 4470d381c807SPiotr Pietruszewski * ixgbe_get_default_advertise - Get default advertised speed settings 44718eb6488eSEric Joyner * 44728eb6488eSEric Joyner * Formatted for sysctl usage. 44738eb6488eSEric Joyner * Flags: 44748eb6488eSEric Joyner * 0x1 - advertise 100 Mb 44758eb6488eSEric Joyner * 0x2 - advertise 1G 44768eb6488eSEric Joyner * 0x4 - advertise 10G 44778eb6488eSEric Joyner * 0x8 - advertise 10 Mb (yes, Mb) 4478d381c807SPiotr Pietruszewski * 0x10 - advertise 2.5G (disabled by default) 4479d381c807SPiotr Pietruszewski * 0x20 - advertise 5G (disabled by default) 44808eb6488eSEric Joyner ************************************************************************/ 44818eb6488eSEric Joyner static int 4482d381c807SPiotr Pietruszewski ixgbe_get_default_advertise(struct ixgbe_softc *sc) 44838eb6488eSEric Joyner { 4484b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 44858eb6488eSEric Joyner int speed; 44868eb6488eSEric Joyner ixgbe_link_speed link_caps = 0; 44878eb6488eSEric Joyner s32 err; 448879b36ec9SKevin Bowling bool negotiate = false; 4489758cc3dcSJack F Vogel 4490758cc3dcSJack F Vogel /* 44918eb6488eSEric Joyner * Advertised speed means nothing unless it's copper or 44928eb6488eSEric Joyner * multi-speed fiber 4493758cc3dcSJack F Vogel */ 44948eb6488eSEric Joyner if (!(hw->phy.media_type == ixgbe_media_type_copper) && 44958eb6488eSEric Joyner !(hw->phy.multispeed_fiber)) 4496758cc3dcSJack F Vogel return (0); 4497758cc3dcSJack F Vogel 44988eb6488eSEric Joyner err = hw->mac.ops.get_link_capabilities(hw, &link_caps, &negotiate); 44998eb6488eSEric Joyner if (err != IXGBE_SUCCESS) 45008eb6488eSEric Joyner return (0); 45018eb6488eSEric Joyner 4502d381c807SPiotr Pietruszewski if (hw->mac.type == ixgbe_mac_X550) { 4503d381c807SPiotr Pietruszewski /* 4504d381c807SPiotr Pietruszewski * 2.5G and 5G autonegotiation speeds on X550 4505d381c807SPiotr Pietruszewski * are disabled by default due to reported 4506d381c807SPiotr Pietruszewski * interoperability issues with some switches. 4507d381c807SPiotr Pietruszewski */ 4508d381c807SPiotr Pietruszewski link_caps &= ~(IXGBE_LINK_SPEED_2_5GB_FULL | 4509d381c807SPiotr Pietruszewski IXGBE_LINK_SPEED_5GB_FULL); 4510d381c807SPiotr Pietruszewski } 4511d381c807SPiotr Pietruszewski 45128eb6488eSEric Joyner speed = 4513d381c807SPiotr Pietruszewski ((link_caps & IXGBE_LINK_SPEED_10GB_FULL) ? 0x4 : 0) | 4514d381c807SPiotr Pietruszewski ((link_caps & IXGBE_LINK_SPEED_5GB_FULL) ? 0x20 : 0) | 4515d381c807SPiotr Pietruszewski ((link_caps & IXGBE_LINK_SPEED_2_5GB_FULL) ? 0x10 : 0) | 4516d381c807SPiotr Pietruszewski ((link_caps & IXGBE_LINK_SPEED_1GB_FULL) ? 0x2 : 0) | 4517d381c807SPiotr Pietruszewski ((link_caps & IXGBE_LINK_SPEED_100_FULL) ? 0x1 : 0) | 4518d381c807SPiotr Pietruszewski ((link_caps & IXGBE_LINK_SPEED_10_FULL) ? 0x8 : 0); 45198eb6488eSEric Joyner 45208eb6488eSEric Joyner return speed; 4521d381c807SPiotr Pietruszewski } /* ixgbe_get_default_advertise */ 45228eb6488eSEric Joyner 45238eb6488eSEric Joyner /************************************************************************ 45248eb6488eSEric Joyner * ixgbe_sysctl_dmac - Manage DMA Coalescing 45258eb6488eSEric Joyner * 45268eb6488eSEric Joyner * Control values: 45278eb6488eSEric Joyner * 0/1 - off / on (use default value of 1000) 45288eb6488eSEric Joyner * 45298eb6488eSEric Joyner * Legal timer values are: 45308eb6488eSEric Joyner * 50,100,250,500,1000,2000,5000,10000 45318eb6488eSEric Joyner * 45328eb6488eSEric Joyner * Turning off interrupt moderation will also turn this off. 45338eb6488eSEric Joyner ************************************************************************/ 45346f37f232SEric Joyner static int 45356f37f232SEric Joyner ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS) 45366f37f232SEric Joyner { 4537b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4538ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(sc->ctx); 45396f37f232SEric Joyner int error; 4540c19c7afeSEric Joyner u16 newval; 45416f37f232SEric Joyner 4542b1d5caf3SKevin Bowling newval = sc->dmac; 4543c19c7afeSEric Joyner error = sysctl_handle_16(oidp, &newval, 0, req); 45446f37f232SEric Joyner if ((error) || (req->newptr == NULL)) 45456f37f232SEric Joyner return (error); 45466f37f232SEric Joyner 4547a9ca1c79SSean Bruno switch (newval) { 45486f37f232SEric Joyner case 0: 45496f37f232SEric Joyner /* Disabled */ 4550b1d5caf3SKevin Bowling sc->dmac = 0; 45516f37f232SEric Joyner break; 4552a9ca1c79SSean Bruno case 1: 4553a9ca1c79SSean Bruno /* Enable and use default */ 4554b1d5caf3SKevin Bowling sc->dmac = 1000; 45556f37f232SEric Joyner break; 45566f37f232SEric Joyner case 50: 45576f37f232SEric Joyner case 100: 45586f37f232SEric Joyner case 250: 45596f37f232SEric Joyner case 500: 45606f37f232SEric Joyner case 1000: 45616f37f232SEric Joyner case 2000: 45626f37f232SEric Joyner case 5000: 45636f37f232SEric Joyner case 10000: 45646f37f232SEric Joyner /* Legal values - allow */ 4565b1d5caf3SKevin Bowling sc->dmac = newval; 45666f37f232SEric Joyner break; 45676f37f232SEric Joyner default: 45686f37f232SEric Joyner /* Do nothing, illegal value */ 45696f37f232SEric Joyner return (EINVAL); 45706f37f232SEric Joyner } 45716f37f232SEric Joyner 45726f37f232SEric Joyner /* Re-initialize hardware if it's already running */ 4573ff06a8dbSJustin Hibbits if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) 4574ff06a8dbSJustin Hibbits if_init(ifp, ifp); 45756f37f232SEric Joyner 45766f37f232SEric Joyner return (0); 45778eb6488eSEric Joyner } /* ixgbe_sysctl_dmac */ 45786f37f232SEric Joyner 4579a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 45808eb6488eSEric Joyner /************************************************************************ 45818eb6488eSEric Joyner * ixgbe_sysctl_power_state 45828eb6488eSEric Joyner * 4583a9ca1c79SSean Bruno * Sysctl to test power states 4584a9ca1c79SSean Bruno * Values: 4585a9ca1c79SSean Bruno * 0 - set device to D0 4586a9ca1c79SSean Bruno * 3 - set device to D3 4587a9ca1c79SSean Bruno * (none) - get current device power state 45888eb6488eSEric Joyner ************************************************************************/ 4589a9ca1c79SSean Bruno static int 4590a9ca1c79SSean Bruno ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS) 4591a9ca1c79SSean Bruno { 4592b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4593b1d5caf3SKevin Bowling device_t dev = sc->dev; 4594a9ca1c79SSean Bruno int curr_ps, new_ps, error = 0; 4595a9ca1c79SSean Bruno 4596a9ca1c79SSean Bruno curr_ps = new_ps = pci_get_powerstate(dev); 4597a9ca1c79SSean Bruno 4598a9ca1c79SSean Bruno error = sysctl_handle_int(oidp, &new_ps, 0, req); 4599a9ca1c79SSean Bruno if ((error) || (req->newptr == NULL)) 4600a9ca1c79SSean Bruno return (error); 4601a9ca1c79SSean Bruno 4602a9ca1c79SSean Bruno if (new_ps == curr_ps) 4603a9ca1c79SSean Bruno return (0); 4604a9ca1c79SSean Bruno 4605a9ca1c79SSean Bruno if (new_ps == 3 && curr_ps == 0) 4606a9ca1c79SSean Bruno error = DEVICE_SUSPEND(dev); 4607a9ca1c79SSean Bruno else if (new_ps == 0 && curr_ps == 3) 4608a9ca1c79SSean Bruno error = DEVICE_RESUME(dev); 4609a9ca1c79SSean Bruno else 4610a9ca1c79SSean Bruno return (EINVAL); 4611a9ca1c79SSean Bruno 4612a9ca1c79SSean Bruno device_printf(dev, "New state: %d\n", pci_get_powerstate(dev)); 4613a9ca1c79SSean Bruno 4614a9ca1c79SSean Bruno return (error); 46158eb6488eSEric Joyner } /* ixgbe_sysctl_power_state */ 4616a9ca1c79SSean Bruno #endif 46178eb6488eSEric Joyner 46188eb6488eSEric Joyner /************************************************************************ 46198eb6488eSEric Joyner * ixgbe_sysctl_wol_enable 46208eb6488eSEric Joyner * 46218eb6488eSEric Joyner * Sysctl to enable/disable the WoL capability, 46228eb6488eSEric Joyner * if supported by the adapter. 46238eb6488eSEric Joyner * 46246f37f232SEric Joyner * Values: 46256f37f232SEric Joyner * 0 - disabled 46266f37f232SEric Joyner * 1 - enabled 46278eb6488eSEric Joyner ************************************************************************/ 46286f37f232SEric Joyner static int 46296f37f232SEric Joyner ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS) 46306f37f232SEric Joyner { 4631b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4632b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 46336f37f232SEric Joyner int new_wol_enabled; 46346f37f232SEric Joyner int error = 0; 46356f37f232SEric Joyner 46366f37f232SEric Joyner new_wol_enabled = hw->wol_enabled; 46376f37f232SEric Joyner error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req); 46386f37f232SEric Joyner if ((error) || (req->newptr == NULL)) 46396f37f232SEric Joyner return (error); 4640a9ca1c79SSean Bruno new_wol_enabled = !!(new_wol_enabled); 46416f37f232SEric Joyner if (new_wol_enabled == hw->wol_enabled) 46426f37f232SEric Joyner return (0); 46436f37f232SEric Joyner 4644b1d5caf3SKevin Bowling if (new_wol_enabled > 0 && !sc->wol_support) 46456f37f232SEric Joyner return (ENODEV); 46466f37f232SEric Joyner else 4647a9ca1c79SSean Bruno hw->wol_enabled = new_wol_enabled; 46486f37f232SEric Joyner 46496f37f232SEric Joyner return (0); 46508eb6488eSEric Joyner } /* ixgbe_sysctl_wol_enable */ 46516f37f232SEric Joyner 46528eb6488eSEric Joyner /************************************************************************ 46538eb6488eSEric Joyner * ixgbe_sysctl_wufc - Wake Up Filter Control 46548eb6488eSEric Joyner * 46556f37f232SEric Joyner * Sysctl to enable/disable the types of packets that the 46566f37f232SEric Joyner * adapter will wake up on upon receipt. 46576f37f232SEric Joyner * Flags: 46586f37f232SEric Joyner * 0x1 - Link Status Change 46596f37f232SEric Joyner * 0x2 - Magic Packet 46606f37f232SEric Joyner * 0x4 - Direct Exact 46616f37f232SEric Joyner * 0x8 - Directed Multicast 46626f37f232SEric Joyner * 0x10 - Broadcast 46636f37f232SEric Joyner * 0x20 - ARP/IPv4 Request Packet 46646f37f232SEric Joyner * 0x40 - Direct IPv4 Packet 46656f37f232SEric Joyner * 0x80 - Direct IPv6 Packet 46666f37f232SEric Joyner * 46678eb6488eSEric Joyner * Settings not listed above will cause the sysctl to return an error. 46688eb6488eSEric Joyner ************************************************************************/ 46696f37f232SEric Joyner static int 46706f37f232SEric Joyner ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS) 46716f37f232SEric Joyner { 4672b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 46736f37f232SEric Joyner int error = 0; 46746f37f232SEric Joyner u32 new_wufc; 46756f37f232SEric Joyner 4676b1d5caf3SKevin Bowling new_wufc = sc->wufc; 46776f37f232SEric Joyner 4678c19c7afeSEric Joyner error = sysctl_handle_32(oidp, &new_wufc, 0, req); 46796f37f232SEric Joyner if ((error) || (req->newptr == NULL)) 46806f37f232SEric Joyner return (error); 4681b1d5caf3SKevin Bowling if (new_wufc == sc->wufc) 46826f37f232SEric Joyner return (0); 46836f37f232SEric Joyner 46846f37f232SEric Joyner if (new_wufc & 0xffffff00) 46856f37f232SEric Joyner return (EINVAL); 46868eb6488eSEric Joyner 46876f37f232SEric Joyner new_wufc &= 0xff; 4688b1d5caf3SKevin Bowling new_wufc |= (0xffffff & sc->wufc); 4689b1d5caf3SKevin Bowling sc->wufc = new_wufc; 46906f37f232SEric Joyner 46916f37f232SEric Joyner return (0); 46928eb6488eSEric Joyner } /* ixgbe_sysctl_wufc */ 46936f37f232SEric Joyner 4694a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 46958eb6488eSEric Joyner /************************************************************************ 46968eb6488eSEric Joyner * ixgbe_sysctl_print_rss_config 46978eb6488eSEric Joyner ************************************************************************/ 4698a9ca1c79SSean Bruno static int 4699a9ca1c79SSean Bruno ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS) 4700a9ca1c79SSean Bruno { 4701b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4702b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 4703b1d5caf3SKevin Bowling device_t dev = sc->dev; 4704a9ca1c79SSean Bruno struct sbuf *buf; 47058eb6488eSEric Joyner int error = 0, reta_size; 4706a9ca1c79SSean Bruno u32 reg; 4707a9ca1c79SSean Bruno 4708f72de14eSKevin Bowling if (atomic_load_acq_int(&sc->recovery_mode)) 4709f72de14eSKevin Bowling return (EPERM); 4710f72de14eSKevin Bowling 4711a9ca1c79SSean Bruno buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); 4712a9ca1c79SSean Bruno if (!buf) { 4713a9ca1c79SSean Bruno device_printf(dev, "Could not allocate sbuf for output.\n"); 4714a9ca1c79SSean Bruno return (ENOMEM); 4715a9ca1c79SSean Bruno } 4716a9ca1c79SSean Bruno 4717a9ca1c79SSean Bruno // TODO: use sbufs to make a string to print out 4718a9ca1c79SSean Bruno /* Set multiplier for RETA setup and table size based on MAC */ 4719b1d5caf3SKevin Bowling switch (sc->hw.mac.type) { 4720a9ca1c79SSean Bruno case ixgbe_mac_X550: 4721a9ca1c79SSean Bruno case ixgbe_mac_X550EM_x: 47228eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 4723a9ca1c79SSean Bruno reta_size = 128; 4724a9ca1c79SSean Bruno break; 4725a9ca1c79SSean Bruno default: 4726a9ca1c79SSean Bruno reta_size = 32; 4727a9ca1c79SSean Bruno break; 4728a9ca1c79SSean Bruno } 4729a9ca1c79SSean Bruno 4730a9ca1c79SSean Bruno /* Print out the redirection table */ 4731a9ca1c79SSean Bruno sbuf_cat(buf, "\n"); 4732a9ca1c79SSean Bruno for (int i = 0; i < reta_size; i++) { 4733a9ca1c79SSean Bruno if (i < 32) { 4734a9ca1c79SSean Bruno reg = IXGBE_READ_REG(hw, IXGBE_RETA(i)); 4735a9ca1c79SSean Bruno sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg); 4736a9ca1c79SSean Bruno } else { 4737a9ca1c79SSean Bruno reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32)); 4738a9ca1c79SSean Bruno sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg); 4739a9ca1c79SSean Bruno } 4740a9ca1c79SSean Bruno } 4741a9ca1c79SSean Bruno 4742a9ca1c79SSean Bruno // TODO: print more config 4743a9ca1c79SSean Bruno 4744a9ca1c79SSean Bruno error = sbuf_finish(buf); 4745a9ca1c79SSean Bruno if (error) 4746a9ca1c79SSean Bruno device_printf(dev, "Error finishing sbuf: %d\n", error); 4747a9ca1c79SSean Bruno 4748a9ca1c79SSean Bruno sbuf_delete(buf); 47498eb6488eSEric Joyner 4750a9ca1c79SSean Bruno return (0); 47518eb6488eSEric Joyner } /* ixgbe_sysctl_print_rss_config */ 4752a9ca1c79SSean Bruno #endif /* IXGBE_DEBUG */ 4753a9ca1c79SSean Bruno 47548eb6488eSEric Joyner /************************************************************************ 47558eb6488eSEric Joyner * ixgbe_sysctl_phy_temp - Retrieve temperature of PHY 47568eb6488eSEric Joyner * 47578eb6488eSEric Joyner * For X552/X557-AT devices using an external PHY 47588eb6488eSEric Joyner ************************************************************************/ 47598eb6488eSEric Joyner static int 47608eb6488eSEric Joyner ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS) 47618eb6488eSEric Joyner { 4762b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4763b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 47648eb6488eSEric Joyner u16 reg; 47658eb6488eSEric Joyner 4766f72de14eSKevin Bowling if (atomic_load_acq_int(&sc->recovery_mode)) 4767f72de14eSKevin Bowling return (EPERM); 4768f72de14eSKevin Bowling 47698eb6488eSEric Joyner if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { 4770b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 47718eb6488eSEric Joyner "Device has no supported external thermal sensor.\n"); 47728eb6488eSEric Joyner return (ENODEV); 47738eb6488eSEric Joyner } 47748eb6488eSEric Joyner 47758eb6488eSEric Joyner if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP, 47768eb6488eSEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) { 4777b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 4778*c58d34ddSKevin Bowling "Error reading from PHY's current temperature register" 4779*c58d34ddSKevin Bowling "\n"); 47808eb6488eSEric Joyner return (EAGAIN); 47818eb6488eSEric Joyner } 47828eb6488eSEric Joyner 47838eb6488eSEric Joyner /* Shift temp for output */ 47848eb6488eSEric Joyner reg = reg >> 8; 47858eb6488eSEric Joyner 4786c19c7afeSEric Joyner return (sysctl_handle_16(oidp, NULL, reg, req)); 47878eb6488eSEric Joyner } /* ixgbe_sysctl_phy_temp */ 47888eb6488eSEric Joyner 47898eb6488eSEric Joyner /************************************************************************ 47908eb6488eSEric Joyner * ixgbe_sysctl_phy_overtemp_occurred 47918eb6488eSEric Joyner * 47928eb6488eSEric Joyner * Reports (directly from the PHY) whether the current PHY 47938eb6488eSEric Joyner * temperature is over the overtemp threshold. 47948eb6488eSEric Joyner ************************************************************************/ 47958eb6488eSEric Joyner static int 47968eb6488eSEric Joyner ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS) 47978eb6488eSEric Joyner { 4798b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4799b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 48008eb6488eSEric Joyner u16 reg; 48018eb6488eSEric Joyner 4802f72de14eSKevin Bowling if (atomic_load_acq_int(&sc->recovery_mode)) 4803f72de14eSKevin Bowling return (EPERM); 4804f72de14eSKevin Bowling 48058eb6488eSEric Joyner if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { 4806b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 48078eb6488eSEric Joyner "Device has no supported external thermal sensor.\n"); 48088eb6488eSEric Joyner return (ENODEV); 48098eb6488eSEric Joyner } 48108eb6488eSEric Joyner 48118eb6488eSEric Joyner if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS, 48128eb6488eSEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) { 4813b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 48148eb6488eSEric Joyner "Error reading from PHY's temperature status register\n"); 48158eb6488eSEric Joyner return (EAGAIN); 48168eb6488eSEric Joyner } 48178eb6488eSEric Joyner 48188eb6488eSEric Joyner /* Get occurrence bit */ 48198eb6488eSEric Joyner reg = !!(reg & 0x4000); 48208eb6488eSEric Joyner 4821c19c7afeSEric Joyner return (sysctl_handle_16(oidp, 0, reg, req)); 48228eb6488eSEric Joyner } /* ixgbe_sysctl_phy_overtemp_occurred */ 48238eb6488eSEric Joyner 48248eb6488eSEric Joyner /************************************************************************ 48258eb6488eSEric Joyner * ixgbe_sysctl_eee_state 48268eb6488eSEric Joyner * 48278eb6488eSEric Joyner * Sysctl to set EEE power saving feature 48288eb6488eSEric Joyner * Values: 48298eb6488eSEric Joyner * 0 - disable EEE 48308eb6488eSEric Joyner * 1 - enable EEE 48318eb6488eSEric Joyner * (none) - get current device EEE state 48328eb6488eSEric Joyner ************************************************************************/ 48338eb6488eSEric Joyner static int 48348eb6488eSEric Joyner ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS) 48358eb6488eSEric Joyner { 4836b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4837b1d5caf3SKevin Bowling device_t dev = sc->dev; 4838ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(sc->ctx); 48398eb6488eSEric Joyner int curr_eee, new_eee, error = 0; 48408eb6488eSEric Joyner s32 retval; 48418eb6488eSEric Joyner 4842f72de14eSKevin Bowling if (atomic_load_acq_int(&sc->recovery_mode)) 4843f72de14eSKevin Bowling return (EPERM); 4844f72de14eSKevin Bowling 4845b1d5caf3SKevin Bowling curr_eee = new_eee = !!(sc->feat_en & IXGBE_FEATURE_EEE); 48468eb6488eSEric Joyner 48478eb6488eSEric Joyner error = sysctl_handle_int(oidp, &new_eee, 0, req); 48488eb6488eSEric Joyner if ((error) || (req->newptr == NULL)) 48498eb6488eSEric Joyner return (error); 48508eb6488eSEric Joyner 48518eb6488eSEric Joyner /* Nothing to do */ 48528eb6488eSEric Joyner if (new_eee == curr_eee) 48538eb6488eSEric Joyner return (0); 48548eb6488eSEric Joyner 48558eb6488eSEric Joyner /* Not supported */ 4856b1d5caf3SKevin Bowling if (!(sc->feat_cap & IXGBE_FEATURE_EEE)) 48578eb6488eSEric Joyner return (EINVAL); 48588eb6488eSEric Joyner 48598eb6488eSEric Joyner /* Bounds checking */ 48608eb6488eSEric Joyner if ((new_eee < 0) || (new_eee > 1)) 48618eb6488eSEric Joyner return (EINVAL); 48628eb6488eSEric Joyner 4863b1d5caf3SKevin Bowling retval = ixgbe_setup_eee(&sc->hw, new_eee); 48648eb6488eSEric Joyner if (retval) { 48658eb6488eSEric Joyner device_printf(dev, "Error in EEE setup: 0x%08X\n", retval); 48668eb6488eSEric Joyner return (EINVAL); 48678eb6488eSEric Joyner } 48688eb6488eSEric Joyner 48698eb6488eSEric Joyner /* Restart auto-neg */ 4870ff06a8dbSJustin Hibbits if_init(ifp, ifp); 48718eb6488eSEric Joyner 48728eb6488eSEric Joyner device_printf(dev, "New EEE state: %d\n", new_eee); 48738eb6488eSEric Joyner 48748eb6488eSEric Joyner /* Cache new value */ 48758eb6488eSEric Joyner if (new_eee) 4876b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_EEE; 48778eb6488eSEric Joyner else 4878b1d5caf3SKevin Bowling sc->feat_en &= ~IXGBE_FEATURE_EEE; 48798eb6488eSEric Joyner 48808eb6488eSEric Joyner return (error); 48818eb6488eSEric Joyner } /* ixgbe_sysctl_eee_state */ 48828eb6488eSEric Joyner 4883eea2e089SMichael Tuexen static int 4884eea2e089SMichael Tuexen ixgbe_sysctl_tso_tcp_flags_mask(SYSCTL_HANDLER_ARGS) 4885eea2e089SMichael Tuexen { 4886eea2e089SMichael Tuexen struct ixgbe_softc *sc; 4887eea2e089SMichael Tuexen u32 reg, val, shift; 4888eea2e089SMichael Tuexen int error, mask; 4889eea2e089SMichael Tuexen 4890eea2e089SMichael Tuexen sc = oidp->oid_arg1; 4891eea2e089SMichael Tuexen switch (oidp->oid_arg2) { 4892eea2e089SMichael Tuexen case 0: 4893eea2e089SMichael Tuexen reg = IXGBE_DTXTCPFLGL; 4894eea2e089SMichael Tuexen shift = 0; 4895eea2e089SMichael Tuexen break; 4896eea2e089SMichael Tuexen case 1: 4897eea2e089SMichael Tuexen reg = IXGBE_DTXTCPFLGL; 4898eea2e089SMichael Tuexen shift = 16; 4899eea2e089SMichael Tuexen break; 4900eea2e089SMichael Tuexen case 2: 4901eea2e089SMichael Tuexen reg = IXGBE_DTXTCPFLGH; 4902eea2e089SMichael Tuexen shift = 0; 4903eea2e089SMichael Tuexen break; 4904eea2e089SMichael Tuexen default: 4905eea2e089SMichael Tuexen return (EINVAL); 4906eea2e089SMichael Tuexen break; 4907eea2e089SMichael Tuexen } 4908eea2e089SMichael Tuexen val = IXGBE_READ_REG(&sc->hw, reg); 4909eea2e089SMichael Tuexen mask = (val >> shift) & 0xfff; 4910eea2e089SMichael Tuexen error = sysctl_handle_int(oidp, &mask, 0, req); 4911eea2e089SMichael Tuexen if (error != 0 || req->newptr == NULL) 4912eea2e089SMichael Tuexen return (error); 4913eea2e089SMichael Tuexen if (mask < 0 || mask > 0xfff) 4914eea2e089SMichael Tuexen return (EINVAL); 4915eea2e089SMichael Tuexen val = (val & ~(0xfff << shift)) | (mask << shift); 4916eea2e089SMichael Tuexen IXGBE_WRITE_REG(&sc->hw, reg, val); 4917eea2e089SMichael Tuexen return (0); 4918eea2e089SMichael Tuexen } 4919eea2e089SMichael Tuexen 49208eb6488eSEric Joyner /************************************************************************ 49218eb6488eSEric Joyner * ixgbe_init_device_features 49228eb6488eSEric Joyner ************************************************************************/ 49238eb6488eSEric Joyner static void 4924b1d5caf3SKevin Bowling ixgbe_init_device_features(struct ixgbe_softc *sc) 49258eb6488eSEric Joyner { 4926*c58d34ddSKevin Bowling sc->feat_cap = IXGBE_FEATURE_NETMAP | 4927*c58d34ddSKevin Bowling IXGBE_FEATURE_RSS | 4928*c58d34ddSKevin Bowling IXGBE_FEATURE_MSI | 4929*c58d34ddSKevin Bowling IXGBE_FEATURE_MSIX | 4930*c58d34ddSKevin Bowling IXGBE_FEATURE_LEGACY_IRQ; 49318eb6488eSEric Joyner 49328eb6488eSEric Joyner /* Set capabilities first... */ 4933b1d5caf3SKevin Bowling switch (sc->hw.mac.type) { 49348eb6488eSEric Joyner case ixgbe_mac_82598EB: 4935b1d5caf3SKevin Bowling if (sc->hw.device_id == IXGBE_DEV_ID_82598AT) 4936b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_FAN_FAIL; 49378eb6488eSEric Joyner break; 49388eb6488eSEric Joyner case ixgbe_mac_X540: 4939b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_SRIOV; 4940b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_FDIR; 4941b1d5caf3SKevin Bowling if ((sc->hw.device_id == IXGBE_DEV_ID_X540_BYPASS) && 4942b1d5caf3SKevin Bowling (sc->hw.bus.func == 0)) 4943b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_BYPASS; 49448eb6488eSEric Joyner break; 49458eb6488eSEric Joyner case ixgbe_mac_X550: 4946f72de14eSKevin Bowling sc->feat_cap |= IXGBE_FEATURE_RECOVERY_MODE; 4947b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR; 4948b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_SRIOV; 4949b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_FDIR; 49508eb6488eSEric Joyner break; 49518eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 4952f72de14eSKevin Bowling sc->feat_cap |= IXGBE_FEATURE_RECOVERY_MODE; 4953b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_SRIOV; 4954b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_FDIR; 4955f72de14eSKevin Bowling if (sc->hw.device_id == IXGBE_DEV_ID_X550EM_X_KR) 4956f72de14eSKevin Bowling sc->feat_cap |= IXGBE_FEATURE_EEE; 49578eb6488eSEric Joyner break; 49588eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 4959f72de14eSKevin Bowling sc->feat_cap |= IXGBE_FEATURE_RECOVERY_MODE; 4960b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_SRIOV; 4961b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_FDIR; 4962b1d5caf3SKevin Bowling sc->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ; 4963b1d5caf3SKevin Bowling if ((sc->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T) || 4964b1d5caf3SKevin Bowling (sc->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) { 4965b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR; 4966b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_EEE; 49678eb6488eSEric Joyner } 49688eb6488eSEric Joyner break; 49698eb6488eSEric Joyner case ixgbe_mac_82599EB: 4970b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_SRIOV; 4971b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_FDIR; 4972b1d5caf3SKevin Bowling if ((sc->hw.device_id == IXGBE_DEV_ID_82599_BYPASS) && 4973b1d5caf3SKevin Bowling (sc->hw.bus.func == 0)) 4974b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_BYPASS; 4975b1d5caf3SKevin Bowling if (sc->hw.device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) 4976b1d5caf3SKevin Bowling sc->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ; 49778eb6488eSEric Joyner break; 49788eb6488eSEric Joyner default: 49798eb6488eSEric Joyner break; 49808eb6488eSEric Joyner } 49818eb6488eSEric Joyner 49828eb6488eSEric Joyner /* Enabled by default... */ 49838eb6488eSEric Joyner /* Fan failure detection */ 4984b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_FAN_FAIL) 4985b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_FAN_FAIL; 49868eb6488eSEric Joyner /* Netmap */ 4987b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_NETMAP) 4988b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_NETMAP; 49898eb6488eSEric Joyner /* EEE */ 4990b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_EEE) 4991b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_EEE; 49928eb6488eSEric Joyner /* Thermal Sensor */ 4993b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_TEMP_SENSOR) 4994b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_TEMP_SENSOR; 4995f72de14eSKevin Bowling /* Recovery mode */ 4996f72de14eSKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_RECOVERY_MODE) 4997f72de14eSKevin Bowling sc->feat_en |= IXGBE_FEATURE_RECOVERY_MODE; 49988eb6488eSEric Joyner 49998eb6488eSEric Joyner /* Enabled via global sysctl... */ 50008eb6488eSEric Joyner /* Flow Director */ 50018eb6488eSEric Joyner if (ixgbe_enable_fdir) { 5002b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_FDIR) 5003b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_FDIR; 50048eb6488eSEric Joyner else 5005*c58d34ddSKevin Bowling device_printf(sc->dev, 5006*c58d34ddSKevin Bowling "Device does not support Flow Director." 5007*c58d34ddSKevin Bowling " Leaving disabled."); 50088eb6488eSEric Joyner } 50096f37f232SEric Joyner /* 50108eb6488eSEric Joyner * Message Signal Interrupts - Extended (MSI-X) 50118eb6488eSEric Joyner * Normal MSI is only enabled if MSI-X calls fail. 5012758cc3dcSJack F Vogel */ 50138eb6488eSEric Joyner if (!ixgbe_enable_msix) 5014b1d5caf3SKevin Bowling sc->feat_cap &= ~IXGBE_FEATURE_MSIX; 50158eb6488eSEric Joyner /* Receive-Side Scaling (RSS) */ 5016b1d5caf3SKevin Bowling if ((sc->feat_cap & IXGBE_FEATURE_RSS) && ixgbe_enable_rss) 5017b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_RSS; 50188eb6488eSEric Joyner 50198eb6488eSEric Joyner /* Disable features with unmet dependencies... */ 50208eb6488eSEric Joyner /* No MSI-X */ 5021b1d5caf3SKevin Bowling if (!(sc->feat_cap & IXGBE_FEATURE_MSIX)) { 5022b1d5caf3SKevin Bowling sc->feat_cap &= ~IXGBE_FEATURE_RSS; 5023b1d5caf3SKevin Bowling sc->feat_cap &= ~IXGBE_FEATURE_SRIOV; 5024b1d5caf3SKevin Bowling sc->feat_en &= ~IXGBE_FEATURE_RSS; 5025b1d5caf3SKevin Bowling sc->feat_en &= ~IXGBE_FEATURE_SRIOV; 50268eb6488eSEric Joyner } 50278eb6488eSEric Joyner } /* ixgbe_init_device_features */ 50288eb6488eSEric Joyner 50298eb6488eSEric Joyner /************************************************************************ 50308eb6488eSEric Joyner * ixgbe_check_fan_failure 50318eb6488eSEric Joyner ************************************************************************/ 50328eb6488eSEric Joyner static void 5033b1d5caf3SKevin Bowling ixgbe_check_fan_failure(struct ixgbe_softc *sc, u32 reg, bool in_interrupt) 50348eb6488eSEric Joyner { 50358eb6488eSEric Joyner u32 mask; 50368eb6488eSEric Joyner 5037b1d5caf3SKevin Bowling mask = (in_interrupt) ? IXGBE_EICR_GPI_SDP1_BY_MAC(&sc->hw) : 50388eb6488eSEric Joyner IXGBE_ESDP_SDP1; 50398eb6488eSEric Joyner 50408eb6488eSEric Joyner if (reg & mask) 5041*c58d34ddSKevin Bowling device_printf(sc->dev, 5042*c58d34ddSKevin Bowling "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n"); 50438eb6488eSEric Joyner } /* ixgbe_check_fan_failure */ 50447660e4eaSKevin Bowling 50457660e4eaSKevin Bowling /************************************************************************ 50467660e4eaSKevin Bowling * ixgbe_sbuf_fw_version 50477660e4eaSKevin Bowling ************************************************************************/ 50487660e4eaSKevin Bowling static void 50497660e4eaSKevin Bowling ixgbe_sbuf_fw_version(struct ixgbe_hw *hw, struct sbuf *buf) 50507660e4eaSKevin Bowling { 50517660e4eaSKevin Bowling struct ixgbe_nvm_version nvm_ver = {0}; 50525de5419bSKevin Bowling const char *space = ""; 50537660e4eaSKevin Bowling 5054f72de14eSKevin Bowling ixgbe_get_nvm_version(hw, &nvm_ver); /* NVM version */ 50557660e4eaSKevin Bowling ixgbe_get_oem_prod_version(hw, &nvm_ver); /* OEM's NVM version */ 5056*c58d34ddSKevin Bowling ixgbe_get_etk_id(hw, &nvm_ver); /* eTrack a build ID in Intel's SCM */ 5057f72de14eSKevin Bowling ixgbe_get_orom_version(hw, &nvm_ver); /* Option ROM */ 5058f72de14eSKevin Bowling 5059f72de14eSKevin Bowling /* FW version */ 5060f72de14eSKevin Bowling if ((nvm_ver.phy_fw_maj == 0x0 && 5061f72de14eSKevin Bowling nvm_ver.phy_fw_min == 0x0 && 5062f72de14eSKevin Bowling nvm_ver.phy_fw_id == 0x0) || 5063f72de14eSKevin Bowling (nvm_ver.phy_fw_maj == 0xF && 5064f72de14eSKevin Bowling nvm_ver.phy_fw_min == 0xFF && 5065f72de14eSKevin Bowling nvm_ver.phy_fw_id == 0xF)) { 5066f72de14eSKevin Bowling /* If major, minor and id numbers are set to 0, 5067f72de14eSKevin Bowling * reading FW version is unsupported. If major number 5068f72de14eSKevin Bowling * is set to 0xF, minor is set to 0xFF and id is set 5069f72de14eSKevin Bowling * to 0xF, this means that number read is invalid. */ 5070f72de14eSKevin Bowling } else 5071f72de14eSKevin Bowling sbuf_printf(buf, "fw %d.%d.%d ", 5072*c58d34ddSKevin Bowling nvm_ver.phy_fw_maj, nvm_ver.phy_fw_min, 5073*c58d34ddSKevin Bowling nvm_ver.phy_fw_id); 5074f72de14eSKevin Bowling 5075f72de14eSKevin Bowling /* NVM version */ 5076f72de14eSKevin Bowling if ((nvm_ver.nvm_major == 0x0 && 5077f72de14eSKevin Bowling nvm_ver.nvm_minor == 0x0 && 5078f72de14eSKevin Bowling nvm_ver.nvm_id == 0x0) || 5079f72de14eSKevin Bowling (nvm_ver.nvm_major == 0xF && 5080f72de14eSKevin Bowling nvm_ver.nvm_minor == 0xFF && 5081f72de14eSKevin Bowling nvm_ver.nvm_id == 0xF)) { 5082f72de14eSKevin Bowling /* If major, minor and id numbers are set to 0, 5083f72de14eSKevin Bowling * reading NVM version is unsupported. If major number 5084f72de14eSKevin Bowling * is set to 0xF, minor is set to 0xFF and id is set 5085f72de14eSKevin Bowling * to 0xF, this means that number read is invalid. */ 5086f72de14eSKevin Bowling } else 5087f72de14eSKevin Bowling sbuf_printf(buf, "nvm %x.%02x.%x ", 5088f72de14eSKevin Bowling nvm_ver.nvm_major, nvm_ver.nvm_minor, nvm_ver.nvm_id); 50897660e4eaSKevin Bowling 50905de5419bSKevin Bowling if (nvm_ver.oem_valid) { 50917660e4eaSKevin Bowling sbuf_printf(buf, "NVM OEM V%d.%d R%d", nvm_ver.oem_major, 50927660e4eaSKevin Bowling nvm_ver.oem_minor, nvm_ver.oem_release); 50935de5419bSKevin Bowling space = " "; 50945de5419bSKevin Bowling } 50957660e4eaSKevin Bowling 50965de5419bSKevin Bowling if (nvm_ver.or_valid) { 50975de5419bSKevin Bowling sbuf_printf(buf, "%sOption ROM V%d-b%d-p%d", 5098*c58d34ddSKevin Bowling space, nvm_ver.or_major, nvm_ver.or_build, 5099*c58d34ddSKevin Bowling nvm_ver.or_patch); 51005de5419bSKevin Bowling space = " "; 51015de5419bSKevin Bowling } 51027660e4eaSKevin Bowling 51035de5419bSKevin Bowling if (nvm_ver.etk_id != ((NVM_VER_INVALID << NVM_ETK_SHIFT) | 5104f72de14eSKevin Bowling NVM_VER_INVALID | 0xFFFFFFFF)) { 51055de5419bSKevin Bowling sbuf_printf(buf, "%seTrack 0x%08x", space, nvm_ver.etk_id); 51065de5419bSKevin Bowling } 51077660e4eaSKevin Bowling } /* ixgbe_sbuf_fw_version */ 51087660e4eaSKevin Bowling 51097660e4eaSKevin Bowling /************************************************************************ 51107660e4eaSKevin Bowling * ixgbe_print_fw_version 51117660e4eaSKevin Bowling ************************************************************************/ 51127660e4eaSKevin Bowling static void 51137660e4eaSKevin Bowling ixgbe_print_fw_version(if_ctx_t ctx) 51147660e4eaSKevin Bowling { 5115b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 5116b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 5117b1d5caf3SKevin Bowling device_t dev = sc->dev; 51187660e4eaSKevin Bowling struct sbuf *buf; 51197660e4eaSKevin Bowling int error = 0; 51207660e4eaSKevin Bowling 51217660e4eaSKevin Bowling buf = sbuf_new_auto(); 51227660e4eaSKevin Bowling if (!buf) { 51237660e4eaSKevin Bowling device_printf(dev, "Could not allocate sbuf for output.\n"); 51247660e4eaSKevin Bowling return; 51257660e4eaSKevin Bowling } 51267660e4eaSKevin Bowling 51277660e4eaSKevin Bowling ixgbe_sbuf_fw_version(hw, buf); 51287660e4eaSKevin Bowling 51297660e4eaSKevin Bowling error = sbuf_finish(buf); 51307660e4eaSKevin Bowling if (error) 51317660e4eaSKevin Bowling device_printf(dev, "Error finishing sbuf: %d\n", error); 51327660e4eaSKevin Bowling else if (sbuf_len(buf)) 51337660e4eaSKevin Bowling device_printf(dev, "%s\n", sbuf_data(buf)); 51347660e4eaSKevin Bowling 51357660e4eaSKevin Bowling sbuf_delete(buf); 51367660e4eaSKevin Bowling } /* ixgbe_print_fw_version */ 51377660e4eaSKevin Bowling 51387660e4eaSKevin Bowling /************************************************************************ 51397660e4eaSKevin Bowling * ixgbe_sysctl_print_fw_version 51407660e4eaSKevin Bowling ************************************************************************/ 51417660e4eaSKevin Bowling static int 51427660e4eaSKevin Bowling ixgbe_sysctl_print_fw_version(SYSCTL_HANDLER_ARGS) 51437660e4eaSKevin Bowling { 5144b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 5145b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 5146b1d5caf3SKevin Bowling device_t dev = sc->dev; 51477660e4eaSKevin Bowling struct sbuf *buf; 51487660e4eaSKevin Bowling int error = 0; 51497660e4eaSKevin Bowling 51507660e4eaSKevin Bowling buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); 51517660e4eaSKevin Bowling if (!buf) { 51527660e4eaSKevin Bowling device_printf(dev, "Could not allocate sbuf for output.\n"); 51537660e4eaSKevin Bowling return (ENOMEM); 51547660e4eaSKevin Bowling } 51557660e4eaSKevin Bowling 51567660e4eaSKevin Bowling ixgbe_sbuf_fw_version(hw, buf); 51577660e4eaSKevin Bowling 51587660e4eaSKevin Bowling error = sbuf_finish(buf); 51597660e4eaSKevin Bowling if (error) 51607660e4eaSKevin Bowling device_printf(dev, "Error finishing sbuf: %d\n", error); 51617660e4eaSKevin Bowling 51627660e4eaSKevin Bowling sbuf_delete(buf); 51637660e4eaSKevin Bowling 51647660e4eaSKevin Bowling return (0); 51657660e4eaSKevin Bowling } /* ixgbe_sysctl_print_fw_version */ 5166