Home | History | Annotate | Line # | Download | only in ixgbe
ixgbe.c revision 1.5.2.2
      1  1.5.2.2  jdolecek /* $NetBSD: ixgbe.c,v 1.5.2.2 2017/12/03 11:37:29 jdolecek Exp $ */
      2  1.5.2.2  jdolecek 
      3      1.1    dyoung /******************************************************************************
      4      1.1    dyoung 
      5  1.5.2.2  jdolecek   Copyright (c) 2001-2017, Intel Corporation
      6      1.1    dyoung   All rights reserved.
      7  1.5.2.2  jdolecek 
      8  1.5.2.2  jdolecek   Redistribution and use in source and binary forms, with or without
      9      1.1    dyoung   modification, are permitted provided that the following conditions are met:
     10  1.5.2.2  jdolecek 
     11  1.5.2.2  jdolecek    1. Redistributions of source code must retain the above copyright notice,
     12      1.1    dyoung       this list of conditions and the following disclaimer.
     13  1.5.2.2  jdolecek 
     14  1.5.2.2  jdolecek    2. Redistributions in binary form must reproduce the above copyright
     15  1.5.2.2  jdolecek       notice, this list of conditions and the following disclaimer in the
     16      1.1    dyoung       documentation and/or other materials provided with the distribution.
     17  1.5.2.2  jdolecek 
     18  1.5.2.2  jdolecek    3. Neither the name of the Intel Corporation nor the names of its
     19  1.5.2.2  jdolecek       contributors may be used to endorse or promote products derived from
     20      1.1    dyoung       this software without specific prior written permission.
     21  1.5.2.2  jdolecek 
     22      1.1    dyoung   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     23  1.5.2.2  jdolecek   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24  1.5.2.2  jdolecek   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25  1.5.2.2  jdolecek   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     26  1.5.2.2  jdolecek   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     27  1.5.2.2  jdolecek   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     28  1.5.2.2  jdolecek   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29  1.5.2.2  jdolecek   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     30  1.5.2.2  jdolecek   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     31      1.1    dyoung   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     32      1.1    dyoung   POSSIBILITY OF SUCH DAMAGE.
     33      1.1    dyoung 
     34      1.1    dyoung ******************************************************************************/
     35  1.5.2.2  jdolecek /*$FreeBSD: head/sys/dev/ixgbe/if_ix.c 320916 2017-07-12 17:35:32Z sbruno $*/
     36  1.5.2.2  jdolecek 
     37      1.1    dyoung /*
     38      1.1    dyoung  * Copyright (c) 2011 The NetBSD Foundation, Inc.
     39      1.1    dyoung  * All rights reserved.
     40      1.1    dyoung  *
     41      1.1    dyoung  * This code is derived from software contributed to The NetBSD Foundation
     42      1.1    dyoung  * by Coyote Point Systems, Inc.
     43      1.1    dyoung  *
     44      1.1    dyoung  * Redistribution and use in source and binary forms, with or without
     45      1.1    dyoung  * modification, are permitted provided that the following conditions
     46      1.1    dyoung  * are met:
     47      1.1    dyoung  * 1. Redistributions of source code must retain the above copyright
     48      1.1    dyoung  *    notice, this list of conditions and the following disclaimer.
     49      1.1    dyoung  * 2. Redistributions in binary form must reproduce the above copyright
     50      1.1    dyoung  *    notice, this list of conditions and the following disclaimer in the
     51      1.1    dyoung  *    documentation and/or other materials provided with the distribution.
     52      1.1    dyoung  *
     53      1.1    dyoung  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     54      1.1    dyoung  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     55      1.1    dyoung  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     56      1.1    dyoung  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     57      1.1    dyoung  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     58      1.1    dyoung  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     59      1.1    dyoung  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     60      1.1    dyoung  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     61      1.1    dyoung  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     62      1.1    dyoung  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     63      1.1    dyoung  * POSSIBILITY OF SUCH DAMAGE.
     64      1.1    dyoung  */
     65      1.1    dyoung 
     66  1.5.2.2  jdolecek #ifdef _KERNEL_OPT
     67      1.1    dyoung #include "opt_inet.h"
     68  1.5.2.2  jdolecek #include "opt_inet6.h"
     69  1.5.2.2  jdolecek #include "opt_net_mpsafe.h"
     70  1.5.2.2  jdolecek #endif
     71      1.1    dyoung 
     72      1.1    dyoung #include "ixgbe.h"
     73  1.5.2.2  jdolecek #include "vlan.h"
     74      1.1    dyoung 
     75  1.5.2.2  jdolecek #include <sys/cprng.h>
     76  1.5.2.2  jdolecek #include <dev/mii/mii.h>
     77  1.5.2.2  jdolecek #include <dev/mii/miivar.h>
     78  1.5.2.2  jdolecek 
     79  1.5.2.2  jdolecek /************************************************************************
     80  1.5.2.2  jdolecek  * Driver version
     81  1.5.2.2  jdolecek  ************************************************************************/
     82  1.5.2.2  jdolecek char ixgbe_driver_version[] = "3.2.12-k";
     83      1.1    dyoung 
     84  1.5.2.2  jdolecek 
     85  1.5.2.2  jdolecek /************************************************************************
     86  1.5.2.2  jdolecek  * PCI Device ID Table
     87  1.5.2.2  jdolecek  *
     88  1.5.2.2  jdolecek  *   Used by probe to select devices to load on
     89  1.5.2.2  jdolecek  *   Last field stores an index into ixgbe_strings
     90  1.5.2.2  jdolecek  *   Last entry must be all 0s
     91  1.5.2.2  jdolecek  *
     92  1.5.2.2  jdolecek  *   { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
     93  1.5.2.2  jdolecek  ************************************************************************/
     94      1.1    dyoung static ixgbe_vendor_info_t ixgbe_vendor_info_array[] =
     95      1.1    dyoung {
     96      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, 0, 0, 0},
     97      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 0, 0, 0},
     98      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, 0, 0, 0},
     99      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0},
    100      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, 0, 0, 0},
    101      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, 0, 0, 0},
    102      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, 0, 0, 0},
    103      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, 0, 0, 0},
    104      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, 0, 0, 0},
    105      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, 0, 0, 0},
    106      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, 0, 0, 0},
    107      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, 0, 0, 0},
    108      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, 0, 0, 0},
    109      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0},
    110      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, 0, 0, 0},
    111      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 0, 0, 0},
    112      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 0, 0, 0},
    113      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 0, 0, 0},
    114      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, 0, 0, 0},
    115  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF2, 0, 0, 0},
    116      1.1    dyoung 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, 0, 0, 0},
    117  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP, 0, 0, 0},
    118  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF_QP, 0, 0, 0},
    119  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_QSFP_SF_QP, 0, 0, 0},
    120  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, 0, 0, 0},
    121  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, 0, 0, 0},
    122  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, 0, 0, 0},
    123  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, 0, 0, 0},
    124  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, 0, 0, 0},
    125  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, 0, 0, 0},
    126  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, 0, 0, 0},
    127  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_1G_T, 0, 0, 0},
    128  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, 0, 0, 0},
    129  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR, 0, 0, 0},
    130  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR_L, 0, 0, 0},
    131  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP, 0, 0, 0},
    132  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP_N, 0, 0, 0},
    133  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII, 0, 0, 0},
    134  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII_L, 0, 0, 0},
    135  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_10G_T, 0, 0, 0},
    136  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T, 0, 0, 0},
    137  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T_L, 0, 0, 0},
    138  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_BYPASS, 0, 0, 0},
    139  1.5.2.2  jdolecek 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BYPASS, 0, 0, 0},
    140      1.1    dyoung 	/* required last entry */
    141      1.1    dyoung 	{0, 0, 0, 0, 0}
    142      1.1    dyoung };
    143      1.1    dyoung 
    144  1.5.2.2  jdolecek /************************************************************************
    145  1.5.2.2  jdolecek  * Table of branding strings
    146  1.5.2.2  jdolecek  ************************************************************************/
    147      1.1    dyoung static const char    *ixgbe_strings[] = {
    148      1.1    dyoung 	"Intel(R) PRO/10GbE PCI-Express Network Driver"
    149      1.1    dyoung };
    150      1.1    dyoung 
    151  1.5.2.2  jdolecek /************************************************************************
    152  1.5.2.2  jdolecek  * Function prototypes
    153  1.5.2.2  jdolecek  ************************************************************************/
    154      1.1    dyoung static int      ixgbe_probe(device_t, cfdata_t, void *);
    155      1.1    dyoung static void     ixgbe_attach(device_t, device_t, void *);
    156      1.1    dyoung static int      ixgbe_detach(device_t, int);
    157      1.1    dyoung #if 0
    158      1.1    dyoung static int      ixgbe_shutdown(device_t);
    159      1.1    dyoung #endif
    160  1.5.2.2  jdolecek static bool	ixgbe_suspend(device_t, const pmf_qual_t *);
    161  1.5.2.2  jdolecek static bool	ixgbe_resume(device_t, const pmf_qual_t *);
    162  1.5.2.2  jdolecek static int	ixgbe_ifflags_cb(struct ethercom *);
    163      1.1    dyoung static int      ixgbe_ioctl(struct ifnet *, u_long, void *);
    164      1.1    dyoung static void	ixgbe_ifstop(struct ifnet *, int);
    165      1.1    dyoung static int	ixgbe_init(struct ifnet *);
    166      1.1    dyoung static void	ixgbe_init_locked(struct adapter *);
    167      1.1    dyoung static void     ixgbe_stop(void *);
    168  1.5.2.2  jdolecek static void     ixgbe_init_device_features(struct adapter *);
    169  1.5.2.2  jdolecek static void     ixgbe_check_fan_failure(struct adapter *, u32, bool);
    170  1.5.2.2  jdolecek static void	ixgbe_add_media_types(struct adapter *);
    171      1.1    dyoung static void     ixgbe_media_status(struct ifnet *, struct ifmediareq *);
    172      1.1    dyoung static int      ixgbe_media_change(struct ifnet *);
    173      1.1    dyoung static int      ixgbe_allocate_pci_resources(struct adapter *,
    174      1.1    dyoung 		    const struct pci_attach_args *);
    175  1.5.2.2  jdolecek static void	ixgbe_get_slot_info(struct adapter *);
    176      1.1    dyoung static int      ixgbe_allocate_msix(struct adapter *,
    177      1.1    dyoung 		    const struct pci_attach_args *);
    178      1.1    dyoung static int      ixgbe_allocate_legacy(struct adapter *,
    179      1.1    dyoung 		    const struct pci_attach_args *);
    180  1.5.2.2  jdolecek static int      ixgbe_configure_interrupts(struct adapter *);
    181      1.1    dyoung static void	ixgbe_free_pci_resources(struct adapter *);
    182      1.1    dyoung static void	ixgbe_local_timer(void *);
    183  1.5.2.2  jdolecek static void	ixgbe_local_timer1(void *);
    184      1.1    dyoung static int	ixgbe_setup_interface(device_t, struct adapter *);
    185  1.5.2.2  jdolecek static void	ixgbe_config_gpie(struct adapter *);
    186  1.5.2.2  jdolecek static void	ixgbe_config_dmac(struct adapter *);
    187  1.5.2.2  jdolecek static void	ixgbe_config_delay_values(struct adapter *);
    188      1.1    dyoung static void	ixgbe_config_link(struct adapter *);
    189  1.5.2.2  jdolecek static void	ixgbe_check_wol_support(struct adapter *);
    190  1.5.2.2  jdolecek static int	ixgbe_setup_low_power_mode(struct adapter *);
    191  1.5.2.2  jdolecek static void	ixgbe_rearm_queues(struct adapter *, u64);
    192      1.1    dyoung 
    193      1.1    dyoung static void     ixgbe_initialize_transmit_units(struct adapter *);
    194      1.1    dyoung static void     ixgbe_initialize_receive_units(struct adapter *);
    195  1.5.2.2  jdolecek static void	ixgbe_enable_rx_drop(struct adapter *);
    196  1.5.2.2  jdolecek static void	ixgbe_disable_rx_drop(struct adapter *);
    197  1.5.2.2  jdolecek static void	ixgbe_initialize_rss_mapping(struct adapter *);
    198      1.1    dyoung 
    199      1.1    dyoung static void     ixgbe_enable_intr(struct adapter *);
    200      1.1    dyoung static void     ixgbe_disable_intr(struct adapter *);
    201      1.1    dyoung static void     ixgbe_update_stats_counters(struct adapter *);
    202      1.1    dyoung static void     ixgbe_set_promisc(struct adapter *);
    203      1.1    dyoung static void     ixgbe_set_multi(struct adapter *);
    204      1.1    dyoung static void     ixgbe_update_link_status(struct adapter *);
    205      1.1    dyoung static void	ixgbe_set_ivar(struct adapter *, u8, u8, s8);
    206      1.1    dyoung static void	ixgbe_configure_ivars(struct adapter *);
    207      1.1    dyoung static u8 *	ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
    208      1.1    dyoung 
    209      1.1    dyoung static void	ixgbe_setup_vlan_hw_support(struct adapter *);
    210      1.1    dyoung #if 0
    211      1.1    dyoung static void	ixgbe_register_vlan(void *, struct ifnet *, u16);
    212      1.1    dyoung static void	ixgbe_unregister_vlan(void *, struct ifnet *, u16);
    213      1.1    dyoung #endif
    214      1.1    dyoung 
    215  1.5.2.2  jdolecek static void	ixgbe_add_device_sysctls(struct adapter *);
    216  1.5.2.2  jdolecek static void     ixgbe_add_hw_stats(struct adapter *);
    217  1.5.2.2  jdolecek static void	ixgbe_clear_evcnt(struct adapter *);
    218  1.5.2.2  jdolecek static int	ixgbe_set_flowcntl(struct adapter *, int);
    219  1.5.2.2  jdolecek static int	ixgbe_set_advertise(struct adapter *, int);
    220  1.5.2.2  jdolecek static int      ixgbe_get_advertise(struct adapter *);
    221  1.5.2.2  jdolecek 
    222  1.5.2.2  jdolecek /* Sysctl handlers */
    223  1.5.2.2  jdolecek static void	ixgbe_set_sysctl_value(struct adapter *, const char *,
    224  1.5.2.2  jdolecek 		     const char *, int *, int);
    225  1.5.2.2  jdolecek static int	ixgbe_sysctl_flowcntl(SYSCTLFN_PROTO);
    226  1.5.2.2  jdolecek static int	ixgbe_sysctl_advertise(SYSCTLFN_PROTO);
    227  1.5.2.2  jdolecek static int      ixgbe_sysctl_interrupt_rate_handler(SYSCTLFN_PROTO);
    228  1.5.2.2  jdolecek static int	ixgbe_sysctl_dmac(SYSCTLFN_PROTO);
    229  1.5.2.2  jdolecek static int	ixgbe_sysctl_phy_temp(SYSCTLFN_PROTO);
    230  1.5.2.2  jdolecek static int	ixgbe_sysctl_phy_overtemp_occurred(SYSCTLFN_PROTO);
    231  1.5.2.2  jdolecek #ifdef IXGBE_DEBUG
    232  1.5.2.2  jdolecek static int	ixgbe_sysctl_power_state(SYSCTLFN_PROTO);
    233  1.5.2.2  jdolecek static int	ixgbe_sysctl_print_rss_config(SYSCTLFN_PROTO);
    234  1.5.2.2  jdolecek #endif
    235  1.5.2.2  jdolecek static int      ixgbe_sysctl_rdh_handler(SYSCTLFN_PROTO);
    236  1.5.2.2  jdolecek static int      ixgbe_sysctl_rdt_handler(SYSCTLFN_PROTO);
    237  1.5.2.2  jdolecek static int      ixgbe_sysctl_tdt_handler(SYSCTLFN_PROTO);
    238  1.5.2.2  jdolecek static int      ixgbe_sysctl_tdh_handler(SYSCTLFN_PROTO);
    239  1.5.2.2  jdolecek static int      ixgbe_sysctl_eee_state(SYSCTLFN_PROTO);
    240  1.5.2.2  jdolecek static int	ixgbe_sysctl_wol_enable(SYSCTLFN_PROTO);
    241  1.5.2.2  jdolecek static int	ixgbe_sysctl_wufc(SYSCTLFN_PROTO);
    242      1.1    dyoung 
    243      1.1    dyoung /* Support for pluggable optic modules */
    244      1.1    dyoung static bool	ixgbe_sfp_probe(struct adapter *);
    245      1.1    dyoung 
    246  1.5.2.2  jdolecek /* Legacy (single vector) interrupt handler */
    247      1.1    dyoung static int	ixgbe_legacy_irq(void *);
    248      1.1    dyoung 
    249  1.5.2.2  jdolecek /* The MSI/MSI-X Interrupt handlers */
    250  1.5.2.2  jdolecek static int	ixgbe_msix_que(void *);
    251  1.5.2.2  jdolecek static int	ixgbe_msix_link(void *);
    252      1.1    dyoung 
    253      1.1    dyoung /* Software interrupts for deferred work */
    254      1.1    dyoung static void	ixgbe_handle_que(void *);
    255      1.1    dyoung static void	ixgbe_handle_link(void *);
    256      1.1    dyoung static void	ixgbe_handle_msf(void *);
    257      1.1    dyoung static void	ixgbe_handle_mod(void *);
    258  1.5.2.2  jdolecek static void	ixgbe_handle_phy(void *);
    259      1.1    dyoung 
    260      1.1    dyoung static ixgbe_vendor_info_t *ixgbe_lookup(const struct pci_attach_args *);
    261      1.1    dyoung 
    262  1.5.2.2  jdolecek /************************************************************************
    263  1.5.2.2  jdolecek  *  NetBSD Device Interface Entry Points
    264  1.5.2.2  jdolecek  ************************************************************************/
    265      1.1    dyoung CFATTACH_DECL3_NEW(ixg, sizeof(struct adapter),
    266      1.1    dyoung     ixgbe_probe, ixgbe_attach, ixgbe_detach, NULL, NULL, NULL,
    267      1.1    dyoung     DVF_DETACH_SHUTDOWN);
    268      1.1    dyoung 
    269      1.1    dyoung #if 0
    270  1.5.2.2  jdolecek devclass_t ix_devclass;
    271  1.5.2.2  jdolecek DRIVER_MODULE(ix, pci, ix_driver, ix_devclass, 0, 0);
    272      1.1    dyoung 
    273  1.5.2.2  jdolecek MODULE_DEPEND(ix, pci, 1, 1, 1);
    274  1.5.2.2  jdolecek MODULE_DEPEND(ix, ether, 1, 1, 1);
    275      1.1    dyoung #endif
    276      1.1    dyoung 
    277      1.1    dyoung /*
    278  1.5.2.2  jdolecek  * TUNEABLE PARAMETERS:
    279  1.5.2.2  jdolecek  */
    280      1.1    dyoung 
    281      1.1    dyoung /*
    282  1.5.2.2  jdolecek  * AIM: Adaptive Interrupt Moderation
    283  1.5.2.2  jdolecek  * which means that the interrupt rate
    284  1.5.2.2  jdolecek  * is varied over time based on the
    285  1.5.2.2  jdolecek  * traffic for that interrupt vector
    286  1.5.2.2  jdolecek  */
    287  1.5.2.2  jdolecek static bool ixgbe_enable_aim = true;
    288  1.5.2.2  jdolecek #define SYSCTL_INT(_a1, _a2, _a3, _a4, _a5, _a6, _a7)
    289  1.5.2.2  jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, enable_aim, CTLFLAG_RDTUN, &ixgbe_enable_aim, 0,
    290  1.5.2.2  jdolecek     "Enable adaptive interrupt moderation");
    291  1.5.2.2  jdolecek 
    292  1.5.2.2  jdolecek static int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY);
    293  1.5.2.2  jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN,
    294  1.5.2.2  jdolecek     &ixgbe_max_interrupt_rate, 0, "Maximum interrupts per second");
    295      1.1    dyoung 
    296      1.1    dyoung /* How many packets rxeof tries to clean at a time */
    297      1.1    dyoung static int ixgbe_rx_process_limit = 256;
    298  1.5.2.2  jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN,
    299  1.5.2.2  jdolecek     &ixgbe_rx_process_limit, 0, "Maximum number of received packets to process at a time, -1 means unlimited");
    300  1.5.2.2  jdolecek 
    301  1.5.2.2  jdolecek /* How many packets txeof tries to clean at a time */
    302  1.5.2.2  jdolecek static int ixgbe_tx_process_limit = 256;
    303  1.5.2.2  jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, tx_process_limit, CTLFLAG_RDTUN,
    304  1.5.2.2  jdolecek     &ixgbe_tx_process_limit, 0,
    305  1.5.2.2  jdolecek     "Maximum number of sent packets to process at a time, -1 means unlimited");
    306      1.1    dyoung 
    307      1.1    dyoung /* Flow control setting, default to full */
    308      1.1    dyoung static int ixgbe_flow_control = ixgbe_fc_full;
    309  1.5.2.2  jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, flow_control, CTLFLAG_RDTUN,
    310  1.5.2.2  jdolecek     &ixgbe_flow_control, 0, "Default flow control used for all adapters");
    311      1.1    dyoung 
    312      1.1    dyoung /*
    313  1.5.2.2  jdolecek  * Smart speed setting, default to on
    314  1.5.2.2  jdolecek  * this only works as a compile option
    315  1.5.2.2  jdolecek  * right now as its during attach, set
    316  1.5.2.2  jdolecek  * this to 'ixgbe_smart_speed_off' to
    317  1.5.2.2  jdolecek  * disable.
    318  1.5.2.2  jdolecek  */
    319      1.1    dyoung static int ixgbe_smart_speed = ixgbe_smart_speed_on;
    320      1.1    dyoung 
    321      1.1    dyoung /*
    322  1.5.2.2  jdolecek  * MSI-X should be the default for best performance,
    323      1.1    dyoung  * but this allows it to be forced off for testing.
    324      1.1    dyoung  */
    325      1.1    dyoung static int ixgbe_enable_msix = 1;
    326  1.5.2.2  jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixgbe_enable_msix, 0,
    327  1.5.2.2  jdolecek     "Enable MSI-X interrupts");
    328      1.1    dyoung 
    329      1.1    dyoung /*
    330      1.1    dyoung  * Number of Queues, can be set to 0,
    331      1.1    dyoung  * it then autoconfigures based on the
    332      1.1    dyoung  * number of cpus with a max of 8. This
    333      1.1    dyoung  * can be overriden manually here.
    334      1.1    dyoung  */
    335      1.1    dyoung static int ixgbe_num_queues = 0;
    336  1.5.2.2  jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, num_queues, CTLFLAG_RDTUN, &ixgbe_num_queues, 0,
    337  1.5.2.2  jdolecek     "Number of queues to configure, 0 indicates autoconfigure");
    338      1.1    dyoung 
    339      1.1    dyoung /*
    340  1.5.2.2  jdolecek  * Number of TX descriptors per ring,
    341  1.5.2.2  jdolecek  * setting higher than RX as this seems
    342  1.5.2.2  jdolecek  * the better performing choice.
    343  1.5.2.2  jdolecek  */
    344      1.1    dyoung static int ixgbe_txd = PERFORM_TXD;
    345  1.5.2.2  jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, txd, CTLFLAG_RDTUN, &ixgbe_txd, 0,
    346  1.5.2.2  jdolecek     "Number of transmit descriptors per queue");
    347      1.1    dyoung 
    348      1.1    dyoung /* Number of RX descriptors per ring */
    349      1.1    dyoung static int ixgbe_rxd = PERFORM_RXD;
    350  1.5.2.2  jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, rxd, CTLFLAG_RDTUN, &ixgbe_rxd, 0,
    351  1.5.2.2  jdolecek     "Number of receive descriptors per queue");
    352  1.5.2.2  jdolecek 
    353  1.5.2.2  jdolecek /*
    354  1.5.2.2  jdolecek  * Defining this on will allow the use
    355  1.5.2.2  jdolecek  * of unsupported SFP+ modules, note that
    356  1.5.2.2  jdolecek  * doing so you are on your own :)
    357  1.5.2.2  jdolecek  */
    358  1.5.2.2  jdolecek static int allow_unsupported_sfp = false;
    359  1.5.2.2  jdolecek #define TUNABLE_INT(__x, __y)
    360  1.5.2.2  jdolecek TUNABLE_INT("hw.ix.unsupported_sfp", &allow_unsupported_sfp);
    361  1.5.2.2  jdolecek 
    362  1.5.2.2  jdolecek /*
    363  1.5.2.2  jdolecek  * Not sure if Flow Director is fully baked,
    364  1.5.2.2  jdolecek  * so we'll default to turning it off.
    365  1.5.2.2  jdolecek  */
    366  1.5.2.2  jdolecek static int ixgbe_enable_fdir = 0;
    367  1.5.2.2  jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, enable_fdir, CTLFLAG_RDTUN, &ixgbe_enable_fdir, 0,
    368  1.5.2.2  jdolecek     "Enable Flow Director");
    369  1.5.2.2  jdolecek 
    370  1.5.2.2  jdolecek /* Legacy Transmit (single queue) */
    371  1.5.2.2  jdolecek static int ixgbe_enable_legacy_tx = 0;
    372  1.5.2.2  jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, enable_legacy_tx, CTLFLAG_RDTUN,
    373  1.5.2.2  jdolecek     &ixgbe_enable_legacy_tx, 0, "Enable Legacy TX flow");
    374  1.5.2.2  jdolecek 
    375  1.5.2.2  jdolecek /* Receive-Side Scaling */
    376  1.5.2.2  jdolecek static int ixgbe_enable_rss = 1;
    377  1.5.2.2  jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, enable_rss, CTLFLAG_RDTUN, &ixgbe_enable_rss, 0,
    378  1.5.2.2  jdolecek     "Enable Receive-Side Scaling (RSS)");
    379      1.1    dyoung 
    380      1.1    dyoung /* Keep running tab on them for sanity check */
    381      1.1    dyoung static int ixgbe_total_ports;
    382      1.1    dyoung 
    383  1.5.2.2  jdolecek #if 0
    384  1.5.2.2  jdolecek static int (*ixgbe_start_locked)(struct ifnet *, struct tx_ring *);
    385  1.5.2.2  jdolecek static int (*ixgbe_ring_empty)(struct ifnet *, pcq_t *);
    386      1.1    dyoung #endif
    387      1.1    dyoung 
    388  1.5.2.2  jdolecek #ifdef NET_MPSAFE
    389  1.5.2.2  jdolecek #define IXGBE_MPSAFE		1
    390  1.5.2.2  jdolecek #define IXGBE_CALLOUT_FLAGS	CALLOUT_MPSAFE
    391  1.5.2.2  jdolecek #define IXGBE_SOFTINFT_FLAGS	SOFTINT_MPSAFE
    392  1.5.2.2  jdolecek #else
    393  1.5.2.2  jdolecek #define IXGBE_CALLOUT_FLAGS	0
    394  1.5.2.2  jdolecek #define IXGBE_SOFTINFT_FLAGS	0
    395  1.5.2.2  jdolecek #endif
    396      1.1    dyoung 
    397  1.5.2.2  jdolecek /************************************************************************
    398  1.5.2.2  jdolecek  * ixgbe_initialize_rss_mapping
    399  1.5.2.2  jdolecek  ************************************************************************/
    400  1.5.2.2  jdolecek static void
    401  1.5.2.2  jdolecek ixgbe_initialize_rss_mapping(struct adapter *adapter)
    402      1.1    dyoung {
    403  1.5.2.2  jdolecek 	struct ixgbe_hw	*hw = &adapter->hw;
    404  1.5.2.2  jdolecek 	u32             reta = 0, mrqc, rss_key[10];
    405  1.5.2.2  jdolecek 	int             queue_id, table_size, index_mult;
    406  1.5.2.2  jdolecek 	int             i, j;
    407  1.5.2.2  jdolecek 	u32             rss_hash_config;
    408  1.5.2.2  jdolecek 
    409  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_RSS) {
    410  1.5.2.2  jdolecek 		/* Fetch the configured RSS key */
    411  1.5.2.2  jdolecek 		rss_getkey((uint8_t *) &rss_key);
    412  1.5.2.2  jdolecek 	} else {
    413  1.5.2.2  jdolecek 		/* set up random bits */
    414  1.5.2.2  jdolecek 		cprng_fast(&rss_key, sizeof(rss_key));
    415  1.5.2.2  jdolecek 	}
    416      1.1    dyoung 
    417  1.5.2.2  jdolecek 	/* Set multiplier for RETA setup and table size based on MAC */
    418  1.5.2.2  jdolecek 	index_mult = 0x1;
    419  1.5.2.2  jdolecek 	table_size = 128;
    420  1.5.2.2  jdolecek 	switch (adapter->hw.mac.type) {
    421  1.5.2.2  jdolecek 	case ixgbe_mac_82598EB:
    422  1.5.2.2  jdolecek 		index_mult = 0x11;
    423  1.5.2.2  jdolecek 		break;
    424  1.5.2.2  jdolecek 	case ixgbe_mac_X550:
    425  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
    426  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
    427  1.5.2.2  jdolecek 		table_size = 512;
    428  1.5.2.2  jdolecek 		break;
    429  1.5.2.2  jdolecek 	default:
    430  1.5.2.2  jdolecek 		break;
    431  1.5.2.2  jdolecek 	}
    432      1.1    dyoung 
    433  1.5.2.2  jdolecek 	/* Set up the redirection table */
    434  1.5.2.2  jdolecek 	for (i = 0, j = 0; i < table_size; i++, j++) {
    435  1.5.2.2  jdolecek 		if (j == adapter->num_queues)
    436  1.5.2.2  jdolecek 			j = 0;
    437  1.5.2.2  jdolecek 
    438  1.5.2.2  jdolecek 		if (adapter->feat_en & IXGBE_FEATURE_RSS) {
    439  1.5.2.2  jdolecek 			/*
    440  1.5.2.2  jdolecek 			 * Fetch the RSS bucket id for the given indirection
    441  1.5.2.2  jdolecek 			 * entry. Cap it at the number of configured buckets
    442  1.5.2.2  jdolecek 			 * (which is num_queues.)
    443  1.5.2.2  jdolecek 			 */
    444  1.5.2.2  jdolecek 			queue_id = rss_get_indirection_to_bucket(i);
    445  1.5.2.2  jdolecek 			queue_id = queue_id % adapter->num_queues;
    446  1.5.2.2  jdolecek 		} else
    447  1.5.2.2  jdolecek 			queue_id = (j * index_mult);
    448  1.5.2.2  jdolecek 
    449  1.5.2.2  jdolecek 		/*
    450  1.5.2.2  jdolecek 		 * The low 8 bits are for hash value (n+0);
    451  1.5.2.2  jdolecek 		 * The next 8 bits are for hash value (n+1), etc.
    452  1.5.2.2  jdolecek 		 */
    453  1.5.2.2  jdolecek 		reta = reta >> 8;
    454  1.5.2.2  jdolecek 		reta = reta | (((uint32_t) queue_id) << 24);
    455  1.5.2.2  jdolecek 		if ((i & 3) == 3) {
    456  1.5.2.2  jdolecek 			if (i < 128)
    457  1.5.2.2  jdolecek 				IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
    458  1.5.2.2  jdolecek 			else
    459  1.5.2.2  jdolecek 				IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32),
    460  1.5.2.2  jdolecek 				    reta);
    461  1.5.2.2  jdolecek 			reta = 0;
    462  1.5.2.2  jdolecek 		}
    463  1.5.2.2  jdolecek 	}
    464  1.5.2.2  jdolecek 
    465  1.5.2.2  jdolecek 	/* Now fill our hash function seeds */
    466  1.5.2.2  jdolecek 	for (i = 0; i < 10; i++)
    467  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]);
    468  1.5.2.2  jdolecek 
    469  1.5.2.2  jdolecek 	/* Perform hash on these packet types */
    470  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_RSS)
    471  1.5.2.2  jdolecek 		rss_hash_config = rss_gethashconfig();
    472  1.5.2.2  jdolecek 	else {
    473  1.5.2.2  jdolecek 		/*
    474  1.5.2.2  jdolecek 		 * Disable UDP - IP fragments aren't currently being handled
    475  1.5.2.2  jdolecek 		 * and so we end up with a mix of 2-tuple and 4-tuple
    476  1.5.2.2  jdolecek 		 * traffic.
    477  1.5.2.2  jdolecek 		 */
    478  1.5.2.2  jdolecek 		rss_hash_config = RSS_HASHTYPE_RSS_IPV4
    479  1.5.2.2  jdolecek 		                | RSS_HASHTYPE_RSS_TCP_IPV4
    480  1.5.2.2  jdolecek 		                | RSS_HASHTYPE_RSS_IPV6
    481  1.5.2.2  jdolecek 		                | RSS_HASHTYPE_RSS_TCP_IPV6
    482  1.5.2.2  jdolecek 		                | RSS_HASHTYPE_RSS_IPV6_EX
    483  1.5.2.2  jdolecek 		                | RSS_HASHTYPE_RSS_TCP_IPV6_EX;
    484  1.5.2.2  jdolecek 	}
    485  1.5.2.2  jdolecek 
    486  1.5.2.2  jdolecek 	mrqc = IXGBE_MRQC_RSSEN;
    487  1.5.2.2  jdolecek 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4)
    488  1.5.2.2  jdolecek 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4;
    489  1.5.2.2  jdolecek 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4)
    490  1.5.2.2  jdolecek 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP;
    491  1.5.2.2  jdolecek 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6)
    492  1.5.2.2  jdolecek 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6;
    493  1.5.2.2  jdolecek 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6)
    494  1.5.2.2  jdolecek 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
    495  1.5.2.2  jdolecek 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX)
    496  1.5.2.2  jdolecek 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX;
    497  1.5.2.2  jdolecek 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX)
    498  1.5.2.2  jdolecek 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP;
    499  1.5.2.2  jdolecek 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4)
    500  1.5.2.2  jdolecek 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
    501  1.5.2.2  jdolecek 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4_EX)
    502  1.5.2.2  jdolecek 		device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_UDP_IPV4_EX defined, but not supported\n",
    503  1.5.2.2  jdolecek 		    __func__);
    504  1.5.2.2  jdolecek 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6)
    505  1.5.2.2  jdolecek 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
    506  1.5.2.2  jdolecek 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX)
    507  1.5.2.2  jdolecek 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
    508  1.5.2.2  jdolecek 	mrqc |= ixgbe_get_mrqc(adapter->iov_mode);
    509  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
    510  1.5.2.2  jdolecek } /* ixgbe_initialize_rss_mapping */
    511  1.5.2.2  jdolecek 
    512  1.5.2.2  jdolecek /************************************************************************
    513  1.5.2.2  jdolecek  * ixgbe_initialize_receive_units - Setup receive registers and features.
    514  1.5.2.2  jdolecek  ************************************************************************/
    515  1.5.2.2  jdolecek #define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1)
    516  1.5.2.2  jdolecek 
    517  1.5.2.2  jdolecek static void
    518  1.5.2.2  jdolecek ixgbe_initialize_receive_units(struct adapter *adapter)
    519      1.1    dyoung {
    520  1.5.2.2  jdolecek 	struct	rx_ring	*rxr = adapter->rx_rings;
    521  1.5.2.2  jdolecek 	struct ixgbe_hw	*hw = &adapter->hw;
    522  1.5.2.2  jdolecek 	struct ifnet    *ifp = adapter->ifp;
    523  1.5.2.2  jdolecek 	int             i, j;
    524  1.5.2.2  jdolecek 	u32		bufsz, fctrl, srrctl, rxcsum;
    525  1.5.2.2  jdolecek 	u32		hlreg;
    526      1.1    dyoung 
    527  1.5.2.2  jdolecek 	/*
    528  1.5.2.2  jdolecek 	 * Make sure receives are disabled while
    529  1.5.2.2  jdolecek 	 * setting up the descriptor ring
    530  1.5.2.2  jdolecek 	 */
    531  1.5.2.2  jdolecek 	ixgbe_disable_rx(hw);
    532      1.1    dyoung 
    533  1.5.2.2  jdolecek 	/* Enable broadcasts */
    534  1.5.2.2  jdolecek 	fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
    535  1.5.2.2  jdolecek 	fctrl |= IXGBE_FCTRL_BAM;
    536  1.5.2.2  jdolecek 	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
    537  1.5.2.2  jdolecek 		fctrl |= IXGBE_FCTRL_DPF;
    538  1.5.2.2  jdolecek 		fctrl |= IXGBE_FCTRL_PMCF;
    539  1.5.2.2  jdolecek 	}
    540  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
    541      1.1    dyoung 
    542  1.5.2.2  jdolecek 	/* Set for Jumbo Frames? */
    543  1.5.2.2  jdolecek 	hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0);
    544  1.5.2.2  jdolecek 	if (ifp->if_mtu > ETHERMTU)
    545  1.5.2.2  jdolecek 		hlreg |= IXGBE_HLREG0_JUMBOEN;
    546  1.5.2.2  jdolecek 	else
    547  1.5.2.2  jdolecek 		hlreg &= ~IXGBE_HLREG0_JUMBOEN;
    548      1.1    dyoung 
    549  1.5.2.2  jdolecek #ifdef DEV_NETMAP
    550  1.5.2.2  jdolecek 	/* CRC stripping is conditional in Netmap */
    551  1.5.2.2  jdolecek 	if ((adapter->feat_en & IXGBE_FEATURE_NETMAP) &&
    552  1.5.2.2  jdolecek 	    (ifp->if_capenable & IFCAP_NETMAP) &&
    553  1.5.2.2  jdolecek 	    !ix_crcstrip)
    554  1.5.2.2  jdolecek 		hlreg &= ~IXGBE_HLREG0_RXCRCSTRP;
    555  1.5.2.2  jdolecek 	else
    556  1.5.2.2  jdolecek #endif /* DEV_NETMAP */
    557  1.5.2.2  jdolecek 		hlreg |= IXGBE_HLREG0_RXCRCSTRP;
    558      1.1    dyoung 
    559  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg);
    560      1.1    dyoung 
    561  1.5.2.2  jdolecek 	bufsz = (adapter->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >>
    562  1.5.2.2  jdolecek 	    IXGBE_SRRCTL_BSIZEPKT_SHIFT;
    563  1.5.2.2  jdolecek 
    564  1.5.2.2  jdolecek 	for (i = 0; i < adapter->num_queues; i++, rxr++) {
    565  1.5.2.2  jdolecek 		u64 rdba = rxr->rxdma.dma_paddr;
    566  1.5.2.2  jdolecek 		u32 tqsmreg, reg;
    567  1.5.2.2  jdolecek 		int regnum = i / 4;	/* 1 register per 4 queues */
    568  1.5.2.2  jdolecek 		int regshift = i % 4;	/* 4 bits per 1 queue */
    569  1.5.2.2  jdolecek 		j = rxr->me;
    570  1.5.2.2  jdolecek 
    571  1.5.2.2  jdolecek 		/* Setup the Base and Length of the Rx Descriptor Ring */
    572  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j),
    573  1.5.2.2  jdolecek 		    (rdba & 0x00000000ffffffffULL));
    574  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32));
    575  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j),
    576  1.5.2.2  jdolecek 		    adapter->num_rx_desc * sizeof(union ixgbe_adv_rx_desc));
    577  1.5.2.2  jdolecek 
    578  1.5.2.2  jdolecek 		/* Set up the SRRCTL register */
    579  1.5.2.2  jdolecek 		srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(j));
    580  1.5.2.2  jdolecek 		srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
    581  1.5.2.2  jdolecek 		srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
    582  1.5.2.2  jdolecek 		srrctl |= bufsz;
    583  1.5.2.2  jdolecek 		srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
    584  1.5.2.2  jdolecek 
    585  1.5.2.2  jdolecek 		/* Set RQSMR (Receive Queue Statistic Mapping) register */
    586  1.5.2.2  jdolecek 		reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(regnum));
    587  1.5.2.2  jdolecek 		reg &= ~(0x000000ff << (regshift * 8));
    588  1.5.2.2  jdolecek 		reg |= i << (regshift * 8);
    589  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_RQSMR(regnum), reg);
    590  1.5.2.2  jdolecek 
    591  1.5.2.2  jdolecek 		/*
    592  1.5.2.2  jdolecek 		 * Set RQSMR (Receive Queue Statistic Mapping) register.
    593  1.5.2.2  jdolecek 		 * Register location for queue 0...7 are different between
    594  1.5.2.2  jdolecek 		 * 82598 and newer.
    595  1.5.2.2  jdolecek 		 */
    596  1.5.2.2  jdolecek 		if (adapter->hw.mac.type == ixgbe_mac_82598EB)
    597  1.5.2.2  jdolecek 			tqsmreg = IXGBE_TQSMR(regnum);
    598  1.5.2.2  jdolecek 		else
    599  1.5.2.2  jdolecek 			tqsmreg = IXGBE_TQSM(regnum);
    600  1.5.2.2  jdolecek 		reg = IXGBE_READ_REG(hw, tqsmreg);
    601  1.5.2.2  jdolecek 		reg &= ~(0x000000ff << (regshift * 8));
    602  1.5.2.2  jdolecek 		reg |= i << (regshift * 8);
    603  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, tqsmreg, reg);
    604  1.5.2.2  jdolecek 
    605  1.5.2.2  jdolecek 		/*
    606  1.5.2.2  jdolecek 		 * Set DROP_EN iff we have no flow control and >1 queue.
    607  1.5.2.2  jdolecek 		 * Note that srrctl was cleared shortly before during reset,
    608  1.5.2.2  jdolecek 		 * so we do not need to clear the bit, but do it just in case
    609  1.5.2.2  jdolecek 		 * this code is moved elsewhere.
    610  1.5.2.2  jdolecek 		 */
    611  1.5.2.2  jdolecek 		if (adapter->num_queues > 1 &&
    612  1.5.2.2  jdolecek 		    adapter->hw.fc.requested_mode == ixgbe_fc_none) {
    613  1.5.2.2  jdolecek 			srrctl |= IXGBE_SRRCTL_DROP_EN;
    614  1.5.2.2  jdolecek 		} else {
    615  1.5.2.2  jdolecek 			srrctl &= ~IXGBE_SRRCTL_DROP_EN;
    616      1.1    dyoung 		}
    617  1.5.2.2  jdolecek 
    618  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl);
    619  1.5.2.2  jdolecek 
    620  1.5.2.2  jdolecek 		/* Setup the HW Rx Head and Tail Descriptor Pointers */
    621  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
    622  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
    623  1.5.2.2  jdolecek 
    624  1.5.2.2  jdolecek 		/* Set the driver rx tail address */
    625  1.5.2.2  jdolecek 		rxr->tail =  IXGBE_RDT(rxr->me);
    626      1.1    dyoung 	}
    627      1.1    dyoung 
    628  1.5.2.2  jdolecek 	if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
    629  1.5.2.2  jdolecek 		u32 psrtype = IXGBE_PSRTYPE_TCPHDR
    630  1.5.2.2  jdolecek 		            | IXGBE_PSRTYPE_UDPHDR
    631  1.5.2.2  jdolecek 		            | IXGBE_PSRTYPE_IPV4HDR
    632  1.5.2.2  jdolecek 		            | IXGBE_PSRTYPE_IPV6HDR;
    633  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype);
    634  1.5.2.2  jdolecek 	}
    635  1.5.2.2  jdolecek 
    636  1.5.2.2  jdolecek 	rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
    637  1.5.2.2  jdolecek 
    638  1.5.2.2  jdolecek 	ixgbe_initialize_rss_mapping(adapter);
    639  1.5.2.2  jdolecek 
    640  1.5.2.2  jdolecek 	if (adapter->num_queues > 1) {
    641  1.5.2.2  jdolecek 		/* RSS and RX IPP Checksum are mutually exclusive */
    642  1.5.2.2  jdolecek 		rxcsum |= IXGBE_RXCSUM_PCSD;
    643  1.5.2.2  jdolecek 	}
    644  1.5.2.2  jdolecek 
    645  1.5.2.2  jdolecek 	if (ifp->if_capenable & IFCAP_RXCSUM)
    646  1.5.2.2  jdolecek 		rxcsum |= IXGBE_RXCSUM_PCSD;
    647  1.5.2.2  jdolecek 
    648  1.5.2.2  jdolecek 	/* This is useful for calculating UDP/IP fragment checksums */
    649  1.5.2.2  jdolecek 	if (!(rxcsum & IXGBE_RXCSUM_PCSD))
    650  1.5.2.2  jdolecek 		rxcsum |= IXGBE_RXCSUM_IPPCSE;
    651  1.5.2.2  jdolecek 
    652  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
    653  1.5.2.2  jdolecek 
    654  1.5.2.2  jdolecek 	return;
    655  1.5.2.2  jdolecek } /* ixgbe_initialize_receive_units */
    656      1.1    dyoung 
    657  1.5.2.2  jdolecek /************************************************************************
    658  1.5.2.2  jdolecek  * ixgbe_initialize_transmit_units - Enable transmit units.
    659  1.5.2.2  jdolecek  ************************************************************************/
    660      1.1    dyoung static void
    661  1.5.2.2  jdolecek ixgbe_initialize_transmit_units(struct adapter *adapter)
    662      1.1    dyoung {
    663  1.5.2.2  jdolecek 	struct tx_ring  *txr = adapter->tx_rings;
    664  1.5.2.2  jdolecek 	struct ixgbe_hw	*hw = &adapter->hw;
    665      1.1    dyoung 
    666  1.5.2.2  jdolecek 	/* Setup the Base and Length of the Tx Descriptor Ring */
    667  1.5.2.2  jdolecek 	for (int i = 0; i < adapter->num_queues; i++, txr++) {
    668  1.5.2.2  jdolecek 		u64 tdba = txr->txdma.dma_paddr;
    669  1.5.2.2  jdolecek 		u32 txctrl = 0;
    670  1.5.2.2  jdolecek 		int j = txr->me;
    671  1.5.2.2  jdolecek 
    672  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
    673  1.5.2.2  jdolecek 		    (tdba & 0x00000000ffffffffULL));
    674  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32));
    675  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j),
    676  1.5.2.2  jdolecek 		    adapter->num_tx_desc * sizeof(union ixgbe_adv_tx_desc));
    677      1.1    dyoung 
    678  1.5.2.2  jdolecek 		/* Setup the HW Tx Head and Tail descriptor pointers */
    679  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
    680  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
    681      1.1    dyoung 
    682  1.5.2.2  jdolecek 		/* Cache the tail address */
    683  1.5.2.2  jdolecek 		txr->tail = IXGBE_TDT(j);
    684      1.1    dyoung 
    685  1.5.2.2  jdolecek 		/* Disable Head Writeback */
    686  1.5.2.2  jdolecek 		/*
    687  1.5.2.2  jdolecek 		 * Note: for X550 series devices, these registers are actually
    688  1.5.2.2  jdolecek 		 * prefixed with TPH_ isntead of DCA_, but the addresses and
    689  1.5.2.2  jdolecek 		 * fields remain the same.
    690  1.5.2.2  jdolecek 		 */
    691  1.5.2.2  jdolecek 		switch (hw->mac.type) {
    692  1.5.2.2  jdolecek 		case ixgbe_mac_82598EB:
    693  1.5.2.2  jdolecek 			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
    694  1.5.2.2  jdolecek 			break;
    695  1.5.2.2  jdolecek 		default:
    696  1.5.2.2  jdolecek 			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j));
    697  1.5.2.2  jdolecek 			break;
    698  1.5.2.2  jdolecek 		}
    699  1.5.2.2  jdolecek 		txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
    700  1.5.2.2  jdolecek 		switch (hw->mac.type) {
    701  1.5.2.2  jdolecek 		case ixgbe_mac_82598EB:
    702  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
    703  1.5.2.2  jdolecek 			break;
    704  1.5.2.2  jdolecek 		default:
    705  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl);
    706  1.5.2.2  jdolecek 			break;
    707  1.5.2.2  jdolecek 		}
    708      1.1    dyoung 
    709  1.5.2.2  jdolecek 	}
    710      1.1    dyoung 
    711  1.5.2.2  jdolecek 	if (hw->mac.type != ixgbe_mac_82598EB) {
    712  1.5.2.2  jdolecek 		u32 dmatxctl, rttdcs;
    713      1.1    dyoung 
    714  1.5.2.2  jdolecek 		dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
    715  1.5.2.2  jdolecek 		dmatxctl |= IXGBE_DMATXCTL_TE;
    716  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
    717  1.5.2.2  jdolecek 		/* Disable arbiter to set MTQC */
    718  1.5.2.2  jdolecek 		rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
    719  1.5.2.2  jdolecek 		rttdcs |= IXGBE_RTTDCS_ARBDIS;
    720  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
    721  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_MTQC,
    722  1.5.2.2  jdolecek 		    ixgbe_get_mtqc(adapter->iov_mode));
    723  1.5.2.2  jdolecek 		rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
    724  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
    725  1.5.2.2  jdolecek 	}
    726  1.5.2.2  jdolecek 
    727  1.5.2.2  jdolecek 	return;
    728  1.5.2.2  jdolecek } /* ixgbe_initialize_transmit_units */
    729      1.1    dyoung 
    730  1.5.2.2  jdolecek /************************************************************************
    731  1.5.2.2  jdolecek  * ixgbe_attach - Device initialization routine
    732      1.1    dyoung  *
    733  1.5.2.2  jdolecek  *   Called when the driver is being loaded.
    734  1.5.2.2  jdolecek  *   Identifies the type of hardware, allocates all resources
    735  1.5.2.2  jdolecek  *   and initializes the hardware.
    736      1.1    dyoung  *
    737  1.5.2.2  jdolecek  *   return 0 on success, positive on failure
    738  1.5.2.2  jdolecek  ************************************************************************/
    739      1.1    dyoung static void
    740      1.1    dyoung ixgbe_attach(device_t parent, device_t dev, void *aux)
    741      1.1    dyoung {
    742  1.5.2.2  jdolecek 	struct adapter  *adapter;
    743      1.1    dyoung 	struct ixgbe_hw *hw;
    744  1.5.2.2  jdolecek 	int             error = -1;
    745      1.1    dyoung 	u32		ctrl_ext;
    746  1.5.2.2  jdolecek 	u16		high, low, nvmreg;
    747  1.5.2.2  jdolecek 	pcireg_t	id, subid;
    748      1.1    dyoung 	ixgbe_vendor_info_t *ent;
    749  1.5.2.2  jdolecek 	struct pci_attach_args *pa = aux;
    750  1.5.2.2  jdolecek 	const char *str;
    751  1.5.2.2  jdolecek 	char buf[256];
    752      1.1    dyoung 
    753      1.1    dyoung 	INIT_DEBUGOUT("ixgbe_attach: begin");
    754      1.1    dyoung 
    755      1.1    dyoung 	/* Allocate, clear, and link in our adapter structure */
    756      1.1    dyoung 	adapter = device_private(dev);
    757  1.5.2.2  jdolecek 	adapter->hw.back = adapter;
    758  1.5.2.2  jdolecek 	adapter->dev = dev;
    759      1.1    dyoung 	hw = &adapter->hw;
    760      1.1    dyoung 	adapter->osdep.pc = pa->pa_pc;
    761      1.1    dyoung 	adapter->osdep.tag = pa->pa_tag;
    762  1.5.2.2  jdolecek 	if (pci_dma64_available(pa))
    763  1.5.2.2  jdolecek 		adapter->osdep.dmat = pa->pa_dmat64;
    764  1.5.2.2  jdolecek 	else
    765  1.5.2.2  jdolecek 		adapter->osdep.dmat = pa->pa_dmat;
    766  1.5.2.2  jdolecek 	adapter->osdep.attached = false;
    767      1.1    dyoung 
    768      1.1    dyoung 	ent = ixgbe_lookup(pa);
    769      1.1    dyoung 
    770      1.1    dyoung 	KASSERT(ent != NULL);
    771      1.1    dyoung 
    772      1.1    dyoung 	aprint_normal(": %s, Version - %s\n",
    773      1.1    dyoung 	    ixgbe_strings[ent->index], ixgbe_driver_version);
    774      1.1    dyoung 
    775      1.1    dyoung 	/* Core Lock Init*/
    776      1.1    dyoung 	IXGBE_CORE_LOCK_INIT(adapter, device_xname(dev));
    777      1.1    dyoung 
    778      1.1    dyoung 	/* Set up the timer callout */
    779  1.5.2.2  jdolecek 	callout_init(&adapter->timer, IXGBE_CALLOUT_FLAGS);
    780      1.1    dyoung 
    781      1.1    dyoung 	/* Determine hardware revision */
    782  1.5.2.2  jdolecek 	id = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG);
    783  1.5.2.2  jdolecek 	subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
    784  1.5.2.2  jdolecek 
    785  1.5.2.2  jdolecek 	hw->vendor_id = PCI_VENDOR(id);
    786  1.5.2.2  jdolecek 	hw->device_id = PCI_PRODUCT(id);
    787  1.5.2.2  jdolecek 	hw->revision_id =
    788  1.5.2.2  jdolecek 	    PCI_REVISION(pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG));
    789  1.5.2.2  jdolecek 	hw->subsystem_vendor_id = PCI_SUBSYS_VENDOR(subid);
    790  1.5.2.2  jdolecek 	hw->subsystem_device_id = PCI_SUBSYS_ID(subid);
    791  1.5.2.2  jdolecek 
    792  1.5.2.2  jdolecek 	/*
    793  1.5.2.2  jdolecek 	 * Make sure BUSMASTER is set
    794  1.5.2.2  jdolecek 	 */
    795  1.5.2.2  jdolecek 	ixgbe_pci_enable_busmaster(pa->pa_pc, pa->pa_tag);
    796      1.1    dyoung 
    797      1.1    dyoung 	/* Do base PCI setup - map BAR0 */
    798      1.1    dyoung 	if (ixgbe_allocate_pci_resources(adapter, pa)) {
    799      1.1    dyoung 		aprint_error_dev(dev, "Allocation of PCI resources failed\n");
    800      1.1    dyoung 		error = ENXIO;
    801      1.1    dyoung 		goto err_out;
    802      1.1    dyoung 	}
    803      1.1    dyoung 
    804  1.5.2.2  jdolecek 	/* let hardware know driver is loaded */
    805  1.5.2.2  jdolecek 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
    806  1.5.2.2  jdolecek 	ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
    807  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
    808      1.1    dyoung 
    809      1.1    dyoung 	/*
    810  1.5.2.2  jdolecek 	 * Initialize the shared code
    811  1.5.2.2  jdolecek 	 */
    812  1.5.2.2  jdolecek 	if (ixgbe_init_shared_code(hw)) {
    813  1.5.2.2  jdolecek 		aprint_error_dev(dev, "Unable to initialize the shared code\n");
    814  1.5.2.2  jdolecek 		error = ENXIO;
    815  1.5.2.2  jdolecek 		goto err_out;
    816  1.5.2.2  jdolecek 	}
    817  1.5.2.2  jdolecek 
    818  1.5.2.2  jdolecek 	switch (hw->mac.type) {
    819  1.5.2.2  jdolecek 	case ixgbe_mac_82598EB:
    820  1.5.2.2  jdolecek 		str = "82598EB";
    821  1.5.2.2  jdolecek 		break;
    822  1.5.2.2  jdolecek 	case ixgbe_mac_82599EB:
    823  1.5.2.2  jdolecek 		str = "82599EB";
    824  1.5.2.2  jdolecek 		break;
    825  1.5.2.2  jdolecek 	case ixgbe_mac_X540:
    826  1.5.2.2  jdolecek 		str = "X540";
    827  1.5.2.2  jdolecek 		break;
    828  1.5.2.2  jdolecek 	case ixgbe_mac_X550:
    829  1.5.2.2  jdolecek 		str = "X550";
    830  1.5.2.2  jdolecek 		break;
    831  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
    832  1.5.2.2  jdolecek 		str = "X550EM";
    833  1.5.2.2  jdolecek 		break;
    834  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
    835  1.5.2.2  jdolecek 		str = "X550EM A";
    836  1.5.2.2  jdolecek 		break;
    837  1.5.2.2  jdolecek 	default:
    838  1.5.2.2  jdolecek 		str = "Unknown";
    839  1.5.2.2  jdolecek 		break;
    840  1.5.2.2  jdolecek 	}
    841  1.5.2.2  jdolecek 	aprint_normal_dev(dev, "device %s\n", str);
    842  1.5.2.2  jdolecek 
    843  1.5.2.2  jdolecek 	if (hw->mbx.ops.init_params)
    844  1.5.2.2  jdolecek 		hw->mbx.ops.init_params(hw);
    845  1.5.2.2  jdolecek 
    846  1.5.2.2  jdolecek 	hw->allow_unsupported_sfp = allow_unsupported_sfp;
    847  1.5.2.2  jdolecek 
    848  1.5.2.2  jdolecek 	/* Pick up the 82599 settings */
    849  1.5.2.2  jdolecek 	if (hw->mac.type != ixgbe_mac_82598EB) {
    850  1.5.2.2  jdolecek 		hw->phy.smart_speed = ixgbe_smart_speed;
    851  1.5.2.2  jdolecek 		adapter->num_segs = IXGBE_82599_SCATTER;
    852  1.5.2.2  jdolecek 	} else
    853  1.5.2.2  jdolecek 		adapter->num_segs = IXGBE_82598_SCATTER;
    854  1.5.2.2  jdolecek 
    855  1.5.2.2  jdolecek 	hw->mac.ops.set_lan_id(hw);
    856  1.5.2.2  jdolecek 	ixgbe_init_device_features(adapter);
    857  1.5.2.2  jdolecek 
    858  1.5.2.2  jdolecek 	if (ixgbe_configure_interrupts(adapter)) {
    859  1.5.2.2  jdolecek 		error = ENXIO;
    860  1.5.2.2  jdolecek 		goto err_out;
    861  1.5.2.2  jdolecek 	}
    862  1.5.2.2  jdolecek 
    863  1.5.2.2  jdolecek 	/* Allocate multicast array memory. */
    864  1.5.2.2  jdolecek 	adapter->mta = malloc(sizeof(*adapter->mta) *
    865  1.5.2.2  jdolecek 	    MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT);
    866  1.5.2.2  jdolecek 	if (adapter->mta == NULL) {
    867  1.5.2.2  jdolecek 		aprint_error_dev(dev, "Cannot allocate multicast setup array\n");
    868  1.5.2.2  jdolecek 		error = ENOMEM;
    869  1.5.2.2  jdolecek 		goto err_out;
    870  1.5.2.2  jdolecek 	}
    871  1.5.2.2  jdolecek 
    872  1.5.2.2  jdolecek 	/* Enable WoL (if supported) */
    873  1.5.2.2  jdolecek 	ixgbe_check_wol_support(adapter);
    874  1.5.2.2  jdolecek 
    875  1.5.2.2  jdolecek 	/* Verify adapter fan is still functional (if applicable) */
    876  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
    877  1.5.2.2  jdolecek 		u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
    878  1.5.2.2  jdolecek 		ixgbe_check_fan_failure(adapter, esdp, FALSE);
    879  1.5.2.2  jdolecek 	}
    880  1.5.2.2  jdolecek 
    881  1.5.2.2  jdolecek 	/* Ensure SW/FW semaphore is free */
    882  1.5.2.2  jdolecek 	ixgbe_init_swfw_semaphore(hw);
    883  1.5.2.2  jdolecek 
    884  1.5.2.2  jdolecek 	/* Enable EEE power saving */
    885  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_EEE)
    886  1.5.2.2  jdolecek 		hw->mac.ops.setup_eee(hw, TRUE);
    887  1.5.2.2  jdolecek 
    888  1.5.2.2  jdolecek 	/* Set an initial default flow control value */
    889  1.5.2.2  jdolecek 	hw->fc.requested_mode = ixgbe_flow_control;
    890  1.5.2.2  jdolecek 
    891  1.5.2.2  jdolecek 	/* Sysctls for limiting the amount of work done in the taskqueues */
    892  1.5.2.2  jdolecek 	ixgbe_set_sysctl_value(adapter, "rx_processing_limit",
    893  1.5.2.2  jdolecek 	    "max number of rx packets to process",
    894  1.5.2.2  jdolecek 	    &adapter->rx_process_limit, ixgbe_rx_process_limit);
    895  1.5.2.2  jdolecek 
    896  1.5.2.2  jdolecek 	ixgbe_set_sysctl_value(adapter, "tx_processing_limit",
    897  1.5.2.2  jdolecek 	    "max number of tx packets to process",
    898  1.5.2.2  jdolecek 	    &adapter->tx_process_limit, ixgbe_tx_process_limit);
    899  1.5.2.2  jdolecek 
    900  1.5.2.2  jdolecek 	/* Do descriptor calc and sanity checks */
    901  1.5.2.2  jdolecek 	if (((ixgbe_txd * sizeof(union ixgbe_adv_tx_desc)) % DBA_ALIGN) != 0 ||
    902  1.5.2.2  jdolecek 	    ixgbe_txd < MIN_TXD || ixgbe_txd > MAX_TXD) {
    903  1.5.2.2  jdolecek 		aprint_error_dev(dev, "TXD config issue, using default!\n");
    904  1.5.2.2  jdolecek 		adapter->num_tx_desc = DEFAULT_TXD;
    905  1.5.2.2  jdolecek 	} else
    906  1.5.2.2  jdolecek 		adapter->num_tx_desc = ixgbe_txd;
    907  1.5.2.2  jdolecek 
    908  1.5.2.2  jdolecek 	/*
    909  1.5.2.2  jdolecek 	 * With many RX rings it is easy to exceed the
    910  1.5.2.2  jdolecek 	 * system mbuf allocation. Tuning nmbclusters
    911  1.5.2.2  jdolecek 	 * can alleviate this.
    912  1.5.2.2  jdolecek 	 */
    913  1.5.2.2  jdolecek 	if (nmbclusters > 0) {
    914  1.5.2.2  jdolecek 		int s;
    915  1.5.2.2  jdolecek 		s = (ixgbe_rxd * adapter->num_queues) * ixgbe_total_ports;
    916  1.5.2.2  jdolecek 		if (s > nmbclusters) {
    917  1.5.2.2  jdolecek 			aprint_error_dev(dev, "RX Descriptors exceed "
    918  1.5.2.2  jdolecek 			    "system mbuf max, using default instead!\n");
    919      1.1    dyoung 			ixgbe_rxd = DEFAULT_RXD;
    920      1.1    dyoung 		}
    921      1.1    dyoung 	}
    922      1.1    dyoung 
    923      1.1    dyoung 	if (((ixgbe_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 ||
    924  1.5.2.2  jdolecek 	    ixgbe_rxd < MIN_RXD || ixgbe_rxd > MAX_RXD) {
    925      1.1    dyoung 		aprint_error_dev(dev, "RXD config issue, using default!\n");
    926      1.1    dyoung 		adapter->num_rx_desc = DEFAULT_RXD;
    927      1.1    dyoung 	} else
    928      1.1    dyoung 		adapter->num_rx_desc = ixgbe_rxd;
    929      1.1    dyoung 
    930      1.1    dyoung 	/* Allocate our TX/RX Queues */
    931      1.1    dyoung 	if (ixgbe_allocate_queues(adapter)) {
    932      1.1    dyoung 		error = ENOMEM;
    933      1.1    dyoung 		goto err_out;
    934      1.1    dyoung 	}
    935      1.1    dyoung 
    936  1.5.2.2  jdolecek 	hw->phy.reset_if_overtemp = TRUE;
    937  1.5.2.2  jdolecek 	error = ixgbe_reset_hw(hw);
    938  1.5.2.2  jdolecek 	hw->phy.reset_if_overtemp = FALSE;
    939      1.1    dyoung 	if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
    940      1.1    dyoung 		/*
    941  1.5.2.2  jdolecek 		 * No optics in this port, set up
    942  1.5.2.2  jdolecek 		 * so the timer routine will probe
    943  1.5.2.2  jdolecek 		 * for later insertion.
    944  1.5.2.2  jdolecek 		 */
    945      1.1    dyoung 		adapter->sfp_probe = TRUE;
    946  1.5.2.2  jdolecek 		error = IXGBE_SUCCESS;
    947      1.1    dyoung 	} else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
    948  1.5.2.2  jdolecek 		aprint_error_dev(dev, "Unsupported SFP+ module detected!\n");
    949      1.1    dyoung 		error = EIO;
    950      1.1    dyoung 		goto err_late;
    951      1.1    dyoung 	} else if (error) {
    952  1.5.2.2  jdolecek 		aprint_error_dev(dev, "Hardware initialization failed\n");
    953      1.1    dyoung 		error = EIO;
    954      1.1    dyoung 		goto err_late;
    955      1.1    dyoung 	}
    956      1.1    dyoung 
    957      1.1    dyoung 	/* Make sure we have a good EEPROM before we read from it */
    958  1.5.2.2  jdolecek 	if (ixgbe_validate_eeprom_checksum(&adapter->hw, NULL) < 0) {
    959  1.5.2.2  jdolecek 		aprint_error_dev(dev, "The EEPROM Checksum Is Not Valid\n");
    960      1.1    dyoung 		error = EIO;
    961      1.1    dyoung 		goto err_late;
    962      1.1    dyoung 	}
    963      1.1    dyoung 
    964  1.5.2.2  jdolecek 	aprint_normal("%s:", device_xname(dev));
    965  1.5.2.2  jdolecek 	/* NVM Image Version */
    966  1.5.2.2  jdolecek 	switch (hw->mac.type) {
    967  1.5.2.2  jdolecek 	case ixgbe_mac_X540:
    968  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
    969  1.5.2.2  jdolecek 		hw->eeprom.ops.read(hw, IXGBE_NVM_IMAGE_VER, &nvmreg);
    970  1.5.2.2  jdolecek 		if (nvmreg == 0xffff)
    971  1.5.2.2  jdolecek 			break;
    972  1.5.2.2  jdolecek 		high = (nvmreg >> 12) & 0x0f;
    973  1.5.2.2  jdolecek 		low = (nvmreg >> 4) & 0xff;
    974  1.5.2.2  jdolecek 		id = nvmreg & 0x0f;
    975  1.5.2.2  jdolecek 		aprint_normal(" NVM Image Version %u.", high);
    976  1.5.2.2  jdolecek 		if (hw->mac.type == ixgbe_mac_X540)
    977  1.5.2.2  jdolecek 			str = "%x";
    978  1.5.2.2  jdolecek 		else
    979  1.5.2.2  jdolecek 			str = "%02x";
    980  1.5.2.2  jdolecek 		aprint_normal(str, low);
    981  1.5.2.2  jdolecek 		aprint_normal(" ID 0x%x,", id);
    982  1.5.2.2  jdolecek 		break;
    983  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
    984  1.5.2.2  jdolecek 	case ixgbe_mac_X550:
    985  1.5.2.2  jdolecek 		hw->eeprom.ops.read(hw, IXGBE_NVM_IMAGE_VER, &nvmreg);
    986  1.5.2.2  jdolecek 		if (nvmreg == 0xffff)
    987  1.5.2.2  jdolecek 			break;
    988  1.5.2.2  jdolecek 		high = (nvmreg >> 12) & 0x0f;
    989  1.5.2.2  jdolecek 		low = nvmreg & 0xff;
    990  1.5.2.2  jdolecek 		aprint_normal(" NVM Image Version %u.%02x,", high, low);
    991  1.5.2.2  jdolecek 		break;
    992  1.5.2.2  jdolecek 	default:
    993  1.5.2.2  jdolecek 		break;
    994  1.5.2.2  jdolecek 	}
    995      1.1    dyoung 
    996  1.5.2.2  jdolecek 	/* PHY firmware revision */
    997  1.5.2.2  jdolecek 	switch (hw->mac.type) {
    998  1.5.2.2  jdolecek 	case ixgbe_mac_X540:
    999  1.5.2.2  jdolecek 	case ixgbe_mac_X550:
   1000  1.5.2.2  jdolecek 		hw->eeprom.ops.read(hw, IXGBE_PHYFW_REV, &nvmreg);
   1001  1.5.2.2  jdolecek 		if (nvmreg == 0xffff)
   1002  1.5.2.2  jdolecek 			break;
   1003  1.5.2.2  jdolecek 		high = (nvmreg >> 12) & 0x0f;
   1004  1.5.2.2  jdolecek 		low = (nvmreg >> 4) & 0xff;
   1005  1.5.2.2  jdolecek 		id = nvmreg & 0x000f;
   1006  1.5.2.2  jdolecek 		aprint_normal(" PHY FW Revision %u.", high);
   1007  1.5.2.2  jdolecek 		if (hw->mac.type == ixgbe_mac_X540)
   1008  1.5.2.2  jdolecek 			str = "%x";
   1009  1.5.2.2  jdolecek 		else
   1010  1.5.2.2  jdolecek 			str = "%02x";
   1011  1.5.2.2  jdolecek 		aprint_normal(str, low);
   1012  1.5.2.2  jdolecek 		aprint_normal(" ID 0x%x,", id);
   1013  1.5.2.2  jdolecek 		break;
   1014  1.5.2.2  jdolecek 	default:
   1015  1.5.2.2  jdolecek 		break;
   1016  1.5.2.2  jdolecek 	}
   1017      1.1    dyoung 
   1018  1.5.2.2  jdolecek 	/* NVM Map version & OEM NVM Image version */
   1019  1.5.2.2  jdolecek 	switch (hw->mac.type) {
   1020  1.5.2.2  jdolecek 	case ixgbe_mac_X550:
   1021  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
   1022  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
   1023  1.5.2.2  jdolecek 		hw->eeprom.ops.read(hw, IXGBE_NVM_MAP_VER, &nvmreg);
   1024  1.5.2.2  jdolecek 		if (nvmreg != 0xffff) {
   1025  1.5.2.2  jdolecek 			high = (nvmreg >> 12) & 0x0f;
   1026  1.5.2.2  jdolecek 			low = nvmreg & 0x00ff;
   1027  1.5.2.2  jdolecek 			aprint_normal(" NVM Map version %u.%02x,", high, low);
   1028  1.5.2.2  jdolecek 		}
   1029  1.5.2.2  jdolecek 		hw->eeprom.ops.read(hw, IXGBE_OEM_NVM_IMAGE_VER, &nvmreg);
   1030  1.5.2.2  jdolecek 		if (nvmreg != 0xffff) {
   1031  1.5.2.2  jdolecek 			high = (nvmreg >> 12) & 0x0f;
   1032  1.5.2.2  jdolecek 			low = nvmreg & 0x00ff;
   1033  1.5.2.2  jdolecek 			aprint_verbose(" OEM NVM Image version %u.%02x,", high,
   1034  1.5.2.2  jdolecek 			    low);
   1035  1.5.2.2  jdolecek 		}
   1036  1.5.2.2  jdolecek 		break;
   1037  1.5.2.2  jdolecek 	default:
   1038  1.5.2.2  jdolecek 		break;
   1039      1.1    dyoung 	}
   1040      1.1    dyoung 
   1041  1.5.2.2  jdolecek 	/* Print the ETrackID */
   1042  1.5.2.2  jdolecek 	hw->eeprom.ops.read(hw, IXGBE_ETRACKID_H, &high);
   1043  1.5.2.2  jdolecek 	hw->eeprom.ops.read(hw, IXGBE_ETRACKID_L, &low);
   1044  1.5.2.2  jdolecek 	aprint_normal(" ETrackID %08x\n", ((uint32_t)high << 16) | low);
   1045  1.5.2.2  jdolecek 
   1046  1.5.2.2  jdolecek 	/* Setup OS specific network interface */
   1047  1.5.2.2  jdolecek 	if (ixgbe_setup_interface(dev, adapter) != 0)
   1048  1.5.2.2  jdolecek 		goto err_late;
   1049      1.1    dyoung 
   1050  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_MSIX)
   1051  1.5.2.2  jdolecek 		error = ixgbe_allocate_msix(adapter, pa);
   1052      1.1    dyoung 	else
   1053  1.5.2.2  jdolecek 		error = ixgbe_allocate_legacy(adapter, pa);
   1054      1.1    dyoung 	if (error)
   1055      1.1    dyoung 		goto err_late;
   1056      1.1    dyoung 
   1057  1.5.2.2  jdolecek 	error = ixgbe_start_hw(hw);
   1058  1.5.2.2  jdolecek 	switch (error) {
   1059  1.5.2.2  jdolecek 	case IXGBE_ERR_EEPROM_VERSION:
   1060  1.5.2.2  jdolecek 		aprint_error_dev(dev, "This device is a pre-production adapter/"
   1061  1.5.2.2  jdolecek 		    "LOM.  Please be aware there may be issues associated "
   1062  1.5.2.2  jdolecek 		    "with your hardware.\nIf you are experiencing problems "
   1063  1.5.2.2  jdolecek 		    "please contact your Intel or hardware representative "
   1064  1.5.2.2  jdolecek 		    "who provided you with this hardware.\n");
   1065  1.5.2.2  jdolecek 		break;
   1066  1.5.2.2  jdolecek 	case IXGBE_ERR_SFP_NOT_SUPPORTED:
   1067  1.5.2.2  jdolecek 		aprint_error_dev(dev, "Unsupported SFP+ Module\n");
   1068  1.5.2.2  jdolecek 		error = EIO;
   1069      1.1    dyoung 		goto err_late;
   1070  1.5.2.2  jdolecek 	case IXGBE_ERR_SFP_NOT_PRESENT:
   1071  1.5.2.2  jdolecek 		aprint_error_dev(dev, "No SFP+ Module found\n");
   1072  1.5.2.2  jdolecek 		/* falls thru */
   1073  1.5.2.2  jdolecek 	default:
   1074  1.5.2.2  jdolecek 		break;
   1075  1.5.2.2  jdolecek 	}
   1076  1.5.2.2  jdolecek 
   1077  1.5.2.2  jdolecek 	/*
   1078  1.5.2.2  jdolecek 	 *  Print PHY ID only for copper PHY. On device which has SFP(+) cage
   1079  1.5.2.2  jdolecek 	 * and a module is inserted, phy.id is not MII PHY id but SFF 8024 ID.
   1080  1.5.2.2  jdolecek 	 */
   1081  1.5.2.2  jdolecek 	if (hw->phy.media_type == ixgbe_media_type_copper) {
   1082  1.5.2.2  jdolecek 		uint16_t id1, id2;
   1083  1.5.2.2  jdolecek 		int oui, model, rev;
   1084  1.5.2.2  jdolecek 		const char *descr;
   1085  1.5.2.2  jdolecek 
   1086  1.5.2.2  jdolecek 		id1 = hw->phy.id >> 16;
   1087  1.5.2.2  jdolecek 		id2 = hw->phy.id & 0xffff;
   1088  1.5.2.2  jdolecek 		oui = MII_OUI(id1, id2);
   1089  1.5.2.2  jdolecek 		model = MII_MODEL(id2);
   1090  1.5.2.2  jdolecek 		rev = MII_REV(id2);
   1091  1.5.2.2  jdolecek 		if ((descr = mii_get_descr(oui, model)) != NULL)
   1092  1.5.2.2  jdolecek 			aprint_normal_dev(dev,
   1093  1.5.2.2  jdolecek 			    "PHY: %s (OUI 0x%06x, model 0x%04x), rev. %d\n",
   1094  1.5.2.2  jdolecek 			    descr, oui, model, rev);
   1095  1.5.2.2  jdolecek 		else
   1096  1.5.2.2  jdolecek 			aprint_normal_dev(dev,
   1097  1.5.2.2  jdolecek 			    "PHY OUI 0x%06x, model 0x%04x, rev. %d\n",
   1098  1.5.2.2  jdolecek 			    oui, model, rev);
   1099  1.5.2.2  jdolecek 	}
   1100  1.5.2.2  jdolecek 
   1101  1.5.2.2  jdolecek 	/* Enable the optics for 82599 SFP+ fiber */
   1102  1.5.2.2  jdolecek 	ixgbe_enable_tx_laser(hw);
   1103      1.1    dyoung 
   1104  1.5.2.2  jdolecek 	/* Enable power to the phy. */
   1105  1.5.2.2  jdolecek 	ixgbe_set_phy_power(hw, TRUE);
   1106      1.1    dyoung 
   1107      1.1    dyoung 	/* Initialize statistics */
   1108      1.1    dyoung 	ixgbe_update_stats_counters(adapter);
   1109      1.1    dyoung 
   1110  1.5.2.2  jdolecek 	/* Check PCIE slot type/speed/width */
   1111  1.5.2.2  jdolecek 	ixgbe_get_slot_info(adapter);
   1112      1.1    dyoung 
   1113  1.5.2.2  jdolecek 	/*
   1114  1.5.2.2  jdolecek 	 * Do time init and sysctl init here, but
   1115  1.5.2.2  jdolecek 	 * only on the first port of a bypass adapter.
   1116  1.5.2.2  jdolecek 	 */
   1117  1.5.2.2  jdolecek 	ixgbe_bypass_init(adapter);
   1118  1.5.2.2  jdolecek 
   1119  1.5.2.2  jdolecek 	/* Set an initial dmac value */
   1120  1.5.2.2  jdolecek 	adapter->dmac = 0;
   1121  1.5.2.2  jdolecek 	/* Set initial advertised speeds (if applicable) */
   1122  1.5.2.2  jdolecek 	adapter->advertise = ixgbe_get_advertise(adapter);
   1123      1.1    dyoung 
   1124  1.5.2.2  jdolecek 	if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
   1125  1.5.2.2  jdolecek 		ixgbe_define_iov_schemas(dev, &error);
   1126  1.5.2.2  jdolecek 
   1127  1.5.2.2  jdolecek 	/* Add sysctls */
   1128  1.5.2.2  jdolecek 	ixgbe_add_device_sysctls(adapter);
   1129      1.1    dyoung 	ixgbe_add_hw_stats(adapter);
   1130      1.1    dyoung 
   1131  1.5.2.2  jdolecek 	/* For Netmap */
   1132  1.5.2.2  jdolecek 	adapter->init_locked = ixgbe_init_locked;
   1133  1.5.2.2  jdolecek 	adapter->stop_locked = ixgbe_stop;
   1134  1.5.2.2  jdolecek 
   1135  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_NETMAP)
   1136  1.5.2.2  jdolecek 		ixgbe_netmap_attach(adapter);
   1137  1.5.2.2  jdolecek 
   1138  1.5.2.2  jdolecek 	snprintb(buf, sizeof(buf), IXGBE_FEATURE_FLAGS, adapter->feat_cap);
   1139  1.5.2.2  jdolecek 	aprint_verbose_dev(dev, "feature cap %s\n", buf);
   1140  1.5.2.2  jdolecek 	snprintb(buf, sizeof(buf), IXGBE_FEATURE_FLAGS, adapter->feat_en);
   1141  1.5.2.2  jdolecek 	aprint_verbose_dev(dev, "feature ena %s\n", buf);
   1142  1.5.2.2  jdolecek 
   1143  1.5.2.2  jdolecek 	if (pmf_device_register(dev, ixgbe_suspend, ixgbe_resume))
   1144  1.5.2.2  jdolecek 		pmf_class_network_register(dev, adapter->ifp);
   1145  1.5.2.2  jdolecek 	else
   1146  1.5.2.2  jdolecek 		aprint_error_dev(dev, "couldn't establish power handler\n");
   1147  1.5.2.2  jdolecek 
   1148      1.1    dyoung 	INIT_DEBUGOUT("ixgbe_attach: end");
   1149  1.5.2.2  jdolecek 	adapter->osdep.attached = true;
   1150  1.5.2.2  jdolecek 
   1151      1.1    dyoung 	return;
   1152  1.5.2.2  jdolecek 
   1153      1.1    dyoung err_late:
   1154      1.1    dyoung 	ixgbe_free_transmit_structures(adapter);
   1155      1.1    dyoung 	ixgbe_free_receive_structures(adapter);
   1156  1.5.2.2  jdolecek 	free(adapter->queues, M_DEVBUF);
   1157      1.1    dyoung err_out:
   1158      1.1    dyoung 	if (adapter->ifp != NULL)
   1159      1.1    dyoung 		if_free(adapter->ifp);
   1160  1.5.2.2  jdolecek 	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
   1161  1.5.2.2  jdolecek 	ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
   1162  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
   1163      1.1    dyoung 	ixgbe_free_pci_resources(adapter);
   1164      1.1    dyoung 	if (adapter->mta != NULL)
   1165      1.1    dyoung 		free(adapter->mta, M_DEVBUF);
   1166  1.5.2.2  jdolecek 	IXGBE_CORE_LOCK_DESTROY(adapter);
   1167      1.1    dyoung 
   1168  1.5.2.2  jdolecek 	return;
   1169  1.5.2.2  jdolecek } /* ixgbe_attach */
   1170      1.1    dyoung 
   1171  1.5.2.2  jdolecek /************************************************************************
   1172  1.5.2.2  jdolecek  * ixgbe_check_wol_support
   1173      1.1    dyoung  *
   1174  1.5.2.2  jdolecek  *   Checks whether the adapter's ports are capable of
   1175  1.5.2.2  jdolecek  *   Wake On LAN by reading the adapter's NVM.
   1176      1.1    dyoung  *
   1177  1.5.2.2  jdolecek  *   Sets each port's hw->wol_enabled value depending
   1178  1.5.2.2  jdolecek  *   on the value read here.
   1179  1.5.2.2  jdolecek  ************************************************************************/
   1180  1.5.2.2  jdolecek static void
   1181  1.5.2.2  jdolecek ixgbe_check_wol_support(struct adapter *adapter)
   1182  1.5.2.2  jdolecek {
   1183  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   1184  1.5.2.2  jdolecek 	u16             dev_caps = 0;
   1185  1.5.2.2  jdolecek 
   1186  1.5.2.2  jdolecek 	/* Find out WoL support for port */
   1187  1.5.2.2  jdolecek 	adapter->wol_support = hw->wol_enabled = 0;
   1188  1.5.2.2  jdolecek 	ixgbe_get_device_caps(hw, &dev_caps);
   1189  1.5.2.2  jdolecek 	if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
   1190  1.5.2.2  jdolecek 	    ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) &&
   1191  1.5.2.2  jdolecek 	     hw->bus.func == 0))
   1192  1.5.2.2  jdolecek 		adapter->wol_support = hw->wol_enabled = 1;
   1193      1.1    dyoung 
   1194  1.5.2.2  jdolecek 	/* Save initial wake up filter configuration */
   1195  1.5.2.2  jdolecek 	adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC);
   1196  1.5.2.2  jdolecek 
   1197  1.5.2.2  jdolecek 	return;
   1198  1.5.2.2  jdolecek } /* ixgbe_check_wol_support */
   1199  1.5.2.2  jdolecek 
   1200  1.5.2.2  jdolecek /************************************************************************
   1201  1.5.2.2  jdolecek  * ixgbe_setup_interface
   1202  1.5.2.2  jdolecek  *
   1203  1.5.2.2  jdolecek  *   Setup networking device structure and register an interface.
   1204  1.5.2.2  jdolecek  ************************************************************************/
   1205      1.1    dyoung static int
   1206  1.5.2.2  jdolecek ixgbe_setup_interface(device_t dev, struct adapter *adapter)
   1207      1.1    dyoung {
   1208  1.5.2.2  jdolecek 	struct ethercom *ec = &adapter->osdep.ec;
   1209  1.5.2.2  jdolecek 	struct ifnet   *ifp;
   1210  1.5.2.2  jdolecek 	int rv;
   1211      1.1    dyoung 
   1212  1.5.2.2  jdolecek 	INIT_DEBUGOUT("ixgbe_setup_interface: begin");
   1213      1.1    dyoung 
   1214  1.5.2.2  jdolecek 	ifp = adapter->ifp = &ec->ec_if;
   1215  1.5.2.2  jdolecek 	strlcpy(ifp->if_xname, device_xname(dev), IFNAMSIZ);
   1216  1.5.2.2  jdolecek 	ifp->if_baudrate = IF_Gbps(10);
   1217  1.5.2.2  jdolecek 	ifp->if_init = ixgbe_init;
   1218  1.5.2.2  jdolecek 	ifp->if_stop = ixgbe_ifstop;
   1219  1.5.2.2  jdolecek 	ifp->if_softc = adapter;
   1220  1.5.2.2  jdolecek 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
   1221  1.5.2.2  jdolecek #ifdef IXGBE_MPSAFE
   1222  1.5.2.2  jdolecek 	ifp->if_extflags = IFEF_MPSAFE;
   1223  1.5.2.2  jdolecek #endif
   1224  1.5.2.2  jdolecek 	ifp->if_ioctl = ixgbe_ioctl;
   1225  1.5.2.2  jdolecek #if __FreeBSD_version >= 1100045
   1226  1.5.2.2  jdolecek 	/* TSO parameters */
   1227  1.5.2.2  jdolecek 	ifp->if_hw_tsomax = 65518;
   1228  1.5.2.2  jdolecek 	ifp->if_hw_tsomaxsegcount = IXGBE_82599_SCATTER;
   1229  1.5.2.2  jdolecek 	ifp->if_hw_tsomaxsegsize = 2048;
   1230  1.5.2.2  jdolecek #endif
   1231  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_LEGACY_TX) {
   1232  1.5.2.2  jdolecek #if 0
   1233  1.5.2.2  jdolecek 		ixgbe_start_locked = ixgbe_legacy_start_locked;
   1234  1.5.2.2  jdolecek #endif
   1235  1.5.2.2  jdolecek 	} else {
   1236  1.5.2.2  jdolecek 		ifp->if_transmit = ixgbe_mq_start;
   1237  1.5.2.2  jdolecek #if 0
   1238  1.5.2.2  jdolecek 		ixgbe_start_locked = ixgbe_mq_start_locked;
   1239  1.5.2.2  jdolecek #endif
   1240      1.1    dyoung 	}
   1241  1.5.2.2  jdolecek 	ifp->if_start = ixgbe_legacy_start;
   1242  1.5.2.2  jdolecek 	IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 2);
   1243  1.5.2.2  jdolecek 	IFQ_SET_READY(&ifp->if_snd);
   1244      1.1    dyoung 
   1245  1.5.2.2  jdolecek 	rv = if_initialize(ifp);
   1246  1.5.2.2  jdolecek 	if (rv != 0) {
   1247  1.5.2.2  jdolecek 		aprint_error_dev(dev, "if_initialize failed(%d)\n", rv);
   1248  1.5.2.2  jdolecek 		return rv;
   1249      1.1    dyoung 	}
   1250  1.5.2.2  jdolecek 	adapter->ipq = if_percpuq_create(&adapter->osdep.ec.ec_if);
   1251  1.5.2.2  jdolecek 	ether_ifattach(ifp, adapter->hw.mac.addr);
   1252  1.5.2.2  jdolecek 	/*
   1253  1.5.2.2  jdolecek 	 * We use per TX queue softint, so if_deferred_start_init() isn't
   1254  1.5.2.2  jdolecek 	 * used.
   1255  1.5.2.2  jdolecek 	 */
   1256  1.5.2.2  jdolecek 	if_register(ifp);
   1257  1.5.2.2  jdolecek 	ether_set_ifflags_cb(ec, ixgbe_ifflags_cb);
   1258      1.1    dyoung 
   1259  1.5.2.2  jdolecek 	adapter->max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
   1260      1.1    dyoung 
   1261  1.5.2.2  jdolecek 	/*
   1262  1.5.2.2  jdolecek 	 * Tell the upper layer(s) we support long frames.
   1263  1.5.2.2  jdolecek 	 */
   1264  1.5.2.2  jdolecek 	ifp->if_hdrlen = sizeof(struct ether_vlan_header);
   1265      1.1    dyoung 
   1266  1.5.2.2  jdolecek 	/* Set capability flags */
   1267  1.5.2.2  jdolecek 	ifp->if_capabilities |= IFCAP_RXCSUM
   1268  1.5.2.2  jdolecek 			     |  IFCAP_TXCSUM
   1269  1.5.2.2  jdolecek 			     |  IFCAP_TSOv4
   1270  1.5.2.2  jdolecek 			     |  IFCAP_TSOv6
   1271  1.5.2.2  jdolecek 			     |  IFCAP_LRO;
   1272  1.5.2.2  jdolecek 	ifp->if_capenable = 0;
   1273      1.1    dyoung 
   1274  1.5.2.2  jdolecek 	ec->ec_capabilities |= ETHERCAP_VLAN_HWTAGGING
   1275  1.5.2.2  jdolecek 	    		    |  ETHERCAP_VLAN_HWCSUM
   1276  1.5.2.2  jdolecek 	    		    |  ETHERCAP_JUMBO_MTU
   1277  1.5.2.2  jdolecek 	    		    |  ETHERCAP_VLAN_MTU;
   1278      1.1    dyoung 
   1279  1.5.2.2  jdolecek 	/* Enable the above capabilities by default */
   1280  1.5.2.2  jdolecek 	ec->ec_capenable = ec->ec_capabilities;
   1281      1.1    dyoung 
   1282  1.5.2.2  jdolecek 	/*
   1283  1.5.2.2  jdolecek 	 * Don't turn this on by default, if vlans are
   1284  1.5.2.2  jdolecek 	 * created on another pseudo device (eg. lagg)
   1285  1.5.2.2  jdolecek 	 * then vlan events are not passed thru, breaking
   1286  1.5.2.2  jdolecek 	 * operation, but with HW FILTER off it works. If
   1287  1.5.2.2  jdolecek 	 * using vlans directly on the ixgbe driver you can
   1288  1.5.2.2  jdolecek 	 * enable this and get full hardware tag filtering.
   1289  1.5.2.2  jdolecek 	 */
   1290  1.5.2.2  jdolecek 	ec->ec_capabilities |= ETHERCAP_VLAN_HWFILTER;
   1291      1.1    dyoung 
   1292  1.5.2.2  jdolecek 	/*
   1293  1.5.2.2  jdolecek 	 * Specify the media types supported by this adapter and register
   1294  1.5.2.2  jdolecek 	 * callbacks to update media and link information
   1295  1.5.2.2  jdolecek 	 */
   1296  1.5.2.2  jdolecek 	ifmedia_init(&adapter->media, IFM_IMASK, ixgbe_media_change,
   1297  1.5.2.2  jdolecek 	    ixgbe_media_status);
   1298      1.1    dyoung 
   1299  1.5.2.2  jdolecek 	adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw);
   1300  1.5.2.2  jdolecek 	ixgbe_add_media_types(adapter);
   1301      1.1    dyoung 
   1302  1.5.2.2  jdolecek 	/* Set autoselect media by default */
   1303  1.5.2.2  jdolecek 	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
   1304      1.1    dyoung 
   1305      1.1    dyoung 	return (0);
   1306  1.5.2.2  jdolecek } /* ixgbe_setup_interface */
   1307      1.1    dyoung 
   1308  1.5.2.2  jdolecek /************************************************************************
   1309  1.5.2.2  jdolecek  * ixgbe_add_media_types
   1310  1.5.2.2  jdolecek  ************************************************************************/
   1311      1.1    dyoung static void
   1312  1.5.2.2  jdolecek ixgbe_add_media_types(struct adapter *adapter)
   1313      1.1    dyoung {
   1314  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   1315  1.5.2.2  jdolecek 	device_t        dev = adapter->dev;
   1316  1.5.2.2  jdolecek 	u64             layer;
   1317      1.1    dyoung 
   1318  1.5.2.2  jdolecek 	layer = adapter->phy_layer;
   1319      1.1    dyoung 
   1320  1.5.2.2  jdolecek #define	ADD(mm, dd)							\
   1321  1.5.2.2  jdolecek 	ifmedia_add(&adapter->media, IFM_ETHER | (mm), (dd), NULL);
   1322      1.1    dyoung 
   1323  1.5.2.2  jdolecek 	/* Media types with matching NetBSD media defines */
   1324  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) {
   1325  1.5.2.2  jdolecek 		ADD(IFM_10G_T | IFM_FDX, 0);
   1326  1.5.2.2  jdolecek 	}
   1327  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) {
   1328  1.5.2.2  jdolecek 		ADD(IFM_1000_T | IFM_FDX, 0);
   1329  1.5.2.2  jdolecek 	}
   1330  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) {
   1331  1.5.2.2  jdolecek 		ADD(IFM_100_TX | IFM_FDX, 0);
   1332  1.5.2.2  jdolecek 	}
   1333  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T) {
   1334  1.5.2.2  jdolecek 		ADD(IFM_10_T | IFM_FDX, 0);
   1335  1.5.2.2  jdolecek 	}
   1336      1.1    dyoung 
   1337  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
   1338  1.5.2.2  jdolecek 	    layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) {
   1339  1.5.2.2  jdolecek 		ADD(IFM_10G_TWINAX | IFM_FDX, 0);
   1340  1.5.2.2  jdolecek 	}
   1341      1.1    dyoung 
   1342  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) {
   1343  1.5.2.2  jdolecek 		ADD(IFM_10G_LR | IFM_FDX, 0);
   1344  1.5.2.2  jdolecek 		if (hw->phy.multispeed_fiber) {
   1345  1.5.2.2  jdolecek 			ADD(IFM_1000_LX | IFM_FDX, 0);
   1346      1.1    dyoung 		}
   1347  1.5.2.2  jdolecek 	}
   1348  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
   1349  1.5.2.2  jdolecek 		ADD(IFM_10G_SR | IFM_FDX, 0);
   1350  1.5.2.2  jdolecek 		if (hw->phy.multispeed_fiber) {
   1351  1.5.2.2  jdolecek 			ADD(IFM_1000_SX | IFM_FDX, 0);
   1352      1.1    dyoung 		}
   1353  1.5.2.2  jdolecek 	} else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) {
   1354  1.5.2.2  jdolecek 		ADD(IFM_1000_SX | IFM_FDX, 0);
   1355  1.5.2.2  jdolecek 	}
   1356  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) {
   1357  1.5.2.2  jdolecek 		ADD(IFM_10G_CX4 | IFM_FDX, 0);
   1358  1.5.2.2  jdolecek 	}
   1359      1.1    dyoung 
   1360  1.5.2.2  jdolecek #ifdef IFM_ETH_XTYPE
   1361  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
   1362  1.5.2.2  jdolecek 		ADD(IFM_10G_KR | IFM_FDX, 0);
   1363  1.5.2.2  jdolecek 	}
   1364  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) {
   1365  1.5.2.2  jdolecek 		ADD(AIFM_10G_KX4 | IFM_FDX, 0);
   1366  1.5.2.2  jdolecek 	}
   1367  1.5.2.2  jdolecek #else
   1368  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
   1369  1.5.2.2  jdolecek 		device_printf(dev, "Media supported: 10GbaseKR\n");
   1370  1.5.2.2  jdolecek 		device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n");
   1371  1.5.2.2  jdolecek 		ADD(IFM_10G_SR | IFM_FDX, 0);
   1372  1.5.2.2  jdolecek 	}
   1373  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) {
   1374  1.5.2.2  jdolecek 		device_printf(dev, "Media supported: 10GbaseKX4\n");
   1375  1.5.2.2  jdolecek 		device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n");
   1376  1.5.2.2  jdolecek 		ADD(IFM_10G_CX4 | IFM_FDX, 0);
   1377  1.5.2.2  jdolecek 	}
   1378  1.5.2.2  jdolecek #endif
   1379  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) {
   1380  1.5.2.2  jdolecek 		ADD(IFM_1000_KX | IFM_FDX, 0);
   1381  1.5.2.2  jdolecek 	}
   1382  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) {
   1383  1.5.2.2  jdolecek 		ADD(IFM_2500_KX | IFM_FDX, 0);
   1384  1.5.2.2  jdolecek 	}
   1385  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_T) {
   1386  1.5.2.2  jdolecek 		ADD(IFM_2500_T | IFM_FDX, 0);
   1387  1.5.2.2  jdolecek 	}
   1388  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_5GBASE_T) {
   1389  1.5.2.2  jdolecek 		ADD(IFM_5000_T | IFM_FDX, 0);
   1390  1.5.2.2  jdolecek 	}
   1391  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX)
   1392  1.5.2.2  jdolecek 		device_printf(dev, "Media supported: 1000baseBX\n");
   1393  1.5.2.2  jdolecek 	/* XXX no ifmedia_set? */
   1394  1.5.2.2  jdolecek 
   1395  1.5.2.2  jdolecek 	ADD(IFM_AUTO, 0);
   1396      1.1    dyoung 
   1397  1.5.2.2  jdolecek #undef ADD
   1398  1.5.2.2  jdolecek } /* ixgbe_add_media_types */
   1399      1.1    dyoung 
   1400  1.5.2.2  jdolecek /************************************************************************
   1401  1.5.2.2  jdolecek  * ixgbe_is_sfp
   1402  1.5.2.2  jdolecek  ************************************************************************/
   1403  1.5.2.2  jdolecek static inline bool
   1404  1.5.2.2  jdolecek ixgbe_is_sfp(struct ixgbe_hw *hw)
   1405  1.5.2.2  jdolecek {
   1406  1.5.2.2  jdolecek 	switch (hw->mac.type) {
   1407  1.5.2.2  jdolecek 	case ixgbe_mac_82598EB:
   1408  1.5.2.2  jdolecek 		if (hw->phy.type == ixgbe_phy_nl)
   1409  1.5.2.2  jdolecek 			return TRUE;
   1410  1.5.2.2  jdolecek 		return FALSE;
   1411  1.5.2.2  jdolecek 	case ixgbe_mac_82599EB:
   1412  1.5.2.2  jdolecek 		switch (hw->mac.ops.get_media_type(hw)) {
   1413  1.5.2.2  jdolecek 		case ixgbe_media_type_fiber:
   1414  1.5.2.2  jdolecek 		case ixgbe_media_type_fiber_qsfp:
   1415  1.5.2.2  jdolecek 			return TRUE;
   1416  1.5.2.2  jdolecek 		default:
   1417  1.5.2.2  jdolecek 			return FALSE;
   1418  1.5.2.2  jdolecek 		}
   1419  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
   1420  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
   1421  1.5.2.2  jdolecek 		if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber)
   1422  1.5.2.2  jdolecek 			return TRUE;
   1423  1.5.2.2  jdolecek 		return FALSE;
   1424  1.5.2.2  jdolecek 	default:
   1425  1.5.2.2  jdolecek 		return FALSE;
   1426      1.1    dyoung 	}
   1427  1.5.2.2  jdolecek } /* ixgbe_is_sfp */
   1428      1.1    dyoung 
   1429  1.5.2.2  jdolecek /************************************************************************
   1430  1.5.2.2  jdolecek  * ixgbe_config_link
   1431  1.5.2.2  jdolecek  ************************************************************************/
   1432      1.1    dyoung static void
   1433  1.5.2.2  jdolecek ixgbe_config_link(struct adapter *adapter)
   1434      1.1    dyoung {
   1435  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   1436  1.5.2.2  jdolecek 	u32             autoneg, err = 0;
   1437  1.5.2.2  jdolecek 	bool            sfp, negotiate = false;
   1438      1.1    dyoung 
   1439  1.5.2.2  jdolecek 	sfp = ixgbe_is_sfp(hw);
   1440  1.5.2.2  jdolecek 
   1441  1.5.2.2  jdolecek 	if (sfp) {
   1442  1.5.2.2  jdolecek 		if (hw->phy.multispeed_fiber) {
   1443  1.5.2.2  jdolecek 			hw->mac.ops.setup_sfp(hw);
   1444  1.5.2.2  jdolecek 			ixgbe_enable_tx_laser(hw);
   1445  1.5.2.2  jdolecek 			kpreempt_disable();
   1446  1.5.2.2  jdolecek 			softint_schedule(adapter->msf_si);
   1447  1.5.2.2  jdolecek 			kpreempt_enable();
   1448  1.5.2.2  jdolecek 		} else {
   1449  1.5.2.2  jdolecek 			kpreempt_disable();
   1450  1.5.2.2  jdolecek 			softint_schedule(adapter->mod_si);
   1451  1.5.2.2  jdolecek 			kpreempt_enable();
   1452  1.5.2.2  jdolecek 		}
   1453  1.5.2.2  jdolecek 	} else {
   1454  1.5.2.2  jdolecek 		if (hw->mac.ops.check_link)
   1455  1.5.2.2  jdolecek 			err = ixgbe_check_link(hw, &adapter->link_speed,
   1456  1.5.2.2  jdolecek 			    &adapter->link_up, FALSE);
   1457  1.5.2.2  jdolecek 		if (err)
   1458  1.5.2.2  jdolecek 			goto out;
   1459  1.5.2.2  jdolecek 		autoneg = hw->phy.autoneg_advertised;
   1460  1.5.2.2  jdolecek 		if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
   1461  1.5.2.2  jdolecek                 	err = hw->mac.ops.get_link_capabilities(hw, &autoneg,
   1462  1.5.2.2  jdolecek 			    &negotiate);
   1463  1.5.2.2  jdolecek 		if (err)
   1464  1.5.2.2  jdolecek 			goto out;
   1465  1.5.2.2  jdolecek 		if (hw->mac.ops.setup_link)
   1466  1.5.2.2  jdolecek                 	err = hw->mac.ops.setup_link(hw, autoneg,
   1467  1.5.2.2  jdolecek 			    adapter->link_up);
   1468      1.1    dyoung 	}
   1469  1.5.2.2  jdolecek out:
   1470  1.5.2.2  jdolecek 
   1471      1.1    dyoung 	return;
   1472  1.5.2.2  jdolecek } /* ixgbe_config_link */
   1473      1.1    dyoung 
   1474  1.5.2.2  jdolecek /************************************************************************
   1475  1.5.2.2  jdolecek  * ixgbe_update_stats_counters - Update board statistics counters.
   1476  1.5.2.2  jdolecek  ************************************************************************/
   1477  1.5.2.2  jdolecek static void
   1478  1.5.2.2  jdolecek ixgbe_update_stats_counters(struct adapter *adapter)
   1479      1.1    dyoung {
   1480  1.5.2.2  jdolecek 	struct ifnet          *ifp = adapter->ifp;
   1481  1.5.2.2  jdolecek 	struct ixgbe_hw       *hw = &adapter->hw;
   1482  1.5.2.2  jdolecek 	struct ixgbe_hw_stats *stats = &adapter->stats.pf;
   1483  1.5.2.2  jdolecek 	u32                   missed_rx = 0, bprc, lxon, lxoff, total;
   1484  1.5.2.2  jdolecek 	u64                   total_missed_rx = 0;
   1485  1.5.2.2  jdolecek 	uint64_t              crcerrs, rlec;
   1486  1.5.2.2  jdolecek 
   1487  1.5.2.2  jdolecek 	crcerrs = IXGBE_READ_REG(hw, IXGBE_CRCERRS);
   1488  1.5.2.2  jdolecek 	stats->crcerrs.ev_count += crcerrs;
   1489  1.5.2.2  jdolecek 	stats->illerrc.ev_count += IXGBE_READ_REG(hw, IXGBE_ILLERRC);
   1490  1.5.2.2  jdolecek 	stats->errbc.ev_count += IXGBE_READ_REG(hw, IXGBE_ERRBC);
   1491  1.5.2.2  jdolecek 	stats->mspdc.ev_count += IXGBE_READ_REG(hw, IXGBE_MSPDC);
   1492  1.5.2.2  jdolecek 	if (hw->mac.type == ixgbe_mac_X550)
   1493  1.5.2.2  jdolecek 		stats->mbsdc.ev_count += IXGBE_READ_REG(hw, IXGBE_MBSDC);
   1494      1.1    dyoung 
   1495  1.5.2.2  jdolecek 	for (int i = 0; i < __arraycount(stats->qprc); i++) {
   1496  1.5.2.2  jdolecek 		int j = i % adapter->num_queues;
   1497  1.5.2.2  jdolecek 		stats->qprc[j].ev_count += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
   1498  1.5.2.2  jdolecek 		stats->qptc[j].ev_count += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
   1499  1.5.2.2  jdolecek 		stats->qprdc[j].ev_count += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
   1500  1.5.2.2  jdolecek 	}
   1501  1.5.2.2  jdolecek 	for (int i = 0; i < __arraycount(stats->mpc); i++) {
   1502  1.5.2.2  jdolecek 		uint32_t mp;
   1503  1.5.2.2  jdolecek 		int j = i % adapter->num_queues;
   1504      1.1    dyoung 
   1505  1.5.2.2  jdolecek 		mp = IXGBE_READ_REG(hw, IXGBE_MPC(i));
   1506  1.5.2.2  jdolecek 		/* global total per queue */
   1507  1.5.2.2  jdolecek 		stats->mpc[j].ev_count += mp;
   1508  1.5.2.2  jdolecek 		/* running comprehensive total for stats display */
   1509  1.5.2.2  jdolecek 		total_missed_rx += mp;
   1510  1.5.2.2  jdolecek 
   1511  1.5.2.2  jdolecek 		if (hw->mac.type == ixgbe_mac_82598EB)
   1512  1.5.2.2  jdolecek 			stats->rnbc[j].ev_count
   1513  1.5.2.2  jdolecek 			    += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
   1514  1.5.2.2  jdolecek 
   1515  1.5.2.2  jdolecek 	}
   1516  1.5.2.2  jdolecek 	stats->mpctotal.ev_count += total_missed_rx;
   1517  1.5.2.2  jdolecek 
   1518  1.5.2.2  jdolecek 	/* Document says M[LR]FC are valid when link is up and 10Gbps */
   1519  1.5.2.2  jdolecek 	if ((adapter->link_active == TRUE)
   1520  1.5.2.2  jdolecek 	    && (adapter->link_speed == IXGBE_LINK_SPEED_10GB_FULL)) {
   1521  1.5.2.2  jdolecek 		stats->mlfc.ev_count += IXGBE_READ_REG(hw, IXGBE_MLFC);
   1522  1.5.2.2  jdolecek 		stats->mrfc.ev_count += IXGBE_READ_REG(hw, IXGBE_MRFC);
   1523      1.1    dyoung 	}
   1524  1.5.2.2  jdolecek 	rlec = IXGBE_READ_REG(hw, IXGBE_RLEC);
   1525  1.5.2.2  jdolecek 	stats->rlec.ev_count += rlec;
   1526      1.1    dyoung 
   1527  1.5.2.2  jdolecek 	/* Hardware workaround, gprc counts missed packets */
   1528  1.5.2.2  jdolecek 	stats->gprc.ev_count += IXGBE_READ_REG(hw, IXGBE_GPRC) - missed_rx;
   1529      1.1    dyoung 
   1530  1.5.2.2  jdolecek 	lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
   1531  1.5.2.2  jdolecek 	stats->lxontxc.ev_count += lxon;
   1532  1.5.2.2  jdolecek 	lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
   1533  1.5.2.2  jdolecek 	stats->lxofftxc.ev_count += lxoff;
   1534  1.5.2.2  jdolecek 	total = lxon + lxoff;
   1535      1.1    dyoung 
   1536  1.5.2.2  jdolecek 	if (hw->mac.type != ixgbe_mac_82598EB) {
   1537  1.5.2.2  jdolecek 		stats->gorc.ev_count += IXGBE_READ_REG(hw, IXGBE_GORCL) +
   1538  1.5.2.2  jdolecek 		    ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32);
   1539  1.5.2.2  jdolecek 		stats->gotc.ev_count += IXGBE_READ_REG(hw, IXGBE_GOTCL) +
   1540  1.5.2.2  jdolecek 		    ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32) - total * ETHER_MIN_LEN;
   1541  1.5.2.2  jdolecek 		stats->tor.ev_count += IXGBE_READ_REG(hw, IXGBE_TORL) +
   1542  1.5.2.2  jdolecek 		    ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32);
   1543  1.5.2.2  jdolecek 		stats->lxonrxc.ev_count += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
   1544  1.5.2.2  jdolecek 		stats->lxoffrxc.ev_count += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
   1545  1.5.2.2  jdolecek 	} else {
   1546  1.5.2.2  jdolecek 		stats->lxonrxc.ev_count += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
   1547  1.5.2.2  jdolecek 		stats->lxoffrxc.ev_count += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
   1548  1.5.2.2  jdolecek 		/* 82598 only has a counter in the high register */
   1549  1.5.2.2  jdolecek 		stats->gorc.ev_count += IXGBE_READ_REG(hw, IXGBE_GORCH);
   1550  1.5.2.2  jdolecek 		stats->gotc.ev_count += IXGBE_READ_REG(hw, IXGBE_GOTCH) - total * ETHER_MIN_LEN;
   1551  1.5.2.2  jdolecek 		stats->tor.ev_count += IXGBE_READ_REG(hw, IXGBE_TORH);
   1552      1.1    dyoung 	}
   1553      1.1    dyoung 
   1554  1.5.2.2  jdolecek 	/*
   1555  1.5.2.2  jdolecek 	 * Workaround: mprc hardware is incorrectly counting
   1556  1.5.2.2  jdolecek 	 * broadcasts, so for now we subtract those.
   1557  1.5.2.2  jdolecek 	 */
   1558  1.5.2.2  jdolecek 	bprc = IXGBE_READ_REG(hw, IXGBE_BPRC);
   1559  1.5.2.2  jdolecek 	stats->bprc.ev_count += bprc;
   1560  1.5.2.2  jdolecek 	stats->mprc.ev_count += IXGBE_READ_REG(hw, IXGBE_MPRC)
   1561  1.5.2.2  jdolecek 	    - ((hw->mac.type == ixgbe_mac_82598EB) ? bprc : 0);
   1562  1.5.2.2  jdolecek 
   1563  1.5.2.2  jdolecek 	stats->prc64.ev_count += IXGBE_READ_REG(hw, IXGBE_PRC64);
   1564  1.5.2.2  jdolecek 	stats->prc127.ev_count += IXGBE_READ_REG(hw, IXGBE_PRC127);
   1565  1.5.2.2  jdolecek 	stats->prc255.ev_count += IXGBE_READ_REG(hw, IXGBE_PRC255);
   1566  1.5.2.2  jdolecek 	stats->prc511.ev_count += IXGBE_READ_REG(hw, IXGBE_PRC511);
   1567  1.5.2.2  jdolecek 	stats->prc1023.ev_count += IXGBE_READ_REG(hw, IXGBE_PRC1023);
   1568  1.5.2.2  jdolecek 	stats->prc1522.ev_count += IXGBE_READ_REG(hw, IXGBE_PRC1522);
   1569  1.5.2.2  jdolecek 
   1570  1.5.2.2  jdolecek 	stats->gptc.ev_count += IXGBE_READ_REG(hw, IXGBE_GPTC) - total;
   1571  1.5.2.2  jdolecek 	stats->mptc.ev_count += IXGBE_READ_REG(hw, IXGBE_MPTC) - total;
   1572  1.5.2.2  jdolecek 	stats->ptc64.ev_count += IXGBE_READ_REG(hw, IXGBE_PTC64) - total;
   1573  1.5.2.2  jdolecek 
   1574  1.5.2.2  jdolecek 	stats->ruc.ev_count += IXGBE_READ_REG(hw, IXGBE_RUC);
   1575  1.5.2.2  jdolecek 	stats->rfc.ev_count += IXGBE_READ_REG(hw, IXGBE_RFC);
   1576  1.5.2.2  jdolecek 	stats->roc.ev_count += IXGBE_READ_REG(hw, IXGBE_ROC);
   1577  1.5.2.2  jdolecek 	stats->rjc.ev_count += IXGBE_READ_REG(hw, IXGBE_RJC);
   1578  1.5.2.2  jdolecek 	stats->mngprc.ev_count += IXGBE_READ_REG(hw, IXGBE_MNGPRC);
   1579  1.5.2.2  jdolecek 	stats->mngpdc.ev_count += IXGBE_READ_REG(hw, IXGBE_MNGPDC);
   1580  1.5.2.2  jdolecek 	stats->mngptc.ev_count += IXGBE_READ_REG(hw, IXGBE_MNGPTC);
   1581  1.5.2.2  jdolecek 	stats->tpr.ev_count += IXGBE_READ_REG(hw, IXGBE_TPR);
   1582  1.5.2.2  jdolecek 	stats->tpt.ev_count += IXGBE_READ_REG(hw, IXGBE_TPT);
   1583  1.5.2.2  jdolecek 	stats->ptc127.ev_count += IXGBE_READ_REG(hw, IXGBE_PTC127);
   1584  1.5.2.2  jdolecek 	stats->ptc255.ev_count += IXGBE_READ_REG(hw, IXGBE_PTC255);
   1585  1.5.2.2  jdolecek 	stats->ptc511.ev_count += IXGBE_READ_REG(hw, IXGBE_PTC511);
   1586  1.5.2.2  jdolecek 	stats->ptc1023.ev_count += IXGBE_READ_REG(hw, IXGBE_PTC1023);
   1587  1.5.2.2  jdolecek 	stats->ptc1522.ev_count += IXGBE_READ_REG(hw, IXGBE_PTC1522);
   1588  1.5.2.2  jdolecek 	stats->bptc.ev_count += IXGBE_READ_REG(hw, IXGBE_BPTC);
   1589  1.5.2.2  jdolecek 	stats->xec.ev_count += IXGBE_READ_REG(hw, IXGBE_XEC);
   1590  1.5.2.2  jdolecek 	stats->fccrc.ev_count += IXGBE_READ_REG(hw, IXGBE_FCCRC);
   1591  1.5.2.2  jdolecek 	stats->fclast.ev_count += IXGBE_READ_REG(hw, IXGBE_FCLAST);
   1592  1.5.2.2  jdolecek 	/* Only read FCOE on 82599 */
   1593  1.5.2.2  jdolecek 	if (hw->mac.type != ixgbe_mac_82598EB) {
   1594  1.5.2.2  jdolecek 		stats->fcoerpdc.ev_count += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
   1595  1.5.2.2  jdolecek 		stats->fcoeprc.ev_count += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
   1596  1.5.2.2  jdolecek 		stats->fcoeptc.ev_count += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
   1597  1.5.2.2  jdolecek 		stats->fcoedwrc.ev_count += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
   1598  1.5.2.2  jdolecek 		stats->fcoedwtc.ev_count += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
   1599      1.1    dyoung 	}
   1600      1.1    dyoung 
   1601  1.5.2.2  jdolecek 	/* Fill out the OS statistics structure */
   1602  1.5.2.2  jdolecek 	/*
   1603  1.5.2.2  jdolecek 	 * NetBSD: Don't override if_{i|o}{packets|bytes|mcasts} with
   1604  1.5.2.2  jdolecek 	 * adapter->stats counters. It's required to make ifconfig -z
   1605  1.5.2.2  jdolecek 	 * (SOICZIFDATA) work.
   1606  1.5.2.2  jdolecek 	 */
   1607  1.5.2.2  jdolecek 	ifp->if_collisions = 0;
   1608      1.1    dyoung 
   1609  1.5.2.2  jdolecek 	/* Rx Errors */
   1610  1.5.2.2  jdolecek 	ifp->if_iqdrops += total_missed_rx;
   1611  1.5.2.2  jdolecek 	ifp->if_ierrors += crcerrs + rlec;
   1612  1.5.2.2  jdolecek } /* ixgbe_update_stats_counters */
   1613      1.1    dyoung 
   1614  1.5.2.2  jdolecek /************************************************************************
   1615  1.5.2.2  jdolecek  * ixgbe_add_hw_stats
   1616  1.5.2.2  jdolecek  *
   1617  1.5.2.2  jdolecek  *   Add sysctl variables, one per statistic, to the system.
   1618  1.5.2.2  jdolecek  ************************************************************************/
   1619  1.5.2.2  jdolecek static void
   1620  1.5.2.2  jdolecek ixgbe_add_hw_stats(struct adapter *adapter)
   1621      1.1    dyoung {
   1622  1.5.2.2  jdolecek 	device_t dev = adapter->dev;
   1623  1.5.2.2  jdolecek 	const struct sysctlnode *rnode, *cnode;
   1624  1.5.2.2  jdolecek 	struct sysctllog **log = &adapter->sysctllog;
   1625  1.5.2.2  jdolecek 	struct tx_ring *txr = adapter->tx_rings;
   1626  1.5.2.2  jdolecek 	struct rx_ring *rxr = adapter->rx_rings;
   1627  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   1628  1.5.2.2  jdolecek 	struct ixgbe_hw_stats *stats = &adapter->stats.pf;
   1629  1.5.2.2  jdolecek 	const char *xname = device_xname(dev);
   1630      1.1    dyoung 
   1631  1.5.2.2  jdolecek 	/* Driver Statistics */
   1632  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&adapter->handleq, EVCNT_TYPE_MISC,
   1633  1.5.2.2  jdolecek 	    NULL, xname, "Handled queue in softint");
   1634  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&adapter->req, EVCNT_TYPE_MISC,
   1635  1.5.2.2  jdolecek 	    NULL, xname, "Requeued in softint");
   1636  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&adapter->efbig_tx_dma_setup, EVCNT_TYPE_MISC,
   1637  1.5.2.2  jdolecek 	    NULL, xname, "Driver tx dma soft fail EFBIG");
   1638  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&adapter->mbuf_defrag_failed, EVCNT_TYPE_MISC,
   1639  1.5.2.2  jdolecek 	    NULL, xname, "m_defrag() failed");
   1640  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&adapter->efbig2_tx_dma_setup, EVCNT_TYPE_MISC,
   1641  1.5.2.2  jdolecek 	    NULL, xname, "Driver tx dma hard fail EFBIG");
   1642  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&adapter->einval_tx_dma_setup, EVCNT_TYPE_MISC,
   1643  1.5.2.2  jdolecek 	    NULL, xname, "Driver tx dma hard fail EINVAL");
   1644  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&adapter->other_tx_dma_setup, EVCNT_TYPE_MISC,
   1645  1.5.2.2  jdolecek 	    NULL, xname, "Driver tx dma hard fail other");
   1646  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&adapter->eagain_tx_dma_setup, EVCNT_TYPE_MISC,
   1647  1.5.2.2  jdolecek 	    NULL, xname, "Driver tx dma soft fail EAGAIN");
   1648  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&adapter->enomem_tx_dma_setup, EVCNT_TYPE_MISC,
   1649  1.5.2.2  jdolecek 	    NULL, xname, "Driver tx dma soft fail ENOMEM");
   1650  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&adapter->watchdog_events, EVCNT_TYPE_MISC,
   1651  1.5.2.2  jdolecek 	    NULL, xname, "Watchdog timeouts");
   1652  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&adapter->tso_err, EVCNT_TYPE_MISC,
   1653  1.5.2.2  jdolecek 	    NULL, xname, "TSO errors");
   1654  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&adapter->link_irq, EVCNT_TYPE_INTR,
   1655  1.5.2.2  jdolecek 	    NULL, xname, "Link MSI-X IRQ Handled");
   1656      1.1    dyoung 
   1657  1.5.2.2  jdolecek 	for (int i = 0; i < adapter->num_queues; i++, rxr++, txr++) {
   1658  1.5.2.2  jdolecek 		snprintf(adapter->queues[i].evnamebuf,
   1659  1.5.2.2  jdolecek 		    sizeof(adapter->queues[i].evnamebuf), "%s q%d",
   1660  1.5.2.2  jdolecek 		    xname, i);
   1661  1.5.2.2  jdolecek 		snprintf(adapter->queues[i].namebuf,
   1662  1.5.2.2  jdolecek 		    sizeof(adapter->queues[i].namebuf), "q%d", i);
   1663      1.1    dyoung 
   1664  1.5.2.2  jdolecek 		if ((rnode = ixgbe_sysctl_instance(adapter)) == NULL) {
   1665  1.5.2.2  jdolecek 			aprint_error_dev(dev, "could not create sysctl root\n");
   1666  1.5.2.2  jdolecek 			break;
   1667  1.5.2.2  jdolecek 		}
   1668      1.1    dyoung 
   1669  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &rnode, &rnode,
   1670  1.5.2.2  jdolecek 		    0, CTLTYPE_NODE,
   1671  1.5.2.2  jdolecek 		    adapter->queues[i].namebuf, SYSCTL_DESCR("Queue Name"),
   1672  1.5.2.2  jdolecek 		    NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL) != 0)
   1673  1.5.2.2  jdolecek 			break;
   1674      1.1    dyoung 
   1675  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &rnode, &cnode,
   1676  1.5.2.2  jdolecek 		    CTLFLAG_READWRITE, CTLTYPE_INT,
   1677  1.5.2.2  jdolecek 		    "interrupt_rate", SYSCTL_DESCR("Interrupt Rate"),
   1678  1.5.2.2  jdolecek 		    ixgbe_sysctl_interrupt_rate_handler, 0,
   1679  1.5.2.2  jdolecek 		    (void *)&adapter->queues[i], 0, CTL_CREATE, CTL_EOL) != 0)
   1680  1.5.2.2  jdolecek 			break;
   1681      1.1    dyoung 
   1682  1.5.2.2  jdolecek #if 0 /* XXX msaitoh */
   1683  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &rnode, &cnode,
   1684  1.5.2.2  jdolecek 		    CTLFLAG_READONLY, CTLTYPE_QUAD,
   1685  1.5.2.2  jdolecek 		    "irqs", SYSCTL_DESCR("irqs on this queue"),
   1686  1.5.2.2  jdolecek 			NULL, 0, &(adapter->queues[i].irqs),
   1687  1.5.2.2  jdolecek 		    0, CTL_CREATE, CTL_EOL) != 0)
   1688  1.5.2.2  jdolecek 			break;
   1689  1.5.2.2  jdolecek #endif
   1690      1.1    dyoung 
   1691  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &rnode, &cnode,
   1692  1.5.2.2  jdolecek 		    CTLFLAG_READONLY, CTLTYPE_INT,
   1693  1.5.2.2  jdolecek 		    "txd_head", SYSCTL_DESCR("Transmit Descriptor Head"),
   1694  1.5.2.2  jdolecek 		    ixgbe_sysctl_tdh_handler, 0, (void *)txr,
   1695  1.5.2.2  jdolecek 		    0, CTL_CREATE, CTL_EOL) != 0)
   1696  1.5.2.2  jdolecek 			break;
   1697      1.1    dyoung 
   1698  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &rnode, &cnode,
   1699  1.5.2.2  jdolecek 		    CTLFLAG_READONLY, CTLTYPE_INT,
   1700  1.5.2.2  jdolecek 		    "txd_tail", SYSCTL_DESCR("Transmit Descriptor Tail"),
   1701  1.5.2.2  jdolecek 		    ixgbe_sysctl_tdt_handler, 0, (void *)txr,
   1702  1.5.2.2  jdolecek 		    0, CTL_CREATE, CTL_EOL) != 0)
   1703  1.5.2.2  jdolecek 			break;
   1704      1.1    dyoung 
   1705  1.5.2.2  jdolecek 		evcnt_attach_dynamic(&adapter->queues[i].irqs, EVCNT_TYPE_INTR,
   1706  1.5.2.2  jdolecek 		    NULL, adapter->queues[i].evnamebuf, "IRQs on queue");
   1707  1.5.2.2  jdolecek 		evcnt_attach_dynamic(&txr->tso_tx, EVCNT_TYPE_MISC,
   1708  1.5.2.2  jdolecek 		    NULL, adapter->queues[i].evnamebuf, "TSO");
   1709  1.5.2.2  jdolecek 		evcnt_attach_dynamic(&txr->no_desc_avail, EVCNT_TYPE_MISC,
   1710  1.5.2.2  jdolecek 		    NULL, adapter->queues[i].evnamebuf,
   1711  1.5.2.2  jdolecek 		    "Queue No Descriptor Available");
   1712  1.5.2.2  jdolecek 		evcnt_attach_dynamic(&txr->total_packets, EVCNT_TYPE_MISC,
   1713  1.5.2.2  jdolecek 		    NULL, adapter->queues[i].evnamebuf,
   1714  1.5.2.2  jdolecek 		    "Queue Packets Transmitted");
   1715  1.5.2.2  jdolecek #ifndef IXGBE_LEGACY_TX
   1716  1.5.2.2  jdolecek 		evcnt_attach_dynamic(&txr->pcq_drops, EVCNT_TYPE_MISC,
   1717  1.5.2.2  jdolecek 		    NULL, adapter->queues[i].evnamebuf,
   1718  1.5.2.2  jdolecek 		    "Packets dropped in pcq");
   1719  1.5.2.2  jdolecek #endif
   1720      1.1    dyoung 
   1721  1.5.2.2  jdolecek #ifdef LRO
   1722  1.5.2.2  jdolecek 		struct lro_ctrl *lro = &rxr->lro;
   1723  1.5.2.2  jdolecek #endif /* LRO */
   1724      1.1    dyoung 
   1725  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &rnode, &cnode,
   1726  1.5.2.2  jdolecek 		    CTLFLAG_READONLY,
   1727  1.5.2.2  jdolecek 		    CTLTYPE_INT,
   1728  1.5.2.2  jdolecek 		    "rxd_head", SYSCTL_DESCR("Receive Descriptor Head"),
   1729  1.5.2.2  jdolecek 		    ixgbe_sysctl_rdh_handler, 0, (void *)rxr, 0,
   1730  1.5.2.2  jdolecek 		    CTL_CREATE, CTL_EOL) != 0)
   1731  1.5.2.2  jdolecek 			break;
   1732      1.1    dyoung 
   1733  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &rnode, &cnode,
   1734  1.5.2.2  jdolecek 		    CTLFLAG_READONLY,
   1735  1.5.2.2  jdolecek 		    CTLTYPE_INT,
   1736  1.5.2.2  jdolecek 		    "rxd_tail", SYSCTL_DESCR("Receive Descriptor Tail"),
   1737  1.5.2.2  jdolecek 		    ixgbe_sysctl_rdt_handler, 0, (void *)rxr, 0,
   1738  1.5.2.2  jdolecek 		    CTL_CREATE, CTL_EOL) != 0)
   1739  1.5.2.2  jdolecek 			break;
   1740      1.1    dyoung 
   1741  1.5.2.2  jdolecek 		if (i < __arraycount(stats->mpc)) {
   1742  1.5.2.2  jdolecek 			evcnt_attach_dynamic(&stats->mpc[i],
   1743  1.5.2.2  jdolecek 			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
   1744  1.5.2.2  jdolecek 			    "RX Missed Packet Count");
   1745  1.5.2.2  jdolecek 			if (hw->mac.type == ixgbe_mac_82598EB)
   1746  1.5.2.2  jdolecek 				evcnt_attach_dynamic(&stats->rnbc[i],
   1747  1.5.2.2  jdolecek 				    EVCNT_TYPE_MISC, NULL,
   1748  1.5.2.2  jdolecek 				    adapter->queues[i].evnamebuf,
   1749  1.5.2.2  jdolecek 				    "Receive No Buffers");
   1750      1.1    dyoung 		}
   1751  1.5.2.2  jdolecek 		if (i < __arraycount(stats->pxontxc)) {
   1752  1.5.2.2  jdolecek 			evcnt_attach_dynamic(&stats->pxontxc[i],
   1753  1.5.2.2  jdolecek 			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
   1754  1.5.2.2  jdolecek 			    "pxontxc");
   1755  1.5.2.2  jdolecek 			evcnt_attach_dynamic(&stats->pxonrxc[i],
   1756  1.5.2.2  jdolecek 			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
   1757  1.5.2.2  jdolecek 			    "pxonrxc");
   1758  1.5.2.2  jdolecek 			evcnt_attach_dynamic(&stats->pxofftxc[i],
   1759  1.5.2.2  jdolecek 			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
   1760  1.5.2.2  jdolecek 			    "pxofftxc");
   1761  1.5.2.2  jdolecek 			evcnt_attach_dynamic(&stats->pxoffrxc[i],
   1762  1.5.2.2  jdolecek 			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
   1763  1.5.2.2  jdolecek 			    "pxoffrxc");
   1764  1.5.2.2  jdolecek 			evcnt_attach_dynamic(&stats->pxon2offc[i],
   1765  1.5.2.2  jdolecek 			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
   1766  1.5.2.2  jdolecek 			    "pxon2offc");
   1767      1.1    dyoung 		}
   1768  1.5.2.2  jdolecek 		if (i < __arraycount(stats->qprc)) {
   1769  1.5.2.2  jdolecek 			evcnt_attach_dynamic(&stats->qprc[i],
   1770  1.5.2.2  jdolecek 			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
   1771  1.5.2.2  jdolecek 			    "qprc");
   1772  1.5.2.2  jdolecek 			evcnt_attach_dynamic(&stats->qptc[i],
   1773  1.5.2.2  jdolecek 			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
   1774  1.5.2.2  jdolecek 			    "qptc");
   1775  1.5.2.2  jdolecek 			evcnt_attach_dynamic(&stats->qbrc[i],
   1776  1.5.2.2  jdolecek 			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
   1777  1.5.2.2  jdolecek 			    "qbrc");
   1778  1.5.2.2  jdolecek 			evcnt_attach_dynamic(&stats->qbtc[i],
   1779  1.5.2.2  jdolecek 			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
   1780  1.5.2.2  jdolecek 			    "qbtc");
   1781  1.5.2.2  jdolecek 			evcnt_attach_dynamic(&stats->qprdc[i],
   1782  1.5.2.2  jdolecek 			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
   1783  1.5.2.2  jdolecek 			    "qprdc");
   1784  1.5.2.2  jdolecek 		}
   1785  1.5.2.2  jdolecek 
   1786  1.5.2.2  jdolecek 		evcnt_attach_dynamic(&rxr->rx_packets, EVCNT_TYPE_MISC,
   1787  1.5.2.2  jdolecek 		    NULL, adapter->queues[i].evnamebuf, "Queue Packets Received");
   1788  1.5.2.2  jdolecek 		evcnt_attach_dynamic(&rxr->rx_bytes, EVCNT_TYPE_MISC,
   1789  1.5.2.2  jdolecek 		    NULL, adapter->queues[i].evnamebuf, "Queue Bytes Received");
   1790  1.5.2.2  jdolecek 		evcnt_attach_dynamic(&rxr->rx_copies, EVCNT_TYPE_MISC,
   1791  1.5.2.2  jdolecek 		    NULL, adapter->queues[i].evnamebuf, "Copied RX Frames");
   1792  1.5.2.2  jdolecek 		evcnt_attach_dynamic(&rxr->no_jmbuf, EVCNT_TYPE_MISC,
   1793  1.5.2.2  jdolecek 		    NULL, adapter->queues[i].evnamebuf, "Rx no jumbo mbuf");
   1794  1.5.2.2  jdolecek 		evcnt_attach_dynamic(&rxr->rx_discarded, EVCNT_TYPE_MISC,
   1795  1.5.2.2  jdolecek 		    NULL, adapter->queues[i].evnamebuf, "Rx discarded");
   1796  1.5.2.2  jdolecek #ifdef LRO
   1797  1.5.2.2  jdolecek 		SYSCTL_ADD_INT(ctx, queue_list, OID_AUTO, "lro_queued",
   1798  1.5.2.2  jdolecek 				CTLFLAG_RD, &lro->lro_queued, 0,
   1799  1.5.2.2  jdolecek 				"LRO Queued");
   1800  1.5.2.2  jdolecek 		SYSCTL_ADD_INT(ctx, queue_list, OID_AUTO, "lro_flushed",
   1801  1.5.2.2  jdolecek 				CTLFLAG_RD, &lro->lro_flushed, 0,
   1802  1.5.2.2  jdolecek 				"LRO Flushed");
   1803  1.5.2.2  jdolecek #endif /* LRO */
   1804      1.1    dyoung 	}
   1805      1.1    dyoung 
   1806  1.5.2.2  jdolecek 	/* MAC stats get their own sub node */
   1807      1.1    dyoung 
   1808  1.5.2.2  jdolecek 	snprintf(stats->namebuf,
   1809  1.5.2.2  jdolecek 	    sizeof(stats->namebuf), "%s MAC Statistics", xname);
   1810      1.1    dyoung 
   1811  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->ipcs, EVCNT_TYPE_MISC, NULL,
   1812  1.5.2.2  jdolecek 	    stats->namebuf, "rx csum offload - IP");
   1813  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->l4cs, EVCNT_TYPE_MISC, NULL,
   1814  1.5.2.2  jdolecek 	    stats->namebuf, "rx csum offload - L4");
   1815  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->ipcs_bad, EVCNT_TYPE_MISC, NULL,
   1816  1.5.2.2  jdolecek 	    stats->namebuf, "rx csum offload - IP bad");
   1817  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->l4cs_bad, EVCNT_TYPE_MISC, NULL,
   1818  1.5.2.2  jdolecek 	    stats->namebuf, "rx csum offload - L4 bad");
   1819  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->intzero, EVCNT_TYPE_MISC, NULL,
   1820  1.5.2.2  jdolecek 	    stats->namebuf, "Interrupt conditions zero");
   1821  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->legint, EVCNT_TYPE_MISC, NULL,
   1822  1.5.2.2  jdolecek 	    stats->namebuf, "Legacy interrupts");
   1823      1.1    dyoung 
   1824  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->crcerrs, EVCNT_TYPE_MISC, NULL,
   1825  1.5.2.2  jdolecek 	    stats->namebuf, "CRC Errors");
   1826  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->illerrc, EVCNT_TYPE_MISC, NULL,
   1827  1.5.2.2  jdolecek 	    stats->namebuf, "Illegal Byte Errors");
   1828  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->errbc, EVCNT_TYPE_MISC, NULL,
   1829  1.5.2.2  jdolecek 	    stats->namebuf, "Byte Errors");
   1830  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->mspdc, EVCNT_TYPE_MISC, NULL,
   1831  1.5.2.2  jdolecek 	    stats->namebuf, "MAC Short Packets Discarded");
   1832  1.5.2.2  jdolecek 	if (hw->mac.type >= ixgbe_mac_X550)
   1833  1.5.2.2  jdolecek 		evcnt_attach_dynamic(&stats->mbsdc, EVCNT_TYPE_MISC, NULL,
   1834  1.5.2.2  jdolecek 		    stats->namebuf, "Bad SFD");
   1835  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->mpctotal, EVCNT_TYPE_MISC, NULL,
   1836  1.5.2.2  jdolecek 	    stats->namebuf, "Total Packets Missed");
   1837  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->mlfc, EVCNT_TYPE_MISC, NULL,
   1838  1.5.2.2  jdolecek 	    stats->namebuf, "MAC Local Faults");
   1839  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->mrfc, EVCNT_TYPE_MISC, NULL,
   1840  1.5.2.2  jdolecek 	    stats->namebuf, "MAC Remote Faults");
   1841  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->rlec, EVCNT_TYPE_MISC, NULL,
   1842  1.5.2.2  jdolecek 	    stats->namebuf, "Receive Length Errors");
   1843  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->lxontxc, EVCNT_TYPE_MISC, NULL,
   1844  1.5.2.2  jdolecek 	    stats->namebuf, "Link XON Transmitted");
   1845  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->lxonrxc, EVCNT_TYPE_MISC, NULL,
   1846  1.5.2.2  jdolecek 	    stats->namebuf, "Link XON Received");
   1847  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->lxofftxc, EVCNT_TYPE_MISC, NULL,
   1848  1.5.2.2  jdolecek 	    stats->namebuf, "Link XOFF Transmitted");
   1849  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->lxoffrxc, EVCNT_TYPE_MISC, NULL,
   1850  1.5.2.2  jdolecek 	    stats->namebuf, "Link XOFF Received");
   1851      1.1    dyoung 
   1852  1.5.2.2  jdolecek 	/* Packet Reception Stats */
   1853  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->tor, EVCNT_TYPE_MISC, NULL,
   1854  1.5.2.2  jdolecek 	    stats->namebuf, "Total Octets Received");
   1855  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->gorc, EVCNT_TYPE_MISC, NULL,
   1856  1.5.2.2  jdolecek 	    stats->namebuf, "Good Octets Received");
   1857  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->tpr, EVCNT_TYPE_MISC, NULL,
   1858  1.5.2.2  jdolecek 	    stats->namebuf, "Total Packets Received");
   1859  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->gprc, EVCNT_TYPE_MISC, NULL,
   1860  1.5.2.2  jdolecek 	    stats->namebuf, "Good Packets Received");
   1861  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->mprc, EVCNT_TYPE_MISC, NULL,
   1862  1.5.2.2  jdolecek 	    stats->namebuf, "Multicast Packets Received");
   1863  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->bprc, EVCNT_TYPE_MISC, NULL,
   1864  1.5.2.2  jdolecek 	    stats->namebuf, "Broadcast Packets Received");
   1865  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->prc64, EVCNT_TYPE_MISC, NULL,
   1866  1.5.2.2  jdolecek 	    stats->namebuf, "64 byte frames received ");
   1867  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->prc127, EVCNT_TYPE_MISC, NULL,
   1868  1.5.2.2  jdolecek 	    stats->namebuf, "65-127 byte frames received");
   1869  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->prc255, EVCNT_TYPE_MISC, NULL,
   1870  1.5.2.2  jdolecek 	    stats->namebuf, "128-255 byte frames received");
   1871  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->prc511, EVCNT_TYPE_MISC, NULL,
   1872  1.5.2.2  jdolecek 	    stats->namebuf, "256-511 byte frames received");
   1873  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->prc1023, EVCNT_TYPE_MISC, NULL,
   1874  1.5.2.2  jdolecek 	    stats->namebuf, "512-1023 byte frames received");
   1875  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->prc1522, EVCNT_TYPE_MISC, NULL,
   1876  1.5.2.2  jdolecek 	    stats->namebuf, "1023-1522 byte frames received");
   1877  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->ruc, EVCNT_TYPE_MISC, NULL,
   1878  1.5.2.2  jdolecek 	    stats->namebuf, "Receive Undersized");
   1879  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->rfc, EVCNT_TYPE_MISC, NULL,
   1880  1.5.2.2  jdolecek 	    stats->namebuf, "Fragmented Packets Received ");
   1881  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->roc, EVCNT_TYPE_MISC, NULL,
   1882  1.5.2.2  jdolecek 	    stats->namebuf, "Oversized Packets Received");
   1883  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->rjc, EVCNT_TYPE_MISC, NULL,
   1884  1.5.2.2  jdolecek 	    stats->namebuf, "Received Jabber");
   1885  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->mngprc, EVCNT_TYPE_MISC, NULL,
   1886  1.5.2.2  jdolecek 	    stats->namebuf, "Management Packets Received");
   1887  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->mngpdc, EVCNT_TYPE_MISC, NULL,
   1888  1.5.2.2  jdolecek 	    stats->namebuf, "Management Packets Dropped");
   1889  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->xec, EVCNT_TYPE_MISC, NULL,
   1890  1.5.2.2  jdolecek 	    stats->namebuf, "Checksum Errors");
   1891      1.1    dyoung 
   1892  1.5.2.2  jdolecek 	/* Packet Transmission Stats */
   1893  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->gotc, EVCNT_TYPE_MISC, NULL,
   1894  1.5.2.2  jdolecek 	    stats->namebuf, "Good Octets Transmitted");
   1895  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->tpt, EVCNT_TYPE_MISC, NULL,
   1896  1.5.2.2  jdolecek 	    stats->namebuf, "Total Packets Transmitted");
   1897  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->gptc, EVCNT_TYPE_MISC, NULL,
   1898  1.5.2.2  jdolecek 	    stats->namebuf, "Good Packets Transmitted");
   1899  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->bptc, EVCNT_TYPE_MISC, NULL,
   1900  1.5.2.2  jdolecek 	    stats->namebuf, "Broadcast Packets Transmitted");
   1901  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->mptc, EVCNT_TYPE_MISC, NULL,
   1902  1.5.2.2  jdolecek 	    stats->namebuf, "Multicast Packets Transmitted");
   1903  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->mngptc, EVCNT_TYPE_MISC, NULL,
   1904  1.5.2.2  jdolecek 	    stats->namebuf, "Management Packets Transmitted");
   1905  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->ptc64, EVCNT_TYPE_MISC, NULL,
   1906  1.5.2.2  jdolecek 	    stats->namebuf, "64 byte frames transmitted ");
   1907  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->ptc127, EVCNT_TYPE_MISC, NULL,
   1908  1.5.2.2  jdolecek 	    stats->namebuf, "65-127 byte frames transmitted");
   1909  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->ptc255, EVCNT_TYPE_MISC, NULL,
   1910  1.5.2.2  jdolecek 	    stats->namebuf, "128-255 byte frames transmitted");
   1911  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->ptc511, EVCNT_TYPE_MISC, NULL,
   1912  1.5.2.2  jdolecek 	    stats->namebuf, "256-511 byte frames transmitted");
   1913  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->ptc1023, EVCNT_TYPE_MISC, NULL,
   1914  1.5.2.2  jdolecek 	    stats->namebuf, "512-1023 byte frames transmitted");
   1915  1.5.2.2  jdolecek 	evcnt_attach_dynamic(&stats->ptc1522, EVCNT_TYPE_MISC, NULL,
   1916  1.5.2.2  jdolecek 	    stats->namebuf, "1024-1522 byte frames transmitted");
   1917  1.5.2.2  jdolecek } /* ixgbe_add_hw_stats */
   1918      1.1    dyoung 
   1919  1.5.2.2  jdolecek static void
   1920  1.5.2.2  jdolecek ixgbe_clear_evcnt(struct adapter *adapter)
   1921  1.5.2.2  jdolecek {
   1922  1.5.2.2  jdolecek 	struct tx_ring *txr = adapter->tx_rings;
   1923  1.5.2.2  jdolecek 	struct rx_ring *rxr = adapter->rx_rings;
   1924  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   1925  1.5.2.2  jdolecek 	struct ixgbe_hw_stats *stats = &adapter->stats.pf;
   1926      1.1    dyoung 
   1927  1.5.2.2  jdolecek 	adapter->handleq.ev_count = 0;
   1928  1.5.2.2  jdolecek 	adapter->req.ev_count = 0;
   1929  1.5.2.2  jdolecek 	adapter->efbig_tx_dma_setup.ev_count = 0;
   1930  1.5.2.2  jdolecek 	adapter->mbuf_defrag_failed.ev_count = 0;
   1931  1.5.2.2  jdolecek 	adapter->efbig2_tx_dma_setup.ev_count = 0;
   1932  1.5.2.2  jdolecek 	adapter->einval_tx_dma_setup.ev_count = 0;
   1933  1.5.2.2  jdolecek 	adapter->other_tx_dma_setup.ev_count = 0;
   1934  1.5.2.2  jdolecek 	adapter->eagain_tx_dma_setup.ev_count = 0;
   1935  1.5.2.2  jdolecek 	adapter->enomem_tx_dma_setup.ev_count = 0;
   1936  1.5.2.2  jdolecek 	adapter->watchdog_events.ev_count = 0;
   1937  1.5.2.2  jdolecek 	adapter->tso_err.ev_count = 0;
   1938  1.5.2.2  jdolecek 	adapter->link_irq.ev_count = 0;
   1939      1.1    dyoung 
   1940  1.5.2.2  jdolecek 	txr = adapter->tx_rings;
   1941  1.5.2.2  jdolecek 	for (int i = 0; i < adapter->num_queues; i++, rxr++, txr++) {
   1942  1.5.2.2  jdolecek 		adapter->queues[i].irqs.ev_count = 0;
   1943  1.5.2.2  jdolecek 		txr->no_desc_avail.ev_count = 0;
   1944  1.5.2.2  jdolecek 		txr->total_packets.ev_count = 0;
   1945  1.5.2.2  jdolecek 		txr->tso_tx.ev_count = 0;
   1946  1.5.2.2  jdolecek #ifndef IXGBE_LEGACY_TX
   1947  1.5.2.2  jdolecek 		txr->pcq_drops.ev_count = 0;
   1948  1.5.2.2  jdolecek #endif
   1949  1.5.2.2  jdolecek 
   1950  1.5.2.2  jdolecek 		if (i < __arraycount(stats->mpc)) {
   1951  1.5.2.2  jdolecek 			stats->mpc[i].ev_count = 0;
   1952  1.5.2.2  jdolecek 			if (hw->mac.type == ixgbe_mac_82598EB)
   1953  1.5.2.2  jdolecek 				stats->rnbc[i].ev_count = 0;
   1954  1.5.2.2  jdolecek 		}
   1955  1.5.2.2  jdolecek 		if (i < __arraycount(stats->pxontxc)) {
   1956  1.5.2.2  jdolecek 			stats->pxontxc[i].ev_count = 0;
   1957  1.5.2.2  jdolecek 			stats->pxonrxc[i].ev_count = 0;
   1958  1.5.2.2  jdolecek 			stats->pxofftxc[i].ev_count = 0;
   1959  1.5.2.2  jdolecek 			stats->pxoffrxc[i].ev_count = 0;
   1960  1.5.2.2  jdolecek 			stats->pxon2offc[i].ev_count = 0;
   1961  1.5.2.2  jdolecek 		}
   1962  1.5.2.2  jdolecek 		if (i < __arraycount(stats->qprc)) {
   1963  1.5.2.2  jdolecek 			stats->qprc[i].ev_count = 0;
   1964  1.5.2.2  jdolecek 			stats->qptc[i].ev_count = 0;
   1965  1.5.2.2  jdolecek 			stats->qbrc[i].ev_count = 0;
   1966  1.5.2.2  jdolecek 			stats->qbtc[i].ev_count = 0;
   1967  1.5.2.2  jdolecek 			stats->qprdc[i].ev_count = 0;
   1968  1.5.2.2  jdolecek 		}
   1969  1.5.2.2  jdolecek 
   1970  1.5.2.2  jdolecek 		rxr->rx_packets.ev_count = 0;
   1971  1.5.2.2  jdolecek 		rxr->rx_bytes.ev_count = 0;
   1972  1.5.2.2  jdolecek 		rxr->rx_copies.ev_count = 0;
   1973  1.5.2.2  jdolecek 		rxr->no_jmbuf.ev_count = 0;
   1974  1.5.2.2  jdolecek 		rxr->rx_discarded.ev_count = 0;
   1975  1.5.2.2  jdolecek 	}
   1976  1.5.2.2  jdolecek 	stats->ipcs.ev_count = 0;
   1977  1.5.2.2  jdolecek 	stats->l4cs.ev_count = 0;
   1978  1.5.2.2  jdolecek 	stats->ipcs_bad.ev_count = 0;
   1979  1.5.2.2  jdolecek 	stats->l4cs_bad.ev_count = 0;
   1980  1.5.2.2  jdolecek 	stats->intzero.ev_count = 0;
   1981  1.5.2.2  jdolecek 	stats->legint.ev_count = 0;
   1982  1.5.2.2  jdolecek 	stats->crcerrs.ev_count = 0;
   1983  1.5.2.2  jdolecek 	stats->illerrc.ev_count = 0;
   1984  1.5.2.2  jdolecek 	stats->errbc.ev_count = 0;
   1985  1.5.2.2  jdolecek 	stats->mspdc.ev_count = 0;
   1986  1.5.2.2  jdolecek 	stats->mbsdc.ev_count = 0;
   1987  1.5.2.2  jdolecek 	stats->mpctotal.ev_count = 0;
   1988  1.5.2.2  jdolecek 	stats->mlfc.ev_count = 0;
   1989  1.5.2.2  jdolecek 	stats->mrfc.ev_count = 0;
   1990  1.5.2.2  jdolecek 	stats->rlec.ev_count = 0;
   1991  1.5.2.2  jdolecek 	stats->lxontxc.ev_count = 0;
   1992  1.5.2.2  jdolecek 	stats->lxonrxc.ev_count = 0;
   1993  1.5.2.2  jdolecek 	stats->lxofftxc.ev_count = 0;
   1994  1.5.2.2  jdolecek 	stats->lxoffrxc.ev_count = 0;
   1995      1.1    dyoung 
   1996  1.5.2.2  jdolecek 	/* Packet Reception Stats */
   1997  1.5.2.2  jdolecek 	stats->tor.ev_count = 0;
   1998  1.5.2.2  jdolecek 	stats->gorc.ev_count = 0;
   1999  1.5.2.2  jdolecek 	stats->tpr.ev_count = 0;
   2000  1.5.2.2  jdolecek 	stats->gprc.ev_count = 0;
   2001  1.5.2.2  jdolecek 	stats->mprc.ev_count = 0;
   2002  1.5.2.2  jdolecek 	stats->bprc.ev_count = 0;
   2003  1.5.2.2  jdolecek 	stats->prc64.ev_count = 0;
   2004  1.5.2.2  jdolecek 	stats->prc127.ev_count = 0;
   2005  1.5.2.2  jdolecek 	stats->prc255.ev_count = 0;
   2006  1.5.2.2  jdolecek 	stats->prc511.ev_count = 0;
   2007  1.5.2.2  jdolecek 	stats->prc1023.ev_count = 0;
   2008  1.5.2.2  jdolecek 	stats->prc1522.ev_count = 0;
   2009  1.5.2.2  jdolecek 	stats->ruc.ev_count = 0;
   2010  1.5.2.2  jdolecek 	stats->rfc.ev_count = 0;
   2011  1.5.2.2  jdolecek 	stats->roc.ev_count = 0;
   2012  1.5.2.2  jdolecek 	stats->rjc.ev_count = 0;
   2013  1.5.2.2  jdolecek 	stats->mngprc.ev_count = 0;
   2014  1.5.2.2  jdolecek 	stats->mngpdc.ev_count = 0;
   2015  1.5.2.2  jdolecek 	stats->xec.ev_count = 0;
   2016      1.1    dyoung 
   2017  1.5.2.2  jdolecek 	/* Packet Transmission Stats */
   2018  1.5.2.2  jdolecek 	stats->gotc.ev_count = 0;
   2019  1.5.2.2  jdolecek 	stats->tpt.ev_count = 0;
   2020  1.5.2.2  jdolecek 	stats->gptc.ev_count = 0;
   2021  1.5.2.2  jdolecek 	stats->bptc.ev_count = 0;
   2022  1.5.2.2  jdolecek 	stats->mptc.ev_count = 0;
   2023  1.5.2.2  jdolecek 	stats->mngptc.ev_count = 0;
   2024  1.5.2.2  jdolecek 	stats->ptc64.ev_count = 0;
   2025  1.5.2.2  jdolecek 	stats->ptc127.ev_count = 0;
   2026  1.5.2.2  jdolecek 	stats->ptc255.ev_count = 0;
   2027  1.5.2.2  jdolecek 	stats->ptc511.ev_count = 0;
   2028  1.5.2.2  jdolecek 	stats->ptc1023.ev_count = 0;
   2029  1.5.2.2  jdolecek 	stats->ptc1522.ev_count = 0;
   2030      1.1    dyoung }
   2031      1.1    dyoung 
   2032  1.5.2.2  jdolecek /************************************************************************
   2033  1.5.2.2  jdolecek  * ixgbe_sysctl_tdh_handler - Transmit Descriptor Head handler function
   2034  1.5.2.2  jdolecek  *
   2035  1.5.2.2  jdolecek  *   Retrieves the TDH value from the hardware
   2036  1.5.2.2  jdolecek  ************************************************************************/
   2037  1.5.2.2  jdolecek static int
   2038  1.5.2.2  jdolecek ixgbe_sysctl_tdh_handler(SYSCTLFN_ARGS)
   2039      1.1    dyoung {
   2040  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   2041  1.5.2.2  jdolecek 	struct tx_ring *txr = (struct tx_ring *)node.sysctl_data;
   2042  1.5.2.2  jdolecek 	uint32_t val;
   2043      1.1    dyoung 
   2044  1.5.2.2  jdolecek 	if (!txr)
   2045  1.5.2.2  jdolecek 		return (0);
   2046      1.1    dyoung 
   2047  1.5.2.2  jdolecek 	val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me));
   2048  1.5.2.2  jdolecek 	node.sysctl_data = &val;
   2049  1.5.2.2  jdolecek 	return sysctl_lookup(SYSCTLFN_CALL(&node));
   2050  1.5.2.2  jdolecek } /* ixgbe_sysctl_tdh_handler */
   2051      1.1    dyoung 
   2052  1.5.2.2  jdolecek /************************************************************************
   2053  1.5.2.2  jdolecek  * ixgbe_sysctl_tdt_handler - Transmit Descriptor Tail handler function
   2054  1.5.2.2  jdolecek  *
   2055  1.5.2.2  jdolecek  *   Retrieves the TDT value from the hardware
   2056  1.5.2.2  jdolecek  ************************************************************************/
   2057  1.5.2.2  jdolecek static int
   2058  1.5.2.2  jdolecek ixgbe_sysctl_tdt_handler(SYSCTLFN_ARGS)
   2059      1.1    dyoung {
   2060  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   2061  1.5.2.2  jdolecek 	struct tx_ring *txr = (struct tx_ring *)node.sysctl_data;
   2062  1.5.2.2  jdolecek 	uint32_t val;
   2063      1.1    dyoung 
   2064  1.5.2.2  jdolecek 	if (!txr)
   2065  1.5.2.2  jdolecek 		return (0);
   2066  1.5.2.2  jdolecek 
   2067  1.5.2.2  jdolecek 	val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me));
   2068  1.5.2.2  jdolecek 	node.sysctl_data = &val;
   2069  1.5.2.2  jdolecek 	return sysctl_lookup(SYSCTLFN_CALL(&node));
   2070  1.5.2.2  jdolecek } /* ixgbe_sysctl_tdt_handler */
   2071      1.1    dyoung 
   2072  1.5.2.2  jdolecek /************************************************************************
   2073  1.5.2.2  jdolecek  * ixgbe_sysctl_rdh_handler - Receive Descriptor Head handler function
   2074  1.5.2.2  jdolecek  *
   2075  1.5.2.2  jdolecek  *   Retrieves the RDH value from the hardware
   2076  1.5.2.2  jdolecek  ************************************************************************/
   2077  1.5.2.2  jdolecek static int
   2078  1.5.2.2  jdolecek ixgbe_sysctl_rdh_handler(SYSCTLFN_ARGS)
   2079      1.1    dyoung {
   2080  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   2081  1.5.2.2  jdolecek 	struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data;
   2082  1.5.2.2  jdolecek 	uint32_t val;
   2083      1.1    dyoung 
   2084  1.5.2.2  jdolecek 	if (!rxr)
   2085  1.5.2.2  jdolecek 		return (0);
   2086      1.1    dyoung 
   2087  1.5.2.2  jdolecek 	val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me));
   2088  1.5.2.2  jdolecek 	node.sysctl_data = &val;
   2089  1.5.2.2  jdolecek 	return sysctl_lookup(SYSCTLFN_CALL(&node));
   2090  1.5.2.2  jdolecek } /* ixgbe_sysctl_rdh_handler */
   2091  1.5.2.2  jdolecek 
   2092  1.5.2.2  jdolecek /************************************************************************
   2093  1.5.2.2  jdolecek  * ixgbe_sysctl_rdt_handler - Receive Descriptor Tail handler function
   2094  1.5.2.2  jdolecek  *
   2095  1.5.2.2  jdolecek  *   Retrieves the RDT value from the hardware
   2096  1.5.2.2  jdolecek  ************************************************************************/
   2097  1.5.2.2  jdolecek static int
   2098  1.5.2.2  jdolecek ixgbe_sysctl_rdt_handler(SYSCTLFN_ARGS)
   2099      1.1    dyoung {
   2100  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   2101  1.5.2.2  jdolecek 	struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data;
   2102  1.5.2.2  jdolecek 	uint32_t val;
   2103      1.1    dyoung 
   2104  1.5.2.2  jdolecek 	if (!rxr)
   2105  1.5.2.2  jdolecek 		return (0);
   2106      1.1    dyoung 
   2107  1.5.2.2  jdolecek 	val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me));
   2108  1.5.2.2  jdolecek 	node.sysctl_data = &val;
   2109  1.5.2.2  jdolecek 	return sysctl_lookup(SYSCTLFN_CALL(&node));
   2110  1.5.2.2  jdolecek } /* ixgbe_sysctl_rdt_handler */
   2111      1.1    dyoung 
   2112  1.5.2.2  jdolecek #if 0	/* XXX Badly need to overhaul vlan(4) on NetBSD. */
   2113  1.5.2.2  jdolecek /************************************************************************
   2114  1.5.2.2  jdolecek  * ixgbe_register_vlan
   2115  1.5.2.2  jdolecek  *
   2116  1.5.2.2  jdolecek  *   Run via vlan config EVENT, it enables us to use the
   2117  1.5.2.2  jdolecek  *   HW Filter table since we can get the vlan id. This
   2118  1.5.2.2  jdolecek  *   just creates the entry in the soft version of the
   2119  1.5.2.2  jdolecek  *   VFTA, init will repopulate the real table.
   2120  1.5.2.2  jdolecek  ************************************************************************/
   2121      1.1    dyoung static void
   2122  1.5.2.2  jdolecek ixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
   2123      1.1    dyoung {
   2124  1.5.2.2  jdolecek 	struct adapter	*adapter = ifp->if_softc;
   2125  1.5.2.2  jdolecek 	u16		index, bit;
   2126      1.1    dyoung 
   2127  1.5.2.2  jdolecek 	if (ifp->if_softc != arg)   /* Not our event */
   2128  1.5.2.2  jdolecek 		return;
   2129      1.1    dyoung 
   2130  1.5.2.2  jdolecek 	if ((vtag == 0) || (vtag > 4095))	/* Invalid */
   2131  1.5.2.2  jdolecek 		return;
   2132  1.5.2.2  jdolecek 
   2133  1.5.2.2  jdolecek 	IXGBE_CORE_LOCK(adapter);
   2134  1.5.2.2  jdolecek 	index = (vtag >> 5) & 0x7F;
   2135  1.5.2.2  jdolecek 	bit = vtag & 0x1F;
   2136  1.5.2.2  jdolecek 	adapter->shadow_vfta[index] |= (1 << bit);
   2137  1.5.2.2  jdolecek 	ixgbe_setup_vlan_hw_support(adapter);
   2138  1.5.2.2  jdolecek 	IXGBE_CORE_UNLOCK(adapter);
   2139  1.5.2.2  jdolecek } /* ixgbe_register_vlan */
   2140      1.1    dyoung 
   2141  1.5.2.2  jdolecek /************************************************************************
   2142  1.5.2.2  jdolecek  * ixgbe_unregister_vlan
   2143  1.5.2.2  jdolecek  *
   2144  1.5.2.2  jdolecek  *   Run via vlan unconfig EVENT, remove our entry in the soft vfta.
   2145  1.5.2.2  jdolecek  ************************************************************************/
   2146  1.5.2.2  jdolecek static void
   2147  1.5.2.2  jdolecek ixgbe_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
   2148  1.5.2.2  jdolecek {
   2149  1.5.2.2  jdolecek 	struct adapter	*adapter = ifp->if_softc;
   2150  1.5.2.2  jdolecek 	u16		index, bit;
   2151      1.1    dyoung 
   2152  1.5.2.2  jdolecek 	if (ifp->if_softc != arg)
   2153  1.5.2.2  jdolecek 		return;
   2154      1.1    dyoung 
   2155  1.5.2.2  jdolecek 	if ((vtag == 0) || (vtag > 4095))	/* Invalid */
   2156  1.5.2.2  jdolecek 		return;
   2157      1.1    dyoung 
   2158  1.5.2.2  jdolecek 	IXGBE_CORE_LOCK(adapter);
   2159  1.5.2.2  jdolecek 	index = (vtag >> 5) & 0x7F;
   2160  1.5.2.2  jdolecek 	bit = vtag & 0x1F;
   2161  1.5.2.2  jdolecek 	adapter->shadow_vfta[index] &= ~(1 << bit);
   2162  1.5.2.2  jdolecek 	/* Re-init to load the changes */
   2163  1.5.2.2  jdolecek 	ixgbe_setup_vlan_hw_support(adapter);
   2164  1.5.2.2  jdolecek 	IXGBE_CORE_UNLOCK(adapter);
   2165  1.5.2.2  jdolecek } /* ixgbe_unregister_vlan */
   2166  1.5.2.2  jdolecek #endif
   2167      1.1    dyoung 
   2168  1.5.2.2  jdolecek static void
   2169  1.5.2.2  jdolecek ixgbe_setup_vlan_hw_support(struct adapter *adapter)
   2170      1.1    dyoung {
   2171  1.5.2.2  jdolecek 	struct ethercom *ec = &adapter->osdep.ec;
   2172  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   2173  1.5.2.2  jdolecek 	struct rx_ring	*rxr;
   2174  1.5.2.2  jdolecek 	int             i;
   2175  1.5.2.2  jdolecek 	u32		ctrl;
   2176      1.1    dyoung 
   2177      1.1    dyoung 
   2178  1.5.2.2  jdolecek 	/*
   2179  1.5.2.2  jdolecek 	 * We get here thru init_locked, meaning
   2180  1.5.2.2  jdolecek 	 * a soft reset, this has already cleared
   2181  1.5.2.2  jdolecek 	 * the VFTA and other state, so if there
   2182  1.5.2.2  jdolecek 	 * have been no vlan's registered do nothing.
   2183  1.5.2.2  jdolecek 	 */
   2184  1.5.2.2  jdolecek 	if (!VLAN_ATTACHED(&adapter->osdep.ec))
   2185  1.5.2.2  jdolecek 		return;
   2186      1.1    dyoung 
   2187  1.5.2.2  jdolecek 	/* Setup the queues for vlans */
   2188  1.5.2.2  jdolecek 	for (i = 0; i < adapter->num_queues; i++) {
   2189  1.5.2.2  jdolecek 		rxr = &adapter->rx_rings[i];
   2190  1.5.2.2  jdolecek 		/* On 82599 the VLAN enable is per/queue in RXDCTL */
   2191  1.5.2.2  jdolecek 		if (hw->mac.type != ixgbe_mac_82598EB) {
   2192  1.5.2.2  jdolecek 			ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
   2193  1.5.2.2  jdolecek 			ctrl |= IXGBE_RXDCTL_VME;
   2194  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl);
   2195  1.5.2.2  jdolecek 		}
   2196  1.5.2.2  jdolecek 		rxr->vtag_strip = TRUE;
   2197      1.1    dyoung 	}
   2198      1.1    dyoung 
   2199  1.5.2.2  jdolecek 	if ((ec->ec_capenable & ETHERCAP_VLAN_HWFILTER) == 0)
   2200  1.5.2.2  jdolecek 		return;
   2201  1.5.2.2  jdolecek 	/*
   2202  1.5.2.2  jdolecek 	 * A soft reset zero's out the VFTA, so
   2203  1.5.2.2  jdolecek 	 * we need to repopulate it now.
   2204  1.5.2.2  jdolecek 	 */
   2205  1.5.2.2  jdolecek 	for (i = 0; i < IXGBE_VFTA_SIZE; i++)
   2206  1.5.2.2  jdolecek 		if (adapter->shadow_vfta[i] != 0)
   2207  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_VFTA(i),
   2208  1.5.2.2  jdolecek 			    adapter->shadow_vfta[i]);
   2209      1.1    dyoung 
   2210  1.5.2.2  jdolecek 	ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
   2211  1.5.2.2  jdolecek 	/* Enable the Filter Table if enabled */
   2212  1.5.2.2  jdolecek 	if (ec->ec_capenable & ETHERCAP_VLAN_HWFILTER) {
   2213  1.5.2.2  jdolecek 		ctrl &= ~IXGBE_VLNCTRL_CFIEN;
   2214  1.5.2.2  jdolecek 		ctrl |= IXGBE_VLNCTRL_VFE;
   2215  1.5.2.2  jdolecek 	}
   2216  1.5.2.2  jdolecek 	if (hw->mac.type == ixgbe_mac_82598EB)
   2217  1.5.2.2  jdolecek 		ctrl |= IXGBE_VLNCTRL_VME;
   2218  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl);
   2219  1.5.2.2  jdolecek } /* ixgbe_setup_vlan_hw_support */
   2220      1.1    dyoung 
   2221  1.5.2.2  jdolecek /************************************************************************
   2222  1.5.2.2  jdolecek  * ixgbe_get_slot_info
   2223  1.5.2.2  jdolecek  *
   2224  1.5.2.2  jdolecek  *   Get the width and transaction speed of
   2225  1.5.2.2  jdolecek  *   the slot this adapter is plugged into.
   2226  1.5.2.2  jdolecek  ************************************************************************/
   2227  1.5.2.2  jdolecek static void
   2228  1.5.2.2  jdolecek ixgbe_get_slot_info(struct adapter *adapter)
   2229  1.5.2.2  jdolecek {
   2230  1.5.2.2  jdolecek 	device_t		dev = adapter->dev;
   2231  1.5.2.2  jdolecek 	struct ixgbe_hw		*hw = &adapter->hw;
   2232  1.5.2.2  jdolecek 	u32                   offset;
   2233  1.5.2.2  jdolecek //	struct ixgbe_mac_info	*mac = &hw->mac;
   2234  1.5.2.2  jdolecek 	u16			link;
   2235  1.5.2.2  jdolecek 	int                   bus_info_valid = TRUE;
   2236  1.5.2.2  jdolecek 
   2237  1.5.2.2  jdolecek 	/* Some devices are behind an internal bridge */
   2238  1.5.2.2  jdolecek 	switch (hw->device_id) {
   2239  1.5.2.2  jdolecek 	case IXGBE_DEV_ID_82599_SFP_SF_QP:
   2240  1.5.2.2  jdolecek 	case IXGBE_DEV_ID_82599_QSFP_SF_QP:
   2241  1.5.2.2  jdolecek 		goto get_parent_info;
   2242  1.5.2.2  jdolecek 	default:
   2243  1.5.2.2  jdolecek 		break;
   2244      1.1    dyoung 	}
   2245      1.1    dyoung 
   2246  1.5.2.2  jdolecek 	ixgbe_get_bus_info(hw);
   2247  1.5.2.2  jdolecek 
   2248  1.5.2.2  jdolecek 	/*
   2249  1.5.2.2  jdolecek 	 * Some devices don't use PCI-E, but there is no need
   2250  1.5.2.2  jdolecek 	 * to display "Unknown" for bus speed and width.
   2251  1.5.2.2  jdolecek 	 */
   2252  1.5.2.2  jdolecek 	switch (hw->mac.type) {
   2253  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
   2254  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
   2255  1.5.2.2  jdolecek 		return;
   2256  1.5.2.2  jdolecek 	default:
   2257  1.5.2.2  jdolecek 		goto display;
   2258      1.1    dyoung 	}
   2259      1.1    dyoung 
   2260  1.5.2.2  jdolecek get_parent_info:
   2261  1.5.2.2  jdolecek 	/*
   2262  1.5.2.2  jdolecek 	 * For the Quad port adapter we need to parse back
   2263  1.5.2.2  jdolecek 	 * up the PCI tree to find the speed of the expansion
   2264  1.5.2.2  jdolecek 	 * slot into which this adapter is plugged. A bit more work.
   2265  1.5.2.2  jdolecek 	 */
   2266  1.5.2.2  jdolecek 	dev = device_parent(device_parent(dev));
   2267  1.5.2.2  jdolecek #if 0
   2268  1.5.2.2  jdolecek #ifdef IXGBE_DEBUG
   2269  1.5.2.2  jdolecek 	device_printf(dev, "parent pcib = %x,%x,%x\n", pci_get_bus(dev),
   2270  1.5.2.2  jdolecek 	    pci_get_slot(dev), pci_get_function(dev));
   2271  1.5.2.2  jdolecek #endif
   2272  1.5.2.2  jdolecek 	dev = device_parent(device_parent(dev));
   2273  1.5.2.2  jdolecek #ifdef IXGBE_DEBUG
   2274  1.5.2.2  jdolecek 	device_printf(dev, "slot pcib = %x,%x,%x\n", pci_get_bus(dev),
   2275  1.5.2.2  jdolecek 	    pci_get_slot(dev), pci_get_function(dev));
   2276  1.5.2.2  jdolecek #endif
   2277  1.5.2.2  jdolecek #endif
   2278  1.5.2.2  jdolecek 	/* Now get the PCI Express Capabilities offset */
   2279  1.5.2.2  jdolecek 	if (pci_get_capability(adapter->osdep.pc, adapter->osdep.tag,
   2280  1.5.2.2  jdolecek 	    PCI_CAP_PCIEXPRESS, &offset, NULL)) {
   2281  1.5.2.2  jdolecek 		/*
   2282  1.5.2.2  jdolecek 		 * Hmm...can't get PCI-Express capabilities.
   2283  1.5.2.2  jdolecek 		 * Falling back to default method.
   2284  1.5.2.2  jdolecek 		 */
   2285  1.5.2.2  jdolecek 		bus_info_valid = FALSE;
   2286  1.5.2.2  jdolecek 		ixgbe_get_bus_info(hw);
   2287  1.5.2.2  jdolecek 		goto display;
   2288  1.5.2.2  jdolecek 	}
   2289  1.5.2.2  jdolecek 	/* ...and read the Link Status Register */
   2290  1.5.2.2  jdolecek 	link = pci_conf_read(adapter->osdep.pc, adapter->osdep.tag,
   2291  1.5.2.2  jdolecek 	    offset + PCIE_LCSR);
   2292  1.5.2.2  jdolecek 	ixgbe_set_pci_config_data_generic(hw, link >> 16);
   2293  1.5.2.2  jdolecek 
   2294  1.5.2.2  jdolecek display:
   2295  1.5.2.2  jdolecek 	device_printf(dev, "PCI Express Bus: Speed %s Width %s\n",
   2296  1.5.2.2  jdolecek 	    ((hw->bus.speed == ixgbe_bus_speed_8000)    ? "8.0GT/s" :
   2297  1.5.2.2  jdolecek 	     (hw->bus.speed == ixgbe_bus_speed_5000)    ? "5.0GT/s" :
   2298  1.5.2.2  jdolecek 	     (hw->bus.speed == ixgbe_bus_speed_2500)    ? "2.5GT/s" :
   2299  1.5.2.2  jdolecek 	     "Unknown"),
   2300  1.5.2.2  jdolecek 	    ((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "x8" :
   2301  1.5.2.2  jdolecek 	     (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "x4" :
   2302  1.5.2.2  jdolecek 	     (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "x1" :
   2303  1.5.2.2  jdolecek 	     "Unknown"));
   2304  1.5.2.2  jdolecek 
   2305  1.5.2.2  jdolecek 	if (bus_info_valid) {
   2306  1.5.2.2  jdolecek 		if ((hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) &&
   2307  1.5.2.2  jdolecek 		    ((hw->bus.width <= ixgbe_bus_width_pcie_x4) &&
   2308  1.5.2.2  jdolecek 			(hw->bus.speed == ixgbe_bus_speed_2500))) {
   2309  1.5.2.2  jdolecek 			device_printf(dev, "PCI-Express bandwidth available"
   2310  1.5.2.2  jdolecek 			    " for this card\n     is not sufficient for"
   2311  1.5.2.2  jdolecek 			    " optimal performance.\n");
   2312  1.5.2.2  jdolecek 			device_printf(dev, "For optimal performance a x8 "
   2313  1.5.2.2  jdolecek 			    "PCIE, or x4 PCIE Gen2 slot is required.\n");
   2314  1.5.2.2  jdolecek 		}
   2315  1.5.2.2  jdolecek 		if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) &&
   2316  1.5.2.2  jdolecek 		    ((hw->bus.width <= ixgbe_bus_width_pcie_x8) &&
   2317  1.5.2.2  jdolecek 			(hw->bus.speed < ixgbe_bus_speed_8000))) {
   2318  1.5.2.2  jdolecek 			device_printf(dev, "PCI-Express bandwidth available"
   2319  1.5.2.2  jdolecek 			    " for this card\n     is not sufficient for"
   2320  1.5.2.2  jdolecek 			    " optimal performance.\n");
   2321  1.5.2.2  jdolecek 			device_printf(dev, "For optimal performance a x8 "
   2322  1.5.2.2  jdolecek 			    "PCIE Gen3 slot is required.\n");
   2323  1.5.2.2  jdolecek 		}
   2324  1.5.2.2  jdolecek 	} else
   2325  1.5.2.2  jdolecek 		device_printf(dev, "Unable to determine slot speed/width. The speed/width reported are that of the internal switch.\n");
   2326      1.1    dyoung 
   2327  1.5.2.2  jdolecek 	return;
   2328  1.5.2.2  jdolecek } /* ixgbe_get_slot_info */
   2329      1.1    dyoung 
   2330  1.5.2.2  jdolecek /************************************************************************
   2331  1.5.2.2  jdolecek  * ixgbe_enable_queue - MSI-X Interrupt Handlers and Tasklets
   2332  1.5.2.2  jdolecek  ************************************************************************/
   2333  1.5.2.2  jdolecek static inline void
   2334  1.5.2.2  jdolecek ixgbe_enable_queue(struct adapter *adapter, u32 vector)
   2335  1.5.2.2  jdolecek {
   2336  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   2337  1.5.2.2  jdolecek 	u64             queue = (u64)(1ULL << vector);
   2338  1.5.2.2  jdolecek 	u32             mask;
   2339      1.1    dyoung 
   2340  1.5.2.2  jdolecek 	if (hw->mac.type == ixgbe_mac_82598EB) {
   2341  1.5.2.2  jdolecek 		mask = (IXGBE_EIMS_RTX_QUEUE & queue);
   2342  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
   2343  1.5.2.2  jdolecek 	} else {
   2344  1.5.2.2  jdolecek 		mask = (queue & 0xFFFFFFFF);
   2345  1.5.2.2  jdolecek 		if (mask)
   2346  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
   2347  1.5.2.2  jdolecek 		mask = (queue >> 32);
   2348  1.5.2.2  jdolecek 		if (mask)
   2349  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
   2350  1.5.2.2  jdolecek 	}
   2351  1.5.2.2  jdolecek } /* ixgbe_enable_queue */
   2352  1.5.2.2  jdolecek 
   2353  1.5.2.2  jdolecek /************************************************************************
   2354  1.5.2.2  jdolecek  * ixgbe_disable_queue
   2355  1.5.2.2  jdolecek  ************************************************************************/
   2356  1.5.2.2  jdolecek static inline void
   2357  1.5.2.2  jdolecek ixgbe_disable_queue(struct adapter *adapter, u32 vector)
   2358  1.5.2.2  jdolecek {
   2359  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   2360  1.5.2.2  jdolecek 	u64             queue = (u64)(1ULL << vector);
   2361  1.5.2.2  jdolecek 	u32             mask;
   2362  1.5.2.2  jdolecek 
   2363  1.5.2.2  jdolecek 	if (hw->mac.type == ixgbe_mac_82598EB) {
   2364  1.5.2.2  jdolecek 		mask = (IXGBE_EIMS_RTX_QUEUE & queue);
   2365  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask);
   2366  1.5.2.2  jdolecek 	} else {
   2367  1.5.2.2  jdolecek 		mask = (queue & 0xFFFFFFFF);
   2368  1.5.2.2  jdolecek 		if (mask)
   2369  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask);
   2370  1.5.2.2  jdolecek 		mask = (queue >> 32);
   2371  1.5.2.2  jdolecek 		if (mask)
   2372  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
   2373  1.5.2.2  jdolecek 	}
   2374  1.5.2.2  jdolecek } /* ixgbe_disable_queue */
   2375  1.5.2.2  jdolecek 
   2376  1.5.2.2  jdolecek /************************************************************************
   2377  1.5.2.2  jdolecek  * ixgbe_msix_que - MSI-X Queue Interrupt Service routine
   2378  1.5.2.2  jdolecek  ************************************************************************/
   2379  1.5.2.2  jdolecek static int
   2380      1.1    dyoung ixgbe_msix_que(void *arg)
   2381      1.1    dyoung {
   2382      1.1    dyoung 	struct ix_queue	*que = arg;
   2383      1.1    dyoung 	struct adapter  *adapter = que->adapter;
   2384  1.5.2.2  jdolecek 	struct ifnet    *ifp = adapter->ifp;
   2385      1.1    dyoung 	struct tx_ring	*txr = que->txr;
   2386      1.1    dyoung 	struct rx_ring	*rxr = que->rxr;
   2387  1.5.2.2  jdolecek 	bool		more;
   2388      1.1    dyoung 	u32		newitr = 0;
   2389      1.1    dyoung 
   2390  1.5.2.2  jdolecek 	/* Protect against spurious interrupts */
   2391  1.5.2.2  jdolecek 	if ((ifp->if_flags & IFF_RUNNING) == 0)
   2392  1.5.2.2  jdolecek 		return 0;
   2393  1.5.2.2  jdolecek 
   2394  1.5.2.2  jdolecek 	ixgbe_disable_queue(adapter, que->msix);
   2395  1.5.2.2  jdolecek 	++que->irqs.ev_count;
   2396      1.1    dyoung 
   2397  1.5.2.2  jdolecek #ifdef __NetBSD__
   2398  1.5.2.2  jdolecek 	/* Don't run ixgbe_rxeof in interrupt context */
   2399  1.5.2.2  jdolecek 	more = true;
   2400  1.5.2.2  jdolecek #else
   2401  1.5.2.2  jdolecek 	more = ixgbe_rxeof(que);
   2402  1.5.2.2  jdolecek #endif
   2403      1.1    dyoung 
   2404      1.1    dyoung 	IXGBE_TX_LOCK(txr);
   2405  1.5.2.2  jdolecek 	ixgbe_txeof(txr);
   2406      1.1    dyoung 	IXGBE_TX_UNLOCK(txr);
   2407      1.1    dyoung 
   2408      1.1    dyoung 	/* Do AIM now? */
   2409      1.1    dyoung 
   2410  1.5.2.2  jdolecek 	if (adapter->enable_aim == false)
   2411      1.1    dyoung 		goto no_calc;
   2412      1.1    dyoung 	/*
   2413  1.5.2.2  jdolecek 	 * Do Adaptive Interrupt Moderation:
   2414  1.5.2.2  jdolecek 	 *  - Write out last calculated setting
   2415  1.5.2.2  jdolecek 	 *  - Calculate based on average size over
   2416  1.5.2.2  jdolecek 	 *    the last interval.
   2417  1.5.2.2  jdolecek 	 */
   2418  1.5.2.2  jdolecek 	if (que->eitr_setting)
   2419  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(que->msix),
   2420  1.5.2.2  jdolecek 		    que->eitr_setting);
   2421  1.5.2.2  jdolecek 
   2422  1.5.2.2  jdolecek 	que->eitr_setting = 0;
   2423      1.1    dyoung 
   2424  1.5.2.2  jdolecek 	/* Idle, do nothing */
   2425      1.1    dyoung         if ((txr->bytes == 0) && (rxr->bytes == 0))
   2426      1.1    dyoung                 goto no_calc;
   2427      1.1    dyoung 
   2428      1.1    dyoung 	if ((txr->bytes) && (txr->packets))
   2429  1.5.2.2  jdolecek 		newitr = txr->bytes/txr->packets;
   2430      1.1    dyoung 	if ((rxr->bytes) && (rxr->packets))
   2431  1.5.2.2  jdolecek 		newitr = max(newitr, (rxr->bytes / rxr->packets));
   2432      1.1    dyoung 	newitr += 24; /* account for hardware frame, crc */
   2433      1.1    dyoung 
   2434      1.1    dyoung 	/* set an upper boundary */
   2435      1.1    dyoung 	newitr = min(newitr, 3000);
   2436      1.1    dyoung 
   2437      1.1    dyoung 	/* Be nice to the mid range */
   2438      1.1    dyoung 	if ((newitr > 300) && (newitr < 1200))
   2439      1.1    dyoung 		newitr = (newitr / 3);
   2440      1.1    dyoung 	else
   2441      1.1    dyoung 		newitr = (newitr / 2);
   2442      1.1    dyoung 
   2443      1.1    dyoung         if (adapter->hw.mac.type == ixgbe_mac_82598EB)
   2444      1.1    dyoung                 newitr |= newitr << 16;
   2445      1.1    dyoung         else
   2446      1.1    dyoung                 newitr |= IXGBE_EITR_CNT_WDIS;
   2447      1.1    dyoung 
   2448      1.1    dyoung         /* save for next interrupt */
   2449      1.1    dyoung         que->eitr_setting = newitr;
   2450      1.1    dyoung 
   2451  1.5.2.2  jdolecek 	/* Reset state */
   2452  1.5.2.2  jdolecek 	txr->bytes = 0;
   2453  1.5.2.2  jdolecek 	txr->packets = 0;
   2454  1.5.2.2  jdolecek 	rxr->bytes = 0;
   2455  1.5.2.2  jdolecek 	rxr->packets = 0;
   2456      1.1    dyoung 
   2457      1.1    dyoung no_calc:
   2458  1.5.2.2  jdolecek 	if (more)
   2459      1.1    dyoung 		softint_schedule(que->que_si);
   2460  1.5.2.2  jdolecek 	else
   2461      1.1    dyoung 		ixgbe_enable_queue(adapter, que->msix);
   2462      1.1    dyoung 
   2463  1.5.2.2  jdolecek 	return 1;
   2464  1.5.2.2  jdolecek } /* ixgbe_msix_que */
   2465      1.1    dyoung 
   2466  1.5.2.2  jdolecek /************************************************************************
   2467  1.5.2.2  jdolecek  * ixgbe_media_status - Media Ioctl callback
   2468      1.1    dyoung  *
   2469  1.5.2.2  jdolecek  *   Called whenever the user queries the status of
   2470  1.5.2.2  jdolecek  *   the interface using ifconfig.
   2471  1.5.2.2  jdolecek  ************************************************************************/
   2472      1.1    dyoung static void
   2473  1.5.2.2  jdolecek ixgbe_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
   2474      1.1    dyoung {
   2475      1.1    dyoung 	struct adapter *adapter = ifp->if_softc;
   2476  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   2477  1.5.2.2  jdolecek 	int layer;
   2478      1.1    dyoung 
   2479      1.1    dyoung 	INIT_DEBUGOUT("ixgbe_media_status: begin");
   2480      1.1    dyoung 	IXGBE_CORE_LOCK(adapter);
   2481      1.1    dyoung 	ixgbe_update_link_status(adapter);
   2482      1.1    dyoung 
   2483      1.1    dyoung 	ifmr->ifm_status = IFM_AVALID;
   2484      1.1    dyoung 	ifmr->ifm_active = IFM_ETHER;
   2485      1.1    dyoung 
   2486      1.1    dyoung 	if (!adapter->link_active) {
   2487  1.5.2.2  jdolecek 		ifmr->ifm_active |= IFM_NONE;
   2488      1.1    dyoung 		IXGBE_CORE_UNLOCK(adapter);
   2489      1.1    dyoung 		return;
   2490      1.1    dyoung 	}
   2491      1.1    dyoung 
   2492      1.1    dyoung 	ifmr->ifm_status |= IFM_ACTIVE;
   2493  1.5.2.2  jdolecek 	layer = adapter->phy_layer;
   2494      1.1    dyoung 
   2495  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T ||
   2496  1.5.2.2  jdolecek 	    layer & IXGBE_PHYSICAL_LAYER_5GBASE_T ||
   2497  1.5.2.2  jdolecek 	    layer & IXGBE_PHYSICAL_LAYER_2500BASE_T ||
   2498  1.5.2.2  jdolecek 	    layer & IXGBE_PHYSICAL_LAYER_1000BASE_T ||
   2499  1.5.2.2  jdolecek 	    layer & IXGBE_PHYSICAL_LAYER_100BASE_TX ||
   2500  1.5.2.2  jdolecek 	    layer & IXGBE_PHYSICAL_LAYER_10BASE_T)
   2501  1.5.2.2  jdolecek 		switch (adapter->link_speed) {
   2502  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_10GB_FULL:
   2503  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_10G_T | IFM_FDX;
   2504  1.5.2.2  jdolecek 			break;
   2505  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_5GB_FULL:
   2506  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_5000_T | IFM_FDX;
   2507  1.5.2.2  jdolecek 			break;
   2508  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_2_5GB_FULL:
   2509  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_2500_T | IFM_FDX;
   2510  1.5.2.2  jdolecek 			break;
   2511      1.1    dyoung 		case IXGBE_LINK_SPEED_1GB_FULL:
   2512      1.1    dyoung 			ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
   2513      1.1    dyoung 			break;
   2514  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_100_FULL:
   2515  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
   2516  1.5.2.2  jdolecek 			break;
   2517  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_10_FULL:
   2518  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_10_T | IFM_FDX;
   2519  1.5.2.2  jdolecek 			break;
   2520  1.5.2.2  jdolecek 		}
   2521  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
   2522  1.5.2.2  jdolecek 	    layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
   2523  1.5.2.2  jdolecek 		switch (adapter->link_speed) {
   2524  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_10GB_FULL:
   2525  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX;
   2526  1.5.2.2  jdolecek 			break;
   2527  1.5.2.2  jdolecek 		}
   2528  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR)
   2529  1.5.2.2  jdolecek 		switch (adapter->link_speed) {
   2530  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_10GB_FULL:
   2531  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_10G_LR | IFM_FDX;
   2532  1.5.2.2  jdolecek 			break;
   2533  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_1GB_FULL:
   2534  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
   2535  1.5.2.2  jdolecek 			break;
   2536  1.5.2.2  jdolecek 		}
   2537  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM)
   2538  1.5.2.2  jdolecek 		switch (adapter->link_speed) {
   2539  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_10GB_FULL:
   2540  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX;
   2541  1.5.2.2  jdolecek 			break;
   2542  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_1GB_FULL:
   2543  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
   2544  1.5.2.2  jdolecek 			break;
   2545  1.5.2.2  jdolecek 		}
   2546  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR ||
   2547  1.5.2.2  jdolecek 	    layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
   2548  1.5.2.2  jdolecek 		switch (adapter->link_speed) {
   2549  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_10GB_FULL:
   2550  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
   2551  1.5.2.2  jdolecek 			break;
   2552  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_1GB_FULL:
   2553  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
   2554  1.5.2.2  jdolecek 			break;
   2555  1.5.2.2  jdolecek 		}
   2556  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
   2557  1.5.2.2  jdolecek 		switch (adapter->link_speed) {
   2558  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_10GB_FULL:
   2559  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
   2560  1.5.2.2  jdolecek 			break;
   2561  1.5.2.2  jdolecek 		}
   2562  1.5.2.2  jdolecek 	/*
   2563  1.5.2.2  jdolecek 	 * XXX: These need to use the proper media types once
   2564  1.5.2.2  jdolecek 	 * they're added.
   2565  1.5.2.2  jdolecek 	 */
   2566  1.5.2.2  jdolecek 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
   2567  1.5.2.2  jdolecek 		switch (adapter->link_speed) {
   2568  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_10GB_FULL:
   2569  1.5.2.2  jdolecek #ifndef IFM_ETH_XTYPE
   2570  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
   2571  1.5.2.2  jdolecek #else
   2572  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_10G_KR | IFM_FDX;
   2573  1.5.2.2  jdolecek #endif
   2574  1.5.2.2  jdolecek 			break;
   2575  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_2_5GB_FULL:
   2576  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
   2577  1.5.2.2  jdolecek 			break;
   2578  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_1GB_FULL:
   2579  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
   2580  1.5.2.2  jdolecek 			break;
   2581  1.5.2.2  jdolecek 		}
   2582  1.5.2.2  jdolecek 	else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 ||
   2583  1.5.2.2  jdolecek 	    layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX ||
   2584  1.5.2.2  jdolecek 	    layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
   2585  1.5.2.2  jdolecek 		switch (adapter->link_speed) {
   2586      1.1    dyoung 		case IXGBE_LINK_SPEED_10GB_FULL:
   2587  1.5.2.2  jdolecek #ifndef IFM_ETH_XTYPE
   2588  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
   2589  1.5.2.2  jdolecek #else
   2590  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX;
   2591  1.5.2.2  jdolecek #endif
   2592      1.1    dyoung 			break;
   2593  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_2_5GB_FULL:
   2594  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
   2595  1.5.2.2  jdolecek 			break;
   2596  1.5.2.2  jdolecek 		case IXGBE_LINK_SPEED_1GB_FULL:
   2597  1.5.2.2  jdolecek 			ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
   2598  1.5.2.2  jdolecek 			break;
   2599  1.5.2.2  jdolecek 		}
   2600  1.5.2.2  jdolecek 
   2601  1.5.2.2  jdolecek 	/* If nothing is recognized... */
   2602  1.5.2.2  jdolecek #if 0
   2603  1.5.2.2  jdolecek 	if (IFM_SUBTYPE(ifmr->ifm_active) == 0)
   2604  1.5.2.2  jdolecek 		ifmr->ifm_active |= IFM_UNKNOWN;
   2605  1.5.2.2  jdolecek #endif
   2606  1.5.2.2  jdolecek 
   2607  1.5.2.2  jdolecek 	ifp->if_baudrate = ifmedia_baudrate(ifmr->ifm_active);
   2608  1.5.2.2  jdolecek 
   2609  1.5.2.2  jdolecek 	/* Display current flow control setting used on link */
   2610  1.5.2.2  jdolecek 	if (hw->fc.current_mode == ixgbe_fc_rx_pause ||
   2611  1.5.2.2  jdolecek 	    hw->fc.current_mode == ixgbe_fc_full)
   2612  1.5.2.2  jdolecek 		ifmr->ifm_active |= IFM_ETH_RXPAUSE;
   2613  1.5.2.2  jdolecek 	if (hw->fc.current_mode == ixgbe_fc_tx_pause ||
   2614  1.5.2.2  jdolecek 	    hw->fc.current_mode == ixgbe_fc_full)
   2615  1.5.2.2  jdolecek 		ifmr->ifm_active |= IFM_ETH_TXPAUSE;
   2616      1.1    dyoung 
   2617      1.1    dyoung 	IXGBE_CORE_UNLOCK(adapter);
   2618      1.1    dyoung 
   2619      1.1    dyoung 	return;
   2620  1.5.2.2  jdolecek } /* ixgbe_media_status */
   2621      1.1    dyoung 
   2622  1.5.2.2  jdolecek /************************************************************************
   2623  1.5.2.2  jdolecek  * ixgbe_media_change - Media Ioctl callback
   2624      1.1    dyoung  *
   2625  1.5.2.2  jdolecek  *   Called when the user changes speed/duplex using
   2626  1.5.2.2  jdolecek  *   media/mediopt option with ifconfig.
   2627  1.5.2.2  jdolecek  ************************************************************************/
   2628      1.1    dyoung static int
   2629  1.5.2.2  jdolecek ixgbe_media_change(struct ifnet *ifp)
   2630      1.1    dyoung {
   2631  1.5.2.2  jdolecek 	struct adapter   *adapter = ifp->if_softc;
   2632  1.5.2.2  jdolecek 	struct ifmedia   *ifm = &adapter->media;
   2633  1.5.2.2  jdolecek 	struct ixgbe_hw  *hw = &adapter->hw;
   2634  1.5.2.2  jdolecek 	ixgbe_link_speed speed = 0;
   2635  1.5.2.2  jdolecek 	ixgbe_link_speed link_caps = 0;
   2636  1.5.2.2  jdolecek 	bool negotiate = false;
   2637  1.5.2.2  jdolecek 	s32 err = IXGBE_NOT_IMPLEMENTED;
   2638      1.1    dyoung 
   2639      1.1    dyoung 	INIT_DEBUGOUT("ixgbe_media_change: begin");
   2640      1.1    dyoung 
   2641      1.1    dyoung 	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
   2642      1.1    dyoung 		return (EINVAL);
   2643      1.1    dyoung 
   2644  1.5.2.2  jdolecek 	if (hw->phy.media_type == ixgbe_media_type_backplane)
   2645  1.5.2.2  jdolecek 		return (ENODEV);
   2646      1.1    dyoung 
   2647      1.1    dyoung 	/*
   2648  1.5.2.2  jdolecek 	 * We don't actually need to check against the supported
   2649  1.5.2.2  jdolecek 	 * media types of the adapter; ifmedia will take care of
   2650  1.5.2.2  jdolecek 	 * that for us.
   2651      1.1    dyoung 	 */
   2652  1.5.2.2  jdolecek 	switch (IFM_SUBTYPE(ifm->ifm_media)) {
   2653  1.5.2.2  jdolecek 	case IFM_AUTO:
   2654  1.5.2.2  jdolecek 		err = hw->mac.ops.get_link_capabilities(hw, &link_caps,
   2655  1.5.2.2  jdolecek 		    &negotiate);
   2656  1.5.2.2  jdolecek 		if (err != IXGBE_SUCCESS) {
   2657  1.5.2.2  jdolecek 			device_printf(adapter->dev, "Unable to determine "
   2658  1.5.2.2  jdolecek 			    "supported advertise speeds\n");
   2659  1.5.2.2  jdolecek 			return (ENODEV);
   2660  1.5.2.2  jdolecek 		}
   2661  1.5.2.2  jdolecek 		speed |= link_caps;
   2662  1.5.2.2  jdolecek 		break;
   2663  1.5.2.2  jdolecek 	case IFM_10G_T:
   2664  1.5.2.2  jdolecek 	case IFM_10G_LRM:
   2665  1.5.2.2  jdolecek 	case IFM_10G_LR:
   2666  1.5.2.2  jdolecek 	case IFM_10G_TWINAX:
   2667  1.5.2.2  jdolecek #ifndef IFM_ETH_XTYPE
   2668  1.5.2.2  jdolecek 	case IFM_10G_SR: /* KR, too */
   2669  1.5.2.2  jdolecek 	case IFM_10G_CX4: /* KX4 */
   2670  1.5.2.2  jdolecek #else
   2671  1.5.2.2  jdolecek 	case IFM_10G_KR:
   2672  1.5.2.2  jdolecek 	case IFM_10G_KX4:
   2673  1.5.2.2  jdolecek #endif
   2674  1.5.2.2  jdolecek 		speed |= IXGBE_LINK_SPEED_10GB_FULL;
   2675  1.5.2.2  jdolecek 		break;
   2676  1.5.2.2  jdolecek 	case IFM_5000_T:
   2677  1.5.2.2  jdolecek 		speed |= IXGBE_LINK_SPEED_5GB_FULL;
   2678  1.5.2.2  jdolecek 		break;
   2679  1.5.2.2  jdolecek 	case IFM_2500_T:
   2680  1.5.2.2  jdolecek 	case IFM_2500_KX:
   2681  1.5.2.2  jdolecek 		speed |= IXGBE_LINK_SPEED_2_5GB_FULL;
   2682      1.1    dyoung 		break;
   2683  1.5.2.2  jdolecek 	case IFM_1000_T:
   2684  1.5.2.2  jdolecek 	case IFM_1000_LX:
   2685  1.5.2.2  jdolecek 	case IFM_1000_SX:
   2686  1.5.2.2  jdolecek 	case IFM_1000_KX:
   2687  1.5.2.2  jdolecek 		speed |= IXGBE_LINK_SPEED_1GB_FULL;
   2688  1.5.2.2  jdolecek 		break;
   2689  1.5.2.2  jdolecek 	case IFM_100_TX:
   2690  1.5.2.2  jdolecek 		speed |= IXGBE_LINK_SPEED_100_FULL;
   2691  1.5.2.2  jdolecek 		break;
   2692  1.5.2.2  jdolecek 	case IFM_10_T:
   2693  1.5.2.2  jdolecek 		speed |= IXGBE_LINK_SPEED_10_FULL;
   2694  1.5.2.2  jdolecek 		break;
   2695  1.5.2.2  jdolecek 	default:
   2696  1.5.2.2  jdolecek 		goto invalid;
   2697      1.1    dyoung 	}
   2698      1.1    dyoung 
   2699  1.5.2.2  jdolecek 	hw->mac.autotry_restart = TRUE;
   2700  1.5.2.2  jdolecek 	hw->mac.ops.setup_link(hw, speed, TRUE);
   2701  1.5.2.2  jdolecek 	adapter->advertise = 0;
   2702  1.5.2.2  jdolecek 	if (IFM_SUBTYPE(ifm->ifm_media) != IFM_AUTO) {
   2703  1.5.2.2  jdolecek 		if ((speed & IXGBE_LINK_SPEED_10GB_FULL) != 0)
   2704  1.5.2.2  jdolecek 			adapter->advertise |= 1 << 2;
   2705  1.5.2.2  jdolecek 		if ((speed & IXGBE_LINK_SPEED_1GB_FULL) != 0)
   2706  1.5.2.2  jdolecek 			adapter->advertise |= 1 << 1;
   2707  1.5.2.2  jdolecek 		if ((speed & IXGBE_LINK_SPEED_100_FULL) != 0)
   2708  1.5.2.2  jdolecek 			adapter->advertise |= 1 << 0;
   2709  1.5.2.2  jdolecek 		if ((speed & IXGBE_LINK_SPEED_10_FULL) != 0)
   2710  1.5.2.2  jdolecek 			adapter->advertise |= 1 << 3;
   2711  1.5.2.2  jdolecek 		if ((speed & IXGBE_LINK_SPEED_2_5GB_FULL) != 0)
   2712  1.5.2.2  jdolecek 			adapter->advertise |= 1 << 4;
   2713  1.5.2.2  jdolecek 		if ((speed & IXGBE_LINK_SPEED_5GB_FULL) != 0)
   2714  1.5.2.2  jdolecek 			adapter->advertise |= 1 << 5;
   2715      1.1    dyoung 	}
   2716      1.1    dyoung 
   2717  1.5.2.2  jdolecek 	return (0);
   2718      1.1    dyoung 
   2719  1.5.2.2  jdolecek invalid:
   2720  1.5.2.2  jdolecek 	device_printf(adapter->dev, "Invalid media type!\n");
   2721      1.1    dyoung 
   2722  1.5.2.2  jdolecek 	return (EINVAL);
   2723  1.5.2.2  jdolecek } /* ixgbe_media_change */
   2724      1.1    dyoung 
   2725  1.5.2.2  jdolecek /************************************************************************
   2726  1.5.2.2  jdolecek  * ixgbe_set_promisc
   2727  1.5.2.2  jdolecek  ************************************************************************/
   2728      1.1    dyoung static void
   2729      1.1    dyoung ixgbe_set_promisc(struct adapter *adapter)
   2730      1.1    dyoung {
   2731  1.5.2.2  jdolecek 	struct ifnet *ifp = adapter->ifp;
   2732  1.5.2.2  jdolecek 	int          mcnt = 0;
   2733  1.5.2.2  jdolecek 	u32          rctl;
   2734      1.1    dyoung 	struct ether_multi *enm;
   2735      1.1    dyoung 	struct ether_multistep step;
   2736      1.1    dyoung 	struct ethercom *ec = &adapter->osdep.ec;
   2737      1.1    dyoung 
   2738  1.5.2.2  jdolecek 	KASSERT(mutex_owned(&adapter->core_mtx));
   2739  1.5.2.2  jdolecek 	rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
   2740  1.5.2.2  jdolecek 	rctl &= (~IXGBE_FCTRL_UPE);
   2741  1.5.2.2  jdolecek 	if (ifp->if_flags & IFF_ALLMULTI)
   2742  1.5.2.2  jdolecek 		mcnt = MAX_NUM_MULTICAST_ADDRESSES;
   2743  1.5.2.2  jdolecek 	else {
   2744  1.5.2.2  jdolecek 		ETHER_LOCK(ec);
   2745  1.5.2.2  jdolecek 		ETHER_FIRST_MULTI(step, ec, enm);
   2746  1.5.2.2  jdolecek 		while (enm != NULL) {
   2747  1.5.2.2  jdolecek 			if (mcnt == MAX_NUM_MULTICAST_ADDRESSES)
   2748  1.5.2.2  jdolecek 				break;
   2749  1.5.2.2  jdolecek 			mcnt++;
   2750  1.5.2.2  jdolecek 			ETHER_NEXT_MULTI(step, enm);
   2751      1.1    dyoung 		}
   2752  1.5.2.2  jdolecek 		ETHER_UNLOCK(ec);
   2753      1.1    dyoung 	}
   2754  1.5.2.2  jdolecek 	if (mcnt < MAX_NUM_MULTICAST_ADDRESSES)
   2755  1.5.2.2  jdolecek 		rctl &= (~IXGBE_FCTRL_MPE);
   2756  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl);
   2757      1.1    dyoung 
   2758  1.5.2.2  jdolecek 	if (ifp->if_flags & IFF_PROMISC) {
   2759  1.5.2.2  jdolecek 		rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
   2760  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl);
   2761  1.5.2.2  jdolecek 	} else if (ifp->if_flags & IFF_ALLMULTI) {
   2762  1.5.2.2  jdolecek 		rctl |= IXGBE_FCTRL_MPE;
   2763  1.5.2.2  jdolecek 		rctl &= ~IXGBE_FCTRL_UPE;
   2764  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl);
   2765  1.5.2.2  jdolecek 	}
   2766  1.5.2.2  jdolecek } /* ixgbe_set_promisc */
   2767  1.5.2.2  jdolecek 
   2768  1.5.2.2  jdolecek /************************************************************************
   2769  1.5.2.2  jdolecek  * ixgbe_msix_link - Link status change ISR (MSI/MSI-X)
   2770  1.5.2.2  jdolecek  ************************************************************************/
   2771  1.5.2.2  jdolecek static int
   2772  1.5.2.2  jdolecek ixgbe_msix_link(void *arg)
   2773      1.1    dyoung {
   2774  1.5.2.2  jdolecek 	struct adapter	*adapter = arg;
   2775  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   2776  1.5.2.2  jdolecek 	u32		eicr, eicr_mask;
   2777  1.5.2.2  jdolecek 	s32             retval;
   2778      1.1    dyoung 
   2779  1.5.2.2  jdolecek 	++adapter->link_irq.ev_count;
   2780      1.1    dyoung 
   2781  1.5.2.2  jdolecek 	/* Pause other interrupts */
   2782  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER);
   2783      1.1    dyoung 
   2784  1.5.2.2  jdolecek 	/* First get the cause */
   2785  1.5.2.2  jdolecek 	eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
   2786  1.5.2.2  jdolecek 	/* Be sure the queue bits are not cleared */
   2787  1.5.2.2  jdolecek 	eicr &= ~IXGBE_EICR_RTX_QUEUE;
   2788  1.5.2.2  jdolecek 	/* Clear interrupt with write */
   2789  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr);
   2790      1.1    dyoung 
   2791  1.5.2.2  jdolecek 	/* Link status change */
   2792  1.5.2.2  jdolecek 	if (eicr & IXGBE_EICR_LSC) {
   2793  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
   2794  1.5.2.2  jdolecek 		softint_schedule(adapter->link_si);
   2795  1.5.2.2  jdolecek 	}
   2796      1.1    dyoung 
   2797  1.5.2.2  jdolecek 	if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
   2798  1.5.2.2  jdolecek 		if ((adapter->feat_en & IXGBE_FEATURE_FDIR) &&
   2799  1.5.2.2  jdolecek 		    (eicr & IXGBE_EICR_FLOW_DIR)) {
   2800  1.5.2.2  jdolecek 			/* This is probably overkill :) */
   2801  1.5.2.2  jdolecek 			if (!atomic_cas_uint(&adapter->fdir_reinit, 0, 1))
   2802  1.5.2.2  jdolecek 				return 1;
   2803  1.5.2.2  jdolecek 			/* Disable the interrupt */
   2804  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR);
   2805  1.5.2.2  jdolecek 			softint_schedule(adapter->fdir_si);
   2806  1.5.2.2  jdolecek 		}
   2807      1.1    dyoung 
   2808  1.5.2.2  jdolecek 		if (eicr & IXGBE_EICR_ECC) {
   2809  1.5.2.2  jdolecek 			device_printf(adapter->dev,
   2810  1.5.2.2  jdolecek 			    "CRITICAL: ECC ERROR!! Please Reboot!!\n");
   2811  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
   2812  1.5.2.2  jdolecek 		}
   2813      1.1    dyoung 
   2814  1.5.2.2  jdolecek 		/* Check for over temp condition */
   2815  1.5.2.2  jdolecek 		if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR) {
   2816  1.5.2.2  jdolecek 			switch (adapter->hw.mac.type) {
   2817  1.5.2.2  jdolecek 			case ixgbe_mac_X550EM_a:
   2818  1.5.2.2  jdolecek 				if (!(eicr & IXGBE_EICR_GPI_SDP0_X550EM_a))
   2819  1.5.2.2  jdolecek 					break;
   2820  1.5.2.2  jdolecek 				IXGBE_WRITE_REG(hw, IXGBE_EIMC,
   2821  1.5.2.2  jdolecek 				    IXGBE_EICR_GPI_SDP0_X550EM_a);
   2822  1.5.2.2  jdolecek 				IXGBE_WRITE_REG(hw, IXGBE_EICR,
   2823  1.5.2.2  jdolecek 				    IXGBE_EICR_GPI_SDP0_X550EM_a);
   2824  1.5.2.2  jdolecek 				retval = hw->phy.ops.check_overtemp(hw);
   2825  1.5.2.2  jdolecek 				if (retval != IXGBE_ERR_OVERTEMP)
   2826  1.5.2.2  jdolecek 					break;
   2827  1.5.2.2  jdolecek 				device_printf(adapter->dev, "CRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n");
   2828  1.5.2.2  jdolecek 				device_printf(adapter->dev, "System shutdown required!\n");
   2829  1.5.2.2  jdolecek 				break;
   2830  1.5.2.2  jdolecek 			default:
   2831  1.5.2.2  jdolecek 				if (!(eicr & IXGBE_EICR_TS))
   2832  1.5.2.2  jdolecek 					break;
   2833  1.5.2.2  jdolecek 				retval = hw->phy.ops.check_overtemp(hw);
   2834  1.5.2.2  jdolecek 				if (retval != IXGBE_ERR_OVERTEMP)
   2835  1.5.2.2  jdolecek 					break;
   2836  1.5.2.2  jdolecek 				device_printf(adapter->dev, "CRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n");
   2837  1.5.2.2  jdolecek 				device_printf(adapter->dev, "System shutdown required!\n");
   2838  1.5.2.2  jdolecek 				IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS);
   2839  1.5.2.2  jdolecek 				break;
   2840  1.5.2.2  jdolecek 			}
   2841  1.5.2.2  jdolecek 		}
   2842      1.1    dyoung 
   2843  1.5.2.2  jdolecek 		/* Check for VF message */
   2844  1.5.2.2  jdolecek 		if ((adapter->feat_en & IXGBE_FEATURE_SRIOV) &&
   2845  1.5.2.2  jdolecek 		    (eicr & IXGBE_EICR_MAILBOX))
   2846  1.5.2.2  jdolecek 			softint_schedule(adapter->mbx_si);
   2847  1.5.2.2  jdolecek 	}
   2848      1.1    dyoung 
   2849  1.5.2.2  jdolecek 	if (ixgbe_is_sfp(hw)) {
   2850  1.5.2.2  jdolecek 		/* Pluggable optics-related interrupt */
   2851  1.5.2.2  jdolecek 		if (hw->mac.type >= ixgbe_mac_X540)
   2852  1.5.2.2  jdolecek 			eicr_mask = IXGBE_EICR_GPI_SDP0_X540;
   2853  1.5.2.2  jdolecek 		else
   2854  1.5.2.2  jdolecek 			eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw);
   2855      1.1    dyoung 
   2856  1.5.2.2  jdolecek 		if (eicr & eicr_mask) {
   2857  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask);
   2858  1.5.2.2  jdolecek 			softint_schedule(adapter->mod_si);
   2859      1.1    dyoung 		}
   2860  1.5.2.2  jdolecek 
   2861  1.5.2.2  jdolecek 		if ((hw->mac.type == ixgbe_mac_82599EB) &&
   2862  1.5.2.2  jdolecek 		    (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) {
   2863  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_EICR,
   2864  1.5.2.2  jdolecek 			    IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
   2865  1.5.2.2  jdolecek 			softint_schedule(adapter->msf_si);
   2866      1.1    dyoung 		}
   2867      1.1    dyoung 	}
   2868      1.1    dyoung 
   2869  1.5.2.2  jdolecek 	/* Check for fan failure */
   2870  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
   2871  1.5.2.2  jdolecek 		ixgbe_check_fan_failure(adapter, eicr, TRUE);
   2872  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
   2873  1.5.2.2  jdolecek 	}
   2874      1.1    dyoung 
   2875  1.5.2.2  jdolecek 	/* External PHY interrupt */
   2876  1.5.2.2  jdolecek 	if ((hw->phy.type == ixgbe_phy_x550em_ext_t) &&
   2877  1.5.2.2  jdolecek 	    (eicr & IXGBE_EICR_GPI_SDP0_X540)) {
   2878  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540);
   2879  1.5.2.2  jdolecek 		softint_schedule(adapter->phy_si);
   2880  1.5.2.2  jdolecek  	}
   2881      1.1    dyoung 
   2882  1.5.2.2  jdolecek 	/* Re-enable other interrupts */
   2883  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
   2884  1.5.2.2  jdolecek 	return 1;
   2885  1.5.2.2  jdolecek } /* ixgbe_msix_link */
   2886  1.5.2.2  jdolecek 
   2887  1.5.2.2  jdolecek /************************************************************************
   2888  1.5.2.2  jdolecek  * ixgbe_sysctl_interrupt_rate_handler
   2889  1.5.2.2  jdolecek  ************************************************************************/
   2890  1.5.2.2  jdolecek static int
   2891  1.5.2.2  jdolecek ixgbe_sysctl_interrupt_rate_handler(SYSCTLFN_ARGS)
   2892      1.1    dyoung {
   2893  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   2894  1.5.2.2  jdolecek 	struct ix_queue *que = (struct ix_queue *)node.sysctl_data;
   2895  1.5.2.2  jdolecek 	uint32_t reg, usec, rate;
   2896  1.5.2.2  jdolecek 	int error;
   2897      1.1    dyoung 
   2898  1.5.2.2  jdolecek 	if (que == NULL)
   2899  1.5.2.2  jdolecek 		return 0;
   2900  1.5.2.2  jdolecek 	reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix));
   2901  1.5.2.2  jdolecek 	usec = ((reg & 0x0FF8) >> 3);
   2902  1.5.2.2  jdolecek 	if (usec > 0)
   2903  1.5.2.2  jdolecek 		rate = 500000 / usec;
   2904  1.5.2.2  jdolecek 	else
   2905  1.5.2.2  jdolecek 		rate = 0;
   2906  1.5.2.2  jdolecek 	node.sysctl_data = &rate;
   2907  1.5.2.2  jdolecek 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
   2908  1.5.2.2  jdolecek 	if (error || newp == NULL)
   2909  1.5.2.2  jdolecek 		return error;
   2910  1.5.2.2  jdolecek 	reg &= ~0xfff; /* default, no limitation */
   2911  1.5.2.2  jdolecek 	ixgbe_max_interrupt_rate = 0;
   2912  1.5.2.2  jdolecek 	if (rate > 0 && rate < 500000) {
   2913  1.5.2.2  jdolecek 		if (rate < 1000)
   2914  1.5.2.2  jdolecek 			rate = 1000;
   2915  1.5.2.2  jdolecek 		ixgbe_max_interrupt_rate = rate;
   2916  1.5.2.2  jdolecek 		reg |= ((4000000/rate) & 0xff8);
   2917  1.5.2.2  jdolecek 	}
   2918  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(&que->adapter->hw, IXGBE_EITR(que->msix), reg);
   2919      1.1    dyoung 
   2920  1.5.2.2  jdolecek 	return (0);
   2921  1.5.2.2  jdolecek } /* ixgbe_sysctl_interrupt_rate_handler */
   2922      1.1    dyoung 
   2923  1.5.2.2  jdolecek const struct sysctlnode *
   2924  1.5.2.2  jdolecek ixgbe_sysctl_instance(struct adapter *adapter)
   2925      1.1    dyoung {
   2926  1.5.2.2  jdolecek 	const char *dvname;
   2927  1.5.2.2  jdolecek 	struct sysctllog **log;
   2928  1.5.2.2  jdolecek 	int rc;
   2929  1.5.2.2  jdolecek 	const struct sysctlnode *rnode;
   2930      1.1    dyoung 
   2931  1.5.2.2  jdolecek 	if (adapter->sysctltop != NULL)
   2932  1.5.2.2  jdolecek 		return adapter->sysctltop;
   2933      1.1    dyoung 
   2934  1.5.2.2  jdolecek 	log = &adapter->sysctllog;
   2935  1.5.2.2  jdolecek 	dvname = device_xname(adapter->dev);
   2936      1.1    dyoung 
   2937  1.5.2.2  jdolecek 	if ((rc = sysctl_createv(log, 0, NULL, &rnode,
   2938  1.5.2.2  jdolecek 	    0, CTLTYPE_NODE, dvname,
   2939  1.5.2.2  jdolecek 	    SYSCTL_DESCR("ixgbe information and settings"),
   2940  1.5.2.2  jdolecek 	    NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0)
   2941  1.5.2.2  jdolecek 		goto err;
   2942      1.1    dyoung 
   2943  1.5.2.2  jdolecek 	return rnode;
   2944  1.5.2.2  jdolecek err:
   2945  1.5.2.2  jdolecek 	printf("%s: sysctl_createv failed, rc = %d\n", __func__, rc);
   2946  1.5.2.2  jdolecek 	return NULL;
   2947      1.1    dyoung }
   2948      1.1    dyoung 
   2949  1.5.2.2  jdolecek /************************************************************************
   2950  1.5.2.2  jdolecek  * ixgbe_add_device_sysctls
   2951  1.5.2.2  jdolecek  ************************************************************************/
   2952      1.1    dyoung static void
   2953  1.5.2.2  jdolecek ixgbe_add_device_sysctls(struct adapter *adapter)
   2954      1.1    dyoung {
   2955  1.5.2.2  jdolecek 	device_t               dev = adapter->dev;
   2956  1.5.2.2  jdolecek 	struct ixgbe_hw        *hw = &adapter->hw;
   2957  1.5.2.2  jdolecek 	struct sysctllog **log;
   2958  1.5.2.2  jdolecek 	const struct sysctlnode *rnode, *cnode;
   2959      1.1    dyoung 
   2960  1.5.2.2  jdolecek 	log = &adapter->sysctllog;
   2961      1.1    dyoung 
   2962  1.5.2.2  jdolecek 	if ((rnode = ixgbe_sysctl_instance(adapter)) == NULL) {
   2963  1.5.2.2  jdolecek 		aprint_error_dev(dev, "could not create sysctl root\n");
   2964  1.5.2.2  jdolecek 		return;
   2965  1.5.2.2  jdolecek 	}
   2966      1.1    dyoung 
   2967  1.5.2.2  jdolecek 	if (sysctl_createv(log, 0, &rnode, &cnode,
   2968  1.5.2.2  jdolecek 	    CTLFLAG_READONLY, CTLTYPE_INT,
   2969  1.5.2.2  jdolecek 	    "num_rx_desc", SYSCTL_DESCR("Number of rx descriptors"),
   2970  1.5.2.2  jdolecek 	    NULL, 0, &adapter->num_rx_desc, 0, CTL_CREATE, CTL_EOL) != 0)
   2971  1.5.2.2  jdolecek 		aprint_error_dev(dev, "could not create sysctl\n");
   2972      1.1    dyoung 
   2973  1.5.2.2  jdolecek 	if (sysctl_createv(log, 0, &rnode, &cnode,
   2974  1.5.2.2  jdolecek 	    CTLFLAG_READONLY, CTLTYPE_INT,
   2975  1.5.2.2  jdolecek 	    "num_queues", SYSCTL_DESCR("Number of queues"),
   2976  1.5.2.2  jdolecek 	    NULL, 0, &adapter->num_queues, 0, CTL_CREATE, CTL_EOL) != 0)
   2977  1.5.2.2  jdolecek 		aprint_error_dev(dev, "could not create sysctl\n");
   2978      1.1    dyoung 
   2979  1.5.2.2  jdolecek 	/* Sysctls for all devices */
   2980  1.5.2.2  jdolecek 	if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
   2981  1.5.2.2  jdolecek 	    CTLTYPE_INT, "fc", SYSCTL_DESCR(IXGBE_SYSCTL_DESC_SET_FC),
   2982  1.5.2.2  jdolecek 	    ixgbe_sysctl_flowcntl, 0, (void *)adapter, 0, CTL_CREATE,
   2983  1.5.2.2  jdolecek 	    CTL_EOL) != 0)
   2984  1.5.2.2  jdolecek 		aprint_error_dev(dev, "could not create sysctl\n");
   2985      1.1    dyoung 
   2986  1.5.2.2  jdolecek 	adapter->enable_aim = ixgbe_enable_aim;
   2987  1.5.2.2  jdolecek 	if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
   2988  1.5.2.2  jdolecek 	    CTLTYPE_BOOL, "enable_aim", SYSCTL_DESCR("Interrupt Moderation"),
   2989  1.5.2.2  jdolecek 	    NULL, 0, &adapter->enable_aim, 0, CTL_CREATE, CTL_EOL) != 0)
   2990  1.5.2.2  jdolecek 		aprint_error_dev(dev, "could not create sysctl\n");
   2991      1.1    dyoung 
   2992  1.5.2.2  jdolecek 	if (sysctl_createv(log, 0, &rnode, &cnode,
   2993  1.5.2.2  jdolecek 	    CTLFLAG_READWRITE, CTLTYPE_INT,
   2994  1.5.2.2  jdolecek 	    "advertise_speed", SYSCTL_DESCR(IXGBE_SYSCTL_DESC_ADV_SPEED),
   2995  1.5.2.2  jdolecek 	    ixgbe_sysctl_advertise, 0, (void *)adapter, 0, CTL_CREATE,
   2996  1.5.2.2  jdolecek 	    CTL_EOL) != 0)
   2997  1.5.2.2  jdolecek 		aprint_error_dev(dev, "could not create sysctl\n");
   2998  1.5.2.2  jdolecek 
   2999  1.5.2.2  jdolecek #ifdef IXGBE_DEBUG
   3000  1.5.2.2  jdolecek 	/* testing sysctls (for all devices) */
   3001  1.5.2.2  jdolecek 	if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
   3002  1.5.2.2  jdolecek 	    CTLTYPE_INT, "power_state", SYSCTL_DESCR("PCI Power State"),
   3003  1.5.2.2  jdolecek 	    ixgbe_sysctl_power_state, 0, (void *)adapter, 0, CTL_CREATE,
   3004  1.5.2.2  jdolecek 	    CTL_EOL) != 0)
   3005  1.5.2.2  jdolecek 		aprint_error_dev(dev, "could not create sysctl\n");
   3006  1.5.2.2  jdolecek 
   3007  1.5.2.2  jdolecek 	if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READONLY,
   3008  1.5.2.2  jdolecek 	    CTLTYPE_STRING, "print_rss_config",
   3009  1.5.2.2  jdolecek 	    SYSCTL_DESCR("Prints RSS Configuration"),
   3010  1.5.2.2  jdolecek 	    ixgbe_sysctl_print_rss_config, 0, (void *)adapter, 0, CTL_CREATE,
   3011  1.5.2.2  jdolecek 	    CTL_EOL) != 0)
   3012  1.5.2.2  jdolecek 		aprint_error_dev(dev, "could not create sysctl\n");
   3013  1.5.2.2  jdolecek #endif
   3014  1.5.2.2  jdolecek 	/* for X550 series devices */
   3015  1.5.2.2  jdolecek 	if (hw->mac.type >= ixgbe_mac_X550)
   3016  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
   3017  1.5.2.2  jdolecek 		    CTLTYPE_INT, "dmac", SYSCTL_DESCR("DMA Coalesce"),
   3018  1.5.2.2  jdolecek 		    ixgbe_sysctl_dmac, 0, (void *)adapter, 0, CTL_CREATE,
   3019  1.5.2.2  jdolecek 		    CTL_EOL) != 0)
   3020  1.5.2.2  jdolecek 			aprint_error_dev(dev, "could not create sysctl\n");
   3021  1.5.2.2  jdolecek 
   3022  1.5.2.2  jdolecek 	/* for WoL-capable devices */
   3023  1.5.2.2  jdolecek 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
   3024  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
   3025  1.5.2.2  jdolecek 		    CTLTYPE_BOOL, "wol_enable",
   3026  1.5.2.2  jdolecek 		    SYSCTL_DESCR("Enable/Disable Wake on LAN"),
   3027  1.5.2.2  jdolecek 		    ixgbe_sysctl_wol_enable, 0, (void *)adapter, 0, CTL_CREATE,
   3028  1.5.2.2  jdolecek 		    CTL_EOL) != 0)
   3029  1.5.2.2  jdolecek 			aprint_error_dev(dev, "could not create sysctl\n");
   3030  1.5.2.2  jdolecek 
   3031  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
   3032  1.5.2.2  jdolecek 		    CTLTYPE_INT, "wufc",
   3033  1.5.2.2  jdolecek 		    SYSCTL_DESCR("Enable/Disable Wake Up Filters"),
   3034  1.5.2.2  jdolecek 		    ixgbe_sysctl_wufc, 0, (void *)adapter, 0, CTL_CREATE,
   3035  1.5.2.2  jdolecek 		    CTL_EOL) != 0)
   3036  1.5.2.2  jdolecek 			aprint_error_dev(dev, "could not create sysctl\n");
   3037  1.5.2.2  jdolecek 	}
   3038  1.5.2.2  jdolecek 
   3039  1.5.2.2  jdolecek 	/* for X552/X557-AT devices */
   3040  1.5.2.2  jdolecek 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
   3041  1.5.2.2  jdolecek 		const struct sysctlnode *phy_node;
   3042  1.5.2.2  jdolecek 
   3043  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &rnode, &phy_node, 0, CTLTYPE_NODE,
   3044  1.5.2.2  jdolecek 		    "phy", SYSCTL_DESCR("External PHY sysctls"),
   3045  1.5.2.2  jdolecek 		    NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL) != 0) {
   3046  1.5.2.2  jdolecek 			aprint_error_dev(dev, "could not create sysctl\n");
   3047  1.5.2.2  jdolecek 			return;
   3048  1.5.2.2  jdolecek 		}
   3049  1.5.2.2  jdolecek 
   3050  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &phy_node, &cnode, CTLFLAG_READONLY,
   3051  1.5.2.2  jdolecek 		    CTLTYPE_INT, "temp",
   3052  1.5.2.2  jdolecek 		    SYSCTL_DESCR("Current External PHY Temperature (Celsius)"),
   3053  1.5.2.2  jdolecek 		    ixgbe_sysctl_phy_temp, 0, (void *)adapter, 0, CTL_CREATE,
   3054  1.5.2.2  jdolecek 		    CTL_EOL) != 0)
   3055  1.5.2.2  jdolecek 			aprint_error_dev(dev, "could not create sysctl\n");
   3056  1.5.2.2  jdolecek 
   3057  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &phy_node, &cnode, CTLFLAG_READONLY,
   3058  1.5.2.2  jdolecek 		    CTLTYPE_INT, "overtemp_occurred",
   3059  1.5.2.2  jdolecek 		    SYSCTL_DESCR("External PHY High Temperature Event Occurred"),
   3060  1.5.2.2  jdolecek 		    ixgbe_sysctl_phy_overtemp_occurred, 0, (void *)adapter, 0,
   3061  1.5.2.2  jdolecek 		    CTL_CREATE, CTL_EOL) != 0)
   3062  1.5.2.2  jdolecek 			aprint_error_dev(dev, "could not create sysctl\n");
   3063      1.1    dyoung 	}
   3064      1.1    dyoung 
   3065  1.5.2.2  jdolecek 	if (adapter->feat_cap & IXGBE_FEATURE_EEE) {
   3066  1.5.2.2  jdolecek 		if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
   3067  1.5.2.2  jdolecek 		    CTLTYPE_INT, "eee_state",
   3068  1.5.2.2  jdolecek 		    SYSCTL_DESCR("EEE Power Save State"),
   3069  1.5.2.2  jdolecek 		    ixgbe_sysctl_eee_state, 0, (void *)adapter, 0, CTL_CREATE,
   3070  1.5.2.2  jdolecek 		    CTL_EOL) != 0)
   3071  1.5.2.2  jdolecek 			aprint_error_dev(dev, "could not create sysctl\n");
   3072  1.5.2.2  jdolecek 	}
   3073  1.5.2.2  jdolecek } /* ixgbe_add_device_sysctls */
   3074  1.5.2.2  jdolecek 
   3075  1.5.2.2  jdolecek /************************************************************************
   3076  1.5.2.2  jdolecek  * ixgbe_allocate_pci_resources
   3077  1.5.2.2  jdolecek  ************************************************************************/
   3078      1.1    dyoung static int
   3079  1.5.2.2  jdolecek ixgbe_allocate_pci_resources(struct adapter *adapter,
   3080  1.5.2.2  jdolecek     const struct pci_attach_args *pa)
   3081      1.1    dyoung {
   3082  1.5.2.2  jdolecek 	pcireg_t	memtype;
   3083      1.1    dyoung 	device_t dev = adapter->dev;
   3084  1.5.2.2  jdolecek 	bus_addr_t addr;
   3085  1.5.2.2  jdolecek 	int flags;
   3086      1.1    dyoung 
   3087  1.5.2.2  jdolecek 	memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_BAR(0));
   3088  1.5.2.2  jdolecek 	switch (memtype) {
   3089  1.5.2.2  jdolecek 	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
   3090  1.5.2.2  jdolecek 	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
   3091  1.5.2.2  jdolecek 		adapter->osdep.mem_bus_space_tag = pa->pa_memt;
   3092  1.5.2.2  jdolecek 		if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PCI_BAR(0),
   3093  1.5.2.2  jdolecek 	              memtype, &addr, &adapter->osdep.mem_size, &flags) != 0)
   3094  1.5.2.2  jdolecek 			goto map_err;
   3095  1.5.2.2  jdolecek 		if ((flags & BUS_SPACE_MAP_PREFETCHABLE) != 0) {
   3096  1.5.2.2  jdolecek 			aprint_normal_dev(dev, "clearing prefetchable bit\n");
   3097  1.5.2.2  jdolecek 			flags &= ~BUS_SPACE_MAP_PREFETCHABLE;
   3098  1.5.2.2  jdolecek 		}
   3099  1.5.2.2  jdolecek 		if (bus_space_map(adapter->osdep.mem_bus_space_tag, addr,
   3100  1.5.2.2  jdolecek 		     adapter->osdep.mem_size, flags,
   3101  1.5.2.2  jdolecek 		     &adapter->osdep.mem_bus_space_handle) != 0) {
   3102  1.5.2.2  jdolecek map_err:
   3103  1.5.2.2  jdolecek 			adapter->osdep.mem_size = 0;
   3104  1.5.2.2  jdolecek 			aprint_error_dev(dev, "unable to map BAR0\n");
   3105  1.5.2.2  jdolecek 			return ENXIO;
   3106  1.5.2.2  jdolecek 		}
   3107  1.5.2.2  jdolecek 		break;
   3108  1.5.2.2  jdolecek 	default:
   3109  1.5.2.2  jdolecek 		aprint_error_dev(dev, "unexpected type on BAR0\n");
   3110      1.1    dyoung 		return ENXIO;
   3111      1.1    dyoung 	}
   3112      1.1    dyoung 
   3113  1.5.2.2  jdolecek 	return (0);
   3114  1.5.2.2  jdolecek } /* ixgbe_allocate_pci_resources */
   3115      1.1    dyoung 
   3116  1.5.2.2  jdolecek /************************************************************************
   3117  1.5.2.2  jdolecek  * ixgbe_detach - Device removal routine
   3118  1.5.2.2  jdolecek  *
   3119  1.5.2.2  jdolecek  *   Called when the driver is being removed.
   3120  1.5.2.2  jdolecek  *   Stops the adapter and deallocates all the resources
   3121  1.5.2.2  jdolecek  *   that were allocated for driver operation.
   3122  1.5.2.2  jdolecek  *
   3123  1.5.2.2  jdolecek  *   return 0 on success, positive on failure
   3124  1.5.2.2  jdolecek  ************************************************************************/
   3125  1.5.2.2  jdolecek static int
   3126  1.5.2.2  jdolecek ixgbe_detach(device_t dev, int flags)
   3127  1.5.2.2  jdolecek {
   3128  1.5.2.2  jdolecek 	struct adapter *adapter = device_private(dev);
   3129  1.5.2.2  jdolecek 	struct ix_queue *que = adapter->queues;
   3130  1.5.2.2  jdolecek 	struct rx_ring *rxr = adapter->rx_rings;
   3131  1.5.2.2  jdolecek 	struct tx_ring *txr = adapter->tx_rings;
   3132  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   3133  1.5.2.2  jdolecek 	struct ixgbe_hw_stats *stats = &adapter->stats.pf;
   3134  1.5.2.2  jdolecek 	u32	ctrl_ext;
   3135  1.5.2.2  jdolecek 
   3136  1.5.2.2  jdolecek 	INIT_DEBUGOUT("ixgbe_detach: begin");
   3137  1.5.2.2  jdolecek 	if (adapter->osdep.attached == false)
   3138  1.5.2.2  jdolecek 		return 0;
   3139  1.5.2.2  jdolecek 
   3140  1.5.2.2  jdolecek 	if (ixgbe_pci_iov_detach(dev) != 0) {
   3141  1.5.2.2  jdolecek 		device_printf(dev, "SR-IOV in use; detach first.\n");
   3142  1.5.2.2  jdolecek 		return (EBUSY);
   3143      1.1    dyoung 	}
   3144      1.1    dyoung 
   3145  1.5.2.2  jdolecek 	/* Stop the interface. Callouts are stopped in it. */
   3146  1.5.2.2  jdolecek 	ixgbe_ifstop(adapter->ifp, 1);
   3147  1.5.2.2  jdolecek #if NVLAN > 0
   3148  1.5.2.2  jdolecek 	/* Make sure VLANs are not using driver */
   3149  1.5.2.2  jdolecek 	if (!VLAN_ATTACHED(&adapter->osdep.ec))
   3150  1.5.2.2  jdolecek 		;	/* nothing to do: no VLANs */
   3151  1.5.2.2  jdolecek 	else if ((flags & (DETACH_SHUTDOWN|DETACH_FORCE)) != 0)
   3152  1.5.2.2  jdolecek 		vlan_ifdetach(adapter->ifp);
   3153  1.5.2.2  jdolecek 	else {
   3154  1.5.2.2  jdolecek 		aprint_error_dev(dev, "VLANs in use, detach first\n");
   3155  1.5.2.2  jdolecek 		return (EBUSY);
   3156  1.5.2.2  jdolecek 	}
   3157      1.1    dyoung #endif
   3158  1.5.2.2  jdolecek 
   3159  1.5.2.2  jdolecek 	pmf_device_deregister(dev);
   3160  1.5.2.2  jdolecek 
   3161  1.5.2.2  jdolecek 	ether_ifdetach(adapter->ifp);
   3162  1.5.2.2  jdolecek 	/* Stop the adapter */
   3163  1.5.2.2  jdolecek 	IXGBE_CORE_LOCK(adapter);
   3164  1.5.2.2  jdolecek 	ixgbe_setup_low_power_mode(adapter);
   3165  1.5.2.2  jdolecek 	IXGBE_CORE_UNLOCK(adapter);
   3166  1.5.2.2  jdolecek 
   3167  1.5.2.2  jdolecek 	for (int i = 0; i < adapter->num_queues; i++, que++, txr++) {
   3168  1.5.2.2  jdolecek 		if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX))
   3169  1.5.2.2  jdolecek 			softint_disestablish(txr->txr_si);
   3170  1.5.2.2  jdolecek 		softint_disestablish(que->que_si);
   3171      1.1    dyoung 	}
   3172      1.1    dyoung 
   3173  1.5.2.2  jdolecek 	/* Drain the Link queue */
   3174  1.5.2.2  jdolecek 	softint_disestablish(adapter->link_si);
   3175  1.5.2.2  jdolecek 	softint_disestablish(adapter->mod_si);
   3176  1.5.2.2  jdolecek 	softint_disestablish(adapter->msf_si);
   3177  1.5.2.2  jdolecek 	if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
   3178  1.5.2.2  jdolecek 		softint_disestablish(adapter->mbx_si);
   3179  1.5.2.2  jdolecek 	softint_disestablish(adapter->phy_si);
   3180  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_FDIR)
   3181  1.5.2.2  jdolecek 		softint_disestablish(adapter->fdir_si);
   3182      1.1    dyoung 
   3183  1.5.2.2  jdolecek 	/* let hardware know driver is unloading */
   3184  1.5.2.2  jdolecek 	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
   3185  1.5.2.2  jdolecek 	ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
   3186  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
   3187      1.1    dyoung 
   3188  1.5.2.2  jdolecek 	callout_halt(&adapter->timer, NULL);
   3189      1.1    dyoung 
   3190  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_NETMAP)
   3191  1.5.2.2  jdolecek 		netmap_detach(adapter->ifp);
   3192  1.5.2.2  jdolecek 
   3193  1.5.2.2  jdolecek 	ixgbe_free_pci_resources(adapter);
   3194  1.5.2.2  jdolecek #if 0	/* XXX the NetBSD port is probably missing something here */
   3195  1.5.2.2  jdolecek 	bus_generic_detach(dev);
   3196      1.1    dyoung #endif
   3197  1.5.2.2  jdolecek 	if_detach(adapter->ifp);
   3198  1.5.2.2  jdolecek 	if_percpuq_destroy(adapter->ipq);
   3199      1.1    dyoung 
   3200  1.5.2.2  jdolecek 	sysctl_teardown(&adapter->sysctllog);
   3201  1.5.2.2  jdolecek 	evcnt_detach(&adapter->handleq);
   3202  1.5.2.2  jdolecek 	evcnt_detach(&adapter->req);
   3203  1.5.2.2  jdolecek 	evcnt_detach(&adapter->efbig_tx_dma_setup);
   3204  1.5.2.2  jdolecek 	evcnt_detach(&adapter->mbuf_defrag_failed);
   3205  1.5.2.2  jdolecek 	evcnt_detach(&adapter->efbig2_tx_dma_setup);
   3206  1.5.2.2  jdolecek 	evcnt_detach(&adapter->einval_tx_dma_setup);
   3207  1.5.2.2  jdolecek 	evcnt_detach(&adapter->other_tx_dma_setup);
   3208  1.5.2.2  jdolecek 	evcnt_detach(&adapter->eagain_tx_dma_setup);
   3209  1.5.2.2  jdolecek 	evcnt_detach(&adapter->enomem_tx_dma_setup);
   3210  1.5.2.2  jdolecek 	evcnt_detach(&adapter->watchdog_events);
   3211  1.5.2.2  jdolecek 	evcnt_detach(&adapter->tso_err);
   3212  1.5.2.2  jdolecek 	evcnt_detach(&adapter->link_irq);
   3213  1.5.2.2  jdolecek 
   3214  1.5.2.2  jdolecek 	txr = adapter->tx_rings;
   3215  1.5.2.2  jdolecek 	for (int i = 0; i < adapter->num_queues; i++, rxr++, txr++) {
   3216  1.5.2.2  jdolecek 		evcnt_detach(&adapter->queues[i].irqs);
   3217  1.5.2.2  jdolecek 		evcnt_detach(&txr->no_desc_avail);
   3218  1.5.2.2  jdolecek 		evcnt_detach(&txr->total_packets);
   3219  1.5.2.2  jdolecek 		evcnt_detach(&txr->tso_tx);
   3220  1.5.2.2  jdolecek #ifndef IXGBE_LEGACY_TX
   3221  1.5.2.2  jdolecek 		evcnt_detach(&txr->pcq_drops);
   3222  1.5.2.2  jdolecek #endif
   3223  1.5.2.2  jdolecek 
   3224  1.5.2.2  jdolecek 		if (i < __arraycount(stats->mpc)) {
   3225  1.5.2.2  jdolecek 			evcnt_detach(&stats->mpc[i]);
   3226  1.5.2.2  jdolecek 			if (hw->mac.type == ixgbe_mac_82598EB)
   3227  1.5.2.2  jdolecek 				evcnt_detach(&stats->rnbc[i]);
   3228  1.5.2.2  jdolecek 		}
   3229  1.5.2.2  jdolecek 		if (i < __arraycount(stats->pxontxc)) {
   3230  1.5.2.2  jdolecek 			evcnt_detach(&stats->pxontxc[i]);
   3231  1.5.2.2  jdolecek 			evcnt_detach(&stats->pxonrxc[i]);
   3232  1.5.2.2  jdolecek 			evcnt_detach(&stats->pxofftxc[i]);
   3233  1.5.2.2  jdolecek 			evcnt_detach(&stats->pxoffrxc[i]);
   3234  1.5.2.2  jdolecek 			evcnt_detach(&stats->pxon2offc[i]);
   3235  1.5.2.2  jdolecek 		}
   3236  1.5.2.2  jdolecek 		if (i < __arraycount(stats->qprc)) {
   3237  1.5.2.2  jdolecek 			evcnt_detach(&stats->qprc[i]);
   3238  1.5.2.2  jdolecek 			evcnt_detach(&stats->qptc[i]);
   3239  1.5.2.2  jdolecek 			evcnt_detach(&stats->qbrc[i]);
   3240  1.5.2.2  jdolecek 			evcnt_detach(&stats->qbtc[i]);
   3241  1.5.2.2  jdolecek 			evcnt_detach(&stats->qprdc[i]);
   3242      1.1    dyoung 		}
   3243      1.1    dyoung 
   3244  1.5.2.2  jdolecek 		evcnt_detach(&rxr->rx_packets);
   3245  1.5.2.2  jdolecek 		evcnt_detach(&rxr->rx_bytes);
   3246  1.5.2.2  jdolecek 		evcnt_detach(&rxr->rx_copies);
   3247  1.5.2.2  jdolecek 		evcnt_detach(&rxr->no_jmbuf);
   3248  1.5.2.2  jdolecek 		evcnt_detach(&rxr->rx_discarded);
   3249      1.1    dyoung 	}
   3250  1.5.2.2  jdolecek 	evcnt_detach(&stats->ipcs);
   3251  1.5.2.2  jdolecek 	evcnt_detach(&stats->l4cs);
   3252  1.5.2.2  jdolecek 	evcnt_detach(&stats->ipcs_bad);
   3253  1.5.2.2  jdolecek 	evcnt_detach(&stats->l4cs_bad);
   3254  1.5.2.2  jdolecek 	evcnt_detach(&stats->intzero);
   3255  1.5.2.2  jdolecek 	evcnt_detach(&stats->legint);
   3256  1.5.2.2  jdolecek 	evcnt_detach(&stats->crcerrs);
   3257  1.5.2.2  jdolecek 	evcnt_detach(&stats->illerrc);
   3258  1.5.2.2  jdolecek 	evcnt_detach(&stats->errbc);
   3259  1.5.2.2  jdolecek 	evcnt_detach(&stats->mspdc);
   3260  1.5.2.2  jdolecek 	if (hw->mac.type >= ixgbe_mac_X550)
   3261  1.5.2.2  jdolecek 		evcnt_detach(&stats->mbsdc);
   3262  1.5.2.2  jdolecek 	evcnt_detach(&stats->mpctotal);
   3263  1.5.2.2  jdolecek 	evcnt_detach(&stats->mlfc);
   3264  1.5.2.2  jdolecek 	evcnt_detach(&stats->mrfc);
   3265  1.5.2.2  jdolecek 	evcnt_detach(&stats->rlec);
   3266  1.5.2.2  jdolecek 	evcnt_detach(&stats->lxontxc);
   3267  1.5.2.2  jdolecek 	evcnt_detach(&stats->lxonrxc);
   3268  1.5.2.2  jdolecek 	evcnt_detach(&stats->lxofftxc);
   3269  1.5.2.2  jdolecek 	evcnt_detach(&stats->lxoffrxc);
   3270  1.5.2.2  jdolecek 
   3271  1.5.2.2  jdolecek 	/* Packet Reception Stats */
   3272  1.5.2.2  jdolecek 	evcnt_detach(&stats->tor);
   3273  1.5.2.2  jdolecek 	evcnt_detach(&stats->gorc);
   3274  1.5.2.2  jdolecek 	evcnt_detach(&stats->tpr);
   3275  1.5.2.2  jdolecek 	evcnt_detach(&stats->gprc);
   3276  1.5.2.2  jdolecek 	evcnt_detach(&stats->mprc);
   3277  1.5.2.2  jdolecek 	evcnt_detach(&stats->bprc);
   3278  1.5.2.2  jdolecek 	evcnt_detach(&stats->prc64);
   3279  1.5.2.2  jdolecek 	evcnt_detach(&stats->prc127);
   3280  1.5.2.2  jdolecek 	evcnt_detach(&stats->prc255);
   3281  1.5.2.2  jdolecek 	evcnt_detach(&stats->prc511);
   3282  1.5.2.2  jdolecek 	evcnt_detach(&stats->prc1023);
   3283  1.5.2.2  jdolecek 	evcnt_detach(&stats->prc1522);
   3284  1.5.2.2  jdolecek 	evcnt_detach(&stats->ruc);
   3285  1.5.2.2  jdolecek 	evcnt_detach(&stats->rfc);
   3286  1.5.2.2  jdolecek 	evcnt_detach(&stats->roc);
   3287  1.5.2.2  jdolecek 	evcnt_detach(&stats->rjc);
   3288  1.5.2.2  jdolecek 	evcnt_detach(&stats->mngprc);
   3289  1.5.2.2  jdolecek 	evcnt_detach(&stats->mngpdc);
   3290  1.5.2.2  jdolecek 	evcnt_detach(&stats->xec);
   3291  1.5.2.2  jdolecek 
   3292  1.5.2.2  jdolecek 	/* Packet Transmission Stats */
   3293  1.5.2.2  jdolecek 	evcnt_detach(&stats->gotc);
   3294  1.5.2.2  jdolecek 	evcnt_detach(&stats->tpt);
   3295  1.5.2.2  jdolecek 	evcnt_detach(&stats->gptc);
   3296  1.5.2.2  jdolecek 	evcnt_detach(&stats->bptc);
   3297  1.5.2.2  jdolecek 	evcnt_detach(&stats->mptc);
   3298  1.5.2.2  jdolecek 	evcnt_detach(&stats->mngptc);
   3299  1.5.2.2  jdolecek 	evcnt_detach(&stats->ptc64);
   3300  1.5.2.2  jdolecek 	evcnt_detach(&stats->ptc127);
   3301  1.5.2.2  jdolecek 	evcnt_detach(&stats->ptc255);
   3302  1.5.2.2  jdolecek 	evcnt_detach(&stats->ptc511);
   3303  1.5.2.2  jdolecek 	evcnt_detach(&stats->ptc1023);
   3304  1.5.2.2  jdolecek 	evcnt_detach(&stats->ptc1522);
   3305  1.5.2.2  jdolecek 
   3306  1.5.2.2  jdolecek 	ixgbe_free_transmit_structures(adapter);
   3307  1.5.2.2  jdolecek 	ixgbe_free_receive_structures(adapter);
   3308  1.5.2.2  jdolecek 	free(adapter->queues, M_DEVBUF);
   3309  1.5.2.2  jdolecek 	free(adapter->mta, M_DEVBUF);
   3310  1.5.2.2  jdolecek 
   3311  1.5.2.2  jdolecek 	IXGBE_CORE_LOCK_DESTROY(adapter);
   3312      1.1    dyoung 
   3313      1.1    dyoung 	return (0);
   3314  1.5.2.2  jdolecek } /* ixgbe_detach */
   3315      1.1    dyoung 
   3316  1.5.2.2  jdolecek /************************************************************************
   3317  1.5.2.2  jdolecek  * ixgbe_setup_low_power_mode - LPLU/WoL preparation
   3318  1.5.2.2  jdolecek  *
   3319  1.5.2.2  jdolecek  *   Prepare the adapter/port for LPLU and/or WoL
   3320  1.5.2.2  jdolecek  ************************************************************************/
   3321      1.1    dyoung static int
   3322  1.5.2.2  jdolecek ixgbe_setup_low_power_mode(struct adapter *adapter)
   3323      1.1    dyoung {
   3324  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   3325  1.5.2.2  jdolecek 	device_t        dev = adapter->dev;
   3326  1.5.2.2  jdolecek 	s32             error = 0;
   3327      1.1    dyoung 
   3328  1.5.2.2  jdolecek 	KASSERT(mutex_owned(&adapter->core_mtx));
   3329      1.1    dyoung 
   3330  1.5.2.2  jdolecek 	/* Limit power management flow to X550EM baseT */
   3331  1.5.2.2  jdolecek 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T &&
   3332  1.5.2.2  jdolecek 	    hw->phy.ops.enter_lplu) {
   3333  1.5.2.2  jdolecek 		/* X550EM baseT adapters need a special LPLU flow */
   3334  1.5.2.2  jdolecek 		hw->phy.reset_disable = true;
   3335  1.5.2.2  jdolecek 		ixgbe_stop(adapter);
   3336  1.5.2.2  jdolecek 		error = hw->phy.ops.enter_lplu(hw);
   3337  1.5.2.2  jdolecek 		if (error)
   3338  1.5.2.2  jdolecek 			device_printf(dev,
   3339  1.5.2.2  jdolecek 			    "Error entering LPLU: %d\n", error);
   3340  1.5.2.2  jdolecek 		hw->phy.reset_disable = false;
   3341  1.5.2.2  jdolecek 	} else {
   3342  1.5.2.2  jdolecek 		/* Just stop for other adapters */
   3343  1.5.2.2  jdolecek 		ixgbe_stop(adapter);
   3344      1.1    dyoung 	}
   3345      1.1    dyoung 
   3346  1.5.2.2  jdolecek 	if (!hw->wol_enabled) {
   3347  1.5.2.2  jdolecek 		ixgbe_set_phy_power(hw, FALSE);
   3348  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0);
   3349  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_WUC, 0);
   3350  1.5.2.2  jdolecek 	} else {
   3351  1.5.2.2  jdolecek 		/* Turn off support for APM wakeup. (Using ACPI instead) */
   3352  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_GRC,
   3353  1.5.2.2  jdolecek 		    IXGBE_READ_REG(hw, IXGBE_GRC) & ~(u32)2);
   3354      1.1    dyoung 
   3355  1.5.2.2  jdolecek 		/*
   3356  1.5.2.2  jdolecek 		 * Clear Wake Up Status register to prevent any previous wakeup
   3357  1.5.2.2  jdolecek 		 * events from waking us up immediately after we suspend.
   3358  1.5.2.2  jdolecek 		 */
   3359  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
   3360      1.1    dyoung 
   3361  1.5.2.2  jdolecek 		/*
   3362  1.5.2.2  jdolecek 		 * Program the Wakeup Filter Control register with user filter
   3363  1.5.2.2  jdolecek 		 * settings
   3364  1.5.2.2  jdolecek 		 */
   3365  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_WUFC, adapter->wufc);
   3366  1.5.2.2  jdolecek 
   3367  1.5.2.2  jdolecek 		/* Enable wakeups and power management in Wakeup Control */
   3368  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_WUC,
   3369  1.5.2.2  jdolecek 		    IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN);
   3370      1.1    dyoung 
   3371      1.1    dyoung 	}
   3372      1.1    dyoung 
   3373  1.5.2.2  jdolecek 	return error;
   3374  1.5.2.2  jdolecek } /* ixgbe_setup_low_power_mode */
   3375      1.1    dyoung 
   3376  1.5.2.2  jdolecek /************************************************************************
   3377  1.5.2.2  jdolecek  * ixgbe_shutdown - Shutdown entry point
   3378  1.5.2.2  jdolecek  ************************************************************************/
   3379  1.5.2.2  jdolecek #if 0 /* XXX NetBSD ought to register something like this through pmf(9) */
   3380      1.1    dyoung static int
   3381  1.5.2.2  jdolecek ixgbe_shutdown(device_t dev)
   3382      1.1    dyoung {
   3383  1.5.2.2  jdolecek 	struct adapter *adapter = device_private(dev);
   3384  1.5.2.2  jdolecek 	int error = 0;
   3385      1.1    dyoung 
   3386  1.5.2.2  jdolecek 	INIT_DEBUGOUT("ixgbe_shutdown: begin");
   3387      1.1    dyoung 
   3388  1.5.2.2  jdolecek 	IXGBE_CORE_LOCK(adapter);
   3389  1.5.2.2  jdolecek 	error = ixgbe_setup_low_power_mode(adapter);
   3390  1.5.2.2  jdolecek 	IXGBE_CORE_UNLOCK(adapter);
   3391      1.1    dyoung 
   3392  1.5.2.2  jdolecek 	return (error);
   3393  1.5.2.2  jdolecek } /* ixgbe_shutdown */
   3394  1.5.2.2  jdolecek #endif
   3395      1.1    dyoung 
   3396  1.5.2.2  jdolecek /************************************************************************
   3397  1.5.2.2  jdolecek  * ixgbe_suspend
   3398  1.5.2.2  jdolecek  *
   3399  1.5.2.2  jdolecek  *   From D0 to D3
   3400  1.5.2.2  jdolecek  ************************************************************************/
   3401  1.5.2.2  jdolecek static bool
   3402  1.5.2.2  jdolecek ixgbe_suspend(device_t dev, const pmf_qual_t *qual)
   3403      1.1    dyoung {
   3404  1.5.2.2  jdolecek 	struct adapter *adapter = device_private(dev);
   3405  1.5.2.2  jdolecek 	int            error = 0;
   3406      1.1    dyoung 
   3407  1.5.2.2  jdolecek 	INIT_DEBUGOUT("ixgbe_suspend: begin");
   3408      1.1    dyoung 
   3409  1.5.2.2  jdolecek 	IXGBE_CORE_LOCK(adapter);
   3410      1.1    dyoung 
   3411  1.5.2.2  jdolecek 	error = ixgbe_setup_low_power_mode(adapter);
   3412      1.1    dyoung 
   3413  1.5.2.2  jdolecek 	IXGBE_CORE_UNLOCK(adapter);
   3414  1.5.2.2  jdolecek 
   3415  1.5.2.2  jdolecek 	return (error);
   3416  1.5.2.2  jdolecek } /* ixgbe_suspend */
   3417      1.1    dyoung 
   3418  1.5.2.2  jdolecek /************************************************************************
   3419  1.5.2.2  jdolecek  * ixgbe_resume
   3420  1.5.2.2  jdolecek  *
   3421  1.5.2.2  jdolecek  *   From D3 to D0
   3422  1.5.2.2  jdolecek  ************************************************************************/
   3423  1.5.2.2  jdolecek static bool
   3424  1.5.2.2  jdolecek ixgbe_resume(device_t dev, const pmf_qual_t *qual)
   3425  1.5.2.2  jdolecek {
   3426  1.5.2.2  jdolecek 	struct adapter  *adapter = device_private(dev);
   3427  1.5.2.2  jdolecek 	struct ifnet    *ifp = adapter->ifp;
   3428  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   3429  1.5.2.2  jdolecek 	u32             wus;
   3430      1.1    dyoung 
   3431  1.5.2.2  jdolecek 	INIT_DEBUGOUT("ixgbe_resume: begin");
   3432      1.1    dyoung 
   3433  1.5.2.2  jdolecek 	IXGBE_CORE_LOCK(adapter);
   3434      1.1    dyoung 
   3435  1.5.2.2  jdolecek 	/* Read & clear WUS register */
   3436  1.5.2.2  jdolecek 	wus = IXGBE_READ_REG(hw, IXGBE_WUS);
   3437  1.5.2.2  jdolecek 	if (wus)
   3438  1.5.2.2  jdolecek 		device_printf(dev, "Woken up by (WUS): %#010x\n",
   3439  1.5.2.2  jdolecek 		    IXGBE_READ_REG(hw, IXGBE_WUS));
   3440  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
   3441  1.5.2.2  jdolecek 	/* And clear WUFC until next low-power transition */
   3442  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0);
   3443  1.5.2.2  jdolecek 
   3444  1.5.2.2  jdolecek 	/*
   3445  1.5.2.2  jdolecek 	 * Required after D3->D0 transition;
   3446  1.5.2.2  jdolecek 	 * will re-advertise all previous advertised speeds
   3447  1.5.2.2  jdolecek 	 */
   3448  1.5.2.2  jdolecek 	if (ifp->if_flags & IFF_UP)
   3449  1.5.2.2  jdolecek 		ixgbe_init_locked(adapter);
   3450  1.5.2.2  jdolecek 
   3451  1.5.2.2  jdolecek 	IXGBE_CORE_UNLOCK(adapter);
   3452  1.5.2.2  jdolecek 
   3453  1.5.2.2  jdolecek 	return true;
   3454  1.5.2.2  jdolecek } /* ixgbe_resume */
   3455  1.5.2.2  jdolecek 
   3456  1.5.2.2  jdolecek /*
   3457  1.5.2.2  jdolecek  * Set the various hardware offload abilities.
   3458  1.5.2.2  jdolecek  *
   3459  1.5.2.2  jdolecek  * This takes the ifnet's if_capenable flags (e.g. set by the user using
   3460  1.5.2.2  jdolecek  * ifconfig) and indicates to the OS via the ifnet's if_hwassist field what
   3461  1.5.2.2  jdolecek  * mbuf offload flags the driver will understand.
   3462  1.5.2.2  jdolecek  */
   3463  1.5.2.2  jdolecek static void
   3464  1.5.2.2  jdolecek ixgbe_set_if_hwassist(struct adapter *adapter)
   3465  1.5.2.2  jdolecek {
   3466  1.5.2.2  jdolecek 	/* XXX */
   3467      1.1    dyoung }
   3468      1.1    dyoung 
   3469  1.5.2.2  jdolecek /************************************************************************
   3470  1.5.2.2  jdolecek  * ixgbe_init_locked - Init entry point
   3471      1.1    dyoung  *
   3472  1.5.2.2  jdolecek  *   Used in two ways: It is used by the stack as an init
   3473  1.5.2.2  jdolecek  *   entry point in network interface structure. It is also
   3474  1.5.2.2  jdolecek  *   used by the driver as a hw/sw initialization routine to
   3475  1.5.2.2  jdolecek  *   get to a consistent state.
   3476      1.1    dyoung  *
   3477  1.5.2.2  jdolecek  *   return 0 on success, positive on failure
   3478  1.5.2.2  jdolecek  ************************************************************************/
   3479  1.5.2.2  jdolecek static void
   3480  1.5.2.2  jdolecek ixgbe_init_locked(struct adapter *adapter)
   3481      1.1    dyoung {
   3482  1.5.2.2  jdolecek 	struct ifnet   *ifp = adapter->ifp;
   3483  1.5.2.2  jdolecek 	device_t 	dev = adapter->dev;
   3484      1.1    dyoung 	struct ixgbe_hw *hw = &adapter->hw;
   3485  1.5.2.2  jdolecek 	struct tx_ring  *txr;
   3486  1.5.2.2  jdolecek 	struct rx_ring  *rxr;
   3487  1.5.2.2  jdolecek 	u32		txdctl, mhadd;
   3488  1.5.2.2  jdolecek 	u32		rxdctl, rxctrl;
   3489  1.5.2.2  jdolecek 	u32             ctrl_ext;
   3490  1.5.2.2  jdolecek 	int             err = 0;
   3491      1.1    dyoung 
   3492  1.5.2.2  jdolecek 	/* XXX check IFF_UP and IFF_RUNNING, power-saving state! */
   3493      1.1    dyoung 
   3494  1.5.2.2  jdolecek 	KASSERT(mutex_owned(&adapter->core_mtx));
   3495  1.5.2.2  jdolecek 	INIT_DEBUGOUT("ixgbe_init_locked: begin");
   3496      1.1    dyoung 
   3497  1.5.2.2  jdolecek 	hw->adapter_stopped = FALSE;
   3498  1.5.2.2  jdolecek 	ixgbe_stop_adapter(hw);
   3499  1.5.2.2  jdolecek         callout_stop(&adapter->timer);
   3500      1.1    dyoung 
   3501  1.5.2.2  jdolecek 	/* XXX I moved this here from the SIOCSIFMTU case in ixgbe_ioctl(). */
   3502      1.1    dyoung 	adapter->max_frame_size =
   3503  1.5.2.2  jdolecek 		ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
   3504      1.1    dyoung 
   3505  1.5.2.2  jdolecek 	/* Queue indices may change with IOV mode */
   3506  1.5.2.2  jdolecek 	ixgbe_align_all_queue_indices(adapter);
   3507      1.1    dyoung 
   3508  1.5.2.2  jdolecek 	/* reprogram the RAR[0] in case user changed it. */
   3509  1.5.2.2  jdolecek 	ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, IXGBE_RAH_AV);
   3510      1.1    dyoung 
   3511  1.5.2.2  jdolecek 	/* Get the latest mac address, User can use a LAA */
   3512  1.5.2.2  jdolecek 	memcpy(hw->mac.addr, CLLADDR(ifp->if_sadl),
   3513  1.5.2.2  jdolecek 	    IXGBE_ETH_LENGTH_OF_ADDRESS);
   3514  1.5.2.2  jdolecek 	ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1);
   3515  1.5.2.2  jdolecek 	hw->addr_ctrl.rar_used_count = 1;
   3516  1.5.2.2  jdolecek 
   3517  1.5.2.2  jdolecek 	/* Set hardware offload abilities from ifnet flags */
   3518  1.5.2.2  jdolecek 	ixgbe_set_if_hwassist(adapter);
   3519  1.5.2.2  jdolecek 
   3520  1.5.2.2  jdolecek 	/* Prepare transmit descriptors and buffers */
   3521  1.5.2.2  jdolecek 	if (ixgbe_setup_transmit_structures(adapter)) {
   3522  1.5.2.2  jdolecek 		device_printf(dev, "Could not setup transmit structures\n");
   3523  1.5.2.2  jdolecek 		ixgbe_stop(adapter);
   3524  1.5.2.2  jdolecek 		return;
   3525  1.5.2.2  jdolecek 	}
   3526  1.5.2.2  jdolecek 
   3527  1.5.2.2  jdolecek 	ixgbe_init_hw(hw);
   3528  1.5.2.2  jdolecek 	ixgbe_initialize_iov(adapter);
   3529  1.5.2.2  jdolecek 	ixgbe_initialize_transmit_units(adapter);
   3530  1.5.2.2  jdolecek 
   3531  1.5.2.2  jdolecek 	/* Setup Multicast table */
   3532  1.5.2.2  jdolecek 	ixgbe_set_multi(adapter);
   3533  1.5.2.2  jdolecek 
   3534  1.5.2.2  jdolecek 	/* Determine the correct mbuf pool, based on frame size */
   3535  1.5.2.2  jdolecek 	if (adapter->max_frame_size <= MCLBYTES)
   3536  1.5.2.2  jdolecek 		adapter->rx_mbuf_sz = MCLBYTES;
   3537  1.5.2.2  jdolecek 	else
   3538  1.5.2.2  jdolecek 		adapter->rx_mbuf_sz = MJUMPAGESIZE;
   3539  1.5.2.2  jdolecek 
   3540  1.5.2.2  jdolecek 	/* Prepare receive descriptors and buffers */
   3541  1.5.2.2  jdolecek 	if (ixgbe_setup_receive_structures(adapter)) {
   3542  1.5.2.2  jdolecek 		device_printf(dev, "Could not setup receive structures\n");
   3543  1.5.2.2  jdolecek 		ixgbe_stop(adapter);
   3544  1.5.2.2  jdolecek 		return;
   3545  1.5.2.2  jdolecek 	}
   3546  1.5.2.2  jdolecek 
   3547  1.5.2.2  jdolecek 	/* Configure RX settings */
   3548  1.5.2.2  jdolecek 	ixgbe_initialize_receive_units(adapter);
   3549  1.5.2.2  jdolecek 
   3550  1.5.2.2  jdolecek 	/* Enable SDP & MSI-X interrupts based on adapter */
   3551  1.5.2.2  jdolecek 	ixgbe_config_gpie(adapter);
   3552  1.5.2.2  jdolecek 
   3553  1.5.2.2  jdolecek 	/* Set MTU size */
   3554  1.5.2.2  jdolecek 	if (ifp->if_mtu > ETHERMTU) {
   3555  1.5.2.2  jdolecek 		/* aka IXGBE_MAXFRS on 82599 and newer */
   3556  1.5.2.2  jdolecek 		mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
   3557  1.5.2.2  jdolecek 		mhadd &= ~IXGBE_MHADD_MFS_MASK;
   3558  1.5.2.2  jdolecek 		mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
   3559  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
   3560  1.5.2.2  jdolecek 	}
   3561  1.5.2.2  jdolecek 
   3562  1.5.2.2  jdolecek 	/* Now enable all the queues */
   3563  1.5.2.2  jdolecek 	for (int i = 0; i < adapter->num_queues; i++) {
   3564  1.5.2.2  jdolecek 		txr = &adapter->tx_rings[i];
   3565  1.5.2.2  jdolecek 		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me));
   3566  1.5.2.2  jdolecek 		txdctl |= IXGBE_TXDCTL_ENABLE;
   3567  1.5.2.2  jdolecek 		/* Set WTHRESH to 8, burst writeback */
   3568  1.5.2.2  jdolecek 		txdctl |= (8 << 16);
   3569  1.5.2.2  jdolecek 		/*
   3570  1.5.2.2  jdolecek 		 * When the internal queue falls below PTHRESH (32),
   3571  1.5.2.2  jdolecek 		 * start prefetching as long as there are at least
   3572  1.5.2.2  jdolecek 		 * HTHRESH (1) buffers ready. The values are taken
   3573  1.5.2.2  jdolecek 		 * from the Intel linux driver 3.8.21.
   3574  1.5.2.2  jdolecek 		 * Prefetching enables tx line rate even with 1 queue.
   3575  1.5.2.2  jdolecek 		 */
   3576  1.5.2.2  jdolecek 		txdctl |= (32 << 0) | (1 << 8);
   3577  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl);
   3578  1.5.2.2  jdolecek 	}
   3579  1.5.2.2  jdolecek 
   3580  1.5.2.2  jdolecek 	for (int i = 0, j = 0; i < adapter->num_queues; i++) {
   3581  1.5.2.2  jdolecek 		rxr = &adapter->rx_rings[i];
   3582  1.5.2.2  jdolecek 		rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
   3583  1.5.2.2  jdolecek 		if (hw->mac.type == ixgbe_mac_82598EB) {
   3584  1.5.2.2  jdolecek 			/*
   3585  1.5.2.2  jdolecek 			 * PTHRESH = 21
   3586  1.5.2.2  jdolecek 			 * HTHRESH = 4
   3587  1.5.2.2  jdolecek 			 * WTHRESH = 8
   3588  1.5.2.2  jdolecek 			 */
   3589  1.5.2.2  jdolecek 			rxdctl &= ~0x3FFFFF;
   3590  1.5.2.2  jdolecek 			rxdctl |= 0x080420;
   3591  1.5.2.2  jdolecek 		}
   3592  1.5.2.2  jdolecek 		rxdctl |= IXGBE_RXDCTL_ENABLE;
   3593  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), rxdctl);
   3594  1.5.2.2  jdolecek 		for (; j < 10; j++) {
   3595  1.5.2.2  jdolecek 			if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)) &
   3596  1.5.2.2  jdolecek 			    IXGBE_RXDCTL_ENABLE)
   3597  1.5.2.2  jdolecek 				break;
   3598  1.5.2.2  jdolecek 			else
   3599  1.5.2.2  jdolecek 				msec_delay(1);
   3600  1.5.2.2  jdolecek 		}
   3601  1.5.2.2  jdolecek 		wmb();
   3602  1.5.2.2  jdolecek 
   3603  1.5.2.2  jdolecek 		/*
   3604  1.5.2.2  jdolecek 		 * In netmap mode, we must preserve the buffers made
   3605  1.5.2.2  jdolecek 		 * available to userspace before the if_init()
   3606  1.5.2.2  jdolecek 		 * (this is true by default on the TX side, because
   3607  1.5.2.2  jdolecek 		 * init makes all buffers available to userspace).
   3608  1.5.2.2  jdolecek 		 *
   3609  1.5.2.2  jdolecek 		 * netmap_reset() and the device specific routines
   3610  1.5.2.2  jdolecek 		 * (e.g. ixgbe_setup_receive_rings()) map these
   3611  1.5.2.2  jdolecek 		 * buffers at the end of the NIC ring, so here we
   3612  1.5.2.2  jdolecek 		 * must set the RDT (tail) register to make sure
   3613  1.5.2.2  jdolecek 		 * they are not overwritten.
   3614  1.5.2.2  jdolecek 		 *
   3615  1.5.2.2  jdolecek 		 * In this driver the NIC ring starts at RDH = 0,
   3616  1.5.2.2  jdolecek 		 * RDT points to the last slot available for reception (?),
   3617  1.5.2.2  jdolecek 		 * so RDT = num_rx_desc - 1 means the whole ring is available.
   3618  1.5.2.2  jdolecek 		 */
   3619  1.5.2.2  jdolecek #ifdef DEV_NETMAP
   3620  1.5.2.2  jdolecek 		if ((adapter->feat_en & IXGBE_FEATURE_NETMAP) &&
   3621  1.5.2.2  jdolecek 		    (ifp->if_capenable & IFCAP_NETMAP)) {
   3622  1.5.2.2  jdolecek 			struct netmap_adapter *na = NA(adapter->ifp);
   3623  1.5.2.2  jdolecek 			struct netmap_kring *kring = &na->rx_rings[i];
   3624  1.5.2.2  jdolecek 			int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
   3625  1.5.2.2  jdolecek 
   3626  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me), t);
   3627  1.5.2.2  jdolecek 		} else
   3628  1.5.2.2  jdolecek #endif /* DEV_NETMAP */
   3629  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me),
   3630  1.5.2.2  jdolecek 			    adapter->num_rx_desc - 1);
   3631  1.5.2.2  jdolecek 	}
   3632  1.5.2.2  jdolecek 
   3633  1.5.2.2  jdolecek 	/* Enable Receive engine */
   3634  1.5.2.2  jdolecek 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
   3635  1.5.2.2  jdolecek 	if (hw->mac.type == ixgbe_mac_82598EB)
   3636  1.5.2.2  jdolecek 		rxctrl |= IXGBE_RXCTRL_DMBYPS;
   3637  1.5.2.2  jdolecek 	rxctrl |= IXGBE_RXCTRL_RXEN;
   3638  1.5.2.2  jdolecek 	ixgbe_enable_rx_dma(hw, rxctrl);
   3639  1.5.2.2  jdolecek 
   3640  1.5.2.2  jdolecek 	callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
   3641      1.1    dyoung 
   3642  1.5.2.2  jdolecek 	/* Set up MSI-X routing */
   3643  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_MSIX) {
   3644  1.5.2.2  jdolecek 		ixgbe_configure_ivars(adapter);
   3645  1.5.2.2  jdolecek 		/* Set up auto-mask */
   3646  1.5.2.2  jdolecek 		if (hw->mac.type == ixgbe_mac_82598EB)
   3647  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
   3648  1.5.2.2  jdolecek 		else {
   3649  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF);
   3650  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF);
   3651  1.5.2.2  jdolecek 		}
   3652  1.5.2.2  jdolecek 	} else {  /* Simple settings for Legacy/MSI */
   3653  1.5.2.2  jdolecek 		ixgbe_set_ivar(adapter, 0, 0, 0);
   3654  1.5.2.2  jdolecek 		ixgbe_set_ivar(adapter, 0, 0, 1);
   3655  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
   3656  1.5.2.2  jdolecek 	}
   3657      1.1    dyoung 
   3658  1.5.2.2  jdolecek 	ixgbe_init_fdir(adapter);
   3659      1.1    dyoung 
   3660      1.1    dyoung 	/*
   3661  1.5.2.2  jdolecek 	 * Check on any SFP devices that
   3662  1.5.2.2  jdolecek 	 * need to be kick-started
   3663      1.1    dyoung 	 */
   3664  1.5.2.2  jdolecek 	if (hw->phy.type == ixgbe_phy_none) {
   3665  1.5.2.2  jdolecek 		err = hw->phy.ops.identify(hw);
   3666  1.5.2.2  jdolecek 		if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
   3667  1.5.2.2  jdolecek                 	device_printf(dev,
   3668  1.5.2.2  jdolecek 			    "Unsupported SFP+ module type was detected.\n");
   3669  1.5.2.2  jdolecek 			return;
   3670  1.5.2.2  jdolecek         	}
   3671      1.1    dyoung 	}
   3672      1.1    dyoung 
   3673  1.5.2.2  jdolecek 	/* Set moderation on the Link interrupt */
   3674  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR);
   3675      1.1    dyoung 
   3676  1.5.2.2  jdolecek 	/* Config/Enable Link */
   3677  1.5.2.2  jdolecek 	ixgbe_config_link(adapter);
   3678      1.1    dyoung 
   3679  1.5.2.2  jdolecek 	/* Hardware Packet Buffer & Flow Control setup */
   3680  1.5.2.2  jdolecek 	ixgbe_config_delay_values(adapter);
   3681      1.1    dyoung 
   3682  1.5.2.2  jdolecek 	/* Initialize the FC settings */
   3683  1.5.2.2  jdolecek 	ixgbe_start_hw(hw);
   3684      1.1    dyoung 
   3685  1.5.2.2  jdolecek 	/* Set up VLAN support and filter */
   3686  1.5.2.2  jdolecek 	ixgbe_setup_vlan_hw_support(adapter);
   3687      1.1    dyoung 
   3688  1.5.2.2  jdolecek 	/* Setup DMA Coalescing */
   3689  1.5.2.2  jdolecek 	ixgbe_config_dmac(adapter);
   3690      1.1    dyoung 
   3691  1.5.2.2  jdolecek 	/* And now turn on interrupts */
   3692  1.5.2.2  jdolecek 	ixgbe_enable_intr(adapter);
   3693      1.1    dyoung 
   3694  1.5.2.2  jdolecek 	/* Enable the use of the MBX by the VF's */
   3695  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_SRIOV) {
   3696  1.5.2.2  jdolecek 		ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
   3697  1.5.2.2  jdolecek 		ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
   3698  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
   3699      1.1    dyoung 	}
   3700      1.1    dyoung 
   3701  1.5.2.2  jdolecek 	/* Now inform the stack we're ready */
   3702  1.5.2.2  jdolecek 	ifp->if_flags |= IFF_RUNNING;
   3703      1.1    dyoung 
   3704  1.5.2.2  jdolecek 	return;
   3705  1.5.2.2  jdolecek } /* ixgbe_init_locked */
   3706      1.1    dyoung 
   3707  1.5.2.2  jdolecek /************************************************************************
   3708  1.5.2.2  jdolecek  * ixgbe_init
   3709  1.5.2.2  jdolecek  ************************************************************************/
   3710      1.1    dyoung static int
   3711  1.5.2.2  jdolecek ixgbe_init(struct ifnet *ifp)
   3712      1.1    dyoung {
   3713  1.5.2.2  jdolecek 	struct adapter *adapter = ifp->if_softc;
   3714      1.1    dyoung 
   3715  1.5.2.2  jdolecek 	IXGBE_CORE_LOCK(adapter);
   3716  1.5.2.2  jdolecek 	ixgbe_init_locked(adapter);
   3717  1.5.2.2  jdolecek 	IXGBE_CORE_UNLOCK(adapter);
   3718      1.1    dyoung 
   3719  1.5.2.2  jdolecek 	return 0;	/* XXX ixgbe_init_locked cannot fail?  really? */
   3720  1.5.2.2  jdolecek } /* ixgbe_init */
   3721  1.5.2.2  jdolecek 
   3722  1.5.2.2  jdolecek /************************************************************************
   3723  1.5.2.2  jdolecek  * ixgbe_set_ivar
   3724  1.5.2.2  jdolecek  *
   3725  1.5.2.2  jdolecek  *   Setup the correct IVAR register for a particular MSI-X interrupt
   3726  1.5.2.2  jdolecek  *     (yes this is all very magic and confusing :)
   3727  1.5.2.2  jdolecek  *    - entry is the register array entry
   3728  1.5.2.2  jdolecek  *    - vector is the MSI-X vector for this queue
   3729  1.5.2.2  jdolecek  *    - type is RX/TX/MISC
   3730  1.5.2.2  jdolecek  ************************************************************************/
   3731  1.5.2.2  jdolecek static void
   3732  1.5.2.2  jdolecek ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type)
   3733  1.5.2.2  jdolecek {
   3734  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   3735  1.5.2.2  jdolecek 	u32 ivar, index;
   3736      1.1    dyoung 
   3737  1.5.2.2  jdolecek 	vector |= IXGBE_IVAR_ALLOC_VAL;
   3738      1.1    dyoung 
   3739  1.5.2.2  jdolecek 	switch (hw->mac.type) {
   3740      1.1    dyoung 
   3741  1.5.2.2  jdolecek 	case ixgbe_mac_82598EB:
   3742  1.5.2.2  jdolecek 		if (type == -1)
   3743  1.5.2.2  jdolecek 			entry = IXGBE_IVAR_OTHER_CAUSES_INDEX;
   3744  1.5.2.2  jdolecek 		else
   3745  1.5.2.2  jdolecek 			entry += (type * 64);
   3746  1.5.2.2  jdolecek 		index = (entry >> 2) & 0x1F;
   3747  1.5.2.2  jdolecek 		ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index));
   3748  1.5.2.2  jdolecek 		ivar &= ~(0xFF << (8 * (entry & 0x3)));
   3749  1.5.2.2  jdolecek 		ivar |= (vector << (8 * (entry & 0x3)));
   3750  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR(index), ivar);
   3751  1.5.2.2  jdolecek 		break;
   3752      1.1    dyoung 
   3753  1.5.2.2  jdolecek 	case ixgbe_mac_82599EB:
   3754  1.5.2.2  jdolecek 	case ixgbe_mac_X540:
   3755  1.5.2.2  jdolecek 	case ixgbe_mac_X550:
   3756  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
   3757  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
   3758  1.5.2.2  jdolecek 		if (type == -1) { /* MISC IVAR */
   3759  1.5.2.2  jdolecek 			index = (entry & 1) * 8;
   3760  1.5.2.2  jdolecek 			ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC);
   3761  1.5.2.2  jdolecek 			ivar &= ~(0xFF << index);
   3762  1.5.2.2  jdolecek 			ivar |= (vector << index);
   3763  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar);
   3764  1.5.2.2  jdolecek 		} else {	/* RX/TX IVARS */
   3765  1.5.2.2  jdolecek 			index = (16 * (entry & 1)) + (8 * type);
   3766  1.5.2.2  jdolecek 			ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1));
   3767  1.5.2.2  jdolecek 			ivar &= ~(0xFF << index);
   3768  1.5.2.2  jdolecek 			ivar |= (vector << index);
   3769  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar);
   3770      1.1    dyoung 		}
   3771      1.1    dyoung 
   3772  1.5.2.2  jdolecek 	default:
   3773  1.5.2.2  jdolecek 		break;
   3774      1.1    dyoung 	}
   3775  1.5.2.2  jdolecek } /* ixgbe_set_ivar */
   3776      1.1    dyoung 
   3777  1.5.2.2  jdolecek /************************************************************************
   3778  1.5.2.2  jdolecek  * ixgbe_configure_ivars
   3779  1.5.2.2  jdolecek  ************************************************************************/
   3780  1.5.2.2  jdolecek static void
   3781  1.5.2.2  jdolecek ixgbe_configure_ivars(struct adapter *adapter)
   3782  1.5.2.2  jdolecek {
   3783  1.5.2.2  jdolecek 	struct ix_queue *que = adapter->queues;
   3784  1.5.2.2  jdolecek 	u32             newitr;
   3785      1.1    dyoung 
   3786  1.5.2.2  jdolecek 	if (ixgbe_max_interrupt_rate > 0)
   3787  1.5.2.2  jdolecek 		newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8;
   3788  1.5.2.2  jdolecek 	else {
   3789  1.5.2.2  jdolecek 		/*
   3790  1.5.2.2  jdolecek 		 * Disable DMA coalescing if interrupt moderation is
   3791  1.5.2.2  jdolecek 		 * disabled.
   3792  1.5.2.2  jdolecek 		 */
   3793  1.5.2.2  jdolecek 		adapter->dmac = 0;
   3794  1.5.2.2  jdolecek 		newitr = 0;
   3795      1.1    dyoung 	}
   3796      1.1    dyoung 
   3797  1.5.2.2  jdolecek         for (int i = 0; i < adapter->num_queues; i++, que++) {
   3798  1.5.2.2  jdolecek 		struct rx_ring *rxr = &adapter->rx_rings[i];
   3799  1.5.2.2  jdolecek 		struct tx_ring *txr = &adapter->tx_rings[i];
   3800  1.5.2.2  jdolecek 		/* First the RX queue entry */
   3801  1.5.2.2  jdolecek                 ixgbe_set_ivar(adapter, rxr->me, que->msix, 0);
   3802  1.5.2.2  jdolecek 		/* ... and the TX */
   3803  1.5.2.2  jdolecek 		ixgbe_set_ivar(adapter, txr->me, que->msix, 1);
   3804  1.5.2.2  jdolecek 		/* Set an Initial EITR value */
   3805  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(que->msix), newitr);
   3806      1.1    dyoung 	}
   3807      1.1    dyoung 
   3808  1.5.2.2  jdolecek 	/* For the Link interrupt */
   3809  1.5.2.2  jdolecek         ixgbe_set_ivar(adapter, 1, adapter->vector, -1);
   3810  1.5.2.2  jdolecek } /* ixgbe_configure_ivars */
   3811      1.1    dyoung 
   3812  1.5.2.2  jdolecek /************************************************************************
   3813  1.5.2.2  jdolecek  * ixgbe_config_gpie
   3814  1.5.2.2  jdolecek  ************************************************************************/
   3815  1.5.2.2  jdolecek static void
   3816  1.5.2.2  jdolecek ixgbe_config_gpie(struct adapter *adapter)
   3817      1.1    dyoung {
   3818  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   3819  1.5.2.2  jdolecek 	u32             gpie;
   3820      1.1    dyoung 
   3821  1.5.2.2  jdolecek 	gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
   3822      1.1    dyoung 
   3823  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_MSIX) {
   3824  1.5.2.2  jdolecek 		/* Enable Enhanced MSI-X mode */
   3825  1.5.2.2  jdolecek 		gpie |= IXGBE_GPIE_MSIX_MODE
   3826  1.5.2.2  jdolecek 		     |  IXGBE_GPIE_EIAME
   3827  1.5.2.2  jdolecek 		     |  IXGBE_GPIE_PBA_SUPPORT
   3828  1.5.2.2  jdolecek 		     |  IXGBE_GPIE_OCD;
   3829      1.1    dyoung 	}
   3830      1.1    dyoung 
   3831  1.5.2.2  jdolecek 	/* Fan Failure Interrupt */
   3832  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL)
   3833  1.5.2.2  jdolecek 		gpie |= IXGBE_SDP1_GPIEN;
   3834  1.5.2.2  jdolecek 
   3835  1.5.2.2  jdolecek 	/* Thermal Sensor Interrupt */
   3836  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR)
   3837  1.5.2.2  jdolecek 		gpie |= IXGBE_SDP0_GPIEN_X540;
   3838  1.5.2.2  jdolecek 
   3839  1.5.2.2  jdolecek 	/* Link detection */
   3840  1.5.2.2  jdolecek 	switch (hw->mac.type) {
   3841  1.5.2.2  jdolecek 	case ixgbe_mac_82599EB:
   3842  1.5.2.2  jdolecek 		gpie |= IXGBE_SDP1_GPIEN | IXGBE_SDP2_GPIEN;
   3843  1.5.2.2  jdolecek 		break;
   3844  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
   3845  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
   3846  1.5.2.2  jdolecek 		gpie |= IXGBE_SDP0_GPIEN_X540;
   3847  1.5.2.2  jdolecek 		break;
   3848  1.5.2.2  jdolecek 	default:
   3849  1.5.2.2  jdolecek 		break;
   3850      1.1    dyoung 	}
   3851      1.1    dyoung 
   3852  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
   3853      1.1    dyoung 
   3854  1.5.2.2  jdolecek 	return;
   3855  1.5.2.2  jdolecek } /* ixgbe_config_gpie */
   3856  1.5.2.2  jdolecek 
   3857  1.5.2.2  jdolecek /************************************************************************
   3858  1.5.2.2  jdolecek  * ixgbe_config_delay_values
   3859      1.1    dyoung  *
   3860  1.5.2.2  jdolecek  *   Requires adapter->max_frame_size to be set.
   3861  1.5.2.2  jdolecek  ************************************************************************/
   3862      1.1    dyoung static void
   3863  1.5.2.2  jdolecek ixgbe_config_delay_values(struct adapter *adapter)
   3864      1.1    dyoung {
   3865  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   3866  1.5.2.2  jdolecek 	u32             rxpb, frame, size, tmp;
   3867      1.1    dyoung 
   3868  1.5.2.2  jdolecek 	frame = adapter->max_frame_size;
   3869      1.1    dyoung 
   3870  1.5.2.2  jdolecek 	/* Calculate High Water */
   3871  1.5.2.2  jdolecek 	switch (hw->mac.type) {
   3872  1.5.2.2  jdolecek 	case ixgbe_mac_X540:
   3873  1.5.2.2  jdolecek 	case ixgbe_mac_X550:
   3874  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
   3875  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
   3876  1.5.2.2  jdolecek 		tmp = IXGBE_DV_X540(frame, frame);
   3877  1.5.2.2  jdolecek 		break;
   3878  1.5.2.2  jdolecek 	default:
   3879  1.5.2.2  jdolecek 		tmp = IXGBE_DV(frame, frame);
   3880  1.5.2.2  jdolecek 		break;
   3881  1.5.2.2  jdolecek 	}
   3882  1.5.2.2  jdolecek 	size = IXGBE_BT2KB(tmp);
   3883  1.5.2.2  jdolecek 	rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10;
   3884  1.5.2.2  jdolecek 	hw->fc.high_water[0] = rxpb - size;
   3885      1.1    dyoung 
   3886  1.5.2.2  jdolecek 	/* Now calculate Low Water */
   3887  1.5.2.2  jdolecek 	switch (hw->mac.type) {
   3888  1.5.2.2  jdolecek 	case ixgbe_mac_X540:
   3889  1.5.2.2  jdolecek 	case ixgbe_mac_X550:
   3890  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
   3891  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
   3892  1.5.2.2  jdolecek 		tmp = IXGBE_LOW_DV_X540(frame);
   3893  1.5.2.2  jdolecek 		break;
   3894  1.5.2.2  jdolecek 	default:
   3895  1.5.2.2  jdolecek 		tmp = IXGBE_LOW_DV(frame);
   3896  1.5.2.2  jdolecek 		break;
   3897  1.5.2.2  jdolecek 	}
   3898  1.5.2.2  jdolecek 	hw->fc.low_water[0] = IXGBE_BT2KB(tmp);
   3899      1.1    dyoung 
   3900  1.5.2.2  jdolecek 	hw->fc.pause_time = IXGBE_FC_PAUSE;
   3901  1.5.2.2  jdolecek 	hw->fc.send_xon = TRUE;
   3902  1.5.2.2  jdolecek } /* ixgbe_config_delay_values */
   3903      1.1    dyoung 
   3904  1.5.2.2  jdolecek /************************************************************************
   3905  1.5.2.2  jdolecek  * ixgbe_set_multi - Multicast Update
   3906      1.1    dyoung  *
   3907  1.5.2.2  jdolecek  *   Called whenever multicast address list is updated.
   3908  1.5.2.2  jdolecek  ************************************************************************/
   3909      1.1    dyoung static void
   3910  1.5.2.2  jdolecek ixgbe_set_multi(struct adapter *adapter)
   3911      1.1    dyoung {
   3912  1.5.2.2  jdolecek 	struct ixgbe_mc_addr	*mta;
   3913  1.5.2.2  jdolecek 	struct ifnet		*ifp = adapter->ifp;
   3914  1.5.2.2  jdolecek 	u8			*update_ptr;
   3915  1.5.2.2  jdolecek 	int			mcnt = 0;
   3916  1.5.2.2  jdolecek 	u32			fctrl;
   3917  1.5.2.2  jdolecek 	struct ethercom		*ec = &adapter->osdep.ec;
   3918  1.5.2.2  jdolecek 	struct ether_multi	*enm;
   3919  1.5.2.2  jdolecek 	struct ether_multistep	step;
   3920      1.1    dyoung 
   3921  1.5.2.2  jdolecek 	KASSERT(mutex_owned(&adapter->core_mtx));
   3922  1.5.2.2  jdolecek 	IOCTL_DEBUGOUT("ixgbe_set_multi: begin");
   3923      1.1    dyoung 
   3924  1.5.2.2  jdolecek 	mta = adapter->mta;
   3925  1.5.2.2  jdolecek 	bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES);
   3926      1.1    dyoung 
   3927  1.5.2.2  jdolecek 	ifp->if_flags &= ~IFF_ALLMULTI;
   3928  1.5.2.2  jdolecek 	ETHER_LOCK(ec);
   3929  1.5.2.2  jdolecek 	ETHER_FIRST_MULTI(step, ec, enm);
   3930  1.5.2.2  jdolecek 	while (enm != NULL) {
   3931  1.5.2.2  jdolecek 		if ((mcnt == MAX_NUM_MULTICAST_ADDRESSES) ||
   3932  1.5.2.2  jdolecek 		    (memcmp(enm->enm_addrlo, enm->enm_addrhi,
   3933  1.5.2.2  jdolecek 			ETHER_ADDR_LEN) != 0)) {
   3934  1.5.2.2  jdolecek 			ifp->if_flags |= IFF_ALLMULTI;
   3935      1.1    dyoung 			break;
   3936      1.1    dyoung 		}
   3937  1.5.2.2  jdolecek 		bcopy(enm->enm_addrlo,
   3938  1.5.2.2  jdolecek 		    mta[mcnt].addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
   3939  1.5.2.2  jdolecek 		mta[mcnt].vmdq = adapter->pool;
   3940  1.5.2.2  jdolecek 		mcnt++;
   3941  1.5.2.2  jdolecek 		ETHER_NEXT_MULTI(step, enm);
   3942      1.1    dyoung 	}
   3943  1.5.2.2  jdolecek 	ETHER_UNLOCK(ec);
   3944      1.1    dyoung 
   3945  1.5.2.2  jdolecek 	fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
   3946  1.5.2.2  jdolecek 	fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
   3947  1.5.2.2  jdolecek 	if (ifp->if_flags & IFF_PROMISC)
   3948  1.5.2.2  jdolecek 		fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
   3949  1.5.2.2  jdolecek 	else if (ifp->if_flags & IFF_ALLMULTI) {
   3950  1.5.2.2  jdolecek 		fctrl |= IXGBE_FCTRL_MPE;
   3951  1.5.2.2  jdolecek 	}
   3952  1.5.2.2  jdolecek 
   3953  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);
   3954  1.5.2.2  jdolecek 
   3955  1.5.2.2  jdolecek 	if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) {
   3956  1.5.2.2  jdolecek 		update_ptr = (u8 *)mta;
   3957  1.5.2.2  jdolecek 		ixgbe_update_mc_addr_list(&adapter->hw, update_ptr, mcnt,
   3958  1.5.2.2  jdolecek 		    ixgbe_mc_array_itr, TRUE);
   3959      1.1    dyoung 	}
   3960      1.1    dyoung 
   3961      1.1    dyoung 	return;
   3962  1.5.2.2  jdolecek } /* ixgbe_set_multi */
   3963      1.1    dyoung 
   3964  1.5.2.2  jdolecek /************************************************************************
   3965  1.5.2.2  jdolecek  * ixgbe_mc_array_itr
   3966      1.1    dyoung  *
   3967  1.5.2.2  jdolecek  *   An iterator function needed by the multicast shared code.
   3968  1.5.2.2  jdolecek  *   It feeds the shared code routine the addresses in the
   3969  1.5.2.2  jdolecek  *   array of ixgbe_set_multi() one by one.
   3970  1.5.2.2  jdolecek  ************************************************************************/
   3971  1.5.2.2  jdolecek static u8 *
   3972  1.5.2.2  jdolecek ixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq)
   3973      1.1    dyoung {
   3974  1.5.2.2  jdolecek 	struct ixgbe_mc_addr *mta;
   3975      1.1    dyoung 
   3976  1.5.2.2  jdolecek 	mta = (struct ixgbe_mc_addr *)*update_ptr;
   3977  1.5.2.2  jdolecek 	*vmdq = mta->vmdq;
   3978      1.1    dyoung 
   3979  1.5.2.2  jdolecek 	*update_ptr = (u8*)(mta + 1);
   3980  1.5.2.2  jdolecek 
   3981  1.5.2.2  jdolecek 	return (mta->addr);
   3982  1.5.2.2  jdolecek } /* ixgbe_mc_array_itr */
   3983  1.5.2.2  jdolecek 
   3984  1.5.2.2  jdolecek /************************************************************************
   3985  1.5.2.2  jdolecek  * ixgbe_local_timer - Timer routine
   3986      1.1    dyoung  *
   3987  1.5.2.2  jdolecek  *   Checks for link status, updates statistics,
   3988  1.5.2.2  jdolecek  *   and runs the watchdog check.
   3989  1.5.2.2  jdolecek  ************************************************************************/
   3990      1.1    dyoung static void
   3991  1.5.2.2  jdolecek ixgbe_local_timer(void *arg)
   3992      1.1    dyoung {
   3993  1.5.2.2  jdolecek 	struct adapter *adapter = arg;
   3994      1.1    dyoung 
   3995  1.5.2.2  jdolecek 	IXGBE_CORE_LOCK(adapter);
   3996  1.5.2.2  jdolecek 	ixgbe_local_timer1(adapter);
   3997  1.5.2.2  jdolecek 	IXGBE_CORE_UNLOCK(adapter);
   3998      1.1    dyoung }
   3999      1.1    dyoung 
   4000  1.5.2.2  jdolecek static void
   4001  1.5.2.2  jdolecek ixgbe_local_timer1(void *arg)
   4002      1.1    dyoung {
   4003  1.5.2.2  jdolecek 	struct adapter	*adapter = arg;
   4004  1.5.2.2  jdolecek 	device_t	dev = adapter->dev;
   4005  1.5.2.2  jdolecek 	struct ix_queue *que = adapter->queues;
   4006  1.5.2.2  jdolecek 	u64		queues = 0;
   4007  1.5.2.2  jdolecek 	int		hung = 0;
   4008      1.1    dyoung 
   4009  1.5.2.2  jdolecek 	KASSERT(mutex_owned(&adapter->core_mtx));
   4010      1.1    dyoung 
   4011  1.5.2.2  jdolecek 	/* Check for pluggable optics */
   4012  1.5.2.2  jdolecek 	if (adapter->sfp_probe)
   4013  1.5.2.2  jdolecek 		if (!ixgbe_sfp_probe(adapter))
   4014  1.5.2.2  jdolecek 			goto out; /* Nothing to do */
   4015      1.1    dyoung 
   4016  1.5.2.2  jdolecek 	ixgbe_update_link_status(adapter);
   4017  1.5.2.2  jdolecek 	ixgbe_update_stats_counters(adapter);
   4018      1.1    dyoung 
   4019      1.1    dyoung 	/*
   4020  1.5.2.2  jdolecek 	 * Check the TX queues status
   4021  1.5.2.2  jdolecek 	 *      - mark hung queues so we don't schedule on them
   4022  1.5.2.2  jdolecek 	 *      - watchdog only if all queues show hung
   4023      1.1    dyoung 	 */
   4024  1.5.2.2  jdolecek 	for (int i = 0; i < adapter->num_queues; i++, que++) {
   4025  1.5.2.2  jdolecek 		/* Keep track of queues with work for soft irq */
   4026  1.5.2.2  jdolecek 		if (que->txr->busy)
   4027  1.5.2.2  jdolecek 			queues |= ((u64)1 << que->me);
   4028  1.5.2.2  jdolecek 		/*
   4029  1.5.2.2  jdolecek 		 * Each time txeof runs without cleaning, but there
   4030  1.5.2.2  jdolecek 		 * are uncleaned descriptors it increments busy. If
   4031  1.5.2.2  jdolecek 		 * we get to the MAX we declare it hung.
   4032  1.5.2.2  jdolecek 		 */
   4033  1.5.2.2  jdolecek 		if (que->busy == IXGBE_QUEUE_HUNG) {
   4034  1.5.2.2  jdolecek 			++hung;
   4035  1.5.2.2  jdolecek 			/* Mark the queue as inactive */
   4036  1.5.2.2  jdolecek 			adapter->active_queues &= ~((u64)1 << que->me);
   4037  1.5.2.2  jdolecek 			continue;
   4038  1.5.2.2  jdolecek 		} else {
   4039  1.5.2.2  jdolecek 			/* Check if we've come back from hung */
   4040  1.5.2.2  jdolecek 			if ((adapter->active_queues & ((u64)1 << que->me)) == 0)
   4041  1.5.2.2  jdolecek 				adapter->active_queues |= ((u64)1 << que->me);
   4042  1.5.2.2  jdolecek 		}
   4043  1.5.2.2  jdolecek 		if (que->busy >= IXGBE_MAX_TX_BUSY) {
   4044  1.5.2.2  jdolecek 			device_printf(dev,
   4045  1.5.2.2  jdolecek 			    "Warning queue %d appears to be hung!\n", i);
   4046  1.5.2.2  jdolecek 			que->txr->busy = IXGBE_QUEUE_HUNG;
   4047  1.5.2.2  jdolecek 			++hung;
   4048  1.5.2.2  jdolecek 		}
   4049      1.1    dyoung 	}
   4050      1.1    dyoung 
   4051  1.5.2.2  jdolecek 	/* Only truely watchdog if all queues show hung */
   4052  1.5.2.2  jdolecek 	if (hung == adapter->num_queues)
   4053  1.5.2.2  jdolecek 		goto watchdog;
   4054  1.5.2.2  jdolecek 	else if (queues != 0) { /* Force an IRQ on queues with work */
   4055  1.5.2.2  jdolecek 		ixgbe_rearm_queues(adapter, queues);
   4056      1.1    dyoung 	}
   4057      1.1    dyoung 
   4058  1.5.2.2  jdolecek out:
   4059  1.5.2.2  jdolecek 	callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
   4060  1.5.2.2  jdolecek 	return;
   4061      1.1    dyoung 
   4062  1.5.2.2  jdolecek watchdog:
   4063  1.5.2.2  jdolecek 	device_printf(adapter->dev, "Watchdog timeout -- resetting\n");
   4064  1.5.2.2  jdolecek 	adapter->ifp->if_flags &= ~IFF_RUNNING;
   4065  1.5.2.2  jdolecek 	adapter->watchdog_events.ev_count++;
   4066  1.5.2.2  jdolecek 	ixgbe_init_locked(adapter);
   4067  1.5.2.2  jdolecek } /* ixgbe_local_timer */
   4068      1.1    dyoung 
   4069  1.5.2.2  jdolecek /************************************************************************
   4070  1.5.2.2  jdolecek  * ixgbe_sfp_probe
   4071      1.1    dyoung  *
   4072  1.5.2.2  jdolecek  *   Determine if a port had optics inserted.
   4073  1.5.2.2  jdolecek  ************************************************************************/
   4074      1.1    dyoung static bool
   4075  1.5.2.2  jdolecek ixgbe_sfp_probe(struct adapter *adapter)
   4076      1.1    dyoung {
   4077  1.5.2.2  jdolecek 	struct ixgbe_hw	*hw = &adapter->hw;
   4078  1.5.2.2  jdolecek 	device_t	dev = adapter->dev;
   4079  1.5.2.2  jdolecek 	bool		result = FALSE;
   4080      1.1    dyoung 
   4081  1.5.2.2  jdolecek 	if ((hw->phy.type == ixgbe_phy_nl) &&
   4082  1.5.2.2  jdolecek 	    (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
   4083  1.5.2.2  jdolecek 		s32 ret = hw->phy.ops.identify_sfp(hw);
   4084  1.5.2.2  jdolecek 		if (ret)
   4085  1.5.2.2  jdolecek 			goto out;
   4086  1.5.2.2  jdolecek 		ret = hw->phy.ops.reset(hw);
   4087  1.5.2.2  jdolecek 		adapter->sfp_probe = FALSE;
   4088  1.5.2.2  jdolecek 		if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
   4089  1.5.2.2  jdolecek 			device_printf(dev,"Unsupported SFP+ module detected!");
   4090  1.5.2.2  jdolecek 			device_printf(dev,
   4091  1.5.2.2  jdolecek 			    "Reload driver with supported module.\n");
   4092  1.5.2.2  jdolecek                         goto out;
   4093  1.5.2.2  jdolecek 		} else
   4094  1.5.2.2  jdolecek 			device_printf(dev, "SFP+ module detected!\n");
   4095  1.5.2.2  jdolecek 		/* We now have supported optics */
   4096  1.5.2.2  jdolecek 		result = TRUE;
   4097  1.5.2.2  jdolecek 	}
   4098  1.5.2.2  jdolecek out:
   4099      1.1    dyoung 
   4100  1.5.2.2  jdolecek 	return (result);
   4101  1.5.2.2  jdolecek } /* ixgbe_sfp_probe */
   4102      1.1    dyoung 
   4103  1.5.2.2  jdolecek /************************************************************************
   4104  1.5.2.2  jdolecek  * ixgbe_handle_mod - Tasklet for SFP module interrupts
   4105  1.5.2.2  jdolecek  ************************************************************************/
   4106  1.5.2.2  jdolecek static void
   4107  1.5.2.2  jdolecek ixgbe_handle_mod(void *context)
   4108  1.5.2.2  jdolecek {
   4109  1.5.2.2  jdolecek 	struct adapter  *adapter = context;
   4110  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   4111  1.5.2.2  jdolecek 	device_t	dev = adapter->dev;
   4112  1.5.2.2  jdolecek 	u32             err, cage_full = 0;
   4113      1.1    dyoung 
   4114  1.5.2.2  jdolecek 	if (adapter->hw.need_crosstalk_fix) {
   4115  1.5.2.2  jdolecek 		switch (hw->mac.type) {
   4116  1.5.2.2  jdolecek 		case ixgbe_mac_82599EB:
   4117  1.5.2.2  jdolecek 			cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
   4118  1.5.2.2  jdolecek 			    IXGBE_ESDP_SDP2;
   4119  1.5.2.2  jdolecek 			break;
   4120  1.5.2.2  jdolecek 		case ixgbe_mac_X550EM_x:
   4121  1.5.2.2  jdolecek 		case ixgbe_mac_X550EM_a:
   4122  1.5.2.2  jdolecek 			cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
   4123  1.5.2.2  jdolecek 			    IXGBE_ESDP_SDP0;
   4124  1.5.2.2  jdolecek 			break;
   4125  1.5.2.2  jdolecek 		default:
   4126  1.5.2.2  jdolecek 			break;
   4127  1.5.2.2  jdolecek 		}
   4128      1.1    dyoung 
   4129  1.5.2.2  jdolecek 		if (!cage_full)
   4130  1.5.2.2  jdolecek 			return;
   4131      1.1    dyoung 	}
   4132      1.1    dyoung 
   4133  1.5.2.2  jdolecek 	err = hw->phy.ops.identify_sfp(hw);
   4134  1.5.2.2  jdolecek 	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
   4135  1.5.2.2  jdolecek 		device_printf(dev,
   4136  1.5.2.2  jdolecek 		    "Unsupported SFP+ module type was detected.\n");
   4137      1.1    dyoung 		return;
   4138  1.5.2.2  jdolecek 	}
   4139      1.1    dyoung 
   4140  1.5.2.2  jdolecek 	err = hw->mac.ops.setup_sfp(hw);
   4141  1.5.2.2  jdolecek 	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
   4142  1.5.2.2  jdolecek 		device_printf(dev,
   4143  1.5.2.2  jdolecek 		    "Setup failure - unsupported SFP+ module type.\n");
   4144      1.1    dyoung 		return;
   4145      1.1    dyoung 	}
   4146  1.5.2.2  jdolecek 	softint_schedule(adapter->msf_si);
   4147  1.5.2.2  jdolecek } /* ixgbe_handle_mod */
   4148      1.1    dyoung 
   4149      1.1    dyoung 
   4150  1.5.2.2  jdolecek /************************************************************************
   4151  1.5.2.2  jdolecek  * ixgbe_handle_msf - Tasklet for MSF (multispeed fiber) interrupts
   4152  1.5.2.2  jdolecek  ************************************************************************/
   4153  1.5.2.2  jdolecek static void
   4154  1.5.2.2  jdolecek ixgbe_handle_msf(void *context)
   4155      1.1    dyoung {
   4156  1.5.2.2  jdolecek 	struct adapter  *adapter = context;
   4157  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   4158  1.5.2.2  jdolecek 	u32             autoneg;
   4159  1.5.2.2  jdolecek 	bool            negotiate;
   4160      1.1    dyoung 
   4161  1.5.2.2  jdolecek 	/* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */
   4162  1.5.2.2  jdolecek 	adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
   4163      1.1    dyoung 
   4164  1.5.2.2  jdolecek 	autoneg = hw->phy.autoneg_advertised;
   4165  1.5.2.2  jdolecek 	if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
   4166  1.5.2.2  jdolecek 		hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate);
   4167  1.5.2.2  jdolecek 	else
   4168  1.5.2.2  jdolecek 		negotiate = 0;
   4169  1.5.2.2  jdolecek 	if (hw->mac.ops.setup_link)
   4170  1.5.2.2  jdolecek 		hw->mac.ops.setup_link(hw, autoneg, TRUE);
   4171      1.1    dyoung 
   4172  1.5.2.2  jdolecek 	/* Adjust media types shown in ifconfig */
   4173  1.5.2.2  jdolecek 	ifmedia_removeall(&adapter->media);
   4174  1.5.2.2  jdolecek 	ixgbe_add_media_types(adapter);
   4175  1.5.2.2  jdolecek 	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
   4176  1.5.2.2  jdolecek } /* ixgbe_handle_msf */
   4177      1.1    dyoung 
   4178  1.5.2.2  jdolecek /************************************************************************
   4179  1.5.2.2  jdolecek  * ixgbe_handle_phy - Tasklet for external PHY interrupts
   4180  1.5.2.2  jdolecek  ************************************************************************/
   4181  1.5.2.2  jdolecek static void
   4182  1.5.2.2  jdolecek ixgbe_handle_phy(void *context)
   4183  1.5.2.2  jdolecek {
   4184  1.5.2.2  jdolecek 	struct adapter  *adapter = context;
   4185  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   4186  1.5.2.2  jdolecek 	int error;
   4187      1.1    dyoung 
   4188  1.5.2.2  jdolecek 	error = hw->phy.ops.handle_lasi(hw);
   4189  1.5.2.2  jdolecek 	if (error == IXGBE_ERR_OVERTEMP)
   4190  1.5.2.2  jdolecek 		device_printf(adapter->dev,
   4191  1.5.2.2  jdolecek 		    "CRITICAL: EXTERNAL PHY OVER TEMP!! "
   4192  1.5.2.2  jdolecek 		    " PHY will downshift to lower power state!\n");
   4193  1.5.2.2  jdolecek 	else if (error)
   4194  1.5.2.2  jdolecek 		device_printf(adapter->dev,
   4195  1.5.2.2  jdolecek 		    "Error handling LASI interrupt: %d\n", error);
   4196  1.5.2.2  jdolecek } /* ixgbe_handle_phy */
   4197      1.1    dyoung 
   4198  1.5.2.2  jdolecek static void
   4199  1.5.2.2  jdolecek ixgbe_ifstop(struct ifnet *ifp, int disable)
   4200  1.5.2.2  jdolecek {
   4201  1.5.2.2  jdolecek 	struct adapter *adapter = ifp->if_softc;
   4202      1.1    dyoung 
   4203  1.5.2.2  jdolecek 	IXGBE_CORE_LOCK(adapter);
   4204  1.5.2.2  jdolecek 	ixgbe_stop(adapter);
   4205  1.5.2.2  jdolecek 	IXGBE_CORE_UNLOCK(adapter);
   4206      1.1    dyoung }
   4207      1.1    dyoung 
   4208  1.5.2.2  jdolecek /************************************************************************
   4209  1.5.2.2  jdolecek  * ixgbe_stop - Stop the hardware
   4210      1.1    dyoung  *
   4211  1.5.2.2  jdolecek  *   Disables all traffic on the adapter by issuing a
   4212  1.5.2.2  jdolecek  *   global reset on the MAC and deallocates TX/RX buffers.
   4213  1.5.2.2  jdolecek  ************************************************************************/
   4214  1.5.2.2  jdolecek static void
   4215  1.5.2.2  jdolecek ixgbe_stop(void *arg)
   4216  1.5.2.2  jdolecek {
   4217  1.5.2.2  jdolecek 	struct ifnet    *ifp;
   4218  1.5.2.2  jdolecek 	struct adapter  *adapter = arg;
   4219  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   4220      1.1    dyoung 
   4221  1.5.2.2  jdolecek 	ifp = adapter->ifp;
   4222      1.1    dyoung 
   4223  1.5.2.2  jdolecek 	KASSERT(mutex_owned(&adapter->core_mtx));
   4224      1.1    dyoung 
   4225  1.5.2.2  jdolecek 	INIT_DEBUGOUT("ixgbe_stop: begin\n");
   4226  1.5.2.2  jdolecek 	ixgbe_disable_intr(adapter);
   4227  1.5.2.2  jdolecek 	callout_stop(&adapter->timer);
   4228      1.1    dyoung 
   4229  1.5.2.2  jdolecek 	/* Let the stack know...*/
   4230  1.5.2.2  jdolecek 	ifp->if_flags &= ~IFF_RUNNING;
   4231      1.1    dyoung 
   4232  1.5.2.2  jdolecek 	ixgbe_reset_hw(hw);
   4233  1.5.2.2  jdolecek 	hw->adapter_stopped = FALSE;
   4234  1.5.2.2  jdolecek 	ixgbe_stop_adapter(hw);
   4235  1.5.2.2  jdolecek 	if (hw->mac.type == ixgbe_mac_82599EB)
   4236  1.5.2.2  jdolecek 		ixgbe_stop_mac_link_on_d3_82599(hw);
   4237  1.5.2.2  jdolecek 	/* Turn off the laser - noop with no optics */
   4238  1.5.2.2  jdolecek 	ixgbe_disable_tx_laser(hw);
   4239      1.1    dyoung 
   4240  1.5.2.2  jdolecek 	/* Update the stack */
   4241  1.5.2.2  jdolecek 	adapter->link_up = FALSE;
   4242  1.5.2.2  jdolecek 	ixgbe_update_link_status(adapter);
   4243      1.1    dyoung 
   4244  1.5.2.2  jdolecek 	/* reprogram the RAR[0] in case user changed it. */
   4245  1.5.2.2  jdolecek 	ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
   4246      1.1    dyoung 
   4247  1.5.2.2  jdolecek 	return;
   4248  1.5.2.2  jdolecek } /* ixgbe_stop */
   4249  1.5.2.2  jdolecek 
   4250  1.5.2.2  jdolecek /************************************************************************
   4251  1.5.2.2  jdolecek  * ixgbe_update_link_status - Update OS on link state
   4252      1.1    dyoung  *
   4253  1.5.2.2  jdolecek  * Note: Only updates the OS on the cached link state.
   4254  1.5.2.2  jdolecek  *       The real check of the hardware only happens with
   4255  1.5.2.2  jdolecek  *       a link interrupt.
   4256  1.5.2.2  jdolecek  ************************************************************************/
   4257      1.1    dyoung static void
   4258  1.5.2.2  jdolecek ixgbe_update_link_status(struct adapter *adapter)
   4259      1.1    dyoung {
   4260  1.5.2.2  jdolecek 	struct ifnet	*ifp = adapter->ifp;
   4261  1.5.2.2  jdolecek 	device_t        dev = adapter->dev;
   4262  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   4263      1.1    dyoung 
   4264  1.5.2.2  jdolecek 	if (adapter->link_up) {
   4265  1.5.2.2  jdolecek 		if (adapter->link_active == FALSE) {
   4266  1.5.2.2  jdolecek 			if (adapter->link_speed == IXGBE_LINK_SPEED_10GB_FULL){
   4267  1.5.2.2  jdolecek 				/*
   4268  1.5.2.2  jdolecek 				 *  Discard count for both MAC Local Fault and
   4269  1.5.2.2  jdolecek 				 * Remote Fault because those registers are
   4270  1.5.2.2  jdolecek 				 * valid only when the link speed is up and
   4271  1.5.2.2  jdolecek 				 * 10Gbps.
   4272  1.5.2.2  jdolecek 				 */
   4273  1.5.2.2  jdolecek 				IXGBE_READ_REG(hw, IXGBE_MLFC);
   4274  1.5.2.2  jdolecek 				IXGBE_READ_REG(hw, IXGBE_MRFC);
   4275  1.5.2.2  jdolecek 			}
   4276      1.1    dyoung 
   4277  1.5.2.2  jdolecek 			if (bootverbose) {
   4278  1.5.2.2  jdolecek 				const char *bpsmsg;
   4279      1.1    dyoung 
   4280  1.5.2.2  jdolecek 				switch (adapter->link_speed) {
   4281  1.5.2.2  jdolecek 				case IXGBE_LINK_SPEED_10GB_FULL:
   4282  1.5.2.2  jdolecek 					bpsmsg = "10 Gbps";
   4283  1.5.2.2  jdolecek 					break;
   4284  1.5.2.2  jdolecek 				case IXGBE_LINK_SPEED_5GB_FULL:
   4285  1.5.2.2  jdolecek 					bpsmsg = "5 Gbps";
   4286  1.5.2.2  jdolecek 					break;
   4287  1.5.2.2  jdolecek 				case IXGBE_LINK_SPEED_2_5GB_FULL:
   4288  1.5.2.2  jdolecek 					bpsmsg = "2.5 Gbps";
   4289  1.5.2.2  jdolecek 					break;
   4290  1.5.2.2  jdolecek 				case IXGBE_LINK_SPEED_1GB_FULL:
   4291  1.5.2.2  jdolecek 					bpsmsg = "1 Gbps";
   4292  1.5.2.2  jdolecek 					break;
   4293  1.5.2.2  jdolecek 				case IXGBE_LINK_SPEED_100_FULL:
   4294  1.5.2.2  jdolecek 					bpsmsg = "100 Mbps";
   4295  1.5.2.2  jdolecek 					break;
   4296  1.5.2.2  jdolecek 				case IXGBE_LINK_SPEED_10_FULL:
   4297  1.5.2.2  jdolecek 					bpsmsg = "10 Mbps";
   4298  1.5.2.2  jdolecek 					break;
   4299  1.5.2.2  jdolecek 				default:
   4300  1.5.2.2  jdolecek 					bpsmsg = "unknown speed";
   4301  1.5.2.2  jdolecek 					break;
   4302  1.5.2.2  jdolecek 				}
   4303  1.5.2.2  jdolecek 				device_printf(dev, "Link is up %s %s \n",
   4304  1.5.2.2  jdolecek 				    bpsmsg, "Full Duplex");
   4305  1.5.2.2  jdolecek 			}
   4306  1.5.2.2  jdolecek 			adapter->link_active = TRUE;
   4307  1.5.2.2  jdolecek 			/* Update any Flow Control changes */
   4308  1.5.2.2  jdolecek 			ixgbe_fc_enable(&adapter->hw);
   4309  1.5.2.2  jdolecek 			/* Update DMA coalescing config */
   4310  1.5.2.2  jdolecek 			ixgbe_config_dmac(adapter);
   4311  1.5.2.2  jdolecek 			if_link_state_change(ifp, LINK_STATE_UP);
   4312  1.5.2.2  jdolecek 			if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
   4313  1.5.2.2  jdolecek 				ixgbe_ping_all_vfs(adapter);
   4314  1.5.2.2  jdolecek 		}
   4315  1.5.2.2  jdolecek 	} else { /* Link down */
   4316  1.5.2.2  jdolecek 		if (adapter->link_active == TRUE) {
   4317  1.5.2.2  jdolecek 			if (bootverbose)
   4318  1.5.2.2  jdolecek 				device_printf(dev, "Link is Down\n");
   4319  1.5.2.2  jdolecek 			if_link_state_change(ifp, LINK_STATE_DOWN);
   4320  1.5.2.2  jdolecek 			adapter->link_active = FALSE;
   4321  1.5.2.2  jdolecek 			if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
   4322  1.5.2.2  jdolecek 				ixgbe_ping_all_vfs(adapter);
   4323      1.1    dyoung 		}
   4324      1.1    dyoung 	}
   4325      1.1    dyoung 
   4326  1.5.2.2  jdolecek 	return;
   4327  1.5.2.2  jdolecek } /* ixgbe_update_link_status */
   4328      1.1    dyoung 
   4329  1.5.2.2  jdolecek /************************************************************************
   4330  1.5.2.2  jdolecek  * ixgbe_config_dmac - Configure DMA Coalescing
   4331  1.5.2.2  jdolecek  ************************************************************************/
   4332  1.5.2.2  jdolecek static void
   4333  1.5.2.2  jdolecek ixgbe_config_dmac(struct adapter *adapter)
   4334  1.5.2.2  jdolecek {
   4335  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   4336  1.5.2.2  jdolecek 	struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config;
   4337      1.1    dyoung 
   4338  1.5.2.2  jdolecek 	if (hw->mac.type < ixgbe_mac_X550 || !hw->mac.ops.dmac_config)
   4339  1.5.2.2  jdolecek 		return;
   4340      1.1    dyoung 
   4341  1.5.2.2  jdolecek 	if (dcfg->watchdog_timer ^ adapter->dmac ||
   4342  1.5.2.2  jdolecek 	    dcfg->link_speed ^ adapter->link_speed) {
   4343  1.5.2.2  jdolecek 		dcfg->watchdog_timer = adapter->dmac;
   4344  1.5.2.2  jdolecek 		dcfg->fcoe_en = false;
   4345  1.5.2.2  jdolecek 		dcfg->link_speed = adapter->link_speed;
   4346  1.5.2.2  jdolecek 		dcfg->num_tcs = 1;
   4347  1.5.2.2  jdolecek 
   4348  1.5.2.2  jdolecek 		INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n",
   4349  1.5.2.2  jdolecek 		    dcfg->watchdog_timer, dcfg->link_speed);
   4350  1.5.2.2  jdolecek 
   4351  1.5.2.2  jdolecek 		hw->mac.ops.dmac_config(hw);
   4352  1.5.2.2  jdolecek 	}
   4353  1.5.2.2  jdolecek } /* ixgbe_config_dmac */
   4354  1.5.2.2  jdolecek 
   4355  1.5.2.2  jdolecek /************************************************************************
   4356  1.5.2.2  jdolecek  * ixgbe_enable_intr
   4357  1.5.2.2  jdolecek  ************************************************************************/
   4358  1.5.2.2  jdolecek static void
   4359  1.5.2.2  jdolecek ixgbe_enable_intr(struct adapter *adapter)
   4360  1.5.2.2  jdolecek {
   4361  1.5.2.2  jdolecek 	struct ixgbe_hw	*hw = &adapter->hw;
   4362  1.5.2.2  jdolecek 	struct ix_queue	*que = adapter->queues;
   4363  1.5.2.2  jdolecek 	u32		mask, fwsm;
   4364      1.1    dyoung 
   4365  1.5.2.2  jdolecek 	mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
   4366      1.1    dyoung 
   4367  1.5.2.2  jdolecek 	switch (adapter->hw.mac.type) {
   4368  1.5.2.2  jdolecek 	case ixgbe_mac_82599EB:
   4369  1.5.2.2  jdolecek 		mask |= IXGBE_EIMS_ECC;
   4370  1.5.2.2  jdolecek 		/* Temperature sensor on some adapters */
   4371  1.5.2.2  jdolecek 		mask |= IXGBE_EIMS_GPI_SDP0;
   4372  1.5.2.2  jdolecek 		/* SFP+ (RX_LOS_N & MOD_ABS_N) */
   4373  1.5.2.2  jdolecek 		mask |= IXGBE_EIMS_GPI_SDP1;
   4374  1.5.2.2  jdolecek 		mask |= IXGBE_EIMS_GPI_SDP2;
   4375  1.5.2.2  jdolecek 		break;
   4376  1.5.2.2  jdolecek 	case ixgbe_mac_X540:
   4377  1.5.2.2  jdolecek 		/* Detect if Thermal Sensor is enabled */
   4378  1.5.2.2  jdolecek 		fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
   4379  1.5.2.2  jdolecek 		if (fwsm & IXGBE_FWSM_TS_ENABLED)
   4380  1.5.2.2  jdolecek 			mask |= IXGBE_EIMS_TS;
   4381  1.5.2.2  jdolecek 		mask |= IXGBE_EIMS_ECC;
   4382  1.5.2.2  jdolecek 		break;
   4383  1.5.2.2  jdolecek 	case ixgbe_mac_X550:
   4384  1.5.2.2  jdolecek 		/* MAC thermal sensor is automatically enabled */
   4385  1.5.2.2  jdolecek 		mask |= IXGBE_EIMS_TS;
   4386  1.5.2.2  jdolecek 		mask |= IXGBE_EIMS_ECC;
   4387  1.5.2.2  jdolecek 		break;
   4388  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
   4389  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
   4390  1.5.2.2  jdolecek 		/* Some devices use SDP0 for important information */
   4391  1.5.2.2  jdolecek 		if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
   4392  1.5.2.2  jdolecek 		    hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP ||
   4393  1.5.2.2  jdolecek 		    hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N ||
   4394  1.5.2.2  jdolecek 		    hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T)
   4395  1.5.2.2  jdolecek 			mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw);
   4396  1.5.2.2  jdolecek 		if (hw->phy.type == ixgbe_phy_x550em_ext_t)
   4397  1.5.2.2  jdolecek 			mask |= IXGBE_EICR_GPI_SDP0_X540;
   4398  1.5.2.2  jdolecek 		mask |= IXGBE_EIMS_ECC;
   4399  1.5.2.2  jdolecek 		break;
   4400  1.5.2.2  jdolecek 	default:
   4401  1.5.2.2  jdolecek 		break;
   4402  1.5.2.2  jdolecek 	}
   4403      1.1    dyoung 
   4404  1.5.2.2  jdolecek 	/* Enable Fan Failure detection */
   4405  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL)
   4406  1.5.2.2  jdolecek 		mask |= IXGBE_EIMS_GPI_SDP1;
   4407  1.5.2.2  jdolecek 	/* Enable SR-IOV */
   4408  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
   4409  1.5.2.2  jdolecek 		mask |= IXGBE_EIMS_MAILBOX;
   4410  1.5.2.2  jdolecek 	/* Enable Flow Director */
   4411  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_FDIR)
   4412  1.5.2.2  jdolecek 		mask |= IXGBE_EIMS_FLOW_DIR;
   4413      1.1    dyoung 
   4414  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
   4415      1.1    dyoung 
   4416  1.5.2.2  jdolecek 	/* With MSI-X we use auto clear */
   4417  1.5.2.2  jdolecek 	if (adapter->msix_mem) {
   4418  1.5.2.2  jdolecek 		mask = IXGBE_EIMS_ENABLE_MASK;
   4419  1.5.2.2  jdolecek 		/* Don't autoclear Link */
   4420  1.5.2.2  jdolecek 		mask &= ~IXGBE_EIMS_OTHER;
   4421  1.5.2.2  jdolecek 		mask &= ~IXGBE_EIMS_LSC;
   4422  1.5.2.2  jdolecek 		if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
   4423  1.5.2.2  jdolecek 			mask &= ~IXGBE_EIMS_MAILBOX;
   4424  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask);
   4425  1.5.2.2  jdolecek 	}
   4426      1.1    dyoung 
   4427      1.1    dyoung 	/*
   4428  1.5.2.2  jdolecek 	 * Now enable all queues, this is done separately to
   4429  1.5.2.2  jdolecek 	 * allow for handling the extended (beyond 32) MSI-X
   4430  1.5.2.2  jdolecek 	 * vectors that can be used by 82599
   4431      1.1    dyoung 	 */
   4432  1.5.2.2  jdolecek         for (int i = 0; i < adapter->num_queues; i++, que++)
   4433  1.5.2.2  jdolecek                 ixgbe_enable_queue(adapter, que->msix);
   4434      1.1    dyoung 
   4435  1.5.2.2  jdolecek 	IXGBE_WRITE_FLUSH(hw);
   4436      1.1    dyoung 
   4437  1.5.2.2  jdolecek 	return;
   4438  1.5.2.2  jdolecek } /* ixgbe_enable_intr */
   4439      1.1    dyoung 
   4440  1.5.2.2  jdolecek /************************************************************************
   4441  1.5.2.2  jdolecek  * ixgbe_disable_intr
   4442  1.5.2.2  jdolecek  ************************************************************************/
   4443      1.1    dyoung static void
   4444  1.5.2.2  jdolecek ixgbe_disable_intr(struct adapter *adapter)
   4445      1.1    dyoung {
   4446  1.5.2.2  jdolecek 	if (adapter->msix_mem)
   4447  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 0);
   4448  1.5.2.2  jdolecek 	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
   4449  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
   4450  1.5.2.2  jdolecek 	} else {
   4451  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
   4452  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
   4453  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
   4454  1.5.2.2  jdolecek 	}
   4455  1.5.2.2  jdolecek 	IXGBE_WRITE_FLUSH(&adapter->hw);
   4456      1.1    dyoung 
   4457  1.5.2.2  jdolecek 	return;
   4458  1.5.2.2  jdolecek } /* ixgbe_disable_intr */
   4459      1.1    dyoung 
   4460  1.5.2.2  jdolecek /************************************************************************
   4461  1.5.2.2  jdolecek  * ixgbe_legacy_irq - Legacy Interrupt Service routine
   4462  1.5.2.2  jdolecek  ************************************************************************/
   4463  1.5.2.2  jdolecek static int
   4464  1.5.2.2  jdolecek ixgbe_legacy_irq(void *arg)
   4465  1.5.2.2  jdolecek {
   4466  1.5.2.2  jdolecek 	struct ix_queue *que = arg;
   4467  1.5.2.2  jdolecek 	struct adapter	*adapter = que->adapter;
   4468  1.5.2.2  jdolecek 	struct ixgbe_hw	*hw = &adapter->hw;
   4469  1.5.2.2  jdolecek 	struct ifnet    *ifp = adapter->ifp;
   4470  1.5.2.2  jdolecek 	struct 		tx_ring *txr = adapter->tx_rings;
   4471  1.5.2.2  jdolecek 	bool		more = false;
   4472  1.5.2.2  jdolecek 	u32             eicr, eicr_mask;
   4473      1.1    dyoung 
   4474  1.5.2.2  jdolecek 	/* Silicon errata #26 on 82598 */
   4475  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
   4476      1.1    dyoung 
   4477  1.5.2.2  jdolecek 	eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
   4478      1.1    dyoung 
   4479  1.5.2.2  jdolecek 	adapter->stats.pf.legint.ev_count++;
   4480  1.5.2.2  jdolecek 	++que->irqs.ev_count;
   4481  1.5.2.2  jdolecek 	if (eicr == 0) {
   4482  1.5.2.2  jdolecek 		adapter->stats.pf.intzero.ev_count++;
   4483  1.5.2.2  jdolecek 		if ((ifp->if_flags & IFF_UP) != 0)
   4484  1.5.2.2  jdolecek 			ixgbe_enable_intr(adapter);
   4485  1.5.2.2  jdolecek 		return 0;
   4486  1.5.2.2  jdolecek 	}
   4487      1.1    dyoung 
   4488  1.5.2.2  jdolecek 	if ((ifp->if_flags & IFF_RUNNING) != 0) {
   4489  1.5.2.2  jdolecek #ifdef __NetBSD__
   4490  1.5.2.2  jdolecek 		/* Don't run ixgbe_rxeof in interrupt context */
   4491  1.5.2.2  jdolecek 		more = true;
   4492  1.5.2.2  jdolecek #else
   4493  1.5.2.2  jdolecek 		more = ixgbe_rxeof(que);
   4494  1.5.2.2  jdolecek #endif
   4495      1.1    dyoung 
   4496  1.5.2.2  jdolecek 		IXGBE_TX_LOCK(txr);
   4497  1.5.2.2  jdolecek 		ixgbe_txeof(txr);
   4498  1.5.2.2  jdolecek #ifdef notyet
   4499  1.5.2.2  jdolecek 		if (!ixgbe_ring_empty(ifp, txr->br))
   4500  1.5.2.2  jdolecek 			ixgbe_start_locked(ifp, txr);
   4501  1.5.2.2  jdolecek #endif
   4502  1.5.2.2  jdolecek 		IXGBE_TX_UNLOCK(txr);
   4503      1.1    dyoung 	}
   4504      1.1    dyoung 
   4505  1.5.2.2  jdolecek 	/* Check for fan failure */
   4506  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
   4507  1.5.2.2  jdolecek 		ixgbe_check_fan_failure(adapter, eicr, true);
   4508  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
   4509      1.1    dyoung 	}
   4510      1.1    dyoung 
   4511  1.5.2.2  jdolecek 	/* Link status change */
   4512  1.5.2.2  jdolecek 	if (eicr & IXGBE_EICR_LSC)
   4513  1.5.2.2  jdolecek 		softint_schedule(adapter->link_si);
   4514      1.1    dyoung 
   4515  1.5.2.2  jdolecek 	if (ixgbe_is_sfp(hw)) {
   4516  1.5.2.2  jdolecek 		/* Pluggable optics-related interrupt */
   4517  1.5.2.2  jdolecek 		if (hw->mac.type >= ixgbe_mac_X540)
   4518  1.5.2.2  jdolecek 			eicr_mask = IXGBE_EICR_GPI_SDP0_X540;
   4519  1.5.2.2  jdolecek 		else
   4520  1.5.2.2  jdolecek 			eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw);
   4521      1.1    dyoung 
   4522  1.5.2.2  jdolecek 		if (eicr & eicr_mask) {
   4523  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask);
   4524  1.5.2.2  jdolecek 			softint_schedule(adapter->mod_si);
   4525      1.1    dyoung 		}
   4526      1.1    dyoung 
   4527  1.5.2.2  jdolecek 		if ((hw->mac.type == ixgbe_mac_82599EB) &&
   4528  1.5.2.2  jdolecek 		    (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) {
   4529  1.5.2.2  jdolecek 			IXGBE_WRITE_REG(hw, IXGBE_EICR,
   4530  1.5.2.2  jdolecek 			    IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
   4531  1.5.2.2  jdolecek 			softint_schedule(adapter->msf_si);
   4532  1.5.2.2  jdolecek 		}
   4533      1.1    dyoung 	}
   4534      1.1    dyoung 
   4535  1.5.2.2  jdolecek 	/* External PHY interrupt */
   4536  1.5.2.2  jdolecek 	if ((hw->phy.type == ixgbe_phy_x550em_ext_t) &&
   4537  1.5.2.2  jdolecek 	    (eicr & IXGBE_EICR_GPI_SDP0_X540))
   4538  1.5.2.2  jdolecek 		softint_schedule(adapter->phy_si);
   4539      1.1    dyoung 
   4540  1.5.2.2  jdolecek 	if (more)
   4541  1.5.2.2  jdolecek 		softint_schedule(que->que_si);
   4542  1.5.2.2  jdolecek 	else
   4543  1.5.2.2  jdolecek 		ixgbe_enable_intr(adapter);
   4544      1.1    dyoung 
   4545  1.5.2.2  jdolecek 	return 1;
   4546  1.5.2.2  jdolecek } /* ixgbe_legacy_irq */
   4547      1.1    dyoung 
   4548  1.5.2.2  jdolecek /************************************************************************
   4549  1.5.2.2  jdolecek  * ixgbe_free_pci_resources
   4550  1.5.2.2  jdolecek  ************************************************************************/
   4551      1.1    dyoung static void
   4552  1.5.2.2  jdolecek ixgbe_free_pci_resources(struct adapter *adapter)
   4553      1.1    dyoung {
   4554  1.5.2.2  jdolecek 	struct ix_queue *que = adapter->queues;
   4555  1.5.2.2  jdolecek 	int		rid;
   4556      1.1    dyoung 
   4557  1.5.2.2  jdolecek 	/*
   4558  1.5.2.2  jdolecek 	 * Release all msix queue resources:
   4559  1.5.2.2  jdolecek 	 */
   4560  1.5.2.2  jdolecek 	for (int i = 0; i < adapter->num_queues; i++, que++) {
   4561  1.5.2.2  jdolecek 		if (que->res != NULL)
   4562  1.5.2.2  jdolecek 			pci_intr_disestablish(adapter->osdep.pc,
   4563  1.5.2.2  jdolecek 			    adapter->osdep.ihs[i]);
   4564      1.1    dyoung 	}
   4565      1.1    dyoung 
   4566  1.5.2.2  jdolecek 	/* Clean the Legacy or Link interrupt last */
   4567  1.5.2.2  jdolecek 	if (adapter->vector) /* we are doing MSIX */
   4568  1.5.2.2  jdolecek 		rid = adapter->vector;
   4569  1.5.2.2  jdolecek 	else
   4570  1.5.2.2  jdolecek 		rid = 0;
   4571      1.1    dyoung 
   4572  1.5.2.2  jdolecek 	if (adapter->osdep.ihs[rid] != NULL) {
   4573  1.5.2.2  jdolecek 		pci_intr_disestablish(adapter->osdep.pc,
   4574  1.5.2.2  jdolecek 		    adapter->osdep.ihs[rid]);
   4575  1.5.2.2  jdolecek 		adapter->osdep.ihs[rid] = NULL;
   4576      1.1    dyoung 	}
   4577      1.1    dyoung 
   4578  1.5.2.2  jdolecek 	pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs,
   4579  1.5.2.2  jdolecek 	    adapter->osdep.nintrs);
   4580  1.5.2.2  jdolecek 
   4581  1.5.2.2  jdolecek 	if (adapter->osdep.mem_size != 0) {
   4582  1.5.2.2  jdolecek 		bus_space_unmap(adapter->osdep.mem_bus_space_tag,
   4583  1.5.2.2  jdolecek 		    adapter->osdep.mem_bus_space_handle,
   4584  1.5.2.2  jdolecek 		    adapter->osdep.mem_size);
   4585      1.1    dyoung 	}
   4586      1.1    dyoung 
   4587      1.1    dyoung 	return;
   4588  1.5.2.2  jdolecek } /* ixgbe_free_pci_resources */
   4589      1.1    dyoung 
   4590  1.5.2.2  jdolecek /************************************************************************
   4591  1.5.2.2  jdolecek  * ixgbe_set_sysctl_value
   4592  1.5.2.2  jdolecek  ************************************************************************/
   4593  1.5.2.2  jdolecek static void
   4594  1.5.2.2  jdolecek ixgbe_set_sysctl_value(struct adapter *adapter, const char *name,
   4595  1.5.2.2  jdolecek     const char *description, int *limit, int value)
   4596      1.1    dyoung {
   4597  1.5.2.2  jdolecek 	device_t dev =  adapter->dev;
   4598  1.5.2.2  jdolecek 	struct sysctllog **log;
   4599  1.5.2.2  jdolecek 	const struct sysctlnode *rnode, *cnode;
   4600      1.1    dyoung 
   4601  1.5.2.2  jdolecek 	log = &adapter->sysctllog;
   4602  1.5.2.2  jdolecek 	if ((rnode = ixgbe_sysctl_instance(adapter)) == NULL) {
   4603  1.5.2.2  jdolecek 		aprint_error_dev(dev, "could not create sysctl root\n");
   4604  1.5.2.2  jdolecek 		return;
   4605  1.5.2.2  jdolecek 	}
   4606  1.5.2.2  jdolecek 	if (sysctl_createv(log, 0, &rnode, &cnode,
   4607  1.5.2.2  jdolecek 	    CTLFLAG_READWRITE, CTLTYPE_INT,
   4608  1.5.2.2  jdolecek 	    name, SYSCTL_DESCR(description),
   4609  1.5.2.2  jdolecek 		NULL, 0, limit, 0, CTL_CREATE, CTL_EOL) != 0)
   4610  1.5.2.2  jdolecek 		aprint_error_dev(dev, "could not create sysctl\n");
   4611  1.5.2.2  jdolecek 	*limit = value;
   4612  1.5.2.2  jdolecek } /* ixgbe_set_sysctl_value */
   4613      1.1    dyoung 
   4614  1.5.2.2  jdolecek /************************************************************************
   4615  1.5.2.2  jdolecek  * ixgbe_sysctl_flowcntl
   4616  1.5.2.2  jdolecek  *
   4617  1.5.2.2  jdolecek  *   SYSCTL wrapper around setting Flow Control
   4618  1.5.2.2  jdolecek  ************************************************************************/
   4619  1.5.2.2  jdolecek static int
   4620  1.5.2.2  jdolecek ixgbe_sysctl_flowcntl(SYSCTLFN_ARGS)
   4621      1.1    dyoung {
   4622  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   4623  1.5.2.2  jdolecek 	struct adapter *adapter = (struct adapter *)node.sysctl_data;
   4624  1.5.2.2  jdolecek 	int error, fc;
   4625      1.1    dyoung 
   4626  1.5.2.2  jdolecek 	fc = adapter->hw.fc.current_mode;
   4627  1.5.2.2  jdolecek 	node.sysctl_data = &fc;
   4628  1.5.2.2  jdolecek 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
   4629  1.5.2.2  jdolecek 	if (error != 0 || newp == NULL)
   4630  1.5.2.2  jdolecek 		return error;
   4631      1.1    dyoung 
   4632  1.5.2.2  jdolecek 	/* Don't bother if it's not changed */
   4633  1.5.2.2  jdolecek 	if (fc == adapter->hw.fc.current_mode)
   4634  1.5.2.2  jdolecek 		return (0);
   4635      1.1    dyoung 
   4636  1.5.2.2  jdolecek 	return ixgbe_set_flowcntl(adapter, fc);
   4637  1.5.2.2  jdolecek } /* ixgbe_sysctl_flowcntl */
   4638      1.1    dyoung 
   4639  1.5.2.2  jdolecek /************************************************************************
   4640  1.5.2.2  jdolecek  * ixgbe_set_flowcntl - Set flow control
   4641      1.1    dyoung  *
   4642  1.5.2.2  jdolecek  *   Flow control values:
   4643  1.5.2.2  jdolecek  *     0 - off
   4644  1.5.2.2  jdolecek  *     1 - rx pause
   4645  1.5.2.2  jdolecek  *     2 - tx pause
   4646  1.5.2.2  jdolecek  *     3 - full
   4647  1.5.2.2  jdolecek  ************************************************************************/
   4648  1.5.2.2  jdolecek static int
   4649  1.5.2.2  jdolecek ixgbe_set_flowcntl(struct adapter *adapter, int fc)
   4650      1.1    dyoung {
   4651  1.5.2.2  jdolecek 	switch (fc) {
   4652  1.5.2.2  jdolecek 		case ixgbe_fc_rx_pause:
   4653  1.5.2.2  jdolecek 		case ixgbe_fc_tx_pause:
   4654  1.5.2.2  jdolecek 		case ixgbe_fc_full:
   4655  1.5.2.2  jdolecek 			adapter->hw.fc.requested_mode = fc;
   4656  1.5.2.2  jdolecek 			if (adapter->num_queues > 1)
   4657  1.5.2.2  jdolecek 				ixgbe_disable_rx_drop(adapter);
   4658      1.1    dyoung 			break;
   4659  1.5.2.2  jdolecek 		case ixgbe_fc_none:
   4660  1.5.2.2  jdolecek 			adapter->hw.fc.requested_mode = ixgbe_fc_none;
   4661  1.5.2.2  jdolecek 			if (adapter->num_queues > 1)
   4662  1.5.2.2  jdolecek 				ixgbe_enable_rx_drop(adapter);
   4663      1.1    dyoung 			break;
   4664  1.5.2.2  jdolecek 		default:
   4665  1.5.2.2  jdolecek 			return (EINVAL);
   4666  1.5.2.2  jdolecek 	}
   4667      1.1    dyoung 
   4668  1.5.2.2  jdolecek #if 0 /* XXX NetBSD */
   4669  1.5.2.2  jdolecek 	/* Don't autoneg if forcing a value */
   4670  1.5.2.2  jdolecek 	adapter->hw.fc.disable_fc_autoneg = TRUE;
   4671      1.1    dyoung #endif
   4672  1.5.2.2  jdolecek 	ixgbe_fc_enable(&adapter->hw);
   4673      1.1    dyoung 
   4674  1.5.2.2  jdolecek 	return (0);
   4675  1.5.2.2  jdolecek } /* ixgbe_set_flowcntl */
   4676      1.1    dyoung 
   4677  1.5.2.2  jdolecek /************************************************************************
   4678  1.5.2.2  jdolecek  * ixgbe_enable_rx_drop
   4679  1.5.2.2  jdolecek  *
   4680  1.5.2.2  jdolecek  *   Enable the hardware to drop packets when the buffer is
   4681  1.5.2.2  jdolecek  *   full. This is useful with multiqueue, so that no single
   4682  1.5.2.2  jdolecek  *   queue being full stalls the entire RX engine. We only
   4683  1.5.2.2  jdolecek  *   enable this when Multiqueue is enabled AND Flow Control
   4684  1.5.2.2  jdolecek  *   is disabled.
   4685  1.5.2.2  jdolecek  ************************************************************************/
   4686  1.5.2.2  jdolecek static void
   4687  1.5.2.2  jdolecek ixgbe_enable_rx_drop(struct adapter *adapter)
   4688  1.5.2.2  jdolecek {
   4689  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   4690  1.5.2.2  jdolecek 	struct rx_ring  *rxr;
   4691  1.5.2.2  jdolecek 	u32             srrctl;
   4692      1.1    dyoung 
   4693  1.5.2.2  jdolecek 	for (int i = 0; i < adapter->num_queues; i++) {
   4694  1.5.2.2  jdolecek 		rxr = &adapter->rx_rings[i];
   4695  1.5.2.2  jdolecek 		srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
   4696  1.5.2.2  jdolecek 		srrctl |= IXGBE_SRRCTL_DROP_EN;
   4697  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
   4698      1.1    dyoung 	}
   4699      1.1    dyoung 
   4700  1.5.2.2  jdolecek 	/* enable drop for each vf */
   4701  1.5.2.2  jdolecek 	for (int i = 0; i < adapter->num_vfs; i++) {
   4702  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_QDE,
   4703  1.5.2.2  jdolecek 		    (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT) |
   4704  1.5.2.2  jdolecek 		    IXGBE_QDE_ENABLE));
   4705  1.5.2.2  jdolecek 	}
   4706  1.5.2.2  jdolecek } /* ixgbe_enable_rx_drop */
   4707      1.1    dyoung 
   4708  1.5.2.2  jdolecek /************************************************************************
   4709  1.5.2.2  jdolecek  * ixgbe_disable_rx_drop
   4710  1.5.2.2  jdolecek  ************************************************************************/
   4711  1.5.2.2  jdolecek static void
   4712  1.5.2.2  jdolecek ixgbe_disable_rx_drop(struct adapter *adapter)
   4713  1.5.2.2  jdolecek {
   4714  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   4715  1.5.2.2  jdolecek 	struct rx_ring  *rxr;
   4716  1.5.2.2  jdolecek 	u32             srrctl;
   4717      1.1    dyoung 
   4718  1.5.2.2  jdolecek 	for (int i = 0; i < adapter->num_queues; i++) {
   4719  1.5.2.2  jdolecek 		rxr = &adapter->rx_rings[i];
   4720  1.5.2.2  jdolecek         	srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
   4721  1.5.2.2  jdolecek         	srrctl &= ~IXGBE_SRRCTL_DROP_EN;
   4722  1.5.2.2  jdolecek         	IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
   4723      1.1    dyoung 	}
   4724      1.1    dyoung 
   4725  1.5.2.2  jdolecek 	/* disable drop for each vf */
   4726  1.5.2.2  jdolecek 	for (int i = 0; i < adapter->num_vfs; i++) {
   4727  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(hw, IXGBE_QDE,
   4728  1.5.2.2  jdolecek 		    (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT)));
   4729      1.1    dyoung 	}
   4730  1.5.2.2  jdolecek } /* ixgbe_disable_rx_drop */
   4731      1.1    dyoung 
   4732  1.5.2.2  jdolecek /************************************************************************
   4733  1.5.2.2  jdolecek  * ixgbe_sysctl_advertise
   4734  1.5.2.2  jdolecek  *
   4735  1.5.2.2  jdolecek  *   SYSCTL wrapper around setting advertised speed
   4736  1.5.2.2  jdolecek  ************************************************************************/
   4737  1.5.2.2  jdolecek static int
   4738  1.5.2.2  jdolecek ixgbe_sysctl_advertise(SYSCTLFN_ARGS)
   4739  1.5.2.2  jdolecek {
   4740  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   4741  1.5.2.2  jdolecek 	struct adapter *adapter = (struct adapter *)node.sysctl_data;
   4742  1.5.2.2  jdolecek 	int            error = 0, advertise;
   4743      1.1    dyoung 
   4744  1.5.2.2  jdolecek 	advertise = adapter->advertise;
   4745  1.5.2.2  jdolecek 	node.sysctl_data = &advertise;
   4746  1.5.2.2  jdolecek 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
   4747  1.5.2.2  jdolecek 	if (error != 0 || newp == NULL)
   4748  1.5.2.2  jdolecek 		return error;
   4749      1.1    dyoung 
   4750  1.5.2.2  jdolecek 	return ixgbe_set_advertise(adapter, advertise);
   4751  1.5.2.2  jdolecek } /* ixgbe_sysctl_advertise */
   4752  1.5.2.2  jdolecek 
   4753  1.5.2.2  jdolecek /************************************************************************
   4754  1.5.2.2  jdolecek  * ixgbe_set_advertise - Control advertised link speed
   4755      1.1    dyoung  *
   4756  1.5.2.2  jdolecek  *   Flags:
   4757  1.5.2.2  jdolecek  *     0x00 - Default (all capable link speed)
   4758  1.5.2.2  jdolecek  *     0x01 - advertise 100 Mb
   4759  1.5.2.2  jdolecek  *     0x02 - advertise 1G
   4760  1.5.2.2  jdolecek  *     0x04 - advertise 10G
   4761  1.5.2.2  jdolecek  *     0x08 - advertise 10 Mb
   4762  1.5.2.2  jdolecek  *     0x10 - advertise 2.5G
   4763  1.5.2.2  jdolecek  *     0x20 - advertise 5G
   4764  1.5.2.2  jdolecek  ************************************************************************/
   4765  1.5.2.2  jdolecek static int
   4766  1.5.2.2  jdolecek ixgbe_set_advertise(struct adapter *adapter, int advertise)
   4767      1.1    dyoung {
   4768  1.5.2.2  jdolecek 	device_t         dev;
   4769  1.5.2.2  jdolecek 	struct ixgbe_hw  *hw;
   4770  1.5.2.2  jdolecek 	ixgbe_link_speed speed = 0;
   4771  1.5.2.2  jdolecek 	ixgbe_link_speed link_caps = 0;
   4772  1.5.2.2  jdolecek 	s32              err = IXGBE_NOT_IMPLEMENTED;
   4773  1.5.2.2  jdolecek 	bool             negotiate = FALSE;
   4774      1.1    dyoung 
   4775  1.5.2.2  jdolecek 	/* Checks to validate new value */
   4776  1.5.2.2  jdolecek 	if (adapter->advertise == advertise) /* no change */
   4777  1.5.2.2  jdolecek 		return (0);
   4778  1.5.2.2  jdolecek 
   4779  1.5.2.2  jdolecek 	dev = adapter->dev;
   4780  1.5.2.2  jdolecek 	hw = &adapter->hw;
   4781      1.1    dyoung 
   4782  1.5.2.2  jdolecek 	/* No speed changes for backplane media */
   4783  1.5.2.2  jdolecek 	if (hw->phy.media_type == ixgbe_media_type_backplane)
   4784  1.5.2.2  jdolecek 		return (ENODEV);
   4785      1.1    dyoung 
   4786  1.5.2.2  jdolecek 	if (!((hw->phy.media_type == ixgbe_media_type_copper) ||
   4787  1.5.2.2  jdolecek 	    (hw->phy.multispeed_fiber))) {
   4788  1.5.2.2  jdolecek 		device_printf(dev,
   4789  1.5.2.2  jdolecek 		    "Advertised speed can only be set on copper or "
   4790  1.5.2.2  jdolecek 		    "multispeed fiber media types.\n");
   4791  1.5.2.2  jdolecek 		return (EINVAL);
   4792  1.5.2.2  jdolecek 	}
   4793  1.5.2.2  jdolecek 
   4794  1.5.2.2  jdolecek 	if (advertise < 0x0 || advertise > 0x2f) {
   4795  1.5.2.2  jdolecek 		device_printf(dev,
   4796  1.5.2.2  jdolecek 		    "Invalid advertised speed; valid modes are 0x0 through 0x7\n");
   4797  1.5.2.2  jdolecek 		return (EINVAL);
   4798  1.5.2.2  jdolecek 	}
   4799  1.5.2.2  jdolecek 
   4800  1.5.2.2  jdolecek 	if (hw->mac.ops.get_link_capabilities) {
   4801  1.5.2.2  jdolecek 		err = hw->mac.ops.get_link_capabilities(hw, &link_caps,
   4802  1.5.2.2  jdolecek 		    &negotiate);
   4803  1.5.2.2  jdolecek 		if (err != IXGBE_SUCCESS) {
   4804  1.5.2.2  jdolecek 			device_printf(dev, "Unable to determine supported advertise speeds\n");
   4805  1.5.2.2  jdolecek 			return (ENODEV);
   4806      1.1    dyoung 		}
   4807      1.1    dyoung 	}
   4808  1.5.2.2  jdolecek 
   4809  1.5.2.2  jdolecek 	/* Set new value and report new advertised mode */
   4810  1.5.2.2  jdolecek 	if (advertise & 0x1) {
   4811  1.5.2.2  jdolecek 		if (!(link_caps & IXGBE_LINK_SPEED_100_FULL)) {
   4812  1.5.2.2  jdolecek 			device_printf(dev, "Interface does not support 100Mb advertised speed\n");
   4813  1.5.2.2  jdolecek 			return (EINVAL);
   4814      1.1    dyoung 		}
   4815  1.5.2.2  jdolecek 		speed |= IXGBE_LINK_SPEED_100_FULL;
   4816      1.1    dyoung 	}
   4817  1.5.2.2  jdolecek 	if (advertise & 0x2) {
   4818  1.5.2.2  jdolecek 		if (!(link_caps & IXGBE_LINK_SPEED_1GB_FULL)) {
   4819  1.5.2.2  jdolecek 			device_printf(dev, "Interface does not support 1Gb advertised speed\n");
   4820  1.5.2.2  jdolecek 			return (EINVAL);
   4821  1.5.2.2  jdolecek 		}
   4822  1.5.2.2  jdolecek 		speed |= IXGBE_LINK_SPEED_1GB_FULL;
   4823  1.5.2.2  jdolecek 	}
   4824  1.5.2.2  jdolecek 	if (advertise & 0x4) {
   4825  1.5.2.2  jdolecek 		if (!(link_caps & IXGBE_LINK_SPEED_10GB_FULL)) {
   4826  1.5.2.2  jdolecek 			device_printf(dev, "Interface does not support 10Gb advertised speed\n");
   4827  1.5.2.2  jdolecek 			return (EINVAL);
   4828  1.5.2.2  jdolecek 		}
   4829  1.5.2.2  jdolecek 		speed |= IXGBE_LINK_SPEED_10GB_FULL;
   4830  1.5.2.2  jdolecek 	}
   4831  1.5.2.2  jdolecek 	if (advertise & 0x8) {
   4832  1.5.2.2  jdolecek 		if (!(link_caps & IXGBE_LINK_SPEED_10_FULL)) {
   4833  1.5.2.2  jdolecek 			device_printf(dev, "Interface does not support 10Mb advertised speed\n");
   4834  1.5.2.2  jdolecek 			return (EINVAL);
   4835  1.5.2.2  jdolecek 		}
   4836  1.5.2.2  jdolecek 		speed |= IXGBE_LINK_SPEED_10_FULL;
   4837  1.5.2.2  jdolecek 	}
   4838  1.5.2.2  jdolecek 	if (advertise & 0x10) {
   4839  1.5.2.2  jdolecek 		if (!(link_caps & IXGBE_LINK_SPEED_2_5GB_FULL)) {
   4840  1.5.2.2  jdolecek 			device_printf(dev, "Interface does not support 2.5Gb advertised speed\n");
   4841  1.5.2.2  jdolecek 			return (EINVAL);
   4842  1.5.2.2  jdolecek 		}
   4843  1.5.2.2  jdolecek 		speed |= IXGBE_LINK_SPEED_2_5GB_FULL;
   4844  1.5.2.2  jdolecek 	}
   4845  1.5.2.2  jdolecek 	if (advertise & 0x20) {
   4846  1.5.2.2  jdolecek 		if (!(link_caps & IXGBE_LINK_SPEED_5GB_FULL)) {
   4847  1.5.2.2  jdolecek 			device_printf(dev, "Interface does not support 5Gb advertised speed\n");
   4848  1.5.2.2  jdolecek 			return (EINVAL);
   4849  1.5.2.2  jdolecek 		}
   4850  1.5.2.2  jdolecek 		speed |= IXGBE_LINK_SPEED_5GB_FULL;
   4851  1.5.2.2  jdolecek 	}
   4852  1.5.2.2  jdolecek 	if (advertise == 0)
   4853  1.5.2.2  jdolecek 		speed = link_caps; /* All capable link speed */
   4854      1.1    dyoung 
   4855  1.5.2.2  jdolecek 	hw->mac.autotry_restart = TRUE;
   4856  1.5.2.2  jdolecek 	hw->mac.ops.setup_link(hw, speed, TRUE);
   4857  1.5.2.2  jdolecek 	adapter->advertise = advertise;
   4858      1.1    dyoung 
   4859  1.5.2.2  jdolecek 	return (0);
   4860  1.5.2.2  jdolecek } /* ixgbe_set_advertise */
   4861      1.1    dyoung 
   4862  1.5.2.2  jdolecek /************************************************************************
   4863  1.5.2.2  jdolecek  * ixgbe_get_advertise - Get current advertised speed settings
   4864  1.5.2.2  jdolecek  *
   4865  1.5.2.2  jdolecek  *   Formatted for sysctl usage.
   4866  1.5.2.2  jdolecek  *   Flags:
   4867  1.5.2.2  jdolecek  *     0x01 - advertise 100 Mb
   4868  1.5.2.2  jdolecek  *     0x02 - advertise 1G
   4869  1.5.2.2  jdolecek  *     0x04 - advertise 10G
   4870  1.5.2.2  jdolecek  *     0x08 - advertise 10 Mb (yes, Mb)
   4871  1.5.2.2  jdolecek  *     0x10 - advertise 2.5G
   4872  1.5.2.2  jdolecek  *     0x20 - advertise 5G
   4873  1.5.2.2  jdolecek  ************************************************************************/
   4874  1.5.2.2  jdolecek static int
   4875  1.5.2.2  jdolecek ixgbe_get_advertise(struct adapter *adapter)
   4876  1.5.2.2  jdolecek {
   4877  1.5.2.2  jdolecek 	struct ixgbe_hw  *hw = &adapter->hw;
   4878  1.5.2.2  jdolecek 	int              speed;
   4879  1.5.2.2  jdolecek 	ixgbe_link_speed link_caps = 0;
   4880  1.5.2.2  jdolecek 	s32              err;
   4881  1.5.2.2  jdolecek 	bool             negotiate = FALSE;
   4882      1.1    dyoung 
   4883  1.5.2.2  jdolecek 	/*
   4884  1.5.2.2  jdolecek 	 * Advertised speed means nothing unless it's copper or
   4885  1.5.2.2  jdolecek 	 * multi-speed fiber
   4886  1.5.2.2  jdolecek 	 */
   4887  1.5.2.2  jdolecek 	if (!(hw->phy.media_type == ixgbe_media_type_copper) &&
   4888  1.5.2.2  jdolecek 	    !(hw->phy.multispeed_fiber))
   4889  1.5.2.2  jdolecek 		return (0);
   4890      1.1    dyoung 
   4891  1.5.2.2  jdolecek 	err = hw->mac.ops.get_link_capabilities(hw, &link_caps, &negotiate);
   4892  1.5.2.2  jdolecek 	if (err != IXGBE_SUCCESS)
   4893  1.5.2.2  jdolecek 		return (0);
   4894      1.1    dyoung 
   4895  1.5.2.2  jdolecek 	speed =
   4896  1.5.2.2  jdolecek 	    ((link_caps & IXGBE_LINK_SPEED_10GB_FULL)  ? 0x04 : 0) |
   4897  1.5.2.2  jdolecek 	    ((link_caps & IXGBE_LINK_SPEED_1GB_FULL)   ? 0x02 : 0) |
   4898  1.5.2.2  jdolecek 	    ((link_caps & IXGBE_LINK_SPEED_100_FULL)   ? 0x01 : 0) |
   4899  1.5.2.2  jdolecek 	    ((link_caps & IXGBE_LINK_SPEED_10_FULL)    ? 0x08 : 0) |
   4900  1.5.2.2  jdolecek 	    ((link_caps & IXGBE_LINK_SPEED_2_5GB_FULL) ? 0x10 : 0) |
   4901  1.5.2.2  jdolecek 	    ((link_caps & IXGBE_LINK_SPEED_5GB_FULL)   ? 0x20 : 0);
   4902  1.5.2.2  jdolecek 
   4903  1.5.2.2  jdolecek 	return speed;
   4904  1.5.2.2  jdolecek } /* ixgbe_get_advertise */
   4905  1.5.2.2  jdolecek 
   4906  1.5.2.2  jdolecek /************************************************************************
   4907  1.5.2.2  jdolecek  * ixgbe_sysctl_dmac - Manage DMA Coalescing
   4908  1.5.2.2  jdolecek  *
   4909  1.5.2.2  jdolecek  *   Control values:
   4910  1.5.2.2  jdolecek  *     0/1 - off / on (use default value of 1000)
   4911  1.5.2.2  jdolecek  *
   4912  1.5.2.2  jdolecek  *     Legal timer values are:
   4913  1.5.2.2  jdolecek  *     50,100,250,500,1000,2000,5000,10000
   4914  1.5.2.2  jdolecek  *
   4915  1.5.2.2  jdolecek  *     Turning off interrupt moderation will also turn this off.
   4916  1.5.2.2  jdolecek  ************************************************************************/
   4917  1.5.2.2  jdolecek static int
   4918  1.5.2.2  jdolecek ixgbe_sysctl_dmac(SYSCTLFN_ARGS)
   4919      1.1    dyoung {
   4920  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   4921  1.5.2.2  jdolecek 	struct adapter *adapter = (struct adapter *)node.sysctl_data;
   4922  1.5.2.2  jdolecek 	struct ifnet   *ifp = adapter->ifp;
   4923  1.5.2.2  jdolecek 	int            error;
   4924  1.5.2.2  jdolecek 	int            newval;
   4925      1.1    dyoung 
   4926  1.5.2.2  jdolecek 	newval = adapter->dmac;
   4927  1.5.2.2  jdolecek 	node.sysctl_data = &newval;
   4928  1.5.2.2  jdolecek 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
   4929  1.5.2.2  jdolecek 	if ((error) || (newp == NULL))
   4930  1.5.2.2  jdolecek 		return (error);
   4931      1.1    dyoung 
   4932  1.5.2.2  jdolecek 	switch (newval) {
   4933  1.5.2.2  jdolecek 	case 0:
   4934  1.5.2.2  jdolecek 		/* Disabled */
   4935  1.5.2.2  jdolecek 		adapter->dmac = 0;
   4936  1.5.2.2  jdolecek 		break;
   4937  1.5.2.2  jdolecek 	case 1:
   4938  1.5.2.2  jdolecek 		/* Enable and use default */
   4939  1.5.2.2  jdolecek 		adapter->dmac = 1000;
   4940  1.5.2.2  jdolecek 		break;
   4941  1.5.2.2  jdolecek 	case 50:
   4942  1.5.2.2  jdolecek 	case 100:
   4943  1.5.2.2  jdolecek 	case 250:
   4944  1.5.2.2  jdolecek 	case 500:
   4945  1.5.2.2  jdolecek 	case 1000:
   4946  1.5.2.2  jdolecek 	case 2000:
   4947  1.5.2.2  jdolecek 	case 5000:
   4948  1.5.2.2  jdolecek 	case 10000:
   4949  1.5.2.2  jdolecek 		/* Legal values - allow */
   4950  1.5.2.2  jdolecek 		adapter->dmac = newval;
   4951  1.5.2.2  jdolecek 		break;
   4952  1.5.2.2  jdolecek 	default:
   4953  1.5.2.2  jdolecek 		/* Do nothing, illegal value */
   4954  1.5.2.2  jdolecek 		return (EINVAL);
   4955  1.5.2.2  jdolecek 	}
   4956      1.1    dyoung 
   4957  1.5.2.2  jdolecek 	/* Re-initialize hardware if it's already running */
   4958  1.5.2.2  jdolecek 	if (ifp->if_flags & IFF_RUNNING)
   4959  1.5.2.2  jdolecek 		ixgbe_init(ifp);
   4960  1.5.2.2  jdolecek 
   4961  1.5.2.2  jdolecek 	return (0);
   4962      1.1    dyoung }
   4963      1.1    dyoung 
   4964  1.5.2.2  jdolecek #ifdef IXGBE_DEBUG
   4965  1.5.2.2  jdolecek /************************************************************************
   4966  1.5.2.2  jdolecek  * ixgbe_sysctl_power_state
   4967  1.5.2.2  jdolecek  *
   4968  1.5.2.2  jdolecek  *   Sysctl to test power states
   4969  1.5.2.2  jdolecek  *   Values:
   4970  1.5.2.2  jdolecek  *     0      - set device to D0
   4971  1.5.2.2  jdolecek  *     3      - set device to D3
   4972  1.5.2.2  jdolecek  *     (none) - get current device power state
   4973  1.5.2.2  jdolecek  ************************************************************************/
   4974  1.5.2.2  jdolecek static int
   4975  1.5.2.2  jdolecek ixgbe_sysctl_power_state(SYSCTLFN_ARGS)
   4976      1.1    dyoung {
   4977  1.5.2.2  jdolecek #ifdef notyet
   4978  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   4979  1.5.2.2  jdolecek 	struct adapter *adapter = (struct adapter *)node.sysctl_data;
   4980  1.5.2.2  jdolecek 	device_t       dev =  adapter->dev;
   4981  1.5.2.2  jdolecek 	int            curr_ps, new_ps, error = 0;
   4982      1.1    dyoung 
   4983  1.5.2.2  jdolecek 	curr_ps = new_ps = pci_get_powerstate(dev);
   4984      1.1    dyoung 
   4985  1.5.2.2  jdolecek 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
   4986  1.5.2.2  jdolecek 	if ((error) || (req->newp == NULL))
   4987  1.5.2.2  jdolecek 		return (error);
   4988      1.1    dyoung 
   4989  1.5.2.2  jdolecek 	if (new_ps == curr_ps)
   4990  1.5.2.2  jdolecek 		return (0);
   4991      1.1    dyoung 
   4992  1.5.2.2  jdolecek 	if (new_ps == 3 && curr_ps == 0)
   4993  1.5.2.2  jdolecek 		error = DEVICE_SUSPEND(dev);
   4994  1.5.2.2  jdolecek 	else if (new_ps == 0 && curr_ps == 3)
   4995  1.5.2.2  jdolecek 		error = DEVICE_RESUME(dev);
   4996  1.5.2.2  jdolecek 	else
   4997  1.5.2.2  jdolecek 		return (EINVAL);
   4998      1.1    dyoung 
   4999  1.5.2.2  jdolecek 	device_printf(dev, "New state: %d\n", pci_get_powerstate(dev));
   5000      1.1    dyoung 
   5001  1.5.2.2  jdolecek 	return (error);
   5002  1.5.2.2  jdolecek #else
   5003  1.5.2.2  jdolecek 	return 0;
   5004  1.5.2.2  jdolecek #endif
   5005  1.5.2.2  jdolecek } /* ixgbe_sysctl_power_state */
   5006      1.1    dyoung #endif
   5007      1.1    dyoung 
   5008  1.5.2.2  jdolecek /************************************************************************
   5009  1.5.2.2  jdolecek  * ixgbe_sysctl_wol_enable
   5010  1.5.2.2  jdolecek  *
   5011  1.5.2.2  jdolecek  *   Sysctl to enable/disable the WoL capability,
   5012  1.5.2.2  jdolecek  *   if supported by the adapter.
   5013  1.5.2.2  jdolecek  *
   5014  1.5.2.2  jdolecek  *   Values:
   5015  1.5.2.2  jdolecek  *     0 - disabled
   5016  1.5.2.2  jdolecek  *     1 - enabled
   5017  1.5.2.2  jdolecek  ************************************************************************/
   5018  1.5.2.2  jdolecek static int
   5019  1.5.2.2  jdolecek ixgbe_sysctl_wol_enable(SYSCTLFN_ARGS)
   5020  1.5.2.2  jdolecek {
   5021  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   5022  1.5.2.2  jdolecek 	struct adapter  *adapter = (struct adapter *)node.sysctl_data;
   5023  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   5024  1.5.2.2  jdolecek 	bool            new_wol_enabled;
   5025  1.5.2.2  jdolecek 	int             error = 0;
   5026      1.1    dyoung 
   5027  1.5.2.2  jdolecek 	new_wol_enabled = hw->wol_enabled;
   5028  1.5.2.2  jdolecek 	node.sysctl_data = &new_wol_enabled;
   5029  1.5.2.2  jdolecek 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
   5030  1.5.2.2  jdolecek 	if ((error) || (newp == NULL))
   5031  1.5.2.2  jdolecek 		return (error);
   5032  1.5.2.2  jdolecek 	if (new_wol_enabled == hw->wol_enabled)
   5033  1.5.2.2  jdolecek 		return (0);
   5034      1.1    dyoung 
   5035  1.5.2.2  jdolecek 	if (new_wol_enabled && !adapter->wol_support)
   5036  1.5.2.2  jdolecek 		return (ENODEV);
   5037  1.5.2.2  jdolecek 	else
   5038  1.5.2.2  jdolecek 		hw->wol_enabled = new_wol_enabled;
   5039      1.1    dyoung 
   5040  1.5.2.2  jdolecek 	return (0);
   5041  1.5.2.2  jdolecek } /* ixgbe_sysctl_wol_enable */
   5042      1.1    dyoung 
   5043  1.5.2.2  jdolecek /************************************************************************
   5044  1.5.2.2  jdolecek  * ixgbe_sysctl_wufc - Wake Up Filter Control
   5045  1.5.2.2  jdolecek  *
   5046  1.5.2.2  jdolecek  *   Sysctl to enable/disable the types of packets that the
   5047  1.5.2.2  jdolecek  *   adapter will wake up on upon receipt.
   5048  1.5.2.2  jdolecek  *   Flags:
   5049  1.5.2.2  jdolecek  *     0x1  - Link Status Change
   5050  1.5.2.2  jdolecek  *     0x2  - Magic Packet
   5051  1.5.2.2  jdolecek  *     0x4  - Direct Exact
   5052  1.5.2.2  jdolecek  *     0x8  - Directed Multicast
   5053  1.5.2.2  jdolecek  *     0x10 - Broadcast
   5054  1.5.2.2  jdolecek  *     0x20 - ARP/IPv4 Request Packet
   5055  1.5.2.2  jdolecek  *     0x40 - Direct IPv4 Packet
   5056  1.5.2.2  jdolecek  *     0x80 - Direct IPv6 Packet
   5057  1.5.2.2  jdolecek  *
   5058  1.5.2.2  jdolecek  *   Settings not listed above will cause the sysctl to return an error.
   5059  1.5.2.2  jdolecek  ************************************************************************/
   5060  1.5.2.2  jdolecek static int
   5061  1.5.2.2  jdolecek ixgbe_sysctl_wufc(SYSCTLFN_ARGS)
   5062      1.1    dyoung {
   5063  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   5064  1.5.2.2  jdolecek 	struct adapter *adapter = (struct adapter *)node.sysctl_data;
   5065  1.5.2.2  jdolecek 	int error = 0;
   5066  1.5.2.2  jdolecek 	u32 new_wufc;
   5067      1.1    dyoung 
   5068  1.5.2.2  jdolecek 	new_wufc = adapter->wufc;
   5069  1.5.2.2  jdolecek 	node.sysctl_data = &new_wufc;
   5070  1.5.2.2  jdolecek 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
   5071  1.5.2.2  jdolecek 	if ((error) || (newp == NULL))
   5072  1.5.2.2  jdolecek 		return (error);
   5073  1.5.2.2  jdolecek 	if (new_wufc == adapter->wufc)
   5074  1.5.2.2  jdolecek 		return (0);
   5075      1.1    dyoung 
   5076  1.5.2.2  jdolecek 	if (new_wufc & 0xffffff00)
   5077  1.5.2.2  jdolecek 		return (EINVAL);
   5078      1.1    dyoung 
   5079  1.5.2.2  jdolecek 	new_wufc &= 0xff;
   5080  1.5.2.2  jdolecek 	new_wufc |= (0xffffff & adapter->wufc);
   5081  1.5.2.2  jdolecek 	adapter->wufc = new_wufc;
   5082      1.1    dyoung 
   5083  1.5.2.2  jdolecek 	return (0);
   5084  1.5.2.2  jdolecek } /* ixgbe_sysctl_wufc */
   5085      1.1    dyoung 
   5086  1.5.2.2  jdolecek #ifdef IXGBE_DEBUG
   5087  1.5.2.2  jdolecek /************************************************************************
   5088  1.5.2.2  jdolecek  * ixgbe_sysctl_print_rss_config
   5089  1.5.2.2  jdolecek  ************************************************************************/
   5090  1.5.2.2  jdolecek static int
   5091  1.5.2.2  jdolecek ixgbe_sysctl_print_rss_config(SYSCTLFN_ARGS)
   5092      1.1    dyoung {
   5093  1.5.2.2  jdolecek #ifdef notyet
   5094  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   5095  1.5.2.2  jdolecek 	struct adapter  *adapter = (struct adapter *)node.sysctl_data;
   5096      1.1    dyoung 	struct ixgbe_hw *hw = &adapter->hw;
   5097  1.5.2.2  jdolecek 	device_t        dev = adapter->dev;
   5098  1.5.2.2  jdolecek 	struct sbuf     *buf;
   5099  1.5.2.2  jdolecek 	int             error = 0, reta_size;
   5100  1.5.2.2  jdolecek 	u32             reg;
   5101  1.5.2.2  jdolecek 
   5102  1.5.2.2  jdolecek 	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
   5103  1.5.2.2  jdolecek 	if (!buf) {
   5104  1.5.2.2  jdolecek 		device_printf(dev, "Could not allocate sbuf for output.\n");
   5105  1.5.2.2  jdolecek 		return (ENOMEM);
   5106  1.5.2.2  jdolecek 	}
   5107  1.5.2.2  jdolecek 
   5108  1.5.2.2  jdolecek 	// TODO: use sbufs to make a string to print out
   5109  1.5.2.2  jdolecek 	/* Set multiplier for RETA setup and table size based on MAC */
   5110  1.5.2.2  jdolecek 	switch (adapter->hw.mac.type) {
   5111  1.5.2.2  jdolecek 	case ixgbe_mac_X550:
   5112  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
   5113  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
   5114  1.5.2.2  jdolecek 		reta_size = 128;
   5115      1.1    dyoung 		break;
   5116      1.1    dyoung 	default:
   5117  1.5.2.2  jdolecek 		reta_size = 32;
   5118      1.1    dyoung 		break;
   5119      1.1    dyoung 	}
   5120      1.1    dyoung 
   5121  1.5.2.2  jdolecek 	/* Print out the redirection table */
   5122  1.5.2.2  jdolecek 	sbuf_cat(buf, "\n");
   5123  1.5.2.2  jdolecek 	for (int i = 0; i < reta_size; i++) {
   5124  1.5.2.2  jdolecek 		if (i < 32) {
   5125  1.5.2.2  jdolecek 			reg = IXGBE_READ_REG(hw, IXGBE_RETA(i));
   5126  1.5.2.2  jdolecek 			sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg);
   5127  1.5.2.2  jdolecek 		} else {
   5128  1.5.2.2  jdolecek 			reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32));
   5129  1.5.2.2  jdolecek 			sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg);
   5130  1.5.2.2  jdolecek 		}
   5131  1.5.2.2  jdolecek 	}
   5132      1.1    dyoung 
   5133  1.5.2.2  jdolecek 	// TODO: print more config
   5134      1.1    dyoung 
   5135  1.5.2.2  jdolecek 	error = sbuf_finish(buf);
   5136  1.5.2.2  jdolecek 	if (error)
   5137  1.5.2.2  jdolecek 		device_printf(dev, "Error finishing sbuf: %d\n", error);
   5138      1.1    dyoung 
   5139  1.5.2.2  jdolecek 	sbuf_delete(buf);
   5140  1.5.2.2  jdolecek #endif
   5141  1.5.2.2  jdolecek 	return (0);
   5142  1.5.2.2  jdolecek } /* ixgbe_sysctl_print_rss_config */
   5143  1.5.2.2  jdolecek #endif /* IXGBE_DEBUG */
   5144      1.1    dyoung 
   5145  1.5.2.2  jdolecek /************************************************************************
   5146  1.5.2.2  jdolecek  * ixgbe_sysctl_phy_temp - Retrieve temperature of PHY
   5147  1.5.2.2  jdolecek  *
   5148  1.5.2.2  jdolecek  *   For X552/X557-AT devices using an external PHY
   5149  1.5.2.2  jdolecek  ************************************************************************/
   5150  1.5.2.2  jdolecek static int
   5151  1.5.2.2  jdolecek ixgbe_sysctl_phy_temp(SYSCTLFN_ARGS)
   5152      1.1    dyoung {
   5153  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   5154  1.5.2.2  jdolecek 	struct adapter	*adapter = (struct adapter *)node.sysctl_data;
   5155  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   5156  1.5.2.2  jdolecek 	int val;
   5157  1.5.2.2  jdolecek 	u16 reg;
   5158  1.5.2.2  jdolecek 	int		error;
   5159      1.1    dyoung 
   5160  1.5.2.2  jdolecek 	if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
   5161  1.5.2.2  jdolecek 		device_printf(adapter->dev,
   5162  1.5.2.2  jdolecek 		    "Device has no supported external thermal sensor.\n");
   5163  1.5.2.2  jdolecek 		return (ENODEV);
   5164      1.1    dyoung 	}
   5165      1.1    dyoung 
   5166  1.5.2.2  jdolecek 	if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP,
   5167  1.5.2.2  jdolecek 		IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &reg)) {
   5168  1.5.2.2  jdolecek 		device_printf(adapter->dev,
   5169  1.5.2.2  jdolecek 		    "Error reading from PHY's current temperature register\n");
   5170  1.5.2.2  jdolecek 		return (EAGAIN);
   5171  1.5.2.2  jdolecek 	}
   5172      1.1    dyoung 
   5173  1.5.2.2  jdolecek 	node.sysctl_data = &val;
   5174      1.1    dyoung 
   5175  1.5.2.2  jdolecek 	/* Shift temp for output */
   5176  1.5.2.2  jdolecek 	val = reg >> 8;
   5177  1.5.2.2  jdolecek 
   5178  1.5.2.2  jdolecek 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
   5179  1.5.2.2  jdolecek 	if ((error) || (newp == NULL))
   5180  1.5.2.2  jdolecek 		return (error);
   5181  1.5.2.2  jdolecek 
   5182  1.5.2.2  jdolecek 	return (0);
   5183  1.5.2.2  jdolecek } /* ixgbe_sysctl_phy_temp */
   5184  1.5.2.2  jdolecek 
   5185  1.5.2.2  jdolecek /************************************************************************
   5186  1.5.2.2  jdolecek  * ixgbe_sysctl_phy_overtemp_occurred
   5187  1.5.2.2  jdolecek  *
   5188  1.5.2.2  jdolecek  *   Reports (directly from the PHY) whether the current PHY
   5189  1.5.2.2  jdolecek  *   temperature is over the overtemp threshold.
   5190  1.5.2.2  jdolecek  ************************************************************************/
   5191  1.5.2.2  jdolecek static int
   5192  1.5.2.2  jdolecek ixgbe_sysctl_phy_overtemp_occurred(SYSCTLFN_ARGS)
   5193      1.1    dyoung {
   5194  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   5195  1.5.2.2  jdolecek 	struct adapter	*adapter = (struct adapter *)node.sysctl_data;
   5196      1.1    dyoung 	struct ixgbe_hw *hw = &adapter->hw;
   5197  1.5.2.2  jdolecek 	int val, error;
   5198  1.5.2.2  jdolecek 	u16 reg;
   5199      1.1    dyoung 
   5200  1.5.2.2  jdolecek 	if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
   5201  1.5.2.2  jdolecek 		device_printf(adapter->dev,
   5202  1.5.2.2  jdolecek 		    "Device has no supported external thermal sensor.\n");
   5203  1.5.2.2  jdolecek 		return (ENODEV);
   5204      1.1    dyoung 	}
   5205      1.1    dyoung 
   5206  1.5.2.2  jdolecek 	if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS,
   5207  1.5.2.2  jdolecek 		IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &reg)) {
   5208  1.5.2.2  jdolecek 		device_printf(adapter->dev,
   5209  1.5.2.2  jdolecek 		    "Error reading from PHY's temperature status register\n");
   5210  1.5.2.2  jdolecek 		return (EAGAIN);
   5211  1.5.2.2  jdolecek 	}
   5212      1.1    dyoung 
   5213  1.5.2.2  jdolecek 	node.sysctl_data = &val;
   5214      1.1    dyoung 
   5215  1.5.2.2  jdolecek 	/* Get occurrence bit */
   5216  1.5.2.2  jdolecek 	val = !!(reg & 0x4000);
   5217      1.1    dyoung 
   5218  1.5.2.2  jdolecek 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
   5219  1.5.2.2  jdolecek 	if ((error) || (newp == NULL))
   5220  1.5.2.2  jdolecek 		return (error);
   5221      1.1    dyoung 
   5222  1.5.2.2  jdolecek 	return (0);
   5223  1.5.2.2  jdolecek } /* ixgbe_sysctl_phy_overtemp_occurred */
   5224      1.1    dyoung 
   5225  1.5.2.2  jdolecek /************************************************************************
   5226  1.5.2.2  jdolecek  * ixgbe_sysctl_eee_state
   5227      1.1    dyoung  *
   5228  1.5.2.2  jdolecek  *   Sysctl to set EEE power saving feature
   5229  1.5.2.2  jdolecek  *   Values:
   5230  1.5.2.2  jdolecek  *     0      - disable EEE
   5231  1.5.2.2  jdolecek  *     1      - enable EEE
   5232  1.5.2.2  jdolecek  *     (none) - get current device EEE state
   5233  1.5.2.2  jdolecek  ************************************************************************/
   5234  1.5.2.2  jdolecek static int
   5235  1.5.2.2  jdolecek ixgbe_sysctl_eee_state(SYSCTLFN_ARGS)
   5236      1.1    dyoung {
   5237  1.5.2.2  jdolecek 	struct sysctlnode node = *rnode;
   5238  1.5.2.2  jdolecek 	struct adapter *adapter = (struct adapter *)node.sysctl_data;
   5239      1.1    dyoung 	struct ifnet   *ifp = adapter->ifp;
   5240  1.5.2.2  jdolecek 	device_t       dev = adapter->dev;
   5241  1.5.2.2  jdolecek 	int            curr_eee, new_eee, error = 0;
   5242  1.5.2.2  jdolecek 	s32            retval;
   5243      1.1    dyoung 
   5244  1.5.2.2  jdolecek 	curr_eee = new_eee = !!(adapter->feat_en & IXGBE_FEATURE_EEE);
   5245  1.5.2.2  jdolecek 	node.sysctl_data = &new_eee;
   5246  1.5.2.2  jdolecek 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
   5247  1.5.2.2  jdolecek 	if ((error) || (newp == NULL))
   5248  1.5.2.2  jdolecek 		return (error);
   5249      1.1    dyoung 
   5250  1.5.2.2  jdolecek 	/* Nothing to do */
   5251  1.5.2.2  jdolecek 	if (new_eee == curr_eee)
   5252  1.5.2.2  jdolecek 		return (0);
   5253      1.1    dyoung 
   5254  1.5.2.2  jdolecek 	/* Not supported */
   5255  1.5.2.2  jdolecek 	if (!(adapter->feat_cap & IXGBE_FEATURE_EEE))
   5256  1.5.2.2  jdolecek 		return (EINVAL);
   5257      1.1    dyoung 
   5258  1.5.2.2  jdolecek 	/* Bounds checking */
   5259  1.5.2.2  jdolecek 	if ((new_eee < 0) || (new_eee > 1))
   5260  1.5.2.2  jdolecek 		return (EINVAL);
   5261      1.1    dyoung 
   5262  1.5.2.2  jdolecek 	retval = adapter->hw.mac.ops.setup_eee(&adapter->hw, new_eee);
   5263  1.5.2.2  jdolecek 	if (retval) {
   5264  1.5.2.2  jdolecek 		device_printf(dev, "Error in EEE setup: 0x%08X\n", retval);
   5265  1.5.2.2  jdolecek 		return (EINVAL);
   5266      1.1    dyoung 	}
   5267      1.1    dyoung 
   5268  1.5.2.2  jdolecek 	/* Restart auto-neg */
   5269  1.5.2.2  jdolecek 	ixgbe_init(ifp);
   5270      1.1    dyoung 
   5271  1.5.2.2  jdolecek 	device_printf(dev, "New EEE state: %d\n", new_eee);
   5272      1.1    dyoung 
   5273  1.5.2.2  jdolecek 	/* Cache new value */
   5274  1.5.2.2  jdolecek 	if (new_eee)
   5275  1.5.2.2  jdolecek 		adapter->feat_en |= IXGBE_FEATURE_EEE;
   5276  1.5.2.2  jdolecek 	else
   5277  1.5.2.2  jdolecek 		adapter->feat_en &= ~IXGBE_FEATURE_EEE;
   5278  1.5.2.2  jdolecek 
   5279  1.5.2.2  jdolecek 	return (error);
   5280  1.5.2.2  jdolecek } /* ixgbe_sysctl_eee_state */
   5281  1.5.2.2  jdolecek 
   5282  1.5.2.2  jdolecek /************************************************************************
   5283  1.5.2.2  jdolecek  * ixgbe_init_device_features
   5284  1.5.2.2  jdolecek  ************************************************************************/
   5285  1.5.2.2  jdolecek static void
   5286  1.5.2.2  jdolecek ixgbe_init_device_features(struct adapter *adapter)
   5287  1.5.2.2  jdolecek {
   5288  1.5.2.2  jdolecek 	adapter->feat_cap = IXGBE_FEATURE_NETMAP
   5289  1.5.2.2  jdolecek 	                  | IXGBE_FEATURE_RSS
   5290  1.5.2.2  jdolecek 	                  | IXGBE_FEATURE_MSI
   5291  1.5.2.2  jdolecek 	                  | IXGBE_FEATURE_MSIX
   5292  1.5.2.2  jdolecek 	                  | IXGBE_FEATURE_LEGACY_IRQ
   5293  1.5.2.2  jdolecek 	                  | IXGBE_FEATURE_LEGACY_TX;
   5294  1.5.2.2  jdolecek 
   5295  1.5.2.2  jdolecek 	/* Set capabilities first... */
   5296  1.5.2.2  jdolecek 	switch (adapter->hw.mac.type) {
   5297  1.5.2.2  jdolecek 	case ixgbe_mac_82598EB:
   5298  1.5.2.2  jdolecek 		if (adapter->hw.device_id == IXGBE_DEV_ID_82598AT)
   5299  1.5.2.2  jdolecek 			adapter->feat_cap |= IXGBE_FEATURE_FAN_FAIL;
   5300  1.5.2.2  jdolecek 		break;
   5301  1.5.2.2  jdolecek 	case ixgbe_mac_X540:
   5302  1.5.2.2  jdolecek 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
   5303  1.5.2.2  jdolecek 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
   5304  1.5.2.2  jdolecek 		if ((adapter->hw.device_id == IXGBE_DEV_ID_X540_BYPASS) &&
   5305  1.5.2.2  jdolecek 		    (adapter->hw.bus.func == 0))
   5306  1.5.2.2  jdolecek 			adapter->feat_cap |= IXGBE_FEATURE_BYPASS;
   5307  1.5.2.2  jdolecek 		break;
   5308  1.5.2.2  jdolecek 	case ixgbe_mac_X550:
   5309  1.5.2.2  jdolecek 		adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR;
   5310  1.5.2.2  jdolecek 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
   5311  1.5.2.2  jdolecek 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
   5312  1.5.2.2  jdolecek 		break;
   5313  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
   5314  1.5.2.2  jdolecek 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
   5315  1.5.2.2  jdolecek 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
   5316  1.5.2.2  jdolecek 		if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_X_KR)
   5317  1.5.2.2  jdolecek 			adapter->feat_cap |= IXGBE_FEATURE_EEE;
   5318  1.5.2.2  jdolecek 		break;
   5319  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
   5320  1.5.2.2  jdolecek 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
   5321  1.5.2.2  jdolecek 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
   5322  1.5.2.2  jdolecek 		adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ;
   5323  1.5.2.2  jdolecek 		if ((adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T) ||
   5324  1.5.2.2  jdolecek 		    (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) {
   5325  1.5.2.2  jdolecek 			adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR;
   5326  1.5.2.2  jdolecek 			adapter->feat_cap |= IXGBE_FEATURE_EEE;
   5327  1.5.2.2  jdolecek 		}
   5328  1.5.2.2  jdolecek 		break;
   5329  1.5.2.2  jdolecek 	case ixgbe_mac_82599EB:
   5330  1.5.2.2  jdolecek 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
   5331  1.5.2.2  jdolecek 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
   5332  1.5.2.2  jdolecek 		if ((adapter->hw.device_id == IXGBE_DEV_ID_82599_BYPASS) &&
   5333  1.5.2.2  jdolecek 		    (adapter->hw.bus.func == 0))
   5334  1.5.2.2  jdolecek 			adapter->feat_cap |= IXGBE_FEATURE_BYPASS;
   5335  1.5.2.2  jdolecek 		if (adapter->hw.device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP)
   5336  1.5.2.2  jdolecek 			adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ;
   5337  1.5.2.2  jdolecek 		break;
   5338  1.5.2.2  jdolecek 	default:
   5339  1.5.2.2  jdolecek 		break;
   5340      1.1    dyoung 	}
   5341      1.1    dyoung 
   5342  1.5.2.2  jdolecek 	/* Enabled by default... */
   5343  1.5.2.2  jdolecek 	/* Fan failure detection */
   5344  1.5.2.2  jdolecek 	if (adapter->feat_cap & IXGBE_FEATURE_FAN_FAIL)
   5345  1.5.2.2  jdolecek 		adapter->feat_en |= IXGBE_FEATURE_FAN_FAIL;
   5346  1.5.2.2  jdolecek 	/* Netmap */
   5347  1.5.2.2  jdolecek 	if (adapter->feat_cap & IXGBE_FEATURE_NETMAP)
   5348  1.5.2.2  jdolecek 		adapter->feat_en |= IXGBE_FEATURE_NETMAP;
   5349  1.5.2.2  jdolecek 	/* EEE */
   5350  1.5.2.2  jdolecek 	if (adapter->feat_cap & IXGBE_FEATURE_EEE)
   5351  1.5.2.2  jdolecek 		adapter->feat_en |= IXGBE_FEATURE_EEE;
   5352  1.5.2.2  jdolecek 	/* Thermal Sensor */
   5353  1.5.2.2  jdolecek 	if (adapter->feat_cap & IXGBE_FEATURE_TEMP_SENSOR)
   5354  1.5.2.2  jdolecek 		adapter->feat_en |= IXGBE_FEATURE_TEMP_SENSOR;
   5355  1.5.2.2  jdolecek 
   5356  1.5.2.2  jdolecek 	/* Enabled via global sysctl... */
   5357  1.5.2.2  jdolecek 	/* Flow Director */
   5358  1.5.2.2  jdolecek 	if (ixgbe_enable_fdir) {
   5359  1.5.2.2  jdolecek 		if (adapter->feat_cap & IXGBE_FEATURE_FDIR)
   5360  1.5.2.2  jdolecek 			adapter->feat_en |= IXGBE_FEATURE_FDIR;
   5361  1.5.2.2  jdolecek 		else
   5362  1.5.2.2  jdolecek 			device_printf(adapter->dev, "Device does not support Flow Director. Leaving disabled.");
   5363  1.5.2.2  jdolecek 	}
   5364  1.5.2.2  jdolecek 	/* Legacy (single queue) transmit */
   5365  1.5.2.2  jdolecek 	if ((adapter->feat_cap & IXGBE_FEATURE_LEGACY_TX) &&
   5366  1.5.2.2  jdolecek 	    ixgbe_enable_legacy_tx)
   5367  1.5.2.2  jdolecek 		adapter->feat_en |= IXGBE_FEATURE_LEGACY_TX;
   5368  1.5.2.2  jdolecek 	/*
   5369  1.5.2.2  jdolecek 	 * Message Signal Interrupts - Extended (MSI-X)
   5370  1.5.2.2  jdolecek 	 * Normal MSI is only enabled if MSI-X calls fail.
   5371  1.5.2.2  jdolecek 	 */
   5372  1.5.2.2  jdolecek 	if (!ixgbe_enable_msix)
   5373  1.5.2.2  jdolecek 		adapter->feat_cap &= ~IXGBE_FEATURE_MSIX;
   5374  1.5.2.2  jdolecek 	/* Receive-Side Scaling (RSS) */
   5375  1.5.2.2  jdolecek 	if ((adapter->feat_cap & IXGBE_FEATURE_RSS) && ixgbe_enable_rss)
   5376  1.5.2.2  jdolecek 		adapter->feat_en |= IXGBE_FEATURE_RSS;
   5377  1.5.2.2  jdolecek 
   5378  1.5.2.2  jdolecek 	/* Disable features with unmet dependencies... */
   5379  1.5.2.2  jdolecek 	/* No MSI-X */
   5380  1.5.2.2  jdolecek 	if (!(adapter->feat_cap & IXGBE_FEATURE_MSIX)) {
   5381  1.5.2.2  jdolecek 		adapter->feat_cap &= ~IXGBE_FEATURE_RSS;
   5382  1.5.2.2  jdolecek 		adapter->feat_cap &= ~IXGBE_FEATURE_SRIOV;
   5383  1.5.2.2  jdolecek 		adapter->feat_en &= ~IXGBE_FEATURE_RSS;
   5384  1.5.2.2  jdolecek 		adapter->feat_en &= ~IXGBE_FEATURE_SRIOV;
   5385  1.5.2.2  jdolecek 	}
   5386  1.5.2.2  jdolecek } /* ixgbe_init_device_features */
   5387      1.1    dyoung 
   5388  1.5.2.2  jdolecek /************************************************************************
   5389  1.5.2.2  jdolecek  * ixgbe_probe - Device identification routine
   5390  1.5.2.2  jdolecek  *
   5391  1.5.2.2  jdolecek  *   Determines if the driver should be loaded on
   5392  1.5.2.2  jdolecek  *   adapter based on its PCI vendor/device ID.
   5393  1.5.2.2  jdolecek  *
   5394  1.5.2.2  jdolecek  *   return BUS_PROBE_DEFAULT on success, positive on failure
   5395  1.5.2.2  jdolecek  ************************************************************************/
   5396  1.5.2.2  jdolecek static int
   5397  1.5.2.2  jdolecek ixgbe_probe(device_t dev, cfdata_t cf, void *aux)
   5398  1.5.2.2  jdolecek {
   5399  1.5.2.2  jdolecek 	const struct pci_attach_args *pa = aux;
   5400  1.5.2.2  jdolecek 
   5401  1.5.2.2  jdolecek 	return (ixgbe_lookup(pa) != NULL) ? 1 : 0;
   5402      1.1    dyoung }
   5403      1.1    dyoung 
   5404  1.5.2.2  jdolecek static ixgbe_vendor_info_t *
   5405  1.5.2.2  jdolecek ixgbe_lookup(const struct pci_attach_args *pa)
   5406      1.1    dyoung {
   5407  1.5.2.2  jdolecek 	ixgbe_vendor_info_t *ent;
   5408  1.5.2.2  jdolecek 	pcireg_t subid;
   5409      1.1    dyoung 
   5410  1.5.2.2  jdolecek 	INIT_DEBUGOUT("ixgbe_lookup: begin");
   5411  1.5.2.2  jdolecek 
   5412  1.5.2.2  jdolecek 	if (PCI_VENDOR(pa->pa_id) != IXGBE_INTEL_VENDOR_ID)
   5413  1.5.2.2  jdolecek 		return NULL;
   5414  1.5.2.2  jdolecek 
   5415  1.5.2.2  jdolecek 	subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
   5416  1.5.2.2  jdolecek 
   5417  1.5.2.2  jdolecek 	for (ent = ixgbe_vendor_info_array; ent->vendor_id != 0; ent++) {
   5418  1.5.2.2  jdolecek 		if ((PCI_VENDOR(pa->pa_id) == ent->vendor_id) &&
   5419  1.5.2.2  jdolecek 		    (PCI_PRODUCT(pa->pa_id) == ent->device_id) &&
   5420  1.5.2.2  jdolecek 		    ((PCI_SUBSYS_VENDOR(subid) == ent->subvendor_id) ||
   5421  1.5.2.2  jdolecek 			(ent->subvendor_id == 0)) &&
   5422  1.5.2.2  jdolecek 		    ((PCI_SUBSYS_ID(subid) == ent->subdevice_id) ||
   5423  1.5.2.2  jdolecek 			(ent->subdevice_id == 0))) {
   5424  1.5.2.2  jdolecek 			++ixgbe_total_ports;
   5425  1.5.2.2  jdolecek 			return ent;
   5426  1.5.2.2  jdolecek 		}
   5427  1.5.2.2  jdolecek 	}
   5428  1.5.2.2  jdolecek 	return NULL;
   5429      1.1    dyoung }
   5430      1.1    dyoung 
   5431  1.5.2.2  jdolecek static int
   5432  1.5.2.2  jdolecek ixgbe_ifflags_cb(struct ethercom *ec)
   5433      1.1    dyoung {
   5434  1.5.2.2  jdolecek 	struct ifnet *ifp = &ec->ec_if;
   5435  1.5.2.2  jdolecek 	struct adapter *adapter = ifp->if_softc;
   5436  1.5.2.2  jdolecek 	int change = ifp->if_flags ^ adapter->if_flags, rc = 0;
   5437      1.1    dyoung 
   5438  1.5.2.2  jdolecek 	IXGBE_CORE_LOCK(adapter);
   5439  1.5.2.2  jdolecek 
   5440  1.5.2.2  jdolecek 	if (change != 0)
   5441  1.5.2.2  jdolecek 		adapter->if_flags = ifp->if_flags;
   5442  1.5.2.2  jdolecek 
   5443  1.5.2.2  jdolecek 	if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0)
   5444  1.5.2.2  jdolecek 		rc = ENETRESET;
   5445  1.5.2.2  jdolecek 	else if ((change & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
   5446  1.5.2.2  jdolecek 		ixgbe_set_promisc(adapter);
   5447  1.5.2.2  jdolecek 
   5448  1.5.2.2  jdolecek 	/* Set up VLAN support and filter */
   5449  1.5.2.2  jdolecek 	ixgbe_setup_vlan_hw_support(adapter);
   5450  1.5.2.2  jdolecek 
   5451  1.5.2.2  jdolecek 	IXGBE_CORE_UNLOCK(adapter);
   5452  1.5.2.2  jdolecek 
   5453  1.5.2.2  jdolecek 	return rc;
   5454      1.1    dyoung }
   5455      1.1    dyoung 
   5456  1.5.2.2  jdolecek /************************************************************************
   5457  1.5.2.2  jdolecek  * ixgbe_ioctl - Ioctl entry point
   5458  1.5.2.2  jdolecek  *
   5459  1.5.2.2  jdolecek  *   Called when the user wants to configure the interface.
   5460  1.5.2.2  jdolecek  *
   5461  1.5.2.2  jdolecek  *   return 0 on success, positive on failure
   5462  1.5.2.2  jdolecek  ************************************************************************/
   5463  1.5.2.2  jdolecek static int
   5464  1.5.2.2  jdolecek ixgbe_ioctl(struct ifnet * ifp, u_long command, void *data)
   5465      1.1    dyoung {
   5466  1.5.2.2  jdolecek 	struct adapter	*adapter = ifp->if_softc;
   5467  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   5468  1.5.2.2  jdolecek 	struct ifcapreq *ifcr = data;
   5469  1.5.2.2  jdolecek 	struct ifreq	*ifr = data;
   5470  1.5.2.2  jdolecek 	int             error = 0;
   5471  1.5.2.2  jdolecek 	int l4csum_en;
   5472  1.5.2.2  jdolecek 	const int l4csum = IFCAP_CSUM_TCPv4_Rx|IFCAP_CSUM_UDPv4_Rx|
   5473  1.5.2.2  jdolecek 	     IFCAP_CSUM_TCPv6_Rx|IFCAP_CSUM_UDPv6_Rx;
   5474  1.5.2.2  jdolecek 
   5475  1.5.2.2  jdolecek 	switch (command) {
   5476  1.5.2.2  jdolecek 	case SIOCSIFFLAGS:
   5477  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)");
   5478  1.5.2.2  jdolecek 		break;
   5479  1.5.2.2  jdolecek 	case SIOCADDMULTI:
   5480  1.5.2.2  jdolecek 	case SIOCDELMULTI:
   5481  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI");
   5482  1.5.2.2  jdolecek 		break;
   5483  1.5.2.2  jdolecek 	case SIOCSIFMEDIA:
   5484  1.5.2.2  jdolecek 	case SIOCGIFMEDIA:
   5485  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCxIFMEDIA (Get/Set Interface Media)");
   5486  1.5.2.2  jdolecek 		break;
   5487  1.5.2.2  jdolecek 	case SIOCSIFCAP:
   5488  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)");
   5489  1.5.2.2  jdolecek 		break;
   5490  1.5.2.2  jdolecek 	case SIOCSIFMTU:
   5491  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
   5492  1.5.2.2  jdolecek 		break;
   5493  1.5.2.2  jdolecek #ifdef __NetBSD__
   5494  1.5.2.2  jdolecek 	case SIOCINITIFADDR:
   5495  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCINITIFADDR");
   5496  1.5.2.2  jdolecek 		break;
   5497  1.5.2.2  jdolecek 	case SIOCGIFFLAGS:
   5498  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCGIFFLAGS");
   5499  1.5.2.2  jdolecek 		break;
   5500  1.5.2.2  jdolecek 	case SIOCGIFAFLAG_IN:
   5501  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCGIFAFLAG_IN");
   5502  1.5.2.2  jdolecek 		break;
   5503  1.5.2.2  jdolecek 	case SIOCGIFADDR:
   5504  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCGIFADDR");
   5505  1.5.2.2  jdolecek 		break;
   5506  1.5.2.2  jdolecek 	case SIOCGIFMTU:
   5507  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCGIFMTU (Get Interface MTU)");
   5508  1.5.2.2  jdolecek 		break;
   5509  1.5.2.2  jdolecek 	case SIOCGIFCAP:
   5510  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCGIFCAP (Get IF cap)");
   5511  1.5.2.2  jdolecek 		break;
   5512  1.5.2.2  jdolecek 	case SIOCGETHERCAP:
   5513  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCGETHERCAP (Get ethercap)");
   5514  1.5.2.2  jdolecek 		break;
   5515  1.5.2.2  jdolecek 	case SIOCGLIFADDR:
   5516  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCGLIFADDR (Get Interface addr)");
   5517  1.5.2.2  jdolecek 		break;
   5518  1.5.2.2  jdolecek 	case SIOCZIFDATA:
   5519  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCZIFDATA (Zero counter)");
   5520  1.5.2.2  jdolecek 		hw->mac.ops.clear_hw_cntrs(hw);
   5521  1.5.2.2  jdolecek 		ixgbe_clear_evcnt(adapter);
   5522  1.5.2.2  jdolecek 		break;
   5523  1.5.2.2  jdolecek 	case SIOCAIFADDR:
   5524  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCAIFADDR (add/chg IF alias)");
   5525  1.5.2.2  jdolecek 		break;
   5526  1.5.2.2  jdolecek #endif
   5527  1.5.2.2  jdolecek 	default:
   5528  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)", (int)command);
   5529  1.5.2.2  jdolecek 		break;
   5530  1.5.2.2  jdolecek 	}
   5531      1.1    dyoung 
   5532  1.5.2.2  jdolecek 	switch (command) {
   5533  1.5.2.2  jdolecek 	case SIOCSIFMEDIA:
   5534  1.5.2.2  jdolecek 	case SIOCGIFMEDIA:
   5535  1.5.2.2  jdolecek 		return ifmedia_ioctl(ifp, ifr, &adapter->media, command);
   5536  1.5.2.2  jdolecek 	case SIOCGI2C:
   5537  1.5.2.2  jdolecek 	{
   5538  1.5.2.2  jdolecek 		struct ixgbe_i2c_req	i2c;
   5539      1.1    dyoung 
   5540  1.5.2.2  jdolecek 		IOCTL_DEBUGOUT("ioctl: SIOCGI2C (Get I2C Data)");
   5541  1.5.2.2  jdolecek 		error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));
   5542  1.5.2.2  jdolecek 		if (error != 0)
   5543  1.5.2.2  jdolecek 			break;
   5544  1.5.2.2  jdolecek 		if (i2c.dev_addr != 0xA0 && i2c.dev_addr != 0xA2) {
   5545  1.5.2.2  jdolecek 			error = EINVAL;
   5546  1.5.2.2  jdolecek 			break;
   5547  1.5.2.2  jdolecek 		}
   5548  1.5.2.2  jdolecek 		if (i2c.len > sizeof(i2c.data)) {
   5549  1.5.2.2  jdolecek 			error = EINVAL;
   5550  1.5.2.2  jdolecek 			break;
   5551  1.5.2.2  jdolecek 		}
   5552      1.1    dyoung 
   5553  1.5.2.2  jdolecek 		hw->phy.ops.read_i2c_byte(hw, i2c.offset,
   5554  1.5.2.2  jdolecek 		    i2c.dev_addr, i2c.data);
   5555  1.5.2.2  jdolecek 		error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
   5556  1.5.2.2  jdolecek 		break;
   5557  1.5.2.2  jdolecek 	}
   5558  1.5.2.2  jdolecek 	case SIOCSIFCAP:
   5559  1.5.2.2  jdolecek 		/* Layer-4 Rx checksum offload has to be turned on and
   5560  1.5.2.2  jdolecek 		 * off as a unit.
   5561  1.5.2.2  jdolecek 		 */
   5562  1.5.2.2  jdolecek 		l4csum_en = ifcr->ifcr_capenable & l4csum;
   5563  1.5.2.2  jdolecek 		if (l4csum_en != l4csum && l4csum_en != 0)
   5564  1.5.2.2  jdolecek 			return EINVAL;
   5565  1.5.2.2  jdolecek 		/*FALLTHROUGH*/
   5566  1.5.2.2  jdolecek 	case SIOCADDMULTI:
   5567  1.5.2.2  jdolecek 	case SIOCDELMULTI:
   5568  1.5.2.2  jdolecek 	case SIOCSIFFLAGS:
   5569  1.5.2.2  jdolecek 	case SIOCSIFMTU:
   5570  1.5.2.2  jdolecek 	default:
   5571  1.5.2.2  jdolecek 		if ((error = ether_ioctl(ifp, command, data)) != ENETRESET)
   5572  1.5.2.2  jdolecek 			return error;
   5573  1.5.2.2  jdolecek 		if ((ifp->if_flags & IFF_RUNNING) == 0)
   5574  1.5.2.2  jdolecek 			;
   5575  1.5.2.2  jdolecek 		else if (command == SIOCSIFCAP || command == SIOCSIFMTU) {
   5576  1.5.2.2  jdolecek 			IXGBE_CORE_LOCK(adapter);
   5577  1.5.2.2  jdolecek 			ixgbe_init_locked(adapter);
   5578  1.5.2.2  jdolecek 			ixgbe_recalculate_max_frame(adapter);
   5579  1.5.2.2  jdolecek 			IXGBE_CORE_UNLOCK(adapter);
   5580  1.5.2.2  jdolecek 		} else if (command == SIOCADDMULTI || command == SIOCDELMULTI) {
   5581  1.5.2.2  jdolecek 			/*
   5582  1.5.2.2  jdolecek 			 * Multicast list has changed; set the hardware filter
   5583  1.5.2.2  jdolecek 			 * accordingly.
   5584  1.5.2.2  jdolecek 			 */
   5585  1.5.2.2  jdolecek 			IXGBE_CORE_LOCK(adapter);
   5586  1.5.2.2  jdolecek 			ixgbe_disable_intr(adapter);
   5587  1.5.2.2  jdolecek 			ixgbe_set_multi(adapter);
   5588  1.5.2.2  jdolecek 			ixgbe_enable_intr(adapter);
   5589  1.5.2.2  jdolecek 			IXGBE_CORE_UNLOCK(adapter);
   5590  1.5.2.2  jdolecek 		}
   5591      1.1    dyoung 		return 0;
   5592  1.5.2.2  jdolecek 	}
   5593      1.1    dyoung 
   5594  1.5.2.2  jdolecek 	return error;
   5595  1.5.2.2  jdolecek } /* ixgbe_ioctl */
   5596      1.1    dyoung 
   5597  1.5.2.2  jdolecek /************************************************************************
   5598  1.5.2.2  jdolecek  * ixgbe_check_fan_failure
   5599  1.5.2.2  jdolecek  ************************************************************************/
   5600  1.5.2.2  jdolecek static void
   5601  1.5.2.2  jdolecek ixgbe_check_fan_failure(struct adapter *adapter, u32 reg, bool in_interrupt)
   5602      1.1    dyoung {
   5603  1.5.2.2  jdolecek 	u32 mask;
   5604      1.1    dyoung 
   5605  1.5.2.2  jdolecek 	mask = (in_interrupt) ? IXGBE_EICR_GPI_SDP1_BY_MAC(&adapter->hw) :
   5606  1.5.2.2  jdolecek 	    IXGBE_ESDP_SDP1;
   5607      1.1    dyoung 
   5608  1.5.2.2  jdolecek 	if (reg & mask)
   5609  1.5.2.2  jdolecek 		device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n");
   5610  1.5.2.2  jdolecek } /* ixgbe_check_fan_failure */
   5611  1.5.2.2  jdolecek 
   5612  1.5.2.2  jdolecek /************************************************************************
   5613  1.5.2.2  jdolecek  * ixgbe_handle_que
   5614  1.5.2.2  jdolecek  ************************************************************************/
   5615      1.1    dyoung static void
   5616  1.5.2.2  jdolecek ixgbe_handle_que(void *context)
   5617      1.1    dyoung {
   5618  1.5.2.2  jdolecek 	struct ix_queue *que = context;
   5619  1.5.2.2  jdolecek 	struct adapter  *adapter = que->adapter;
   5620  1.5.2.2  jdolecek 	struct tx_ring  *txr = que->txr;
   5621  1.5.2.2  jdolecek 	struct ifnet    *ifp = adapter->ifp;
   5622      1.1    dyoung 
   5623  1.5.2.2  jdolecek 	adapter->handleq.ev_count++;
   5624      1.1    dyoung 
   5625  1.5.2.2  jdolecek 	if (ifp->if_flags & IFF_RUNNING) {
   5626  1.5.2.2  jdolecek 		ixgbe_rxeof(que);
   5627  1.5.2.2  jdolecek 		IXGBE_TX_LOCK(txr);
   5628  1.5.2.2  jdolecek 		ixgbe_txeof(txr);
   5629  1.5.2.2  jdolecek 		if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX))
   5630  1.5.2.2  jdolecek 			if (!ixgbe_mq_ring_empty(ifp, txr->txr_interq))
   5631  1.5.2.2  jdolecek 				ixgbe_mq_start_locked(ifp, txr);
   5632  1.5.2.2  jdolecek 		/* Only for queue 0 */
   5633  1.5.2.2  jdolecek 		/* NetBSD still needs this for CBQ */
   5634  1.5.2.2  jdolecek 		if ((&adapter->queues[0] == que)
   5635  1.5.2.2  jdolecek 		    && (!ixgbe_legacy_ring_empty(ifp, NULL)))
   5636  1.5.2.2  jdolecek 			ixgbe_legacy_start_locked(ifp, txr);
   5637  1.5.2.2  jdolecek 		IXGBE_TX_UNLOCK(txr);
   5638  1.5.2.2  jdolecek 	}
   5639      1.1    dyoung 
   5640  1.5.2.2  jdolecek 	/* Re-enable this interrupt */
   5641  1.5.2.2  jdolecek 	if (que->res != NULL)
   5642  1.5.2.2  jdolecek 		ixgbe_enable_queue(adapter, que->msix);
   5643  1.5.2.2  jdolecek 	else
   5644  1.5.2.2  jdolecek 		ixgbe_enable_intr(adapter);
   5645      1.1    dyoung 
   5646  1.5.2.2  jdolecek 	return;
   5647  1.5.2.2  jdolecek } /* ixgbe_handle_que */
   5648      1.1    dyoung 
   5649  1.5.2.2  jdolecek /************************************************************************
   5650  1.5.2.2  jdolecek  * ixgbe_allocate_legacy - Setup the Legacy or MSI Interrupt handler
   5651  1.5.2.2  jdolecek  ************************************************************************/
   5652  1.5.2.2  jdolecek static int
   5653  1.5.2.2  jdolecek ixgbe_allocate_legacy(struct adapter *adapter,
   5654  1.5.2.2  jdolecek     const struct pci_attach_args *pa)
   5655  1.5.2.2  jdolecek {
   5656  1.5.2.2  jdolecek 	device_t	dev = adapter->dev;
   5657  1.5.2.2  jdolecek 	struct ix_queue *que = adapter->queues;
   5658  1.5.2.2  jdolecek 	struct tx_ring  *txr = adapter->tx_rings;
   5659  1.5.2.2  jdolecek 	int		counts[PCI_INTR_TYPE_SIZE];
   5660  1.5.2.2  jdolecek 	pci_intr_type_t intr_type, max_type;
   5661  1.5.2.2  jdolecek 	char            intrbuf[PCI_INTRSTR_LEN];
   5662  1.5.2.2  jdolecek 	const char	*intrstr = NULL;
   5663  1.5.2.2  jdolecek 
   5664  1.5.2.2  jdolecek 	/* We allocate a single interrupt resource */
   5665  1.5.2.2  jdolecek 	max_type = PCI_INTR_TYPE_MSI;
   5666  1.5.2.2  jdolecek 	counts[PCI_INTR_TYPE_MSIX] = 0;
   5667  1.5.2.2  jdolecek 	counts[PCI_INTR_TYPE_MSI] =
   5668  1.5.2.2  jdolecek 	    (adapter->feat_en & IXGBE_FEATURE_MSI) ? 1 : 0;
   5669  1.5.2.2  jdolecek 	counts[PCI_INTR_TYPE_INTX] =
   5670  1.5.2.2  jdolecek 	    (adapter->feat_en & IXGBE_FEATURE_LEGACY_IRQ) ? 1 : 0;
   5671  1.5.2.2  jdolecek 
   5672  1.5.2.2  jdolecek alloc_retry:
   5673  1.5.2.2  jdolecek 	if (pci_intr_alloc(pa, &adapter->osdep.intrs, counts, max_type) != 0) {
   5674  1.5.2.2  jdolecek 		aprint_error_dev(dev, "couldn't alloc interrupt\n");
   5675  1.5.2.2  jdolecek 		return ENXIO;
   5676  1.5.2.2  jdolecek 	}
   5677  1.5.2.2  jdolecek 	adapter->osdep.nintrs = 1;
   5678  1.5.2.2  jdolecek 	intrstr = pci_intr_string(adapter->osdep.pc, adapter->osdep.intrs[0],
   5679  1.5.2.2  jdolecek 	    intrbuf, sizeof(intrbuf));
   5680  1.5.2.2  jdolecek 	adapter->osdep.ihs[0] = pci_intr_establish_xname(adapter->osdep.pc,
   5681  1.5.2.2  jdolecek 	    adapter->osdep.intrs[0], IPL_NET, ixgbe_legacy_irq, que,
   5682  1.5.2.2  jdolecek 	    device_xname(dev));
   5683  1.5.2.2  jdolecek 	if (adapter->osdep.ihs[0] == NULL) {
   5684  1.5.2.2  jdolecek 		intr_type = pci_intr_type(adapter->osdep.pc,
   5685  1.5.2.2  jdolecek 		    adapter->osdep.intrs[0]);
   5686  1.5.2.2  jdolecek 		aprint_error_dev(dev,"unable to establish %s\n",
   5687  1.5.2.2  jdolecek 		    (intr_type == PCI_INTR_TYPE_MSI) ? "MSI" : "INTx");
   5688  1.5.2.2  jdolecek 		pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs, 1);
   5689  1.5.2.2  jdolecek 		switch (intr_type) {
   5690  1.5.2.2  jdolecek 		case PCI_INTR_TYPE_MSI:
   5691  1.5.2.2  jdolecek 			/* The next try is for INTx: Disable MSI */
   5692  1.5.2.2  jdolecek 			max_type = PCI_INTR_TYPE_INTX;
   5693  1.5.2.2  jdolecek 			counts[PCI_INTR_TYPE_INTX] = 1;
   5694  1.5.2.2  jdolecek 			goto alloc_retry;
   5695  1.5.2.2  jdolecek 		case PCI_INTR_TYPE_INTX:
   5696  1.5.2.2  jdolecek 		default:
   5697  1.5.2.2  jdolecek 			/* See below */
   5698      1.1    dyoung 			break;
   5699  1.5.2.2  jdolecek 		}
   5700  1.5.2.2  jdolecek 	}
   5701  1.5.2.2  jdolecek 	if (adapter->osdep.ihs[0] == NULL) {
   5702  1.5.2.2  jdolecek 		aprint_error_dev(dev,
   5703  1.5.2.2  jdolecek 		    "couldn't establish interrupt%s%s\n",
   5704  1.5.2.2  jdolecek 		    intrstr ? " at " : "", intrstr ? intrstr : "");
   5705  1.5.2.2  jdolecek 		pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs, 1);
   5706  1.5.2.2  jdolecek 		return ENXIO;
   5707  1.5.2.2  jdolecek 	}
   5708  1.5.2.2  jdolecek 	aprint_normal_dev(dev, "interrupting at %s\n", intrstr);
   5709  1.5.2.2  jdolecek 	/*
   5710  1.5.2.2  jdolecek 	 * Try allocating a fast interrupt and the associated deferred
   5711  1.5.2.2  jdolecek 	 * processing contexts.
   5712  1.5.2.2  jdolecek 	 */
   5713  1.5.2.2  jdolecek 	if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX))
   5714  1.5.2.2  jdolecek 		txr->txr_si =
   5715  1.5.2.2  jdolecek 		    softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
   5716  1.5.2.2  jdolecek 			ixgbe_deferred_mq_start, txr);
   5717  1.5.2.2  jdolecek 	que->que_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
   5718  1.5.2.2  jdolecek 	    ixgbe_handle_que, que);
   5719      1.1    dyoung 
   5720  1.5.2.2  jdolecek 	/* Tasklets for Link, SFP and Multispeed Fiber */
   5721  1.5.2.2  jdolecek 	adapter->link_si = softint_establish(SOFTINT_NET |IXGBE_SOFTINFT_FLAGS,
   5722  1.5.2.2  jdolecek 	    ixgbe_handle_link, adapter);
   5723  1.5.2.2  jdolecek 	adapter->mod_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
   5724  1.5.2.2  jdolecek 	    ixgbe_handle_mod, adapter);
   5725  1.5.2.2  jdolecek 	adapter->msf_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
   5726  1.5.2.2  jdolecek 	    ixgbe_handle_msf, adapter);
   5727  1.5.2.2  jdolecek 	adapter->phy_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
   5728  1.5.2.2  jdolecek 	    ixgbe_handle_phy, adapter);
   5729  1.5.2.2  jdolecek 
   5730  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_FDIR)
   5731  1.5.2.2  jdolecek 		adapter->fdir_si =
   5732  1.5.2.2  jdolecek 		    softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
   5733  1.5.2.2  jdolecek 			ixgbe_reinit_fdir, adapter);
   5734  1.5.2.2  jdolecek 
   5735  1.5.2.2  jdolecek 	if ((!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX) &
   5736  1.5.2.2  jdolecek 		(txr->txr_si == NULL)) ||
   5737  1.5.2.2  jdolecek 	    que->que_si == NULL ||
   5738  1.5.2.2  jdolecek 	    adapter->link_si == NULL ||
   5739  1.5.2.2  jdolecek 	    adapter->mod_si == NULL ||
   5740  1.5.2.2  jdolecek 	    ((adapter->feat_en & IXGBE_FEATURE_FDIR) &
   5741  1.5.2.2  jdolecek 		(adapter->fdir_si == NULL)) ||
   5742  1.5.2.2  jdolecek 	    adapter->msf_si == NULL) {
   5743  1.5.2.2  jdolecek 		aprint_error_dev(dev,
   5744  1.5.2.2  jdolecek 		    "could not establish software interrupts\n");
   5745      1.1    dyoung 
   5746  1.5.2.2  jdolecek 		return ENXIO;
   5747  1.5.2.2  jdolecek 	}
   5748  1.5.2.2  jdolecek 	/* For simplicity in the handlers */
   5749  1.5.2.2  jdolecek 	adapter->active_queues = IXGBE_EIMS_ENABLE_MASK;
   5750      1.1    dyoung 
   5751  1.5.2.2  jdolecek 	return (0);
   5752  1.5.2.2  jdolecek } /* ixgbe_allocate_legacy */
   5753      1.1    dyoung 
   5754      1.1    dyoung 
   5755  1.5.2.2  jdolecek /************************************************************************
   5756  1.5.2.2  jdolecek  * ixgbe_allocate_msix - Setup MSI-X Interrupt resources and handlers
   5757  1.5.2.2  jdolecek  ************************************************************************/
   5758  1.5.2.2  jdolecek static int
   5759  1.5.2.2  jdolecek ixgbe_allocate_msix(struct adapter *adapter, const struct pci_attach_args *pa)
   5760  1.5.2.2  jdolecek {
   5761  1.5.2.2  jdolecek 	device_t        dev = adapter->dev;
   5762  1.5.2.2  jdolecek 	struct 		ix_queue *que = adapter->queues;
   5763  1.5.2.2  jdolecek 	struct  	tx_ring *txr = adapter->tx_rings;
   5764  1.5.2.2  jdolecek 	pci_chipset_tag_t pc;
   5765  1.5.2.2  jdolecek 	char		intrbuf[PCI_INTRSTR_LEN];
   5766  1.5.2.2  jdolecek 	char		intr_xname[32];
   5767  1.5.2.2  jdolecek 	const char	*intrstr = NULL;
   5768  1.5.2.2  jdolecek 	int 		error, vector = 0;
   5769  1.5.2.2  jdolecek 	int		cpu_id = 0;
   5770  1.5.2.2  jdolecek 	kcpuset_t	*affinity;
   5771  1.5.2.2  jdolecek #ifdef RSS
   5772  1.5.2.2  jdolecek 	unsigned int    rss_buckets = 0;
   5773  1.5.2.2  jdolecek 	kcpuset_t	cpu_mask;
   5774  1.5.2.2  jdolecek #endif
   5775      1.1    dyoung 
   5776  1.5.2.2  jdolecek 	pc = adapter->osdep.pc;
   5777  1.5.2.2  jdolecek #ifdef	RSS
   5778  1.5.2.2  jdolecek 	/*
   5779  1.5.2.2  jdolecek 	 * If we're doing RSS, the number of queues needs to
   5780  1.5.2.2  jdolecek 	 * match the number of RSS buckets that are configured.
   5781  1.5.2.2  jdolecek 	 *
   5782  1.5.2.2  jdolecek 	 * + If there's more queues than RSS buckets, we'll end
   5783  1.5.2.2  jdolecek 	 *   up with queues that get no traffic.
   5784  1.5.2.2  jdolecek 	 *
   5785  1.5.2.2  jdolecek 	 * + If there's more RSS buckets than queues, we'll end
   5786  1.5.2.2  jdolecek 	 *   up having multiple RSS buckets map to the same queue,
   5787  1.5.2.2  jdolecek 	 *   so there'll be some contention.
   5788  1.5.2.2  jdolecek 	 */
   5789  1.5.2.2  jdolecek 	rss_buckets = rss_getnumbuckets();
   5790  1.5.2.2  jdolecek 	if ((adapter->feat_en & IXGBE_FEATURE_RSS) &&
   5791  1.5.2.2  jdolecek 	    (adapter->num_queues != rss_buckets)) {
   5792  1.5.2.2  jdolecek 		device_printf(dev,
   5793  1.5.2.2  jdolecek 		    "%s: number of queues (%d) != number of RSS buckets (%d)"
   5794  1.5.2.2  jdolecek 		    "; performance will be impacted.\n",
   5795  1.5.2.2  jdolecek 		    __func__, adapter->num_queues, rss_buckets);
   5796  1.5.2.2  jdolecek 	}
   5797  1.5.2.2  jdolecek #endif
   5798      1.1    dyoung 
   5799  1.5.2.2  jdolecek 	adapter->osdep.nintrs = adapter->num_queues + 1;
   5800  1.5.2.2  jdolecek 	if (pci_msix_alloc_exact(pa, &adapter->osdep.intrs,
   5801  1.5.2.2  jdolecek 	    adapter->osdep.nintrs) != 0) {
   5802  1.5.2.2  jdolecek 		aprint_error_dev(dev,
   5803  1.5.2.2  jdolecek 		    "failed to allocate MSI-X interrupt\n");
   5804  1.5.2.2  jdolecek 		return (ENXIO);
   5805  1.5.2.2  jdolecek 	}
   5806      1.1    dyoung 
   5807  1.5.2.2  jdolecek 	kcpuset_create(&affinity, false);
   5808  1.5.2.2  jdolecek 	for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) {
   5809  1.5.2.2  jdolecek 		snprintf(intr_xname, sizeof(intr_xname), "%s TXRX%d",
   5810  1.5.2.2  jdolecek 		    device_xname(dev), i);
   5811  1.5.2.2  jdolecek 		intrstr = pci_intr_string(pc, adapter->osdep.intrs[i], intrbuf,
   5812  1.5.2.2  jdolecek 		    sizeof(intrbuf));
   5813  1.5.2.2  jdolecek #ifdef IXGBE_MPSAFE
   5814  1.5.2.2  jdolecek 		pci_intr_setattr(pc, &adapter->osdep.intrs[i], PCI_INTR_MPSAFE,
   5815  1.5.2.2  jdolecek 		    true);
   5816  1.5.2.2  jdolecek #endif
   5817  1.5.2.2  jdolecek 		/* Set the handler function */
   5818  1.5.2.2  jdolecek 		que->res = adapter->osdep.ihs[i] = pci_intr_establish_xname(pc,
   5819  1.5.2.2  jdolecek 		    adapter->osdep.intrs[i], IPL_NET, ixgbe_msix_que, que,
   5820  1.5.2.2  jdolecek 		    intr_xname);
   5821  1.5.2.2  jdolecek 		if (que->res == NULL) {
   5822  1.5.2.2  jdolecek 			pci_intr_release(pc, adapter->osdep.intrs,
   5823  1.5.2.2  jdolecek 			    adapter->osdep.nintrs);
   5824  1.5.2.2  jdolecek 			aprint_error_dev(dev,
   5825  1.5.2.2  jdolecek 			    "Failed to register QUE handler\n");
   5826  1.5.2.2  jdolecek 			kcpuset_destroy(affinity);
   5827  1.5.2.2  jdolecek 			return ENXIO;
   5828      1.1    dyoung 		}
   5829  1.5.2.2  jdolecek 		que->msix = vector;
   5830  1.5.2.2  jdolecek 		adapter->active_queues |= (u64)(1 << que->msix);
   5831  1.5.2.2  jdolecek 
   5832  1.5.2.2  jdolecek 		if (adapter->feat_en & IXGBE_FEATURE_RSS) {
   5833  1.5.2.2  jdolecek #ifdef	RSS
   5834  1.5.2.2  jdolecek 			/*
   5835  1.5.2.2  jdolecek 			 * The queue ID is used as the RSS layer bucket ID.
   5836  1.5.2.2  jdolecek 			 * We look up the queue ID -> RSS CPU ID and select
   5837  1.5.2.2  jdolecek 			 * that.
   5838  1.5.2.2  jdolecek 			 */
   5839  1.5.2.2  jdolecek 			cpu_id = rss_getcpu(i % rss_getnumbuckets());
   5840  1.5.2.2  jdolecek 			CPU_SETOF(cpu_id, &cpu_mask);
   5841  1.5.2.2  jdolecek #endif
   5842  1.5.2.2  jdolecek 		} else {
   5843  1.5.2.2  jdolecek 			/*
   5844  1.5.2.2  jdolecek 			 * Bind the MSI-X vector, and thus the
   5845  1.5.2.2  jdolecek 			 * rings to the corresponding CPU.
   5846  1.5.2.2  jdolecek 			 *
   5847  1.5.2.2  jdolecek 			 * This just happens to match the default RSS
   5848  1.5.2.2  jdolecek 			 * round-robin bucket -> queue -> CPU allocation.
   5849  1.5.2.2  jdolecek 			 */
   5850  1.5.2.2  jdolecek 			if (adapter->num_queues > 1)
   5851  1.5.2.2  jdolecek 				cpu_id = i;
   5852      1.1    dyoung 		}
   5853  1.5.2.2  jdolecek 		/* Round-robin affinity */
   5854  1.5.2.2  jdolecek 		kcpuset_zero(affinity);
   5855  1.5.2.2  jdolecek 		kcpuset_set(affinity, cpu_id % ncpu);
   5856  1.5.2.2  jdolecek 		error = interrupt_distribute(adapter->osdep.ihs[i], affinity,
   5857  1.5.2.2  jdolecek 		    NULL);
   5858  1.5.2.2  jdolecek 		aprint_normal_dev(dev, "for TX/RX, interrupting at %s",
   5859  1.5.2.2  jdolecek 		    intrstr);
   5860  1.5.2.2  jdolecek 		if (error == 0) {
   5861  1.5.2.2  jdolecek #if 1 /* def IXGBE_DEBUG */
   5862  1.5.2.2  jdolecek #ifdef	RSS
   5863  1.5.2.2  jdolecek 			aprintf_normal(", bound RSS bucket %d to CPU %d", i,
   5864  1.5.2.2  jdolecek 			    cpu_id % ncpu);
   5865  1.5.2.2  jdolecek #else
   5866  1.5.2.2  jdolecek 			aprint_normal(", bound queue %d to cpu %d", i,
   5867  1.5.2.2  jdolecek 			    cpu_id % ncpu);
   5868  1.5.2.2  jdolecek #endif
   5869  1.5.2.2  jdolecek #endif /* IXGBE_DEBUG */
   5870      1.1    dyoung 		}
   5871  1.5.2.2  jdolecek 		aprint_normal("\n");
   5872      1.1    dyoung 
   5873  1.5.2.2  jdolecek 		if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX))
   5874  1.5.2.2  jdolecek 			txr->txr_si = softint_establish(
   5875  1.5.2.2  jdolecek 				SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
   5876  1.5.2.2  jdolecek 				ixgbe_deferred_mq_start, txr);
   5877  1.5.2.2  jdolecek 		que->que_si
   5878  1.5.2.2  jdolecek 		    = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
   5879  1.5.2.2  jdolecek 			ixgbe_handle_que, que);
   5880  1.5.2.2  jdolecek 		if (que->que_si == NULL) {
   5881  1.5.2.2  jdolecek 			aprint_error_dev(dev,
   5882  1.5.2.2  jdolecek 			    "could not establish software interrupt\n");
   5883  1.5.2.2  jdolecek 		}
   5884      1.1    dyoung 	}
   5885      1.1    dyoung 
   5886  1.5.2.2  jdolecek 	/* and Link */
   5887  1.5.2.2  jdolecek 	cpu_id++;
   5888  1.5.2.2  jdolecek 	snprintf(intr_xname, sizeof(intr_xname), "%s link", device_xname(dev));
   5889  1.5.2.2  jdolecek 	intrstr = pci_intr_string(pc, adapter->osdep.intrs[vector], intrbuf,
   5890  1.5.2.2  jdolecek 	    sizeof(intrbuf));
   5891  1.5.2.2  jdolecek #ifdef IXGBE_MPSAFE
   5892  1.5.2.2  jdolecek 	pci_intr_setattr(pc, &adapter->osdep.intrs[vector], PCI_INTR_MPSAFE,
   5893  1.5.2.2  jdolecek 	    true);
   5894  1.5.2.2  jdolecek #endif
   5895  1.5.2.2  jdolecek 	/* Set the link handler function */
   5896  1.5.2.2  jdolecek 	adapter->osdep.ihs[vector] = pci_intr_establish_xname(pc,
   5897  1.5.2.2  jdolecek 	    adapter->osdep.intrs[vector], IPL_NET, ixgbe_msix_link, adapter,
   5898  1.5.2.2  jdolecek 	    intr_xname);
   5899  1.5.2.2  jdolecek 	if (adapter->osdep.ihs[vector] == NULL) {
   5900  1.5.2.2  jdolecek 		adapter->res = NULL;
   5901  1.5.2.2  jdolecek 		aprint_error_dev(dev, "Failed to register LINK handler\n");
   5902  1.5.2.2  jdolecek 		kcpuset_destroy(affinity);
   5903  1.5.2.2  jdolecek 		return (ENXIO);
   5904  1.5.2.2  jdolecek 	}
   5905  1.5.2.2  jdolecek 	/* Round-robin affinity */
   5906  1.5.2.2  jdolecek 	kcpuset_zero(affinity);
   5907  1.5.2.2  jdolecek 	kcpuset_set(affinity, cpu_id % ncpu);
   5908  1.5.2.2  jdolecek 	error = interrupt_distribute(adapter->osdep.ihs[vector], affinity,NULL);
   5909  1.5.2.2  jdolecek 
   5910  1.5.2.2  jdolecek 	aprint_normal_dev(dev,
   5911  1.5.2.2  jdolecek 	    "for link, interrupting at %s", intrstr);
   5912  1.5.2.2  jdolecek 	if (error == 0)
   5913  1.5.2.2  jdolecek 		aprint_normal(", affinity to cpu %d\n", cpu_id % ncpu);
   5914  1.5.2.2  jdolecek 	else
   5915  1.5.2.2  jdolecek 		aprint_normal("\n");
   5916      1.1    dyoung 
   5917  1.5.2.2  jdolecek 	adapter->vector = vector;
   5918  1.5.2.2  jdolecek 	/* Tasklets for Link, SFP and Multispeed Fiber */
   5919  1.5.2.2  jdolecek 	adapter->link_si = softint_establish(SOFTINT_NET |IXGBE_SOFTINFT_FLAGS,
   5920  1.5.2.2  jdolecek 	    ixgbe_handle_link, adapter);
   5921  1.5.2.2  jdolecek 	adapter->mod_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
   5922  1.5.2.2  jdolecek 	    ixgbe_handle_mod, adapter);
   5923  1.5.2.2  jdolecek 	adapter->msf_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
   5924  1.5.2.2  jdolecek 	    ixgbe_handle_msf, adapter);
   5925  1.5.2.2  jdolecek 	if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
   5926  1.5.2.2  jdolecek 		adapter->mbx_si =
   5927  1.5.2.2  jdolecek 		    softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
   5928  1.5.2.2  jdolecek 			ixgbe_handle_mbx, adapter);
   5929  1.5.2.2  jdolecek 	adapter->phy_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
   5930  1.5.2.2  jdolecek 		ixgbe_handle_phy, adapter);
   5931  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_FDIR)
   5932  1.5.2.2  jdolecek 		adapter->fdir_si =
   5933  1.5.2.2  jdolecek 		    softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
   5934  1.5.2.2  jdolecek 			ixgbe_reinit_fdir, adapter);
   5935      1.1    dyoung 
   5936  1.5.2.2  jdolecek 	kcpuset_destroy(affinity);
   5937      1.1    dyoung 
   5938  1.5.2.2  jdolecek 	return (0);
   5939  1.5.2.2  jdolecek } /* ixgbe_allocate_msix */
   5940      1.1    dyoung 
   5941  1.5.2.2  jdolecek /************************************************************************
   5942  1.5.2.2  jdolecek  * ixgbe_configure_interrupts
   5943  1.5.2.2  jdolecek  *
   5944  1.5.2.2  jdolecek  *   Setup MSI-X, MSI, or legacy interrupts (in that order).
   5945  1.5.2.2  jdolecek  *   This will also depend on user settings.
   5946  1.5.2.2  jdolecek  ************************************************************************/
   5947  1.5.2.2  jdolecek static int
   5948  1.5.2.2  jdolecek ixgbe_configure_interrupts(struct adapter *adapter)
   5949  1.5.2.2  jdolecek {
   5950  1.5.2.2  jdolecek 	device_t dev = adapter->dev;
   5951  1.5.2.2  jdolecek 	struct ixgbe_mac_info *mac = &adapter->hw.mac;
   5952  1.5.2.2  jdolecek 	int want, queues, msgs;
   5953      1.1    dyoung 
   5954  1.5.2.2  jdolecek 	/* Default to 1 queue if MSI-X setup fails */
   5955  1.5.2.2  jdolecek 	adapter->num_queues = 1;
   5956      1.1    dyoung 
   5957  1.5.2.2  jdolecek 	/* Override by tuneable */
   5958  1.5.2.2  jdolecek 	if (!(adapter->feat_cap & IXGBE_FEATURE_MSIX))
   5959  1.5.2.2  jdolecek 		goto msi;
   5960      1.1    dyoung 
   5961  1.5.2.2  jdolecek 	/* First try MSI-X */
   5962  1.5.2.2  jdolecek 	msgs = pci_msix_count(adapter->osdep.pc, adapter->osdep.tag);
   5963  1.5.2.2  jdolecek 	msgs = MIN(msgs, IXG_MAX_NINTR);
   5964  1.5.2.2  jdolecek 	if (msgs < 2)
   5965  1.5.2.2  jdolecek 		goto msi;
   5966      1.1    dyoung 
   5967  1.5.2.2  jdolecek 	adapter->msix_mem = (void *)1; /* XXX */
   5968      1.1    dyoung 
   5969  1.5.2.2  jdolecek 	/* Figure out a reasonable auto config value */
   5970  1.5.2.2  jdolecek 	queues = (ncpu > (msgs - 1)) ? (msgs - 1) : ncpu;
   5971      1.1    dyoung 
   5972  1.5.2.2  jdolecek #ifdef	RSS
   5973  1.5.2.2  jdolecek 	/* If we're doing RSS, clamp at the number of RSS buckets */
   5974  1.5.2.2  jdolecek 	if (adapter->feat_en & IXGBE_FEATURE_RSS)
   5975  1.5.2.2  jdolecek 		queues = min(queues, rss_getnumbuckets());
   5976  1.5.2.2  jdolecek #endif
   5977  1.5.2.2  jdolecek 	if (ixgbe_num_queues > queues) {
   5978  1.5.2.2  jdolecek 		aprint_error_dev(adapter->dev, "ixgbe_num_queues (%d) is too large, using reduced amount (%d).\n", ixgbe_num_queues, queues);
   5979  1.5.2.2  jdolecek 		ixgbe_num_queues = queues;
   5980      1.1    dyoung 	}
   5981      1.1    dyoung 
   5982  1.5.2.2  jdolecek 	if (ixgbe_num_queues != 0)
   5983  1.5.2.2  jdolecek 		queues = ixgbe_num_queues;
   5984  1.5.2.2  jdolecek 	else
   5985  1.5.2.2  jdolecek 		queues = min(queues,
   5986  1.5.2.2  jdolecek 		    min(mac->max_tx_queues, mac->max_rx_queues));
   5987      1.1    dyoung 
   5988  1.5.2.2  jdolecek 	/* reflect correct sysctl value */
   5989  1.5.2.2  jdolecek 	ixgbe_num_queues = queues;
   5990      1.1    dyoung 
   5991  1.5.2.2  jdolecek 	/*
   5992  1.5.2.2  jdolecek 	 * Want one vector (RX/TX pair) per queue
   5993  1.5.2.2  jdolecek 	 * plus an additional for Link.
   5994  1.5.2.2  jdolecek 	 */
   5995  1.5.2.2  jdolecek 	want = queues + 1;
   5996  1.5.2.2  jdolecek 	if (msgs >= want)
   5997  1.5.2.2  jdolecek 		msgs = want;
   5998  1.5.2.2  jdolecek 	else {
   5999  1.5.2.2  jdolecek                	aprint_error_dev(dev, "MSI-X Configuration Problem, "
   6000  1.5.2.2  jdolecek 		    "%d vectors but %d queues wanted!\n",
   6001  1.5.2.2  jdolecek 		    msgs, want);
   6002  1.5.2.2  jdolecek 		goto msi;
   6003      1.1    dyoung 	}
   6004  1.5.2.2  jdolecek 	device_printf(dev,
   6005  1.5.2.2  jdolecek 	    "Using MSI-X interrupts with %d vectors\n", msgs);
   6006  1.5.2.2  jdolecek 	adapter->num_queues = queues;
   6007  1.5.2.2  jdolecek 	adapter->feat_en |= IXGBE_FEATURE_MSIX;
   6008  1.5.2.2  jdolecek 	return (0);
   6009      1.1    dyoung 
   6010  1.5.2.2  jdolecek 	/*
   6011  1.5.2.2  jdolecek 	 * MSI-X allocation failed or provided us with
   6012  1.5.2.2  jdolecek 	 * less vectors than needed. Free MSI-X resources
   6013  1.5.2.2  jdolecek 	 * and we'll try enabling MSI.
   6014  1.5.2.2  jdolecek 	 */
   6015  1.5.2.2  jdolecek msi:
   6016  1.5.2.2  jdolecek 	/* Without MSI-X, some features are no longer supported */
   6017  1.5.2.2  jdolecek 	adapter->feat_cap &= ~IXGBE_FEATURE_RSS;
   6018  1.5.2.2  jdolecek 	adapter->feat_en  &= ~IXGBE_FEATURE_RSS;
   6019  1.5.2.2  jdolecek 	adapter->feat_cap &= ~IXGBE_FEATURE_SRIOV;
   6020  1.5.2.2  jdolecek 	adapter->feat_en  &= ~IXGBE_FEATURE_SRIOV;
   6021  1.5.2.2  jdolecek 
   6022  1.5.2.2  jdolecek        	msgs = pci_msi_count(adapter->osdep.pc, adapter->osdep.tag);
   6023  1.5.2.2  jdolecek 	adapter->msix_mem = NULL; /* XXX */
   6024  1.5.2.2  jdolecek 	if (msgs > 1)
   6025  1.5.2.2  jdolecek 		msgs = 1;
   6026  1.5.2.2  jdolecek 	if (msgs != 0) {
   6027  1.5.2.2  jdolecek 		msgs = 1;
   6028  1.5.2.2  jdolecek 		adapter->feat_en |= IXGBE_FEATURE_MSI;
   6029  1.5.2.2  jdolecek 		aprint_normal_dev(dev, "Using an MSI interrupt\n");
   6030  1.5.2.2  jdolecek 		return (0);
   6031  1.5.2.2  jdolecek 	}
   6032      1.1    dyoung 
   6033  1.5.2.2  jdolecek 	if (!(adapter->feat_cap & IXGBE_FEATURE_LEGACY_IRQ)) {
   6034  1.5.2.2  jdolecek 		aprint_error_dev(dev,
   6035  1.5.2.2  jdolecek 		    "Device does not support legacy interrupts.\n");
   6036  1.5.2.2  jdolecek 		return 1;
   6037  1.5.2.2  jdolecek 	}
   6038      1.1    dyoung 
   6039  1.5.2.2  jdolecek 	adapter->feat_en |= IXGBE_FEATURE_LEGACY_IRQ;
   6040  1.5.2.2  jdolecek 	aprint_normal_dev(dev, "Using a Legacy interrupt\n");
   6041      1.1    dyoung 
   6042  1.5.2.2  jdolecek 	return (0);
   6043  1.5.2.2  jdolecek } /* ixgbe_configure_interrupts */
   6044      1.1    dyoung 
   6045      1.1    dyoung 
   6046  1.5.2.2  jdolecek /************************************************************************
   6047  1.5.2.2  jdolecek  * ixgbe_handle_link - Tasklet for MSI-X Link interrupts
   6048  1.5.2.2  jdolecek  *
   6049  1.5.2.2  jdolecek  *   Done outside of interrupt context since the driver might sleep
   6050  1.5.2.2  jdolecek  ************************************************************************/
   6051  1.5.2.2  jdolecek static void
   6052  1.5.2.2  jdolecek ixgbe_handle_link(void *context)
   6053  1.5.2.2  jdolecek {
   6054  1.5.2.2  jdolecek 	struct adapter  *adapter = context;
   6055  1.5.2.2  jdolecek 	struct ixgbe_hw *hw = &adapter->hw;
   6056      1.1    dyoung 
   6057  1.5.2.2  jdolecek 	ixgbe_check_link(hw, &adapter->link_speed, &adapter->link_up, 0);
   6058  1.5.2.2  jdolecek 	ixgbe_update_link_status(adapter);
   6059      1.1    dyoung 
   6060  1.5.2.2  jdolecek 	/* Re-enable link interrupts */
   6061  1.5.2.2  jdolecek 	IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_LSC);
   6062  1.5.2.2  jdolecek } /* ixgbe_handle_link */
   6063  1.5.2.2  jdolecek 
   6064  1.5.2.2  jdolecek /************************************************************************
   6065  1.5.2.2  jdolecek  * ixgbe_rearm_queues
   6066  1.5.2.2  jdolecek  ************************************************************************/
   6067  1.5.2.2  jdolecek static void
   6068  1.5.2.2  jdolecek ixgbe_rearm_queues(struct adapter *adapter, u64 queues)
   6069  1.5.2.2  jdolecek {
   6070  1.5.2.2  jdolecek 	u32 mask;
   6071      1.1    dyoung 
   6072  1.5.2.2  jdolecek 	switch (adapter->hw.mac.type) {
   6073  1.5.2.2  jdolecek 	case ixgbe_mac_82598EB:
   6074  1.5.2.2  jdolecek 		mask = (IXGBE_EIMS_RTX_QUEUE & queues);
   6075  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask);
   6076  1.5.2.2  jdolecek 		break;
   6077  1.5.2.2  jdolecek 	case ixgbe_mac_82599EB:
   6078  1.5.2.2  jdolecek 	case ixgbe_mac_X540:
   6079  1.5.2.2  jdolecek 	case ixgbe_mac_X550:
   6080  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_x:
   6081  1.5.2.2  jdolecek 	case ixgbe_mac_X550EM_a:
   6082  1.5.2.2  jdolecek 		mask = (queues & 0xFFFFFFFF);
   6083  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask);
   6084  1.5.2.2  jdolecek 		mask = (queues >> 32);
   6085  1.5.2.2  jdolecek 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), mask);
   6086  1.5.2.2  jdolecek 		break;
   6087  1.5.2.2  jdolecek 	default:
   6088  1.5.2.2  jdolecek 		break;
   6089  1.5.2.2  jdolecek 	}
   6090  1.5.2.2  jdolecek } /* ixgbe_rearm_queues */
   6091