1758cc3dcSJack F Vogel /****************************************************************************** 2758cc3dcSJack F Vogel 38eb6488eSEric Joyner Copyright (c) 2001-2017, Intel Corporation 4758cc3dcSJack F Vogel All rights reserved. 5758cc3dcSJack F Vogel 6758cc3dcSJack F Vogel Redistribution and use in source and binary forms, with or without 7758cc3dcSJack F Vogel modification, are permitted provided that the following conditions are met: 8758cc3dcSJack F Vogel 9758cc3dcSJack F Vogel 1. Redistributions of source code must retain the above copyright notice, 10758cc3dcSJack F Vogel this list of conditions and the following disclaimer. 11758cc3dcSJack F Vogel 12758cc3dcSJack F Vogel 2. Redistributions in binary form must reproduce the above copyright 13758cc3dcSJack F Vogel notice, this list of conditions and the following disclaimer in the 14758cc3dcSJack F Vogel documentation and/or other materials provided with the distribution. 15758cc3dcSJack F Vogel 16758cc3dcSJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its 17758cc3dcSJack F Vogel contributors may be used to endorse or promote products derived from 18758cc3dcSJack F Vogel this software without specific prior written permission. 19758cc3dcSJack F Vogel 20758cc3dcSJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21758cc3dcSJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22758cc3dcSJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23758cc3dcSJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24758cc3dcSJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25758cc3dcSJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26758cc3dcSJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27758cc3dcSJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28758cc3dcSJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29758cc3dcSJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30758cc3dcSJack F Vogel POSSIBILITY OF SUCH DAMAGE. 31758cc3dcSJack F Vogel 32758cc3dcSJack F Vogel ******************************************************************************/ 33758cc3dcSJack F Vogel /*$FreeBSD$*/ 34758cc3dcSJack F Vogel 35758cc3dcSJack F Vogel 36758cc3dcSJack F Vogel #include "opt_inet.h" 37758cc3dcSJack F Vogel #include "opt_inet6.h" 38758cc3dcSJack F Vogel #include "opt_rss.h" 39758cc3dcSJack F Vogel 40758cc3dcSJack F Vogel #include "ixgbe.h" 41c19c7afeSEric Joyner #include "ixgbe_sriov.h" 42c19c7afeSEric Joyner #include "ifdi_if.h" 43c19c7afeSEric Joyner 44c19c7afeSEric Joyner #include <net/netmap.h> 45c19c7afeSEric Joyner #include <dev/netmap/netmap_kern.h> 46758cc3dcSJack F Vogel 478eb6488eSEric Joyner /************************************************************************ 48758cc3dcSJack F Vogel * Driver version 498eb6488eSEric Joyner ************************************************************************/ 507d48aa4cSEric Joyner char ixgbe_driver_version[] = "4.0.1-k"; 51a9ca1c79SSean Bruno 52758cc3dcSJack F Vogel 538eb6488eSEric Joyner /************************************************************************ 54758cc3dcSJack F Vogel * PCI Device ID Table 55758cc3dcSJack F Vogel * 56758cc3dcSJack F Vogel * Used by probe to select devices to load on 57758cc3dcSJack F Vogel * Last field stores an index into ixgbe_strings 58758cc3dcSJack F Vogel * Last entry must be all 0s 59758cc3dcSJack F Vogel * 60758cc3dcSJack F Vogel * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } 618eb6488eSEric Joyner ************************************************************************/ 62c19c7afeSEric Joyner static pci_vendor_info_t ixgbe_vendor_info_array[] = 63758cc3dcSJack F Vogel { 64c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 65c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 66c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 67c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 68c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 69c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 70c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 71c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 72c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 73c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 74c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 75c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 76c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 77c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 78c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 79c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 80c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 81c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 82c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 83c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF2, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 84c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 85c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 86c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF_QP, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 87c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_QSFP_SF_QP, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 88c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 89c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 90c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 91c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 92c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 93c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 94c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 957d48aa4cSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_1G_T, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 96c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 97c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 98c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR_L, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 99c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 100c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP_N, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 101c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 102c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII_L, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 103c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_10G_T, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 104c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 105c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T_L, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 106c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_BYPASS, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 107c19c7afeSEric Joyner PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BYPASS, "Intel(R) PRO/10GbE PCI-Express Network Driver"), 108758cc3dcSJack F Vogel /* required last entry */ 109c19c7afeSEric Joyner PVID_END 110758cc3dcSJack F Vogel }; 111758cc3dcSJack F Vogel 112c19c7afeSEric Joyner static void *ixgbe_register(device_t dev); 113c19c7afeSEric Joyner static int ixgbe_if_attach_pre(if_ctx_t ctx); 114c19c7afeSEric Joyner static int ixgbe_if_attach_post(if_ctx_t ctx); 115c19c7afeSEric Joyner static int ixgbe_if_detach(if_ctx_t ctx); 116c19c7afeSEric Joyner static int ixgbe_if_shutdown(if_ctx_t ctx); 117c19c7afeSEric Joyner static int ixgbe_if_suspend(if_ctx_t ctx); 118c19c7afeSEric Joyner static int ixgbe_if_resume(if_ctx_t ctx); 119c19c7afeSEric Joyner 120c19c7afeSEric Joyner static void ixgbe_if_stop(if_ctx_t ctx); 121c19c7afeSEric Joyner void ixgbe_if_enable_intr(if_ctx_t ctx); 122c19c7afeSEric Joyner static void ixgbe_if_disable_intr(if_ctx_t ctx); 123b2c1e8e6SEric Joyner static void ixgbe_link_intr_enable(if_ctx_t ctx); 124c19c7afeSEric Joyner static int ixgbe_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid); 125c19c7afeSEric Joyner static void ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr); 126c19c7afeSEric Joyner static int ixgbe_if_media_change(if_ctx_t ctx); 127c19c7afeSEric Joyner static int ixgbe_if_msix_intr_assign(if_ctx_t, int); 128c19c7afeSEric Joyner static int ixgbe_if_mtu_set(if_ctx_t ctx, uint32_t mtu); 129c19c7afeSEric Joyner static void ixgbe_if_crcstrip_set(if_ctx_t ctx, int onoff, int strip); 130c19c7afeSEric Joyner static void ixgbe_if_multi_set(if_ctx_t ctx); 131c19c7afeSEric Joyner static int ixgbe_if_promisc_set(if_ctx_t ctx, int flags); 132c19c7afeSEric Joyner static int ixgbe_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, 133c19c7afeSEric Joyner uint64_t *paddrs, int nrxqs, int nrxqsets); 134c19c7afeSEric Joyner static int ixgbe_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, 135c19c7afeSEric Joyner uint64_t *paddrs, int nrxqs, int nrxqsets); 136c19c7afeSEric Joyner static void ixgbe_if_queues_free(if_ctx_t ctx); 137c19c7afeSEric Joyner static void ixgbe_if_timer(if_ctx_t ctx, uint16_t); 138c19c7afeSEric Joyner static void ixgbe_if_update_admin_status(if_ctx_t ctx); 139c19c7afeSEric Joyner static void ixgbe_if_vlan_register(if_ctx_t ctx, u16 vtag); 140c19c7afeSEric Joyner static void ixgbe_if_vlan_unregister(if_ctx_t ctx, u16 vtag); 141bca38080SAndrew Gallatin static int ixgbe_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req); 142cf150917SEric Joyner static bool ixgbe_if_needs_restart(if_ctx_t ctx, enum iflib_restart_event event); 143c19c7afeSEric Joyner int ixgbe_intr(void *arg); 144758cc3dcSJack F Vogel 1458eb6488eSEric Joyner /************************************************************************ 146758cc3dcSJack F Vogel * Function prototypes 1478eb6488eSEric Joyner ************************************************************************/ 148758cc3dcSJack F Vogel #if __FreeBSD_version >= 1100036 149c19c7afeSEric Joyner static uint64_t ixgbe_if_get_counter(if_ctx_t, ift_counter); 150758cc3dcSJack F Vogel #endif 151758cc3dcSJack F Vogel 152c19c7afeSEric Joyner static void ixgbe_enable_queue(struct adapter *adapter, u32 vector); 153c19c7afeSEric Joyner static void ixgbe_disable_queue(struct adapter *adapter, u32 vector); 154c19c7afeSEric Joyner static void ixgbe_add_device_sysctls(if_ctx_t ctx); 155c19c7afeSEric Joyner static int ixgbe_allocate_pci_resources(if_ctx_t ctx); 156c19c7afeSEric Joyner static int ixgbe_setup_low_power_mode(if_ctx_t ctx); 157c19c7afeSEric Joyner 158c19c7afeSEric Joyner static void ixgbe_config_dmac(struct adapter *adapter); 159c19c7afeSEric Joyner static void ixgbe_configure_ivars(struct adapter *adapter); 160c19c7afeSEric Joyner static void ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, 161c19c7afeSEric Joyner s8 type); 162c19c7afeSEric Joyner static u8 *ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); 163c19c7afeSEric Joyner static bool ixgbe_sfp_probe(if_ctx_t ctx); 164c19c7afeSEric Joyner 165c19c7afeSEric Joyner static void ixgbe_free_pci_resources(if_ctx_t ctx); 166c19c7afeSEric Joyner 167c19c7afeSEric Joyner static int ixgbe_msix_link(void *arg); 168c19c7afeSEric Joyner static int ixgbe_msix_que(void *arg); 169c19c7afeSEric Joyner static void ixgbe_initialize_rss_mapping(struct adapter *adapter); 170c19c7afeSEric Joyner static void ixgbe_initialize_receive_units(if_ctx_t ctx); 171c19c7afeSEric Joyner static void ixgbe_initialize_transmit_units(if_ctx_t ctx); 172c19c7afeSEric Joyner 173c19c7afeSEric Joyner static int ixgbe_setup_interface(if_ctx_t ctx); 174c19c7afeSEric Joyner static void ixgbe_init_device_features(struct adapter *adapter); 175c19c7afeSEric Joyner static void ixgbe_check_fan_failure(struct adapter *, u32, bool); 176c19c7afeSEric Joyner static void ixgbe_add_media_types(if_ctx_t ctx); 177c19c7afeSEric Joyner static void ixgbe_update_stats_counters(struct adapter *adapter); 178b2c1e8e6SEric Joyner static void ixgbe_config_link(if_ctx_t ctx); 179c19c7afeSEric Joyner static void ixgbe_get_slot_info(struct adapter *); 180c19c7afeSEric Joyner static void ixgbe_check_wol_support(struct adapter *adapter); 181758cc3dcSJack F Vogel static void ixgbe_enable_rx_drop(struct adapter *); 182758cc3dcSJack F Vogel static void ixgbe_disable_rx_drop(struct adapter *); 183758cc3dcSJack F Vogel 184c19c7afeSEric Joyner static void ixgbe_add_hw_stats(struct adapter *adapter); 185f2c4db54SSteven Hartland static int ixgbe_set_flowcntl(struct adapter *, int); 186f2c4db54SSteven Hartland static int ixgbe_set_advertise(struct adapter *, int); 1878eb6488eSEric Joyner static int ixgbe_get_advertise(struct adapter *); 188c19c7afeSEric Joyner static void ixgbe_setup_vlan_hw_support(if_ctx_t ctx); 189c19c7afeSEric Joyner static void ixgbe_config_gpie(struct adapter *adapter); 190c19c7afeSEric Joyner static void ixgbe_config_delay_values(struct adapter *adapter); 1916f37f232SEric Joyner 1926f37f232SEric Joyner /* Sysctl handlers */ 193f2c4db54SSteven Hartland static int ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS); 194f2c4db54SSteven Hartland static int ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS); 1958eb6488eSEric Joyner static int ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS); 1966f37f232SEric Joyner static int ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS); 1976f37f232SEric Joyner static int ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS); 1986f37f232SEric Joyner static int ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS); 199a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 200a9ca1c79SSean Bruno static int ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS); 201a9ca1c79SSean Bruno static int ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS); 202a9ca1c79SSean Bruno #endif 2038eb6488eSEric Joyner static int ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS); 2048eb6488eSEric Joyner static int ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS); 2058eb6488eSEric Joyner static int ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS); 2068eb6488eSEric Joyner static int ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS); 2078eb6488eSEric Joyner static int ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS); 2086f37f232SEric Joyner static int ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS); 2096f37f232SEric Joyner static int ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS); 210758cc3dcSJack F Vogel 211758cc3dcSJack F Vogel /* Deferred interrupt tasklets */ 212c19c7afeSEric Joyner static void ixgbe_handle_msf(void *); 213c19c7afeSEric Joyner static void ixgbe_handle_mod(void *); 214c19c7afeSEric Joyner static void ixgbe_handle_phy(void *); 215758cc3dcSJack F Vogel 2168eb6488eSEric Joyner /************************************************************************ 217758cc3dcSJack F Vogel * FreeBSD Device Interface Entry Points 2188eb6488eSEric Joyner ************************************************************************/ 219a1edda90SAdrian Chadd static device_method_t ix_methods[] = { 220758cc3dcSJack F Vogel /* Device interface */ 221c19c7afeSEric Joyner DEVMETHOD(device_register, ixgbe_register), 222c19c7afeSEric Joyner DEVMETHOD(device_probe, iflib_device_probe), 223c19c7afeSEric Joyner DEVMETHOD(device_attach, iflib_device_attach), 224c19c7afeSEric Joyner DEVMETHOD(device_detach, iflib_device_detach), 225c19c7afeSEric Joyner DEVMETHOD(device_shutdown, iflib_device_shutdown), 226c19c7afeSEric Joyner DEVMETHOD(device_suspend, iflib_device_suspend), 227c19c7afeSEric Joyner DEVMETHOD(device_resume, iflib_device_resume), 22848056c88SJack F Vogel #ifdef PCI_IOV 229c19c7afeSEric Joyner DEVMETHOD(pci_iov_init, iflib_device_iov_init), 230c19c7afeSEric Joyner DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit), 231c19c7afeSEric Joyner DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf), 23248056c88SJack F Vogel #endif /* PCI_IOV */ 233758cc3dcSJack F Vogel DEVMETHOD_END 234758cc3dcSJack F Vogel }; 235758cc3dcSJack F Vogel 236a1edda90SAdrian Chadd static driver_t ix_driver = { 237a1edda90SAdrian Chadd "ix", ix_methods, sizeof(struct adapter), 238758cc3dcSJack F Vogel }; 239758cc3dcSJack F Vogel 240a1edda90SAdrian Chadd devclass_t ix_devclass; 241a1edda90SAdrian Chadd DRIVER_MODULE(ix, pci, ix_driver, ix_devclass, 0, 0); 242937b0f25SYuri Pankov IFLIB_PNP_INFO(pci, ix_driver, ixgbe_vendor_info_array); 243a1edda90SAdrian Chadd MODULE_DEPEND(ix, pci, 1, 1, 1); 244a1edda90SAdrian Chadd MODULE_DEPEND(ix, ether, 1, 1, 1); 245c19c7afeSEric Joyner MODULE_DEPEND(ix, iflib, 1, 1, 1); 246c19c7afeSEric Joyner 247c19c7afeSEric Joyner static device_method_t ixgbe_if_methods[] = { 248c19c7afeSEric Joyner DEVMETHOD(ifdi_attach_pre, ixgbe_if_attach_pre), 249c19c7afeSEric Joyner DEVMETHOD(ifdi_attach_post, ixgbe_if_attach_post), 250c19c7afeSEric Joyner DEVMETHOD(ifdi_detach, ixgbe_if_detach), 251c19c7afeSEric Joyner DEVMETHOD(ifdi_shutdown, ixgbe_if_shutdown), 252c19c7afeSEric Joyner DEVMETHOD(ifdi_suspend, ixgbe_if_suspend), 253c19c7afeSEric Joyner DEVMETHOD(ifdi_resume, ixgbe_if_resume), 254c19c7afeSEric Joyner DEVMETHOD(ifdi_init, ixgbe_if_init), 255c19c7afeSEric Joyner DEVMETHOD(ifdi_stop, ixgbe_if_stop), 256c19c7afeSEric Joyner DEVMETHOD(ifdi_msix_intr_assign, ixgbe_if_msix_intr_assign), 257c19c7afeSEric Joyner DEVMETHOD(ifdi_intr_enable, ixgbe_if_enable_intr), 258c19c7afeSEric Joyner DEVMETHOD(ifdi_intr_disable, ixgbe_if_disable_intr), 259b2c1e8e6SEric Joyner DEVMETHOD(ifdi_link_intr_enable, ixgbe_link_intr_enable), 260c19c7afeSEric Joyner DEVMETHOD(ifdi_tx_queue_intr_enable, ixgbe_if_rx_queue_intr_enable), 261c19c7afeSEric Joyner DEVMETHOD(ifdi_rx_queue_intr_enable, ixgbe_if_rx_queue_intr_enable), 262c19c7afeSEric Joyner DEVMETHOD(ifdi_tx_queues_alloc, ixgbe_if_tx_queues_alloc), 263c19c7afeSEric Joyner DEVMETHOD(ifdi_rx_queues_alloc, ixgbe_if_rx_queues_alloc), 264c19c7afeSEric Joyner DEVMETHOD(ifdi_queues_free, ixgbe_if_queues_free), 265c19c7afeSEric Joyner DEVMETHOD(ifdi_update_admin_status, ixgbe_if_update_admin_status), 266c19c7afeSEric Joyner DEVMETHOD(ifdi_multi_set, ixgbe_if_multi_set), 267c19c7afeSEric Joyner DEVMETHOD(ifdi_mtu_set, ixgbe_if_mtu_set), 268c19c7afeSEric Joyner DEVMETHOD(ifdi_crcstrip_set, ixgbe_if_crcstrip_set), 269c19c7afeSEric Joyner DEVMETHOD(ifdi_media_status, ixgbe_if_media_status), 270c19c7afeSEric Joyner DEVMETHOD(ifdi_media_change, ixgbe_if_media_change), 271c19c7afeSEric Joyner DEVMETHOD(ifdi_promisc_set, ixgbe_if_promisc_set), 272c19c7afeSEric Joyner DEVMETHOD(ifdi_timer, ixgbe_if_timer), 273c19c7afeSEric Joyner DEVMETHOD(ifdi_vlan_register, ixgbe_if_vlan_register), 274c19c7afeSEric Joyner DEVMETHOD(ifdi_vlan_unregister, ixgbe_if_vlan_unregister), 275c19c7afeSEric Joyner DEVMETHOD(ifdi_get_counter, ixgbe_if_get_counter), 276bca38080SAndrew Gallatin DEVMETHOD(ifdi_i2c_req, ixgbe_if_i2c_req), 277cf150917SEric Joyner DEVMETHOD(ifdi_needs_restart, ixgbe_if_needs_restart), 278c19c7afeSEric Joyner #ifdef PCI_IOV 279c19c7afeSEric Joyner DEVMETHOD(ifdi_iov_init, ixgbe_if_iov_init), 280c19c7afeSEric Joyner DEVMETHOD(ifdi_iov_uninit, ixgbe_if_iov_uninit), 281c19c7afeSEric Joyner DEVMETHOD(ifdi_iov_vf_add, ixgbe_if_iov_vf_add), 282c19c7afeSEric Joyner #endif /* PCI_IOV */ 283c19c7afeSEric Joyner DEVMETHOD_END 284c19c7afeSEric Joyner }; 285758cc3dcSJack F Vogel 286758cc3dcSJack F Vogel /* 2878eb6488eSEric Joyner * TUNEABLE PARAMETERS: 288758cc3dcSJack F Vogel */ 289758cc3dcSJack F Vogel 29020b91f0aSPawel Biernacki static SYSCTL_NODE(_hw, OID_AUTO, ix, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 29120b91f0aSPawel Biernacki "IXGBE driver parameters"); 292c19c7afeSEric Joyner static driver_t ixgbe_if_driver = { 293c19c7afeSEric Joyner "ixgbe_if", ixgbe_if_methods, sizeof(struct adapter) 294c19c7afeSEric Joyner }; 295758cc3dcSJack F Vogel 296758cc3dcSJack F Vogel static int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY); 297758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN, 298758cc3dcSJack F Vogel &ixgbe_max_interrupt_rate, 0, "Maximum interrupts per second"); 299758cc3dcSJack F Vogel 300f2c4db54SSteven Hartland /* Flow control setting, default to full */ 301f2c4db54SSteven Hartland static int ixgbe_flow_control = ixgbe_fc_full; 302f2c4db54SSteven Hartland SYSCTL_INT(_hw_ix, OID_AUTO, flow_control, CTLFLAG_RDTUN, 303f2c4db54SSteven Hartland &ixgbe_flow_control, 0, "Default flow control used for all adapters"); 304f2c4db54SSteven Hartland 305f2c4db54SSteven Hartland /* Advertise Speed, default to 0 (auto) */ 306f2c4db54SSteven Hartland static int ixgbe_advertise_speed = 0; 307f2c4db54SSteven Hartland SYSCTL_INT(_hw_ix, OID_AUTO, advertise_speed, CTLFLAG_RDTUN, 308f2c4db54SSteven Hartland &ixgbe_advertise_speed, 0, "Default advertised speed for all adapters"); 309f2c4db54SSteven Hartland 310758cc3dcSJack F Vogel /* 3118eb6488eSEric Joyner * Smart speed setting, default to on 3128eb6488eSEric Joyner * this only works as a compile option 3138eb6488eSEric Joyner * right now as its during attach, set 3148eb6488eSEric Joyner * this to 'ixgbe_smart_speed_off' to 3158eb6488eSEric Joyner * disable. 316758cc3dcSJack F Vogel */ 317758cc3dcSJack F Vogel static int ixgbe_smart_speed = ixgbe_smart_speed_on; 318758cc3dcSJack F Vogel 319758cc3dcSJack F Vogel /* 3208eb6488eSEric Joyner * MSI-X should be the default for best performance, 321758cc3dcSJack F Vogel * but this allows it to be forced off for testing. 322758cc3dcSJack F Vogel */ 323758cc3dcSJack F Vogel static int ixgbe_enable_msix = 1; 324758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixgbe_enable_msix, 0, 325758cc3dcSJack F Vogel "Enable MSI-X interrupts"); 326758cc3dcSJack F Vogel 327758cc3dcSJack F Vogel /* 3288eb6488eSEric Joyner * Defining this on will allow the use 3298eb6488eSEric Joyner * of unsupported SFP+ modules, note that 3308eb6488eSEric Joyner * doing so you are on your own :) 331758cc3dcSJack F Vogel */ 332758cc3dcSJack F Vogel static int allow_unsupported_sfp = FALSE; 333fb6aa95dSSean Bruno SYSCTL_INT(_hw_ix, OID_AUTO, unsupported_sfp, CTLFLAG_RDTUN, 3348eb6488eSEric Joyner &allow_unsupported_sfp, 0, 3358eb6488eSEric Joyner "Allow unsupported SFP modules...use at your own risk"); 3368eb6488eSEric Joyner 3378eb6488eSEric Joyner /* 3388eb6488eSEric Joyner * Not sure if Flow Director is fully baked, 3398eb6488eSEric Joyner * so we'll default to turning it off. 3408eb6488eSEric Joyner */ 3418eb6488eSEric Joyner static int ixgbe_enable_fdir = 0; 3428eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_fdir, CTLFLAG_RDTUN, &ixgbe_enable_fdir, 0, 3438eb6488eSEric Joyner "Enable Flow Director"); 3448eb6488eSEric Joyner 3458eb6488eSEric Joyner /* Receive-Side Scaling */ 3468eb6488eSEric Joyner static int ixgbe_enable_rss = 1; 3478eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_rss, CTLFLAG_RDTUN, &ixgbe_enable_rss, 0, 3488eb6488eSEric Joyner "Enable Receive-Side Scaling (RSS)"); 349758cc3dcSJack F Vogel 350c19c7afeSEric Joyner #if 0 351758cc3dcSJack F Vogel /* Keep running tab on them for sanity check */ 352758cc3dcSJack F Vogel static int ixgbe_total_ports; 353c19c7afeSEric Joyner #endif 354758cc3dcSJack F Vogel 3558eb6488eSEric Joyner MALLOC_DEFINE(M_IXGBE, "ix", "ix driver allocations"); 356758cc3dcSJack F Vogel 357c19c7afeSEric Joyner /* 358c19c7afeSEric Joyner * For Flow Director: this is the number of TX packets we sample 359c19c7afeSEric Joyner * for the filter pool, this means every 20th packet will be probed. 360c19c7afeSEric Joyner * 361c19c7afeSEric Joyner * This feature can be disabled by setting this to 0. 362c19c7afeSEric Joyner */ 363c19c7afeSEric Joyner static int atr_sample_rate = 20; 364c19c7afeSEric Joyner 365c19c7afeSEric Joyner extern struct if_txrx ixgbe_txrx; 366c19c7afeSEric Joyner 367c19c7afeSEric Joyner static struct if_shared_ctx ixgbe_sctx_init = { 368c19c7afeSEric Joyner .isc_magic = IFLIB_MAGIC, 369c19c7afeSEric Joyner .isc_q_align = PAGE_SIZE,/* max(DBA_ALIGN, PAGE_SIZE) */ 3707f87c040SMarius Strobl .isc_tx_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header), 371c19c7afeSEric Joyner .isc_tx_maxsegsize = PAGE_SIZE, 3727f87c040SMarius Strobl .isc_tso_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header), 3737f87c040SMarius Strobl .isc_tso_maxsegsize = PAGE_SIZE, 374c19c7afeSEric Joyner .isc_rx_maxsize = PAGE_SIZE*4, 375c19c7afeSEric Joyner .isc_rx_nsegments = 1, 376c19c7afeSEric Joyner .isc_rx_maxsegsize = PAGE_SIZE*4, 377c19c7afeSEric Joyner .isc_nfl = 1, 378c19c7afeSEric Joyner .isc_ntxqs = 1, 379c19c7afeSEric Joyner .isc_nrxqs = 1, 380c19c7afeSEric Joyner 381c19c7afeSEric Joyner .isc_admin_intrcnt = 1, 382c19c7afeSEric Joyner .isc_vendor_info = ixgbe_vendor_info_array, 383c19c7afeSEric Joyner .isc_driver_version = ixgbe_driver_version, 384c19c7afeSEric Joyner .isc_driver = &ixgbe_if_driver, 3857aad1f4eSEric Joyner .isc_flags = IFLIB_TSO_INIT_IP, 386c19c7afeSEric Joyner 387c19c7afeSEric Joyner .isc_nrxd_min = {MIN_RXD}, 388c19c7afeSEric Joyner .isc_ntxd_min = {MIN_TXD}, 389c19c7afeSEric Joyner .isc_nrxd_max = {MAX_RXD}, 390c19c7afeSEric Joyner .isc_ntxd_max = {MAX_TXD}, 391c19c7afeSEric Joyner .isc_nrxd_default = {DEFAULT_RXD}, 392c19c7afeSEric Joyner .isc_ntxd_default = {DEFAULT_TXD}, 393c19c7afeSEric Joyner }; 394c19c7afeSEric Joyner 395c19c7afeSEric Joyner if_shared_ctx_t ixgbe_sctx = &ixgbe_sctx_init; 396c19c7afeSEric Joyner 397c19c7afeSEric Joyner /************************************************************************ 398c19c7afeSEric Joyner * ixgbe_if_tx_queues_alloc 399c19c7afeSEric Joyner ************************************************************************/ 400c19c7afeSEric Joyner static int 401c19c7afeSEric Joyner ixgbe_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, 402c19c7afeSEric Joyner int ntxqs, int ntxqsets) 403c19c7afeSEric Joyner { 404c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 405c19c7afeSEric Joyner if_softc_ctx_t scctx = adapter->shared; 406c19c7afeSEric Joyner struct ix_tx_queue *que; 407c19c7afeSEric Joyner int i, j, error; 408c19c7afeSEric Joyner 409c19c7afeSEric Joyner MPASS(adapter->num_tx_queues > 0); 410c19c7afeSEric Joyner MPASS(adapter->num_tx_queues == ntxqsets); 411c19c7afeSEric Joyner MPASS(ntxqs == 1); 412c19c7afeSEric Joyner 413c19c7afeSEric Joyner /* Allocate queue structure memory */ 414c19c7afeSEric Joyner adapter->tx_queues = 415c19c7afeSEric Joyner (struct ix_tx_queue *)malloc(sizeof(struct ix_tx_queue) * ntxqsets, 416c19c7afeSEric Joyner M_IXGBE, M_NOWAIT | M_ZERO); 417c19c7afeSEric Joyner if (!adapter->tx_queues) { 418c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), 419c19c7afeSEric Joyner "Unable to allocate TX ring memory\n"); 420c19c7afeSEric Joyner return (ENOMEM); 421c19c7afeSEric Joyner } 422c19c7afeSEric Joyner 423c19c7afeSEric Joyner for (i = 0, que = adapter->tx_queues; i < ntxqsets; i++, que++) { 424c19c7afeSEric Joyner struct tx_ring *txr = &que->txr; 425c19c7afeSEric Joyner 426c19c7afeSEric Joyner /* In case SR-IOV is enabled, align the index properly */ 427c19c7afeSEric Joyner txr->me = ixgbe_vf_que_index(adapter->iov_mode, adapter->pool, 428c19c7afeSEric Joyner i); 429c19c7afeSEric Joyner 430c19c7afeSEric Joyner txr->adapter = que->adapter = adapter; 431c19c7afeSEric Joyner 432c19c7afeSEric Joyner /* Allocate report status array */ 433c19c7afeSEric Joyner txr->tx_rsq = (qidx_t *)malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_IXGBE, M_NOWAIT | M_ZERO); 434c19c7afeSEric Joyner if (txr->tx_rsq == NULL) { 435c19c7afeSEric Joyner error = ENOMEM; 436c19c7afeSEric Joyner goto fail; 437c19c7afeSEric Joyner } 438c19c7afeSEric Joyner for (j = 0; j < scctx->isc_ntxd[0]; j++) 439c19c7afeSEric Joyner txr->tx_rsq[j] = QIDX_INVALID; 440c19c7afeSEric Joyner /* get the virtual and physical address of the hardware queues */ 441c19c7afeSEric Joyner txr->tail = IXGBE_TDT(txr->me); 442c19c7afeSEric Joyner txr->tx_base = (union ixgbe_adv_tx_desc *)vaddrs[i]; 443c19c7afeSEric Joyner txr->tx_paddr = paddrs[i]; 444c19c7afeSEric Joyner 445c19c7afeSEric Joyner txr->bytes = 0; 446c19c7afeSEric Joyner txr->total_packets = 0; 447c19c7afeSEric Joyner 448c19c7afeSEric Joyner /* Set the rate at which we sample packets */ 449c19c7afeSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FDIR) 450c19c7afeSEric Joyner txr->atr_sample = atr_sample_rate; 451c19c7afeSEric Joyner 452c19c7afeSEric Joyner } 453c19c7afeSEric Joyner 454c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), "allocated for %d queues\n", 455c19c7afeSEric Joyner adapter->num_tx_queues); 456c19c7afeSEric Joyner 457c19c7afeSEric Joyner return (0); 458c19c7afeSEric Joyner 459c19c7afeSEric Joyner fail: 460c19c7afeSEric Joyner ixgbe_if_queues_free(ctx); 461c19c7afeSEric Joyner 462c19c7afeSEric Joyner return (error); 463c19c7afeSEric Joyner } /* ixgbe_if_tx_queues_alloc */ 464c19c7afeSEric Joyner 465c19c7afeSEric Joyner /************************************************************************ 466c19c7afeSEric Joyner * ixgbe_if_rx_queues_alloc 467c19c7afeSEric Joyner ************************************************************************/ 468c19c7afeSEric Joyner static int 469c19c7afeSEric Joyner ixgbe_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, 470c19c7afeSEric Joyner int nrxqs, int nrxqsets) 471c19c7afeSEric Joyner { 472c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 473c19c7afeSEric Joyner struct ix_rx_queue *que; 474c19c7afeSEric Joyner int i; 475c19c7afeSEric Joyner 476c19c7afeSEric Joyner MPASS(adapter->num_rx_queues > 0); 477c19c7afeSEric Joyner MPASS(adapter->num_rx_queues == nrxqsets); 478c19c7afeSEric Joyner MPASS(nrxqs == 1); 479c19c7afeSEric Joyner 480c19c7afeSEric Joyner /* Allocate queue structure memory */ 481c19c7afeSEric Joyner adapter->rx_queues = 482c19c7afeSEric Joyner (struct ix_rx_queue *)malloc(sizeof(struct ix_rx_queue)*nrxqsets, 483c19c7afeSEric Joyner M_IXGBE, M_NOWAIT | M_ZERO); 484c19c7afeSEric Joyner if (!adapter->rx_queues) { 485c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), 486c19c7afeSEric Joyner "Unable to allocate TX ring memory\n"); 487c19c7afeSEric Joyner return (ENOMEM); 488c19c7afeSEric Joyner } 489c19c7afeSEric Joyner 490c19c7afeSEric Joyner for (i = 0, que = adapter->rx_queues; i < nrxqsets; i++, que++) { 491c19c7afeSEric Joyner struct rx_ring *rxr = &que->rxr; 492c19c7afeSEric Joyner 493c19c7afeSEric Joyner /* In case SR-IOV is enabled, align the index properly */ 494c19c7afeSEric Joyner rxr->me = ixgbe_vf_que_index(adapter->iov_mode, adapter->pool, 495c19c7afeSEric Joyner i); 496c19c7afeSEric Joyner 497c19c7afeSEric Joyner rxr->adapter = que->adapter = adapter; 498c19c7afeSEric Joyner 499c19c7afeSEric Joyner /* get the virtual and physical address of the hw queues */ 500c19c7afeSEric Joyner rxr->tail = IXGBE_RDT(rxr->me); 501c19c7afeSEric Joyner rxr->rx_base = (union ixgbe_adv_rx_desc *)vaddrs[i]; 502c19c7afeSEric Joyner rxr->rx_paddr = paddrs[i]; 503c19c7afeSEric Joyner rxr->bytes = 0; 504c19c7afeSEric Joyner rxr->que = que; 505c19c7afeSEric Joyner } 506c19c7afeSEric Joyner 507c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), "allocated for %d rx queues\n", 508c19c7afeSEric Joyner adapter->num_rx_queues); 509c19c7afeSEric Joyner 510c19c7afeSEric Joyner return (0); 511c19c7afeSEric Joyner } /* ixgbe_if_rx_queues_alloc */ 512c19c7afeSEric Joyner 513c19c7afeSEric Joyner /************************************************************************ 514c19c7afeSEric Joyner * ixgbe_if_queues_free 515c19c7afeSEric Joyner ************************************************************************/ 516c19c7afeSEric Joyner static void 517c19c7afeSEric Joyner ixgbe_if_queues_free(if_ctx_t ctx) 518c19c7afeSEric Joyner { 519c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 520c19c7afeSEric Joyner struct ix_tx_queue *tx_que = adapter->tx_queues; 521c19c7afeSEric Joyner struct ix_rx_queue *rx_que = adapter->rx_queues; 522c19c7afeSEric Joyner int i; 523c19c7afeSEric Joyner 524c19c7afeSEric Joyner if (tx_que != NULL) { 525c19c7afeSEric Joyner for (i = 0; i < adapter->num_tx_queues; i++, tx_que++) { 526c19c7afeSEric Joyner struct tx_ring *txr = &tx_que->txr; 527c19c7afeSEric Joyner if (txr->tx_rsq == NULL) 528c19c7afeSEric Joyner break; 529c19c7afeSEric Joyner 530c19c7afeSEric Joyner free(txr->tx_rsq, M_IXGBE); 531c19c7afeSEric Joyner txr->tx_rsq = NULL; 532c19c7afeSEric Joyner } 533c19c7afeSEric Joyner 534c19c7afeSEric Joyner free(adapter->tx_queues, M_IXGBE); 535c19c7afeSEric Joyner adapter->tx_queues = NULL; 536c19c7afeSEric Joyner } 537c19c7afeSEric Joyner if (rx_que != NULL) { 538c19c7afeSEric Joyner free(adapter->rx_queues, M_IXGBE); 539c19c7afeSEric Joyner adapter->rx_queues = NULL; 540c19c7afeSEric Joyner } 541c19c7afeSEric Joyner } /* ixgbe_if_queues_free */ 542c19c7afeSEric Joyner 5438eb6488eSEric Joyner /************************************************************************ 5448eb6488eSEric Joyner * ixgbe_initialize_rss_mapping 5458eb6488eSEric Joyner ************************************************************************/ 5468eb6488eSEric Joyner static void 5478eb6488eSEric Joyner ixgbe_initialize_rss_mapping(struct adapter *adapter) 548758cc3dcSJack F Vogel { 5496f37f232SEric Joyner struct ixgbe_hw *hw = &adapter->hw; 5508eb6488eSEric Joyner u32 reta = 0, mrqc, rss_key[10]; 5518eb6488eSEric Joyner int queue_id, table_size, index_mult; 5528eb6488eSEric Joyner int i, j; 5538eb6488eSEric Joyner u32 rss_hash_config; 5546f37f232SEric Joyner 5558eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_RSS) { 5568eb6488eSEric Joyner /* Fetch the configured RSS key */ 5578eb6488eSEric Joyner rss_getkey((uint8_t *)&rss_key); 558758cc3dcSJack F Vogel } else { 5598eb6488eSEric Joyner /* set up random bits */ 5608eb6488eSEric Joyner arc4rand(&rss_key, sizeof(rss_key), 0); 561758cc3dcSJack F Vogel } 562758cc3dcSJack F Vogel 5638eb6488eSEric Joyner /* Set multiplier for RETA setup and table size based on MAC */ 5648eb6488eSEric Joyner index_mult = 0x1; 5658eb6488eSEric Joyner table_size = 128; 5668eb6488eSEric Joyner switch (adapter->hw.mac.type) { 5678eb6488eSEric Joyner case ixgbe_mac_82598EB: 5688eb6488eSEric Joyner index_mult = 0x11; 569758cc3dcSJack F Vogel break; 5708eb6488eSEric Joyner case ixgbe_mac_X550: 5718eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 5728eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 5738eb6488eSEric Joyner table_size = 512; 5748eb6488eSEric Joyner break; 575758cc3dcSJack F Vogel default: 576758cc3dcSJack F Vogel break; 577758cc3dcSJack F Vogel } 578758cc3dcSJack F Vogel 5798eb6488eSEric Joyner /* Set up the redirection table */ 5808eb6488eSEric Joyner for (i = 0, j = 0; i < table_size; i++, j++) { 581c19c7afeSEric Joyner if (j == adapter->num_rx_queues) 5828eb6488eSEric Joyner j = 0; 583758cc3dcSJack F Vogel 5848eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_RSS) { 585a9ca1c79SSean Bruno /* 5868eb6488eSEric Joyner * Fetch the RSS bucket id for the given indirection 5878eb6488eSEric Joyner * entry. Cap it at the number of configured buckets 588c19c7afeSEric Joyner * (which is num_rx_queues.) 589a9ca1c79SSean Bruno */ 5908eb6488eSEric Joyner queue_id = rss_get_indirection_to_bucket(i); 591c19c7afeSEric Joyner queue_id = queue_id % adapter->num_rx_queues; 592758cc3dcSJack F Vogel } else 5938eb6488eSEric Joyner queue_id = (j * index_mult); 5948eb6488eSEric Joyner 5958eb6488eSEric Joyner /* 5968eb6488eSEric Joyner * The low 8 bits are for hash value (n+0); 5978eb6488eSEric Joyner * The next 8 bits are for hash value (n+1), etc. 5988eb6488eSEric Joyner */ 5998eb6488eSEric Joyner reta = reta >> 8; 6008eb6488eSEric Joyner reta = reta | (((uint32_t)queue_id) << 24); 6018eb6488eSEric Joyner if ((i & 3) == 3) { 6028eb6488eSEric Joyner if (i < 128) 6038eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta); 6048eb6488eSEric Joyner else 6058eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32), 6068eb6488eSEric Joyner reta); 6078eb6488eSEric Joyner reta = 0; 6088eb6488eSEric Joyner } 609758cc3dcSJack F Vogel } 610758cc3dcSJack F Vogel 6118eb6488eSEric Joyner /* Now fill our hash function seeds */ 6128eb6488eSEric Joyner for (i = 0; i < 10; i++) 6138eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]); 614758cc3dcSJack F Vogel 6158eb6488eSEric Joyner /* Perform hash on these packet types */ 6168eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_RSS) 6178eb6488eSEric Joyner rss_hash_config = rss_gethashconfig(); 618758cc3dcSJack F Vogel else { 619758cc3dcSJack F Vogel /* 6208eb6488eSEric Joyner * Disable UDP - IP fragments aren't currently being handled 6218eb6488eSEric Joyner * and so we end up with a mix of 2-tuple and 4-tuple 6228eb6488eSEric Joyner * traffic. 623758cc3dcSJack F Vogel */ 6248eb6488eSEric Joyner rss_hash_config = RSS_HASHTYPE_RSS_IPV4 6258eb6488eSEric Joyner | RSS_HASHTYPE_RSS_TCP_IPV4 6268eb6488eSEric Joyner | RSS_HASHTYPE_RSS_IPV6 6278eb6488eSEric Joyner | RSS_HASHTYPE_RSS_TCP_IPV6 6288eb6488eSEric Joyner | RSS_HASHTYPE_RSS_IPV6_EX 6298eb6488eSEric Joyner | RSS_HASHTYPE_RSS_TCP_IPV6_EX; 630758cc3dcSJack F Vogel } 631758cc3dcSJack F Vogel 6328eb6488eSEric Joyner mrqc = IXGBE_MRQC_RSSEN; 6338eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4) 6348eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4; 6358eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4) 6368eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP; 6378eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6) 6388eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6; 6398eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6) 6408eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP; 6418eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX) 6428eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX; 6438eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX) 6448eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP; 6458eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4) 6468eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; 6478eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6) 6488eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; 6498eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX) 6508eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP; 6518eb6488eSEric Joyner mrqc |= ixgbe_get_mrqc(adapter->iov_mode); 6528eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); 6538eb6488eSEric Joyner } /* ixgbe_initialize_rss_mapping */ 654758cc3dcSJack F Vogel 6558eb6488eSEric Joyner /************************************************************************ 6568eb6488eSEric Joyner * ixgbe_initialize_receive_units - Setup receive registers and features. 6578eb6488eSEric Joyner ************************************************************************/ 6588eb6488eSEric Joyner #define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1) 659758cc3dcSJack F Vogel 660758cc3dcSJack F Vogel static void 661c19c7afeSEric Joyner ixgbe_initialize_receive_units(if_ctx_t ctx) 662758cc3dcSJack F Vogel { 663c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 664c19c7afeSEric Joyner if_softc_ctx_t scctx = adapter->shared; 66548056c88SJack F Vogel struct ixgbe_hw *hw = &adapter->hw; 666c19c7afeSEric Joyner struct ifnet *ifp = iflib_get_ifp(ctx); 667c19c7afeSEric Joyner struct ix_rx_queue *que; 6688eb6488eSEric Joyner int i, j; 6698eb6488eSEric Joyner u32 bufsz, fctrl, srrctl, rxcsum; 6708eb6488eSEric Joyner u32 hlreg; 67148056c88SJack F Vogel 67248056c88SJack F Vogel /* 6738eb6488eSEric Joyner * Make sure receives are disabled while 6748eb6488eSEric Joyner * setting up the descriptor ring 67548056c88SJack F Vogel */ 6768eb6488eSEric Joyner ixgbe_disable_rx(hw); 6778eb6488eSEric Joyner 6788eb6488eSEric Joyner /* Enable broadcasts */ 6798eb6488eSEric Joyner fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 6808eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_BAM; 6818eb6488eSEric Joyner if (adapter->hw.mac.type == ixgbe_mac_82598EB) { 6828eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_DPF; 6838eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_PMCF; 68448056c88SJack F Vogel } 6858eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 6868eb6488eSEric Joyner 6878eb6488eSEric Joyner /* Set for Jumbo Frames? */ 6888eb6488eSEric Joyner hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0); 6898eb6488eSEric Joyner if (ifp->if_mtu > ETHERMTU) 6908eb6488eSEric Joyner hlreg |= IXGBE_HLREG0_JUMBOEN; 6918eb6488eSEric Joyner else 6928eb6488eSEric Joyner hlreg &= ~IXGBE_HLREG0_JUMBOEN; 6938eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg); 6948eb6488eSEric Joyner 6958eb6488eSEric Joyner bufsz = (adapter->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >> 6968eb6488eSEric Joyner IXGBE_SRRCTL_BSIZEPKT_SHIFT; 6978eb6488eSEric Joyner 698c19c7afeSEric Joyner /* Setup the Base and Length of the Rx Descriptor Ring */ 699c19c7afeSEric Joyner for (i = 0, que = adapter->rx_queues; i < adapter->num_rx_queues; i++, que++) { 700c19c7afeSEric Joyner struct rx_ring *rxr = &que->rxr; 701c19c7afeSEric Joyner u64 rdba = rxr->rx_paddr; 702c19c7afeSEric Joyner 7038eb6488eSEric Joyner j = rxr->me; 7048eb6488eSEric Joyner 7058eb6488eSEric Joyner /* Setup the Base and Length of the Rx Descriptor Ring */ 7068eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), 7078eb6488eSEric Joyner (rdba & 0x00000000ffffffffULL)); 7088eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32)); 7098eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j), 710c19c7afeSEric Joyner scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc)); 7118eb6488eSEric Joyner 7128eb6488eSEric Joyner /* Set up the SRRCTL register */ 7138eb6488eSEric Joyner srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(j)); 7148eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK; 7158eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK; 7168eb6488eSEric Joyner srrctl |= bufsz; 7178eb6488eSEric Joyner srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; 71848056c88SJack F Vogel 71948056c88SJack F Vogel /* 7208eb6488eSEric Joyner * Set DROP_EN iff we have no flow control and >1 queue. 7218eb6488eSEric Joyner * Note that srrctl was cleared shortly before during reset, 7228eb6488eSEric Joyner * so we do not need to clear the bit, but do it just in case 7238eb6488eSEric Joyner * this code is moved elsewhere. 72448056c88SJack F Vogel */ 725c19c7afeSEric Joyner if (adapter->num_rx_queues > 1 && 7268eb6488eSEric Joyner adapter->hw.fc.requested_mode == ixgbe_fc_none) { 7278eb6488eSEric Joyner srrctl |= IXGBE_SRRCTL_DROP_EN; 728758cc3dcSJack F Vogel } else { 7298eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_DROP_EN; 730758cc3dcSJack F Vogel } 731758cc3dcSJack F Vogel 7328eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl); 733758cc3dcSJack F Vogel 7348eb6488eSEric Joyner /* Setup the HW Rx Head and Tail Descriptor Pointers */ 7358eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0); 7368eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0); 737758cc3dcSJack F Vogel 7388eb6488eSEric Joyner /* Set the driver rx tail address */ 7398eb6488eSEric Joyner rxr->tail = IXGBE_RDT(rxr->me); 740a9ca1c79SSean Bruno } 741758cc3dcSJack F Vogel 742758cc3dcSJack F Vogel if (adapter->hw.mac.type != ixgbe_mac_82598EB) { 7438eb6488eSEric Joyner u32 psrtype = IXGBE_PSRTYPE_TCPHDR 7448eb6488eSEric Joyner | IXGBE_PSRTYPE_UDPHDR 7458eb6488eSEric Joyner | IXGBE_PSRTYPE_IPV4HDR 7468eb6488eSEric Joyner | IXGBE_PSRTYPE_IPV6HDR; 7478eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype); 7486f37f232SEric Joyner } 7496f37f232SEric Joyner 7508eb6488eSEric Joyner rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); 7518eb6488eSEric Joyner 7528eb6488eSEric Joyner ixgbe_initialize_rss_mapping(adapter); 7538eb6488eSEric Joyner 754c19c7afeSEric Joyner if (adapter->num_rx_queues > 1) { 7558eb6488eSEric Joyner /* RSS and RX IPP Checksum are mutually exclusive */ 7568eb6488eSEric Joyner rxcsum |= IXGBE_RXCSUM_PCSD; 7576f37f232SEric Joyner } 7586f37f232SEric Joyner 7598eb6488eSEric Joyner if (ifp->if_capenable & IFCAP_RXCSUM) 7608eb6488eSEric Joyner rxcsum |= IXGBE_RXCSUM_PCSD; 761758cc3dcSJack F Vogel 7628eb6488eSEric Joyner /* This is useful for calculating UDP/IP fragment checksums */ 7638eb6488eSEric Joyner if (!(rxcsum & IXGBE_RXCSUM_PCSD)) 7648eb6488eSEric Joyner rxcsum |= IXGBE_RXCSUM_IPPCSE; 765758cc3dcSJack F Vogel 7668eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum); 767758cc3dcSJack F Vogel 7688eb6488eSEric Joyner } /* ixgbe_initialize_receive_units */ 769758cc3dcSJack F Vogel 7708eb6488eSEric Joyner /************************************************************************ 7718eb6488eSEric Joyner * ixgbe_initialize_transmit_units - Enable transmit units. 7728eb6488eSEric Joyner ************************************************************************/ 773758cc3dcSJack F Vogel static void 774c19c7afeSEric Joyner ixgbe_initialize_transmit_units(if_ctx_t ctx) 775758cc3dcSJack F Vogel { 776c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 777758cc3dcSJack F Vogel struct ixgbe_hw *hw = &adapter->hw; 778c19c7afeSEric Joyner if_softc_ctx_t scctx = adapter->shared; 779c19c7afeSEric Joyner struct ix_tx_queue *que; 780c19c7afeSEric Joyner int i; 781758cc3dcSJack F Vogel 782758cc3dcSJack F Vogel /* Setup the Base and Length of the Tx Descriptor Ring */ 783c19c7afeSEric Joyner for (i = 0, que = adapter->tx_queues; i < adapter->num_tx_queues; 784c19c7afeSEric Joyner i++, que++) { 785c19c7afeSEric Joyner struct tx_ring *txr = &que->txr; 786c19c7afeSEric Joyner u64 tdba = txr->tx_paddr; 787758cc3dcSJack F Vogel u32 txctrl = 0; 78848056c88SJack F Vogel int j = txr->me; 789758cc3dcSJack F Vogel 79048056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j), 791758cc3dcSJack F Vogel (tdba & 0x00000000ffffffffULL)); 79248056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32)); 79348056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), 794c19c7afeSEric Joyner scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc)); 795758cc3dcSJack F Vogel 796758cc3dcSJack F Vogel /* Setup the HW Tx Head and Tail descriptor pointers */ 79748056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0); 79848056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0); 799758cc3dcSJack F Vogel 800758cc3dcSJack F Vogel /* Cache the tail address */ 8012dc2d580SEric Joyner txr->tail = IXGBE_TDT(txr->me); 8022dc2d580SEric Joyner 803088a0b27SEric Joyner txr->tx_rs_cidx = txr->tx_rs_pidx; 804088a0b27SEric Joyner txr->tx_cidx_processed = scctx->isc_ntxd[0] - 1; 805c19c7afeSEric Joyner for (int k = 0; k < scctx->isc_ntxd[0]; k++) 806c19c7afeSEric Joyner txr->tx_rsq[k] = QIDX_INVALID; 807758cc3dcSJack F Vogel 808758cc3dcSJack F Vogel /* Disable Head Writeback */ 809a9ca1c79SSean Bruno /* 810a9ca1c79SSean Bruno * Note: for X550 series devices, these registers are actually 811a9ca1c79SSean Bruno * prefixed with TPH_ isntead of DCA_, but the addresses and 812a9ca1c79SSean Bruno * fields remain the same. 813a9ca1c79SSean Bruno */ 814758cc3dcSJack F Vogel switch (hw->mac.type) { 815758cc3dcSJack F Vogel case ixgbe_mac_82598EB: 81648056c88SJack F Vogel txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j)); 817758cc3dcSJack F Vogel break; 818758cc3dcSJack F Vogel default: 81948056c88SJack F Vogel txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j)); 820758cc3dcSJack F Vogel break; 821758cc3dcSJack F Vogel } 822758cc3dcSJack F Vogel txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; 823758cc3dcSJack F Vogel switch (hw->mac.type) { 824758cc3dcSJack F Vogel case ixgbe_mac_82598EB: 82548056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl); 826758cc3dcSJack F Vogel break; 827758cc3dcSJack F Vogel default: 82848056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl); 829758cc3dcSJack F Vogel break; 830758cc3dcSJack F Vogel } 831758cc3dcSJack F Vogel 832758cc3dcSJack F Vogel } 833758cc3dcSJack F Vogel 834758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 835758cc3dcSJack F Vogel u32 dmatxctl, rttdcs; 8368eb6488eSEric Joyner 837758cc3dcSJack F Vogel dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); 838758cc3dcSJack F Vogel dmatxctl |= IXGBE_DMATXCTL_TE; 839758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); 840758cc3dcSJack F Vogel /* Disable arbiter to set MTQC */ 841758cc3dcSJack F Vogel rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); 842758cc3dcSJack F Vogel rttdcs |= IXGBE_RTTDCS_ARBDIS; 843758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); 8448eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_MTQC, 8458eb6488eSEric Joyner ixgbe_get_mtqc(adapter->iov_mode)); 846758cc3dcSJack F Vogel rttdcs &= ~IXGBE_RTTDCS_ARBDIS; 847758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); 848758cc3dcSJack F Vogel } 849758cc3dcSJack F Vogel 8508eb6488eSEric Joyner } /* ixgbe_initialize_transmit_units */ 851758cc3dcSJack F Vogel 8528eb6488eSEric Joyner /************************************************************************ 853c19c7afeSEric Joyner * ixgbe_register 854c19c7afeSEric Joyner ************************************************************************/ 855c19c7afeSEric Joyner static void * 856c19c7afeSEric Joyner ixgbe_register(device_t dev) 857c19c7afeSEric Joyner { 858c19c7afeSEric Joyner return (ixgbe_sctx); 859c19c7afeSEric Joyner } /* ixgbe_register */ 860c19c7afeSEric Joyner 861c19c7afeSEric Joyner /************************************************************************ 862c19c7afeSEric Joyner * ixgbe_if_attach_pre - Device initialization routine, part 1 863758cc3dcSJack F Vogel * 8648eb6488eSEric Joyner * Called when the driver is being loaded. 865c19c7afeSEric Joyner * Identifies the type of hardware, initializes the hardware, 866c19c7afeSEric Joyner * and initializes iflib structures. 867758cc3dcSJack F Vogel * 8688eb6488eSEric Joyner * return 0 on success, positive on failure 8698eb6488eSEric Joyner ************************************************************************/ 8708eb6488eSEric Joyner static int 871c19c7afeSEric Joyner ixgbe_if_attach_pre(if_ctx_t ctx) 872758cc3dcSJack F Vogel { 8738eb6488eSEric Joyner struct adapter *adapter; 874c19c7afeSEric Joyner device_t dev; 875c19c7afeSEric Joyner if_softc_ctx_t scctx; 8768eb6488eSEric Joyner struct ixgbe_hw *hw; 8778eb6488eSEric Joyner int error = 0; 8788eb6488eSEric Joyner u32 ctrl_ext; 8798eb6488eSEric Joyner 8808eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_attach: begin"); 8818eb6488eSEric Joyner 8828eb6488eSEric Joyner /* Allocate, clear, and link in our adapter structure */ 883c19c7afeSEric Joyner dev = iflib_get_dev(ctx); 884c19c7afeSEric Joyner adapter = iflib_get_softc(ctx); 8858eb6488eSEric Joyner adapter->hw.back = adapter; 886c19c7afeSEric Joyner adapter->ctx = ctx; 8878eb6488eSEric Joyner adapter->dev = dev; 888c19c7afeSEric Joyner scctx = adapter->shared = iflib_get_softc_ctx(ctx); 889c19c7afeSEric Joyner adapter->media = iflib_get_media(ctx); 8908eb6488eSEric Joyner hw = &adapter->hw; 8918eb6488eSEric Joyner 8928eb6488eSEric Joyner /* Determine hardware revision */ 8938eb6488eSEric Joyner hw->vendor_id = pci_get_vendor(dev); 8948eb6488eSEric Joyner hw->device_id = pci_get_device(dev); 8958eb6488eSEric Joyner hw->revision_id = pci_get_revid(dev); 8968eb6488eSEric Joyner hw->subsystem_vendor_id = pci_get_subvendor(dev); 8978eb6488eSEric Joyner hw->subsystem_device_id = pci_get_subdevice(dev); 898758cc3dcSJack F Vogel 8998eb6488eSEric Joyner /* Do base PCI setup - map BAR0 */ 900c19c7afeSEric Joyner if (ixgbe_allocate_pci_resources(ctx)) { 9018eb6488eSEric Joyner device_printf(dev, "Allocation of PCI resources failed\n"); 902c19c7afeSEric Joyner return (ENXIO); 9036f37f232SEric Joyner } 904758cc3dcSJack F Vogel 9058eb6488eSEric Joyner /* let hardware know driver is loaded */ 9068eb6488eSEric Joyner ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 9078eb6488eSEric Joyner ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD; 9088eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 909758cc3dcSJack F Vogel 910758cc3dcSJack F Vogel /* 9118eb6488eSEric Joyner * Initialize the shared code 912758cc3dcSJack F Vogel */ 913c19c7afeSEric Joyner if (ixgbe_init_shared_code(hw) != 0) { 9148eb6488eSEric Joyner device_printf(dev, "Unable to initialize the shared code\n"); 9158eb6488eSEric Joyner error = ENXIO; 916c19c7afeSEric Joyner goto err_pci; 91730126537SJack F Vogel } 918758cc3dcSJack F Vogel 9198eb6488eSEric Joyner if (hw->mbx.ops.init_params) 9208eb6488eSEric Joyner hw->mbx.ops.init_params(hw); 921758cc3dcSJack F Vogel 9228eb6488eSEric Joyner hw->allow_unsupported_sfp = allow_unsupported_sfp; 923758cc3dcSJack F Vogel 924c19c7afeSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) 9258eb6488eSEric Joyner hw->phy.smart_speed = ixgbe_smart_speed; 9268eb6488eSEric Joyner 9278eb6488eSEric Joyner ixgbe_init_device_features(adapter); 9288eb6488eSEric Joyner 9298eb6488eSEric Joyner /* Enable WoL (if supported) */ 9308eb6488eSEric Joyner ixgbe_check_wol_support(adapter); 9318eb6488eSEric Joyner 9328eb6488eSEric Joyner /* Verify adapter fan is still functional (if applicable) */ 9338eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) { 9348eb6488eSEric Joyner u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 9358eb6488eSEric Joyner ixgbe_check_fan_failure(adapter, esdp, FALSE); 9368eb6488eSEric Joyner } 9378eb6488eSEric Joyner 9388eb6488eSEric Joyner /* Ensure SW/FW semaphore is free */ 9398eb6488eSEric Joyner ixgbe_init_swfw_semaphore(hw); 9408eb6488eSEric Joyner 9418eb6488eSEric Joyner /* Set an initial default flow control value */ 9428eb6488eSEric Joyner hw->fc.requested_mode = ixgbe_flow_control; 9438eb6488eSEric Joyner 9448eb6488eSEric Joyner hw->phy.reset_if_overtemp = TRUE; 9458eb6488eSEric Joyner error = ixgbe_reset_hw(hw); 9468eb6488eSEric Joyner hw->phy.reset_if_overtemp = FALSE; 9478eb6488eSEric Joyner if (error == IXGBE_ERR_SFP_NOT_PRESENT) { 948758cc3dcSJack F Vogel /* 9498eb6488eSEric Joyner * No optics in this port, set up 9508eb6488eSEric Joyner * so the timer routine will probe 9518eb6488eSEric Joyner * for later insertion. 952758cc3dcSJack F Vogel */ 9538eb6488eSEric Joyner adapter->sfp_probe = TRUE; 954c19c7afeSEric Joyner error = 0; 9558eb6488eSEric Joyner } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) { 9568eb6488eSEric Joyner device_printf(dev, "Unsupported SFP+ module detected!\n"); 9578eb6488eSEric Joyner error = EIO; 958c19c7afeSEric Joyner goto err_pci; 9598eb6488eSEric Joyner } else if (error) { 9608eb6488eSEric Joyner device_printf(dev, "Hardware initialization failed\n"); 9618eb6488eSEric Joyner error = EIO; 962c19c7afeSEric Joyner goto err_pci; 96397f9586eSSean Bruno } 96497f9586eSSean Bruno 9658eb6488eSEric Joyner /* Make sure we have a good EEPROM before we read from it */ 9668eb6488eSEric Joyner if (ixgbe_validate_eeprom_checksum(&adapter->hw, NULL) < 0) { 9678eb6488eSEric Joyner device_printf(dev, "The EEPROM Checksum Is Not Valid\n"); 9688eb6488eSEric Joyner error = EIO; 969c19c7afeSEric Joyner goto err_pci; 97097f9586eSSean Bruno } 97197f9586eSSean Bruno 9728eb6488eSEric Joyner error = ixgbe_start_hw(hw); 9738eb6488eSEric Joyner switch (error) { 9748eb6488eSEric Joyner case IXGBE_ERR_EEPROM_VERSION: 9758eb6488eSEric Joyner device_printf(dev, "This device is a pre-production adapter/LOM. Please be aware there may be issues associated with your hardware.\nIf you are experiencing problems please contact your Intel or hardware representative who provided you with this hardware.\n"); 97697f9586eSSean Bruno break; 9778eb6488eSEric Joyner case IXGBE_ERR_SFP_NOT_SUPPORTED: 9788eb6488eSEric Joyner device_printf(dev, "Unsupported SFP+ Module\n"); 9798eb6488eSEric Joyner error = EIO; 980c19c7afeSEric Joyner goto err_pci; 9818eb6488eSEric Joyner case IXGBE_ERR_SFP_NOT_PRESENT: 9828eb6488eSEric Joyner device_printf(dev, "No SFP+ Module found\n"); 9838eb6488eSEric Joyner /* falls thru */ 98497f9586eSSean Bruno default: 98597f9586eSSean Bruno break; 98697f9586eSSean Bruno } 98797f9586eSSean Bruno 988c19c7afeSEric Joyner /* Most of the iflib initialization... */ 989c19c7afeSEric Joyner 990c19c7afeSEric Joyner iflib_set_mac(ctx, hw->mac.addr); 991c19c7afeSEric Joyner switch (adapter->hw.mac.type) { 992c19c7afeSEric Joyner case ixgbe_mac_X550: 993c19c7afeSEric Joyner case ixgbe_mac_X550EM_x: 994c19c7afeSEric Joyner case ixgbe_mac_X550EM_a: 995c19c7afeSEric Joyner scctx->isc_rss_table_size = 512; 996c19c7afeSEric Joyner scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 64; 997c19c7afeSEric Joyner break; 998c19c7afeSEric Joyner default: 999c19c7afeSEric Joyner scctx->isc_rss_table_size = 128; 1000c19c7afeSEric Joyner scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 16; 1001c19c7afeSEric Joyner } 1002c19c7afeSEric Joyner 1003c19c7afeSEric Joyner /* Allow legacy interrupts */ 1004c19c7afeSEric Joyner ixgbe_txrx.ift_legacy_intr = ixgbe_intr; 1005c19c7afeSEric Joyner 1006c19c7afeSEric Joyner scctx->isc_txqsizes[0] = 1007c19c7afeSEric Joyner roundup2(scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc) + 1008c19c7afeSEric Joyner sizeof(u32), DBA_ALIGN), 1009c19c7afeSEric Joyner scctx->isc_rxqsizes[0] = 1010c19c7afeSEric Joyner roundup2(scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc), 1011c19c7afeSEric Joyner DBA_ALIGN); 1012c19c7afeSEric Joyner 1013c19c7afeSEric Joyner /* XXX */ 1014c19c7afeSEric Joyner scctx->isc_tx_csum_flags = CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO | 1015c19c7afeSEric Joyner CSUM_IP6_TCP | CSUM_IP6_UDP | CSUM_IP6_TSO; 1016c19c7afeSEric Joyner if (adapter->hw.mac.type == ixgbe_mac_82598EB) { 1017c19c7afeSEric Joyner scctx->isc_tx_nsegments = IXGBE_82598_SCATTER; 1018c19c7afeSEric Joyner } else { 1019c19c7afeSEric Joyner scctx->isc_tx_csum_flags |= CSUM_SCTP |CSUM_IP6_SCTP; 1020c19c7afeSEric Joyner scctx->isc_tx_nsegments = IXGBE_82599_SCATTER; 1021c19c7afeSEric Joyner } 1022749597dcSEric Joyner 1023749597dcSEric Joyner scctx->isc_msix_bar = pci_msix_table_bar(dev); 1024749597dcSEric Joyner 1025c19c7afeSEric Joyner scctx->isc_tx_tso_segments_max = scctx->isc_tx_nsegments; 1026c19c7afeSEric Joyner scctx->isc_tx_tso_size_max = IXGBE_TSO_SIZE; 1027c19c7afeSEric Joyner scctx->isc_tx_tso_segsize_max = PAGE_SIZE; 1028c19c7afeSEric Joyner 1029c19c7afeSEric Joyner scctx->isc_txrx = &ixgbe_txrx; 1030c19c7afeSEric Joyner 10317f87c040SMarius Strobl scctx->isc_capabilities = scctx->isc_capenable = IXGBE_CAPS; 1032c19c7afeSEric Joyner 1033c19c7afeSEric Joyner return (0); 1034c19c7afeSEric Joyner 1035c19c7afeSEric Joyner err_pci: 1036c19c7afeSEric Joyner ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); 1037c19c7afeSEric Joyner ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD; 1038c19c7afeSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext); 1039c19c7afeSEric Joyner ixgbe_free_pci_resources(ctx); 1040c19c7afeSEric Joyner 1041c19c7afeSEric Joyner return (error); 1042c19c7afeSEric Joyner } /* ixgbe_if_attach_pre */ 1043c19c7afeSEric Joyner 1044c19c7afeSEric Joyner /********************************************************************* 1045c19c7afeSEric Joyner * ixgbe_if_attach_post - Device initialization routine, part 2 1046c19c7afeSEric Joyner * 1047c19c7afeSEric Joyner * Called during driver load, but after interrupts and 1048c19c7afeSEric Joyner * resources have been allocated and configured. 1049c19c7afeSEric Joyner * Sets up some data structures not relevant to iflib. 1050c19c7afeSEric Joyner * 1051c19c7afeSEric Joyner * return 0 on success, positive on failure 1052c19c7afeSEric Joyner *********************************************************************/ 1053c19c7afeSEric Joyner static int 1054c19c7afeSEric Joyner ixgbe_if_attach_post(if_ctx_t ctx) 1055c19c7afeSEric Joyner { 1056c19c7afeSEric Joyner device_t dev; 1057c19c7afeSEric Joyner struct adapter *adapter; 1058c19c7afeSEric Joyner struct ixgbe_hw *hw; 1059c19c7afeSEric Joyner int error = 0; 1060c19c7afeSEric Joyner 1061c19c7afeSEric Joyner dev = iflib_get_dev(ctx); 1062c19c7afeSEric Joyner adapter = iflib_get_softc(ctx); 1063c19c7afeSEric Joyner hw = &adapter->hw; 1064c19c7afeSEric Joyner 1065c19c7afeSEric Joyner 1066c19c7afeSEric Joyner if (adapter->intr_type == IFLIB_INTR_LEGACY && 1067c19c7afeSEric Joyner (adapter->feat_cap & IXGBE_FEATURE_LEGACY_IRQ) == 0) { 1068c19c7afeSEric Joyner device_printf(dev, "Device does not support legacy interrupts"); 1069c19c7afeSEric Joyner error = ENXIO; 1070c19c7afeSEric Joyner goto err; 1071c19c7afeSEric Joyner } 1072c19c7afeSEric Joyner 1073c19c7afeSEric Joyner /* Allocate multicast array memory. */ 1074c19c7afeSEric Joyner adapter->mta = malloc(sizeof(*adapter->mta) * 1075c19c7afeSEric Joyner MAX_NUM_MULTICAST_ADDRESSES, M_IXGBE, M_NOWAIT); 1076c19c7afeSEric Joyner if (adapter->mta == NULL) { 1077c19c7afeSEric Joyner device_printf(dev, "Can not allocate multicast setup array\n"); 1078c19c7afeSEric Joyner error = ENOMEM; 1079c19c7afeSEric Joyner goto err; 1080c19c7afeSEric Joyner } 1081c19c7afeSEric Joyner 1082c19c7afeSEric Joyner /* hw.ix defaults init */ 1083c19c7afeSEric Joyner ixgbe_set_advertise(adapter, ixgbe_advertise_speed); 1084c19c7afeSEric Joyner 10858eb6488eSEric Joyner /* Enable the optics for 82599 SFP+ fiber */ 10868eb6488eSEric Joyner ixgbe_enable_tx_laser(hw); 1087758cc3dcSJack F Vogel 10888eb6488eSEric Joyner /* Enable power to the phy. */ 10898eb6488eSEric Joyner ixgbe_set_phy_power(hw, TRUE); 10908eb6488eSEric Joyner 1091c19c7afeSEric Joyner ixgbe_initialize_iov(adapter); 1092c19c7afeSEric Joyner 1093c19c7afeSEric Joyner error = ixgbe_setup_interface(ctx); 1094c19c7afeSEric Joyner if (error) { 1095c19c7afeSEric Joyner device_printf(dev, "Interface setup failed: %d\n", error); 1096c19c7afeSEric Joyner goto err; 1097c19c7afeSEric Joyner } 1098c19c7afeSEric Joyner 1099c19c7afeSEric Joyner ixgbe_if_update_admin_status(ctx); 1100c19c7afeSEric Joyner 11018eb6488eSEric Joyner /* Initialize statistics */ 11028eb6488eSEric Joyner ixgbe_update_stats_counters(adapter); 1103c19c7afeSEric Joyner ixgbe_add_hw_stats(adapter); 11048eb6488eSEric Joyner 11058eb6488eSEric Joyner /* Check PCIE slot type/speed/width */ 11068eb6488eSEric Joyner ixgbe_get_slot_info(adapter); 1107758cc3dcSJack F Vogel 1108758cc3dcSJack F Vogel /* 11098eb6488eSEric Joyner * Do time init and sysctl init here, but 11108eb6488eSEric Joyner * only on the first port of a bypass adapter. 1111758cc3dcSJack F Vogel */ 11128eb6488eSEric Joyner ixgbe_bypass_init(adapter); 1113758cc3dcSJack F Vogel 11148eb6488eSEric Joyner /* Set an initial dmac value */ 11158eb6488eSEric Joyner adapter->dmac = 0; 11168eb6488eSEric Joyner /* Set initial advertised speeds (if applicable) */ 11178eb6488eSEric Joyner adapter->advertise = ixgbe_get_advertise(adapter); 1118758cc3dcSJack F Vogel 11198eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_SRIOV) 11208eb6488eSEric Joyner ixgbe_define_iov_schemas(dev, &error); 1121758cc3dcSJack F Vogel 11228eb6488eSEric Joyner /* Add sysctls */ 1123c19c7afeSEric Joyner ixgbe_add_device_sysctls(ctx); 1124758cc3dcSJack F Vogel 11258eb6488eSEric Joyner return (0); 1126c19c7afeSEric Joyner err: 11278eb6488eSEric Joyner return (error); 1128c19c7afeSEric Joyner } /* ixgbe_if_attach_post */ 11298eb6488eSEric Joyner 11308eb6488eSEric Joyner /************************************************************************ 11318eb6488eSEric Joyner * ixgbe_check_wol_support 11326f37f232SEric Joyner * 11336f37f232SEric Joyner * Checks whether the adapter's ports are capable of 11346f37f232SEric Joyner * Wake On LAN by reading the adapter's NVM. 11356f37f232SEric Joyner * 11366f37f232SEric Joyner * Sets each port's hw->wol_enabled value depending 11376f37f232SEric Joyner * on the value read here. 11388eb6488eSEric Joyner ************************************************************************/ 11396f37f232SEric Joyner static void 11406f37f232SEric Joyner ixgbe_check_wol_support(struct adapter *adapter) 11416f37f232SEric Joyner { 11426f37f232SEric Joyner struct ixgbe_hw *hw = &adapter->hw; 11436f37f232SEric Joyner u16 dev_caps = 0; 11446f37f232SEric Joyner 11456f37f232SEric Joyner /* Find out WoL support for port */ 11466f37f232SEric Joyner adapter->wol_support = hw->wol_enabled = 0; 11476f37f232SEric Joyner ixgbe_get_device_caps(hw, &dev_caps); 11486f37f232SEric Joyner if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) || 11496f37f232SEric Joyner ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) && 11506f37f232SEric Joyner hw->bus.func == 0)) 11516f37f232SEric Joyner adapter->wol_support = hw->wol_enabled = 1; 11526f37f232SEric Joyner 11536f37f232SEric Joyner /* Save initial wake up filter configuration */ 11546f37f232SEric Joyner adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC); 11556f37f232SEric Joyner 11566f37f232SEric Joyner return; 11578eb6488eSEric Joyner } /* ixgbe_check_wol_support */ 11586f37f232SEric Joyner 11598eb6488eSEric Joyner /************************************************************************ 11608eb6488eSEric Joyner * ixgbe_setup_interface 11618eb6488eSEric Joyner * 11628eb6488eSEric Joyner * Setup networking device structure and register an interface. 11638eb6488eSEric Joyner ************************************************************************/ 11646f37f232SEric Joyner static int 1165c19c7afeSEric Joyner ixgbe_setup_interface(if_ctx_t ctx) 11666f37f232SEric Joyner { 1167c19c7afeSEric Joyner struct ifnet *ifp = iflib_get_ifp(ctx); 1168c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 11696f37f232SEric Joyner 11708eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_setup_interface: begin"); 11716f37f232SEric Joyner 1172c19c7afeSEric Joyner if_setbaudrate(ifp, IF_Gbps(10)); 11736f37f232SEric Joyner 11748eb6488eSEric Joyner adapter->max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; 1175758cc3dcSJack F Vogel 11768eb6488eSEric Joyner adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw); 11778eb6488eSEric Joyner 1178c19c7afeSEric Joyner ixgbe_add_media_types(ctx); 1179c19c7afeSEric Joyner 1180c19c7afeSEric Joyner /* Autoselect media by default */ 1181c19c7afeSEric Joyner ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO); 11828eb6488eSEric Joyner 11838eb6488eSEric Joyner return (0); 11848eb6488eSEric Joyner } /* ixgbe_setup_interface */ 1185758cc3dcSJack F Vogel 11868eb6488eSEric Joyner /************************************************************************ 1187c19c7afeSEric Joyner * ixgbe_if_get_counter 11888eb6488eSEric Joyner ************************************************************************/ 1189758cc3dcSJack F Vogel static uint64_t 1190c19c7afeSEric Joyner ixgbe_if_get_counter(if_ctx_t ctx, ift_counter cnt) 1191758cc3dcSJack F Vogel { 1192c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 1193c19c7afeSEric Joyner if_t ifp = iflib_get_ifp(ctx); 1194758cc3dcSJack F Vogel 1195758cc3dcSJack F Vogel switch (cnt) { 1196758cc3dcSJack F Vogel case IFCOUNTER_IPACKETS: 1197758cc3dcSJack F Vogel return (adapter->ipackets); 1198758cc3dcSJack F Vogel case IFCOUNTER_OPACKETS: 1199758cc3dcSJack F Vogel return (adapter->opackets); 1200758cc3dcSJack F Vogel case IFCOUNTER_IBYTES: 1201758cc3dcSJack F Vogel return (adapter->ibytes); 1202758cc3dcSJack F Vogel case IFCOUNTER_OBYTES: 1203758cc3dcSJack F Vogel return (adapter->obytes); 1204758cc3dcSJack F Vogel case IFCOUNTER_IMCASTS: 1205758cc3dcSJack F Vogel return (adapter->imcasts); 1206758cc3dcSJack F Vogel case IFCOUNTER_OMCASTS: 1207758cc3dcSJack F Vogel return (adapter->omcasts); 1208758cc3dcSJack F Vogel case IFCOUNTER_COLLISIONS: 1209758cc3dcSJack F Vogel return (0); 1210758cc3dcSJack F Vogel case IFCOUNTER_IQDROPS: 1211758cc3dcSJack F Vogel return (adapter->iqdrops); 1212625d12c6SJohn Baldwin case IFCOUNTER_OQDROPS: 1213c19c7afeSEric Joyner return (0); 1214758cc3dcSJack F Vogel case IFCOUNTER_IERRORS: 1215758cc3dcSJack F Vogel return (adapter->ierrors); 1216758cc3dcSJack F Vogel default: 1217758cc3dcSJack F Vogel return (if_get_counter_default(ifp, cnt)); 1218758cc3dcSJack F Vogel } 1219c19c7afeSEric Joyner } /* ixgbe_if_get_counter */ 1220758cc3dcSJack F Vogel 12218eb6488eSEric Joyner /************************************************************************ 1222bca38080SAndrew Gallatin * ixgbe_if_i2c_req 1223bca38080SAndrew Gallatin ************************************************************************/ 1224bca38080SAndrew Gallatin static int 1225bca38080SAndrew Gallatin ixgbe_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req) 1226bca38080SAndrew Gallatin { 1227bca38080SAndrew Gallatin struct adapter *adapter = iflib_get_softc(ctx); 1228bca38080SAndrew Gallatin struct ixgbe_hw *hw = &adapter->hw; 1229bca38080SAndrew Gallatin int i; 1230bca38080SAndrew Gallatin 1231bca38080SAndrew Gallatin 1232bca38080SAndrew Gallatin if (hw->phy.ops.read_i2c_byte == NULL) 1233bca38080SAndrew Gallatin return (ENXIO); 1234bca38080SAndrew Gallatin for (i = 0; i < req->len; i++) 1235bca38080SAndrew Gallatin hw->phy.ops.read_i2c_byte(hw, req->offset + i, 1236bca38080SAndrew Gallatin req->dev_addr, &req->data[i]); 1237bca38080SAndrew Gallatin return (0); 1238bca38080SAndrew Gallatin } /* ixgbe_if_i2c_req */ 1239bca38080SAndrew Gallatin 1240cf150917SEric Joyner /* ixgbe_if_needs_restart - Tell iflib when the driver needs to be reinitialized 1241cf150917SEric Joyner * @ctx: iflib context 1242cf150917SEric Joyner * @event: event code to check 1243cf150917SEric Joyner * 1244cf150917SEric Joyner * Defaults to returning true for unknown events. 1245cf150917SEric Joyner * 1246cf150917SEric Joyner * @returns true if iflib needs to reinit the interface 1247cf150917SEric Joyner */ 1248cf150917SEric Joyner static bool 1249cf150917SEric Joyner ixgbe_if_needs_restart(if_ctx_t ctx __unused, enum iflib_restart_event event) 1250cf150917SEric Joyner { 1251cf150917SEric Joyner switch (event) { 1252cf150917SEric Joyner case IFLIB_RESTART_VLAN_CONFIG: 1253cf150917SEric Joyner return (false); 1254cf150917SEric Joyner default: 1255cf150917SEric Joyner return (true); 1256cf150917SEric Joyner } 1257cf150917SEric Joyner } 1258cf150917SEric Joyner 1259bca38080SAndrew Gallatin /************************************************************************ 12608eb6488eSEric Joyner * ixgbe_add_media_types 12618eb6488eSEric Joyner ************************************************************************/ 12628eb6488eSEric Joyner static void 1263c19c7afeSEric Joyner ixgbe_add_media_types(if_ctx_t ctx) 12648eb6488eSEric Joyner { 1265c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 12668eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 1267c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 12688eb6488eSEric Joyner u64 layer; 12698eb6488eSEric Joyner 1270c19c7afeSEric Joyner layer = adapter->phy_layer = ixgbe_get_supported_physical_layer(hw); 12718eb6488eSEric Joyner 12728eb6488eSEric Joyner /* Media types with matching FreeBSD media defines */ 12738eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) 1274c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_T, 0, NULL); 12758eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) 1276c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL); 12778eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) 1278c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_100_TX, 0, NULL); 12798eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T) 1280c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_10_T, 0, NULL); 12818eb6488eSEric Joyner 12828eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || 12838eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) 1284c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_TWINAX, 0, 12858eb6488eSEric Joyner NULL); 12868eb6488eSEric Joyner 12878eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) { 1288c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_LR, 0, NULL); 12898eb6488eSEric Joyner if (hw->phy.multispeed_fiber) 1290c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_LX, 0, 12918eb6488eSEric Joyner NULL); 12928eb6488eSEric Joyner } 12938eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) { 1294c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL); 12958eb6488eSEric Joyner if (hw->phy.multispeed_fiber) 1296c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_SX, 0, 12978eb6488eSEric Joyner NULL); 12988eb6488eSEric Joyner } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) 1299c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL); 13008eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) 1301c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); 13028eb6488eSEric Joyner 13038eb6488eSEric Joyner #ifdef IFM_ETH_XTYPE 13048eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 1305c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_KR, 0, NULL); 13068eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) 1307c19c7afeSEric Joyner ifmedia_add( adapter->media, IFM_ETHER | IFM_10G_KX4, 0, NULL); 13088eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 1309c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_KX, 0, NULL); 13108eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) 1311c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_2500_KX, 0, NULL); 13128eb6488eSEric Joyner #else 13138eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) { 13148eb6488eSEric Joyner device_printf(dev, "Media supported: 10GbaseKR\n"); 13158eb6488eSEric Joyner device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n"); 1316c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL); 13178eb6488eSEric Joyner } 13188eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) { 13198eb6488eSEric Joyner device_printf(dev, "Media supported: 10GbaseKX4\n"); 13208eb6488eSEric Joyner device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n"); 1321c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); 13228eb6488eSEric Joyner } 13238eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) { 13248eb6488eSEric Joyner device_printf(dev, "Media supported: 1000baseKX\n"); 13258eb6488eSEric Joyner device_printf(dev, "1000baseKX mapped to 1000baseCX\n"); 1326c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_CX, 0, NULL); 13278eb6488eSEric Joyner } 13288eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) { 13298eb6488eSEric Joyner device_printf(dev, "Media supported: 2500baseKX\n"); 13308eb6488eSEric Joyner device_printf(dev, "2500baseKX mapped to 2500baseSX\n"); 1331c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_2500_SX, 0, NULL); 13328eb6488eSEric Joyner } 13338eb6488eSEric Joyner #endif 13348eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) 13358eb6488eSEric Joyner device_printf(dev, "Media supported: 1000baseBX\n"); 13368eb6488eSEric Joyner 13378eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_82598AT) { 1338c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 13398eb6488eSEric Joyner 0, NULL); 1340c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL); 13418eb6488eSEric Joyner } 13428eb6488eSEric Joyner 1343c19c7afeSEric Joyner ifmedia_add(adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); 13448eb6488eSEric Joyner } /* ixgbe_add_media_types */ 13458eb6488eSEric Joyner 13468eb6488eSEric Joyner /************************************************************************ 13478eb6488eSEric Joyner * ixgbe_is_sfp 13488eb6488eSEric Joyner ************************************************************************/ 13498eb6488eSEric Joyner static inline bool 13508eb6488eSEric Joyner ixgbe_is_sfp(struct ixgbe_hw *hw) 13518eb6488eSEric Joyner { 13528eb6488eSEric Joyner switch (hw->mac.type) { 13538eb6488eSEric Joyner case ixgbe_mac_82598EB: 13548eb6488eSEric Joyner if (hw->phy.type == ixgbe_phy_nl) 1355c19c7afeSEric Joyner return (TRUE); 1356c19c7afeSEric Joyner return (FALSE); 13578eb6488eSEric Joyner case ixgbe_mac_82599EB: 13588eb6488eSEric Joyner switch (hw->mac.ops.get_media_type(hw)) { 13598eb6488eSEric Joyner case ixgbe_media_type_fiber: 13608eb6488eSEric Joyner case ixgbe_media_type_fiber_qsfp: 1361c19c7afeSEric Joyner return (TRUE); 13628eb6488eSEric Joyner default: 1363c19c7afeSEric Joyner return (FALSE); 13648eb6488eSEric Joyner } 13658eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 13668eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 13678eb6488eSEric Joyner if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) 1368c19c7afeSEric Joyner return (TRUE); 1369c19c7afeSEric Joyner return (FALSE); 13708eb6488eSEric Joyner default: 1371c19c7afeSEric Joyner return (FALSE); 13728eb6488eSEric Joyner } 13738eb6488eSEric Joyner } /* ixgbe_is_sfp */ 13748eb6488eSEric Joyner 13758eb6488eSEric Joyner /************************************************************************ 13768eb6488eSEric Joyner * ixgbe_config_link 13778eb6488eSEric Joyner ************************************************************************/ 13788eb6488eSEric Joyner static void 1379b2c1e8e6SEric Joyner ixgbe_config_link(if_ctx_t ctx) 13808eb6488eSEric Joyner { 1381b2c1e8e6SEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 13828eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 13838eb6488eSEric Joyner u32 autoneg, err = 0; 13848eb6488eSEric Joyner bool sfp, negotiate; 13858eb6488eSEric Joyner 13868eb6488eSEric Joyner sfp = ixgbe_is_sfp(hw); 13878eb6488eSEric Joyner 13888eb6488eSEric Joyner if (sfp) { 1389b2c1e8e6SEric Joyner adapter->task_requests |= IXGBE_REQUEST_TASK_MOD; 1390b2c1e8e6SEric Joyner iflib_admin_intr_deferred(ctx); 13918eb6488eSEric Joyner } else { 13928eb6488eSEric Joyner if (hw->mac.ops.check_link) 13938eb6488eSEric Joyner err = ixgbe_check_link(hw, &adapter->link_speed, 13948eb6488eSEric Joyner &adapter->link_up, FALSE); 13958eb6488eSEric Joyner if (err) 1396c19c7afeSEric Joyner return; 13978eb6488eSEric Joyner autoneg = hw->phy.autoneg_advertised; 13988eb6488eSEric Joyner if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) 13998eb6488eSEric Joyner err = hw->mac.ops.get_link_capabilities(hw, &autoneg, 14008eb6488eSEric Joyner &negotiate); 14018eb6488eSEric Joyner if (err) 1402c19c7afeSEric Joyner return; 14038eb6488eSEric Joyner if (hw->mac.ops.setup_link) 14048eb6488eSEric Joyner err = hw->mac.ops.setup_link(hw, autoneg, 14058eb6488eSEric Joyner adapter->link_up); 14068eb6488eSEric Joyner } 14078eb6488eSEric Joyner } /* ixgbe_config_link */ 14088eb6488eSEric Joyner 14098eb6488eSEric Joyner /************************************************************************ 14108eb6488eSEric Joyner * ixgbe_update_stats_counters - Update board statistics counters. 14118eb6488eSEric Joyner ************************************************************************/ 14128eb6488eSEric Joyner static void 14138eb6488eSEric Joyner ixgbe_update_stats_counters(struct adapter *adapter) 14148eb6488eSEric Joyner { 14158eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 14168eb6488eSEric Joyner struct ixgbe_hw_stats *stats = &adapter->stats.pf; 14178eb6488eSEric Joyner u32 missed_rx = 0, bprc, lxon, lxoff, total; 1418e37d3dc1SEric Joyner u32 lxoffrxc; 14198eb6488eSEric Joyner u64 total_missed_rx = 0; 14208eb6488eSEric Joyner 14218eb6488eSEric Joyner stats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); 14228eb6488eSEric Joyner stats->illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC); 14238eb6488eSEric Joyner stats->errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC); 14248eb6488eSEric Joyner stats->mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC); 14258eb6488eSEric Joyner stats->mpc[0] += IXGBE_READ_REG(hw, IXGBE_MPC(0)); 14268eb6488eSEric Joyner 14278eb6488eSEric Joyner for (int i = 0; i < 16; i++) { 14288eb6488eSEric Joyner stats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 14298eb6488eSEric Joyner stats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 14308eb6488eSEric Joyner stats->qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); 14318eb6488eSEric Joyner } 14328eb6488eSEric Joyner stats->mlfc += IXGBE_READ_REG(hw, IXGBE_MLFC); 14338eb6488eSEric Joyner stats->mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC); 14348eb6488eSEric Joyner stats->rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); 14358eb6488eSEric Joyner 14368eb6488eSEric Joyner /* Hardware workaround, gprc counts missed packets */ 14378eb6488eSEric Joyner stats->gprc += IXGBE_READ_REG(hw, IXGBE_GPRC); 14388eb6488eSEric Joyner stats->gprc -= missed_rx; 14398eb6488eSEric Joyner 14408eb6488eSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) { 14418eb6488eSEric Joyner stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL) + 14428eb6488eSEric Joyner ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32); 14438eb6488eSEric Joyner stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL) + 14448eb6488eSEric Joyner ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32); 14458eb6488eSEric Joyner stats->tor += IXGBE_READ_REG(hw, IXGBE_TORL) + 14468eb6488eSEric Joyner ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32); 14478eb6488eSEric Joyner stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 1448e37d3dc1SEric Joyner lxoffrxc = IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 1449e37d3dc1SEric Joyner stats->lxoffrxc += lxoffrxc; 14508eb6488eSEric Joyner } else { 14518eb6488eSEric Joyner stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); 1452e37d3dc1SEric Joyner lxoffrxc = IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 1453e37d3dc1SEric Joyner stats->lxoffrxc += lxoffrxc; 14548eb6488eSEric Joyner /* 82598 only has a counter in the high register */ 14558eb6488eSEric Joyner stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); 14568eb6488eSEric Joyner stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); 14578eb6488eSEric Joyner stats->tor += IXGBE_READ_REG(hw, IXGBE_TORH); 14588eb6488eSEric Joyner } 14598eb6488eSEric Joyner 14608eb6488eSEric Joyner /* 1461e37d3dc1SEric Joyner * For watchdog management we need to know if we have been paused 1462e37d3dc1SEric Joyner * during the last interval, so capture that here. 1463e37d3dc1SEric Joyner */ 1464e37d3dc1SEric Joyner if (lxoffrxc) 1465e37d3dc1SEric Joyner adapter->shared->isc_pause_frames = 1; 1466e37d3dc1SEric Joyner 1467e37d3dc1SEric Joyner /* 14688eb6488eSEric Joyner * Workaround: mprc hardware is incorrectly counting 14698eb6488eSEric Joyner * broadcasts, so for now we subtract those. 1470758cc3dcSJack F Vogel */ 14718eb6488eSEric Joyner bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); 14728eb6488eSEric Joyner stats->bprc += bprc; 14738eb6488eSEric Joyner stats->mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); 14748eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 14758eb6488eSEric Joyner stats->mprc -= bprc; 14768eb6488eSEric Joyner 14778eb6488eSEric Joyner stats->prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64); 14788eb6488eSEric Joyner stats->prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127); 14798eb6488eSEric Joyner stats->prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255); 14808eb6488eSEric Joyner stats->prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511); 14818eb6488eSEric Joyner stats->prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023); 14828eb6488eSEric Joyner stats->prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522); 14838eb6488eSEric Joyner 14848eb6488eSEric Joyner lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC); 14858eb6488eSEric Joyner stats->lxontxc += lxon; 14868eb6488eSEric Joyner lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 14878eb6488eSEric Joyner stats->lxofftxc += lxoff; 14888eb6488eSEric Joyner total = lxon + lxoff; 14898eb6488eSEric Joyner 14908eb6488eSEric Joyner stats->gptc += IXGBE_READ_REG(hw, IXGBE_GPTC); 14918eb6488eSEric Joyner stats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC); 14928eb6488eSEric Joyner stats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64); 14938eb6488eSEric Joyner stats->gptc -= total; 14948eb6488eSEric Joyner stats->mptc -= total; 14958eb6488eSEric Joyner stats->ptc64 -= total; 14968eb6488eSEric Joyner stats->gotc -= total * ETHER_MIN_LEN; 14978eb6488eSEric Joyner 14988eb6488eSEric Joyner stats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC); 14998eb6488eSEric Joyner stats->rfc += IXGBE_READ_REG(hw, IXGBE_RFC); 15008eb6488eSEric Joyner stats->roc += IXGBE_READ_REG(hw, IXGBE_ROC); 15018eb6488eSEric Joyner stats->rjc += IXGBE_READ_REG(hw, IXGBE_RJC); 15028eb6488eSEric Joyner stats->mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC); 15038eb6488eSEric Joyner stats->mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC); 15048eb6488eSEric Joyner stats->mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC); 15058eb6488eSEric Joyner stats->tpr += IXGBE_READ_REG(hw, IXGBE_TPR); 15068eb6488eSEric Joyner stats->tpt += IXGBE_READ_REG(hw, IXGBE_TPT); 15078eb6488eSEric Joyner stats->ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127); 15088eb6488eSEric Joyner stats->ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255); 15098eb6488eSEric Joyner stats->ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511); 15108eb6488eSEric Joyner stats->ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023); 15118eb6488eSEric Joyner stats->ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522); 15128eb6488eSEric Joyner stats->bptc += IXGBE_READ_REG(hw, IXGBE_BPTC); 15138eb6488eSEric Joyner stats->xec += IXGBE_READ_REG(hw, IXGBE_XEC); 15148eb6488eSEric Joyner stats->fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC); 15158eb6488eSEric Joyner stats->fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST); 15168eb6488eSEric Joyner /* Only read FCOE on 82599 */ 15178eb6488eSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) { 15188eb6488eSEric Joyner stats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC); 15198eb6488eSEric Joyner stats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC); 15208eb6488eSEric Joyner stats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC); 15218eb6488eSEric Joyner stats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC); 15228eb6488eSEric Joyner stats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC); 15238eb6488eSEric Joyner } 15248eb6488eSEric Joyner 15258eb6488eSEric Joyner /* Fill out the OS statistics structure */ 15268eb6488eSEric Joyner IXGBE_SET_IPACKETS(adapter, stats->gprc); 15278eb6488eSEric Joyner IXGBE_SET_OPACKETS(adapter, stats->gptc); 15288eb6488eSEric Joyner IXGBE_SET_IBYTES(adapter, stats->gorc); 15298eb6488eSEric Joyner IXGBE_SET_OBYTES(adapter, stats->gotc); 15308eb6488eSEric Joyner IXGBE_SET_IMCASTS(adapter, stats->mprc); 15318eb6488eSEric Joyner IXGBE_SET_OMCASTS(adapter, stats->mptc); 15328eb6488eSEric Joyner IXGBE_SET_COLLISIONS(adapter, 0); 15338eb6488eSEric Joyner IXGBE_SET_IQDROPS(adapter, total_missed_rx); 1534*afb1aa4eSPiotr Pietruszewski 1535*afb1aa4eSPiotr Pietruszewski /* 1536*afb1aa4eSPiotr Pietruszewski * Aggregate following types of errors as RX errors: 1537*afb1aa4eSPiotr Pietruszewski * - CRC error count, 1538*afb1aa4eSPiotr Pietruszewski * - illegal byte error count, 1539*afb1aa4eSPiotr Pietruszewski * - checksum error count, 1540*afb1aa4eSPiotr Pietruszewski * - missed packets count, 1541*afb1aa4eSPiotr Pietruszewski * - length error count, 1542*afb1aa4eSPiotr Pietruszewski * - undersized packets count, 1543*afb1aa4eSPiotr Pietruszewski * - fragmented packets count, 1544*afb1aa4eSPiotr Pietruszewski * - oversized packets count, 1545*afb1aa4eSPiotr Pietruszewski * - jabber count. 1546*afb1aa4eSPiotr Pietruszewski */ 1547*afb1aa4eSPiotr Pietruszewski IXGBE_SET_IERRORS(adapter, stats->crcerrs + stats->illerrc + stats->xec + 1548*afb1aa4eSPiotr Pietruszewski stats->mpc[0] + stats->rlec + stats->ruc + stats->rfc + stats->roc + 1549*afb1aa4eSPiotr Pietruszewski stats->rjc); 15508eb6488eSEric Joyner } /* ixgbe_update_stats_counters */ 15518eb6488eSEric Joyner 15528eb6488eSEric Joyner /************************************************************************ 15538eb6488eSEric Joyner * ixgbe_add_hw_stats 15548eb6488eSEric Joyner * 15558eb6488eSEric Joyner * Add sysctl variables, one per statistic, to the system. 15568eb6488eSEric Joyner ************************************************************************/ 15578eb6488eSEric Joyner static void 15588eb6488eSEric Joyner ixgbe_add_hw_stats(struct adapter *adapter) 15598eb6488eSEric Joyner { 1560c19c7afeSEric Joyner device_t dev = iflib_get_dev(adapter->ctx); 1561c19c7afeSEric Joyner struct ix_rx_queue *rx_que; 1562c19c7afeSEric Joyner struct ix_tx_queue *tx_que; 15638eb6488eSEric Joyner struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 15648eb6488eSEric Joyner struct sysctl_oid *tree = device_get_sysctl_tree(dev); 15658eb6488eSEric Joyner struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); 15668eb6488eSEric Joyner struct ixgbe_hw_stats *stats = &adapter->stats.pf; 15678eb6488eSEric Joyner struct sysctl_oid *stat_node, *queue_node; 15688eb6488eSEric Joyner struct sysctl_oid_list *stat_list, *queue_list; 1569c19c7afeSEric Joyner int i; 15708eb6488eSEric Joyner 15718eb6488eSEric Joyner #define QUEUE_NAME_LEN 32 15728eb6488eSEric Joyner char namebuf[QUEUE_NAME_LEN]; 15738eb6488eSEric Joyner 15748eb6488eSEric Joyner /* Driver Statistics */ 15758eb6488eSEric Joyner SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", 15768eb6488eSEric Joyner CTLFLAG_RD, &adapter->dropped_pkts, "Driver dropped packets"); 15778eb6488eSEric Joyner SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events", 15788eb6488eSEric Joyner CTLFLAG_RD, &adapter->watchdog_events, "Watchdog timeouts"); 15798eb6488eSEric Joyner SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq", 15808eb6488eSEric Joyner CTLFLAG_RD, &adapter->link_irq, "Link MSI-X IRQ Handled"); 15818eb6488eSEric Joyner 1582c19c7afeSEric Joyner for (i = 0, tx_que = adapter->tx_queues; i < adapter->num_tx_queues; i++, tx_que++) { 1583c19c7afeSEric Joyner struct tx_ring *txr = &tx_que->txr; 15848eb6488eSEric Joyner snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); 15858eb6488eSEric Joyner queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, 158620b91f0aSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name"); 15878eb6488eSEric Joyner queue_list = SYSCTL_CHILDREN(queue_node); 15888eb6488eSEric Joyner 15898eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head", 159020b91f0aSPawel Biernacki CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, txr, 0, 15918eb6488eSEric Joyner ixgbe_sysctl_tdh_handler, "IU", "Transmit Descriptor Head"); 15928eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail", 159320b91f0aSPawel Biernacki CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, txr, 0, 15948eb6488eSEric Joyner ixgbe_sysctl_tdt_handler, "IU", "Transmit Descriptor Tail"); 15958eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx", 15968eb6488eSEric Joyner CTLFLAG_RD, &txr->tso_tx, "TSO"); 15978eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets", 15988eb6488eSEric Joyner CTLFLAG_RD, &txr->total_packets, 15998eb6488eSEric Joyner "Queue Packets Transmitted"); 16008eb6488eSEric Joyner } 16018eb6488eSEric Joyner 1602c19c7afeSEric Joyner for (i = 0, rx_que = adapter->rx_queues; i < adapter->num_rx_queues; i++, rx_que++) { 1603c19c7afeSEric Joyner struct rx_ring *rxr = &rx_que->rxr; 16048eb6488eSEric Joyner snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); 16058eb6488eSEric Joyner queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, 160620b91f0aSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name"); 16078eb6488eSEric Joyner queue_list = SYSCTL_CHILDREN(queue_node); 16088eb6488eSEric Joyner 1609c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate", 161020b91f0aSPawel Biernacki CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 161120b91f0aSPawel Biernacki &adapter->rx_queues[i], 0, 1612c19c7afeSEric Joyner ixgbe_sysctl_interrupt_rate_handler, "IU", 1613c19c7afeSEric Joyner "Interrupt Rate"); 1614c19c7afeSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs", 1615c19c7afeSEric Joyner CTLFLAG_RD, &(adapter->rx_queues[i].irqs), 1616c19c7afeSEric Joyner "irqs on this queue"); 16178eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head", 161820b91f0aSPawel Biernacki CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, rxr, 0, 16198eb6488eSEric Joyner ixgbe_sysctl_rdh_handler, "IU", "Receive Descriptor Head"); 16208eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail", 162120b91f0aSPawel Biernacki CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, rxr, 0, 16228eb6488eSEric Joyner ixgbe_sysctl_rdt_handler, "IU", "Receive Descriptor Tail"); 16238eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets", 16248eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_packets, "Queue Packets Received"); 16258eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes", 16268eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_bytes, "Queue Bytes Received"); 16278eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_copies", 16288eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_copies, "Copied RX Frames"); 16298eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_discarded", 16308eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_discarded, "Discarded RX packets"); 16318eb6488eSEric Joyner } 16328eb6488eSEric Joyner 16338eb6488eSEric Joyner /* MAC stats get their own sub node */ 16348eb6488eSEric Joyner 16358eb6488eSEric Joyner stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats", 163620b91f0aSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "MAC Statistics"); 16378eb6488eSEric Joyner stat_list = SYSCTL_CHILDREN(stat_node); 16388eb6488eSEric Joyner 1639*afb1aa4eSPiotr Pietruszewski SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_errs", 1640*afb1aa4eSPiotr Pietruszewski CTLFLAG_RD, &adapter->ierrors, IXGBE_SYSCTL_DESC_RX_ERRS); 16418eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs", 16428eb6488eSEric Joyner CTLFLAG_RD, &stats->crcerrs, "CRC Errors"); 16438eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ill_errs", 16448eb6488eSEric Joyner CTLFLAG_RD, &stats->illerrc, "Illegal Byte Errors"); 16458eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "byte_errs", 16468eb6488eSEric Joyner CTLFLAG_RD, &stats->errbc, "Byte Errors"); 16478eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "short_discards", 16488eb6488eSEric Joyner CTLFLAG_RD, &stats->mspdc, "MAC Short Packets Discarded"); 16498eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "local_faults", 16508eb6488eSEric Joyner CTLFLAG_RD, &stats->mlfc, "MAC Local Faults"); 16518eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "remote_faults", 16528eb6488eSEric Joyner CTLFLAG_RD, &stats->mrfc, "MAC Remote Faults"); 16538eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rec_len_errs", 16548eb6488eSEric Joyner CTLFLAG_RD, &stats->rlec, "Receive Length Errors"); 16558eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_missed_packets", 16568eb6488eSEric Joyner CTLFLAG_RD, &stats->mpc[0], "RX Missed Packet Count"); 16578eb6488eSEric Joyner 16588eb6488eSEric Joyner /* Flow Control stats */ 16598eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd", 16608eb6488eSEric Joyner CTLFLAG_RD, &stats->lxontxc, "Link XON Transmitted"); 16618eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd", 16628eb6488eSEric Joyner CTLFLAG_RD, &stats->lxonrxc, "Link XON Received"); 16638eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd", 16648eb6488eSEric Joyner CTLFLAG_RD, &stats->lxofftxc, "Link XOFF Transmitted"); 16658eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd", 16668eb6488eSEric Joyner CTLFLAG_RD, &stats->lxoffrxc, "Link XOFF Received"); 16678eb6488eSEric Joyner 16688eb6488eSEric Joyner /* Packet Reception Stats */ 16698eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_octets_rcvd", 16708eb6488eSEric Joyner CTLFLAG_RD, &stats->tor, "Total Octets Received"); 16718eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd", 16728eb6488eSEric Joyner CTLFLAG_RD, &stats->gorc, "Good Octets Received"); 16738eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_rcvd", 16748eb6488eSEric Joyner CTLFLAG_RD, &stats->tpr, "Total Packets Received"); 16758eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd", 16768eb6488eSEric Joyner CTLFLAG_RD, &stats->gprc, "Good Packets Received"); 16778eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd", 16788eb6488eSEric Joyner CTLFLAG_RD, &stats->mprc, "Multicast Packets Received"); 16798eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_rcvd", 16808eb6488eSEric Joyner CTLFLAG_RD, &stats->bprc, "Broadcast Packets Received"); 16818eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64", 16828eb6488eSEric Joyner CTLFLAG_RD, &stats->prc64, "64 byte frames received "); 16838eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127", 16848eb6488eSEric Joyner CTLFLAG_RD, &stats->prc127, "65-127 byte frames received"); 16858eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255", 16868eb6488eSEric Joyner CTLFLAG_RD, &stats->prc255, "128-255 byte frames received"); 16878eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511", 16888eb6488eSEric Joyner CTLFLAG_RD, &stats->prc511, "256-511 byte frames received"); 16898eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023", 16908eb6488eSEric Joyner CTLFLAG_RD, &stats->prc1023, "512-1023 byte frames received"); 16918eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522", 16928eb6488eSEric Joyner CTLFLAG_RD, &stats->prc1522, "1023-1522 byte frames received"); 16938eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersized", 16948eb6488eSEric Joyner CTLFLAG_RD, &stats->ruc, "Receive Undersized"); 16958eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented", 16968eb6488eSEric Joyner CTLFLAG_RD, &stats->rfc, "Fragmented Packets Received "); 16978eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversized", 16988eb6488eSEric Joyner CTLFLAG_RD, &stats->roc, "Oversized Packets Received"); 16998eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabberd", 17008eb6488eSEric Joyner CTLFLAG_RD, &stats->rjc, "Received Jabber"); 17018eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_rcvd", 17028eb6488eSEric Joyner CTLFLAG_RD, &stats->mngprc, "Management Packets Received"); 17038eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_drpd", 17048eb6488eSEric Joyner CTLFLAG_RD, &stats->mngptc, "Management Packets Dropped"); 17058eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "checksum_errs", 17068eb6488eSEric Joyner CTLFLAG_RD, &stats->xec, "Checksum Errors"); 17078eb6488eSEric Joyner 17088eb6488eSEric Joyner /* Packet Transmission Stats */ 17098eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd", 17108eb6488eSEric Joyner CTLFLAG_RD, &stats->gotc, "Good Octets Transmitted"); 17118eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd", 17128eb6488eSEric Joyner CTLFLAG_RD, &stats->tpt, "Total Packets Transmitted"); 17138eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd", 17148eb6488eSEric Joyner CTLFLAG_RD, &stats->gptc, "Good Packets Transmitted"); 17158eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd", 17168eb6488eSEric Joyner CTLFLAG_RD, &stats->bptc, "Broadcast Packets Transmitted"); 17178eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd", 17188eb6488eSEric Joyner CTLFLAG_RD, &stats->mptc, "Multicast Packets Transmitted"); 17198eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_txd", 17208eb6488eSEric Joyner CTLFLAG_RD, &stats->mngptc, "Management Packets Transmitted"); 17218eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64", 17228eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc64, "64 byte frames transmitted "); 17238eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127", 17248eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc127, "65-127 byte frames transmitted"); 17258eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255", 17268eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc255, "128-255 byte frames transmitted"); 17278eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511", 17288eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc511, "256-511 byte frames transmitted"); 17298eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023", 17308eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc1023, "512-1023 byte frames transmitted"); 17318eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522", 17328eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc1522, "1024-1522 byte frames transmitted"); 17338eb6488eSEric Joyner } /* ixgbe_add_hw_stats */ 17348eb6488eSEric Joyner 17358eb6488eSEric Joyner /************************************************************************ 17368eb6488eSEric Joyner * ixgbe_sysctl_tdh_handler - Transmit Descriptor Head handler function 17378eb6488eSEric Joyner * 17388eb6488eSEric Joyner * Retrieves the TDH value from the hardware 17398eb6488eSEric Joyner ************************************************************************/ 1740758cc3dcSJack F Vogel static int 1741758cc3dcSJack F Vogel ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS) 1742758cc3dcSJack F Vogel { 1743758cc3dcSJack F Vogel struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); 17448eb6488eSEric Joyner int error; 17458eb6488eSEric Joyner unsigned int val; 1746758cc3dcSJack F Vogel 17478eb6488eSEric Joyner if (!txr) 17488eb6488eSEric Joyner return (0); 17498eb6488eSEric Joyner 17508eb6488eSEric Joyner val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me)); 1751758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1752758cc3dcSJack F Vogel if (error || !req->newptr) 1753758cc3dcSJack F Vogel return error; 1754758cc3dcSJack F Vogel 17558eb6488eSEric Joyner return (0); 17568eb6488eSEric Joyner } /* ixgbe_sysctl_tdh_handler */ 17578eb6488eSEric Joyner 17588eb6488eSEric Joyner /************************************************************************ 17598eb6488eSEric Joyner * ixgbe_sysctl_tdt_handler - Transmit Descriptor Tail handler function 17608eb6488eSEric Joyner * 1761758cc3dcSJack F Vogel * Retrieves the TDT value from the hardware 17628eb6488eSEric Joyner ************************************************************************/ 1763758cc3dcSJack F Vogel static int 1764758cc3dcSJack F Vogel ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS) 1765758cc3dcSJack F Vogel { 1766758cc3dcSJack F Vogel struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); 17678eb6488eSEric Joyner int error; 17688eb6488eSEric Joyner unsigned int val; 1769758cc3dcSJack F Vogel 17708eb6488eSEric Joyner if (!txr) 17718eb6488eSEric Joyner return (0); 17728eb6488eSEric Joyner 17738eb6488eSEric Joyner val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me)); 1774758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1775758cc3dcSJack F Vogel if (error || !req->newptr) 1776758cc3dcSJack F Vogel return error; 1777758cc3dcSJack F Vogel 17788eb6488eSEric Joyner return (0); 17798eb6488eSEric Joyner } /* ixgbe_sysctl_tdt_handler */ 17808eb6488eSEric Joyner 17818eb6488eSEric Joyner /************************************************************************ 17828eb6488eSEric Joyner * ixgbe_sysctl_rdh_handler - Receive Descriptor Head handler function 17838eb6488eSEric Joyner * 1784758cc3dcSJack F Vogel * Retrieves the RDH value from the hardware 17858eb6488eSEric Joyner ************************************************************************/ 1786758cc3dcSJack F Vogel static int 1787758cc3dcSJack F Vogel ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS) 1788758cc3dcSJack F Vogel { 1789758cc3dcSJack F Vogel struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); 17908eb6488eSEric Joyner int error; 17918eb6488eSEric Joyner unsigned int val; 1792758cc3dcSJack F Vogel 17938eb6488eSEric Joyner if (!rxr) 17948eb6488eSEric Joyner return (0); 17958eb6488eSEric Joyner 17968eb6488eSEric Joyner val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me)); 1797758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1798758cc3dcSJack F Vogel if (error || !req->newptr) 1799758cc3dcSJack F Vogel return error; 1800758cc3dcSJack F Vogel 18018eb6488eSEric Joyner return (0); 18028eb6488eSEric Joyner } /* ixgbe_sysctl_rdh_handler */ 18038eb6488eSEric Joyner 18048eb6488eSEric Joyner /************************************************************************ 18058eb6488eSEric Joyner * ixgbe_sysctl_rdt_handler - Receive Descriptor Tail handler function 18068eb6488eSEric Joyner * 1807758cc3dcSJack F Vogel * Retrieves the RDT value from the hardware 18088eb6488eSEric Joyner ************************************************************************/ 1809758cc3dcSJack F Vogel static int 1810758cc3dcSJack F Vogel ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS) 1811758cc3dcSJack F Vogel { 1812758cc3dcSJack F Vogel struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); 18138eb6488eSEric Joyner int error; 18148eb6488eSEric Joyner unsigned int val; 1815758cc3dcSJack F Vogel 18168eb6488eSEric Joyner if (!rxr) 18178eb6488eSEric Joyner return (0); 18188eb6488eSEric Joyner 18198eb6488eSEric Joyner val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me)); 1820758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1821758cc3dcSJack F Vogel if (error || !req->newptr) 1822758cc3dcSJack F Vogel return error; 18238eb6488eSEric Joyner 18248eb6488eSEric Joyner return (0); 18258eb6488eSEric Joyner } /* ixgbe_sysctl_rdt_handler */ 18268eb6488eSEric Joyner 18278eb6488eSEric Joyner /************************************************************************ 1828c19c7afeSEric Joyner * ixgbe_if_vlan_register 18298eb6488eSEric Joyner * 18308eb6488eSEric Joyner * Run via vlan config EVENT, it enables us to use the 18318eb6488eSEric Joyner * HW Filter table since we can get the vlan id. This 18328eb6488eSEric Joyner * just creates the entry in the soft version of the 18338eb6488eSEric Joyner * VFTA, init will repopulate the real table. 18348eb6488eSEric Joyner ************************************************************************/ 18358eb6488eSEric Joyner static void 1836c19c7afeSEric Joyner ixgbe_if_vlan_register(if_ctx_t ctx, u16 vtag) 18378eb6488eSEric Joyner { 1838c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 18398eb6488eSEric Joyner u16 index, bit; 18408eb6488eSEric Joyner 18418eb6488eSEric Joyner index = (vtag >> 5) & 0x7F; 18428eb6488eSEric Joyner bit = vtag & 0x1F; 18438eb6488eSEric Joyner adapter->shadow_vfta[index] |= (1 << bit); 18448eb6488eSEric Joyner ++adapter->num_vlans; 1845c19c7afeSEric Joyner ixgbe_setup_vlan_hw_support(ctx); 1846c19c7afeSEric Joyner } /* ixgbe_if_vlan_register */ 18478eb6488eSEric Joyner 18488eb6488eSEric Joyner /************************************************************************ 1849c19c7afeSEric Joyner * ixgbe_if_vlan_unregister 18508eb6488eSEric Joyner * 18518eb6488eSEric Joyner * Run via vlan unconfig EVENT, remove our entry in the soft vfta. 18528eb6488eSEric Joyner ************************************************************************/ 18538eb6488eSEric Joyner static void 1854c19c7afeSEric Joyner ixgbe_if_vlan_unregister(if_ctx_t ctx, u16 vtag) 18558eb6488eSEric Joyner { 1856c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 18578eb6488eSEric Joyner u16 index, bit; 18588eb6488eSEric Joyner 18598eb6488eSEric Joyner index = (vtag >> 5) & 0x7F; 18608eb6488eSEric Joyner bit = vtag & 0x1F; 18618eb6488eSEric Joyner adapter->shadow_vfta[index] &= ~(1 << bit); 18628eb6488eSEric Joyner --adapter->num_vlans; 18638eb6488eSEric Joyner /* Re-init to load the changes */ 1864c19c7afeSEric Joyner ixgbe_setup_vlan_hw_support(ctx); 1865c19c7afeSEric Joyner } /* ixgbe_if_vlan_unregister */ 18668eb6488eSEric Joyner 18678eb6488eSEric Joyner /************************************************************************ 18688eb6488eSEric Joyner * ixgbe_setup_vlan_hw_support 18698eb6488eSEric Joyner ************************************************************************/ 18708eb6488eSEric Joyner static void 1871c19c7afeSEric Joyner ixgbe_setup_vlan_hw_support(if_ctx_t ctx) 18728eb6488eSEric Joyner { 1873c19c7afeSEric Joyner struct ifnet *ifp = iflib_get_ifp(ctx); 1874c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 18758eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 18768eb6488eSEric Joyner struct rx_ring *rxr; 18778eb6488eSEric Joyner int i; 18788eb6488eSEric Joyner u32 ctrl; 18798eb6488eSEric Joyner 18808eb6488eSEric Joyner 18818eb6488eSEric Joyner /* 18828eb6488eSEric Joyner * We get here thru init_locked, meaning 18838eb6488eSEric Joyner * a soft reset, this has already cleared 18848eb6488eSEric Joyner * the VFTA and other state, so if there 18858eb6488eSEric Joyner * have been no vlan's registered do nothing. 18868eb6488eSEric Joyner */ 18878eb6488eSEric Joyner if (adapter->num_vlans == 0) 18888eb6488eSEric Joyner return; 18898eb6488eSEric Joyner 18908eb6488eSEric Joyner /* Setup the queues for vlans */ 18919c92bb71SSean Bruno if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { 1892c19c7afeSEric Joyner for (i = 0; i < adapter->num_rx_queues; i++) { 1893c19c7afeSEric Joyner rxr = &adapter->rx_queues[i].rxr; 18948eb6488eSEric Joyner /* On 82599 the VLAN enable is per/queue in RXDCTL */ 18958eb6488eSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) { 18968eb6488eSEric Joyner ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); 18978eb6488eSEric Joyner ctrl |= IXGBE_RXDCTL_VME; 18988eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl); 18998eb6488eSEric Joyner } 19008eb6488eSEric Joyner rxr->vtag_strip = TRUE; 1901758cc3dcSJack F Vogel } 19029c92bb71SSean Bruno } 1903758cc3dcSJack F Vogel 19048eb6488eSEric Joyner if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0) 19058eb6488eSEric Joyner return; 19068eb6488eSEric Joyner /* 19078eb6488eSEric Joyner * A soft reset zero's out the VFTA, so 19088eb6488eSEric Joyner * we need to repopulate it now. 19098eb6488eSEric Joyner */ 19108eb6488eSEric Joyner for (i = 0; i < IXGBE_VFTA_SIZE; i++) 19118eb6488eSEric Joyner if (adapter->shadow_vfta[i] != 0) 19128eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), 19138eb6488eSEric Joyner adapter->shadow_vfta[i]); 19148eb6488eSEric Joyner 19158eb6488eSEric Joyner ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); 19168eb6488eSEric Joyner /* Enable the Filter Table if enabled */ 19178eb6488eSEric Joyner if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) { 19188eb6488eSEric Joyner ctrl &= ~IXGBE_VLNCTRL_CFIEN; 19198eb6488eSEric Joyner ctrl |= IXGBE_VLNCTRL_VFE; 19208eb6488eSEric Joyner } 19218eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 19228eb6488eSEric Joyner ctrl |= IXGBE_VLNCTRL_VME; 19238eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); 19248eb6488eSEric Joyner } /* ixgbe_setup_vlan_hw_support */ 19258eb6488eSEric Joyner 19268eb6488eSEric Joyner /************************************************************************ 19278eb6488eSEric Joyner * ixgbe_get_slot_info 19288eb6488eSEric Joyner * 19298eb6488eSEric Joyner * Get the width and transaction speed of 19308eb6488eSEric Joyner * the slot this adapter is plugged into. 19318eb6488eSEric Joyner ************************************************************************/ 19328eb6488eSEric Joyner static void 19338eb6488eSEric Joyner ixgbe_get_slot_info(struct adapter *adapter) 19348eb6488eSEric Joyner { 1935c19c7afeSEric Joyner device_t dev = iflib_get_dev(adapter->ctx); 19368eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 1937c19c7afeSEric Joyner int bus_info_valid = TRUE; 19388eb6488eSEric Joyner u32 offset; 19398eb6488eSEric Joyner u16 link; 19408eb6488eSEric Joyner 19418eb6488eSEric Joyner /* Some devices are behind an internal bridge */ 19428eb6488eSEric Joyner switch (hw->device_id) { 19438eb6488eSEric Joyner case IXGBE_DEV_ID_82599_SFP_SF_QP: 19448eb6488eSEric Joyner case IXGBE_DEV_ID_82599_QSFP_SF_QP: 19458eb6488eSEric Joyner goto get_parent_info; 19468eb6488eSEric Joyner default: 19478eb6488eSEric Joyner break; 19488eb6488eSEric Joyner } 19498eb6488eSEric Joyner 19508eb6488eSEric Joyner ixgbe_get_bus_info(hw); 19518eb6488eSEric Joyner 19528eb6488eSEric Joyner /* 19538eb6488eSEric Joyner * Some devices don't use PCI-E, but there is no need 19548eb6488eSEric Joyner * to display "Unknown" for bus speed and width. 19558eb6488eSEric Joyner */ 19568eb6488eSEric Joyner switch (hw->mac.type) { 19578eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 19588eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 19598eb6488eSEric Joyner return; 19608eb6488eSEric Joyner default: 19618eb6488eSEric Joyner goto display; 19628eb6488eSEric Joyner } 19638eb6488eSEric Joyner 19648eb6488eSEric Joyner get_parent_info: 19658eb6488eSEric Joyner /* 19668eb6488eSEric Joyner * For the Quad port adapter we need to parse back 19678eb6488eSEric Joyner * up the PCI tree to find the speed of the expansion 19688eb6488eSEric Joyner * slot into which this adapter is plugged. A bit more work. 19698eb6488eSEric Joyner */ 19708eb6488eSEric Joyner dev = device_get_parent(device_get_parent(dev)); 19718eb6488eSEric Joyner #ifdef IXGBE_DEBUG 19728eb6488eSEric Joyner device_printf(dev, "parent pcib = %x,%x,%x\n", pci_get_bus(dev), 19738eb6488eSEric Joyner pci_get_slot(dev), pci_get_function(dev)); 19748eb6488eSEric Joyner #endif 19758eb6488eSEric Joyner dev = device_get_parent(device_get_parent(dev)); 19768eb6488eSEric Joyner #ifdef IXGBE_DEBUG 19778eb6488eSEric Joyner device_printf(dev, "slot pcib = %x,%x,%x\n", pci_get_bus(dev), 19788eb6488eSEric Joyner pci_get_slot(dev), pci_get_function(dev)); 19798eb6488eSEric Joyner #endif 19808eb6488eSEric Joyner /* Now get the PCI Express Capabilities offset */ 19818eb6488eSEric Joyner if (pci_find_cap(dev, PCIY_EXPRESS, &offset)) { 19828eb6488eSEric Joyner /* 19838eb6488eSEric Joyner * Hmm...can't get PCI-Express capabilities. 19848eb6488eSEric Joyner * Falling back to default method. 19858eb6488eSEric Joyner */ 19868eb6488eSEric Joyner bus_info_valid = FALSE; 19878eb6488eSEric Joyner ixgbe_get_bus_info(hw); 19888eb6488eSEric Joyner goto display; 19898eb6488eSEric Joyner } 19908eb6488eSEric Joyner /* ...and read the Link Status Register */ 19918eb6488eSEric Joyner link = pci_read_config(dev, offset + PCIER_LINK_STA, 2); 19928eb6488eSEric Joyner ixgbe_set_pci_config_data_generic(hw, link); 19938eb6488eSEric Joyner 19948eb6488eSEric Joyner display: 19958eb6488eSEric Joyner device_printf(dev, "PCI Express Bus: Speed %s %s\n", 19968eb6488eSEric Joyner ((hw->bus.speed == ixgbe_bus_speed_8000) ? "8.0GT/s" : 19978eb6488eSEric Joyner (hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0GT/s" : 19988eb6488eSEric Joyner (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5GT/s" : 19998eb6488eSEric Joyner "Unknown"), 20008eb6488eSEric Joyner ((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" : 20018eb6488eSEric Joyner (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" : 20028eb6488eSEric Joyner (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" : 20038eb6488eSEric Joyner "Unknown")); 20048eb6488eSEric Joyner 20058eb6488eSEric Joyner if (bus_info_valid) { 20068eb6488eSEric Joyner if ((hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) && 20078eb6488eSEric Joyner ((hw->bus.width <= ixgbe_bus_width_pcie_x4) && 20088eb6488eSEric Joyner (hw->bus.speed == ixgbe_bus_speed_2500))) { 20098eb6488eSEric Joyner device_printf(dev, "PCI-Express bandwidth available for this card\n is not sufficient for optimal performance.\n"); 20108eb6488eSEric Joyner device_printf(dev, "For optimal performance a x8 PCIE, or x4 PCIE Gen2 slot is required.\n"); 20118eb6488eSEric Joyner } 20128eb6488eSEric Joyner if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) && 20138eb6488eSEric Joyner ((hw->bus.width <= ixgbe_bus_width_pcie_x8) && 20148eb6488eSEric Joyner (hw->bus.speed < ixgbe_bus_speed_8000))) { 20158eb6488eSEric Joyner device_printf(dev, "PCI-Express bandwidth available for this card\n is not sufficient for optimal performance.\n"); 20168eb6488eSEric Joyner device_printf(dev, "For optimal performance a x8 PCIE Gen3 slot is required.\n"); 20178eb6488eSEric Joyner } 20188eb6488eSEric Joyner } else 20198eb6488eSEric Joyner device_printf(dev, "Unable to determine slot speed/width. The speed/width reported are that of the internal switch.\n"); 20208eb6488eSEric Joyner 20218eb6488eSEric Joyner return; 20228eb6488eSEric Joyner } /* ixgbe_get_slot_info */ 20238eb6488eSEric Joyner 20248eb6488eSEric Joyner /************************************************************************ 2025c19c7afeSEric Joyner * ixgbe_if_msix_intr_assign 2026c19c7afeSEric Joyner * 2027c19c7afeSEric Joyner * Setup MSI-X Interrupt resources and handlers 20288eb6488eSEric Joyner ************************************************************************/ 2029c19c7afeSEric Joyner static int 2030c19c7afeSEric Joyner ixgbe_if_msix_intr_assign(if_ctx_t ctx, int msix) 20318eb6488eSEric Joyner { 2032c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 2033c19c7afeSEric Joyner struct ix_rx_queue *rx_que = adapter->rx_queues; 2034c19c7afeSEric Joyner struct ix_tx_queue *tx_que; 2035c19c7afeSEric Joyner int error, rid, vector = 0; 2036c19c7afeSEric Joyner int cpu_id = 0; 2037c19c7afeSEric Joyner char buf[16]; 20388eb6488eSEric Joyner 2039c19c7afeSEric Joyner /* Admin Que is vector 0*/ 2040c19c7afeSEric Joyner rid = vector + 1; 2041c19c7afeSEric Joyner for (int i = 0; i < adapter->num_rx_queues; i++, vector++, rx_que++) { 2042c19c7afeSEric Joyner rid = vector + 1; 2043c19c7afeSEric Joyner 2044c19c7afeSEric Joyner snprintf(buf, sizeof(buf), "rxq%d", i); 2045c19c7afeSEric Joyner error = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid, 204681be6552SMatt Macy IFLIB_INTR_RXTX, ixgbe_msix_que, rx_que, rx_que->rxr.me, buf); 2047c19c7afeSEric Joyner 2048c19c7afeSEric Joyner if (error) { 2049c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), 2050c19c7afeSEric Joyner "Failed to allocate que int %d err: %d", i, error); 2051c19c7afeSEric Joyner adapter->num_rx_queues = i + 1; 2052c19c7afeSEric Joyner goto fail; 20538eb6488eSEric Joyner } 20548eb6488eSEric Joyner 2055c19c7afeSEric Joyner rx_que->msix = vector; 2056c19c7afeSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_RSS) { 2057c19c7afeSEric Joyner /* 2058c19c7afeSEric Joyner * The queue ID is used as the RSS layer bucket ID. 2059c19c7afeSEric Joyner * We look up the queue ID -> RSS CPU ID and select 2060c19c7afeSEric Joyner * that. 2061c19c7afeSEric Joyner */ 2062c19c7afeSEric Joyner cpu_id = rss_getcpu(i % rss_getnumbuckets()); 20638eb6488eSEric Joyner } else { 2064c19c7afeSEric Joyner /* 2065b97de13aSMarius Strobl * Bind the MSI-X vector, and thus the 2066c19c7afeSEric Joyner * rings to the corresponding cpu. 2067c19c7afeSEric Joyner * 2068c19c7afeSEric Joyner * This just happens to match the default RSS 2069c19c7afeSEric Joyner * round-robin bucket -> queue -> CPU allocation. 2070c19c7afeSEric Joyner */ 2071c19c7afeSEric Joyner if (adapter->num_rx_queues > 1) 2072c19c7afeSEric Joyner cpu_id = i; 20738eb6488eSEric Joyner } 20748eb6488eSEric Joyner 2075c19c7afeSEric Joyner } 2076c19c7afeSEric Joyner for (int i = 0; i < adapter->num_tx_queues; i++) { 2077c19c7afeSEric Joyner snprintf(buf, sizeof(buf), "txq%d", i); 2078c19c7afeSEric Joyner tx_que = &adapter->tx_queues[i]; 2079c19c7afeSEric Joyner tx_que->msix = i % adapter->num_rx_queues; 2080c19c7afeSEric Joyner iflib_softirq_alloc_generic(ctx, 2081c19c7afeSEric Joyner &adapter->rx_queues[tx_que->msix].que_irq, 2082c19c7afeSEric Joyner IFLIB_INTR_TX, tx_que, tx_que->txr.me, buf); 2083c19c7afeSEric Joyner } 2084c19c7afeSEric Joyner rid = vector + 1; 2085c19c7afeSEric Joyner error = iflib_irq_alloc_generic(ctx, &adapter->irq, rid, 2086c19c7afeSEric Joyner IFLIB_INTR_ADMIN, ixgbe_msix_link, adapter, 0, "aq"); 2087c19c7afeSEric Joyner if (error) { 2088c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), 2089c19c7afeSEric Joyner "Failed to register admin handler"); 2090c19c7afeSEric Joyner return (error); 2091c19c7afeSEric Joyner } 2092c19c7afeSEric Joyner 2093c19c7afeSEric Joyner adapter->vector = vector; 2094c19c7afeSEric Joyner 2095c19c7afeSEric Joyner return (0); 2096c19c7afeSEric Joyner fail: 2097c19c7afeSEric Joyner iflib_irq_free(ctx, &adapter->irq); 2098c19c7afeSEric Joyner rx_que = adapter->rx_queues; 2099c19c7afeSEric Joyner for (int i = 0; i < adapter->num_rx_queues; i++, rx_que++) 2100c19c7afeSEric Joyner iflib_irq_free(ctx, &rx_que->que_irq); 2101c19c7afeSEric Joyner 2102c19c7afeSEric Joyner return (error); 2103c19c7afeSEric Joyner } /* ixgbe_if_msix_intr_assign */ 2104c19c7afeSEric Joyner 2105c19c7afeSEric Joyner /********************************************************************* 21068eb6488eSEric Joyner * ixgbe_msix_que - MSI-X Queue Interrupt Service routine 2107c19c7afeSEric Joyner **********************************************************************/ 2108c19c7afeSEric Joyner static int 21098eb6488eSEric Joyner ixgbe_msix_que(void *arg) 21108eb6488eSEric Joyner { 2111c19c7afeSEric Joyner struct ix_rx_queue *que = arg; 21128eb6488eSEric Joyner struct adapter *adapter = que->adapter; 2113c19c7afeSEric Joyner struct ifnet *ifp = iflib_get_ifp(que->adapter->ctx); 21148eb6488eSEric Joyner 21158eb6488eSEric Joyner /* Protect against spurious interrupts */ 21168eb6488eSEric Joyner if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 21176c351041SEric Joyner return (FILTER_HANDLED); 21188eb6488eSEric Joyner 21198eb6488eSEric Joyner ixgbe_disable_queue(adapter, que->msix); 21208eb6488eSEric Joyner ++que->irqs; 21218eb6488eSEric Joyner 2122c19c7afeSEric Joyner return (FILTER_SCHEDULE_THREAD); 21238eb6488eSEric Joyner } /* ixgbe_msix_que */ 21248eb6488eSEric Joyner 21258eb6488eSEric Joyner /************************************************************************ 21268eb6488eSEric Joyner * ixgbe_media_status - Media Ioctl callback 21278eb6488eSEric Joyner * 21288eb6488eSEric Joyner * Called whenever the user queries the status of 21298eb6488eSEric Joyner * the interface using ifconfig. 21308eb6488eSEric Joyner ************************************************************************/ 21318eb6488eSEric Joyner static void 2132c19c7afeSEric Joyner ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr) 21338eb6488eSEric Joyner { 2134c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 21358eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 21368eb6488eSEric Joyner int layer; 21378eb6488eSEric Joyner 2138c19c7afeSEric Joyner INIT_DEBUGOUT("ixgbe_if_media_status: begin"); 2139c19c7afeSEric Joyner 21408eb6488eSEric Joyner ifmr->ifm_status = IFM_AVALID; 21418eb6488eSEric Joyner ifmr->ifm_active = IFM_ETHER; 21428eb6488eSEric Joyner 2143c19c7afeSEric Joyner if (!adapter->link_active) 21448eb6488eSEric Joyner return; 21458eb6488eSEric Joyner 21468eb6488eSEric Joyner ifmr->ifm_status |= IFM_ACTIVE; 21478eb6488eSEric Joyner layer = adapter->phy_layer; 21488eb6488eSEric Joyner 21498eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T || 21508eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_T || 21518eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_100BASE_TX || 21528eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_10BASE_T) 21538eb6488eSEric Joyner switch (adapter->link_speed) { 21548eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 21558eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_T | IFM_FDX; 21568eb6488eSEric Joyner break; 21578eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 21588eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_T | IFM_FDX; 21598eb6488eSEric Joyner break; 21608eb6488eSEric Joyner case IXGBE_LINK_SPEED_100_FULL: 21618eb6488eSEric Joyner ifmr->ifm_active |= IFM_100_TX | IFM_FDX; 21628eb6488eSEric Joyner break; 21638eb6488eSEric Joyner case IXGBE_LINK_SPEED_10_FULL: 21648eb6488eSEric Joyner ifmr->ifm_active |= IFM_10_T | IFM_FDX; 21658eb6488eSEric Joyner break; 21668eb6488eSEric Joyner } 21678eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || 21688eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) 21698eb6488eSEric Joyner switch (adapter->link_speed) { 21708eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 21718eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX; 21728eb6488eSEric Joyner break; 21738eb6488eSEric Joyner } 21748eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) 21758eb6488eSEric Joyner switch (adapter->link_speed) { 21768eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 21778eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_LR | IFM_FDX; 21788eb6488eSEric Joyner break; 21798eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 21808eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; 21818eb6488eSEric Joyner break; 21828eb6488eSEric Joyner } 21838eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM) 21848eb6488eSEric Joyner switch (adapter->link_speed) { 21858eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 21868eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX; 21878eb6488eSEric Joyner break; 21888eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 21898eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; 21908eb6488eSEric Joyner break; 21918eb6488eSEric Joyner } 21928eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR || 21938eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) 21948eb6488eSEric Joyner switch (adapter->link_speed) { 21958eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 21968eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; 21978eb6488eSEric Joyner break; 21988eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 21998eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_SX | IFM_FDX; 22008eb6488eSEric Joyner break; 22018eb6488eSEric Joyner } 22028eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) 22038eb6488eSEric Joyner switch (adapter->link_speed) { 22048eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 22058eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; 22068eb6488eSEric Joyner break; 22078eb6488eSEric Joyner } 22088eb6488eSEric Joyner /* 22098eb6488eSEric Joyner * XXX: These need to use the proper media types once 22108eb6488eSEric Joyner * they're added. 22118eb6488eSEric Joyner */ 22128eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE 22138eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 22148eb6488eSEric Joyner switch (adapter->link_speed) { 22158eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 22168eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; 22178eb6488eSEric Joyner break; 22188eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 22198eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; 22208eb6488eSEric Joyner break; 22218eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 22228eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; 22238eb6488eSEric Joyner break; 22248eb6488eSEric Joyner } 22258eb6488eSEric Joyner else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 || 22268eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX || 22278eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 22288eb6488eSEric Joyner switch (adapter->link_speed) { 22298eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 22308eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; 22318eb6488eSEric Joyner break; 22328eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 22338eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; 22348eb6488eSEric Joyner break; 22358eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 22368eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; 22378eb6488eSEric Joyner break; 22388eb6488eSEric Joyner } 22398eb6488eSEric Joyner #else 22408eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 22418eb6488eSEric Joyner switch (adapter->link_speed) { 22428eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 22438eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_KR | IFM_FDX; 22448eb6488eSEric Joyner break; 22458eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 22468eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; 22478eb6488eSEric Joyner break; 22488eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 22498eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; 22508eb6488eSEric Joyner break; 22518eb6488eSEric Joyner } 22528eb6488eSEric Joyner else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 || 22538eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX || 22548eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 22558eb6488eSEric Joyner switch (adapter->link_speed) { 22568eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 22578eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX; 22588eb6488eSEric Joyner break; 22598eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 22608eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; 22618eb6488eSEric Joyner break; 22628eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 22638eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; 22648eb6488eSEric Joyner break; 22658eb6488eSEric Joyner } 22668eb6488eSEric Joyner #endif 22678eb6488eSEric Joyner 22688eb6488eSEric Joyner /* If nothing is recognized... */ 22698eb6488eSEric Joyner if (IFM_SUBTYPE(ifmr->ifm_active) == 0) 22708eb6488eSEric Joyner ifmr->ifm_active |= IFM_UNKNOWN; 22718eb6488eSEric Joyner 22728eb6488eSEric Joyner /* Display current flow control setting used on link */ 22738eb6488eSEric Joyner if (hw->fc.current_mode == ixgbe_fc_rx_pause || 22748eb6488eSEric Joyner hw->fc.current_mode == ixgbe_fc_full) 22758eb6488eSEric Joyner ifmr->ifm_active |= IFM_ETH_RXPAUSE; 22768eb6488eSEric Joyner if (hw->fc.current_mode == ixgbe_fc_tx_pause || 22778eb6488eSEric Joyner hw->fc.current_mode == ixgbe_fc_full) 22788eb6488eSEric Joyner ifmr->ifm_active |= IFM_ETH_TXPAUSE; 22798eb6488eSEric Joyner } /* ixgbe_media_status */ 22808eb6488eSEric Joyner 22818eb6488eSEric Joyner /************************************************************************ 22828eb6488eSEric Joyner * ixgbe_media_change - Media Ioctl callback 22838eb6488eSEric Joyner * 22848eb6488eSEric Joyner * Called when the user changes speed/duplex using 22858eb6488eSEric Joyner * media/mediopt option with ifconfig. 22868eb6488eSEric Joyner ************************************************************************/ 22878eb6488eSEric Joyner static int 2288c19c7afeSEric Joyner ixgbe_if_media_change(if_ctx_t ctx) 22898eb6488eSEric Joyner { 2290c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 2291c19c7afeSEric Joyner struct ifmedia *ifm = iflib_get_media(ctx); 22928eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 22938eb6488eSEric Joyner ixgbe_link_speed speed = 0; 22948eb6488eSEric Joyner 2295c19c7afeSEric Joyner INIT_DEBUGOUT("ixgbe_if_media_change: begin"); 22968eb6488eSEric Joyner 22978eb6488eSEric Joyner if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 22988eb6488eSEric Joyner return (EINVAL); 22998eb6488eSEric Joyner 23008eb6488eSEric Joyner if (hw->phy.media_type == ixgbe_media_type_backplane) 2301c19c7afeSEric Joyner return (EPERM); 23028eb6488eSEric Joyner 23038eb6488eSEric Joyner /* 23048eb6488eSEric Joyner * We don't actually need to check against the supported 23058eb6488eSEric Joyner * media types of the adapter; ifmedia will take care of 23068eb6488eSEric Joyner * that for us. 23078eb6488eSEric Joyner */ 23088eb6488eSEric Joyner switch (IFM_SUBTYPE(ifm->ifm_media)) { 23098eb6488eSEric Joyner case IFM_AUTO: 23108eb6488eSEric Joyner case IFM_10G_T: 23118eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_100_FULL; 23128eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 23138eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10GB_FULL; 23148eb6488eSEric Joyner break; 23158eb6488eSEric Joyner case IFM_10G_LRM: 23168eb6488eSEric Joyner case IFM_10G_LR: 23178eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE 23188eb6488eSEric Joyner case IFM_10G_SR: /* KR, too */ 23198eb6488eSEric Joyner case IFM_10G_CX4: /* KX4 */ 23208eb6488eSEric Joyner #else 23218eb6488eSEric Joyner case IFM_10G_KR: 23228eb6488eSEric Joyner case IFM_10G_KX4: 23238eb6488eSEric Joyner #endif 23248eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 23258eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10GB_FULL; 23268eb6488eSEric Joyner break; 23278eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE 23288eb6488eSEric Joyner case IFM_1000_CX: /* KX */ 23298eb6488eSEric Joyner #else 23308eb6488eSEric Joyner case IFM_1000_KX: 23318eb6488eSEric Joyner #endif 23328eb6488eSEric Joyner case IFM_1000_LX: 23338eb6488eSEric Joyner case IFM_1000_SX: 23348eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 23358eb6488eSEric Joyner break; 23368eb6488eSEric Joyner case IFM_1000_T: 23378eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_100_FULL; 23388eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 23398eb6488eSEric Joyner break; 23408eb6488eSEric Joyner case IFM_10G_TWINAX: 23418eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10GB_FULL; 23428eb6488eSEric Joyner break; 23438eb6488eSEric Joyner case IFM_100_TX: 23448eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_100_FULL; 23458eb6488eSEric Joyner break; 23468eb6488eSEric Joyner case IFM_10_T: 23478eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10_FULL; 23488eb6488eSEric Joyner break; 23498eb6488eSEric Joyner default: 23508eb6488eSEric Joyner goto invalid; 23518eb6488eSEric Joyner } 23528eb6488eSEric Joyner 23538eb6488eSEric Joyner hw->mac.autotry_restart = TRUE; 23548eb6488eSEric Joyner hw->mac.ops.setup_link(hw, speed, TRUE); 23558eb6488eSEric Joyner adapter->advertise = 23568eb6488eSEric Joyner ((speed & IXGBE_LINK_SPEED_10GB_FULL) ? 4 : 0) | 23578eb6488eSEric Joyner ((speed & IXGBE_LINK_SPEED_1GB_FULL) ? 2 : 0) | 23588eb6488eSEric Joyner ((speed & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0) | 23598eb6488eSEric Joyner ((speed & IXGBE_LINK_SPEED_10_FULL) ? 8 : 0); 23608eb6488eSEric Joyner 23618eb6488eSEric Joyner return (0); 23628eb6488eSEric Joyner 23638eb6488eSEric Joyner invalid: 2364c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), "Invalid media type!\n"); 23658eb6488eSEric Joyner 23668eb6488eSEric Joyner return (EINVAL); 2367c19c7afeSEric Joyner } /* ixgbe_if_media_change */ 23688eb6488eSEric Joyner 23698eb6488eSEric Joyner /************************************************************************ 23708eb6488eSEric Joyner * ixgbe_set_promisc 23718eb6488eSEric Joyner ************************************************************************/ 2372c19c7afeSEric Joyner static int 2373c19c7afeSEric Joyner ixgbe_if_promisc_set(if_ctx_t ctx, int flags) 23748eb6488eSEric Joyner { 2375c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 2376c19c7afeSEric Joyner struct ifnet *ifp = iflib_get_ifp(ctx); 23778eb6488eSEric Joyner u32 rctl; 2378c19c7afeSEric Joyner int mcnt = 0; 23798eb6488eSEric Joyner 23808eb6488eSEric Joyner rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); 23818eb6488eSEric Joyner rctl &= (~IXGBE_FCTRL_UPE); 23828eb6488eSEric Joyner if (ifp->if_flags & IFF_ALLMULTI) 23838eb6488eSEric Joyner mcnt = MAX_NUM_MULTICAST_ADDRESSES; 23848eb6488eSEric Joyner else { 2385ba76aa63SGleb Smirnoff mcnt = min(if_llmaddr_count(ifp), MAX_NUM_MULTICAST_ADDRESSES); 23868eb6488eSEric Joyner } 23878eb6488eSEric Joyner if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) 23888eb6488eSEric Joyner rctl &= (~IXGBE_FCTRL_MPE); 23898eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl); 23908eb6488eSEric Joyner 23918eb6488eSEric Joyner if (ifp->if_flags & IFF_PROMISC) { 23928eb6488eSEric Joyner rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 23938eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl); 23948eb6488eSEric Joyner } else if (ifp->if_flags & IFF_ALLMULTI) { 23958eb6488eSEric Joyner rctl |= IXGBE_FCTRL_MPE; 23968eb6488eSEric Joyner rctl &= ~IXGBE_FCTRL_UPE; 23978eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl); 23988eb6488eSEric Joyner } 2399c19c7afeSEric Joyner return (0); 2400c19c7afeSEric Joyner } /* ixgbe_if_promisc_set */ 24018eb6488eSEric Joyner 24028eb6488eSEric Joyner /************************************************************************ 24038eb6488eSEric Joyner * ixgbe_msix_link - Link status change ISR (MSI/MSI-X) 24048eb6488eSEric Joyner ************************************************************************/ 2405c19c7afeSEric Joyner static int 24068eb6488eSEric Joyner ixgbe_msix_link(void *arg) 24078eb6488eSEric Joyner { 24088eb6488eSEric Joyner struct adapter *adapter = arg; 24098eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 24108eb6488eSEric Joyner u32 eicr, eicr_mask; 24118eb6488eSEric Joyner s32 retval; 24128eb6488eSEric Joyner 24138eb6488eSEric Joyner ++adapter->link_irq; 24148eb6488eSEric Joyner 24158eb6488eSEric Joyner /* Pause other interrupts */ 24168eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER); 24178eb6488eSEric Joyner 24188eb6488eSEric Joyner /* First get the cause */ 24198eb6488eSEric Joyner eicr = IXGBE_READ_REG(hw, IXGBE_EICS); 24208eb6488eSEric Joyner /* Be sure the queue bits are not cleared */ 24218eb6488eSEric Joyner eicr &= ~IXGBE_EICR_RTX_QUEUE; 24228eb6488eSEric Joyner /* Clear interrupt with write */ 24238eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr); 24248eb6488eSEric Joyner 24258eb6488eSEric Joyner /* Link status change */ 24268eb6488eSEric Joyner if (eicr & IXGBE_EICR_LSC) { 24278eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); 2428b2c1e8e6SEric Joyner adapter->task_requests |= IXGBE_REQUEST_TASK_LSC; 24298eb6488eSEric Joyner } 24308eb6488eSEric Joyner 24318eb6488eSEric Joyner if (adapter->hw.mac.type != ixgbe_mac_82598EB) { 24328eb6488eSEric Joyner if ((adapter->feat_en & IXGBE_FEATURE_FDIR) && 24338eb6488eSEric Joyner (eicr & IXGBE_EICR_FLOW_DIR)) { 24348eb6488eSEric Joyner /* This is probably overkill :) */ 24358eb6488eSEric Joyner if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1)) 2436c19c7afeSEric Joyner return (FILTER_HANDLED); 24378eb6488eSEric Joyner /* Disable the interrupt */ 2438c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR); 2439b2c1e8e6SEric Joyner adapter->task_requests |= IXGBE_REQUEST_TASK_FDIR; 2440c19c7afeSEric Joyner } else 24418eb6488eSEric Joyner if (eicr & IXGBE_EICR_ECC) { 2442c19c7afeSEric Joyner device_printf(iflib_get_dev(adapter->ctx), 2443c19c7afeSEric Joyner "\nCRITICAL: ECC ERROR!! Please Reboot!!\n"); 24448eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC); 24458eb6488eSEric Joyner } 24468eb6488eSEric Joyner 24478eb6488eSEric Joyner /* Check for over temp condition */ 24488eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR) { 24498eb6488eSEric Joyner switch (adapter->hw.mac.type) { 24508eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 24518eb6488eSEric Joyner if (!(eicr & IXGBE_EICR_GPI_SDP0_X550EM_a)) 24528eb6488eSEric Joyner break; 24538eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, 24548eb6488eSEric Joyner IXGBE_EICR_GPI_SDP0_X550EM_a); 24558eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, 24568eb6488eSEric Joyner IXGBE_EICR_GPI_SDP0_X550EM_a); 24578eb6488eSEric Joyner retval = hw->phy.ops.check_overtemp(hw); 24588eb6488eSEric Joyner if (retval != IXGBE_ERR_OVERTEMP) 24598eb6488eSEric Joyner break; 2460c19c7afeSEric Joyner device_printf(iflib_get_dev(adapter->ctx), 2461c19c7afeSEric Joyner "\nCRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n"); 2462c19c7afeSEric Joyner device_printf(iflib_get_dev(adapter->ctx), 2463c19c7afeSEric Joyner "System shutdown required!\n"); 24648eb6488eSEric Joyner break; 24658eb6488eSEric Joyner default: 24668eb6488eSEric Joyner if (!(eicr & IXGBE_EICR_TS)) 24678eb6488eSEric Joyner break; 24688eb6488eSEric Joyner retval = hw->phy.ops.check_overtemp(hw); 24698eb6488eSEric Joyner if (retval != IXGBE_ERR_OVERTEMP) 24708eb6488eSEric Joyner break; 2471c19c7afeSEric Joyner device_printf(iflib_get_dev(adapter->ctx), 2472c19c7afeSEric Joyner "\nCRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n"); 2473c19c7afeSEric Joyner device_printf(iflib_get_dev(adapter->ctx), 2474c19c7afeSEric Joyner "System shutdown required!\n"); 24758eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS); 24768eb6488eSEric Joyner break; 24778eb6488eSEric Joyner } 24788eb6488eSEric Joyner } 24798eb6488eSEric Joyner 24808eb6488eSEric Joyner /* Check for VF message */ 24818eb6488eSEric Joyner if ((adapter->feat_en & IXGBE_FEATURE_SRIOV) && 24828eb6488eSEric Joyner (eicr & IXGBE_EICR_MAILBOX)) 2483b2c1e8e6SEric Joyner adapter->task_requests |= IXGBE_REQUEST_TASK_MBX; 24848eb6488eSEric Joyner } 24858eb6488eSEric Joyner 24868eb6488eSEric Joyner if (ixgbe_is_sfp(hw)) { 24878eb6488eSEric Joyner /* Pluggable optics-related interrupt */ 24888eb6488eSEric Joyner if (hw->mac.type >= ixgbe_mac_X540) 24898eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP0_X540; 24908eb6488eSEric Joyner else 24918eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); 24928eb6488eSEric Joyner 24938eb6488eSEric Joyner if (eicr & eicr_mask) { 24948eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); 2495b2c1e8e6SEric Joyner adapter->task_requests |= IXGBE_REQUEST_TASK_MOD; 24968eb6488eSEric Joyner } 24978eb6488eSEric Joyner 24988eb6488eSEric Joyner if ((hw->mac.type == ixgbe_mac_82599EB) && 24998eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { 25008eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, 25018eb6488eSEric Joyner IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 2502b2c1e8e6SEric Joyner adapter->task_requests |= IXGBE_REQUEST_TASK_MSF; 25038eb6488eSEric Joyner } 25048eb6488eSEric Joyner } 25058eb6488eSEric Joyner 25068eb6488eSEric Joyner /* Check for fan failure */ 25078eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) { 25088eb6488eSEric Joyner ixgbe_check_fan_failure(adapter, eicr, TRUE); 25098eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 25108eb6488eSEric Joyner } 25118eb6488eSEric Joyner 25128eb6488eSEric Joyner /* External PHY interrupt */ 25138eb6488eSEric Joyner if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && 25148eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP0_X540)) { 25158eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540); 2516b2c1e8e6SEric Joyner adapter->task_requests |= IXGBE_REQUEST_TASK_PHY; 25178eb6488eSEric Joyner } 25188eb6488eSEric Joyner 2519b2c1e8e6SEric Joyner return (adapter->task_requests != 0) ? FILTER_SCHEDULE_THREAD : FILTER_HANDLED; 25208eb6488eSEric Joyner } /* ixgbe_msix_link */ 25218eb6488eSEric Joyner 25228eb6488eSEric Joyner /************************************************************************ 25238eb6488eSEric Joyner * ixgbe_sysctl_interrupt_rate_handler 25248eb6488eSEric Joyner ************************************************************************/ 2525758cc3dcSJack F Vogel static int 2526758cc3dcSJack F Vogel ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS) 2527758cc3dcSJack F Vogel { 2528c19c7afeSEric Joyner struct ix_rx_queue *que = ((struct ix_rx_queue *)oidp->oid_arg1); 25298eb6488eSEric Joyner int error; 2530758cc3dcSJack F Vogel unsigned int reg, usec, rate; 2531758cc3dcSJack F Vogel 2532758cc3dcSJack F Vogel reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix)); 2533758cc3dcSJack F Vogel usec = ((reg & 0x0FF8) >> 3); 2534758cc3dcSJack F Vogel if (usec > 0) 2535758cc3dcSJack F Vogel rate = 500000 / usec; 2536758cc3dcSJack F Vogel else 2537758cc3dcSJack F Vogel rate = 0; 2538758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &rate, 0, req); 2539758cc3dcSJack F Vogel if (error || !req->newptr) 2540758cc3dcSJack F Vogel return error; 2541758cc3dcSJack F Vogel reg &= ~0xfff; /* default, no limitation */ 2542758cc3dcSJack F Vogel ixgbe_max_interrupt_rate = 0; 2543758cc3dcSJack F Vogel if (rate > 0 && rate < 500000) { 2544758cc3dcSJack F Vogel if (rate < 1000) 2545758cc3dcSJack F Vogel rate = 1000; 2546758cc3dcSJack F Vogel ixgbe_max_interrupt_rate = rate; 2547758cc3dcSJack F Vogel reg |= ((4000000/rate) & 0xff8); 2548758cc3dcSJack F Vogel } 2549758cc3dcSJack F Vogel IXGBE_WRITE_REG(&que->adapter->hw, IXGBE_EITR(que->msix), reg); 2550758cc3dcSJack F Vogel 25518eb6488eSEric Joyner return (0); 25528eb6488eSEric Joyner } /* ixgbe_sysctl_interrupt_rate_handler */ 25538eb6488eSEric Joyner 25548eb6488eSEric Joyner /************************************************************************ 25558eb6488eSEric Joyner * ixgbe_add_device_sysctls 25568eb6488eSEric Joyner ************************************************************************/ 25576f37f232SEric Joyner static void 2558c19c7afeSEric Joyner ixgbe_add_device_sysctls(if_ctx_t ctx) 25596f37f232SEric Joyner { 2560c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 2561c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 25626f37f232SEric Joyner struct ixgbe_hw *hw = &adapter->hw; 25636f37f232SEric Joyner struct sysctl_oid_list *child; 2564c19c7afeSEric Joyner struct sysctl_ctx_list *ctx_list; 25656f37f232SEric Joyner 2566c19c7afeSEric Joyner ctx_list = device_get_sysctl_ctx(dev); 25676f37f232SEric Joyner child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); 25686f37f232SEric Joyner 25696f37f232SEric Joyner /* Sysctls for all devices */ 2570c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "fc", 257120b91f0aSPawel Biernacki CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 257220b91f0aSPawel Biernacki adapter, 0, ixgbe_sysctl_flowcntl, "I", 2573c19c7afeSEric Joyner IXGBE_SYSCTL_DESC_SET_FC); 25746f37f232SEric Joyner 2575c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "advertise_speed", 257620b91f0aSPawel Biernacki CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 257720b91f0aSPawel Biernacki adapter, 0, ixgbe_sysctl_advertise, "I", 25788eb6488eSEric Joyner IXGBE_SYSCTL_DESC_ADV_SPEED); 25796f37f232SEric Joyner 2580a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 2581a9ca1c79SSean Bruno /* testing sysctls (for all devices) */ 2582c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "power_state", 258320b91f0aSPawel Biernacki CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 258420b91f0aSPawel Biernacki adapter, 0, ixgbe_sysctl_power_state, 25858eb6488eSEric Joyner "I", "PCI Power State"); 2586a9ca1c79SSean Bruno 2587c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "print_rss_config", 258820b91f0aSPawel Biernacki CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, adapter, 0, 2589a9ca1c79SSean Bruno ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration"); 2590a9ca1c79SSean Bruno #endif 2591a9ca1c79SSean Bruno /* for X550 series devices */ 25926f37f232SEric Joyner if (hw->mac.type >= ixgbe_mac_X550) 2593c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "dmac", 259420b91f0aSPawel Biernacki CTLTYPE_U16 | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 259520b91f0aSPawel Biernacki adapter, 0, ixgbe_sysctl_dmac, 25968eb6488eSEric Joyner "I", "DMA Coalesce"); 25976f37f232SEric Joyner 2598a9ca1c79SSean Bruno /* for WoL-capable devices */ 2599a9ca1c79SSean Bruno if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { 2600c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wol_enable", 260120b91f0aSPawel Biernacki CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, adapter, 0, 26028eb6488eSEric Joyner ixgbe_sysctl_wol_enable, "I", "Enable/Disable Wake on LAN"); 26036f37f232SEric Joyner 2604c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wufc", 260520b91f0aSPawel Biernacki CTLTYPE_U32 | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 260620b91f0aSPawel Biernacki adapter, 0, ixgbe_sysctl_wufc, 26078eb6488eSEric Joyner "I", "Enable/Disable Wake Up Filters"); 26086f37f232SEric Joyner } 26096f37f232SEric Joyner 2610a9ca1c79SSean Bruno /* for X552/X557-AT devices */ 26116f37f232SEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { 26126f37f232SEric Joyner struct sysctl_oid *phy_node; 26136f37f232SEric Joyner struct sysctl_oid_list *phy_list; 26146f37f232SEric Joyner 2615c19c7afeSEric Joyner phy_node = SYSCTL_ADD_NODE(ctx_list, child, OID_AUTO, "phy", 261620b91f0aSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "External PHY sysctls"); 26176f37f232SEric Joyner phy_list = SYSCTL_CHILDREN(phy_node); 26186f37f232SEric Joyner 2619c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO, "temp", 262020b91f0aSPawel Biernacki CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_NEEDGIANT, 262120b91f0aSPawel Biernacki adapter, 0, ixgbe_sysctl_phy_temp, 26228eb6488eSEric Joyner "I", "Current External PHY Temperature (Celsius)"); 26236f37f232SEric Joyner 2624c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO, 262520b91f0aSPawel Biernacki "overtemp_occurred", 262620b91f0aSPawel Biernacki CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_NEEDGIANT, adapter, 0, 26276f37f232SEric Joyner ixgbe_sysctl_phy_overtemp_occurred, "I", 26286f37f232SEric Joyner "External PHY High Temperature Event Occurred"); 26296f37f232SEric Joyner } 26308eb6488eSEric Joyner 26318eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_EEE) { 2632c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "eee_state", 263320b91f0aSPawel Biernacki CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, adapter, 0, 26348eb6488eSEric Joyner ixgbe_sysctl_eee_state, "I", "EEE Power Save State"); 26358eb6488eSEric Joyner } 26368eb6488eSEric Joyner } /* ixgbe_add_device_sysctls */ 26378eb6488eSEric Joyner 26388eb6488eSEric Joyner /************************************************************************ 26398eb6488eSEric Joyner * ixgbe_allocate_pci_resources 26408eb6488eSEric Joyner ************************************************************************/ 26418eb6488eSEric Joyner static int 2642c19c7afeSEric Joyner ixgbe_allocate_pci_resources(if_ctx_t ctx) 26438eb6488eSEric Joyner { 2644c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 2645c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 26468eb6488eSEric Joyner int rid; 26478eb6488eSEric Joyner 26488eb6488eSEric Joyner rid = PCIR_BAR(0); 26498eb6488eSEric Joyner adapter->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 26508eb6488eSEric Joyner RF_ACTIVE); 26518eb6488eSEric Joyner 26528eb6488eSEric Joyner if (!(adapter->pci_mem)) { 26538eb6488eSEric Joyner device_printf(dev, "Unable to allocate bus resource: memory\n"); 26548eb6488eSEric Joyner return (ENXIO); 26558eb6488eSEric Joyner } 26568eb6488eSEric Joyner 26578eb6488eSEric Joyner /* Save bus_space values for READ/WRITE_REG macros */ 26588eb6488eSEric Joyner adapter->osdep.mem_bus_space_tag = rman_get_bustag(adapter->pci_mem); 26598eb6488eSEric Joyner adapter->osdep.mem_bus_space_handle = 26608eb6488eSEric Joyner rman_get_bushandle(adapter->pci_mem); 26618eb6488eSEric Joyner /* Set hw values for shared code */ 26628eb6488eSEric Joyner adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle; 26638eb6488eSEric Joyner 26648eb6488eSEric Joyner return (0); 26658eb6488eSEric Joyner } /* ixgbe_allocate_pci_resources */ 26668eb6488eSEric Joyner 26678eb6488eSEric Joyner /************************************************************************ 26688eb6488eSEric Joyner * ixgbe_detach - Device removal routine 26698eb6488eSEric Joyner * 26708eb6488eSEric Joyner * Called when the driver is being removed. 26718eb6488eSEric Joyner * Stops the adapter and deallocates all the resources 26728eb6488eSEric Joyner * that were allocated for driver operation. 26738eb6488eSEric Joyner * 26748eb6488eSEric Joyner * return 0 on success, positive on failure 26758eb6488eSEric Joyner ************************************************************************/ 26768eb6488eSEric Joyner static int 2677c19c7afeSEric Joyner ixgbe_if_detach(if_ctx_t ctx) 26788eb6488eSEric Joyner { 2679c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 2680c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 26818eb6488eSEric Joyner u32 ctrl_ext; 26828eb6488eSEric Joyner 26838eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_detach: begin"); 26848eb6488eSEric Joyner 26858eb6488eSEric Joyner if (ixgbe_pci_iov_detach(dev) != 0) { 26868eb6488eSEric Joyner device_printf(dev, "SR-IOV in use; detach first.\n"); 26878eb6488eSEric Joyner return (EBUSY); 26888eb6488eSEric Joyner } 26898eb6488eSEric Joyner 2690c19c7afeSEric Joyner ixgbe_setup_low_power_mode(ctx); 26918eb6488eSEric Joyner 26928eb6488eSEric Joyner /* let hardware know driver is unloading */ 26938eb6488eSEric Joyner ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); 26948eb6488eSEric Joyner ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD; 26958eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext); 26968eb6488eSEric Joyner 2697c19c7afeSEric Joyner ixgbe_free_pci_resources(ctx); 26988eb6488eSEric Joyner free(adapter->mta, M_IXGBE); 26998eb6488eSEric Joyner 27008eb6488eSEric Joyner return (0); 2701c19c7afeSEric Joyner } /* ixgbe_if_detach */ 27028eb6488eSEric Joyner 27038eb6488eSEric Joyner /************************************************************************ 27048eb6488eSEric Joyner * ixgbe_setup_low_power_mode - LPLU/WoL preparation 27058eb6488eSEric Joyner * 27068eb6488eSEric Joyner * Prepare the adapter/port for LPLU and/or WoL 27078eb6488eSEric Joyner ************************************************************************/ 27088eb6488eSEric Joyner static int 2709c19c7afeSEric Joyner ixgbe_setup_low_power_mode(if_ctx_t ctx) 27108eb6488eSEric Joyner { 2711c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 27128eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 2713c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 27148eb6488eSEric Joyner s32 error = 0; 27158eb6488eSEric Joyner 2716c19c7afeSEric Joyner if (!hw->wol_enabled) 2717c19c7afeSEric Joyner ixgbe_set_phy_power(hw, FALSE); 27188eb6488eSEric Joyner 27198eb6488eSEric Joyner /* Limit power management flow to X550EM baseT */ 27208eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T && 27218eb6488eSEric Joyner hw->phy.ops.enter_lplu) { 27228eb6488eSEric Joyner /* Turn off support for APM wakeup. (Using ACPI instead) */ 27238eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_GRC, 27248eb6488eSEric Joyner IXGBE_READ_REG(hw, IXGBE_GRC) & ~(u32)2); 27258eb6488eSEric Joyner 27268eb6488eSEric Joyner /* 27278eb6488eSEric Joyner * Clear Wake Up Status register to prevent any previous wakeup 27288eb6488eSEric Joyner * events from waking us up immediately after we suspend. 27298eb6488eSEric Joyner */ 27308eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff); 27318eb6488eSEric Joyner 27328eb6488eSEric Joyner /* 27338eb6488eSEric Joyner * Program the Wakeup Filter Control register with user filter 27348eb6488eSEric Joyner * settings 27358eb6488eSEric Joyner */ 27368eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUFC, adapter->wufc); 27378eb6488eSEric Joyner 27388eb6488eSEric Joyner /* Enable wakeups and power management in Wakeup Control */ 27398eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUC, 27408eb6488eSEric Joyner IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN); 27418eb6488eSEric Joyner 27428eb6488eSEric Joyner /* X550EM baseT adapters need a special LPLU flow */ 2743c19c7afeSEric Joyner hw->phy.reset_disable = TRUE; 2744c19c7afeSEric Joyner ixgbe_if_stop(ctx); 27458eb6488eSEric Joyner error = hw->phy.ops.enter_lplu(hw); 27468eb6488eSEric Joyner if (error) 27478eb6488eSEric Joyner device_printf(dev, "Error entering LPLU: %d\n", error); 2748c19c7afeSEric Joyner hw->phy.reset_disable = FALSE; 27498eb6488eSEric Joyner } else { 27508eb6488eSEric Joyner /* Just stop for other adapters */ 2751c19c7afeSEric Joyner ixgbe_if_stop(ctx); 27528eb6488eSEric Joyner } 27538eb6488eSEric Joyner 27548eb6488eSEric Joyner return error; 27558eb6488eSEric Joyner } /* ixgbe_setup_low_power_mode */ 27568eb6488eSEric Joyner 27578eb6488eSEric Joyner /************************************************************************ 27588eb6488eSEric Joyner * ixgbe_shutdown - Shutdown entry point 27598eb6488eSEric Joyner ************************************************************************/ 27608eb6488eSEric Joyner static int 2761c19c7afeSEric Joyner ixgbe_if_shutdown(if_ctx_t ctx) 27628eb6488eSEric Joyner { 27638eb6488eSEric Joyner int error = 0; 27648eb6488eSEric Joyner 27658eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_shutdown: begin"); 27668eb6488eSEric Joyner 2767c19c7afeSEric Joyner error = ixgbe_setup_low_power_mode(ctx); 27688eb6488eSEric Joyner 27698eb6488eSEric Joyner return (error); 2770c19c7afeSEric Joyner } /* ixgbe_if_shutdown */ 27718eb6488eSEric Joyner 27728eb6488eSEric Joyner /************************************************************************ 27738eb6488eSEric Joyner * ixgbe_suspend 27748eb6488eSEric Joyner * 27758eb6488eSEric Joyner * From D0 to D3 27768eb6488eSEric Joyner ************************************************************************/ 27778eb6488eSEric Joyner static int 2778c19c7afeSEric Joyner ixgbe_if_suspend(if_ctx_t ctx) 27798eb6488eSEric Joyner { 27808eb6488eSEric Joyner int error = 0; 27818eb6488eSEric Joyner 27828eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_suspend: begin"); 27838eb6488eSEric Joyner 2784c19c7afeSEric Joyner error = ixgbe_setup_low_power_mode(ctx); 27858eb6488eSEric Joyner 27868eb6488eSEric Joyner return (error); 2787c19c7afeSEric Joyner } /* ixgbe_if_suspend */ 27888eb6488eSEric Joyner 27898eb6488eSEric Joyner /************************************************************************ 27908eb6488eSEric Joyner * ixgbe_resume 27918eb6488eSEric Joyner * 27928eb6488eSEric Joyner * From D3 to D0 27938eb6488eSEric Joyner ************************************************************************/ 27948eb6488eSEric Joyner static int 2795c19c7afeSEric Joyner ixgbe_if_resume(if_ctx_t ctx) 27968eb6488eSEric Joyner { 2797c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 2798c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 2799c19c7afeSEric Joyner struct ifnet *ifp = iflib_get_ifp(ctx); 28008eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 28018eb6488eSEric Joyner u32 wus; 28028eb6488eSEric Joyner 28038eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_resume: begin"); 28048eb6488eSEric Joyner 28058eb6488eSEric Joyner /* Read & clear WUS register */ 28068eb6488eSEric Joyner wus = IXGBE_READ_REG(hw, IXGBE_WUS); 28078eb6488eSEric Joyner if (wus) 28088eb6488eSEric Joyner device_printf(dev, "Woken up by (WUS): %#010x\n", 28098eb6488eSEric Joyner IXGBE_READ_REG(hw, IXGBE_WUS)); 28108eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff); 28118eb6488eSEric Joyner /* And clear WUFC until next low-power transition */ 28128eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0); 28138eb6488eSEric Joyner 28148eb6488eSEric Joyner /* 28158eb6488eSEric Joyner * Required after D3->D0 transition; 28168eb6488eSEric Joyner * will re-advertise all previous advertised speeds 28178eb6488eSEric Joyner */ 28188eb6488eSEric Joyner if (ifp->if_flags & IFF_UP) 2819c19c7afeSEric Joyner ixgbe_if_init(ctx); 28208eb6488eSEric Joyner 28218eb6488eSEric Joyner return (0); 2822c19c7afeSEric Joyner } /* ixgbe_if_resume */ 28238eb6488eSEric Joyner 28248eb6488eSEric Joyner /************************************************************************ 2825c19c7afeSEric Joyner * ixgbe_if_mtu_set - Ioctl mtu entry point 28268eb6488eSEric Joyner * 2827c19c7afeSEric Joyner * Return 0 on success, EINVAL on failure 2828c19c7afeSEric Joyner ************************************************************************/ 2829c19c7afeSEric Joyner static int 2830c19c7afeSEric Joyner ixgbe_if_mtu_set(if_ctx_t ctx, uint32_t mtu) 2831c19c7afeSEric Joyner { 2832c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 2833c19c7afeSEric Joyner int error = 0; 2834c19c7afeSEric Joyner 2835c19c7afeSEric Joyner IOCTL_DEBUGOUT("ioctl: SIOCIFMTU (Set Interface MTU)"); 2836c19c7afeSEric Joyner 2837c19c7afeSEric Joyner if (mtu > IXGBE_MAX_MTU) { 2838c19c7afeSEric Joyner error = EINVAL; 2839c19c7afeSEric Joyner } else { 2840c19c7afeSEric Joyner adapter->max_frame_size = mtu + IXGBE_MTU_HDR; 2841c19c7afeSEric Joyner } 2842c19c7afeSEric Joyner 2843c19c7afeSEric Joyner return error; 2844c19c7afeSEric Joyner } /* ixgbe_if_mtu_set */ 2845c19c7afeSEric Joyner 2846c19c7afeSEric Joyner /************************************************************************ 2847c19c7afeSEric Joyner * ixgbe_if_crcstrip_set 28488eb6488eSEric Joyner ************************************************************************/ 28498eb6488eSEric Joyner static void 2850c19c7afeSEric Joyner ixgbe_if_crcstrip_set(if_ctx_t ctx, int onoff, int crcstrip) 28518eb6488eSEric Joyner { 2852c19c7afeSEric Joyner struct adapter *sc = iflib_get_softc(ctx); 2853c19c7afeSEric Joyner struct ixgbe_hw *hw = &sc->hw; 2854c19c7afeSEric Joyner /* crc stripping is set in two places: 2855c19c7afeSEric Joyner * IXGBE_HLREG0 (modified on init_locked and hw reset) 2856c19c7afeSEric Joyner * IXGBE_RDRXCTL (set by the original driver in 2857c19c7afeSEric Joyner * ixgbe_setup_hw_rsc() called in init_locked. 2858c19c7afeSEric Joyner * We disable the setting when netmap is compiled in). 2859c19c7afeSEric Joyner * We update the values here, but also in ixgbe.c because 2860c19c7afeSEric Joyner * init_locked sometimes is called outside our control. 2861c19c7afeSEric Joyner */ 2862c19c7afeSEric Joyner uint32_t hl, rxc; 28638eb6488eSEric Joyner 2864c19c7afeSEric Joyner hl = IXGBE_READ_REG(hw, IXGBE_HLREG0); 2865c19c7afeSEric Joyner rxc = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); 2866c19c7afeSEric Joyner #ifdef NETMAP 2867c19c7afeSEric Joyner if (netmap_verbose) 2868c19c7afeSEric Joyner D("%s read HLREG 0x%x rxc 0x%x", 2869c19c7afeSEric Joyner onoff ? "enter" : "exit", hl, rxc); 28708eb6488eSEric Joyner #endif 2871c19c7afeSEric Joyner /* hw requirements ... */ 2872c19c7afeSEric Joyner rxc &= ~IXGBE_RDRXCTL_RSCFRSTSIZE; 2873c19c7afeSEric Joyner rxc |= IXGBE_RDRXCTL_RSCACKC; 2874c19c7afeSEric Joyner if (onoff && !crcstrip) { 2875c19c7afeSEric Joyner /* keep the crc. Fast rx */ 2876c19c7afeSEric Joyner hl &= ~IXGBE_HLREG0_RXCRCSTRP; 2877c19c7afeSEric Joyner rxc &= ~IXGBE_RDRXCTL_CRCSTRIP; 2878c19c7afeSEric Joyner } else { 2879c19c7afeSEric Joyner /* reset default mode */ 2880c19c7afeSEric Joyner hl |= IXGBE_HLREG0_RXCRCSTRP; 2881c19c7afeSEric Joyner rxc |= IXGBE_RDRXCTL_CRCSTRIP; 2882c19c7afeSEric Joyner } 2883c19c7afeSEric Joyner #ifdef NETMAP 2884c19c7afeSEric Joyner if (netmap_verbose) 2885c19c7afeSEric Joyner D("%s write HLREG 0x%x rxc 0x%x", 2886c19c7afeSEric Joyner onoff ? "enter" : "exit", hl, rxc); 2887c19c7afeSEric Joyner #endif 2888c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hl); 2889c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rxc); 2890c19c7afeSEric Joyner } /* ixgbe_if_crcstrip_set */ 28918eb6488eSEric Joyner 2892c19c7afeSEric Joyner /********************************************************************* 2893c19c7afeSEric Joyner * ixgbe_if_init - Init entry point 28948eb6488eSEric Joyner * 28958eb6488eSEric Joyner * Used in two ways: It is used by the stack as an init 28968eb6488eSEric Joyner * entry point in network interface structure. It is also 28978eb6488eSEric Joyner * used by the driver as a hw/sw initialization routine to 28988eb6488eSEric Joyner * get to a consistent state. 28998eb6488eSEric Joyner * 2900c19c7afeSEric Joyner * Return 0 on success, positive on failure 2901c19c7afeSEric Joyner **********************************************************************/ 29028eb6488eSEric Joyner void 2903c19c7afeSEric Joyner ixgbe_if_init(if_ctx_t ctx) 29048eb6488eSEric Joyner { 2905c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 2906c19c7afeSEric Joyner struct ifnet *ifp = iflib_get_ifp(ctx); 2907c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 29088eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 2909c19c7afeSEric Joyner struct ix_rx_queue *rx_que; 2910c19c7afeSEric Joyner struct ix_tx_queue *tx_que; 29118eb6488eSEric Joyner u32 txdctl, mhadd; 29128eb6488eSEric Joyner u32 rxdctl, rxctrl; 29138eb6488eSEric Joyner u32 ctrl_ext; 29148eb6488eSEric Joyner 2915c19c7afeSEric Joyner int i, j, err; 29168eb6488eSEric Joyner 2917c19c7afeSEric Joyner INIT_DEBUGOUT("ixgbe_if_init: begin"); 29188eb6488eSEric Joyner 29198eb6488eSEric Joyner /* Queue indices may change with IOV mode */ 29208eb6488eSEric Joyner ixgbe_align_all_queue_indices(adapter); 29218eb6488eSEric Joyner 29228eb6488eSEric Joyner /* reprogram the RAR[0] in case user changed it. */ 29238eb6488eSEric Joyner ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, IXGBE_RAH_AV); 29248eb6488eSEric Joyner 29258eb6488eSEric Joyner /* Get the latest mac address, User can use a LAA */ 29268eb6488eSEric Joyner bcopy(IF_LLADDR(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS); 29278eb6488eSEric Joyner ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1); 29288eb6488eSEric Joyner hw->addr_ctrl.rar_used_count = 1; 29298eb6488eSEric Joyner 29308eb6488eSEric Joyner ixgbe_init_hw(hw); 2931c19c7afeSEric Joyner 29328eb6488eSEric Joyner ixgbe_initialize_iov(adapter); 2933c19c7afeSEric Joyner 2934c19c7afeSEric Joyner ixgbe_initialize_transmit_units(ctx); 29358eb6488eSEric Joyner 29368eb6488eSEric Joyner /* Setup Multicast table */ 2937c19c7afeSEric Joyner ixgbe_if_multi_set(ctx); 29388eb6488eSEric Joyner 29398eb6488eSEric Joyner /* Determine the correct mbuf pool, based on frame size */ 29401b9d9394SEric Joyner adapter->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx); 29418eb6488eSEric Joyner 29428eb6488eSEric Joyner /* Configure RX settings */ 2943c19c7afeSEric Joyner ixgbe_initialize_receive_units(ctx); 29448eb6488eSEric Joyner 2945b2c1e8e6SEric Joyner /* 2946b2c1e8e6SEric Joyner * Initialize variable holding task enqueue requests 2947b2c1e8e6SEric Joyner * from MSI-X interrupts 2948b2c1e8e6SEric Joyner */ 2949b2c1e8e6SEric Joyner adapter->task_requests = 0; 2950b2c1e8e6SEric Joyner 29518eb6488eSEric Joyner /* Enable SDP & MSI-X interrupts based on adapter */ 29528eb6488eSEric Joyner ixgbe_config_gpie(adapter); 29538eb6488eSEric Joyner 29548eb6488eSEric Joyner /* Set MTU size */ 29558eb6488eSEric Joyner if (ifp->if_mtu > ETHERMTU) { 29568eb6488eSEric Joyner /* aka IXGBE_MAXFRS on 82599 and newer */ 29578eb6488eSEric Joyner mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); 29588eb6488eSEric Joyner mhadd &= ~IXGBE_MHADD_MFS_MASK; 29598eb6488eSEric Joyner mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT; 29608eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); 29618eb6488eSEric Joyner } 29628eb6488eSEric Joyner 29638eb6488eSEric Joyner /* Now enable all the queues */ 2964c19c7afeSEric Joyner for (i = 0, tx_que = adapter->tx_queues; i < adapter->num_tx_queues; i++, tx_que++) { 2965c19c7afeSEric Joyner struct tx_ring *txr = &tx_que->txr; 2966c19c7afeSEric Joyner 29678eb6488eSEric Joyner txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me)); 29688eb6488eSEric Joyner txdctl |= IXGBE_TXDCTL_ENABLE; 29698eb6488eSEric Joyner /* Set WTHRESH to 8, burst writeback */ 29708eb6488eSEric Joyner txdctl |= (8 << 16); 29718eb6488eSEric Joyner /* 29728eb6488eSEric Joyner * When the internal queue falls below PTHRESH (32), 29738eb6488eSEric Joyner * start prefetching as long as there are at least 29748eb6488eSEric Joyner * HTHRESH (1) buffers ready. The values are taken 29758eb6488eSEric Joyner * from the Intel linux driver 3.8.21. 29768eb6488eSEric Joyner * Prefetching enables tx line rate even with 1 queue. 29778eb6488eSEric Joyner */ 29788eb6488eSEric Joyner txdctl |= (32 << 0) | (1 << 8); 29798eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl); 29808eb6488eSEric Joyner } 29818eb6488eSEric Joyner 2982c19c7afeSEric Joyner for (i = 0, rx_que = adapter->rx_queues; i < adapter->num_rx_queues; i++, rx_que++) { 2983c19c7afeSEric Joyner struct rx_ring *rxr = &rx_que->rxr; 2984c19c7afeSEric Joyner 29858eb6488eSEric Joyner rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); 29868eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) { 29878eb6488eSEric Joyner /* 29888eb6488eSEric Joyner * PTHRESH = 21 29898eb6488eSEric Joyner * HTHRESH = 4 29908eb6488eSEric Joyner * WTHRESH = 8 29918eb6488eSEric Joyner */ 29928eb6488eSEric Joyner rxdctl &= ~0x3FFFFF; 29938eb6488eSEric Joyner rxdctl |= 0x080420; 29948eb6488eSEric Joyner } 29958eb6488eSEric Joyner rxdctl |= IXGBE_RXDCTL_ENABLE; 29968eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), rxdctl); 2997c19c7afeSEric Joyner for (j = 0; j < 10; j++) { 29988eb6488eSEric Joyner if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)) & 29998eb6488eSEric Joyner IXGBE_RXDCTL_ENABLE) 30008eb6488eSEric Joyner break; 30018eb6488eSEric Joyner else 30028eb6488eSEric Joyner msec_delay(1); 30038eb6488eSEric Joyner } 30048eb6488eSEric Joyner wmb(); 30058eb6488eSEric Joyner } 30068eb6488eSEric Joyner 30078eb6488eSEric Joyner /* Enable Receive engine */ 30088eb6488eSEric Joyner rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 30098eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 30108eb6488eSEric Joyner rxctrl |= IXGBE_RXCTRL_DMBYPS; 30118eb6488eSEric Joyner rxctrl |= IXGBE_RXCTRL_RXEN; 30128eb6488eSEric Joyner ixgbe_enable_rx_dma(hw, rxctrl); 30138eb6488eSEric Joyner 3014c19c7afeSEric Joyner /* Set up MSI/MSI-X routing */ 3015c19c7afeSEric Joyner if (ixgbe_enable_msix) { 30168eb6488eSEric Joyner ixgbe_configure_ivars(adapter); 30178eb6488eSEric Joyner /* Set up auto-mask */ 30188eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 30198eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); 30208eb6488eSEric Joyner else { 30218eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF); 30228eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF); 30238eb6488eSEric Joyner } 30248eb6488eSEric Joyner } else { /* Simple settings for Legacy/MSI */ 30258eb6488eSEric Joyner ixgbe_set_ivar(adapter, 0, 0, 0); 30268eb6488eSEric Joyner ixgbe_set_ivar(adapter, 0, 0, 1); 30278eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); 30288eb6488eSEric Joyner } 30298eb6488eSEric Joyner 30308eb6488eSEric Joyner ixgbe_init_fdir(adapter); 30318eb6488eSEric Joyner 30328eb6488eSEric Joyner /* 30338eb6488eSEric Joyner * Check on any SFP devices that 30348eb6488eSEric Joyner * need to be kick-started 30358eb6488eSEric Joyner */ 30368eb6488eSEric Joyner if (hw->phy.type == ixgbe_phy_none) { 30378eb6488eSEric Joyner err = hw->phy.ops.identify(hw); 30388eb6488eSEric Joyner if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 30398eb6488eSEric Joyner device_printf(dev, 30408eb6488eSEric Joyner "Unsupported SFP+ module type was detected.\n"); 30418eb6488eSEric Joyner return; 30428eb6488eSEric Joyner } 30438eb6488eSEric Joyner } 30448eb6488eSEric Joyner 30458eb6488eSEric Joyner /* Set moderation on the Link interrupt */ 30468eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR); 30478eb6488eSEric Joyner 3048c19c7afeSEric Joyner /* Enable power to the phy. */ 3049c19c7afeSEric Joyner ixgbe_set_phy_power(hw, TRUE); 3050c19c7afeSEric Joyner 30518eb6488eSEric Joyner /* Config/Enable Link */ 3052b2c1e8e6SEric Joyner ixgbe_config_link(ctx); 30538eb6488eSEric Joyner 30548eb6488eSEric Joyner /* Hardware Packet Buffer & Flow Control setup */ 30558eb6488eSEric Joyner ixgbe_config_delay_values(adapter); 30568eb6488eSEric Joyner 30578eb6488eSEric Joyner /* Initialize the FC settings */ 30588eb6488eSEric Joyner ixgbe_start_hw(hw); 30598eb6488eSEric Joyner 30608eb6488eSEric Joyner /* Set up VLAN support and filter */ 3061c19c7afeSEric Joyner ixgbe_setup_vlan_hw_support(ctx); 30628eb6488eSEric Joyner 30638eb6488eSEric Joyner /* Setup DMA Coalescing */ 30648eb6488eSEric Joyner ixgbe_config_dmac(adapter); 30658eb6488eSEric Joyner 30668eb6488eSEric Joyner /* And now turn on interrupts */ 3067c19c7afeSEric Joyner ixgbe_if_enable_intr(ctx); 30688eb6488eSEric Joyner 30698eb6488eSEric Joyner /* Enable the use of the MBX by the VF's */ 30708eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_SRIOV) { 30718eb6488eSEric Joyner ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 30728eb6488eSEric Joyner ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD; 30738eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 30748eb6488eSEric Joyner } 30758eb6488eSEric Joyner 30768eb6488eSEric Joyner } /* ixgbe_init_locked */ 30778eb6488eSEric Joyner 30788eb6488eSEric Joyner /************************************************************************ 30798eb6488eSEric Joyner * ixgbe_set_ivar 30808eb6488eSEric Joyner * 30818eb6488eSEric Joyner * Setup the correct IVAR register for a particular MSI-X interrupt 30828eb6488eSEric Joyner * (yes this is all very magic and confusing :) 30838eb6488eSEric Joyner * - entry is the register array entry 30848eb6488eSEric Joyner * - vector is the MSI-X vector for this queue 30858eb6488eSEric Joyner * - type is RX/TX/MISC 30868eb6488eSEric Joyner ************************************************************************/ 30878eb6488eSEric Joyner static void 30888eb6488eSEric Joyner ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type) 30898eb6488eSEric Joyner { 30908eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 30918eb6488eSEric Joyner u32 ivar, index; 30928eb6488eSEric Joyner 30938eb6488eSEric Joyner vector |= IXGBE_IVAR_ALLOC_VAL; 30948eb6488eSEric Joyner 30958eb6488eSEric Joyner switch (hw->mac.type) { 30968eb6488eSEric Joyner case ixgbe_mac_82598EB: 30978eb6488eSEric Joyner if (type == -1) 30988eb6488eSEric Joyner entry = IXGBE_IVAR_OTHER_CAUSES_INDEX; 30998eb6488eSEric Joyner else 31008eb6488eSEric Joyner entry += (type * 64); 31018eb6488eSEric Joyner index = (entry >> 2) & 0x1F; 31028eb6488eSEric Joyner ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index)); 31038eb6488eSEric Joyner ivar &= ~(0xFF << (8 * (entry & 0x3))); 31048eb6488eSEric Joyner ivar |= (vector << (8 * (entry & 0x3))); 31058eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR(index), ivar); 31068eb6488eSEric Joyner break; 31078eb6488eSEric Joyner case ixgbe_mac_82599EB: 31088eb6488eSEric Joyner case ixgbe_mac_X540: 31098eb6488eSEric Joyner case ixgbe_mac_X550: 31108eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 31118eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 31128eb6488eSEric Joyner if (type == -1) { /* MISC IVAR */ 31138eb6488eSEric Joyner index = (entry & 1) * 8; 31148eb6488eSEric Joyner ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC); 31158eb6488eSEric Joyner ivar &= ~(0xFF << index); 31168eb6488eSEric Joyner ivar |= (vector << index); 31178eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar); 31188eb6488eSEric Joyner } else { /* RX/TX IVARS */ 31198eb6488eSEric Joyner index = (16 * (entry & 1)) + (8 * type); 31208eb6488eSEric Joyner ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1)); 31218eb6488eSEric Joyner ivar &= ~(0xFF << index); 31228eb6488eSEric Joyner ivar |= (vector << index); 31238eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar); 31248eb6488eSEric Joyner } 31258eb6488eSEric Joyner default: 31268eb6488eSEric Joyner break; 31278eb6488eSEric Joyner } 31288eb6488eSEric Joyner } /* ixgbe_set_ivar */ 31298eb6488eSEric Joyner 31308eb6488eSEric Joyner /************************************************************************ 31318eb6488eSEric Joyner * ixgbe_configure_ivars 31328eb6488eSEric Joyner ************************************************************************/ 31338eb6488eSEric Joyner static void 31348eb6488eSEric Joyner ixgbe_configure_ivars(struct adapter *adapter) 31358eb6488eSEric Joyner { 3136c19c7afeSEric Joyner struct ix_rx_queue *rx_que = adapter->rx_queues; 3137c19c7afeSEric Joyner struct ix_tx_queue *tx_que = adapter->tx_queues; 31388eb6488eSEric Joyner u32 newitr; 31398eb6488eSEric Joyner 31408eb6488eSEric Joyner if (ixgbe_max_interrupt_rate > 0) 31418eb6488eSEric Joyner newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8; 31428eb6488eSEric Joyner else { 31438eb6488eSEric Joyner /* 31448eb6488eSEric Joyner * Disable DMA coalescing if interrupt moderation is 31458eb6488eSEric Joyner * disabled. 31468eb6488eSEric Joyner */ 31478eb6488eSEric Joyner adapter->dmac = 0; 31488eb6488eSEric Joyner newitr = 0; 31498eb6488eSEric Joyner } 31508eb6488eSEric Joyner 3151c19c7afeSEric Joyner for (int i = 0; i < adapter->num_rx_queues; i++, rx_que++) { 3152c19c7afeSEric Joyner struct rx_ring *rxr = &rx_que->rxr; 31538eb6488eSEric Joyner 3154c19c7afeSEric Joyner /* First the RX queue entry */ 3155c19c7afeSEric Joyner ixgbe_set_ivar(adapter, rxr->me, rx_que->msix, 0); 3156c19c7afeSEric Joyner 3157c19c7afeSEric Joyner /* Set an Initial EITR value */ 3158c19c7afeSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(rx_que->msix), newitr); 3159c19c7afeSEric Joyner } 3160c19c7afeSEric Joyner for (int i = 0; i < adapter->num_tx_queues; i++, tx_que++) { 3161c19c7afeSEric Joyner struct tx_ring *txr = &tx_que->txr; 3162c19c7afeSEric Joyner 3163c19c7afeSEric Joyner /* ... and the TX */ 3164c19c7afeSEric Joyner ixgbe_set_ivar(adapter, txr->me, tx_que->msix, 1); 3165c19c7afeSEric Joyner } 31668eb6488eSEric Joyner /* For the Link interrupt */ 31678eb6488eSEric Joyner ixgbe_set_ivar(adapter, 1, adapter->vector, -1); 31688eb6488eSEric Joyner } /* ixgbe_configure_ivars */ 31698eb6488eSEric Joyner 31708eb6488eSEric Joyner /************************************************************************ 31718eb6488eSEric Joyner * ixgbe_config_gpie 31728eb6488eSEric Joyner ************************************************************************/ 31738eb6488eSEric Joyner static void 31748eb6488eSEric Joyner ixgbe_config_gpie(struct adapter *adapter) 31758eb6488eSEric Joyner { 31768eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 31778eb6488eSEric Joyner u32 gpie; 31788eb6488eSEric Joyner 31798eb6488eSEric Joyner gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); 31808eb6488eSEric Joyner 3181c19c7afeSEric Joyner if (adapter->intr_type == IFLIB_INTR_MSIX) { 31828eb6488eSEric Joyner /* Enable Enhanced MSI-X mode */ 31838eb6488eSEric Joyner gpie |= IXGBE_GPIE_MSIX_MODE 31848eb6488eSEric Joyner | IXGBE_GPIE_EIAME 31858eb6488eSEric Joyner | IXGBE_GPIE_PBA_SUPPORT 31868eb6488eSEric Joyner | IXGBE_GPIE_OCD; 31878eb6488eSEric Joyner } 31888eb6488eSEric Joyner 31898eb6488eSEric Joyner /* Fan Failure Interrupt */ 31908eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) 31918eb6488eSEric Joyner gpie |= IXGBE_SDP1_GPIEN; 31928eb6488eSEric Joyner 31938eb6488eSEric Joyner /* Thermal Sensor Interrupt */ 31948eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR) 31958eb6488eSEric Joyner gpie |= IXGBE_SDP0_GPIEN_X540; 31968eb6488eSEric Joyner 31978eb6488eSEric Joyner /* Link detection */ 31988eb6488eSEric Joyner switch (hw->mac.type) { 31998eb6488eSEric Joyner case ixgbe_mac_82599EB: 32008eb6488eSEric Joyner gpie |= IXGBE_SDP1_GPIEN | IXGBE_SDP2_GPIEN; 32018eb6488eSEric Joyner break; 32028eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 32038eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 32048eb6488eSEric Joyner gpie |= IXGBE_SDP0_GPIEN_X540; 32058eb6488eSEric Joyner break; 32068eb6488eSEric Joyner default: 32078eb6488eSEric Joyner break; 32088eb6488eSEric Joyner } 32098eb6488eSEric Joyner 32108eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); 32118eb6488eSEric Joyner 32128eb6488eSEric Joyner } /* ixgbe_config_gpie */ 32138eb6488eSEric Joyner 32148eb6488eSEric Joyner /************************************************************************ 32158eb6488eSEric Joyner * ixgbe_config_delay_values 32168eb6488eSEric Joyner * 32178eb6488eSEric Joyner * Requires adapter->max_frame_size to be set. 32188eb6488eSEric Joyner ************************************************************************/ 32198eb6488eSEric Joyner static void 32208eb6488eSEric Joyner ixgbe_config_delay_values(struct adapter *adapter) 32218eb6488eSEric Joyner { 32228eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 32238eb6488eSEric Joyner u32 rxpb, frame, size, tmp; 32248eb6488eSEric Joyner 32258eb6488eSEric Joyner frame = adapter->max_frame_size; 32268eb6488eSEric Joyner 32278eb6488eSEric Joyner /* Calculate High Water */ 32288eb6488eSEric Joyner switch (hw->mac.type) { 32298eb6488eSEric Joyner case ixgbe_mac_X540: 32308eb6488eSEric Joyner case ixgbe_mac_X550: 32318eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 32328eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 32338eb6488eSEric Joyner tmp = IXGBE_DV_X540(frame, frame); 32348eb6488eSEric Joyner break; 32358eb6488eSEric Joyner default: 32368eb6488eSEric Joyner tmp = IXGBE_DV(frame, frame); 32378eb6488eSEric Joyner break; 32388eb6488eSEric Joyner } 32398eb6488eSEric Joyner size = IXGBE_BT2KB(tmp); 32408eb6488eSEric Joyner rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10; 32418eb6488eSEric Joyner hw->fc.high_water[0] = rxpb - size; 32428eb6488eSEric Joyner 32438eb6488eSEric Joyner /* Now calculate Low Water */ 32448eb6488eSEric Joyner switch (hw->mac.type) { 32458eb6488eSEric Joyner case ixgbe_mac_X540: 32468eb6488eSEric Joyner case ixgbe_mac_X550: 32478eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 32488eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 32498eb6488eSEric Joyner tmp = IXGBE_LOW_DV_X540(frame); 32508eb6488eSEric Joyner break; 32518eb6488eSEric Joyner default: 32528eb6488eSEric Joyner tmp = IXGBE_LOW_DV(frame); 32538eb6488eSEric Joyner break; 32548eb6488eSEric Joyner } 32558eb6488eSEric Joyner hw->fc.low_water[0] = IXGBE_BT2KB(tmp); 32568eb6488eSEric Joyner 32578eb6488eSEric Joyner hw->fc.pause_time = IXGBE_FC_PAUSE; 32588eb6488eSEric Joyner hw->fc.send_xon = TRUE; 32598eb6488eSEric Joyner } /* ixgbe_config_delay_values */ 32608eb6488eSEric Joyner 32618eb6488eSEric Joyner /************************************************************************ 32628eb6488eSEric Joyner * ixgbe_set_multi - Multicast Update 32638eb6488eSEric Joyner * 32648eb6488eSEric Joyner * Called whenever multicast address list is updated. 32658eb6488eSEric Joyner ************************************************************************/ 3266ba76aa63SGleb Smirnoff static u_int 3267ba76aa63SGleb Smirnoff ixgbe_mc_filter_apply(void *arg, struct sockaddr_dl *sdl, u_int count) 32688eb6488eSEric Joyner { 3269c19c7afeSEric Joyner struct adapter *adapter = arg; 3270c19c7afeSEric Joyner struct ixgbe_mc_addr *mta = adapter->mta; 3271c19c7afeSEric Joyner 3272c19c7afeSEric Joyner if (count == MAX_NUM_MULTICAST_ADDRESSES) 3273c19c7afeSEric Joyner return (0); 3274ba76aa63SGleb Smirnoff bcopy(LLADDR(sdl), mta[count].addr, IXGBE_ETH_LENGTH_OF_ADDRESS); 3275c19c7afeSEric Joyner mta[count].vmdq = adapter->pool; 3276c19c7afeSEric Joyner 3277c19c7afeSEric Joyner return (1); 3278c19c7afeSEric Joyner } /* ixgbe_mc_filter_apply */ 3279c19c7afeSEric Joyner 3280c19c7afeSEric Joyner static void 3281c19c7afeSEric Joyner ixgbe_if_multi_set(if_ctx_t ctx) 3282c19c7afeSEric Joyner { 3283c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 32848eb6488eSEric Joyner struct ixgbe_mc_addr *mta; 3285c19c7afeSEric Joyner struct ifnet *ifp = iflib_get_ifp(ctx); 32868eb6488eSEric Joyner u8 *update_ptr; 32878eb6488eSEric Joyner u32 fctrl; 3288ba76aa63SGleb Smirnoff u_int mcnt; 32898eb6488eSEric Joyner 3290c19c7afeSEric Joyner IOCTL_DEBUGOUT("ixgbe_if_multi_set: begin"); 32918eb6488eSEric Joyner 32928eb6488eSEric Joyner mta = adapter->mta; 32938eb6488eSEric Joyner bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES); 32948eb6488eSEric Joyner 3295ba76aa63SGleb Smirnoff mcnt = if_foreach_llmaddr(iflib_get_ifp(ctx), ixgbe_mc_filter_apply, 3296ba76aa63SGleb Smirnoff adapter); 32978eb6488eSEric Joyner 32988eb6488eSEric Joyner fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); 32998eb6488eSEric Joyner fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 33008eb6488eSEric Joyner if (ifp->if_flags & IFF_PROMISC) 33018eb6488eSEric Joyner fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 33028eb6488eSEric Joyner else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES || 33038eb6488eSEric Joyner ifp->if_flags & IFF_ALLMULTI) { 33048eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_MPE; 33058eb6488eSEric Joyner fctrl &= ~IXGBE_FCTRL_UPE; 33068eb6488eSEric Joyner } else 33078eb6488eSEric Joyner fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 33088eb6488eSEric Joyner 33098eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl); 33108eb6488eSEric Joyner 33118eb6488eSEric Joyner if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) { 33128eb6488eSEric Joyner update_ptr = (u8 *)mta; 33138eb6488eSEric Joyner ixgbe_update_mc_addr_list(&adapter->hw, update_ptr, mcnt, 33148eb6488eSEric Joyner ixgbe_mc_array_itr, TRUE); 33158eb6488eSEric Joyner } 33168eb6488eSEric Joyner 3317c19c7afeSEric Joyner } /* ixgbe_if_multi_set */ 33188eb6488eSEric Joyner 33198eb6488eSEric Joyner /************************************************************************ 33208eb6488eSEric Joyner * ixgbe_mc_array_itr 33218eb6488eSEric Joyner * 33228eb6488eSEric Joyner * An iterator function needed by the multicast shared code. 33238eb6488eSEric Joyner * It feeds the shared code routine the addresses in the 33248eb6488eSEric Joyner * array of ixgbe_set_multi() one by one. 33258eb6488eSEric Joyner ************************************************************************/ 33268eb6488eSEric Joyner static u8 * 33278eb6488eSEric Joyner ixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq) 33288eb6488eSEric Joyner { 33298eb6488eSEric Joyner struct ixgbe_mc_addr *mta; 33308eb6488eSEric Joyner 33318eb6488eSEric Joyner mta = (struct ixgbe_mc_addr *)*update_ptr; 33328eb6488eSEric Joyner *vmdq = mta->vmdq; 33338eb6488eSEric Joyner 33348eb6488eSEric Joyner *update_ptr = (u8*)(mta + 1); 33358eb6488eSEric Joyner 33368eb6488eSEric Joyner return (mta->addr); 33378eb6488eSEric Joyner } /* ixgbe_mc_array_itr */ 33388eb6488eSEric Joyner 33398eb6488eSEric Joyner /************************************************************************ 33408eb6488eSEric Joyner * ixgbe_local_timer - Timer routine 33418eb6488eSEric Joyner * 33428eb6488eSEric Joyner * Checks for link status, updates statistics, 33438eb6488eSEric Joyner * and runs the watchdog check. 33448eb6488eSEric Joyner ************************************************************************/ 33458eb6488eSEric Joyner static void 3346c19c7afeSEric Joyner ixgbe_if_timer(if_ctx_t ctx, uint16_t qid) 33478eb6488eSEric Joyner { 3348c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 33498eb6488eSEric Joyner 3350c19c7afeSEric Joyner if (qid != 0) 3351c19c7afeSEric Joyner return; 33528eb6488eSEric Joyner 33538eb6488eSEric Joyner /* Check for pluggable optics */ 33548eb6488eSEric Joyner if (adapter->sfp_probe) 3355c19c7afeSEric Joyner if (!ixgbe_sfp_probe(ctx)) 3356c19c7afeSEric Joyner return; /* Nothing to do */ 33578eb6488eSEric Joyner 3358c19c7afeSEric Joyner ixgbe_check_link(&adapter->hw, &adapter->link_speed, 3359c19c7afeSEric Joyner &adapter->link_up, 0); 33608eb6488eSEric Joyner 3361c19c7afeSEric Joyner /* Fire off the adminq task */ 3362c19c7afeSEric Joyner iflib_admin_intr_deferred(ctx); 33638eb6488eSEric Joyner 3364c19c7afeSEric Joyner } /* ixgbe_if_timer */ 33658eb6488eSEric Joyner 33668eb6488eSEric Joyner /************************************************************************ 33678eb6488eSEric Joyner * ixgbe_sfp_probe 33688eb6488eSEric Joyner * 33698eb6488eSEric Joyner * Determine if a port had optics inserted. 33708eb6488eSEric Joyner ************************************************************************/ 33718eb6488eSEric Joyner static bool 3372c19c7afeSEric Joyner ixgbe_sfp_probe(if_ctx_t ctx) 33738eb6488eSEric Joyner { 3374c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 33758eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 3376c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 33778eb6488eSEric Joyner bool result = FALSE; 33788eb6488eSEric Joyner 33798eb6488eSEric Joyner if ((hw->phy.type == ixgbe_phy_nl) && 33808eb6488eSEric Joyner (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) { 33818eb6488eSEric Joyner s32 ret = hw->phy.ops.identify_sfp(hw); 33828eb6488eSEric Joyner if (ret) 33838eb6488eSEric Joyner goto out; 33848eb6488eSEric Joyner ret = hw->phy.ops.reset(hw); 33858eb6488eSEric Joyner adapter->sfp_probe = FALSE; 33868eb6488eSEric Joyner if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { 33878eb6488eSEric Joyner device_printf(dev, "Unsupported SFP+ module detected!"); 33888eb6488eSEric Joyner device_printf(dev, 33898eb6488eSEric Joyner "Reload driver with supported module.\n"); 33908eb6488eSEric Joyner goto out; 33918eb6488eSEric Joyner } else 33928eb6488eSEric Joyner device_printf(dev, "SFP+ module detected!\n"); 33938eb6488eSEric Joyner /* We now have supported optics */ 33948eb6488eSEric Joyner result = TRUE; 33958eb6488eSEric Joyner } 33968eb6488eSEric Joyner out: 33978eb6488eSEric Joyner 33988eb6488eSEric Joyner return (result); 33998eb6488eSEric Joyner } /* ixgbe_sfp_probe */ 34008eb6488eSEric Joyner 34018eb6488eSEric Joyner /************************************************************************ 34028eb6488eSEric Joyner * ixgbe_handle_mod - Tasklet for SFP module interrupts 34038eb6488eSEric Joyner ************************************************************************/ 34048eb6488eSEric Joyner static void 3405c19c7afeSEric Joyner ixgbe_handle_mod(void *context) 34068eb6488eSEric Joyner { 3407c19c7afeSEric Joyner if_ctx_t ctx = context; 3408c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 34098eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 3410c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 34118eb6488eSEric Joyner u32 err, cage_full = 0; 34128eb6488eSEric Joyner 34138eb6488eSEric Joyner if (adapter->hw.need_crosstalk_fix) { 34148eb6488eSEric Joyner switch (hw->mac.type) { 34158eb6488eSEric Joyner case ixgbe_mac_82599EB: 34168eb6488eSEric Joyner cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 34178eb6488eSEric Joyner IXGBE_ESDP_SDP2; 34188eb6488eSEric Joyner break; 34198eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 34208eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 34218eb6488eSEric Joyner cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 34228eb6488eSEric Joyner IXGBE_ESDP_SDP0; 34238eb6488eSEric Joyner break; 34248eb6488eSEric Joyner default: 34258eb6488eSEric Joyner break; 34268eb6488eSEric Joyner } 34278eb6488eSEric Joyner 34288eb6488eSEric Joyner if (!cage_full) 3429c19c7afeSEric Joyner goto handle_mod_out; 34308eb6488eSEric Joyner } 34318eb6488eSEric Joyner 34328eb6488eSEric Joyner err = hw->phy.ops.identify_sfp(hw); 34338eb6488eSEric Joyner if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 34348eb6488eSEric Joyner device_printf(dev, 34358eb6488eSEric Joyner "Unsupported SFP+ module type was detected.\n"); 3436c19c7afeSEric Joyner goto handle_mod_out; 34378eb6488eSEric Joyner } 34388eb6488eSEric Joyner 3439c19c7afeSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 3440c19c7afeSEric Joyner err = hw->phy.ops.reset(hw); 3441c19c7afeSEric Joyner else 34428eb6488eSEric Joyner err = hw->mac.ops.setup_sfp(hw); 3443c19c7afeSEric Joyner 34448eb6488eSEric Joyner if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 34458eb6488eSEric Joyner device_printf(dev, 34468eb6488eSEric Joyner "Setup failure - unsupported SFP+ module type.\n"); 3447c19c7afeSEric Joyner goto handle_mod_out; 34488eb6488eSEric Joyner } 3449b2c1e8e6SEric Joyner adapter->task_requests |= IXGBE_REQUEST_TASK_MSF; 3450c19c7afeSEric Joyner return; 3451c19c7afeSEric Joyner 3452c19c7afeSEric Joyner handle_mod_out: 3453b2c1e8e6SEric Joyner adapter->task_requests &= ~(IXGBE_REQUEST_TASK_MSF); 34548eb6488eSEric Joyner } /* ixgbe_handle_mod */ 34558eb6488eSEric Joyner 34568eb6488eSEric Joyner 34578eb6488eSEric Joyner /************************************************************************ 34588eb6488eSEric Joyner * ixgbe_handle_msf - Tasklet for MSF (multispeed fiber) interrupts 34598eb6488eSEric Joyner ************************************************************************/ 34608eb6488eSEric Joyner static void 3461c19c7afeSEric Joyner ixgbe_handle_msf(void *context) 34628eb6488eSEric Joyner { 3463c19c7afeSEric Joyner if_ctx_t ctx = context; 3464c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 34658eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 34668eb6488eSEric Joyner u32 autoneg; 34678eb6488eSEric Joyner bool negotiate; 34688eb6488eSEric Joyner 34698eb6488eSEric Joyner /* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */ 34708eb6488eSEric Joyner adapter->phy_layer = ixgbe_get_supported_physical_layer(hw); 34718eb6488eSEric Joyner 34728eb6488eSEric Joyner autoneg = hw->phy.autoneg_advertised; 34738eb6488eSEric Joyner if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) 34748eb6488eSEric Joyner hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate); 34758eb6488eSEric Joyner if (hw->mac.ops.setup_link) 34768eb6488eSEric Joyner hw->mac.ops.setup_link(hw, autoneg, TRUE); 34778eb6488eSEric Joyner 34788eb6488eSEric Joyner /* Adjust media types shown in ifconfig */ 3479c19c7afeSEric Joyner ifmedia_removeall(adapter->media); 3480c19c7afeSEric Joyner ixgbe_add_media_types(adapter->ctx); 3481c19c7afeSEric Joyner ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO); 34828eb6488eSEric Joyner } /* ixgbe_handle_msf */ 34838eb6488eSEric Joyner 34848eb6488eSEric Joyner /************************************************************************ 34858eb6488eSEric Joyner * ixgbe_handle_phy - Tasklet for external PHY interrupts 34868eb6488eSEric Joyner ************************************************************************/ 34878eb6488eSEric Joyner static void 3488c19c7afeSEric Joyner ixgbe_handle_phy(void *context) 34898eb6488eSEric Joyner { 3490c19c7afeSEric Joyner if_ctx_t ctx = context; 3491c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 34928eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 34938eb6488eSEric Joyner int error; 34948eb6488eSEric Joyner 34958eb6488eSEric Joyner error = hw->phy.ops.handle_lasi(hw); 34968eb6488eSEric Joyner if (error == IXGBE_ERR_OVERTEMP) 34978eb6488eSEric Joyner device_printf(adapter->dev, "CRITICAL: EXTERNAL PHY OVER TEMP!! PHY will downshift to lower power state!\n"); 34988eb6488eSEric Joyner else if (error) 34998eb6488eSEric Joyner device_printf(adapter->dev, 35008eb6488eSEric Joyner "Error handling LASI interrupt: %d\n", error); 35018eb6488eSEric Joyner } /* ixgbe_handle_phy */ 35028eb6488eSEric Joyner 35038eb6488eSEric Joyner /************************************************************************ 3504c19c7afeSEric Joyner * ixgbe_if_stop - Stop the hardware 35058eb6488eSEric Joyner * 35068eb6488eSEric Joyner * Disables all traffic on the adapter by issuing a 35078eb6488eSEric Joyner * global reset on the MAC and deallocates TX/RX buffers. 35088eb6488eSEric Joyner ************************************************************************/ 35098eb6488eSEric Joyner static void 3510c19c7afeSEric Joyner ixgbe_if_stop(if_ctx_t ctx) 35118eb6488eSEric Joyner { 3512c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 35138eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 35148eb6488eSEric Joyner 3515c19c7afeSEric Joyner INIT_DEBUGOUT("ixgbe_if_stop: begin\n"); 35168eb6488eSEric Joyner 35178eb6488eSEric Joyner ixgbe_reset_hw(hw); 35188eb6488eSEric Joyner hw->adapter_stopped = FALSE; 35198eb6488eSEric Joyner ixgbe_stop_adapter(hw); 35208eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82599EB) 35218eb6488eSEric Joyner ixgbe_stop_mac_link_on_d3_82599(hw); 35228eb6488eSEric Joyner /* Turn off the laser - noop with no optics */ 35238eb6488eSEric Joyner ixgbe_disable_tx_laser(hw); 35248eb6488eSEric Joyner 35258eb6488eSEric Joyner /* Update the stack */ 35268eb6488eSEric Joyner adapter->link_up = FALSE; 3527c19c7afeSEric Joyner ixgbe_if_update_admin_status(ctx); 35288eb6488eSEric Joyner 35298eb6488eSEric Joyner /* reprogram the RAR[0] in case user changed it. */ 35308eb6488eSEric Joyner ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV); 35318eb6488eSEric Joyner 35328eb6488eSEric Joyner return; 3533c19c7afeSEric Joyner } /* ixgbe_if_stop */ 35348eb6488eSEric Joyner 35358eb6488eSEric Joyner /************************************************************************ 35368eb6488eSEric Joyner * ixgbe_update_link_status - Update OS on link state 35378eb6488eSEric Joyner * 35388eb6488eSEric Joyner * Note: Only updates the OS on the cached link state. 35398eb6488eSEric Joyner * The real check of the hardware only happens with 35408eb6488eSEric Joyner * a link interrupt. 35418eb6488eSEric Joyner ************************************************************************/ 35428eb6488eSEric Joyner static void 3543c19c7afeSEric Joyner ixgbe_if_update_admin_status(if_ctx_t ctx) 35448eb6488eSEric Joyner { 3545c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 3546c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 35478eb6488eSEric Joyner 35488eb6488eSEric Joyner if (adapter->link_up) { 35498eb6488eSEric Joyner if (adapter->link_active == FALSE) { 35508eb6488eSEric Joyner if (bootverbose) 35518eb6488eSEric Joyner device_printf(dev, "Link is up %d Gbps %s \n", 35528eb6488eSEric Joyner ((adapter->link_speed == 128) ? 10 : 1), 35538eb6488eSEric Joyner "Full Duplex"); 35548eb6488eSEric Joyner adapter->link_active = TRUE; 35558eb6488eSEric Joyner /* Update any Flow Control changes */ 35568eb6488eSEric Joyner ixgbe_fc_enable(&adapter->hw); 35578eb6488eSEric Joyner /* Update DMA coalescing config */ 35588eb6488eSEric Joyner ixgbe_config_dmac(adapter); 3559c19c7afeSEric Joyner /* should actually be negotiated value */ 3560c19c7afeSEric Joyner iflib_link_state_change(ctx, LINK_STATE_UP, IF_Gbps(10)); 3561c19c7afeSEric Joyner 35628eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_SRIOV) 35638eb6488eSEric Joyner ixgbe_ping_all_vfs(adapter); 35648eb6488eSEric Joyner } 35658eb6488eSEric Joyner } else { /* Link down */ 35668eb6488eSEric Joyner if (adapter->link_active == TRUE) { 35678eb6488eSEric Joyner if (bootverbose) 35688eb6488eSEric Joyner device_printf(dev, "Link is Down\n"); 3569c19c7afeSEric Joyner iflib_link_state_change(ctx, LINK_STATE_DOWN, 0); 35708eb6488eSEric Joyner adapter->link_active = FALSE; 35718eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_SRIOV) 35728eb6488eSEric Joyner ixgbe_ping_all_vfs(adapter); 35738eb6488eSEric Joyner } 35748eb6488eSEric Joyner } 35758eb6488eSEric Joyner 3576b2c1e8e6SEric Joyner /* Handle task requests from msix_link() */ 3577b2c1e8e6SEric Joyner if (adapter->task_requests & IXGBE_REQUEST_TASK_MOD) 3578b2c1e8e6SEric Joyner ixgbe_handle_mod(ctx); 3579b2c1e8e6SEric Joyner if (adapter->task_requests & IXGBE_REQUEST_TASK_MSF) 3580b2c1e8e6SEric Joyner ixgbe_handle_msf(ctx); 3581b2c1e8e6SEric Joyner if (adapter->task_requests & IXGBE_REQUEST_TASK_MBX) 3582b2c1e8e6SEric Joyner ixgbe_handle_mbx(ctx); 3583b2c1e8e6SEric Joyner if (adapter->task_requests & IXGBE_REQUEST_TASK_FDIR) 3584b2c1e8e6SEric Joyner ixgbe_reinit_fdir(ctx); 3585b2c1e8e6SEric Joyner if (adapter->task_requests & IXGBE_REQUEST_TASK_PHY) 3586b2c1e8e6SEric Joyner ixgbe_handle_phy(ctx); 3587b2c1e8e6SEric Joyner adapter->task_requests = 0; 3588c19c7afeSEric Joyner 3589b2c1e8e6SEric Joyner ixgbe_update_stats_counters(adapter); 3590c19c7afeSEric Joyner } /* ixgbe_if_update_admin_status */ 35918eb6488eSEric Joyner 35928eb6488eSEric Joyner /************************************************************************ 35938eb6488eSEric Joyner * ixgbe_config_dmac - Configure DMA Coalescing 35948eb6488eSEric Joyner ************************************************************************/ 35958eb6488eSEric Joyner static void 35968eb6488eSEric Joyner ixgbe_config_dmac(struct adapter *adapter) 35978eb6488eSEric Joyner { 35988eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 35998eb6488eSEric Joyner struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config; 36008eb6488eSEric Joyner 36018eb6488eSEric Joyner if (hw->mac.type < ixgbe_mac_X550 || !hw->mac.ops.dmac_config) 36028eb6488eSEric Joyner return; 36038eb6488eSEric Joyner 36048eb6488eSEric Joyner if (dcfg->watchdog_timer ^ adapter->dmac || 36058eb6488eSEric Joyner dcfg->link_speed ^ adapter->link_speed) { 36068eb6488eSEric Joyner dcfg->watchdog_timer = adapter->dmac; 3607c19c7afeSEric Joyner dcfg->fcoe_en = FALSE; 36088eb6488eSEric Joyner dcfg->link_speed = adapter->link_speed; 36098eb6488eSEric Joyner dcfg->num_tcs = 1; 36108eb6488eSEric Joyner 36118eb6488eSEric Joyner INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n", 36128eb6488eSEric Joyner dcfg->watchdog_timer, dcfg->link_speed); 36138eb6488eSEric Joyner 36148eb6488eSEric Joyner hw->mac.ops.dmac_config(hw); 36158eb6488eSEric Joyner } 36168eb6488eSEric Joyner } /* ixgbe_config_dmac */ 36178eb6488eSEric Joyner 36188eb6488eSEric Joyner /************************************************************************ 3619c19c7afeSEric Joyner * ixgbe_if_enable_intr 36208eb6488eSEric Joyner ************************************************************************/ 3621c19c7afeSEric Joyner void 3622c19c7afeSEric Joyner ixgbe_if_enable_intr(if_ctx_t ctx) 36238eb6488eSEric Joyner { 3624c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 36258eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 3626c19c7afeSEric Joyner struct ix_rx_queue *que = adapter->rx_queues; 36278eb6488eSEric Joyner u32 mask, fwsm; 36288eb6488eSEric Joyner 36298eb6488eSEric Joyner mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); 36308eb6488eSEric Joyner 36318eb6488eSEric Joyner switch (adapter->hw.mac.type) { 36328eb6488eSEric Joyner case ixgbe_mac_82599EB: 36338eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 36348eb6488eSEric Joyner /* Temperature sensor on some adapters */ 36358eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP0; 36368eb6488eSEric Joyner /* SFP+ (RX_LOS_N & MOD_ABS_N) */ 36378eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP1; 36388eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP2; 36398eb6488eSEric Joyner break; 36408eb6488eSEric Joyner case ixgbe_mac_X540: 36418eb6488eSEric Joyner /* Detect if Thermal Sensor is enabled */ 36428eb6488eSEric Joyner fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); 36438eb6488eSEric Joyner if (fwsm & IXGBE_FWSM_TS_ENABLED) 36448eb6488eSEric Joyner mask |= IXGBE_EIMS_TS; 36458eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 36468eb6488eSEric Joyner break; 36478eb6488eSEric Joyner case ixgbe_mac_X550: 36488eb6488eSEric Joyner /* MAC thermal sensor is automatically enabled */ 36498eb6488eSEric Joyner mask |= IXGBE_EIMS_TS; 36508eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 36518eb6488eSEric Joyner break; 36528eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 36538eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 36548eb6488eSEric Joyner /* Some devices use SDP0 for important information */ 36558eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP || 36568eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP || 36578eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N || 36588eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) 36598eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw); 36608eb6488eSEric Joyner if (hw->phy.type == ixgbe_phy_x550em_ext_t) 36618eb6488eSEric Joyner mask |= IXGBE_EICR_GPI_SDP0_X540; 36628eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 36638eb6488eSEric Joyner break; 36648eb6488eSEric Joyner default: 36658eb6488eSEric Joyner break; 36668eb6488eSEric Joyner } 36678eb6488eSEric Joyner 36688eb6488eSEric Joyner /* Enable Fan Failure detection */ 36698eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) 36708eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP1; 36718eb6488eSEric Joyner /* Enable SR-IOV */ 36728eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_SRIOV) 36738eb6488eSEric Joyner mask |= IXGBE_EIMS_MAILBOX; 36748eb6488eSEric Joyner /* Enable Flow Director */ 36758eb6488eSEric Joyner if (adapter->feat_en & IXGBE_FEATURE_FDIR) 36768eb6488eSEric Joyner mask |= IXGBE_EIMS_FLOW_DIR; 36778eb6488eSEric Joyner 36788eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); 36798eb6488eSEric Joyner 36808eb6488eSEric Joyner /* With MSI-X we use auto clear */ 3681c19c7afeSEric Joyner if (adapter->intr_type == IFLIB_INTR_MSIX) { 36828eb6488eSEric Joyner mask = IXGBE_EIMS_ENABLE_MASK; 36838eb6488eSEric Joyner /* Don't autoclear Link */ 36848eb6488eSEric Joyner mask &= ~IXGBE_EIMS_OTHER; 36858eb6488eSEric Joyner mask &= ~IXGBE_EIMS_LSC; 36868eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_SRIOV) 36878eb6488eSEric Joyner mask &= ~IXGBE_EIMS_MAILBOX; 36888eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask); 36896f37f232SEric Joyner } 36906f37f232SEric Joyner 3691758cc3dcSJack F Vogel /* 36928eb6488eSEric Joyner * Now enable all queues, this is done separately to 36938eb6488eSEric Joyner * allow for handling the extended (beyond 32) MSI-X 36948eb6488eSEric Joyner * vectors that can be used by 82599 3695758cc3dcSJack F Vogel */ 3696c19c7afeSEric Joyner for (int i = 0; i < adapter->num_rx_queues; i++, que++) 36978eb6488eSEric Joyner ixgbe_enable_queue(adapter, que->msix); 36988eb6488eSEric Joyner 36998eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 37008eb6488eSEric Joyner 3701c19c7afeSEric Joyner } /* ixgbe_if_enable_intr */ 37028eb6488eSEric Joyner 37038eb6488eSEric Joyner /************************************************************************ 37048eb6488eSEric Joyner * ixgbe_disable_intr 37058eb6488eSEric Joyner ************************************************************************/ 3706758cc3dcSJack F Vogel static void 3707c19c7afeSEric Joyner ixgbe_if_disable_intr(if_ctx_t ctx) 3708758cc3dcSJack F Vogel { 3709c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 3710c19c7afeSEric Joyner 3711c19c7afeSEric Joyner if (adapter->intr_type == IFLIB_INTR_MSIX) 37128eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 0); 37138eb6488eSEric Joyner if (adapter->hw.mac.type == ixgbe_mac_82598EB) { 37148eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); 37158eb6488eSEric Joyner } else { 37168eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000); 37178eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0); 37188eb6488eSEric Joyner IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); 37198eb6488eSEric Joyner } 37208eb6488eSEric Joyner IXGBE_WRITE_FLUSH(&adapter->hw); 3721758cc3dcSJack F Vogel 3722c19c7afeSEric Joyner } /* ixgbe_if_disable_intr */ 37238eb6488eSEric Joyner 37248eb6488eSEric Joyner /************************************************************************ 3725b2c1e8e6SEric Joyner * ixgbe_link_intr_enable 3726b2c1e8e6SEric Joyner ************************************************************************/ 3727b2c1e8e6SEric Joyner static void 3728b2c1e8e6SEric Joyner ixgbe_link_intr_enable(if_ctx_t ctx) 3729b2c1e8e6SEric Joyner { 3730b2c1e8e6SEric Joyner struct ixgbe_hw *hw = &((struct adapter *)iflib_get_softc(ctx))->hw; 3731b2c1e8e6SEric Joyner 3732b2c1e8e6SEric Joyner /* Re-enable other interrupts */ 3733b2c1e8e6SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC); 3734b2c1e8e6SEric Joyner } /* ixgbe_link_intr_enable */ 3735b2c1e8e6SEric Joyner 3736b2c1e8e6SEric Joyner /************************************************************************ 3737c19c7afeSEric Joyner * ixgbe_if_rx_queue_intr_enable 3738c19c7afeSEric Joyner ************************************************************************/ 3739c19c7afeSEric Joyner static int 3740c19c7afeSEric Joyner ixgbe_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid) 3741c19c7afeSEric Joyner { 3742c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 3743c19c7afeSEric Joyner struct ix_rx_queue *que = &adapter->rx_queues[rxqid]; 3744c19c7afeSEric Joyner 37452dc2d580SEric Joyner ixgbe_enable_queue(adapter, que->msix); 3746c19c7afeSEric Joyner 3747c19c7afeSEric Joyner return (0); 3748c19c7afeSEric Joyner } /* ixgbe_if_rx_queue_intr_enable */ 3749c19c7afeSEric Joyner 3750c19c7afeSEric Joyner /************************************************************************ 3751c19c7afeSEric Joyner * ixgbe_enable_queue 37528eb6488eSEric Joyner ************************************************************************/ 37538eb6488eSEric Joyner static void 3754c19c7afeSEric Joyner ixgbe_enable_queue(struct adapter *adapter, u32 vector) 37558eb6488eSEric Joyner { 37568eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 37572dc2d580SEric Joyner u64 queue = 1ULL << vector; 3758c19c7afeSEric Joyner u32 mask; 3759758cc3dcSJack F Vogel 3760c19c7afeSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) { 3761c19c7afeSEric Joyner mask = (IXGBE_EIMS_RTX_QUEUE & queue); 3762c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); 3763c19c7afeSEric Joyner } else { 3764c19c7afeSEric Joyner mask = (queue & 0xFFFFFFFF); 3765c19c7afeSEric Joyner if (mask) 3766c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); 3767c19c7afeSEric Joyner mask = (queue >> 32); 3768c19c7afeSEric Joyner if (mask) 3769c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask); 3770c19c7afeSEric Joyner } 3771c19c7afeSEric Joyner } /* ixgbe_enable_queue */ 3772c19c7afeSEric Joyner 3773c19c7afeSEric Joyner /************************************************************************ 3774c19c7afeSEric Joyner * ixgbe_disable_queue 3775c19c7afeSEric Joyner ************************************************************************/ 3776c19c7afeSEric Joyner static void 3777c19c7afeSEric Joyner ixgbe_disable_queue(struct adapter *adapter, u32 vector) 3778c19c7afeSEric Joyner { 3779c19c7afeSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 37802dc2d580SEric Joyner u64 queue = 1ULL << vector; 3781c19c7afeSEric Joyner u32 mask; 3782c19c7afeSEric Joyner 3783c19c7afeSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) { 3784c19c7afeSEric Joyner mask = (IXGBE_EIMS_RTX_QUEUE & queue); 3785c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask); 3786c19c7afeSEric Joyner } else { 3787c19c7afeSEric Joyner mask = (queue & 0xFFFFFFFF); 3788c19c7afeSEric Joyner if (mask) 3789c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask); 3790c19c7afeSEric Joyner mask = (queue >> 32); 3791c19c7afeSEric Joyner if (mask) 3792c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask); 3793c19c7afeSEric Joyner } 3794c19c7afeSEric Joyner } /* ixgbe_disable_queue */ 3795c19c7afeSEric Joyner 3796c19c7afeSEric Joyner /************************************************************************ 3797c19c7afeSEric Joyner * ixgbe_intr - Legacy Interrupt Service Routine 3798c19c7afeSEric Joyner ************************************************************************/ 3799c19c7afeSEric Joyner int 3800c19c7afeSEric Joyner ixgbe_intr(void *arg) 3801c19c7afeSEric Joyner { 3802c19c7afeSEric Joyner struct adapter *adapter = arg; 3803c19c7afeSEric Joyner struct ix_rx_queue *que = adapter->rx_queues; 3804c19c7afeSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 3805c19c7afeSEric Joyner if_ctx_t ctx = adapter->ctx; 3806c19c7afeSEric Joyner u32 eicr, eicr_mask; 3807758cc3dcSJack F Vogel 38088eb6488eSEric Joyner eicr = IXGBE_READ_REG(hw, IXGBE_EICR); 3809758cc3dcSJack F Vogel 38108eb6488eSEric Joyner ++que->irqs; 38118eb6488eSEric Joyner if (eicr == 0) { 3812c19c7afeSEric Joyner ixgbe_if_enable_intr(ctx); 3813c19c7afeSEric Joyner return (FILTER_HANDLED); 3814758cc3dcSJack F Vogel } 3815758cc3dcSJack F Vogel 38168eb6488eSEric Joyner /* Check for fan failure */ 3817c19c7afeSEric Joyner if ((hw->device_id == IXGBE_DEV_ID_82598AT) && 3818c19c7afeSEric Joyner (eicr & IXGBE_EICR_GPI_SDP1)) { 3819c19c7afeSEric Joyner device_printf(adapter->dev, 3820c19c7afeSEric Joyner "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n"); 38218eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 3822758cc3dcSJack F Vogel } 3823758cc3dcSJack F Vogel 38248eb6488eSEric Joyner /* Link status change */ 3825c19c7afeSEric Joyner if (eicr & IXGBE_EICR_LSC) { 3826c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); 3827c19c7afeSEric Joyner iflib_admin_intr_deferred(ctx); 3828c19c7afeSEric Joyner } 38298eb6488eSEric Joyner 38308eb6488eSEric Joyner if (ixgbe_is_sfp(hw)) { 38318eb6488eSEric Joyner /* Pluggable optics-related interrupt */ 38328eb6488eSEric Joyner if (hw->mac.type >= ixgbe_mac_X540) 38338eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP0_X540; 38348eb6488eSEric Joyner else 38358eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); 38368eb6488eSEric Joyner 38378eb6488eSEric Joyner if (eicr & eicr_mask) { 38388eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); 3839b2c1e8e6SEric Joyner adapter->task_requests |= IXGBE_REQUEST_TASK_MOD; 38408eb6488eSEric Joyner } 38418eb6488eSEric Joyner 38428eb6488eSEric Joyner if ((hw->mac.type == ixgbe_mac_82599EB) && 38438eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { 38448eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, 38458eb6488eSEric Joyner IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 3846b2c1e8e6SEric Joyner adapter->task_requests |= IXGBE_REQUEST_TASK_MSF; 38478eb6488eSEric Joyner } 38488eb6488eSEric Joyner } 38498eb6488eSEric Joyner 38508eb6488eSEric Joyner /* External PHY interrupt */ 38518eb6488eSEric Joyner if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && 38528eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP0_X540)) 3853b2c1e8e6SEric Joyner adapter->task_requests |= IXGBE_REQUEST_TASK_PHY; 38548eb6488eSEric Joyner 3855c19c7afeSEric Joyner return (FILTER_SCHEDULE_THREAD); 3856c19c7afeSEric Joyner } /* ixgbe_intr */ 38578eb6488eSEric Joyner 38588eb6488eSEric Joyner /************************************************************************ 38598eb6488eSEric Joyner * ixgbe_free_pci_resources 38608eb6488eSEric Joyner ************************************************************************/ 38618eb6488eSEric Joyner static void 3862c19c7afeSEric Joyner ixgbe_free_pci_resources(if_ctx_t ctx) 38638eb6488eSEric Joyner { 3864c19c7afeSEric Joyner struct adapter *adapter = iflib_get_softc(ctx); 3865c19c7afeSEric Joyner struct ix_rx_queue *que = adapter->rx_queues; 3866c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 38678eb6488eSEric Joyner 3868b97de13aSMarius Strobl /* Release all MSI-X queue resources */ 3869c19c7afeSEric Joyner if (adapter->intr_type == IFLIB_INTR_MSIX) 3870c19c7afeSEric Joyner iflib_irq_free(ctx, &adapter->irq); 3871c19c7afeSEric Joyner 3872c19c7afeSEric Joyner if (que != NULL) { 3873c19c7afeSEric Joyner for (int i = 0; i < adapter->num_rx_queues; i++, que++) { 3874c19c7afeSEric Joyner iflib_irq_free(ctx, &que->que_irq); 3875c19c7afeSEric Joyner } 3876c19c7afeSEric Joyner } 38778eb6488eSEric Joyner 38788eb6488eSEric Joyner if (adapter->pci_mem != NULL) 3879c19c7afeSEric Joyner bus_release_resource(dev, SYS_RES_MEMORY, 3880b97de13aSMarius Strobl rman_get_rid(adapter->pci_mem), adapter->pci_mem); 38818eb6488eSEric Joyner } /* ixgbe_free_pci_resources */ 38828eb6488eSEric Joyner 38838eb6488eSEric Joyner /************************************************************************ 38848eb6488eSEric Joyner * ixgbe_sysctl_flowcntl 38858eb6488eSEric Joyner * 38868eb6488eSEric Joyner * SYSCTL wrapper around setting Flow Control 38878eb6488eSEric Joyner ************************************************************************/ 3888758cc3dcSJack F Vogel static int 3889f2c4db54SSteven Hartland ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS) 3890758cc3dcSJack F Vogel { 3891f2c4db54SSteven Hartland struct adapter *adapter; 38928eb6488eSEric Joyner int error, fc; 3893758cc3dcSJack F Vogel 3894f2c4db54SSteven Hartland adapter = (struct adapter *)arg1; 38958eb6488eSEric Joyner fc = adapter->hw.fc.current_mode; 3896f2c4db54SSteven Hartland 3897f2c4db54SSteven Hartland error = sysctl_handle_int(oidp, &fc, 0, req); 3898758cc3dcSJack F Vogel if ((error) || (req->newptr == NULL)) 3899758cc3dcSJack F Vogel return (error); 3900758cc3dcSJack F Vogel 3901758cc3dcSJack F Vogel /* Don't bother if it's not changed */ 39028eb6488eSEric Joyner if (fc == adapter->hw.fc.current_mode) 3903758cc3dcSJack F Vogel return (0); 3904758cc3dcSJack F Vogel 3905f2c4db54SSteven Hartland return ixgbe_set_flowcntl(adapter, fc); 39068eb6488eSEric Joyner } /* ixgbe_sysctl_flowcntl */ 3907f2c4db54SSteven Hartland 39088eb6488eSEric Joyner /************************************************************************ 39098eb6488eSEric Joyner * ixgbe_set_flowcntl - Set flow control 39108eb6488eSEric Joyner * 39118eb6488eSEric Joyner * Flow control values: 39128eb6488eSEric Joyner * 0 - off 39138eb6488eSEric Joyner * 1 - rx pause 39148eb6488eSEric Joyner * 2 - tx pause 39158eb6488eSEric Joyner * 3 - full 39168eb6488eSEric Joyner ************************************************************************/ 3917f2c4db54SSteven Hartland static int 3918f2c4db54SSteven Hartland ixgbe_set_flowcntl(struct adapter *adapter, int fc) 3919f2c4db54SSteven Hartland { 3920f2c4db54SSteven Hartland switch (fc) { 3921758cc3dcSJack F Vogel case ixgbe_fc_rx_pause: 3922758cc3dcSJack F Vogel case ixgbe_fc_tx_pause: 3923758cc3dcSJack F Vogel case ixgbe_fc_full: 39248eb6488eSEric Joyner adapter->hw.fc.requested_mode = fc; 3925c19c7afeSEric Joyner if (adapter->num_rx_queues > 1) 3926758cc3dcSJack F Vogel ixgbe_disable_rx_drop(adapter); 3927758cc3dcSJack F Vogel break; 3928758cc3dcSJack F Vogel case ixgbe_fc_none: 3929758cc3dcSJack F Vogel adapter->hw.fc.requested_mode = ixgbe_fc_none; 3930c19c7afeSEric Joyner if (adapter->num_rx_queues > 1) 3931758cc3dcSJack F Vogel ixgbe_enable_rx_drop(adapter); 3932758cc3dcSJack F Vogel break; 3933758cc3dcSJack F Vogel default: 3934758cc3dcSJack F Vogel return (EINVAL); 3935758cc3dcSJack F Vogel } 39368eb6488eSEric Joyner 3937758cc3dcSJack F Vogel /* Don't autoneg if forcing a value */ 3938758cc3dcSJack F Vogel adapter->hw.fc.disable_fc_autoneg = TRUE; 3939758cc3dcSJack F Vogel ixgbe_fc_enable(&adapter->hw); 39408eb6488eSEric Joyner 3941f2c4db54SSteven Hartland return (0); 39428eb6488eSEric Joyner } /* ixgbe_set_flowcntl */ 39438eb6488eSEric Joyner 39448eb6488eSEric Joyner /************************************************************************ 39458eb6488eSEric Joyner * ixgbe_enable_rx_drop 39468eb6488eSEric Joyner * 39478eb6488eSEric Joyner * Enable the hardware to drop packets when the buffer is 39488eb6488eSEric Joyner * full. This is useful with multiqueue, so that no single 39498eb6488eSEric Joyner * queue being full stalls the entire RX engine. We only 39508eb6488eSEric Joyner * enable this when Multiqueue is enabled AND Flow Control 39518eb6488eSEric Joyner * is disabled. 39528eb6488eSEric Joyner ************************************************************************/ 39538eb6488eSEric Joyner static void 39548eb6488eSEric Joyner ixgbe_enable_rx_drop(struct adapter *adapter) 39558eb6488eSEric Joyner { 39568eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 39578eb6488eSEric Joyner struct rx_ring *rxr; 39588eb6488eSEric Joyner u32 srrctl; 39598eb6488eSEric Joyner 3960c19c7afeSEric Joyner for (int i = 0; i < adapter->num_rx_queues; i++) { 3961c19c7afeSEric Joyner rxr = &adapter->rx_queues[i].rxr; 39628eb6488eSEric Joyner srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); 39638eb6488eSEric Joyner srrctl |= IXGBE_SRRCTL_DROP_EN; 39648eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); 3965758cc3dcSJack F Vogel } 3966758cc3dcSJack F Vogel 39678eb6488eSEric Joyner /* enable drop for each vf */ 39688eb6488eSEric Joyner for (int i = 0; i < adapter->num_vfs; i++) { 39698eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_QDE, 39708eb6488eSEric Joyner (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT) | 39718eb6488eSEric Joyner IXGBE_QDE_ENABLE)); 39728eb6488eSEric Joyner } 39738eb6488eSEric Joyner } /* ixgbe_enable_rx_drop */ 39748eb6488eSEric Joyner 39758eb6488eSEric Joyner /************************************************************************ 39768eb6488eSEric Joyner * ixgbe_disable_rx_drop 39778eb6488eSEric Joyner ************************************************************************/ 39788eb6488eSEric Joyner static void 39798eb6488eSEric Joyner ixgbe_disable_rx_drop(struct adapter *adapter) 39808eb6488eSEric Joyner { 39818eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 39828eb6488eSEric Joyner struct rx_ring *rxr; 39838eb6488eSEric Joyner u32 srrctl; 39848eb6488eSEric Joyner 3985c19c7afeSEric Joyner for (int i = 0; i < adapter->num_rx_queues; i++) { 3986c19c7afeSEric Joyner rxr = &adapter->rx_queues[i].rxr; 39878eb6488eSEric Joyner srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); 39888eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_DROP_EN; 39898eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); 39908eb6488eSEric Joyner } 39918eb6488eSEric Joyner 39928eb6488eSEric Joyner /* disable drop for each vf */ 39938eb6488eSEric Joyner for (int i = 0; i < adapter->num_vfs; i++) { 39948eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_QDE, 39958eb6488eSEric Joyner (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT))); 39968eb6488eSEric Joyner } 39978eb6488eSEric Joyner } /* ixgbe_disable_rx_drop */ 39988eb6488eSEric Joyner 39998eb6488eSEric Joyner /************************************************************************ 40008eb6488eSEric Joyner * ixgbe_sysctl_advertise 40018eb6488eSEric Joyner * 40028eb6488eSEric Joyner * SYSCTL wrapper around setting advertised speed 40038eb6488eSEric Joyner ************************************************************************/ 4004758cc3dcSJack F Vogel static int 4005f2c4db54SSteven Hartland ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS) 4006758cc3dcSJack F Vogel { 4007758cc3dcSJack F Vogel struct adapter *adapter; 40088eb6488eSEric Joyner int error, advertise; 4009758cc3dcSJack F Vogel 4010758cc3dcSJack F Vogel adapter = (struct adapter *)arg1; 4011f2c4db54SSteven Hartland advertise = adapter->advertise; 4012758cc3dcSJack F Vogel 4013f2c4db54SSteven Hartland error = sysctl_handle_int(oidp, &advertise, 0, req); 4014758cc3dcSJack F Vogel if ((error) || (req->newptr == NULL)) 4015758cc3dcSJack F Vogel return (error); 4016758cc3dcSJack F Vogel 4017f2c4db54SSteven Hartland return ixgbe_set_advertise(adapter, advertise); 40188eb6488eSEric Joyner } /* ixgbe_sysctl_advertise */ 4019f2c4db54SSteven Hartland 40208eb6488eSEric Joyner /************************************************************************ 40218eb6488eSEric Joyner * ixgbe_set_advertise - Control advertised link speed 40228eb6488eSEric Joyner * 40238eb6488eSEric Joyner * Flags: 40248eb6488eSEric Joyner * 0x1 - advertise 100 Mb 40258eb6488eSEric Joyner * 0x2 - advertise 1G 40268eb6488eSEric Joyner * 0x4 - advertise 10G 40278eb6488eSEric Joyner * 0x8 - advertise 10 Mb (yes, Mb) 40288eb6488eSEric Joyner ************************************************************************/ 4029f2c4db54SSteven Hartland static int 4030f2c4db54SSteven Hartland ixgbe_set_advertise(struct adapter *adapter, int advertise) 4031f2c4db54SSteven Hartland { 4032c19c7afeSEric Joyner device_t dev = iflib_get_dev(adapter->ctx); 4033f2c4db54SSteven Hartland struct ixgbe_hw *hw; 40348eb6488eSEric Joyner ixgbe_link_speed speed = 0; 40358eb6488eSEric Joyner ixgbe_link_speed link_caps = 0; 40368eb6488eSEric Joyner s32 err = IXGBE_NOT_IMPLEMENTED; 40378eb6488eSEric Joyner bool negotiate = FALSE; 4038f2c4db54SSteven Hartland 4039d775d23aSSteven Hartland /* Checks to validate new value */ 4040d775d23aSSteven Hartland if (adapter->advertise == advertise) /* no change */ 4041d775d23aSSteven Hartland return (0); 4042d775d23aSSteven Hartland 40438eb6488eSEric Joyner hw = &adapter->hw; 4044f2c4db54SSteven Hartland 4045a9ca1c79SSean Bruno /* No speed changes for backplane media */ 4046a9ca1c79SSean Bruno if (hw->phy.media_type == ixgbe_media_type_backplane) 4047a9ca1c79SSean Bruno return (ENODEV); 4048a9ca1c79SSean Bruno 4049758cc3dcSJack F Vogel if (!((hw->phy.media_type == ixgbe_media_type_copper) || 4050758cc3dcSJack F Vogel (hw->phy.multispeed_fiber))) { 40518eb6488eSEric Joyner device_printf(dev, "Advertised speed can only be set on copper or multispeed fiber media types.\n"); 4052758cc3dcSJack F Vogel return (EINVAL); 4053758cc3dcSJack F Vogel } 4054758cc3dcSJack F Vogel 40558eb6488eSEric Joyner if (advertise < 0x1 || advertise > 0xF) { 40568eb6488eSEric Joyner device_printf(dev, "Invalid advertised speed; valid modes are 0x1 through 0xF\n"); 4057758cc3dcSJack F Vogel return (EINVAL); 4058758cc3dcSJack F Vogel } 4059758cc3dcSJack F Vogel 40608eb6488eSEric Joyner if (hw->mac.ops.get_link_capabilities) { 40618eb6488eSEric Joyner err = hw->mac.ops.get_link_capabilities(hw, &link_caps, 40628eb6488eSEric Joyner &negotiate); 40638eb6488eSEric Joyner if (err != IXGBE_SUCCESS) { 40648eb6488eSEric Joyner device_printf(dev, "Unable to determine supported advertise speeds\n"); 40658eb6488eSEric Joyner return (ENODEV); 40668eb6488eSEric Joyner } 4067758cc3dcSJack F Vogel } 4068758cc3dcSJack F Vogel 4069758cc3dcSJack F Vogel /* Set new value and report new advertised mode */ 40708eb6488eSEric Joyner if (advertise & 0x1) { 40718eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_100_FULL)) { 40728eb6488eSEric Joyner device_printf(dev, "Interface does not support 100Mb advertised speed\n"); 40738eb6488eSEric Joyner return (EINVAL); 40748eb6488eSEric Joyner } 4075758cc3dcSJack F Vogel speed |= IXGBE_LINK_SPEED_100_FULL; 40768eb6488eSEric Joyner } 40778eb6488eSEric Joyner if (advertise & 0x2) { 40788eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_1GB_FULL)) { 40798eb6488eSEric Joyner device_printf(dev, "Interface does not support 1Gb advertised speed\n"); 40808eb6488eSEric Joyner return (EINVAL); 40818eb6488eSEric Joyner } 4082758cc3dcSJack F Vogel speed |= IXGBE_LINK_SPEED_1GB_FULL; 40838eb6488eSEric Joyner } 40848eb6488eSEric Joyner if (advertise & 0x4) { 40858eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_10GB_FULL)) { 40868eb6488eSEric Joyner device_printf(dev, "Interface does not support 10Gb advertised speed\n"); 40878eb6488eSEric Joyner return (EINVAL); 40888eb6488eSEric Joyner } 4089758cc3dcSJack F Vogel speed |= IXGBE_LINK_SPEED_10GB_FULL; 40908eb6488eSEric Joyner } 40918eb6488eSEric Joyner if (advertise & 0x8) { 40928eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_10_FULL)) { 40938eb6488eSEric Joyner device_printf(dev, "Interface does not support 10Mb advertised speed\n"); 40948eb6488eSEric Joyner return (EINVAL); 40958eb6488eSEric Joyner } 40968eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10_FULL; 40978eb6488eSEric Joyner } 4098758cc3dcSJack F Vogel 4099758cc3dcSJack F Vogel hw->mac.autotry_restart = TRUE; 4100758cc3dcSJack F Vogel hw->mac.ops.setup_link(hw, speed, TRUE); 41018eb6488eSEric Joyner adapter->advertise = advertise; 4102758cc3dcSJack F Vogel 4103f2c4db54SSteven Hartland return (0); 41048eb6488eSEric Joyner } /* ixgbe_set_advertise */ 41058eb6488eSEric Joyner 41068eb6488eSEric Joyner /************************************************************************ 41078eb6488eSEric Joyner * ixgbe_get_advertise - Get current advertised speed settings 41088eb6488eSEric Joyner * 41098eb6488eSEric Joyner * Formatted for sysctl usage. 41108eb6488eSEric Joyner * Flags: 41118eb6488eSEric Joyner * 0x1 - advertise 100 Mb 41128eb6488eSEric Joyner * 0x2 - advertise 1G 41138eb6488eSEric Joyner * 0x4 - advertise 10G 41148eb6488eSEric Joyner * 0x8 - advertise 10 Mb (yes, Mb) 41158eb6488eSEric Joyner ************************************************************************/ 41168eb6488eSEric Joyner static int 41178eb6488eSEric Joyner ixgbe_get_advertise(struct adapter *adapter) 41188eb6488eSEric Joyner { 41198eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 41208eb6488eSEric Joyner int speed; 41218eb6488eSEric Joyner ixgbe_link_speed link_caps = 0; 41228eb6488eSEric Joyner s32 err; 41238eb6488eSEric Joyner bool negotiate = FALSE; 4124758cc3dcSJack F Vogel 4125758cc3dcSJack F Vogel /* 41268eb6488eSEric Joyner * Advertised speed means nothing unless it's copper or 41278eb6488eSEric Joyner * multi-speed fiber 4128758cc3dcSJack F Vogel */ 41298eb6488eSEric Joyner if (!(hw->phy.media_type == ixgbe_media_type_copper) && 41308eb6488eSEric Joyner !(hw->phy.multispeed_fiber)) 4131758cc3dcSJack F Vogel return (0); 4132758cc3dcSJack F Vogel 41338eb6488eSEric Joyner err = hw->mac.ops.get_link_capabilities(hw, &link_caps, &negotiate); 41348eb6488eSEric Joyner if (err != IXGBE_SUCCESS) 41358eb6488eSEric Joyner return (0); 41368eb6488eSEric Joyner 41378eb6488eSEric Joyner speed = 41388eb6488eSEric Joyner ((link_caps & IXGBE_LINK_SPEED_10GB_FULL) ? 4 : 0) | 41398eb6488eSEric Joyner ((link_caps & IXGBE_LINK_SPEED_1GB_FULL) ? 2 : 0) | 41408eb6488eSEric Joyner ((link_caps & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0) | 41418eb6488eSEric Joyner ((link_caps & IXGBE_LINK_SPEED_10_FULL) ? 8 : 0); 41428eb6488eSEric Joyner 41438eb6488eSEric Joyner return speed; 41448eb6488eSEric Joyner } /* ixgbe_get_advertise */ 41458eb6488eSEric Joyner 41468eb6488eSEric Joyner /************************************************************************ 41478eb6488eSEric Joyner * ixgbe_sysctl_dmac - Manage DMA Coalescing 41488eb6488eSEric Joyner * 41498eb6488eSEric Joyner * Control values: 41508eb6488eSEric Joyner * 0/1 - off / on (use default value of 1000) 41518eb6488eSEric Joyner * 41528eb6488eSEric Joyner * Legal timer values are: 41538eb6488eSEric Joyner * 50,100,250,500,1000,2000,5000,10000 41548eb6488eSEric Joyner * 41558eb6488eSEric Joyner * Turning off interrupt moderation will also turn this off. 41568eb6488eSEric Joyner ************************************************************************/ 41576f37f232SEric Joyner static int 41586f37f232SEric Joyner ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS) 41596f37f232SEric Joyner { 41606f37f232SEric Joyner struct adapter *adapter = (struct adapter *)arg1; 4161c19c7afeSEric Joyner struct ifnet *ifp = iflib_get_ifp(adapter->ctx); 41626f37f232SEric Joyner int error; 4163c19c7afeSEric Joyner u16 newval; 41646f37f232SEric Joyner 4165a9ca1c79SSean Bruno newval = adapter->dmac; 4166c19c7afeSEric Joyner error = sysctl_handle_16(oidp, &newval, 0, req); 41676f37f232SEric Joyner if ((error) || (req->newptr == NULL)) 41686f37f232SEric Joyner return (error); 41696f37f232SEric Joyner 4170a9ca1c79SSean Bruno switch (newval) { 41716f37f232SEric Joyner case 0: 41726f37f232SEric Joyner /* Disabled */ 4173a9ca1c79SSean Bruno adapter->dmac = 0; 41746f37f232SEric Joyner break; 4175a9ca1c79SSean Bruno case 1: 4176a9ca1c79SSean Bruno /* Enable and use default */ 41776f37f232SEric Joyner adapter->dmac = 1000; 41786f37f232SEric Joyner break; 41796f37f232SEric Joyner case 50: 41806f37f232SEric Joyner case 100: 41816f37f232SEric Joyner case 250: 41826f37f232SEric Joyner case 500: 41836f37f232SEric Joyner case 1000: 41846f37f232SEric Joyner case 2000: 41856f37f232SEric Joyner case 5000: 41866f37f232SEric Joyner case 10000: 41876f37f232SEric Joyner /* Legal values - allow */ 4188a9ca1c79SSean Bruno adapter->dmac = newval; 41896f37f232SEric Joyner break; 41906f37f232SEric Joyner default: 41916f37f232SEric Joyner /* Do nothing, illegal value */ 41926f37f232SEric Joyner return (EINVAL); 41936f37f232SEric Joyner } 41946f37f232SEric Joyner 41956f37f232SEric Joyner /* Re-initialize hardware if it's already running */ 41966f37f232SEric Joyner if (ifp->if_drv_flags & IFF_DRV_RUNNING) 4197c19c7afeSEric Joyner ifp->if_init(ifp); 41986f37f232SEric Joyner 41996f37f232SEric Joyner return (0); 42008eb6488eSEric Joyner } /* ixgbe_sysctl_dmac */ 42016f37f232SEric Joyner 4202a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 42038eb6488eSEric Joyner /************************************************************************ 42048eb6488eSEric Joyner * ixgbe_sysctl_power_state 42058eb6488eSEric Joyner * 4206a9ca1c79SSean Bruno * Sysctl to test power states 4207a9ca1c79SSean Bruno * Values: 4208a9ca1c79SSean Bruno * 0 - set device to D0 4209a9ca1c79SSean Bruno * 3 - set device to D3 4210a9ca1c79SSean Bruno * (none) - get current device power state 42118eb6488eSEric Joyner ************************************************************************/ 4212a9ca1c79SSean Bruno static int 4213a9ca1c79SSean Bruno ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS) 4214a9ca1c79SSean Bruno { 4215a9ca1c79SSean Bruno struct adapter *adapter = (struct adapter *)arg1; 4216a9ca1c79SSean Bruno device_t dev = adapter->dev; 4217a9ca1c79SSean Bruno int curr_ps, new_ps, error = 0; 4218a9ca1c79SSean Bruno 4219a9ca1c79SSean Bruno curr_ps = new_ps = pci_get_powerstate(dev); 4220a9ca1c79SSean Bruno 4221a9ca1c79SSean Bruno error = sysctl_handle_int(oidp, &new_ps, 0, req); 4222a9ca1c79SSean Bruno if ((error) || (req->newptr == NULL)) 4223a9ca1c79SSean Bruno return (error); 4224a9ca1c79SSean Bruno 4225a9ca1c79SSean Bruno if (new_ps == curr_ps) 4226a9ca1c79SSean Bruno return (0); 4227a9ca1c79SSean Bruno 4228a9ca1c79SSean Bruno if (new_ps == 3 && curr_ps == 0) 4229a9ca1c79SSean Bruno error = DEVICE_SUSPEND(dev); 4230a9ca1c79SSean Bruno else if (new_ps == 0 && curr_ps == 3) 4231a9ca1c79SSean Bruno error = DEVICE_RESUME(dev); 4232a9ca1c79SSean Bruno else 4233a9ca1c79SSean Bruno return (EINVAL); 4234a9ca1c79SSean Bruno 4235a9ca1c79SSean Bruno device_printf(dev, "New state: %d\n", pci_get_powerstate(dev)); 4236a9ca1c79SSean Bruno 4237a9ca1c79SSean Bruno return (error); 42388eb6488eSEric Joyner } /* ixgbe_sysctl_power_state */ 4239a9ca1c79SSean Bruno #endif 42408eb6488eSEric Joyner 42418eb6488eSEric Joyner /************************************************************************ 42428eb6488eSEric Joyner * ixgbe_sysctl_wol_enable 42438eb6488eSEric Joyner * 42448eb6488eSEric Joyner * Sysctl to enable/disable the WoL capability, 42458eb6488eSEric Joyner * if supported by the adapter. 42468eb6488eSEric Joyner * 42476f37f232SEric Joyner * Values: 42486f37f232SEric Joyner * 0 - disabled 42496f37f232SEric Joyner * 1 - enabled 42508eb6488eSEric Joyner ************************************************************************/ 42516f37f232SEric Joyner static int 42526f37f232SEric Joyner ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS) 42536f37f232SEric Joyner { 42546f37f232SEric Joyner struct adapter *adapter = (struct adapter *)arg1; 42556f37f232SEric Joyner struct ixgbe_hw *hw = &adapter->hw; 42566f37f232SEric Joyner int new_wol_enabled; 42576f37f232SEric Joyner int error = 0; 42586f37f232SEric Joyner 42596f37f232SEric Joyner new_wol_enabled = hw->wol_enabled; 42606f37f232SEric Joyner error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req); 42616f37f232SEric Joyner if ((error) || (req->newptr == NULL)) 42626f37f232SEric Joyner return (error); 4263a9ca1c79SSean Bruno new_wol_enabled = !!(new_wol_enabled); 42646f37f232SEric Joyner if (new_wol_enabled == hw->wol_enabled) 42656f37f232SEric Joyner return (0); 42666f37f232SEric Joyner 42676f37f232SEric Joyner if (new_wol_enabled > 0 && !adapter->wol_support) 42686f37f232SEric Joyner return (ENODEV); 42696f37f232SEric Joyner else 4270a9ca1c79SSean Bruno hw->wol_enabled = new_wol_enabled; 42716f37f232SEric Joyner 42726f37f232SEric Joyner return (0); 42738eb6488eSEric Joyner } /* ixgbe_sysctl_wol_enable */ 42746f37f232SEric Joyner 42758eb6488eSEric Joyner /************************************************************************ 42768eb6488eSEric Joyner * ixgbe_sysctl_wufc - Wake Up Filter Control 42778eb6488eSEric Joyner * 42786f37f232SEric Joyner * Sysctl to enable/disable the types of packets that the 42796f37f232SEric Joyner * adapter will wake up on upon receipt. 42806f37f232SEric Joyner * Flags: 42816f37f232SEric Joyner * 0x1 - Link Status Change 42826f37f232SEric Joyner * 0x2 - Magic Packet 42836f37f232SEric Joyner * 0x4 - Direct Exact 42846f37f232SEric Joyner * 0x8 - Directed Multicast 42856f37f232SEric Joyner * 0x10 - Broadcast 42866f37f232SEric Joyner * 0x20 - ARP/IPv4 Request Packet 42876f37f232SEric Joyner * 0x40 - Direct IPv4 Packet 42886f37f232SEric Joyner * 0x80 - Direct IPv6 Packet 42896f37f232SEric Joyner * 42908eb6488eSEric Joyner * Settings not listed above will cause the sysctl to return an error. 42918eb6488eSEric Joyner ************************************************************************/ 42926f37f232SEric Joyner static int 42936f37f232SEric Joyner ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS) 42946f37f232SEric Joyner { 42956f37f232SEric Joyner struct adapter *adapter = (struct adapter *)arg1; 42966f37f232SEric Joyner int error = 0; 42976f37f232SEric Joyner u32 new_wufc; 42986f37f232SEric Joyner 42996f37f232SEric Joyner new_wufc = adapter->wufc; 43006f37f232SEric Joyner 4301c19c7afeSEric Joyner error = sysctl_handle_32(oidp, &new_wufc, 0, req); 43026f37f232SEric Joyner if ((error) || (req->newptr == NULL)) 43036f37f232SEric Joyner return (error); 43046f37f232SEric Joyner if (new_wufc == adapter->wufc) 43056f37f232SEric Joyner return (0); 43066f37f232SEric Joyner 43076f37f232SEric Joyner if (new_wufc & 0xffffff00) 43086f37f232SEric Joyner return (EINVAL); 43098eb6488eSEric Joyner 43106f37f232SEric Joyner new_wufc &= 0xff; 43116f37f232SEric Joyner new_wufc |= (0xffffff & adapter->wufc); 43126f37f232SEric Joyner adapter->wufc = new_wufc; 43136f37f232SEric Joyner 43146f37f232SEric Joyner return (0); 43158eb6488eSEric Joyner } /* ixgbe_sysctl_wufc */ 43166f37f232SEric Joyner 4317a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 43188eb6488eSEric Joyner /************************************************************************ 43198eb6488eSEric Joyner * ixgbe_sysctl_print_rss_config 43208eb6488eSEric Joyner ************************************************************************/ 4321a9ca1c79SSean Bruno static int 4322a9ca1c79SSean Bruno ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS) 4323a9ca1c79SSean Bruno { 4324a9ca1c79SSean Bruno struct adapter *adapter = (struct adapter *)arg1; 4325a9ca1c79SSean Bruno struct ixgbe_hw *hw = &adapter->hw; 4326a9ca1c79SSean Bruno device_t dev = adapter->dev; 4327a9ca1c79SSean Bruno struct sbuf *buf; 43288eb6488eSEric Joyner int error = 0, reta_size; 4329a9ca1c79SSean Bruno u32 reg; 4330a9ca1c79SSean Bruno 4331a9ca1c79SSean Bruno buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); 4332a9ca1c79SSean Bruno if (!buf) { 4333a9ca1c79SSean Bruno device_printf(dev, "Could not allocate sbuf for output.\n"); 4334a9ca1c79SSean Bruno return (ENOMEM); 4335a9ca1c79SSean Bruno } 4336a9ca1c79SSean Bruno 4337a9ca1c79SSean Bruno // TODO: use sbufs to make a string to print out 4338a9ca1c79SSean Bruno /* Set multiplier for RETA setup and table size based on MAC */ 4339a9ca1c79SSean Bruno switch (adapter->hw.mac.type) { 4340a9ca1c79SSean Bruno case ixgbe_mac_X550: 4341a9ca1c79SSean Bruno case ixgbe_mac_X550EM_x: 43428eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 4343a9ca1c79SSean Bruno reta_size = 128; 4344a9ca1c79SSean Bruno break; 4345a9ca1c79SSean Bruno default: 4346a9ca1c79SSean Bruno reta_size = 32; 4347a9ca1c79SSean Bruno break; 4348a9ca1c79SSean Bruno } 4349a9ca1c79SSean Bruno 4350a9ca1c79SSean Bruno /* Print out the redirection table */ 4351a9ca1c79SSean Bruno sbuf_cat(buf, "\n"); 4352a9ca1c79SSean Bruno for (int i = 0; i < reta_size; i++) { 4353a9ca1c79SSean Bruno if (i < 32) { 4354a9ca1c79SSean Bruno reg = IXGBE_READ_REG(hw, IXGBE_RETA(i)); 4355a9ca1c79SSean Bruno sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg); 4356a9ca1c79SSean Bruno } else { 4357a9ca1c79SSean Bruno reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32)); 4358a9ca1c79SSean Bruno sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg); 4359a9ca1c79SSean Bruno } 4360a9ca1c79SSean Bruno } 4361a9ca1c79SSean Bruno 4362a9ca1c79SSean Bruno // TODO: print more config 4363a9ca1c79SSean Bruno 4364a9ca1c79SSean Bruno error = sbuf_finish(buf); 4365a9ca1c79SSean Bruno if (error) 4366a9ca1c79SSean Bruno device_printf(dev, "Error finishing sbuf: %d\n", error); 4367a9ca1c79SSean Bruno 4368a9ca1c79SSean Bruno sbuf_delete(buf); 43698eb6488eSEric Joyner 4370a9ca1c79SSean Bruno return (0); 43718eb6488eSEric Joyner } /* ixgbe_sysctl_print_rss_config */ 4372a9ca1c79SSean Bruno #endif /* IXGBE_DEBUG */ 4373a9ca1c79SSean Bruno 43748eb6488eSEric Joyner /************************************************************************ 43758eb6488eSEric Joyner * ixgbe_sysctl_phy_temp - Retrieve temperature of PHY 43768eb6488eSEric Joyner * 43778eb6488eSEric Joyner * For X552/X557-AT devices using an external PHY 43788eb6488eSEric Joyner ************************************************************************/ 43798eb6488eSEric Joyner static int 43808eb6488eSEric Joyner ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS) 43818eb6488eSEric Joyner { 43828eb6488eSEric Joyner struct adapter *adapter = (struct adapter *)arg1; 43838eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 43848eb6488eSEric Joyner u16 reg; 43858eb6488eSEric Joyner 43868eb6488eSEric Joyner if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { 4387c19c7afeSEric Joyner device_printf(iflib_get_dev(adapter->ctx), 43888eb6488eSEric Joyner "Device has no supported external thermal sensor.\n"); 43898eb6488eSEric Joyner return (ENODEV); 43908eb6488eSEric Joyner } 43918eb6488eSEric Joyner 43928eb6488eSEric Joyner if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP, 43938eb6488eSEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) { 4394c19c7afeSEric Joyner device_printf(iflib_get_dev(adapter->ctx), 43958eb6488eSEric Joyner "Error reading from PHY's current temperature register\n"); 43968eb6488eSEric Joyner return (EAGAIN); 43978eb6488eSEric Joyner } 43988eb6488eSEric Joyner 43998eb6488eSEric Joyner /* Shift temp for output */ 44008eb6488eSEric Joyner reg = reg >> 8; 44018eb6488eSEric Joyner 4402c19c7afeSEric Joyner return (sysctl_handle_16(oidp, NULL, reg, req)); 44038eb6488eSEric Joyner } /* ixgbe_sysctl_phy_temp */ 44048eb6488eSEric Joyner 44058eb6488eSEric Joyner /************************************************************************ 44068eb6488eSEric Joyner * ixgbe_sysctl_phy_overtemp_occurred 44078eb6488eSEric Joyner * 44088eb6488eSEric Joyner * Reports (directly from the PHY) whether the current PHY 44098eb6488eSEric Joyner * temperature is over the overtemp threshold. 44108eb6488eSEric Joyner ************************************************************************/ 44118eb6488eSEric Joyner static int 44128eb6488eSEric Joyner ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS) 44138eb6488eSEric Joyner { 44148eb6488eSEric Joyner struct adapter *adapter = (struct adapter *)arg1; 44158eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 44168eb6488eSEric Joyner u16 reg; 44178eb6488eSEric Joyner 44188eb6488eSEric Joyner if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { 4419c19c7afeSEric Joyner device_printf(iflib_get_dev(adapter->ctx), 44208eb6488eSEric Joyner "Device has no supported external thermal sensor.\n"); 44218eb6488eSEric Joyner return (ENODEV); 44228eb6488eSEric Joyner } 44238eb6488eSEric Joyner 44248eb6488eSEric Joyner if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS, 44258eb6488eSEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) { 4426c19c7afeSEric Joyner device_printf(iflib_get_dev(adapter->ctx), 44278eb6488eSEric Joyner "Error reading from PHY's temperature status register\n"); 44288eb6488eSEric Joyner return (EAGAIN); 44298eb6488eSEric Joyner } 44308eb6488eSEric Joyner 44318eb6488eSEric Joyner /* Get occurrence bit */ 44328eb6488eSEric Joyner reg = !!(reg & 0x4000); 44338eb6488eSEric Joyner 4434c19c7afeSEric Joyner return (sysctl_handle_16(oidp, 0, reg, req)); 44358eb6488eSEric Joyner } /* ixgbe_sysctl_phy_overtemp_occurred */ 44368eb6488eSEric Joyner 44378eb6488eSEric Joyner /************************************************************************ 44388eb6488eSEric Joyner * ixgbe_sysctl_eee_state 44398eb6488eSEric Joyner * 44408eb6488eSEric Joyner * Sysctl to set EEE power saving feature 44418eb6488eSEric Joyner * Values: 44428eb6488eSEric Joyner * 0 - disable EEE 44438eb6488eSEric Joyner * 1 - enable EEE 44448eb6488eSEric Joyner * (none) - get current device EEE state 44458eb6488eSEric Joyner ************************************************************************/ 44468eb6488eSEric Joyner static int 44478eb6488eSEric Joyner ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS) 44488eb6488eSEric Joyner { 44498eb6488eSEric Joyner struct adapter *adapter = (struct adapter *)arg1; 44508eb6488eSEric Joyner device_t dev = adapter->dev; 4451c19c7afeSEric Joyner struct ifnet *ifp = iflib_get_ifp(adapter->ctx); 44528eb6488eSEric Joyner int curr_eee, new_eee, error = 0; 44538eb6488eSEric Joyner s32 retval; 44548eb6488eSEric Joyner 44558eb6488eSEric Joyner curr_eee = new_eee = !!(adapter->feat_en & IXGBE_FEATURE_EEE); 44568eb6488eSEric Joyner 44578eb6488eSEric Joyner error = sysctl_handle_int(oidp, &new_eee, 0, req); 44588eb6488eSEric Joyner if ((error) || (req->newptr == NULL)) 44598eb6488eSEric Joyner return (error); 44608eb6488eSEric Joyner 44618eb6488eSEric Joyner /* Nothing to do */ 44628eb6488eSEric Joyner if (new_eee == curr_eee) 44638eb6488eSEric Joyner return (0); 44648eb6488eSEric Joyner 44658eb6488eSEric Joyner /* Not supported */ 44668eb6488eSEric Joyner if (!(adapter->feat_cap & IXGBE_FEATURE_EEE)) 44678eb6488eSEric Joyner return (EINVAL); 44688eb6488eSEric Joyner 44698eb6488eSEric Joyner /* Bounds checking */ 44708eb6488eSEric Joyner if ((new_eee < 0) || (new_eee > 1)) 44718eb6488eSEric Joyner return (EINVAL); 44728eb6488eSEric Joyner 4473d61b6a41SEric Joyner retval = ixgbe_setup_eee(&adapter->hw, new_eee); 44748eb6488eSEric Joyner if (retval) { 44758eb6488eSEric Joyner device_printf(dev, "Error in EEE setup: 0x%08X\n", retval); 44768eb6488eSEric Joyner return (EINVAL); 44778eb6488eSEric Joyner } 44788eb6488eSEric Joyner 44798eb6488eSEric Joyner /* Restart auto-neg */ 4480c19c7afeSEric Joyner ifp->if_init(ifp); 44818eb6488eSEric Joyner 44828eb6488eSEric Joyner device_printf(dev, "New EEE state: %d\n", new_eee); 44838eb6488eSEric Joyner 44848eb6488eSEric Joyner /* Cache new value */ 44858eb6488eSEric Joyner if (new_eee) 44868eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_EEE; 44878eb6488eSEric Joyner else 44888eb6488eSEric Joyner adapter->feat_en &= ~IXGBE_FEATURE_EEE; 44898eb6488eSEric Joyner 44908eb6488eSEric Joyner return (error); 44918eb6488eSEric Joyner } /* ixgbe_sysctl_eee_state */ 44928eb6488eSEric Joyner 44938eb6488eSEric Joyner /************************************************************************ 44948eb6488eSEric Joyner * ixgbe_init_device_features 44958eb6488eSEric Joyner ************************************************************************/ 44968eb6488eSEric Joyner static void 44978eb6488eSEric Joyner ixgbe_init_device_features(struct adapter *adapter) 44988eb6488eSEric Joyner { 44998eb6488eSEric Joyner adapter->feat_cap = IXGBE_FEATURE_NETMAP 45008eb6488eSEric Joyner | IXGBE_FEATURE_RSS 45018eb6488eSEric Joyner | IXGBE_FEATURE_MSI 45028eb6488eSEric Joyner | IXGBE_FEATURE_MSIX 4503c19c7afeSEric Joyner | IXGBE_FEATURE_LEGACY_IRQ; 45048eb6488eSEric Joyner 45058eb6488eSEric Joyner /* Set capabilities first... */ 45068eb6488eSEric Joyner switch (adapter->hw.mac.type) { 45078eb6488eSEric Joyner case ixgbe_mac_82598EB: 45088eb6488eSEric Joyner if (adapter->hw.device_id == IXGBE_DEV_ID_82598AT) 45098eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_FAN_FAIL; 45108eb6488eSEric Joyner break; 45118eb6488eSEric Joyner case ixgbe_mac_X540: 45128eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_SRIOV; 45138eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_FDIR; 45148eb6488eSEric Joyner if ((adapter->hw.device_id == IXGBE_DEV_ID_X540_BYPASS) && 45158eb6488eSEric Joyner (adapter->hw.bus.func == 0)) 45168eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_BYPASS; 45178eb6488eSEric Joyner break; 45188eb6488eSEric Joyner case ixgbe_mac_X550: 45198eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR; 45208eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_SRIOV; 45218eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_FDIR; 45228eb6488eSEric Joyner break; 45238eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 45248eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_SRIOV; 45258eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_FDIR; 45268eb6488eSEric Joyner break; 45278eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 45288eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_SRIOV; 45298eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_FDIR; 45308eb6488eSEric Joyner adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ; 45318eb6488eSEric Joyner if ((adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T) || 45328eb6488eSEric Joyner (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) { 45338eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR; 45348eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_EEE; 45358eb6488eSEric Joyner } 45368eb6488eSEric Joyner break; 45378eb6488eSEric Joyner case ixgbe_mac_82599EB: 45388eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_SRIOV; 45398eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_FDIR; 45408eb6488eSEric Joyner if ((adapter->hw.device_id == IXGBE_DEV_ID_82599_BYPASS) && 45418eb6488eSEric Joyner (adapter->hw.bus.func == 0)) 45428eb6488eSEric Joyner adapter->feat_cap |= IXGBE_FEATURE_BYPASS; 45438eb6488eSEric Joyner if (adapter->hw.device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) 45448eb6488eSEric Joyner adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ; 45458eb6488eSEric Joyner break; 45468eb6488eSEric Joyner default: 45478eb6488eSEric Joyner break; 45488eb6488eSEric Joyner } 45498eb6488eSEric Joyner 45508eb6488eSEric Joyner /* Enabled by default... */ 45518eb6488eSEric Joyner /* Fan failure detection */ 45528eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_FAN_FAIL) 45538eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_FAN_FAIL; 45548eb6488eSEric Joyner /* Netmap */ 45558eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_NETMAP) 45568eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_NETMAP; 45578eb6488eSEric Joyner /* EEE */ 45588eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_EEE) 45598eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_EEE; 45608eb6488eSEric Joyner /* Thermal Sensor */ 45618eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_TEMP_SENSOR) 45628eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_TEMP_SENSOR; 45638eb6488eSEric Joyner 45648eb6488eSEric Joyner /* Enabled via global sysctl... */ 45658eb6488eSEric Joyner /* Flow Director */ 45668eb6488eSEric Joyner if (ixgbe_enable_fdir) { 45678eb6488eSEric Joyner if (adapter->feat_cap & IXGBE_FEATURE_FDIR) 45688eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_FDIR; 45698eb6488eSEric Joyner else 45708eb6488eSEric Joyner device_printf(adapter->dev, "Device does not support Flow Director. Leaving disabled."); 45718eb6488eSEric Joyner } 45726f37f232SEric Joyner /* 45738eb6488eSEric Joyner * Message Signal Interrupts - Extended (MSI-X) 45748eb6488eSEric Joyner * Normal MSI is only enabled if MSI-X calls fail. 4575758cc3dcSJack F Vogel */ 45768eb6488eSEric Joyner if (!ixgbe_enable_msix) 45778eb6488eSEric Joyner adapter->feat_cap &= ~IXGBE_FEATURE_MSIX; 45788eb6488eSEric Joyner /* Receive-Side Scaling (RSS) */ 45798eb6488eSEric Joyner if ((adapter->feat_cap & IXGBE_FEATURE_RSS) && ixgbe_enable_rss) 45808eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_RSS; 45818eb6488eSEric Joyner 45828eb6488eSEric Joyner /* Disable features with unmet dependencies... */ 45838eb6488eSEric Joyner /* No MSI-X */ 45848eb6488eSEric Joyner if (!(adapter->feat_cap & IXGBE_FEATURE_MSIX)) { 45858eb6488eSEric Joyner adapter->feat_cap &= ~IXGBE_FEATURE_RSS; 45868eb6488eSEric Joyner adapter->feat_cap &= ~IXGBE_FEATURE_SRIOV; 45878eb6488eSEric Joyner adapter->feat_en &= ~IXGBE_FEATURE_RSS; 45888eb6488eSEric Joyner adapter->feat_en &= ~IXGBE_FEATURE_SRIOV; 45898eb6488eSEric Joyner } 45908eb6488eSEric Joyner } /* ixgbe_init_device_features */ 45918eb6488eSEric Joyner 45928eb6488eSEric Joyner /************************************************************************ 45938eb6488eSEric Joyner * ixgbe_check_fan_failure 45948eb6488eSEric Joyner ************************************************************************/ 45958eb6488eSEric Joyner static void 45968eb6488eSEric Joyner ixgbe_check_fan_failure(struct adapter *adapter, u32 reg, bool in_interrupt) 45978eb6488eSEric Joyner { 45988eb6488eSEric Joyner u32 mask; 45998eb6488eSEric Joyner 46008eb6488eSEric Joyner mask = (in_interrupt) ? IXGBE_EICR_GPI_SDP1_BY_MAC(&adapter->hw) : 46018eb6488eSEric Joyner IXGBE_ESDP_SDP1; 46028eb6488eSEric Joyner 46038eb6488eSEric Joyner if (reg & mask) 46048eb6488eSEric Joyner device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n"); 46058eb6488eSEric Joyner } /* ixgbe_check_fan_failure */ 4606