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 34758cc3dcSJack F Vogel #include "opt_inet.h" 35758cc3dcSJack F Vogel #include "opt_inet6.h" 36758cc3dcSJack F Vogel #include "opt_rss.h" 37758cc3dcSJack F Vogel 38758cc3dcSJack F Vogel #include "ixgbe.h" 39c19c7afeSEric Joyner #include "ixgbe_sriov.h" 40c19c7afeSEric Joyner #include "ifdi_if.h" 41c19c7afeSEric Joyner 42c19c7afeSEric Joyner #include <net/netmap.h> 43c19c7afeSEric Joyner #include <dev/netmap/netmap_kern.h> 44758cc3dcSJack F Vogel 458eb6488eSEric Joyner /************************************************************************ 46758cc3dcSJack F Vogel * Driver version 478eb6488eSEric Joyner ************************************************************************/ 4851e23514SMarius Strobl static const char ixgbe_driver_version[] = "4.0.1-k"; 49a9ca1c79SSean Bruno 508eb6488eSEric Joyner /************************************************************************ 51758cc3dcSJack F Vogel * PCI Device ID Table 52758cc3dcSJack F Vogel * 53758cc3dcSJack F Vogel * Used by probe to select devices to load on 54758cc3dcSJack F Vogel * Last field stores an index into ixgbe_strings 55758cc3dcSJack F Vogel * Last entry must be all 0s 56758cc3dcSJack F Vogel * 57758cc3dcSJack F Vogel * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } 588eb6488eSEric Joyner ************************************************************************/ 5951e23514SMarius Strobl static const pci_vendor_info_t ixgbe_vendor_info_array[] = 60758cc3dcSJack F Vogel { 61fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, "Intel(R) 82598EB AF (Dual Fiber)"), 62fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, "Intel(R) 82598EB AF (Fiber)"), 63fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, "Intel(R) 82598EB AT (CX4)"), 64fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, "Intel(R) 82598EB AT"), 65fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, "Intel(R) 82598EB AT2"), 66fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, "Intel(R) 82598"), 67fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, "Intel(R) 82598EB AF DA (Dual Fiber)"), 68fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, "Intel(R) 82598EB AT (Dual CX4)"), 69fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, "Intel(R) 82598EB AF (Dual Fiber LR)"), 70fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, "Intel(R) 82598EB AF (Dual Fiber SR)"), 71fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, "Intel(R) 82598EB LOM"), 72fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, "Intel(R) X520 82599 (KX4)"), 73fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, "Intel(R) X520 82599 (KX4 Mezzanine)"), 74fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, "Intel(R) X520 82599ES (SFI/SFP+)"), 75fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, "Intel(R) X520 82599 (XAUI/BX4)"), 76fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, "Intel(R) X520 82599 (Dual CX4)"), 77fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, "Intel(R) X520-T 82599 LOM"), 789228ac3aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_LS, "Intel(R) X520 82599 LS"), 79fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, "Intel(R) X520 82599 (Combined Backplane)"), 80fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, "Intel(R) X520 82599 (Backplane w/FCoE)"), 81fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF2, "Intel(R) X520 82599 (Dual SFP+)"), 82fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, "Intel(R) X520 82599 (Dual SFP+ w/FCoE)"), 83fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP, "Intel(R) X520-1 82599EN (SFP+)"), 84fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF_QP, "Intel(R) X520-4 82599 (Quad SFP+)"), 85fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_QSFP_SF_QP, "Intel(R) X520-Q1 82599 (QSFP+)"), 86fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, "Intel(R) X540-AT2"), 87fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, "Intel(R) X540-T1"), 88fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, "Intel(R) X550-T2"), 89fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, "Intel(R) X550-T1"), 90fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, "Intel(R) X552 (KR Backplane)"), 91fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, "Intel(R) X552 (KX4 Backplane)"), 92fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, "Intel(R) X552/X557-AT (10GBASE-T)"), 93fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_1G_T, "Intel(R) X552 (1000BASE-T)"), 94fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, "Intel(R) X552 (SFP+)"), 95fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR, "Intel(R) X553 (KR Backplane)"), 96fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR_L, "Intel(R) X553 L (KR Backplane)"), 97fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP, "Intel(R) X553 (SFP+)"), 98fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP_N, "Intel(R) X553 N (SFP+)"), 99fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII, "Intel(R) X553 (1GbE SGMII)"), 100fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII_L, "Intel(R) X553 L (1GbE SGMII)"), 101fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_10G_T, "Intel(R) X553/X557-AT (10GBASE-T)"), 102fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T, "Intel(R) X553 (1GbE)"), 103fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T_L, "Intel(R) X553 L (1GbE)"), 104fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_BYPASS, "Intel(R) X540-T2 (Bypass)"), 105fdbcd35aSKevin Bowling PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BYPASS, "Intel(R) X520 82599 (Bypass)"), 106758cc3dcSJack F Vogel /* required last entry */ 107c19c7afeSEric Joyner PVID_END 108758cc3dcSJack F Vogel }; 109758cc3dcSJack F Vogel 110b1d5caf3SKevin Bowling static void *ixgbe_register(device_t); 111b1d5caf3SKevin Bowling static int ixgbe_if_attach_pre(if_ctx_t); 112b1d5caf3SKevin Bowling static int ixgbe_if_attach_post(if_ctx_t); 113b1d5caf3SKevin Bowling static int ixgbe_if_detach(if_ctx_t); 114b1d5caf3SKevin Bowling static int ixgbe_if_shutdown(if_ctx_t); 115b1d5caf3SKevin Bowling static int ixgbe_if_suspend(if_ctx_t); 116b1d5caf3SKevin Bowling static int ixgbe_if_resume(if_ctx_t); 117c19c7afeSEric Joyner 118b1d5caf3SKevin Bowling static void ixgbe_if_stop(if_ctx_t); 119b1d5caf3SKevin Bowling void ixgbe_if_enable_intr(if_ctx_t); 120b1d5caf3SKevin Bowling static void ixgbe_if_disable_intr(if_ctx_t); 121b1d5caf3SKevin Bowling static void ixgbe_link_intr_enable(if_ctx_t); 122b1d5caf3SKevin Bowling static int ixgbe_if_rx_queue_intr_enable(if_ctx_t, uint16_t); 123b1d5caf3SKevin Bowling static void ixgbe_if_media_status(if_ctx_t, struct ifmediareq *); 124b1d5caf3SKevin Bowling static int ixgbe_if_media_change(if_ctx_t); 125c19c7afeSEric Joyner static int ixgbe_if_msix_intr_assign(if_ctx_t, int); 126b1d5caf3SKevin Bowling static int ixgbe_if_mtu_set(if_ctx_t, uint32_t); 127b1d5caf3SKevin Bowling static void ixgbe_if_crcstrip_set(if_ctx_t, int, int); 128b1d5caf3SKevin Bowling static void ixgbe_if_multi_set(if_ctx_t); 129b1d5caf3SKevin Bowling static int ixgbe_if_promisc_set(if_ctx_t, int); 130b1d5caf3SKevin Bowling static int ixgbe_if_tx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int, int); 131b1d5caf3SKevin Bowling static int ixgbe_if_rx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int, int); 132b1d5caf3SKevin Bowling static void ixgbe_if_queues_free(if_ctx_t); 133b1d5caf3SKevin Bowling static void ixgbe_if_timer(if_ctx_t, uint16_t); 134b1d5caf3SKevin Bowling static void ixgbe_if_update_admin_status(if_ctx_t); 135b1d5caf3SKevin Bowling static void ixgbe_if_vlan_register(if_ctx_t, u16); 136b1d5caf3SKevin Bowling static void ixgbe_if_vlan_unregister(if_ctx_t, u16); 137b1d5caf3SKevin Bowling static int ixgbe_if_i2c_req(if_ctx_t, struct ifi2creq *); 138b1d5caf3SKevin Bowling static bool ixgbe_if_needs_restart(if_ctx_t, enum iflib_restart_event); 139b1d5caf3SKevin Bowling int ixgbe_intr(void *); 140758cc3dcSJack F Vogel 1418eb6488eSEric Joyner /************************************************************************ 142758cc3dcSJack F Vogel * Function prototypes 1438eb6488eSEric Joyner ************************************************************************/ 144c19c7afeSEric Joyner static uint64_t ixgbe_if_get_counter(if_ctx_t, ift_counter); 145758cc3dcSJack F Vogel 146b1d5caf3SKevin Bowling static void ixgbe_enable_queue(struct ixgbe_softc *, u32); 147b1d5caf3SKevin Bowling static void ixgbe_disable_queue(struct ixgbe_softc *, u32); 148b1d5caf3SKevin Bowling static void ixgbe_add_device_sysctls(if_ctx_t); 149b1d5caf3SKevin Bowling static int ixgbe_allocate_pci_resources(if_ctx_t); 150b1d5caf3SKevin Bowling static int ixgbe_setup_low_power_mode(if_ctx_t); 151c19c7afeSEric Joyner 152b1d5caf3SKevin Bowling static void ixgbe_config_dmac(struct ixgbe_softc *); 153b1d5caf3SKevin Bowling static void ixgbe_configure_ivars(struct ixgbe_softc *); 154b1d5caf3SKevin Bowling static void ixgbe_set_ivar(struct ixgbe_softc *, u8, u8, s8); 155c19c7afeSEric Joyner static u8 *ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); 156b1d5caf3SKevin Bowling static bool ixgbe_sfp_probe(if_ctx_t); 157c19c7afeSEric Joyner 158b1d5caf3SKevin Bowling static void ixgbe_free_pci_resources(if_ctx_t); 159c19c7afeSEric Joyner 160b1d5caf3SKevin Bowling static int ixgbe_msix_link(void *); 161b1d5caf3SKevin Bowling static int ixgbe_msix_que(void *); 162b1d5caf3SKevin Bowling static void ixgbe_initialize_rss_mapping(struct ixgbe_softc *); 163b1d5caf3SKevin Bowling static void ixgbe_initialize_receive_units(if_ctx_t); 164b1d5caf3SKevin Bowling static void ixgbe_initialize_transmit_units(if_ctx_t); 165c19c7afeSEric Joyner 166b1d5caf3SKevin Bowling static int ixgbe_setup_interface(if_ctx_t); 167b1d5caf3SKevin Bowling static void ixgbe_init_device_features(struct ixgbe_softc *); 168b1d5caf3SKevin Bowling static void ixgbe_check_fan_failure(struct ixgbe_softc *, u32, bool); 1697660e4eaSKevin Bowling static void ixgbe_sbuf_fw_version(struct ixgbe_hw *, struct sbuf *); 170b1d5caf3SKevin Bowling static void ixgbe_print_fw_version(if_ctx_t); 171b1d5caf3SKevin Bowling static void ixgbe_add_media_types(if_ctx_t); 172b1d5caf3SKevin Bowling static void ixgbe_update_stats_counters(struct ixgbe_softc *); 173b1d5caf3SKevin Bowling static void ixgbe_config_link(if_ctx_t); 174b1d5caf3SKevin Bowling static void ixgbe_get_slot_info(struct ixgbe_softc *); 175f72de14eSKevin Bowling static void ixgbe_fw_mode_timer(void *); 176b1d5caf3SKevin Bowling static void ixgbe_check_wol_support(struct ixgbe_softc *); 177b1d5caf3SKevin Bowling static void ixgbe_enable_rx_drop(struct ixgbe_softc *); 178b1d5caf3SKevin Bowling static void ixgbe_disable_rx_drop(struct ixgbe_softc *); 179758cc3dcSJack F Vogel 180b1d5caf3SKevin Bowling static void ixgbe_add_hw_stats(struct ixgbe_softc *); 181b1d5caf3SKevin Bowling static int ixgbe_set_flowcntl(struct ixgbe_softc *, int); 182b1d5caf3SKevin Bowling static int ixgbe_set_advertise(struct ixgbe_softc *, int); 183d381c807SPiotr Pietruszewski static int ixgbe_get_default_advertise(struct ixgbe_softc *); 184b1d5caf3SKevin Bowling static void ixgbe_setup_vlan_hw_support(if_ctx_t); 185b1d5caf3SKevin Bowling static void ixgbe_config_gpie(struct ixgbe_softc *); 186b1d5caf3SKevin Bowling static void ixgbe_config_delay_values(struct ixgbe_softc *); 1876f37f232SEric Joyner 1886f37f232SEric Joyner /* Sysctl handlers */ 189f2c4db54SSteven Hartland static int ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS); 190f2c4db54SSteven Hartland static int ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS); 1918eb6488eSEric Joyner static int ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS); 1926f37f232SEric Joyner static int ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS); 1936f37f232SEric Joyner static int ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS); 1946f37f232SEric Joyner static int ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS); 1957660e4eaSKevin Bowling static int ixgbe_sysctl_print_fw_version(SYSCTL_HANDLER_ARGS); 196a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 197a9ca1c79SSean Bruno static int ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS); 198a9ca1c79SSean Bruno static int ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS); 199a9ca1c79SSean Bruno #endif 2008eb6488eSEric Joyner static int ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS); 2018eb6488eSEric Joyner static int ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS); 2028eb6488eSEric Joyner static int ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS); 2038eb6488eSEric Joyner static int ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS); 2048eb6488eSEric Joyner static int ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS); 2056f37f232SEric Joyner static int ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS); 2066f37f232SEric Joyner static int ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS); 207758cc3dcSJack F Vogel 208758cc3dcSJack F Vogel /* Deferred interrupt tasklets */ 209c19c7afeSEric Joyner static void ixgbe_handle_msf(void *); 210c19c7afeSEric Joyner static void ixgbe_handle_mod(void *); 211c19c7afeSEric Joyner static void ixgbe_handle_phy(void *); 212758cc3dcSJack F Vogel 2138eb6488eSEric Joyner /************************************************************************ 214758cc3dcSJack F Vogel * FreeBSD Device Interface Entry Points 2158eb6488eSEric Joyner ************************************************************************/ 216a1edda90SAdrian Chadd static device_method_t ix_methods[] = { 217758cc3dcSJack F Vogel /* Device interface */ 218c19c7afeSEric Joyner DEVMETHOD(device_register, ixgbe_register), 219c19c7afeSEric Joyner DEVMETHOD(device_probe, iflib_device_probe), 220c19c7afeSEric Joyner DEVMETHOD(device_attach, iflib_device_attach), 221c19c7afeSEric Joyner DEVMETHOD(device_detach, iflib_device_detach), 222c19c7afeSEric Joyner DEVMETHOD(device_shutdown, iflib_device_shutdown), 223c19c7afeSEric Joyner DEVMETHOD(device_suspend, iflib_device_suspend), 224c19c7afeSEric Joyner DEVMETHOD(device_resume, iflib_device_resume), 22548056c88SJack F Vogel #ifdef PCI_IOV 226c19c7afeSEric Joyner DEVMETHOD(pci_iov_init, iflib_device_iov_init), 227c19c7afeSEric Joyner DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit), 228c19c7afeSEric Joyner DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf), 22948056c88SJack F Vogel #endif /* PCI_IOV */ 230758cc3dcSJack F Vogel DEVMETHOD_END 231758cc3dcSJack F Vogel }; 232758cc3dcSJack F Vogel 233a1edda90SAdrian Chadd static driver_t ix_driver = { 234b1d5caf3SKevin Bowling "ix", ix_methods, sizeof(struct ixgbe_softc), 235758cc3dcSJack F Vogel }; 236758cc3dcSJack F Vogel 237964c2b3aSJohn Baldwin DRIVER_MODULE(ix, pci, ix_driver, 0, 0); 238937b0f25SYuri Pankov IFLIB_PNP_INFO(pci, ix_driver, ixgbe_vendor_info_array); 239a1edda90SAdrian Chadd MODULE_DEPEND(ix, pci, 1, 1, 1); 240a1edda90SAdrian Chadd MODULE_DEPEND(ix, ether, 1, 1, 1); 241c19c7afeSEric Joyner MODULE_DEPEND(ix, iflib, 1, 1, 1); 242c19c7afeSEric Joyner 243c19c7afeSEric Joyner static device_method_t ixgbe_if_methods[] = { 244c19c7afeSEric Joyner DEVMETHOD(ifdi_attach_pre, ixgbe_if_attach_pre), 245c19c7afeSEric Joyner DEVMETHOD(ifdi_attach_post, ixgbe_if_attach_post), 246c19c7afeSEric Joyner DEVMETHOD(ifdi_detach, ixgbe_if_detach), 247c19c7afeSEric Joyner DEVMETHOD(ifdi_shutdown, ixgbe_if_shutdown), 248c19c7afeSEric Joyner DEVMETHOD(ifdi_suspend, ixgbe_if_suspend), 249c19c7afeSEric Joyner DEVMETHOD(ifdi_resume, ixgbe_if_resume), 250c19c7afeSEric Joyner DEVMETHOD(ifdi_init, ixgbe_if_init), 251c19c7afeSEric Joyner DEVMETHOD(ifdi_stop, ixgbe_if_stop), 252c19c7afeSEric Joyner DEVMETHOD(ifdi_msix_intr_assign, ixgbe_if_msix_intr_assign), 253c19c7afeSEric Joyner DEVMETHOD(ifdi_intr_enable, ixgbe_if_enable_intr), 254c19c7afeSEric Joyner DEVMETHOD(ifdi_intr_disable, ixgbe_if_disable_intr), 255b2c1e8e6SEric Joyner DEVMETHOD(ifdi_link_intr_enable, ixgbe_link_intr_enable), 256c19c7afeSEric Joyner DEVMETHOD(ifdi_tx_queue_intr_enable, ixgbe_if_rx_queue_intr_enable), 257c19c7afeSEric Joyner DEVMETHOD(ifdi_rx_queue_intr_enable, ixgbe_if_rx_queue_intr_enable), 258c19c7afeSEric Joyner DEVMETHOD(ifdi_tx_queues_alloc, ixgbe_if_tx_queues_alloc), 259c19c7afeSEric Joyner DEVMETHOD(ifdi_rx_queues_alloc, ixgbe_if_rx_queues_alloc), 260c19c7afeSEric Joyner DEVMETHOD(ifdi_queues_free, ixgbe_if_queues_free), 261c19c7afeSEric Joyner DEVMETHOD(ifdi_update_admin_status, ixgbe_if_update_admin_status), 262c19c7afeSEric Joyner DEVMETHOD(ifdi_multi_set, ixgbe_if_multi_set), 263c19c7afeSEric Joyner DEVMETHOD(ifdi_mtu_set, ixgbe_if_mtu_set), 264c19c7afeSEric Joyner DEVMETHOD(ifdi_crcstrip_set, ixgbe_if_crcstrip_set), 265c19c7afeSEric Joyner DEVMETHOD(ifdi_media_status, ixgbe_if_media_status), 266c19c7afeSEric Joyner DEVMETHOD(ifdi_media_change, ixgbe_if_media_change), 267c19c7afeSEric Joyner DEVMETHOD(ifdi_promisc_set, ixgbe_if_promisc_set), 268c19c7afeSEric Joyner DEVMETHOD(ifdi_timer, ixgbe_if_timer), 269c19c7afeSEric Joyner DEVMETHOD(ifdi_vlan_register, ixgbe_if_vlan_register), 270c19c7afeSEric Joyner DEVMETHOD(ifdi_vlan_unregister, ixgbe_if_vlan_unregister), 271c19c7afeSEric Joyner DEVMETHOD(ifdi_get_counter, ixgbe_if_get_counter), 272bca38080SAndrew Gallatin DEVMETHOD(ifdi_i2c_req, ixgbe_if_i2c_req), 273cf150917SEric Joyner DEVMETHOD(ifdi_needs_restart, ixgbe_if_needs_restart), 274c19c7afeSEric Joyner #ifdef PCI_IOV 275c19c7afeSEric Joyner DEVMETHOD(ifdi_iov_init, ixgbe_if_iov_init), 276c19c7afeSEric Joyner DEVMETHOD(ifdi_iov_uninit, ixgbe_if_iov_uninit), 277c19c7afeSEric Joyner DEVMETHOD(ifdi_iov_vf_add, ixgbe_if_iov_vf_add), 278c19c7afeSEric Joyner #endif /* PCI_IOV */ 279c19c7afeSEric Joyner DEVMETHOD_END 280c19c7afeSEric Joyner }; 281758cc3dcSJack F Vogel 282758cc3dcSJack F Vogel /* 2838eb6488eSEric Joyner * TUNEABLE PARAMETERS: 284758cc3dcSJack F Vogel */ 285758cc3dcSJack F Vogel 28620b91f0aSPawel Biernacki static SYSCTL_NODE(_hw, OID_AUTO, ix, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 28720b91f0aSPawel Biernacki "IXGBE driver parameters"); 288c19c7afeSEric Joyner static driver_t ixgbe_if_driver = { 289b1d5caf3SKevin Bowling "ixgbe_if", ixgbe_if_methods, sizeof(struct ixgbe_softc) 290c19c7afeSEric Joyner }; 291758cc3dcSJack F Vogel 292758cc3dcSJack F Vogel static int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY); 293758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN, 294758cc3dcSJack F Vogel &ixgbe_max_interrupt_rate, 0, "Maximum interrupts per second"); 295758cc3dcSJack F Vogel 296f2c4db54SSteven Hartland /* Flow control setting, default to full */ 297f2c4db54SSteven Hartland static int ixgbe_flow_control = ixgbe_fc_full; 298f2c4db54SSteven Hartland SYSCTL_INT(_hw_ix, OID_AUTO, flow_control, CTLFLAG_RDTUN, 299f2c4db54SSteven Hartland &ixgbe_flow_control, 0, "Default flow control used for all adapters"); 300f2c4db54SSteven Hartland 301f2c4db54SSteven Hartland /* Advertise Speed, default to 0 (auto) */ 302f2c4db54SSteven Hartland static int ixgbe_advertise_speed = 0; 303f2c4db54SSteven Hartland SYSCTL_INT(_hw_ix, OID_AUTO, advertise_speed, CTLFLAG_RDTUN, 304f2c4db54SSteven Hartland &ixgbe_advertise_speed, 0, "Default advertised speed for all adapters"); 305f2c4db54SSteven Hartland 306758cc3dcSJack F Vogel /* 3078eb6488eSEric Joyner * Smart speed setting, default to on 3088eb6488eSEric Joyner * this only works as a compile option 3098eb6488eSEric Joyner * right now as its during attach, set 3108eb6488eSEric Joyner * this to 'ixgbe_smart_speed_off' to 3118eb6488eSEric Joyner * disable. 312758cc3dcSJack F Vogel */ 313758cc3dcSJack F Vogel static int ixgbe_smart_speed = ixgbe_smart_speed_on; 314758cc3dcSJack F Vogel 315758cc3dcSJack F Vogel /* 3168eb6488eSEric Joyner * MSI-X should be the default for best performance, 317758cc3dcSJack F Vogel * but this allows it to be forced off for testing. 318758cc3dcSJack F Vogel */ 319758cc3dcSJack F Vogel static int ixgbe_enable_msix = 1; 320758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixgbe_enable_msix, 0, 321758cc3dcSJack F Vogel "Enable MSI-X interrupts"); 322758cc3dcSJack F Vogel 323758cc3dcSJack F Vogel /* 3248eb6488eSEric Joyner * Defining this on will allow the use 3258eb6488eSEric Joyner * of unsupported SFP+ modules, note that 3268eb6488eSEric Joyner * doing so you are on your own :) 327758cc3dcSJack F Vogel */ 32879b36ec9SKevin Bowling static int allow_unsupported_sfp = false; 329fb6aa95dSSean Bruno SYSCTL_INT(_hw_ix, OID_AUTO, unsupported_sfp, CTLFLAG_RDTUN, 3308eb6488eSEric Joyner &allow_unsupported_sfp, 0, 3318eb6488eSEric Joyner "Allow unsupported SFP modules...use at your own risk"); 3328eb6488eSEric Joyner 3338eb6488eSEric Joyner /* 3348eb6488eSEric Joyner * Not sure if Flow Director is fully baked, 3358eb6488eSEric Joyner * so we'll default to turning it off. 3368eb6488eSEric Joyner */ 3378eb6488eSEric Joyner static int ixgbe_enable_fdir = 0; 3388eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_fdir, CTLFLAG_RDTUN, &ixgbe_enable_fdir, 0, 3398eb6488eSEric Joyner "Enable Flow Director"); 3408eb6488eSEric Joyner 3418eb6488eSEric Joyner /* Receive-Side Scaling */ 3428eb6488eSEric Joyner static int ixgbe_enable_rss = 1; 3438eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_rss, CTLFLAG_RDTUN, &ixgbe_enable_rss, 0, 3448eb6488eSEric Joyner "Enable Receive-Side Scaling (RSS)"); 345758cc3dcSJack F Vogel 34664881da4SSai Rajesh Tallamraju /* 34764881da4SSai Rajesh Tallamraju * AIM: Adaptive Interrupt Moderation 34864881da4SSai Rajesh Tallamraju * which means that the interrupt rate 34964881da4SSai Rajesh Tallamraju * is varied over time based on the 35064881da4SSai Rajesh Tallamraju * traffic for that interrupt vector 35164881da4SSai Rajesh Tallamraju */ 35279b36ec9SKevin Bowling static int ixgbe_enable_aim = false; 35364881da4SSai Rajesh Tallamraju SYSCTL_INT(_hw_ix, OID_AUTO, enable_aim, CTLFLAG_RWTUN, &ixgbe_enable_aim, 0, 35464881da4SSai Rajesh Tallamraju "Enable adaptive interrupt moderation"); 35564881da4SSai Rajesh Tallamraju 356c19c7afeSEric Joyner #if 0 357758cc3dcSJack F Vogel /* Keep running tab on them for sanity check */ 358758cc3dcSJack F Vogel static int ixgbe_total_ports; 359c19c7afeSEric Joyner #endif 360758cc3dcSJack F Vogel 3618eb6488eSEric Joyner MALLOC_DEFINE(M_IXGBE, "ix", "ix driver allocations"); 362758cc3dcSJack F Vogel 363c19c7afeSEric Joyner /* 364c19c7afeSEric Joyner * For Flow Director: this is the number of TX packets we sample 365c19c7afeSEric Joyner * for the filter pool, this means every 20th packet will be probed. 366c19c7afeSEric Joyner * 367c19c7afeSEric Joyner * This feature can be disabled by setting this to 0. 368c19c7afeSEric Joyner */ 369c19c7afeSEric Joyner static int atr_sample_rate = 20; 370c19c7afeSEric Joyner 371c19c7afeSEric Joyner extern struct if_txrx ixgbe_txrx; 372c19c7afeSEric Joyner 373c19c7afeSEric Joyner static struct if_shared_ctx ixgbe_sctx_init = { 374c19c7afeSEric Joyner .isc_magic = IFLIB_MAGIC, 375c19c7afeSEric Joyner .isc_q_align = PAGE_SIZE,/* max(DBA_ALIGN, PAGE_SIZE) */ 3767f87c040SMarius Strobl .isc_tx_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header), 377c19c7afeSEric Joyner .isc_tx_maxsegsize = PAGE_SIZE, 3787f87c040SMarius Strobl .isc_tso_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header), 3797f87c040SMarius Strobl .isc_tso_maxsegsize = PAGE_SIZE, 380c19c7afeSEric Joyner .isc_rx_maxsize = PAGE_SIZE*4, 381c19c7afeSEric Joyner .isc_rx_nsegments = 1, 382c19c7afeSEric Joyner .isc_rx_maxsegsize = PAGE_SIZE*4, 383c19c7afeSEric Joyner .isc_nfl = 1, 384c19c7afeSEric Joyner .isc_ntxqs = 1, 385c19c7afeSEric Joyner .isc_nrxqs = 1, 386c19c7afeSEric Joyner 387c19c7afeSEric Joyner .isc_admin_intrcnt = 1, 388c19c7afeSEric Joyner .isc_vendor_info = ixgbe_vendor_info_array, 389c19c7afeSEric Joyner .isc_driver_version = ixgbe_driver_version, 390c19c7afeSEric Joyner .isc_driver = &ixgbe_if_driver, 3917aad1f4eSEric Joyner .isc_flags = IFLIB_TSO_INIT_IP, 392c19c7afeSEric Joyner 393c19c7afeSEric Joyner .isc_nrxd_min = {MIN_RXD}, 394c19c7afeSEric Joyner .isc_ntxd_min = {MIN_TXD}, 395c19c7afeSEric Joyner .isc_nrxd_max = {MAX_RXD}, 396c19c7afeSEric Joyner .isc_ntxd_max = {MAX_TXD}, 397c19c7afeSEric Joyner .isc_nrxd_default = {DEFAULT_RXD}, 398c19c7afeSEric Joyner .isc_ntxd_default = {DEFAULT_TXD}, 399c19c7afeSEric Joyner }; 400c19c7afeSEric Joyner 401c19c7afeSEric Joyner /************************************************************************ 402c19c7afeSEric Joyner * ixgbe_if_tx_queues_alloc 403c19c7afeSEric Joyner ************************************************************************/ 404c19c7afeSEric Joyner static int 405c19c7afeSEric Joyner ixgbe_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, 406c19c7afeSEric Joyner int ntxqs, int ntxqsets) 407c19c7afeSEric Joyner { 408b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 409b1d5caf3SKevin Bowling if_softc_ctx_t scctx = sc->shared; 410c19c7afeSEric Joyner struct ix_tx_queue *que; 411c19c7afeSEric Joyner int i, j, error; 412c19c7afeSEric Joyner 413b1d5caf3SKevin Bowling MPASS(sc->num_tx_queues > 0); 414b1d5caf3SKevin Bowling MPASS(sc->num_tx_queues == ntxqsets); 415c19c7afeSEric Joyner MPASS(ntxqs == 1); 416c19c7afeSEric Joyner 417c19c7afeSEric Joyner /* Allocate queue structure memory */ 418b1d5caf3SKevin Bowling sc->tx_queues = 419c19c7afeSEric Joyner (struct ix_tx_queue *)malloc(sizeof(struct ix_tx_queue) * ntxqsets, 420c19c7afeSEric Joyner M_IXGBE, M_NOWAIT | M_ZERO); 421b1d5caf3SKevin Bowling if (!sc->tx_queues) { 422c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), 423c19c7afeSEric Joyner "Unable to allocate TX ring memory\n"); 424c19c7afeSEric Joyner return (ENOMEM); 425c19c7afeSEric Joyner } 426c19c7afeSEric Joyner 427b1d5caf3SKevin Bowling for (i = 0, que = sc->tx_queues; i < ntxqsets; i++, que++) { 428c19c7afeSEric Joyner struct tx_ring *txr = &que->txr; 429c19c7afeSEric Joyner 430c19c7afeSEric Joyner /* In case SR-IOV is enabled, align the index properly */ 431b1d5caf3SKevin Bowling txr->me = ixgbe_vf_que_index(sc->iov_mode, sc->pool, 432c19c7afeSEric Joyner i); 433c19c7afeSEric Joyner 434b1d5caf3SKevin Bowling txr->sc = que->sc = sc; 435c19c7afeSEric Joyner 436c19c7afeSEric Joyner /* Allocate report status array */ 437c19c7afeSEric Joyner txr->tx_rsq = (qidx_t *)malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_IXGBE, M_NOWAIT | M_ZERO); 438c19c7afeSEric Joyner if (txr->tx_rsq == NULL) { 439c19c7afeSEric Joyner error = ENOMEM; 440c19c7afeSEric Joyner goto fail; 441c19c7afeSEric Joyner } 442c19c7afeSEric Joyner for (j = 0; j < scctx->isc_ntxd[0]; j++) 443c19c7afeSEric Joyner txr->tx_rsq[j] = QIDX_INVALID; 444c19c7afeSEric Joyner /* get the virtual and physical address of the hardware queues */ 445c19c7afeSEric Joyner txr->tail = IXGBE_TDT(txr->me); 446c19c7afeSEric Joyner txr->tx_base = (union ixgbe_adv_tx_desc *)vaddrs[i]; 447c19c7afeSEric Joyner txr->tx_paddr = paddrs[i]; 448c19c7afeSEric Joyner 449c19c7afeSEric Joyner txr->bytes = 0; 450c19c7afeSEric Joyner txr->total_packets = 0; 451c19c7afeSEric Joyner 452c19c7afeSEric Joyner /* Set the rate at which we sample packets */ 453b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_FDIR) 454c19c7afeSEric Joyner txr->atr_sample = atr_sample_rate; 455c19c7afeSEric Joyner 456c19c7afeSEric Joyner } 457c19c7afeSEric Joyner 458c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), "allocated for %d queues\n", 459b1d5caf3SKevin Bowling sc->num_tx_queues); 460c19c7afeSEric Joyner 461c19c7afeSEric Joyner return (0); 462c19c7afeSEric Joyner 463c19c7afeSEric Joyner fail: 464c19c7afeSEric Joyner ixgbe_if_queues_free(ctx); 465c19c7afeSEric Joyner 466c19c7afeSEric Joyner return (error); 467c19c7afeSEric Joyner } /* ixgbe_if_tx_queues_alloc */ 468c19c7afeSEric Joyner 469c19c7afeSEric Joyner /************************************************************************ 470c19c7afeSEric Joyner * ixgbe_if_rx_queues_alloc 471c19c7afeSEric Joyner ************************************************************************/ 472c19c7afeSEric Joyner static int 473c19c7afeSEric Joyner ixgbe_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, 474c19c7afeSEric Joyner int nrxqs, int nrxqsets) 475c19c7afeSEric Joyner { 476b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 477c19c7afeSEric Joyner struct ix_rx_queue *que; 478c19c7afeSEric Joyner int i; 479c19c7afeSEric Joyner 480b1d5caf3SKevin Bowling MPASS(sc->num_rx_queues > 0); 481b1d5caf3SKevin Bowling MPASS(sc->num_rx_queues == nrxqsets); 482c19c7afeSEric Joyner MPASS(nrxqs == 1); 483c19c7afeSEric Joyner 484c19c7afeSEric Joyner /* Allocate queue structure memory */ 485b1d5caf3SKevin Bowling sc->rx_queues = 486c19c7afeSEric Joyner (struct ix_rx_queue *)malloc(sizeof(struct ix_rx_queue)*nrxqsets, 487c19c7afeSEric Joyner M_IXGBE, M_NOWAIT | M_ZERO); 488b1d5caf3SKevin Bowling if (!sc->rx_queues) { 489c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), 490c19c7afeSEric Joyner "Unable to allocate TX ring memory\n"); 491c19c7afeSEric Joyner return (ENOMEM); 492c19c7afeSEric Joyner } 493c19c7afeSEric Joyner 494b1d5caf3SKevin Bowling for (i = 0, que = sc->rx_queues; i < nrxqsets; i++, que++) { 495c19c7afeSEric Joyner struct rx_ring *rxr = &que->rxr; 496c19c7afeSEric Joyner 497c19c7afeSEric Joyner /* In case SR-IOV is enabled, align the index properly */ 498b1d5caf3SKevin Bowling rxr->me = ixgbe_vf_que_index(sc->iov_mode, sc->pool, 499c19c7afeSEric Joyner i); 500c19c7afeSEric Joyner 501b1d5caf3SKevin Bowling rxr->sc = que->sc = sc; 502c19c7afeSEric Joyner 503c19c7afeSEric Joyner /* get the virtual and physical address of the hw queues */ 504c19c7afeSEric Joyner rxr->tail = IXGBE_RDT(rxr->me); 505c19c7afeSEric Joyner rxr->rx_base = (union ixgbe_adv_rx_desc *)vaddrs[i]; 506c19c7afeSEric Joyner rxr->rx_paddr = paddrs[i]; 507c19c7afeSEric Joyner rxr->bytes = 0; 508c19c7afeSEric Joyner rxr->que = que; 509c19c7afeSEric Joyner } 510c19c7afeSEric Joyner 511c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), "allocated for %d rx queues\n", 512b1d5caf3SKevin Bowling sc->num_rx_queues); 513c19c7afeSEric Joyner 514c19c7afeSEric Joyner return (0); 515c19c7afeSEric Joyner } /* ixgbe_if_rx_queues_alloc */ 516c19c7afeSEric Joyner 517c19c7afeSEric Joyner /************************************************************************ 518c19c7afeSEric Joyner * ixgbe_if_queues_free 519c19c7afeSEric Joyner ************************************************************************/ 520c19c7afeSEric Joyner static void 521c19c7afeSEric Joyner ixgbe_if_queues_free(if_ctx_t ctx) 522c19c7afeSEric Joyner { 523b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 524b1d5caf3SKevin Bowling struct ix_tx_queue *tx_que = sc->tx_queues; 525b1d5caf3SKevin Bowling struct ix_rx_queue *rx_que = sc->rx_queues; 526c19c7afeSEric Joyner int i; 527c19c7afeSEric Joyner 528c19c7afeSEric Joyner if (tx_que != NULL) { 529b1d5caf3SKevin Bowling for (i = 0; i < sc->num_tx_queues; i++, tx_que++) { 530c19c7afeSEric Joyner struct tx_ring *txr = &tx_que->txr; 531c19c7afeSEric Joyner if (txr->tx_rsq == NULL) 532c19c7afeSEric Joyner break; 533c19c7afeSEric Joyner 534c19c7afeSEric Joyner free(txr->tx_rsq, M_IXGBE); 535c19c7afeSEric Joyner txr->tx_rsq = NULL; 536c19c7afeSEric Joyner } 537c19c7afeSEric Joyner 538b1d5caf3SKevin Bowling free(sc->tx_queues, M_IXGBE); 539b1d5caf3SKevin Bowling sc->tx_queues = NULL; 540c19c7afeSEric Joyner } 541c19c7afeSEric Joyner if (rx_que != NULL) { 542b1d5caf3SKevin Bowling free(sc->rx_queues, M_IXGBE); 543b1d5caf3SKevin Bowling sc->rx_queues = NULL; 544c19c7afeSEric Joyner } 545c19c7afeSEric Joyner } /* ixgbe_if_queues_free */ 546c19c7afeSEric Joyner 5478eb6488eSEric Joyner /************************************************************************ 5488eb6488eSEric Joyner * ixgbe_initialize_rss_mapping 5498eb6488eSEric Joyner ************************************************************************/ 5508eb6488eSEric Joyner static void 551b1d5caf3SKevin Bowling ixgbe_initialize_rss_mapping(struct ixgbe_softc *sc) 552758cc3dcSJack F Vogel { 553b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 5548eb6488eSEric Joyner u32 reta = 0, mrqc, rss_key[10]; 5558eb6488eSEric Joyner int queue_id, table_size, index_mult; 5568eb6488eSEric Joyner int i, j; 5578eb6488eSEric Joyner u32 rss_hash_config; 5586f37f232SEric Joyner 559b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_RSS) { 5608eb6488eSEric Joyner /* Fetch the configured RSS key */ 5618eb6488eSEric Joyner rss_getkey((uint8_t *)&rss_key); 562758cc3dcSJack F Vogel } else { 5638eb6488eSEric Joyner /* set up random bits */ 5648eb6488eSEric Joyner arc4rand(&rss_key, sizeof(rss_key), 0); 565758cc3dcSJack F Vogel } 566758cc3dcSJack F Vogel 5678eb6488eSEric Joyner /* Set multiplier for RETA setup and table size based on MAC */ 5688eb6488eSEric Joyner index_mult = 0x1; 5698eb6488eSEric Joyner table_size = 128; 570b1d5caf3SKevin Bowling switch (sc->hw.mac.type) { 5718eb6488eSEric Joyner case ixgbe_mac_82598EB: 5728eb6488eSEric Joyner index_mult = 0x11; 573758cc3dcSJack F Vogel break; 5748eb6488eSEric Joyner case ixgbe_mac_X550: 5758eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 5768eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 5778eb6488eSEric Joyner table_size = 512; 5788eb6488eSEric Joyner break; 579758cc3dcSJack F Vogel default: 580758cc3dcSJack F Vogel break; 581758cc3dcSJack F Vogel } 582758cc3dcSJack F Vogel 5838eb6488eSEric Joyner /* Set up the redirection table */ 5848eb6488eSEric Joyner for (i = 0, j = 0; i < table_size; i++, j++) { 585b1d5caf3SKevin Bowling if (j == sc->num_rx_queues) 5868eb6488eSEric Joyner j = 0; 587758cc3dcSJack F Vogel 588b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_RSS) { 589a9ca1c79SSean Bruno /* 5908eb6488eSEric Joyner * Fetch the RSS bucket id for the given indirection 5918eb6488eSEric Joyner * entry. Cap it at the number of configured buckets 592c19c7afeSEric Joyner * (which is num_rx_queues.) 593a9ca1c79SSean Bruno */ 5948eb6488eSEric Joyner queue_id = rss_get_indirection_to_bucket(i); 595b1d5caf3SKevin Bowling queue_id = queue_id % sc->num_rx_queues; 596758cc3dcSJack F Vogel } else 5978eb6488eSEric Joyner queue_id = (j * index_mult); 5988eb6488eSEric Joyner 5998eb6488eSEric Joyner /* 6008eb6488eSEric Joyner * The low 8 bits are for hash value (n+0); 6018eb6488eSEric Joyner * The next 8 bits are for hash value (n+1), etc. 6028eb6488eSEric Joyner */ 6038eb6488eSEric Joyner reta = reta >> 8; 6048eb6488eSEric Joyner reta = reta | (((uint32_t)queue_id) << 24); 6058eb6488eSEric Joyner if ((i & 3) == 3) { 6068eb6488eSEric Joyner if (i < 128) 6078eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta); 6088eb6488eSEric Joyner else 6098eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32), 6108eb6488eSEric Joyner reta); 6118eb6488eSEric Joyner reta = 0; 6128eb6488eSEric Joyner } 613758cc3dcSJack F Vogel } 614758cc3dcSJack F Vogel 6158eb6488eSEric Joyner /* Now fill our hash function seeds */ 6168eb6488eSEric Joyner for (i = 0; i < 10; i++) 6178eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]); 618758cc3dcSJack F Vogel 6198eb6488eSEric Joyner /* Perform hash on these packet types */ 620b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_RSS) 6218eb6488eSEric Joyner rss_hash_config = rss_gethashconfig(); 622758cc3dcSJack F Vogel else { 623758cc3dcSJack F Vogel /* 6248eb6488eSEric Joyner * Disable UDP - IP fragments aren't currently being handled 6258eb6488eSEric Joyner * and so we end up with a mix of 2-tuple and 4-tuple 6268eb6488eSEric Joyner * traffic. 627758cc3dcSJack F Vogel */ 6288eb6488eSEric Joyner rss_hash_config = RSS_HASHTYPE_RSS_IPV4 6298eb6488eSEric Joyner | RSS_HASHTYPE_RSS_TCP_IPV4 6308eb6488eSEric Joyner | RSS_HASHTYPE_RSS_IPV6 6318eb6488eSEric Joyner | RSS_HASHTYPE_RSS_TCP_IPV6 6328eb6488eSEric Joyner | RSS_HASHTYPE_RSS_IPV6_EX 6338eb6488eSEric Joyner | RSS_HASHTYPE_RSS_TCP_IPV6_EX; 634758cc3dcSJack F Vogel } 635758cc3dcSJack F Vogel 6368eb6488eSEric Joyner mrqc = IXGBE_MRQC_RSSEN; 6378eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4) 6388eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4; 6398eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4) 6408eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP; 6418eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6) 6428eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6; 6438eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6) 6448eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP; 6458eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX) 6468eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX; 6478eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX) 6488eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP; 6498eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4) 6508eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; 6518eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6) 6528eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; 6538eb6488eSEric Joyner if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX) 6548eb6488eSEric Joyner mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP; 655b1d5caf3SKevin Bowling mrqc |= ixgbe_get_mrqc(sc->iov_mode); 6568eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); 6578eb6488eSEric Joyner } /* ixgbe_initialize_rss_mapping */ 658758cc3dcSJack F Vogel 6598eb6488eSEric Joyner /************************************************************************ 6608eb6488eSEric Joyner * ixgbe_initialize_receive_units - Setup receive registers and features. 6618eb6488eSEric Joyner ************************************************************************/ 6628eb6488eSEric Joyner #define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1) 663758cc3dcSJack F Vogel 664758cc3dcSJack F Vogel static void 665c19c7afeSEric Joyner ixgbe_initialize_receive_units(if_ctx_t ctx) 666758cc3dcSJack F Vogel { 667b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 668b1d5caf3SKevin Bowling if_softc_ctx_t scctx = sc->shared; 669b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 670ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 671c19c7afeSEric Joyner struct ix_rx_queue *que; 6728eb6488eSEric Joyner int i, j; 6738eb6488eSEric Joyner u32 bufsz, fctrl, srrctl, rxcsum; 6748eb6488eSEric Joyner u32 hlreg; 67548056c88SJack F Vogel 67648056c88SJack F Vogel /* 6778eb6488eSEric Joyner * Make sure receives are disabled while 6788eb6488eSEric Joyner * setting up the descriptor ring 67948056c88SJack F Vogel */ 6808eb6488eSEric Joyner ixgbe_disable_rx(hw); 6818eb6488eSEric Joyner 6828eb6488eSEric Joyner /* Enable broadcasts */ 6838eb6488eSEric Joyner fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 6848eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_BAM; 685b1d5caf3SKevin Bowling if (sc->hw.mac.type == ixgbe_mac_82598EB) { 6868eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_DPF; 6878eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_PMCF; 68848056c88SJack F Vogel } 6898eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 6908eb6488eSEric Joyner 6918eb6488eSEric Joyner /* Set for Jumbo Frames? */ 6928eb6488eSEric Joyner hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0); 693ff06a8dbSJustin Hibbits if (if_getmtu(ifp) > ETHERMTU) 6948eb6488eSEric Joyner hlreg |= IXGBE_HLREG0_JUMBOEN; 6958eb6488eSEric Joyner else 6968eb6488eSEric Joyner hlreg &= ~IXGBE_HLREG0_JUMBOEN; 6978eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg); 6988eb6488eSEric Joyner 699b1d5caf3SKevin Bowling bufsz = (sc->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >> 7008eb6488eSEric Joyner IXGBE_SRRCTL_BSIZEPKT_SHIFT; 7018eb6488eSEric Joyner 702c19c7afeSEric Joyner /* Setup the Base and Length of the Rx Descriptor Ring */ 703b1d5caf3SKevin Bowling for (i = 0, que = sc->rx_queues; i < sc->num_rx_queues; i++, que++) { 704c19c7afeSEric Joyner struct rx_ring *rxr = &que->rxr; 705c19c7afeSEric Joyner u64 rdba = rxr->rx_paddr; 706c19c7afeSEric Joyner 7078eb6488eSEric Joyner j = rxr->me; 7088eb6488eSEric Joyner 7098eb6488eSEric Joyner /* Setup the Base and Length of the Rx Descriptor Ring */ 7108eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), 7118eb6488eSEric Joyner (rdba & 0x00000000ffffffffULL)); 7128eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32)); 7138eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j), 714c19c7afeSEric Joyner scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc)); 7158eb6488eSEric Joyner 7168eb6488eSEric Joyner /* Set up the SRRCTL register */ 7178eb6488eSEric Joyner srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(j)); 7188eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK; 7198eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK; 7208eb6488eSEric Joyner srrctl |= bufsz; 7218eb6488eSEric Joyner srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; 72248056c88SJack F Vogel 72348056c88SJack F Vogel /* 7248eb6488eSEric Joyner * Set DROP_EN iff we have no flow control and >1 queue. 7258eb6488eSEric Joyner * Note that srrctl was cleared shortly before during reset, 7268eb6488eSEric Joyner * so we do not need to clear the bit, but do it just in case 7278eb6488eSEric Joyner * this code is moved elsewhere. 72848056c88SJack F Vogel */ 729b1d5caf3SKevin Bowling if (sc->num_rx_queues > 1 && 730b1d5caf3SKevin Bowling sc->hw.fc.requested_mode == ixgbe_fc_none) { 7318eb6488eSEric Joyner srrctl |= IXGBE_SRRCTL_DROP_EN; 732758cc3dcSJack F Vogel } else { 7338eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_DROP_EN; 734758cc3dcSJack F Vogel } 735758cc3dcSJack F Vogel 7368eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl); 737758cc3dcSJack F Vogel 7388eb6488eSEric Joyner /* Setup the HW Rx Head and Tail Descriptor Pointers */ 7398eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0); 7408eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0); 741758cc3dcSJack F Vogel 7428eb6488eSEric Joyner /* Set the driver rx tail address */ 7438eb6488eSEric Joyner rxr->tail = IXGBE_RDT(rxr->me); 744a9ca1c79SSean Bruno } 745758cc3dcSJack F Vogel 746b1d5caf3SKevin Bowling if (sc->hw.mac.type != ixgbe_mac_82598EB) { 7478eb6488eSEric Joyner u32 psrtype = IXGBE_PSRTYPE_TCPHDR 7488eb6488eSEric Joyner | IXGBE_PSRTYPE_UDPHDR 7498eb6488eSEric Joyner | IXGBE_PSRTYPE_IPV4HDR 7508eb6488eSEric Joyner | IXGBE_PSRTYPE_IPV6HDR; 7518eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype); 7526f37f232SEric Joyner } 7536f37f232SEric Joyner 7548eb6488eSEric Joyner rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); 7558eb6488eSEric Joyner 756b1d5caf3SKevin Bowling ixgbe_initialize_rss_mapping(sc); 7578eb6488eSEric Joyner 758156424fcSPrzemyslaw Lewandowski if (sc->feat_en & IXGBE_FEATURE_RSS) { 7598eb6488eSEric Joyner /* RSS and RX IPP Checksum are mutually exclusive */ 7608eb6488eSEric Joyner rxcsum |= IXGBE_RXCSUM_PCSD; 7616f37f232SEric Joyner } 7626f37f232SEric Joyner 763ff06a8dbSJustin Hibbits if (if_getcapenable(ifp) & IFCAP_RXCSUM) 7648eb6488eSEric Joyner rxcsum |= IXGBE_RXCSUM_PCSD; 765758cc3dcSJack F Vogel 7668eb6488eSEric Joyner /* This is useful for calculating UDP/IP fragment checksums */ 7678eb6488eSEric Joyner if (!(rxcsum & IXGBE_RXCSUM_PCSD)) 7688eb6488eSEric Joyner rxcsum |= IXGBE_RXCSUM_IPPCSE; 769758cc3dcSJack F Vogel 7708eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum); 771758cc3dcSJack F Vogel 7728eb6488eSEric Joyner } /* ixgbe_initialize_receive_units */ 773758cc3dcSJack F Vogel 7748eb6488eSEric Joyner /************************************************************************ 7758eb6488eSEric Joyner * ixgbe_initialize_transmit_units - Enable transmit units. 7768eb6488eSEric Joyner ************************************************************************/ 777758cc3dcSJack F Vogel static void 778c19c7afeSEric Joyner ixgbe_initialize_transmit_units(if_ctx_t ctx) 779758cc3dcSJack F Vogel { 780b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 781b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 782b1d5caf3SKevin Bowling if_softc_ctx_t scctx = sc->shared; 783c19c7afeSEric Joyner struct ix_tx_queue *que; 784c19c7afeSEric Joyner int i; 785758cc3dcSJack F Vogel 786758cc3dcSJack F Vogel /* Setup the Base and Length of the Tx Descriptor Ring */ 787b1d5caf3SKevin Bowling for (i = 0, que = sc->tx_queues; i < sc->num_tx_queues; 788c19c7afeSEric Joyner i++, que++) { 789c19c7afeSEric Joyner struct tx_ring *txr = &que->txr; 790c19c7afeSEric Joyner u64 tdba = txr->tx_paddr; 791758cc3dcSJack F Vogel u32 txctrl = 0; 79248056c88SJack F Vogel int j = txr->me; 793758cc3dcSJack F Vogel 79448056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j), 795758cc3dcSJack F Vogel (tdba & 0x00000000ffffffffULL)); 79648056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32)); 79748056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), 798c19c7afeSEric Joyner scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc)); 799758cc3dcSJack F Vogel 800758cc3dcSJack F Vogel /* Setup the HW Tx Head and Tail descriptor pointers */ 80148056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0); 80248056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0); 803758cc3dcSJack F Vogel 804758cc3dcSJack F Vogel /* Cache the tail address */ 8052dc2d580SEric Joyner txr->tail = IXGBE_TDT(txr->me); 8062dc2d580SEric Joyner 807088a0b27SEric Joyner txr->tx_rs_cidx = txr->tx_rs_pidx; 808088a0b27SEric Joyner txr->tx_cidx_processed = scctx->isc_ntxd[0] - 1; 809c19c7afeSEric Joyner for (int k = 0; k < scctx->isc_ntxd[0]; k++) 810c19c7afeSEric Joyner txr->tx_rsq[k] = QIDX_INVALID; 811758cc3dcSJack F Vogel 812758cc3dcSJack F Vogel /* Disable Head Writeback */ 813a9ca1c79SSean Bruno /* 814a9ca1c79SSean Bruno * Note: for X550 series devices, these registers are actually 815a9ca1c79SSean Bruno * prefixed with TPH_ isntead of DCA_, but the addresses and 816a9ca1c79SSean Bruno * fields remain the same. 817a9ca1c79SSean Bruno */ 818758cc3dcSJack F Vogel switch (hw->mac.type) { 819758cc3dcSJack F Vogel case ixgbe_mac_82598EB: 82048056c88SJack F Vogel txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j)); 821758cc3dcSJack F Vogel break; 822758cc3dcSJack F Vogel default: 82348056c88SJack F Vogel txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j)); 824758cc3dcSJack F Vogel break; 825758cc3dcSJack F Vogel } 826758cc3dcSJack F Vogel txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; 827758cc3dcSJack F Vogel switch (hw->mac.type) { 828758cc3dcSJack F Vogel case ixgbe_mac_82598EB: 82948056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl); 830758cc3dcSJack F Vogel break; 831758cc3dcSJack F Vogel default: 83248056c88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl); 833758cc3dcSJack F Vogel break; 834758cc3dcSJack F Vogel } 835758cc3dcSJack F Vogel 836758cc3dcSJack F Vogel } 837758cc3dcSJack F Vogel 838758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 839758cc3dcSJack F Vogel u32 dmatxctl, rttdcs; 8408eb6488eSEric Joyner 841758cc3dcSJack F Vogel dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); 842758cc3dcSJack F Vogel dmatxctl |= IXGBE_DMATXCTL_TE; 843758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); 844758cc3dcSJack F Vogel /* Disable arbiter to set MTQC */ 845758cc3dcSJack F Vogel rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); 846758cc3dcSJack F Vogel rttdcs |= IXGBE_RTTDCS_ARBDIS; 847758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); 8488eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_MTQC, 849b1d5caf3SKevin Bowling ixgbe_get_mtqc(sc->iov_mode)); 850758cc3dcSJack F Vogel rttdcs &= ~IXGBE_RTTDCS_ARBDIS; 851758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); 852758cc3dcSJack F Vogel } 853758cc3dcSJack F Vogel 8548eb6488eSEric Joyner } /* ixgbe_initialize_transmit_units */ 855758cc3dcSJack F Vogel 8568eb6488eSEric Joyner /************************************************************************ 857c19c7afeSEric Joyner * ixgbe_register 858c19c7afeSEric Joyner ************************************************************************/ 859c19c7afeSEric Joyner static void * 860c19c7afeSEric Joyner ixgbe_register(device_t dev) 861c19c7afeSEric Joyner { 862ffe3def9SMark Johnston return (&ixgbe_sctx_init); 863c19c7afeSEric Joyner } /* ixgbe_register */ 864c19c7afeSEric Joyner 865c19c7afeSEric Joyner /************************************************************************ 866c19c7afeSEric Joyner * ixgbe_if_attach_pre - Device initialization routine, part 1 867758cc3dcSJack F Vogel * 8688eb6488eSEric Joyner * Called when the driver is being loaded. 869c19c7afeSEric Joyner * Identifies the type of hardware, initializes the hardware, 870c19c7afeSEric Joyner * and initializes iflib structures. 871758cc3dcSJack F Vogel * 8728eb6488eSEric Joyner * return 0 on success, positive on failure 8738eb6488eSEric Joyner ************************************************************************/ 8748eb6488eSEric Joyner static int 875c19c7afeSEric Joyner ixgbe_if_attach_pre(if_ctx_t ctx) 876758cc3dcSJack F Vogel { 877b1d5caf3SKevin Bowling struct ixgbe_softc *sc; 878c19c7afeSEric Joyner device_t dev; 879c19c7afeSEric Joyner if_softc_ctx_t scctx; 8808eb6488eSEric Joyner struct ixgbe_hw *hw; 8818eb6488eSEric Joyner int error = 0; 8828eb6488eSEric Joyner u32 ctrl_ext; 8837234c309SJakub Chylkowski size_t i; 8848eb6488eSEric Joyner 8858eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_attach: begin"); 8868eb6488eSEric Joyner 8878eb6488eSEric Joyner /* Allocate, clear, and link in our adapter structure */ 888c19c7afeSEric Joyner dev = iflib_get_dev(ctx); 889b1d5caf3SKevin Bowling sc = iflib_get_softc(ctx); 890b1d5caf3SKevin Bowling sc->hw.back = sc; 891b1d5caf3SKevin Bowling sc->ctx = ctx; 892b1d5caf3SKevin Bowling sc->dev = dev; 893b1d5caf3SKevin Bowling scctx = sc->shared = iflib_get_softc_ctx(ctx); 894b1d5caf3SKevin Bowling sc->media = iflib_get_media(ctx); 895b1d5caf3SKevin Bowling hw = &sc->hw; 8968eb6488eSEric Joyner 8978eb6488eSEric Joyner /* Determine hardware revision */ 8988eb6488eSEric Joyner hw->vendor_id = pci_get_vendor(dev); 8998eb6488eSEric Joyner hw->device_id = pci_get_device(dev); 9008eb6488eSEric Joyner hw->revision_id = pci_get_revid(dev); 9018eb6488eSEric Joyner hw->subsystem_vendor_id = pci_get_subvendor(dev); 9028eb6488eSEric Joyner hw->subsystem_device_id = pci_get_subdevice(dev); 903758cc3dcSJack F Vogel 9048eb6488eSEric Joyner /* Do base PCI setup - map BAR0 */ 905c19c7afeSEric Joyner if (ixgbe_allocate_pci_resources(ctx)) { 9068eb6488eSEric Joyner device_printf(dev, "Allocation of PCI resources failed\n"); 907c19c7afeSEric Joyner return (ENXIO); 9086f37f232SEric Joyner } 909758cc3dcSJack F Vogel 9108eb6488eSEric Joyner /* let hardware know driver is loaded */ 9118eb6488eSEric Joyner ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 9128eb6488eSEric Joyner ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD; 9138eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 914758cc3dcSJack F Vogel 915758cc3dcSJack F Vogel /* 9168eb6488eSEric Joyner * Initialize the shared code 917758cc3dcSJack F Vogel */ 918c19c7afeSEric Joyner if (ixgbe_init_shared_code(hw) != 0) { 9198eb6488eSEric Joyner device_printf(dev, "Unable to initialize the shared code\n"); 9208eb6488eSEric Joyner error = ENXIO; 921c19c7afeSEric Joyner goto err_pci; 92230126537SJack F Vogel } 923758cc3dcSJack F Vogel 9248b4a3fbdSKevin Bowling if (hw->mac.ops.fw_recovery_mode && hw->mac.ops.fw_recovery_mode(hw)) { 9258b4a3fbdSKevin Bowling device_printf(dev, "Firmware recovery mode detected. Limiting " 9268b4a3fbdSKevin Bowling "functionality.\nRefer to the Intel(R) Ethernet Adapters " 9278b4a3fbdSKevin Bowling "and Devices User Guide for details on firmware recovery " 9288b4a3fbdSKevin Bowling "mode."); 9298b4a3fbdSKevin Bowling error = ENOSYS; 9308b4a3fbdSKevin Bowling goto err_pci; 9318b4a3fbdSKevin Bowling } 9328b4a3fbdSKevin Bowling 9337234c309SJakub Chylkowski /* 82598 Does not support SR-IOV, initialize everything else */ 9347234c309SJakub Chylkowski if (hw->mac.type >= ixgbe_mac_82599_vf) { 9357234c309SJakub Chylkowski for (i = 0; i < sc->num_vfs; i++) 9367234c309SJakub Chylkowski hw->mbx.ops[i].init_params(hw); 9377234c309SJakub Chylkowski } 938758cc3dcSJack F Vogel 9398eb6488eSEric Joyner hw->allow_unsupported_sfp = allow_unsupported_sfp; 940758cc3dcSJack F Vogel 941c19c7afeSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) 9428eb6488eSEric Joyner hw->phy.smart_speed = ixgbe_smart_speed; 9438eb6488eSEric Joyner 944b1d5caf3SKevin Bowling ixgbe_init_device_features(sc); 9458eb6488eSEric Joyner 9468eb6488eSEric Joyner /* Enable WoL (if supported) */ 947b1d5caf3SKevin Bowling ixgbe_check_wol_support(sc); 9488eb6488eSEric Joyner 9498eb6488eSEric Joyner /* Verify adapter fan is still functional (if applicable) */ 950b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_FAN_FAIL) { 9518eb6488eSEric Joyner u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 952b1d5caf3SKevin Bowling ixgbe_check_fan_failure(sc, esdp, false); 9538eb6488eSEric Joyner } 9548eb6488eSEric Joyner 9558eb6488eSEric Joyner /* Ensure SW/FW semaphore is free */ 9568eb6488eSEric Joyner ixgbe_init_swfw_semaphore(hw); 9578eb6488eSEric Joyner 9588eb6488eSEric Joyner /* Set an initial default flow control value */ 9598eb6488eSEric Joyner hw->fc.requested_mode = ixgbe_flow_control; 9608eb6488eSEric Joyner 96179b36ec9SKevin Bowling hw->phy.reset_if_overtemp = true; 9628eb6488eSEric Joyner error = ixgbe_reset_hw(hw); 96379b36ec9SKevin Bowling hw->phy.reset_if_overtemp = false; 9648eb6488eSEric Joyner if (error == IXGBE_ERR_SFP_NOT_PRESENT) { 965758cc3dcSJack F Vogel /* 9668eb6488eSEric Joyner * No optics in this port, set up 9678eb6488eSEric Joyner * so the timer routine will probe 9688eb6488eSEric Joyner * for later insertion. 969758cc3dcSJack F Vogel */ 970b1d5caf3SKevin Bowling sc->sfp_probe = true; 971c19c7afeSEric Joyner error = 0; 9728eb6488eSEric Joyner } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) { 9738eb6488eSEric Joyner device_printf(dev, "Unsupported SFP+ module detected!\n"); 9748eb6488eSEric Joyner error = EIO; 975c19c7afeSEric Joyner goto err_pci; 9768eb6488eSEric Joyner } else if (error) { 9778eb6488eSEric Joyner device_printf(dev, "Hardware initialization failed\n"); 9788eb6488eSEric Joyner error = EIO; 979c19c7afeSEric Joyner goto err_pci; 98097f9586eSSean Bruno } 98197f9586eSSean Bruno 9828eb6488eSEric Joyner /* Make sure we have a good EEPROM before we read from it */ 983b1d5caf3SKevin Bowling if (ixgbe_validate_eeprom_checksum(&sc->hw, NULL) < 0) { 9848eb6488eSEric Joyner device_printf(dev, "The EEPROM Checksum Is Not Valid\n"); 9858eb6488eSEric Joyner error = EIO; 986c19c7afeSEric Joyner goto err_pci; 98797f9586eSSean Bruno } 98897f9586eSSean Bruno 9898eb6488eSEric Joyner error = ixgbe_start_hw(hw); 9908eb6488eSEric Joyner switch (error) { 9918eb6488eSEric Joyner case IXGBE_ERR_EEPROM_VERSION: 9928eb6488eSEric 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"); 99397f9586eSSean Bruno break; 9948eb6488eSEric Joyner case IXGBE_ERR_SFP_NOT_SUPPORTED: 9958eb6488eSEric Joyner device_printf(dev, "Unsupported SFP+ Module\n"); 9968eb6488eSEric Joyner error = EIO; 997c19c7afeSEric Joyner goto err_pci; 9988eb6488eSEric Joyner case IXGBE_ERR_SFP_NOT_PRESENT: 9998eb6488eSEric Joyner device_printf(dev, "No SFP+ Module found\n"); 10008eb6488eSEric Joyner /* falls thru */ 100197f9586eSSean Bruno default: 100297f9586eSSean Bruno break; 100397f9586eSSean Bruno } 100497f9586eSSean Bruno 1005c19c7afeSEric Joyner /* Most of the iflib initialization... */ 1006c19c7afeSEric Joyner 1007c19c7afeSEric Joyner iflib_set_mac(ctx, hw->mac.addr); 1008b1d5caf3SKevin Bowling switch (sc->hw.mac.type) { 1009c19c7afeSEric Joyner case ixgbe_mac_X550: 1010c19c7afeSEric Joyner case ixgbe_mac_X550EM_x: 1011c19c7afeSEric Joyner case ixgbe_mac_X550EM_a: 1012c19c7afeSEric Joyner scctx->isc_rss_table_size = 512; 1013c19c7afeSEric Joyner scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 64; 1014c19c7afeSEric Joyner break; 1015c19c7afeSEric Joyner default: 1016c19c7afeSEric Joyner scctx->isc_rss_table_size = 128; 1017c19c7afeSEric Joyner scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 16; 1018c19c7afeSEric Joyner } 1019c19c7afeSEric Joyner 1020c19c7afeSEric Joyner /* Allow legacy interrupts */ 1021c19c7afeSEric Joyner ixgbe_txrx.ift_legacy_intr = ixgbe_intr; 1022c19c7afeSEric Joyner 1023c19c7afeSEric Joyner scctx->isc_txqsizes[0] = 1024c19c7afeSEric Joyner roundup2(scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc) + 1025c19c7afeSEric Joyner sizeof(u32), DBA_ALIGN), 1026c19c7afeSEric Joyner scctx->isc_rxqsizes[0] = 1027c19c7afeSEric Joyner roundup2(scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc), 1028c19c7afeSEric Joyner DBA_ALIGN); 1029c19c7afeSEric Joyner 1030c19c7afeSEric Joyner /* XXX */ 1031c19c7afeSEric Joyner scctx->isc_tx_csum_flags = CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO | 1032c19c7afeSEric Joyner CSUM_IP6_TCP | CSUM_IP6_UDP | CSUM_IP6_TSO; 1033b1d5caf3SKevin Bowling if (sc->hw.mac.type == ixgbe_mac_82598EB) { 1034c19c7afeSEric Joyner scctx->isc_tx_nsegments = IXGBE_82598_SCATTER; 1035c19c7afeSEric Joyner } else { 1036c19c7afeSEric Joyner scctx->isc_tx_csum_flags |= CSUM_SCTP |CSUM_IP6_SCTP; 1037c19c7afeSEric Joyner scctx->isc_tx_nsegments = IXGBE_82599_SCATTER; 1038c19c7afeSEric Joyner } 1039749597dcSEric Joyner 1040749597dcSEric Joyner scctx->isc_msix_bar = pci_msix_table_bar(dev); 1041749597dcSEric Joyner 1042c19c7afeSEric Joyner scctx->isc_tx_tso_segments_max = scctx->isc_tx_nsegments; 1043c19c7afeSEric Joyner scctx->isc_tx_tso_size_max = IXGBE_TSO_SIZE; 1044c19c7afeSEric Joyner scctx->isc_tx_tso_segsize_max = PAGE_SIZE; 1045c19c7afeSEric Joyner 1046c19c7afeSEric Joyner scctx->isc_txrx = &ixgbe_txrx; 1047c19c7afeSEric Joyner 10487f87c040SMarius Strobl scctx->isc_capabilities = scctx->isc_capenable = IXGBE_CAPS; 1049c19c7afeSEric Joyner 1050c19c7afeSEric Joyner return (0); 1051c19c7afeSEric Joyner 1052c19c7afeSEric Joyner err_pci: 1053b1d5caf3SKevin Bowling ctrl_ext = IXGBE_READ_REG(&sc->hw, IXGBE_CTRL_EXT); 1054c19c7afeSEric Joyner ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD; 1055b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_CTRL_EXT, ctrl_ext); 1056c19c7afeSEric Joyner ixgbe_free_pci_resources(ctx); 1057c19c7afeSEric Joyner 1058c19c7afeSEric Joyner return (error); 1059c19c7afeSEric Joyner } /* ixgbe_if_attach_pre */ 1060c19c7afeSEric Joyner 1061c19c7afeSEric Joyner /********************************************************************* 1062c19c7afeSEric Joyner * ixgbe_if_attach_post - Device initialization routine, part 2 1063c19c7afeSEric Joyner * 1064c19c7afeSEric Joyner * Called during driver load, but after interrupts and 1065c19c7afeSEric Joyner * resources have been allocated and configured. 1066c19c7afeSEric Joyner * Sets up some data structures not relevant to iflib. 1067c19c7afeSEric Joyner * 1068c19c7afeSEric Joyner * return 0 on success, positive on failure 1069c19c7afeSEric Joyner *********************************************************************/ 1070c19c7afeSEric Joyner static int 1071c19c7afeSEric Joyner ixgbe_if_attach_post(if_ctx_t ctx) 1072c19c7afeSEric Joyner { 1073c19c7afeSEric Joyner device_t dev; 1074b1d5caf3SKevin Bowling struct ixgbe_softc *sc; 1075c19c7afeSEric Joyner struct ixgbe_hw *hw; 1076c19c7afeSEric Joyner int error = 0; 1077c19c7afeSEric Joyner 1078c19c7afeSEric Joyner dev = iflib_get_dev(ctx); 1079b1d5caf3SKevin Bowling sc = iflib_get_softc(ctx); 1080b1d5caf3SKevin Bowling hw = &sc->hw; 1081c19c7afeSEric Joyner 1082c19c7afeSEric Joyner 1083b1d5caf3SKevin Bowling if (sc->intr_type == IFLIB_INTR_LEGACY && 1084b1d5caf3SKevin Bowling (sc->feat_cap & IXGBE_FEATURE_LEGACY_IRQ) == 0) { 1085c19c7afeSEric Joyner device_printf(dev, "Device does not support legacy interrupts"); 1086c19c7afeSEric Joyner error = ENXIO; 1087c19c7afeSEric Joyner goto err; 1088c19c7afeSEric Joyner } 1089c19c7afeSEric Joyner 1090c19c7afeSEric Joyner /* Allocate multicast array memory. */ 1091b1d5caf3SKevin Bowling sc->mta = malloc(sizeof(*sc->mta) * 1092c19c7afeSEric Joyner MAX_NUM_MULTICAST_ADDRESSES, M_IXGBE, M_NOWAIT); 1093b1d5caf3SKevin Bowling if (sc->mta == NULL) { 1094c19c7afeSEric Joyner device_printf(dev, "Can not allocate multicast setup array\n"); 1095c19c7afeSEric Joyner error = ENOMEM; 1096c19c7afeSEric Joyner goto err; 1097c19c7afeSEric Joyner } 1098c19c7afeSEric Joyner 1099c19c7afeSEric Joyner /* hw.ix defaults init */ 1100b1d5caf3SKevin Bowling ixgbe_set_advertise(sc, ixgbe_advertise_speed); 1101c19c7afeSEric Joyner 11028eb6488eSEric Joyner /* Enable the optics for 82599 SFP+ fiber */ 11038eb6488eSEric Joyner ixgbe_enable_tx_laser(hw); 1104758cc3dcSJack F Vogel 11058eb6488eSEric Joyner /* Enable power to the phy. */ 110679b36ec9SKevin Bowling ixgbe_set_phy_power(hw, true); 11078eb6488eSEric Joyner 1108b1d5caf3SKevin Bowling ixgbe_initialize_iov(sc); 1109c19c7afeSEric Joyner 1110c19c7afeSEric Joyner error = ixgbe_setup_interface(ctx); 1111c19c7afeSEric Joyner if (error) { 1112c19c7afeSEric Joyner device_printf(dev, "Interface setup failed: %d\n", error); 1113c19c7afeSEric Joyner goto err; 1114c19c7afeSEric Joyner } 1115c19c7afeSEric Joyner 1116c19c7afeSEric Joyner ixgbe_if_update_admin_status(ctx); 1117c19c7afeSEric Joyner 11188eb6488eSEric Joyner /* Initialize statistics */ 1119b1d5caf3SKevin Bowling ixgbe_update_stats_counters(sc); 1120b1d5caf3SKevin Bowling ixgbe_add_hw_stats(sc); 11218eb6488eSEric Joyner 11228eb6488eSEric Joyner /* Check PCIE slot type/speed/width */ 1123b1d5caf3SKevin Bowling ixgbe_get_slot_info(sc); 1124758cc3dcSJack F Vogel 1125758cc3dcSJack F Vogel /* 11268eb6488eSEric Joyner * Do time init and sysctl init here, but 1127b1d5caf3SKevin Bowling * only on the first port of a bypass sc. 1128758cc3dcSJack F Vogel */ 1129b1d5caf3SKevin Bowling ixgbe_bypass_init(sc); 1130758cc3dcSJack F Vogel 11317660e4eaSKevin Bowling /* Display NVM and Option ROM versions */ 11327660e4eaSKevin Bowling ixgbe_print_fw_version(ctx); 11337660e4eaSKevin Bowling 11348eb6488eSEric Joyner /* Set an initial dmac value */ 1135b1d5caf3SKevin Bowling sc->dmac = 0; 11368eb6488eSEric Joyner /* Set initial advertised speeds (if applicable) */ 1137d381c807SPiotr Pietruszewski sc->advertise = ixgbe_get_default_advertise(sc); 1138758cc3dcSJack F Vogel 1139b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_SRIOV) 11408eb6488eSEric Joyner ixgbe_define_iov_schemas(dev, &error); 1141758cc3dcSJack F Vogel 11428eb6488eSEric Joyner /* Add sysctls */ 1143c19c7afeSEric Joyner ixgbe_add_device_sysctls(ctx); 1144758cc3dcSJack F Vogel 1145f72de14eSKevin Bowling /* Init recovery mode timer and state variable */ 1146f72de14eSKevin Bowling if (sc->feat_en & IXGBE_FEATURE_RECOVERY_MODE) { 1147f72de14eSKevin Bowling sc->recovery_mode = 0; 1148f72de14eSKevin Bowling 1149f72de14eSKevin Bowling /* Set up the timer callout */ 1150f72de14eSKevin Bowling callout_init(&sc->fw_mode_timer, true); 1151f72de14eSKevin Bowling 1152f72de14eSKevin Bowling /* Start the task */ 1153*a924b5eeSKevin Bowling callout_reset(&sc->fw_mode_timer, hz, ixgbe_fw_mode_timer, sc); 1154f72de14eSKevin Bowling } 1155f72de14eSKevin Bowling 11568eb6488eSEric Joyner return (0); 1157c19c7afeSEric Joyner err: 11588eb6488eSEric Joyner return (error); 1159c19c7afeSEric Joyner } /* ixgbe_if_attach_post */ 11608eb6488eSEric Joyner 11618eb6488eSEric Joyner /************************************************************************ 11628eb6488eSEric Joyner * ixgbe_check_wol_support 11636f37f232SEric Joyner * 11646f37f232SEric Joyner * Checks whether the adapter's ports are capable of 11656f37f232SEric Joyner * Wake On LAN by reading the adapter's NVM. 11666f37f232SEric Joyner * 11676f37f232SEric Joyner * Sets each port's hw->wol_enabled value depending 11686f37f232SEric Joyner * on the value read here. 11698eb6488eSEric Joyner ************************************************************************/ 11706f37f232SEric Joyner static void 1171b1d5caf3SKevin Bowling ixgbe_check_wol_support(struct ixgbe_softc *sc) 11726f37f232SEric Joyner { 1173b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 11746f37f232SEric Joyner u16 dev_caps = 0; 11756f37f232SEric Joyner 11766f37f232SEric Joyner /* Find out WoL support for port */ 1177b1d5caf3SKevin Bowling sc->wol_support = hw->wol_enabled = 0; 11786f37f232SEric Joyner ixgbe_get_device_caps(hw, &dev_caps); 11796f37f232SEric Joyner if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) || 11806f37f232SEric Joyner ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) && 11816f37f232SEric Joyner hw->bus.func == 0)) 1182b1d5caf3SKevin Bowling sc->wol_support = hw->wol_enabled = 1; 11836f37f232SEric Joyner 11846f37f232SEric Joyner /* Save initial wake up filter configuration */ 1185b1d5caf3SKevin Bowling sc->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC); 11866f37f232SEric Joyner 11876f37f232SEric Joyner return; 11888eb6488eSEric Joyner } /* ixgbe_check_wol_support */ 11896f37f232SEric Joyner 11908eb6488eSEric Joyner /************************************************************************ 11918eb6488eSEric Joyner * ixgbe_setup_interface 11928eb6488eSEric Joyner * 11938eb6488eSEric Joyner * Setup networking device structure and register an interface. 11948eb6488eSEric Joyner ************************************************************************/ 11956f37f232SEric Joyner static int 1196c19c7afeSEric Joyner ixgbe_setup_interface(if_ctx_t ctx) 11976f37f232SEric Joyner { 1198ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 1199b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 12006f37f232SEric Joyner 12018eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_setup_interface: begin"); 12026f37f232SEric Joyner 1203c19c7afeSEric Joyner if_setbaudrate(ifp, IF_Gbps(10)); 12046f37f232SEric Joyner 1205ff06a8dbSJustin Hibbits sc->max_frame_size = if_getmtu(ifp) + ETHER_HDR_LEN + ETHER_CRC_LEN; 1206758cc3dcSJack F Vogel 1207b1d5caf3SKevin Bowling sc->phy_layer = ixgbe_get_supported_physical_layer(&sc->hw); 12088eb6488eSEric Joyner 1209c19c7afeSEric Joyner ixgbe_add_media_types(ctx); 1210c19c7afeSEric Joyner 1211c19c7afeSEric Joyner /* Autoselect media by default */ 1212b1d5caf3SKevin Bowling ifmedia_set(sc->media, IFM_ETHER | IFM_AUTO); 12138eb6488eSEric Joyner 12148eb6488eSEric Joyner return (0); 12158eb6488eSEric Joyner } /* ixgbe_setup_interface */ 1216758cc3dcSJack F Vogel 12178eb6488eSEric Joyner /************************************************************************ 1218c19c7afeSEric Joyner * ixgbe_if_get_counter 12198eb6488eSEric Joyner ************************************************************************/ 1220758cc3dcSJack F Vogel static uint64_t 1221c19c7afeSEric Joyner ixgbe_if_get_counter(if_ctx_t ctx, ift_counter cnt) 1222758cc3dcSJack F Vogel { 1223b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 1224c19c7afeSEric Joyner if_t ifp = iflib_get_ifp(ctx); 1225758cc3dcSJack F Vogel 1226758cc3dcSJack F Vogel switch (cnt) { 1227758cc3dcSJack F Vogel case IFCOUNTER_IPACKETS: 1228b1d5caf3SKevin Bowling return (sc->ipackets); 1229758cc3dcSJack F Vogel case IFCOUNTER_OPACKETS: 1230b1d5caf3SKevin Bowling return (sc->opackets); 1231758cc3dcSJack F Vogel case IFCOUNTER_IBYTES: 1232b1d5caf3SKevin Bowling return (sc->ibytes); 1233758cc3dcSJack F Vogel case IFCOUNTER_OBYTES: 1234b1d5caf3SKevin Bowling return (sc->obytes); 1235758cc3dcSJack F Vogel case IFCOUNTER_IMCASTS: 1236b1d5caf3SKevin Bowling return (sc->imcasts); 1237758cc3dcSJack F Vogel case IFCOUNTER_OMCASTS: 1238b1d5caf3SKevin Bowling return (sc->omcasts); 1239758cc3dcSJack F Vogel case IFCOUNTER_COLLISIONS: 1240758cc3dcSJack F Vogel return (0); 1241758cc3dcSJack F Vogel case IFCOUNTER_IQDROPS: 1242b1d5caf3SKevin Bowling return (sc->iqdrops); 1243625d12c6SJohn Baldwin case IFCOUNTER_OQDROPS: 1244c19c7afeSEric Joyner return (0); 1245758cc3dcSJack F Vogel case IFCOUNTER_IERRORS: 1246b1d5caf3SKevin Bowling return (sc->ierrors); 1247758cc3dcSJack F Vogel default: 1248758cc3dcSJack F Vogel return (if_get_counter_default(ifp, cnt)); 1249758cc3dcSJack F Vogel } 1250c19c7afeSEric Joyner } /* ixgbe_if_get_counter */ 1251758cc3dcSJack F Vogel 12528eb6488eSEric Joyner /************************************************************************ 1253bca38080SAndrew Gallatin * ixgbe_if_i2c_req 1254bca38080SAndrew Gallatin ************************************************************************/ 1255bca38080SAndrew Gallatin static int 1256bca38080SAndrew Gallatin ixgbe_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req) 1257bca38080SAndrew Gallatin { 1258b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 1259b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 1260bca38080SAndrew Gallatin int i; 1261bca38080SAndrew Gallatin 1262bca38080SAndrew Gallatin 1263bca38080SAndrew Gallatin if (hw->phy.ops.read_i2c_byte == NULL) 1264bca38080SAndrew Gallatin return (ENXIO); 1265bca38080SAndrew Gallatin for (i = 0; i < req->len; i++) 1266bca38080SAndrew Gallatin hw->phy.ops.read_i2c_byte(hw, req->offset + i, 1267bca38080SAndrew Gallatin req->dev_addr, &req->data[i]); 1268bca38080SAndrew Gallatin return (0); 1269bca38080SAndrew Gallatin } /* ixgbe_if_i2c_req */ 1270bca38080SAndrew Gallatin 1271cf150917SEric Joyner /* ixgbe_if_needs_restart - Tell iflib when the driver needs to be reinitialized 1272cf150917SEric Joyner * @ctx: iflib context 1273cf150917SEric Joyner * @event: event code to check 1274cf150917SEric Joyner * 1275725e4008SKevin Bowling * Defaults to returning false for unknown events. 1276cf150917SEric Joyner * 1277cf150917SEric Joyner * @returns true if iflib needs to reinit the interface 1278cf150917SEric Joyner */ 1279cf150917SEric Joyner static bool 1280cf150917SEric Joyner ixgbe_if_needs_restart(if_ctx_t ctx __unused, enum iflib_restart_event event) 1281cf150917SEric Joyner { 1282cf150917SEric Joyner switch (event) { 1283cf150917SEric Joyner case IFLIB_RESTART_VLAN_CONFIG: 1284cf150917SEric Joyner default: 1285725e4008SKevin Bowling return (false); 1286cf150917SEric Joyner } 1287cf150917SEric Joyner } 1288cf150917SEric Joyner 1289bca38080SAndrew Gallatin /************************************************************************ 12908eb6488eSEric Joyner * ixgbe_add_media_types 12918eb6488eSEric Joyner ************************************************************************/ 12928eb6488eSEric Joyner static void 1293c19c7afeSEric Joyner ixgbe_add_media_types(if_ctx_t ctx) 12948eb6488eSEric Joyner { 1295b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 1296b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 1297c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 12988eb6488eSEric Joyner u64 layer; 12998eb6488eSEric Joyner 1300b1d5caf3SKevin Bowling layer = sc->phy_layer = ixgbe_get_supported_physical_layer(hw); 13018eb6488eSEric Joyner 13028eb6488eSEric Joyner /* Media types with matching FreeBSD media defines */ 13038eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) 1304b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_T, 0, NULL); 13058eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) 1306b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_T, 0, NULL); 13078eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) 1308b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_100_TX, 0, NULL); 13098eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T) 1310b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10_T, 0, NULL); 13118eb6488eSEric Joyner 1312d381c807SPiotr Pietruszewski if (hw->mac.type == ixgbe_mac_X550) { 1313d381c807SPiotr Pietruszewski ifmedia_add(sc->media, IFM_ETHER | IFM_2500_T, 0, NULL); 1314d381c807SPiotr Pietruszewski ifmedia_add(sc->media, IFM_ETHER | IFM_5000_T, 0, NULL); 1315d381c807SPiotr Pietruszewski } 1316d381c807SPiotr Pietruszewski 13178eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || 13188eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) 1319b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_TWINAX, 0, 13208eb6488eSEric Joyner NULL); 13218eb6488eSEric Joyner 13228eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) { 1323b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_LR, 0, NULL); 13248eb6488eSEric Joyner if (hw->phy.multispeed_fiber) 1325b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_LX, 0, 13268eb6488eSEric Joyner NULL); 13278eb6488eSEric Joyner } 13288eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) { 1329b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_SR, 0, NULL); 13308eb6488eSEric Joyner if (hw->phy.multispeed_fiber) 1331b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_SX, 0, 13328eb6488eSEric Joyner NULL); 13338eb6488eSEric Joyner } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) 1334b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_SX, 0, NULL); 13358eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) 1336b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); 13378eb6488eSEric Joyner 13388eb6488eSEric Joyner #ifdef IFM_ETH_XTYPE 13398eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 1340b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_KR, 0, NULL); 13418eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) 1342b1d5caf3SKevin Bowling ifmedia_add( sc->media, IFM_ETHER | IFM_10G_KX4, 0, NULL); 13438eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 1344b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_KX, 0, NULL); 13458eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) 1346b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_2500_KX, 0, NULL); 13478eb6488eSEric Joyner #else 13488eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) { 13498eb6488eSEric Joyner device_printf(dev, "Media supported: 10GbaseKR\n"); 13508eb6488eSEric Joyner device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n"); 1351b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_SR, 0, NULL); 13528eb6488eSEric Joyner } 13538eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) { 13548eb6488eSEric Joyner device_printf(dev, "Media supported: 10GbaseKX4\n"); 13558eb6488eSEric Joyner device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n"); 1356b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); 13578eb6488eSEric Joyner } 13588eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) { 13598eb6488eSEric Joyner device_printf(dev, "Media supported: 1000baseKX\n"); 13608eb6488eSEric Joyner device_printf(dev, "1000baseKX mapped to 1000baseCX\n"); 1361b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_CX, 0, NULL); 13628eb6488eSEric Joyner } 13638eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) { 13648eb6488eSEric Joyner device_printf(dev, "Media supported: 2500baseKX\n"); 13658eb6488eSEric Joyner device_printf(dev, "2500baseKX mapped to 2500baseSX\n"); 1366b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_2500_SX, 0, NULL); 13678eb6488eSEric Joyner } 13688eb6488eSEric Joyner #endif 13698eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) 13708eb6488eSEric Joyner device_printf(dev, "Media supported: 1000baseBX\n"); 13718eb6488eSEric Joyner 13728eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_82598AT) { 1373b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 13748eb6488eSEric Joyner 0, NULL); 1375b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_1000_T, 0, NULL); 13768eb6488eSEric Joyner } 13778eb6488eSEric Joyner 1378b1d5caf3SKevin Bowling ifmedia_add(sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); 13798eb6488eSEric Joyner } /* ixgbe_add_media_types */ 13808eb6488eSEric Joyner 13818eb6488eSEric Joyner /************************************************************************ 13828eb6488eSEric Joyner * ixgbe_is_sfp 13838eb6488eSEric Joyner ************************************************************************/ 13848eb6488eSEric Joyner static inline bool 13858eb6488eSEric Joyner ixgbe_is_sfp(struct ixgbe_hw *hw) 13868eb6488eSEric Joyner { 13878eb6488eSEric Joyner switch (hw->mac.type) { 13888eb6488eSEric Joyner case ixgbe_mac_82598EB: 13898eb6488eSEric Joyner if (hw->phy.type == ixgbe_phy_nl) 139079b36ec9SKevin Bowling return (true); 139179b36ec9SKevin Bowling return (false); 13928eb6488eSEric Joyner case ixgbe_mac_82599EB: 13938eb6488eSEric Joyner switch (hw->mac.ops.get_media_type(hw)) { 13948eb6488eSEric Joyner case ixgbe_media_type_fiber: 13958eb6488eSEric Joyner case ixgbe_media_type_fiber_qsfp: 139679b36ec9SKevin Bowling return (true); 13978eb6488eSEric Joyner default: 139879b36ec9SKevin Bowling return (false); 13998eb6488eSEric Joyner } 14008eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 14018eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 14028eb6488eSEric Joyner if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) 140379b36ec9SKevin Bowling return (true); 140479b36ec9SKevin Bowling return (false); 14058eb6488eSEric Joyner default: 140679b36ec9SKevin Bowling return (false); 14078eb6488eSEric Joyner } 14088eb6488eSEric Joyner } /* ixgbe_is_sfp */ 14098eb6488eSEric Joyner 14108eb6488eSEric Joyner /************************************************************************ 14118eb6488eSEric Joyner * ixgbe_config_link 14128eb6488eSEric Joyner ************************************************************************/ 14138eb6488eSEric Joyner static void 1414b2c1e8e6SEric Joyner ixgbe_config_link(if_ctx_t ctx) 14158eb6488eSEric Joyner { 1416b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 1417b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 14188eb6488eSEric Joyner u32 autoneg, err = 0; 14198eb6488eSEric Joyner bool sfp, negotiate; 14208eb6488eSEric Joyner 14218eb6488eSEric Joyner sfp = ixgbe_is_sfp(hw); 14228eb6488eSEric Joyner 14238eb6488eSEric Joyner if (sfp) { 1424b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MOD; 1425b2c1e8e6SEric Joyner iflib_admin_intr_deferred(ctx); 14268eb6488eSEric Joyner } else { 14278eb6488eSEric Joyner if (hw->mac.ops.check_link) 1428b1d5caf3SKevin Bowling err = ixgbe_check_link(hw, &sc->link_speed, 1429b1d5caf3SKevin Bowling &sc->link_up, false); 14308eb6488eSEric Joyner if (err) 1431c19c7afeSEric Joyner return; 14328eb6488eSEric Joyner autoneg = hw->phy.autoneg_advertised; 14338eb6488eSEric Joyner if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) 14348eb6488eSEric Joyner err = hw->mac.ops.get_link_capabilities(hw, &autoneg, 14358eb6488eSEric Joyner &negotiate); 14368eb6488eSEric Joyner if (err) 1437c19c7afeSEric Joyner return; 1438d381c807SPiotr Pietruszewski 1439d381c807SPiotr Pietruszewski if (hw->mac.type == ixgbe_mac_X550 && 1440d381c807SPiotr Pietruszewski hw->phy.autoneg_advertised == 0) { 1441d381c807SPiotr Pietruszewski /* 1442d381c807SPiotr Pietruszewski * 2.5G and 5G autonegotiation speeds on X550 1443d381c807SPiotr Pietruszewski * are disabled by default due to reported 1444d381c807SPiotr Pietruszewski * interoperability issues with some switches. 1445d381c807SPiotr Pietruszewski * 1446d381c807SPiotr Pietruszewski * The second condition checks if any operations 1447d381c807SPiotr Pietruszewski * involving setting autonegotiation speeds have 1448d381c807SPiotr Pietruszewski * been performed prior to this ixgbe_config_link() 1449d381c807SPiotr Pietruszewski * call. 1450d381c807SPiotr Pietruszewski * 1451d381c807SPiotr Pietruszewski * If hw->phy.autoneg_advertised does not 1452d381c807SPiotr Pietruszewski * equal 0, this means that the user might have 1453d381c807SPiotr Pietruszewski * set autonegotiation speeds via the sysctl 1454d381c807SPiotr Pietruszewski * before bringing the interface up. In this 1455d381c807SPiotr Pietruszewski * case, we should not disable 2.5G and 5G 1456d381c807SPiotr Pietruszewski * since that speeds might be selected by the 1457d381c807SPiotr Pietruszewski * user. 1458d381c807SPiotr Pietruszewski * 1459d381c807SPiotr Pietruszewski * Otherwise (i.e. if hw->phy.autoneg_advertised 1460d381c807SPiotr Pietruszewski * is set to 0), it is the first time we set 1461d381c807SPiotr Pietruszewski * autonegotiation preferences and the default 1462d381c807SPiotr Pietruszewski * set of speeds should exclude 2.5G and 5G. 1463d381c807SPiotr Pietruszewski */ 1464d381c807SPiotr Pietruszewski autoneg &= ~(IXGBE_LINK_SPEED_2_5GB_FULL | 1465d381c807SPiotr Pietruszewski IXGBE_LINK_SPEED_5GB_FULL); 1466d381c807SPiotr Pietruszewski } 1467d381c807SPiotr Pietruszewski 14688eb6488eSEric Joyner if (hw->mac.ops.setup_link) 14698eb6488eSEric Joyner err = hw->mac.ops.setup_link(hw, autoneg, 1470b1d5caf3SKevin Bowling sc->link_up); 14718eb6488eSEric Joyner } 14728eb6488eSEric Joyner } /* ixgbe_config_link */ 14738eb6488eSEric Joyner 14748eb6488eSEric Joyner /************************************************************************ 14758eb6488eSEric Joyner * ixgbe_update_stats_counters - Update board statistics counters. 14768eb6488eSEric Joyner ************************************************************************/ 14778eb6488eSEric Joyner static void 1478b1d5caf3SKevin Bowling ixgbe_update_stats_counters(struct ixgbe_softc *sc) 14798eb6488eSEric Joyner { 1480b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 1481b1d5caf3SKevin Bowling struct ixgbe_hw_stats *stats = &sc->stats.pf; 14828eb6488eSEric Joyner u32 missed_rx = 0, bprc, lxon, lxoff, total; 1483e37d3dc1SEric Joyner u32 lxoffrxc; 14848eb6488eSEric Joyner u64 total_missed_rx = 0; 14858eb6488eSEric Joyner 14868eb6488eSEric Joyner stats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); 14878eb6488eSEric Joyner stats->illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC); 14888eb6488eSEric Joyner stats->errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC); 14898eb6488eSEric Joyner stats->mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC); 14908eb6488eSEric Joyner stats->mpc[0] += IXGBE_READ_REG(hw, IXGBE_MPC(0)); 14918eb6488eSEric Joyner 14928eb6488eSEric Joyner for (int i = 0; i < 16; i++) { 14938eb6488eSEric Joyner stats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 14948eb6488eSEric Joyner stats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 14958eb6488eSEric Joyner stats->qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); 14968eb6488eSEric Joyner } 14978eb6488eSEric Joyner stats->mlfc += IXGBE_READ_REG(hw, IXGBE_MLFC); 14988eb6488eSEric Joyner stats->mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC); 14998eb6488eSEric Joyner stats->rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); 15008eb6488eSEric Joyner 15018eb6488eSEric Joyner /* Hardware workaround, gprc counts missed packets */ 15028eb6488eSEric Joyner stats->gprc += IXGBE_READ_REG(hw, IXGBE_GPRC); 15038eb6488eSEric Joyner stats->gprc -= missed_rx; 15048eb6488eSEric Joyner 15058eb6488eSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) { 15068eb6488eSEric Joyner stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL) + 15078eb6488eSEric Joyner ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32); 15088eb6488eSEric Joyner stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL) + 15098eb6488eSEric Joyner ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32); 15108eb6488eSEric Joyner stats->tor += IXGBE_READ_REG(hw, IXGBE_TORL) + 15118eb6488eSEric Joyner ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32); 15128eb6488eSEric Joyner stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 1513e37d3dc1SEric Joyner lxoffrxc = IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 1514e37d3dc1SEric Joyner stats->lxoffrxc += lxoffrxc; 15158eb6488eSEric Joyner } else { 15168eb6488eSEric Joyner stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); 1517e37d3dc1SEric Joyner lxoffrxc = IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 1518e37d3dc1SEric Joyner stats->lxoffrxc += lxoffrxc; 15198eb6488eSEric Joyner /* 82598 only has a counter in the high register */ 15208eb6488eSEric Joyner stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); 15218eb6488eSEric Joyner stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); 15228eb6488eSEric Joyner stats->tor += IXGBE_READ_REG(hw, IXGBE_TORH); 15238eb6488eSEric Joyner } 15248eb6488eSEric Joyner 15258eb6488eSEric Joyner /* 1526e37d3dc1SEric Joyner * For watchdog management we need to know if we have been paused 1527e37d3dc1SEric Joyner * during the last interval, so capture that here. 1528e37d3dc1SEric Joyner */ 1529e37d3dc1SEric Joyner if (lxoffrxc) 1530b1d5caf3SKevin Bowling sc->shared->isc_pause_frames = 1; 1531e37d3dc1SEric Joyner 1532e37d3dc1SEric Joyner /* 15338eb6488eSEric Joyner * Workaround: mprc hardware is incorrectly counting 15348eb6488eSEric Joyner * broadcasts, so for now we subtract those. 1535758cc3dcSJack F Vogel */ 15368eb6488eSEric Joyner bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); 15378eb6488eSEric Joyner stats->bprc += bprc; 15388eb6488eSEric Joyner stats->mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); 15398eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 15408eb6488eSEric Joyner stats->mprc -= bprc; 15418eb6488eSEric Joyner 15428eb6488eSEric Joyner stats->prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64); 15438eb6488eSEric Joyner stats->prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127); 15448eb6488eSEric Joyner stats->prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255); 15458eb6488eSEric Joyner stats->prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511); 15468eb6488eSEric Joyner stats->prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023); 15478eb6488eSEric Joyner stats->prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522); 15488eb6488eSEric Joyner 15498eb6488eSEric Joyner lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC); 15508eb6488eSEric Joyner stats->lxontxc += lxon; 15518eb6488eSEric Joyner lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 15528eb6488eSEric Joyner stats->lxofftxc += lxoff; 15538eb6488eSEric Joyner total = lxon + lxoff; 15548eb6488eSEric Joyner 15558eb6488eSEric Joyner stats->gptc += IXGBE_READ_REG(hw, IXGBE_GPTC); 15568eb6488eSEric Joyner stats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC); 15578eb6488eSEric Joyner stats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64); 15588eb6488eSEric Joyner stats->gptc -= total; 15598eb6488eSEric Joyner stats->mptc -= total; 15608eb6488eSEric Joyner stats->ptc64 -= total; 15618eb6488eSEric Joyner stats->gotc -= total * ETHER_MIN_LEN; 15628eb6488eSEric Joyner 15638eb6488eSEric Joyner stats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC); 15648eb6488eSEric Joyner stats->rfc += IXGBE_READ_REG(hw, IXGBE_RFC); 15658eb6488eSEric Joyner stats->roc += IXGBE_READ_REG(hw, IXGBE_ROC); 15668eb6488eSEric Joyner stats->rjc += IXGBE_READ_REG(hw, IXGBE_RJC); 15678eb6488eSEric Joyner stats->mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC); 15688eb6488eSEric Joyner stats->mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC); 15698eb6488eSEric Joyner stats->mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC); 15708eb6488eSEric Joyner stats->tpr += IXGBE_READ_REG(hw, IXGBE_TPR); 15718eb6488eSEric Joyner stats->tpt += IXGBE_READ_REG(hw, IXGBE_TPT); 15728eb6488eSEric Joyner stats->ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127); 15738eb6488eSEric Joyner stats->ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255); 15748eb6488eSEric Joyner stats->ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511); 15758eb6488eSEric Joyner stats->ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023); 15768eb6488eSEric Joyner stats->ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522); 15778eb6488eSEric Joyner stats->bptc += IXGBE_READ_REG(hw, IXGBE_BPTC); 15788eb6488eSEric Joyner stats->xec += IXGBE_READ_REG(hw, IXGBE_XEC); 15798eb6488eSEric Joyner stats->fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC); 15808eb6488eSEric Joyner stats->fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST); 15818eb6488eSEric Joyner /* Only read FCOE on 82599 */ 15828eb6488eSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) { 15838eb6488eSEric Joyner stats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC); 15848eb6488eSEric Joyner stats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC); 15858eb6488eSEric Joyner stats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC); 15868eb6488eSEric Joyner stats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC); 15878eb6488eSEric Joyner stats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC); 15888eb6488eSEric Joyner } 15898eb6488eSEric Joyner 15908eb6488eSEric Joyner /* Fill out the OS statistics structure */ 1591b1d5caf3SKevin Bowling IXGBE_SET_IPACKETS(sc, stats->gprc); 1592b1d5caf3SKevin Bowling IXGBE_SET_OPACKETS(sc, stats->gptc); 1593b1d5caf3SKevin Bowling IXGBE_SET_IBYTES(sc, stats->gorc); 1594b1d5caf3SKevin Bowling IXGBE_SET_OBYTES(sc, stats->gotc); 1595b1d5caf3SKevin Bowling IXGBE_SET_IMCASTS(sc, stats->mprc); 1596b1d5caf3SKevin Bowling IXGBE_SET_OMCASTS(sc, stats->mptc); 1597b1d5caf3SKevin Bowling IXGBE_SET_COLLISIONS(sc, 0); 1598b1d5caf3SKevin Bowling IXGBE_SET_IQDROPS(sc, total_missed_rx); 1599afb1aa4eSPiotr Pietruszewski 1600afb1aa4eSPiotr Pietruszewski /* 1601afb1aa4eSPiotr Pietruszewski * Aggregate following types of errors as RX errors: 1602afb1aa4eSPiotr Pietruszewski * - CRC error count, 1603afb1aa4eSPiotr Pietruszewski * - illegal byte error count, 1604afb1aa4eSPiotr Pietruszewski * - missed packets count, 1605afb1aa4eSPiotr Pietruszewski * - length error count, 1606afb1aa4eSPiotr Pietruszewski * - undersized packets count, 1607afb1aa4eSPiotr Pietruszewski * - fragmented packets count, 1608afb1aa4eSPiotr Pietruszewski * - oversized packets count, 1609afb1aa4eSPiotr Pietruszewski * - jabber count. 1610afb1aa4eSPiotr Pietruszewski */ 16118526120aSAndrey V. Elsukov IXGBE_SET_IERRORS(sc, stats->crcerrs + stats->illerrc + 1612afb1aa4eSPiotr Pietruszewski stats->mpc[0] + stats->rlec + stats->ruc + stats->rfc + stats->roc + 1613afb1aa4eSPiotr Pietruszewski stats->rjc); 16148eb6488eSEric Joyner } /* ixgbe_update_stats_counters */ 16158eb6488eSEric Joyner 16168eb6488eSEric Joyner /************************************************************************ 16178eb6488eSEric Joyner * ixgbe_add_hw_stats 16188eb6488eSEric Joyner * 16198eb6488eSEric Joyner * Add sysctl variables, one per statistic, to the system. 16208eb6488eSEric Joyner ************************************************************************/ 16218eb6488eSEric Joyner static void 1622b1d5caf3SKevin Bowling ixgbe_add_hw_stats(struct ixgbe_softc *sc) 16238eb6488eSEric Joyner { 1624b1d5caf3SKevin Bowling device_t dev = iflib_get_dev(sc->ctx); 1625c19c7afeSEric Joyner struct ix_rx_queue *rx_que; 1626c19c7afeSEric Joyner struct ix_tx_queue *tx_que; 16278eb6488eSEric Joyner struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 16288eb6488eSEric Joyner struct sysctl_oid *tree = device_get_sysctl_tree(dev); 16298eb6488eSEric Joyner struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); 1630b1d5caf3SKevin Bowling struct ixgbe_hw_stats *stats = &sc->stats.pf; 16318eb6488eSEric Joyner struct sysctl_oid *stat_node, *queue_node; 16328eb6488eSEric Joyner struct sysctl_oid_list *stat_list, *queue_list; 1633c19c7afeSEric Joyner int i; 16348eb6488eSEric Joyner 16358eb6488eSEric Joyner #define QUEUE_NAME_LEN 32 16368eb6488eSEric Joyner char namebuf[QUEUE_NAME_LEN]; 16378eb6488eSEric Joyner 16388eb6488eSEric Joyner /* Driver Statistics */ 16398eb6488eSEric Joyner SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", 1640b1d5caf3SKevin Bowling CTLFLAG_RD, &sc->dropped_pkts, "Driver dropped packets"); 16418eb6488eSEric Joyner SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events", 1642b1d5caf3SKevin Bowling CTLFLAG_RD, &sc->watchdog_events, "Watchdog timeouts"); 16438eb6488eSEric Joyner SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq", 1644b1d5caf3SKevin Bowling CTLFLAG_RD, &sc->link_irq, "Link MSI-X IRQ Handled"); 16458eb6488eSEric Joyner 1646b1d5caf3SKevin Bowling for (i = 0, tx_que = sc->tx_queues; i < sc->num_tx_queues; i++, tx_que++) { 1647c19c7afeSEric Joyner struct tx_ring *txr = &tx_que->txr; 16488eb6488eSEric Joyner snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); 16498eb6488eSEric Joyner queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, 165020b91f0aSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name"); 16518eb6488eSEric Joyner queue_list = SYSCTL_CHILDREN(queue_node); 16528eb6488eSEric Joyner 16538eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head", 1654f72de14eSKevin Bowling CTLTYPE_UINT | CTLFLAG_RD, txr, 0, 16558eb6488eSEric Joyner ixgbe_sysctl_tdh_handler, "IU", "Transmit Descriptor Head"); 16568eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail", 1657f72de14eSKevin Bowling CTLTYPE_UINT | CTLFLAG_RD, txr, 0, 16588eb6488eSEric Joyner ixgbe_sysctl_tdt_handler, "IU", "Transmit Descriptor Tail"); 16598eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx", 16608eb6488eSEric Joyner CTLFLAG_RD, &txr->tso_tx, "TSO"); 16618eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets", 16628eb6488eSEric Joyner CTLFLAG_RD, &txr->total_packets, 16638eb6488eSEric Joyner "Queue Packets Transmitted"); 16648eb6488eSEric Joyner } 16658eb6488eSEric Joyner 1666b1d5caf3SKevin Bowling for (i = 0, rx_que = sc->rx_queues; i < sc->num_rx_queues; i++, rx_que++) { 1667c19c7afeSEric Joyner struct rx_ring *rxr = &rx_que->rxr; 16688eb6488eSEric Joyner snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); 16698eb6488eSEric Joyner queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, 167020b91f0aSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name"); 16718eb6488eSEric Joyner queue_list = SYSCTL_CHILDREN(queue_node); 16728eb6488eSEric Joyner 1673c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate", 1674f72de14eSKevin Bowling CTLTYPE_UINT | CTLFLAG_RW, 1675b1d5caf3SKevin Bowling &sc->rx_queues[i], 0, 1676c19c7afeSEric Joyner ixgbe_sysctl_interrupt_rate_handler, "IU", 1677c19c7afeSEric Joyner "Interrupt Rate"); 1678c19c7afeSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs", 1679b1d5caf3SKevin Bowling CTLFLAG_RD, &(sc->rx_queues[i].irqs), 1680c19c7afeSEric Joyner "irqs on this queue"); 16818eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head", 1682f72de14eSKevin Bowling CTLTYPE_UINT | CTLFLAG_RD, rxr, 0, 16838eb6488eSEric Joyner ixgbe_sysctl_rdh_handler, "IU", "Receive Descriptor Head"); 16848eb6488eSEric Joyner SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail", 1685f72de14eSKevin Bowling CTLTYPE_UINT | CTLFLAG_RD, rxr, 0, 16868eb6488eSEric Joyner ixgbe_sysctl_rdt_handler, "IU", "Receive Descriptor Tail"); 16878eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets", 16888eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_packets, "Queue Packets Received"); 16898eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes", 16908eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_bytes, "Queue Bytes Received"); 16918eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_copies", 16928eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_copies, "Copied RX Frames"); 16938eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_discarded", 16948eb6488eSEric Joyner CTLFLAG_RD, &rxr->rx_discarded, "Discarded RX packets"); 16958eb6488eSEric Joyner } 16968eb6488eSEric Joyner 16978eb6488eSEric Joyner /* MAC stats get their own sub node */ 16988eb6488eSEric Joyner 16998eb6488eSEric Joyner stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats", 170020b91f0aSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "MAC Statistics"); 17018eb6488eSEric Joyner stat_list = SYSCTL_CHILDREN(stat_node); 17028eb6488eSEric Joyner 1703afb1aa4eSPiotr Pietruszewski SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_errs", 1704b1d5caf3SKevin Bowling CTLFLAG_RD, &sc->ierrors, IXGBE_SYSCTL_DESC_RX_ERRS); 17058eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs", 17068eb6488eSEric Joyner CTLFLAG_RD, &stats->crcerrs, "CRC Errors"); 17078eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ill_errs", 17088eb6488eSEric Joyner CTLFLAG_RD, &stats->illerrc, "Illegal Byte Errors"); 17098eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "byte_errs", 17108eb6488eSEric Joyner CTLFLAG_RD, &stats->errbc, "Byte Errors"); 17118eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "short_discards", 17128eb6488eSEric Joyner CTLFLAG_RD, &stats->mspdc, "MAC Short Packets Discarded"); 17138eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "local_faults", 17148eb6488eSEric Joyner CTLFLAG_RD, &stats->mlfc, "MAC Local Faults"); 17158eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "remote_faults", 17168eb6488eSEric Joyner CTLFLAG_RD, &stats->mrfc, "MAC Remote Faults"); 17178eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rec_len_errs", 17188eb6488eSEric Joyner CTLFLAG_RD, &stats->rlec, "Receive Length Errors"); 17198eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_missed_packets", 17208eb6488eSEric Joyner CTLFLAG_RD, &stats->mpc[0], "RX Missed Packet Count"); 17218eb6488eSEric Joyner 17228eb6488eSEric Joyner /* Flow Control stats */ 17238eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd", 17248eb6488eSEric Joyner CTLFLAG_RD, &stats->lxontxc, "Link XON Transmitted"); 17258eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd", 17268eb6488eSEric Joyner CTLFLAG_RD, &stats->lxonrxc, "Link XON Received"); 17278eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd", 17288eb6488eSEric Joyner CTLFLAG_RD, &stats->lxofftxc, "Link XOFF Transmitted"); 17298eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd", 17308eb6488eSEric Joyner CTLFLAG_RD, &stats->lxoffrxc, "Link XOFF Received"); 17318eb6488eSEric Joyner 17328eb6488eSEric Joyner /* Packet Reception Stats */ 17338eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_octets_rcvd", 17348eb6488eSEric Joyner CTLFLAG_RD, &stats->tor, "Total Octets Received"); 17358eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd", 17368eb6488eSEric Joyner CTLFLAG_RD, &stats->gorc, "Good Octets Received"); 17378eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_rcvd", 17388eb6488eSEric Joyner CTLFLAG_RD, &stats->tpr, "Total Packets Received"); 17398eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd", 17408eb6488eSEric Joyner CTLFLAG_RD, &stats->gprc, "Good Packets Received"); 17418eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd", 17428eb6488eSEric Joyner CTLFLAG_RD, &stats->mprc, "Multicast Packets Received"); 17438eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_rcvd", 17448eb6488eSEric Joyner CTLFLAG_RD, &stats->bprc, "Broadcast Packets Received"); 17458eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64", 17468eb6488eSEric Joyner CTLFLAG_RD, &stats->prc64, "64 byte frames received "); 17478eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127", 17488eb6488eSEric Joyner CTLFLAG_RD, &stats->prc127, "65-127 byte frames received"); 17498eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255", 17508eb6488eSEric Joyner CTLFLAG_RD, &stats->prc255, "128-255 byte frames received"); 17518eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511", 17528eb6488eSEric Joyner CTLFLAG_RD, &stats->prc511, "256-511 byte frames received"); 17538eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023", 17548eb6488eSEric Joyner CTLFLAG_RD, &stats->prc1023, "512-1023 byte frames received"); 17558eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522", 17568eb6488eSEric Joyner CTLFLAG_RD, &stats->prc1522, "1023-1522 byte frames received"); 17578eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersized", 17588eb6488eSEric Joyner CTLFLAG_RD, &stats->ruc, "Receive Undersized"); 17598eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented", 17608eb6488eSEric Joyner CTLFLAG_RD, &stats->rfc, "Fragmented Packets Received "); 17618eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversized", 17628eb6488eSEric Joyner CTLFLAG_RD, &stats->roc, "Oversized Packets Received"); 17638eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabberd", 17648eb6488eSEric Joyner CTLFLAG_RD, &stats->rjc, "Received Jabber"); 17658eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_rcvd", 17668eb6488eSEric Joyner CTLFLAG_RD, &stats->mngprc, "Management Packets Received"); 17678eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_drpd", 17688eb6488eSEric Joyner CTLFLAG_RD, &stats->mngptc, "Management Packets Dropped"); 17698eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "checksum_errs", 17708eb6488eSEric Joyner CTLFLAG_RD, &stats->xec, "Checksum Errors"); 17718eb6488eSEric Joyner 17728eb6488eSEric Joyner /* Packet Transmission Stats */ 17738eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd", 17748eb6488eSEric Joyner CTLFLAG_RD, &stats->gotc, "Good Octets Transmitted"); 17758eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd", 17768eb6488eSEric Joyner CTLFLAG_RD, &stats->tpt, "Total Packets Transmitted"); 17778eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd", 17788eb6488eSEric Joyner CTLFLAG_RD, &stats->gptc, "Good Packets Transmitted"); 17798eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd", 17808eb6488eSEric Joyner CTLFLAG_RD, &stats->bptc, "Broadcast Packets Transmitted"); 17818eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd", 17828eb6488eSEric Joyner CTLFLAG_RD, &stats->mptc, "Multicast Packets Transmitted"); 17838eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_txd", 17848eb6488eSEric Joyner CTLFLAG_RD, &stats->mngptc, "Management Packets Transmitted"); 17858eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64", 17868eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc64, "64 byte frames transmitted "); 17878eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127", 17888eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc127, "65-127 byte frames transmitted"); 17898eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255", 17908eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc255, "128-255 byte frames transmitted"); 17918eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511", 17928eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc511, "256-511 byte frames transmitted"); 17938eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023", 17948eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc1023, "512-1023 byte frames transmitted"); 17958eb6488eSEric Joyner SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522", 17968eb6488eSEric Joyner CTLFLAG_RD, &stats->ptc1522, "1024-1522 byte frames transmitted"); 17978eb6488eSEric Joyner } /* ixgbe_add_hw_stats */ 17988eb6488eSEric Joyner 17998eb6488eSEric Joyner /************************************************************************ 18008eb6488eSEric Joyner * ixgbe_sysctl_tdh_handler - Transmit Descriptor Head handler function 18018eb6488eSEric Joyner * 18028eb6488eSEric Joyner * Retrieves the TDH value from the hardware 18038eb6488eSEric Joyner ************************************************************************/ 1804758cc3dcSJack F Vogel static int 1805758cc3dcSJack F Vogel ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS) 1806758cc3dcSJack F Vogel { 1807758cc3dcSJack F Vogel struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); 18088eb6488eSEric Joyner int error; 18098eb6488eSEric Joyner unsigned int val; 1810758cc3dcSJack F Vogel 18118eb6488eSEric Joyner if (!txr) 18128eb6488eSEric Joyner return (0); 18138eb6488eSEric Joyner 1814f72de14eSKevin Bowling 1815f72de14eSKevin Bowling if (atomic_load_acq_int(&txr->sc->recovery_mode)) 1816f72de14eSKevin Bowling return (EPERM); 1817f72de14eSKevin Bowling 1818b1d5caf3SKevin Bowling val = IXGBE_READ_REG(&txr->sc->hw, IXGBE_TDH(txr->me)); 1819758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1820758cc3dcSJack F Vogel if (error || !req->newptr) 1821758cc3dcSJack F Vogel return error; 1822758cc3dcSJack F Vogel 18238eb6488eSEric Joyner return (0); 18248eb6488eSEric Joyner } /* ixgbe_sysctl_tdh_handler */ 18258eb6488eSEric Joyner 18268eb6488eSEric Joyner /************************************************************************ 18278eb6488eSEric Joyner * ixgbe_sysctl_tdt_handler - Transmit Descriptor Tail handler function 18288eb6488eSEric Joyner * 1829758cc3dcSJack F Vogel * Retrieves the TDT value from the hardware 18308eb6488eSEric Joyner ************************************************************************/ 1831758cc3dcSJack F Vogel static int 1832758cc3dcSJack F Vogel ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS) 1833758cc3dcSJack F Vogel { 1834758cc3dcSJack F Vogel struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); 18358eb6488eSEric Joyner int error; 18368eb6488eSEric Joyner unsigned int val; 1837758cc3dcSJack F Vogel 18388eb6488eSEric Joyner if (!txr) 18398eb6488eSEric Joyner return (0); 18408eb6488eSEric Joyner 1841f72de14eSKevin Bowling if (atomic_load_acq_int(&txr->sc->recovery_mode)) 1842f72de14eSKevin Bowling return (EPERM); 1843f72de14eSKevin Bowling 1844b1d5caf3SKevin Bowling val = IXGBE_READ_REG(&txr->sc->hw, IXGBE_TDT(txr->me)); 1845758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1846758cc3dcSJack F Vogel if (error || !req->newptr) 1847758cc3dcSJack F Vogel return error; 1848758cc3dcSJack F Vogel 18498eb6488eSEric Joyner return (0); 18508eb6488eSEric Joyner } /* ixgbe_sysctl_tdt_handler */ 18518eb6488eSEric Joyner 18528eb6488eSEric Joyner /************************************************************************ 18538eb6488eSEric Joyner * ixgbe_sysctl_rdh_handler - Receive Descriptor Head handler function 18548eb6488eSEric Joyner * 1855758cc3dcSJack F Vogel * Retrieves the RDH value from the hardware 18568eb6488eSEric Joyner ************************************************************************/ 1857758cc3dcSJack F Vogel static int 1858758cc3dcSJack F Vogel ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS) 1859758cc3dcSJack F Vogel { 1860758cc3dcSJack F Vogel struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); 18618eb6488eSEric Joyner int error; 18628eb6488eSEric Joyner unsigned int val; 1863758cc3dcSJack F Vogel 18648eb6488eSEric Joyner if (!rxr) 18658eb6488eSEric Joyner return (0); 18668eb6488eSEric Joyner 1867f72de14eSKevin Bowling if (atomic_load_acq_int(&rxr->sc->recovery_mode)) 1868f72de14eSKevin Bowling return (EPERM); 1869f72de14eSKevin Bowling 1870b1d5caf3SKevin Bowling val = IXGBE_READ_REG(&rxr->sc->hw, IXGBE_RDH(rxr->me)); 1871758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1872758cc3dcSJack F Vogel if (error || !req->newptr) 1873758cc3dcSJack F Vogel return error; 1874758cc3dcSJack F Vogel 18758eb6488eSEric Joyner return (0); 18768eb6488eSEric Joyner } /* ixgbe_sysctl_rdh_handler */ 18778eb6488eSEric Joyner 18788eb6488eSEric Joyner /************************************************************************ 18798eb6488eSEric Joyner * ixgbe_sysctl_rdt_handler - Receive Descriptor Tail handler function 18808eb6488eSEric Joyner * 1881758cc3dcSJack F Vogel * Retrieves the RDT value from the hardware 18828eb6488eSEric Joyner ************************************************************************/ 1883758cc3dcSJack F Vogel static int 1884758cc3dcSJack F Vogel ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS) 1885758cc3dcSJack F Vogel { 1886758cc3dcSJack F Vogel struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); 18878eb6488eSEric Joyner int error; 18888eb6488eSEric Joyner unsigned int val; 1889758cc3dcSJack F Vogel 18908eb6488eSEric Joyner if (!rxr) 18918eb6488eSEric Joyner return (0); 18928eb6488eSEric Joyner 1893f72de14eSKevin Bowling if (atomic_load_acq_int(&rxr->sc->recovery_mode)) 1894f72de14eSKevin Bowling return (EPERM); 1895f72de14eSKevin Bowling 1896b1d5caf3SKevin Bowling val = IXGBE_READ_REG(&rxr->sc->hw, IXGBE_RDT(rxr->me)); 1897758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &val, 0, req); 1898758cc3dcSJack F Vogel if (error || !req->newptr) 1899758cc3dcSJack F Vogel return error; 19008eb6488eSEric Joyner 19018eb6488eSEric Joyner return (0); 19028eb6488eSEric Joyner } /* ixgbe_sysctl_rdt_handler */ 19038eb6488eSEric Joyner 19048eb6488eSEric Joyner /************************************************************************ 1905c19c7afeSEric Joyner * ixgbe_if_vlan_register 19068eb6488eSEric Joyner * 19078eb6488eSEric Joyner * Run via vlan config EVENT, it enables us to use the 19088eb6488eSEric Joyner * HW Filter table since we can get the vlan id. This 19098eb6488eSEric Joyner * just creates the entry in the soft version of the 19108eb6488eSEric Joyner * VFTA, init will repopulate the real table. 19118eb6488eSEric Joyner ************************************************************************/ 19128eb6488eSEric Joyner static void 1913c19c7afeSEric Joyner ixgbe_if_vlan_register(if_ctx_t ctx, u16 vtag) 19148eb6488eSEric Joyner { 1915b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 19168eb6488eSEric Joyner u16 index, bit; 19178eb6488eSEric Joyner 19188eb6488eSEric Joyner index = (vtag >> 5) & 0x7F; 19198eb6488eSEric Joyner bit = vtag & 0x1F; 1920b1d5caf3SKevin Bowling sc->shadow_vfta[index] |= (1 << bit); 1921b1d5caf3SKevin Bowling ++sc->num_vlans; 1922c19c7afeSEric Joyner ixgbe_setup_vlan_hw_support(ctx); 1923c19c7afeSEric Joyner } /* ixgbe_if_vlan_register */ 19248eb6488eSEric Joyner 19258eb6488eSEric Joyner /************************************************************************ 1926c19c7afeSEric Joyner * ixgbe_if_vlan_unregister 19278eb6488eSEric Joyner * 19288eb6488eSEric Joyner * Run via vlan unconfig EVENT, remove our entry in the soft vfta. 19298eb6488eSEric Joyner ************************************************************************/ 19308eb6488eSEric Joyner static void 1931c19c7afeSEric Joyner ixgbe_if_vlan_unregister(if_ctx_t ctx, u16 vtag) 19328eb6488eSEric Joyner { 1933b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 19348eb6488eSEric Joyner u16 index, bit; 19358eb6488eSEric Joyner 19368eb6488eSEric Joyner index = (vtag >> 5) & 0x7F; 19378eb6488eSEric Joyner bit = vtag & 0x1F; 1938b1d5caf3SKevin Bowling sc->shadow_vfta[index] &= ~(1 << bit); 1939b1d5caf3SKevin Bowling --sc->num_vlans; 19408eb6488eSEric Joyner /* Re-init to load the changes */ 1941c19c7afeSEric Joyner ixgbe_setup_vlan_hw_support(ctx); 1942c19c7afeSEric Joyner } /* ixgbe_if_vlan_unregister */ 19438eb6488eSEric Joyner 19448eb6488eSEric Joyner /************************************************************************ 19458eb6488eSEric Joyner * ixgbe_setup_vlan_hw_support 19468eb6488eSEric Joyner ************************************************************************/ 19478eb6488eSEric Joyner static void 1948c19c7afeSEric Joyner ixgbe_setup_vlan_hw_support(if_ctx_t ctx) 19498eb6488eSEric Joyner { 1950ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 1951b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 1952b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 19538eb6488eSEric Joyner struct rx_ring *rxr; 19548eb6488eSEric Joyner int i; 19558eb6488eSEric Joyner u32 ctrl; 19568eb6488eSEric Joyner 19578eb6488eSEric Joyner 19588eb6488eSEric Joyner /* 19598eb6488eSEric Joyner * We get here thru init_locked, meaning 19608eb6488eSEric Joyner * a soft reset, this has already cleared 19618eb6488eSEric Joyner * the VFTA and other state, so if there 19628eb6488eSEric Joyner * have been no vlan's registered do nothing. 19638eb6488eSEric Joyner */ 1964ff06a8dbSJustin Hibbits if (sc->num_vlans == 0 || (if_getcapenable(ifp) & IFCAP_VLAN_HWTAGGING) == 0) { 1965e7abb897SKristof Provost /* Clear the vlan hw flag */ 1966e7abb897SKristof Provost for (i = 0; i < sc->num_rx_queues; i++) { 1967e7abb897SKristof Provost rxr = &sc->rx_queues[i].rxr; 1968e7abb897SKristof Provost /* On 82599 the VLAN enable is per/queue in RXDCTL */ 1969e7abb897SKristof Provost if (hw->mac.type != ixgbe_mac_82598EB) { 1970e7abb897SKristof Provost ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); 1971e7abb897SKristof Provost ctrl &= ~IXGBE_RXDCTL_VME; 1972e7abb897SKristof Provost IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl); 1973e7abb897SKristof Provost } 1974e7abb897SKristof Provost rxr->vtag_strip = false; 1975e7abb897SKristof Provost } 1976e7abb897SKristof Provost ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); 1977e7abb897SKristof Provost /* Enable the Filter Table if enabled */ 1978e7abb897SKristof Provost ctrl |= IXGBE_VLNCTRL_CFIEN; 1979e7abb897SKristof Provost ctrl &= ~IXGBE_VLNCTRL_VFE; 1980e7abb897SKristof Provost if (hw->mac.type == ixgbe_mac_82598EB) 1981e7abb897SKristof Provost ctrl &= ~IXGBE_VLNCTRL_VME; 1982e7abb897SKristof Provost IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); 19838eb6488eSEric Joyner return; 1984e7abb897SKristof Provost } 19858eb6488eSEric Joyner 19868eb6488eSEric Joyner /* Setup the queues for vlans */ 1987ff06a8dbSJustin Hibbits if (if_getcapenable(ifp) & IFCAP_VLAN_HWTAGGING) { 1988b1d5caf3SKevin Bowling for (i = 0; i < sc->num_rx_queues; i++) { 1989b1d5caf3SKevin Bowling rxr = &sc->rx_queues[i].rxr; 19908eb6488eSEric Joyner /* On 82599 the VLAN enable is per/queue in RXDCTL */ 19918eb6488eSEric Joyner if (hw->mac.type != ixgbe_mac_82598EB) { 19928eb6488eSEric Joyner ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); 19938eb6488eSEric Joyner ctrl |= IXGBE_RXDCTL_VME; 19948eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl); 19958eb6488eSEric Joyner } 199679b36ec9SKevin Bowling rxr->vtag_strip = true; 1997758cc3dcSJack F Vogel } 19989c92bb71SSean Bruno } 1999758cc3dcSJack F Vogel 2000ff06a8dbSJustin Hibbits if ((if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER) == 0) 20018eb6488eSEric Joyner return; 20028eb6488eSEric Joyner /* 20038eb6488eSEric Joyner * A soft reset zero's out the VFTA, so 20048eb6488eSEric Joyner * we need to repopulate it now. 20058eb6488eSEric Joyner */ 20068eb6488eSEric Joyner for (i = 0; i < IXGBE_VFTA_SIZE; i++) 2007b1d5caf3SKevin Bowling if (sc->shadow_vfta[i] != 0) 20088eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), 2009b1d5caf3SKevin Bowling sc->shadow_vfta[i]); 20108eb6488eSEric Joyner 20118eb6488eSEric Joyner ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); 20128eb6488eSEric Joyner /* Enable the Filter Table if enabled */ 2013ff06a8dbSJustin Hibbits if (if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER) { 20148eb6488eSEric Joyner ctrl &= ~IXGBE_VLNCTRL_CFIEN; 20158eb6488eSEric Joyner ctrl |= IXGBE_VLNCTRL_VFE; 20168eb6488eSEric Joyner } 20178eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 20188eb6488eSEric Joyner ctrl |= IXGBE_VLNCTRL_VME; 20198eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); 20208eb6488eSEric Joyner } /* ixgbe_setup_vlan_hw_support */ 20218eb6488eSEric Joyner 20228eb6488eSEric Joyner /************************************************************************ 20238eb6488eSEric Joyner * ixgbe_get_slot_info 20248eb6488eSEric Joyner * 20258eb6488eSEric Joyner * Get the width and transaction speed of 20268eb6488eSEric Joyner * the slot this adapter is plugged into. 20278eb6488eSEric Joyner ************************************************************************/ 20288eb6488eSEric Joyner static void 2029b1d5caf3SKevin Bowling ixgbe_get_slot_info(struct ixgbe_softc *sc) 20308eb6488eSEric Joyner { 2031b1d5caf3SKevin Bowling device_t dev = iflib_get_dev(sc->ctx); 2032b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 203379b36ec9SKevin Bowling int bus_info_valid = true; 20348eb6488eSEric Joyner u32 offset; 20358eb6488eSEric Joyner u16 link; 20368eb6488eSEric Joyner 20378eb6488eSEric Joyner /* Some devices are behind an internal bridge */ 20388eb6488eSEric Joyner switch (hw->device_id) { 20398eb6488eSEric Joyner case IXGBE_DEV_ID_82599_SFP_SF_QP: 20408eb6488eSEric Joyner case IXGBE_DEV_ID_82599_QSFP_SF_QP: 20418eb6488eSEric Joyner goto get_parent_info; 20428eb6488eSEric Joyner default: 20438eb6488eSEric Joyner break; 20448eb6488eSEric Joyner } 20458eb6488eSEric Joyner 20468eb6488eSEric Joyner ixgbe_get_bus_info(hw); 20478eb6488eSEric Joyner 20488eb6488eSEric Joyner /* 20498eb6488eSEric Joyner * Some devices don't use PCI-E, but there is no need 20508eb6488eSEric Joyner * to display "Unknown" for bus speed and width. 20518eb6488eSEric Joyner */ 20528eb6488eSEric Joyner switch (hw->mac.type) { 20538eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 20548eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 20558eb6488eSEric Joyner return; 20568eb6488eSEric Joyner default: 20578eb6488eSEric Joyner goto display; 20588eb6488eSEric Joyner } 20598eb6488eSEric Joyner 20608eb6488eSEric Joyner get_parent_info: 20618eb6488eSEric Joyner /* 20628eb6488eSEric Joyner * For the Quad port adapter we need to parse back 20638eb6488eSEric Joyner * up the PCI tree to find the speed of the expansion 20648eb6488eSEric Joyner * slot into which this adapter is plugged. A bit more work. 20658eb6488eSEric Joyner */ 20668eb6488eSEric Joyner dev = device_get_parent(device_get_parent(dev)); 20678eb6488eSEric Joyner #ifdef IXGBE_DEBUG 20688eb6488eSEric Joyner device_printf(dev, "parent pcib = %x,%x,%x\n", pci_get_bus(dev), 20698eb6488eSEric Joyner pci_get_slot(dev), pci_get_function(dev)); 20708eb6488eSEric Joyner #endif 20718eb6488eSEric Joyner dev = device_get_parent(device_get_parent(dev)); 20728eb6488eSEric Joyner #ifdef IXGBE_DEBUG 20738eb6488eSEric Joyner device_printf(dev, "slot pcib = %x,%x,%x\n", pci_get_bus(dev), 20748eb6488eSEric Joyner pci_get_slot(dev), pci_get_function(dev)); 20758eb6488eSEric Joyner #endif 20768eb6488eSEric Joyner /* Now get the PCI Express Capabilities offset */ 20778eb6488eSEric Joyner if (pci_find_cap(dev, PCIY_EXPRESS, &offset)) { 20788eb6488eSEric Joyner /* 20798eb6488eSEric Joyner * Hmm...can't get PCI-Express capabilities. 20808eb6488eSEric Joyner * Falling back to default method. 20818eb6488eSEric Joyner */ 208279b36ec9SKevin Bowling bus_info_valid = false; 20838eb6488eSEric Joyner ixgbe_get_bus_info(hw); 20848eb6488eSEric Joyner goto display; 20858eb6488eSEric Joyner } 20868eb6488eSEric Joyner /* ...and read the Link Status Register */ 20878eb6488eSEric Joyner link = pci_read_config(dev, offset + PCIER_LINK_STA, 2); 20888eb6488eSEric Joyner ixgbe_set_pci_config_data_generic(hw, link); 20898eb6488eSEric Joyner 20908eb6488eSEric Joyner display: 20918eb6488eSEric Joyner device_printf(dev, "PCI Express Bus: Speed %s %s\n", 20928eb6488eSEric Joyner ((hw->bus.speed == ixgbe_bus_speed_8000) ? "8.0GT/s" : 20938eb6488eSEric Joyner (hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0GT/s" : 20948eb6488eSEric Joyner (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5GT/s" : 20958eb6488eSEric Joyner "Unknown"), 20968eb6488eSEric Joyner ((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" : 20978eb6488eSEric Joyner (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" : 20988eb6488eSEric Joyner (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" : 20998eb6488eSEric Joyner "Unknown")); 21008eb6488eSEric Joyner 21018eb6488eSEric Joyner if (bus_info_valid) { 21028eb6488eSEric Joyner if ((hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) && 21038eb6488eSEric Joyner ((hw->bus.width <= ixgbe_bus_width_pcie_x4) && 21048eb6488eSEric Joyner (hw->bus.speed == ixgbe_bus_speed_2500))) { 21058eb6488eSEric Joyner device_printf(dev, "PCI-Express bandwidth available for this card\n is not sufficient for optimal performance.\n"); 21068eb6488eSEric Joyner device_printf(dev, "For optimal performance a x8 PCIE, or x4 PCIE Gen2 slot is required.\n"); 21078eb6488eSEric Joyner } 21088eb6488eSEric Joyner if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) && 21098eb6488eSEric Joyner ((hw->bus.width <= ixgbe_bus_width_pcie_x8) && 21108eb6488eSEric Joyner (hw->bus.speed < ixgbe_bus_speed_8000))) { 21118eb6488eSEric Joyner device_printf(dev, "PCI-Express bandwidth available for this card\n is not sufficient for optimal performance.\n"); 21128eb6488eSEric Joyner device_printf(dev, "For optimal performance a x8 PCIE Gen3 slot is required.\n"); 21138eb6488eSEric Joyner } 21148eb6488eSEric Joyner } else 21158eb6488eSEric Joyner device_printf(dev, "Unable to determine slot speed/width. The speed/width reported are that of the internal switch.\n"); 21168eb6488eSEric Joyner 21178eb6488eSEric Joyner return; 21188eb6488eSEric Joyner } /* ixgbe_get_slot_info */ 21198eb6488eSEric Joyner 21208eb6488eSEric Joyner /************************************************************************ 2121c19c7afeSEric Joyner * ixgbe_if_msix_intr_assign 2122c19c7afeSEric Joyner * 2123c19c7afeSEric Joyner * Setup MSI-X Interrupt resources and handlers 21248eb6488eSEric Joyner ************************************************************************/ 2125c19c7afeSEric Joyner static int 2126c19c7afeSEric Joyner ixgbe_if_msix_intr_assign(if_ctx_t ctx, int msix) 21278eb6488eSEric Joyner { 2128b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2129b1d5caf3SKevin Bowling struct ix_rx_queue *rx_que = sc->rx_queues; 2130c19c7afeSEric Joyner struct ix_tx_queue *tx_que; 2131c19c7afeSEric Joyner int error, rid, vector = 0; 2132c19c7afeSEric Joyner char buf[16]; 21338eb6488eSEric Joyner 2134c19c7afeSEric Joyner /* Admin Que is vector 0*/ 2135c19c7afeSEric Joyner rid = vector + 1; 2136b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++, vector++, rx_que++) { 2137c19c7afeSEric Joyner rid = vector + 1; 2138c19c7afeSEric Joyner 2139c19c7afeSEric Joyner snprintf(buf, sizeof(buf), "rxq%d", i); 2140c19c7afeSEric Joyner error = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid, 214181be6552SMatt Macy IFLIB_INTR_RXTX, ixgbe_msix_que, rx_que, rx_que->rxr.me, buf); 2142c19c7afeSEric Joyner 2143c19c7afeSEric Joyner if (error) { 2144c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), 2145c19c7afeSEric Joyner "Failed to allocate que int %d err: %d", i, error); 2146b1d5caf3SKevin Bowling sc->num_rx_queues = i + 1; 2147c19c7afeSEric Joyner goto fail; 21488eb6488eSEric Joyner } 21498eb6488eSEric Joyner 2150c19c7afeSEric Joyner rx_que->msix = vector; 2151c19c7afeSEric Joyner } 2152b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_tx_queues; i++) { 2153c19c7afeSEric Joyner snprintf(buf, sizeof(buf), "txq%d", i); 2154b1d5caf3SKevin Bowling tx_que = &sc->tx_queues[i]; 2155b1d5caf3SKevin Bowling tx_que->msix = i % sc->num_rx_queues; 2156c19c7afeSEric Joyner iflib_softirq_alloc_generic(ctx, 2157b1d5caf3SKevin Bowling &sc->rx_queues[tx_que->msix].que_irq, 2158c19c7afeSEric Joyner IFLIB_INTR_TX, tx_que, tx_que->txr.me, buf); 2159c19c7afeSEric Joyner } 2160c19c7afeSEric Joyner rid = vector + 1; 2161b1d5caf3SKevin Bowling error = iflib_irq_alloc_generic(ctx, &sc->irq, rid, 2162b1d5caf3SKevin Bowling IFLIB_INTR_ADMIN, ixgbe_msix_link, sc, 0, "aq"); 2163c19c7afeSEric Joyner if (error) { 2164c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), 2165c19c7afeSEric Joyner "Failed to register admin handler"); 2166c19c7afeSEric Joyner return (error); 2167c19c7afeSEric Joyner } 2168c19c7afeSEric Joyner 2169b1d5caf3SKevin Bowling sc->vector = vector; 2170c19c7afeSEric Joyner 2171c19c7afeSEric Joyner return (0); 2172c19c7afeSEric Joyner fail: 2173b1d5caf3SKevin Bowling iflib_irq_free(ctx, &sc->irq); 2174b1d5caf3SKevin Bowling rx_que = sc->rx_queues; 2175b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++, rx_que++) 2176c19c7afeSEric Joyner iflib_irq_free(ctx, &rx_que->que_irq); 2177c19c7afeSEric Joyner 2178c19c7afeSEric Joyner return (error); 2179c19c7afeSEric Joyner } /* ixgbe_if_msix_intr_assign */ 2180c19c7afeSEric Joyner 218164881da4SSai Rajesh Tallamraju static inline void 2182b1d5caf3SKevin Bowling ixgbe_perform_aim(struct ixgbe_softc *sc, struct ix_rx_queue *que) 218364881da4SSai Rajesh Tallamraju { 218464881da4SSai Rajesh Tallamraju uint32_t newitr = 0; 218564881da4SSai Rajesh Tallamraju struct rx_ring *rxr = &que->rxr; 2186f72de14eSKevin Bowling /* FIXME struct tx_ring *txr = ... ->txr; */ 218764881da4SSai Rajesh Tallamraju 218864881da4SSai Rajesh Tallamraju /* 218964881da4SSai Rajesh Tallamraju * Do Adaptive Interrupt Moderation: 219064881da4SSai Rajesh Tallamraju * - Write out last calculated setting 219164881da4SSai Rajesh Tallamraju * - Calculate based on average size over 219264881da4SSai Rajesh Tallamraju * the last interval. 219364881da4SSai Rajesh Tallamraju */ 219464881da4SSai Rajesh Tallamraju if (que->eitr_setting) { 2195b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(que->msix), 219664881da4SSai Rajesh Tallamraju que->eitr_setting); 219764881da4SSai Rajesh Tallamraju } 219864881da4SSai Rajesh Tallamraju 219964881da4SSai Rajesh Tallamraju que->eitr_setting = 0; 220064881da4SSai Rajesh Tallamraju /* Idle, do nothing */ 220164881da4SSai Rajesh Tallamraju if (rxr->bytes == 0) { 2202f72de14eSKevin Bowling /* FIXME && txr->bytes == 0 */ 220364881da4SSai Rajesh Tallamraju return; 220464881da4SSai Rajesh Tallamraju } 220564881da4SSai Rajesh Tallamraju 2206f72de14eSKevin Bowling if ((rxr->bytes) && (rxr->packets)) 2207f72de14eSKevin Bowling newitr = rxr->bytes / rxr->packets; 2208f72de14eSKevin Bowling /* FIXME for transmit accounting 2209f72de14eSKevin Bowling * if ((txr->bytes) && (txr->packets)) 2210f72de14eSKevin Bowling * newitr = txr->bytes/txr->packets; 2211f72de14eSKevin Bowling * if ((rxr->bytes) && (rxr->packets)) 2212f72de14eSKevin Bowling * newitr = max(newitr, (rxr->bytes / rxr->packets)); 2213f72de14eSKevin Bowling */ 221464881da4SSai Rajesh Tallamraju 221564881da4SSai Rajesh Tallamraju newitr += 24; /* account for hardware frame, crc */ 221664881da4SSai Rajesh Tallamraju /* set an upper boundary */ 221764881da4SSai Rajesh Tallamraju newitr = min(newitr, 3000); 221864881da4SSai Rajesh Tallamraju 221964881da4SSai Rajesh Tallamraju /* Be nice to the mid range */ 222064881da4SSai Rajesh Tallamraju if ((newitr > 300) && (newitr < 1200)) { 222164881da4SSai Rajesh Tallamraju newitr = (newitr / 3); 222264881da4SSai Rajesh Tallamraju } else { 222364881da4SSai Rajesh Tallamraju newitr = (newitr / 2); 222464881da4SSai Rajesh Tallamraju } 222564881da4SSai Rajesh Tallamraju 2226b1d5caf3SKevin Bowling if (sc->hw.mac.type == ixgbe_mac_82598EB) { 222764881da4SSai Rajesh Tallamraju newitr |= newitr << 16; 222864881da4SSai Rajesh Tallamraju } else { 222964881da4SSai Rajesh Tallamraju newitr |= IXGBE_EITR_CNT_WDIS; 223064881da4SSai Rajesh Tallamraju } 223164881da4SSai Rajesh Tallamraju 223264881da4SSai Rajesh Tallamraju /* save for next interrupt */ 223364881da4SSai Rajesh Tallamraju que->eitr_setting = newitr; 223464881da4SSai Rajesh Tallamraju 223564881da4SSai Rajesh Tallamraju /* Reset state */ 2236f72de14eSKevin Bowling /* FIXME txr->bytes = 0; */ 2237f72de14eSKevin Bowling /* FIXME txr->packets = 0; */ 223864881da4SSai Rajesh Tallamraju rxr->bytes = 0; 223964881da4SSai Rajesh Tallamraju rxr->packets = 0; 224064881da4SSai Rajesh Tallamraju 224164881da4SSai Rajesh Tallamraju return; 224264881da4SSai Rajesh Tallamraju } 224364881da4SSai Rajesh Tallamraju 2244c19c7afeSEric Joyner /********************************************************************* 22458eb6488eSEric Joyner * ixgbe_msix_que - MSI-X Queue Interrupt Service routine 2246c19c7afeSEric Joyner **********************************************************************/ 2247c19c7afeSEric Joyner static int 22488eb6488eSEric Joyner ixgbe_msix_que(void *arg) 22498eb6488eSEric Joyner { 2250c19c7afeSEric Joyner struct ix_rx_queue *que = arg; 2251b1d5caf3SKevin Bowling struct ixgbe_softc *sc = que->sc; 2252ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(que->sc->ctx); 22538eb6488eSEric Joyner 22548eb6488eSEric Joyner /* Protect against spurious interrupts */ 2255ff06a8dbSJustin Hibbits if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) 22566c351041SEric Joyner return (FILTER_HANDLED); 22578eb6488eSEric Joyner 2258b1d5caf3SKevin Bowling ixgbe_disable_queue(sc, que->msix); 22598eb6488eSEric Joyner ++que->irqs; 22608eb6488eSEric Joyner 226164881da4SSai Rajesh Tallamraju /* Check for AIM */ 2262b1d5caf3SKevin Bowling if (sc->enable_aim) { 2263b1d5caf3SKevin Bowling ixgbe_perform_aim(sc, que); 226464881da4SSai Rajesh Tallamraju } 226564881da4SSai Rajesh Tallamraju 2266c19c7afeSEric Joyner return (FILTER_SCHEDULE_THREAD); 22678eb6488eSEric Joyner } /* ixgbe_msix_que */ 22688eb6488eSEric Joyner 22698eb6488eSEric Joyner /************************************************************************ 22708eb6488eSEric Joyner * ixgbe_media_status - Media Ioctl callback 22718eb6488eSEric Joyner * 22728eb6488eSEric Joyner * Called whenever the user queries the status of 22738eb6488eSEric Joyner * the interface using ifconfig. 22748eb6488eSEric Joyner ************************************************************************/ 22758eb6488eSEric Joyner static void 2276c19c7afeSEric Joyner ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr) 22778eb6488eSEric Joyner { 2278b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2279b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 22808eb6488eSEric Joyner int layer; 22818eb6488eSEric Joyner 2282c19c7afeSEric Joyner INIT_DEBUGOUT("ixgbe_if_media_status: begin"); 2283c19c7afeSEric Joyner 22848eb6488eSEric Joyner ifmr->ifm_status = IFM_AVALID; 22858eb6488eSEric Joyner ifmr->ifm_active = IFM_ETHER; 22868eb6488eSEric Joyner 2287b1d5caf3SKevin Bowling if (!sc->link_active) 22888eb6488eSEric Joyner return; 22898eb6488eSEric Joyner 22908eb6488eSEric Joyner ifmr->ifm_status |= IFM_ACTIVE; 2291b1d5caf3SKevin Bowling layer = sc->phy_layer; 22928eb6488eSEric Joyner 22938eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T || 22948eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_T || 22958eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_100BASE_TX || 22968eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_10BASE_T) 2297b1d5caf3SKevin Bowling switch (sc->link_speed) { 22988eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 22998eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_T | IFM_FDX; 23008eb6488eSEric Joyner break; 23018eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 23028eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_T | IFM_FDX; 23038eb6488eSEric Joyner break; 23048eb6488eSEric Joyner case IXGBE_LINK_SPEED_100_FULL: 23058eb6488eSEric Joyner ifmr->ifm_active |= IFM_100_TX | IFM_FDX; 23068eb6488eSEric Joyner break; 23078eb6488eSEric Joyner case IXGBE_LINK_SPEED_10_FULL: 23088eb6488eSEric Joyner ifmr->ifm_active |= IFM_10_T | IFM_FDX; 23098eb6488eSEric Joyner break; 23108eb6488eSEric Joyner } 2311d381c807SPiotr Pietruszewski if (hw->mac.type == ixgbe_mac_X550) 2312d381c807SPiotr Pietruszewski switch (sc->link_speed) { 2313d381c807SPiotr Pietruszewski case IXGBE_LINK_SPEED_5GB_FULL: 2314d381c807SPiotr Pietruszewski ifmr->ifm_active |= IFM_5000_T | IFM_FDX; 2315d381c807SPiotr Pietruszewski break; 2316d381c807SPiotr Pietruszewski case IXGBE_LINK_SPEED_2_5GB_FULL: 2317d381c807SPiotr Pietruszewski ifmr->ifm_active |= IFM_2500_T | IFM_FDX; 2318d381c807SPiotr Pietruszewski break; 2319d381c807SPiotr Pietruszewski } 23208eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || 23218eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) 2322b1d5caf3SKevin Bowling switch (sc->link_speed) { 23238eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 23248eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX; 23258eb6488eSEric Joyner break; 23268eb6488eSEric Joyner } 23278eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) 2328b1d5caf3SKevin Bowling switch (sc->link_speed) { 23298eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 23308eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_LR | IFM_FDX; 23318eb6488eSEric Joyner break; 23328eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 23338eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; 23348eb6488eSEric Joyner break; 23358eb6488eSEric Joyner } 23368eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM) 2337b1d5caf3SKevin Bowling switch (sc->link_speed) { 23388eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 23398eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX; 23408eb6488eSEric Joyner break; 23418eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 23428eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; 23438eb6488eSEric Joyner break; 23448eb6488eSEric Joyner } 23458eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR || 23468eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) 2347b1d5caf3SKevin Bowling switch (sc->link_speed) { 23488eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 23498eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; 23508eb6488eSEric Joyner break; 23518eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 23528eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_SX | IFM_FDX; 23538eb6488eSEric Joyner break; 23548eb6488eSEric Joyner } 23558eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) 2356b1d5caf3SKevin Bowling switch (sc->link_speed) { 23578eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 23588eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; 23598eb6488eSEric Joyner break; 23608eb6488eSEric Joyner } 23618eb6488eSEric Joyner /* 23628eb6488eSEric Joyner * XXX: These need to use the proper media types once 23638eb6488eSEric Joyner * they're added. 23648eb6488eSEric Joyner */ 23658eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE 23668eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 2367b1d5caf3SKevin Bowling switch (sc->link_speed) { 23688eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 23698eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; 23708eb6488eSEric Joyner break; 23718eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 23728eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; 23738eb6488eSEric Joyner break; 23748eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 23758eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; 23768eb6488eSEric Joyner break; 23778eb6488eSEric Joyner } 23788eb6488eSEric Joyner else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 || 23798eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX || 23808eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 2381b1d5caf3SKevin Bowling switch (sc->link_speed) { 23828eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 23838eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; 23848eb6488eSEric Joyner break; 23858eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 23868eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; 23878eb6488eSEric Joyner break; 23888eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 23898eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; 23908eb6488eSEric Joyner break; 23918eb6488eSEric Joyner } 23928eb6488eSEric Joyner #else 23938eb6488eSEric Joyner if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 2394b1d5caf3SKevin Bowling switch (sc->link_speed) { 23958eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 23968eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_KR | IFM_FDX; 23978eb6488eSEric Joyner break; 23988eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 23998eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; 24008eb6488eSEric Joyner break; 24018eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 24028eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; 24038eb6488eSEric Joyner break; 24048eb6488eSEric Joyner } 24058eb6488eSEric Joyner else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 || 24068eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX || 24078eb6488eSEric Joyner layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 2408b1d5caf3SKevin Bowling switch (sc->link_speed) { 24098eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL: 24108eb6488eSEric Joyner ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX; 24118eb6488eSEric Joyner break; 24128eb6488eSEric Joyner case IXGBE_LINK_SPEED_2_5GB_FULL: 24138eb6488eSEric Joyner ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; 24148eb6488eSEric Joyner break; 24158eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL: 24168eb6488eSEric Joyner ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; 24178eb6488eSEric Joyner break; 24188eb6488eSEric Joyner } 24198eb6488eSEric Joyner #endif 24208eb6488eSEric Joyner 24218eb6488eSEric Joyner /* If nothing is recognized... */ 24228eb6488eSEric Joyner if (IFM_SUBTYPE(ifmr->ifm_active) == 0) 24238eb6488eSEric Joyner ifmr->ifm_active |= IFM_UNKNOWN; 24248eb6488eSEric Joyner 24258eb6488eSEric Joyner /* Display current flow control setting used on link */ 24268eb6488eSEric Joyner if (hw->fc.current_mode == ixgbe_fc_rx_pause || 24278eb6488eSEric Joyner hw->fc.current_mode == ixgbe_fc_full) 24288eb6488eSEric Joyner ifmr->ifm_active |= IFM_ETH_RXPAUSE; 24298eb6488eSEric Joyner if (hw->fc.current_mode == ixgbe_fc_tx_pause || 24308eb6488eSEric Joyner hw->fc.current_mode == ixgbe_fc_full) 24318eb6488eSEric Joyner ifmr->ifm_active |= IFM_ETH_TXPAUSE; 24328eb6488eSEric Joyner } /* ixgbe_media_status */ 24338eb6488eSEric Joyner 24348eb6488eSEric Joyner /************************************************************************ 24358eb6488eSEric Joyner * ixgbe_media_change - Media Ioctl callback 24368eb6488eSEric Joyner * 24378eb6488eSEric Joyner * Called when the user changes speed/duplex using 24388eb6488eSEric Joyner * media/mediopt option with ifconfig. 24398eb6488eSEric Joyner ************************************************************************/ 24408eb6488eSEric Joyner static int 2441c19c7afeSEric Joyner ixgbe_if_media_change(if_ctx_t ctx) 24428eb6488eSEric Joyner { 2443b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2444c19c7afeSEric Joyner struct ifmedia *ifm = iflib_get_media(ctx); 2445b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 24468eb6488eSEric Joyner ixgbe_link_speed speed = 0; 24478eb6488eSEric Joyner 2448c19c7afeSEric Joyner INIT_DEBUGOUT("ixgbe_if_media_change: begin"); 24498eb6488eSEric Joyner 24508eb6488eSEric Joyner if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 24518eb6488eSEric Joyner return (EINVAL); 24528eb6488eSEric Joyner 24538eb6488eSEric Joyner if (hw->phy.media_type == ixgbe_media_type_backplane) 2454c19c7afeSEric Joyner return (EPERM); 24558eb6488eSEric Joyner 24568eb6488eSEric Joyner /* 24578eb6488eSEric Joyner * We don't actually need to check against the supported 24588eb6488eSEric Joyner * media types of the adapter; ifmedia will take care of 24598eb6488eSEric Joyner * that for us. 24608eb6488eSEric Joyner */ 24618eb6488eSEric Joyner switch (IFM_SUBTYPE(ifm->ifm_media)) { 24628eb6488eSEric Joyner case IFM_AUTO: 24638eb6488eSEric Joyner case IFM_10G_T: 24648eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_100_FULL; 24658eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 24668eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10GB_FULL; 24678eb6488eSEric Joyner break; 24688eb6488eSEric Joyner case IFM_10G_LRM: 24698eb6488eSEric Joyner case IFM_10G_LR: 24708eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE 24718eb6488eSEric Joyner case IFM_10G_SR: /* KR, too */ 24728eb6488eSEric Joyner case IFM_10G_CX4: /* KX4 */ 24738eb6488eSEric Joyner #else 24748eb6488eSEric Joyner case IFM_10G_KR: 24758eb6488eSEric Joyner case IFM_10G_KX4: 24768eb6488eSEric Joyner #endif 24778eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 24788eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10GB_FULL; 24798eb6488eSEric Joyner break; 24808eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE 24818eb6488eSEric Joyner case IFM_1000_CX: /* KX */ 24828eb6488eSEric Joyner #else 24838eb6488eSEric Joyner case IFM_1000_KX: 24848eb6488eSEric Joyner #endif 24858eb6488eSEric Joyner case IFM_1000_LX: 24868eb6488eSEric Joyner case IFM_1000_SX: 24878eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 24888eb6488eSEric Joyner break; 24898eb6488eSEric Joyner case IFM_1000_T: 24908eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_100_FULL; 24918eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_1GB_FULL; 24928eb6488eSEric Joyner break; 24938eb6488eSEric Joyner case IFM_10G_TWINAX: 24948eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10GB_FULL; 24958eb6488eSEric Joyner break; 2496d381c807SPiotr Pietruszewski case IFM_5000_T: 2497d381c807SPiotr Pietruszewski speed |= IXGBE_LINK_SPEED_5GB_FULL; 2498d381c807SPiotr Pietruszewski break; 2499d381c807SPiotr Pietruszewski case IFM_2500_T: 2500d381c807SPiotr Pietruszewski speed |= IXGBE_LINK_SPEED_2_5GB_FULL; 2501d381c807SPiotr Pietruszewski break; 25028eb6488eSEric Joyner case IFM_100_TX: 25038eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_100_FULL; 25048eb6488eSEric Joyner break; 25058eb6488eSEric Joyner case IFM_10_T: 25068eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10_FULL; 25078eb6488eSEric Joyner break; 25088eb6488eSEric Joyner default: 25098eb6488eSEric Joyner goto invalid; 25108eb6488eSEric Joyner } 25118eb6488eSEric Joyner 251279b36ec9SKevin Bowling hw->mac.autotry_restart = true; 251379b36ec9SKevin Bowling hw->mac.ops.setup_link(hw, speed, true); 2514b1d5caf3SKevin Bowling sc->advertise = 2515d381c807SPiotr Pietruszewski ((speed & IXGBE_LINK_SPEED_10GB_FULL) ? 0x4 : 0) | 2516d381c807SPiotr Pietruszewski ((speed & IXGBE_LINK_SPEED_5GB_FULL) ? 0x20 : 0) | 2517d381c807SPiotr Pietruszewski ((speed & IXGBE_LINK_SPEED_2_5GB_FULL) ? 0x10 : 0) | 2518d381c807SPiotr Pietruszewski ((speed & IXGBE_LINK_SPEED_1GB_FULL) ? 0x2 : 0) | 2519d381c807SPiotr Pietruszewski ((speed & IXGBE_LINK_SPEED_100_FULL) ? 0x1 : 0) | 2520d381c807SPiotr Pietruszewski ((speed & IXGBE_LINK_SPEED_10_FULL) ? 0x8 : 0); 25218eb6488eSEric Joyner 25228eb6488eSEric Joyner return (0); 25238eb6488eSEric Joyner 25248eb6488eSEric Joyner invalid: 2525c19c7afeSEric Joyner device_printf(iflib_get_dev(ctx), "Invalid media type!\n"); 25268eb6488eSEric Joyner 25278eb6488eSEric Joyner return (EINVAL); 2528c19c7afeSEric Joyner } /* ixgbe_if_media_change */ 25298eb6488eSEric Joyner 25308eb6488eSEric Joyner /************************************************************************ 25318eb6488eSEric Joyner * ixgbe_set_promisc 25328eb6488eSEric Joyner ************************************************************************/ 2533c19c7afeSEric Joyner static int 2534c19c7afeSEric Joyner ixgbe_if_promisc_set(if_ctx_t ctx, int flags) 25358eb6488eSEric Joyner { 2536b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2537ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 25388eb6488eSEric Joyner u32 rctl; 2539c19c7afeSEric Joyner int mcnt = 0; 25408eb6488eSEric Joyner 2541b1d5caf3SKevin Bowling rctl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL); 25428eb6488eSEric Joyner rctl &= (~IXGBE_FCTRL_UPE); 2543ff06a8dbSJustin Hibbits if (if_getflags(ifp) & IFF_ALLMULTI) 25448eb6488eSEric Joyner mcnt = MAX_NUM_MULTICAST_ADDRESSES; 25458eb6488eSEric Joyner else { 2546ba76aa63SGleb Smirnoff mcnt = min(if_llmaddr_count(ifp), MAX_NUM_MULTICAST_ADDRESSES); 25478eb6488eSEric Joyner } 25488eb6488eSEric Joyner if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) 25498eb6488eSEric Joyner rctl &= (~IXGBE_FCTRL_MPE); 2550b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, rctl); 25518eb6488eSEric Joyner 2552ff06a8dbSJustin Hibbits if (if_getflags(ifp) & IFF_PROMISC) { 25538eb6488eSEric Joyner rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 2554b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, rctl); 2555ff06a8dbSJustin Hibbits } else if (if_getflags(ifp) & IFF_ALLMULTI) { 25568eb6488eSEric Joyner rctl |= IXGBE_FCTRL_MPE; 25578eb6488eSEric Joyner rctl &= ~IXGBE_FCTRL_UPE; 2558b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, rctl); 25598eb6488eSEric Joyner } 2560c19c7afeSEric Joyner return (0); 2561c19c7afeSEric Joyner } /* ixgbe_if_promisc_set */ 25628eb6488eSEric Joyner 25638eb6488eSEric Joyner /************************************************************************ 25648eb6488eSEric Joyner * ixgbe_msix_link - Link status change ISR (MSI/MSI-X) 25658eb6488eSEric Joyner ************************************************************************/ 2566c19c7afeSEric Joyner static int 25678eb6488eSEric Joyner ixgbe_msix_link(void *arg) 25688eb6488eSEric Joyner { 2569b1d5caf3SKevin Bowling struct ixgbe_softc *sc = arg; 2570b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 25718eb6488eSEric Joyner u32 eicr, eicr_mask; 25728eb6488eSEric Joyner s32 retval; 25738eb6488eSEric Joyner 2574b1d5caf3SKevin Bowling ++sc->link_irq; 25758eb6488eSEric Joyner 25768eb6488eSEric Joyner /* Pause other interrupts */ 25778eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER); 25788eb6488eSEric Joyner 25798eb6488eSEric Joyner /* First get the cause */ 25808eb6488eSEric Joyner eicr = IXGBE_READ_REG(hw, IXGBE_EICS); 25818eb6488eSEric Joyner /* Be sure the queue bits are not cleared */ 25828eb6488eSEric Joyner eicr &= ~IXGBE_EICR_RTX_QUEUE; 25838eb6488eSEric Joyner /* Clear interrupt with write */ 25848eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr); 25858eb6488eSEric Joyner 25868eb6488eSEric Joyner /* Link status change */ 25878eb6488eSEric Joyner if (eicr & IXGBE_EICR_LSC) { 25888eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); 2589b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_LSC; 25908eb6488eSEric Joyner } 25918eb6488eSEric Joyner 2592b1d5caf3SKevin Bowling if (sc->hw.mac.type != ixgbe_mac_82598EB) { 2593b1d5caf3SKevin Bowling if ((sc->feat_en & IXGBE_FEATURE_FDIR) && 25948eb6488eSEric Joyner (eicr & IXGBE_EICR_FLOW_DIR)) { 25958eb6488eSEric Joyner /* This is probably overkill :) */ 2596b1d5caf3SKevin Bowling if (!atomic_cmpset_int(&sc->fdir_reinit, 0, 1)) 2597c19c7afeSEric Joyner return (FILTER_HANDLED); 25988eb6488eSEric Joyner /* Disable the interrupt */ 2599c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR); 2600b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_FDIR; 2601c19c7afeSEric Joyner } else 26028eb6488eSEric Joyner if (eicr & IXGBE_EICR_ECC) { 2603b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 26044f1d91e4SNeel Chauhan "Received ECC Err, initiating reset\n"); 26054f1d91e4SNeel Chauhan hw->mac.flags |= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 26064f1d91e4SNeel Chauhan ixgbe_reset_hw(hw); 26078eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC); 26088eb6488eSEric Joyner } 26098eb6488eSEric Joyner 26108eb6488eSEric Joyner /* Check for over temp condition */ 2611b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_TEMP_SENSOR) { 2612b1d5caf3SKevin Bowling switch (sc->hw.mac.type) { 26138eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 26148eb6488eSEric Joyner if (!(eicr & IXGBE_EICR_GPI_SDP0_X550EM_a)) 26158eb6488eSEric Joyner break; 26168eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, 26178eb6488eSEric Joyner IXGBE_EICR_GPI_SDP0_X550EM_a); 26188eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, 26198eb6488eSEric Joyner IXGBE_EICR_GPI_SDP0_X550EM_a); 26208eb6488eSEric Joyner retval = hw->phy.ops.check_overtemp(hw); 26218eb6488eSEric Joyner if (retval != IXGBE_ERR_OVERTEMP) 26228eb6488eSEric Joyner break; 2623b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 2624c19c7afeSEric Joyner "\nCRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n"); 2625b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 2626c19c7afeSEric Joyner "System shutdown required!\n"); 26278eb6488eSEric Joyner break; 26288eb6488eSEric Joyner default: 26298eb6488eSEric Joyner if (!(eicr & IXGBE_EICR_TS)) 26308eb6488eSEric Joyner break; 26318eb6488eSEric Joyner retval = hw->phy.ops.check_overtemp(hw); 26328eb6488eSEric Joyner if (retval != IXGBE_ERR_OVERTEMP) 26338eb6488eSEric Joyner break; 2634b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 2635c19c7afeSEric Joyner "\nCRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n"); 2636b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 2637c19c7afeSEric Joyner "System shutdown required!\n"); 26388eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS); 26398eb6488eSEric Joyner break; 26408eb6488eSEric Joyner } 26418eb6488eSEric Joyner } 26428eb6488eSEric Joyner 26438eb6488eSEric Joyner /* Check for VF message */ 2644b1d5caf3SKevin Bowling if ((sc->feat_en & IXGBE_FEATURE_SRIOV) && 26458eb6488eSEric Joyner (eicr & IXGBE_EICR_MAILBOX)) 2646b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MBX; 26478eb6488eSEric Joyner } 26488eb6488eSEric Joyner 26498eb6488eSEric Joyner if (ixgbe_is_sfp(hw)) { 26508eb6488eSEric Joyner /* Pluggable optics-related interrupt */ 26518eb6488eSEric Joyner if (hw->mac.type >= ixgbe_mac_X540) 26528eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP0_X540; 26538eb6488eSEric Joyner else 26548eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); 26558eb6488eSEric Joyner 26568eb6488eSEric Joyner if (eicr & eicr_mask) { 26578eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); 2658b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MOD; 26598eb6488eSEric Joyner } 26608eb6488eSEric Joyner 26618eb6488eSEric Joyner if ((hw->mac.type == ixgbe_mac_82599EB) && 26628eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { 26638eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, 26648eb6488eSEric Joyner IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 2665b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MSF; 26668eb6488eSEric Joyner } 26678eb6488eSEric Joyner } 26688eb6488eSEric Joyner 26698eb6488eSEric Joyner /* Check for fan failure */ 2670b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_FAN_FAIL) { 2671b1d5caf3SKevin Bowling ixgbe_check_fan_failure(sc, eicr, true); 26728eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 26738eb6488eSEric Joyner } 26748eb6488eSEric Joyner 26758eb6488eSEric Joyner /* External PHY interrupt */ 26768eb6488eSEric Joyner if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && 26778eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP0_X540)) { 26788eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540); 2679b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_PHY; 26808eb6488eSEric Joyner } 26818eb6488eSEric Joyner 2682b1d5caf3SKevin Bowling return (sc->task_requests != 0) ? FILTER_SCHEDULE_THREAD : FILTER_HANDLED; 26838eb6488eSEric Joyner } /* ixgbe_msix_link */ 26848eb6488eSEric Joyner 26858eb6488eSEric Joyner /************************************************************************ 26868eb6488eSEric Joyner * ixgbe_sysctl_interrupt_rate_handler 26878eb6488eSEric Joyner ************************************************************************/ 2688758cc3dcSJack F Vogel static int 2689758cc3dcSJack F Vogel ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS) 2690758cc3dcSJack F Vogel { 2691c19c7afeSEric Joyner struct ix_rx_queue *que = ((struct ix_rx_queue *)oidp->oid_arg1); 26928eb6488eSEric Joyner int error; 2693758cc3dcSJack F Vogel unsigned int reg, usec, rate; 2694758cc3dcSJack F Vogel 2695f72de14eSKevin Bowling if (atomic_load_acq_int(&que->sc->recovery_mode)) 2696f72de14eSKevin Bowling return (EPERM); 2697f72de14eSKevin Bowling 2698b1d5caf3SKevin Bowling reg = IXGBE_READ_REG(&que->sc->hw, IXGBE_EITR(que->msix)); 2699758cc3dcSJack F Vogel usec = ((reg & 0x0FF8) >> 3); 2700758cc3dcSJack F Vogel if (usec > 0) 2701758cc3dcSJack F Vogel rate = 500000 / usec; 2702758cc3dcSJack F Vogel else 2703758cc3dcSJack F Vogel rate = 0; 2704758cc3dcSJack F Vogel error = sysctl_handle_int(oidp, &rate, 0, req); 2705758cc3dcSJack F Vogel if (error || !req->newptr) 2706758cc3dcSJack F Vogel return error; 2707758cc3dcSJack F Vogel reg &= ~0xfff; /* default, no limitation */ 2708758cc3dcSJack F Vogel ixgbe_max_interrupt_rate = 0; 2709758cc3dcSJack F Vogel if (rate > 0 && rate < 500000) { 2710758cc3dcSJack F Vogel if (rate < 1000) 2711758cc3dcSJack F Vogel rate = 1000; 2712758cc3dcSJack F Vogel ixgbe_max_interrupt_rate = rate; 2713758cc3dcSJack F Vogel reg |= ((4000000/rate) & 0xff8); 2714758cc3dcSJack F Vogel } 2715b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&que->sc->hw, IXGBE_EITR(que->msix), reg); 2716758cc3dcSJack F Vogel 27178eb6488eSEric Joyner return (0); 27188eb6488eSEric Joyner } /* ixgbe_sysctl_interrupt_rate_handler */ 27198eb6488eSEric Joyner 27208eb6488eSEric Joyner /************************************************************************ 27218eb6488eSEric Joyner * ixgbe_add_device_sysctls 27228eb6488eSEric Joyner ************************************************************************/ 27236f37f232SEric Joyner static void 2724c19c7afeSEric Joyner ixgbe_add_device_sysctls(if_ctx_t ctx) 27256f37f232SEric Joyner { 2726b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2727c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 2728b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 27296f37f232SEric Joyner struct sysctl_oid_list *child; 2730c19c7afeSEric Joyner struct sysctl_ctx_list *ctx_list; 27316f37f232SEric Joyner 2732c19c7afeSEric Joyner ctx_list = device_get_sysctl_ctx(dev); 27336f37f232SEric Joyner child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); 27346f37f232SEric Joyner 27356f37f232SEric Joyner /* Sysctls for all devices */ 2736c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "fc", 2737f72de14eSKevin Bowling CTLTYPE_INT | CTLFLAG_RW, 2738b1d5caf3SKevin Bowling sc, 0, ixgbe_sysctl_flowcntl, "I", 2739c19c7afeSEric Joyner IXGBE_SYSCTL_DESC_SET_FC); 27406f37f232SEric Joyner 2741c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "advertise_speed", 2742f72de14eSKevin Bowling CTLTYPE_INT | CTLFLAG_RW, 2743b1d5caf3SKevin Bowling sc, 0, ixgbe_sysctl_advertise, "I", 27448eb6488eSEric Joyner IXGBE_SYSCTL_DESC_ADV_SPEED); 27456f37f232SEric Joyner 2746b1d5caf3SKevin Bowling sc->enable_aim = ixgbe_enable_aim; 274764881da4SSai Rajesh Tallamraju SYSCTL_ADD_INT(ctx_list, child, OID_AUTO, "enable_aim", CTLFLAG_RW, 2748b1d5caf3SKevin Bowling &sc->enable_aim, 0, "Interrupt Moderation"); 274964881da4SSai Rajesh Tallamraju 27507660e4eaSKevin Bowling SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "fw_version", 2751f72de14eSKevin Bowling CTLTYPE_STRING | CTLFLAG_RD, sc, 0, 27527660e4eaSKevin Bowling ixgbe_sysctl_print_fw_version, "A", "Prints FW/NVM Versions"); 27537660e4eaSKevin Bowling 2754a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 2755a9ca1c79SSean Bruno /* testing sysctls (for all devices) */ 2756c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "power_state", 2757f72de14eSKevin Bowling CTLTYPE_INT | CTLFLAG_RW, 2758b1d5caf3SKevin Bowling sc, 0, ixgbe_sysctl_power_state, 27598eb6488eSEric Joyner "I", "PCI Power State"); 2760a9ca1c79SSean Bruno 2761c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "print_rss_config", 2762f72de14eSKevin Bowling CTLTYPE_STRING | CTLFLAG_RD, sc, 0, 2763a9ca1c79SSean Bruno ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration"); 2764a9ca1c79SSean Bruno #endif 2765a9ca1c79SSean Bruno /* for X550 series devices */ 27666f37f232SEric Joyner if (hw->mac.type >= ixgbe_mac_X550) 2767c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "dmac", 2768f72de14eSKevin Bowling CTLTYPE_U16 | CTLFLAG_RW, 2769b1d5caf3SKevin Bowling sc, 0, ixgbe_sysctl_dmac, 27708eb6488eSEric Joyner "I", "DMA Coalesce"); 27716f37f232SEric Joyner 2772a9ca1c79SSean Bruno /* for WoL-capable devices */ 2773a9ca1c79SSean Bruno if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { 2774c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wol_enable", 2775f72de14eSKevin Bowling CTLTYPE_INT | CTLFLAG_RW, sc, 0, 27768eb6488eSEric Joyner ixgbe_sysctl_wol_enable, "I", "Enable/Disable Wake on LAN"); 27776f37f232SEric Joyner 2778c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wufc", 2779f72de14eSKevin Bowling CTLTYPE_U32 | CTLFLAG_RW, 2780b1d5caf3SKevin Bowling sc, 0, ixgbe_sysctl_wufc, 27818eb6488eSEric Joyner "I", "Enable/Disable Wake Up Filters"); 27826f37f232SEric Joyner } 27836f37f232SEric Joyner 2784a9ca1c79SSean Bruno /* for X552/X557-AT devices */ 27856f37f232SEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { 27866f37f232SEric Joyner struct sysctl_oid *phy_node; 27876f37f232SEric Joyner struct sysctl_oid_list *phy_list; 27886f37f232SEric Joyner 2789c19c7afeSEric Joyner phy_node = SYSCTL_ADD_NODE(ctx_list, child, OID_AUTO, "phy", 279020b91f0aSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "External PHY sysctls"); 27916f37f232SEric Joyner phy_list = SYSCTL_CHILDREN(phy_node); 27926f37f232SEric Joyner 2793c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO, "temp", 2794f72de14eSKevin Bowling CTLTYPE_U16 | CTLFLAG_RD, 2795b1d5caf3SKevin Bowling sc, 0, ixgbe_sysctl_phy_temp, 27968eb6488eSEric Joyner "I", "Current External PHY Temperature (Celsius)"); 27976f37f232SEric Joyner 2798c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO, 279920b91f0aSPawel Biernacki "overtemp_occurred", 2800f72de14eSKevin Bowling CTLTYPE_U16 | CTLFLAG_RD, sc, 0, 28016f37f232SEric Joyner ixgbe_sysctl_phy_overtemp_occurred, "I", 28026f37f232SEric Joyner "External PHY High Temperature Event Occurred"); 28036f37f232SEric Joyner } 28048eb6488eSEric Joyner 2805b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_EEE) { 2806c19c7afeSEric Joyner SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "eee_state", 2807f72de14eSKevin Bowling CTLTYPE_INT | CTLFLAG_RW, sc, 0, 28088eb6488eSEric Joyner ixgbe_sysctl_eee_state, "I", "EEE Power Save State"); 28098eb6488eSEric Joyner } 28108eb6488eSEric Joyner } /* ixgbe_add_device_sysctls */ 28118eb6488eSEric Joyner 28128eb6488eSEric Joyner /************************************************************************ 28138eb6488eSEric Joyner * ixgbe_allocate_pci_resources 28148eb6488eSEric Joyner ************************************************************************/ 28158eb6488eSEric Joyner static int 2816c19c7afeSEric Joyner ixgbe_allocate_pci_resources(if_ctx_t ctx) 28178eb6488eSEric Joyner { 2818b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2819c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 28208eb6488eSEric Joyner int rid; 28218eb6488eSEric Joyner 28228eb6488eSEric Joyner rid = PCIR_BAR(0); 2823b1d5caf3SKevin Bowling sc->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 28248eb6488eSEric Joyner RF_ACTIVE); 28258eb6488eSEric Joyner 2826b1d5caf3SKevin Bowling if (!(sc->pci_mem)) { 28278eb6488eSEric Joyner device_printf(dev, "Unable to allocate bus resource: memory\n"); 28288eb6488eSEric Joyner return (ENXIO); 28298eb6488eSEric Joyner } 28308eb6488eSEric Joyner 28318eb6488eSEric Joyner /* Save bus_space values for READ/WRITE_REG macros */ 2832b1d5caf3SKevin Bowling sc->osdep.mem_bus_space_tag = rman_get_bustag(sc->pci_mem); 2833b1d5caf3SKevin Bowling sc->osdep.mem_bus_space_handle = 2834b1d5caf3SKevin Bowling rman_get_bushandle(sc->pci_mem); 28358eb6488eSEric Joyner /* Set hw values for shared code */ 2836b1d5caf3SKevin Bowling sc->hw.hw_addr = (u8 *)&sc->osdep.mem_bus_space_handle; 28378eb6488eSEric Joyner 28388eb6488eSEric Joyner return (0); 28398eb6488eSEric Joyner } /* ixgbe_allocate_pci_resources */ 28408eb6488eSEric Joyner 28418eb6488eSEric Joyner /************************************************************************ 28428eb6488eSEric Joyner * ixgbe_detach - Device removal routine 28438eb6488eSEric Joyner * 28448eb6488eSEric Joyner * Called when the driver is being removed. 28458eb6488eSEric Joyner * Stops the adapter and deallocates all the resources 28468eb6488eSEric Joyner * that were allocated for driver operation. 28478eb6488eSEric Joyner * 28488eb6488eSEric Joyner * return 0 on success, positive on failure 28498eb6488eSEric Joyner ************************************************************************/ 28508eb6488eSEric Joyner static int 2851c19c7afeSEric Joyner ixgbe_if_detach(if_ctx_t ctx) 28528eb6488eSEric Joyner { 2853b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2854c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 28558eb6488eSEric Joyner u32 ctrl_ext; 28568eb6488eSEric Joyner 28578eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_detach: begin"); 28588eb6488eSEric Joyner 28598eb6488eSEric Joyner if (ixgbe_pci_iov_detach(dev) != 0) { 28608eb6488eSEric Joyner device_printf(dev, "SR-IOV in use; detach first.\n"); 28618eb6488eSEric Joyner return (EBUSY); 28628eb6488eSEric Joyner } 28638eb6488eSEric Joyner 2864c19c7afeSEric Joyner ixgbe_setup_low_power_mode(ctx); 28658eb6488eSEric Joyner 28668eb6488eSEric Joyner /* let hardware know driver is unloading */ 2867b1d5caf3SKevin Bowling ctrl_ext = IXGBE_READ_REG(&sc->hw, IXGBE_CTRL_EXT); 28688eb6488eSEric Joyner ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD; 2869b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_CTRL_EXT, ctrl_ext); 28708eb6488eSEric Joyner 2871f72de14eSKevin Bowling callout_drain(&sc->fw_mode_timer); 2872f72de14eSKevin Bowling 2873c19c7afeSEric Joyner ixgbe_free_pci_resources(ctx); 2874b1d5caf3SKevin Bowling free(sc->mta, M_IXGBE); 28758eb6488eSEric Joyner 28768eb6488eSEric Joyner return (0); 2877c19c7afeSEric Joyner } /* ixgbe_if_detach */ 28788eb6488eSEric Joyner 28798eb6488eSEric Joyner /************************************************************************ 28808eb6488eSEric Joyner * ixgbe_setup_low_power_mode - LPLU/WoL preparation 28818eb6488eSEric Joyner * 28828eb6488eSEric Joyner * Prepare the adapter/port for LPLU and/or WoL 28838eb6488eSEric Joyner ************************************************************************/ 28848eb6488eSEric Joyner static int 2885c19c7afeSEric Joyner ixgbe_setup_low_power_mode(if_ctx_t ctx) 28868eb6488eSEric Joyner { 2887b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2888b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 2889c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 28908eb6488eSEric Joyner s32 error = 0; 28918eb6488eSEric Joyner 2892c19c7afeSEric Joyner if (!hw->wol_enabled) 289379b36ec9SKevin Bowling ixgbe_set_phy_power(hw, false); 28948eb6488eSEric Joyner 28958eb6488eSEric Joyner /* Limit power management flow to X550EM baseT */ 28968eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T && 28978eb6488eSEric Joyner hw->phy.ops.enter_lplu) { 28988eb6488eSEric Joyner /* Turn off support for APM wakeup. (Using ACPI instead) */ 289973fa89e0SPiotr Pietruszewski IXGBE_WRITE_REG(hw, IXGBE_GRC_BY_MAC(hw), 290073fa89e0SPiotr Pietruszewski IXGBE_READ_REG(hw, IXGBE_GRC_BY_MAC(hw)) & ~(u32)2); 29018eb6488eSEric Joyner 29028eb6488eSEric Joyner /* 29038eb6488eSEric Joyner * Clear Wake Up Status register to prevent any previous wakeup 29048eb6488eSEric Joyner * events from waking us up immediately after we suspend. 29058eb6488eSEric Joyner */ 29068eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff); 29078eb6488eSEric Joyner 29088eb6488eSEric Joyner /* 29098eb6488eSEric Joyner * Program the Wakeup Filter Control register with user filter 29108eb6488eSEric Joyner * settings 29118eb6488eSEric Joyner */ 2912b1d5caf3SKevin Bowling IXGBE_WRITE_REG(hw, IXGBE_WUFC, sc->wufc); 29138eb6488eSEric Joyner 29148eb6488eSEric Joyner /* Enable wakeups and power management in Wakeup Control */ 29158eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUC, 29168eb6488eSEric Joyner IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN); 29178eb6488eSEric Joyner 29188eb6488eSEric Joyner /* X550EM baseT adapters need a special LPLU flow */ 291979b36ec9SKevin Bowling hw->phy.reset_disable = true; 2920c19c7afeSEric Joyner ixgbe_if_stop(ctx); 29218eb6488eSEric Joyner error = hw->phy.ops.enter_lplu(hw); 29228eb6488eSEric Joyner if (error) 29238eb6488eSEric Joyner device_printf(dev, "Error entering LPLU: %d\n", error); 292479b36ec9SKevin Bowling hw->phy.reset_disable = false; 29258eb6488eSEric Joyner } else { 29268eb6488eSEric Joyner /* Just stop for other adapters */ 2927c19c7afeSEric Joyner ixgbe_if_stop(ctx); 29288eb6488eSEric Joyner } 29298eb6488eSEric Joyner 29308eb6488eSEric Joyner return error; 29318eb6488eSEric Joyner } /* ixgbe_setup_low_power_mode */ 29328eb6488eSEric Joyner 29338eb6488eSEric Joyner /************************************************************************ 29348eb6488eSEric Joyner * ixgbe_shutdown - Shutdown entry point 29358eb6488eSEric Joyner ************************************************************************/ 29368eb6488eSEric Joyner static int 2937c19c7afeSEric Joyner ixgbe_if_shutdown(if_ctx_t ctx) 29388eb6488eSEric Joyner { 29398eb6488eSEric Joyner int error = 0; 29408eb6488eSEric Joyner 29418eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_shutdown: begin"); 29428eb6488eSEric Joyner 2943c19c7afeSEric Joyner error = ixgbe_setup_low_power_mode(ctx); 29448eb6488eSEric Joyner 29458eb6488eSEric Joyner return (error); 2946c19c7afeSEric Joyner } /* ixgbe_if_shutdown */ 29478eb6488eSEric Joyner 29488eb6488eSEric Joyner /************************************************************************ 29498eb6488eSEric Joyner * ixgbe_suspend 29508eb6488eSEric Joyner * 29518eb6488eSEric Joyner * From D0 to D3 29528eb6488eSEric Joyner ************************************************************************/ 29538eb6488eSEric Joyner static int 2954c19c7afeSEric Joyner ixgbe_if_suspend(if_ctx_t ctx) 29558eb6488eSEric Joyner { 29568eb6488eSEric Joyner int error = 0; 29578eb6488eSEric Joyner 29588eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_suspend: begin"); 29598eb6488eSEric Joyner 2960c19c7afeSEric Joyner error = ixgbe_setup_low_power_mode(ctx); 29618eb6488eSEric Joyner 29628eb6488eSEric Joyner return (error); 2963c19c7afeSEric Joyner } /* ixgbe_if_suspend */ 29648eb6488eSEric Joyner 29658eb6488eSEric Joyner /************************************************************************ 29668eb6488eSEric Joyner * ixgbe_resume 29678eb6488eSEric Joyner * 29688eb6488eSEric Joyner * From D3 to D0 29698eb6488eSEric Joyner ************************************************************************/ 29708eb6488eSEric Joyner static int 2971c19c7afeSEric Joyner ixgbe_if_resume(if_ctx_t ctx) 29728eb6488eSEric Joyner { 2973b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 2974c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 2975ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 2976b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 29778eb6488eSEric Joyner u32 wus; 29788eb6488eSEric Joyner 29798eb6488eSEric Joyner INIT_DEBUGOUT("ixgbe_resume: begin"); 29808eb6488eSEric Joyner 29818eb6488eSEric Joyner /* Read & clear WUS register */ 29828eb6488eSEric Joyner wus = IXGBE_READ_REG(hw, IXGBE_WUS); 29838eb6488eSEric Joyner if (wus) 29848eb6488eSEric Joyner device_printf(dev, "Woken up by (WUS): %#010x\n", 29858eb6488eSEric Joyner IXGBE_READ_REG(hw, IXGBE_WUS)); 29868eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff); 29878eb6488eSEric Joyner /* And clear WUFC until next low-power transition */ 29888eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0); 29898eb6488eSEric Joyner 29908eb6488eSEric Joyner /* 29918eb6488eSEric Joyner * Required after D3->D0 transition; 29928eb6488eSEric Joyner * will re-advertise all previous advertised speeds 29938eb6488eSEric Joyner */ 2994ff06a8dbSJustin Hibbits if (if_getflags(ifp) & IFF_UP) 2995c19c7afeSEric Joyner ixgbe_if_init(ctx); 29968eb6488eSEric Joyner 29978eb6488eSEric Joyner return (0); 2998c19c7afeSEric Joyner } /* ixgbe_if_resume */ 29998eb6488eSEric Joyner 30008eb6488eSEric Joyner /************************************************************************ 3001c19c7afeSEric Joyner * ixgbe_if_mtu_set - Ioctl mtu entry point 30028eb6488eSEric Joyner * 3003c19c7afeSEric Joyner * Return 0 on success, EINVAL on failure 3004c19c7afeSEric Joyner ************************************************************************/ 3005c19c7afeSEric Joyner static int 3006c19c7afeSEric Joyner ixgbe_if_mtu_set(if_ctx_t ctx, uint32_t mtu) 3007c19c7afeSEric Joyner { 3008b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3009c19c7afeSEric Joyner int error = 0; 3010c19c7afeSEric Joyner 3011c19c7afeSEric Joyner IOCTL_DEBUGOUT("ioctl: SIOCIFMTU (Set Interface MTU)"); 3012c19c7afeSEric Joyner 3013c19c7afeSEric Joyner if (mtu > IXGBE_MAX_MTU) { 3014c19c7afeSEric Joyner error = EINVAL; 3015c19c7afeSEric Joyner } else { 3016b1d5caf3SKevin Bowling sc->max_frame_size = mtu + IXGBE_MTU_HDR; 3017c19c7afeSEric Joyner } 3018c19c7afeSEric Joyner 3019c19c7afeSEric Joyner return error; 3020c19c7afeSEric Joyner } /* ixgbe_if_mtu_set */ 3021c19c7afeSEric Joyner 3022c19c7afeSEric Joyner /************************************************************************ 3023c19c7afeSEric Joyner * ixgbe_if_crcstrip_set 30248eb6488eSEric Joyner ************************************************************************/ 30258eb6488eSEric Joyner static void 3026c19c7afeSEric Joyner ixgbe_if_crcstrip_set(if_ctx_t ctx, int onoff, int crcstrip) 30278eb6488eSEric Joyner { 3028b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3029c19c7afeSEric Joyner struct ixgbe_hw *hw = &sc->hw; 3030c19c7afeSEric Joyner /* crc stripping is set in two places: 3031c19c7afeSEric Joyner * IXGBE_HLREG0 (modified on init_locked and hw reset) 3032c19c7afeSEric Joyner * IXGBE_RDRXCTL (set by the original driver in 3033c19c7afeSEric Joyner * ixgbe_setup_hw_rsc() called in init_locked. 3034c19c7afeSEric Joyner * We disable the setting when netmap is compiled in). 3035c19c7afeSEric Joyner * We update the values here, but also in ixgbe.c because 3036c19c7afeSEric Joyner * init_locked sometimes is called outside our control. 3037c19c7afeSEric Joyner */ 3038c19c7afeSEric Joyner uint32_t hl, rxc; 30398eb6488eSEric Joyner 3040c19c7afeSEric Joyner hl = IXGBE_READ_REG(hw, IXGBE_HLREG0); 3041c19c7afeSEric Joyner rxc = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); 3042c19c7afeSEric Joyner #ifdef NETMAP 3043c19c7afeSEric Joyner if (netmap_verbose) 3044c19c7afeSEric Joyner D("%s read HLREG 0x%x rxc 0x%x", 3045c19c7afeSEric Joyner onoff ? "enter" : "exit", hl, rxc); 30468eb6488eSEric Joyner #endif 3047c19c7afeSEric Joyner /* hw requirements ... */ 3048c19c7afeSEric Joyner rxc &= ~IXGBE_RDRXCTL_RSCFRSTSIZE; 3049c19c7afeSEric Joyner rxc |= IXGBE_RDRXCTL_RSCACKC; 3050c19c7afeSEric Joyner if (onoff && !crcstrip) { 3051c19c7afeSEric Joyner /* keep the crc. Fast rx */ 3052c19c7afeSEric Joyner hl &= ~IXGBE_HLREG0_RXCRCSTRP; 3053c19c7afeSEric Joyner rxc &= ~IXGBE_RDRXCTL_CRCSTRIP; 3054c19c7afeSEric Joyner } else { 3055c19c7afeSEric Joyner /* reset default mode */ 3056c19c7afeSEric Joyner hl |= IXGBE_HLREG0_RXCRCSTRP; 3057c19c7afeSEric Joyner rxc |= IXGBE_RDRXCTL_CRCSTRIP; 3058c19c7afeSEric Joyner } 3059c19c7afeSEric Joyner #ifdef NETMAP 3060c19c7afeSEric Joyner if (netmap_verbose) 3061c19c7afeSEric Joyner D("%s write HLREG 0x%x rxc 0x%x", 3062c19c7afeSEric Joyner onoff ? "enter" : "exit", hl, rxc); 3063c19c7afeSEric Joyner #endif 3064c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hl); 3065c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rxc); 3066c19c7afeSEric Joyner } /* ixgbe_if_crcstrip_set */ 30678eb6488eSEric Joyner 3068c19c7afeSEric Joyner /********************************************************************* 3069c19c7afeSEric Joyner * ixgbe_if_init - Init entry point 30708eb6488eSEric Joyner * 30718eb6488eSEric Joyner * Used in two ways: It is used by the stack as an init 30728eb6488eSEric Joyner * entry point in network interface structure. It is also 30738eb6488eSEric Joyner * used by the driver as a hw/sw initialization routine to 30748eb6488eSEric Joyner * get to a consistent state. 30758eb6488eSEric Joyner * 3076c19c7afeSEric Joyner * Return 0 on success, positive on failure 3077c19c7afeSEric Joyner **********************************************************************/ 30788eb6488eSEric Joyner void 3079c19c7afeSEric Joyner ixgbe_if_init(if_ctx_t ctx) 30808eb6488eSEric Joyner { 3081b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3082ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 3083c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 3084b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 3085c19c7afeSEric Joyner struct ix_rx_queue *rx_que; 3086c19c7afeSEric Joyner struct ix_tx_queue *tx_que; 30878eb6488eSEric Joyner u32 txdctl, mhadd; 30888eb6488eSEric Joyner u32 rxdctl, rxctrl; 30898eb6488eSEric Joyner u32 ctrl_ext; 30908eb6488eSEric Joyner 3091c19c7afeSEric Joyner int i, j, err; 30928eb6488eSEric Joyner 3093c19c7afeSEric Joyner INIT_DEBUGOUT("ixgbe_if_init: begin"); 30948eb6488eSEric Joyner 30958eb6488eSEric Joyner /* Queue indices may change with IOV mode */ 3096b1d5caf3SKevin Bowling ixgbe_align_all_queue_indices(sc); 30978eb6488eSEric Joyner 30988eb6488eSEric Joyner /* reprogram the RAR[0] in case user changed it. */ 3099b1d5caf3SKevin Bowling ixgbe_set_rar(hw, 0, hw->mac.addr, sc->pool, IXGBE_RAH_AV); 31008eb6488eSEric Joyner 31018eb6488eSEric Joyner /* Get the latest mac address, User can use a LAA */ 3102ff06a8dbSJustin Hibbits bcopy(if_getlladdr(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS); 3103b1d5caf3SKevin Bowling ixgbe_set_rar(hw, 0, hw->mac.addr, sc->pool, 1); 31048eb6488eSEric Joyner hw->addr_ctrl.rar_used_count = 1; 31058eb6488eSEric Joyner 31068eb6488eSEric Joyner ixgbe_init_hw(hw); 3107c19c7afeSEric Joyner 3108b1d5caf3SKevin Bowling ixgbe_initialize_iov(sc); 3109c19c7afeSEric Joyner 3110c19c7afeSEric Joyner ixgbe_initialize_transmit_units(ctx); 31118eb6488eSEric Joyner 31128eb6488eSEric Joyner /* Setup Multicast table */ 3113c19c7afeSEric Joyner ixgbe_if_multi_set(ctx); 31148eb6488eSEric Joyner 31158eb6488eSEric Joyner /* Determine the correct mbuf pool, based on frame size */ 3116b1d5caf3SKevin Bowling sc->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx); 31178eb6488eSEric Joyner 31188eb6488eSEric Joyner /* Configure RX settings */ 3119c19c7afeSEric Joyner ixgbe_initialize_receive_units(ctx); 31208eb6488eSEric Joyner 3121b2c1e8e6SEric Joyner /* 3122b2c1e8e6SEric Joyner * Initialize variable holding task enqueue requests 3123b2c1e8e6SEric Joyner * from MSI-X interrupts 3124b2c1e8e6SEric Joyner */ 3125b1d5caf3SKevin Bowling sc->task_requests = 0; 3126b2c1e8e6SEric Joyner 31278eb6488eSEric Joyner /* Enable SDP & MSI-X interrupts based on adapter */ 3128b1d5caf3SKevin Bowling ixgbe_config_gpie(sc); 31298eb6488eSEric Joyner 31308eb6488eSEric Joyner /* Set MTU size */ 3131ff06a8dbSJustin Hibbits if (if_getmtu(ifp) > ETHERMTU) { 31328eb6488eSEric Joyner /* aka IXGBE_MAXFRS on 82599 and newer */ 31338eb6488eSEric Joyner mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); 31348eb6488eSEric Joyner mhadd &= ~IXGBE_MHADD_MFS_MASK; 3135b1d5caf3SKevin Bowling mhadd |= sc->max_frame_size << IXGBE_MHADD_MFS_SHIFT; 31368eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); 31378eb6488eSEric Joyner } 31388eb6488eSEric Joyner 31398eb6488eSEric Joyner /* Now enable all the queues */ 3140b1d5caf3SKevin Bowling for (i = 0, tx_que = sc->tx_queues; i < sc->num_tx_queues; i++, tx_que++) { 3141c19c7afeSEric Joyner struct tx_ring *txr = &tx_que->txr; 3142c19c7afeSEric Joyner 31438eb6488eSEric Joyner txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me)); 31448eb6488eSEric Joyner txdctl |= IXGBE_TXDCTL_ENABLE; 31458eb6488eSEric Joyner /* Set WTHRESH to 8, burst writeback */ 31468eb6488eSEric Joyner txdctl |= (8 << 16); 31478eb6488eSEric Joyner /* 31488eb6488eSEric Joyner * When the internal queue falls below PTHRESH (32), 31498eb6488eSEric Joyner * start prefetching as long as there are at least 31508eb6488eSEric Joyner * HTHRESH (1) buffers ready. The values are taken 31518eb6488eSEric Joyner * from the Intel linux driver 3.8.21. 31528eb6488eSEric Joyner * Prefetching enables tx line rate even with 1 queue. 31538eb6488eSEric Joyner */ 31548eb6488eSEric Joyner txdctl |= (32 << 0) | (1 << 8); 31558eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl); 31568eb6488eSEric Joyner } 31578eb6488eSEric Joyner 3158b1d5caf3SKevin Bowling for (i = 0, rx_que = sc->rx_queues; i < sc->num_rx_queues; i++, rx_que++) { 3159c19c7afeSEric Joyner struct rx_ring *rxr = &rx_que->rxr; 3160c19c7afeSEric Joyner 31618eb6488eSEric Joyner rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); 31628eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) { 31638eb6488eSEric Joyner /* 31648eb6488eSEric Joyner * PTHRESH = 21 31658eb6488eSEric Joyner * HTHRESH = 4 31668eb6488eSEric Joyner * WTHRESH = 8 31678eb6488eSEric Joyner */ 31688eb6488eSEric Joyner rxdctl &= ~0x3FFFFF; 31698eb6488eSEric Joyner rxdctl |= 0x080420; 31708eb6488eSEric Joyner } 31718eb6488eSEric Joyner rxdctl |= IXGBE_RXDCTL_ENABLE; 31728eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), rxdctl); 3173c19c7afeSEric Joyner for (j = 0; j < 10; j++) { 31748eb6488eSEric Joyner if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)) & 31758eb6488eSEric Joyner IXGBE_RXDCTL_ENABLE) 31768eb6488eSEric Joyner break; 31778eb6488eSEric Joyner else 31788eb6488eSEric Joyner msec_delay(1); 31798eb6488eSEric Joyner } 31808eb6488eSEric Joyner wmb(); 31818eb6488eSEric Joyner } 31828eb6488eSEric Joyner 31838eb6488eSEric Joyner /* Enable Receive engine */ 31848eb6488eSEric Joyner rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 31858eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 31868eb6488eSEric Joyner rxctrl |= IXGBE_RXCTRL_DMBYPS; 31878eb6488eSEric Joyner rxctrl |= IXGBE_RXCTRL_RXEN; 31888eb6488eSEric Joyner ixgbe_enable_rx_dma(hw, rxctrl); 31898eb6488eSEric Joyner 3190c19c7afeSEric Joyner /* Set up MSI/MSI-X routing */ 3191c19c7afeSEric Joyner if (ixgbe_enable_msix) { 3192b1d5caf3SKevin Bowling ixgbe_configure_ivars(sc); 31938eb6488eSEric Joyner /* Set up auto-mask */ 31948eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 31958eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); 31968eb6488eSEric Joyner else { 31978eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF); 31988eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF); 31998eb6488eSEric Joyner } 32008eb6488eSEric Joyner } else { /* Simple settings for Legacy/MSI */ 3201b1d5caf3SKevin Bowling ixgbe_set_ivar(sc, 0, 0, 0); 3202b1d5caf3SKevin Bowling ixgbe_set_ivar(sc, 0, 0, 1); 32038eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); 32048eb6488eSEric Joyner } 32058eb6488eSEric Joyner 3206b1d5caf3SKevin Bowling ixgbe_init_fdir(sc); 32078eb6488eSEric Joyner 32088eb6488eSEric Joyner /* 32098eb6488eSEric Joyner * Check on any SFP devices that 32108eb6488eSEric Joyner * need to be kick-started 32118eb6488eSEric Joyner */ 32128eb6488eSEric Joyner if (hw->phy.type == ixgbe_phy_none) { 32138eb6488eSEric Joyner err = hw->phy.ops.identify(hw); 32148eb6488eSEric Joyner if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 32158eb6488eSEric Joyner device_printf(dev, 32168eb6488eSEric Joyner "Unsupported SFP+ module type was detected.\n"); 32178eb6488eSEric Joyner return; 32188eb6488eSEric Joyner } 32198eb6488eSEric Joyner } 32208eb6488eSEric Joyner 32218eb6488eSEric Joyner /* Set moderation on the Link interrupt */ 3222b1d5caf3SKevin Bowling IXGBE_WRITE_REG(hw, IXGBE_EITR(sc->vector), IXGBE_LINK_ITR); 32238eb6488eSEric Joyner 3224c19c7afeSEric Joyner /* Enable power to the phy. */ 322579b36ec9SKevin Bowling ixgbe_set_phy_power(hw, true); 3226c19c7afeSEric Joyner 32278eb6488eSEric Joyner /* Config/Enable Link */ 3228b2c1e8e6SEric Joyner ixgbe_config_link(ctx); 32298eb6488eSEric Joyner 32308eb6488eSEric Joyner /* Hardware Packet Buffer & Flow Control setup */ 3231b1d5caf3SKevin Bowling ixgbe_config_delay_values(sc); 32328eb6488eSEric Joyner 32338eb6488eSEric Joyner /* Initialize the FC settings */ 32348eb6488eSEric Joyner ixgbe_start_hw(hw); 32358eb6488eSEric Joyner 32368eb6488eSEric Joyner /* Set up VLAN support and filter */ 3237c19c7afeSEric Joyner ixgbe_setup_vlan_hw_support(ctx); 32388eb6488eSEric Joyner 32398eb6488eSEric Joyner /* Setup DMA Coalescing */ 3240b1d5caf3SKevin Bowling ixgbe_config_dmac(sc); 32418eb6488eSEric Joyner 32428eb6488eSEric Joyner /* And now turn on interrupts */ 3243c19c7afeSEric Joyner ixgbe_if_enable_intr(ctx); 32448eb6488eSEric Joyner 32458eb6488eSEric Joyner /* Enable the use of the MBX by the VF's */ 3246b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_SRIOV) { 32478eb6488eSEric Joyner ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 32488eb6488eSEric Joyner ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD; 32498eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 32508eb6488eSEric Joyner } 32518eb6488eSEric Joyner 32528eb6488eSEric Joyner } /* ixgbe_init_locked */ 32538eb6488eSEric Joyner 32548eb6488eSEric Joyner /************************************************************************ 32558eb6488eSEric Joyner * ixgbe_set_ivar 32568eb6488eSEric Joyner * 32578eb6488eSEric Joyner * Setup the correct IVAR register for a particular MSI-X interrupt 32588eb6488eSEric Joyner * (yes this is all very magic and confusing :) 32598eb6488eSEric Joyner * - entry is the register array entry 32608eb6488eSEric Joyner * - vector is the MSI-X vector for this queue 32618eb6488eSEric Joyner * - type is RX/TX/MISC 32628eb6488eSEric Joyner ************************************************************************/ 32638eb6488eSEric Joyner static void 3264b1d5caf3SKevin Bowling ixgbe_set_ivar(struct ixgbe_softc *sc, u8 entry, u8 vector, s8 type) 32658eb6488eSEric Joyner { 3266b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 32678eb6488eSEric Joyner u32 ivar, index; 32688eb6488eSEric Joyner 32698eb6488eSEric Joyner vector |= IXGBE_IVAR_ALLOC_VAL; 32708eb6488eSEric Joyner 32718eb6488eSEric Joyner switch (hw->mac.type) { 32728eb6488eSEric Joyner case ixgbe_mac_82598EB: 32738eb6488eSEric Joyner if (type == -1) 32748eb6488eSEric Joyner entry = IXGBE_IVAR_OTHER_CAUSES_INDEX; 32758eb6488eSEric Joyner else 32768eb6488eSEric Joyner entry += (type * 64); 32778eb6488eSEric Joyner index = (entry >> 2) & 0x1F; 32788eb6488eSEric Joyner ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index)); 32798eb6488eSEric Joyner ivar &= ~(0xFF << (8 * (entry & 0x3))); 32808eb6488eSEric Joyner ivar |= (vector << (8 * (entry & 0x3))); 3281b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_IVAR(index), ivar); 32828eb6488eSEric Joyner break; 32838eb6488eSEric Joyner case ixgbe_mac_82599EB: 32848eb6488eSEric Joyner case ixgbe_mac_X540: 32858eb6488eSEric Joyner case ixgbe_mac_X550: 32868eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 32878eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 32888eb6488eSEric Joyner if (type == -1) { /* MISC IVAR */ 32898eb6488eSEric Joyner index = (entry & 1) * 8; 32908eb6488eSEric Joyner ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC); 32918eb6488eSEric Joyner ivar &= ~(0xFF << index); 32928eb6488eSEric Joyner ivar |= (vector << index); 32938eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar); 32948eb6488eSEric Joyner } else { /* RX/TX IVARS */ 32958eb6488eSEric Joyner index = (16 * (entry & 1)) + (8 * type); 32968eb6488eSEric Joyner ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1)); 32978eb6488eSEric Joyner ivar &= ~(0xFF << index); 32988eb6488eSEric Joyner ivar |= (vector << index); 32998eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar); 33008eb6488eSEric Joyner } 33018eb6488eSEric Joyner default: 33028eb6488eSEric Joyner break; 33038eb6488eSEric Joyner } 33048eb6488eSEric Joyner } /* ixgbe_set_ivar */ 33058eb6488eSEric Joyner 33068eb6488eSEric Joyner /************************************************************************ 33078eb6488eSEric Joyner * ixgbe_configure_ivars 33088eb6488eSEric Joyner ************************************************************************/ 33098eb6488eSEric Joyner static void 3310b1d5caf3SKevin Bowling ixgbe_configure_ivars(struct ixgbe_softc *sc) 33118eb6488eSEric Joyner { 3312b1d5caf3SKevin Bowling struct ix_rx_queue *rx_que = sc->rx_queues; 3313b1d5caf3SKevin Bowling struct ix_tx_queue *tx_que = sc->tx_queues; 33148eb6488eSEric Joyner u32 newitr; 33158eb6488eSEric Joyner 33168eb6488eSEric Joyner if (ixgbe_max_interrupt_rate > 0) 33178eb6488eSEric Joyner newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8; 33188eb6488eSEric Joyner else { 33198eb6488eSEric Joyner /* 33208eb6488eSEric Joyner * Disable DMA coalescing if interrupt moderation is 33218eb6488eSEric Joyner * disabled. 33228eb6488eSEric Joyner */ 3323b1d5caf3SKevin Bowling sc->dmac = 0; 33248eb6488eSEric Joyner newitr = 0; 33258eb6488eSEric Joyner } 33268eb6488eSEric Joyner 3327b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++, rx_que++) { 3328c19c7afeSEric Joyner struct rx_ring *rxr = &rx_que->rxr; 33298eb6488eSEric Joyner 3330c19c7afeSEric Joyner /* First the RX queue entry */ 3331b1d5caf3SKevin Bowling ixgbe_set_ivar(sc, rxr->me, rx_que->msix, 0); 3332c19c7afeSEric Joyner 3333c19c7afeSEric Joyner /* Set an Initial EITR value */ 3334b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(rx_que->msix), newitr); 3335c19c7afeSEric Joyner } 3336b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_tx_queues; i++, tx_que++) { 3337c19c7afeSEric Joyner struct tx_ring *txr = &tx_que->txr; 3338c19c7afeSEric Joyner 3339c19c7afeSEric Joyner /* ... and the TX */ 3340b1d5caf3SKevin Bowling ixgbe_set_ivar(sc, txr->me, tx_que->msix, 1); 3341c19c7afeSEric Joyner } 33428eb6488eSEric Joyner /* For the Link interrupt */ 3343b1d5caf3SKevin Bowling ixgbe_set_ivar(sc, 1, sc->vector, -1); 33448eb6488eSEric Joyner } /* ixgbe_configure_ivars */ 33458eb6488eSEric Joyner 33468eb6488eSEric Joyner /************************************************************************ 33478eb6488eSEric Joyner * ixgbe_config_gpie 33488eb6488eSEric Joyner ************************************************************************/ 33498eb6488eSEric Joyner static void 3350b1d5caf3SKevin Bowling ixgbe_config_gpie(struct ixgbe_softc *sc) 33518eb6488eSEric Joyner { 3352b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 33538eb6488eSEric Joyner u32 gpie; 33548eb6488eSEric Joyner 33558eb6488eSEric Joyner gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); 33568eb6488eSEric Joyner 3357b1d5caf3SKevin Bowling if (sc->intr_type == IFLIB_INTR_MSIX) { 33588eb6488eSEric Joyner /* Enable Enhanced MSI-X mode */ 33598eb6488eSEric Joyner gpie |= IXGBE_GPIE_MSIX_MODE 33608eb6488eSEric Joyner | IXGBE_GPIE_EIAME 33618eb6488eSEric Joyner | IXGBE_GPIE_PBA_SUPPORT 33628eb6488eSEric Joyner | IXGBE_GPIE_OCD; 33638eb6488eSEric Joyner } 33648eb6488eSEric Joyner 33658eb6488eSEric Joyner /* Fan Failure Interrupt */ 3366b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_FAN_FAIL) 33678eb6488eSEric Joyner gpie |= IXGBE_SDP1_GPIEN; 33688eb6488eSEric Joyner 33698eb6488eSEric Joyner /* Thermal Sensor Interrupt */ 3370b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_TEMP_SENSOR) 33718eb6488eSEric Joyner gpie |= IXGBE_SDP0_GPIEN_X540; 33728eb6488eSEric Joyner 33738eb6488eSEric Joyner /* Link detection */ 33748eb6488eSEric Joyner switch (hw->mac.type) { 33758eb6488eSEric Joyner case ixgbe_mac_82599EB: 33768eb6488eSEric Joyner gpie |= IXGBE_SDP1_GPIEN | IXGBE_SDP2_GPIEN; 33778eb6488eSEric Joyner break; 33788eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 33798eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 33808eb6488eSEric Joyner gpie |= IXGBE_SDP0_GPIEN_X540; 33818eb6488eSEric Joyner break; 33828eb6488eSEric Joyner default: 33838eb6488eSEric Joyner break; 33848eb6488eSEric Joyner } 33858eb6488eSEric Joyner 33868eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); 33878eb6488eSEric Joyner 33888eb6488eSEric Joyner } /* ixgbe_config_gpie */ 33898eb6488eSEric Joyner 33908eb6488eSEric Joyner /************************************************************************ 33918eb6488eSEric Joyner * ixgbe_config_delay_values 33928eb6488eSEric Joyner * 3393b1d5caf3SKevin Bowling * Requires sc->max_frame_size to be set. 33948eb6488eSEric Joyner ************************************************************************/ 33958eb6488eSEric Joyner static void 3396b1d5caf3SKevin Bowling ixgbe_config_delay_values(struct ixgbe_softc *sc) 33978eb6488eSEric Joyner { 3398b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 33998eb6488eSEric Joyner u32 rxpb, frame, size, tmp; 34008eb6488eSEric Joyner 3401b1d5caf3SKevin Bowling frame = sc->max_frame_size; 34028eb6488eSEric Joyner 34038eb6488eSEric Joyner /* Calculate High Water */ 34048eb6488eSEric Joyner switch (hw->mac.type) { 34058eb6488eSEric Joyner case ixgbe_mac_X540: 34068eb6488eSEric Joyner case ixgbe_mac_X550: 34078eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 34088eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 34098eb6488eSEric Joyner tmp = IXGBE_DV_X540(frame, frame); 34108eb6488eSEric Joyner break; 34118eb6488eSEric Joyner default: 34128eb6488eSEric Joyner tmp = IXGBE_DV(frame, frame); 34138eb6488eSEric Joyner break; 34148eb6488eSEric Joyner } 34158eb6488eSEric Joyner size = IXGBE_BT2KB(tmp); 34168eb6488eSEric Joyner rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10; 34178eb6488eSEric Joyner hw->fc.high_water[0] = rxpb - size; 34188eb6488eSEric Joyner 34198eb6488eSEric Joyner /* Now calculate Low Water */ 34208eb6488eSEric Joyner switch (hw->mac.type) { 34218eb6488eSEric Joyner case ixgbe_mac_X540: 34228eb6488eSEric Joyner case ixgbe_mac_X550: 34238eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 34248eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 34258eb6488eSEric Joyner tmp = IXGBE_LOW_DV_X540(frame); 34268eb6488eSEric Joyner break; 34278eb6488eSEric Joyner default: 34288eb6488eSEric Joyner tmp = IXGBE_LOW_DV(frame); 34298eb6488eSEric Joyner break; 34308eb6488eSEric Joyner } 34318eb6488eSEric Joyner hw->fc.low_water[0] = IXGBE_BT2KB(tmp); 34328eb6488eSEric Joyner 34338eb6488eSEric Joyner hw->fc.pause_time = IXGBE_FC_PAUSE; 343479b36ec9SKevin Bowling hw->fc.send_xon = true; 34358eb6488eSEric Joyner } /* ixgbe_config_delay_values */ 34368eb6488eSEric Joyner 34378eb6488eSEric Joyner /************************************************************************ 34388eb6488eSEric Joyner * ixgbe_set_multi - Multicast Update 34398eb6488eSEric Joyner * 34408eb6488eSEric Joyner * Called whenever multicast address list is updated. 34418eb6488eSEric Joyner ************************************************************************/ 3442ba76aa63SGleb Smirnoff static u_int 344321afed4bSKevin Bowling ixgbe_mc_filter_apply(void *arg, struct sockaddr_dl *sdl, u_int idx) 34448eb6488eSEric Joyner { 3445b1d5caf3SKevin Bowling struct ixgbe_softc *sc = arg; 3446b1d5caf3SKevin Bowling struct ixgbe_mc_addr *mta = sc->mta; 3447c19c7afeSEric Joyner 344821afed4bSKevin Bowling if (idx == MAX_NUM_MULTICAST_ADDRESSES) 3449c19c7afeSEric Joyner return (0); 345021afed4bSKevin Bowling bcopy(LLADDR(sdl), mta[idx].addr, IXGBE_ETH_LENGTH_OF_ADDRESS); 3451b1d5caf3SKevin Bowling mta[idx].vmdq = sc->pool; 3452c19c7afeSEric Joyner 3453c19c7afeSEric Joyner return (1); 3454c19c7afeSEric Joyner } /* ixgbe_mc_filter_apply */ 3455c19c7afeSEric Joyner 3456c19c7afeSEric Joyner static void 3457c19c7afeSEric Joyner ixgbe_if_multi_set(if_ctx_t ctx) 3458c19c7afeSEric Joyner { 3459b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 34608eb6488eSEric Joyner struct ixgbe_mc_addr *mta; 3461ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(ctx); 34628eb6488eSEric Joyner u8 *update_ptr; 34638eb6488eSEric Joyner u32 fctrl; 3464ba76aa63SGleb Smirnoff u_int mcnt; 34658eb6488eSEric Joyner 3466c19c7afeSEric Joyner IOCTL_DEBUGOUT("ixgbe_if_multi_set: begin"); 34678eb6488eSEric Joyner 3468b1d5caf3SKevin Bowling mta = sc->mta; 34698eb6488eSEric Joyner bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES); 34708eb6488eSEric Joyner 3471b1d5caf3SKevin Bowling mcnt = if_foreach_llmaddr(iflib_get_ifp(ctx), ixgbe_mc_filter_apply, sc); 34728eb6488eSEric Joyner 3473395cc55dSKevin Bowling if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) { 3474395cc55dSKevin Bowling update_ptr = (u8 *)mta; 3475395cc55dSKevin Bowling ixgbe_update_mc_addr_list(&sc->hw, update_ptr, mcnt, 3476395cc55dSKevin Bowling ixgbe_mc_array_itr, true); 3477395cc55dSKevin Bowling } 3478395cc55dSKevin Bowling 3479b1d5caf3SKevin Bowling fctrl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL); 3480deecaa14SKevin Bowling 3481ff06a8dbSJustin Hibbits if (if_getflags(ifp) & IFF_PROMISC) 34828eb6488eSEric Joyner fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 34838eb6488eSEric Joyner else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES || 3484ff06a8dbSJustin Hibbits if_getflags(ifp) & IFF_ALLMULTI) { 34858eb6488eSEric Joyner fctrl |= IXGBE_FCTRL_MPE; 34868eb6488eSEric Joyner fctrl &= ~IXGBE_FCTRL_UPE; 34878eb6488eSEric Joyner } else 34888eb6488eSEric Joyner fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 34898eb6488eSEric Joyner 3490b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, fctrl); 3491c19c7afeSEric Joyner } /* ixgbe_if_multi_set */ 34928eb6488eSEric Joyner 34938eb6488eSEric Joyner /************************************************************************ 34948eb6488eSEric Joyner * ixgbe_mc_array_itr 34958eb6488eSEric Joyner * 34968eb6488eSEric Joyner * An iterator function needed by the multicast shared code. 34978eb6488eSEric Joyner * It feeds the shared code routine the addresses in the 34988eb6488eSEric Joyner * array of ixgbe_set_multi() one by one. 34998eb6488eSEric Joyner ************************************************************************/ 35008eb6488eSEric Joyner static u8 * 35018eb6488eSEric Joyner ixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq) 35028eb6488eSEric Joyner { 35038eb6488eSEric Joyner struct ixgbe_mc_addr *mta; 35048eb6488eSEric Joyner 35058eb6488eSEric Joyner mta = (struct ixgbe_mc_addr *)*update_ptr; 35068eb6488eSEric Joyner *vmdq = mta->vmdq; 35078eb6488eSEric Joyner 35088eb6488eSEric Joyner *update_ptr = (u8*)(mta + 1); 35098eb6488eSEric Joyner 35108eb6488eSEric Joyner return (mta->addr); 35118eb6488eSEric Joyner } /* ixgbe_mc_array_itr */ 35128eb6488eSEric Joyner 35138eb6488eSEric Joyner /************************************************************************ 35148eb6488eSEric Joyner * ixgbe_local_timer - Timer routine 35158eb6488eSEric Joyner * 35168eb6488eSEric Joyner * Checks for link status, updates statistics, 35178eb6488eSEric Joyner * and runs the watchdog check. 35188eb6488eSEric Joyner ************************************************************************/ 35198eb6488eSEric Joyner static void 3520c19c7afeSEric Joyner ixgbe_if_timer(if_ctx_t ctx, uint16_t qid) 35218eb6488eSEric Joyner { 3522b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 35238eb6488eSEric Joyner 3524c19c7afeSEric Joyner if (qid != 0) 3525c19c7afeSEric Joyner return; 35268eb6488eSEric Joyner 35278eb6488eSEric Joyner /* Check for pluggable optics */ 3528b1d5caf3SKevin Bowling if (sc->sfp_probe) 3529c19c7afeSEric Joyner if (!ixgbe_sfp_probe(ctx)) 3530c19c7afeSEric Joyner return; /* Nothing to do */ 35318eb6488eSEric Joyner 3532b1d5caf3SKevin Bowling ixgbe_check_link(&sc->hw, &sc->link_speed, &sc->link_up, 0); 35338eb6488eSEric Joyner 3534c19c7afeSEric Joyner /* Fire off the adminq task */ 3535c19c7afeSEric Joyner iflib_admin_intr_deferred(ctx); 35368eb6488eSEric Joyner 3537c19c7afeSEric Joyner } /* ixgbe_if_timer */ 35388eb6488eSEric Joyner 35398eb6488eSEric Joyner /************************************************************************ 3540f72de14eSKevin Bowling * ixgbe_fw_mode_timer - FW mode timer routine 3541f72de14eSKevin Bowling ************************************************************************/ 3542f72de14eSKevin Bowling static void 3543f72de14eSKevin Bowling ixgbe_fw_mode_timer(void *arg) 3544f72de14eSKevin Bowling { 3545f72de14eSKevin Bowling struct ixgbe_softc *sc = arg; 3546f72de14eSKevin Bowling struct ixgbe_hw *hw = &sc->hw; 3547f72de14eSKevin Bowling 3548f72de14eSKevin Bowling if (ixgbe_fw_recovery_mode(hw)) { 3549f72de14eSKevin Bowling if (atomic_cmpset_acq_int(&sc->recovery_mode, 0, 1)) { 3550f72de14eSKevin Bowling /* Firmware error detected, entering recovery mode */ 3551f72de14eSKevin Bowling device_printf(sc->dev, "Firmware recovery mode detected. Limiting" 3552f72de14eSKevin Bowling " functionality. Refer to the Intel(R) Ethernet Adapters" 3553f72de14eSKevin Bowling " and Devices User Guide for details on firmware recovery" 3554f72de14eSKevin Bowling " mode.\n"); 3555f72de14eSKevin Bowling 3556f72de14eSKevin Bowling if (hw->adapter_stopped == FALSE) 3557f72de14eSKevin Bowling ixgbe_if_stop(sc->ctx); 3558f72de14eSKevin Bowling } 3559f72de14eSKevin Bowling } else 3560f72de14eSKevin Bowling atomic_cmpset_acq_int(&sc->recovery_mode, 1, 0); 3561f72de14eSKevin Bowling 3562f72de14eSKevin Bowling 3563f72de14eSKevin Bowling callout_reset(&sc->fw_mode_timer, hz, 3564f72de14eSKevin Bowling ixgbe_fw_mode_timer, sc); 3565f72de14eSKevin Bowling } /* ixgbe_fw_mode_timer */ 3566f72de14eSKevin Bowling 3567f72de14eSKevin Bowling /************************************************************************ 35688eb6488eSEric Joyner * ixgbe_sfp_probe 35698eb6488eSEric Joyner * 35708eb6488eSEric Joyner * Determine if a port had optics inserted. 35718eb6488eSEric Joyner ************************************************************************/ 35728eb6488eSEric Joyner static bool 3573c19c7afeSEric Joyner ixgbe_sfp_probe(if_ctx_t ctx) 35748eb6488eSEric Joyner { 3575b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3576b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 3577c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 357879b36ec9SKevin Bowling bool result = false; 35798eb6488eSEric Joyner 35808eb6488eSEric Joyner if ((hw->phy.type == ixgbe_phy_nl) && 35818eb6488eSEric Joyner (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) { 35828eb6488eSEric Joyner s32 ret = hw->phy.ops.identify_sfp(hw); 35838eb6488eSEric Joyner if (ret) 35848eb6488eSEric Joyner goto out; 35858eb6488eSEric Joyner ret = hw->phy.ops.reset(hw); 3586b1d5caf3SKevin Bowling sc->sfp_probe = false; 35878eb6488eSEric Joyner if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { 35888eb6488eSEric Joyner device_printf(dev, "Unsupported SFP+ module detected!"); 35898eb6488eSEric Joyner device_printf(dev, 35908eb6488eSEric Joyner "Reload driver with supported module.\n"); 35918eb6488eSEric Joyner goto out; 35928eb6488eSEric Joyner } else 35938eb6488eSEric Joyner device_printf(dev, "SFP+ module detected!\n"); 35948eb6488eSEric Joyner /* We now have supported optics */ 359579b36ec9SKevin Bowling result = true; 35968eb6488eSEric Joyner } 35978eb6488eSEric Joyner out: 35988eb6488eSEric Joyner 35998eb6488eSEric Joyner return (result); 36008eb6488eSEric Joyner } /* ixgbe_sfp_probe */ 36018eb6488eSEric Joyner 36028eb6488eSEric Joyner /************************************************************************ 36038eb6488eSEric Joyner * ixgbe_handle_mod - Tasklet for SFP module interrupts 36048eb6488eSEric Joyner ************************************************************************/ 36058eb6488eSEric Joyner static void 3606c19c7afeSEric Joyner ixgbe_handle_mod(void *context) 36078eb6488eSEric Joyner { 3608c19c7afeSEric Joyner if_ctx_t ctx = context; 3609b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3610b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 3611c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 36128eb6488eSEric Joyner u32 err, cage_full = 0; 36138eb6488eSEric Joyner 3614b1d5caf3SKevin Bowling if (sc->hw.need_crosstalk_fix) { 36158eb6488eSEric Joyner switch (hw->mac.type) { 36168eb6488eSEric Joyner case ixgbe_mac_82599EB: 36178eb6488eSEric Joyner cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 36188eb6488eSEric Joyner IXGBE_ESDP_SDP2; 36198eb6488eSEric Joyner break; 36208eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 36218eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 36228eb6488eSEric Joyner cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 36238eb6488eSEric Joyner IXGBE_ESDP_SDP0; 36248eb6488eSEric Joyner break; 36258eb6488eSEric Joyner default: 36268eb6488eSEric Joyner break; 36278eb6488eSEric Joyner } 36288eb6488eSEric Joyner 36298eb6488eSEric Joyner if (!cage_full) 3630c19c7afeSEric Joyner goto handle_mod_out; 36318eb6488eSEric Joyner } 36328eb6488eSEric Joyner 36338eb6488eSEric Joyner err = hw->phy.ops.identify_sfp(hw); 36348eb6488eSEric Joyner if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 36358eb6488eSEric Joyner device_printf(dev, 36368eb6488eSEric Joyner "Unsupported SFP+ module type was detected.\n"); 3637c19c7afeSEric Joyner goto handle_mod_out; 36388eb6488eSEric Joyner } 36398eb6488eSEric Joyner 3640c19c7afeSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) 3641c19c7afeSEric Joyner err = hw->phy.ops.reset(hw); 3642c19c7afeSEric Joyner else 36438eb6488eSEric Joyner err = hw->mac.ops.setup_sfp(hw); 3644c19c7afeSEric Joyner 36458eb6488eSEric Joyner if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 36468eb6488eSEric Joyner device_printf(dev, 36478eb6488eSEric Joyner "Setup failure - unsupported SFP+ module type.\n"); 3648c19c7afeSEric Joyner goto handle_mod_out; 36498eb6488eSEric Joyner } 3650b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MSF; 3651c19c7afeSEric Joyner return; 3652c19c7afeSEric Joyner 3653c19c7afeSEric Joyner handle_mod_out: 3654b1d5caf3SKevin Bowling sc->task_requests &= ~(IXGBE_REQUEST_TASK_MSF); 36558eb6488eSEric Joyner } /* ixgbe_handle_mod */ 36568eb6488eSEric Joyner 36578eb6488eSEric Joyner 36588eb6488eSEric Joyner /************************************************************************ 36598eb6488eSEric Joyner * ixgbe_handle_msf - Tasklet for MSF (multispeed fiber) interrupts 36608eb6488eSEric Joyner ************************************************************************/ 36618eb6488eSEric Joyner static void 3662c19c7afeSEric Joyner ixgbe_handle_msf(void *context) 36638eb6488eSEric Joyner { 3664c19c7afeSEric Joyner if_ctx_t ctx = context; 3665b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3666b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 36678eb6488eSEric Joyner u32 autoneg; 36688eb6488eSEric Joyner bool negotiate; 36698eb6488eSEric Joyner 36708eb6488eSEric Joyner /* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */ 3671b1d5caf3SKevin Bowling sc->phy_layer = ixgbe_get_supported_physical_layer(hw); 36728eb6488eSEric Joyner 36738eb6488eSEric Joyner autoneg = hw->phy.autoneg_advertised; 36748eb6488eSEric Joyner if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) 36758eb6488eSEric Joyner hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate); 36768eb6488eSEric Joyner if (hw->mac.ops.setup_link) 367779b36ec9SKevin Bowling hw->mac.ops.setup_link(hw, autoneg, true); 36788eb6488eSEric Joyner 36798eb6488eSEric Joyner /* Adjust media types shown in ifconfig */ 3680b1d5caf3SKevin Bowling ifmedia_removeall(sc->media); 3681b1d5caf3SKevin Bowling ixgbe_add_media_types(sc->ctx); 3682b1d5caf3SKevin Bowling ifmedia_set(sc->media, IFM_ETHER | IFM_AUTO); 36838eb6488eSEric Joyner } /* ixgbe_handle_msf */ 36848eb6488eSEric Joyner 36858eb6488eSEric Joyner /************************************************************************ 36868eb6488eSEric Joyner * ixgbe_handle_phy - Tasklet for external PHY interrupts 36878eb6488eSEric Joyner ************************************************************************/ 36888eb6488eSEric Joyner static void 3689c19c7afeSEric Joyner ixgbe_handle_phy(void *context) 36908eb6488eSEric Joyner { 3691c19c7afeSEric Joyner if_ctx_t ctx = context; 3692b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3693b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 36948eb6488eSEric Joyner int error; 36958eb6488eSEric Joyner 36968eb6488eSEric Joyner error = hw->phy.ops.handle_lasi(hw); 36978eb6488eSEric Joyner if (error == IXGBE_ERR_OVERTEMP) 3698b1d5caf3SKevin Bowling device_printf(sc->dev, "CRITICAL: EXTERNAL PHY OVER TEMP!! PHY will downshift to lower power state!\n"); 36998eb6488eSEric Joyner else if (error) 3700b1d5caf3SKevin Bowling device_printf(sc->dev, 37018eb6488eSEric Joyner "Error handling LASI interrupt: %d\n", error); 37028eb6488eSEric Joyner } /* ixgbe_handle_phy */ 37038eb6488eSEric Joyner 37048eb6488eSEric Joyner /************************************************************************ 3705c19c7afeSEric Joyner * ixgbe_if_stop - Stop the hardware 37068eb6488eSEric Joyner * 37078eb6488eSEric Joyner * Disables all traffic on the adapter by issuing a 37088eb6488eSEric Joyner * global reset on the MAC and deallocates TX/RX buffers. 37098eb6488eSEric Joyner ************************************************************************/ 37108eb6488eSEric Joyner static void 3711c19c7afeSEric Joyner ixgbe_if_stop(if_ctx_t ctx) 37128eb6488eSEric Joyner { 3713b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3714b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 37158eb6488eSEric Joyner 3716c19c7afeSEric Joyner INIT_DEBUGOUT("ixgbe_if_stop: begin\n"); 37178eb6488eSEric Joyner 37188eb6488eSEric Joyner ixgbe_reset_hw(hw); 371979b36ec9SKevin Bowling hw->adapter_stopped = false; 37208eb6488eSEric Joyner ixgbe_stop_adapter(hw); 37218eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_82599EB) 37228eb6488eSEric Joyner ixgbe_stop_mac_link_on_d3_82599(hw); 37238eb6488eSEric Joyner /* Turn off the laser - noop with no optics */ 37248eb6488eSEric Joyner ixgbe_disable_tx_laser(hw); 37258eb6488eSEric Joyner 37268eb6488eSEric Joyner /* Update the stack */ 3727b1d5caf3SKevin Bowling sc->link_up = false; 3728c19c7afeSEric Joyner ixgbe_if_update_admin_status(ctx); 37298eb6488eSEric Joyner 37308eb6488eSEric Joyner /* reprogram the RAR[0] in case user changed it. */ 3731b1d5caf3SKevin Bowling ixgbe_set_rar(&sc->hw, 0, sc->hw.mac.addr, 0, IXGBE_RAH_AV); 37328eb6488eSEric Joyner 37338eb6488eSEric Joyner return; 3734c19c7afeSEric Joyner } /* ixgbe_if_stop */ 37358eb6488eSEric Joyner 37368eb6488eSEric Joyner /************************************************************************ 37378eb6488eSEric Joyner * ixgbe_update_link_status - Update OS on link state 37388eb6488eSEric Joyner * 37398eb6488eSEric Joyner * Note: Only updates the OS on the cached link state. 37408eb6488eSEric Joyner * The real check of the hardware only happens with 37418eb6488eSEric Joyner * a link interrupt. 37428eb6488eSEric Joyner ************************************************************************/ 37438eb6488eSEric Joyner static void 3744c19c7afeSEric Joyner ixgbe_if_update_admin_status(if_ctx_t ctx) 37458eb6488eSEric Joyner { 3746b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3747c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 37488eb6488eSEric Joyner 3749b1d5caf3SKevin Bowling if (sc->link_up) { 3750b1d5caf3SKevin Bowling if (sc->link_active == false) { 37518eb6488eSEric Joyner if (bootverbose) 37528eb6488eSEric Joyner device_printf(dev, "Link is up %d Gbps %s \n", 3753b1d5caf3SKevin Bowling ((sc->link_speed == 128) ? 10 : 1), 37548eb6488eSEric Joyner "Full Duplex"); 3755b1d5caf3SKevin Bowling sc->link_active = true; 37568eb6488eSEric Joyner /* Update any Flow Control changes */ 3757b1d5caf3SKevin Bowling ixgbe_fc_enable(&sc->hw); 37588eb6488eSEric Joyner /* Update DMA coalescing config */ 3759b1d5caf3SKevin Bowling ixgbe_config_dmac(sc); 3760a0302c92SPiotr Pietruszewski iflib_link_state_change(ctx, LINK_STATE_UP, 37615ddb1aa3SPiotr Kubaj ixgbe_link_speed_to_baudrate(sc->link_speed)); 3762c19c7afeSEric Joyner 3763b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_SRIOV) 3764b1d5caf3SKevin Bowling ixgbe_ping_all_vfs(sc); 37658eb6488eSEric Joyner } 37668eb6488eSEric Joyner } else { /* Link down */ 3767b1d5caf3SKevin Bowling if (sc->link_active == true) { 37688eb6488eSEric Joyner if (bootverbose) 37698eb6488eSEric Joyner device_printf(dev, "Link is Down\n"); 3770c19c7afeSEric Joyner iflib_link_state_change(ctx, LINK_STATE_DOWN, 0); 3771b1d5caf3SKevin Bowling sc->link_active = false; 3772b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_SRIOV) 3773b1d5caf3SKevin Bowling ixgbe_ping_all_vfs(sc); 37748eb6488eSEric Joyner } 37758eb6488eSEric Joyner } 37768eb6488eSEric Joyner 3777b2c1e8e6SEric Joyner /* Handle task requests from msix_link() */ 3778b1d5caf3SKevin Bowling if (sc->task_requests & IXGBE_REQUEST_TASK_MOD) 3779b2c1e8e6SEric Joyner ixgbe_handle_mod(ctx); 3780b1d5caf3SKevin Bowling if (sc->task_requests & IXGBE_REQUEST_TASK_MSF) 3781b2c1e8e6SEric Joyner ixgbe_handle_msf(ctx); 3782b1d5caf3SKevin Bowling if (sc->task_requests & IXGBE_REQUEST_TASK_MBX) 3783b2c1e8e6SEric Joyner ixgbe_handle_mbx(ctx); 3784b1d5caf3SKevin Bowling if (sc->task_requests & IXGBE_REQUEST_TASK_FDIR) 3785b2c1e8e6SEric Joyner ixgbe_reinit_fdir(ctx); 3786b1d5caf3SKevin Bowling if (sc->task_requests & IXGBE_REQUEST_TASK_PHY) 3787b2c1e8e6SEric Joyner ixgbe_handle_phy(ctx); 3788b1d5caf3SKevin Bowling sc->task_requests = 0; 3789c19c7afeSEric Joyner 3790b1d5caf3SKevin Bowling ixgbe_update_stats_counters(sc); 3791c19c7afeSEric Joyner } /* ixgbe_if_update_admin_status */ 37928eb6488eSEric Joyner 37938eb6488eSEric Joyner /************************************************************************ 37948eb6488eSEric Joyner * ixgbe_config_dmac - Configure DMA Coalescing 37958eb6488eSEric Joyner ************************************************************************/ 37968eb6488eSEric Joyner static void 3797b1d5caf3SKevin Bowling ixgbe_config_dmac(struct ixgbe_softc *sc) 37988eb6488eSEric Joyner { 3799b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 38008eb6488eSEric Joyner struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config; 38018eb6488eSEric Joyner 38028eb6488eSEric Joyner if (hw->mac.type < ixgbe_mac_X550 || !hw->mac.ops.dmac_config) 38038eb6488eSEric Joyner return; 38048eb6488eSEric Joyner 3805b1d5caf3SKevin Bowling if (dcfg->watchdog_timer ^ sc->dmac || 3806b1d5caf3SKevin Bowling dcfg->link_speed ^ sc->link_speed) { 3807b1d5caf3SKevin Bowling dcfg->watchdog_timer = sc->dmac; 380879b36ec9SKevin Bowling dcfg->fcoe_en = false; 3809b1d5caf3SKevin Bowling dcfg->link_speed = sc->link_speed; 38108eb6488eSEric Joyner dcfg->num_tcs = 1; 38118eb6488eSEric Joyner 38128eb6488eSEric Joyner INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n", 38138eb6488eSEric Joyner dcfg->watchdog_timer, dcfg->link_speed); 38148eb6488eSEric Joyner 38158eb6488eSEric Joyner hw->mac.ops.dmac_config(hw); 38168eb6488eSEric Joyner } 38178eb6488eSEric Joyner } /* ixgbe_config_dmac */ 38188eb6488eSEric Joyner 38198eb6488eSEric Joyner /************************************************************************ 3820c19c7afeSEric Joyner * ixgbe_if_enable_intr 38218eb6488eSEric Joyner ************************************************************************/ 3822c19c7afeSEric Joyner void 3823c19c7afeSEric Joyner ixgbe_if_enable_intr(if_ctx_t ctx) 38248eb6488eSEric Joyner { 3825b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3826b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 3827b1d5caf3SKevin Bowling struct ix_rx_queue *que = sc->rx_queues; 38288eb6488eSEric Joyner u32 mask, fwsm; 38298eb6488eSEric Joyner 38308eb6488eSEric Joyner mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); 38318eb6488eSEric Joyner 3832b1d5caf3SKevin Bowling switch (sc->hw.mac.type) { 38338eb6488eSEric Joyner case ixgbe_mac_82599EB: 38348eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 3835b1d5caf3SKevin Bowling /* Temperature sensor on some scs */ 38368eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP0; 38378eb6488eSEric Joyner /* SFP+ (RX_LOS_N & MOD_ABS_N) */ 38388eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP1; 38398eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP2; 38408eb6488eSEric Joyner break; 38418eb6488eSEric Joyner case ixgbe_mac_X540: 38428eb6488eSEric Joyner /* Detect if Thermal Sensor is enabled */ 38438eb6488eSEric Joyner fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); 38448eb6488eSEric Joyner if (fwsm & IXGBE_FWSM_TS_ENABLED) 38458eb6488eSEric Joyner mask |= IXGBE_EIMS_TS; 38468eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 38478eb6488eSEric Joyner break; 38488eb6488eSEric Joyner case ixgbe_mac_X550: 38498eb6488eSEric Joyner /* MAC thermal sensor is automatically enabled */ 38508eb6488eSEric Joyner mask |= IXGBE_EIMS_TS; 38518eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 38528eb6488eSEric Joyner break; 38538eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 38548eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 38558eb6488eSEric Joyner /* Some devices use SDP0 for important information */ 38568eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP || 38578eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP || 38588eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N || 38598eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) 38608eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw); 38618eb6488eSEric Joyner if (hw->phy.type == ixgbe_phy_x550em_ext_t) 38628eb6488eSEric Joyner mask |= IXGBE_EICR_GPI_SDP0_X540; 38638eb6488eSEric Joyner mask |= IXGBE_EIMS_ECC; 38648eb6488eSEric Joyner break; 38658eb6488eSEric Joyner default: 38668eb6488eSEric Joyner break; 38678eb6488eSEric Joyner } 38688eb6488eSEric Joyner 38698eb6488eSEric Joyner /* Enable Fan Failure detection */ 3870b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_FAN_FAIL) 38718eb6488eSEric Joyner mask |= IXGBE_EIMS_GPI_SDP1; 38728eb6488eSEric Joyner /* Enable SR-IOV */ 3873b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_SRIOV) 38748eb6488eSEric Joyner mask |= IXGBE_EIMS_MAILBOX; 38758eb6488eSEric Joyner /* Enable Flow Director */ 3876b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_FDIR) 38778eb6488eSEric Joyner mask |= IXGBE_EIMS_FLOW_DIR; 38788eb6488eSEric Joyner 38798eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); 38808eb6488eSEric Joyner 38818eb6488eSEric Joyner /* With MSI-X we use auto clear */ 3882b1d5caf3SKevin Bowling if (sc->intr_type == IFLIB_INTR_MSIX) { 38838eb6488eSEric Joyner mask = IXGBE_EIMS_ENABLE_MASK; 38848eb6488eSEric Joyner /* Don't autoclear Link */ 38858eb6488eSEric Joyner mask &= ~IXGBE_EIMS_OTHER; 38868eb6488eSEric Joyner mask &= ~IXGBE_EIMS_LSC; 3887b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_SRIOV) 38888eb6488eSEric Joyner mask &= ~IXGBE_EIMS_MAILBOX; 38898eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask); 38906f37f232SEric Joyner } 38916f37f232SEric Joyner 3892758cc3dcSJack F Vogel /* 38938eb6488eSEric Joyner * Now enable all queues, this is done separately to 38948eb6488eSEric Joyner * allow for handling the extended (beyond 32) MSI-X 38958eb6488eSEric Joyner * vectors that can be used by 82599 3896758cc3dcSJack F Vogel */ 3897b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++, que++) 3898b1d5caf3SKevin Bowling ixgbe_enable_queue(sc, que->msix); 38998eb6488eSEric Joyner 39008eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 39018eb6488eSEric Joyner 3902c19c7afeSEric Joyner } /* ixgbe_if_enable_intr */ 39038eb6488eSEric Joyner 39048eb6488eSEric Joyner /************************************************************************ 39058eb6488eSEric Joyner * ixgbe_disable_intr 39068eb6488eSEric Joyner ************************************************************************/ 3907758cc3dcSJack F Vogel static void 3908c19c7afeSEric Joyner ixgbe_if_disable_intr(if_ctx_t ctx) 3909758cc3dcSJack F Vogel { 3910b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3911c19c7afeSEric Joyner 3912b1d5caf3SKevin Bowling if (sc->intr_type == IFLIB_INTR_MSIX) 3913b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAC, 0); 3914b1d5caf3SKevin Bowling if (sc->hw.mac.type == ixgbe_mac_82598EB) { 3915b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC, ~0); 39168eb6488eSEric Joyner } else { 3917b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC, 0xFFFF0000); 3918b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC_EX(0), ~0); 3919b1d5caf3SKevin Bowling IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC_EX(1), ~0); 39208eb6488eSEric Joyner } 3921b1d5caf3SKevin Bowling IXGBE_WRITE_FLUSH(&sc->hw); 3922758cc3dcSJack F Vogel 3923c19c7afeSEric Joyner } /* ixgbe_if_disable_intr */ 39248eb6488eSEric Joyner 39258eb6488eSEric Joyner /************************************************************************ 3926b2c1e8e6SEric Joyner * ixgbe_link_intr_enable 3927b2c1e8e6SEric Joyner ************************************************************************/ 3928b2c1e8e6SEric Joyner static void 3929b2c1e8e6SEric Joyner ixgbe_link_intr_enable(if_ctx_t ctx) 3930b2c1e8e6SEric Joyner { 3931b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &((struct ixgbe_softc *)iflib_get_softc(ctx))->hw; 3932b2c1e8e6SEric Joyner 3933b2c1e8e6SEric Joyner /* Re-enable other interrupts */ 3934b2c1e8e6SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC); 3935b2c1e8e6SEric Joyner } /* ixgbe_link_intr_enable */ 3936b2c1e8e6SEric Joyner 3937b2c1e8e6SEric Joyner /************************************************************************ 3938c19c7afeSEric Joyner * ixgbe_if_rx_queue_intr_enable 3939c19c7afeSEric Joyner ************************************************************************/ 3940c19c7afeSEric Joyner static int 3941c19c7afeSEric Joyner ixgbe_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid) 3942c19c7afeSEric Joyner { 3943b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 3944b1d5caf3SKevin Bowling struct ix_rx_queue *que = &sc->rx_queues[rxqid]; 3945c19c7afeSEric Joyner 3946b1d5caf3SKevin Bowling ixgbe_enable_queue(sc, que->msix); 3947c19c7afeSEric Joyner 3948c19c7afeSEric Joyner return (0); 3949c19c7afeSEric Joyner } /* ixgbe_if_rx_queue_intr_enable */ 3950c19c7afeSEric Joyner 3951c19c7afeSEric Joyner /************************************************************************ 3952c19c7afeSEric Joyner * ixgbe_enable_queue 39538eb6488eSEric Joyner ************************************************************************/ 39548eb6488eSEric Joyner static void 3955b1d5caf3SKevin Bowling ixgbe_enable_queue(struct ixgbe_softc *sc, u32 vector) 39568eb6488eSEric Joyner { 3957b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 39582dc2d580SEric Joyner u64 queue = 1ULL << vector; 3959c19c7afeSEric Joyner u32 mask; 3960758cc3dcSJack F Vogel 3961c19c7afeSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) { 3962c19c7afeSEric Joyner mask = (IXGBE_EIMS_RTX_QUEUE & queue); 3963c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); 3964c19c7afeSEric Joyner } else { 3965c19c7afeSEric Joyner mask = (queue & 0xFFFFFFFF); 3966c19c7afeSEric Joyner if (mask) 3967c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); 3968c19c7afeSEric Joyner mask = (queue >> 32); 3969c19c7afeSEric Joyner if (mask) 3970c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask); 3971c19c7afeSEric Joyner } 3972c19c7afeSEric Joyner } /* ixgbe_enable_queue */ 3973c19c7afeSEric Joyner 3974c19c7afeSEric Joyner /************************************************************************ 3975c19c7afeSEric Joyner * ixgbe_disable_queue 3976c19c7afeSEric Joyner ************************************************************************/ 3977c19c7afeSEric Joyner static void 3978b1d5caf3SKevin Bowling ixgbe_disable_queue(struct ixgbe_softc *sc, u32 vector) 3979c19c7afeSEric Joyner { 3980b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 39812dc2d580SEric Joyner u64 queue = 1ULL << vector; 3982c19c7afeSEric Joyner u32 mask; 3983c19c7afeSEric Joyner 3984c19c7afeSEric Joyner if (hw->mac.type == ixgbe_mac_82598EB) { 3985c19c7afeSEric Joyner mask = (IXGBE_EIMS_RTX_QUEUE & queue); 3986c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask); 3987c19c7afeSEric Joyner } else { 3988c19c7afeSEric Joyner mask = (queue & 0xFFFFFFFF); 3989c19c7afeSEric Joyner if (mask) 3990c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask); 3991c19c7afeSEric Joyner mask = (queue >> 32); 3992c19c7afeSEric Joyner if (mask) 3993c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask); 3994c19c7afeSEric Joyner } 3995c19c7afeSEric Joyner } /* ixgbe_disable_queue */ 3996c19c7afeSEric Joyner 3997c19c7afeSEric Joyner /************************************************************************ 3998c19c7afeSEric Joyner * ixgbe_intr - Legacy Interrupt Service Routine 3999c19c7afeSEric Joyner ************************************************************************/ 4000c19c7afeSEric Joyner int 4001c19c7afeSEric Joyner ixgbe_intr(void *arg) 4002c19c7afeSEric Joyner { 4003b1d5caf3SKevin Bowling struct ixgbe_softc *sc = arg; 4004b1d5caf3SKevin Bowling struct ix_rx_queue *que = sc->rx_queues; 4005b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 4006b1d5caf3SKevin Bowling if_ctx_t ctx = sc->ctx; 4007c19c7afeSEric Joyner u32 eicr, eicr_mask; 4008758cc3dcSJack F Vogel 40098eb6488eSEric Joyner eicr = IXGBE_READ_REG(hw, IXGBE_EICR); 4010758cc3dcSJack F Vogel 40118eb6488eSEric Joyner ++que->irqs; 40128eb6488eSEric Joyner if (eicr == 0) { 4013c19c7afeSEric Joyner ixgbe_if_enable_intr(ctx); 4014c19c7afeSEric Joyner return (FILTER_HANDLED); 4015758cc3dcSJack F Vogel } 4016758cc3dcSJack F Vogel 40178eb6488eSEric Joyner /* Check for fan failure */ 4018f72de14eSKevin Bowling if ((sc->feat_en & IXGBE_FEATURE_FAN_FAIL) && 4019c19c7afeSEric Joyner (eicr & IXGBE_EICR_GPI_SDP1)) { 4020b1d5caf3SKevin Bowling device_printf(sc->dev, 4021c19c7afeSEric Joyner "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n"); 40228eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 4023758cc3dcSJack F Vogel } 4024758cc3dcSJack F Vogel 40258eb6488eSEric Joyner /* Link status change */ 4026c19c7afeSEric Joyner if (eicr & IXGBE_EICR_LSC) { 4027c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); 4028c19c7afeSEric Joyner iflib_admin_intr_deferred(ctx); 4029c19c7afeSEric Joyner } 40308eb6488eSEric Joyner 40318eb6488eSEric Joyner if (ixgbe_is_sfp(hw)) { 40328eb6488eSEric Joyner /* Pluggable optics-related interrupt */ 40338eb6488eSEric Joyner if (hw->mac.type >= ixgbe_mac_X540) 40348eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP0_X540; 40358eb6488eSEric Joyner else 40368eb6488eSEric Joyner eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); 40378eb6488eSEric Joyner 40388eb6488eSEric Joyner if (eicr & eicr_mask) { 40398eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); 4040b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MOD; 40418eb6488eSEric Joyner } 40428eb6488eSEric Joyner 40438eb6488eSEric Joyner if ((hw->mac.type == ixgbe_mac_82599EB) && 40448eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { 40458eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_EICR, 40468eb6488eSEric Joyner IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 4047b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_MSF; 40488eb6488eSEric Joyner } 40498eb6488eSEric Joyner } 40508eb6488eSEric Joyner 40518eb6488eSEric Joyner /* External PHY interrupt */ 40528eb6488eSEric Joyner if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && 40538eb6488eSEric Joyner (eicr & IXGBE_EICR_GPI_SDP0_X540)) 4054b1d5caf3SKevin Bowling sc->task_requests |= IXGBE_REQUEST_TASK_PHY; 40558eb6488eSEric Joyner 4056c19c7afeSEric Joyner return (FILTER_SCHEDULE_THREAD); 4057c19c7afeSEric Joyner } /* ixgbe_intr */ 40588eb6488eSEric Joyner 40598eb6488eSEric Joyner /************************************************************************ 40608eb6488eSEric Joyner * ixgbe_free_pci_resources 40618eb6488eSEric Joyner ************************************************************************/ 40628eb6488eSEric Joyner static void 4063c19c7afeSEric Joyner ixgbe_free_pci_resources(if_ctx_t ctx) 40648eb6488eSEric Joyner { 4065b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 4066b1d5caf3SKevin Bowling struct ix_rx_queue *que = sc->rx_queues; 4067c19c7afeSEric Joyner device_t dev = iflib_get_dev(ctx); 40688eb6488eSEric Joyner 4069b97de13aSMarius Strobl /* Release all MSI-X queue resources */ 4070b1d5caf3SKevin Bowling if (sc->intr_type == IFLIB_INTR_MSIX) 4071b1d5caf3SKevin Bowling iflib_irq_free(ctx, &sc->irq); 4072c19c7afeSEric Joyner 4073c19c7afeSEric Joyner if (que != NULL) { 4074b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++, que++) { 4075c19c7afeSEric Joyner iflib_irq_free(ctx, &que->que_irq); 4076c19c7afeSEric Joyner } 4077c19c7afeSEric Joyner } 40788eb6488eSEric Joyner 4079b1d5caf3SKevin Bowling if (sc->pci_mem != NULL) 4080c19c7afeSEric Joyner bus_release_resource(dev, SYS_RES_MEMORY, 4081b1d5caf3SKevin Bowling rman_get_rid(sc->pci_mem), sc->pci_mem); 40828eb6488eSEric Joyner } /* ixgbe_free_pci_resources */ 40838eb6488eSEric Joyner 40848eb6488eSEric Joyner /************************************************************************ 40858eb6488eSEric Joyner * ixgbe_sysctl_flowcntl 40868eb6488eSEric Joyner * 40878eb6488eSEric Joyner * SYSCTL wrapper around setting Flow Control 40888eb6488eSEric Joyner ************************************************************************/ 4089758cc3dcSJack F Vogel static int 4090f2c4db54SSteven Hartland ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS) 4091758cc3dcSJack F Vogel { 4092b1d5caf3SKevin Bowling struct ixgbe_softc *sc; 40938eb6488eSEric Joyner int error, fc; 4094758cc3dcSJack F Vogel 4095b1d5caf3SKevin Bowling sc = (struct ixgbe_softc *)arg1; 4096b1d5caf3SKevin Bowling fc = sc->hw.fc.current_mode; 4097f2c4db54SSteven Hartland 4098f2c4db54SSteven Hartland error = sysctl_handle_int(oidp, &fc, 0, req); 4099758cc3dcSJack F Vogel if ((error) || (req->newptr == NULL)) 4100758cc3dcSJack F Vogel return (error); 4101758cc3dcSJack F Vogel 4102758cc3dcSJack F Vogel /* Don't bother if it's not changed */ 4103b1d5caf3SKevin Bowling if (fc == sc->hw.fc.current_mode) 4104758cc3dcSJack F Vogel return (0); 4105758cc3dcSJack F Vogel 4106b1d5caf3SKevin Bowling return ixgbe_set_flowcntl(sc, fc); 41078eb6488eSEric Joyner } /* ixgbe_sysctl_flowcntl */ 4108f2c4db54SSteven Hartland 41098eb6488eSEric Joyner /************************************************************************ 41108eb6488eSEric Joyner * ixgbe_set_flowcntl - Set flow control 41118eb6488eSEric Joyner * 41128eb6488eSEric Joyner * Flow control values: 41138eb6488eSEric Joyner * 0 - off 41148eb6488eSEric Joyner * 1 - rx pause 41158eb6488eSEric Joyner * 2 - tx pause 41168eb6488eSEric Joyner * 3 - full 41178eb6488eSEric Joyner ************************************************************************/ 4118f2c4db54SSteven Hartland static int 4119b1d5caf3SKevin Bowling ixgbe_set_flowcntl(struct ixgbe_softc *sc, int fc) 4120f2c4db54SSteven Hartland { 4121f2c4db54SSteven Hartland switch (fc) { 4122758cc3dcSJack F Vogel case ixgbe_fc_rx_pause: 4123758cc3dcSJack F Vogel case ixgbe_fc_tx_pause: 4124758cc3dcSJack F Vogel case ixgbe_fc_full: 4125b1d5caf3SKevin Bowling sc->hw.fc.requested_mode = fc; 4126b1d5caf3SKevin Bowling if (sc->num_rx_queues > 1) 4127b1d5caf3SKevin Bowling ixgbe_disable_rx_drop(sc); 4128758cc3dcSJack F Vogel break; 4129758cc3dcSJack F Vogel case ixgbe_fc_none: 4130b1d5caf3SKevin Bowling sc->hw.fc.requested_mode = ixgbe_fc_none; 4131b1d5caf3SKevin Bowling if (sc->num_rx_queues > 1) 4132b1d5caf3SKevin Bowling ixgbe_enable_rx_drop(sc); 4133758cc3dcSJack F Vogel break; 4134758cc3dcSJack F Vogel default: 4135758cc3dcSJack F Vogel return (EINVAL); 4136758cc3dcSJack F Vogel } 41378eb6488eSEric Joyner 4138758cc3dcSJack F Vogel /* Don't autoneg if forcing a value */ 4139b1d5caf3SKevin Bowling sc->hw.fc.disable_fc_autoneg = true; 4140b1d5caf3SKevin Bowling ixgbe_fc_enable(&sc->hw); 41418eb6488eSEric Joyner 4142f2c4db54SSteven Hartland return (0); 41438eb6488eSEric Joyner } /* ixgbe_set_flowcntl */ 41448eb6488eSEric Joyner 41458eb6488eSEric Joyner /************************************************************************ 41468eb6488eSEric Joyner * ixgbe_enable_rx_drop 41478eb6488eSEric Joyner * 41488eb6488eSEric Joyner * Enable the hardware to drop packets when the buffer is 41498eb6488eSEric Joyner * full. This is useful with multiqueue, so that no single 41508eb6488eSEric Joyner * queue being full stalls the entire RX engine. We only 41518eb6488eSEric Joyner * enable this when Multiqueue is enabled AND Flow Control 41528eb6488eSEric Joyner * is disabled. 41538eb6488eSEric Joyner ************************************************************************/ 41548eb6488eSEric Joyner static void 4155b1d5caf3SKevin Bowling ixgbe_enable_rx_drop(struct ixgbe_softc *sc) 41568eb6488eSEric Joyner { 4157b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 41588eb6488eSEric Joyner struct rx_ring *rxr; 41598eb6488eSEric Joyner u32 srrctl; 41608eb6488eSEric Joyner 4161b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++) { 4162b1d5caf3SKevin Bowling rxr = &sc->rx_queues[i].rxr; 41638eb6488eSEric Joyner srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); 41648eb6488eSEric Joyner srrctl |= IXGBE_SRRCTL_DROP_EN; 41658eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); 4166758cc3dcSJack F Vogel } 4167758cc3dcSJack F Vogel 41688eb6488eSEric Joyner /* enable drop for each vf */ 4169b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_vfs; i++) { 41708eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_QDE, 41718eb6488eSEric Joyner (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT) | 41728eb6488eSEric Joyner IXGBE_QDE_ENABLE)); 41738eb6488eSEric Joyner } 41748eb6488eSEric Joyner } /* ixgbe_enable_rx_drop */ 41758eb6488eSEric Joyner 41768eb6488eSEric Joyner /************************************************************************ 41778eb6488eSEric Joyner * ixgbe_disable_rx_drop 41788eb6488eSEric Joyner ************************************************************************/ 41798eb6488eSEric Joyner static void 4180b1d5caf3SKevin Bowling ixgbe_disable_rx_drop(struct ixgbe_softc *sc) 41818eb6488eSEric Joyner { 4182b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 41838eb6488eSEric Joyner struct rx_ring *rxr; 41848eb6488eSEric Joyner u32 srrctl; 41858eb6488eSEric Joyner 4186b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_rx_queues; i++) { 4187b1d5caf3SKevin Bowling rxr = &sc->rx_queues[i].rxr; 41888eb6488eSEric Joyner srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); 41898eb6488eSEric Joyner srrctl &= ~IXGBE_SRRCTL_DROP_EN; 41908eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); 41918eb6488eSEric Joyner } 41928eb6488eSEric Joyner 41938eb6488eSEric Joyner /* disable drop for each vf */ 4194b1d5caf3SKevin Bowling for (int i = 0; i < sc->num_vfs; i++) { 41958eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_QDE, 41968eb6488eSEric Joyner (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT))); 41978eb6488eSEric Joyner } 41988eb6488eSEric Joyner } /* ixgbe_disable_rx_drop */ 41998eb6488eSEric Joyner 42008eb6488eSEric Joyner /************************************************************************ 42018eb6488eSEric Joyner * ixgbe_sysctl_advertise 42028eb6488eSEric Joyner * 42038eb6488eSEric Joyner * SYSCTL wrapper around setting advertised speed 42048eb6488eSEric Joyner ************************************************************************/ 4205758cc3dcSJack F Vogel static int 4206f2c4db54SSteven Hartland ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS) 4207758cc3dcSJack F Vogel { 4208b1d5caf3SKevin Bowling struct ixgbe_softc *sc; 42098eb6488eSEric Joyner int error, advertise; 4210758cc3dcSJack F Vogel 4211b1d5caf3SKevin Bowling sc = (struct ixgbe_softc *)arg1; 4212f72de14eSKevin Bowling if (atomic_load_acq_int(&sc->recovery_mode)) 4213f72de14eSKevin Bowling return (EPERM); 4214f72de14eSKevin Bowling 4215b1d5caf3SKevin Bowling advertise = sc->advertise; 4216758cc3dcSJack F Vogel 4217f2c4db54SSteven Hartland error = sysctl_handle_int(oidp, &advertise, 0, req); 4218758cc3dcSJack F Vogel if ((error) || (req->newptr == NULL)) 4219758cc3dcSJack F Vogel return (error); 4220758cc3dcSJack F Vogel 4221b1d5caf3SKevin Bowling return ixgbe_set_advertise(sc, advertise); 42228eb6488eSEric Joyner } /* ixgbe_sysctl_advertise */ 4223f2c4db54SSteven Hartland 42248eb6488eSEric Joyner /************************************************************************ 42258eb6488eSEric Joyner * ixgbe_set_advertise - Control advertised link speed 42268eb6488eSEric Joyner * 42278eb6488eSEric Joyner * Flags: 42288eb6488eSEric Joyner * 0x1 - advertise 100 Mb 42298eb6488eSEric Joyner * 0x2 - advertise 1G 42308eb6488eSEric Joyner * 0x4 - advertise 10G 42318eb6488eSEric Joyner * 0x8 - advertise 10 Mb (yes, Mb) 4232d381c807SPiotr Pietruszewski * 0x10 - advertise 2.5G (disabled by default) 4233d381c807SPiotr Pietruszewski * 0x20 - advertise 5G (disabled by default) 4234d381c807SPiotr Pietruszewski * 42358eb6488eSEric Joyner ************************************************************************/ 4236f2c4db54SSteven Hartland static int 4237b1d5caf3SKevin Bowling ixgbe_set_advertise(struct ixgbe_softc *sc, int advertise) 4238f2c4db54SSteven Hartland { 4239b1d5caf3SKevin Bowling device_t dev = iflib_get_dev(sc->ctx); 4240f2c4db54SSteven Hartland struct ixgbe_hw *hw; 42418eb6488eSEric Joyner ixgbe_link_speed speed = 0; 42428eb6488eSEric Joyner ixgbe_link_speed link_caps = 0; 42438eb6488eSEric Joyner s32 err = IXGBE_NOT_IMPLEMENTED; 424479b36ec9SKevin Bowling bool negotiate = false; 4245f2c4db54SSteven Hartland 4246d775d23aSSteven Hartland /* Checks to validate new value */ 4247b1d5caf3SKevin Bowling if (sc->advertise == advertise) /* no change */ 4248d775d23aSSteven Hartland return (0); 4249d775d23aSSteven Hartland 4250b1d5caf3SKevin Bowling hw = &sc->hw; 4251f2c4db54SSteven Hartland 4252a9ca1c79SSean Bruno /* No speed changes for backplane media */ 4253a9ca1c79SSean Bruno if (hw->phy.media_type == ixgbe_media_type_backplane) 4254a9ca1c79SSean Bruno return (ENODEV); 4255a9ca1c79SSean Bruno 4256758cc3dcSJack F Vogel if (!((hw->phy.media_type == ixgbe_media_type_copper) || 4257758cc3dcSJack F Vogel (hw->phy.multispeed_fiber))) { 42588eb6488eSEric Joyner device_printf(dev, "Advertised speed can only be set on copper or multispeed fiber media types.\n"); 4259758cc3dcSJack F Vogel return (EINVAL); 4260758cc3dcSJack F Vogel } 4261758cc3dcSJack F Vogel 4262d381c807SPiotr Pietruszewski if (advertise < 0x1 || advertise > 0x3F) { 4263d381c807SPiotr Pietruszewski device_printf(dev, "Invalid advertised speed; valid modes are 0x1 through 0x3F\n"); 4264758cc3dcSJack F Vogel return (EINVAL); 4265758cc3dcSJack F Vogel } 4266758cc3dcSJack F Vogel 42678eb6488eSEric Joyner if (hw->mac.ops.get_link_capabilities) { 42688eb6488eSEric Joyner err = hw->mac.ops.get_link_capabilities(hw, &link_caps, 42698eb6488eSEric Joyner &negotiate); 42708eb6488eSEric Joyner if (err != IXGBE_SUCCESS) { 42718eb6488eSEric Joyner device_printf(dev, "Unable to determine supported advertise speeds\n"); 42728eb6488eSEric Joyner return (ENODEV); 42738eb6488eSEric Joyner } 4274758cc3dcSJack F Vogel } 4275758cc3dcSJack F Vogel 4276758cc3dcSJack F Vogel /* Set new value and report new advertised mode */ 42778eb6488eSEric Joyner if (advertise & 0x1) { 42788eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_100_FULL)) { 42798eb6488eSEric Joyner device_printf(dev, "Interface does not support 100Mb advertised speed\n"); 42808eb6488eSEric Joyner return (EINVAL); 42818eb6488eSEric Joyner } 4282758cc3dcSJack F Vogel speed |= IXGBE_LINK_SPEED_100_FULL; 42838eb6488eSEric Joyner } 42848eb6488eSEric Joyner if (advertise & 0x2) { 42858eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_1GB_FULL)) { 42868eb6488eSEric Joyner device_printf(dev, "Interface does not support 1Gb advertised speed\n"); 42878eb6488eSEric Joyner return (EINVAL); 42888eb6488eSEric Joyner } 4289758cc3dcSJack F Vogel speed |= IXGBE_LINK_SPEED_1GB_FULL; 42908eb6488eSEric Joyner } 42918eb6488eSEric Joyner if (advertise & 0x4) { 42928eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_10GB_FULL)) { 42938eb6488eSEric Joyner device_printf(dev, "Interface does not support 10Gb advertised speed\n"); 42948eb6488eSEric Joyner return (EINVAL); 42958eb6488eSEric Joyner } 4296758cc3dcSJack F Vogel speed |= IXGBE_LINK_SPEED_10GB_FULL; 42978eb6488eSEric Joyner } 42988eb6488eSEric Joyner if (advertise & 0x8) { 42998eb6488eSEric Joyner if (!(link_caps & IXGBE_LINK_SPEED_10_FULL)) { 43008eb6488eSEric Joyner device_printf(dev, "Interface does not support 10Mb advertised speed\n"); 43018eb6488eSEric Joyner return (EINVAL); 43028eb6488eSEric Joyner } 43038eb6488eSEric Joyner speed |= IXGBE_LINK_SPEED_10_FULL; 43048eb6488eSEric Joyner } 4305d381c807SPiotr Pietruszewski if (advertise & 0x10) { 4306d381c807SPiotr Pietruszewski if (!(link_caps & IXGBE_LINK_SPEED_2_5GB_FULL)) { 4307d381c807SPiotr Pietruszewski device_printf(dev, "Interface does not support 2.5G advertised speed\n"); 4308d381c807SPiotr Pietruszewski return (EINVAL); 4309d381c807SPiotr Pietruszewski } 4310d381c807SPiotr Pietruszewski speed |= IXGBE_LINK_SPEED_2_5GB_FULL; 4311d381c807SPiotr Pietruszewski } 4312d381c807SPiotr Pietruszewski if (advertise & 0x20) { 4313d381c807SPiotr Pietruszewski if (!(link_caps & IXGBE_LINK_SPEED_5GB_FULL)) { 4314d381c807SPiotr Pietruszewski device_printf(dev, "Interface does not support 5G advertised speed\n"); 4315d381c807SPiotr Pietruszewski return (EINVAL); 4316d381c807SPiotr Pietruszewski } 4317d381c807SPiotr Pietruszewski speed |= IXGBE_LINK_SPEED_5GB_FULL; 4318d381c807SPiotr Pietruszewski } 4319758cc3dcSJack F Vogel 432079b36ec9SKevin Bowling hw->mac.autotry_restart = true; 432179b36ec9SKevin Bowling hw->mac.ops.setup_link(hw, speed, true); 4322b1d5caf3SKevin Bowling sc->advertise = advertise; 4323758cc3dcSJack F Vogel 4324f2c4db54SSteven Hartland return (0); 43258eb6488eSEric Joyner } /* ixgbe_set_advertise */ 43268eb6488eSEric Joyner 43278eb6488eSEric Joyner /************************************************************************ 4328d381c807SPiotr Pietruszewski * ixgbe_get_default_advertise - Get default advertised speed settings 43298eb6488eSEric Joyner * 43308eb6488eSEric Joyner * Formatted for sysctl usage. 43318eb6488eSEric Joyner * Flags: 43328eb6488eSEric Joyner * 0x1 - advertise 100 Mb 43338eb6488eSEric Joyner * 0x2 - advertise 1G 43348eb6488eSEric Joyner * 0x4 - advertise 10G 43358eb6488eSEric Joyner * 0x8 - advertise 10 Mb (yes, Mb) 4336d381c807SPiotr Pietruszewski * 0x10 - advertise 2.5G (disabled by default) 4337d381c807SPiotr Pietruszewski * 0x20 - advertise 5G (disabled by default) 43388eb6488eSEric Joyner ************************************************************************/ 43398eb6488eSEric Joyner static int 4340d381c807SPiotr Pietruszewski ixgbe_get_default_advertise(struct ixgbe_softc *sc) 43418eb6488eSEric Joyner { 4342b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 43438eb6488eSEric Joyner int speed; 43448eb6488eSEric Joyner ixgbe_link_speed link_caps = 0; 43458eb6488eSEric Joyner s32 err; 434679b36ec9SKevin Bowling bool negotiate = false; 4347758cc3dcSJack F Vogel 4348758cc3dcSJack F Vogel /* 43498eb6488eSEric Joyner * Advertised speed means nothing unless it's copper or 43508eb6488eSEric Joyner * multi-speed fiber 4351758cc3dcSJack F Vogel */ 43528eb6488eSEric Joyner if (!(hw->phy.media_type == ixgbe_media_type_copper) && 43538eb6488eSEric Joyner !(hw->phy.multispeed_fiber)) 4354758cc3dcSJack F Vogel return (0); 4355758cc3dcSJack F Vogel 43568eb6488eSEric Joyner err = hw->mac.ops.get_link_capabilities(hw, &link_caps, &negotiate); 43578eb6488eSEric Joyner if (err != IXGBE_SUCCESS) 43588eb6488eSEric Joyner return (0); 43598eb6488eSEric Joyner 4360d381c807SPiotr Pietruszewski if (hw->mac.type == ixgbe_mac_X550) { 4361d381c807SPiotr Pietruszewski /* 4362d381c807SPiotr Pietruszewski * 2.5G and 5G autonegotiation speeds on X550 4363d381c807SPiotr Pietruszewski * are disabled by default due to reported 4364d381c807SPiotr Pietruszewski * interoperability issues with some switches. 4365d381c807SPiotr Pietruszewski */ 4366d381c807SPiotr Pietruszewski link_caps &= ~(IXGBE_LINK_SPEED_2_5GB_FULL | 4367d381c807SPiotr Pietruszewski IXGBE_LINK_SPEED_5GB_FULL); 4368d381c807SPiotr Pietruszewski } 4369d381c807SPiotr Pietruszewski 43708eb6488eSEric Joyner speed = 4371d381c807SPiotr Pietruszewski ((link_caps & IXGBE_LINK_SPEED_10GB_FULL) ? 0x4 : 0) | 4372d381c807SPiotr Pietruszewski ((link_caps & IXGBE_LINK_SPEED_5GB_FULL) ? 0x20 : 0) | 4373d381c807SPiotr Pietruszewski ((link_caps & IXGBE_LINK_SPEED_2_5GB_FULL) ? 0x10 : 0) | 4374d381c807SPiotr Pietruszewski ((link_caps & IXGBE_LINK_SPEED_1GB_FULL) ? 0x2 : 0) | 4375d381c807SPiotr Pietruszewski ((link_caps & IXGBE_LINK_SPEED_100_FULL) ? 0x1 : 0) | 4376d381c807SPiotr Pietruszewski ((link_caps & IXGBE_LINK_SPEED_10_FULL) ? 0x8 : 0); 43778eb6488eSEric Joyner 43788eb6488eSEric Joyner return speed; 4379d381c807SPiotr Pietruszewski } /* ixgbe_get_default_advertise */ 43808eb6488eSEric Joyner 43818eb6488eSEric Joyner /************************************************************************ 43828eb6488eSEric Joyner * ixgbe_sysctl_dmac - Manage DMA Coalescing 43838eb6488eSEric Joyner * 43848eb6488eSEric Joyner * Control values: 43858eb6488eSEric Joyner * 0/1 - off / on (use default value of 1000) 43868eb6488eSEric Joyner * 43878eb6488eSEric Joyner * Legal timer values are: 43888eb6488eSEric Joyner * 50,100,250,500,1000,2000,5000,10000 43898eb6488eSEric Joyner * 43908eb6488eSEric Joyner * Turning off interrupt moderation will also turn this off. 43918eb6488eSEric Joyner ************************************************************************/ 43926f37f232SEric Joyner static int 43936f37f232SEric Joyner ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS) 43946f37f232SEric Joyner { 4395b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4396ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(sc->ctx); 43976f37f232SEric Joyner int error; 4398c19c7afeSEric Joyner u16 newval; 43996f37f232SEric Joyner 4400b1d5caf3SKevin Bowling newval = sc->dmac; 4401c19c7afeSEric Joyner error = sysctl_handle_16(oidp, &newval, 0, req); 44026f37f232SEric Joyner if ((error) || (req->newptr == NULL)) 44036f37f232SEric Joyner return (error); 44046f37f232SEric Joyner 4405a9ca1c79SSean Bruno switch (newval) { 44066f37f232SEric Joyner case 0: 44076f37f232SEric Joyner /* Disabled */ 4408b1d5caf3SKevin Bowling sc->dmac = 0; 44096f37f232SEric Joyner break; 4410a9ca1c79SSean Bruno case 1: 4411a9ca1c79SSean Bruno /* Enable and use default */ 4412b1d5caf3SKevin Bowling sc->dmac = 1000; 44136f37f232SEric Joyner break; 44146f37f232SEric Joyner case 50: 44156f37f232SEric Joyner case 100: 44166f37f232SEric Joyner case 250: 44176f37f232SEric Joyner case 500: 44186f37f232SEric Joyner case 1000: 44196f37f232SEric Joyner case 2000: 44206f37f232SEric Joyner case 5000: 44216f37f232SEric Joyner case 10000: 44226f37f232SEric Joyner /* Legal values - allow */ 4423b1d5caf3SKevin Bowling sc->dmac = newval; 44246f37f232SEric Joyner break; 44256f37f232SEric Joyner default: 44266f37f232SEric Joyner /* Do nothing, illegal value */ 44276f37f232SEric Joyner return (EINVAL); 44286f37f232SEric Joyner } 44296f37f232SEric Joyner 44306f37f232SEric Joyner /* Re-initialize hardware if it's already running */ 4431ff06a8dbSJustin Hibbits if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) 4432ff06a8dbSJustin Hibbits if_init(ifp, ifp); 44336f37f232SEric Joyner 44346f37f232SEric Joyner return (0); 44358eb6488eSEric Joyner } /* ixgbe_sysctl_dmac */ 44366f37f232SEric Joyner 4437a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 44388eb6488eSEric Joyner /************************************************************************ 44398eb6488eSEric Joyner * ixgbe_sysctl_power_state 44408eb6488eSEric Joyner * 4441a9ca1c79SSean Bruno * Sysctl to test power states 4442a9ca1c79SSean Bruno * Values: 4443a9ca1c79SSean Bruno * 0 - set device to D0 4444a9ca1c79SSean Bruno * 3 - set device to D3 4445a9ca1c79SSean Bruno * (none) - get current device power state 44468eb6488eSEric Joyner ************************************************************************/ 4447a9ca1c79SSean Bruno static int 4448a9ca1c79SSean Bruno ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS) 4449a9ca1c79SSean Bruno { 4450b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4451b1d5caf3SKevin Bowling device_t dev = sc->dev; 4452a9ca1c79SSean Bruno int curr_ps, new_ps, error = 0; 4453a9ca1c79SSean Bruno 4454a9ca1c79SSean Bruno curr_ps = new_ps = pci_get_powerstate(dev); 4455a9ca1c79SSean Bruno 4456a9ca1c79SSean Bruno error = sysctl_handle_int(oidp, &new_ps, 0, req); 4457a9ca1c79SSean Bruno if ((error) || (req->newptr == NULL)) 4458a9ca1c79SSean Bruno return (error); 4459a9ca1c79SSean Bruno 4460a9ca1c79SSean Bruno if (new_ps == curr_ps) 4461a9ca1c79SSean Bruno return (0); 4462a9ca1c79SSean Bruno 4463a9ca1c79SSean Bruno if (new_ps == 3 && curr_ps == 0) 4464a9ca1c79SSean Bruno error = DEVICE_SUSPEND(dev); 4465a9ca1c79SSean Bruno else if (new_ps == 0 && curr_ps == 3) 4466a9ca1c79SSean Bruno error = DEVICE_RESUME(dev); 4467a9ca1c79SSean Bruno else 4468a9ca1c79SSean Bruno return (EINVAL); 4469a9ca1c79SSean Bruno 4470a9ca1c79SSean Bruno device_printf(dev, "New state: %d\n", pci_get_powerstate(dev)); 4471a9ca1c79SSean Bruno 4472a9ca1c79SSean Bruno return (error); 44738eb6488eSEric Joyner } /* ixgbe_sysctl_power_state */ 4474a9ca1c79SSean Bruno #endif 44758eb6488eSEric Joyner 44768eb6488eSEric Joyner /************************************************************************ 44778eb6488eSEric Joyner * ixgbe_sysctl_wol_enable 44788eb6488eSEric Joyner * 44798eb6488eSEric Joyner * Sysctl to enable/disable the WoL capability, 44808eb6488eSEric Joyner * if supported by the adapter. 44818eb6488eSEric Joyner * 44826f37f232SEric Joyner * Values: 44836f37f232SEric Joyner * 0 - disabled 44846f37f232SEric Joyner * 1 - enabled 44858eb6488eSEric Joyner ************************************************************************/ 44866f37f232SEric Joyner static int 44876f37f232SEric Joyner ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS) 44886f37f232SEric Joyner { 4489b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4490b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 44916f37f232SEric Joyner int new_wol_enabled; 44926f37f232SEric Joyner int error = 0; 44936f37f232SEric Joyner 44946f37f232SEric Joyner new_wol_enabled = hw->wol_enabled; 44956f37f232SEric Joyner error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req); 44966f37f232SEric Joyner if ((error) || (req->newptr == NULL)) 44976f37f232SEric Joyner return (error); 4498a9ca1c79SSean Bruno new_wol_enabled = !!(new_wol_enabled); 44996f37f232SEric Joyner if (new_wol_enabled == hw->wol_enabled) 45006f37f232SEric Joyner return (0); 45016f37f232SEric Joyner 4502b1d5caf3SKevin Bowling if (new_wol_enabled > 0 && !sc->wol_support) 45036f37f232SEric Joyner return (ENODEV); 45046f37f232SEric Joyner else 4505a9ca1c79SSean Bruno hw->wol_enabled = new_wol_enabled; 45066f37f232SEric Joyner 45076f37f232SEric Joyner return (0); 45088eb6488eSEric Joyner } /* ixgbe_sysctl_wol_enable */ 45096f37f232SEric Joyner 45108eb6488eSEric Joyner /************************************************************************ 45118eb6488eSEric Joyner * ixgbe_sysctl_wufc - Wake Up Filter Control 45128eb6488eSEric Joyner * 45136f37f232SEric Joyner * Sysctl to enable/disable the types of packets that the 45146f37f232SEric Joyner * adapter will wake up on upon receipt. 45156f37f232SEric Joyner * Flags: 45166f37f232SEric Joyner * 0x1 - Link Status Change 45176f37f232SEric Joyner * 0x2 - Magic Packet 45186f37f232SEric Joyner * 0x4 - Direct Exact 45196f37f232SEric Joyner * 0x8 - Directed Multicast 45206f37f232SEric Joyner * 0x10 - Broadcast 45216f37f232SEric Joyner * 0x20 - ARP/IPv4 Request Packet 45226f37f232SEric Joyner * 0x40 - Direct IPv4 Packet 45236f37f232SEric Joyner * 0x80 - Direct IPv6 Packet 45246f37f232SEric Joyner * 45258eb6488eSEric Joyner * Settings not listed above will cause the sysctl to return an error. 45268eb6488eSEric Joyner ************************************************************************/ 45276f37f232SEric Joyner static int 45286f37f232SEric Joyner ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS) 45296f37f232SEric Joyner { 4530b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 45316f37f232SEric Joyner int error = 0; 45326f37f232SEric Joyner u32 new_wufc; 45336f37f232SEric Joyner 4534b1d5caf3SKevin Bowling new_wufc = sc->wufc; 45356f37f232SEric Joyner 4536c19c7afeSEric Joyner error = sysctl_handle_32(oidp, &new_wufc, 0, req); 45376f37f232SEric Joyner if ((error) || (req->newptr == NULL)) 45386f37f232SEric Joyner return (error); 4539b1d5caf3SKevin Bowling if (new_wufc == sc->wufc) 45406f37f232SEric Joyner return (0); 45416f37f232SEric Joyner 45426f37f232SEric Joyner if (new_wufc & 0xffffff00) 45436f37f232SEric Joyner return (EINVAL); 45448eb6488eSEric Joyner 45456f37f232SEric Joyner new_wufc &= 0xff; 4546b1d5caf3SKevin Bowling new_wufc |= (0xffffff & sc->wufc); 4547b1d5caf3SKevin Bowling sc->wufc = new_wufc; 45486f37f232SEric Joyner 45496f37f232SEric Joyner return (0); 45508eb6488eSEric Joyner } /* ixgbe_sysctl_wufc */ 45516f37f232SEric Joyner 4552a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG 45538eb6488eSEric Joyner /************************************************************************ 45548eb6488eSEric Joyner * ixgbe_sysctl_print_rss_config 45558eb6488eSEric Joyner ************************************************************************/ 4556a9ca1c79SSean Bruno static int 4557a9ca1c79SSean Bruno ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS) 4558a9ca1c79SSean Bruno { 4559b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4560b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 4561b1d5caf3SKevin Bowling device_t dev = sc->dev; 4562a9ca1c79SSean Bruno struct sbuf *buf; 45638eb6488eSEric Joyner int error = 0, reta_size; 4564a9ca1c79SSean Bruno u32 reg; 4565a9ca1c79SSean Bruno 4566f72de14eSKevin Bowling if (atomic_load_acq_int(&sc->recovery_mode)) 4567f72de14eSKevin Bowling return (EPERM); 4568f72de14eSKevin Bowling 4569a9ca1c79SSean Bruno buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); 4570a9ca1c79SSean Bruno if (!buf) { 4571a9ca1c79SSean Bruno device_printf(dev, "Could not allocate sbuf for output.\n"); 4572a9ca1c79SSean Bruno return (ENOMEM); 4573a9ca1c79SSean Bruno } 4574a9ca1c79SSean Bruno 4575a9ca1c79SSean Bruno // TODO: use sbufs to make a string to print out 4576a9ca1c79SSean Bruno /* Set multiplier for RETA setup and table size based on MAC */ 4577b1d5caf3SKevin Bowling switch (sc->hw.mac.type) { 4578a9ca1c79SSean Bruno case ixgbe_mac_X550: 4579a9ca1c79SSean Bruno case ixgbe_mac_X550EM_x: 45808eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 4581a9ca1c79SSean Bruno reta_size = 128; 4582a9ca1c79SSean Bruno break; 4583a9ca1c79SSean Bruno default: 4584a9ca1c79SSean Bruno reta_size = 32; 4585a9ca1c79SSean Bruno break; 4586a9ca1c79SSean Bruno } 4587a9ca1c79SSean Bruno 4588a9ca1c79SSean Bruno /* Print out the redirection table */ 4589a9ca1c79SSean Bruno sbuf_cat(buf, "\n"); 4590a9ca1c79SSean Bruno for (int i = 0; i < reta_size; i++) { 4591a9ca1c79SSean Bruno if (i < 32) { 4592a9ca1c79SSean Bruno reg = IXGBE_READ_REG(hw, IXGBE_RETA(i)); 4593a9ca1c79SSean Bruno sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg); 4594a9ca1c79SSean Bruno } else { 4595a9ca1c79SSean Bruno reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32)); 4596a9ca1c79SSean Bruno sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg); 4597a9ca1c79SSean Bruno } 4598a9ca1c79SSean Bruno } 4599a9ca1c79SSean Bruno 4600a9ca1c79SSean Bruno // TODO: print more config 4601a9ca1c79SSean Bruno 4602a9ca1c79SSean Bruno error = sbuf_finish(buf); 4603a9ca1c79SSean Bruno if (error) 4604a9ca1c79SSean Bruno device_printf(dev, "Error finishing sbuf: %d\n", error); 4605a9ca1c79SSean Bruno 4606a9ca1c79SSean Bruno sbuf_delete(buf); 46078eb6488eSEric Joyner 4608a9ca1c79SSean Bruno return (0); 46098eb6488eSEric Joyner } /* ixgbe_sysctl_print_rss_config */ 4610a9ca1c79SSean Bruno #endif /* IXGBE_DEBUG */ 4611a9ca1c79SSean Bruno 46128eb6488eSEric Joyner /************************************************************************ 46138eb6488eSEric Joyner * ixgbe_sysctl_phy_temp - Retrieve temperature of PHY 46148eb6488eSEric Joyner * 46158eb6488eSEric Joyner * For X552/X557-AT devices using an external PHY 46168eb6488eSEric Joyner ************************************************************************/ 46178eb6488eSEric Joyner static int 46188eb6488eSEric Joyner ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS) 46198eb6488eSEric Joyner { 4620b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4621b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 46228eb6488eSEric Joyner u16 reg; 46238eb6488eSEric Joyner 4624f72de14eSKevin Bowling if (atomic_load_acq_int(&sc->recovery_mode)) 4625f72de14eSKevin Bowling return (EPERM); 4626f72de14eSKevin Bowling 46278eb6488eSEric Joyner if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { 4628b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 46298eb6488eSEric Joyner "Device has no supported external thermal sensor.\n"); 46308eb6488eSEric Joyner return (ENODEV); 46318eb6488eSEric Joyner } 46328eb6488eSEric Joyner 46338eb6488eSEric Joyner if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP, 46348eb6488eSEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) { 4635b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 46368eb6488eSEric Joyner "Error reading from PHY's current temperature register\n"); 46378eb6488eSEric Joyner return (EAGAIN); 46388eb6488eSEric Joyner } 46398eb6488eSEric Joyner 46408eb6488eSEric Joyner /* Shift temp for output */ 46418eb6488eSEric Joyner reg = reg >> 8; 46428eb6488eSEric Joyner 4643c19c7afeSEric Joyner return (sysctl_handle_16(oidp, NULL, reg, req)); 46448eb6488eSEric Joyner } /* ixgbe_sysctl_phy_temp */ 46458eb6488eSEric Joyner 46468eb6488eSEric Joyner /************************************************************************ 46478eb6488eSEric Joyner * ixgbe_sysctl_phy_overtemp_occurred 46488eb6488eSEric Joyner * 46498eb6488eSEric Joyner * Reports (directly from the PHY) whether the current PHY 46508eb6488eSEric Joyner * temperature is over the overtemp threshold. 46518eb6488eSEric Joyner ************************************************************************/ 46528eb6488eSEric Joyner static int 46538eb6488eSEric Joyner ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS) 46548eb6488eSEric Joyner { 4655b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4656b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 46578eb6488eSEric Joyner u16 reg; 46588eb6488eSEric Joyner 4659f72de14eSKevin Bowling if (atomic_load_acq_int(&sc->recovery_mode)) 4660f72de14eSKevin Bowling return (EPERM); 4661f72de14eSKevin Bowling 46628eb6488eSEric Joyner if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { 4663b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 46648eb6488eSEric Joyner "Device has no supported external thermal sensor.\n"); 46658eb6488eSEric Joyner return (ENODEV); 46668eb6488eSEric Joyner } 46678eb6488eSEric Joyner 46688eb6488eSEric Joyner if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS, 46698eb6488eSEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) { 4670b1d5caf3SKevin Bowling device_printf(iflib_get_dev(sc->ctx), 46718eb6488eSEric Joyner "Error reading from PHY's temperature status register\n"); 46728eb6488eSEric Joyner return (EAGAIN); 46738eb6488eSEric Joyner } 46748eb6488eSEric Joyner 46758eb6488eSEric Joyner /* Get occurrence bit */ 46768eb6488eSEric Joyner reg = !!(reg & 0x4000); 46778eb6488eSEric Joyner 4678c19c7afeSEric Joyner return (sysctl_handle_16(oidp, 0, reg, req)); 46798eb6488eSEric Joyner } /* ixgbe_sysctl_phy_overtemp_occurred */ 46808eb6488eSEric Joyner 46818eb6488eSEric Joyner /************************************************************************ 46828eb6488eSEric Joyner * ixgbe_sysctl_eee_state 46838eb6488eSEric Joyner * 46848eb6488eSEric Joyner * Sysctl to set EEE power saving feature 46858eb6488eSEric Joyner * Values: 46868eb6488eSEric Joyner * 0 - disable EEE 46878eb6488eSEric Joyner * 1 - enable EEE 46888eb6488eSEric Joyner * (none) - get current device EEE state 46898eb6488eSEric Joyner ************************************************************************/ 46908eb6488eSEric Joyner static int 46918eb6488eSEric Joyner ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS) 46928eb6488eSEric Joyner { 4693b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4694b1d5caf3SKevin Bowling device_t dev = sc->dev; 4695ff06a8dbSJustin Hibbits if_t ifp = iflib_get_ifp(sc->ctx); 46968eb6488eSEric Joyner int curr_eee, new_eee, error = 0; 46978eb6488eSEric Joyner s32 retval; 46988eb6488eSEric Joyner 4699f72de14eSKevin Bowling if (atomic_load_acq_int(&sc->recovery_mode)) 4700f72de14eSKevin Bowling return (EPERM); 4701f72de14eSKevin Bowling 4702b1d5caf3SKevin Bowling curr_eee = new_eee = !!(sc->feat_en & IXGBE_FEATURE_EEE); 47038eb6488eSEric Joyner 47048eb6488eSEric Joyner error = sysctl_handle_int(oidp, &new_eee, 0, req); 47058eb6488eSEric Joyner if ((error) || (req->newptr == NULL)) 47068eb6488eSEric Joyner return (error); 47078eb6488eSEric Joyner 47088eb6488eSEric Joyner /* Nothing to do */ 47098eb6488eSEric Joyner if (new_eee == curr_eee) 47108eb6488eSEric Joyner return (0); 47118eb6488eSEric Joyner 47128eb6488eSEric Joyner /* Not supported */ 4713b1d5caf3SKevin Bowling if (!(sc->feat_cap & IXGBE_FEATURE_EEE)) 47148eb6488eSEric Joyner return (EINVAL); 47158eb6488eSEric Joyner 47168eb6488eSEric Joyner /* Bounds checking */ 47178eb6488eSEric Joyner if ((new_eee < 0) || (new_eee > 1)) 47188eb6488eSEric Joyner return (EINVAL); 47198eb6488eSEric Joyner 4720b1d5caf3SKevin Bowling retval = ixgbe_setup_eee(&sc->hw, new_eee); 47218eb6488eSEric Joyner if (retval) { 47228eb6488eSEric Joyner device_printf(dev, "Error in EEE setup: 0x%08X\n", retval); 47238eb6488eSEric Joyner return (EINVAL); 47248eb6488eSEric Joyner } 47258eb6488eSEric Joyner 47268eb6488eSEric Joyner /* Restart auto-neg */ 4727ff06a8dbSJustin Hibbits if_init(ifp, ifp); 47288eb6488eSEric Joyner 47298eb6488eSEric Joyner device_printf(dev, "New EEE state: %d\n", new_eee); 47308eb6488eSEric Joyner 47318eb6488eSEric Joyner /* Cache new value */ 47328eb6488eSEric Joyner if (new_eee) 4733b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_EEE; 47348eb6488eSEric Joyner else 4735b1d5caf3SKevin Bowling sc->feat_en &= ~IXGBE_FEATURE_EEE; 47368eb6488eSEric Joyner 47378eb6488eSEric Joyner return (error); 47388eb6488eSEric Joyner } /* ixgbe_sysctl_eee_state */ 47398eb6488eSEric Joyner 47408eb6488eSEric Joyner /************************************************************************ 47418eb6488eSEric Joyner * ixgbe_init_device_features 47428eb6488eSEric Joyner ************************************************************************/ 47438eb6488eSEric Joyner static void 4744b1d5caf3SKevin Bowling ixgbe_init_device_features(struct ixgbe_softc *sc) 47458eb6488eSEric Joyner { 4746b1d5caf3SKevin Bowling sc->feat_cap = IXGBE_FEATURE_NETMAP 47478eb6488eSEric Joyner | IXGBE_FEATURE_RSS 47488eb6488eSEric Joyner | IXGBE_FEATURE_MSI 47498eb6488eSEric Joyner | IXGBE_FEATURE_MSIX 4750c19c7afeSEric Joyner | IXGBE_FEATURE_LEGACY_IRQ; 47518eb6488eSEric Joyner 47528eb6488eSEric Joyner /* Set capabilities first... */ 4753b1d5caf3SKevin Bowling switch (sc->hw.mac.type) { 47548eb6488eSEric Joyner case ixgbe_mac_82598EB: 4755b1d5caf3SKevin Bowling if (sc->hw.device_id == IXGBE_DEV_ID_82598AT) 4756b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_FAN_FAIL; 47578eb6488eSEric Joyner break; 47588eb6488eSEric Joyner case ixgbe_mac_X540: 4759b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_SRIOV; 4760b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_FDIR; 4761b1d5caf3SKevin Bowling if ((sc->hw.device_id == IXGBE_DEV_ID_X540_BYPASS) && 4762b1d5caf3SKevin Bowling (sc->hw.bus.func == 0)) 4763b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_BYPASS; 47648eb6488eSEric Joyner break; 47658eb6488eSEric Joyner case ixgbe_mac_X550: 4766f72de14eSKevin Bowling sc->feat_cap |= IXGBE_FEATURE_RECOVERY_MODE; 4767b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR; 4768b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_SRIOV; 4769b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_FDIR; 47708eb6488eSEric Joyner break; 47718eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 4772f72de14eSKevin Bowling sc->feat_cap |= IXGBE_FEATURE_RECOVERY_MODE; 4773b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_SRIOV; 4774b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_FDIR; 4775f72de14eSKevin Bowling if (sc->hw.device_id == IXGBE_DEV_ID_X550EM_X_KR) 4776f72de14eSKevin Bowling sc->feat_cap |= IXGBE_FEATURE_EEE; 47778eb6488eSEric Joyner break; 47788eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 4779f72de14eSKevin Bowling sc->feat_cap |= IXGBE_FEATURE_RECOVERY_MODE; 4780b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_SRIOV; 4781b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_FDIR; 4782b1d5caf3SKevin Bowling sc->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ; 4783b1d5caf3SKevin Bowling if ((sc->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T) || 4784b1d5caf3SKevin Bowling (sc->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) { 4785b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR; 4786b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_EEE; 47878eb6488eSEric Joyner } 47888eb6488eSEric Joyner break; 47898eb6488eSEric Joyner case ixgbe_mac_82599EB: 4790b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_SRIOV; 4791b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_FDIR; 4792b1d5caf3SKevin Bowling if ((sc->hw.device_id == IXGBE_DEV_ID_82599_BYPASS) && 4793b1d5caf3SKevin Bowling (sc->hw.bus.func == 0)) 4794b1d5caf3SKevin Bowling sc->feat_cap |= IXGBE_FEATURE_BYPASS; 4795b1d5caf3SKevin Bowling if (sc->hw.device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) 4796b1d5caf3SKevin Bowling sc->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ; 47978eb6488eSEric Joyner break; 47988eb6488eSEric Joyner default: 47998eb6488eSEric Joyner break; 48008eb6488eSEric Joyner } 48018eb6488eSEric Joyner 48028eb6488eSEric Joyner /* Enabled by default... */ 48038eb6488eSEric Joyner /* Fan failure detection */ 4804b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_FAN_FAIL) 4805b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_FAN_FAIL; 48068eb6488eSEric Joyner /* Netmap */ 4807b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_NETMAP) 4808b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_NETMAP; 48098eb6488eSEric Joyner /* EEE */ 4810b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_EEE) 4811b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_EEE; 48128eb6488eSEric Joyner /* Thermal Sensor */ 4813b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_TEMP_SENSOR) 4814b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_TEMP_SENSOR; 4815f72de14eSKevin Bowling /* Recovery mode */ 4816f72de14eSKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_RECOVERY_MODE) 4817f72de14eSKevin Bowling sc->feat_en |= IXGBE_FEATURE_RECOVERY_MODE; 48188eb6488eSEric Joyner 48198eb6488eSEric Joyner /* Enabled via global sysctl... */ 48208eb6488eSEric Joyner /* Flow Director */ 48218eb6488eSEric Joyner if (ixgbe_enable_fdir) { 4822b1d5caf3SKevin Bowling if (sc->feat_cap & IXGBE_FEATURE_FDIR) 4823b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_FDIR; 48248eb6488eSEric Joyner else 4825b1d5caf3SKevin Bowling device_printf(sc->dev, "Device does not support Flow Director. Leaving disabled."); 48268eb6488eSEric Joyner } 48276f37f232SEric Joyner /* 48288eb6488eSEric Joyner * Message Signal Interrupts - Extended (MSI-X) 48298eb6488eSEric Joyner * Normal MSI is only enabled if MSI-X calls fail. 4830758cc3dcSJack F Vogel */ 48318eb6488eSEric Joyner if (!ixgbe_enable_msix) 4832b1d5caf3SKevin Bowling sc->feat_cap &= ~IXGBE_FEATURE_MSIX; 48338eb6488eSEric Joyner /* Receive-Side Scaling (RSS) */ 4834b1d5caf3SKevin Bowling if ((sc->feat_cap & IXGBE_FEATURE_RSS) && ixgbe_enable_rss) 4835b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_RSS; 48368eb6488eSEric Joyner 48378eb6488eSEric Joyner /* Disable features with unmet dependencies... */ 48388eb6488eSEric Joyner /* No MSI-X */ 4839b1d5caf3SKevin Bowling if (!(sc->feat_cap & IXGBE_FEATURE_MSIX)) { 4840b1d5caf3SKevin Bowling sc->feat_cap &= ~IXGBE_FEATURE_RSS; 4841b1d5caf3SKevin Bowling sc->feat_cap &= ~IXGBE_FEATURE_SRIOV; 4842b1d5caf3SKevin Bowling sc->feat_en &= ~IXGBE_FEATURE_RSS; 4843b1d5caf3SKevin Bowling sc->feat_en &= ~IXGBE_FEATURE_SRIOV; 48448eb6488eSEric Joyner } 48458eb6488eSEric Joyner } /* ixgbe_init_device_features */ 48468eb6488eSEric Joyner 48478eb6488eSEric Joyner /************************************************************************ 48488eb6488eSEric Joyner * ixgbe_check_fan_failure 48498eb6488eSEric Joyner ************************************************************************/ 48508eb6488eSEric Joyner static void 4851b1d5caf3SKevin Bowling ixgbe_check_fan_failure(struct ixgbe_softc *sc, u32 reg, bool in_interrupt) 48528eb6488eSEric Joyner { 48538eb6488eSEric Joyner u32 mask; 48548eb6488eSEric Joyner 4855b1d5caf3SKevin Bowling mask = (in_interrupt) ? IXGBE_EICR_GPI_SDP1_BY_MAC(&sc->hw) : 48568eb6488eSEric Joyner IXGBE_ESDP_SDP1; 48578eb6488eSEric Joyner 48588eb6488eSEric Joyner if (reg & mask) 4859b1d5caf3SKevin Bowling device_printf(sc->dev, "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n"); 48608eb6488eSEric Joyner } /* ixgbe_check_fan_failure */ 48617660e4eaSKevin Bowling 48627660e4eaSKevin Bowling /************************************************************************ 48637660e4eaSKevin Bowling * ixgbe_sbuf_fw_version 48647660e4eaSKevin Bowling ************************************************************************/ 48657660e4eaSKevin Bowling static void 48667660e4eaSKevin Bowling ixgbe_sbuf_fw_version(struct ixgbe_hw *hw, struct sbuf *buf) 48677660e4eaSKevin Bowling { 48687660e4eaSKevin Bowling struct ixgbe_nvm_version nvm_ver = {0}; 48695de5419bSKevin Bowling const char *space = ""; 48707660e4eaSKevin Bowling 4871f72de14eSKevin Bowling ixgbe_get_nvm_version(hw, &nvm_ver); /* NVM version */ 48727660e4eaSKevin Bowling ixgbe_get_oem_prod_version(hw, &nvm_ver); /* OEM's NVM version */ 48737660e4eaSKevin Bowling ixgbe_get_etk_id(hw, &nvm_ver); /* eTrack identifies a build in Intel's SCM */ 4874f72de14eSKevin Bowling ixgbe_get_orom_version(hw, &nvm_ver); /* Option ROM */ 4875f72de14eSKevin Bowling 4876f72de14eSKevin Bowling /* FW version */ 4877f72de14eSKevin Bowling if ((nvm_ver.phy_fw_maj == 0x0 && 4878f72de14eSKevin Bowling nvm_ver.phy_fw_min == 0x0 && 4879f72de14eSKevin Bowling nvm_ver.phy_fw_id == 0x0) || 4880f72de14eSKevin Bowling (nvm_ver.phy_fw_maj == 0xF && 4881f72de14eSKevin Bowling nvm_ver.phy_fw_min == 0xFF && 4882f72de14eSKevin Bowling nvm_ver.phy_fw_id == 0xF)) { 4883f72de14eSKevin Bowling /* If major, minor and id numbers are set to 0, 4884f72de14eSKevin Bowling * reading FW version is unsupported. If major number 4885f72de14eSKevin Bowling * is set to 0xF, minor is set to 0xFF and id is set 4886f72de14eSKevin Bowling * to 0xF, this means that number read is invalid. */ 4887f72de14eSKevin Bowling } else 4888f72de14eSKevin Bowling sbuf_printf(buf, "fw %d.%d.%d ", 4889f72de14eSKevin Bowling nvm_ver.phy_fw_maj, nvm_ver.phy_fw_min, nvm_ver.phy_fw_id); 4890f72de14eSKevin Bowling 4891f72de14eSKevin Bowling /* NVM version */ 4892f72de14eSKevin Bowling if ((nvm_ver.nvm_major == 0x0 && 4893f72de14eSKevin Bowling nvm_ver.nvm_minor == 0x0 && 4894f72de14eSKevin Bowling nvm_ver.nvm_id == 0x0) || 4895f72de14eSKevin Bowling (nvm_ver.nvm_major == 0xF && 4896f72de14eSKevin Bowling nvm_ver.nvm_minor == 0xFF && 4897f72de14eSKevin Bowling nvm_ver.nvm_id == 0xF)) { 4898f72de14eSKevin Bowling /* If major, minor and id numbers are set to 0, 4899f72de14eSKevin Bowling * reading NVM version is unsupported. If major number 4900f72de14eSKevin Bowling * is set to 0xF, minor is set to 0xFF and id is set 4901f72de14eSKevin Bowling * to 0xF, this means that number read is invalid. */ 4902f72de14eSKevin Bowling } else 4903f72de14eSKevin Bowling sbuf_printf(buf, "nvm %x.%02x.%x ", 4904f72de14eSKevin Bowling nvm_ver.nvm_major, nvm_ver.nvm_minor, nvm_ver.nvm_id); 49057660e4eaSKevin Bowling 49065de5419bSKevin Bowling if (nvm_ver.oem_valid) { 49077660e4eaSKevin Bowling sbuf_printf(buf, "NVM OEM V%d.%d R%d", nvm_ver.oem_major, 49087660e4eaSKevin Bowling nvm_ver.oem_minor, nvm_ver.oem_release); 49095de5419bSKevin Bowling space = " "; 49105de5419bSKevin Bowling } 49117660e4eaSKevin Bowling 49125de5419bSKevin Bowling if (nvm_ver.or_valid) { 49135de5419bSKevin Bowling sbuf_printf(buf, "%sOption ROM V%d-b%d-p%d", 49145de5419bSKevin Bowling space, nvm_ver.or_major, nvm_ver.or_build, nvm_ver.or_patch); 49155de5419bSKevin Bowling space = " "; 49165de5419bSKevin Bowling } 49177660e4eaSKevin Bowling 49185de5419bSKevin Bowling if (nvm_ver.etk_id != ((NVM_VER_INVALID << NVM_ETK_SHIFT) | 4919f72de14eSKevin Bowling NVM_VER_INVALID | 0xFFFFFFFF)) { 49205de5419bSKevin Bowling sbuf_printf(buf, "%seTrack 0x%08x", space, nvm_ver.etk_id); 49215de5419bSKevin Bowling } 49227660e4eaSKevin Bowling } /* ixgbe_sbuf_fw_version */ 49237660e4eaSKevin Bowling 49247660e4eaSKevin Bowling /************************************************************************ 49257660e4eaSKevin Bowling * ixgbe_print_fw_version 49267660e4eaSKevin Bowling ************************************************************************/ 49277660e4eaSKevin Bowling static void 49287660e4eaSKevin Bowling ixgbe_print_fw_version(if_ctx_t ctx) 49297660e4eaSKevin Bowling { 4930b1d5caf3SKevin Bowling struct ixgbe_softc *sc = iflib_get_softc(ctx); 4931b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 4932b1d5caf3SKevin Bowling device_t dev = sc->dev; 49337660e4eaSKevin Bowling struct sbuf *buf; 49347660e4eaSKevin Bowling int error = 0; 49357660e4eaSKevin Bowling 49367660e4eaSKevin Bowling buf = sbuf_new_auto(); 49377660e4eaSKevin Bowling if (!buf) { 49387660e4eaSKevin Bowling device_printf(dev, "Could not allocate sbuf for output.\n"); 49397660e4eaSKevin Bowling return; 49407660e4eaSKevin Bowling } 49417660e4eaSKevin Bowling 49427660e4eaSKevin Bowling ixgbe_sbuf_fw_version(hw, buf); 49437660e4eaSKevin Bowling 49447660e4eaSKevin Bowling error = sbuf_finish(buf); 49457660e4eaSKevin Bowling if (error) 49467660e4eaSKevin Bowling device_printf(dev, "Error finishing sbuf: %d\n", error); 49477660e4eaSKevin Bowling else if (sbuf_len(buf)) 49487660e4eaSKevin Bowling device_printf(dev, "%s\n", sbuf_data(buf)); 49497660e4eaSKevin Bowling 49507660e4eaSKevin Bowling sbuf_delete(buf); 49517660e4eaSKevin Bowling } /* ixgbe_print_fw_version */ 49527660e4eaSKevin Bowling 49537660e4eaSKevin Bowling /************************************************************************ 49547660e4eaSKevin Bowling * ixgbe_sysctl_print_fw_version 49557660e4eaSKevin Bowling ************************************************************************/ 49567660e4eaSKevin Bowling static int 49577660e4eaSKevin Bowling ixgbe_sysctl_print_fw_version(SYSCTL_HANDLER_ARGS) 49587660e4eaSKevin Bowling { 4959b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; 4960b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw; 4961b1d5caf3SKevin Bowling device_t dev = sc->dev; 49627660e4eaSKevin Bowling struct sbuf *buf; 49637660e4eaSKevin Bowling int error = 0; 49647660e4eaSKevin Bowling 49657660e4eaSKevin Bowling buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); 49667660e4eaSKevin Bowling if (!buf) { 49677660e4eaSKevin Bowling device_printf(dev, "Could not allocate sbuf for output.\n"); 49687660e4eaSKevin Bowling return (ENOMEM); 49697660e4eaSKevin Bowling } 49707660e4eaSKevin Bowling 49717660e4eaSKevin Bowling ixgbe_sbuf_fw_version(hw, buf); 49727660e4eaSKevin Bowling 49737660e4eaSKevin Bowling error = sbuf_finish(buf); 49747660e4eaSKevin Bowling if (error) 49757660e4eaSKevin Bowling device_printf(dev, "Error finishing sbuf: %d\n", error); 49767660e4eaSKevin Bowling 49777660e4eaSKevin Bowling sbuf_delete(buf); 49787660e4eaSKevin Bowling 49797660e4eaSKevin Bowling return (0); 49807660e4eaSKevin Bowling } /* ixgbe_sysctl_print_fw_version */ 4981