1280182Sjfv/****************************************************************************** 2280182Sjfv 3280182Sjfv Copyright (c) 2001-2015, Intel Corporation 4280182Sjfv All rights reserved. 5280182Sjfv 6280182Sjfv Redistribution and use in source and binary forms, with or without 7280182Sjfv modification, are permitted provided that the following conditions are met: 8280182Sjfv 9280182Sjfv 1. Redistributions of source code must retain the above copyright notice, 10280182Sjfv this list of conditions and the following disclaimer. 11280182Sjfv 12280182Sjfv 2. Redistributions in binary form must reproduce the above copyright 13280182Sjfv notice, this list of conditions and the following disclaimer in the 14280182Sjfv documentation and/or other materials provided with the distribution. 15280182Sjfv 16280182Sjfv 3. Neither the name of the Intel Corporation nor the names of its 17280182Sjfv contributors may be used to endorse or promote products derived from 18280182Sjfv this software without specific prior written permission. 19280182Sjfv 20280182Sjfv THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21280182Sjfv AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22280182Sjfv IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23280182Sjfv ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24280182Sjfv LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25280182Sjfv CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26280182Sjfv SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27280182Sjfv INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28280182Sjfv CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29280182Sjfv ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30280182Sjfv POSSIBILITY OF SUCH DAMAGE. 31280182Sjfv 32280182Sjfv******************************************************************************/ 33280182Sjfv/*$FreeBSD: releng/11.0/sys/dev/ixgbe/if_ix.c 302384 2016-07-07 03:39:18Z sbruno $*/ 34280182Sjfv 35280182Sjfv 36280182Sjfv#ifndef IXGBE_STANDALONE_BUILD 37280182Sjfv#include "opt_inet.h" 38280182Sjfv#include "opt_inet6.h" 39280182Sjfv#include "opt_rss.h" 40280182Sjfv#endif 41280182Sjfv 42280182Sjfv#include "ixgbe.h" 43280182Sjfv 44280182Sjfv#ifdef RSS 45280204Sadrian#include <net/rss_config.h> 46280182Sjfv#include <netinet/in_rss.h> 47280182Sjfv#endif 48280182Sjfv 49280182Sjfv/********************************************************************* 50280182Sjfv * Driver version 51280182Sjfv *********************************************************************/ 52292674Ssbrunochar ixgbe_driver_version[] = "3.1.13-k"; 53280182Sjfv 54292674Ssbruno 55280182Sjfv/********************************************************************* 56280182Sjfv * PCI Device ID Table 57280182Sjfv * 58280182Sjfv * Used by probe to select devices to load on 59280182Sjfv * Last field stores an index into ixgbe_strings 60280182Sjfv * Last entry must be all 0s 61280182Sjfv * 62280182Sjfv * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } 63280182Sjfv *********************************************************************/ 64280182Sjfv 65280182Sjfvstatic ixgbe_vendor_info_t ixgbe_vendor_info_array[] = 66280182Sjfv{ 67280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, 0, 0, 0}, 68280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 0, 0, 0}, 69280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, 0, 0, 0}, 70280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0}, 71280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, 0, 0, 0}, 72280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, 0, 0, 0}, 73280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, 0, 0, 0}, 74280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, 0, 0, 0}, 75280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, 0, 0, 0}, 76280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, 0, 0, 0}, 77280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, 0, 0, 0}, 78280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, 0, 0, 0}, 79280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, 0, 0, 0}, 80280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0}, 81280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, 0, 0, 0}, 82280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 0, 0, 0}, 83280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 0, 0, 0}, 84280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 0, 0, 0}, 85280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, 0, 0, 0}, 86280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF2, 0, 0, 0}, 87280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, 0, 0, 0}, 88280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP, 0, 0, 0}, 89280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF_QP, 0, 0, 0}, 90280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_QSFP_SF_QP, 0, 0, 0}, 91280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, 0, 0, 0}, 92280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, 0, 0, 0}, 93280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, 0, 0, 0}, 94292674Ssbruno {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, 0, 0, 0}, 95280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, 0, 0, 0}, 96280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, 0, 0, 0}, 97280182Sjfv {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, 0, 0, 0}, 98292674Ssbruno {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, 0, 0, 0}, 99280182Sjfv /* required last entry */ 100280182Sjfv {0, 0, 0, 0, 0} 101280182Sjfv}; 102280182Sjfv 103280182Sjfv/********************************************************************* 104280182Sjfv * Table of branding strings 105280182Sjfv *********************************************************************/ 106280182Sjfv 107280182Sjfvstatic char *ixgbe_strings[] = { 108280182Sjfv "Intel(R) PRO/10GbE PCI-Express Network Driver" 109280182Sjfv}; 110280182Sjfv 111280182Sjfv/********************************************************************* 112280182Sjfv * Function prototypes 113280182Sjfv *********************************************************************/ 114280182Sjfvstatic int ixgbe_probe(device_t); 115280182Sjfvstatic int ixgbe_attach(device_t); 116280182Sjfvstatic int ixgbe_detach(device_t); 117280182Sjfvstatic int ixgbe_shutdown(device_t); 118282289Serjstatic int ixgbe_suspend(device_t); 119282289Serjstatic int ixgbe_resume(device_t); 120280182Sjfvstatic int ixgbe_ioctl(struct ifnet *, u_long, caddr_t); 121280182Sjfvstatic void ixgbe_init(void *); 122280182Sjfvstatic void ixgbe_init_locked(struct adapter *); 123280182Sjfvstatic void ixgbe_stop(void *); 124280182Sjfv#if __FreeBSD_version >= 1100036 125280182Sjfvstatic uint64_t ixgbe_get_counter(struct ifnet *, ift_counter); 126280182Sjfv#endif 127280182Sjfvstatic void ixgbe_add_media_types(struct adapter *); 128280182Sjfvstatic void ixgbe_media_status(struct ifnet *, struct ifmediareq *); 129280182Sjfvstatic int ixgbe_media_change(struct ifnet *); 130280182Sjfvstatic void ixgbe_identify_hardware(struct adapter *); 131280182Sjfvstatic int ixgbe_allocate_pci_resources(struct adapter *); 132292674Ssbrunostatic void ixgbe_get_slot_info(struct adapter *); 133280182Sjfvstatic int ixgbe_allocate_msix(struct adapter *); 134280182Sjfvstatic int ixgbe_allocate_legacy(struct adapter *); 135280182Sjfvstatic int ixgbe_setup_msix(struct adapter *); 136280182Sjfvstatic void ixgbe_free_pci_resources(struct adapter *); 137280182Sjfvstatic void ixgbe_local_timer(void *); 138280182Sjfvstatic int ixgbe_setup_interface(device_t, struct adapter *); 139283883Sjfvstatic void ixgbe_config_gpie(struct adapter *); 140282289Serjstatic void ixgbe_config_dmac(struct adapter *); 141282289Serjstatic void ixgbe_config_delay_values(struct adapter *); 142280182Sjfvstatic void ixgbe_config_link(struct adapter *); 143282289Serjstatic void ixgbe_check_wol_support(struct adapter *); 144282289Serjstatic int ixgbe_setup_low_power_mode(struct adapter *); 145280182Sjfvstatic void ixgbe_rearm_queues(struct adapter *, u64); 146280182Sjfv 147280182Sjfvstatic void ixgbe_initialize_transmit_units(struct adapter *); 148280182Sjfvstatic void ixgbe_initialize_receive_units(struct adapter *); 149280182Sjfvstatic void ixgbe_enable_rx_drop(struct adapter *); 150280182Sjfvstatic void ixgbe_disable_rx_drop(struct adapter *); 151292674Ssbrunostatic void ixgbe_initialize_rss_mapping(struct adapter *); 152280182Sjfv 153280182Sjfvstatic void ixgbe_enable_intr(struct adapter *); 154280182Sjfvstatic void ixgbe_disable_intr(struct adapter *); 155280182Sjfvstatic void ixgbe_update_stats_counters(struct adapter *); 156280182Sjfvstatic void ixgbe_set_promisc(struct adapter *); 157280182Sjfvstatic void ixgbe_set_multi(struct adapter *); 158280182Sjfvstatic void ixgbe_update_link_status(struct adapter *); 159280182Sjfvstatic void ixgbe_set_ivar(struct adapter *, u8, u8, s8); 160280182Sjfvstatic void ixgbe_configure_ivars(struct adapter *); 161280182Sjfvstatic u8 * ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); 162280182Sjfv 163280182Sjfvstatic void ixgbe_setup_vlan_hw_support(struct adapter *); 164280182Sjfvstatic void ixgbe_register_vlan(void *, struct ifnet *, u16); 165280182Sjfvstatic void ixgbe_unregister_vlan(void *, struct ifnet *, u16); 166280182Sjfv 167282289Serjstatic void ixgbe_add_device_sysctls(struct adapter *); 168282289Serjstatic void ixgbe_add_hw_stats(struct adapter *); 169294795Ssmhstatic int ixgbe_set_flowcntl(struct adapter *, int); 170294795Ssmhstatic int ixgbe_set_advertise(struct adapter *, int); 171280182Sjfv 172282289Serj/* Sysctl handlers */ 173289238Ssbrunostatic void ixgbe_set_sysctl_value(struct adapter *, const char *, 174292674Ssbruno const char *, int *, int); 175294795Ssmhstatic int ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS); 176294795Ssmhstatic int ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS); 177282289Serjstatic int ixgbe_sysctl_thermal_test(SYSCTL_HANDLER_ARGS); 178282289Serjstatic int ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS); 179282289Serjstatic int ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS); 180282289Serjstatic int ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS); 181292674Ssbruno#ifdef IXGBE_DEBUG 182292674Ssbrunostatic int ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS); 183292674Ssbrunostatic int ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS); 184292674Ssbruno#endif 185282289Serjstatic int ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS); 186282289Serjstatic int ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS); 187282289Serjstatic int ixgbe_sysctl_eee_enable(SYSCTL_HANDLER_ARGS); 188282289Serjstatic int ixgbe_sysctl_eee_negotiated(SYSCTL_HANDLER_ARGS); 189282289Serjstatic int ixgbe_sysctl_eee_rx_lpi_status(SYSCTL_HANDLER_ARGS); 190282289Serjstatic int ixgbe_sysctl_eee_tx_lpi_status(SYSCTL_HANDLER_ARGS); 191292674Ssbrunostatic int ixgbe_sysctl_eee_tx_lpi_delay(SYSCTL_HANDLER_ARGS); 192282289Serj 193280182Sjfv/* Support for pluggable optic modules */ 194280182Sjfvstatic bool ixgbe_sfp_probe(struct adapter *); 195280182Sjfvstatic void ixgbe_setup_optics(struct adapter *); 196280182Sjfv 197280182Sjfv/* Legacy (single vector interrupt handler */ 198280182Sjfvstatic void ixgbe_legacy_irq(void *); 199280182Sjfv 200280182Sjfv/* The MSI/X Interrupt handlers */ 201280182Sjfvstatic void ixgbe_msix_que(void *); 202280182Sjfvstatic void ixgbe_msix_link(void *); 203280182Sjfv 204280182Sjfv/* Deferred interrupt tasklets */ 205280182Sjfvstatic void ixgbe_handle_que(void *, int); 206280182Sjfvstatic void ixgbe_handle_link(void *, int); 207280182Sjfvstatic void ixgbe_handle_msf(void *, int); 208280182Sjfvstatic void ixgbe_handle_mod(void *, int); 209282289Serjstatic void ixgbe_handle_phy(void *, int); 210280182Sjfv 211280182Sjfv#ifdef IXGBE_FDIR 212280182Sjfvstatic void ixgbe_reinit_fdir(void *, int); 213280182Sjfv#endif 214280182Sjfv 215283883Sjfv#ifdef PCI_IOV 216283883Sjfvstatic void ixgbe_ping_all_vfs(struct adapter *); 217283883Sjfvstatic void ixgbe_handle_mbx(void *, int); 218283883Sjfvstatic int ixgbe_init_iov(device_t, u16, const nvlist_t *); 219283883Sjfvstatic void ixgbe_uninit_iov(device_t); 220283883Sjfvstatic int ixgbe_add_vf(device_t, u16, const nvlist_t *); 221283883Sjfvstatic void ixgbe_initialize_iov(struct adapter *); 222283883Sjfvstatic void ixgbe_recalculate_max_frame(struct adapter *); 223283883Sjfvstatic void ixgbe_init_vf(struct adapter *, struct ixgbe_vf *); 224283883Sjfv#endif /* PCI_IOV */ 225283883Sjfv 226283883Sjfv 227280182Sjfv/********************************************************************* 228280182Sjfv * FreeBSD Device Interface Entry Points 229280182Sjfv *********************************************************************/ 230280182Sjfv 231280204Sadrianstatic device_method_t ix_methods[] = { 232280182Sjfv /* Device interface */ 233280182Sjfv DEVMETHOD(device_probe, ixgbe_probe), 234280182Sjfv DEVMETHOD(device_attach, ixgbe_attach), 235280182Sjfv DEVMETHOD(device_detach, ixgbe_detach), 236280182Sjfv DEVMETHOD(device_shutdown, ixgbe_shutdown), 237282289Serj DEVMETHOD(device_suspend, ixgbe_suspend), 238282289Serj DEVMETHOD(device_resume, ixgbe_resume), 239283883Sjfv#ifdef PCI_IOV 240283893Sjhb DEVMETHOD(pci_iov_init, ixgbe_init_iov), 241283893Sjhb DEVMETHOD(pci_iov_uninit, ixgbe_uninit_iov), 242283893Sjhb DEVMETHOD(pci_iov_add_vf, ixgbe_add_vf), 243283883Sjfv#endif /* PCI_IOV */ 244280182Sjfv DEVMETHOD_END 245280182Sjfv}; 246280182Sjfv 247280204Sadrianstatic driver_t ix_driver = { 248280204Sadrian "ix", ix_methods, sizeof(struct adapter), 249280182Sjfv}; 250280182Sjfv 251280204Sadriandevclass_t ix_devclass; 252280204SadrianDRIVER_MODULE(ix, pci, ix_driver, ix_devclass, 0, 0); 253280182Sjfv 254280204SadrianMODULE_DEPEND(ix, pci, 1, 1, 1); 255280204SadrianMODULE_DEPEND(ix, ether, 1, 1, 1); 256285349Sluigi#ifdef DEV_NETMAP 257285349SluigiMODULE_DEPEND(ix, netmap, 1, 1, 1); 258285349Sluigi#endif /* DEV_NETMAP */ 259280182Sjfv 260280182Sjfv/* 261280182Sjfv** TUNEABLE PARAMETERS: 262280182Sjfv*/ 263280182Sjfv 264280182Sjfvstatic SYSCTL_NODE(_hw, OID_AUTO, ix, CTLFLAG_RD, 0, 265280182Sjfv "IXGBE driver parameters"); 266280182Sjfv 267280182Sjfv/* 268280182Sjfv** AIM: Adaptive Interrupt Moderation 269280182Sjfv** which means that the interrupt rate 270280182Sjfv** is varied over time based on the 271280182Sjfv** traffic for that interrupt vector 272280182Sjfv*/ 273280182Sjfvstatic int ixgbe_enable_aim = TRUE; 274280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, enable_aim, CTLFLAG_RWTUN, &ixgbe_enable_aim, 0, 275280182Sjfv "Enable adaptive interrupt moderation"); 276280182Sjfv 277280182Sjfvstatic int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY); 278280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN, 279280182Sjfv &ixgbe_max_interrupt_rate, 0, "Maximum interrupts per second"); 280280182Sjfv 281280182Sjfv/* How many packets rxeof tries to clean at a time */ 282280182Sjfvstatic int ixgbe_rx_process_limit = 256; 283280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN, 284280182Sjfv &ixgbe_rx_process_limit, 0, 285280182Sjfv "Maximum number of received packets to process at a time," 286280182Sjfv "-1 means unlimited"); 287280182Sjfv 288280182Sjfv/* How many packets txeof tries to clean at a time */ 289280182Sjfvstatic int ixgbe_tx_process_limit = 256; 290280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, tx_process_limit, CTLFLAG_RDTUN, 291280182Sjfv &ixgbe_tx_process_limit, 0, 292280182Sjfv "Maximum number of sent packets to process at a time," 293280182Sjfv "-1 means unlimited"); 294280182Sjfv 295294795Ssmh/* Flow control setting, default to full */ 296294795Ssmhstatic int ixgbe_flow_control = ixgbe_fc_full; 297294795SsmhSYSCTL_INT(_hw_ix, OID_AUTO, flow_control, CTLFLAG_RDTUN, 298294795Ssmh &ixgbe_flow_control, 0, "Default flow control used for all adapters"); 299294795Ssmh 300294795Ssmh/* Advertise Speed, default to 0 (auto) */ 301294795Ssmhstatic int ixgbe_advertise_speed = 0; 302294795SsmhSYSCTL_INT(_hw_ix, OID_AUTO, advertise_speed, CTLFLAG_RDTUN, 303294795Ssmh &ixgbe_advertise_speed, 0, "Default advertised speed for all adapters"); 304294795Ssmh 305280182Sjfv/* 306280182Sjfv** Smart speed setting, default to on 307280182Sjfv** this only works as a compile option 308280182Sjfv** right now as its during attach, set 309280182Sjfv** this to 'ixgbe_smart_speed_off' to 310280182Sjfv** disable. 311280182Sjfv*/ 312280182Sjfvstatic int ixgbe_smart_speed = ixgbe_smart_speed_on; 313280182Sjfv 314280182Sjfv/* 315280182Sjfv * MSIX should be the default for best performance, 316280182Sjfv * but this allows it to be forced off for testing. 317280182Sjfv */ 318280182Sjfvstatic int ixgbe_enable_msix = 1; 319280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixgbe_enable_msix, 0, 320280182Sjfv "Enable MSI-X interrupts"); 321280182Sjfv 322280182Sjfv/* 323280182Sjfv * Number of Queues, can be set to 0, 324280182Sjfv * it then autoconfigures based on the 325280182Sjfv * number of cpus with a max of 8. This 326280182Sjfv * can be overriden manually here. 327280182Sjfv */ 328280182Sjfvstatic int ixgbe_num_queues = 0; 329280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, num_queues, CTLFLAG_RDTUN, &ixgbe_num_queues, 0, 330280182Sjfv "Number of queues to configure, 0 indicates autoconfigure"); 331280182Sjfv 332280182Sjfv/* 333280182Sjfv** Number of TX descriptors per ring, 334280182Sjfv** setting higher than RX as this seems 335280182Sjfv** the better performing choice. 336280182Sjfv*/ 337280182Sjfvstatic int ixgbe_txd = PERFORM_TXD; 338280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, txd, CTLFLAG_RDTUN, &ixgbe_txd, 0, 339280182Sjfv "Number of transmit descriptors per queue"); 340280182Sjfv 341280182Sjfv/* Number of RX descriptors per ring */ 342280182Sjfvstatic int ixgbe_rxd = PERFORM_RXD; 343280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, rxd, CTLFLAG_RDTUN, &ixgbe_rxd, 0, 344280182Sjfv "Number of receive descriptors per queue"); 345280182Sjfv 346280182Sjfv/* 347280182Sjfv** Defining this on will allow the use 348280182Sjfv** of unsupported SFP+ modules, note that 349280182Sjfv** doing so you are on your own :) 350280182Sjfv*/ 351280182Sjfvstatic int allow_unsupported_sfp = FALSE; 352280182SjfvTUNABLE_INT("hw.ix.unsupported_sfp", &allow_unsupported_sfp); 353280182Sjfv 354280182Sjfv/* Keep running tab on them for sanity check */ 355280182Sjfvstatic int ixgbe_total_ports; 356280182Sjfv 357280182Sjfv#ifdef IXGBE_FDIR 358280182Sjfv/* 359280182Sjfv** Flow Director actually 'steals' 360280182Sjfv** part of the packet buffer as its 361280182Sjfv** filter pool, this variable controls 362280182Sjfv** how much it uses: 363280182Sjfv** 0 = 64K, 1 = 128K, 2 = 256K 364280182Sjfv*/ 365280182Sjfvstatic int fdir_pballoc = 1; 366280182Sjfv#endif 367280182Sjfv 368280182Sjfv#ifdef DEV_NETMAP 369280182Sjfv/* 370280182Sjfv * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to 371280182Sjfv * be a reference on how to implement netmap support in a driver. 372280182Sjfv * Additional comments are in ixgbe_netmap.h . 373280182Sjfv * 374280182Sjfv * <dev/netmap/ixgbe_netmap.h> contains functions for netmap support 375280182Sjfv * that extend the standard driver. 376280182Sjfv */ 377280182Sjfv#include <dev/netmap/ixgbe_netmap.h> 378280182Sjfv#endif /* DEV_NETMAP */ 379280182Sjfv 380283883Sjfvstatic MALLOC_DEFINE(M_IXGBE, "ix", "ix driver allocations"); 381283883Sjfv 382280182Sjfv/********************************************************************* 383280182Sjfv * Device identification routine 384280182Sjfv * 385280182Sjfv * ixgbe_probe determines if the driver should be loaded on 386280182Sjfv * adapter based on PCI vendor/device id of the adapter. 387280182Sjfv * 388280182Sjfv * return BUS_PROBE_DEFAULT on success, positive on failure 389280182Sjfv *********************************************************************/ 390280182Sjfv 391280182Sjfvstatic int 392280182Sjfvixgbe_probe(device_t dev) 393280182Sjfv{ 394280182Sjfv ixgbe_vendor_info_t *ent; 395280182Sjfv 396280182Sjfv u16 pci_vendor_id = 0; 397280182Sjfv u16 pci_device_id = 0; 398280182Sjfv u16 pci_subvendor_id = 0; 399280182Sjfv u16 pci_subdevice_id = 0; 400280182Sjfv char adapter_name[256]; 401280182Sjfv 402280182Sjfv INIT_DEBUGOUT("ixgbe_probe: begin"); 403280182Sjfv 404280182Sjfv pci_vendor_id = pci_get_vendor(dev); 405280182Sjfv if (pci_vendor_id != IXGBE_INTEL_VENDOR_ID) 406280182Sjfv return (ENXIO); 407280182Sjfv 408280182Sjfv pci_device_id = pci_get_device(dev); 409280182Sjfv pci_subvendor_id = pci_get_subvendor(dev); 410280182Sjfv pci_subdevice_id = pci_get_subdevice(dev); 411280182Sjfv 412280182Sjfv ent = ixgbe_vendor_info_array; 413280182Sjfv while (ent->vendor_id != 0) { 414280182Sjfv if ((pci_vendor_id == ent->vendor_id) && 415280182Sjfv (pci_device_id == ent->device_id) && 416280182Sjfv 417280182Sjfv ((pci_subvendor_id == ent->subvendor_id) || 418280182Sjfv (ent->subvendor_id == 0)) && 419280182Sjfv 420280182Sjfv ((pci_subdevice_id == ent->subdevice_id) || 421280182Sjfv (ent->subdevice_id == 0))) { 422280182Sjfv sprintf(adapter_name, "%s, Version - %s", 423280182Sjfv ixgbe_strings[ent->index], 424280182Sjfv ixgbe_driver_version); 425280182Sjfv device_set_desc_copy(dev, adapter_name); 426280182Sjfv ++ixgbe_total_ports; 427280182Sjfv return (BUS_PROBE_DEFAULT); 428280182Sjfv } 429280182Sjfv ent++; 430280182Sjfv } 431280182Sjfv return (ENXIO); 432280182Sjfv} 433280182Sjfv 434280182Sjfv/********************************************************************* 435280182Sjfv * Device initialization routine 436280182Sjfv * 437280182Sjfv * The attach entry point is called when the driver is being loaded. 438280182Sjfv * This routine identifies the type of hardware, allocates all resources 439280182Sjfv * and initializes the hardware. 440280182Sjfv * 441280182Sjfv * return 0 on success, positive on failure 442280182Sjfv *********************************************************************/ 443280182Sjfv 444280182Sjfvstatic int 445280182Sjfvixgbe_attach(device_t dev) 446280182Sjfv{ 447280182Sjfv struct adapter *adapter; 448280182Sjfv struct ixgbe_hw *hw; 449280182Sjfv int error = 0; 450280182Sjfv u16 csum; 451280182Sjfv u32 ctrl_ext; 452280182Sjfv 453280182Sjfv INIT_DEBUGOUT("ixgbe_attach: begin"); 454280182Sjfv 455280182Sjfv /* Allocate, clear, and link in our adapter structure */ 456280182Sjfv adapter = device_get_softc(dev); 457292674Ssbruno adapter->dev = dev; 458280182Sjfv hw = &adapter->hw; 459280182Sjfv 460285592Spkelsey#ifdef DEV_NETMAP 461285592Spkelsey adapter->init_locked = ixgbe_init_locked; 462285592Spkelsey adapter->stop_locked = ixgbe_stop; 463285592Spkelsey#endif 464285592Spkelsey 465280182Sjfv /* Core Lock Init*/ 466280182Sjfv IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev)); 467280182Sjfv 468280182Sjfv /* Set up the timer callout */ 469280182Sjfv callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0); 470280182Sjfv 471280182Sjfv /* Determine hardware revision */ 472280182Sjfv ixgbe_identify_hardware(adapter); 473280182Sjfv 474280182Sjfv /* Do base PCI setup - map BAR0 */ 475280182Sjfv if (ixgbe_allocate_pci_resources(adapter)) { 476280182Sjfv device_printf(dev, "Allocation of PCI resources failed\n"); 477280182Sjfv error = ENXIO; 478280182Sjfv goto err_out; 479280182Sjfv } 480280182Sjfv 481289238Ssbruno /* Sysctls for limiting the amount of work done in the taskqueues */ 482289238Ssbruno ixgbe_set_sysctl_value(adapter, "rx_processing_limit", 483289238Ssbruno "max number of rx packets to process", 484289238Ssbruno &adapter->rx_process_limit, ixgbe_rx_process_limit); 485289238Ssbruno 486289238Ssbruno ixgbe_set_sysctl_value(adapter, "tx_processing_limit", 487289238Ssbruno "max number of tx packets to process", 488289238Ssbruno &adapter->tx_process_limit, ixgbe_tx_process_limit); 489289238Ssbruno 490280182Sjfv /* Do descriptor calc and sanity checks */ 491280182Sjfv if (((ixgbe_txd * sizeof(union ixgbe_adv_tx_desc)) % DBA_ALIGN) != 0 || 492280182Sjfv ixgbe_txd < MIN_TXD || ixgbe_txd > MAX_TXD) { 493280182Sjfv device_printf(dev, "TXD config issue, using default!\n"); 494280182Sjfv adapter->num_tx_desc = DEFAULT_TXD; 495280182Sjfv } else 496280182Sjfv adapter->num_tx_desc = ixgbe_txd; 497280182Sjfv 498280182Sjfv /* 499280182Sjfv ** With many RX rings it is easy to exceed the 500280182Sjfv ** system mbuf allocation. Tuning nmbclusters 501280182Sjfv ** can alleviate this. 502280182Sjfv */ 503280182Sjfv if (nmbclusters > 0) { 504280182Sjfv int s; 505280182Sjfv s = (ixgbe_rxd * adapter->num_queues) * ixgbe_total_ports; 506280182Sjfv if (s > nmbclusters) { 507280182Sjfv device_printf(dev, "RX Descriptors exceed " 508280182Sjfv "system mbuf max, using default instead!\n"); 509280182Sjfv ixgbe_rxd = DEFAULT_RXD; 510280182Sjfv } 511280182Sjfv } 512280182Sjfv 513280182Sjfv if (((ixgbe_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 || 514280182Sjfv ixgbe_rxd < MIN_RXD || ixgbe_rxd > MAX_RXD) { 515280182Sjfv device_printf(dev, "RXD config issue, using default!\n"); 516280182Sjfv adapter->num_rx_desc = DEFAULT_RXD; 517280182Sjfv } else 518280182Sjfv adapter->num_rx_desc = ixgbe_rxd; 519280182Sjfv 520280182Sjfv /* Allocate our TX/RX Queues */ 521280182Sjfv if (ixgbe_allocate_queues(adapter)) { 522280182Sjfv error = ENOMEM; 523280182Sjfv goto err_out; 524280182Sjfv } 525280182Sjfv 526280182Sjfv /* Allocate multicast array memory. */ 527283883Sjfv adapter->mta = malloc(sizeof(*adapter->mta) * 528280182Sjfv MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT); 529280182Sjfv if (adapter->mta == NULL) { 530280182Sjfv device_printf(dev, "Can not allocate multicast setup array\n"); 531280182Sjfv error = ENOMEM; 532280182Sjfv goto err_late; 533280182Sjfv } 534280182Sjfv 535280182Sjfv /* Initialize the shared code */ 536280182Sjfv hw->allow_unsupported_sfp = allow_unsupported_sfp; 537280182Sjfv error = ixgbe_init_shared_code(hw); 538280182Sjfv if (error == IXGBE_ERR_SFP_NOT_PRESENT) { 539280182Sjfv /* 540280182Sjfv ** No optics in this port, set up 541280182Sjfv ** so the timer routine will probe 542280182Sjfv ** for later insertion. 543280182Sjfv */ 544280182Sjfv adapter->sfp_probe = TRUE; 545280182Sjfv error = 0; 546280182Sjfv } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) { 547292674Ssbruno device_printf(dev, "Unsupported SFP+ module detected!\n"); 548280182Sjfv error = EIO; 549280182Sjfv goto err_late; 550280182Sjfv } else if (error) { 551292674Ssbruno device_printf(dev, "Unable to initialize the shared code\n"); 552280182Sjfv error = EIO; 553280182Sjfv goto err_late; 554280182Sjfv } 555280182Sjfv 556280182Sjfv /* Make sure we have a good EEPROM before we read from it */ 557280182Sjfv if (ixgbe_validate_eeprom_checksum(&adapter->hw, &csum) < 0) { 558292674Ssbruno device_printf(dev, "The EEPROM Checksum Is Not Valid\n"); 559280182Sjfv error = EIO; 560280182Sjfv goto err_late; 561280182Sjfv } 562280182Sjfv 563280182Sjfv error = ixgbe_init_hw(hw); 564280182Sjfv switch (error) { 565280182Sjfv case IXGBE_ERR_EEPROM_VERSION: 566280182Sjfv device_printf(dev, "This device is a pre-production adapter/" 567280182Sjfv "LOM. Please be aware there may be issues associated " 568292674Ssbruno "with your hardware.\nIf you are experiencing problems " 569280182Sjfv "please contact your Intel or hardware representative " 570280182Sjfv "who provided you with this hardware.\n"); 571280182Sjfv break; 572280182Sjfv case IXGBE_ERR_SFP_NOT_SUPPORTED: 573292674Ssbruno device_printf(dev, "Unsupported SFP+ Module\n"); 574280182Sjfv error = EIO; 575280182Sjfv goto err_late; 576280182Sjfv case IXGBE_ERR_SFP_NOT_PRESENT: 577292674Ssbruno device_printf(dev, "No SFP+ Module found\n"); 578280182Sjfv /* falls thru */ 579280182Sjfv default: 580280182Sjfv break; 581280182Sjfv } 582280182Sjfv 583294795Ssmh /* hw.ix defaults init */ 584294795Ssmh ixgbe_set_advertise(adapter, ixgbe_advertise_speed); 585294795Ssmh ixgbe_set_flowcntl(adapter, ixgbe_flow_control); 586294795Ssmh adapter->enable_aim = ixgbe_enable_aim; 587294795Ssmh 588280182Sjfv if ((adapter->msix > 1) && (ixgbe_enable_msix)) 589280182Sjfv error = ixgbe_allocate_msix(adapter); 590280182Sjfv else 591280182Sjfv error = ixgbe_allocate_legacy(adapter); 592280182Sjfv if (error) 593280182Sjfv goto err_late; 594280182Sjfv 595295093Ssmh /* Enable the optics for 82599 SFP+ fiber */ 596295093Ssmh ixgbe_enable_tx_laser(hw); 597295093Ssmh 598295093Ssmh /* Enable power to the phy. */ 599295093Ssmh ixgbe_set_phy_power(hw, TRUE); 600295093Ssmh 601280182Sjfv /* Setup OS specific network interface */ 602280182Sjfv if (ixgbe_setup_interface(dev, adapter) != 0) 603280182Sjfv goto err_late; 604280182Sjfv 605280182Sjfv /* Initialize statistics */ 606280182Sjfv ixgbe_update_stats_counters(adapter); 607280182Sjfv 608280182Sjfv /* Register for VLAN events */ 609280182Sjfv adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, 610280182Sjfv ixgbe_register_vlan, adapter, EVENTHANDLER_PRI_FIRST); 611280182Sjfv adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, 612280182Sjfv ixgbe_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST); 613280182Sjfv 614282289Serj /* Check PCIE slot type/speed/width */ 615292674Ssbruno ixgbe_get_slot_info(adapter); 616280182Sjfv 617292674Ssbruno /* Set an initial default flow control & dmac value */ 618280182Sjfv adapter->fc = ixgbe_fc_full; 619292674Ssbruno adapter->dmac = 0; 620292674Ssbruno adapter->eee_enabled = 0; 621280182Sjfv 622283883Sjfv#ifdef PCI_IOV 623283883Sjfv if ((hw->mac.type != ixgbe_mac_82598EB) && (adapter->msix > 1)) { 624283883Sjfv nvlist_t *pf_schema, *vf_schema; 625283883Sjfv 626283883Sjfv hw->mbx.ops.init_params(hw); 627283883Sjfv pf_schema = pci_iov_schema_alloc_node(); 628283883Sjfv vf_schema = pci_iov_schema_alloc_node(); 629283883Sjfv pci_iov_schema_add_unicast_mac(vf_schema, "mac-addr", 0, NULL); 630283883Sjfv pci_iov_schema_add_bool(vf_schema, "mac-anti-spoof", 631283883Sjfv IOV_SCHEMA_HASDEFAULT, TRUE); 632283883Sjfv pci_iov_schema_add_bool(vf_schema, "allow-set-mac", 633283883Sjfv IOV_SCHEMA_HASDEFAULT, FALSE); 634283883Sjfv pci_iov_schema_add_bool(vf_schema, "allow-promisc", 635283883Sjfv IOV_SCHEMA_HASDEFAULT, FALSE); 636283883Sjfv error = pci_iov_attach(dev, pf_schema, vf_schema); 637283883Sjfv if (error != 0) { 638283883Sjfv device_printf(dev, 639283883Sjfv "Error %d setting up SR-IOV\n", error); 640283883Sjfv } 641283883Sjfv } 642283883Sjfv#endif /* PCI_IOV */ 643283883Sjfv 644282289Serj /* Check for certain supported features */ 645282289Serj ixgbe_check_wol_support(adapter); 646282289Serj 647282289Serj /* Add sysctls */ 648282289Serj ixgbe_add_device_sysctls(adapter); 649282289Serj ixgbe_add_hw_stats(adapter); 650282289Serj 651280182Sjfv /* let hardware know driver is loaded */ 652280182Sjfv ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 653280182Sjfv ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD; 654280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 655280182Sjfv 656280182Sjfv#ifdef DEV_NETMAP 657280182Sjfv ixgbe_netmap_attach(adapter); 658280182Sjfv#endif /* DEV_NETMAP */ 659280182Sjfv INIT_DEBUGOUT("ixgbe_attach: end"); 660280182Sjfv return (0); 661280182Sjfv 662280182Sjfverr_late: 663280182Sjfv ixgbe_free_transmit_structures(adapter); 664280182Sjfv ixgbe_free_receive_structures(adapter); 665280182Sjfverr_out: 666280182Sjfv if (adapter->ifp != NULL) 667280182Sjfv if_free(adapter->ifp); 668280182Sjfv ixgbe_free_pci_resources(adapter); 669280182Sjfv free(adapter->mta, M_DEVBUF); 670280182Sjfv return (error); 671280182Sjfv} 672280182Sjfv 673280182Sjfv/********************************************************************* 674280182Sjfv * Device removal routine 675280182Sjfv * 676280182Sjfv * The detach entry point is called when the driver is being removed. 677280182Sjfv * This routine stops the adapter and deallocates all the resources 678280182Sjfv * that were allocated for driver operation. 679280182Sjfv * 680280182Sjfv * return 0 on success, positive on failure 681280182Sjfv *********************************************************************/ 682280182Sjfv 683280182Sjfvstatic int 684280182Sjfvixgbe_detach(device_t dev) 685280182Sjfv{ 686280182Sjfv struct adapter *adapter = device_get_softc(dev); 687280182Sjfv struct ix_queue *que = adapter->queues; 688280182Sjfv struct tx_ring *txr = adapter->tx_rings; 689280182Sjfv u32 ctrl_ext; 690280182Sjfv 691280182Sjfv INIT_DEBUGOUT("ixgbe_detach: begin"); 692280182Sjfv 693280182Sjfv /* Make sure VLANS are not using driver */ 694280182Sjfv if (adapter->ifp->if_vlantrunk != NULL) { 695280182Sjfv device_printf(dev,"Vlan in use, detach first\n"); 696280182Sjfv return (EBUSY); 697280182Sjfv } 698280182Sjfv 699283883Sjfv#ifdef PCI_IOV 700283883Sjfv if (pci_iov_detach(dev) != 0) { 701283883Sjfv device_printf(dev, "SR-IOV in use; detach first.\n"); 702283883Sjfv return (EBUSY); 703283883Sjfv } 704283883Sjfv#endif /* PCI_IOV */ 705283883Sjfv 706292674Ssbruno ether_ifdetach(adapter->ifp); 707282289Serj /* Stop the adapter */ 708280182Sjfv IXGBE_CORE_LOCK(adapter); 709282289Serj ixgbe_setup_low_power_mode(adapter); 710280182Sjfv IXGBE_CORE_UNLOCK(adapter); 711280182Sjfv 712280182Sjfv for (int i = 0; i < adapter->num_queues; i++, que++, txr++) { 713280182Sjfv if (que->tq) { 714280182Sjfv#ifndef IXGBE_LEGACY_TX 715280182Sjfv taskqueue_drain(que->tq, &txr->txq_task); 716280182Sjfv#endif 717280182Sjfv taskqueue_drain(que->tq, &que->que_task); 718280182Sjfv taskqueue_free(que->tq); 719280182Sjfv } 720280182Sjfv } 721280182Sjfv 722280182Sjfv /* Drain the Link queue */ 723280182Sjfv if (adapter->tq) { 724280182Sjfv taskqueue_drain(adapter->tq, &adapter->link_task); 725280182Sjfv taskqueue_drain(adapter->tq, &adapter->mod_task); 726280182Sjfv taskqueue_drain(adapter->tq, &adapter->msf_task); 727283883Sjfv#ifdef PCI_IOV 728283883Sjfv taskqueue_drain(adapter->tq, &adapter->mbx_task); 729283883Sjfv#endif 730282289Serj taskqueue_drain(adapter->tq, &adapter->phy_task); 731280182Sjfv#ifdef IXGBE_FDIR 732280182Sjfv taskqueue_drain(adapter->tq, &adapter->fdir_task); 733280182Sjfv#endif 734280182Sjfv taskqueue_free(adapter->tq); 735280182Sjfv } 736280182Sjfv 737280182Sjfv /* let hardware know driver is unloading */ 738280182Sjfv ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); 739280182Sjfv ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD; 740280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext); 741280182Sjfv 742280182Sjfv /* Unregister VLAN events */ 743280182Sjfv if (adapter->vlan_attach != NULL) 744280182Sjfv EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach); 745280182Sjfv if (adapter->vlan_detach != NULL) 746280182Sjfv EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach); 747280182Sjfv 748280182Sjfv callout_drain(&adapter->timer); 749280182Sjfv#ifdef DEV_NETMAP 750280182Sjfv netmap_detach(adapter->ifp); 751280182Sjfv#endif /* DEV_NETMAP */ 752280182Sjfv ixgbe_free_pci_resources(adapter); 753280182Sjfv bus_generic_detach(dev); 754280182Sjfv if_free(adapter->ifp); 755280182Sjfv 756280182Sjfv ixgbe_free_transmit_structures(adapter); 757280182Sjfv ixgbe_free_receive_structures(adapter); 758280182Sjfv free(adapter->mta, M_DEVBUF); 759280182Sjfv 760280182Sjfv IXGBE_CORE_LOCK_DESTROY(adapter); 761280182Sjfv return (0); 762280182Sjfv} 763280182Sjfv 764280182Sjfv/********************************************************************* 765280182Sjfv * 766280182Sjfv * Shutdown entry point 767280182Sjfv * 768280182Sjfv **********************************************************************/ 769280182Sjfv 770280182Sjfvstatic int 771280182Sjfvixgbe_shutdown(device_t dev) 772280182Sjfv{ 773280182Sjfv struct adapter *adapter = device_get_softc(dev); 774282289Serj int error = 0; 775282289Serj 776282289Serj INIT_DEBUGOUT("ixgbe_shutdown: begin"); 777282289Serj 778280182Sjfv IXGBE_CORE_LOCK(adapter); 779282289Serj error = ixgbe_setup_low_power_mode(adapter); 780280182Sjfv IXGBE_CORE_UNLOCK(adapter); 781282289Serj 782282289Serj return (error); 783282289Serj} 784282289Serj 785282289Serj/** 786282289Serj * Methods for going from: 787282289Serj * D0 -> D3: ixgbe_suspend 788282289Serj * D3 -> D0: ixgbe_resume 789282289Serj */ 790282289Serjstatic int 791282289Serjixgbe_suspend(device_t dev) 792282289Serj{ 793282289Serj struct adapter *adapter = device_get_softc(dev); 794282289Serj int error = 0; 795282289Serj 796282289Serj INIT_DEBUGOUT("ixgbe_suspend: begin"); 797282289Serj 798282289Serj IXGBE_CORE_LOCK(adapter); 799282289Serj 800282289Serj error = ixgbe_setup_low_power_mode(adapter); 801282289Serj 802282289Serj IXGBE_CORE_UNLOCK(adapter); 803282289Serj 804282289Serj return (error); 805282289Serj} 806282289Serj 807282289Serjstatic int 808282289Serjixgbe_resume(device_t dev) 809282289Serj{ 810282289Serj struct adapter *adapter = device_get_softc(dev); 811282289Serj struct ifnet *ifp = adapter->ifp; 812282289Serj struct ixgbe_hw *hw = &adapter->hw; 813282289Serj u32 wus; 814282289Serj 815282289Serj INIT_DEBUGOUT("ixgbe_resume: begin"); 816282289Serj 817282289Serj IXGBE_CORE_LOCK(adapter); 818282289Serj 819282289Serj /* Read & clear WUS register */ 820282289Serj wus = IXGBE_READ_REG(hw, IXGBE_WUS); 821282289Serj if (wus) 822282289Serj device_printf(dev, "Woken up by (WUS): %#010x\n", 823282289Serj IXGBE_READ_REG(hw, IXGBE_WUS)); 824282289Serj IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff); 825282289Serj /* And clear WUFC until next low-power transition */ 826282289Serj IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0); 827282289Serj 828282289Serj /* 829282289Serj * Required after D3->D0 transition; 830282289Serj * will re-advertise all previous advertised speeds 831282289Serj */ 832282289Serj if (ifp->if_flags & IFF_UP) 833282289Serj ixgbe_init_locked(adapter); 834282289Serj 835282289Serj IXGBE_CORE_UNLOCK(adapter); 836282289Serj 837280182Sjfv return (0); 838280182Sjfv} 839280182Sjfv 840280182Sjfv 841280182Sjfv/********************************************************************* 842280182Sjfv * Ioctl entry point 843280182Sjfv * 844280182Sjfv * ixgbe_ioctl is called when the user wants to configure the 845280182Sjfv * interface. 846280182Sjfv * 847280182Sjfv * return 0 on success, positive on failure 848280182Sjfv **********************************************************************/ 849280182Sjfv 850280182Sjfvstatic int 851280182Sjfvixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) 852280182Sjfv{ 853280182Sjfv struct adapter *adapter = ifp->if_softc; 854280182Sjfv struct ifreq *ifr = (struct ifreq *) data; 855280182Sjfv#if defined(INET) || defined(INET6) 856280182Sjfv struct ifaddr *ifa = (struct ifaddr *)data; 857280182Sjfv#endif 858280182Sjfv int error = 0; 859286238Ssbruno bool avoid_reset = FALSE; 860280182Sjfv 861280182Sjfv switch (command) { 862280182Sjfv 863280182Sjfv case SIOCSIFADDR: 864280182Sjfv#ifdef INET 865280182Sjfv if (ifa->ifa_addr->sa_family == AF_INET) 866280182Sjfv avoid_reset = TRUE; 867280182Sjfv#endif 868280182Sjfv#ifdef INET6 869280182Sjfv if (ifa->ifa_addr->sa_family == AF_INET6) 870280182Sjfv avoid_reset = TRUE; 871280182Sjfv#endif 872280182Sjfv /* 873280182Sjfv ** Calling init results in link renegotiation, 874280182Sjfv ** so we avoid doing it when possible. 875280182Sjfv */ 876280182Sjfv if (avoid_reset) { 877280182Sjfv ifp->if_flags |= IFF_UP; 878280182Sjfv if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 879280182Sjfv ixgbe_init(adapter); 880292674Ssbruno#ifdef INET 881280182Sjfv if (!(ifp->if_flags & IFF_NOARP)) 882280182Sjfv arp_ifinit(ifp, ifa); 883286238Ssbruno#endif 884280182Sjfv } else 885280182Sjfv error = ether_ioctl(ifp, command, data); 886280182Sjfv break; 887280182Sjfv case SIOCSIFMTU: 888280182Sjfv IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)"); 889282289Serj if (ifr->ifr_mtu > IXGBE_MAX_MTU) { 890280182Sjfv error = EINVAL; 891280182Sjfv } else { 892280182Sjfv IXGBE_CORE_LOCK(adapter); 893280182Sjfv ifp->if_mtu = ifr->ifr_mtu; 894280182Sjfv adapter->max_frame_size = 895282289Serj ifp->if_mtu + IXGBE_MTU_HDR; 896302384Ssbruno if (ifp->if_drv_flags & IFF_DRV_RUNNING) 897302384Ssbruno ixgbe_init_locked(adapter); 898283883Sjfv#ifdef PCI_IOV 899283883Sjfv ixgbe_recalculate_max_frame(adapter); 900283883Sjfv#endif 901280182Sjfv IXGBE_CORE_UNLOCK(adapter); 902280182Sjfv } 903280182Sjfv break; 904280182Sjfv case SIOCSIFFLAGS: 905280182Sjfv IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)"); 906280182Sjfv IXGBE_CORE_LOCK(adapter); 907280182Sjfv if (ifp->if_flags & IFF_UP) { 908280182Sjfv if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) { 909280182Sjfv if ((ifp->if_flags ^ adapter->if_flags) & 910280182Sjfv (IFF_PROMISC | IFF_ALLMULTI)) { 911280182Sjfv ixgbe_set_promisc(adapter); 912280182Sjfv } 913280182Sjfv } else 914280182Sjfv ixgbe_init_locked(adapter); 915280182Sjfv } else 916280182Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) 917280182Sjfv ixgbe_stop(adapter); 918280182Sjfv adapter->if_flags = ifp->if_flags; 919280182Sjfv IXGBE_CORE_UNLOCK(adapter); 920280182Sjfv break; 921280182Sjfv case SIOCADDMULTI: 922280182Sjfv case SIOCDELMULTI: 923280182Sjfv IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI"); 924280182Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 925280182Sjfv IXGBE_CORE_LOCK(adapter); 926280182Sjfv ixgbe_disable_intr(adapter); 927280182Sjfv ixgbe_set_multi(adapter); 928280182Sjfv ixgbe_enable_intr(adapter); 929280182Sjfv IXGBE_CORE_UNLOCK(adapter); 930280182Sjfv } 931280182Sjfv break; 932280182Sjfv case SIOCSIFMEDIA: 933280182Sjfv case SIOCGIFMEDIA: 934280182Sjfv IOCTL_DEBUGOUT("ioctl: SIOCxIFMEDIA (Get/Set Interface Media)"); 935280182Sjfv error = ifmedia_ioctl(ifp, ifr, &adapter->media, command); 936280182Sjfv break; 937280182Sjfv case SIOCSIFCAP: 938280182Sjfv { 939292674Ssbruno IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)"); 940292674Ssbruno 941280182Sjfv int mask = ifr->ifr_reqcap ^ ifp->if_capenable; 942292674Ssbruno if (!mask) 943292674Ssbruno break; 944292674Ssbruno 945292674Ssbruno /* HW cannot turn these on/off separately */ 946292674Ssbruno if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) { 947292674Ssbruno ifp->if_capenable ^= IFCAP_RXCSUM; 948292674Ssbruno ifp->if_capenable ^= IFCAP_RXCSUM_IPV6; 949292674Ssbruno } 950292674Ssbruno if (mask & IFCAP_TXCSUM) 951292674Ssbruno ifp->if_capenable ^= IFCAP_TXCSUM; 952292674Ssbruno if (mask & IFCAP_TXCSUM_IPV6) 953292674Ssbruno ifp->if_capenable ^= IFCAP_TXCSUM_IPV6; 954280182Sjfv if (mask & IFCAP_TSO4) 955280182Sjfv ifp->if_capenable ^= IFCAP_TSO4; 956280182Sjfv if (mask & IFCAP_TSO6) 957280182Sjfv ifp->if_capenable ^= IFCAP_TSO6; 958280182Sjfv if (mask & IFCAP_LRO) 959280182Sjfv ifp->if_capenable ^= IFCAP_LRO; 960280182Sjfv if (mask & IFCAP_VLAN_HWTAGGING) 961280182Sjfv ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 962280182Sjfv if (mask & IFCAP_VLAN_HWFILTER) 963280182Sjfv ifp->if_capenable ^= IFCAP_VLAN_HWFILTER; 964280182Sjfv if (mask & IFCAP_VLAN_HWTSO) 965280182Sjfv ifp->if_capenable ^= IFCAP_VLAN_HWTSO; 966292674Ssbruno 967280182Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 968280182Sjfv IXGBE_CORE_LOCK(adapter); 969280182Sjfv ixgbe_init_locked(adapter); 970280182Sjfv IXGBE_CORE_UNLOCK(adapter); 971280182Sjfv } 972280182Sjfv VLAN_CAPABILITIES(ifp); 973280182Sjfv break; 974280182Sjfv } 975280182Sjfv#if __FreeBSD_version >= 1100036 976280182Sjfv case SIOCGI2C: 977280182Sjfv { 978280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 979280182Sjfv struct ifi2creq i2c; 980280182Sjfv int i; 981280182Sjfv IOCTL_DEBUGOUT("ioctl: SIOCGI2C (Get I2C Data)"); 982280182Sjfv error = copyin(ifr->ifr_data, &i2c, sizeof(i2c)); 983280182Sjfv if (error != 0) 984280182Sjfv break; 985280182Sjfv if (i2c.dev_addr != 0xA0 && i2c.dev_addr != 0xA2) { 986280182Sjfv error = EINVAL; 987280182Sjfv break; 988280182Sjfv } 989280182Sjfv if (i2c.len > sizeof(i2c.data)) { 990280182Sjfv error = EINVAL; 991280182Sjfv break; 992280182Sjfv } 993280182Sjfv 994280182Sjfv for (i = 0; i < i2c.len; i++) 995280182Sjfv hw->phy.ops.read_i2c_byte(hw, i2c.offset + i, 996280182Sjfv i2c.dev_addr, &i2c.data[i]); 997280182Sjfv error = copyout(&i2c, ifr->ifr_data, sizeof(i2c)); 998280182Sjfv break; 999280182Sjfv } 1000280182Sjfv#endif 1001280182Sjfv default: 1002280182Sjfv IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command); 1003280182Sjfv error = ether_ioctl(ifp, command, data); 1004280182Sjfv break; 1005280182Sjfv } 1006280182Sjfv 1007280182Sjfv return (error); 1008280182Sjfv} 1009280182Sjfv 1010292674Ssbruno/* 1011292674Ssbruno * Set the various hardware offload abilities. 1012292674Ssbruno * 1013292674Ssbruno * This takes the ifnet's if_capenable flags (e.g. set by the user using 1014292674Ssbruno * ifconfig) and indicates to the OS via the ifnet's if_hwassist field what 1015292674Ssbruno * mbuf offload flags the driver will understand. 1016292674Ssbruno */ 1017292674Ssbrunostatic void 1018292674Ssbrunoixgbe_set_if_hwassist(struct adapter *adapter) 1019292674Ssbruno{ 1020292674Ssbruno struct ifnet *ifp = adapter->ifp; 1021295273Stuexen struct ixgbe_hw *hw = &adapter->hw; 1022292674Ssbruno 1023292674Ssbruno ifp->if_hwassist = 0; 1024292674Ssbruno#if __FreeBSD_version >= 1000000 1025292674Ssbruno if (ifp->if_capenable & IFCAP_TSO4) 1026292674Ssbruno ifp->if_hwassist |= CSUM_IP_TSO; 1027292674Ssbruno if (ifp->if_capenable & IFCAP_TSO6) 1028292674Ssbruno ifp->if_hwassist |= CSUM_IP6_TSO; 1029295273Stuexen if (ifp->if_capenable & IFCAP_TXCSUM) { 1030295273Stuexen ifp->if_hwassist |= (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP); 1031295273Stuexen if (hw->mac.type != ixgbe_mac_82598EB) 1032295273Stuexen ifp->if_hwassist |= CSUM_IP_SCTP; 1033295273Stuexen } 1034295273Stuexen if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) { 1035295273Stuexen ifp->if_hwassist |= (CSUM_IP6_UDP | CSUM_IP6_TCP); 1036295273Stuexen if (hw->mac.type != ixgbe_mac_82598EB) 1037295273Stuexen ifp->if_hwassist |= CSUM_IP6_SCTP; 1038295273Stuexen } 1039292674Ssbruno#else 1040292674Ssbruno if (ifp->if_capenable & IFCAP_TSO) 1041292674Ssbruno ifp->if_hwassist |= CSUM_TSO; 1042292674Ssbruno if (ifp->if_capenable & IFCAP_TXCSUM) { 1043292674Ssbruno ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); 1044292674Ssbruno if (hw->mac.type != ixgbe_mac_82598EB) 1045292674Ssbruno ifp->if_hwassist |= CSUM_SCTP; 1046292674Ssbruno } 1047292674Ssbruno#endif 1048292674Ssbruno} 1049292674Ssbruno 1050280182Sjfv/********************************************************************* 1051280182Sjfv * Init entry point 1052280182Sjfv * 1053280182Sjfv * This routine is used in two ways. It is used by the stack as 1054280182Sjfv * init entry point in network interface structure. It is also used 1055280182Sjfv * by the driver as a hw/sw initialization routine to get to a 1056280182Sjfv * consistent state. 1057280182Sjfv * 1058280182Sjfv * return 0 on success, positive on failure 1059280182Sjfv **********************************************************************/ 1060280182Sjfv#define IXGBE_MHADD_MFS_SHIFT 16 1061280182Sjfv 1062280182Sjfvstatic void 1063280182Sjfvixgbe_init_locked(struct adapter *adapter) 1064280182Sjfv{ 1065280182Sjfv struct ifnet *ifp = adapter->ifp; 1066280182Sjfv device_t dev = adapter->dev; 1067280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 1068283883Sjfv struct tx_ring *txr; 1069283883Sjfv struct rx_ring *rxr; 1070283883Sjfv u32 txdctl, mhadd; 1071280182Sjfv u32 rxdctl, rxctrl; 1072292674Ssbruno int err = 0; 1073283883Sjfv#ifdef PCI_IOV 1074283883Sjfv enum ixgbe_iov_mode mode; 1075283883Sjfv#endif 1076280182Sjfv 1077280182Sjfv mtx_assert(&adapter->core_mtx, MA_OWNED); 1078280182Sjfv INIT_DEBUGOUT("ixgbe_init_locked: begin"); 1079283883Sjfv 1080280182Sjfv hw->adapter_stopped = FALSE; 1081280182Sjfv ixgbe_stop_adapter(hw); 1082280182Sjfv callout_stop(&adapter->timer); 1083280182Sjfv 1084283883Sjfv#ifdef PCI_IOV 1085283883Sjfv mode = ixgbe_get_iov_mode(adapter); 1086283883Sjfv adapter->pool = ixgbe_max_vfs(mode); 1087283883Sjfv /* Queue indices may change with IOV mode */ 1088283883Sjfv for (int i = 0; i < adapter->num_queues; i++) { 1089283883Sjfv adapter->rx_rings[i].me = ixgbe_pf_que_index(mode, i); 1090283883Sjfv adapter->tx_rings[i].me = ixgbe_pf_que_index(mode, i); 1091283883Sjfv } 1092283883Sjfv#endif 1093280182Sjfv /* reprogram the RAR[0] in case user changed it. */ 1094283883Sjfv ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, IXGBE_RAH_AV); 1095280182Sjfv 1096280182Sjfv /* Get the latest mac address, User can use a LAA */ 1097283883Sjfv bcopy(IF_LLADDR(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS); 1098283883Sjfv ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1); 1099280182Sjfv hw->addr_ctrl.rar_used_count = 1; 1100280182Sjfv 1101292674Ssbruno /* Set hardware offload abilities from ifnet flags */ 1102292674Ssbruno ixgbe_set_if_hwassist(adapter); 1103280182Sjfv 1104280182Sjfv /* Prepare transmit descriptors and buffers */ 1105280182Sjfv if (ixgbe_setup_transmit_structures(adapter)) { 1106282289Serj device_printf(dev, "Could not setup transmit structures\n"); 1107280182Sjfv ixgbe_stop(adapter); 1108280182Sjfv return; 1109280182Sjfv } 1110280182Sjfv 1111280182Sjfv ixgbe_init_hw(hw); 1112283883Sjfv#ifdef PCI_IOV 1113283883Sjfv ixgbe_initialize_iov(adapter); 1114283883Sjfv#endif 1115280182Sjfv ixgbe_initialize_transmit_units(adapter); 1116280182Sjfv 1117280182Sjfv /* Setup Multicast table */ 1118280182Sjfv ixgbe_set_multi(adapter); 1119280182Sjfv 1120292674Ssbruno /* Determine the correct mbuf pool, based on frame size */ 1121283883Sjfv if (adapter->max_frame_size <= MCLBYTES) 1122280182Sjfv adapter->rx_mbuf_sz = MCLBYTES; 1123283883Sjfv else 1124283882Sjfv adapter->rx_mbuf_sz = MJUMPAGESIZE; 1125280182Sjfv 1126280182Sjfv /* Prepare receive descriptors and buffers */ 1127280182Sjfv if (ixgbe_setup_receive_structures(adapter)) { 1128282289Serj device_printf(dev, "Could not setup receive structures\n"); 1129280182Sjfv ixgbe_stop(adapter); 1130280182Sjfv return; 1131280182Sjfv } 1132280182Sjfv 1133280182Sjfv /* Configure RX settings */ 1134280182Sjfv ixgbe_initialize_receive_units(adapter); 1135280182Sjfv 1136283883Sjfv /* Enable SDP & MSIX interrupts based on adapter */ 1137283883Sjfv ixgbe_config_gpie(adapter); 1138280182Sjfv 1139280182Sjfv /* Set MTU size */ 1140280182Sjfv if (ifp->if_mtu > ETHERMTU) { 1141282289Serj /* aka IXGBE_MAXFRS on 82599 and newer */ 1142280182Sjfv mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); 1143280182Sjfv mhadd &= ~IXGBE_MHADD_MFS_MASK; 1144280182Sjfv mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT; 1145280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); 1146280182Sjfv } 1147280182Sjfv 1148280182Sjfv /* Now enable all the queues */ 1149280182Sjfv for (int i = 0; i < adapter->num_queues; i++) { 1150283883Sjfv txr = &adapter->tx_rings[i]; 1151283883Sjfv txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me)); 1152280182Sjfv txdctl |= IXGBE_TXDCTL_ENABLE; 1153280182Sjfv /* Set WTHRESH to 8, burst writeback */ 1154280182Sjfv txdctl |= (8 << 16); 1155280182Sjfv /* 1156280182Sjfv * When the internal queue falls below PTHRESH (32), 1157280182Sjfv * start prefetching as long as there are at least 1158280182Sjfv * HTHRESH (1) buffers ready. The values are taken 1159280182Sjfv * from the Intel linux driver 3.8.21. 1160280182Sjfv * Prefetching enables tx line rate even with 1 queue. 1161280182Sjfv */ 1162280182Sjfv txdctl |= (32 << 0) | (1 << 8); 1163283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl); 1164280182Sjfv } 1165280182Sjfv 1166283883Sjfv for (int i = 0, j = 0; i < adapter->num_queues; i++) { 1167283883Sjfv rxr = &adapter->rx_rings[i]; 1168283883Sjfv rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); 1169280182Sjfv if (hw->mac.type == ixgbe_mac_82598EB) { 1170280182Sjfv /* 1171280182Sjfv ** PTHRESH = 21 1172280182Sjfv ** HTHRESH = 4 1173280182Sjfv ** WTHRESH = 8 1174280182Sjfv */ 1175280182Sjfv rxdctl &= ~0x3FFFFF; 1176280182Sjfv rxdctl |= 0x080420; 1177280182Sjfv } 1178280182Sjfv rxdctl |= IXGBE_RXDCTL_ENABLE; 1179283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), rxdctl); 1180283883Sjfv for (; j < 10; j++) { 1181283883Sjfv if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)) & 1182280182Sjfv IXGBE_RXDCTL_ENABLE) 1183280182Sjfv break; 1184280182Sjfv else 1185280182Sjfv msec_delay(1); 1186280182Sjfv } 1187280182Sjfv wmb(); 1188280182Sjfv#ifdef DEV_NETMAP 1189280182Sjfv /* 1190280182Sjfv * In netmap mode, we must preserve the buffers made 1191280182Sjfv * available to userspace before the if_init() 1192280182Sjfv * (this is true by default on the TX side, because 1193280182Sjfv * init makes all buffers available to userspace). 1194280182Sjfv * 1195280182Sjfv * netmap_reset() and the device specific routines 1196280182Sjfv * (e.g. ixgbe_setup_receive_rings()) map these 1197280182Sjfv * buffers at the end of the NIC ring, so here we 1198280182Sjfv * must set the RDT (tail) register to make sure 1199280182Sjfv * they are not overwritten. 1200280182Sjfv * 1201280182Sjfv * In this driver the NIC ring starts at RDH = 0, 1202280182Sjfv * RDT points to the last slot available for reception (?), 1203280182Sjfv * so RDT = num_rx_desc - 1 means the whole ring is available. 1204280182Sjfv */ 1205280182Sjfv if (ifp->if_capenable & IFCAP_NETMAP) { 1206280182Sjfv struct netmap_adapter *na = NA(adapter->ifp); 1207280182Sjfv struct netmap_kring *kring = &na->rx_rings[i]; 1208280182Sjfv int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring); 1209280182Sjfv 1210283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me), t); 1211280182Sjfv } else 1212280182Sjfv#endif /* DEV_NETMAP */ 1213283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me), adapter->num_rx_desc - 1); 1214280182Sjfv } 1215280182Sjfv 1216280182Sjfv /* Enable Receive engine */ 1217280182Sjfv rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 1218280182Sjfv if (hw->mac.type == ixgbe_mac_82598EB) 1219280182Sjfv rxctrl |= IXGBE_RXCTRL_DMBYPS; 1220280182Sjfv rxctrl |= IXGBE_RXCTRL_RXEN; 1221280182Sjfv ixgbe_enable_rx_dma(hw, rxctrl); 1222280182Sjfv 1223280182Sjfv callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter); 1224280182Sjfv 1225280182Sjfv /* Set up MSI/X routing */ 1226280182Sjfv if (ixgbe_enable_msix) { 1227280182Sjfv ixgbe_configure_ivars(adapter); 1228280182Sjfv /* Set up auto-mask */ 1229280182Sjfv if (hw->mac.type == ixgbe_mac_82598EB) 1230280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); 1231280182Sjfv else { 1232280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF); 1233280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF); 1234280182Sjfv } 1235280182Sjfv } else { /* Simple settings for Legacy/MSI */ 1236280182Sjfv ixgbe_set_ivar(adapter, 0, 0, 0); 1237280182Sjfv ixgbe_set_ivar(adapter, 0, 0, 1); 1238280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); 1239280182Sjfv } 1240280182Sjfv 1241280182Sjfv#ifdef IXGBE_FDIR 1242280182Sjfv /* Init Flow director */ 1243280182Sjfv if (hw->mac.type != ixgbe_mac_82598EB) { 1244280182Sjfv u32 hdrm = 32 << fdir_pballoc; 1245280182Sjfv 1246280182Sjfv hw->mac.ops.setup_rxpba(hw, 0, hdrm, PBA_STRATEGY_EQUAL); 1247280182Sjfv ixgbe_init_fdir_signature_82599(&adapter->hw, fdir_pballoc); 1248280182Sjfv } 1249280182Sjfv#endif 1250280182Sjfv 1251280182Sjfv /* 1252283883Sjfv * Check on any SFP devices that 1253283883Sjfv * need to be kick-started 1254283883Sjfv */ 1255280182Sjfv if (hw->phy.type == ixgbe_phy_none) { 1256292674Ssbruno err = hw->phy.ops.identify(hw); 1257280182Sjfv if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 1258280182Sjfv device_printf(dev, 1259280182Sjfv "Unsupported SFP+ module type was detected.\n"); 1260280182Sjfv return; 1261280182Sjfv } 1262280182Sjfv } 1263280182Sjfv 1264280182Sjfv /* Set moderation on the Link interrupt */ 1265280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR); 1266280182Sjfv 1267282289Serj /* Configure Energy Efficient Ethernet for supported devices */ 1268292674Ssbruno if (hw->mac.ops.setup_eee) { 1269292674Ssbruno err = hw->mac.ops.setup_eee(hw, adapter->eee_enabled); 1270292674Ssbruno if (err) 1271292674Ssbruno device_printf(dev, "Error setting up EEE: %d\n", err); 1272292674Ssbruno } 1273282289Serj 1274295093Ssmh /* Enable power to the phy. */ 1275295093Ssmh ixgbe_set_phy_power(hw, TRUE); 1276295093Ssmh 1277280182Sjfv /* Config/Enable Link */ 1278280182Sjfv ixgbe_config_link(adapter); 1279280182Sjfv 1280280182Sjfv /* Hardware Packet Buffer & Flow Control setup */ 1281282289Serj ixgbe_config_delay_values(adapter); 1282280182Sjfv 1283280182Sjfv /* Initialize the FC settings */ 1284280182Sjfv ixgbe_start_hw(hw); 1285280182Sjfv 1286280182Sjfv /* Set up VLAN support and filter */ 1287280182Sjfv ixgbe_setup_vlan_hw_support(adapter); 1288280182Sjfv 1289282289Serj /* Setup DMA Coalescing */ 1290282289Serj ixgbe_config_dmac(adapter); 1291282289Serj 1292280182Sjfv /* And now turn on interrupts */ 1293280182Sjfv ixgbe_enable_intr(adapter); 1294280182Sjfv 1295283883Sjfv#ifdef PCI_IOV 1296283883Sjfv /* Enable the use of the MBX by the VF's */ 1297283883Sjfv { 1298283883Sjfv u32 reg = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 1299283883Sjfv reg |= IXGBE_CTRL_EXT_PFRSTD; 1300283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, reg); 1301283883Sjfv } 1302283883Sjfv#endif 1303283883Sjfv 1304280182Sjfv /* Now inform the stack we're ready */ 1305280182Sjfv ifp->if_drv_flags |= IFF_DRV_RUNNING; 1306280182Sjfv 1307280182Sjfv return; 1308280182Sjfv} 1309280182Sjfv 1310280182Sjfvstatic void 1311280182Sjfvixgbe_init(void *arg) 1312280182Sjfv{ 1313280182Sjfv struct adapter *adapter = arg; 1314280182Sjfv 1315280182Sjfv IXGBE_CORE_LOCK(adapter); 1316280182Sjfv ixgbe_init_locked(adapter); 1317280182Sjfv IXGBE_CORE_UNLOCK(adapter); 1318280182Sjfv return; 1319280182Sjfv} 1320280182Sjfv 1321282289Serjstatic void 1322283883Sjfvixgbe_config_gpie(struct adapter *adapter) 1323283883Sjfv{ 1324283883Sjfv struct ixgbe_hw *hw = &adapter->hw; 1325283883Sjfv u32 gpie; 1326283883Sjfv 1327283883Sjfv gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); 1328283883Sjfv 1329283883Sjfv /* Fan Failure Interrupt */ 1330283883Sjfv if (hw->device_id == IXGBE_DEV_ID_82598AT) 1331283883Sjfv gpie |= IXGBE_SDP1_GPIEN; 1332283883Sjfv 1333283883Sjfv /* 1334283883Sjfv * Module detection (SDP2) 1335283883Sjfv * Media ready (SDP1) 1336283883Sjfv */ 1337283883Sjfv if (hw->mac.type == ixgbe_mac_82599EB) { 1338283883Sjfv gpie |= IXGBE_SDP2_GPIEN; 1339283883Sjfv if (hw->device_id != IXGBE_DEV_ID_82599_QSFP_SF_QP) 1340283883Sjfv gpie |= IXGBE_SDP1_GPIEN; 1341283883Sjfv } 1342283883Sjfv 1343283883Sjfv /* 1344283883Sjfv * Thermal Failure Detection (X540) 1345292674Ssbruno * Link Detection (X552 SFP+, X552/X557-AT) 1346283883Sjfv */ 1347283883Sjfv if (hw->mac.type == ixgbe_mac_X540 || 1348283883Sjfv hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP || 1349283883Sjfv hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) 1350283883Sjfv gpie |= IXGBE_SDP0_GPIEN_X540; 1351283883Sjfv 1352283883Sjfv if (adapter->msix > 1) { 1353283883Sjfv /* Enable Enhanced MSIX mode */ 1354283883Sjfv gpie |= IXGBE_GPIE_MSIX_MODE; 1355283883Sjfv gpie |= IXGBE_GPIE_EIAME | IXGBE_GPIE_PBA_SUPPORT | 1356283883Sjfv IXGBE_GPIE_OCD; 1357283883Sjfv } 1358283883Sjfv 1359283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); 1360283883Sjfv return; 1361283883Sjfv} 1362283883Sjfv 1363283883Sjfv/* 1364283883Sjfv * Requires adapter->max_frame_size to be set. 1365283883Sjfv */ 1366283883Sjfvstatic void 1367282289Serjixgbe_config_delay_values(struct adapter *adapter) 1368282289Serj{ 1369282289Serj struct ixgbe_hw *hw = &adapter->hw; 1370282289Serj u32 rxpb, frame, size, tmp; 1371280182Sjfv 1372282289Serj frame = adapter->max_frame_size; 1373282289Serj 1374282289Serj /* Calculate High Water */ 1375282289Serj switch (hw->mac.type) { 1376282289Serj case ixgbe_mac_X540: 1377282289Serj case ixgbe_mac_X550: 1378282289Serj case ixgbe_mac_X550EM_x: 1379282289Serj tmp = IXGBE_DV_X540(frame, frame); 1380282289Serj break; 1381282289Serj default: 1382282289Serj tmp = IXGBE_DV(frame, frame); 1383282289Serj break; 1384282289Serj } 1385282289Serj size = IXGBE_BT2KB(tmp); 1386282289Serj rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10; 1387282289Serj hw->fc.high_water[0] = rxpb - size; 1388282289Serj 1389282289Serj /* Now calculate Low Water */ 1390282289Serj switch (hw->mac.type) { 1391282289Serj case ixgbe_mac_X540: 1392282289Serj case ixgbe_mac_X550: 1393282289Serj case ixgbe_mac_X550EM_x: 1394282289Serj tmp = IXGBE_LOW_DV_X540(frame); 1395282289Serj break; 1396282289Serj default: 1397282289Serj tmp = IXGBE_LOW_DV(frame); 1398282289Serj break; 1399282289Serj } 1400282289Serj hw->fc.low_water[0] = IXGBE_BT2KB(tmp); 1401282289Serj 1402282289Serj hw->fc.requested_mode = adapter->fc; 1403282289Serj hw->fc.pause_time = IXGBE_FC_PAUSE; 1404282289Serj hw->fc.send_xon = TRUE; 1405282289Serj} 1406282289Serj 1407280182Sjfv/* 1408280182Sjfv** 1409280182Sjfv** MSIX Interrupt Handlers and Tasklets 1410280182Sjfv** 1411280182Sjfv*/ 1412280182Sjfv 1413280182Sjfvstatic inline void 1414280182Sjfvixgbe_enable_queue(struct adapter *adapter, u32 vector) 1415280182Sjfv{ 1416280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 1417280182Sjfv u64 queue = (u64)(1 << vector); 1418280182Sjfv u32 mask; 1419280182Sjfv 1420280182Sjfv if (hw->mac.type == ixgbe_mac_82598EB) { 1421280182Sjfv mask = (IXGBE_EIMS_RTX_QUEUE & queue); 1422280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); 1423280182Sjfv } else { 1424280182Sjfv mask = (queue & 0xFFFFFFFF); 1425280182Sjfv if (mask) 1426280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); 1427280182Sjfv mask = (queue >> 32); 1428280182Sjfv if (mask) 1429280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask); 1430280182Sjfv } 1431280182Sjfv} 1432280182Sjfv 1433280182Sjfvstatic inline void 1434280182Sjfvixgbe_disable_queue(struct adapter *adapter, u32 vector) 1435280182Sjfv{ 1436280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 1437280182Sjfv u64 queue = (u64)(1 << vector); 1438280182Sjfv u32 mask; 1439280182Sjfv 1440280182Sjfv if (hw->mac.type == ixgbe_mac_82598EB) { 1441280182Sjfv mask = (IXGBE_EIMS_RTX_QUEUE & queue); 1442280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask); 1443280182Sjfv } else { 1444280182Sjfv mask = (queue & 0xFFFFFFFF); 1445280182Sjfv if (mask) 1446280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask); 1447280182Sjfv mask = (queue >> 32); 1448280182Sjfv if (mask) 1449280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask); 1450280182Sjfv } 1451280182Sjfv} 1452280182Sjfv 1453280182Sjfvstatic void 1454280182Sjfvixgbe_handle_que(void *context, int pending) 1455280182Sjfv{ 1456280182Sjfv struct ix_queue *que = context; 1457280182Sjfv struct adapter *adapter = que->adapter; 1458280182Sjfv struct tx_ring *txr = que->txr; 1459280182Sjfv struct ifnet *ifp = adapter->ifp; 1460280182Sjfv 1461280182Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1462283883Sjfv ixgbe_rxeof(que); 1463280182Sjfv IXGBE_TX_LOCK(txr); 1464280182Sjfv ixgbe_txeof(txr); 1465280182Sjfv#ifndef IXGBE_LEGACY_TX 1466280182Sjfv if (!drbr_empty(ifp, txr->br)) 1467280182Sjfv ixgbe_mq_start_locked(ifp, txr); 1468280182Sjfv#else 1469280182Sjfv if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1470280182Sjfv ixgbe_start_locked(txr, ifp); 1471280182Sjfv#endif 1472280182Sjfv IXGBE_TX_UNLOCK(txr); 1473280182Sjfv } 1474280182Sjfv 1475280182Sjfv /* Reenable this interrupt */ 1476280182Sjfv if (que->res != NULL) 1477280182Sjfv ixgbe_enable_queue(adapter, que->msix); 1478280182Sjfv else 1479280182Sjfv ixgbe_enable_intr(adapter); 1480280182Sjfv return; 1481280182Sjfv} 1482280182Sjfv 1483280182Sjfv 1484280182Sjfv/********************************************************************* 1485280182Sjfv * 1486280182Sjfv * Legacy Interrupt Service routine 1487280182Sjfv * 1488280182Sjfv **********************************************************************/ 1489280182Sjfv 1490280182Sjfvstatic void 1491280182Sjfvixgbe_legacy_irq(void *arg) 1492280182Sjfv{ 1493280182Sjfv struct ix_queue *que = arg; 1494280182Sjfv struct adapter *adapter = que->adapter; 1495280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 1496280182Sjfv struct ifnet *ifp = adapter->ifp; 1497280182Sjfv struct tx_ring *txr = adapter->tx_rings; 1498280182Sjfv bool more; 1499280182Sjfv u32 reg_eicr; 1500280182Sjfv 1501280182Sjfv 1502280182Sjfv reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR); 1503280182Sjfv 1504280182Sjfv ++que->irqs; 1505280182Sjfv if (reg_eicr == 0) { 1506280182Sjfv ixgbe_enable_intr(adapter); 1507280182Sjfv return; 1508280182Sjfv } 1509280182Sjfv 1510280182Sjfv more = ixgbe_rxeof(que); 1511280182Sjfv 1512280182Sjfv IXGBE_TX_LOCK(txr); 1513280182Sjfv ixgbe_txeof(txr); 1514280182Sjfv#ifdef IXGBE_LEGACY_TX 1515280182Sjfv if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1516280182Sjfv ixgbe_start_locked(txr, ifp); 1517280182Sjfv#else 1518280182Sjfv if (!drbr_empty(ifp, txr->br)) 1519280182Sjfv ixgbe_mq_start_locked(ifp, txr); 1520280182Sjfv#endif 1521280182Sjfv IXGBE_TX_UNLOCK(txr); 1522280182Sjfv 1523280182Sjfv /* Check for fan failure */ 1524283883Sjfv if ((hw->device_id == IXGBE_DEV_ID_82598AT) && 1525283883Sjfv (reg_eicr & IXGBE_EICR_GPI_SDP1)) { 1526280182Sjfv device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! " 1527280182Sjfv "REPLACE IMMEDIATELY!!\n"); 1528280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 1529280182Sjfv } 1530280182Sjfv 1531280182Sjfv /* Link status change */ 1532280182Sjfv if (reg_eicr & IXGBE_EICR_LSC) 1533280182Sjfv taskqueue_enqueue(adapter->tq, &adapter->link_task); 1534280182Sjfv 1535282289Serj /* External PHY interrupt */ 1536282289Serj if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T && 1537282289Serj (reg_eicr & IXGBE_EICR_GPI_SDP0_X540)) 1538282289Serj taskqueue_enqueue(adapter->tq, &adapter->phy_task); 1539282289Serj 1540280182Sjfv if (more) 1541280182Sjfv taskqueue_enqueue(que->tq, &que->que_task); 1542280182Sjfv else 1543280182Sjfv ixgbe_enable_intr(adapter); 1544280182Sjfv return; 1545280182Sjfv} 1546280182Sjfv 1547280182Sjfv 1548280182Sjfv/********************************************************************* 1549280182Sjfv * 1550280182Sjfv * MSIX Queue Interrupt Service routine 1551280182Sjfv * 1552280182Sjfv **********************************************************************/ 1553280182Sjfvvoid 1554280182Sjfvixgbe_msix_que(void *arg) 1555280182Sjfv{ 1556280182Sjfv struct ix_queue *que = arg; 1557280182Sjfv struct adapter *adapter = que->adapter; 1558280182Sjfv struct ifnet *ifp = adapter->ifp; 1559280182Sjfv struct tx_ring *txr = que->txr; 1560280182Sjfv struct rx_ring *rxr = que->rxr; 1561280182Sjfv bool more; 1562280182Sjfv u32 newitr = 0; 1563280182Sjfv 1564283883Sjfv 1565280182Sjfv /* Protect against spurious interrupts */ 1566280182Sjfv if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1567280182Sjfv return; 1568280182Sjfv 1569280182Sjfv ixgbe_disable_queue(adapter, que->msix); 1570280182Sjfv ++que->irqs; 1571280182Sjfv 1572280182Sjfv more = ixgbe_rxeof(que); 1573280182Sjfv 1574280182Sjfv IXGBE_TX_LOCK(txr); 1575280182Sjfv ixgbe_txeof(txr); 1576280182Sjfv#ifdef IXGBE_LEGACY_TX 1577280182Sjfv if (!IFQ_DRV_IS_EMPTY(ifp->if_snd)) 1578280182Sjfv ixgbe_start_locked(txr, ifp); 1579280182Sjfv#else 1580280182Sjfv if (!drbr_empty(ifp, txr->br)) 1581280182Sjfv ixgbe_mq_start_locked(ifp, txr); 1582280182Sjfv#endif 1583280182Sjfv IXGBE_TX_UNLOCK(txr); 1584280182Sjfv 1585280182Sjfv /* Do AIM now? */ 1586280182Sjfv 1587294795Ssmh if (adapter->enable_aim == FALSE) 1588280182Sjfv goto no_calc; 1589280182Sjfv /* 1590280182Sjfv ** Do Adaptive Interrupt Moderation: 1591280182Sjfv ** - Write out last calculated setting 1592280182Sjfv ** - Calculate based on average size over 1593280182Sjfv ** the last interval. 1594280182Sjfv */ 1595280182Sjfv if (que->eitr_setting) 1596280182Sjfv IXGBE_WRITE_REG(&adapter->hw, 1597280182Sjfv IXGBE_EITR(que->msix), que->eitr_setting); 1598280182Sjfv 1599280182Sjfv que->eitr_setting = 0; 1600280182Sjfv 1601280182Sjfv /* Idle, do nothing */ 1602280182Sjfv if ((txr->bytes == 0) && (rxr->bytes == 0)) 1603280182Sjfv goto no_calc; 1604280182Sjfv 1605280182Sjfv if ((txr->bytes) && (txr->packets)) 1606280182Sjfv newitr = txr->bytes/txr->packets; 1607280182Sjfv if ((rxr->bytes) && (rxr->packets)) 1608280182Sjfv newitr = max(newitr, 1609280182Sjfv (rxr->bytes / rxr->packets)); 1610280182Sjfv newitr += 24; /* account for hardware frame, crc */ 1611280182Sjfv 1612280182Sjfv /* set an upper boundary */ 1613280182Sjfv newitr = min(newitr, 3000); 1614280182Sjfv 1615280182Sjfv /* Be nice to the mid range */ 1616280182Sjfv if ((newitr > 300) && (newitr < 1200)) 1617280182Sjfv newitr = (newitr / 3); 1618280182Sjfv else 1619280182Sjfv newitr = (newitr / 2); 1620280182Sjfv 1621280182Sjfv if (adapter->hw.mac.type == ixgbe_mac_82598EB) 1622280182Sjfv newitr |= newitr << 16; 1623280182Sjfv else 1624280182Sjfv newitr |= IXGBE_EITR_CNT_WDIS; 1625280182Sjfv 1626280182Sjfv /* save for next interrupt */ 1627280182Sjfv que->eitr_setting = newitr; 1628280182Sjfv 1629280182Sjfv /* Reset state */ 1630280182Sjfv txr->bytes = 0; 1631280182Sjfv txr->packets = 0; 1632280182Sjfv rxr->bytes = 0; 1633280182Sjfv rxr->packets = 0; 1634280182Sjfv 1635280182Sjfvno_calc: 1636280182Sjfv if (more) 1637280182Sjfv taskqueue_enqueue(que->tq, &que->que_task); 1638280182Sjfv else 1639280182Sjfv ixgbe_enable_queue(adapter, que->msix); 1640280182Sjfv return; 1641280182Sjfv} 1642280182Sjfv 1643280182Sjfv 1644280182Sjfvstatic void 1645280182Sjfvixgbe_msix_link(void *arg) 1646280182Sjfv{ 1647280182Sjfv struct adapter *adapter = arg; 1648280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 1649282289Serj u32 reg_eicr, mod_mask; 1650280182Sjfv 1651282289Serj ++adapter->link_irq; 1652280182Sjfv 1653292674Ssbruno /* Pause other interrupts */ 1654292674Ssbruno IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER); 1655292674Ssbruno 1656280182Sjfv /* First get the cause */ 1657280182Sjfv reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICS); 1658280182Sjfv /* Be sure the queue bits are not cleared */ 1659280182Sjfv reg_eicr &= ~IXGBE_EICR_RTX_QUEUE; 1660280182Sjfv /* Clear interrupt with write */ 1661280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EICR, reg_eicr); 1662280182Sjfv 1663280182Sjfv /* Link status change */ 1664292674Ssbruno if (reg_eicr & IXGBE_EICR_LSC) { 1665292674Ssbruno IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); 1666280182Sjfv taskqueue_enqueue(adapter->tq, &adapter->link_task); 1667292674Ssbruno } 1668280182Sjfv 1669280182Sjfv if (adapter->hw.mac.type != ixgbe_mac_82598EB) { 1670280182Sjfv#ifdef IXGBE_FDIR 1671280182Sjfv if (reg_eicr & IXGBE_EICR_FLOW_DIR) { 1672280182Sjfv /* This is probably overkill :) */ 1673280182Sjfv if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1)) 1674280182Sjfv return; 1675280182Sjfv /* Disable the interrupt */ 1676280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR); 1677280182Sjfv taskqueue_enqueue(adapter->tq, &adapter->fdir_task); 1678280182Sjfv } else 1679280182Sjfv#endif 1680280182Sjfv if (reg_eicr & IXGBE_EICR_ECC) { 1681292674Ssbruno device_printf(adapter->dev, "CRITICAL: ECC ERROR!! " 1682280182Sjfv "Please Reboot!!\n"); 1683280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC); 1684282289Serj } 1685280182Sjfv 1686282289Serj /* Check for over temp condition */ 1687282289Serj if (reg_eicr & IXGBE_EICR_TS) { 1688292674Ssbruno device_printf(adapter->dev, "CRITICAL: OVER TEMP!! " 1689282289Serj "PHY IS SHUT DOWN!!\n"); 1690282289Serj device_printf(adapter->dev, "System shutdown required!\n"); 1691282289Serj IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS); 1692280182Sjfv } 1693283883Sjfv#ifdef PCI_IOV 1694283883Sjfv if (reg_eicr & IXGBE_EICR_MAILBOX) 1695283883Sjfv taskqueue_enqueue(adapter->tq, &adapter->mbx_task); 1696283883Sjfv#endif 1697282289Serj } 1698280182Sjfv 1699282289Serj /* Pluggable optics-related interrupt */ 1700282289Serj if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) 1701282289Serj mod_mask = IXGBE_EICR_GPI_SDP0_X540; 1702282289Serj else 1703282289Serj mod_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); 1704282289Serj 1705282289Serj if (ixgbe_is_sfp(hw)) { 1706282289Serj if (reg_eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw)) { 1707282289Serj IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); 1708282289Serj taskqueue_enqueue(adapter->tq, &adapter->msf_task); 1709282289Serj } else if (reg_eicr & mod_mask) { 1710282289Serj IXGBE_WRITE_REG(hw, IXGBE_EICR, mod_mask); 1711282289Serj taskqueue_enqueue(adapter->tq, &adapter->mod_task); 1712282289Serj } 1713282289Serj } 1714282289Serj 1715280182Sjfv /* Check for fan failure */ 1716280182Sjfv if ((hw->device_id == IXGBE_DEV_ID_82598AT) && 1717282289Serj (reg_eicr & IXGBE_EICR_GPI_SDP1)) { 1718282289Serj IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1); 1719280182Sjfv device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! " 1720280182Sjfv "REPLACE IMMEDIATELY!!\n"); 1721280182Sjfv } 1722280182Sjfv 1723282289Serj /* External PHY interrupt */ 1724282289Serj if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T && 1725282289Serj (reg_eicr & IXGBE_EICR_GPI_SDP0_X540)) { 1726282289Serj IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540); 1727282289Serj taskqueue_enqueue(adapter->tq, &adapter->phy_task); 1728280182Sjfv } 1729280182Sjfv 1730292674Ssbruno /* Re-enable other interrupts */ 1731280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); 1732280182Sjfv return; 1733280182Sjfv} 1734280182Sjfv 1735280182Sjfv/********************************************************************* 1736280182Sjfv * 1737280182Sjfv * Media Ioctl callback 1738280182Sjfv * 1739280182Sjfv * This routine is called whenever the user queries the status of 1740280182Sjfv * the interface using ifconfig. 1741280182Sjfv * 1742280182Sjfv **********************************************************************/ 1743280182Sjfvstatic void 1744280182Sjfvixgbe_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) 1745280182Sjfv{ 1746280182Sjfv struct adapter *adapter = ifp->if_softc; 1747280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 1748280182Sjfv int layer; 1749280182Sjfv 1750280182Sjfv INIT_DEBUGOUT("ixgbe_media_status: begin"); 1751280182Sjfv IXGBE_CORE_LOCK(adapter); 1752280182Sjfv ixgbe_update_link_status(adapter); 1753280182Sjfv 1754280182Sjfv ifmr->ifm_status = IFM_AVALID; 1755280182Sjfv ifmr->ifm_active = IFM_ETHER; 1756280182Sjfv 1757280182Sjfv if (!adapter->link_active) { 1758280182Sjfv IXGBE_CORE_UNLOCK(adapter); 1759280182Sjfv return; 1760280182Sjfv } 1761280182Sjfv 1762280182Sjfv ifmr->ifm_status |= IFM_ACTIVE; 1763283883Sjfv layer = adapter->phy_layer; 1764280182Sjfv 1765280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T || 1766280182Sjfv layer & IXGBE_PHYSICAL_LAYER_1000BASE_T || 1767280182Sjfv layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) 1768280182Sjfv switch (adapter->link_speed) { 1769280182Sjfv case IXGBE_LINK_SPEED_10GB_FULL: 1770280182Sjfv ifmr->ifm_active |= IFM_10G_T | IFM_FDX; 1771280182Sjfv break; 1772280182Sjfv case IXGBE_LINK_SPEED_1GB_FULL: 1773280182Sjfv ifmr->ifm_active |= IFM_1000_T | IFM_FDX; 1774280182Sjfv break; 1775280182Sjfv case IXGBE_LINK_SPEED_100_FULL: 1776280182Sjfv ifmr->ifm_active |= IFM_100_TX | IFM_FDX; 1777280182Sjfv break; 1778280182Sjfv } 1779280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || 1780280182Sjfv layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) 1781280182Sjfv switch (adapter->link_speed) { 1782280182Sjfv case IXGBE_LINK_SPEED_10GB_FULL: 1783280182Sjfv ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX; 1784280182Sjfv break; 1785280182Sjfv } 1786280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) 1787280182Sjfv switch (adapter->link_speed) { 1788280182Sjfv case IXGBE_LINK_SPEED_10GB_FULL: 1789280182Sjfv ifmr->ifm_active |= IFM_10G_LR | IFM_FDX; 1790280182Sjfv break; 1791280182Sjfv case IXGBE_LINK_SPEED_1GB_FULL: 1792280182Sjfv ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; 1793280182Sjfv break; 1794280182Sjfv } 1795280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM) 1796280182Sjfv switch (adapter->link_speed) { 1797280182Sjfv case IXGBE_LINK_SPEED_10GB_FULL: 1798280182Sjfv ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX; 1799280182Sjfv break; 1800280182Sjfv case IXGBE_LINK_SPEED_1GB_FULL: 1801280182Sjfv ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; 1802280182Sjfv break; 1803280182Sjfv } 1804280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR || 1805280182Sjfv layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) 1806280182Sjfv switch (adapter->link_speed) { 1807280182Sjfv case IXGBE_LINK_SPEED_10GB_FULL: 1808280182Sjfv ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; 1809280182Sjfv break; 1810280182Sjfv case IXGBE_LINK_SPEED_1GB_FULL: 1811280182Sjfv ifmr->ifm_active |= IFM_1000_SX | IFM_FDX; 1812280182Sjfv break; 1813280182Sjfv } 1814280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) 1815280182Sjfv switch (adapter->link_speed) { 1816280182Sjfv case IXGBE_LINK_SPEED_10GB_FULL: 1817280182Sjfv ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; 1818280182Sjfv break; 1819280182Sjfv } 1820280182Sjfv /* 1821280182Sjfv ** XXX: These need to use the proper media types once 1822280182Sjfv ** they're added. 1823280182Sjfv */ 1824292674Ssbruno#ifndef IFM_ETH_XTYPE 1825280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 1826280182Sjfv switch (adapter->link_speed) { 1827280182Sjfv case IXGBE_LINK_SPEED_10GB_FULL: 1828282289Serj ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; 1829280182Sjfv break; 1830282289Serj case IXGBE_LINK_SPEED_2_5GB_FULL: 1831282289Serj ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; 1832282289Serj break; 1833280182Sjfv case IXGBE_LINK_SPEED_1GB_FULL: 1834282289Serj ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; 1835280182Sjfv break; 1836280182Sjfv } 1837282289Serj else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 1838280182Sjfv || layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 1839280182Sjfv switch (adapter->link_speed) { 1840280182Sjfv case IXGBE_LINK_SPEED_10GB_FULL: 1841282289Serj ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; 1842280182Sjfv break; 1843282289Serj case IXGBE_LINK_SPEED_2_5GB_FULL: 1844282289Serj ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; 1845282289Serj break; 1846280182Sjfv case IXGBE_LINK_SPEED_1GB_FULL: 1847282289Serj ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; 1848280182Sjfv break; 1849280182Sjfv } 1850292674Ssbruno#else 1851292674Ssbruno if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 1852292674Ssbruno switch (adapter->link_speed) { 1853292674Ssbruno case IXGBE_LINK_SPEED_10GB_FULL: 1854292674Ssbruno ifmr->ifm_active |= IFM_10G_KR | IFM_FDX; 1855292674Ssbruno break; 1856292674Ssbruno case IXGBE_LINK_SPEED_2_5GB_FULL: 1857292674Ssbruno ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; 1858292674Ssbruno break; 1859292674Ssbruno case IXGBE_LINK_SPEED_1GB_FULL: 1860292674Ssbruno ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; 1861292674Ssbruno break; 1862292674Ssbruno } 1863292674Ssbruno else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 1864292674Ssbruno || layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 1865292674Ssbruno switch (adapter->link_speed) { 1866292674Ssbruno case IXGBE_LINK_SPEED_10GB_FULL: 1867292674Ssbruno ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX; 1868292674Ssbruno break; 1869292674Ssbruno case IXGBE_LINK_SPEED_2_5GB_FULL: 1870292674Ssbruno ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; 1871292674Ssbruno break; 1872292674Ssbruno case IXGBE_LINK_SPEED_1GB_FULL: 1873292674Ssbruno ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; 1874292674Ssbruno break; 1875292674Ssbruno } 1876292674Ssbruno#endif 1877280182Sjfv 1878280182Sjfv /* If nothing is recognized... */ 1879280182Sjfv if (IFM_SUBTYPE(ifmr->ifm_active) == 0) 1880280182Sjfv ifmr->ifm_active |= IFM_UNKNOWN; 1881280182Sjfv 1882280182Sjfv#if __FreeBSD_version >= 900025 1883282289Serj /* Display current flow control setting used on link */ 1884282289Serj if (hw->fc.current_mode == ixgbe_fc_rx_pause || 1885282289Serj hw->fc.current_mode == ixgbe_fc_full) 1886280182Sjfv ifmr->ifm_active |= IFM_ETH_RXPAUSE; 1887282289Serj if (hw->fc.current_mode == ixgbe_fc_tx_pause || 1888282289Serj hw->fc.current_mode == ixgbe_fc_full) 1889280182Sjfv ifmr->ifm_active |= IFM_ETH_TXPAUSE; 1890280182Sjfv#endif 1891280182Sjfv 1892280182Sjfv IXGBE_CORE_UNLOCK(adapter); 1893280182Sjfv 1894280182Sjfv return; 1895280182Sjfv} 1896280182Sjfv 1897280182Sjfv/********************************************************************* 1898280182Sjfv * 1899280182Sjfv * Media Ioctl callback 1900280182Sjfv * 1901280182Sjfv * This routine is called when the user changes speed/duplex using 1902280182Sjfv * media/mediopt option with ifconfig. 1903280182Sjfv * 1904280182Sjfv **********************************************************************/ 1905280182Sjfvstatic int 1906280182Sjfvixgbe_media_change(struct ifnet * ifp) 1907280182Sjfv{ 1908280182Sjfv struct adapter *adapter = ifp->if_softc; 1909280182Sjfv struct ifmedia *ifm = &adapter->media; 1910280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 1911280182Sjfv ixgbe_link_speed speed = 0; 1912280182Sjfv 1913280182Sjfv INIT_DEBUGOUT("ixgbe_media_change: begin"); 1914280182Sjfv 1915280182Sjfv if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 1916280182Sjfv return (EINVAL); 1917280182Sjfv 1918282289Serj if (hw->phy.media_type == ixgbe_media_type_backplane) 1919292674Ssbruno return (ENODEV); 1920282289Serj 1921280182Sjfv /* 1922280182Sjfv ** We don't actually need to check against the supported 1923280182Sjfv ** media types of the adapter; ifmedia will take care of 1924280182Sjfv ** that for us. 1925280182Sjfv */ 1926292674Ssbruno#ifndef IFM_ETH_XTYPE 1927280182Sjfv switch (IFM_SUBTYPE(ifm->ifm_media)) { 1928280182Sjfv case IFM_AUTO: 1929280182Sjfv case IFM_10G_T: 1930280182Sjfv speed |= IXGBE_LINK_SPEED_100_FULL; 1931280182Sjfv case IFM_10G_LRM: 1932282289Serj case IFM_10G_SR: /* KR, too */ 1933280182Sjfv case IFM_10G_LR: 1934282289Serj case IFM_10G_CX4: /* KX4 */ 1935280182Sjfv speed |= IXGBE_LINK_SPEED_1GB_FULL; 1936280182Sjfv case IFM_10G_TWINAX: 1937280182Sjfv speed |= IXGBE_LINK_SPEED_10GB_FULL; 1938280182Sjfv break; 1939280182Sjfv case IFM_1000_T: 1940280182Sjfv speed |= IXGBE_LINK_SPEED_100_FULL; 1941280182Sjfv case IFM_1000_LX: 1942280182Sjfv case IFM_1000_SX: 1943282289Serj case IFM_1000_CX: /* KX */ 1944280182Sjfv speed |= IXGBE_LINK_SPEED_1GB_FULL; 1945280182Sjfv break; 1946280182Sjfv case IFM_100_TX: 1947280182Sjfv speed |= IXGBE_LINK_SPEED_100_FULL; 1948280182Sjfv break; 1949280182Sjfv default: 1950280182Sjfv goto invalid; 1951280182Sjfv } 1952292674Ssbruno#else 1953292674Ssbruno switch (IFM_SUBTYPE(ifm->ifm_media)) { 1954292674Ssbruno case IFM_AUTO: 1955292674Ssbruno case IFM_10G_T: 1956292674Ssbruno speed |= IXGBE_LINK_SPEED_100_FULL; 1957292674Ssbruno case IFM_10G_LRM: 1958292674Ssbruno case IFM_10G_KR: 1959292674Ssbruno case IFM_10G_LR: 1960292674Ssbruno case IFM_10G_KX4: 1961292674Ssbruno speed |= IXGBE_LINK_SPEED_1GB_FULL; 1962292674Ssbruno case IFM_10G_TWINAX: 1963292674Ssbruno speed |= IXGBE_LINK_SPEED_10GB_FULL; 1964292674Ssbruno break; 1965292674Ssbruno case IFM_1000_T: 1966292674Ssbruno speed |= IXGBE_LINK_SPEED_100_FULL; 1967292674Ssbruno case IFM_1000_LX: 1968292674Ssbruno case IFM_1000_SX: 1969292674Ssbruno case IFM_1000_KX: 1970292674Ssbruno speed |= IXGBE_LINK_SPEED_1GB_FULL; 1971292674Ssbruno break; 1972292674Ssbruno case IFM_100_TX: 1973292674Ssbruno speed |= IXGBE_LINK_SPEED_100_FULL; 1974292674Ssbruno break; 1975292674Ssbruno default: 1976292674Ssbruno goto invalid; 1977292674Ssbruno } 1978292674Ssbruno#endif 1979280182Sjfv 1980280182Sjfv hw->mac.autotry_restart = TRUE; 1981280182Sjfv hw->mac.ops.setup_link(hw, speed, TRUE); 1982294578Ssmh if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) { 1983294578Ssmh adapter->advertise = 0; 1984294578Ssmh } else { 1985294578Ssmh if ((speed & IXGBE_LINK_SPEED_10GB_FULL) != 0) 1986294578Ssmh adapter->advertise |= 1 << 2; 1987294578Ssmh if ((speed & IXGBE_LINK_SPEED_1GB_FULL) != 0) 1988294578Ssmh adapter->advertise |= 1 << 1; 1989294578Ssmh if ((speed & IXGBE_LINK_SPEED_100_FULL) != 0) 1990294578Ssmh adapter->advertise |= 1 << 0; 1991294578Ssmh } 1992280182Sjfv 1993280182Sjfv return (0); 1994280182Sjfv 1995280182Sjfvinvalid: 1996282289Serj device_printf(adapter->dev, "Invalid media type!\n"); 1997280182Sjfv return (EINVAL); 1998280182Sjfv} 1999280182Sjfv 2000280182Sjfvstatic void 2001280182Sjfvixgbe_set_promisc(struct adapter *adapter) 2002280182Sjfv{ 2003280182Sjfv u_int32_t reg_rctl; 2004280182Sjfv struct ifnet *ifp = adapter->ifp; 2005280182Sjfv int mcnt = 0; 2006280182Sjfv 2007280182Sjfv reg_rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); 2008280182Sjfv reg_rctl &= (~IXGBE_FCTRL_UPE); 2009280182Sjfv if (ifp->if_flags & IFF_ALLMULTI) 2010280182Sjfv mcnt = MAX_NUM_MULTICAST_ADDRESSES; 2011280182Sjfv else { 2012280182Sjfv struct ifmultiaddr *ifma; 2013280182Sjfv#if __FreeBSD_version < 800000 2014280182Sjfv IF_ADDR_LOCK(ifp); 2015280182Sjfv#else 2016280182Sjfv if_maddr_rlock(ifp); 2017280182Sjfv#endif 2018280182Sjfv TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 2019280182Sjfv if (ifma->ifma_addr->sa_family != AF_LINK) 2020280182Sjfv continue; 2021280182Sjfv if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) 2022280182Sjfv break; 2023280182Sjfv mcnt++; 2024280182Sjfv } 2025280182Sjfv#if __FreeBSD_version < 800000 2026280182Sjfv IF_ADDR_UNLOCK(ifp); 2027280182Sjfv#else 2028280182Sjfv if_maddr_runlock(ifp); 2029280182Sjfv#endif 2030280182Sjfv } 2031280182Sjfv if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) 2032280182Sjfv reg_rctl &= (~IXGBE_FCTRL_MPE); 2033280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl); 2034280182Sjfv 2035280182Sjfv if (ifp->if_flags & IFF_PROMISC) { 2036280182Sjfv reg_rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 2037280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl); 2038280182Sjfv } else if (ifp->if_flags & IFF_ALLMULTI) { 2039280182Sjfv reg_rctl |= IXGBE_FCTRL_MPE; 2040280182Sjfv reg_rctl &= ~IXGBE_FCTRL_UPE; 2041280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl); 2042280182Sjfv } 2043280182Sjfv return; 2044280182Sjfv} 2045280182Sjfv 2046280182Sjfv 2047280182Sjfv/********************************************************************* 2048280182Sjfv * Multicast Update 2049280182Sjfv * 2050280182Sjfv * This routine is called whenever multicast address list is updated. 2051280182Sjfv * 2052280182Sjfv **********************************************************************/ 2053280182Sjfv#define IXGBE_RAR_ENTRIES 16 2054280182Sjfv 2055280182Sjfvstatic void 2056280182Sjfvixgbe_set_multi(struct adapter *adapter) 2057280182Sjfv{ 2058283883Sjfv u32 fctrl; 2059283883Sjfv u8 *update_ptr; 2060283883Sjfv struct ifmultiaddr *ifma; 2061283883Sjfv struct ixgbe_mc_addr *mta; 2062283883Sjfv int mcnt = 0; 2063283883Sjfv struct ifnet *ifp = adapter->ifp; 2064280182Sjfv 2065280182Sjfv IOCTL_DEBUGOUT("ixgbe_set_multi: begin"); 2066280182Sjfv 2067280182Sjfv mta = adapter->mta; 2068283883Sjfv bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES); 2069280182Sjfv 2070280182Sjfv#if __FreeBSD_version < 800000 2071280182Sjfv IF_ADDR_LOCK(ifp); 2072280182Sjfv#else 2073280182Sjfv if_maddr_rlock(ifp); 2074280182Sjfv#endif 2075280182Sjfv TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 2076280182Sjfv if (ifma->ifma_addr->sa_family != AF_LINK) 2077280182Sjfv continue; 2078280182Sjfv if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) 2079280182Sjfv break; 2080280182Sjfv bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr), 2081283883Sjfv mta[mcnt].addr, IXGBE_ETH_LENGTH_OF_ADDRESS); 2082283883Sjfv mta[mcnt].vmdq = adapter->pool; 2083280182Sjfv mcnt++; 2084280182Sjfv } 2085280182Sjfv#if __FreeBSD_version < 800000 2086280182Sjfv IF_ADDR_UNLOCK(ifp); 2087280182Sjfv#else 2088280182Sjfv if_maddr_runlock(ifp); 2089280182Sjfv#endif 2090280182Sjfv 2091280182Sjfv fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); 2092280182Sjfv fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 2093280182Sjfv if (ifp->if_flags & IFF_PROMISC) 2094280182Sjfv fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 2095280182Sjfv else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES || 2096280182Sjfv ifp->if_flags & IFF_ALLMULTI) { 2097280182Sjfv fctrl |= IXGBE_FCTRL_MPE; 2098280182Sjfv fctrl &= ~IXGBE_FCTRL_UPE; 2099280182Sjfv } else 2100280182Sjfv fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 2101280182Sjfv 2102280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl); 2103280182Sjfv 2104280182Sjfv if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) { 2105283883Sjfv update_ptr = (u8 *)mta; 2106280182Sjfv ixgbe_update_mc_addr_list(&adapter->hw, 2107280182Sjfv update_ptr, mcnt, ixgbe_mc_array_itr, TRUE); 2108280182Sjfv } 2109280182Sjfv 2110280182Sjfv return; 2111280182Sjfv} 2112280182Sjfv 2113280182Sjfv/* 2114280182Sjfv * This is an iterator function now needed by the multicast 2115280182Sjfv * shared code. It simply feeds the shared code routine the 2116280182Sjfv * addresses in the array of ixgbe_set_multi() one by one. 2117280182Sjfv */ 2118280182Sjfvstatic u8 * 2119280182Sjfvixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq) 2120280182Sjfv{ 2121283883Sjfv struct ixgbe_mc_addr *mta; 2122280182Sjfv 2123283883Sjfv mta = (struct ixgbe_mc_addr *)*update_ptr; 2124283883Sjfv *vmdq = mta->vmdq; 2125283883Sjfv 2126297793Spfg *update_ptr = (u8*)(mta + 1); 2127283883Sjfv return (mta->addr); 2128280182Sjfv} 2129280182Sjfv 2130280182Sjfv 2131280182Sjfv/********************************************************************* 2132280182Sjfv * Timer routine 2133280182Sjfv * 2134280182Sjfv * This routine checks for link status,updates statistics, 2135280182Sjfv * and runs the watchdog check. 2136280182Sjfv * 2137280182Sjfv **********************************************************************/ 2138280182Sjfv 2139280182Sjfvstatic void 2140280182Sjfvixgbe_local_timer(void *arg) 2141280182Sjfv{ 2142280182Sjfv struct adapter *adapter = arg; 2143280182Sjfv device_t dev = adapter->dev; 2144280182Sjfv struct ix_queue *que = adapter->queues; 2145280182Sjfv u64 queues = 0; 2146280182Sjfv int hung = 0; 2147280182Sjfv 2148280182Sjfv mtx_assert(&adapter->core_mtx, MA_OWNED); 2149280182Sjfv 2150280182Sjfv /* Check for pluggable optics */ 2151280182Sjfv if (adapter->sfp_probe) 2152280182Sjfv if (!ixgbe_sfp_probe(adapter)) 2153280182Sjfv goto out; /* Nothing to do */ 2154280182Sjfv 2155280182Sjfv ixgbe_update_link_status(adapter); 2156280182Sjfv ixgbe_update_stats_counters(adapter); 2157280182Sjfv 2158280182Sjfv /* 2159280182Sjfv ** Check the TX queues status 2160280182Sjfv ** - mark hung queues so we don't schedule on them 2161280182Sjfv ** - watchdog only if all queues show hung 2162280182Sjfv */ 2163280182Sjfv for (int i = 0; i < adapter->num_queues; i++, que++) { 2164280182Sjfv /* Keep track of queues with work for soft irq */ 2165280182Sjfv if (que->txr->busy) 2166280182Sjfv queues |= ((u64)1 << que->me); 2167280182Sjfv /* 2168280182Sjfv ** Each time txeof runs without cleaning, but there 2169280182Sjfv ** are uncleaned descriptors it increments busy. If 2170280182Sjfv ** we get to the MAX we declare it hung. 2171280182Sjfv */ 2172280182Sjfv if (que->busy == IXGBE_QUEUE_HUNG) { 2173280182Sjfv ++hung; 2174280182Sjfv /* Mark the queue as inactive */ 2175280182Sjfv adapter->active_queues &= ~((u64)1 << que->me); 2176280182Sjfv continue; 2177280182Sjfv } else { 2178280182Sjfv /* Check if we've come back from hung */ 2179280182Sjfv if ((adapter->active_queues & ((u64)1 << que->me)) == 0) 2180280182Sjfv adapter->active_queues |= ((u64)1 << que->me); 2181280182Sjfv } 2182280182Sjfv if (que->busy >= IXGBE_MAX_TX_BUSY) { 2183280182Sjfv device_printf(dev,"Warning queue %d " 2184280182Sjfv "appears to be hung!\n", i); 2185280182Sjfv que->txr->busy = IXGBE_QUEUE_HUNG; 2186280182Sjfv ++hung; 2187280182Sjfv } 2188280182Sjfv 2189280182Sjfv } 2190280182Sjfv 2191280182Sjfv /* Only truly watchdog if all queues show hung */ 2192280182Sjfv if (hung == adapter->num_queues) 2193280182Sjfv goto watchdog; 2194280182Sjfv else if (queues != 0) { /* Force an IRQ on queues with work */ 2195280182Sjfv ixgbe_rearm_queues(adapter, queues); 2196280182Sjfv } 2197280182Sjfv 2198280182Sjfvout: 2199280182Sjfv callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter); 2200280182Sjfv return; 2201280182Sjfv 2202280182Sjfvwatchdog: 2203280182Sjfv device_printf(adapter->dev, "Watchdog timeout -- resetting\n"); 2204280182Sjfv adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 2205280182Sjfv adapter->watchdog_events++; 2206280182Sjfv ixgbe_init_locked(adapter); 2207280182Sjfv} 2208280182Sjfv 2209283883Sjfv 2210280182Sjfv/* 2211280182Sjfv** Note: this routine updates the OS on the link state 2212280182Sjfv** the real check of the hardware only happens with 2213280182Sjfv** a link interrupt. 2214280182Sjfv*/ 2215280182Sjfvstatic void 2216280182Sjfvixgbe_update_link_status(struct adapter *adapter) 2217280182Sjfv{ 2218280182Sjfv struct ifnet *ifp = adapter->ifp; 2219280182Sjfv device_t dev = adapter->dev; 2220280182Sjfv 2221280182Sjfv if (adapter->link_up){ 2222280182Sjfv if (adapter->link_active == FALSE) { 2223280182Sjfv if (bootverbose) 2224280182Sjfv device_printf(dev,"Link is up %d Gbps %s \n", 2225280182Sjfv ((adapter->link_speed == 128)? 10:1), 2226280182Sjfv "Full Duplex"); 2227280182Sjfv adapter->link_active = TRUE; 2228280182Sjfv /* Update any Flow Control changes */ 2229280182Sjfv ixgbe_fc_enable(&adapter->hw); 2230282289Serj /* Update DMA coalescing config */ 2231282289Serj ixgbe_config_dmac(adapter); 2232280182Sjfv if_link_state_change(ifp, LINK_STATE_UP); 2233283883Sjfv#ifdef PCI_IOV 2234283883Sjfv ixgbe_ping_all_vfs(adapter); 2235283883Sjfv#endif 2236280182Sjfv } 2237280182Sjfv } else { /* Link down */ 2238280182Sjfv if (adapter->link_active == TRUE) { 2239280182Sjfv if (bootverbose) 2240280182Sjfv device_printf(dev,"Link is Down\n"); 2241280182Sjfv if_link_state_change(ifp, LINK_STATE_DOWN); 2242280182Sjfv adapter->link_active = FALSE; 2243283883Sjfv#ifdef PCI_IOV 2244283883Sjfv ixgbe_ping_all_vfs(adapter); 2245283883Sjfv#endif 2246280182Sjfv } 2247280182Sjfv } 2248280182Sjfv 2249280182Sjfv return; 2250280182Sjfv} 2251280182Sjfv 2252280182Sjfv 2253280182Sjfv/********************************************************************* 2254280182Sjfv * 2255280182Sjfv * This routine disables all traffic on the adapter by issuing a 2256280182Sjfv * global reset on the MAC and deallocates TX/RX buffers. 2257280182Sjfv * 2258280182Sjfv **********************************************************************/ 2259280182Sjfv 2260280182Sjfvstatic void 2261280182Sjfvixgbe_stop(void *arg) 2262280182Sjfv{ 2263280182Sjfv struct ifnet *ifp; 2264280182Sjfv struct adapter *adapter = arg; 2265280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 2266280182Sjfv ifp = adapter->ifp; 2267280182Sjfv 2268280182Sjfv mtx_assert(&adapter->core_mtx, MA_OWNED); 2269280182Sjfv 2270280182Sjfv INIT_DEBUGOUT("ixgbe_stop: begin\n"); 2271280182Sjfv ixgbe_disable_intr(adapter); 2272280182Sjfv callout_stop(&adapter->timer); 2273280182Sjfv 2274280182Sjfv /* Let the stack know...*/ 2275280182Sjfv ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 2276280182Sjfv 2277280182Sjfv ixgbe_reset_hw(hw); 2278280182Sjfv hw->adapter_stopped = FALSE; 2279280182Sjfv ixgbe_stop_adapter(hw); 2280280182Sjfv if (hw->mac.type == ixgbe_mac_82599EB) 2281280182Sjfv ixgbe_stop_mac_link_on_d3_82599(hw); 2282280182Sjfv /* Turn off the laser - noop with no optics */ 2283280182Sjfv ixgbe_disable_tx_laser(hw); 2284280182Sjfv 2285280182Sjfv /* Update the stack */ 2286280182Sjfv adapter->link_up = FALSE; 2287280182Sjfv ixgbe_update_link_status(adapter); 2288280182Sjfv 2289280182Sjfv /* reprogram the RAR[0] in case user changed it. */ 2290280182Sjfv ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV); 2291280182Sjfv 2292280182Sjfv return; 2293280182Sjfv} 2294280182Sjfv 2295280182Sjfv 2296280182Sjfv/********************************************************************* 2297280182Sjfv * 2298280182Sjfv * Determine hardware revision. 2299280182Sjfv * 2300280182Sjfv **********************************************************************/ 2301280182Sjfvstatic void 2302280182Sjfvixgbe_identify_hardware(struct adapter *adapter) 2303280182Sjfv{ 2304280182Sjfv device_t dev = adapter->dev; 2305280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 2306280182Sjfv 2307280182Sjfv /* Save off the information about this board */ 2308280182Sjfv hw->vendor_id = pci_get_vendor(dev); 2309280182Sjfv hw->device_id = pci_get_device(dev); 2310280182Sjfv hw->revision_id = pci_read_config(dev, PCIR_REVID, 1); 2311280182Sjfv hw->subsystem_vendor_id = 2312280182Sjfv pci_read_config(dev, PCIR_SUBVEND_0, 2); 2313280182Sjfv hw->subsystem_device_id = 2314280182Sjfv pci_read_config(dev, PCIR_SUBDEV_0, 2); 2315280182Sjfv 2316280182Sjfv /* 2317280182Sjfv ** Make sure BUSMASTER is set 2318280182Sjfv */ 2319280182Sjfv pci_enable_busmaster(dev); 2320280182Sjfv 2321280182Sjfv /* We need this here to set the num_segs below */ 2322280182Sjfv ixgbe_set_mac_type(hw); 2323280182Sjfv 2324282289Serj /* Pick up the 82599 settings */ 2325280182Sjfv if (hw->mac.type != ixgbe_mac_82598EB) { 2326280182Sjfv hw->phy.smart_speed = ixgbe_smart_speed; 2327280182Sjfv adapter->num_segs = IXGBE_82599_SCATTER; 2328280182Sjfv } else 2329280182Sjfv adapter->num_segs = IXGBE_82598_SCATTER; 2330280182Sjfv 2331280182Sjfv return; 2332280182Sjfv} 2333280182Sjfv 2334280182Sjfv/********************************************************************* 2335280182Sjfv * 2336280182Sjfv * Determine optic type 2337280182Sjfv * 2338280182Sjfv **********************************************************************/ 2339280182Sjfvstatic void 2340280182Sjfvixgbe_setup_optics(struct adapter *adapter) 2341280182Sjfv{ 2342280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 2343280182Sjfv int layer; 2344280182Sjfv 2345283883Sjfv layer = adapter->phy_layer = ixgbe_get_supported_physical_layer(hw); 2346280182Sjfv 2347280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) { 2348280182Sjfv adapter->optics = IFM_10G_T; 2349280182Sjfv return; 2350280182Sjfv } 2351280182Sjfv 2352280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) { 2353280182Sjfv adapter->optics = IFM_1000_T; 2354280182Sjfv return; 2355280182Sjfv } 2356280182Sjfv 2357280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) { 2358280182Sjfv adapter->optics = IFM_1000_SX; 2359280182Sjfv return; 2360280182Sjfv } 2361280182Sjfv 2362280182Sjfv if (layer & (IXGBE_PHYSICAL_LAYER_10GBASE_LR | 2363280182Sjfv IXGBE_PHYSICAL_LAYER_10GBASE_LRM)) { 2364280182Sjfv adapter->optics = IFM_10G_LR; 2365280182Sjfv return; 2366280182Sjfv } 2367280182Sjfv 2368280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) { 2369280182Sjfv adapter->optics = IFM_10G_SR; 2370280182Sjfv return; 2371280182Sjfv } 2372280182Sjfv 2373280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU) { 2374280182Sjfv adapter->optics = IFM_10G_TWINAX; 2375280182Sjfv return; 2376280182Sjfv } 2377280182Sjfv 2378280182Sjfv if (layer & (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 | 2379280182Sjfv IXGBE_PHYSICAL_LAYER_10GBASE_CX4)) { 2380280182Sjfv adapter->optics = IFM_10G_CX4; 2381280182Sjfv return; 2382280182Sjfv } 2383280182Sjfv 2384280182Sjfv /* If we get here just set the default */ 2385280182Sjfv adapter->optics = IFM_ETHER | IFM_AUTO; 2386280182Sjfv return; 2387280182Sjfv} 2388280182Sjfv 2389280182Sjfv/********************************************************************* 2390280182Sjfv * 2391280182Sjfv * Setup the Legacy or MSI Interrupt handler 2392280182Sjfv * 2393280182Sjfv **********************************************************************/ 2394280182Sjfvstatic int 2395280182Sjfvixgbe_allocate_legacy(struct adapter *adapter) 2396280182Sjfv{ 2397280182Sjfv device_t dev = adapter->dev; 2398280182Sjfv struct ix_queue *que = adapter->queues; 2399280182Sjfv#ifndef IXGBE_LEGACY_TX 2400280182Sjfv struct tx_ring *txr = adapter->tx_rings; 2401280182Sjfv#endif 2402280182Sjfv int error, rid = 0; 2403280182Sjfv 2404280182Sjfv /* MSI RID at 1 */ 2405280182Sjfv if (adapter->msix == 1) 2406280182Sjfv rid = 1; 2407280182Sjfv 2408280182Sjfv /* We allocate a single interrupt resource */ 2409280182Sjfv adapter->res = bus_alloc_resource_any(dev, 2410280182Sjfv SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); 2411280182Sjfv if (adapter->res == NULL) { 2412280182Sjfv device_printf(dev, "Unable to allocate bus resource: " 2413280182Sjfv "interrupt\n"); 2414280182Sjfv return (ENXIO); 2415280182Sjfv } 2416280182Sjfv 2417280182Sjfv /* 2418280182Sjfv * Try allocating a fast interrupt and the associated deferred 2419280182Sjfv * processing contexts. 2420280182Sjfv */ 2421280182Sjfv#ifndef IXGBE_LEGACY_TX 2422280182Sjfv TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr); 2423280182Sjfv#endif 2424280182Sjfv TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que); 2425280182Sjfv que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT, 2426280182Sjfv taskqueue_thread_enqueue, &que->tq); 2427280182Sjfv taskqueue_start_threads(&que->tq, 1, PI_NET, "%s ixq", 2428280182Sjfv device_get_nameunit(adapter->dev)); 2429280182Sjfv 2430280182Sjfv /* Tasklets for Link, SFP and Multispeed Fiber */ 2431280182Sjfv TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter); 2432280182Sjfv TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter); 2433280182Sjfv TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter); 2434282289Serj TASK_INIT(&adapter->phy_task, 0, ixgbe_handle_phy, adapter); 2435280182Sjfv#ifdef IXGBE_FDIR 2436280182Sjfv TASK_INIT(&adapter->fdir_task, 0, ixgbe_reinit_fdir, adapter); 2437280182Sjfv#endif 2438280182Sjfv adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT, 2439280182Sjfv taskqueue_thread_enqueue, &adapter->tq); 2440280182Sjfv taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq", 2441280182Sjfv device_get_nameunit(adapter->dev)); 2442280182Sjfv 2443280182Sjfv if ((error = bus_setup_intr(dev, adapter->res, 2444280182Sjfv INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_legacy_irq, 2445280182Sjfv que, &adapter->tag)) != 0) { 2446280182Sjfv device_printf(dev, "Failed to register fast interrupt " 2447280182Sjfv "handler: %d\n", error); 2448280182Sjfv taskqueue_free(que->tq); 2449280182Sjfv taskqueue_free(adapter->tq); 2450280182Sjfv que->tq = NULL; 2451280182Sjfv adapter->tq = NULL; 2452280182Sjfv return (error); 2453280182Sjfv } 2454280182Sjfv /* For simplicity in the handlers */ 2455280182Sjfv adapter->active_queues = IXGBE_EIMS_ENABLE_MASK; 2456280182Sjfv 2457280182Sjfv return (0); 2458280182Sjfv} 2459280182Sjfv 2460280182Sjfv 2461280182Sjfv/********************************************************************* 2462280182Sjfv * 2463280182Sjfv * Setup MSIX Interrupt resources and handlers 2464280182Sjfv * 2465280182Sjfv **********************************************************************/ 2466280182Sjfvstatic int 2467280182Sjfvixgbe_allocate_msix(struct adapter *adapter) 2468280182Sjfv{ 2469280182Sjfv device_t dev = adapter->dev; 2470280182Sjfv struct ix_queue *que = adapter->queues; 2471280182Sjfv struct tx_ring *txr = adapter->tx_rings; 2472280182Sjfv int error, rid, vector = 0; 2473280182Sjfv int cpu_id = 0; 2474280204Sadrian#ifdef RSS 2475280204Sadrian cpuset_t cpu_mask; 2476280204Sadrian#endif 2477280182Sjfv 2478280182Sjfv#ifdef RSS 2479280182Sjfv /* 2480280182Sjfv * If we're doing RSS, the number of queues needs to 2481280182Sjfv * match the number of RSS buckets that are configured. 2482280182Sjfv * 2483280182Sjfv * + If there's more queues than RSS buckets, we'll end 2484280182Sjfv * up with queues that get no traffic. 2485280182Sjfv * 2486280182Sjfv * + If there's more RSS buckets than queues, we'll end 2487280182Sjfv * up having multiple RSS buckets map to the same queue, 2488280182Sjfv * so there'll be some contention. 2489280182Sjfv */ 2490280182Sjfv if (adapter->num_queues != rss_getnumbuckets()) { 2491280182Sjfv device_printf(dev, 2492280182Sjfv "%s: number of queues (%d) != number of RSS buckets (%d)" 2493280182Sjfv "; performance will be impacted.\n", 2494280182Sjfv __func__, 2495280182Sjfv adapter->num_queues, 2496280182Sjfv rss_getnumbuckets()); 2497280182Sjfv } 2498280182Sjfv#endif 2499280182Sjfv 2500280182Sjfv for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) { 2501280182Sjfv rid = vector + 1; 2502280182Sjfv que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 2503280182Sjfv RF_SHAREABLE | RF_ACTIVE); 2504280182Sjfv if (que->res == NULL) { 2505280182Sjfv device_printf(dev,"Unable to allocate" 2506280182Sjfv " bus resource: que interrupt [%d]\n", vector); 2507280182Sjfv return (ENXIO); 2508280182Sjfv } 2509280182Sjfv /* Set the handler function */ 2510280182Sjfv error = bus_setup_intr(dev, que->res, 2511280182Sjfv INTR_TYPE_NET | INTR_MPSAFE, NULL, 2512280182Sjfv ixgbe_msix_que, que, &que->tag); 2513280182Sjfv if (error) { 2514280182Sjfv que->res = NULL; 2515280182Sjfv device_printf(dev, "Failed to register QUE handler"); 2516280182Sjfv return (error); 2517280182Sjfv } 2518280182Sjfv#if __FreeBSD_version >= 800504 2519292674Ssbruno bus_describe_intr(dev, que->res, que->tag, "q%d", i); 2520280182Sjfv#endif 2521280182Sjfv que->msix = vector; 2522280182Sjfv adapter->active_queues |= (u64)(1 << que->msix); 2523280182Sjfv#ifdef RSS 2524280182Sjfv /* 2525280182Sjfv * The queue ID is used as the RSS layer bucket ID. 2526280182Sjfv * We look up the queue ID -> RSS CPU ID and select 2527280182Sjfv * that. 2528280182Sjfv */ 2529280182Sjfv cpu_id = rss_getcpu(i % rss_getnumbuckets()); 2530280182Sjfv#else 2531280182Sjfv /* 2532280182Sjfv * Bind the msix vector, and thus the 2533280182Sjfv * rings to the corresponding cpu. 2534280182Sjfv * 2535280182Sjfv * This just happens to match the default RSS round-robin 2536280182Sjfv * bucket -> queue -> CPU allocation. 2537280182Sjfv */ 2538280182Sjfv if (adapter->num_queues > 1) 2539280182Sjfv cpu_id = i; 2540280182Sjfv#endif 2541280182Sjfv if (adapter->num_queues > 1) 2542280182Sjfv bus_bind_intr(dev, que->res, cpu_id); 2543283883Sjfv#ifdef IXGBE_DEBUG 2544280182Sjfv#ifdef RSS 2545280182Sjfv device_printf(dev, 2546280182Sjfv "Bound RSS bucket %d to CPU %d\n", 2547280182Sjfv i, cpu_id); 2548280182Sjfv#else 2549283883Sjfv device_printf(dev, 2550283883Sjfv "Bound queue %d to cpu %d\n", 2551283883Sjfv i, cpu_id); 2552280182Sjfv#endif 2553283883Sjfv#endif /* IXGBE_DEBUG */ 2554283883Sjfv 2555283883Sjfv 2556280182Sjfv#ifndef IXGBE_LEGACY_TX 2557280182Sjfv TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr); 2558280182Sjfv#endif 2559280182Sjfv TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que); 2560280182Sjfv que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT, 2561280182Sjfv taskqueue_thread_enqueue, &que->tq); 2562280182Sjfv#ifdef RSS 2563280204Sadrian CPU_SETOF(cpu_id, &cpu_mask); 2564280204Sadrian taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET, 2565280204Sadrian &cpu_mask, 2566280182Sjfv "%s (bucket %d)", 2567280182Sjfv device_get_nameunit(adapter->dev), 2568280182Sjfv cpu_id); 2569280182Sjfv#else 2570292674Ssbruno taskqueue_start_threads(&que->tq, 1, PI_NET, "%s:q%d", 2571292674Ssbruno device_get_nameunit(adapter->dev), i); 2572280182Sjfv#endif 2573280182Sjfv } 2574280182Sjfv 2575280182Sjfv /* and Link */ 2576280182Sjfv rid = vector + 1; 2577280182Sjfv adapter->res = bus_alloc_resource_any(dev, 2578280182Sjfv SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); 2579280182Sjfv if (!adapter->res) { 2580280182Sjfv device_printf(dev,"Unable to allocate" 2581280182Sjfv " bus resource: Link interrupt [%d]\n", rid); 2582280182Sjfv return (ENXIO); 2583280182Sjfv } 2584280182Sjfv /* Set the link handler function */ 2585280182Sjfv error = bus_setup_intr(dev, adapter->res, 2586280182Sjfv INTR_TYPE_NET | INTR_MPSAFE, NULL, 2587280182Sjfv ixgbe_msix_link, adapter, &adapter->tag); 2588280182Sjfv if (error) { 2589280182Sjfv adapter->res = NULL; 2590280182Sjfv device_printf(dev, "Failed to register LINK handler"); 2591280182Sjfv return (error); 2592280182Sjfv } 2593280182Sjfv#if __FreeBSD_version >= 800504 2594280182Sjfv bus_describe_intr(dev, adapter->res, adapter->tag, "link"); 2595280182Sjfv#endif 2596280182Sjfv adapter->vector = vector; 2597280182Sjfv /* Tasklets for Link, SFP and Multispeed Fiber */ 2598280182Sjfv TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter); 2599280182Sjfv TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter); 2600280182Sjfv TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter); 2601283883Sjfv#ifdef PCI_IOV 2602283883Sjfv TASK_INIT(&adapter->mbx_task, 0, ixgbe_handle_mbx, adapter); 2603283883Sjfv#endif 2604282289Serj TASK_INIT(&adapter->phy_task, 0, ixgbe_handle_phy, adapter); 2605280182Sjfv#ifdef IXGBE_FDIR 2606280182Sjfv TASK_INIT(&adapter->fdir_task, 0, ixgbe_reinit_fdir, adapter); 2607280182Sjfv#endif 2608280182Sjfv adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT, 2609280182Sjfv taskqueue_thread_enqueue, &adapter->tq); 2610280182Sjfv taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq", 2611280182Sjfv device_get_nameunit(adapter->dev)); 2612280182Sjfv 2613280182Sjfv return (0); 2614280182Sjfv} 2615280182Sjfv 2616280182Sjfv/* 2617280182Sjfv * Setup Either MSI/X or MSI 2618280182Sjfv */ 2619280182Sjfvstatic int 2620280182Sjfvixgbe_setup_msix(struct adapter *adapter) 2621280182Sjfv{ 2622280182Sjfv device_t dev = adapter->dev; 2623280182Sjfv int rid, want, queues, msgs; 2624280182Sjfv 2625280182Sjfv /* Override by tuneable */ 2626280182Sjfv if (ixgbe_enable_msix == 0) 2627280182Sjfv goto msi; 2628280182Sjfv 2629280182Sjfv /* First try MSI/X */ 2630280182Sjfv msgs = pci_msix_count(dev); 2631280182Sjfv if (msgs == 0) 2632280182Sjfv goto msi; 2633280182Sjfv rid = PCIR_BAR(MSIX_82598_BAR); 2634280182Sjfv adapter->msix_mem = bus_alloc_resource_any(dev, 2635280182Sjfv SYS_RES_MEMORY, &rid, RF_ACTIVE); 2636280182Sjfv if (adapter->msix_mem == NULL) { 2637280182Sjfv rid += 4; /* 82599 maps in higher BAR */ 2638280182Sjfv adapter->msix_mem = bus_alloc_resource_any(dev, 2639280182Sjfv SYS_RES_MEMORY, &rid, RF_ACTIVE); 2640280182Sjfv } 2641280182Sjfv if (adapter->msix_mem == NULL) { 2642280182Sjfv /* May not be enabled */ 2643280182Sjfv device_printf(adapter->dev, 2644280182Sjfv "Unable to map MSIX table \n"); 2645280182Sjfv goto msi; 2646280182Sjfv } 2647280182Sjfv 2648280182Sjfv /* Figure out a reasonable auto config value */ 2649292674Ssbruno queues = (mp_ncpus > (msgs - 1)) ? (msgs - 1) : mp_ncpus; 2650280182Sjfv 2651280182Sjfv#ifdef RSS 2652280182Sjfv /* If we're doing RSS, clamp at the number of RSS buckets */ 2653280182Sjfv if (queues > rss_getnumbuckets()) 2654280182Sjfv queues = rss_getnumbuckets(); 2655280182Sjfv#endif 2656280182Sjfv 2657280182Sjfv if (ixgbe_num_queues != 0) 2658280182Sjfv queues = ixgbe_num_queues; 2659292674Ssbruno /* Set max queues to 8 when autoconfiguring */ 2660292674Ssbruno else if ((ixgbe_num_queues == 0) && (queues > 8)) 2661292674Ssbruno queues = 8; 2662280182Sjfv 2663280182Sjfv /* reflect correct sysctl value */ 2664280182Sjfv ixgbe_num_queues = queues; 2665280182Sjfv 2666280182Sjfv /* 2667280182Sjfv ** Want one vector (RX/TX pair) per queue 2668280182Sjfv ** plus an additional for Link. 2669280182Sjfv */ 2670280182Sjfv want = queues + 1; 2671280182Sjfv if (msgs >= want) 2672280182Sjfv msgs = want; 2673280182Sjfv else { 2674280182Sjfv device_printf(adapter->dev, 2675280182Sjfv "MSIX Configuration Problem, " 2676280182Sjfv "%d vectors but %d queues wanted!\n", 2677280182Sjfv msgs, want); 2678280182Sjfv goto msi; 2679280182Sjfv } 2680280182Sjfv if ((pci_alloc_msix(dev, &msgs) == 0) && (msgs == want)) { 2681280182Sjfv device_printf(adapter->dev, 2682280182Sjfv "Using MSIX interrupts with %d vectors\n", msgs); 2683280182Sjfv adapter->num_queues = queues; 2684280182Sjfv return (msgs); 2685280182Sjfv } 2686280182Sjfv /* 2687280182Sjfv ** If MSIX alloc failed or provided us with 2688280182Sjfv ** less than needed, free and fall through to MSI 2689280182Sjfv */ 2690280182Sjfv pci_release_msi(dev); 2691280182Sjfv 2692280182Sjfvmsi: 2693280182Sjfv if (adapter->msix_mem != NULL) { 2694280182Sjfv bus_release_resource(dev, SYS_RES_MEMORY, 2695280182Sjfv rid, adapter->msix_mem); 2696280182Sjfv adapter->msix_mem = NULL; 2697280182Sjfv } 2698292674Ssbruno msgs = 1; 2699292674Ssbruno if (pci_alloc_msi(dev, &msgs) == 0) { 2700292674Ssbruno device_printf(adapter->dev, "Using an MSI interrupt\n"); 2701280182Sjfv return (msgs); 2702280182Sjfv } 2703292674Ssbruno device_printf(adapter->dev, "Using a Legacy interrupt\n"); 2704280182Sjfv return (0); 2705280182Sjfv} 2706280182Sjfv 2707280182Sjfv 2708280182Sjfvstatic int 2709280182Sjfvixgbe_allocate_pci_resources(struct adapter *adapter) 2710280182Sjfv{ 2711280182Sjfv int rid; 2712280182Sjfv device_t dev = adapter->dev; 2713280182Sjfv 2714280182Sjfv rid = PCIR_BAR(0); 2715280182Sjfv adapter->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 2716280182Sjfv &rid, RF_ACTIVE); 2717280182Sjfv 2718280182Sjfv if (!(adapter->pci_mem)) { 2719292674Ssbruno device_printf(dev, "Unable to allocate bus resource: memory\n"); 2720280182Sjfv return (ENXIO); 2721280182Sjfv } 2722280182Sjfv 2723292674Ssbruno /* Save bus_space values for READ/WRITE_REG macros */ 2724280182Sjfv adapter->osdep.mem_bus_space_tag = 2725280182Sjfv rman_get_bustag(adapter->pci_mem); 2726280182Sjfv adapter->osdep.mem_bus_space_handle = 2727280182Sjfv rman_get_bushandle(adapter->pci_mem); 2728292674Ssbruno /* Set hw values for shared code */ 2729280182Sjfv adapter->hw.hw_addr = (u8 *) &adapter->osdep.mem_bus_space_handle; 2730292674Ssbruno adapter->hw.back = adapter; 2731280182Sjfv 2732292674Ssbruno /* Default to 1 queue if MSI-X setup fails */ 2733280182Sjfv adapter->num_queues = 1; 2734280182Sjfv 2735280182Sjfv /* 2736292674Ssbruno ** Now setup MSI or MSI-X, should 2737280182Sjfv ** return us the number of supported 2738280182Sjfv ** vectors. (Will be 1 for MSI) 2739280182Sjfv */ 2740280182Sjfv adapter->msix = ixgbe_setup_msix(adapter); 2741280182Sjfv return (0); 2742280182Sjfv} 2743280182Sjfv 2744280182Sjfvstatic void 2745280182Sjfvixgbe_free_pci_resources(struct adapter * adapter) 2746280182Sjfv{ 2747280182Sjfv struct ix_queue *que = adapter->queues; 2748280182Sjfv device_t dev = adapter->dev; 2749280182Sjfv int rid, memrid; 2750280182Sjfv 2751280182Sjfv if (adapter->hw.mac.type == ixgbe_mac_82598EB) 2752280182Sjfv memrid = PCIR_BAR(MSIX_82598_BAR); 2753280182Sjfv else 2754280182Sjfv memrid = PCIR_BAR(MSIX_82599_BAR); 2755280182Sjfv 2756280182Sjfv /* 2757280182Sjfv ** There is a slight possibility of a failure mode 2758280182Sjfv ** in attach that will result in entering this function 2759280182Sjfv ** before interrupt resources have been initialized, and 2760280182Sjfv ** in that case we do not want to execute the loops below 2761280182Sjfv ** We can detect this reliably by the state of the adapter 2762280182Sjfv ** res pointer. 2763280182Sjfv */ 2764280182Sjfv if (adapter->res == NULL) 2765280182Sjfv goto mem; 2766280182Sjfv 2767280182Sjfv /* 2768280182Sjfv ** Release all msix queue resources: 2769280182Sjfv */ 2770280182Sjfv for (int i = 0; i < adapter->num_queues; i++, que++) { 2771280182Sjfv rid = que->msix + 1; 2772280182Sjfv if (que->tag != NULL) { 2773280182Sjfv bus_teardown_intr(dev, que->res, que->tag); 2774280182Sjfv que->tag = NULL; 2775280182Sjfv } 2776280182Sjfv if (que->res != NULL) 2777280182Sjfv bus_release_resource(dev, SYS_RES_IRQ, rid, que->res); 2778280182Sjfv } 2779280182Sjfv 2780280182Sjfv 2781280182Sjfv /* Clean the Legacy or Link interrupt last */ 2782280182Sjfv if (adapter->vector) /* we are doing MSIX */ 2783280182Sjfv rid = adapter->vector + 1; 2784280182Sjfv else 2785280182Sjfv (adapter->msix != 0) ? (rid = 1):(rid = 0); 2786280182Sjfv 2787280182Sjfv if (adapter->tag != NULL) { 2788280182Sjfv bus_teardown_intr(dev, adapter->res, adapter->tag); 2789280182Sjfv adapter->tag = NULL; 2790280182Sjfv } 2791280182Sjfv if (adapter->res != NULL) 2792280182Sjfv bus_release_resource(dev, SYS_RES_IRQ, rid, adapter->res); 2793280182Sjfv 2794280182Sjfvmem: 2795280182Sjfv if (adapter->msix) 2796280182Sjfv pci_release_msi(dev); 2797280182Sjfv 2798280182Sjfv if (adapter->msix_mem != NULL) 2799280182Sjfv bus_release_resource(dev, SYS_RES_MEMORY, 2800280182Sjfv memrid, adapter->msix_mem); 2801280182Sjfv 2802280182Sjfv if (adapter->pci_mem != NULL) 2803280182Sjfv bus_release_resource(dev, SYS_RES_MEMORY, 2804280182Sjfv PCIR_BAR(0), adapter->pci_mem); 2805280182Sjfv 2806280182Sjfv return; 2807280182Sjfv} 2808280182Sjfv 2809280182Sjfv/********************************************************************* 2810280182Sjfv * 2811280182Sjfv * Setup networking device structure and register an interface. 2812280182Sjfv * 2813280182Sjfv **********************************************************************/ 2814280182Sjfvstatic int 2815280182Sjfvixgbe_setup_interface(device_t dev, struct adapter *adapter) 2816280182Sjfv{ 2817280182Sjfv struct ifnet *ifp; 2818280182Sjfv 2819280182Sjfv INIT_DEBUGOUT("ixgbe_setup_interface: begin"); 2820280182Sjfv 2821280182Sjfv ifp = adapter->ifp = if_alloc(IFT_ETHER); 2822280182Sjfv if (ifp == NULL) { 2823280182Sjfv device_printf(dev, "can not allocate ifnet structure\n"); 2824280182Sjfv return (-1); 2825280182Sjfv } 2826280182Sjfv if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 2827280182Sjfv ifp->if_baudrate = IF_Gbps(10); 2828280182Sjfv ifp->if_init = ixgbe_init; 2829280182Sjfv ifp->if_softc = adapter; 2830280182Sjfv ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 2831280182Sjfv ifp->if_ioctl = ixgbe_ioctl; 2832280182Sjfv#if __FreeBSD_version >= 1100036 2833280182Sjfv if_setgetcounterfn(ifp, ixgbe_get_counter); 2834280182Sjfv#endif 2835282289Serj#if __FreeBSD_version >= 1100045 2836282289Serj /* TSO parameters */ 2837282289Serj ifp->if_hw_tsomax = 65518; 2838282289Serj ifp->if_hw_tsomaxsegcount = IXGBE_82599_SCATTER; 2839282289Serj ifp->if_hw_tsomaxsegsize = 2048; 2840282289Serj#endif 2841280182Sjfv#ifndef IXGBE_LEGACY_TX 2842280182Sjfv ifp->if_transmit = ixgbe_mq_start; 2843280182Sjfv ifp->if_qflush = ixgbe_qflush; 2844280182Sjfv#else 2845280182Sjfv ifp->if_start = ixgbe_start; 2846280182Sjfv IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 2); 2847280182Sjfv ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 2; 2848280182Sjfv IFQ_SET_READY(&ifp->if_snd); 2849280182Sjfv#endif 2850280182Sjfv 2851280182Sjfv ether_ifattach(ifp, adapter->hw.mac.addr); 2852280182Sjfv 2853280182Sjfv adapter->max_frame_size = 2854280182Sjfv ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; 2855280182Sjfv 2856280182Sjfv /* 2857280182Sjfv * Tell the upper layer(s) we support long frames. 2858280182Sjfv */ 2859280182Sjfv ifp->if_hdrlen = sizeof(struct ether_vlan_header); 2860280182Sjfv 2861292674Ssbruno /* Set capability flags */ 2862292674Ssbruno ifp->if_capabilities |= IFCAP_RXCSUM 2863292674Ssbruno | IFCAP_TXCSUM 2864292674Ssbruno | IFCAP_RXCSUM_IPV6 2865292674Ssbruno | IFCAP_TXCSUM_IPV6 2866292674Ssbruno | IFCAP_TSO4 2867292674Ssbruno | IFCAP_TSO6 2868292674Ssbruno | IFCAP_LRO 2869292674Ssbruno | IFCAP_VLAN_HWTAGGING 2870280182Sjfv | IFCAP_VLAN_HWTSO 2871292674Ssbruno | IFCAP_VLAN_HWCSUM 2872292674Ssbruno | IFCAP_JUMBO_MTU 2873280182Sjfv | IFCAP_VLAN_MTU 2874280182Sjfv | IFCAP_HWSTATS; 2875292674Ssbruno 2876292674Ssbruno /* Enable the above capabilities by default */ 2877280182Sjfv ifp->if_capenable = ifp->if_capabilities; 2878280182Sjfv 2879280182Sjfv /* 2880280182Sjfv ** Don't turn this on by default, if vlans are 2881280182Sjfv ** created on another pseudo device (eg. lagg) 2882280182Sjfv ** then vlan events are not passed thru, breaking 2883280182Sjfv ** operation, but with HW FILTER off it works. If 2884280182Sjfv ** using vlans directly on the ixgbe driver you can 2885280182Sjfv ** enable this and get full hardware tag filtering. 2886280182Sjfv */ 2887280182Sjfv ifp->if_capabilities |= IFCAP_VLAN_HWFILTER; 2888280182Sjfv 2889280182Sjfv /* 2890280182Sjfv * Specify the media types supported by this adapter and register 2891280182Sjfv * callbacks to update media and link information 2892280182Sjfv */ 2893280182Sjfv ifmedia_init(&adapter->media, IFM_IMASK, ixgbe_media_change, 2894280182Sjfv ixgbe_media_status); 2895280182Sjfv 2896292674Ssbruno adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw); 2897280182Sjfv ixgbe_add_media_types(adapter); 2898280182Sjfv 2899292674Ssbruno /* Set autoselect media by default */ 2900280182Sjfv ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); 2901280182Sjfv 2902280182Sjfv return (0); 2903280182Sjfv} 2904280182Sjfv 2905280182Sjfvstatic void 2906280182Sjfvixgbe_add_media_types(struct adapter *adapter) 2907280182Sjfv{ 2908280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 2909280182Sjfv device_t dev = adapter->dev; 2910280182Sjfv int layer; 2911280182Sjfv 2912292674Ssbruno layer = adapter->phy_layer; 2913280182Sjfv 2914280182Sjfv /* Media types with matching FreeBSD media defines */ 2915280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) 2916280182Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_T, 0, NULL); 2917280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) 2918280182Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL); 2919280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) 2920280182Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX, 0, NULL); 2921280182Sjfv 2922280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || 2923280182Sjfv layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) 2924280182Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL); 2925280182Sjfv 2926292674Ssbruno if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) { 2927280182Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_LR, 0, NULL); 2928292674Ssbruno if (hw->phy.multispeed_fiber) 2929292674Ssbruno ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_LX, 0, NULL); 2930292674Ssbruno } 2931292674Ssbruno if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) { 2932280182Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL); 2933292674Ssbruno if (hw->phy.multispeed_fiber) 2934292674Ssbruno ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL); 2935292674Ssbruno } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) 2936292674Ssbruno ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL); 2937280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) 2938280182Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); 2939280182Sjfv 2940292674Ssbruno#ifdef IFM_ETH_XTYPE 2941292674Ssbruno if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) 2942292674Ssbruno ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KR, 0, NULL); 2943292674Ssbruno if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) 2944292674Ssbruno ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KX4, 0, NULL); 2945292674Ssbruno if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) 2946292674Ssbruno ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_KX, 0, NULL); 2947292674Ssbruno#else 2948280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) { 2949280182Sjfv device_printf(dev, "Media supported: 10GbaseKR\n"); 2950282289Serj device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n"); 2951282289Serj ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL); 2952280182Sjfv } 2953280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) { 2954280182Sjfv device_printf(dev, "Media supported: 10GbaseKX4\n"); 2955282289Serj device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n"); 2956282289Serj ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); 2957280182Sjfv } 2958280182Sjfv if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) { 2959280182Sjfv device_printf(dev, "Media supported: 1000baseKX\n"); 2960282289Serj device_printf(dev, "1000baseKX mapped to 1000baseCX\n"); 2961282289Serj ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_CX, 0, NULL); 2962280182Sjfv } 2963292674Ssbruno#endif 2964292674Ssbruno if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) 2965280182Sjfv device_printf(dev, "Media supported: 1000baseBX\n"); 2966280182Sjfv 2967280182Sjfv if (hw->device_id == IXGBE_DEV_ID_82598AT) { 2968280182Sjfv ifmedia_add(&adapter->media, 2969280182Sjfv IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); 2970280182Sjfv ifmedia_add(&adapter->media, 2971280182Sjfv IFM_ETHER | IFM_1000_T, 0, NULL); 2972280182Sjfv } 2973280182Sjfv 2974280182Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); 2975280182Sjfv} 2976280182Sjfv 2977280182Sjfvstatic void 2978280182Sjfvixgbe_config_link(struct adapter *adapter) 2979280182Sjfv{ 2980280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 2981280182Sjfv u32 autoneg, err = 0; 2982280182Sjfv bool sfp, negotiate; 2983280182Sjfv 2984280182Sjfv sfp = ixgbe_is_sfp(hw); 2985280182Sjfv 2986280182Sjfv if (sfp) { 2987293334Ssbruno taskqueue_enqueue(adapter->tq, &adapter->mod_task); 2988280182Sjfv } else { 2989280182Sjfv if (hw->mac.ops.check_link) 2990280182Sjfv err = ixgbe_check_link(hw, &adapter->link_speed, 2991280182Sjfv &adapter->link_up, FALSE); 2992280182Sjfv if (err) 2993280182Sjfv goto out; 2994280182Sjfv autoneg = hw->phy.autoneg_advertised; 2995280182Sjfv if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) 2996280182Sjfv err = hw->mac.ops.get_link_capabilities(hw, 2997280182Sjfv &autoneg, &negotiate); 2998280182Sjfv if (err) 2999280182Sjfv goto out; 3000280182Sjfv if (hw->mac.ops.setup_link) 3001280182Sjfv err = hw->mac.ops.setup_link(hw, 3002280182Sjfv autoneg, adapter->link_up); 3003280182Sjfv } 3004280182Sjfvout: 3005280182Sjfv return; 3006280182Sjfv} 3007280182Sjfv 3008280182Sjfv 3009280182Sjfv/********************************************************************* 3010280182Sjfv * 3011280182Sjfv * Enable transmit units. 3012280182Sjfv * 3013280182Sjfv **********************************************************************/ 3014280182Sjfvstatic void 3015280182Sjfvixgbe_initialize_transmit_units(struct adapter *adapter) 3016280182Sjfv{ 3017280182Sjfv struct tx_ring *txr = adapter->tx_rings; 3018280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 3019280182Sjfv 3020280182Sjfv /* Setup the Base and Length of the Tx Descriptor Ring */ 3021280182Sjfv for (int i = 0; i < adapter->num_queues; i++, txr++) { 3022280182Sjfv u64 tdba = txr->txdma.dma_paddr; 3023280182Sjfv u32 txctrl = 0; 3024283883Sjfv int j = txr->me; 3025280182Sjfv 3026283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j), 3027280182Sjfv (tdba & 0x00000000ffffffffULL)); 3028283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32)); 3029283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), 3030280182Sjfv adapter->num_tx_desc * sizeof(union ixgbe_adv_tx_desc)); 3031280182Sjfv 3032280182Sjfv /* Setup the HW Tx Head and Tail descriptor pointers */ 3033283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0); 3034283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0); 3035280182Sjfv 3036280182Sjfv /* Cache the tail address */ 3037283883Sjfv txr->tail = IXGBE_TDT(j); 3038280182Sjfv 3039280182Sjfv /* Disable Head Writeback */ 3040292674Ssbruno /* 3041292674Ssbruno * Note: for X550 series devices, these registers are actually 3042292674Ssbruno * prefixed with TPH_ isntead of DCA_, but the addresses and 3043292674Ssbruno * fields remain the same. 3044292674Ssbruno */ 3045280182Sjfv switch (hw->mac.type) { 3046280182Sjfv case ixgbe_mac_82598EB: 3047283883Sjfv txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j)); 3048280182Sjfv break; 3049280182Sjfv default: 3050283883Sjfv txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j)); 3051280182Sjfv break; 3052280182Sjfv } 3053280182Sjfv txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; 3054280182Sjfv switch (hw->mac.type) { 3055280182Sjfv case ixgbe_mac_82598EB: 3056283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl); 3057280182Sjfv break; 3058280182Sjfv default: 3059283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl); 3060280182Sjfv break; 3061280182Sjfv } 3062280182Sjfv 3063280182Sjfv } 3064280182Sjfv 3065280182Sjfv if (hw->mac.type != ixgbe_mac_82598EB) { 3066280182Sjfv u32 dmatxctl, rttdcs; 3067283883Sjfv#ifdef PCI_IOV 3068283883Sjfv enum ixgbe_iov_mode mode = ixgbe_get_iov_mode(adapter); 3069283883Sjfv#endif 3070280182Sjfv dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); 3071280182Sjfv dmatxctl |= IXGBE_DMATXCTL_TE; 3072280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); 3073280182Sjfv /* Disable arbiter to set MTQC */ 3074280182Sjfv rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); 3075280182Sjfv rttdcs |= IXGBE_RTTDCS_ARBDIS; 3076280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); 3077283883Sjfv#ifdef PCI_IOV 3078283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_MTQC, ixgbe_get_mtqc(mode)); 3079283883Sjfv#else 3080280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB); 3081283883Sjfv#endif 3082280182Sjfv rttdcs &= ~IXGBE_RTTDCS_ARBDIS; 3083280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); 3084280182Sjfv } 3085280182Sjfv 3086280182Sjfv return; 3087280182Sjfv} 3088280182Sjfv 3089280182Sjfvstatic void 3090292674Ssbrunoixgbe_initialize_rss_mapping(struct adapter *adapter) 3091280182Sjfv{ 3092280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 3093283883Sjfv u32 reta = 0, mrqc, rss_key[10]; 3094283883Sjfv int queue_id, table_size, index_mult; 3095280182Sjfv#ifdef RSS 3096283883Sjfv u32 rss_hash_config; 3097280182Sjfv#endif 3098283883Sjfv#ifdef PCI_IOV 3099283883Sjfv enum ixgbe_iov_mode mode; 3100283883Sjfv#endif 3101280182Sjfv 3102280182Sjfv#ifdef RSS 3103280182Sjfv /* Fetch the configured RSS key */ 3104280182Sjfv rss_getkey((uint8_t *) &rss_key); 3105280182Sjfv#else 3106280182Sjfv /* set up random bits */ 3107280182Sjfv arc4rand(&rss_key, sizeof(rss_key), 0); 3108280182Sjfv#endif 3109280182Sjfv 3110282289Serj /* Set multiplier for RETA setup and table size based on MAC */ 3111282289Serj index_mult = 0x1; 3112282289Serj table_size = 128; 3113282289Serj switch (adapter->hw.mac.type) { 3114282289Serj case ixgbe_mac_82598EB: 3115282289Serj index_mult = 0x11; 3116282289Serj break; 3117282289Serj case ixgbe_mac_X550: 3118282289Serj case ixgbe_mac_X550EM_x: 3119282289Serj table_size = 512; 3120282289Serj break; 3121282289Serj default: 3122282289Serj break; 3123282289Serj } 3124282289Serj 3125280182Sjfv /* Set up the redirection table */ 3126283883Sjfv for (int i = 0, j = 0; i < table_size; i++, j++) { 3127280182Sjfv if (j == adapter->num_queues) j = 0; 3128280182Sjfv#ifdef RSS 3129280182Sjfv /* 3130280182Sjfv * Fetch the RSS bucket id for the given indirection entry. 3131280182Sjfv * Cap it at the number of configured buckets (which is 3132280182Sjfv * num_queues.) 3133280182Sjfv */ 3134280182Sjfv queue_id = rss_get_indirection_to_bucket(i); 3135280182Sjfv queue_id = queue_id % adapter->num_queues; 3136280182Sjfv#else 3137282289Serj queue_id = (j * index_mult); 3138280182Sjfv#endif 3139280182Sjfv /* 3140280182Sjfv * The low 8 bits are for hash value (n+0); 3141280182Sjfv * The next 8 bits are for hash value (n+1), etc. 3142280182Sjfv */ 3143280182Sjfv reta = reta >> 8; 3144280182Sjfv reta = reta | ( ((uint32_t) queue_id) << 24); 3145280182Sjfv if ((i & 3) == 3) { 3146282289Serj if (i < 128) 3147282289Serj IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta); 3148282289Serj else 3149282289Serj IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32), reta); 3150280182Sjfv reta = 0; 3151280182Sjfv } 3152280182Sjfv } 3153280182Sjfv 3154280182Sjfv /* Now fill our hash function seeds */ 3155280182Sjfv for (int i = 0; i < 10; i++) 3156280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]); 3157280182Sjfv 3158280182Sjfv /* Perform hash on these packet types */ 3159280182Sjfv#ifdef RSS 3160280182Sjfv mrqc = IXGBE_MRQC_RSSEN; 3161280182Sjfv rss_hash_config = rss_gethashconfig(); 3162280182Sjfv if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4) 3163280182Sjfv mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4; 3164280182Sjfv if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4) 3165280182Sjfv mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP; 3166280182Sjfv if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6) 3167280182Sjfv mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6; 3168280182Sjfv if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6) 3169280182Sjfv mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP; 3170280182Sjfv if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX) 3171280182Sjfv mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX; 3172280182Sjfv if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX) 3173280182Sjfv mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP; 3174280182Sjfv if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4) 3175280182Sjfv mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; 3176280182Sjfv if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4_EX) 3177280182Sjfv device_printf(adapter->dev, 3178280182Sjfv "%s: RSS_HASHTYPE_RSS_UDP_IPV4_EX defined, " 3179280182Sjfv "but not supported\n", __func__); 3180280182Sjfv if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6) 3181280182Sjfv mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; 3182280182Sjfv if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX) 3183280182Sjfv mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP; 3184280182Sjfv#else 3185280182Sjfv /* 3186280182Sjfv * Disable UDP - IP fragments aren't currently being handled 3187280182Sjfv * and so we end up with a mix of 2-tuple and 4-tuple 3188280182Sjfv * traffic. 3189280182Sjfv */ 3190280182Sjfv mrqc = IXGBE_MRQC_RSSEN 3191280182Sjfv | IXGBE_MRQC_RSS_FIELD_IPV4 3192280182Sjfv | IXGBE_MRQC_RSS_FIELD_IPV4_TCP 3193280182Sjfv | IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP 3194280182Sjfv | IXGBE_MRQC_RSS_FIELD_IPV6_EX 3195280182Sjfv | IXGBE_MRQC_RSS_FIELD_IPV6 3196280182Sjfv | IXGBE_MRQC_RSS_FIELD_IPV6_TCP 3197280182Sjfv ; 3198280182Sjfv#endif /* RSS */ 3199283883Sjfv#ifdef PCI_IOV 3200283883Sjfv mode = ixgbe_get_iov_mode(adapter); 3201283883Sjfv mrqc |= ixgbe_get_mrqc(mode); 3202283883Sjfv#endif 3203280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); 3204280182Sjfv} 3205280182Sjfv 3206280182Sjfv 3207280182Sjfv/********************************************************************* 3208280182Sjfv * 3209280182Sjfv * Setup receive registers and features. 3210280182Sjfv * 3211280182Sjfv **********************************************************************/ 3212280182Sjfv#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 3213280182Sjfv 3214280182Sjfv#define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1) 3215280182Sjfv 3216280182Sjfvstatic void 3217280182Sjfvixgbe_initialize_receive_units(struct adapter *adapter) 3218280182Sjfv{ 3219280182Sjfv struct rx_ring *rxr = adapter->rx_rings; 3220280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 3221280182Sjfv struct ifnet *ifp = adapter->ifp; 3222280182Sjfv u32 bufsz, fctrl, srrctl, rxcsum; 3223280182Sjfv u32 hlreg; 3224280182Sjfv 3225280182Sjfv /* 3226280182Sjfv * Make sure receives are disabled while 3227280182Sjfv * setting up the descriptor ring 3228280182Sjfv */ 3229280182Sjfv ixgbe_disable_rx(hw); 3230280182Sjfv 3231280182Sjfv /* Enable broadcasts */ 3232280182Sjfv fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 3233280182Sjfv fctrl |= IXGBE_FCTRL_BAM; 3234282289Serj if (adapter->hw.mac.type == ixgbe_mac_82598EB) { 3235282289Serj fctrl |= IXGBE_FCTRL_DPF; 3236282289Serj fctrl |= IXGBE_FCTRL_PMCF; 3237282289Serj } 3238280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 3239280182Sjfv 3240280182Sjfv /* Set for Jumbo Frames? */ 3241280182Sjfv hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0); 3242280182Sjfv if (ifp->if_mtu > ETHERMTU) 3243280182Sjfv hlreg |= IXGBE_HLREG0_JUMBOEN; 3244280182Sjfv else 3245280182Sjfv hlreg &= ~IXGBE_HLREG0_JUMBOEN; 3246280182Sjfv#ifdef DEV_NETMAP 3247280182Sjfv /* crcstrip is conditional in netmap (in RDRXCTL too ?) */ 3248280182Sjfv if (ifp->if_capenable & IFCAP_NETMAP && !ix_crcstrip) 3249280182Sjfv hlreg &= ~IXGBE_HLREG0_RXCRCSTRP; 3250280182Sjfv else 3251280182Sjfv hlreg |= IXGBE_HLREG0_RXCRCSTRP; 3252280182Sjfv#endif /* DEV_NETMAP */ 3253280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg); 3254280182Sjfv 3255280182Sjfv bufsz = (adapter->rx_mbuf_sz + 3256280182Sjfv BSIZEPKT_ROUNDUP) >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; 3257280182Sjfv 3258280182Sjfv for (int i = 0; i < adapter->num_queues; i++, rxr++) { 3259280182Sjfv u64 rdba = rxr->rxdma.dma_paddr; 3260283883Sjfv int j = rxr->me; 3261280182Sjfv 3262280182Sjfv /* Setup the Base and Length of the Rx Descriptor Ring */ 3263283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), 3264280182Sjfv (rdba & 0x00000000ffffffffULL)); 3265283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32)); 3266283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j), 3267280182Sjfv adapter->num_rx_desc * sizeof(union ixgbe_adv_rx_desc)); 3268280182Sjfv 3269280182Sjfv /* Set up the SRRCTL register */ 3270283883Sjfv srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(j)); 3271280182Sjfv srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK; 3272280182Sjfv srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK; 3273280182Sjfv srrctl |= bufsz; 3274280182Sjfv srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; 3275280182Sjfv 3276280182Sjfv /* 3277280182Sjfv * Set DROP_EN iff we have no flow control and >1 queue. 3278280182Sjfv * Note that srrctl was cleared shortly before during reset, 3279280182Sjfv * so we do not need to clear the bit, but do it just in case 3280280182Sjfv * this code is moved elsewhere. 3281280182Sjfv */ 3282283882Sjfv if (adapter->num_queues > 1 && 3283283882Sjfv adapter->hw.fc.requested_mode == ixgbe_fc_none) { 3284280182Sjfv srrctl |= IXGBE_SRRCTL_DROP_EN; 3285283882Sjfv } else { 3286280182Sjfv srrctl &= ~IXGBE_SRRCTL_DROP_EN; 3287283882Sjfv } 3288280182Sjfv 3289283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl); 3290280182Sjfv 3291280182Sjfv /* Setup the HW Rx Head and Tail Descriptor Pointers */ 3292283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0); 3293283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0); 3294280182Sjfv 3295280182Sjfv /* Set the driver rx tail address */ 3296280182Sjfv rxr->tail = IXGBE_RDT(rxr->me); 3297280182Sjfv } 3298280182Sjfv 3299280182Sjfv if (adapter->hw.mac.type != ixgbe_mac_82598EB) { 3300280182Sjfv u32 psrtype = IXGBE_PSRTYPE_TCPHDR | 3301280182Sjfv IXGBE_PSRTYPE_UDPHDR | 3302280182Sjfv IXGBE_PSRTYPE_IPV4HDR | 3303280182Sjfv IXGBE_PSRTYPE_IPV6HDR; 3304280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype); 3305280182Sjfv } 3306280182Sjfv 3307280182Sjfv rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); 3308280182Sjfv 3309292674Ssbruno ixgbe_initialize_rss_mapping(adapter); 3310280182Sjfv 3311280182Sjfv if (adapter->num_queues > 1) { 3312280182Sjfv /* RSS and RX IPP Checksum are mutually exclusive */ 3313280182Sjfv rxcsum |= IXGBE_RXCSUM_PCSD; 3314280182Sjfv } 3315280182Sjfv 3316280182Sjfv if (ifp->if_capenable & IFCAP_RXCSUM) 3317280182Sjfv rxcsum |= IXGBE_RXCSUM_PCSD; 3318280182Sjfv 3319292674Ssbruno /* This is useful for calculating UDP/IP fragment checksums */ 3320280182Sjfv if (!(rxcsum & IXGBE_RXCSUM_PCSD)) 3321280182Sjfv rxcsum |= IXGBE_RXCSUM_IPPCSE; 3322280182Sjfv 3323280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum); 3324280182Sjfv 3325280182Sjfv return; 3326280182Sjfv} 3327280182Sjfv 3328280182Sjfv 3329280182Sjfv/* 3330280182Sjfv** This routine is run via an vlan config EVENT, 3331280182Sjfv** it enables us to use the HW Filter table since 3332280182Sjfv** we can get the vlan id. This just creates the 3333280182Sjfv** entry in the soft version of the VFTA, init will 3334280182Sjfv** repopulate the real table. 3335280182Sjfv*/ 3336280182Sjfvstatic void 3337280182Sjfvixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) 3338280182Sjfv{ 3339280182Sjfv struct adapter *adapter = ifp->if_softc; 3340280182Sjfv u16 index, bit; 3341280182Sjfv 3342280182Sjfv if (ifp->if_softc != arg) /* Not our event */ 3343280182Sjfv return; 3344280182Sjfv 3345280182Sjfv if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 3346280182Sjfv return; 3347280182Sjfv 3348280182Sjfv IXGBE_CORE_LOCK(adapter); 3349280182Sjfv index = (vtag >> 5) & 0x7F; 3350280182Sjfv bit = vtag & 0x1F; 3351280182Sjfv adapter->shadow_vfta[index] |= (1 << bit); 3352280182Sjfv ++adapter->num_vlans; 3353280182Sjfv ixgbe_setup_vlan_hw_support(adapter); 3354280182Sjfv IXGBE_CORE_UNLOCK(adapter); 3355280182Sjfv} 3356280182Sjfv 3357280182Sjfv/* 3358280182Sjfv** This routine is run via an vlan 3359280182Sjfv** unconfig EVENT, remove our entry 3360280182Sjfv** in the soft vfta. 3361280182Sjfv*/ 3362280182Sjfvstatic void 3363280182Sjfvixgbe_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) 3364280182Sjfv{ 3365280182Sjfv struct adapter *adapter = ifp->if_softc; 3366280182Sjfv u16 index, bit; 3367280182Sjfv 3368280182Sjfv if (ifp->if_softc != arg) 3369280182Sjfv return; 3370280182Sjfv 3371280182Sjfv if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 3372280182Sjfv return; 3373280182Sjfv 3374280182Sjfv IXGBE_CORE_LOCK(adapter); 3375280182Sjfv index = (vtag >> 5) & 0x7F; 3376280182Sjfv bit = vtag & 0x1F; 3377280182Sjfv adapter->shadow_vfta[index] &= ~(1 << bit); 3378280182Sjfv --adapter->num_vlans; 3379280182Sjfv /* Re-init to load the changes */ 3380280182Sjfv ixgbe_setup_vlan_hw_support(adapter); 3381280182Sjfv IXGBE_CORE_UNLOCK(adapter); 3382280182Sjfv} 3383280182Sjfv 3384280182Sjfvstatic void 3385280182Sjfvixgbe_setup_vlan_hw_support(struct adapter *adapter) 3386280182Sjfv{ 3387280182Sjfv struct ifnet *ifp = adapter->ifp; 3388280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 3389280182Sjfv struct rx_ring *rxr; 3390280182Sjfv u32 ctrl; 3391280182Sjfv 3392280182Sjfv 3393280182Sjfv /* 3394280182Sjfv ** We get here thru init_locked, meaning 3395280182Sjfv ** a soft reset, this has already cleared 3396280182Sjfv ** the VFTA and other state, so if there 3397280182Sjfv ** have been no vlan's registered do nothing. 3398280182Sjfv */ 3399280182Sjfv if (adapter->num_vlans == 0) 3400280182Sjfv return; 3401280182Sjfv 3402280182Sjfv /* Setup the queues for vlans */ 3403280182Sjfv for (int i = 0; i < adapter->num_queues; i++) { 3404280182Sjfv rxr = &adapter->rx_rings[i]; 3405280182Sjfv /* On 82599 the VLAN enable is per/queue in RXDCTL */ 3406280182Sjfv if (hw->mac.type != ixgbe_mac_82598EB) { 3407283883Sjfv ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); 3408280182Sjfv ctrl |= IXGBE_RXDCTL_VME; 3409283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl); 3410280182Sjfv } 3411280182Sjfv rxr->vtag_strip = TRUE; 3412280182Sjfv } 3413280182Sjfv 3414280182Sjfv if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0) 3415280182Sjfv return; 3416280182Sjfv /* 3417280182Sjfv ** A soft reset zero's out the VFTA, so 3418280182Sjfv ** we need to repopulate it now. 3419280182Sjfv */ 3420280182Sjfv for (int i = 0; i < IXGBE_VFTA_SIZE; i++) 3421280182Sjfv if (adapter->shadow_vfta[i] != 0) 3422280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), 3423280182Sjfv adapter->shadow_vfta[i]); 3424280182Sjfv 3425280182Sjfv ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); 3426280182Sjfv /* Enable the Filter Table if enabled */ 3427280182Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) { 3428280182Sjfv ctrl &= ~IXGBE_VLNCTRL_CFIEN; 3429280182Sjfv ctrl |= IXGBE_VLNCTRL_VFE; 3430280182Sjfv } 3431280182Sjfv if (hw->mac.type == ixgbe_mac_82598EB) 3432280182Sjfv ctrl |= IXGBE_VLNCTRL_VME; 3433280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); 3434280182Sjfv} 3435280182Sjfv 3436280182Sjfvstatic void 3437280182Sjfvixgbe_enable_intr(struct adapter *adapter) 3438280182Sjfv{ 3439280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 3440280182Sjfv struct ix_queue *que = adapter->queues; 3441280182Sjfv u32 mask, fwsm; 3442280182Sjfv 3443280182Sjfv mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); 3444280182Sjfv /* Enable Fan Failure detection */ 3445280182Sjfv if (hw->device_id == IXGBE_DEV_ID_82598AT) 3446282289Serj mask |= IXGBE_EIMS_GPI_SDP1; 3447280182Sjfv 3448280182Sjfv switch (adapter->hw.mac.type) { 3449280182Sjfv case ixgbe_mac_82599EB: 3450280182Sjfv mask |= IXGBE_EIMS_ECC; 3451280182Sjfv /* Temperature sensor on some adapters */ 3452282289Serj mask |= IXGBE_EIMS_GPI_SDP0; 3453280182Sjfv /* SFP+ (RX_LOS_N & MOD_ABS_N) */ 3454282289Serj mask |= IXGBE_EIMS_GPI_SDP1; 3455282289Serj mask |= IXGBE_EIMS_GPI_SDP2; 3456280182Sjfv#ifdef IXGBE_FDIR 3457280182Sjfv mask |= IXGBE_EIMS_FLOW_DIR; 3458280182Sjfv#endif 3459283883Sjfv#ifdef PCI_IOV 3460283883Sjfv mask |= IXGBE_EIMS_MAILBOX; 3461283883Sjfv#endif 3462280182Sjfv break; 3463280182Sjfv case ixgbe_mac_X540: 3464280182Sjfv /* Detect if Thermal Sensor is enabled */ 3465280182Sjfv fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); 3466280182Sjfv if (fwsm & IXGBE_FWSM_TS_ENABLED) 3467280182Sjfv mask |= IXGBE_EIMS_TS; 3468282289Serj mask |= IXGBE_EIMS_ECC; 3469282289Serj#ifdef IXGBE_FDIR 3470282289Serj mask |= IXGBE_EIMS_FLOW_DIR; 3471282289Serj#endif 3472282289Serj break; 3473282289Serj case ixgbe_mac_X550: 3474282289Serj case ixgbe_mac_X550EM_x: 3475282289Serj /* MAC thermal sensor is automatically enabled */ 3476282289Serj mask |= IXGBE_EIMS_TS; 3477282289Serj /* Some devices use SDP0 for important information */ 3478282289Serj if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP || 3479282289Serj hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) 3480280182Sjfv mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw); 3481280182Sjfv mask |= IXGBE_EIMS_ECC; 3482280182Sjfv#ifdef IXGBE_FDIR 3483280182Sjfv mask |= IXGBE_EIMS_FLOW_DIR; 3484280182Sjfv#endif 3485283883Sjfv#ifdef PCI_IOV 3486283883Sjfv mask |= IXGBE_EIMS_MAILBOX; 3487283883Sjfv#endif 3488280182Sjfv /* falls through */ 3489280182Sjfv default: 3490280182Sjfv break; 3491280182Sjfv } 3492280182Sjfv 3493280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); 3494280182Sjfv 3495282289Serj /* With MSI-X we use auto clear */ 3496280182Sjfv if (adapter->msix_mem) { 3497280182Sjfv mask = IXGBE_EIMS_ENABLE_MASK; 3498280182Sjfv /* Don't autoclear Link */ 3499280182Sjfv mask &= ~IXGBE_EIMS_OTHER; 3500280182Sjfv mask &= ~IXGBE_EIMS_LSC; 3501283883Sjfv#ifdef PCI_IOV 3502283883Sjfv mask &= ~IXGBE_EIMS_MAILBOX; 3503283883Sjfv#endif 3504280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask); 3505280182Sjfv } 3506280182Sjfv 3507280182Sjfv /* 3508280182Sjfv ** Now enable all queues, this is done separately to 3509280182Sjfv ** allow for handling the extended (beyond 32) MSIX 3510280182Sjfv ** vectors that can be used by 82599 3511280182Sjfv */ 3512280182Sjfv for (int i = 0; i < adapter->num_queues; i++, que++) 3513280182Sjfv ixgbe_enable_queue(adapter, que->msix); 3514280182Sjfv 3515280182Sjfv IXGBE_WRITE_FLUSH(hw); 3516280182Sjfv 3517280182Sjfv return; 3518280182Sjfv} 3519280182Sjfv 3520280182Sjfvstatic void 3521280182Sjfvixgbe_disable_intr(struct adapter *adapter) 3522280182Sjfv{ 3523280182Sjfv if (adapter->msix_mem) 3524280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 0); 3525280182Sjfv if (adapter->hw.mac.type == ixgbe_mac_82598EB) { 3526280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); 3527280182Sjfv } else { 3528280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000); 3529280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0); 3530280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); 3531280182Sjfv } 3532280182Sjfv IXGBE_WRITE_FLUSH(&adapter->hw); 3533280182Sjfv return; 3534280182Sjfv} 3535280182Sjfv 3536280182Sjfv/* 3537280182Sjfv** Get the width and transaction speed of 3538280182Sjfv** the slot this adapter is plugged into. 3539280182Sjfv*/ 3540280182Sjfvstatic void 3541292674Ssbrunoixgbe_get_slot_info(struct adapter *adapter) 3542280182Sjfv{ 3543292674Ssbruno device_t dev = adapter->dev; 3544292674Ssbruno struct ixgbe_hw *hw = &adapter->hw; 3545280182Sjfv struct ixgbe_mac_info *mac = &hw->mac; 3546280182Sjfv u16 link; 3547280182Sjfv u32 offset; 3548280182Sjfv 3549280182Sjfv /* For most devices simply call the shared code routine */ 3550280182Sjfv if (hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) { 3551280182Sjfv ixgbe_get_bus_info(hw); 3552280182Sjfv /* These devices don't use PCI-E */ 3553282289Serj switch (hw->mac.type) { 3554282289Serj case ixgbe_mac_X550EM_x: 3555280182Sjfv return; 3556282289Serj default: 3557282289Serj goto display; 3558282289Serj } 3559280182Sjfv } 3560280182Sjfv 3561280182Sjfv /* 3562280182Sjfv ** For the Quad port adapter we need to parse back 3563280182Sjfv ** up the PCI tree to find the speed of the expansion 3564280182Sjfv ** slot into which this adapter is plugged. A bit more work. 3565280182Sjfv */ 3566280182Sjfv dev = device_get_parent(device_get_parent(dev)); 3567280182Sjfv#ifdef IXGBE_DEBUG 3568280182Sjfv device_printf(dev, "parent pcib = %x,%x,%x\n", 3569280182Sjfv pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev)); 3570280182Sjfv#endif 3571280182Sjfv dev = device_get_parent(device_get_parent(dev)); 3572280182Sjfv#ifdef IXGBE_DEBUG 3573280182Sjfv device_printf(dev, "slot pcib = %x,%x,%x\n", 3574280182Sjfv pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev)); 3575280182Sjfv#endif 3576280182Sjfv /* Now get the PCI Express Capabilities offset */ 3577280182Sjfv pci_find_cap(dev, PCIY_EXPRESS, &offset); 3578280182Sjfv /* ...and read the Link Status Register */ 3579280182Sjfv link = pci_read_config(dev, offset + PCIER_LINK_STA, 2); 3580280182Sjfv switch (link & IXGBE_PCI_LINK_WIDTH) { 3581280182Sjfv case IXGBE_PCI_LINK_WIDTH_1: 3582280182Sjfv hw->bus.width = ixgbe_bus_width_pcie_x1; 3583280182Sjfv break; 3584280182Sjfv case IXGBE_PCI_LINK_WIDTH_2: 3585280182Sjfv hw->bus.width = ixgbe_bus_width_pcie_x2; 3586280182Sjfv break; 3587280182Sjfv case IXGBE_PCI_LINK_WIDTH_4: 3588280182Sjfv hw->bus.width = ixgbe_bus_width_pcie_x4; 3589280182Sjfv break; 3590280182Sjfv case IXGBE_PCI_LINK_WIDTH_8: 3591280182Sjfv hw->bus.width = ixgbe_bus_width_pcie_x8; 3592280182Sjfv break; 3593280182Sjfv default: 3594280182Sjfv hw->bus.width = ixgbe_bus_width_unknown; 3595280182Sjfv break; 3596280182Sjfv } 3597280182Sjfv 3598280182Sjfv switch (link & IXGBE_PCI_LINK_SPEED) { 3599280182Sjfv case IXGBE_PCI_LINK_SPEED_2500: 3600280182Sjfv hw->bus.speed = ixgbe_bus_speed_2500; 3601280182Sjfv break; 3602280182Sjfv case IXGBE_PCI_LINK_SPEED_5000: 3603280182Sjfv hw->bus.speed = ixgbe_bus_speed_5000; 3604280182Sjfv break; 3605280182Sjfv case IXGBE_PCI_LINK_SPEED_8000: 3606280182Sjfv hw->bus.speed = ixgbe_bus_speed_8000; 3607280182Sjfv break; 3608280182Sjfv default: 3609280182Sjfv hw->bus.speed = ixgbe_bus_speed_unknown; 3610280182Sjfv break; 3611280182Sjfv } 3612280182Sjfv 3613280182Sjfv mac->ops.set_lan_id(hw); 3614280182Sjfv 3615280182Sjfvdisplay: 3616280182Sjfv device_printf(dev,"PCI Express Bus: Speed %s %s\n", 3617280182Sjfv ((hw->bus.speed == ixgbe_bus_speed_8000) ? "8.0GT/s": 3618280182Sjfv (hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0GT/s": 3619280182Sjfv (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5GT/s":"Unknown"), 3620280182Sjfv (hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" : 3621280182Sjfv (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" : 3622280182Sjfv (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" : 3623280182Sjfv ("Unknown")); 3624280182Sjfv 3625280182Sjfv if ((hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) && 3626280182Sjfv ((hw->bus.width <= ixgbe_bus_width_pcie_x4) && 3627280182Sjfv (hw->bus.speed == ixgbe_bus_speed_2500))) { 3628280182Sjfv device_printf(dev, "PCI-Express bandwidth available" 3629280182Sjfv " for this card\n is not sufficient for" 3630280182Sjfv " optimal performance.\n"); 3631280182Sjfv device_printf(dev, "For optimal performance a x8 " 3632280182Sjfv "PCIE, or x4 PCIE Gen2 slot is required.\n"); 3633280182Sjfv } 3634280182Sjfv if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) && 3635280182Sjfv ((hw->bus.width <= ixgbe_bus_width_pcie_x8) && 3636280182Sjfv (hw->bus.speed < ixgbe_bus_speed_8000))) { 3637280182Sjfv device_printf(dev, "PCI-Express bandwidth available" 3638280182Sjfv " for this card\n is not sufficient for" 3639280182Sjfv " optimal performance.\n"); 3640280182Sjfv device_printf(dev, "For optimal performance a x8 " 3641280182Sjfv "PCIE Gen3 slot is required.\n"); 3642280182Sjfv } 3643280182Sjfv 3644280182Sjfv return; 3645280182Sjfv} 3646280182Sjfv 3647280182Sjfv 3648280182Sjfv/* 3649280182Sjfv** Setup the correct IVAR register for a particular MSIX interrupt 3650280182Sjfv** (yes this is all very magic and confusing :) 3651280182Sjfv** - entry is the register array entry 3652280182Sjfv** - vector is the MSIX vector for this queue 3653280182Sjfv** - type is RX/TX/MISC 3654280182Sjfv*/ 3655280182Sjfvstatic void 3656280182Sjfvixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type) 3657280182Sjfv{ 3658280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 3659280182Sjfv u32 ivar, index; 3660280182Sjfv 3661280182Sjfv vector |= IXGBE_IVAR_ALLOC_VAL; 3662280182Sjfv 3663280182Sjfv switch (hw->mac.type) { 3664280182Sjfv 3665280182Sjfv case ixgbe_mac_82598EB: 3666280182Sjfv if (type == -1) 3667280182Sjfv entry = IXGBE_IVAR_OTHER_CAUSES_INDEX; 3668280182Sjfv else 3669280182Sjfv entry += (type * 64); 3670280182Sjfv index = (entry >> 2) & 0x1F; 3671280182Sjfv ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index)); 3672280182Sjfv ivar &= ~(0xFF << (8 * (entry & 0x3))); 3673280182Sjfv ivar |= (vector << (8 * (entry & 0x3))); 3674280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR(index), ivar); 3675280182Sjfv break; 3676280182Sjfv 3677280182Sjfv case ixgbe_mac_82599EB: 3678280182Sjfv case ixgbe_mac_X540: 3679280182Sjfv case ixgbe_mac_X550: 3680280182Sjfv case ixgbe_mac_X550EM_x: 3681280182Sjfv if (type == -1) { /* MISC IVAR */ 3682280182Sjfv index = (entry & 1) * 8; 3683280182Sjfv ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC); 3684280182Sjfv ivar &= ~(0xFF << index); 3685280182Sjfv ivar |= (vector << index); 3686280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar); 3687280182Sjfv } else { /* RX/TX IVARS */ 3688280182Sjfv index = (16 * (entry & 1)) + (8 * type); 3689280182Sjfv ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1)); 3690280182Sjfv ivar &= ~(0xFF << index); 3691280182Sjfv ivar |= (vector << index); 3692280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar); 3693280182Sjfv } 3694280182Sjfv 3695280182Sjfv default: 3696280182Sjfv break; 3697280182Sjfv } 3698280182Sjfv} 3699280182Sjfv 3700280182Sjfvstatic void 3701280182Sjfvixgbe_configure_ivars(struct adapter *adapter) 3702280182Sjfv{ 3703283883Sjfv struct ix_queue *que = adapter->queues; 3704283883Sjfv u32 newitr; 3705280182Sjfv 3706280182Sjfv if (ixgbe_max_interrupt_rate > 0) 3707280182Sjfv newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8; 3708282289Serj else { 3709282289Serj /* 3710282289Serj ** Disable DMA coalescing if interrupt moderation is 3711282289Serj ** disabled. 3712282289Serj */ 3713282289Serj adapter->dmac = 0; 3714280182Sjfv newitr = 0; 3715282289Serj } 3716280182Sjfv 3717280182Sjfv for (int i = 0; i < adapter->num_queues; i++, que++) { 3718283883Sjfv struct rx_ring *rxr = &adapter->rx_rings[i]; 3719283883Sjfv struct tx_ring *txr = &adapter->tx_rings[i]; 3720280182Sjfv /* First the RX queue entry */ 3721283883Sjfv ixgbe_set_ivar(adapter, rxr->me, que->msix, 0); 3722280182Sjfv /* ... and the TX */ 3723283883Sjfv ixgbe_set_ivar(adapter, txr->me, que->msix, 1); 3724280182Sjfv /* Set an Initial EITR value */ 3725280182Sjfv IXGBE_WRITE_REG(&adapter->hw, 3726280182Sjfv IXGBE_EITR(que->msix), newitr); 3727280182Sjfv } 3728280182Sjfv 3729280182Sjfv /* For the Link interrupt */ 3730280182Sjfv ixgbe_set_ivar(adapter, 1, adapter->vector, -1); 3731280182Sjfv} 3732280182Sjfv 3733280182Sjfv/* 3734280182Sjfv** ixgbe_sfp_probe - called in the local timer to 3735280182Sjfv** determine if a port had optics inserted. 3736280182Sjfv*/ 3737283883Sjfvstatic bool 3738283883Sjfvixgbe_sfp_probe(struct adapter *adapter) 3739280182Sjfv{ 3740280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 3741280182Sjfv device_t dev = adapter->dev; 3742280182Sjfv bool result = FALSE; 3743280182Sjfv 3744280182Sjfv if ((hw->phy.type == ixgbe_phy_nl) && 3745280182Sjfv (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) { 3746280182Sjfv s32 ret = hw->phy.ops.identify_sfp(hw); 3747280182Sjfv if (ret) 3748280182Sjfv goto out; 3749280182Sjfv ret = hw->phy.ops.reset(hw); 3750280182Sjfv if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { 3751292674Ssbruno device_printf(dev, "Unsupported SFP+ module detected!"); 3752292674Ssbruno device_printf(dev, "Reload driver with supported module.\n"); 3753280182Sjfv adapter->sfp_probe = FALSE; 3754280182Sjfv goto out; 3755280182Sjfv } else 3756292674Ssbruno device_printf(dev, "SFP+ module detected!\n"); 3757280182Sjfv /* We now have supported optics */ 3758280182Sjfv adapter->sfp_probe = FALSE; 3759280182Sjfv /* Set the optics type so system reports correctly */ 3760280182Sjfv ixgbe_setup_optics(adapter); 3761280182Sjfv result = TRUE; 3762280182Sjfv } 3763280182Sjfvout: 3764280182Sjfv return (result); 3765280182Sjfv} 3766280182Sjfv 3767280182Sjfv/* 3768280182Sjfv** Tasklet handler for MSIX Link interrupts 3769280182Sjfv** - do outside interrupt since it might sleep 3770280182Sjfv*/ 3771280182Sjfvstatic void 3772280182Sjfvixgbe_handle_link(void *context, int pending) 3773280182Sjfv{ 3774280182Sjfv struct adapter *adapter = context; 3775292674Ssbruno struct ixgbe_hw *hw = &adapter->hw; 3776280182Sjfv 3777292674Ssbruno ixgbe_check_link(hw, 3778280182Sjfv &adapter->link_speed, &adapter->link_up, 0); 3779282289Serj ixgbe_update_link_status(adapter); 3780292674Ssbruno 3781292674Ssbruno /* Re-enable link interrupts */ 3782292674Ssbruno IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_LSC); 3783280182Sjfv} 3784280182Sjfv 3785280182Sjfv/* 3786280182Sjfv** Tasklet for handling SFP module interrupts 3787280182Sjfv*/ 3788280182Sjfvstatic void 3789280182Sjfvixgbe_handle_mod(void *context, int pending) 3790280182Sjfv{ 3791280182Sjfv struct adapter *adapter = context; 3792280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 3793293334Ssbruno enum ixgbe_phy_type orig_type = hw->phy.type; 3794280182Sjfv device_t dev = adapter->dev; 3795280182Sjfv u32 err; 3796280182Sjfv 3797293334Ssbruno IXGBE_CORE_LOCK(adapter); 3798293334Ssbruno 3799293334Ssbruno /* Check to see if the PHY type changed */ 3800293334Ssbruno if (hw->phy.ops.identify) { 3801293334Ssbruno hw->phy.type = ixgbe_phy_unknown; 3802293334Ssbruno hw->phy.ops.identify(hw); 3803293334Ssbruno } 3804293334Ssbruno 3805293334Ssbruno if (hw->phy.type != orig_type) { 3806293334Ssbruno device_printf(dev, "Detected phy_type %d\n", hw->phy.type); 3807293334Ssbruno 3808293334Ssbruno if (hw->phy.type == ixgbe_phy_none) { 3809293334Ssbruno hw->phy.sfp_type = ixgbe_sfp_type_unknown; 3810293334Ssbruno goto out; 3811293334Ssbruno } 3812293334Ssbruno 3813293334Ssbruno /* Try to do the initialization that was skipped before */ 3814293334Ssbruno if (hw->phy.ops.init) 3815293334Ssbruno hw->phy.ops.init(hw); 3816293334Ssbruno if (hw->phy.ops.reset) 3817293334Ssbruno hw->phy.ops.reset(hw); 3818293334Ssbruno } 3819293334Ssbruno 3820280182Sjfv err = hw->phy.ops.identify_sfp(hw); 3821280182Sjfv if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 3822280182Sjfv device_printf(dev, 3823280182Sjfv "Unsupported SFP+ module type was detected.\n"); 3824293334Ssbruno goto out; 3825280182Sjfv } 3826283883Sjfv 3827280182Sjfv err = hw->mac.ops.setup_sfp(hw); 3828280182Sjfv if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { 3829280182Sjfv device_printf(dev, 3830280182Sjfv "Setup failure - unsupported SFP+ module type.\n"); 3831293334Ssbruno goto out; 3832280182Sjfv } 3833293334Ssbruno if (hw->phy.multispeed_fiber) 3834293334Ssbruno taskqueue_enqueue(adapter->tq, &adapter->msf_task); 3835293334Ssbrunoout: 3836293334Ssbruno /* Update media type */ 3837293334Ssbruno switch (hw->mac.ops.get_media_type(hw)) { 3838293334Ssbruno case ixgbe_media_type_fiber: 3839293334Ssbruno adapter->optics = IFM_10G_SR; 3840293334Ssbruno break; 3841293334Ssbruno case ixgbe_media_type_copper: 3842293334Ssbruno adapter->optics = IFM_10G_TWINAX; 3843293334Ssbruno break; 3844293334Ssbruno case ixgbe_media_type_cx4: 3845293334Ssbruno adapter->optics = IFM_10G_CX4; 3846293334Ssbruno break; 3847293334Ssbruno default: 3848293334Ssbruno adapter->optics = 0; 3849293334Ssbruno break; 3850293334Ssbruno } 3851293334Ssbruno 3852293334Ssbruno IXGBE_CORE_UNLOCK(adapter); 3853280182Sjfv return; 3854280182Sjfv} 3855280182Sjfv 3856280182Sjfv 3857280182Sjfv/* 3858280182Sjfv** Tasklet for handling MSF (multispeed fiber) interrupts 3859280182Sjfv*/ 3860280182Sjfvstatic void 3861280182Sjfvixgbe_handle_msf(void *context, int pending) 3862280182Sjfv{ 3863280182Sjfv struct adapter *adapter = context; 3864280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 3865280182Sjfv u32 autoneg; 3866280182Sjfv bool negotiate; 3867280182Sjfv 3868293334Ssbruno IXGBE_CORE_LOCK(adapter); 3869292674Ssbruno /* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */ 3870292674Ssbruno adapter->phy_layer = ixgbe_get_supported_physical_layer(hw); 3871280182Sjfv 3872280182Sjfv autoneg = hw->phy.autoneg_advertised; 3873280182Sjfv if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) 3874280182Sjfv hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate); 3875280182Sjfv if (hw->mac.ops.setup_link) 3876280182Sjfv hw->mac.ops.setup_link(hw, autoneg, TRUE); 3877280182Sjfv 3878292674Ssbruno /* Adjust media types shown in ifconfig */ 3879280182Sjfv ifmedia_removeall(&adapter->media); 3880280182Sjfv ixgbe_add_media_types(adapter); 3881293334Ssbruno IXGBE_CORE_UNLOCK(adapter); 3882280182Sjfv return; 3883280182Sjfv} 3884280182Sjfv 3885282289Serj/* 3886282289Serj** Tasklet for handling interrupts from an external PHY 3887282289Serj*/ 3888282289Serjstatic void 3889282289Serjixgbe_handle_phy(void *context, int pending) 3890282289Serj{ 3891282289Serj struct adapter *adapter = context; 3892282289Serj struct ixgbe_hw *hw = &adapter->hw; 3893282289Serj int error; 3894282289Serj 3895282289Serj error = hw->phy.ops.handle_lasi(hw); 3896282289Serj if (error == IXGBE_ERR_OVERTEMP) 3897282289Serj device_printf(adapter->dev, 3898282289Serj "CRITICAL: EXTERNAL PHY OVER TEMP!! " 3899282289Serj " PHY will downshift to lower power state!\n"); 3900282289Serj else if (error) 3901282289Serj device_printf(adapter->dev, 3902282289Serj "Error handling LASI interrupt: %d\n", 3903282289Serj error); 3904282289Serj return; 3905282289Serj} 3906282289Serj 3907280182Sjfv#ifdef IXGBE_FDIR 3908280182Sjfv/* 3909280182Sjfv** Tasklet for reinitializing the Flow Director filter table 3910280182Sjfv*/ 3911280182Sjfvstatic void 3912280182Sjfvixgbe_reinit_fdir(void *context, int pending) 3913280182Sjfv{ 3914280182Sjfv struct adapter *adapter = context; 3915280182Sjfv struct ifnet *ifp = adapter->ifp; 3916280182Sjfv 3917280182Sjfv if (adapter->fdir_reinit != 1) /* Shouldn't happen */ 3918280182Sjfv return; 3919280182Sjfv ixgbe_reinit_fdir_tables_82599(&adapter->hw); 3920280182Sjfv adapter->fdir_reinit = 0; 3921280182Sjfv /* re-enable flow director interrupts */ 3922280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR); 3923280182Sjfv /* Restart the interface */ 3924280182Sjfv ifp->if_drv_flags |= IFF_DRV_RUNNING; 3925280182Sjfv return; 3926280182Sjfv} 3927280182Sjfv#endif 3928280182Sjfv 3929282289Serj/********************************************************************* 3930282289Serj * 3931282289Serj * Configure DMA Coalescing 3932282289Serj * 3933282289Serj **********************************************************************/ 3934282289Serjstatic void 3935282289Serjixgbe_config_dmac(struct adapter *adapter) 3936282289Serj{ 3937282289Serj struct ixgbe_hw *hw = &adapter->hw; 3938282289Serj struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config; 3939282289Serj 3940282289Serj if (hw->mac.type < ixgbe_mac_X550 || 3941282289Serj !hw->mac.ops.dmac_config) 3942282289Serj return; 3943282289Serj 3944282289Serj if (dcfg->watchdog_timer ^ adapter->dmac || 3945282289Serj dcfg->link_speed ^ adapter->link_speed) { 3946282289Serj dcfg->watchdog_timer = adapter->dmac; 3947282289Serj dcfg->fcoe_en = false; 3948282289Serj dcfg->link_speed = adapter->link_speed; 3949282289Serj dcfg->num_tcs = 1; 3950282289Serj 3951282289Serj INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n", 3952282289Serj dcfg->watchdog_timer, dcfg->link_speed); 3953282289Serj 3954282289Serj hw->mac.ops.dmac_config(hw); 3955282289Serj } 3956282289Serj} 3957282289Serj 3958282289Serj/* 3959282289Serj * Checks whether the adapter's ports are capable of 3960282289Serj * Wake On LAN by reading the adapter's NVM. 3961282289Serj * 3962282289Serj * Sets each port's hw->wol_enabled value depending 3963282289Serj * on the value read here. 3964282289Serj */ 3965282289Serjstatic void 3966282289Serjixgbe_check_wol_support(struct adapter *adapter) 3967282289Serj{ 3968282289Serj struct ixgbe_hw *hw = &adapter->hw; 3969282289Serj u16 dev_caps = 0; 3970282289Serj 3971282289Serj /* Find out WoL support for port */ 3972282289Serj adapter->wol_support = hw->wol_enabled = 0; 3973282289Serj ixgbe_get_device_caps(hw, &dev_caps); 3974282289Serj if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) || 3975282289Serj ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) && 3976292674Ssbruno hw->bus.func == 0)) 3977292674Ssbruno adapter->wol_support = hw->wol_enabled = 1; 3978282289Serj 3979282289Serj /* Save initial wake up filter configuration */ 3980282289Serj adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC); 3981282289Serj 3982282289Serj return; 3983282289Serj} 3984282289Serj 3985282289Serj/* 3986282289Serj * Prepare the adapter/port for LPLU and/or WoL 3987282289Serj */ 3988282289Serjstatic int 3989282289Serjixgbe_setup_low_power_mode(struct adapter *adapter) 3990282289Serj{ 3991282289Serj struct ixgbe_hw *hw = &adapter->hw; 3992282289Serj device_t dev = adapter->dev; 3993282289Serj s32 error = 0; 3994282289Serj 3995282289Serj mtx_assert(&adapter->core_mtx, MA_OWNED); 3996282289Serj 3997295093Ssmh if (!hw->wol_enabled) 3998295093Ssmh ixgbe_set_phy_power(hw, FALSE); 3999295093Ssmh 4000282289Serj /* Limit power management flow to X550EM baseT */ 4001282289Serj if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T 4002282289Serj && hw->phy.ops.enter_lplu) { 4003282289Serj /* Turn off support for APM wakeup. (Using ACPI instead) */ 4004282289Serj IXGBE_WRITE_REG(hw, IXGBE_GRC, 4005282289Serj IXGBE_READ_REG(hw, IXGBE_GRC) & ~(u32)2); 4006282289Serj 4007282289Serj /* 4008282289Serj * Clear Wake Up Status register to prevent any previous wakeup 4009282289Serj * events from waking us up immediately after we suspend. 4010282289Serj */ 4011282289Serj IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff); 4012282289Serj 4013282289Serj /* 4014282289Serj * Program the Wakeup Filter Control register with user filter 4015282289Serj * settings 4016282289Serj */ 4017282289Serj IXGBE_WRITE_REG(hw, IXGBE_WUFC, adapter->wufc); 4018282289Serj 4019282289Serj /* Enable wakeups and power management in Wakeup Control */ 4020282289Serj IXGBE_WRITE_REG(hw, IXGBE_WUC, 4021282289Serj IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN); 4022282289Serj 4023282289Serj /* X550EM baseT adapters need a special LPLU flow */ 4024282289Serj hw->phy.reset_disable = true; 4025282289Serj ixgbe_stop(adapter); 4026282289Serj error = hw->phy.ops.enter_lplu(hw); 4027282289Serj if (error) 4028282289Serj device_printf(dev, 4029282289Serj "Error entering LPLU: %d\n", error); 4030282289Serj hw->phy.reset_disable = false; 4031282289Serj } else { 4032282289Serj /* Just stop for other adapters */ 4033282289Serj ixgbe_stop(adapter); 4034282289Serj } 4035282289Serj 4036282289Serj return error; 4037282289Serj} 4038282289Serj 4039280182Sjfv/********************************************************************** 4040280182Sjfv * 4041280182Sjfv * Update the board statistics counters. 4042280182Sjfv * 4043280182Sjfv **********************************************************************/ 4044280182Sjfvstatic void 4045280182Sjfvixgbe_update_stats_counters(struct adapter *adapter) 4046280182Sjfv{ 4047280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 4048280182Sjfv u32 missed_rx = 0, bprc, lxon, lxoff, total; 4049280182Sjfv u64 total_missed_rx = 0; 4050280182Sjfv 4051280182Sjfv adapter->stats.pf.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); 4052280182Sjfv adapter->stats.pf.illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC); 4053280182Sjfv adapter->stats.pf.errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC); 4054280182Sjfv adapter->stats.pf.mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC); 4055280182Sjfv 4056280182Sjfv for (int i = 0; i < 16; i++) { 4057280182Sjfv adapter->stats.pf.qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 4058280182Sjfv adapter->stats.pf.qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 4059280182Sjfv adapter->stats.pf.qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); 4060280182Sjfv } 4061280182Sjfv adapter->stats.pf.mlfc += IXGBE_READ_REG(hw, IXGBE_MLFC); 4062280182Sjfv adapter->stats.pf.mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC); 4063280182Sjfv adapter->stats.pf.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); 4064280182Sjfv 4065280182Sjfv /* Hardware workaround, gprc counts missed packets */ 4066280182Sjfv adapter->stats.pf.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC); 4067280182Sjfv adapter->stats.pf.gprc -= missed_rx; 4068280182Sjfv 4069280182Sjfv if (hw->mac.type != ixgbe_mac_82598EB) { 4070280182Sjfv adapter->stats.pf.gorc += IXGBE_READ_REG(hw, IXGBE_GORCL) + 4071280182Sjfv ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32); 4072280182Sjfv adapter->stats.pf.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL) + 4073280182Sjfv ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32); 4074280182Sjfv adapter->stats.pf.tor += IXGBE_READ_REG(hw, IXGBE_TORL) + 4075280182Sjfv ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32); 4076280182Sjfv adapter->stats.pf.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 4077280182Sjfv adapter->stats.pf.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 4078280182Sjfv } else { 4079280182Sjfv adapter->stats.pf.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); 4080280182Sjfv adapter->stats.pf.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 4081280182Sjfv /* 82598 only has a counter in the high register */ 4082280182Sjfv adapter->stats.pf.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); 4083280182Sjfv adapter->stats.pf.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); 4084280182Sjfv adapter->stats.pf.tor += IXGBE_READ_REG(hw, IXGBE_TORH); 4085280182Sjfv } 4086280182Sjfv 4087280182Sjfv /* 4088280182Sjfv * Workaround: mprc hardware is incorrectly counting 4089280182Sjfv * broadcasts, so for now we subtract those. 4090280182Sjfv */ 4091280182Sjfv bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); 4092280182Sjfv adapter->stats.pf.bprc += bprc; 4093280182Sjfv adapter->stats.pf.mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); 4094280182Sjfv if (hw->mac.type == ixgbe_mac_82598EB) 4095280182Sjfv adapter->stats.pf.mprc -= bprc; 4096280182Sjfv 4097280182Sjfv adapter->stats.pf.prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64); 4098280182Sjfv adapter->stats.pf.prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127); 4099280182Sjfv adapter->stats.pf.prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255); 4100280182Sjfv adapter->stats.pf.prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511); 4101280182Sjfv adapter->stats.pf.prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023); 4102280182Sjfv adapter->stats.pf.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522); 4103280182Sjfv 4104280182Sjfv lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC); 4105280182Sjfv adapter->stats.pf.lxontxc += lxon; 4106280182Sjfv lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 4107280182Sjfv adapter->stats.pf.lxofftxc += lxoff; 4108280182Sjfv total = lxon + lxoff; 4109280182Sjfv 4110280182Sjfv adapter->stats.pf.gptc += IXGBE_READ_REG(hw, IXGBE_GPTC); 4111280182Sjfv adapter->stats.pf.mptc += IXGBE_READ_REG(hw, IXGBE_MPTC); 4112280182Sjfv adapter->stats.pf.ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64); 4113280182Sjfv adapter->stats.pf.gptc -= total; 4114280182Sjfv adapter->stats.pf.mptc -= total; 4115280182Sjfv adapter->stats.pf.ptc64 -= total; 4116280182Sjfv adapter->stats.pf.gotc -= total * ETHER_MIN_LEN; 4117280182Sjfv 4118280182Sjfv adapter->stats.pf.ruc += IXGBE_READ_REG(hw, IXGBE_RUC); 4119280182Sjfv adapter->stats.pf.rfc += IXGBE_READ_REG(hw, IXGBE_RFC); 4120280182Sjfv adapter->stats.pf.roc += IXGBE_READ_REG(hw, IXGBE_ROC); 4121280182Sjfv adapter->stats.pf.rjc += IXGBE_READ_REG(hw, IXGBE_RJC); 4122280182Sjfv adapter->stats.pf.mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC); 4123280182Sjfv adapter->stats.pf.mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC); 4124280182Sjfv adapter->stats.pf.mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC); 4125280182Sjfv adapter->stats.pf.tpr += IXGBE_READ_REG(hw, IXGBE_TPR); 4126280182Sjfv adapter->stats.pf.tpt += IXGBE_READ_REG(hw, IXGBE_TPT); 4127280182Sjfv adapter->stats.pf.ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127); 4128280182Sjfv adapter->stats.pf.ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255); 4129280182Sjfv adapter->stats.pf.ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511); 4130280182Sjfv adapter->stats.pf.ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023); 4131280182Sjfv adapter->stats.pf.ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522); 4132280182Sjfv adapter->stats.pf.bptc += IXGBE_READ_REG(hw, IXGBE_BPTC); 4133280182Sjfv adapter->stats.pf.xec += IXGBE_READ_REG(hw, IXGBE_XEC); 4134280182Sjfv adapter->stats.pf.fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC); 4135280182Sjfv adapter->stats.pf.fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST); 4136280182Sjfv /* Only read FCOE on 82599 */ 4137280182Sjfv if (hw->mac.type != ixgbe_mac_82598EB) { 4138280182Sjfv adapter->stats.pf.fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC); 4139280182Sjfv adapter->stats.pf.fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC); 4140280182Sjfv adapter->stats.pf.fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC); 4141280182Sjfv adapter->stats.pf.fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC); 4142280182Sjfv adapter->stats.pf.fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC); 4143280182Sjfv } 4144280182Sjfv 4145280182Sjfv /* Fill out the OS statistics structure */ 4146280182Sjfv IXGBE_SET_IPACKETS(adapter, adapter->stats.pf.gprc); 4147280182Sjfv IXGBE_SET_OPACKETS(adapter, adapter->stats.pf.gptc); 4148280182Sjfv IXGBE_SET_IBYTES(adapter, adapter->stats.pf.gorc); 4149280182Sjfv IXGBE_SET_OBYTES(adapter, adapter->stats.pf.gotc); 4150280182Sjfv IXGBE_SET_IMCASTS(adapter, adapter->stats.pf.mprc); 4151280182Sjfv IXGBE_SET_OMCASTS(adapter, adapter->stats.pf.mptc); 4152280182Sjfv IXGBE_SET_COLLISIONS(adapter, 0); 4153280182Sjfv IXGBE_SET_IQDROPS(adapter, total_missed_rx); 4154280182Sjfv IXGBE_SET_IERRORS(adapter, adapter->stats.pf.crcerrs 4155280182Sjfv + adapter->stats.pf.rlec); 4156280182Sjfv} 4157280182Sjfv 4158280182Sjfv#if __FreeBSD_version >= 1100036 4159280182Sjfvstatic uint64_t 4160280182Sjfvixgbe_get_counter(struct ifnet *ifp, ift_counter cnt) 4161280182Sjfv{ 4162280182Sjfv struct adapter *adapter; 4163282280Sjhb struct tx_ring *txr; 4164282280Sjhb uint64_t rv; 4165280182Sjfv 4166280182Sjfv adapter = if_getsoftc(ifp); 4167280182Sjfv 4168280182Sjfv switch (cnt) { 4169280182Sjfv case IFCOUNTER_IPACKETS: 4170280182Sjfv return (adapter->ipackets); 4171280182Sjfv case IFCOUNTER_OPACKETS: 4172280182Sjfv return (adapter->opackets); 4173280182Sjfv case IFCOUNTER_IBYTES: 4174280182Sjfv return (adapter->ibytes); 4175280182Sjfv case IFCOUNTER_OBYTES: 4176280182Sjfv return (adapter->obytes); 4177280182Sjfv case IFCOUNTER_IMCASTS: 4178280182Sjfv return (adapter->imcasts); 4179280182Sjfv case IFCOUNTER_OMCASTS: 4180280182Sjfv return (adapter->omcasts); 4181280182Sjfv case IFCOUNTER_COLLISIONS: 4182280182Sjfv return (0); 4183280182Sjfv case IFCOUNTER_IQDROPS: 4184280182Sjfv return (adapter->iqdrops); 4185282280Sjhb case IFCOUNTER_OQDROPS: 4186282280Sjhb rv = 0; 4187282280Sjhb txr = adapter->tx_rings; 4188282280Sjhb for (int i = 0; i < adapter->num_queues; i++, txr++) 4189282280Sjhb rv += txr->br->br_drops; 4190282280Sjhb return (rv); 4191280182Sjfv case IFCOUNTER_IERRORS: 4192280182Sjfv return (adapter->ierrors); 4193280182Sjfv default: 4194280182Sjfv return (if_get_counter_default(ifp, cnt)); 4195280182Sjfv } 4196280182Sjfv} 4197280182Sjfv#endif 4198280182Sjfv 4199280182Sjfv/** ixgbe_sysctl_tdh_handler - Handler function 4200280182Sjfv * Retrieves the TDH value from the hardware 4201280182Sjfv */ 4202280182Sjfvstatic int 4203280182Sjfvixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS) 4204280182Sjfv{ 4205280182Sjfv int error; 4206280182Sjfv 4207280182Sjfv struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); 4208280182Sjfv if (!txr) return 0; 4209280182Sjfv 4210280182Sjfv unsigned val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me)); 4211280182Sjfv error = sysctl_handle_int(oidp, &val, 0, req); 4212280182Sjfv if (error || !req->newptr) 4213280182Sjfv return error; 4214280182Sjfv return 0; 4215280182Sjfv} 4216280182Sjfv 4217280182Sjfv/** ixgbe_sysctl_tdt_handler - Handler function 4218280182Sjfv * Retrieves the TDT value from the hardware 4219280182Sjfv */ 4220280182Sjfvstatic int 4221280182Sjfvixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS) 4222280182Sjfv{ 4223280182Sjfv int error; 4224280182Sjfv 4225280182Sjfv struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); 4226280182Sjfv if (!txr) return 0; 4227280182Sjfv 4228280182Sjfv unsigned val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me)); 4229280182Sjfv error = sysctl_handle_int(oidp, &val, 0, req); 4230280182Sjfv if (error || !req->newptr) 4231280182Sjfv return error; 4232280182Sjfv return 0; 4233280182Sjfv} 4234280182Sjfv 4235280182Sjfv/** ixgbe_sysctl_rdh_handler - Handler function 4236280182Sjfv * Retrieves the RDH value from the hardware 4237280182Sjfv */ 4238280182Sjfvstatic int 4239280182Sjfvixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS) 4240280182Sjfv{ 4241280182Sjfv int error; 4242280182Sjfv 4243280182Sjfv struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); 4244280182Sjfv if (!rxr) return 0; 4245280182Sjfv 4246280182Sjfv unsigned val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me)); 4247280182Sjfv error = sysctl_handle_int(oidp, &val, 0, req); 4248280182Sjfv if (error || !req->newptr) 4249280182Sjfv return error; 4250280182Sjfv return 0; 4251280182Sjfv} 4252280182Sjfv 4253280182Sjfv/** ixgbe_sysctl_rdt_handler - Handler function 4254280182Sjfv * Retrieves the RDT value from the hardware 4255280182Sjfv */ 4256280182Sjfvstatic int 4257280182Sjfvixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS) 4258280182Sjfv{ 4259280182Sjfv int error; 4260280182Sjfv 4261280182Sjfv struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); 4262280182Sjfv if (!rxr) return 0; 4263280182Sjfv 4264280182Sjfv unsigned val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me)); 4265280182Sjfv error = sysctl_handle_int(oidp, &val, 0, req); 4266280182Sjfv if (error || !req->newptr) 4267280182Sjfv return error; 4268280182Sjfv return 0; 4269280182Sjfv} 4270280182Sjfv 4271280182Sjfvstatic int 4272280182Sjfvixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS) 4273280182Sjfv{ 4274280182Sjfv int error; 4275280182Sjfv struct ix_queue *que = ((struct ix_queue *)oidp->oid_arg1); 4276280182Sjfv unsigned int reg, usec, rate; 4277280182Sjfv 4278280182Sjfv reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix)); 4279280182Sjfv usec = ((reg & 0x0FF8) >> 3); 4280280182Sjfv if (usec > 0) 4281280182Sjfv rate = 500000 / usec; 4282280182Sjfv else 4283280182Sjfv rate = 0; 4284280182Sjfv error = sysctl_handle_int(oidp, &rate, 0, req); 4285280182Sjfv if (error || !req->newptr) 4286280182Sjfv return error; 4287280182Sjfv reg &= ~0xfff; /* default, no limitation */ 4288280182Sjfv ixgbe_max_interrupt_rate = 0; 4289280182Sjfv if (rate > 0 && rate < 500000) { 4290280182Sjfv if (rate < 1000) 4291280182Sjfv rate = 1000; 4292280182Sjfv ixgbe_max_interrupt_rate = rate; 4293280182Sjfv reg |= ((4000000/rate) & 0xff8 ); 4294280182Sjfv } 4295280182Sjfv IXGBE_WRITE_REG(&que->adapter->hw, IXGBE_EITR(que->msix), reg); 4296280182Sjfv return 0; 4297280182Sjfv} 4298280182Sjfv 4299282289Serjstatic void 4300282289Serjixgbe_add_device_sysctls(struct adapter *adapter) 4301282289Serj{ 4302282289Serj device_t dev = adapter->dev; 4303282289Serj struct ixgbe_hw *hw = &adapter->hw; 4304282289Serj struct sysctl_oid_list *child; 4305282289Serj struct sysctl_ctx_list *ctx; 4306282289Serj 4307282289Serj ctx = device_get_sysctl_ctx(dev); 4308282289Serj child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); 4309282289Serj 4310282289Serj /* Sysctls for all devices */ 4311282289Serj SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fc", 4312282289Serj CTLTYPE_INT | CTLFLAG_RW, adapter, 0, 4313294795Ssmh ixgbe_sysctl_flowcntl, "I", IXGBE_SYSCTL_DESC_SET_FC); 4314282289Serj 4315282289Serj SYSCTL_ADD_INT(ctx, child, OID_AUTO, "enable_aim", 4316282289Serj CTLFLAG_RW, 4317282289Serj &ixgbe_enable_aim, 1, "Interrupt Moderation"); 4318282289Serj 4319282289Serj SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "advertise_speed", 4320282289Serj CTLTYPE_INT | CTLFLAG_RW, adapter, 0, 4321294795Ssmh ixgbe_sysctl_advertise, "I", IXGBE_SYSCTL_DESC_ADV_SPEED); 4322282289Serj 4323282289Serj SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "thermal_test", 4324282289Serj CTLTYPE_INT | CTLFLAG_RW, adapter, 0, 4325282289Serj ixgbe_sysctl_thermal_test, "I", "Thermal Test"); 4326282289Serj 4327292674Ssbruno#ifdef IXGBE_DEBUG 4328292674Ssbruno /* testing sysctls (for all devices) */ 4329292674Ssbruno SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "power_state", 4330292674Ssbruno CTLTYPE_INT | CTLFLAG_RW, adapter, 0, 4331292674Ssbruno ixgbe_sysctl_power_state, "I", "PCI Power State"); 4332292674Ssbruno 4333292674Ssbruno SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "print_rss_config", 4334292674Ssbruno CTLTYPE_STRING | CTLFLAG_RD, adapter, 0, 4335292674Ssbruno ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration"); 4336292674Ssbruno#endif 4337292674Ssbruno /* for X550 series devices */ 4338282289Serj if (hw->mac.type >= ixgbe_mac_X550) 4339282289Serj SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "dmac", 4340282289Serj CTLTYPE_INT | CTLFLAG_RW, adapter, 0, 4341282289Serj ixgbe_sysctl_dmac, "I", "DMA Coalesce"); 4342282289Serj 4343292674Ssbruno /* for X552 backplane devices */ 4344292674Ssbruno if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) { 4345282289Serj struct sysctl_oid *eee_node; 4346282289Serj struct sysctl_oid_list *eee_list; 4347282289Serj 4348282289Serj eee_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "eee", 4349282289Serj CTLFLAG_RD, NULL, 4350282289Serj "Energy Efficient Ethernet sysctls"); 4351282289Serj eee_list = SYSCTL_CHILDREN(eee_node); 4352282289Serj 4353282289Serj SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "enable", 4354282289Serj CTLTYPE_INT | CTLFLAG_RW, adapter, 0, 4355282289Serj ixgbe_sysctl_eee_enable, "I", 4356282289Serj "Enable or Disable EEE"); 4357282289Serj 4358282289Serj SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "negotiated", 4359282289Serj CTLTYPE_INT | CTLFLAG_RD, adapter, 0, 4360282289Serj ixgbe_sysctl_eee_negotiated, "I", 4361282289Serj "EEE negotiated on link"); 4362282289Serj 4363282289Serj SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "tx_lpi_status", 4364282289Serj CTLTYPE_INT | CTLFLAG_RD, adapter, 0, 4365282289Serj ixgbe_sysctl_eee_tx_lpi_status, "I", 4366282289Serj "Whether or not TX link is in LPI state"); 4367282289Serj 4368282289Serj SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "rx_lpi_status", 4369282289Serj CTLTYPE_INT | CTLFLAG_RD, adapter, 0, 4370282289Serj ixgbe_sysctl_eee_rx_lpi_status, "I", 4371282289Serj "Whether or not RX link is in LPI state"); 4372292674Ssbruno 4373292674Ssbruno SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "tx_lpi_delay", 4374292674Ssbruno CTLTYPE_INT | CTLFLAG_RD, adapter, 0, 4375292674Ssbruno ixgbe_sysctl_eee_tx_lpi_delay, "I", 4376292674Ssbruno "TX LPI entry delay in microseconds"); 4377282289Serj } 4378282289Serj 4379292674Ssbruno /* for WoL-capable devices */ 4380292674Ssbruno if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { 4381282289Serj SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "wol_enable", 4382282289Serj CTLTYPE_INT | CTLFLAG_RW, adapter, 0, 4383282289Serj ixgbe_sysctl_wol_enable, "I", 4384282289Serj "Enable/Disable Wake on LAN"); 4385282289Serj 4386282289Serj SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "wufc", 4387282289Serj CTLTYPE_INT | CTLFLAG_RW, adapter, 0, 4388282289Serj ixgbe_sysctl_wufc, "I", 4389282289Serj "Enable/Disable Wake Up Filters"); 4390282289Serj } 4391282289Serj 4392292674Ssbruno /* for X552/X557-AT devices */ 4393282289Serj if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { 4394282289Serj struct sysctl_oid *phy_node; 4395282289Serj struct sysctl_oid_list *phy_list; 4396282289Serj 4397282289Serj phy_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "phy", 4398282289Serj CTLFLAG_RD, NULL, 4399282289Serj "External PHY sysctls"); 4400282289Serj phy_list = SYSCTL_CHILDREN(phy_node); 4401282289Serj 4402282289Serj SYSCTL_ADD_PROC(ctx, phy_list, OID_AUTO, "temp", 4403282289Serj CTLTYPE_INT | CTLFLAG_RD, adapter, 0, 4404282289Serj ixgbe_sysctl_phy_temp, "I", 4405282289Serj "Current External PHY Temperature (Celsius)"); 4406282289Serj 4407282289Serj SYSCTL_ADD_PROC(ctx, phy_list, OID_AUTO, "overtemp_occurred", 4408282289Serj CTLTYPE_INT | CTLFLAG_RD, adapter, 0, 4409282289Serj ixgbe_sysctl_phy_overtemp_occurred, "I", 4410282289Serj "External PHY High Temperature Event Occurred"); 4411282289Serj } 4412282289Serj} 4413282289Serj 4414280182Sjfv/* 4415280182Sjfv * Add sysctl variables, one per statistic, to the system. 4416280182Sjfv */ 4417280182Sjfvstatic void 4418280182Sjfvixgbe_add_hw_stats(struct adapter *adapter) 4419280182Sjfv{ 4420280182Sjfv device_t dev = adapter->dev; 4421280182Sjfv 4422280182Sjfv struct tx_ring *txr = adapter->tx_rings; 4423280182Sjfv struct rx_ring *rxr = adapter->rx_rings; 4424280182Sjfv 4425280182Sjfv struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 4426280182Sjfv struct sysctl_oid *tree = device_get_sysctl_tree(dev); 4427280182Sjfv struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); 4428280182Sjfv struct ixgbe_hw_stats *stats = &adapter->stats.pf; 4429280182Sjfv 4430280182Sjfv struct sysctl_oid *stat_node, *queue_node; 4431280182Sjfv struct sysctl_oid_list *stat_list, *queue_list; 4432280182Sjfv 4433280182Sjfv#define QUEUE_NAME_LEN 32 4434280182Sjfv char namebuf[QUEUE_NAME_LEN]; 4435280182Sjfv 4436280182Sjfv /* Driver Statistics */ 4437280182Sjfv SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", 4438280182Sjfv CTLFLAG_RD, &adapter->dropped_pkts, 4439280182Sjfv "Driver dropped packets"); 4440280182Sjfv SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_failed", 4441280182Sjfv CTLFLAG_RD, &adapter->mbuf_defrag_failed, 4442280182Sjfv "m_defrag() failed"); 4443280182Sjfv SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events", 4444280182Sjfv CTLFLAG_RD, &adapter->watchdog_events, 4445280182Sjfv "Watchdog timeouts"); 4446280182Sjfv SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq", 4447282289Serj CTLFLAG_RD, &adapter->link_irq, 4448280182Sjfv "Link MSIX IRQ Handled"); 4449280182Sjfv 4450280182Sjfv for (int i = 0; i < adapter->num_queues; i++, txr++) { 4451280182Sjfv snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); 4452280182Sjfv queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, 4453280182Sjfv CTLFLAG_RD, NULL, "Queue Name"); 4454280182Sjfv queue_list = SYSCTL_CHILDREN(queue_node); 4455280182Sjfv 4456280182Sjfv SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate", 4457280182Sjfv CTLTYPE_UINT | CTLFLAG_RW, &adapter->queues[i], 4458280182Sjfv sizeof(&adapter->queues[i]), 4459280182Sjfv ixgbe_sysctl_interrupt_rate_handler, "IU", 4460280182Sjfv "Interrupt Rate"); 4461280182Sjfv SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs", 4462280182Sjfv CTLFLAG_RD, &(adapter->queues[i].irqs), 4463280182Sjfv "irqs on this queue"); 4464280182Sjfv SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head", 4465280182Sjfv CTLTYPE_UINT | CTLFLAG_RD, txr, sizeof(txr), 4466280182Sjfv ixgbe_sysctl_tdh_handler, "IU", 4467280182Sjfv "Transmit Descriptor Head"); 4468280182Sjfv SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail", 4469280182Sjfv CTLTYPE_UINT | CTLFLAG_RD, txr, sizeof(txr), 4470280182Sjfv ixgbe_sysctl_tdt_handler, "IU", 4471280182Sjfv "Transmit Descriptor Tail"); 4472280182Sjfv SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "tso_tx", 4473280182Sjfv CTLFLAG_RD, &txr->tso_tx, 4474280182Sjfv "TSO"); 4475280182Sjfv SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "no_tx_dma_setup", 4476280182Sjfv CTLFLAG_RD, &txr->no_tx_dma_setup, 4477280182Sjfv "Driver tx dma failure in xmit"); 4478280182Sjfv SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "no_desc_avail", 4479280182Sjfv CTLFLAG_RD, &txr->no_desc_avail, 4480280182Sjfv "Queue No Descriptor Available"); 4481280182Sjfv SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets", 4482280182Sjfv CTLFLAG_RD, &txr->total_packets, 4483280182Sjfv "Queue Packets Transmitted"); 4484282280Sjhb SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "br_drops", 4485282280Sjhb CTLFLAG_RD, &txr->br->br_drops, 4486282280Sjhb "Packets dropped in buf_ring"); 4487280182Sjfv } 4488280182Sjfv 4489280182Sjfv for (int i = 0; i < adapter->num_queues; i++, rxr++) { 4490280182Sjfv snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); 4491280182Sjfv queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, 4492280182Sjfv CTLFLAG_RD, NULL, "Queue Name"); 4493280182Sjfv queue_list = SYSCTL_CHILDREN(queue_node); 4494280182Sjfv 4495280182Sjfv struct lro_ctrl *lro = &rxr->lro; 4496280182Sjfv 4497280182Sjfv snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); 4498280182Sjfv queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, 4499280182Sjfv CTLFLAG_RD, NULL, "Queue Name"); 4500280182Sjfv queue_list = SYSCTL_CHILDREN(queue_node); 4501280182Sjfv 4502280182Sjfv SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head", 4503280182Sjfv CTLTYPE_UINT | CTLFLAG_RD, rxr, sizeof(rxr), 4504280182Sjfv ixgbe_sysctl_rdh_handler, "IU", 4505280182Sjfv "Receive Descriptor Head"); 4506280182Sjfv SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail", 4507280182Sjfv CTLTYPE_UINT | CTLFLAG_RD, rxr, sizeof(rxr), 4508280182Sjfv ixgbe_sysctl_rdt_handler, "IU", 4509280182Sjfv "Receive Descriptor Tail"); 4510280182Sjfv SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets", 4511280182Sjfv CTLFLAG_RD, &rxr->rx_packets, 4512280182Sjfv "Queue Packets Received"); 4513280182Sjfv SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes", 4514280182Sjfv CTLFLAG_RD, &rxr->rx_bytes, 4515280182Sjfv "Queue Bytes Received"); 4516280182Sjfv SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_copies", 4517280182Sjfv CTLFLAG_RD, &rxr->rx_copies, 4518280182Sjfv "Copied RX Frames"); 4519294327Shselasky SYSCTL_ADD_U64(ctx, queue_list, OID_AUTO, "lro_queued", 4520280182Sjfv CTLFLAG_RD, &lro->lro_queued, 0, 4521280182Sjfv "LRO Queued"); 4522294327Shselasky SYSCTL_ADD_U64(ctx, queue_list, OID_AUTO, "lro_flushed", 4523280182Sjfv CTLFLAG_RD, &lro->lro_flushed, 0, 4524280182Sjfv "LRO Flushed"); 4525280182Sjfv } 4526280182Sjfv 4527280182Sjfv /* MAC stats get the own sub node */ 4528280182Sjfv 4529280182Sjfv stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats", 4530280182Sjfv CTLFLAG_RD, NULL, "MAC Statistics"); 4531280182Sjfv stat_list = SYSCTL_CHILDREN(stat_node); 4532280182Sjfv 4533280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs", 4534280182Sjfv CTLFLAG_RD, &stats->crcerrs, 4535280182Sjfv "CRC Errors"); 4536280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ill_errs", 4537280182Sjfv CTLFLAG_RD, &stats->illerrc, 4538280182Sjfv "Illegal Byte Errors"); 4539280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "byte_errs", 4540280182Sjfv CTLFLAG_RD, &stats->errbc, 4541280182Sjfv "Byte Errors"); 4542280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "short_discards", 4543280182Sjfv CTLFLAG_RD, &stats->mspdc, 4544280182Sjfv "MAC Short Packets Discarded"); 4545280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "local_faults", 4546280182Sjfv CTLFLAG_RD, &stats->mlfc, 4547280182Sjfv "MAC Local Faults"); 4548280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "remote_faults", 4549280182Sjfv CTLFLAG_RD, &stats->mrfc, 4550280182Sjfv "MAC Remote Faults"); 4551280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rec_len_errs", 4552280182Sjfv CTLFLAG_RD, &stats->rlec, 4553280182Sjfv "Receive Length Errors"); 4554280182Sjfv 4555280182Sjfv /* Flow Control stats */ 4556280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd", 4557280182Sjfv CTLFLAG_RD, &stats->lxontxc, 4558280182Sjfv "Link XON Transmitted"); 4559280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd", 4560280182Sjfv CTLFLAG_RD, &stats->lxonrxc, 4561280182Sjfv "Link XON Received"); 4562280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd", 4563280182Sjfv CTLFLAG_RD, &stats->lxofftxc, 4564280182Sjfv "Link XOFF Transmitted"); 4565280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd", 4566280182Sjfv CTLFLAG_RD, &stats->lxoffrxc, 4567280182Sjfv "Link XOFF Received"); 4568280182Sjfv 4569280182Sjfv /* Packet Reception Stats */ 4570280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_octets_rcvd", 4571280182Sjfv CTLFLAG_RD, &stats->tor, 4572280182Sjfv "Total Octets Received"); 4573280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd", 4574280182Sjfv CTLFLAG_RD, &stats->gorc, 4575280182Sjfv "Good Octets Received"); 4576280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_rcvd", 4577280182Sjfv CTLFLAG_RD, &stats->tpr, 4578280182Sjfv "Total Packets Received"); 4579280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd", 4580280182Sjfv CTLFLAG_RD, &stats->gprc, 4581280182Sjfv "Good Packets Received"); 4582280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd", 4583280182Sjfv CTLFLAG_RD, &stats->mprc, 4584280182Sjfv "Multicast Packets Received"); 4585280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_rcvd", 4586280182Sjfv CTLFLAG_RD, &stats->bprc, 4587280182Sjfv "Broadcast Packets Received"); 4588280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64", 4589280182Sjfv CTLFLAG_RD, &stats->prc64, 4590280182Sjfv "64 byte frames received "); 4591280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127", 4592280182Sjfv CTLFLAG_RD, &stats->prc127, 4593280182Sjfv "65-127 byte frames received"); 4594280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255", 4595280182Sjfv CTLFLAG_RD, &stats->prc255, 4596280182Sjfv "128-255 byte frames received"); 4597280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511", 4598280182Sjfv CTLFLAG_RD, &stats->prc511, 4599280182Sjfv "256-511 byte frames received"); 4600280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023", 4601280182Sjfv CTLFLAG_RD, &stats->prc1023, 4602280182Sjfv "512-1023 byte frames received"); 4603280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522", 4604280182Sjfv CTLFLAG_RD, &stats->prc1522, 4605280182Sjfv "1023-1522 byte frames received"); 4606280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersized", 4607280182Sjfv CTLFLAG_RD, &stats->ruc, 4608280182Sjfv "Receive Undersized"); 4609280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented", 4610280182Sjfv CTLFLAG_RD, &stats->rfc, 4611280182Sjfv "Fragmented Packets Received "); 4612280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversized", 4613280182Sjfv CTLFLAG_RD, &stats->roc, 4614280182Sjfv "Oversized Packets Received"); 4615280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabberd", 4616280182Sjfv CTLFLAG_RD, &stats->rjc, 4617280182Sjfv "Received Jabber"); 4618280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_rcvd", 4619280182Sjfv CTLFLAG_RD, &stats->mngprc, 4620280182Sjfv "Management Packets Received"); 4621280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_drpd", 4622280182Sjfv CTLFLAG_RD, &stats->mngptc, 4623280182Sjfv "Management Packets Dropped"); 4624280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "checksum_errs", 4625280182Sjfv CTLFLAG_RD, &stats->xec, 4626280182Sjfv "Checksum Errors"); 4627280182Sjfv 4628280182Sjfv /* Packet Transmission Stats */ 4629280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd", 4630280182Sjfv CTLFLAG_RD, &stats->gotc, 4631280182Sjfv "Good Octets Transmitted"); 4632280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd", 4633280182Sjfv CTLFLAG_RD, &stats->tpt, 4634280182Sjfv "Total Packets Transmitted"); 4635280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd", 4636280182Sjfv CTLFLAG_RD, &stats->gptc, 4637280182Sjfv "Good Packets Transmitted"); 4638280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd", 4639280182Sjfv CTLFLAG_RD, &stats->bptc, 4640280182Sjfv "Broadcast Packets Transmitted"); 4641280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd", 4642280182Sjfv CTLFLAG_RD, &stats->mptc, 4643280182Sjfv "Multicast Packets Transmitted"); 4644280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_txd", 4645280182Sjfv CTLFLAG_RD, &stats->mngptc, 4646280182Sjfv "Management Packets Transmitted"); 4647280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64", 4648280182Sjfv CTLFLAG_RD, &stats->ptc64, 4649280182Sjfv "64 byte frames transmitted "); 4650280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127", 4651280182Sjfv CTLFLAG_RD, &stats->ptc127, 4652280182Sjfv "65-127 byte frames transmitted"); 4653280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255", 4654280182Sjfv CTLFLAG_RD, &stats->ptc255, 4655280182Sjfv "128-255 byte frames transmitted"); 4656280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511", 4657280182Sjfv CTLFLAG_RD, &stats->ptc511, 4658280182Sjfv "256-511 byte frames transmitted"); 4659280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023", 4660280182Sjfv CTLFLAG_RD, &stats->ptc1023, 4661280182Sjfv "512-1023 byte frames transmitted"); 4662280182Sjfv SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522", 4663280182Sjfv CTLFLAG_RD, &stats->ptc1522, 4664280182Sjfv "1024-1522 byte frames transmitted"); 4665280182Sjfv} 4666280182Sjfv 4667289238Ssbrunostatic void 4668289238Ssbrunoixgbe_set_sysctl_value(struct adapter *adapter, const char *name, 4669289238Ssbruno const char *description, int *limit, int value) 4670289238Ssbruno{ 4671289238Ssbruno *limit = value; 4672289238Ssbruno SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev), 4673289238Ssbruno SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 4674289238Ssbruno OID_AUTO, name, CTLFLAG_RW, limit, value, description); 4675289238Ssbruno} 4676289238Ssbruno 4677280182Sjfv/* 4678280182Sjfv** Set flow control using sysctl: 4679280182Sjfv** Flow control values: 4680280182Sjfv** 0 - off 4681280182Sjfv** 1 - rx pause 4682280182Sjfv** 2 - tx pause 4683280182Sjfv** 3 - full 4684280182Sjfv*/ 4685280182Sjfvstatic int 4686294795Ssmhixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS) 4687280182Sjfv{ 4688294795Ssmh int error, fc; 4689294795Ssmh struct adapter *adapter; 4690280182Sjfv 4691294795Ssmh adapter = (struct adapter *) arg1; 4692294795Ssmh fc = adapter->fc; 4693294795Ssmh 4694294795Ssmh error = sysctl_handle_int(oidp, &fc, 0, req); 4695280182Sjfv if ((error) || (req->newptr == NULL)) 4696280182Sjfv return (error); 4697280182Sjfv 4698280182Sjfv /* Don't bother if it's not changed */ 4699294795Ssmh if (adapter->fc == fc) 4700280182Sjfv return (0); 4701280182Sjfv 4702294795Ssmh return ixgbe_set_flowcntl(adapter, fc); 4703294795Ssmh} 4704294795Ssmh 4705294795Ssmh 4706294795Ssmhstatic int 4707294795Ssmhixgbe_set_flowcntl(struct adapter *adapter, int fc) 4708294795Ssmh{ 4709294795Ssmh 4710294795Ssmh switch (fc) { 4711294795Ssmh case ixgbe_fc_rx_pause: 4712294795Ssmh case ixgbe_fc_tx_pause: 4713294795Ssmh case ixgbe_fc_full: 4714294795Ssmh adapter->hw.fc.requested_mode = adapter->fc; 4715294795Ssmh if (adapter->num_queues > 1) 4716294795Ssmh ixgbe_disable_rx_drop(adapter); 4717294795Ssmh break; 4718294795Ssmh case ixgbe_fc_none: 4719294795Ssmh adapter->hw.fc.requested_mode = ixgbe_fc_none; 4720294795Ssmh if (adapter->num_queues > 1) 4721294795Ssmh ixgbe_enable_rx_drop(adapter); 4722294795Ssmh break; 4723294795Ssmh default: 4724294795Ssmh return (EINVAL); 4725280182Sjfv } 4726294795Ssmh adapter->fc = fc; 4727280182Sjfv /* Don't autoneg if forcing a value */ 4728280182Sjfv adapter->hw.fc.disable_fc_autoneg = TRUE; 4729280182Sjfv ixgbe_fc_enable(&adapter->hw); 4730294795Ssmh return (0); 4731280182Sjfv} 4732280182Sjfv 4733280182Sjfv/* 4734280182Sjfv** Control advertised link speed: 4735280182Sjfv** Flags: 4736280182Sjfv** 0x1 - advertise 100 Mb 4737280182Sjfv** 0x2 - advertise 1G 4738280182Sjfv** 0x4 - advertise 10G 4739280182Sjfv*/ 4740280182Sjfvstatic int 4741294795Ssmhixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS) 4742280182Sjfv{ 4743294795Ssmh int error, advertise; 4744294795Ssmh struct adapter *adapter; 4745280182Sjfv 4746280182Sjfv adapter = (struct adapter *) arg1; 4747294795Ssmh advertise = adapter->advertise; 4748280182Sjfv 4749294795Ssmh error = sysctl_handle_int(oidp, &advertise, 0, req); 4750280182Sjfv if ((error) || (req->newptr == NULL)) 4751280182Sjfv return (error); 4752280182Sjfv 4753294795Ssmh return ixgbe_set_advertise(adapter, advertise); 4754294795Ssmh} 4755294795Ssmh 4756294795Ssmhstatic int 4757294795Ssmhixgbe_set_advertise(struct adapter *adapter, int advertise) 4758294795Ssmh{ 4759294795Ssmh device_t dev; 4760294795Ssmh struct ixgbe_hw *hw; 4761294795Ssmh ixgbe_link_speed speed; 4762294795Ssmh 4763296922Ssmh /* Checks to validate new value */ 4764296922Ssmh if (adapter->advertise == advertise) /* no change */ 4765296922Ssmh return (0); 4766296922Ssmh 4767294795Ssmh hw = &adapter->hw; 4768294795Ssmh dev = adapter->dev; 4769294795Ssmh 4770292674Ssbruno /* No speed changes for backplane media */ 4771292674Ssbruno if (hw->phy.media_type == ixgbe_media_type_backplane) 4772292674Ssbruno return (ENODEV); 4773292674Ssbruno 4774280182Sjfv if (!((hw->phy.media_type == ixgbe_media_type_copper) || 4775280182Sjfv (hw->phy.multispeed_fiber))) { 4776280182Sjfv device_printf(dev, 4777280182Sjfv "Advertised speed can only be set on copper or " 4778280182Sjfv "multispeed fiber media types.\n"); 4779280182Sjfv return (EINVAL); 4780280182Sjfv } 4781280182Sjfv 4782294795Ssmh if (advertise < 0x1 || advertise > 0x7) { 4783280182Sjfv device_printf(dev, 4784280182Sjfv "Invalid advertised speed; valid modes are 0x1 through 0x7\n"); 4785280182Sjfv return (EINVAL); 4786280182Sjfv } 4787280182Sjfv 4788294795Ssmh if ((advertise & 0x1) 4789280182Sjfv && (hw->mac.type != ixgbe_mac_X540) 4790280182Sjfv && (hw->mac.type != ixgbe_mac_X550)) { 4791280182Sjfv device_printf(dev, "Set Advertise: 100Mb on X540/X550 only\n"); 4792280182Sjfv return (EINVAL); 4793280182Sjfv } 4794280182Sjfv 4795280182Sjfv /* Set new value and report new advertised mode */ 4796294795Ssmh speed = 0; 4797294795Ssmh if (advertise & 0x1) 4798280182Sjfv speed |= IXGBE_LINK_SPEED_100_FULL; 4799294795Ssmh if (advertise & 0x2) 4800280182Sjfv speed |= IXGBE_LINK_SPEED_1GB_FULL; 4801294795Ssmh if (advertise & 0x4) 4802280182Sjfv speed |= IXGBE_LINK_SPEED_10GB_FULL; 4803294795Ssmh adapter->advertise = advertise; 4804280182Sjfv 4805280182Sjfv hw->mac.autotry_restart = TRUE; 4806280182Sjfv hw->mac.ops.setup_link(hw, speed, TRUE); 4807280182Sjfv 4808294795Ssmh return (0); 4809280182Sjfv} 4810280182Sjfv 4811280182Sjfv/* 4812292674Ssbruno * The following two sysctls are for X552/X557-AT devices; 4813282289Serj * they deal with the external PHY used in them. 4814282289Serj */ 4815280182Sjfvstatic int 4816282289Serjixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS) 4817280182Sjfv{ 4818280182Sjfv struct adapter *adapter = (struct adapter *) arg1; 4819280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 4820282289Serj u16 reg; 4821280182Sjfv 4822282289Serj if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { 4823282289Serj device_printf(adapter->dev, 4824282289Serj "Device has no supported external thermal sensor.\n"); 4825282289Serj return (ENODEV); 4826282289Serj } 4827280182Sjfv 4828282289Serj if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP, 4829282289Serj IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 4830282289Serj ®)) { 4831282289Serj device_printf(adapter->dev, 4832282289Serj "Error reading from PHY's current temperature register\n"); 4833282289Serj return (EAGAIN); 4834282289Serj } 4835280182Sjfv 4836282289Serj /* Shift temp for output */ 4837282289Serj reg = reg >> 8; 4838282289Serj 4839282289Serj return (sysctl_handle_int(oidp, NULL, reg, req)); 4840282289Serj} 4841282289Serj 4842282289Serj/* 4843282289Serj * Reports whether the current PHY temperature is over 4844282289Serj * the overtemp threshold. 4845282289Serj * - This is reported directly from the PHY 4846282289Serj */ 4847282289Serjstatic int 4848282289Serjixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS) 4849282289Serj{ 4850282289Serj struct adapter *adapter = (struct adapter *) arg1; 4851282289Serj struct ixgbe_hw *hw = &adapter->hw; 4852282289Serj u16 reg; 4853282289Serj 4854282289Serj if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { 4855282289Serj device_printf(adapter->dev, 4856282289Serj "Device has no supported external thermal sensor.\n"); 4857282289Serj return (ENODEV); 4858282289Serj } 4859282289Serj 4860282289Serj if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS, 4861282289Serj IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 4862282289Serj ®)) { 4863282289Serj device_printf(adapter->dev, 4864282289Serj "Error reading from PHY's temperature status register\n"); 4865282289Serj return (EAGAIN); 4866282289Serj } 4867282289Serj 4868282289Serj /* Get occurrence bit */ 4869282289Serj reg = !!(reg & 0x4000); 4870282289Serj return (sysctl_handle_int(oidp, 0, reg, req)); 4871282289Serj} 4872282289Serj 4873282289Serj/* 4874282289Serj** Thermal Shutdown Trigger (internal MAC) 4875282289Serj** - Set this to 1 to cause an overtemp event to occur 4876282289Serj*/ 4877282289Serjstatic int 4878282289Serjixgbe_sysctl_thermal_test(SYSCTL_HANDLER_ARGS) 4879282289Serj{ 4880282289Serj struct adapter *adapter = (struct adapter *) arg1; 4881282289Serj struct ixgbe_hw *hw = &adapter->hw; 4882282289Serj int error, fire = 0; 4883282289Serj 4884280182Sjfv error = sysctl_handle_int(oidp, &fire, 0, req); 4885280182Sjfv if ((error) || (req->newptr == NULL)) 4886280182Sjfv return (error); 4887280182Sjfv 4888280182Sjfv if (fire) { 4889280182Sjfv u32 reg = IXGBE_READ_REG(hw, IXGBE_EICS); 4890280182Sjfv reg |= IXGBE_EICR_TS; 4891280182Sjfv IXGBE_WRITE_REG(hw, IXGBE_EICS, reg); 4892280182Sjfv } 4893280182Sjfv 4894280182Sjfv return (0); 4895280182Sjfv} 4896280182Sjfv 4897280182Sjfv/* 4898282289Serj** Manage DMA Coalescing. 4899282289Serj** Control values: 4900282289Serj** 0/1 - off / on (use default value of 1000) 4901282289Serj** 4902282289Serj** Legal timer values are: 4903282289Serj** 50,100,250,500,1000,2000,5000,10000 4904282289Serj** 4905282289Serj** Turning off interrupt moderation will also turn this off. 4906282289Serj*/ 4907282289Serjstatic int 4908282289Serjixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS) 4909282289Serj{ 4910282289Serj struct adapter *adapter = (struct adapter *) arg1; 4911282289Serj struct ifnet *ifp = adapter->ifp; 4912282289Serj int error; 4913292674Ssbruno u32 newval; 4914282289Serj 4915292674Ssbruno newval = adapter->dmac; 4916292674Ssbruno error = sysctl_handle_int(oidp, &newval, 0, req); 4917282289Serj if ((error) || (req->newptr == NULL)) 4918282289Serj return (error); 4919282289Serj 4920292674Ssbruno switch (newval) { 4921282289Serj case 0: 4922282289Serj /* Disabled */ 4923292674Ssbruno adapter->dmac = 0; 4924282289Serj break; 4925292674Ssbruno case 1: 4926292674Ssbruno /* Enable and use default */ 4927282289Serj adapter->dmac = 1000; 4928282289Serj break; 4929282289Serj case 50: 4930282289Serj case 100: 4931282289Serj case 250: 4932282289Serj case 500: 4933282289Serj case 1000: 4934282289Serj case 2000: 4935282289Serj case 5000: 4936282289Serj case 10000: 4937282289Serj /* Legal values - allow */ 4938292674Ssbruno adapter->dmac = newval; 4939282289Serj break; 4940282289Serj default: 4941282289Serj /* Do nothing, illegal value */ 4942282289Serj return (EINVAL); 4943282289Serj } 4944282289Serj 4945282289Serj /* Re-initialize hardware if it's already running */ 4946282289Serj if (ifp->if_drv_flags & IFF_DRV_RUNNING) 4947282289Serj ixgbe_init(adapter); 4948282289Serj 4949282289Serj return (0); 4950282289Serj} 4951282289Serj 4952292674Ssbruno#ifdef IXGBE_DEBUG 4953292674Ssbruno/** 4954292674Ssbruno * Sysctl to test power states 4955292674Ssbruno * Values: 4956292674Ssbruno * 0 - set device to D0 4957292674Ssbruno * 3 - set device to D3 4958292674Ssbruno * (none) - get current device power state 4959292674Ssbruno */ 4960292674Ssbrunostatic int 4961292674Ssbrunoixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS) 4962292674Ssbruno{ 4963292674Ssbruno struct adapter *adapter = (struct adapter *) arg1; 4964292674Ssbruno device_t dev = adapter->dev; 4965292674Ssbruno int curr_ps, new_ps, error = 0; 4966292674Ssbruno 4967292674Ssbruno curr_ps = new_ps = pci_get_powerstate(dev); 4968292674Ssbruno 4969292674Ssbruno error = sysctl_handle_int(oidp, &new_ps, 0, req); 4970292674Ssbruno if ((error) || (req->newptr == NULL)) 4971292674Ssbruno return (error); 4972292674Ssbruno 4973292674Ssbruno if (new_ps == curr_ps) 4974292674Ssbruno return (0); 4975292674Ssbruno 4976292674Ssbruno if (new_ps == 3 && curr_ps == 0) 4977292674Ssbruno error = DEVICE_SUSPEND(dev); 4978292674Ssbruno else if (new_ps == 0 && curr_ps == 3) 4979292674Ssbruno error = DEVICE_RESUME(dev); 4980292674Ssbruno else 4981292674Ssbruno return (EINVAL); 4982292674Ssbruno 4983292674Ssbruno device_printf(dev, "New state: %d\n", pci_get_powerstate(dev)); 4984292674Ssbruno 4985292674Ssbruno return (error); 4986292674Ssbruno} 4987292674Ssbruno#endif 4988282289Serj/* 4989282289Serj * Sysctl to enable/disable the WoL capability, if supported by the adapter. 4990282289Serj * Values: 4991282289Serj * 0 - disabled 4992282289Serj * 1 - enabled 4993282289Serj */ 4994282289Serjstatic int 4995282289Serjixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS) 4996282289Serj{ 4997282289Serj struct adapter *adapter = (struct adapter *) arg1; 4998282289Serj struct ixgbe_hw *hw = &adapter->hw; 4999282289Serj int new_wol_enabled; 5000282289Serj int error = 0; 5001282289Serj 5002282289Serj new_wol_enabled = hw->wol_enabled; 5003282289Serj error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req); 5004282289Serj if ((error) || (req->newptr == NULL)) 5005282289Serj return (error); 5006292674Ssbruno new_wol_enabled = !!(new_wol_enabled); 5007282289Serj if (new_wol_enabled == hw->wol_enabled) 5008282289Serj return (0); 5009282289Serj 5010282289Serj if (new_wol_enabled > 0 && !adapter->wol_support) 5011282289Serj return (ENODEV); 5012282289Serj else 5013292674Ssbruno hw->wol_enabled = new_wol_enabled; 5014282289Serj 5015282289Serj return (0); 5016282289Serj} 5017282289Serj 5018282289Serj/* 5019282289Serj * Sysctl to enable/disable the Energy Efficient Ethernet capability, 5020282289Serj * if supported by the adapter. 5021282289Serj * Values: 5022282289Serj * 0 - disabled 5023282289Serj * 1 - enabled 5024282289Serj */ 5025282289Serjstatic int 5026282289Serjixgbe_sysctl_eee_enable(SYSCTL_HANDLER_ARGS) 5027282289Serj{ 5028282289Serj struct adapter *adapter = (struct adapter *) arg1; 5029283883Sjfv struct ixgbe_hw *hw = &adapter->hw; 5030282289Serj struct ifnet *ifp = adapter->ifp; 5031282289Serj int new_eee_enabled, error = 0; 5032282289Serj 5033282289Serj new_eee_enabled = adapter->eee_enabled; 5034282289Serj error = sysctl_handle_int(oidp, &new_eee_enabled, 0, req); 5035282289Serj if ((error) || (req->newptr == NULL)) 5036282289Serj return (error); 5037292674Ssbruno new_eee_enabled = !!(new_eee_enabled); 5038282289Serj if (new_eee_enabled == adapter->eee_enabled) 5039282289Serj return (0); 5040282289Serj 5041283883Sjfv if (new_eee_enabled > 0 && !hw->mac.ops.setup_eee) 5042282289Serj return (ENODEV); 5043282289Serj else 5044292674Ssbruno adapter->eee_enabled = new_eee_enabled; 5045282289Serj 5046282289Serj /* Re-initialize hardware if it's already running */ 5047282289Serj if (ifp->if_drv_flags & IFF_DRV_RUNNING) 5048282289Serj ixgbe_init(adapter); 5049282289Serj 5050282289Serj return (0); 5051282289Serj} 5052282289Serj 5053282289Serj/* 5054282289Serj * Read-only sysctl indicating whether EEE support was negotiated 5055282289Serj * on the link. 5056282289Serj */ 5057282289Serjstatic int 5058282289Serjixgbe_sysctl_eee_negotiated(SYSCTL_HANDLER_ARGS) 5059282289Serj{ 5060282289Serj struct adapter *adapter = (struct adapter *) arg1; 5061282289Serj struct ixgbe_hw *hw = &adapter->hw; 5062282289Serj bool status; 5063282289Serj 5064282289Serj status = !!(IXGBE_READ_REG(hw, IXGBE_EEE_STAT) & IXGBE_EEE_STAT_NEG); 5065282289Serj 5066282289Serj return (sysctl_handle_int(oidp, 0, status, req)); 5067282289Serj} 5068282289Serj 5069282289Serj/* 5070282289Serj * Read-only sysctl indicating whether RX Link is in LPI state. 5071282289Serj */ 5072282289Serjstatic int 5073282289Serjixgbe_sysctl_eee_rx_lpi_status(SYSCTL_HANDLER_ARGS) 5074282289Serj{ 5075282289Serj struct adapter *adapter = (struct adapter *) arg1; 5076282289Serj struct ixgbe_hw *hw = &adapter->hw; 5077282289Serj bool status; 5078282289Serj 5079282289Serj status = !!(IXGBE_READ_REG(hw, IXGBE_EEE_STAT) & 5080282289Serj IXGBE_EEE_RX_LPI_STATUS); 5081282289Serj 5082282289Serj return (sysctl_handle_int(oidp, 0, status, req)); 5083282289Serj} 5084282289Serj 5085282289Serj/* 5086282289Serj * Read-only sysctl indicating whether TX Link is in LPI state. 5087282289Serj */ 5088282289Serjstatic int 5089282289Serjixgbe_sysctl_eee_tx_lpi_status(SYSCTL_HANDLER_ARGS) 5090282289Serj{ 5091282289Serj struct adapter *adapter = (struct adapter *) arg1; 5092282289Serj struct ixgbe_hw *hw = &adapter->hw; 5093282289Serj bool status; 5094282289Serj 5095282289Serj status = !!(IXGBE_READ_REG(hw, IXGBE_EEE_STAT) & 5096282289Serj IXGBE_EEE_TX_LPI_STATUS); 5097282289Serj 5098282289Serj return (sysctl_handle_int(oidp, 0, status, req)); 5099282289Serj} 5100282289Serj 5101282289Serj/* 5102292674Ssbruno * Read-only sysctl indicating TX Link LPI delay 5103292674Ssbruno */ 5104292674Ssbrunostatic int 5105292674Ssbrunoixgbe_sysctl_eee_tx_lpi_delay(SYSCTL_HANDLER_ARGS) 5106292674Ssbruno{ 5107292674Ssbruno struct adapter *adapter = (struct adapter *) arg1; 5108292674Ssbruno struct ixgbe_hw *hw = &adapter->hw; 5109292674Ssbruno u32 reg; 5110292674Ssbruno 5111292674Ssbruno reg = IXGBE_READ_REG(hw, IXGBE_EEE_SU); 5112292674Ssbruno 5113292674Ssbruno return (sysctl_handle_int(oidp, 0, reg >> 26, req)); 5114292674Ssbruno} 5115292674Ssbruno 5116292674Ssbruno/* 5117282289Serj * Sysctl to enable/disable the types of packets that the 5118282289Serj * adapter will wake up on upon receipt. 5119282289Serj * WUFC - Wake Up Filter Control 5120282289Serj * Flags: 5121282289Serj * 0x1 - Link Status Change 5122282289Serj * 0x2 - Magic Packet 5123282289Serj * 0x4 - Direct Exact 5124282289Serj * 0x8 - Directed Multicast 5125282289Serj * 0x10 - Broadcast 5126282289Serj * 0x20 - ARP/IPv4 Request Packet 5127282289Serj * 0x40 - Direct IPv4 Packet 5128282289Serj * 0x80 - Direct IPv6 Packet 5129282289Serj * 5130282289Serj * Setting another flag will cause the sysctl to return an 5131282289Serj * error. 5132282289Serj */ 5133282289Serjstatic int 5134282289Serjixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS) 5135282289Serj{ 5136282289Serj struct adapter *adapter = (struct adapter *) arg1; 5137282289Serj int error = 0; 5138282289Serj u32 new_wufc; 5139282289Serj 5140282289Serj new_wufc = adapter->wufc; 5141282289Serj 5142282289Serj error = sysctl_handle_int(oidp, &new_wufc, 0, req); 5143282289Serj if ((error) || (req->newptr == NULL)) 5144282289Serj return (error); 5145282289Serj if (new_wufc == adapter->wufc) 5146282289Serj return (0); 5147282289Serj 5148282289Serj if (new_wufc & 0xffffff00) 5149282289Serj return (EINVAL); 5150282289Serj else { 5151282289Serj new_wufc &= 0xff; 5152282289Serj new_wufc |= (0xffffff & adapter->wufc); 5153282289Serj adapter->wufc = new_wufc; 5154282289Serj } 5155282289Serj 5156282289Serj return (0); 5157282289Serj} 5158282289Serj 5159292674Ssbruno#ifdef IXGBE_DEBUG 5160292674Ssbrunostatic int 5161292674Ssbrunoixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS) 5162292674Ssbruno{ 5163292674Ssbruno struct adapter *adapter = (struct adapter *)arg1; 5164292674Ssbruno struct ixgbe_hw *hw = &adapter->hw; 5165292674Ssbruno device_t dev = adapter->dev; 5166292674Ssbruno int error = 0, reta_size; 5167292674Ssbruno struct sbuf *buf; 5168292674Ssbruno u32 reg; 5169292674Ssbruno 5170292674Ssbruno buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); 5171292674Ssbruno if (!buf) { 5172292674Ssbruno device_printf(dev, "Could not allocate sbuf for output.\n"); 5173292674Ssbruno return (ENOMEM); 5174292674Ssbruno } 5175292674Ssbruno 5176292674Ssbruno // TODO: use sbufs to make a string to print out 5177292674Ssbruno /* Set multiplier for RETA setup and table size based on MAC */ 5178292674Ssbruno switch (adapter->hw.mac.type) { 5179292674Ssbruno case ixgbe_mac_X550: 5180292674Ssbruno case ixgbe_mac_X550EM_x: 5181292674Ssbruno reta_size = 128; 5182292674Ssbruno break; 5183292674Ssbruno default: 5184292674Ssbruno reta_size = 32; 5185292674Ssbruno break; 5186292674Ssbruno } 5187292674Ssbruno 5188292674Ssbruno /* Print out the redirection table */ 5189292674Ssbruno sbuf_cat(buf, "\n"); 5190292674Ssbruno for (int i = 0; i < reta_size; i++) { 5191292674Ssbruno if (i < 32) { 5192292674Ssbruno reg = IXGBE_READ_REG(hw, IXGBE_RETA(i)); 5193292674Ssbruno sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg); 5194292674Ssbruno } else { 5195292674Ssbruno reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32)); 5196292674Ssbruno sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg); 5197292674Ssbruno } 5198292674Ssbruno } 5199292674Ssbruno 5200292674Ssbruno // TODO: print more config 5201292674Ssbruno 5202292674Ssbruno error = sbuf_finish(buf); 5203292674Ssbruno if (error) 5204292674Ssbruno device_printf(dev, "Error finishing sbuf: %d\n", error); 5205292674Ssbruno 5206292674Ssbruno sbuf_delete(buf); 5207292674Ssbruno return (0); 5208292674Ssbruno} 5209292674Ssbruno#endif /* IXGBE_DEBUG */ 5210292674Ssbruno 5211282289Serj/* 5212280182Sjfv** Enable the hardware to drop packets when the buffer is 5213280182Sjfv** full. This is useful when multiqueue,so that no single 5214280182Sjfv** queue being full stalls the entire RX engine. We only 5215280182Sjfv** enable this when Multiqueue AND when Flow Control is 5216280182Sjfv** disabled. 5217280182Sjfv*/ 5218280182Sjfvstatic void 5219280182Sjfvixgbe_enable_rx_drop(struct adapter *adapter) 5220280182Sjfv{ 5221280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 5222280182Sjfv 5223280182Sjfv for (int i = 0; i < adapter->num_queues; i++) { 5224283883Sjfv struct rx_ring *rxr = &adapter->rx_rings[i]; 5225283883Sjfv u32 srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); 5226280182Sjfv srrctl |= IXGBE_SRRCTL_DROP_EN; 5227283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); 5228280182Sjfv } 5229283883Sjfv#ifdef PCI_IOV 5230283883Sjfv /* enable drop for each vf */ 5231283883Sjfv for (int i = 0; i < adapter->num_vfs; i++) { 5232283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_QDE, 5233283883Sjfv (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT) | 5234283883Sjfv IXGBE_QDE_ENABLE)); 5235283883Sjfv } 5236283883Sjfv#endif 5237280182Sjfv} 5238280182Sjfv 5239280182Sjfvstatic void 5240280182Sjfvixgbe_disable_rx_drop(struct adapter *adapter) 5241280182Sjfv{ 5242280182Sjfv struct ixgbe_hw *hw = &adapter->hw; 5243280182Sjfv 5244280182Sjfv for (int i = 0; i < adapter->num_queues; i++) { 5245283883Sjfv struct rx_ring *rxr = &adapter->rx_rings[i]; 5246283883Sjfv u32 srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); 5247280182Sjfv srrctl &= ~IXGBE_SRRCTL_DROP_EN; 5248283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); 5249280182Sjfv } 5250283883Sjfv#ifdef PCI_IOV 5251283883Sjfv /* disable drop for each vf */ 5252283883Sjfv for (int i = 0; i < adapter->num_vfs; i++) { 5253283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_QDE, 5254283883Sjfv (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT))); 5255283883Sjfv } 5256283883Sjfv#endif 5257280182Sjfv} 5258280182Sjfv 5259280182Sjfvstatic void 5260280182Sjfvixgbe_rearm_queues(struct adapter *adapter, u64 queues) 5261280182Sjfv{ 5262280182Sjfv u32 mask; 5263280182Sjfv 5264280182Sjfv switch (adapter->hw.mac.type) { 5265280182Sjfv case ixgbe_mac_82598EB: 5266280182Sjfv mask = (IXGBE_EIMS_RTX_QUEUE & queues); 5267280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask); 5268280182Sjfv break; 5269280182Sjfv case ixgbe_mac_82599EB: 5270280182Sjfv case ixgbe_mac_X540: 5271280182Sjfv case ixgbe_mac_X550: 5272282289Serj case ixgbe_mac_X550EM_x: 5273280182Sjfv mask = (queues & 0xFFFFFFFF); 5274280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask); 5275280182Sjfv mask = (queues >> 32); 5276280182Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), mask); 5277280182Sjfv break; 5278280182Sjfv default: 5279280182Sjfv break; 5280280182Sjfv } 5281280182Sjfv} 5282280182Sjfv 5283283883Sjfv#ifdef PCI_IOV 5284280182Sjfv 5285283883Sjfv/* 5286283883Sjfv** Support functions for SRIOV/VF management 5287283883Sjfv*/ 5288283883Sjfv 5289283883Sjfvstatic void 5290283883Sjfvixgbe_ping_all_vfs(struct adapter *adapter) 5291283883Sjfv{ 5292283883Sjfv struct ixgbe_vf *vf; 5293283883Sjfv 5294283883Sjfv for (int i = 0; i < adapter->num_vfs; i++) { 5295283883Sjfv vf = &adapter->vfs[i]; 5296283883Sjfv if (vf->flags & IXGBE_VF_ACTIVE) 5297283883Sjfv ixgbe_send_vf_msg(adapter, vf, IXGBE_PF_CONTROL_MSG); 5298283883Sjfv } 5299283883Sjfv} 5300283883Sjfv 5301283883Sjfv 5302283883Sjfvstatic void 5303283883Sjfvixgbe_vf_set_default_vlan(struct adapter *adapter, struct ixgbe_vf *vf, 5304283883Sjfv uint16_t tag) 5305283883Sjfv{ 5306283883Sjfv struct ixgbe_hw *hw; 5307283883Sjfv uint32_t vmolr, vmvir; 5308283883Sjfv 5309283883Sjfv hw = &adapter->hw; 5310283883Sjfv 5311283883Sjfv vf->vlan_tag = tag; 5312283883Sjfv 5313283883Sjfv vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf->pool)); 5314283883Sjfv 5315283883Sjfv /* Do not receive packets that pass inexact filters. */ 5316283883Sjfv vmolr &= ~(IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_ROPE); 5317283883Sjfv 5318283883Sjfv /* Disable Multicast Promicuous Mode. */ 5319283883Sjfv vmolr &= ~IXGBE_VMOLR_MPE; 5320283883Sjfv 5321283883Sjfv /* Accept broadcasts. */ 5322283883Sjfv vmolr |= IXGBE_VMOLR_BAM; 5323283883Sjfv 5324283883Sjfv if (tag == 0) { 5325283883Sjfv /* Accept non-vlan tagged traffic. */ 5326283883Sjfv //vmolr |= IXGBE_VMOLR_AUPE; 5327283883Sjfv 5328283883Sjfv /* Allow VM to tag outgoing traffic; no default tag. */ 5329283883Sjfv vmvir = 0; 5330283883Sjfv } else { 5331283883Sjfv /* Require vlan-tagged traffic. */ 5332283883Sjfv vmolr &= ~IXGBE_VMOLR_AUPE; 5333283883Sjfv 5334283883Sjfv /* Tag all traffic with provided vlan tag. */ 5335283883Sjfv vmvir = (tag | IXGBE_VMVIR_VLANA_DEFAULT); 5336283883Sjfv } 5337283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf->pool), vmolr); 5338283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf->pool), vmvir); 5339283883Sjfv} 5340283883Sjfv 5341283883Sjfv 5342283883Sjfvstatic boolean_t 5343283883Sjfvixgbe_vf_frame_size_compatible(struct adapter *adapter, struct ixgbe_vf *vf) 5344283883Sjfv{ 5345283883Sjfv 5346283883Sjfv /* 5347283883Sjfv * Frame size compatibility between PF and VF is only a problem on 5348283883Sjfv * 82599-based cards. X540 and later support any combination of jumbo 5349283883Sjfv * frames on PFs and VFs. 5350283883Sjfv */ 5351283883Sjfv if (adapter->hw.mac.type != ixgbe_mac_82599EB) 5352283883Sjfv return (TRUE); 5353283883Sjfv 5354283883Sjfv switch (vf->api_ver) { 5355283883Sjfv case IXGBE_API_VER_1_0: 5356283883Sjfv case IXGBE_API_VER_UNKNOWN: 5357283883Sjfv /* 5358283883Sjfv * On legacy (1.0 and older) VF versions, we don't support jumbo 5359283883Sjfv * frames on either the PF or the VF. 5360283883Sjfv */ 5361283883Sjfv if (adapter->max_frame_size > ETHER_MAX_LEN || 5362283883Sjfv vf->max_frame_size > ETHER_MAX_LEN) 5363283883Sjfv return (FALSE); 5364283883Sjfv 5365283883Sjfv return (TRUE); 5366283883Sjfv 5367283883Sjfv break; 5368283883Sjfv case IXGBE_API_VER_1_1: 5369283883Sjfv default: 5370283883Sjfv /* 5371283883Sjfv * 1.1 or later VF versions always work if they aren't using 5372283883Sjfv * jumbo frames. 5373283883Sjfv */ 5374283883Sjfv if (vf->max_frame_size <= ETHER_MAX_LEN) 5375283883Sjfv return (TRUE); 5376283883Sjfv 5377283883Sjfv /* 5378283883Sjfv * Jumbo frames only work with VFs if the PF is also using jumbo 5379283883Sjfv * frames. 5380283883Sjfv */ 5381283883Sjfv if (adapter->max_frame_size <= ETHER_MAX_LEN) 5382283883Sjfv return (TRUE); 5383283883Sjfv 5384283883Sjfv return (FALSE); 5385283883Sjfv 5386283883Sjfv } 5387283883Sjfv} 5388283883Sjfv 5389283883Sjfv 5390283883Sjfvstatic void 5391283883Sjfvixgbe_process_vf_reset(struct adapter *adapter, struct ixgbe_vf *vf) 5392283883Sjfv{ 5393283883Sjfv ixgbe_vf_set_default_vlan(adapter, vf, vf->default_vlan); 5394283883Sjfv 5395283883Sjfv // XXX clear multicast addresses 5396283883Sjfv 5397283883Sjfv ixgbe_clear_rar(&adapter->hw, vf->rar_index); 5398283883Sjfv 5399283883Sjfv vf->api_ver = IXGBE_API_VER_UNKNOWN; 5400283883Sjfv} 5401283883Sjfv 5402283883Sjfv 5403283883Sjfvstatic void 5404283883Sjfvixgbe_vf_enable_transmit(struct adapter *adapter, struct ixgbe_vf *vf) 5405283883Sjfv{ 5406283883Sjfv struct ixgbe_hw *hw; 5407283883Sjfv uint32_t vf_index, vfte; 5408283883Sjfv 5409283883Sjfv hw = &adapter->hw; 5410283883Sjfv 5411283883Sjfv vf_index = IXGBE_VF_INDEX(vf->pool); 5412283883Sjfv vfte = IXGBE_READ_REG(hw, IXGBE_VFTE(vf_index)); 5413283883Sjfv vfte |= IXGBE_VF_BIT(vf->pool); 5414283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_VFTE(vf_index), vfte); 5415283883Sjfv} 5416283883Sjfv 5417283883Sjfv 5418283883Sjfvstatic void 5419283883Sjfvixgbe_vf_enable_receive(struct adapter *adapter, struct ixgbe_vf *vf) 5420283883Sjfv{ 5421283883Sjfv struct ixgbe_hw *hw; 5422283883Sjfv uint32_t vf_index, vfre; 5423283883Sjfv 5424283883Sjfv hw = &adapter->hw; 5425283883Sjfv 5426283883Sjfv vf_index = IXGBE_VF_INDEX(vf->pool); 5427283883Sjfv vfre = IXGBE_READ_REG(hw, IXGBE_VFRE(vf_index)); 5428283883Sjfv if (ixgbe_vf_frame_size_compatible(adapter, vf)) 5429283883Sjfv vfre |= IXGBE_VF_BIT(vf->pool); 5430283883Sjfv else 5431283883Sjfv vfre &= ~IXGBE_VF_BIT(vf->pool); 5432283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_VFRE(vf_index), vfre); 5433283883Sjfv} 5434283883Sjfv 5435283883Sjfv 5436283883Sjfvstatic void 5437283883Sjfvixgbe_vf_reset_msg(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg) 5438283883Sjfv{ 5439283883Sjfv struct ixgbe_hw *hw; 5440283883Sjfv uint32_t ack; 5441283883Sjfv uint32_t resp[IXGBE_VF_PERMADDR_MSG_LEN]; 5442283883Sjfv 5443283883Sjfv hw = &adapter->hw; 5444283883Sjfv 5445283883Sjfv ixgbe_process_vf_reset(adapter, vf); 5446283883Sjfv 5447283883Sjfv if (ixgbe_validate_mac_addr(vf->ether_addr) == 0) { 5448283883Sjfv ixgbe_set_rar(&adapter->hw, vf->rar_index, 5449283883Sjfv vf->ether_addr, vf->pool, TRUE); 5450283883Sjfv ack = IXGBE_VT_MSGTYPE_ACK; 5451283883Sjfv } else 5452283883Sjfv ack = IXGBE_VT_MSGTYPE_NACK; 5453283883Sjfv 5454283883Sjfv ixgbe_vf_enable_transmit(adapter, vf); 5455283883Sjfv ixgbe_vf_enable_receive(adapter, vf); 5456283883Sjfv 5457283883Sjfv vf->flags |= IXGBE_VF_CTS; 5458283883Sjfv 5459283883Sjfv resp[0] = IXGBE_VF_RESET | ack | IXGBE_VT_MSGTYPE_CTS; 5460283883Sjfv bcopy(vf->ether_addr, &resp[1], ETHER_ADDR_LEN); 5461283883Sjfv resp[3] = hw->mac.mc_filter_type; 5462283883Sjfv ixgbe_write_mbx(hw, resp, IXGBE_VF_PERMADDR_MSG_LEN, vf->pool); 5463283883Sjfv} 5464283883Sjfv 5465283883Sjfv 5466283883Sjfvstatic void 5467283883Sjfvixgbe_vf_set_mac(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg) 5468283883Sjfv{ 5469283883Sjfv uint8_t *mac; 5470283883Sjfv 5471283883Sjfv mac = (uint8_t*)&msg[1]; 5472283883Sjfv 5473283883Sjfv /* Check that the VF has permission to change the MAC address. */ 5474283883Sjfv if (!(vf->flags & IXGBE_VF_CAP_MAC) && ixgbe_vf_mac_changed(vf, mac)) { 5475283883Sjfv ixgbe_send_vf_nack(adapter, vf, msg[0]); 5476283883Sjfv return; 5477283883Sjfv } 5478283883Sjfv 5479283883Sjfv if (ixgbe_validate_mac_addr(mac) != 0) { 5480283883Sjfv ixgbe_send_vf_nack(adapter, vf, msg[0]); 5481283883Sjfv return; 5482283883Sjfv } 5483283883Sjfv 5484283883Sjfv bcopy(mac, vf->ether_addr, ETHER_ADDR_LEN); 5485283883Sjfv 5486283883Sjfv ixgbe_set_rar(&adapter->hw, vf->rar_index, vf->ether_addr, 5487283883Sjfv vf->pool, TRUE); 5488283883Sjfv 5489283883Sjfv ixgbe_send_vf_ack(adapter, vf, msg[0]); 5490283883Sjfv} 5491283883Sjfv 5492283883Sjfv 5493283883Sjfv/* 5494283883Sjfv** VF multicast addresses are set by using the appropriate bit in 5495283883Sjfv** 1 of 128 32 bit addresses (4096 possible). 5496283883Sjfv*/ 5497283883Sjfvstatic void 5498283883Sjfvixgbe_vf_set_mc_addr(struct adapter *adapter, struct ixgbe_vf *vf, u32 *msg) 5499283883Sjfv{ 5500283883Sjfv u16 *list = (u16*)&msg[1]; 5501283883Sjfv int entries; 5502283883Sjfv u32 vmolr, vec_bit, vec_reg, mta_reg; 5503283883Sjfv 5504283883Sjfv entries = (msg[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT; 5505283883Sjfv entries = min(entries, IXGBE_MAX_VF_MC); 5506283883Sjfv 5507283883Sjfv vmolr = IXGBE_READ_REG(&adapter->hw, IXGBE_VMOLR(vf->pool)); 5508283883Sjfv 5509283883Sjfv vf->num_mc_hashes = entries; 5510283883Sjfv 5511283883Sjfv /* Set the appropriate MTA bit */ 5512283883Sjfv for (int i = 0; i < entries; i++) { 5513283883Sjfv vf->mc_hash[i] = list[i]; 5514283883Sjfv vec_reg = (vf->mc_hash[i] >> 5) & 0x7F; 5515283883Sjfv vec_bit = vf->mc_hash[i] & 0x1F; 5516283883Sjfv mta_reg = IXGBE_READ_REG(&adapter->hw, IXGBE_MTA(vec_reg)); 5517283883Sjfv mta_reg |= (1 << vec_bit); 5518283883Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_MTA(vec_reg), mta_reg); 5519283883Sjfv } 5520283883Sjfv 5521283883Sjfv vmolr |= IXGBE_VMOLR_ROMPE; 5522283883Sjfv IXGBE_WRITE_REG(&adapter->hw, IXGBE_VMOLR(vf->pool), vmolr); 5523283883Sjfv ixgbe_send_vf_ack(adapter, vf, msg[0]); 5524283883Sjfv return; 5525283883Sjfv} 5526283883Sjfv 5527283883Sjfv 5528283883Sjfvstatic void 5529283883Sjfvixgbe_vf_set_vlan(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg) 5530283883Sjfv{ 5531283883Sjfv struct ixgbe_hw *hw; 5532283883Sjfv int enable; 5533283883Sjfv uint16_t tag; 5534283883Sjfv 5535283883Sjfv hw = &adapter->hw; 5536283883Sjfv enable = IXGBE_VT_MSGINFO(msg[0]); 5537283883Sjfv tag = msg[1] & IXGBE_VLVF_VLANID_MASK; 5538283883Sjfv 5539283883Sjfv if (!(vf->flags & IXGBE_VF_CAP_VLAN)) { 5540283883Sjfv ixgbe_send_vf_nack(adapter, vf, msg[0]); 5541283883Sjfv return; 5542283883Sjfv } 5543283883Sjfv 5544283883Sjfv /* It is illegal to enable vlan tag 0. */ 5545283883Sjfv if (tag == 0 && enable != 0){ 5546283883Sjfv ixgbe_send_vf_nack(adapter, vf, msg[0]); 5547283883Sjfv return; 5548283883Sjfv } 5549283883Sjfv 5550283883Sjfv ixgbe_set_vfta(hw, tag, vf->pool, enable); 5551283883Sjfv ixgbe_send_vf_ack(adapter, vf, msg[0]); 5552283883Sjfv} 5553283883Sjfv 5554283883Sjfv 5555283883Sjfvstatic void 5556283883Sjfvixgbe_vf_set_lpe(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg) 5557283883Sjfv{ 5558283883Sjfv struct ixgbe_hw *hw; 5559283883Sjfv uint32_t vf_max_size, pf_max_size, mhadd; 5560283883Sjfv 5561283883Sjfv hw = &adapter->hw; 5562283883Sjfv vf_max_size = msg[1]; 5563283883Sjfv 5564283883Sjfv if (vf_max_size < ETHER_CRC_LEN) { 5565283883Sjfv /* We intentionally ACK invalid LPE requests. */ 5566283883Sjfv ixgbe_send_vf_ack(adapter, vf, msg[0]); 5567283883Sjfv return; 5568283883Sjfv } 5569283883Sjfv 5570283883Sjfv vf_max_size -= ETHER_CRC_LEN; 5571283883Sjfv 5572283883Sjfv if (vf_max_size > IXGBE_MAX_FRAME_SIZE) { 5573283883Sjfv /* We intentionally ACK invalid LPE requests. */ 5574283883Sjfv ixgbe_send_vf_ack(adapter, vf, msg[0]); 5575283883Sjfv return; 5576283883Sjfv } 5577283883Sjfv 5578283883Sjfv vf->max_frame_size = vf_max_size; 5579283883Sjfv ixgbe_update_max_frame(adapter, vf->max_frame_size); 5580283883Sjfv 5581283883Sjfv /* 5582283883Sjfv * We might have to disable reception to this VF if the frame size is 5583283883Sjfv * not compatible with the config on the PF. 5584283883Sjfv */ 5585283883Sjfv ixgbe_vf_enable_receive(adapter, vf); 5586283883Sjfv 5587283883Sjfv mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); 5588283883Sjfv pf_max_size = (mhadd & IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT; 5589283883Sjfv 5590283883Sjfv if (pf_max_size < adapter->max_frame_size) { 5591283883Sjfv mhadd &= ~IXGBE_MHADD_MFS_MASK; 5592283883Sjfv mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT; 5593283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); 5594283883Sjfv } 5595283883Sjfv 5596283883Sjfv ixgbe_send_vf_ack(adapter, vf, msg[0]); 5597283883Sjfv} 5598283883Sjfv 5599283883Sjfv 5600283883Sjfvstatic void 5601283883Sjfvixgbe_vf_set_macvlan(struct adapter *adapter, struct ixgbe_vf *vf, 5602283883Sjfv uint32_t *msg) 5603283883Sjfv{ 5604283883Sjfv //XXX implement this 5605283883Sjfv ixgbe_send_vf_nack(adapter, vf, msg[0]); 5606283883Sjfv} 5607283883Sjfv 5608283883Sjfv 5609283883Sjfvstatic void 5610283883Sjfvixgbe_vf_api_negotiate(struct adapter *adapter, struct ixgbe_vf *vf, 5611283883Sjfv uint32_t *msg) 5612283883Sjfv{ 5613283883Sjfv 5614285590Spkelsey switch (msg[1]) { 5615283883Sjfv case IXGBE_API_VER_1_0: 5616283883Sjfv case IXGBE_API_VER_1_1: 5617285590Spkelsey vf->api_ver = msg[1]; 5618283883Sjfv ixgbe_send_vf_ack(adapter, vf, msg[0]); 5619283883Sjfv break; 5620283883Sjfv default: 5621283883Sjfv vf->api_ver = IXGBE_API_VER_UNKNOWN; 5622283883Sjfv ixgbe_send_vf_nack(adapter, vf, msg[0]); 5623283883Sjfv break; 5624283883Sjfv } 5625283883Sjfv} 5626283883Sjfv 5627283883Sjfv 5628283883Sjfvstatic void 5629283883Sjfvixgbe_vf_get_queues(struct adapter *adapter, struct ixgbe_vf *vf, 5630283883Sjfv uint32_t *msg) 5631283883Sjfv{ 5632283883Sjfv struct ixgbe_hw *hw; 5633283883Sjfv uint32_t resp[IXGBE_VF_GET_QUEUES_RESP_LEN]; 5634283883Sjfv int num_queues; 5635283883Sjfv 5636283883Sjfv hw = &adapter->hw; 5637283883Sjfv 5638283883Sjfv /* GET_QUEUES is not supported on pre-1.1 APIs. */ 5639283883Sjfv switch (msg[0]) { 5640283883Sjfv case IXGBE_API_VER_1_0: 5641283883Sjfv case IXGBE_API_VER_UNKNOWN: 5642283883Sjfv ixgbe_send_vf_nack(adapter, vf, msg[0]); 5643283883Sjfv return; 5644283883Sjfv } 5645283883Sjfv 5646283883Sjfv resp[0] = IXGBE_VF_GET_QUEUES | IXGBE_VT_MSGTYPE_ACK | 5647283883Sjfv IXGBE_VT_MSGTYPE_CTS; 5648283883Sjfv 5649283883Sjfv num_queues = ixgbe_vf_queues(ixgbe_get_iov_mode(adapter)); 5650283883Sjfv resp[IXGBE_VF_TX_QUEUES] = num_queues; 5651283883Sjfv resp[IXGBE_VF_RX_QUEUES] = num_queues; 5652283883Sjfv resp[IXGBE_VF_TRANS_VLAN] = (vf->default_vlan != 0); 5653283883Sjfv resp[IXGBE_VF_DEF_QUEUE] = 0; 5654283883Sjfv 5655283883Sjfv ixgbe_write_mbx(hw, resp, IXGBE_VF_GET_QUEUES_RESP_LEN, vf->pool); 5656283883Sjfv} 5657283883Sjfv 5658283883Sjfv 5659283883Sjfvstatic void 5660283883Sjfvixgbe_process_vf_msg(struct adapter *adapter, struct ixgbe_vf *vf) 5661283883Sjfv{ 5662283883Sjfv struct ixgbe_hw *hw; 5663283883Sjfv uint32_t msg[IXGBE_VFMAILBOX_SIZE]; 5664283883Sjfv int error; 5665283883Sjfv 5666283883Sjfv hw = &adapter->hw; 5667283883Sjfv 5668283883Sjfv error = ixgbe_read_mbx(hw, msg, IXGBE_VFMAILBOX_SIZE, vf->pool); 5669283883Sjfv 5670283883Sjfv if (error != 0) 5671283883Sjfv return; 5672283883Sjfv 5673283883Sjfv CTR3(KTR_MALLOC, "%s: received msg %x from %d", 5674283883Sjfv adapter->ifp->if_xname, msg[0], vf->pool); 5675283883Sjfv if (msg[0] == IXGBE_VF_RESET) { 5676283883Sjfv ixgbe_vf_reset_msg(adapter, vf, msg); 5677283883Sjfv return; 5678283883Sjfv } 5679283883Sjfv 5680283883Sjfv if (!(vf->flags & IXGBE_VF_CTS)) { 5681283883Sjfv ixgbe_send_vf_nack(adapter, vf, msg[0]); 5682283883Sjfv return; 5683283883Sjfv } 5684283883Sjfv 5685283883Sjfv switch (msg[0] & IXGBE_VT_MSG_MASK) { 5686283883Sjfv case IXGBE_VF_SET_MAC_ADDR: 5687283883Sjfv ixgbe_vf_set_mac(adapter, vf, msg); 5688283883Sjfv break; 5689283883Sjfv case IXGBE_VF_SET_MULTICAST: 5690283883Sjfv ixgbe_vf_set_mc_addr(adapter, vf, msg); 5691283883Sjfv break; 5692283883Sjfv case IXGBE_VF_SET_VLAN: 5693283883Sjfv ixgbe_vf_set_vlan(adapter, vf, msg); 5694283883Sjfv break; 5695283883Sjfv case IXGBE_VF_SET_LPE: 5696283883Sjfv ixgbe_vf_set_lpe(adapter, vf, msg); 5697283883Sjfv break; 5698283883Sjfv case IXGBE_VF_SET_MACVLAN: 5699283883Sjfv ixgbe_vf_set_macvlan(adapter, vf, msg); 5700283883Sjfv break; 5701283883Sjfv case IXGBE_VF_API_NEGOTIATE: 5702283883Sjfv ixgbe_vf_api_negotiate(adapter, vf, msg); 5703283883Sjfv break; 5704283883Sjfv case IXGBE_VF_GET_QUEUES: 5705283883Sjfv ixgbe_vf_get_queues(adapter, vf, msg); 5706283883Sjfv break; 5707283883Sjfv default: 5708283883Sjfv ixgbe_send_vf_nack(adapter, vf, msg[0]); 5709283883Sjfv } 5710283883Sjfv} 5711283883Sjfv 5712283883Sjfv 5713283883Sjfv/* 5714283883Sjfv * Tasklet for handling VF -> PF mailbox messages. 5715283883Sjfv */ 5716283883Sjfvstatic void 5717283883Sjfvixgbe_handle_mbx(void *context, int pending) 5718283883Sjfv{ 5719283883Sjfv struct adapter *adapter; 5720283883Sjfv struct ixgbe_hw *hw; 5721283883Sjfv struct ixgbe_vf *vf; 5722283883Sjfv int i; 5723283883Sjfv 5724283883Sjfv adapter = context; 5725283883Sjfv hw = &adapter->hw; 5726283883Sjfv 5727283883Sjfv IXGBE_CORE_LOCK(adapter); 5728283883Sjfv for (i = 0; i < adapter->num_vfs; i++) { 5729283883Sjfv vf = &adapter->vfs[i]; 5730283883Sjfv 5731283883Sjfv if (vf->flags & IXGBE_VF_ACTIVE) { 5732283883Sjfv if (ixgbe_check_for_rst(hw, vf->pool) == 0) 5733283883Sjfv ixgbe_process_vf_reset(adapter, vf); 5734283883Sjfv 5735283883Sjfv if (ixgbe_check_for_msg(hw, vf->pool) == 0) 5736283883Sjfv ixgbe_process_vf_msg(adapter, vf); 5737283883Sjfv 5738283883Sjfv if (ixgbe_check_for_ack(hw, vf->pool) == 0) 5739283883Sjfv ixgbe_process_vf_ack(adapter, vf); 5740283883Sjfv } 5741283883Sjfv } 5742283883Sjfv IXGBE_CORE_UNLOCK(adapter); 5743283883Sjfv} 5744283883Sjfv 5745283883Sjfv 5746283883Sjfvstatic int 5747283883Sjfvixgbe_init_iov(device_t dev, u16 num_vfs, const nvlist_t *config) 5748283883Sjfv{ 5749283883Sjfv struct adapter *adapter; 5750283883Sjfv enum ixgbe_iov_mode mode; 5751283883Sjfv 5752283883Sjfv adapter = device_get_softc(dev); 5753283883Sjfv adapter->num_vfs = num_vfs; 5754283883Sjfv mode = ixgbe_get_iov_mode(adapter); 5755283883Sjfv 5756283883Sjfv if (num_vfs > ixgbe_max_vfs(mode)) { 5757283883Sjfv adapter->num_vfs = 0; 5758283883Sjfv return (ENOSPC); 5759283883Sjfv } 5760283883Sjfv 5761283883Sjfv IXGBE_CORE_LOCK(adapter); 5762283883Sjfv 5763283883Sjfv adapter->vfs = malloc(sizeof(*adapter->vfs) * num_vfs, M_IXGBE, 5764283883Sjfv M_NOWAIT | M_ZERO); 5765283883Sjfv 5766283883Sjfv if (adapter->vfs == NULL) { 5767283883Sjfv adapter->num_vfs = 0; 5768283883Sjfv IXGBE_CORE_UNLOCK(adapter); 5769283883Sjfv return (ENOMEM); 5770283883Sjfv } 5771283883Sjfv 5772283883Sjfv ixgbe_init_locked(adapter); 5773283883Sjfv 5774283883Sjfv IXGBE_CORE_UNLOCK(adapter); 5775283883Sjfv 5776283883Sjfv return (0); 5777283883Sjfv} 5778283883Sjfv 5779283883Sjfv 5780283883Sjfvstatic void 5781283883Sjfvixgbe_uninit_iov(device_t dev) 5782283883Sjfv{ 5783283883Sjfv struct ixgbe_hw *hw; 5784283883Sjfv struct adapter *adapter; 5785283883Sjfv uint32_t pf_reg, vf_reg; 5786283883Sjfv 5787283883Sjfv adapter = device_get_softc(dev); 5788283883Sjfv hw = &adapter->hw; 5789283883Sjfv 5790283883Sjfv IXGBE_CORE_LOCK(adapter); 5791283883Sjfv 5792283883Sjfv /* Enable rx/tx for the PF and disable it for all VFs. */ 5793283883Sjfv pf_reg = IXGBE_VF_INDEX(adapter->pool); 5794283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_VFRE(pf_reg), 5795283883Sjfv IXGBE_VF_BIT(adapter->pool)); 5796283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_VFTE(pf_reg), 5797283883Sjfv IXGBE_VF_BIT(adapter->pool)); 5798283883Sjfv 5799283883Sjfv if (pf_reg == 0) 5800283883Sjfv vf_reg = 1; 5801283883Sjfv else 5802283883Sjfv vf_reg = 0; 5803283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_VFRE(vf_reg), 0); 5804283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_VFTE(vf_reg), 0); 5805283883Sjfv 5806283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, 0); 5807283883Sjfv 5808283883Sjfv free(adapter->vfs, M_IXGBE); 5809283883Sjfv adapter->vfs = NULL; 5810283883Sjfv adapter->num_vfs = 0; 5811283883Sjfv 5812283883Sjfv IXGBE_CORE_UNLOCK(adapter); 5813283883Sjfv} 5814283883Sjfv 5815283883Sjfv 5816283883Sjfvstatic void 5817283883Sjfvixgbe_initialize_iov(struct adapter *adapter) 5818283883Sjfv{ 5819283883Sjfv struct ixgbe_hw *hw = &adapter->hw; 5820283883Sjfv uint32_t mrqc, mtqc, vt_ctl, vf_reg, gcr_ext, gpie; 5821283883Sjfv enum ixgbe_iov_mode mode; 5822283883Sjfv int i; 5823283883Sjfv 5824283883Sjfv mode = ixgbe_get_iov_mode(adapter); 5825283883Sjfv if (mode == IXGBE_NO_VM) 5826283883Sjfv return; 5827283883Sjfv 5828283883Sjfv IXGBE_CORE_LOCK_ASSERT(adapter); 5829283883Sjfv 5830283883Sjfv mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC); 5831283883Sjfv mrqc &= ~IXGBE_MRQC_MRQE_MASK; 5832283883Sjfv 5833283883Sjfv switch (mode) { 5834283883Sjfv case IXGBE_64_VM: 5835283883Sjfv mrqc |= IXGBE_MRQC_VMDQRSS64EN; 5836283883Sjfv break; 5837283883Sjfv case IXGBE_32_VM: 5838283883Sjfv mrqc |= IXGBE_MRQC_VMDQRSS32EN; 5839283883Sjfv break; 5840283883Sjfv default: 5841283883Sjfv panic("Unexpected SR-IOV mode %d", mode); 5842283883Sjfv } 5843283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); 5844283883Sjfv 5845283883Sjfv mtqc = IXGBE_MTQC_VT_ENA; 5846283883Sjfv switch (mode) { 5847283883Sjfv case IXGBE_64_VM: 5848283883Sjfv mtqc |= IXGBE_MTQC_64VF; 5849283883Sjfv break; 5850283883Sjfv case IXGBE_32_VM: 5851283883Sjfv mtqc |= IXGBE_MTQC_32VF; 5852283883Sjfv break; 5853283883Sjfv default: 5854283883Sjfv panic("Unexpected SR-IOV mode %d", mode); 5855283883Sjfv } 5856283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_MTQC, mtqc); 5857283883Sjfv 5858283883Sjfv 5859283883Sjfv gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); 5860283883Sjfv gcr_ext |= IXGBE_GCR_EXT_MSIX_EN; 5861283883Sjfv gcr_ext &= ~IXGBE_GCR_EXT_VT_MODE_MASK; 5862283883Sjfv switch (mode) { 5863283883Sjfv case IXGBE_64_VM: 5864283883Sjfv gcr_ext |= IXGBE_GCR_EXT_VT_MODE_64; 5865283883Sjfv break; 5866283883Sjfv case IXGBE_32_VM: 5867283883Sjfv gcr_ext |= IXGBE_GCR_EXT_VT_MODE_32; 5868283883Sjfv break; 5869283883Sjfv default: 5870283883Sjfv panic("Unexpected SR-IOV mode %d", mode); 5871283883Sjfv } 5872283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); 5873283883Sjfv 5874283883Sjfv 5875283883Sjfv gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); 5876283883Sjfv gcr_ext &= ~IXGBE_GPIE_VTMODE_MASK; 5877283883Sjfv switch (mode) { 5878283883Sjfv case IXGBE_64_VM: 5879283883Sjfv gpie |= IXGBE_GPIE_VTMODE_64; 5880283883Sjfv break; 5881283883Sjfv case IXGBE_32_VM: 5882283883Sjfv gpie |= IXGBE_GPIE_VTMODE_32; 5883283883Sjfv break; 5884283883Sjfv default: 5885283883Sjfv panic("Unexpected SR-IOV mode %d", mode); 5886283883Sjfv } 5887283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); 5888283883Sjfv 5889283883Sjfv /* Enable rx/tx for the PF. */ 5890283883Sjfv vf_reg = IXGBE_VF_INDEX(adapter->pool); 5891283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_VFRE(vf_reg), 5892283883Sjfv IXGBE_VF_BIT(adapter->pool)); 5893283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_VFTE(vf_reg), 5894283883Sjfv IXGBE_VF_BIT(adapter->pool)); 5895283883Sjfv 5896283883Sjfv /* Allow VM-to-VM communication. */ 5897283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); 5898283883Sjfv 5899283883Sjfv vt_ctl = IXGBE_VT_CTL_VT_ENABLE | IXGBE_VT_CTL_REPLEN; 5900283883Sjfv vt_ctl |= (adapter->pool << IXGBE_VT_CTL_POOL_SHIFT); 5901283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vt_ctl); 5902283883Sjfv 5903283883Sjfv for (i = 0; i < adapter->num_vfs; i++) 5904283883Sjfv ixgbe_init_vf(adapter, &adapter->vfs[i]); 5905283883Sjfv} 5906283883Sjfv 5907283883Sjfv 5908283883Sjfv/* 5909283883Sjfv** Check the max frame setting of all active VF's 5910283883Sjfv*/ 5911283883Sjfvstatic void 5912283883Sjfvixgbe_recalculate_max_frame(struct adapter *adapter) 5913283883Sjfv{ 5914283883Sjfv struct ixgbe_vf *vf; 5915283883Sjfv 5916283883Sjfv IXGBE_CORE_LOCK_ASSERT(adapter); 5917283883Sjfv 5918283883Sjfv for (int i = 0; i < adapter->num_vfs; i++) { 5919283883Sjfv vf = &adapter->vfs[i]; 5920283883Sjfv if (vf->flags & IXGBE_VF_ACTIVE) 5921283883Sjfv ixgbe_update_max_frame(adapter, vf->max_frame_size); 5922283883Sjfv } 5923283883Sjfv} 5924283883Sjfv 5925283883Sjfv 5926283883Sjfvstatic void 5927283883Sjfvixgbe_init_vf(struct adapter *adapter, struct ixgbe_vf *vf) 5928283883Sjfv{ 5929283883Sjfv struct ixgbe_hw *hw; 5930283883Sjfv uint32_t vf_index, pfmbimr; 5931283883Sjfv 5932283883Sjfv IXGBE_CORE_LOCK_ASSERT(adapter); 5933283883Sjfv 5934283883Sjfv hw = &adapter->hw; 5935283883Sjfv 5936283883Sjfv if (!(vf->flags & IXGBE_VF_ACTIVE)) 5937283883Sjfv return; 5938283883Sjfv 5939283883Sjfv vf_index = IXGBE_VF_INDEX(vf->pool); 5940283883Sjfv pfmbimr = IXGBE_READ_REG(hw, IXGBE_PFMBIMR(vf_index)); 5941283883Sjfv pfmbimr |= IXGBE_VF_BIT(vf->pool); 5942283883Sjfv IXGBE_WRITE_REG(hw, IXGBE_PFMBIMR(vf_index), pfmbimr); 5943283883Sjfv 5944283883Sjfv ixgbe_vf_set_default_vlan(adapter, vf, vf->vlan_tag); 5945283883Sjfv 5946283883Sjfv // XXX multicast addresses 5947283883Sjfv 5948283883Sjfv if (ixgbe_validate_mac_addr(vf->ether_addr) == 0) { 5949283883Sjfv ixgbe_set_rar(&adapter->hw, vf->rar_index, 5950283883Sjfv vf->ether_addr, vf->pool, TRUE); 5951283883Sjfv } 5952283883Sjfv 5953283883Sjfv ixgbe_vf_enable_transmit(adapter, vf); 5954283883Sjfv ixgbe_vf_enable_receive(adapter, vf); 5955283883Sjfv 5956283883Sjfv ixgbe_send_vf_msg(adapter, vf, IXGBE_PF_CONTROL_MSG); 5957283883Sjfv} 5958283883Sjfv 5959283883Sjfvstatic int 5960283883Sjfvixgbe_add_vf(device_t dev, u16 vfnum, const nvlist_t *config) 5961283883Sjfv{ 5962283883Sjfv struct adapter *adapter; 5963283883Sjfv struct ixgbe_vf *vf; 5964283883Sjfv const void *mac; 5965283883Sjfv 5966283883Sjfv adapter = device_get_softc(dev); 5967283883Sjfv 5968283883Sjfv KASSERT(vfnum < adapter->num_vfs, ("VF index %d is out of range %d", 5969283883Sjfv vfnum, adapter->num_vfs)); 5970283883Sjfv 5971283883Sjfv IXGBE_CORE_LOCK(adapter); 5972283883Sjfv vf = &adapter->vfs[vfnum]; 5973283883Sjfv vf->pool= vfnum; 5974283883Sjfv 5975283883Sjfv /* RAR[0] is used by the PF so use vfnum + 1 for VF RAR. */ 5976283883Sjfv vf->rar_index = vfnum + 1; 5977283883Sjfv vf->default_vlan = 0; 5978283883Sjfv vf->max_frame_size = ETHER_MAX_LEN; 5979283883Sjfv ixgbe_update_max_frame(adapter, vf->max_frame_size); 5980283883Sjfv 5981283883Sjfv if (nvlist_exists_binary(config, "mac-addr")) { 5982283883Sjfv mac = nvlist_get_binary(config, "mac-addr", NULL); 5983283883Sjfv bcopy(mac, vf->ether_addr, ETHER_ADDR_LEN); 5984283883Sjfv if (nvlist_get_bool(config, "allow-set-mac")) 5985283883Sjfv vf->flags |= IXGBE_VF_CAP_MAC; 5986283883Sjfv } else 5987283883Sjfv /* 5988283883Sjfv * If the administrator has not specified a MAC address then 5989283883Sjfv * we must allow the VF to choose one. 5990283883Sjfv */ 5991283883Sjfv vf->flags |= IXGBE_VF_CAP_MAC; 5992283883Sjfv 5993283883Sjfv vf->flags = IXGBE_VF_ACTIVE; 5994283883Sjfv 5995283883Sjfv ixgbe_init_vf(adapter, vf); 5996283883Sjfv IXGBE_CORE_UNLOCK(adapter); 5997283883Sjfv 5998283883Sjfv return (0); 5999283883Sjfv} 6000283883Sjfv#endif /* PCI_IOV */ 6001283883Sjfv 6002