1*61ae650dSJack F Vogel /****************************************************************************** 2*61ae650dSJack F Vogel 3*61ae650dSJack F Vogel Copyright (c) 2013-2014, Intel Corporation 4*61ae650dSJack F Vogel All rights reserved. 5*61ae650dSJack F Vogel 6*61ae650dSJack F Vogel Redistribution and use in source and binary forms, with or without 7*61ae650dSJack F Vogel modification, are permitted provided that the following conditions are met: 8*61ae650dSJack F Vogel 9*61ae650dSJack F Vogel 1. Redistributions of source code must retain the above copyright notice, 10*61ae650dSJack F Vogel this list of conditions and the following disclaimer. 11*61ae650dSJack F Vogel 12*61ae650dSJack F Vogel 2. Redistributions in binary form must reproduce the above copyright 13*61ae650dSJack F Vogel notice, this list of conditions and the following disclaimer in the 14*61ae650dSJack F Vogel documentation and/or other materials provided with the distribution. 15*61ae650dSJack F Vogel 16*61ae650dSJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its 17*61ae650dSJack F Vogel contributors may be used to endorse or promote products derived from 18*61ae650dSJack F Vogel this software without specific prior written permission. 19*61ae650dSJack F Vogel 20*61ae650dSJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21*61ae650dSJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*61ae650dSJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*61ae650dSJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24*61ae650dSJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25*61ae650dSJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26*61ae650dSJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27*61ae650dSJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28*61ae650dSJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29*61ae650dSJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30*61ae650dSJack F Vogel POSSIBILITY OF SUCH DAMAGE. 31*61ae650dSJack F Vogel 32*61ae650dSJack F Vogel ******************************************************************************/ 33*61ae650dSJack F Vogel /*$FreeBSD$*/ 34*61ae650dSJack F Vogel 35*61ae650dSJack F Vogel #include "opt_inet.h" 36*61ae650dSJack F Vogel #include "opt_inet6.h" 37*61ae650dSJack F Vogel #include "ixl.h" 38*61ae650dSJack F Vogel #include "ixl_pf.h" 39*61ae650dSJack F Vogel 40*61ae650dSJack F Vogel /********************************************************************* 41*61ae650dSJack F Vogel * Driver version 42*61ae650dSJack F Vogel *********************************************************************/ 43*61ae650dSJack F Vogel char ixl_driver_version[] = "1.2.2"; 44*61ae650dSJack F Vogel 45*61ae650dSJack F Vogel /********************************************************************* 46*61ae650dSJack F Vogel * PCI Device ID Table 47*61ae650dSJack F Vogel * 48*61ae650dSJack F Vogel * Used by probe to select devices to load on 49*61ae650dSJack F Vogel * Last field stores an index into ixl_strings 50*61ae650dSJack F Vogel * Last entry must be all 0s 51*61ae650dSJack F Vogel * 52*61ae650dSJack F Vogel * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } 53*61ae650dSJack F Vogel *********************************************************************/ 54*61ae650dSJack F Vogel 55*61ae650dSJack F Vogel static ixl_vendor_info_t ixl_vendor_info_array[] = 56*61ae650dSJack F Vogel { 57*61ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710, 0, 0, 0}, 58*61ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_A, 0, 0, 0}, 59*61ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B, 0, 0, 0}, 60*61ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C, 0, 0, 0}, 61*61ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A, 0, 0, 0}, 62*61ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B, 0, 0, 0}, 63*61ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_C, 0, 0, 0}, 64*61ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T, 0, 0, 0}, 65*61ae650dSJack F Vogel /* required last entry */ 66*61ae650dSJack F Vogel {0, 0, 0, 0, 0} 67*61ae650dSJack F Vogel }; 68*61ae650dSJack F Vogel 69*61ae650dSJack F Vogel /********************************************************************* 70*61ae650dSJack F Vogel * Table of branding strings 71*61ae650dSJack F Vogel *********************************************************************/ 72*61ae650dSJack F Vogel 73*61ae650dSJack F Vogel static char *ixl_strings[] = { 74*61ae650dSJack F Vogel "Intel(R) Ethernet Connection XL710 Driver" 75*61ae650dSJack F Vogel }; 76*61ae650dSJack F Vogel 77*61ae650dSJack F Vogel 78*61ae650dSJack F Vogel /********************************************************************* 79*61ae650dSJack F Vogel * Function prototypes 80*61ae650dSJack F Vogel *********************************************************************/ 81*61ae650dSJack F Vogel static int ixl_probe(device_t); 82*61ae650dSJack F Vogel static int ixl_attach(device_t); 83*61ae650dSJack F Vogel static int ixl_detach(device_t); 84*61ae650dSJack F Vogel static int ixl_shutdown(device_t); 85*61ae650dSJack F Vogel static int ixl_get_hw_capabilities(struct ixl_pf *); 86*61ae650dSJack F Vogel static void ixl_cap_txcsum_tso(struct ixl_vsi *, struct ifnet *, int); 87*61ae650dSJack F Vogel static int ixl_ioctl(struct ifnet *, u_long, caddr_t); 88*61ae650dSJack F Vogel static void ixl_init(void *); 89*61ae650dSJack F Vogel static void ixl_init_locked(struct ixl_pf *); 90*61ae650dSJack F Vogel static void ixl_stop(struct ixl_pf *); 91*61ae650dSJack F Vogel static void ixl_media_status(struct ifnet *, struct ifmediareq *); 92*61ae650dSJack F Vogel static int ixl_media_change(struct ifnet *); 93*61ae650dSJack F Vogel static void ixl_update_link_status(struct ixl_pf *); 94*61ae650dSJack F Vogel static int ixl_allocate_pci_resources(struct ixl_pf *); 95*61ae650dSJack F Vogel static u16 ixl_get_bus_info(struct i40e_hw *, device_t); 96*61ae650dSJack F Vogel static int ixl_setup_stations(struct ixl_pf *); 97*61ae650dSJack F Vogel static int ixl_setup_vsi(struct ixl_vsi *); 98*61ae650dSJack F Vogel static int ixl_initialize_vsi(struct ixl_vsi *); 99*61ae650dSJack F Vogel static int ixl_assign_vsi_msix(struct ixl_pf *); 100*61ae650dSJack F Vogel static int ixl_assign_vsi_legacy(struct ixl_pf *); 101*61ae650dSJack F Vogel static int ixl_init_msix(struct ixl_pf *); 102*61ae650dSJack F Vogel static void ixl_configure_msix(struct ixl_pf *); 103*61ae650dSJack F Vogel static void ixl_configure_itr(struct ixl_pf *); 104*61ae650dSJack F Vogel static void ixl_configure_legacy(struct ixl_pf *); 105*61ae650dSJack F Vogel static void ixl_free_pci_resources(struct ixl_pf *); 106*61ae650dSJack F Vogel static void ixl_local_timer(void *); 107*61ae650dSJack F Vogel static int ixl_setup_interface(device_t, struct ixl_vsi *); 108*61ae650dSJack F Vogel static bool ixl_config_link(struct i40e_hw *); 109*61ae650dSJack F Vogel static void ixl_config_rss(struct ixl_vsi *); 110*61ae650dSJack F Vogel static void ixl_set_queue_rx_itr(struct ixl_queue *); 111*61ae650dSJack F Vogel static void ixl_set_queue_tx_itr(struct ixl_queue *); 112*61ae650dSJack F Vogel 113*61ae650dSJack F Vogel static void ixl_enable_rings(struct ixl_vsi *); 114*61ae650dSJack F Vogel static void ixl_disable_rings(struct ixl_vsi *); 115*61ae650dSJack F Vogel static void ixl_enable_intr(struct ixl_vsi *); 116*61ae650dSJack F Vogel static void ixl_disable_intr(struct ixl_vsi *); 117*61ae650dSJack F Vogel 118*61ae650dSJack F Vogel static void ixl_enable_adminq(struct i40e_hw *); 119*61ae650dSJack F Vogel static void ixl_disable_adminq(struct i40e_hw *); 120*61ae650dSJack F Vogel static void ixl_enable_queue(struct i40e_hw *, int); 121*61ae650dSJack F Vogel static void ixl_disable_queue(struct i40e_hw *, int); 122*61ae650dSJack F Vogel static void ixl_enable_legacy(struct i40e_hw *); 123*61ae650dSJack F Vogel static void ixl_disable_legacy(struct i40e_hw *); 124*61ae650dSJack F Vogel 125*61ae650dSJack F Vogel static void ixl_set_promisc(struct ixl_vsi *); 126*61ae650dSJack F Vogel static void ixl_add_multi(struct ixl_vsi *); 127*61ae650dSJack F Vogel static void ixl_del_multi(struct ixl_vsi *); 128*61ae650dSJack F Vogel static void ixl_register_vlan(void *, struct ifnet *, u16); 129*61ae650dSJack F Vogel static void ixl_unregister_vlan(void *, struct ifnet *, u16); 130*61ae650dSJack F Vogel static void ixl_setup_vlan_filters(struct ixl_vsi *); 131*61ae650dSJack F Vogel 132*61ae650dSJack F Vogel static void ixl_init_filters(struct ixl_vsi *); 133*61ae650dSJack F Vogel static void ixl_add_filter(struct ixl_vsi *, u8 *, s16 vlan); 134*61ae650dSJack F Vogel static void ixl_del_filter(struct ixl_vsi *, u8 *, s16 vlan); 135*61ae650dSJack F Vogel static void ixl_add_hw_filters(struct ixl_vsi *, int, int); 136*61ae650dSJack F Vogel static void ixl_del_hw_filters(struct ixl_vsi *, int); 137*61ae650dSJack F Vogel static struct ixl_mac_filter * 138*61ae650dSJack F Vogel ixl_find_filter(struct ixl_vsi *, u8 *, s16); 139*61ae650dSJack F Vogel static void ixl_add_mc_filter(struct ixl_vsi *, u8 *); 140*61ae650dSJack F Vogel 141*61ae650dSJack F Vogel /* Sysctl debug interface */ 142*61ae650dSJack F Vogel static int ixl_debug_info(SYSCTL_HANDLER_ARGS); 143*61ae650dSJack F Vogel static void ixl_print_debug_info(struct ixl_pf *); 144*61ae650dSJack F Vogel 145*61ae650dSJack F Vogel /* The MSI/X Interrupt handlers */ 146*61ae650dSJack F Vogel static void ixl_intr(void *); 147*61ae650dSJack F Vogel static void ixl_msix_que(void *); 148*61ae650dSJack F Vogel static void ixl_msix_adminq(void *); 149*61ae650dSJack F Vogel static void ixl_handle_mdd_event(struct ixl_pf *); 150*61ae650dSJack F Vogel 151*61ae650dSJack F Vogel /* Deferred interrupt tasklets */ 152*61ae650dSJack F Vogel static void ixl_do_adminq(void *, int); 153*61ae650dSJack F Vogel 154*61ae650dSJack F Vogel /* Sysctl handlers */ 155*61ae650dSJack F Vogel static int ixl_set_flowcntl(SYSCTL_HANDLER_ARGS); 156*61ae650dSJack F Vogel static int ixl_set_advertise(SYSCTL_HANDLER_ARGS); 157*61ae650dSJack F Vogel static int ixl_current_speed(SYSCTL_HANDLER_ARGS); 158*61ae650dSJack F Vogel 159*61ae650dSJack F Vogel /* Statistics */ 160*61ae650dSJack F Vogel static void ixl_add_hw_stats(struct ixl_pf *); 161*61ae650dSJack F Vogel static void ixl_add_sysctls_mac_stats(struct sysctl_ctx_list *, 162*61ae650dSJack F Vogel struct sysctl_oid_list *, struct i40e_hw_port_stats *); 163*61ae650dSJack F Vogel static void ixl_add_sysctls_eth_stats(struct sysctl_ctx_list *, 164*61ae650dSJack F Vogel struct sysctl_oid_list *, 165*61ae650dSJack F Vogel struct i40e_eth_stats *); 166*61ae650dSJack F Vogel static void ixl_update_stats_counters(struct ixl_pf *); 167*61ae650dSJack F Vogel static void ixl_update_eth_stats(struct ixl_vsi *); 168*61ae650dSJack F Vogel static void ixl_pf_reset_stats(struct ixl_pf *); 169*61ae650dSJack F Vogel static void ixl_vsi_reset_stats(struct ixl_vsi *); 170*61ae650dSJack F Vogel static void ixl_stat_update48(struct i40e_hw *, u32, u32, bool, 171*61ae650dSJack F Vogel u64 *, u64 *); 172*61ae650dSJack F Vogel static void ixl_stat_update32(struct i40e_hw *, u32, bool, 173*61ae650dSJack F Vogel u64 *, u64 *); 174*61ae650dSJack F Vogel 175*61ae650dSJack F Vogel #ifdef IXL_DEBUG 176*61ae650dSJack F Vogel static int ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS); 177*61ae650dSJack F Vogel static int ixl_sysctl_phy_abilities(SYSCTL_HANDLER_ARGS); 178*61ae650dSJack F Vogel static int ixl_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS); 179*61ae650dSJack F Vogel static int ixl_sysctl_hw_res_info(SYSCTL_HANDLER_ARGS); 180*61ae650dSJack F Vogel static int ixl_sysctl_dump_txd(SYSCTL_HANDLER_ARGS); 181*61ae650dSJack F Vogel #endif 182*61ae650dSJack F Vogel 183*61ae650dSJack F Vogel /********************************************************************* 184*61ae650dSJack F Vogel * FreeBSD Device Interface Entry Points 185*61ae650dSJack F Vogel *********************************************************************/ 186*61ae650dSJack F Vogel 187*61ae650dSJack F Vogel static device_method_t ixl_methods[] = { 188*61ae650dSJack F Vogel /* Device interface */ 189*61ae650dSJack F Vogel DEVMETHOD(device_probe, ixl_probe), 190*61ae650dSJack F Vogel DEVMETHOD(device_attach, ixl_attach), 191*61ae650dSJack F Vogel DEVMETHOD(device_detach, ixl_detach), 192*61ae650dSJack F Vogel DEVMETHOD(device_shutdown, ixl_shutdown), 193*61ae650dSJack F Vogel {0, 0} 194*61ae650dSJack F Vogel }; 195*61ae650dSJack F Vogel 196*61ae650dSJack F Vogel static driver_t ixl_driver = { 197*61ae650dSJack F Vogel "ixl", ixl_methods, sizeof(struct ixl_pf), 198*61ae650dSJack F Vogel }; 199*61ae650dSJack F Vogel 200*61ae650dSJack F Vogel devclass_t ixl_devclass; 201*61ae650dSJack F Vogel DRIVER_MODULE(ixl, pci, ixl_driver, ixl_devclass, 0, 0); 202*61ae650dSJack F Vogel 203*61ae650dSJack F Vogel MODULE_DEPEND(ixl, pci, 1, 1, 1); 204*61ae650dSJack F Vogel MODULE_DEPEND(ixl, ether, 1, 1, 1); 205*61ae650dSJack F Vogel 206*61ae650dSJack F Vogel /* 207*61ae650dSJack F Vogel ** Global reset mutex 208*61ae650dSJack F Vogel */ 209*61ae650dSJack F Vogel static struct mtx ixl_reset_mtx; 210*61ae650dSJack F Vogel 211*61ae650dSJack F Vogel /* 212*61ae650dSJack F Vogel ** TUNEABLE PARAMETERS: 213*61ae650dSJack F Vogel */ 214*61ae650dSJack F Vogel 215*61ae650dSJack F Vogel static SYSCTL_NODE(_hw, OID_AUTO, ixl, CTLFLAG_RD, 0, 216*61ae650dSJack F Vogel "IXL driver parameters"); 217*61ae650dSJack F Vogel 218*61ae650dSJack F Vogel /* 219*61ae650dSJack F Vogel * MSIX should be the default for best performance, 220*61ae650dSJack F Vogel * but this allows it to be forced off for testing. 221*61ae650dSJack F Vogel */ 222*61ae650dSJack F Vogel static int ixl_enable_msix = 1; 223*61ae650dSJack F Vogel TUNABLE_INT("hw.ixl.enable_msix", &ixl_enable_msix); 224*61ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixl_enable_msix, 0, 225*61ae650dSJack F Vogel "Enable MSI-X interrupts"); 226*61ae650dSJack F Vogel 227*61ae650dSJack F Vogel /* 228*61ae650dSJack F Vogel ** Number of descriptors per ring: 229*61ae650dSJack F Vogel ** - TX and RX are the same size 230*61ae650dSJack F Vogel */ 231*61ae650dSJack F Vogel static int ixl_ringsz = DEFAULT_RING; 232*61ae650dSJack F Vogel TUNABLE_INT("hw.ixl.ringsz", &ixl_ringsz); 233*61ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, ring_size, CTLFLAG_RDTUN, 234*61ae650dSJack F Vogel &ixl_ringsz, 0, "Descriptor Ring Size"); 235*61ae650dSJack F Vogel 236*61ae650dSJack F Vogel /* 237*61ae650dSJack F Vogel ** This can be set manually, if left as 0 the 238*61ae650dSJack F Vogel ** number of queues will be calculated based 239*61ae650dSJack F Vogel ** on cpus and msix vectors available. 240*61ae650dSJack F Vogel */ 241*61ae650dSJack F Vogel int ixl_max_queues = 0; 242*61ae650dSJack F Vogel TUNABLE_INT("hw.ixl.max_queues", &ixl_max_queues); 243*61ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, max_queues, CTLFLAG_RDTUN, 244*61ae650dSJack F Vogel &ixl_max_queues, 0, "Number of Queues"); 245*61ae650dSJack F Vogel 246*61ae650dSJack F Vogel /* 247*61ae650dSJack F Vogel ** Controls for Interrupt Throttling 248*61ae650dSJack F Vogel ** - true/false for dynamic adjustment 249*61ae650dSJack F Vogel ** - default values for static ITR 250*61ae650dSJack F Vogel */ 251*61ae650dSJack F Vogel int ixl_dynamic_rx_itr = 0; 252*61ae650dSJack F Vogel TUNABLE_INT("hw.ixl.dynamic_rx_itr", &ixl_dynamic_rx_itr); 253*61ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_rx_itr, CTLFLAG_RDTUN, 254*61ae650dSJack F Vogel &ixl_dynamic_rx_itr, 0, "Dynamic RX Interrupt Rate"); 255*61ae650dSJack F Vogel 256*61ae650dSJack F Vogel int ixl_dynamic_tx_itr = 0; 257*61ae650dSJack F Vogel TUNABLE_INT("hw.ixl.dynamic_tx_itr", &ixl_dynamic_tx_itr); 258*61ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_tx_itr, CTLFLAG_RDTUN, 259*61ae650dSJack F Vogel &ixl_dynamic_tx_itr, 0, "Dynamic TX Interrupt Rate"); 260*61ae650dSJack F Vogel 261*61ae650dSJack F Vogel int ixl_rx_itr = IXL_ITR_8K; 262*61ae650dSJack F Vogel TUNABLE_INT("hw.ixl.rx_itr", &ixl_rx_itr); 263*61ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, rx_itr, CTLFLAG_RDTUN, 264*61ae650dSJack F Vogel &ixl_rx_itr, 0, "RX Interrupt Rate"); 265*61ae650dSJack F Vogel 266*61ae650dSJack F Vogel int ixl_tx_itr = IXL_ITR_4K; 267*61ae650dSJack F Vogel TUNABLE_INT("hw.ixl.tx_itr", &ixl_tx_itr); 268*61ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, tx_itr, CTLFLAG_RDTUN, 269*61ae650dSJack F Vogel &ixl_tx_itr, 0, "TX Interrupt Rate"); 270*61ae650dSJack F Vogel 271*61ae650dSJack F Vogel #ifdef IXL_FDIR 272*61ae650dSJack F Vogel static int ixl_enable_fdir = 1; 273*61ae650dSJack F Vogel TUNABLE_INT("hw.ixl.enable_fdir", &ixl_enable_fdir); 274*61ae650dSJack F Vogel /* Rate at which we sample */ 275*61ae650dSJack F Vogel int ixl_atr_rate = 20; 276*61ae650dSJack F Vogel TUNABLE_INT("hw.ixl.atr_rate", &ixl_atr_rate); 277*61ae650dSJack F Vogel #endif 278*61ae650dSJack F Vogel 279*61ae650dSJack F Vogel #ifdef DEV_NETMAP 280*61ae650dSJack F Vogel #include <dev/netmap/if_ixl_netmap.h> 281*61ae650dSJack F Vogel #endif /* DEV_NETMAP */ 282*61ae650dSJack F Vogel 283*61ae650dSJack F Vogel static char *ixl_fc_string[6] = { 284*61ae650dSJack F Vogel "None", 285*61ae650dSJack F Vogel "Rx", 286*61ae650dSJack F Vogel "Tx", 287*61ae650dSJack F Vogel "Full", 288*61ae650dSJack F Vogel "Priority", 289*61ae650dSJack F Vogel "Default" 290*61ae650dSJack F Vogel }; 291*61ae650dSJack F Vogel 292*61ae650dSJack F Vogel 293*61ae650dSJack F Vogel /********************************************************************* 294*61ae650dSJack F Vogel * Device identification routine 295*61ae650dSJack F Vogel * 296*61ae650dSJack F Vogel * ixl_probe determines if the driver should be loaded on 297*61ae650dSJack F Vogel * the hardware based on PCI vendor/device id of the device. 298*61ae650dSJack F Vogel * 299*61ae650dSJack F Vogel * return BUS_PROBE_DEFAULT on success, positive on failure 300*61ae650dSJack F Vogel *********************************************************************/ 301*61ae650dSJack F Vogel 302*61ae650dSJack F Vogel static int 303*61ae650dSJack F Vogel ixl_probe(device_t dev) 304*61ae650dSJack F Vogel { 305*61ae650dSJack F Vogel ixl_vendor_info_t *ent; 306*61ae650dSJack F Vogel 307*61ae650dSJack F Vogel u16 pci_vendor_id, pci_device_id; 308*61ae650dSJack F Vogel u16 pci_subvendor_id, pci_subdevice_id; 309*61ae650dSJack F Vogel char device_name[256]; 310*61ae650dSJack F Vogel static bool lock_init = FALSE; 311*61ae650dSJack F Vogel 312*61ae650dSJack F Vogel INIT_DEBUGOUT("ixl_probe: begin"); 313*61ae650dSJack F Vogel 314*61ae650dSJack F Vogel pci_vendor_id = pci_get_vendor(dev); 315*61ae650dSJack F Vogel if (pci_vendor_id != I40E_INTEL_VENDOR_ID) 316*61ae650dSJack F Vogel return (ENXIO); 317*61ae650dSJack F Vogel 318*61ae650dSJack F Vogel pci_device_id = pci_get_device(dev); 319*61ae650dSJack F Vogel pci_subvendor_id = pci_get_subvendor(dev); 320*61ae650dSJack F Vogel pci_subdevice_id = pci_get_subdevice(dev); 321*61ae650dSJack F Vogel 322*61ae650dSJack F Vogel ent = ixl_vendor_info_array; 323*61ae650dSJack F Vogel while (ent->vendor_id != 0) { 324*61ae650dSJack F Vogel if ((pci_vendor_id == ent->vendor_id) && 325*61ae650dSJack F Vogel (pci_device_id == ent->device_id) && 326*61ae650dSJack F Vogel 327*61ae650dSJack F Vogel ((pci_subvendor_id == ent->subvendor_id) || 328*61ae650dSJack F Vogel (ent->subvendor_id == 0)) && 329*61ae650dSJack F Vogel 330*61ae650dSJack F Vogel ((pci_subdevice_id == ent->subdevice_id) || 331*61ae650dSJack F Vogel (ent->subdevice_id == 0))) { 332*61ae650dSJack F Vogel sprintf(device_name, "%s, Version - %s", 333*61ae650dSJack F Vogel ixl_strings[ent->index], 334*61ae650dSJack F Vogel ixl_driver_version); 335*61ae650dSJack F Vogel device_set_desc_copy(dev, device_name); 336*61ae650dSJack F Vogel /* One shot mutex init */ 337*61ae650dSJack F Vogel if (lock_init == FALSE) { 338*61ae650dSJack F Vogel lock_init = TRUE; 339*61ae650dSJack F Vogel mtx_init(&ixl_reset_mtx, 340*61ae650dSJack F Vogel "ixl_reset", 341*61ae650dSJack F Vogel "IXL RESET Lock", MTX_DEF); 342*61ae650dSJack F Vogel } 343*61ae650dSJack F Vogel return (BUS_PROBE_DEFAULT); 344*61ae650dSJack F Vogel } 345*61ae650dSJack F Vogel ent++; 346*61ae650dSJack F Vogel } 347*61ae650dSJack F Vogel return (ENXIO); 348*61ae650dSJack F Vogel } 349*61ae650dSJack F Vogel 350*61ae650dSJack F Vogel /********************************************************************* 351*61ae650dSJack F Vogel * Device initialization routine 352*61ae650dSJack F Vogel * 353*61ae650dSJack F Vogel * The attach entry point is called when the driver is being loaded. 354*61ae650dSJack F Vogel * This routine identifies the type of hardware, allocates all resources 355*61ae650dSJack F Vogel * and initializes the hardware. 356*61ae650dSJack F Vogel * 357*61ae650dSJack F Vogel * return 0 on success, positive on failure 358*61ae650dSJack F Vogel *********************************************************************/ 359*61ae650dSJack F Vogel 360*61ae650dSJack F Vogel static int 361*61ae650dSJack F Vogel ixl_attach(device_t dev) 362*61ae650dSJack F Vogel { 363*61ae650dSJack F Vogel struct ixl_pf *pf; 364*61ae650dSJack F Vogel struct i40e_hw *hw; 365*61ae650dSJack F Vogel struct ixl_vsi *vsi; 366*61ae650dSJack F Vogel u16 bus; 367*61ae650dSJack F Vogel int error = 0; 368*61ae650dSJack F Vogel 369*61ae650dSJack F Vogel INIT_DEBUGOUT("ixl_attach: begin"); 370*61ae650dSJack F Vogel 371*61ae650dSJack F Vogel /* Allocate, clear, and link in our primary soft structure */ 372*61ae650dSJack F Vogel pf = device_get_softc(dev); 373*61ae650dSJack F Vogel pf->dev = pf->osdep.dev = dev; 374*61ae650dSJack F Vogel hw = &pf->hw; 375*61ae650dSJack F Vogel 376*61ae650dSJack F Vogel /* 377*61ae650dSJack F Vogel ** Note this assumes we have a single embedded VSI, 378*61ae650dSJack F Vogel ** this could be enhanced later to allocate multiple 379*61ae650dSJack F Vogel */ 380*61ae650dSJack F Vogel vsi = &pf->vsi; 381*61ae650dSJack F Vogel vsi->dev = pf->dev; 382*61ae650dSJack F Vogel 383*61ae650dSJack F Vogel /* Core Lock Init*/ 384*61ae650dSJack F Vogel IXL_PF_LOCK_INIT(pf, device_get_nameunit(dev)); 385*61ae650dSJack F Vogel 386*61ae650dSJack F Vogel /* Set up the timer callout */ 387*61ae650dSJack F Vogel callout_init_mtx(&pf->timer, &pf->pf_mtx, 0); 388*61ae650dSJack F Vogel 389*61ae650dSJack F Vogel /* Set up sysctls */ 390*61ae650dSJack F Vogel SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 391*61ae650dSJack F Vogel SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 392*61ae650dSJack F Vogel OID_AUTO, "fc", CTLTYPE_INT | CTLFLAG_RW, 393*61ae650dSJack F Vogel pf, 0, ixl_set_flowcntl, "I", "Flow Control"); 394*61ae650dSJack F Vogel 395*61ae650dSJack F Vogel SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 396*61ae650dSJack F Vogel SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 397*61ae650dSJack F Vogel OID_AUTO, "advertise_speed", CTLTYPE_INT | CTLFLAG_RW, 398*61ae650dSJack F Vogel pf, 0, ixl_set_advertise, "I", "Advertised Speed"); 399*61ae650dSJack F Vogel 400*61ae650dSJack F Vogel SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 401*61ae650dSJack F Vogel SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 402*61ae650dSJack F Vogel OID_AUTO, "current_speed", CTLTYPE_STRING | CTLFLAG_RD, 403*61ae650dSJack F Vogel pf, 0, ixl_current_speed, "A", "Current Port Speed"); 404*61ae650dSJack F Vogel 405*61ae650dSJack F Vogel SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 406*61ae650dSJack F Vogel SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 407*61ae650dSJack F Vogel OID_AUTO, "rx_itr", CTLTYPE_INT | CTLFLAG_RW, 408*61ae650dSJack F Vogel &ixl_rx_itr, IXL_ITR_8K, "RX ITR"); 409*61ae650dSJack F Vogel 410*61ae650dSJack F Vogel SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 411*61ae650dSJack F Vogel SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 412*61ae650dSJack F Vogel OID_AUTO, "dynamic_rx_itr", CTLTYPE_INT | CTLFLAG_RW, 413*61ae650dSJack F Vogel &ixl_dynamic_rx_itr, 0, "Dynamic RX ITR"); 414*61ae650dSJack F Vogel 415*61ae650dSJack F Vogel SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 416*61ae650dSJack F Vogel SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 417*61ae650dSJack F Vogel OID_AUTO, "tx_itr", CTLTYPE_INT | CTLFLAG_RW, 418*61ae650dSJack F Vogel &ixl_tx_itr, IXL_ITR_4K, "TX ITR"); 419*61ae650dSJack F Vogel 420*61ae650dSJack F Vogel SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 421*61ae650dSJack F Vogel SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 422*61ae650dSJack F Vogel OID_AUTO, "dynamic_tx_itr", CTLTYPE_INT | CTLFLAG_RW, 423*61ae650dSJack F Vogel &ixl_dynamic_tx_itr, 0, "Dynamic TX ITR"); 424*61ae650dSJack F Vogel 425*61ae650dSJack F Vogel #ifdef IXL_DEBUG 426*61ae650dSJack F Vogel SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 427*61ae650dSJack F Vogel SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 428*61ae650dSJack F Vogel OID_AUTO, "link_status", CTLTYPE_STRING | CTLFLAG_RD, 429*61ae650dSJack F Vogel pf, 0, ixl_sysctl_link_status, "A", "Current Link Status"); 430*61ae650dSJack F Vogel 431*61ae650dSJack F Vogel SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 432*61ae650dSJack F Vogel SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 433*61ae650dSJack F Vogel OID_AUTO, "phy_abilities", CTLTYPE_STRING | CTLFLAG_RD, 434*61ae650dSJack F Vogel pf, 0, ixl_sysctl_phy_abilities, "A", "PHY Abilities"); 435*61ae650dSJack F Vogel 436*61ae650dSJack F Vogel SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 437*61ae650dSJack F Vogel SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 438*61ae650dSJack F Vogel OID_AUTO, "filter_list", CTLTYPE_STRING | CTLFLAG_RD, 439*61ae650dSJack F Vogel pf, 0, ixl_sysctl_sw_filter_list, "A", "SW Filter List"); 440*61ae650dSJack F Vogel 441*61ae650dSJack F Vogel SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 442*61ae650dSJack F Vogel SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 443*61ae650dSJack F Vogel OID_AUTO, "hw_res_info", CTLTYPE_STRING | CTLFLAG_RD, 444*61ae650dSJack F Vogel pf, 0, ixl_sysctl_hw_res_info, "A", "HW Resource Allocation"); 445*61ae650dSJack F Vogel 446*61ae650dSJack F Vogel SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 447*61ae650dSJack F Vogel SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 448*61ae650dSJack F Vogel OID_AUTO, "dump_desc", CTLTYPE_INT | CTLFLAG_WR, 449*61ae650dSJack F Vogel pf, 0, ixl_sysctl_dump_txd, "I", "Desc dump"); 450*61ae650dSJack F Vogel #endif 451*61ae650dSJack F Vogel 452*61ae650dSJack F Vogel /* Save off the information about this board */ 453*61ae650dSJack F Vogel hw->vendor_id = pci_get_vendor(dev); 454*61ae650dSJack F Vogel hw->device_id = pci_get_device(dev); 455*61ae650dSJack F Vogel hw->revision_id = pci_read_config(dev, PCIR_REVID, 1); 456*61ae650dSJack F Vogel hw->subsystem_vendor_id = 457*61ae650dSJack F Vogel pci_read_config(dev, PCIR_SUBVEND_0, 2); 458*61ae650dSJack F Vogel hw->subsystem_device_id = 459*61ae650dSJack F Vogel pci_read_config(dev, PCIR_SUBDEV_0, 2); 460*61ae650dSJack F Vogel 461*61ae650dSJack F Vogel hw->bus.device = pci_get_slot(dev); 462*61ae650dSJack F Vogel hw->bus.func = pci_get_function(dev); 463*61ae650dSJack F Vogel 464*61ae650dSJack F Vogel /* Do PCI setup - map BAR0, etc */ 465*61ae650dSJack F Vogel if (ixl_allocate_pci_resources(pf)) { 466*61ae650dSJack F Vogel device_printf(dev, "Allocation of PCI resources failed\n"); 467*61ae650dSJack F Vogel error = ENXIO; 468*61ae650dSJack F Vogel goto err_out; 469*61ae650dSJack F Vogel } 470*61ae650dSJack F Vogel 471*61ae650dSJack F Vogel /* Create for initial debugging use */ 472*61ae650dSJack F Vogel SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 473*61ae650dSJack F Vogel SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 474*61ae650dSJack F Vogel OID_AUTO, "debug", CTLTYPE_INT|CTLFLAG_RW, pf, 0, 475*61ae650dSJack F Vogel ixl_debug_info, "I", "Debug Information"); 476*61ae650dSJack F Vogel 477*61ae650dSJack F Vogel 478*61ae650dSJack F Vogel /* Establish a clean starting point */ 479*61ae650dSJack F Vogel i40e_clear_hw(hw); 480*61ae650dSJack F Vogel error = i40e_pf_reset(hw); 481*61ae650dSJack F Vogel if (error) { 482*61ae650dSJack F Vogel device_printf(dev,"PF reset failure %x\n", error); 483*61ae650dSJack F Vogel error = EIO; 484*61ae650dSJack F Vogel goto err_out; 485*61ae650dSJack F Vogel } 486*61ae650dSJack F Vogel 487*61ae650dSJack F Vogel /* For now always do an initial CORE reset on first device */ 488*61ae650dSJack F Vogel { 489*61ae650dSJack F Vogel static int ixl_dev_count; 490*61ae650dSJack F Vogel static int ixl_dev_track[32]; 491*61ae650dSJack F Vogel u32 my_dev; 492*61ae650dSJack F Vogel int i, found = FALSE; 493*61ae650dSJack F Vogel u16 bus = pci_get_bus(dev); 494*61ae650dSJack F Vogel 495*61ae650dSJack F Vogel mtx_lock(&ixl_reset_mtx); 496*61ae650dSJack F Vogel my_dev = (bus << 8) | hw->bus.device; 497*61ae650dSJack F Vogel 498*61ae650dSJack F Vogel for (i = 0; i < ixl_dev_count; i++) { 499*61ae650dSJack F Vogel if (ixl_dev_track[i] == my_dev) 500*61ae650dSJack F Vogel found = TRUE; 501*61ae650dSJack F Vogel } 502*61ae650dSJack F Vogel 503*61ae650dSJack F Vogel if (!found) { 504*61ae650dSJack F Vogel u32 reg; 505*61ae650dSJack F Vogel 506*61ae650dSJack F Vogel ixl_dev_track[ixl_dev_count] = my_dev; 507*61ae650dSJack F Vogel ixl_dev_count++; 508*61ae650dSJack F Vogel 509*61ae650dSJack F Vogel INIT_DEBUGOUT("Initial CORE RESET\n"); 510*61ae650dSJack F Vogel wr32(hw, I40E_GLGEN_RTRIG, I40E_GLGEN_RTRIG_CORER_MASK); 511*61ae650dSJack F Vogel ixl_flush(hw); 512*61ae650dSJack F Vogel i = 50; 513*61ae650dSJack F Vogel do { 514*61ae650dSJack F Vogel i40e_msec_delay(50); 515*61ae650dSJack F Vogel reg = rd32(hw, I40E_GLGEN_RSTAT); 516*61ae650dSJack F Vogel if (!(reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK)) 517*61ae650dSJack F Vogel break; 518*61ae650dSJack F Vogel } while (i--); 519*61ae650dSJack F Vogel 520*61ae650dSJack F Vogel /* paranoia */ 521*61ae650dSJack F Vogel wr32(hw, I40E_PF_ATQLEN, 0); 522*61ae650dSJack F Vogel wr32(hw, I40E_PF_ATQBAL, 0); 523*61ae650dSJack F Vogel wr32(hw, I40E_PF_ATQBAH, 0); 524*61ae650dSJack F Vogel i40e_clear_pxe_mode(hw); 525*61ae650dSJack F Vogel } 526*61ae650dSJack F Vogel mtx_unlock(&ixl_reset_mtx); 527*61ae650dSJack F Vogel } 528*61ae650dSJack F Vogel 529*61ae650dSJack F Vogel /* Set admin queue parameters */ 530*61ae650dSJack F Vogel hw->aq.num_arq_entries = IXL_AQ_LEN; 531*61ae650dSJack F Vogel hw->aq.num_asq_entries = IXL_AQ_LEN; 532*61ae650dSJack F Vogel hw->aq.arq_buf_size = IXL_AQ_BUFSZ; 533*61ae650dSJack F Vogel hw->aq.asq_buf_size = IXL_AQ_BUFSZ; 534*61ae650dSJack F Vogel 535*61ae650dSJack F Vogel /* Initialize the shared code */ 536*61ae650dSJack F Vogel error = i40e_init_shared_code(hw); 537*61ae650dSJack F Vogel if (error) { 538*61ae650dSJack F Vogel device_printf(dev,"Unable to initialize the shared code\n"); 539*61ae650dSJack F Vogel error = EIO; 540*61ae650dSJack F Vogel goto err_out; 541*61ae650dSJack F Vogel } 542*61ae650dSJack F Vogel 543*61ae650dSJack F Vogel /* Set up the admin queue */ 544*61ae650dSJack F Vogel error = i40e_init_adminq(hw); 545*61ae650dSJack F Vogel if (error) { 546*61ae650dSJack F Vogel device_printf(dev, "The driver for the device stopped " 547*61ae650dSJack F Vogel "because the NVM image is newer than expected.\n" 548*61ae650dSJack F Vogel "You must install the most recent version of " 549*61ae650dSJack F Vogel " the network driver.\n"); 550*61ae650dSJack F Vogel goto err_out; 551*61ae650dSJack F Vogel } 552*61ae650dSJack F Vogel device_printf(dev, "%s\n", ixl_fw_version_str(hw)); 553*61ae650dSJack F Vogel 554*61ae650dSJack F Vogel if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR && 555*61ae650dSJack F Vogel hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR) 556*61ae650dSJack F Vogel device_printf(dev, "The driver for the device detected " 557*61ae650dSJack F Vogel "a newer version of the NVM image than expected.\n" 558*61ae650dSJack F Vogel "Please install the most recent version of the network driver.\n"); 559*61ae650dSJack F Vogel else if (hw->aq.api_maj_ver < I40E_FW_API_VERSION_MAJOR || 560*61ae650dSJack F Vogel hw->aq.api_min_ver < (I40E_FW_API_VERSION_MINOR - 1)) 561*61ae650dSJack F Vogel device_printf(dev, "The driver for the device detected " 562*61ae650dSJack F Vogel "an older version of the NVM image than expected.\n" 563*61ae650dSJack F Vogel "Please update the NVM image.\n"); 564*61ae650dSJack F Vogel 565*61ae650dSJack F Vogel /* Clear PXE mode */ 566*61ae650dSJack F Vogel i40e_clear_pxe_mode(hw); 567*61ae650dSJack F Vogel 568*61ae650dSJack F Vogel /* Get capabilities from the device */ 569*61ae650dSJack F Vogel error = ixl_get_hw_capabilities(pf); 570*61ae650dSJack F Vogel if (error) { 571*61ae650dSJack F Vogel device_printf(dev, "HW capabilities failure!\n"); 572*61ae650dSJack F Vogel goto err_get_cap; 573*61ae650dSJack F Vogel } 574*61ae650dSJack F Vogel 575*61ae650dSJack F Vogel /* Set up host memory cache */ 576*61ae650dSJack F Vogel error = i40e_init_lan_hmc(hw, vsi->num_queues, vsi->num_queues, 0, 0); 577*61ae650dSJack F Vogel if (error) { 578*61ae650dSJack F Vogel device_printf(dev, "init_lan_hmc failed: %d\n", error); 579*61ae650dSJack F Vogel goto err_get_cap; 580*61ae650dSJack F Vogel } 581*61ae650dSJack F Vogel 582*61ae650dSJack F Vogel error = i40e_configure_lan_hmc(hw, I40E_HMC_MODEL_DIRECT_ONLY); 583*61ae650dSJack F Vogel if (error) { 584*61ae650dSJack F Vogel device_printf(dev, "configure_lan_hmc failed: %d\n", error); 585*61ae650dSJack F Vogel goto err_mac_hmc; 586*61ae650dSJack F Vogel } 587*61ae650dSJack F Vogel 588*61ae650dSJack F Vogel /* Disable LLDP from the firmware */ 589*61ae650dSJack F Vogel i40e_aq_stop_lldp(hw, TRUE, NULL); 590*61ae650dSJack F Vogel 591*61ae650dSJack F Vogel i40e_get_mac_addr(hw, hw->mac.addr); 592*61ae650dSJack F Vogel error = i40e_validate_mac_addr(hw->mac.addr); 593*61ae650dSJack F Vogel if (error) { 594*61ae650dSJack F Vogel device_printf(dev, "validate_mac_addr failed: %d\n", error); 595*61ae650dSJack F Vogel goto err_mac_hmc; 596*61ae650dSJack F Vogel } 597*61ae650dSJack F Vogel bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN); 598*61ae650dSJack F Vogel i40e_get_port_mac_addr(hw, hw->mac.port_addr); 599*61ae650dSJack F Vogel 600*61ae650dSJack F Vogel if (ixl_setup_stations(pf) != 0) { 601*61ae650dSJack F Vogel device_printf(dev, "setup stations failed!\n"); 602*61ae650dSJack F Vogel error = ENOMEM; 603*61ae650dSJack F Vogel goto err_mac_hmc; 604*61ae650dSJack F Vogel } 605*61ae650dSJack F Vogel 606*61ae650dSJack F Vogel /* Initialize mac filter list for VSI */ 607*61ae650dSJack F Vogel SLIST_INIT(&vsi->ftl); 608*61ae650dSJack F Vogel 609*61ae650dSJack F Vogel /* Set up interrupt routing here */ 610*61ae650dSJack F Vogel if (pf->msix > 1) 611*61ae650dSJack F Vogel error = ixl_assign_vsi_msix(pf); 612*61ae650dSJack F Vogel else 613*61ae650dSJack F Vogel error = ixl_assign_vsi_legacy(pf); 614*61ae650dSJack F Vogel if (error) 615*61ae650dSJack F Vogel goto err_late; 616*61ae650dSJack F Vogel 617*61ae650dSJack F Vogel i40e_msec_delay(75); 618*61ae650dSJack F Vogel error = i40e_aq_set_link_restart_an(hw, TRUE, NULL); 619*61ae650dSJack F Vogel if (error) { 620*61ae650dSJack F Vogel device_printf(dev, "link restart failed, aq_err=%d\n", 621*61ae650dSJack F Vogel pf->hw.aq.asq_last_status); 622*61ae650dSJack F Vogel } 623*61ae650dSJack F Vogel 624*61ae650dSJack F Vogel /* Determine link state */ 625*61ae650dSJack F Vogel vsi->link_up = ixl_config_link(hw); 626*61ae650dSJack F Vogel 627*61ae650dSJack F Vogel /* Report if Unqualified modules are found */ 628*61ae650dSJack F Vogel if ((vsi->link_up == FALSE) && 629*61ae650dSJack F Vogel (pf->hw.phy.link_info.link_info & 630*61ae650dSJack F Vogel I40E_AQ_MEDIA_AVAILABLE) && 631*61ae650dSJack F Vogel (!(pf->hw.phy.link_info.an_info & 632*61ae650dSJack F Vogel I40E_AQ_QUALIFIED_MODULE))) 633*61ae650dSJack F Vogel device_printf(dev, "Link failed because " 634*61ae650dSJack F Vogel "an unqualified module was detected\n"); 635*61ae650dSJack F Vogel 636*61ae650dSJack F Vogel /* Setup OS specific network interface */ 637*61ae650dSJack F Vogel if (ixl_setup_interface(dev, vsi) != 0) 638*61ae650dSJack F Vogel goto err_late; 639*61ae650dSJack F Vogel 640*61ae650dSJack F Vogel /* Get the bus configuration and set the shared code */ 641*61ae650dSJack F Vogel bus = ixl_get_bus_info(hw, dev); 642*61ae650dSJack F Vogel i40e_set_pci_config_data(hw, bus); 643*61ae650dSJack F Vogel 644*61ae650dSJack F Vogel /* Initialize statistics */ 645*61ae650dSJack F Vogel ixl_pf_reset_stats(pf); 646*61ae650dSJack F Vogel ixl_update_stats_counters(pf); 647*61ae650dSJack F Vogel ixl_add_hw_stats(pf); 648*61ae650dSJack F Vogel 649*61ae650dSJack F Vogel /* Register for VLAN events */ 650*61ae650dSJack F Vogel vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, 651*61ae650dSJack F Vogel ixl_register_vlan, vsi, EVENTHANDLER_PRI_FIRST); 652*61ae650dSJack F Vogel vsi->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, 653*61ae650dSJack F Vogel ixl_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST); 654*61ae650dSJack F Vogel 655*61ae650dSJack F Vogel #ifdef DEV_NETMAP 656*61ae650dSJack F Vogel ixl_netmap_attach(pf); 657*61ae650dSJack F Vogel #endif /* DEV_NETMAP */ 658*61ae650dSJack F Vogel 659*61ae650dSJack F Vogel INIT_DEBUGOUT("ixl_attach: end"); 660*61ae650dSJack F Vogel return (0); 661*61ae650dSJack F Vogel 662*61ae650dSJack F Vogel err_late: 663*61ae650dSJack F Vogel ixl_free_vsi(vsi); 664*61ae650dSJack F Vogel err_mac_hmc: 665*61ae650dSJack F Vogel i40e_shutdown_lan_hmc(hw); 666*61ae650dSJack F Vogel err_get_cap: 667*61ae650dSJack F Vogel i40e_shutdown_adminq(hw); 668*61ae650dSJack F Vogel err_out: 669*61ae650dSJack F Vogel if (vsi->ifp != NULL) 670*61ae650dSJack F Vogel if_free(vsi->ifp); 671*61ae650dSJack F Vogel ixl_free_pci_resources(pf); 672*61ae650dSJack F Vogel IXL_PF_LOCK_DESTROY(pf); 673*61ae650dSJack F Vogel return (error); 674*61ae650dSJack F Vogel } 675*61ae650dSJack F Vogel 676*61ae650dSJack F Vogel /********************************************************************* 677*61ae650dSJack F Vogel * Device removal routine 678*61ae650dSJack F Vogel * 679*61ae650dSJack F Vogel * The detach entry point is called when the driver is being removed. 680*61ae650dSJack F Vogel * This routine stops the adapter and deallocates all the resources 681*61ae650dSJack F Vogel * that were allocated for driver operation. 682*61ae650dSJack F Vogel * 683*61ae650dSJack F Vogel * return 0 on success, positive on failure 684*61ae650dSJack F Vogel *********************************************************************/ 685*61ae650dSJack F Vogel 686*61ae650dSJack F Vogel static int 687*61ae650dSJack F Vogel ixl_detach(device_t dev) 688*61ae650dSJack F Vogel { 689*61ae650dSJack F Vogel struct ixl_pf *pf = device_get_softc(dev); 690*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 691*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 692*61ae650dSJack F Vogel struct ixl_queue *que = vsi->queues; 693*61ae650dSJack F Vogel i40e_status status; 694*61ae650dSJack F Vogel 695*61ae650dSJack F Vogel INIT_DEBUGOUT("ixl_detach: begin"); 696*61ae650dSJack F Vogel 697*61ae650dSJack F Vogel /* Make sure VLANS are not using driver */ 698*61ae650dSJack F Vogel if (vsi->ifp->if_vlantrunk != NULL) { 699*61ae650dSJack F Vogel device_printf(dev,"Vlan in use, detach first\n"); 700*61ae650dSJack F Vogel return (EBUSY); 701*61ae650dSJack F Vogel } 702*61ae650dSJack F Vogel 703*61ae650dSJack F Vogel IXL_PF_LOCK(pf); 704*61ae650dSJack F Vogel ixl_stop(pf); 705*61ae650dSJack F Vogel IXL_PF_UNLOCK(pf); 706*61ae650dSJack F Vogel 707*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++, que++) { 708*61ae650dSJack F Vogel if (que->tq) { 709*61ae650dSJack F Vogel taskqueue_drain(que->tq, &que->task); 710*61ae650dSJack F Vogel taskqueue_drain(que->tq, &que->tx_task); 711*61ae650dSJack F Vogel taskqueue_free(que->tq); 712*61ae650dSJack F Vogel } 713*61ae650dSJack F Vogel } 714*61ae650dSJack F Vogel 715*61ae650dSJack F Vogel /* Shutdown LAN HMC */ 716*61ae650dSJack F Vogel status = i40e_shutdown_lan_hmc(hw); 717*61ae650dSJack F Vogel if (status) 718*61ae650dSJack F Vogel device_printf(dev, 719*61ae650dSJack F Vogel "Shutdown LAN HMC failed with code %d\n", status); 720*61ae650dSJack F Vogel 721*61ae650dSJack F Vogel /* Shutdown admin queue */ 722*61ae650dSJack F Vogel status = i40e_shutdown_adminq(hw); 723*61ae650dSJack F Vogel if (status) 724*61ae650dSJack F Vogel device_printf(dev, 725*61ae650dSJack F Vogel "Shutdown Admin queue failed with code %d\n", status); 726*61ae650dSJack F Vogel 727*61ae650dSJack F Vogel /* Unregister VLAN events */ 728*61ae650dSJack F Vogel if (vsi->vlan_attach != NULL) 729*61ae650dSJack F Vogel EVENTHANDLER_DEREGISTER(vlan_config, vsi->vlan_attach); 730*61ae650dSJack F Vogel if (vsi->vlan_detach != NULL) 731*61ae650dSJack F Vogel EVENTHANDLER_DEREGISTER(vlan_unconfig, vsi->vlan_detach); 732*61ae650dSJack F Vogel 733*61ae650dSJack F Vogel ether_ifdetach(vsi->ifp); 734*61ae650dSJack F Vogel callout_drain(&pf->timer); 735*61ae650dSJack F Vogel 736*61ae650dSJack F Vogel #ifdef DEV_NETMAP 737*61ae650dSJack F Vogel netmap_detach(vsi->ifp); 738*61ae650dSJack F Vogel #endif /* DEV_NETMAP */ 739*61ae650dSJack F Vogel 740*61ae650dSJack F Vogel ixl_free_pci_resources(pf); 741*61ae650dSJack F Vogel bus_generic_detach(dev); 742*61ae650dSJack F Vogel if_free(vsi->ifp); 743*61ae650dSJack F Vogel ixl_free_vsi(vsi); 744*61ae650dSJack F Vogel IXL_PF_LOCK_DESTROY(pf); 745*61ae650dSJack F Vogel return (0); 746*61ae650dSJack F Vogel } 747*61ae650dSJack F Vogel 748*61ae650dSJack F Vogel /********************************************************************* 749*61ae650dSJack F Vogel * 750*61ae650dSJack F Vogel * Shutdown entry point 751*61ae650dSJack F Vogel * 752*61ae650dSJack F Vogel **********************************************************************/ 753*61ae650dSJack F Vogel 754*61ae650dSJack F Vogel static int 755*61ae650dSJack F Vogel ixl_shutdown(device_t dev) 756*61ae650dSJack F Vogel { 757*61ae650dSJack F Vogel struct ixl_pf *pf = device_get_softc(dev); 758*61ae650dSJack F Vogel IXL_PF_LOCK(pf); 759*61ae650dSJack F Vogel ixl_stop(pf); 760*61ae650dSJack F Vogel IXL_PF_UNLOCK(pf); 761*61ae650dSJack F Vogel return (0); 762*61ae650dSJack F Vogel } 763*61ae650dSJack F Vogel 764*61ae650dSJack F Vogel 765*61ae650dSJack F Vogel /********************************************************************* 766*61ae650dSJack F Vogel * 767*61ae650dSJack F Vogel * Get the hardware capabilities 768*61ae650dSJack F Vogel * 769*61ae650dSJack F Vogel **********************************************************************/ 770*61ae650dSJack F Vogel 771*61ae650dSJack F Vogel static int 772*61ae650dSJack F Vogel ixl_get_hw_capabilities(struct ixl_pf *pf) 773*61ae650dSJack F Vogel { 774*61ae650dSJack F Vogel struct i40e_aqc_list_capabilities_element_resp *buf; 775*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 776*61ae650dSJack F Vogel device_t dev = pf->dev; 777*61ae650dSJack F Vogel int error, len; 778*61ae650dSJack F Vogel u16 needed; 779*61ae650dSJack F Vogel bool again = TRUE; 780*61ae650dSJack F Vogel 781*61ae650dSJack F Vogel len = 40 * sizeof(struct i40e_aqc_list_capabilities_element_resp); 782*61ae650dSJack F Vogel retry: 783*61ae650dSJack F Vogel if (!(buf = (struct i40e_aqc_list_capabilities_element_resp *) 784*61ae650dSJack F Vogel malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO))) { 785*61ae650dSJack F Vogel device_printf(dev, "Unable to allocate cap memory\n"); 786*61ae650dSJack F Vogel return (ENOMEM); 787*61ae650dSJack F Vogel } 788*61ae650dSJack F Vogel 789*61ae650dSJack F Vogel /* This populates the hw struct */ 790*61ae650dSJack F Vogel error = i40e_aq_discover_capabilities(hw, buf, len, 791*61ae650dSJack F Vogel &needed, i40e_aqc_opc_list_func_capabilities, NULL); 792*61ae650dSJack F Vogel free(buf, M_DEVBUF); 793*61ae650dSJack F Vogel if ((pf->hw.aq.asq_last_status == I40E_AQ_RC_ENOMEM) && 794*61ae650dSJack F Vogel (again == TRUE)) { 795*61ae650dSJack F Vogel /* retry once with a larger buffer */ 796*61ae650dSJack F Vogel again = FALSE; 797*61ae650dSJack F Vogel len = needed; 798*61ae650dSJack F Vogel goto retry; 799*61ae650dSJack F Vogel } else if (pf->hw.aq.asq_last_status != I40E_AQ_RC_OK) { 800*61ae650dSJack F Vogel device_printf(dev, "capability discovery failed: %d\n", 801*61ae650dSJack F Vogel pf->hw.aq.asq_last_status); 802*61ae650dSJack F Vogel return (ENODEV); 803*61ae650dSJack F Vogel } 804*61ae650dSJack F Vogel 805*61ae650dSJack F Vogel /* Capture this PF's starting queue pair */ 806*61ae650dSJack F Vogel pf->qbase = hw->func_caps.base_queue; 807*61ae650dSJack F Vogel 808*61ae650dSJack F Vogel #ifdef IXL_DEBUG 809*61ae650dSJack F Vogel device_printf(dev,"pf_id=%d, num_vfs=%d, msix_pf=%d, " 810*61ae650dSJack F Vogel "msix_vf=%d, fd_g=%d, fd_b=%d, tx_qp=%d rx_qp=%d qbase=%d\n", 811*61ae650dSJack F Vogel hw->pf_id, hw->func_caps.num_vfs, 812*61ae650dSJack F Vogel hw->func_caps.num_msix_vectors, 813*61ae650dSJack F Vogel hw->func_caps.num_msix_vectors_vf, 814*61ae650dSJack F Vogel hw->func_caps.fd_filters_guaranteed, 815*61ae650dSJack F Vogel hw->func_caps.fd_filters_best_effort, 816*61ae650dSJack F Vogel hw->func_caps.num_tx_qp, 817*61ae650dSJack F Vogel hw->func_caps.num_rx_qp, 818*61ae650dSJack F Vogel hw->func_caps.base_queue); 819*61ae650dSJack F Vogel #endif 820*61ae650dSJack F Vogel return (error); 821*61ae650dSJack F Vogel } 822*61ae650dSJack F Vogel 823*61ae650dSJack F Vogel static void 824*61ae650dSJack F Vogel ixl_cap_txcsum_tso(struct ixl_vsi *vsi, struct ifnet *ifp, int mask) 825*61ae650dSJack F Vogel { 826*61ae650dSJack F Vogel device_t dev = vsi->dev; 827*61ae650dSJack F Vogel 828*61ae650dSJack F Vogel /* Enable/disable TXCSUM/TSO4 */ 829*61ae650dSJack F Vogel if (!(ifp->if_capenable & IFCAP_TXCSUM) 830*61ae650dSJack F Vogel && !(ifp->if_capenable & IFCAP_TSO4)) { 831*61ae650dSJack F Vogel if (mask & IFCAP_TXCSUM) { 832*61ae650dSJack F Vogel ifp->if_capenable |= IFCAP_TXCSUM; 833*61ae650dSJack F Vogel /* enable TXCSUM, restore TSO if previously enabled */ 834*61ae650dSJack F Vogel if (vsi->flags & IXL_FLAGS_KEEP_TSO4) { 835*61ae650dSJack F Vogel vsi->flags &= ~IXL_FLAGS_KEEP_TSO4; 836*61ae650dSJack F Vogel ifp->if_capenable |= IFCAP_TSO4; 837*61ae650dSJack F Vogel } 838*61ae650dSJack F Vogel } 839*61ae650dSJack F Vogel else if (mask & IFCAP_TSO4) { 840*61ae650dSJack F Vogel ifp->if_capenable |= (IFCAP_TXCSUM | IFCAP_TSO4); 841*61ae650dSJack F Vogel vsi->flags &= ~IXL_FLAGS_KEEP_TSO4; 842*61ae650dSJack F Vogel device_printf(dev, 843*61ae650dSJack F Vogel "TSO4 requires txcsum, enabling both...\n"); 844*61ae650dSJack F Vogel } 845*61ae650dSJack F Vogel } else if((ifp->if_capenable & IFCAP_TXCSUM) 846*61ae650dSJack F Vogel && !(ifp->if_capenable & IFCAP_TSO4)) { 847*61ae650dSJack F Vogel if (mask & IFCAP_TXCSUM) 848*61ae650dSJack F Vogel ifp->if_capenable &= ~IFCAP_TXCSUM; 849*61ae650dSJack F Vogel else if (mask & IFCAP_TSO4) 850*61ae650dSJack F Vogel ifp->if_capenable |= IFCAP_TSO4; 851*61ae650dSJack F Vogel } else if((ifp->if_capenable & IFCAP_TXCSUM) 852*61ae650dSJack F Vogel && (ifp->if_capenable & IFCAP_TSO4)) { 853*61ae650dSJack F Vogel if (mask & IFCAP_TXCSUM) { 854*61ae650dSJack F Vogel vsi->flags |= IXL_FLAGS_KEEP_TSO4; 855*61ae650dSJack F Vogel ifp->if_capenable &= ~(IFCAP_TXCSUM | IFCAP_TSO4); 856*61ae650dSJack F Vogel device_printf(dev, 857*61ae650dSJack F Vogel "TSO4 requires txcsum, disabling both...\n"); 858*61ae650dSJack F Vogel } else if (mask & IFCAP_TSO4) 859*61ae650dSJack F Vogel ifp->if_capenable &= ~IFCAP_TSO4; 860*61ae650dSJack F Vogel } 861*61ae650dSJack F Vogel 862*61ae650dSJack F Vogel /* Enable/disable TXCSUM_IPV6/TSO6 */ 863*61ae650dSJack F Vogel if (!(ifp->if_capenable & IFCAP_TXCSUM_IPV6) 864*61ae650dSJack F Vogel && !(ifp->if_capenable & IFCAP_TSO6)) { 865*61ae650dSJack F Vogel if (mask & IFCAP_TXCSUM_IPV6) { 866*61ae650dSJack F Vogel ifp->if_capenable |= IFCAP_TXCSUM_IPV6; 867*61ae650dSJack F Vogel if (vsi->flags & IXL_FLAGS_KEEP_TSO6) { 868*61ae650dSJack F Vogel vsi->flags &= ~IXL_FLAGS_KEEP_TSO6; 869*61ae650dSJack F Vogel ifp->if_capenable |= IFCAP_TSO6; 870*61ae650dSJack F Vogel } 871*61ae650dSJack F Vogel } else if (mask & IFCAP_TSO6) { 872*61ae650dSJack F Vogel ifp->if_capenable |= (IFCAP_TXCSUM_IPV6 | IFCAP_TSO6); 873*61ae650dSJack F Vogel vsi->flags &= ~IXL_FLAGS_KEEP_TSO6; 874*61ae650dSJack F Vogel device_printf(dev, 875*61ae650dSJack F Vogel "TSO6 requires txcsum6, enabling both...\n"); 876*61ae650dSJack F Vogel } 877*61ae650dSJack F Vogel } else if((ifp->if_capenable & IFCAP_TXCSUM_IPV6) 878*61ae650dSJack F Vogel && !(ifp->if_capenable & IFCAP_TSO6)) { 879*61ae650dSJack F Vogel if (mask & IFCAP_TXCSUM_IPV6) 880*61ae650dSJack F Vogel ifp->if_capenable &= ~IFCAP_TXCSUM_IPV6; 881*61ae650dSJack F Vogel else if (mask & IFCAP_TSO6) 882*61ae650dSJack F Vogel ifp->if_capenable |= IFCAP_TSO6; 883*61ae650dSJack F Vogel } else if ((ifp->if_capenable & IFCAP_TXCSUM_IPV6) 884*61ae650dSJack F Vogel && (ifp->if_capenable & IFCAP_TSO6)) { 885*61ae650dSJack F Vogel if (mask & IFCAP_TXCSUM_IPV6) { 886*61ae650dSJack F Vogel vsi->flags |= IXL_FLAGS_KEEP_TSO6; 887*61ae650dSJack F Vogel ifp->if_capenable &= ~(IFCAP_TXCSUM_IPV6 | IFCAP_TSO6); 888*61ae650dSJack F Vogel device_printf(dev, 889*61ae650dSJack F Vogel "TSO6 requires txcsum6, disabling both...\n"); 890*61ae650dSJack F Vogel } else if (mask & IFCAP_TSO6) 891*61ae650dSJack F Vogel ifp->if_capenable &= ~IFCAP_TSO6; 892*61ae650dSJack F Vogel } 893*61ae650dSJack F Vogel } 894*61ae650dSJack F Vogel 895*61ae650dSJack F Vogel /********************************************************************* 896*61ae650dSJack F Vogel * Ioctl entry point 897*61ae650dSJack F Vogel * 898*61ae650dSJack F Vogel * ixl_ioctl is called when the user wants to configure the 899*61ae650dSJack F Vogel * interface. 900*61ae650dSJack F Vogel * 901*61ae650dSJack F Vogel * return 0 on success, positive on failure 902*61ae650dSJack F Vogel **********************************************************************/ 903*61ae650dSJack F Vogel 904*61ae650dSJack F Vogel static int 905*61ae650dSJack F Vogel ixl_ioctl(struct ifnet * ifp, u_long command, caddr_t data) 906*61ae650dSJack F Vogel { 907*61ae650dSJack F Vogel struct ixl_vsi *vsi = ifp->if_softc; 908*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)vsi->back; 909*61ae650dSJack F Vogel struct ifreq *ifr = (struct ifreq *) data; 910*61ae650dSJack F Vogel #if defined(INET) || defined(INET6) 911*61ae650dSJack F Vogel struct ifaddr *ifa = (struct ifaddr *)data; 912*61ae650dSJack F Vogel bool avoid_reset = FALSE; 913*61ae650dSJack F Vogel #endif 914*61ae650dSJack F Vogel int error = 0; 915*61ae650dSJack F Vogel 916*61ae650dSJack F Vogel switch (command) { 917*61ae650dSJack F Vogel 918*61ae650dSJack F Vogel case SIOCSIFADDR: 919*61ae650dSJack F Vogel #ifdef INET 920*61ae650dSJack F Vogel if (ifa->ifa_addr->sa_family == AF_INET) 921*61ae650dSJack F Vogel avoid_reset = TRUE; 922*61ae650dSJack F Vogel #endif 923*61ae650dSJack F Vogel #ifdef INET6 924*61ae650dSJack F Vogel if (ifa->ifa_addr->sa_family == AF_INET6) 925*61ae650dSJack F Vogel avoid_reset = TRUE; 926*61ae650dSJack F Vogel #endif 927*61ae650dSJack F Vogel #if defined(INET) || defined(INET6) 928*61ae650dSJack F Vogel /* 929*61ae650dSJack F Vogel ** Calling init results in link renegotiation, 930*61ae650dSJack F Vogel ** so we avoid doing it when possible. 931*61ae650dSJack F Vogel */ 932*61ae650dSJack F Vogel if (avoid_reset) { 933*61ae650dSJack F Vogel ifp->if_flags |= IFF_UP; 934*61ae650dSJack F Vogel if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 935*61ae650dSJack F Vogel ixl_init(pf); 936*61ae650dSJack F Vogel if (!(ifp->if_flags & IFF_NOARP)) 937*61ae650dSJack F Vogel arp_ifinit(ifp, ifa); 938*61ae650dSJack F Vogel } else 939*61ae650dSJack F Vogel error = ether_ioctl(ifp, command, data); 940*61ae650dSJack F Vogel break; 941*61ae650dSJack F Vogel #endif 942*61ae650dSJack F Vogel case SIOCSIFMTU: 943*61ae650dSJack F Vogel IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)"); 944*61ae650dSJack F Vogel if (ifr->ifr_mtu > IXL_MAX_FRAME - 945*61ae650dSJack F Vogel ETHER_HDR_LEN - ETHER_CRC_LEN - ETHER_VLAN_ENCAP_LEN) { 946*61ae650dSJack F Vogel error = EINVAL; 947*61ae650dSJack F Vogel } else { 948*61ae650dSJack F Vogel IXL_PF_LOCK(pf); 949*61ae650dSJack F Vogel ifp->if_mtu = ifr->ifr_mtu; 950*61ae650dSJack F Vogel vsi->max_frame_size = 951*61ae650dSJack F Vogel ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN 952*61ae650dSJack F Vogel + ETHER_VLAN_ENCAP_LEN; 953*61ae650dSJack F Vogel ixl_init_locked(pf); 954*61ae650dSJack F Vogel IXL_PF_UNLOCK(pf); 955*61ae650dSJack F Vogel } 956*61ae650dSJack F Vogel break; 957*61ae650dSJack F Vogel case SIOCSIFFLAGS: 958*61ae650dSJack F Vogel IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)"); 959*61ae650dSJack F Vogel IXL_PF_LOCK(pf); 960*61ae650dSJack F Vogel if (ifp->if_flags & IFF_UP) { 961*61ae650dSJack F Vogel if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) { 962*61ae650dSJack F Vogel if ((ifp->if_flags ^ pf->if_flags) & 963*61ae650dSJack F Vogel (IFF_PROMISC | IFF_ALLMULTI)) { 964*61ae650dSJack F Vogel ixl_set_promisc(vsi); 965*61ae650dSJack F Vogel } 966*61ae650dSJack F Vogel } else 967*61ae650dSJack F Vogel ixl_init_locked(pf); 968*61ae650dSJack F Vogel } else 969*61ae650dSJack F Vogel if (ifp->if_drv_flags & IFF_DRV_RUNNING) 970*61ae650dSJack F Vogel ixl_stop(pf); 971*61ae650dSJack F Vogel pf->if_flags = ifp->if_flags; 972*61ae650dSJack F Vogel IXL_PF_UNLOCK(pf); 973*61ae650dSJack F Vogel break; 974*61ae650dSJack F Vogel case SIOCADDMULTI: 975*61ae650dSJack F Vogel IOCTL_DEBUGOUT("ioctl: SIOCADDMULTI"); 976*61ae650dSJack F Vogel if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 977*61ae650dSJack F Vogel IXL_PF_LOCK(pf); 978*61ae650dSJack F Vogel ixl_disable_intr(vsi); 979*61ae650dSJack F Vogel ixl_add_multi(vsi); 980*61ae650dSJack F Vogel ixl_enable_intr(vsi); 981*61ae650dSJack F Vogel IXL_PF_UNLOCK(pf); 982*61ae650dSJack F Vogel } 983*61ae650dSJack F Vogel break; 984*61ae650dSJack F Vogel case SIOCDELMULTI: 985*61ae650dSJack F Vogel IOCTL_DEBUGOUT("ioctl: SIOCDELMULTI"); 986*61ae650dSJack F Vogel if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 987*61ae650dSJack F Vogel IXL_PF_LOCK(pf); 988*61ae650dSJack F Vogel ixl_disable_intr(vsi); 989*61ae650dSJack F Vogel ixl_del_multi(vsi); 990*61ae650dSJack F Vogel ixl_enable_intr(vsi); 991*61ae650dSJack F Vogel IXL_PF_UNLOCK(pf); 992*61ae650dSJack F Vogel } 993*61ae650dSJack F Vogel break; 994*61ae650dSJack F Vogel case SIOCSIFMEDIA: 995*61ae650dSJack F Vogel case SIOCGIFMEDIA: 996*61ae650dSJack F Vogel IOCTL_DEBUGOUT("ioctl: SIOCxIFMEDIA (Get/Set Interface Media)"); 997*61ae650dSJack F Vogel error = ifmedia_ioctl(ifp, ifr, &vsi->media, command); 998*61ae650dSJack F Vogel break; 999*61ae650dSJack F Vogel case SIOCSIFCAP: 1000*61ae650dSJack F Vogel { 1001*61ae650dSJack F Vogel int mask = ifr->ifr_reqcap ^ ifp->if_capenable; 1002*61ae650dSJack F Vogel IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)"); 1003*61ae650dSJack F Vogel 1004*61ae650dSJack F Vogel ixl_cap_txcsum_tso(vsi, ifp, mask); 1005*61ae650dSJack F Vogel 1006*61ae650dSJack F Vogel if (mask & IFCAP_RXCSUM) 1007*61ae650dSJack F Vogel ifp->if_capenable ^= IFCAP_RXCSUM; 1008*61ae650dSJack F Vogel if (mask & IFCAP_RXCSUM_IPV6) 1009*61ae650dSJack F Vogel ifp->if_capenable ^= IFCAP_RXCSUM_IPV6; 1010*61ae650dSJack F Vogel if (mask & IFCAP_LRO) 1011*61ae650dSJack F Vogel ifp->if_capenable ^= IFCAP_LRO; 1012*61ae650dSJack F Vogel if (mask & IFCAP_VLAN_HWTAGGING) 1013*61ae650dSJack F Vogel ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 1014*61ae650dSJack F Vogel if (mask & IFCAP_VLAN_HWFILTER) 1015*61ae650dSJack F Vogel ifp->if_capenable ^= IFCAP_VLAN_HWFILTER; 1016*61ae650dSJack F Vogel if (mask & IFCAP_VLAN_HWTSO) 1017*61ae650dSJack F Vogel ifp->if_capenable ^= IFCAP_VLAN_HWTSO; 1018*61ae650dSJack F Vogel if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1019*61ae650dSJack F Vogel IXL_PF_LOCK(pf); 1020*61ae650dSJack F Vogel ixl_init_locked(pf); 1021*61ae650dSJack F Vogel IXL_PF_UNLOCK(pf); 1022*61ae650dSJack F Vogel } 1023*61ae650dSJack F Vogel VLAN_CAPABILITIES(ifp); 1024*61ae650dSJack F Vogel 1025*61ae650dSJack F Vogel break; 1026*61ae650dSJack F Vogel } 1027*61ae650dSJack F Vogel 1028*61ae650dSJack F Vogel default: 1029*61ae650dSJack F Vogel IOCTL_DEBUGOUT("ioctl: UNKNOWN (0x%X)\n", (int)command); 1030*61ae650dSJack F Vogel error = ether_ioctl(ifp, command, data); 1031*61ae650dSJack F Vogel break; 1032*61ae650dSJack F Vogel } 1033*61ae650dSJack F Vogel 1034*61ae650dSJack F Vogel return (error); 1035*61ae650dSJack F Vogel } 1036*61ae650dSJack F Vogel 1037*61ae650dSJack F Vogel 1038*61ae650dSJack F Vogel /********************************************************************* 1039*61ae650dSJack F Vogel * Init entry point 1040*61ae650dSJack F Vogel * 1041*61ae650dSJack F Vogel * This routine is used in two ways. It is used by the stack as 1042*61ae650dSJack F Vogel * init entry point in network interface structure. It is also used 1043*61ae650dSJack F Vogel * by the driver as a hw/sw initialization routine to get to a 1044*61ae650dSJack F Vogel * consistent state. 1045*61ae650dSJack F Vogel * 1046*61ae650dSJack F Vogel * return 0 on success, positive on failure 1047*61ae650dSJack F Vogel **********************************************************************/ 1048*61ae650dSJack F Vogel 1049*61ae650dSJack F Vogel static void 1050*61ae650dSJack F Vogel ixl_init_locked(struct ixl_pf *pf) 1051*61ae650dSJack F Vogel { 1052*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 1053*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 1054*61ae650dSJack F Vogel struct ifnet *ifp = vsi->ifp; 1055*61ae650dSJack F Vogel device_t dev = pf->dev; 1056*61ae650dSJack F Vogel struct i40e_filter_control_settings filter; 1057*61ae650dSJack F Vogel u8 tmpaddr[ETHER_ADDR_LEN]; 1058*61ae650dSJack F Vogel int ret; 1059*61ae650dSJack F Vogel 1060*61ae650dSJack F Vogel mtx_assert(&pf->pf_mtx, MA_OWNED); 1061*61ae650dSJack F Vogel INIT_DEBUGOUT("ixl_init: begin"); 1062*61ae650dSJack F Vogel ixl_stop(pf); 1063*61ae650dSJack F Vogel 1064*61ae650dSJack F Vogel /* Get the latest mac address... User might use a LAA */ 1065*61ae650dSJack F Vogel bcopy(IF_LLADDR(vsi->ifp), tmpaddr, 1066*61ae650dSJack F Vogel I40E_ETH_LENGTH_OF_ADDRESS); 1067*61ae650dSJack F Vogel if (!cmp_etheraddr(hw->mac.addr, tmpaddr) && 1068*61ae650dSJack F Vogel i40e_validate_mac_addr(tmpaddr)) { 1069*61ae650dSJack F Vogel bcopy(tmpaddr, hw->mac.addr, 1070*61ae650dSJack F Vogel I40E_ETH_LENGTH_OF_ADDRESS); 1071*61ae650dSJack F Vogel ret = i40e_aq_mac_address_write(hw, 1072*61ae650dSJack F Vogel I40E_AQC_WRITE_TYPE_LAA_ONLY, 1073*61ae650dSJack F Vogel hw->mac.addr, NULL); 1074*61ae650dSJack F Vogel if (ret) { 1075*61ae650dSJack F Vogel device_printf(dev, "LLA address" 1076*61ae650dSJack F Vogel "change failed!!\n"); 1077*61ae650dSJack F Vogel return; 1078*61ae650dSJack F Vogel } 1079*61ae650dSJack F Vogel } 1080*61ae650dSJack F Vogel 1081*61ae650dSJack F Vogel /* Set the various hardware offload abilities */ 1082*61ae650dSJack F Vogel ifp->if_hwassist = 0; 1083*61ae650dSJack F Vogel if (ifp->if_capenable & IFCAP_TSO) 1084*61ae650dSJack F Vogel ifp->if_hwassist |= CSUM_TSO; 1085*61ae650dSJack F Vogel if (ifp->if_capenable & IFCAP_TXCSUM) 1086*61ae650dSJack F Vogel ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); 1087*61ae650dSJack F Vogel if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) 1088*61ae650dSJack F Vogel ifp->if_hwassist |= (CSUM_TCP_IPV6 | CSUM_UDP_IPV6); 1089*61ae650dSJack F Vogel 1090*61ae650dSJack F Vogel /* Set up the device filtering */ 1091*61ae650dSJack F Vogel bzero(&filter, sizeof(filter)); 1092*61ae650dSJack F Vogel filter.enable_ethtype = TRUE; 1093*61ae650dSJack F Vogel filter.enable_macvlan = TRUE; 1094*61ae650dSJack F Vogel #ifdef IXL_FDIR 1095*61ae650dSJack F Vogel filter.enable_fdir = TRUE; 1096*61ae650dSJack F Vogel #endif 1097*61ae650dSJack F Vogel if (i40e_set_filter_control(hw, &filter)) 1098*61ae650dSJack F Vogel device_printf(dev, "set_filter_control() failed\n"); 1099*61ae650dSJack F Vogel 1100*61ae650dSJack F Vogel /* Set up RSS */ 1101*61ae650dSJack F Vogel ixl_config_rss(vsi); 1102*61ae650dSJack F Vogel 1103*61ae650dSJack F Vogel /* Setup the VSI */ 1104*61ae650dSJack F Vogel ixl_setup_vsi(vsi); 1105*61ae650dSJack F Vogel 1106*61ae650dSJack F Vogel /* 1107*61ae650dSJack F Vogel ** Prepare the rings, hmc contexts, etc... 1108*61ae650dSJack F Vogel */ 1109*61ae650dSJack F Vogel if (ixl_initialize_vsi(vsi)) { 1110*61ae650dSJack F Vogel device_printf(dev, "initialize vsi failed!!\n"); 1111*61ae650dSJack F Vogel return; 1112*61ae650dSJack F Vogel } 1113*61ae650dSJack F Vogel 1114*61ae650dSJack F Vogel /* Add protocol filters to list */ 1115*61ae650dSJack F Vogel ixl_init_filters(vsi); 1116*61ae650dSJack F Vogel 1117*61ae650dSJack F Vogel /* Setup vlan's if needed */ 1118*61ae650dSJack F Vogel ixl_setup_vlan_filters(vsi); 1119*61ae650dSJack F Vogel 1120*61ae650dSJack F Vogel /* Start the local timer */ 1121*61ae650dSJack F Vogel callout_reset(&pf->timer, hz, ixl_local_timer, pf); 1122*61ae650dSJack F Vogel 1123*61ae650dSJack F Vogel /* Set up MSI/X routing and the ITR settings */ 1124*61ae650dSJack F Vogel if (ixl_enable_msix) { 1125*61ae650dSJack F Vogel ixl_configure_msix(pf); 1126*61ae650dSJack F Vogel ixl_configure_itr(pf); 1127*61ae650dSJack F Vogel } else 1128*61ae650dSJack F Vogel ixl_configure_legacy(pf); 1129*61ae650dSJack F Vogel 1130*61ae650dSJack F Vogel ixl_enable_rings(vsi); 1131*61ae650dSJack F Vogel 1132*61ae650dSJack F Vogel i40e_aq_set_default_vsi(hw, vsi->seid, NULL); 1133*61ae650dSJack F Vogel 1134*61ae650dSJack F Vogel /* Set MTU in hardware*/ 1135*61ae650dSJack F Vogel int aq_error = i40e_aq_set_mac_config(hw, vsi->max_frame_size, 1136*61ae650dSJack F Vogel TRUE, 0, NULL); 1137*61ae650dSJack F Vogel if (aq_error) 1138*61ae650dSJack F Vogel device_printf(vsi->dev, 1139*61ae650dSJack F Vogel "aq_set_mac_config in init error, code %d\n", 1140*61ae650dSJack F Vogel aq_error); 1141*61ae650dSJack F Vogel 1142*61ae650dSJack F Vogel /* And now turn on interrupts */ 1143*61ae650dSJack F Vogel ixl_enable_intr(vsi); 1144*61ae650dSJack F Vogel 1145*61ae650dSJack F Vogel /* Now inform the stack we're ready */ 1146*61ae650dSJack F Vogel ifp->if_drv_flags |= IFF_DRV_RUNNING; 1147*61ae650dSJack F Vogel ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1148*61ae650dSJack F Vogel 1149*61ae650dSJack F Vogel return; 1150*61ae650dSJack F Vogel } 1151*61ae650dSJack F Vogel 1152*61ae650dSJack F Vogel static void 1153*61ae650dSJack F Vogel ixl_init(void *arg) 1154*61ae650dSJack F Vogel { 1155*61ae650dSJack F Vogel struct ixl_pf *pf = arg; 1156*61ae650dSJack F Vogel 1157*61ae650dSJack F Vogel IXL_PF_LOCK(pf); 1158*61ae650dSJack F Vogel ixl_init_locked(pf); 1159*61ae650dSJack F Vogel IXL_PF_UNLOCK(pf); 1160*61ae650dSJack F Vogel return; 1161*61ae650dSJack F Vogel } 1162*61ae650dSJack F Vogel 1163*61ae650dSJack F Vogel /* 1164*61ae650dSJack F Vogel ** 1165*61ae650dSJack F Vogel ** MSIX Interrupt Handlers and Tasklets 1166*61ae650dSJack F Vogel ** 1167*61ae650dSJack F Vogel */ 1168*61ae650dSJack F Vogel static void 1169*61ae650dSJack F Vogel ixl_handle_que(void *context, int pending) 1170*61ae650dSJack F Vogel { 1171*61ae650dSJack F Vogel struct ixl_queue *que = context; 1172*61ae650dSJack F Vogel struct ixl_vsi *vsi = que->vsi; 1173*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 1174*61ae650dSJack F Vogel struct tx_ring *txr = &que->txr; 1175*61ae650dSJack F Vogel struct ifnet *ifp = vsi->ifp; 1176*61ae650dSJack F Vogel bool more; 1177*61ae650dSJack F Vogel 1178*61ae650dSJack F Vogel if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1179*61ae650dSJack F Vogel more = ixl_rxeof(que, IXL_RX_LIMIT); 1180*61ae650dSJack F Vogel IXL_TX_LOCK(txr); 1181*61ae650dSJack F Vogel ixl_txeof(que); 1182*61ae650dSJack F Vogel if (!drbr_empty(ifp, txr->br)) 1183*61ae650dSJack F Vogel ixl_mq_start_locked(ifp, txr); 1184*61ae650dSJack F Vogel IXL_TX_UNLOCK(txr); 1185*61ae650dSJack F Vogel if (more) { 1186*61ae650dSJack F Vogel taskqueue_enqueue(que->tq, &que->task); 1187*61ae650dSJack F Vogel return; 1188*61ae650dSJack F Vogel } 1189*61ae650dSJack F Vogel } 1190*61ae650dSJack F Vogel 1191*61ae650dSJack F Vogel /* Reenable this interrupt - hmmm */ 1192*61ae650dSJack F Vogel ixl_enable_queue(hw, que->me); 1193*61ae650dSJack F Vogel return; 1194*61ae650dSJack F Vogel } 1195*61ae650dSJack F Vogel 1196*61ae650dSJack F Vogel 1197*61ae650dSJack F Vogel /********************************************************************* 1198*61ae650dSJack F Vogel * 1199*61ae650dSJack F Vogel * Legacy Interrupt Service routine 1200*61ae650dSJack F Vogel * 1201*61ae650dSJack F Vogel **********************************************************************/ 1202*61ae650dSJack F Vogel void 1203*61ae650dSJack F Vogel ixl_intr(void *arg) 1204*61ae650dSJack F Vogel { 1205*61ae650dSJack F Vogel struct ixl_pf *pf = arg; 1206*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 1207*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 1208*61ae650dSJack F Vogel struct ixl_queue *que = vsi->queues; 1209*61ae650dSJack F Vogel struct ifnet *ifp = vsi->ifp; 1210*61ae650dSJack F Vogel struct tx_ring *txr = &que->txr; 1211*61ae650dSJack F Vogel u32 reg, icr0, mask; 1212*61ae650dSJack F Vogel bool more_tx, more_rx; 1213*61ae650dSJack F Vogel 1214*61ae650dSJack F Vogel ++que->irqs; 1215*61ae650dSJack F Vogel 1216*61ae650dSJack F Vogel /* Protect against spurious interrupts */ 1217*61ae650dSJack F Vogel if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1218*61ae650dSJack F Vogel return; 1219*61ae650dSJack F Vogel 1220*61ae650dSJack F Vogel icr0 = rd32(hw, I40E_PFINT_ICR0); 1221*61ae650dSJack F Vogel 1222*61ae650dSJack F Vogel reg = rd32(hw, I40E_PFINT_DYN_CTL0); 1223*61ae650dSJack F Vogel reg = reg | I40E_PFINT_DYN_CTL0_CLEARPBA_MASK; 1224*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_DYN_CTL0, reg); 1225*61ae650dSJack F Vogel 1226*61ae650dSJack F Vogel mask = rd32(hw, I40E_PFINT_ICR0_ENA); 1227*61ae650dSJack F Vogel 1228*61ae650dSJack F Vogel if (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK) { 1229*61ae650dSJack F Vogel taskqueue_enqueue(pf->tq, &pf->adminq); 1230*61ae650dSJack F Vogel return; 1231*61ae650dSJack F Vogel } 1232*61ae650dSJack F Vogel 1233*61ae650dSJack F Vogel more_rx = ixl_rxeof(que, IXL_RX_LIMIT); 1234*61ae650dSJack F Vogel 1235*61ae650dSJack F Vogel IXL_TX_LOCK(txr); 1236*61ae650dSJack F Vogel more_tx = ixl_txeof(que); 1237*61ae650dSJack F Vogel if (!drbr_empty(vsi->ifp, txr->br)) 1238*61ae650dSJack F Vogel more_tx = 1; 1239*61ae650dSJack F Vogel IXL_TX_UNLOCK(txr); 1240*61ae650dSJack F Vogel 1241*61ae650dSJack F Vogel /* re-enable other interrupt causes */ 1242*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ICR0_ENA, mask); 1243*61ae650dSJack F Vogel 1244*61ae650dSJack F Vogel /* And now the queues */ 1245*61ae650dSJack F Vogel reg = rd32(hw, I40E_QINT_RQCTL(0)); 1246*61ae650dSJack F Vogel reg |= I40E_QINT_RQCTL_CAUSE_ENA_MASK; 1247*61ae650dSJack F Vogel wr32(hw, I40E_QINT_RQCTL(0), reg); 1248*61ae650dSJack F Vogel 1249*61ae650dSJack F Vogel reg = rd32(hw, I40E_QINT_TQCTL(0)); 1250*61ae650dSJack F Vogel reg |= I40E_QINT_TQCTL_CAUSE_ENA_MASK; 1251*61ae650dSJack F Vogel reg &= ~I40E_PFINT_ICR0_INTEVENT_MASK; 1252*61ae650dSJack F Vogel wr32(hw, I40E_QINT_TQCTL(0), reg); 1253*61ae650dSJack F Vogel 1254*61ae650dSJack F Vogel ixl_enable_legacy(hw); 1255*61ae650dSJack F Vogel 1256*61ae650dSJack F Vogel return; 1257*61ae650dSJack F Vogel } 1258*61ae650dSJack F Vogel 1259*61ae650dSJack F Vogel 1260*61ae650dSJack F Vogel /********************************************************************* 1261*61ae650dSJack F Vogel * 1262*61ae650dSJack F Vogel * MSIX VSI Interrupt Service routine 1263*61ae650dSJack F Vogel * 1264*61ae650dSJack F Vogel **********************************************************************/ 1265*61ae650dSJack F Vogel void 1266*61ae650dSJack F Vogel ixl_msix_que(void *arg) 1267*61ae650dSJack F Vogel { 1268*61ae650dSJack F Vogel struct ixl_queue *que = arg; 1269*61ae650dSJack F Vogel struct ixl_vsi *vsi = que->vsi; 1270*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 1271*61ae650dSJack F Vogel struct tx_ring *txr = &que->txr; 1272*61ae650dSJack F Vogel bool more_tx, more_rx; 1273*61ae650dSJack F Vogel 1274*61ae650dSJack F Vogel /* Protect against spurious interrupts */ 1275*61ae650dSJack F Vogel if (!(vsi->ifp->if_drv_flags & IFF_DRV_RUNNING)) 1276*61ae650dSJack F Vogel return; 1277*61ae650dSJack F Vogel 1278*61ae650dSJack F Vogel ++que->irqs; 1279*61ae650dSJack F Vogel 1280*61ae650dSJack F Vogel more_rx = ixl_rxeof(que, IXL_RX_LIMIT); 1281*61ae650dSJack F Vogel 1282*61ae650dSJack F Vogel IXL_TX_LOCK(txr); 1283*61ae650dSJack F Vogel more_tx = ixl_txeof(que); 1284*61ae650dSJack F Vogel /* 1285*61ae650dSJack F Vogel ** Make certain that if the stack 1286*61ae650dSJack F Vogel ** has anything queued the task gets 1287*61ae650dSJack F Vogel ** scheduled to handle it. 1288*61ae650dSJack F Vogel */ 1289*61ae650dSJack F Vogel if (!drbr_empty(vsi->ifp, txr->br)) 1290*61ae650dSJack F Vogel more_tx = 1; 1291*61ae650dSJack F Vogel IXL_TX_UNLOCK(txr); 1292*61ae650dSJack F Vogel 1293*61ae650dSJack F Vogel ixl_set_queue_rx_itr(que); 1294*61ae650dSJack F Vogel ixl_set_queue_tx_itr(que); 1295*61ae650dSJack F Vogel 1296*61ae650dSJack F Vogel if (more_tx || more_rx) 1297*61ae650dSJack F Vogel taskqueue_enqueue(que->tq, &que->task); 1298*61ae650dSJack F Vogel else 1299*61ae650dSJack F Vogel ixl_enable_queue(hw, que->me); 1300*61ae650dSJack F Vogel 1301*61ae650dSJack F Vogel return; 1302*61ae650dSJack F Vogel } 1303*61ae650dSJack F Vogel 1304*61ae650dSJack F Vogel 1305*61ae650dSJack F Vogel /********************************************************************* 1306*61ae650dSJack F Vogel * 1307*61ae650dSJack F Vogel * MSIX Admin Queue Interrupt Service routine 1308*61ae650dSJack F Vogel * 1309*61ae650dSJack F Vogel **********************************************************************/ 1310*61ae650dSJack F Vogel static void 1311*61ae650dSJack F Vogel ixl_msix_adminq(void *arg) 1312*61ae650dSJack F Vogel { 1313*61ae650dSJack F Vogel struct ixl_pf *pf = arg; 1314*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 1315*61ae650dSJack F Vogel u32 reg, mask; 1316*61ae650dSJack F Vogel 1317*61ae650dSJack F Vogel ++pf->admin_irq; 1318*61ae650dSJack F Vogel 1319*61ae650dSJack F Vogel reg = rd32(hw, I40E_PFINT_ICR0); 1320*61ae650dSJack F Vogel mask = rd32(hw, I40E_PFINT_ICR0_ENA); 1321*61ae650dSJack F Vogel 1322*61ae650dSJack F Vogel /* Check on the cause */ 1323*61ae650dSJack F Vogel if (reg & I40E_PFINT_ICR0_ADMINQ_MASK) 1324*61ae650dSJack F Vogel mask &= ~I40E_PFINT_ICR0_ENA_ADMINQ_MASK; 1325*61ae650dSJack F Vogel 1326*61ae650dSJack F Vogel if (reg & I40E_PFINT_ICR0_MAL_DETECT_MASK) { 1327*61ae650dSJack F Vogel ixl_handle_mdd_event(pf); 1328*61ae650dSJack F Vogel mask &= ~I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK; 1329*61ae650dSJack F Vogel } 1330*61ae650dSJack F Vogel 1331*61ae650dSJack F Vogel if (reg & I40E_PFINT_ICR0_VFLR_MASK) 1332*61ae650dSJack F Vogel mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK; 1333*61ae650dSJack F Vogel 1334*61ae650dSJack F Vogel reg = rd32(hw, I40E_PFINT_DYN_CTL0); 1335*61ae650dSJack F Vogel reg = reg | I40E_PFINT_DYN_CTL0_CLEARPBA_MASK; 1336*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_DYN_CTL0, reg); 1337*61ae650dSJack F Vogel 1338*61ae650dSJack F Vogel taskqueue_enqueue(pf->tq, &pf->adminq); 1339*61ae650dSJack F Vogel return; 1340*61ae650dSJack F Vogel } 1341*61ae650dSJack F Vogel 1342*61ae650dSJack F Vogel /********************************************************************* 1343*61ae650dSJack F Vogel * 1344*61ae650dSJack F Vogel * Media Ioctl callback 1345*61ae650dSJack F Vogel * 1346*61ae650dSJack F Vogel * This routine is called whenever the user queries the status of 1347*61ae650dSJack F Vogel * the interface using ifconfig. 1348*61ae650dSJack F Vogel * 1349*61ae650dSJack F Vogel **********************************************************************/ 1350*61ae650dSJack F Vogel static void 1351*61ae650dSJack F Vogel ixl_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) 1352*61ae650dSJack F Vogel { 1353*61ae650dSJack F Vogel struct ixl_vsi *vsi = ifp->if_softc; 1354*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)vsi->back; 1355*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 1356*61ae650dSJack F Vogel 1357*61ae650dSJack F Vogel INIT_DEBUGOUT("ixl_media_status: begin"); 1358*61ae650dSJack F Vogel IXL_PF_LOCK(pf); 1359*61ae650dSJack F Vogel 1360*61ae650dSJack F Vogel ixl_update_link_status(pf); 1361*61ae650dSJack F Vogel 1362*61ae650dSJack F Vogel ifmr->ifm_status = IFM_AVALID; 1363*61ae650dSJack F Vogel ifmr->ifm_active = IFM_ETHER; 1364*61ae650dSJack F Vogel 1365*61ae650dSJack F Vogel if (!vsi->link_up) { 1366*61ae650dSJack F Vogel IXL_PF_UNLOCK(pf); 1367*61ae650dSJack F Vogel return; 1368*61ae650dSJack F Vogel } 1369*61ae650dSJack F Vogel 1370*61ae650dSJack F Vogel ifmr->ifm_status |= IFM_ACTIVE; 1371*61ae650dSJack F Vogel /* Hardware is always full-duplex */ 1372*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_FDX; 1373*61ae650dSJack F Vogel 1374*61ae650dSJack F Vogel switch (hw->phy.link_info.phy_type) { 1375*61ae650dSJack F Vogel /* 100 M */ 1376*61ae650dSJack F Vogel case I40E_PHY_TYPE_100BASE_TX: 1377*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_100_TX; 1378*61ae650dSJack F Vogel break; 1379*61ae650dSJack F Vogel /* 1 G */ 1380*61ae650dSJack F Vogel case I40E_PHY_TYPE_1000BASE_T: 1381*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_1000_T; 1382*61ae650dSJack F Vogel break; 1383*61ae650dSJack F Vogel case I40E_PHY_TYPE_1000BASE_SX: 1384*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_1000_SX; 1385*61ae650dSJack F Vogel break; 1386*61ae650dSJack F Vogel case I40E_PHY_TYPE_1000BASE_LX: 1387*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_1000_LX; 1388*61ae650dSJack F Vogel break; 1389*61ae650dSJack F Vogel /* 10 G */ 1390*61ae650dSJack F Vogel case I40E_PHY_TYPE_10GBASE_CR1_CU: 1391*61ae650dSJack F Vogel case I40E_PHY_TYPE_10GBASE_SFPP_CU: 1392*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_10G_TWINAX; 1393*61ae650dSJack F Vogel break; 1394*61ae650dSJack F Vogel case I40E_PHY_TYPE_10GBASE_SR: 1395*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_10G_SR; 1396*61ae650dSJack F Vogel break; 1397*61ae650dSJack F Vogel case I40E_PHY_TYPE_10GBASE_LR: 1398*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_10G_LR; 1399*61ae650dSJack F Vogel break; 1400*61ae650dSJack F Vogel case I40E_PHY_TYPE_10GBASE_T: 1401*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_10G_T; 1402*61ae650dSJack F Vogel break; 1403*61ae650dSJack F Vogel /* 40 G */ 1404*61ae650dSJack F Vogel case I40E_PHY_TYPE_40GBASE_CR4: 1405*61ae650dSJack F Vogel case I40E_PHY_TYPE_40GBASE_CR4_CU: 1406*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_40G_CR4; 1407*61ae650dSJack F Vogel break; 1408*61ae650dSJack F Vogel case I40E_PHY_TYPE_40GBASE_SR4: 1409*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_40G_SR4; 1410*61ae650dSJack F Vogel break; 1411*61ae650dSJack F Vogel case I40E_PHY_TYPE_40GBASE_LR4: 1412*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_40G_LR4; 1413*61ae650dSJack F Vogel break; 1414*61ae650dSJack F Vogel default: 1415*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_UNKNOWN; 1416*61ae650dSJack F Vogel break; 1417*61ae650dSJack F Vogel } 1418*61ae650dSJack F Vogel /* Report flow control status as well */ 1419*61ae650dSJack F Vogel if (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX) 1420*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_ETH_TXPAUSE; 1421*61ae650dSJack F Vogel if (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX) 1422*61ae650dSJack F Vogel ifmr->ifm_active |= IFM_ETH_RXPAUSE; 1423*61ae650dSJack F Vogel 1424*61ae650dSJack F Vogel IXL_PF_UNLOCK(pf); 1425*61ae650dSJack F Vogel 1426*61ae650dSJack F Vogel return; 1427*61ae650dSJack F Vogel } 1428*61ae650dSJack F Vogel 1429*61ae650dSJack F Vogel /********************************************************************* 1430*61ae650dSJack F Vogel * 1431*61ae650dSJack F Vogel * Media Ioctl callback 1432*61ae650dSJack F Vogel * 1433*61ae650dSJack F Vogel * This routine is called when the user changes speed/duplex using 1434*61ae650dSJack F Vogel * media/mediopt option with ifconfig. 1435*61ae650dSJack F Vogel * 1436*61ae650dSJack F Vogel **********************************************************************/ 1437*61ae650dSJack F Vogel static int 1438*61ae650dSJack F Vogel ixl_media_change(struct ifnet * ifp) 1439*61ae650dSJack F Vogel { 1440*61ae650dSJack F Vogel struct ixl_vsi *vsi = ifp->if_softc; 1441*61ae650dSJack F Vogel struct ifmedia *ifm = &vsi->media; 1442*61ae650dSJack F Vogel 1443*61ae650dSJack F Vogel INIT_DEBUGOUT("ixl_media_change: begin"); 1444*61ae650dSJack F Vogel 1445*61ae650dSJack F Vogel if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 1446*61ae650dSJack F Vogel return (EINVAL); 1447*61ae650dSJack F Vogel 1448*61ae650dSJack F Vogel if_printf(ifp, "Media change is currently not supported.\n"); 1449*61ae650dSJack F Vogel 1450*61ae650dSJack F Vogel return (ENODEV); 1451*61ae650dSJack F Vogel } 1452*61ae650dSJack F Vogel 1453*61ae650dSJack F Vogel 1454*61ae650dSJack F Vogel #ifdef IXL_FDIR 1455*61ae650dSJack F Vogel /* 1456*61ae650dSJack F Vogel ** ATR: Application Targetted Receive - creates a filter 1457*61ae650dSJack F Vogel ** based on TX flow info that will keep the receive 1458*61ae650dSJack F Vogel ** portion of the flow on the same queue. Based on the 1459*61ae650dSJack F Vogel ** implementation this is only available for TCP connections 1460*61ae650dSJack F Vogel */ 1461*61ae650dSJack F Vogel void 1462*61ae650dSJack F Vogel ixl_atr(struct ixl_queue *que, struct tcphdr *th, int etype) 1463*61ae650dSJack F Vogel { 1464*61ae650dSJack F Vogel struct ixl_vsi *vsi = que->vsi; 1465*61ae650dSJack F Vogel struct tx_ring *txr = &que->txr; 1466*61ae650dSJack F Vogel struct i40e_filter_program_desc *FDIR; 1467*61ae650dSJack F Vogel u32 ptype, dtype; 1468*61ae650dSJack F Vogel int idx; 1469*61ae650dSJack F Vogel 1470*61ae650dSJack F Vogel /* check if ATR is enabled and sample rate */ 1471*61ae650dSJack F Vogel if ((!ixl_enable_fdir) || (!txr->atr_rate)) 1472*61ae650dSJack F Vogel return; 1473*61ae650dSJack F Vogel /* 1474*61ae650dSJack F Vogel ** We sample all TCP SYN/FIN packets, 1475*61ae650dSJack F Vogel ** or at the selected sample rate 1476*61ae650dSJack F Vogel */ 1477*61ae650dSJack F Vogel txr->atr_count++; 1478*61ae650dSJack F Vogel if (((th->th_flags & (TH_FIN | TH_SYN)) == 0) && 1479*61ae650dSJack F Vogel (txr->atr_count < txr->atr_rate)) 1480*61ae650dSJack F Vogel return; 1481*61ae650dSJack F Vogel txr->atr_count = 0; 1482*61ae650dSJack F Vogel 1483*61ae650dSJack F Vogel /* Get a descriptor to use */ 1484*61ae650dSJack F Vogel idx = txr->next_avail; 1485*61ae650dSJack F Vogel FDIR = (struct i40e_filter_program_desc *) &txr->base[idx]; 1486*61ae650dSJack F Vogel if (++idx == que->num_desc) 1487*61ae650dSJack F Vogel idx = 0; 1488*61ae650dSJack F Vogel txr->avail--; 1489*61ae650dSJack F Vogel txr->next_avail = idx; 1490*61ae650dSJack F Vogel 1491*61ae650dSJack F Vogel ptype = (que->me << I40E_TXD_FLTR_QW0_QINDEX_SHIFT) & 1492*61ae650dSJack F Vogel I40E_TXD_FLTR_QW0_QINDEX_MASK; 1493*61ae650dSJack F Vogel 1494*61ae650dSJack F Vogel ptype |= (etype == ETHERTYPE_IP) ? 1495*61ae650dSJack F Vogel (I40E_FILTER_PCTYPE_NONF_IPV4_TCP << 1496*61ae650dSJack F Vogel I40E_TXD_FLTR_QW0_PCTYPE_SHIFT) : 1497*61ae650dSJack F Vogel (I40E_FILTER_PCTYPE_NONF_IPV6_TCP << 1498*61ae650dSJack F Vogel I40E_TXD_FLTR_QW0_PCTYPE_SHIFT); 1499*61ae650dSJack F Vogel 1500*61ae650dSJack F Vogel ptype |= vsi->id << I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT; 1501*61ae650dSJack F Vogel 1502*61ae650dSJack F Vogel dtype = I40E_TX_DESC_DTYPE_FILTER_PROG; 1503*61ae650dSJack F Vogel 1504*61ae650dSJack F Vogel /* 1505*61ae650dSJack F Vogel ** We use the TCP TH_FIN as a trigger to remove 1506*61ae650dSJack F Vogel ** the filter, otherwise its an update. 1507*61ae650dSJack F Vogel */ 1508*61ae650dSJack F Vogel dtype |= (th->th_flags & TH_FIN) ? 1509*61ae650dSJack F Vogel (I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE << 1510*61ae650dSJack F Vogel I40E_TXD_FLTR_QW1_PCMD_SHIFT) : 1511*61ae650dSJack F Vogel (I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE << 1512*61ae650dSJack F Vogel I40E_TXD_FLTR_QW1_PCMD_SHIFT); 1513*61ae650dSJack F Vogel 1514*61ae650dSJack F Vogel dtype |= I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX << 1515*61ae650dSJack F Vogel I40E_TXD_FLTR_QW1_DEST_SHIFT; 1516*61ae650dSJack F Vogel 1517*61ae650dSJack F Vogel dtype |= I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID << 1518*61ae650dSJack F Vogel I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT; 1519*61ae650dSJack F Vogel 1520*61ae650dSJack F Vogel FDIR->qindex_flex_ptype_vsi = htole32(ptype); 1521*61ae650dSJack F Vogel FDIR->dtype_cmd_cntindex = htole32(dtype); 1522*61ae650dSJack F Vogel return; 1523*61ae650dSJack F Vogel } 1524*61ae650dSJack F Vogel #endif 1525*61ae650dSJack F Vogel 1526*61ae650dSJack F Vogel 1527*61ae650dSJack F Vogel static void 1528*61ae650dSJack F Vogel ixl_set_promisc(struct ixl_vsi *vsi) 1529*61ae650dSJack F Vogel { 1530*61ae650dSJack F Vogel struct ifnet *ifp = vsi->ifp; 1531*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 1532*61ae650dSJack F Vogel int err, mcnt = 0; 1533*61ae650dSJack F Vogel bool uni = FALSE, multi = FALSE; 1534*61ae650dSJack F Vogel 1535*61ae650dSJack F Vogel if (ifp->if_flags & IFF_ALLMULTI) 1536*61ae650dSJack F Vogel multi = TRUE; 1537*61ae650dSJack F Vogel else { /* Need to count the multicast addresses */ 1538*61ae650dSJack F Vogel struct ifmultiaddr *ifma; 1539*61ae650dSJack F Vogel if_maddr_rlock(ifp); 1540*61ae650dSJack F Vogel TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1541*61ae650dSJack F Vogel if (ifma->ifma_addr->sa_family != AF_LINK) 1542*61ae650dSJack F Vogel continue; 1543*61ae650dSJack F Vogel if (mcnt == MAX_MULTICAST_ADDR) 1544*61ae650dSJack F Vogel break; 1545*61ae650dSJack F Vogel mcnt++; 1546*61ae650dSJack F Vogel } 1547*61ae650dSJack F Vogel if_maddr_runlock(ifp); 1548*61ae650dSJack F Vogel } 1549*61ae650dSJack F Vogel 1550*61ae650dSJack F Vogel if (mcnt >= MAX_MULTICAST_ADDR) 1551*61ae650dSJack F Vogel multi = TRUE; 1552*61ae650dSJack F Vogel if (ifp->if_flags & IFF_PROMISC) 1553*61ae650dSJack F Vogel uni = TRUE; 1554*61ae650dSJack F Vogel 1555*61ae650dSJack F Vogel err = i40e_aq_set_vsi_unicast_promiscuous(hw, 1556*61ae650dSJack F Vogel vsi->seid, uni, NULL); 1557*61ae650dSJack F Vogel err = i40e_aq_set_vsi_multicast_promiscuous(hw, 1558*61ae650dSJack F Vogel vsi->seid, multi, NULL); 1559*61ae650dSJack F Vogel return; 1560*61ae650dSJack F Vogel } 1561*61ae650dSJack F Vogel 1562*61ae650dSJack F Vogel /********************************************************************* 1563*61ae650dSJack F Vogel * Filter Routines 1564*61ae650dSJack F Vogel * 1565*61ae650dSJack F Vogel * Routines for multicast and vlan filter management. 1566*61ae650dSJack F Vogel * 1567*61ae650dSJack F Vogel *********************************************************************/ 1568*61ae650dSJack F Vogel static void 1569*61ae650dSJack F Vogel ixl_add_multi(struct ixl_vsi *vsi) 1570*61ae650dSJack F Vogel { 1571*61ae650dSJack F Vogel struct ifmultiaddr *ifma; 1572*61ae650dSJack F Vogel struct ifnet *ifp = vsi->ifp; 1573*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 1574*61ae650dSJack F Vogel int mcnt = 0, flags; 1575*61ae650dSJack F Vogel 1576*61ae650dSJack F Vogel IOCTL_DEBUGOUT("ixl_add_multi: begin"); 1577*61ae650dSJack F Vogel 1578*61ae650dSJack F Vogel if_maddr_rlock(ifp); 1579*61ae650dSJack F Vogel /* 1580*61ae650dSJack F Vogel ** First just get a count, to decide if we 1581*61ae650dSJack F Vogel ** we simply use multicast promiscuous. 1582*61ae650dSJack F Vogel */ 1583*61ae650dSJack F Vogel TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1584*61ae650dSJack F Vogel if (ifma->ifma_addr->sa_family != AF_LINK) 1585*61ae650dSJack F Vogel continue; 1586*61ae650dSJack F Vogel mcnt++; 1587*61ae650dSJack F Vogel } 1588*61ae650dSJack F Vogel if_maddr_runlock(ifp); 1589*61ae650dSJack F Vogel 1590*61ae650dSJack F Vogel if (__predict_false(mcnt >= MAX_MULTICAST_ADDR)) { 1591*61ae650dSJack F Vogel /* delete existing MC filters */ 1592*61ae650dSJack F Vogel ixl_del_hw_filters(vsi, mcnt); 1593*61ae650dSJack F Vogel i40e_aq_set_vsi_multicast_promiscuous(hw, 1594*61ae650dSJack F Vogel vsi->seid, TRUE, NULL); 1595*61ae650dSJack F Vogel return; 1596*61ae650dSJack F Vogel } 1597*61ae650dSJack F Vogel 1598*61ae650dSJack F Vogel mcnt = 0; 1599*61ae650dSJack F Vogel if_maddr_rlock(ifp); 1600*61ae650dSJack F Vogel TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1601*61ae650dSJack F Vogel if (ifma->ifma_addr->sa_family != AF_LINK) 1602*61ae650dSJack F Vogel continue; 1603*61ae650dSJack F Vogel ixl_add_mc_filter(vsi, 1604*61ae650dSJack F Vogel (u8*)LLADDR((struct sockaddr_dl *) ifma->ifma_addr)); 1605*61ae650dSJack F Vogel mcnt++; 1606*61ae650dSJack F Vogel } 1607*61ae650dSJack F Vogel if_maddr_runlock(ifp); 1608*61ae650dSJack F Vogel if (mcnt > 0) { 1609*61ae650dSJack F Vogel flags = (IXL_FILTER_ADD | IXL_FILTER_USED | IXL_FILTER_MC); 1610*61ae650dSJack F Vogel ixl_add_hw_filters(vsi, flags, mcnt); 1611*61ae650dSJack F Vogel } 1612*61ae650dSJack F Vogel 1613*61ae650dSJack F Vogel IOCTL_DEBUGOUT("ixl_add_multi: end"); 1614*61ae650dSJack F Vogel return; 1615*61ae650dSJack F Vogel } 1616*61ae650dSJack F Vogel 1617*61ae650dSJack F Vogel static void 1618*61ae650dSJack F Vogel ixl_del_multi(struct ixl_vsi *vsi) 1619*61ae650dSJack F Vogel { 1620*61ae650dSJack F Vogel struct ifnet *ifp = vsi->ifp; 1621*61ae650dSJack F Vogel struct ifmultiaddr *ifma; 1622*61ae650dSJack F Vogel struct ixl_mac_filter *f; 1623*61ae650dSJack F Vogel int mcnt = 0; 1624*61ae650dSJack F Vogel bool match = FALSE; 1625*61ae650dSJack F Vogel 1626*61ae650dSJack F Vogel IOCTL_DEBUGOUT("ixl_del_multi: begin"); 1627*61ae650dSJack F Vogel 1628*61ae650dSJack F Vogel /* Search for removed multicast addresses */ 1629*61ae650dSJack F Vogel if_maddr_rlock(ifp); 1630*61ae650dSJack F Vogel SLIST_FOREACH(f, &vsi->ftl, next) { 1631*61ae650dSJack F Vogel if ((f->flags & IXL_FILTER_USED) && (f->flags & IXL_FILTER_MC)) { 1632*61ae650dSJack F Vogel match = FALSE; 1633*61ae650dSJack F Vogel TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1634*61ae650dSJack F Vogel if (ifma->ifma_addr->sa_family != AF_LINK) 1635*61ae650dSJack F Vogel continue; 1636*61ae650dSJack F Vogel u8 *mc_addr = (u8 *)LLADDR((struct sockaddr_dl *)ifma->ifma_addr); 1637*61ae650dSJack F Vogel if (cmp_etheraddr(f->macaddr, mc_addr)) { 1638*61ae650dSJack F Vogel match = TRUE; 1639*61ae650dSJack F Vogel break; 1640*61ae650dSJack F Vogel } 1641*61ae650dSJack F Vogel } 1642*61ae650dSJack F Vogel if (match == FALSE) { 1643*61ae650dSJack F Vogel f->flags |= IXL_FILTER_DEL; 1644*61ae650dSJack F Vogel mcnt++; 1645*61ae650dSJack F Vogel } 1646*61ae650dSJack F Vogel } 1647*61ae650dSJack F Vogel } 1648*61ae650dSJack F Vogel if_maddr_runlock(ifp); 1649*61ae650dSJack F Vogel 1650*61ae650dSJack F Vogel if (mcnt > 0) 1651*61ae650dSJack F Vogel ixl_del_hw_filters(vsi, mcnt); 1652*61ae650dSJack F Vogel } 1653*61ae650dSJack F Vogel 1654*61ae650dSJack F Vogel 1655*61ae650dSJack F Vogel /********************************************************************* 1656*61ae650dSJack F Vogel * Timer routine 1657*61ae650dSJack F Vogel * 1658*61ae650dSJack F Vogel * This routine checks for link status,updates statistics, 1659*61ae650dSJack F Vogel * and runs the watchdog check. 1660*61ae650dSJack F Vogel * 1661*61ae650dSJack F Vogel **********************************************************************/ 1662*61ae650dSJack F Vogel 1663*61ae650dSJack F Vogel static void 1664*61ae650dSJack F Vogel ixl_local_timer(void *arg) 1665*61ae650dSJack F Vogel { 1666*61ae650dSJack F Vogel struct ixl_pf *pf = arg; 1667*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 1668*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 1669*61ae650dSJack F Vogel struct ixl_queue *que = vsi->queues; 1670*61ae650dSJack F Vogel device_t dev = pf->dev; 1671*61ae650dSJack F Vogel int hung = 0; 1672*61ae650dSJack F Vogel u32 mask; 1673*61ae650dSJack F Vogel 1674*61ae650dSJack F Vogel mtx_assert(&pf->pf_mtx, MA_OWNED); 1675*61ae650dSJack F Vogel 1676*61ae650dSJack F Vogel /* Fire off the adminq task */ 1677*61ae650dSJack F Vogel taskqueue_enqueue(pf->tq, &pf->adminq); 1678*61ae650dSJack F Vogel 1679*61ae650dSJack F Vogel /* Update stats */ 1680*61ae650dSJack F Vogel ixl_update_stats_counters(pf); 1681*61ae650dSJack F Vogel 1682*61ae650dSJack F Vogel /* 1683*61ae650dSJack F Vogel ** Check status of the queues 1684*61ae650dSJack F Vogel */ 1685*61ae650dSJack F Vogel mask = (I40E_PFINT_DYN_CTLN_INTENA_MASK | 1686*61ae650dSJack F Vogel I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK); 1687*61ae650dSJack F Vogel 1688*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++,que++) { 1689*61ae650dSJack F Vogel /* Any queues with outstanding work get a sw irq */ 1690*61ae650dSJack F Vogel if (que->busy) 1691*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_DYN_CTLN(que->me), mask); 1692*61ae650dSJack F Vogel /* 1693*61ae650dSJack F Vogel ** Each time txeof runs without cleaning, but there 1694*61ae650dSJack F Vogel ** are uncleaned descriptors it increments busy. If 1695*61ae650dSJack F Vogel ** we get to 5 we declare it hung. 1696*61ae650dSJack F Vogel */ 1697*61ae650dSJack F Vogel if (que->busy == IXL_QUEUE_HUNG) { 1698*61ae650dSJack F Vogel ++hung; 1699*61ae650dSJack F Vogel /* Mark the queue as inactive */ 1700*61ae650dSJack F Vogel vsi->active_queues &= ~((u64)1 << que->me); 1701*61ae650dSJack F Vogel continue; 1702*61ae650dSJack F Vogel } else { 1703*61ae650dSJack F Vogel /* Check if we've come back from hung */ 1704*61ae650dSJack F Vogel if ((vsi->active_queues & ((u64)1 << que->me)) == 0) 1705*61ae650dSJack F Vogel vsi->active_queues |= ((u64)1 << que->me); 1706*61ae650dSJack F Vogel } 1707*61ae650dSJack F Vogel if (que->busy >= IXL_MAX_TX_BUSY) { 1708*61ae650dSJack F Vogel device_printf(dev,"Warning queue %d " 1709*61ae650dSJack F Vogel "appears to be hung!\n", i); 1710*61ae650dSJack F Vogel que->busy = IXL_QUEUE_HUNG; 1711*61ae650dSJack F Vogel ++hung; 1712*61ae650dSJack F Vogel } 1713*61ae650dSJack F Vogel } 1714*61ae650dSJack F Vogel /* Only reinit if all queues show hung */ 1715*61ae650dSJack F Vogel if (hung == vsi->num_queues) 1716*61ae650dSJack F Vogel goto hung; 1717*61ae650dSJack F Vogel 1718*61ae650dSJack F Vogel callout_reset(&pf->timer, hz, ixl_local_timer, pf); 1719*61ae650dSJack F Vogel return; 1720*61ae650dSJack F Vogel 1721*61ae650dSJack F Vogel hung: 1722*61ae650dSJack F Vogel device_printf(dev, "Local Timer: HANG DETECT - Resetting!!\n"); 1723*61ae650dSJack F Vogel ixl_init_locked(pf); 1724*61ae650dSJack F Vogel } 1725*61ae650dSJack F Vogel 1726*61ae650dSJack F Vogel /* 1727*61ae650dSJack F Vogel ** Note: this routine updates the OS on the link state 1728*61ae650dSJack F Vogel ** the real check of the hardware only happens with 1729*61ae650dSJack F Vogel ** a link interrupt. 1730*61ae650dSJack F Vogel */ 1731*61ae650dSJack F Vogel static void 1732*61ae650dSJack F Vogel ixl_update_link_status(struct ixl_pf *pf) 1733*61ae650dSJack F Vogel { 1734*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 1735*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 1736*61ae650dSJack F Vogel struct ifnet *ifp = vsi->ifp; 1737*61ae650dSJack F Vogel device_t dev = pf->dev; 1738*61ae650dSJack F Vogel enum i40e_fc_mode fc; 1739*61ae650dSJack F Vogel 1740*61ae650dSJack F Vogel 1741*61ae650dSJack F Vogel if (vsi->link_up){ 1742*61ae650dSJack F Vogel if (vsi->link_active == FALSE) { 1743*61ae650dSJack F Vogel i40e_aq_get_link_info(hw, TRUE, NULL, NULL); 1744*61ae650dSJack F Vogel if (bootverbose) { 1745*61ae650dSJack F Vogel fc = hw->fc.current_mode; 1746*61ae650dSJack F Vogel device_printf(dev,"Link is up %d Gbps %s," 1747*61ae650dSJack F Vogel " Flow Control: %s\n", 1748*61ae650dSJack F Vogel ((vsi->link_speed == I40E_LINK_SPEED_40GB)? 40:10), 1749*61ae650dSJack F Vogel "Full Duplex", ixl_fc_string[fc]); 1750*61ae650dSJack F Vogel } 1751*61ae650dSJack F Vogel vsi->link_active = TRUE; 1752*61ae650dSJack F Vogel if_link_state_change(ifp, LINK_STATE_UP); 1753*61ae650dSJack F Vogel } 1754*61ae650dSJack F Vogel } else { /* Link down */ 1755*61ae650dSJack F Vogel if (vsi->link_active == TRUE) { 1756*61ae650dSJack F Vogel if (bootverbose) 1757*61ae650dSJack F Vogel device_printf(dev,"Link is Down\n"); 1758*61ae650dSJack F Vogel if_link_state_change(ifp, LINK_STATE_DOWN); 1759*61ae650dSJack F Vogel vsi->link_active = FALSE; 1760*61ae650dSJack F Vogel } 1761*61ae650dSJack F Vogel } 1762*61ae650dSJack F Vogel 1763*61ae650dSJack F Vogel return; 1764*61ae650dSJack F Vogel } 1765*61ae650dSJack F Vogel 1766*61ae650dSJack F Vogel /********************************************************************* 1767*61ae650dSJack F Vogel * 1768*61ae650dSJack F Vogel * This routine disables all traffic on the adapter by issuing a 1769*61ae650dSJack F Vogel * global reset on the MAC and deallocates TX/RX buffers. 1770*61ae650dSJack F Vogel * 1771*61ae650dSJack F Vogel **********************************************************************/ 1772*61ae650dSJack F Vogel 1773*61ae650dSJack F Vogel static void 1774*61ae650dSJack F Vogel ixl_stop(struct ixl_pf *pf) 1775*61ae650dSJack F Vogel { 1776*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 1777*61ae650dSJack F Vogel struct ifnet *ifp = vsi->ifp; 1778*61ae650dSJack F Vogel 1779*61ae650dSJack F Vogel mtx_assert(&pf->pf_mtx, MA_OWNED); 1780*61ae650dSJack F Vogel 1781*61ae650dSJack F Vogel INIT_DEBUGOUT("ixl_stop: begin\n"); 1782*61ae650dSJack F Vogel ixl_disable_intr(vsi); 1783*61ae650dSJack F Vogel ixl_disable_rings(vsi); 1784*61ae650dSJack F Vogel 1785*61ae650dSJack F Vogel /* Tell the stack that the interface is no longer active */ 1786*61ae650dSJack F Vogel ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 1787*61ae650dSJack F Vogel 1788*61ae650dSJack F Vogel /* Stop the local timer */ 1789*61ae650dSJack F Vogel callout_stop(&pf->timer); 1790*61ae650dSJack F Vogel 1791*61ae650dSJack F Vogel return; 1792*61ae650dSJack F Vogel } 1793*61ae650dSJack F Vogel 1794*61ae650dSJack F Vogel 1795*61ae650dSJack F Vogel /********************************************************************* 1796*61ae650dSJack F Vogel * 1797*61ae650dSJack F Vogel * Setup MSIX Interrupt resources and handlers for the VSI 1798*61ae650dSJack F Vogel * 1799*61ae650dSJack F Vogel **********************************************************************/ 1800*61ae650dSJack F Vogel static int 1801*61ae650dSJack F Vogel ixl_assign_vsi_legacy(struct ixl_pf *pf) 1802*61ae650dSJack F Vogel { 1803*61ae650dSJack F Vogel device_t dev = pf->dev; 1804*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 1805*61ae650dSJack F Vogel struct ixl_queue *que = vsi->queues; 1806*61ae650dSJack F Vogel int error, rid = 0; 1807*61ae650dSJack F Vogel 1808*61ae650dSJack F Vogel if (pf->msix == 1) 1809*61ae650dSJack F Vogel rid = 1; 1810*61ae650dSJack F Vogel pf->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 1811*61ae650dSJack F Vogel &rid, RF_SHAREABLE | RF_ACTIVE); 1812*61ae650dSJack F Vogel if (pf->res == NULL) { 1813*61ae650dSJack F Vogel device_printf(dev,"Unable to allocate" 1814*61ae650dSJack F Vogel " bus resource: vsi legacy/msi interrupt\n"); 1815*61ae650dSJack F Vogel return (ENXIO); 1816*61ae650dSJack F Vogel } 1817*61ae650dSJack F Vogel 1818*61ae650dSJack F Vogel /* Set the handler function */ 1819*61ae650dSJack F Vogel error = bus_setup_intr(dev, pf->res, 1820*61ae650dSJack F Vogel INTR_TYPE_NET | INTR_MPSAFE, NULL, 1821*61ae650dSJack F Vogel ixl_intr, pf, &pf->tag); 1822*61ae650dSJack F Vogel if (error) { 1823*61ae650dSJack F Vogel pf->res = NULL; 1824*61ae650dSJack F Vogel device_printf(dev, "Failed to register legacy/msi handler"); 1825*61ae650dSJack F Vogel return (error); 1826*61ae650dSJack F Vogel } 1827*61ae650dSJack F Vogel bus_describe_intr(dev, pf->res, pf->tag, "irq0"); 1828*61ae650dSJack F Vogel TASK_INIT(&que->tx_task, 0, ixl_deferred_mq_start, que); 1829*61ae650dSJack F Vogel TASK_INIT(&que->task, 0, ixl_handle_que, que); 1830*61ae650dSJack F Vogel que->tq = taskqueue_create_fast("ixl_que", M_NOWAIT, 1831*61ae650dSJack F Vogel taskqueue_thread_enqueue, &que->tq); 1832*61ae650dSJack F Vogel taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que", 1833*61ae650dSJack F Vogel device_get_nameunit(dev)); 1834*61ae650dSJack F Vogel TASK_INIT(&pf->adminq, 0, ixl_do_adminq, pf); 1835*61ae650dSJack F Vogel pf->tq = taskqueue_create_fast("ixl_adm", M_NOWAIT, 1836*61ae650dSJack F Vogel taskqueue_thread_enqueue, &pf->tq); 1837*61ae650dSJack F Vogel taskqueue_start_threads(&pf->tq, 1, PI_NET, "%s adminq", 1838*61ae650dSJack F Vogel device_get_nameunit(dev)); 1839*61ae650dSJack F Vogel 1840*61ae650dSJack F Vogel return (0); 1841*61ae650dSJack F Vogel } 1842*61ae650dSJack F Vogel 1843*61ae650dSJack F Vogel 1844*61ae650dSJack F Vogel /********************************************************************* 1845*61ae650dSJack F Vogel * 1846*61ae650dSJack F Vogel * Setup MSIX Interrupt resources and handlers for the VSI 1847*61ae650dSJack F Vogel * 1848*61ae650dSJack F Vogel **********************************************************************/ 1849*61ae650dSJack F Vogel static int 1850*61ae650dSJack F Vogel ixl_assign_vsi_msix(struct ixl_pf *pf) 1851*61ae650dSJack F Vogel { 1852*61ae650dSJack F Vogel device_t dev = pf->dev; 1853*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 1854*61ae650dSJack F Vogel struct ixl_queue *que = vsi->queues; 1855*61ae650dSJack F Vogel struct tx_ring *txr; 1856*61ae650dSJack F Vogel int error, rid, vector = 0; 1857*61ae650dSJack F Vogel 1858*61ae650dSJack F Vogel /* Admin Que is vector 0*/ 1859*61ae650dSJack F Vogel rid = vector + 1; 1860*61ae650dSJack F Vogel pf->res = bus_alloc_resource_any(dev, 1861*61ae650dSJack F Vogel SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); 1862*61ae650dSJack F Vogel if (!pf->res) { 1863*61ae650dSJack F Vogel device_printf(dev,"Unable to allocate" 1864*61ae650dSJack F Vogel " bus resource: Adminq interrupt [%d]\n", rid); 1865*61ae650dSJack F Vogel return (ENXIO); 1866*61ae650dSJack F Vogel } 1867*61ae650dSJack F Vogel /* Set the adminq vector and handler */ 1868*61ae650dSJack F Vogel error = bus_setup_intr(dev, pf->res, 1869*61ae650dSJack F Vogel INTR_TYPE_NET | INTR_MPSAFE, NULL, 1870*61ae650dSJack F Vogel ixl_msix_adminq, pf, &pf->tag); 1871*61ae650dSJack F Vogel if (error) { 1872*61ae650dSJack F Vogel pf->res = NULL; 1873*61ae650dSJack F Vogel device_printf(dev, "Failed to register Admin que handler"); 1874*61ae650dSJack F Vogel return (error); 1875*61ae650dSJack F Vogel } 1876*61ae650dSJack F Vogel bus_describe_intr(dev, pf->res, pf->tag, "aq"); 1877*61ae650dSJack F Vogel pf->admvec = vector; 1878*61ae650dSJack F Vogel /* Tasklet for Admin Queue */ 1879*61ae650dSJack F Vogel TASK_INIT(&pf->adminq, 0, ixl_do_adminq, pf); 1880*61ae650dSJack F Vogel pf->tq = taskqueue_create_fast("ixl_adm", M_NOWAIT, 1881*61ae650dSJack F Vogel taskqueue_thread_enqueue, &pf->tq); 1882*61ae650dSJack F Vogel taskqueue_start_threads(&pf->tq, 1, PI_NET, "%s adminq", 1883*61ae650dSJack F Vogel device_get_nameunit(pf->dev)); 1884*61ae650dSJack F Vogel ++vector; 1885*61ae650dSJack F Vogel 1886*61ae650dSJack F Vogel /* Now set up the stations */ 1887*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++, vector++, que++) { 1888*61ae650dSJack F Vogel rid = vector + 1; 1889*61ae650dSJack F Vogel txr = &que->txr; 1890*61ae650dSJack F Vogel que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 1891*61ae650dSJack F Vogel RF_SHAREABLE | RF_ACTIVE); 1892*61ae650dSJack F Vogel if (que->res == NULL) { 1893*61ae650dSJack F Vogel device_printf(dev,"Unable to allocate" 1894*61ae650dSJack F Vogel " bus resource: que interrupt [%d]\n", vector); 1895*61ae650dSJack F Vogel return (ENXIO); 1896*61ae650dSJack F Vogel } 1897*61ae650dSJack F Vogel /* Set the handler function */ 1898*61ae650dSJack F Vogel error = bus_setup_intr(dev, que->res, 1899*61ae650dSJack F Vogel INTR_TYPE_NET | INTR_MPSAFE, NULL, 1900*61ae650dSJack F Vogel ixl_msix_que, que, &que->tag); 1901*61ae650dSJack F Vogel if (error) { 1902*61ae650dSJack F Vogel que->res = NULL; 1903*61ae650dSJack F Vogel device_printf(dev, "Failed to register que handler"); 1904*61ae650dSJack F Vogel return (error); 1905*61ae650dSJack F Vogel } 1906*61ae650dSJack F Vogel bus_describe_intr(dev, que->res, que->tag, "q%d", i); 1907*61ae650dSJack F Vogel /* Bind the vector to a CPU */ 1908*61ae650dSJack F Vogel bus_bind_intr(dev, que->res, i); 1909*61ae650dSJack F Vogel que->msix = vector; 1910*61ae650dSJack F Vogel TASK_INIT(&que->tx_task, 0, ixl_deferred_mq_start, que); 1911*61ae650dSJack F Vogel TASK_INIT(&que->task, 0, ixl_handle_que, que); 1912*61ae650dSJack F Vogel que->tq = taskqueue_create_fast("ixl_que", M_NOWAIT, 1913*61ae650dSJack F Vogel taskqueue_thread_enqueue, &que->tq); 1914*61ae650dSJack F Vogel taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que", 1915*61ae650dSJack F Vogel device_get_nameunit(pf->dev)); 1916*61ae650dSJack F Vogel } 1917*61ae650dSJack F Vogel 1918*61ae650dSJack F Vogel return (0); 1919*61ae650dSJack F Vogel } 1920*61ae650dSJack F Vogel 1921*61ae650dSJack F Vogel 1922*61ae650dSJack F Vogel /* 1923*61ae650dSJack F Vogel * Allocate MSI/X vectors 1924*61ae650dSJack F Vogel */ 1925*61ae650dSJack F Vogel static int 1926*61ae650dSJack F Vogel ixl_init_msix(struct ixl_pf *pf) 1927*61ae650dSJack F Vogel { 1928*61ae650dSJack F Vogel device_t dev = pf->dev; 1929*61ae650dSJack F Vogel int rid, want, vectors, queues, available; 1930*61ae650dSJack F Vogel 1931*61ae650dSJack F Vogel /* Override by tuneable */ 1932*61ae650dSJack F Vogel if (ixl_enable_msix == 0) 1933*61ae650dSJack F Vogel goto msi; 1934*61ae650dSJack F Vogel 1935*61ae650dSJack F Vogel /* 1936*61ae650dSJack F Vogel ** When used in a virtualized environment 1937*61ae650dSJack F Vogel ** PCI BUSMASTER capability may not be set 1938*61ae650dSJack F Vogel ** so explicity set it here and rewrite 1939*61ae650dSJack F Vogel ** the ENABLE in the MSIX control register 1940*61ae650dSJack F Vogel ** at this point to cause the host to 1941*61ae650dSJack F Vogel ** successfully initialize us. 1942*61ae650dSJack F Vogel */ 1943*61ae650dSJack F Vogel { 1944*61ae650dSJack F Vogel u16 pci_cmd_word; 1945*61ae650dSJack F Vogel int msix_ctrl; 1946*61ae650dSJack F Vogel pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); 1947*61ae650dSJack F Vogel pci_cmd_word |= PCIM_CMD_BUSMASTEREN; 1948*61ae650dSJack F Vogel pci_write_config(dev, PCIR_COMMAND, pci_cmd_word, 2); 1949*61ae650dSJack F Vogel pci_find_cap(dev, PCIY_MSIX, &rid); 1950*61ae650dSJack F Vogel rid += PCIR_MSIX_CTRL; 1951*61ae650dSJack F Vogel msix_ctrl = pci_read_config(dev, rid, 2); 1952*61ae650dSJack F Vogel msix_ctrl |= PCIM_MSIXCTRL_MSIX_ENABLE; 1953*61ae650dSJack F Vogel pci_write_config(dev, rid, msix_ctrl, 2); 1954*61ae650dSJack F Vogel } 1955*61ae650dSJack F Vogel 1956*61ae650dSJack F Vogel /* First try MSI/X */ 1957*61ae650dSJack F Vogel rid = PCIR_BAR(IXL_BAR); 1958*61ae650dSJack F Vogel pf->msix_mem = bus_alloc_resource_any(dev, 1959*61ae650dSJack F Vogel SYS_RES_MEMORY, &rid, RF_ACTIVE); 1960*61ae650dSJack F Vogel if (!pf->msix_mem) { 1961*61ae650dSJack F Vogel /* May not be enabled */ 1962*61ae650dSJack F Vogel device_printf(pf->dev, 1963*61ae650dSJack F Vogel "Unable to map MSIX table \n"); 1964*61ae650dSJack F Vogel goto msi; 1965*61ae650dSJack F Vogel } 1966*61ae650dSJack F Vogel 1967*61ae650dSJack F Vogel available = pci_msix_count(dev); 1968*61ae650dSJack F Vogel if (available == 0) { /* system has msix disabled */ 1969*61ae650dSJack F Vogel bus_release_resource(dev, SYS_RES_MEMORY, 1970*61ae650dSJack F Vogel rid, pf->msix_mem); 1971*61ae650dSJack F Vogel pf->msix_mem = NULL; 1972*61ae650dSJack F Vogel goto msi; 1973*61ae650dSJack F Vogel } 1974*61ae650dSJack F Vogel 1975*61ae650dSJack F Vogel /* Figure out a reasonable auto config value */ 1976*61ae650dSJack F Vogel queues = (mp_ncpus > (available - 1)) ? (available - 1) : mp_ncpus; 1977*61ae650dSJack F Vogel 1978*61ae650dSJack F Vogel /* Override with hardcoded value if sane */ 1979*61ae650dSJack F Vogel if ((ixl_max_queues != 0) && (ixl_max_queues <= queues)) 1980*61ae650dSJack F Vogel queues = ixl_max_queues; 1981*61ae650dSJack F Vogel 1982*61ae650dSJack F Vogel /* 1983*61ae650dSJack F Vogel ** Want one vector (RX/TX pair) per queue 1984*61ae650dSJack F Vogel ** plus an additional for the admin queue. 1985*61ae650dSJack F Vogel */ 1986*61ae650dSJack F Vogel want = queues + 1; 1987*61ae650dSJack F Vogel if (want <= available) /* Have enough */ 1988*61ae650dSJack F Vogel vectors = want; 1989*61ae650dSJack F Vogel else { 1990*61ae650dSJack F Vogel device_printf(pf->dev, 1991*61ae650dSJack F Vogel "MSIX Configuration Problem, " 1992*61ae650dSJack F Vogel "%d vectors available but %d wanted!\n", 1993*61ae650dSJack F Vogel available, want); 1994*61ae650dSJack F Vogel return (0); /* Will go to Legacy setup */ 1995*61ae650dSJack F Vogel } 1996*61ae650dSJack F Vogel 1997*61ae650dSJack F Vogel if (pci_alloc_msix(dev, &vectors) == 0) { 1998*61ae650dSJack F Vogel device_printf(pf->dev, 1999*61ae650dSJack F Vogel "Using MSIX interrupts with %d vectors\n", vectors); 2000*61ae650dSJack F Vogel pf->msix = vectors; 2001*61ae650dSJack F Vogel pf->vsi.num_queues = queues; 2002*61ae650dSJack F Vogel return (vectors); 2003*61ae650dSJack F Vogel } 2004*61ae650dSJack F Vogel msi: 2005*61ae650dSJack F Vogel vectors = pci_msi_count(dev); 2006*61ae650dSJack F Vogel pf->vsi.num_queues = 1; 2007*61ae650dSJack F Vogel pf->msix = 1; 2008*61ae650dSJack F Vogel ixl_max_queues = 1; 2009*61ae650dSJack F Vogel ixl_enable_msix = 0; 2010*61ae650dSJack F Vogel if (vectors == 1 && pci_alloc_msi(dev, &vectors) == 0) 2011*61ae650dSJack F Vogel device_printf(pf->dev,"Using an MSI interrupt\n"); 2012*61ae650dSJack F Vogel else { 2013*61ae650dSJack F Vogel pf->msix = 0; 2014*61ae650dSJack F Vogel device_printf(pf->dev,"Using a Legacy interrupt\n"); 2015*61ae650dSJack F Vogel } 2016*61ae650dSJack F Vogel return (vectors); 2017*61ae650dSJack F Vogel } 2018*61ae650dSJack F Vogel 2019*61ae650dSJack F Vogel 2020*61ae650dSJack F Vogel /* 2021*61ae650dSJack F Vogel * Plumb MSI/X vectors 2022*61ae650dSJack F Vogel */ 2023*61ae650dSJack F Vogel static void 2024*61ae650dSJack F Vogel ixl_configure_msix(struct ixl_pf *pf) 2025*61ae650dSJack F Vogel { 2026*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 2027*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 2028*61ae650dSJack F Vogel u32 reg; 2029*61ae650dSJack F Vogel u16 vector = 1; 2030*61ae650dSJack F Vogel 2031*61ae650dSJack F Vogel /* First set up the adminq - vector 0 */ 2032*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ICR0_ENA, 0); /* disable all */ 2033*61ae650dSJack F Vogel rd32(hw, I40E_PFINT_ICR0); /* read to clear */ 2034*61ae650dSJack F Vogel 2035*61ae650dSJack F Vogel reg = I40E_PFINT_ICR0_ENA_ECC_ERR_MASK | 2036*61ae650dSJack F Vogel I40E_PFINT_ICR0_ENA_GRST_MASK | 2037*61ae650dSJack F Vogel I40E_PFINT_ICR0_HMC_ERR_MASK | 2038*61ae650dSJack F Vogel I40E_PFINT_ICR0_ENA_ADMINQ_MASK | 2039*61ae650dSJack F Vogel I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK | 2040*61ae650dSJack F Vogel I40E_PFINT_ICR0_ENA_VFLR_MASK | 2041*61ae650dSJack F Vogel I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK; 2042*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ICR0_ENA, reg); 2043*61ae650dSJack F Vogel 2044*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_LNKLST0, 0x7FF); 2045*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ITR0(IXL_RX_ITR), 0x003E); 2046*61ae650dSJack F Vogel 2047*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_DYN_CTL0, 2048*61ae650dSJack F Vogel I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK | 2049*61ae650dSJack F Vogel I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK); 2050*61ae650dSJack F Vogel 2051*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_STAT_CTL0, 0); 2052*61ae650dSJack F Vogel 2053*61ae650dSJack F Vogel /* Next configure the queues */ 2054*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++, vector++) { 2055*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_DYN_CTLN(i), i); 2056*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_LNKLSTN(i), i); 2057*61ae650dSJack F Vogel 2058*61ae650dSJack F Vogel reg = I40E_QINT_RQCTL_CAUSE_ENA_MASK | 2059*61ae650dSJack F Vogel (IXL_RX_ITR << I40E_QINT_RQCTL_ITR_INDX_SHIFT) | 2060*61ae650dSJack F Vogel (vector << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) | 2061*61ae650dSJack F Vogel (i << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) | 2062*61ae650dSJack F Vogel (I40E_QUEUE_TYPE_TX << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT); 2063*61ae650dSJack F Vogel wr32(hw, I40E_QINT_RQCTL(i), reg); 2064*61ae650dSJack F Vogel 2065*61ae650dSJack F Vogel reg = I40E_QINT_TQCTL_CAUSE_ENA_MASK | 2066*61ae650dSJack F Vogel (IXL_TX_ITR << I40E_QINT_TQCTL_ITR_INDX_SHIFT) | 2067*61ae650dSJack F Vogel (vector << I40E_QINT_TQCTL_MSIX_INDX_SHIFT) | 2068*61ae650dSJack F Vogel ((i+1) << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT) | 2069*61ae650dSJack F Vogel (I40E_QUEUE_TYPE_RX << I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT); 2070*61ae650dSJack F Vogel if (i == (vsi->num_queues - 1)) 2071*61ae650dSJack F Vogel reg |= (IXL_QUEUE_EOL 2072*61ae650dSJack F Vogel << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT); 2073*61ae650dSJack F Vogel wr32(hw, I40E_QINT_TQCTL(i), reg); 2074*61ae650dSJack F Vogel } 2075*61ae650dSJack F Vogel } 2076*61ae650dSJack F Vogel 2077*61ae650dSJack F Vogel /* 2078*61ae650dSJack F Vogel * Configure for MSI single vector operation 2079*61ae650dSJack F Vogel */ 2080*61ae650dSJack F Vogel static void 2081*61ae650dSJack F Vogel ixl_configure_legacy(struct ixl_pf *pf) 2082*61ae650dSJack F Vogel { 2083*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 2084*61ae650dSJack F Vogel u32 reg; 2085*61ae650dSJack F Vogel 2086*61ae650dSJack F Vogel 2087*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ITR0(0), 0); 2088*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ITR0(1), 0); 2089*61ae650dSJack F Vogel 2090*61ae650dSJack F Vogel 2091*61ae650dSJack F Vogel /* Setup "other" causes */ 2092*61ae650dSJack F Vogel reg = I40E_PFINT_ICR0_ENA_ECC_ERR_MASK 2093*61ae650dSJack F Vogel | I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK 2094*61ae650dSJack F Vogel | I40E_PFINT_ICR0_ENA_GRST_MASK 2095*61ae650dSJack F Vogel | I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK 2096*61ae650dSJack F Vogel | I40E_PFINT_ICR0_ENA_GPIO_MASK 2097*61ae650dSJack F Vogel | I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK 2098*61ae650dSJack F Vogel | I40E_PFINT_ICR0_ENA_HMC_ERR_MASK 2099*61ae650dSJack F Vogel | I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK 2100*61ae650dSJack F Vogel | I40E_PFINT_ICR0_ENA_VFLR_MASK 2101*61ae650dSJack F Vogel | I40E_PFINT_ICR0_ENA_ADMINQ_MASK 2102*61ae650dSJack F Vogel ; 2103*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ICR0_ENA, reg); 2104*61ae650dSJack F Vogel 2105*61ae650dSJack F Vogel /* SW_ITR_IDX = 0, but don't change INTENA */ 2106*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_DYN_CTL0, 2107*61ae650dSJack F Vogel I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK | 2108*61ae650dSJack F Vogel I40E_PFINT_DYN_CTLN_INTENA_MSK_MASK); 2109*61ae650dSJack F Vogel /* SW_ITR_IDX = 0, OTHER_ITR_IDX = 0 */ 2110*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_STAT_CTL0, 0); 2111*61ae650dSJack F Vogel 2112*61ae650dSJack F Vogel /* FIRSTQ_INDX = 0, FIRSTQ_TYPE = 0 (rx) */ 2113*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_LNKLST0, 0); 2114*61ae650dSJack F Vogel 2115*61ae650dSJack F Vogel /* Associate the queue pair to the vector and enable the q int */ 2116*61ae650dSJack F Vogel reg = I40E_QINT_RQCTL_CAUSE_ENA_MASK 2117*61ae650dSJack F Vogel | (IXL_RX_ITR << I40E_QINT_RQCTL_ITR_INDX_SHIFT) 2118*61ae650dSJack F Vogel | (I40E_QUEUE_TYPE_TX << I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT); 2119*61ae650dSJack F Vogel wr32(hw, I40E_QINT_RQCTL(0), reg); 2120*61ae650dSJack F Vogel 2121*61ae650dSJack F Vogel reg = I40E_QINT_TQCTL_CAUSE_ENA_MASK 2122*61ae650dSJack F Vogel | (IXL_TX_ITR << I40E_QINT_TQCTL_ITR_INDX_SHIFT) 2123*61ae650dSJack F Vogel | (IXL_QUEUE_EOL << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT); 2124*61ae650dSJack F Vogel wr32(hw, I40E_QINT_TQCTL(0), reg); 2125*61ae650dSJack F Vogel 2126*61ae650dSJack F Vogel /* Next enable the queue pair */ 2127*61ae650dSJack F Vogel reg = rd32(hw, I40E_QTX_ENA(0)); 2128*61ae650dSJack F Vogel reg |= I40E_QTX_ENA_QENA_REQ_MASK; 2129*61ae650dSJack F Vogel wr32(hw, I40E_QTX_ENA(0), reg); 2130*61ae650dSJack F Vogel 2131*61ae650dSJack F Vogel reg = rd32(hw, I40E_QRX_ENA(0)); 2132*61ae650dSJack F Vogel reg |= I40E_QRX_ENA_QENA_REQ_MASK; 2133*61ae650dSJack F Vogel wr32(hw, I40E_QRX_ENA(0), reg); 2134*61ae650dSJack F Vogel } 2135*61ae650dSJack F Vogel 2136*61ae650dSJack F Vogel 2137*61ae650dSJack F Vogel /* 2138*61ae650dSJack F Vogel * Set the Initial ITR state 2139*61ae650dSJack F Vogel */ 2140*61ae650dSJack F Vogel static void 2141*61ae650dSJack F Vogel ixl_configure_itr(struct ixl_pf *pf) 2142*61ae650dSJack F Vogel { 2143*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 2144*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 2145*61ae650dSJack F Vogel struct ixl_queue *que = vsi->queues; 2146*61ae650dSJack F Vogel 2147*61ae650dSJack F Vogel vsi->rx_itr_setting = ixl_rx_itr; 2148*61ae650dSJack F Vogel if (ixl_dynamic_rx_itr) 2149*61ae650dSJack F Vogel vsi->rx_itr_setting |= IXL_ITR_DYNAMIC; 2150*61ae650dSJack F Vogel vsi->tx_itr_setting = ixl_tx_itr; 2151*61ae650dSJack F Vogel if (ixl_dynamic_tx_itr) 2152*61ae650dSJack F Vogel vsi->tx_itr_setting |= IXL_ITR_DYNAMIC; 2153*61ae650dSJack F Vogel 2154*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++, que++) { 2155*61ae650dSJack F Vogel struct tx_ring *txr = &que->txr; 2156*61ae650dSJack F Vogel struct rx_ring *rxr = &que->rxr; 2157*61ae650dSJack F Vogel 2158*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ITRN(IXL_RX_ITR, i), 2159*61ae650dSJack F Vogel vsi->rx_itr_setting); 2160*61ae650dSJack F Vogel rxr->itr = vsi->rx_itr_setting; 2161*61ae650dSJack F Vogel rxr->latency = IXL_AVE_LATENCY; 2162*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ITRN(IXL_TX_ITR, i), 2163*61ae650dSJack F Vogel vsi->tx_itr_setting); 2164*61ae650dSJack F Vogel txr->itr = vsi->tx_itr_setting; 2165*61ae650dSJack F Vogel txr->latency = IXL_AVE_LATENCY; 2166*61ae650dSJack F Vogel } 2167*61ae650dSJack F Vogel } 2168*61ae650dSJack F Vogel 2169*61ae650dSJack F Vogel 2170*61ae650dSJack F Vogel static int 2171*61ae650dSJack F Vogel ixl_allocate_pci_resources(struct ixl_pf *pf) 2172*61ae650dSJack F Vogel { 2173*61ae650dSJack F Vogel int rid; 2174*61ae650dSJack F Vogel device_t dev = pf->dev; 2175*61ae650dSJack F Vogel 2176*61ae650dSJack F Vogel rid = PCIR_BAR(0); 2177*61ae650dSJack F Vogel pf->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 2178*61ae650dSJack F Vogel &rid, RF_ACTIVE); 2179*61ae650dSJack F Vogel 2180*61ae650dSJack F Vogel if (!(pf->pci_mem)) { 2181*61ae650dSJack F Vogel device_printf(dev,"Unable to allocate bus resource: memory\n"); 2182*61ae650dSJack F Vogel return (ENXIO); 2183*61ae650dSJack F Vogel } 2184*61ae650dSJack F Vogel 2185*61ae650dSJack F Vogel pf->osdep.mem_bus_space_tag = 2186*61ae650dSJack F Vogel rman_get_bustag(pf->pci_mem); 2187*61ae650dSJack F Vogel pf->osdep.mem_bus_space_handle = 2188*61ae650dSJack F Vogel rman_get_bushandle(pf->pci_mem); 2189*61ae650dSJack F Vogel pf->osdep.mem_bus_space_size = rman_get_size(pf->pci_mem); 2190*61ae650dSJack F Vogel pf->hw.hw_addr = (u8 *) &pf->osdep.mem_bus_space_handle; 2191*61ae650dSJack F Vogel 2192*61ae650dSJack F Vogel pf->hw.back = &pf->osdep; 2193*61ae650dSJack F Vogel 2194*61ae650dSJack F Vogel /* 2195*61ae650dSJack F Vogel ** Now setup MSI or MSI/X, should 2196*61ae650dSJack F Vogel ** return us the number of supported 2197*61ae650dSJack F Vogel ** vectors. (Will be 1 for MSI) 2198*61ae650dSJack F Vogel */ 2199*61ae650dSJack F Vogel pf->msix = ixl_init_msix(pf); 2200*61ae650dSJack F Vogel return (0); 2201*61ae650dSJack F Vogel } 2202*61ae650dSJack F Vogel 2203*61ae650dSJack F Vogel static void 2204*61ae650dSJack F Vogel ixl_free_pci_resources(struct ixl_pf * pf) 2205*61ae650dSJack F Vogel { 2206*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 2207*61ae650dSJack F Vogel struct ixl_queue *que = vsi->queues; 2208*61ae650dSJack F Vogel device_t dev = pf->dev; 2209*61ae650dSJack F Vogel int rid, memrid; 2210*61ae650dSJack F Vogel 2211*61ae650dSJack F Vogel memrid = PCIR_BAR(IXL_BAR); 2212*61ae650dSJack F Vogel 2213*61ae650dSJack F Vogel /* We may get here before stations are setup */ 2214*61ae650dSJack F Vogel if ((!ixl_enable_msix) || (que == NULL)) 2215*61ae650dSJack F Vogel goto early; 2216*61ae650dSJack F Vogel 2217*61ae650dSJack F Vogel /* 2218*61ae650dSJack F Vogel ** Release all msix VSI resources: 2219*61ae650dSJack F Vogel */ 2220*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++, que++) { 2221*61ae650dSJack F Vogel rid = que->msix + 1; 2222*61ae650dSJack F Vogel if (que->tag != NULL) { 2223*61ae650dSJack F Vogel bus_teardown_intr(dev, que->res, que->tag); 2224*61ae650dSJack F Vogel que->tag = NULL; 2225*61ae650dSJack F Vogel } 2226*61ae650dSJack F Vogel if (que->res != NULL) 2227*61ae650dSJack F Vogel bus_release_resource(dev, SYS_RES_IRQ, rid, que->res); 2228*61ae650dSJack F Vogel } 2229*61ae650dSJack F Vogel 2230*61ae650dSJack F Vogel early: 2231*61ae650dSJack F Vogel /* Clean the AdminQ interrupt last */ 2232*61ae650dSJack F Vogel if (pf->admvec) /* we are doing MSIX */ 2233*61ae650dSJack F Vogel rid = pf->admvec + 1; 2234*61ae650dSJack F Vogel else 2235*61ae650dSJack F Vogel (pf->msix != 0) ? (rid = 1):(rid = 0); 2236*61ae650dSJack F Vogel 2237*61ae650dSJack F Vogel if (pf->tag != NULL) { 2238*61ae650dSJack F Vogel bus_teardown_intr(dev, pf->res, pf->tag); 2239*61ae650dSJack F Vogel pf->tag = NULL; 2240*61ae650dSJack F Vogel } 2241*61ae650dSJack F Vogel if (pf->res != NULL) 2242*61ae650dSJack F Vogel bus_release_resource(dev, SYS_RES_IRQ, rid, pf->res); 2243*61ae650dSJack F Vogel 2244*61ae650dSJack F Vogel if (pf->msix) 2245*61ae650dSJack F Vogel pci_release_msi(dev); 2246*61ae650dSJack F Vogel 2247*61ae650dSJack F Vogel if (pf->msix_mem != NULL) 2248*61ae650dSJack F Vogel bus_release_resource(dev, SYS_RES_MEMORY, 2249*61ae650dSJack F Vogel memrid, pf->msix_mem); 2250*61ae650dSJack F Vogel 2251*61ae650dSJack F Vogel if (pf->pci_mem != NULL) 2252*61ae650dSJack F Vogel bus_release_resource(dev, SYS_RES_MEMORY, 2253*61ae650dSJack F Vogel PCIR_BAR(0), pf->pci_mem); 2254*61ae650dSJack F Vogel 2255*61ae650dSJack F Vogel return; 2256*61ae650dSJack F Vogel } 2257*61ae650dSJack F Vogel 2258*61ae650dSJack F Vogel 2259*61ae650dSJack F Vogel /********************************************************************* 2260*61ae650dSJack F Vogel * 2261*61ae650dSJack F Vogel * Setup networking device structure and register an interface. 2262*61ae650dSJack F Vogel * 2263*61ae650dSJack F Vogel **********************************************************************/ 2264*61ae650dSJack F Vogel static int 2265*61ae650dSJack F Vogel ixl_setup_interface(device_t dev, struct ixl_vsi *vsi) 2266*61ae650dSJack F Vogel { 2267*61ae650dSJack F Vogel struct ifnet *ifp; 2268*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 2269*61ae650dSJack F Vogel struct ixl_queue *que = vsi->queues; 2270*61ae650dSJack F Vogel struct i40e_aq_get_phy_abilities_resp abilities_resp; 2271*61ae650dSJack F Vogel enum i40e_status_code aq_error = 0; 2272*61ae650dSJack F Vogel 2273*61ae650dSJack F Vogel INIT_DEBUGOUT("ixl_setup_interface: begin"); 2274*61ae650dSJack F Vogel 2275*61ae650dSJack F Vogel ifp = vsi->ifp = if_alloc(IFT_ETHER); 2276*61ae650dSJack F Vogel if (ifp == NULL) { 2277*61ae650dSJack F Vogel device_printf(dev, "can not allocate ifnet structure\n"); 2278*61ae650dSJack F Vogel return (-1); 2279*61ae650dSJack F Vogel } 2280*61ae650dSJack F Vogel if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 2281*61ae650dSJack F Vogel ifp->if_mtu = ETHERMTU; 2282*61ae650dSJack F Vogel ifp->if_baudrate = 4000000000; // ?? 2283*61ae650dSJack F Vogel ifp->if_init = ixl_init; 2284*61ae650dSJack F Vogel ifp->if_softc = vsi; 2285*61ae650dSJack F Vogel ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 2286*61ae650dSJack F Vogel ifp->if_ioctl = ixl_ioctl; 2287*61ae650dSJack F Vogel 2288*61ae650dSJack F Vogel ifp->if_transmit = ixl_mq_start; 2289*61ae650dSJack F Vogel 2290*61ae650dSJack F Vogel ifp->if_qflush = ixl_qflush; 2291*61ae650dSJack F Vogel 2292*61ae650dSJack F Vogel ifp->if_snd.ifq_maxlen = que->num_desc - 2; 2293*61ae650dSJack F Vogel 2294*61ae650dSJack F Vogel ether_ifattach(ifp, hw->mac.addr); 2295*61ae650dSJack F Vogel 2296*61ae650dSJack F Vogel vsi->max_frame_size = 2297*61ae650dSJack F Vogel ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN 2298*61ae650dSJack F Vogel + ETHER_VLAN_ENCAP_LEN; 2299*61ae650dSJack F Vogel 2300*61ae650dSJack F Vogel /* 2301*61ae650dSJack F Vogel * Tell the upper layer(s) we support long frames. 2302*61ae650dSJack F Vogel */ 2303*61ae650dSJack F Vogel ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 2304*61ae650dSJack F Vogel 2305*61ae650dSJack F Vogel ifp->if_capabilities |= IFCAP_HWCSUM; 2306*61ae650dSJack F Vogel ifp->if_capabilities |= IFCAP_HWCSUM_IPV6; 2307*61ae650dSJack F Vogel ifp->if_capabilities |= IFCAP_TSO; 2308*61ae650dSJack F Vogel ifp->if_capabilities |= IFCAP_JUMBO_MTU; 2309*61ae650dSJack F Vogel ifp->if_capabilities |= IFCAP_LRO; 2310*61ae650dSJack F Vogel 2311*61ae650dSJack F Vogel /* VLAN capabilties */ 2312*61ae650dSJack F Vogel ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING 2313*61ae650dSJack F Vogel | IFCAP_VLAN_HWTSO 2314*61ae650dSJack F Vogel | IFCAP_VLAN_MTU 2315*61ae650dSJack F Vogel | IFCAP_VLAN_HWCSUM; 2316*61ae650dSJack F Vogel ifp->if_capenable = ifp->if_capabilities; 2317*61ae650dSJack F Vogel 2318*61ae650dSJack F Vogel /* 2319*61ae650dSJack F Vogel ** Don't turn this on by default, if vlans are 2320*61ae650dSJack F Vogel ** created on another pseudo device (eg. lagg) 2321*61ae650dSJack F Vogel ** then vlan events are not passed thru, breaking 2322*61ae650dSJack F Vogel ** operation, but with HW FILTER off it works. If 2323*61ae650dSJack F Vogel ** using vlans directly on the ixl driver you can 2324*61ae650dSJack F Vogel ** enable this and get full hardware tag filtering. 2325*61ae650dSJack F Vogel */ 2326*61ae650dSJack F Vogel ifp->if_capabilities |= IFCAP_VLAN_HWFILTER; 2327*61ae650dSJack F Vogel 2328*61ae650dSJack F Vogel /* 2329*61ae650dSJack F Vogel * Specify the media types supported by this adapter and register 2330*61ae650dSJack F Vogel * callbacks to update media and link information 2331*61ae650dSJack F Vogel */ 2332*61ae650dSJack F Vogel ifmedia_init(&vsi->media, IFM_IMASK, ixl_media_change, 2333*61ae650dSJack F Vogel ixl_media_status); 2334*61ae650dSJack F Vogel 2335*61ae650dSJack F Vogel aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, TRUE, &abilities_resp, NULL); 2336*61ae650dSJack F Vogel if (aq_error) { 2337*61ae650dSJack F Vogel printf("Error getting supported media types, AQ error %d\n", aq_error); 2338*61ae650dSJack F Vogel return (EPERM); 2339*61ae650dSJack F Vogel } 2340*61ae650dSJack F Vogel 2341*61ae650dSJack F Vogel /* Display supported media types */ 2342*61ae650dSJack F Vogel if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_100BASE_TX)) 2343*61ae650dSJack F Vogel ifmedia_add(&vsi->media, IFM_ETHER | IFM_100_TX, 0, NULL); 2344*61ae650dSJack F Vogel 2345*61ae650dSJack F Vogel if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_1000BASE_T)) 2346*61ae650dSJack F Vogel ifmedia_add(&vsi->media, IFM_ETHER | IFM_1000_T, 0, NULL); 2347*61ae650dSJack F Vogel 2348*61ae650dSJack F Vogel if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_CR1_CU) || 2349*61ae650dSJack F Vogel abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_SFPP_CU)) 2350*61ae650dSJack F Vogel ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL); 2351*61ae650dSJack F Vogel if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_SR)) 2352*61ae650dSJack F Vogel ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_SR, 0, NULL); 2353*61ae650dSJack F Vogel if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_LR)) 2354*61ae650dSJack F Vogel ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_LR, 0, NULL); 2355*61ae650dSJack F Vogel if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_T)) 2356*61ae650dSJack F Vogel ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_T, 0, NULL); 2357*61ae650dSJack F Vogel 2358*61ae650dSJack F Vogel if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4_CU) || 2359*61ae650dSJack F Vogel abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4)) 2360*61ae650dSJack F Vogel ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_CR4, 0, NULL); 2361*61ae650dSJack F Vogel if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_SR4)) 2362*61ae650dSJack F Vogel ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_SR4, 0, NULL); 2363*61ae650dSJack F Vogel if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_LR4)) 2364*61ae650dSJack F Vogel ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_LR4, 0, NULL); 2365*61ae650dSJack F Vogel 2366*61ae650dSJack F Vogel /* Use autoselect media by default */ 2367*61ae650dSJack F Vogel ifmedia_add(&vsi->media, IFM_ETHER | IFM_AUTO, 0, NULL); 2368*61ae650dSJack F Vogel ifmedia_set(&vsi->media, IFM_ETHER | IFM_AUTO); 2369*61ae650dSJack F Vogel 2370*61ae650dSJack F Vogel return (0); 2371*61ae650dSJack F Vogel } 2372*61ae650dSJack F Vogel 2373*61ae650dSJack F Vogel static bool 2374*61ae650dSJack F Vogel ixl_config_link(struct i40e_hw *hw) 2375*61ae650dSJack F Vogel { 2376*61ae650dSJack F Vogel bool check; 2377*61ae650dSJack F Vogel 2378*61ae650dSJack F Vogel i40e_aq_get_link_info(hw, TRUE, NULL, NULL); 2379*61ae650dSJack F Vogel check = i40e_get_link_status(hw); 2380*61ae650dSJack F Vogel #ifdef IXL_DEBUG 2381*61ae650dSJack F Vogel printf("Link is %s\n", check ? "up":"down"); 2382*61ae650dSJack F Vogel #endif 2383*61ae650dSJack F Vogel return (check); 2384*61ae650dSJack F Vogel } 2385*61ae650dSJack F Vogel 2386*61ae650dSJack F Vogel /********************************************************************* 2387*61ae650dSJack F Vogel * 2388*61ae650dSJack F Vogel * Initialize this VSI 2389*61ae650dSJack F Vogel * 2390*61ae650dSJack F Vogel **********************************************************************/ 2391*61ae650dSJack F Vogel static int 2392*61ae650dSJack F Vogel ixl_setup_vsi(struct ixl_vsi *vsi) 2393*61ae650dSJack F Vogel { 2394*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 2395*61ae650dSJack F Vogel device_t dev = vsi->dev; 2396*61ae650dSJack F Vogel struct i40e_aqc_get_switch_config_resp *sw_config; 2397*61ae650dSJack F Vogel struct i40e_vsi_context ctxt; 2398*61ae650dSJack F Vogel u8 aq_buf[I40E_AQ_LARGE_BUF]; 2399*61ae650dSJack F Vogel int ret = I40E_SUCCESS; 2400*61ae650dSJack F Vogel u16 next = 0; 2401*61ae650dSJack F Vogel 2402*61ae650dSJack F Vogel sw_config = (struct i40e_aqc_get_switch_config_resp *)aq_buf; 2403*61ae650dSJack F Vogel ret = i40e_aq_get_switch_config(hw, sw_config, 2404*61ae650dSJack F Vogel sizeof(aq_buf), &next, NULL); 2405*61ae650dSJack F Vogel if (ret) { 2406*61ae650dSJack F Vogel device_printf(dev,"aq_get_switch_config failed!!\n"); 2407*61ae650dSJack F Vogel return (ret); 2408*61ae650dSJack F Vogel } 2409*61ae650dSJack F Vogel #ifdef IXL_DEBUG 2410*61ae650dSJack F Vogel printf("Switch config: header reported: %d in structure, %d total\n", 2411*61ae650dSJack F Vogel sw_config->header.num_reported, sw_config->header.num_total); 2412*61ae650dSJack F Vogel printf("type=%d seid=%d uplink=%d downlink=%d\n", 2413*61ae650dSJack F Vogel sw_config->element[0].element_type, 2414*61ae650dSJack F Vogel sw_config->element[0].seid, 2415*61ae650dSJack F Vogel sw_config->element[0].uplink_seid, 2416*61ae650dSJack F Vogel sw_config->element[0].downlink_seid); 2417*61ae650dSJack F Vogel #endif 2418*61ae650dSJack F Vogel /* Save off this important value */ 2419*61ae650dSJack F Vogel vsi->seid = sw_config->element[0].seid; 2420*61ae650dSJack F Vogel 2421*61ae650dSJack F Vogel memset(&ctxt, 0, sizeof(ctxt)); 2422*61ae650dSJack F Vogel ctxt.seid = vsi->seid; 2423*61ae650dSJack F Vogel ctxt.pf_num = hw->pf_id; 2424*61ae650dSJack F Vogel ret = i40e_aq_get_vsi_params(hw, &ctxt, NULL); 2425*61ae650dSJack F Vogel if (ret) { 2426*61ae650dSJack F Vogel device_printf(dev,"get vsi params failed %x!!\n", ret); 2427*61ae650dSJack F Vogel return (ret); 2428*61ae650dSJack F Vogel } 2429*61ae650dSJack F Vogel #ifdef IXL_DEBUG 2430*61ae650dSJack F Vogel printf("get_vsi_params: seid: %d, uplinkseid: %d, vsi_number: %d, " 2431*61ae650dSJack F Vogel "vsis_allocated: %d, vsis_unallocated: %d, flags: 0x%x, " 2432*61ae650dSJack F Vogel "pfnum: %d, vfnum: %d, stat idx: %d, enabled: %d\n", ctxt.seid, 2433*61ae650dSJack F Vogel ctxt.uplink_seid, ctxt.vsi_number, 2434*61ae650dSJack F Vogel ctxt.vsis_allocated, ctxt.vsis_unallocated, 2435*61ae650dSJack F Vogel ctxt.flags, ctxt.pf_num, ctxt.vf_num, 2436*61ae650dSJack F Vogel ctxt.info.stat_counter_idx, ctxt.info.up_enable_bits); 2437*61ae650dSJack F Vogel #endif 2438*61ae650dSJack F Vogel /* 2439*61ae650dSJack F Vogel ** Set the queue and traffic class bits 2440*61ae650dSJack F Vogel ** - when multiple traffic classes are supported 2441*61ae650dSJack F Vogel ** this will need to be more robust. 2442*61ae650dSJack F Vogel */ 2443*61ae650dSJack F Vogel ctxt.info.valid_sections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID; 2444*61ae650dSJack F Vogel ctxt.info.mapping_flags |= I40E_AQ_VSI_QUE_MAP_CONTIG; 2445*61ae650dSJack F Vogel ctxt.info.queue_mapping[0] = 0; 2446*61ae650dSJack F Vogel ctxt.info.tc_mapping[0] = 0x0800; 2447*61ae650dSJack F Vogel 2448*61ae650dSJack F Vogel /* Set VLAN receive stripping mode */ 2449*61ae650dSJack F Vogel ctxt.info.valid_sections |= I40E_AQ_VSI_PROP_VLAN_VALID; 2450*61ae650dSJack F Vogel ctxt.info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_ALL; 2451*61ae650dSJack F Vogel if (vsi->ifp->if_capenable & IFCAP_VLAN_HWTAGGING) 2452*61ae650dSJack F Vogel ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH; 2453*61ae650dSJack F Vogel else 2454*61ae650dSJack F Vogel ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_EMOD_NOTHING; 2455*61ae650dSJack F Vogel 2456*61ae650dSJack F Vogel /* Keep copy of VSI info in VSI for statistic counters */ 2457*61ae650dSJack F Vogel memcpy(&vsi->info, &ctxt.info, sizeof(ctxt.info)); 2458*61ae650dSJack F Vogel 2459*61ae650dSJack F Vogel /* Reset VSI statistics */ 2460*61ae650dSJack F Vogel ixl_vsi_reset_stats(vsi); 2461*61ae650dSJack F Vogel vsi->hw_filters_add = 0; 2462*61ae650dSJack F Vogel vsi->hw_filters_del = 0; 2463*61ae650dSJack F Vogel 2464*61ae650dSJack F Vogel ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL); 2465*61ae650dSJack F Vogel if (ret) 2466*61ae650dSJack F Vogel device_printf(dev,"update vsi params failed %x!!\n", 2467*61ae650dSJack F Vogel hw->aq.asq_last_status); 2468*61ae650dSJack F Vogel return (ret); 2469*61ae650dSJack F Vogel } 2470*61ae650dSJack F Vogel 2471*61ae650dSJack F Vogel 2472*61ae650dSJack F Vogel /********************************************************************* 2473*61ae650dSJack F Vogel * 2474*61ae650dSJack F Vogel * Initialize the VSI: this handles contexts, which means things 2475*61ae650dSJack F Vogel * like the number of descriptors, buffer size, 2476*61ae650dSJack F Vogel * plus we init the rings thru this function. 2477*61ae650dSJack F Vogel * 2478*61ae650dSJack F Vogel **********************************************************************/ 2479*61ae650dSJack F Vogel static int 2480*61ae650dSJack F Vogel ixl_initialize_vsi(struct ixl_vsi *vsi) 2481*61ae650dSJack F Vogel { 2482*61ae650dSJack F Vogel struct ixl_queue *que = vsi->queues; 2483*61ae650dSJack F Vogel device_t dev = vsi->dev; 2484*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 2485*61ae650dSJack F Vogel int err = 0; 2486*61ae650dSJack F Vogel 2487*61ae650dSJack F Vogel 2488*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++, que++) { 2489*61ae650dSJack F Vogel struct tx_ring *txr = &que->txr; 2490*61ae650dSJack F Vogel struct rx_ring *rxr = &que->rxr; 2491*61ae650dSJack F Vogel struct i40e_hmc_obj_txq tctx; 2492*61ae650dSJack F Vogel struct i40e_hmc_obj_rxq rctx; 2493*61ae650dSJack F Vogel u32 txctl; 2494*61ae650dSJack F Vogel u16 size; 2495*61ae650dSJack F Vogel 2496*61ae650dSJack F Vogel 2497*61ae650dSJack F Vogel /* Setup the HMC TX Context */ 2498*61ae650dSJack F Vogel size = que->num_desc * sizeof(struct i40e_tx_desc); 2499*61ae650dSJack F Vogel memset(&tctx, 0, sizeof(struct i40e_hmc_obj_txq)); 2500*61ae650dSJack F Vogel tctx.new_context = 1; 2501*61ae650dSJack F Vogel tctx.base = (txr->dma.pa/128); 2502*61ae650dSJack F Vogel tctx.qlen = que->num_desc; 2503*61ae650dSJack F Vogel tctx.fc_ena = 0; 2504*61ae650dSJack F Vogel tctx.rdylist = vsi->info.qs_handle[0]; /* index is TC */ 2505*61ae650dSJack F Vogel /* Enable HEAD writeback */ 2506*61ae650dSJack F Vogel tctx.head_wb_ena = 1; 2507*61ae650dSJack F Vogel tctx.head_wb_addr = txr->dma.pa + 2508*61ae650dSJack F Vogel (que->num_desc * sizeof(struct i40e_tx_desc)); 2509*61ae650dSJack F Vogel tctx.rdylist_act = 0; 2510*61ae650dSJack F Vogel err = i40e_clear_lan_tx_queue_context(hw, i); 2511*61ae650dSJack F Vogel if (err) { 2512*61ae650dSJack F Vogel device_printf(dev, "Unable to clear TX context\n"); 2513*61ae650dSJack F Vogel break; 2514*61ae650dSJack F Vogel } 2515*61ae650dSJack F Vogel err = i40e_set_lan_tx_queue_context(hw, i, &tctx); 2516*61ae650dSJack F Vogel if (err) { 2517*61ae650dSJack F Vogel device_printf(dev, "Unable to set TX context\n"); 2518*61ae650dSJack F Vogel break; 2519*61ae650dSJack F Vogel } 2520*61ae650dSJack F Vogel /* Associate the ring with this PF */ 2521*61ae650dSJack F Vogel txctl = I40E_QTX_CTL_PF_QUEUE; 2522*61ae650dSJack F Vogel txctl |= ((hw->pf_id << I40E_QTX_CTL_PF_INDX_SHIFT) & 2523*61ae650dSJack F Vogel I40E_QTX_CTL_PF_INDX_MASK); 2524*61ae650dSJack F Vogel wr32(hw, I40E_QTX_CTL(i), txctl); 2525*61ae650dSJack F Vogel ixl_flush(hw); 2526*61ae650dSJack F Vogel 2527*61ae650dSJack F Vogel /* Do ring (re)init */ 2528*61ae650dSJack F Vogel ixl_init_tx_ring(que); 2529*61ae650dSJack F Vogel 2530*61ae650dSJack F Vogel /* Next setup the HMC RX Context */ 2531*61ae650dSJack F Vogel if (vsi->max_frame_size <= 2048) 2532*61ae650dSJack F Vogel rxr->mbuf_sz = MCLBYTES; 2533*61ae650dSJack F Vogel else 2534*61ae650dSJack F Vogel rxr->mbuf_sz = MJUMPAGESIZE; 2535*61ae650dSJack F Vogel 2536*61ae650dSJack F Vogel u16 max_rxmax = rxr->mbuf_sz * hw->func_caps.rx_buf_chain_len; 2537*61ae650dSJack F Vogel 2538*61ae650dSJack F Vogel /* Set up an RX context for the HMC */ 2539*61ae650dSJack F Vogel memset(&rctx, 0, sizeof(struct i40e_hmc_obj_rxq)); 2540*61ae650dSJack F Vogel rctx.dbuff = rxr->mbuf_sz >> I40E_RXQ_CTX_DBUFF_SHIFT; 2541*61ae650dSJack F Vogel /* ignore header split for now */ 2542*61ae650dSJack F Vogel rctx.hbuff = 0 >> I40E_RXQ_CTX_HBUFF_SHIFT; 2543*61ae650dSJack F Vogel rctx.rxmax = (vsi->max_frame_size < max_rxmax) ? 2544*61ae650dSJack F Vogel vsi->max_frame_size : max_rxmax; 2545*61ae650dSJack F Vogel rctx.dtype = 0; 2546*61ae650dSJack F Vogel rctx.dsize = 1; /* do 32byte descriptors */ 2547*61ae650dSJack F Vogel rctx.hsplit_0 = 0; /* no HDR split initially */ 2548*61ae650dSJack F Vogel rctx.base = (rxr->dma.pa/128); 2549*61ae650dSJack F Vogel rctx.qlen = que->num_desc; 2550*61ae650dSJack F Vogel rctx.tphrdesc_ena = 1; 2551*61ae650dSJack F Vogel rctx.tphwdesc_ena = 1; 2552*61ae650dSJack F Vogel rctx.tphdata_ena = 0; 2553*61ae650dSJack F Vogel rctx.tphhead_ena = 0; 2554*61ae650dSJack F Vogel rctx.lrxqthresh = 2; 2555*61ae650dSJack F Vogel #ifdef DEV_NETMAP 2556*61ae650dSJack F Vogel /* "CRC strip in netmap is conditional" */ 2557*61ae650dSJack F Vogel if (vsi->ifp->if_capenable & IFCAP_NETMAP && !ixl_crcstrip) 2558*61ae650dSJack F Vogel rctx.crcstrip = 0; 2559*61ae650dSJack F Vogel else 2560*61ae650dSJack F Vogel #endif /* DEV_NETMAP */ 2561*61ae650dSJack F Vogel rctx.crcstrip = 1; 2562*61ae650dSJack F Vogel rctx.l2tsel = 1; 2563*61ae650dSJack F Vogel rctx.showiv = 1; 2564*61ae650dSJack F Vogel rctx.fc_ena = 0; 2565*61ae650dSJack F Vogel rctx.prefena = 1; 2566*61ae650dSJack F Vogel 2567*61ae650dSJack F Vogel err = i40e_clear_lan_rx_queue_context(hw, i); 2568*61ae650dSJack F Vogel if (err) { 2569*61ae650dSJack F Vogel device_printf(dev, 2570*61ae650dSJack F Vogel "Unable to clear RX context %d\n", i); 2571*61ae650dSJack F Vogel break; 2572*61ae650dSJack F Vogel } 2573*61ae650dSJack F Vogel err = i40e_set_lan_rx_queue_context(hw, i, &rctx); 2574*61ae650dSJack F Vogel if (err) { 2575*61ae650dSJack F Vogel device_printf(dev, "Unable to set RX context %d\n", i); 2576*61ae650dSJack F Vogel break; 2577*61ae650dSJack F Vogel } 2578*61ae650dSJack F Vogel err = ixl_init_rx_ring(que); 2579*61ae650dSJack F Vogel if (err) { 2580*61ae650dSJack F Vogel device_printf(dev, "Fail in init_rx_ring %d\n", i); 2581*61ae650dSJack F Vogel break; 2582*61ae650dSJack F Vogel } 2583*61ae650dSJack F Vogel wr32(vsi->hw, I40E_QRX_TAIL(que->me), 0); 2584*61ae650dSJack F Vogel #ifdef DEV_NETMAP 2585*61ae650dSJack F Vogel /* TODO appropriately comment 2586*61ae650dSJack F Vogel * Code based on netmap code in ixgbe_init_locked() 2587*61ae650dSJack F Vogel * Messes with what the software sets as queue 2588*61ae650dSJack F Vogel * descriptor tail in hardware. 2589*61ae650dSJack F Vogel */ 2590*61ae650dSJack F Vogel if (vsi->ifp->if_capenable & IFCAP_NETMAP) 2591*61ae650dSJack F Vogel { 2592*61ae650dSJack F Vogel struct netmap_adapter *na = NA(vsi->ifp); 2593*61ae650dSJack F Vogel struct netmap_kring *kring = &na->rx_rings[que->me]; 2594*61ae650dSJack F Vogel int t = na->num_rx_desc - 1 - kring->nr_hwavail; 2595*61ae650dSJack F Vogel 2596*61ae650dSJack F Vogel wr32(vsi->hw, I40E_QRX_TAIL(que->me), t); 2597*61ae650dSJack F Vogel } else 2598*61ae650dSJack F Vogel #endif /* DEV_NETMAP */ 2599*61ae650dSJack F Vogel wr32(vsi->hw, I40E_QRX_TAIL(que->me), que->num_desc - 1); 2600*61ae650dSJack F Vogel } 2601*61ae650dSJack F Vogel return (err); 2602*61ae650dSJack F Vogel } 2603*61ae650dSJack F Vogel 2604*61ae650dSJack F Vogel 2605*61ae650dSJack F Vogel /********************************************************************* 2606*61ae650dSJack F Vogel * 2607*61ae650dSJack F Vogel * Free all VSI structs. 2608*61ae650dSJack F Vogel * 2609*61ae650dSJack F Vogel **********************************************************************/ 2610*61ae650dSJack F Vogel void 2611*61ae650dSJack F Vogel ixl_free_vsi(struct ixl_vsi *vsi) 2612*61ae650dSJack F Vogel { 2613*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)vsi->back; 2614*61ae650dSJack F Vogel struct ixl_queue *que = vsi->queues; 2615*61ae650dSJack F Vogel struct ixl_mac_filter *f; 2616*61ae650dSJack F Vogel 2617*61ae650dSJack F Vogel /* Free station queues */ 2618*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++, que++) { 2619*61ae650dSJack F Vogel struct tx_ring *txr = &que->txr; 2620*61ae650dSJack F Vogel struct rx_ring *rxr = &que->rxr; 2621*61ae650dSJack F Vogel 2622*61ae650dSJack F Vogel if (!mtx_initialized(&txr->mtx)) /* uninitialized */ 2623*61ae650dSJack F Vogel continue; 2624*61ae650dSJack F Vogel IXL_TX_LOCK(txr); 2625*61ae650dSJack F Vogel ixl_free_que_tx(que); 2626*61ae650dSJack F Vogel if (txr->base) 2627*61ae650dSJack F Vogel i40e_free_dma(&pf->hw, &txr->dma); 2628*61ae650dSJack F Vogel IXL_TX_UNLOCK(txr); 2629*61ae650dSJack F Vogel IXL_TX_LOCK_DESTROY(txr); 2630*61ae650dSJack F Vogel 2631*61ae650dSJack F Vogel if (!mtx_initialized(&rxr->mtx)) /* uninitialized */ 2632*61ae650dSJack F Vogel continue; 2633*61ae650dSJack F Vogel IXL_RX_LOCK(rxr); 2634*61ae650dSJack F Vogel ixl_free_que_rx(que); 2635*61ae650dSJack F Vogel if (rxr->base) 2636*61ae650dSJack F Vogel i40e_free_dma(&pf->hw, &rxr->dma); 2637*61ae650dSJack F Vogel IXL_RX_UNLOCK(rxr); 2638*61ae650dSJack F Vogel IXL_RX_LOCK_DESTROY(rxr); 2639*61ae650dSJack F Vogel 2640*61ae650dSJack F Vogel } 2641*61ae650dSJack F Vogel free(vsi->queues, M_DEVBUF); 2642*61ae650dSJack F Vogel 2643*61ae650dSJack F Vogel /* Free VSI filter list */ 2644*61ae650dSJack F Vogel while (!SLIST_EMPTY(&vsi->ftl)) { 2645*61ae650dSJack F Vogel f = SLIST_FIRST(&vsi->ftl); 2646*61ae650dSJack F Vogel SLIST_REMOVE_HEAD(&vsi->ftl, next); 2647*61ae650dSJack F Vogel free(f, M_DEVBUF); 2648*61ae650dSJack F Vogel } 2649*61ae650dSJack F Vogel } 2650*61ae650dSJack F Vogel 2651*61ae650dSJack F Vogel 2652*61ae650dSJack F Vogel /********************************************************************* 2653*61ae650dSJack F Vogel * 2654*61ae650dSJack F Vogel * Allocate memory for the VSI (virtual station interface) and their 2655*61ae650dSJack F Vogel * associated queues, rings and the descriptors associated with each, 2656*61ae650dSJack F Vogel * called only once at attach. 2657*61ae650dSJack F Vogel * 2658*61ae650dSJack F Vogel **********************************************************************/ 2659*61ae650dSJack F Vogel static int 2660*61ae650dSJack F Vogel ixl_setup_stations(struct ixl_pf *pf) 2661*61ae650dSJack F Vogel { 2662*61ae650dSJack F Vogel device_t dev = pf->dev; 2663*61ae650dSJack F Vogel struct ixl_vsi *vsi; 2664*61ae650dSJack F Vogel struct ixl_queue *que; 2665*61ae650dSJack F Vogel struct tx_ring *txr; 2666*61ae650dSJack F Vogel struct rx_ring *rxr; 2667*61ae650dSJack F Vogel int rsize, tsize; 2668*61ae650dSJack F Vogel int error = I40E_SUCCESS; 2669*61ae650dSJack F Vogel 2670*61ae650dSJack F Vogel vsi = &pf->vsi; 2671*61ae650dSJack F Vogel vsi->back = (void *)pf; 2672*61ae650dSJack F Vogel vsi->hw = &pf->hw; 2673*61ae650dSJack F Vogel vsi->id = 0; 2674*61ae650dSJack F Vogel vsi->num_vlans = 0; 2675*61ae650dSJack F Vogel 2676*61ae650dSJack F Vogel /* Get memory for the station queues */ 2677*61ae650dSJack F Vogel if (!(vsi->queues = 2678*61ae650dSJack F Vogel (struct ixl_queue *) malloc(sizeof(struct ixl_queue) * 2679*61ae650dSJack F Vogel vsi->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { 2680*61ae650dSJack F Vogel device_printf(dev, "Unable to allocate queue memory\n"); 2681*61ae650dSJack F Vogel error = ENOMEM; 2682*61ae650dSJack F Vogel goto early; 2683*61ae650dSJack F Vogel } 2684*61ae650dSJack F Vogel 2685*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++) { 2686*61ae650dSJack F Vogel que = &vsi->queues[i]; 2687*61ae650dSJack F Vogel que->num_desc = ixl_ringsz; 2688*61ae650dSJack F Vogel que->me = i; 2689*61ae650dSJack F Vogel que->vsi = vsi; 2690*61ae650dSJack F Vogel /* mark the queue as active */ 2691*61ae650dSJack F Vogel vsi->active_queues |= (u64)1 << que->me; 2692*61ae650dSJack F Vogel txr = &que->txr; 2693*61ae650dSJack F Vogel txr->que = que; 2694*61ae650dSJack F Vogel txr->tail = I40E_QTX_TAIL(que->me); 2695*61ae650dSJack F Vogel 2696*61ae650dSJack F Vogel /* Initialize the TX lock */ 2697*61ae650dSJack F Vogel snprintf(txr->mtx_name, sizeof(txr->mtx_name), "%s:tx(%d)", 2698*61ae650dSJack F Vogel device_get_nameunit(dev), que->me); 2699*61ae650dSJack F Vogel mtx_init(&txr->mtx, txr->mtx_name, NULL, MTX_DEF); 2700*61ae650dSJack F Vogel /* Create the TX descriptor ring */ 2701*61ae650dSJack F Vogel tsize = roundup2((que->num_desc * 2702*61ae650dSJack F Vogel sizeof(struct i40e_tx_desc)) + 2703*61ae650dSJack F Vogel sizeof(u32), DBA_ALIGN); 2704*61ae650dSJack F Vogel if (i40e_allocate_dma(&pf->hw, 2705*61ae650dSJack F Vogel &txr->dma, tsize, DBA_ALIGN)) { 2706*61ae650dSJack F Vogel device_printf(dev, 2707*61ae650dSJack F Vogel "Unable to allocate TX Descriptor memory\n"); 2708*61ae650dSJack F Vogel error = ENOMEM; 2709*61ae650dSJack F Vogel goto fail; 2710*61ae650dSJack F Vogel } 2711*61ae650dSJack F Vogel txr->base = (struct i40e_tx_desc *)txr->dma.va; 2712*61ae650dSJack F Vogel bzero((void *)txr->base, tsize); 2713*61ae650dSJack F Vogel /* Now allocate transmit soft structs for the ring */ 2714*61ae650dSJack F Vogel if (ixl_allocate_tx_data(que)) { 2715*61ae650dSJack F Vogel device_printf(dev, 2716*61ae650dSJack F Vogel "Critical Failure setting up TX structures\n"); 2717*61ae650dSJack F Vogel error = ENOMEM; 2718*61ae650dSJack F Vogel goto fail; 2719*61ae650dSJack F Vogel } 2720*61ae650dSJack F Vogel /* Allocate a buf ring */ 2721*61ae650dSJack F Vogel txr->br = buf_ring_alloc(4096, M_DEVBUF, 2722*61ae650dSJack F Vogel M_WAITOK, &txr->mtx); 2723*61ae650dSJack F Vogel if (txr->br == NULL) { 2724*61ae650dSJack F Vogel device_printf(dev, 2725*61ae650dSJack F Vogel "Critical Failure setting up TX buf ring\n"); 2726*61ae650dSJack F Vogel error = ENOMEM; 2727*61ae650dSJack F Vogel goto fail; 2728*61ae650dSJack F Vogel } 2729*61ae650dSJack F Vogel 2730*61ae650dSJack F Vogel /* 2731*61ae650dSJack F Vogel * Next the RX queues... 2732*61ae650dSJack F Vogel */ 2733*61ae650dSJack F Vogel rsize = roundup2(que->num_desc * 2734*61ae650dSJack F Vogel sizeof(union i40e_rx_desc), DBA_ALIGN); 2735*61ae650dSJack F Vogel rxr = &que->rxr; 2736*61ae650dSJack F Vogel rxr->que = que; 2737*61ae650dSJack F Vogel rxr->tail = I40E_QRX_TAIL(que->me); 2738*61ae650dSJack F Vogel 2739*61ae650dSJack F Vogel /* Initialize the RX side lock */ 2740*61ae650dSJack F Vogel snprintf(rxr->mtx_name, sizeof(rxr->mtx_name), "%s:rx(%d)", 2741*61ae650dSJack F Vogel device_get_nameunit(dev), que->me); 2742*61ae650dSJack F Vogel mtx_init(&rxr->mtx, rxr->mtx_name, NULL, MTX_DEF); 2743*61ae650dSJack F Vogel 2744*61ae650dSJack F Vogel if (i40e_allocate_dma(&pf->hw, 2745*61ae650dSJack F Vogel &rxr->dma, rsize, 4096)) { 2746*61ae650dSJack F Vogel device_printf(dev, 2747*61ae650dSJack F Vogel "Unable to allocate RX Descriptor memory\n"); 2748*61ae650dSJack F Vogel error = ENOMEM; 2749*61ae650dSJack F Vogel goto fail; 2750*61ae650dSJack F Vogel } 2751*61ae650dSJack F Vogel rxr->base = (union i40e_rx_desc *)rxr->dma.va; 2752*61ae650dSJack F Vogel bzero((void *)rxr->base, rsize); 2753*61ae650dSJack F Vogel 2754*61ae650dSJack F Vogel /* Allocate receive soft structs for the ring*/ 2755*61ae650dSJack F Vogel if (ixl_allocate_rx_data(que)) { 2756*61ae650dSJack F Vogel device_printf(dev, 2757*61ae650dSJack F Vogel "Critical Failure setting up receive structs\n"); 2758*61ae650dSJack F Vogel error = ENOMEM; 2759*61ae650dSJack F Vogel goto fail; 2760*61ae650dSJack F Vogel } 2761*61ae650dSJack F Vogel } 2762*61ae650dSJack F Vogel 2763*61ae650dSJack F Vogel return (0); 2764*61ae650dSJack F Vogel 2765*61ae650dSJack F Vogel fail: 2766*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++) { 2767*61ae650dSJack F Vogel que = &vsi->queues[i]; 2768*61ae650dSJack F Vogel rxr = &que->rxr; 2769*61ae650dSJack F Vogel txr = &que->txr; 2770*61ae650dSJack F Vogel if (rxr->base) 2771*61ae650dSJack F Vogel i40e_free_dma(&pf->hw, &rxr->dma); 2772*61ae650dSJack F Vogel if (txr->base) 2773*61ae650dSJack F Vogel i40e_free_dma(&pf->hw, &txr->dma); 2774*61ae650dSJack F Vogel } 2775*61ae650dSJack F Vogel 2776*61ae650dSJack F Vogel early: 2777*61ae650dSJack F Vogel return (error); 2778*61ae650dSJack F Vogel } 2779*61ae650dSJack F Vogel 2780*61ae650dSJack F Vogel /* 2781*61ae650dSJack F Vogel ** Provide a update to the queue RX 2782*61ae650dSJack F Vogel ** interrupt moderation value. 2783*61ae650dSJack F Vogel */ 2784*61ae650dSJack F Vogel static void 2785*61ae650dSJack F Vogel ixl_set_queue_rx_itr(struct ixl_queue *que) 2786*61ae650dSJack F Vogel { 2787*61ae650dSJack F Vogel struct ixl_vsi *vsi = que->vsi; 2788*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 2789*61ae650dSJack F Vogel struct rx_ring *rxr = &que->rxr; 2790*61ae650dSJack F Vogel u16 rx_itr; 2791*61ae650dSJack F Vogel u16 rx_latency = 0; 2792*61ae650dSJack F Vogel int rx_bytes; 2793*61ae650dSJack F Vogel 2794*61ae650dSJack F Vogel 2795*61ae650dSJack F Vogel /* Idle, do nothing */ 2796*61ae650dSJack F Vogel if (rxr->bytes == 0) 2797*61ae650dSJack F Vogel return; 2798*61ae650dSJack F Vogel 2799*61ae650dSJack F Vogel if (ixl_dynamic_rx_itr) { 2800*61ae650dSJack F Vogel rx_bytes = rxr->bytes/rxr->itr; 2801*61ae650dSJack F Vogel rx_itr = rxr->itr; 2802*61ae650dSJack F Vogel 2803*61ae650dSJack F Vogel /* Adjust latency range */ 2804*61ae650dSJack F Vogel switch (rxr->latency) { 2805*61ae650dSJack F Vogel case IXL_LOW_LATENCY: 2806*61ae650dSJack F Vogel if (rx_bytes > 10) { 2807*61ae650dSJack F Vogel rx_latency = IXL_AVE_LATENCY; 2808*61ae650dSJack F Vogel rx_itr = IXL_ITR_20K; 2809*61ae650dSJack F Vogel } 2810*61ae650dSJack F Vogel break; 2811*61ae650dSJack F Vogel case IXL_AVE_LATENCY: 2812*61ae650dSJack F Vogel if (rx_bytes > 20) { 2813*61ae650dSJack F Vogel rx_latency = IXL_BULK_LATENCY; 2814*61ae650dSJack F Vogel rx_itr = IXL_ITR_8K; 2815*61ae650dSJack F Vogel } else if (rx_bytes <= 10) { 2816*61ae650dSJack F Vogel rx_latency = IXL_LOW_LATENCY; 2817*61ae650dSJack F Vogel rx_itr = IXL_ITR_100K; 2818*61ae650dSJack F Vogel } 2819*61ae650dSJack F Vogel break; 2820*61ae650dSJack F Vogel case IXL_BULK_LATENCY: 2821*61ae650dSJack F Vogel if (rx_bytes <= 20) { 2822*61ae650dSJack F Vogel rx_latency = IXL_AVE_LATENCY; 2823*61ae650dSJack F Vogel rx_itr = IXL_ITR_20K; 2824*61ae650dSJack F Vogel } 2825*61ae650dSJack F Vogel break; 2826*61ae650dSJack F Vogel } 2827*61ae650dSJack F Vogel 2828*61ae650dSJack F Vogel rxr->latency = rx_latency; 2829*61ae650dSJack F Vogel 2830*61ae650dSJack F Vogel if (rx_itr != rxr->itr) { 2831*61ae650dSJack F Vogel /* do an exponential smoothing */ 2832*61ae650dSJack F Vogel rx_itr = (10 * rx_itr * rxr->itr) / 2833*61ae650dSJack F Vogel ((9 * rx_itr) + rxr->itr); 2834*61ae650dSJack F Vogel rxr->itr = rx_itr & IXL_MAX_ITR; 2835*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ITRN(IXL_RX_ITR, 2836*61ae650dSJack F Vogel que->me), rxr->itr); 2837*61ae650dSJack F Vogel } 2838*61ae650dSJack F Vogel } else { /* We may have have toggled to non-dynamic */ 2839*61ae650dSJack F Vogel if (vsi->rx_itr_setting & IXL_ITR_DYNAMIC) 2840*61ae650dSJack F Vogel vsi->rx_itr_setting = ixl_rx_itr; 2841*61ae650dSJack F Vogel /* Update the hardware if needed */ 2842*61ae650dSJack F Vogel if (rxr->itr != vsi->rx_itr_setting) { 2843*61ae650dSJack F Vogel rxr->itr = vsi->rx_itr_setting; 2844*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ITRN(IXL_RX_ITR, 2845*61ae650dSJack F Vogel que->me), rxr->itr); 2846*61ae650dSJack F Vogel } 2847*61ae650dSJack F Vogel } 2848*61ae650dSJack F Vogel rxr->bytes = 0; 2849*61ae650dSJack F Vogel rxr->packets = 0; 2850*61ae650dSJack F Vogel return; 2851*61ae650dSJack F Vogel } 2852*61ae650dSJack F Vogel 2853*61ae650dSJack F Vogel 2854*61ae650dSJack F Vogel /* 2855*61ae650dSJack F Vogel ** Provide a update to the queue TX 2856*61ae650dSJack F Vogel ** interrupt moderation value. 2857*61ae650dSJack F Vogel */ 2858*61ae650dSJack F Vogel static void 2859*61ae650dSJack F Vogel ixl_set_queue_tx_itr(struct ixl_queue *que) 2860*61ae650dSJack F Vogel { 2861*61ae650dSJack F Vogel struct ixl_vsi *vsi = que->vsi; 2862*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 2863*61ae650dSJack F Vogel struct tx_ring *txr = &que->txr; 2864*61ae650dSJack F Vogel u16 tx_itr; 2865*61ae650dSJack F Vogel u16 tx_latency = 0; 2866*61ae650dSJack F Vogel int tx_bytes; 2867*61ae650dSJack F Vogel 2868*61ae650dSJack F Vogel 2869*61ae650dSJack F Vogel /* Idle, do nothing */ 2870*61ae650dSJack F Vogel if (txr->bytes == 0) 2871*61ae650dSJack F Vogel return; 2872*61ae650dSJack F Vogel 2873*61ae650dSJack F Vogel if (ixl_dynamic_tx_itr) { 2874*61ae650dSJack F Vogel tx_bytes = txr->bytes/txr->itr; 2875*61ae650dSJack F Vogel tx_itr = txr->itr; 2876*61ae650dSJack F Vogel 2877*61ae650dSJack F Vogel switch (txr->latency) { 2878*61ae650dSJack F Vogel case IXL_LOW_LATENCY: 2879*61ae650dSJack F Vogel if (tx_bytes > 10) { 2880*61ae650dSJack F Vogel tx_latency = IXL_AVE_LATENCY; 2881*61ae650dSJack F Vogel tx_itr = IXL_ITR_20K; 2882*61ae650dSJack F Vogel } 2883*61ae650dSJack F Vogel break; 2884*61ae650dSJack F Vogel case IXL_AVE_LATENCY: 2885*61ae650dSJack F Vogel if (tx_bytes > 20) { 2886*61ae650dSJack F Vogel tx_latency = IXL_BULK_LATENCY; 2887*61ae650dSJack F Vogel tx_itr = IXL_ITR_8K; 2888*61ae650dSJack F Vogel } else if (tx_bytes <= 10) { 2889*61ae650dSJack F Vogel tx_latency = IXL_LOW_LATENCY; 2890*61ae650dSJack F Vogel tx_itr = IXL_ITR_100K; 2891*61ae650dSJack F Vogel } 2892*61ae650dSJack F Vogel break; 2893*61ae650dSJack F Vogel case IXL_BULK_LATENCY: 2894*61ae650dSJack F Vogel if (tx_bytes <= 20) { 2895*61ae650dSJack F Vogel tx_latency = IXL_AVE_LATENCY; 2896*61ae650dSJack F Vogel tx_itr = IXL_ITR_20K; 2897*61ae650dSJack F Vogel } 2898*61ae650dSJack F Vogel break; 2899*61ae650dSJack F Vogel } 2900*61ae650dSJack F Vogel 2901*61ae650dSJack F Vogel txr->latency = tx_latency; 2902*61ae650dSJack F Vogel 2903*61ae650dSJack F Vogel if (tx_itr != txr->itr) { 2904*61ae650dSJack F Vogel /* do an exponential smoothing */ 2905*61ae650dSJack F Vogel tx_itr = (10 * tx_itr * txr->itr) / 2906*61ae650dSJack F Vogel ((9 * tx_itr) + txr->itr); 2907*61ae650dSJack F Vogel txr->itr = tx_itr & IXL_MAX_ITR; 2908*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ITRN(IXL_TX_ITR, 2909*61ae650dSJack F Vogel que->me), txr->itr); 2910*61ae650dSJack F Vogel } 2911*61ae650dSJack F Vogel 2912*61ae650dSJack F Vogel } else { /* We may have have toggled to non-dynamic */ 2913*61ae650dSJack F Vogel if (vsi->tx_itr_setting & IXL_ITR_DYNAMIC) 2914*61ae650dSJack F Vogel vsi->tx_itr_setting = ixl_tx_itr; 2915*61ae650dSJack F Vogel /* Update the hardware if needed */ 2916*61ae650dSJack F Vogel if (txr->itr != vsi->tx_itr_setting) { 2917*61ae650dSJack F Vogel txr->itr = vsi->tx_itr_setting; 2918*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ITRN(IXL_TX_ITR, 2919*61ae650dSJack F Vogel que->me), txr->itr); 2920*61ae650dSJack F Vogel } 2921*61ae650dSJack F Vogel } 2922*61ae650dSJack F Vogel txr->bytes = 0; 2923*61ae650dSJack F Vogel txr->packets = 0; 2924*61ae650dSJack F Vogel return; 2925*61ae650dSJack F Vogel } 2926*61ae650dSJack F Vogel 2927*61ae650dSJack F Vogel 2928*61ae650dSJack F Vogel static void 2929*61ae650dSJack F Vogel ixl_add_hw_stats(struct ixl_pf *pf) 2930*61ae650dSJack F Vogel { 2931*61ae650dSJack F Vogel device_t dev = pf->dev; 2932*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 2933*61ae650dSJack F Vogel struct ixl_queue *queues = vsi->queues; 2934*61ae650dSJack F Vogel struct i40e_eth_stats *vsi_stats = &vsi->eth_stats; 2935*61ae650dSJack F Vogel struct i40e_hw_port_stats *pf_stats = &pf->stats; 2936*61ae650dSJack F Vogel 2937*61ae650dSJack F Vogel struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 2938*61ae650dSJack F Vogel struct sysctl_oid *tree = device_get_sysctl_tree(dev); 2939*61ae650dSJack F Vogel struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); 2940*61ae650dSJack F Vogel 2941*61ae650dSJack F Vogel struct sysctl_oid *vsi_node, *queue_node; 2942*61ae650dSJack F Vogel struct sysctl_oid_list *vsi_list, *queue_list; 2943*61ae650dSJack F Vogel 2944*61ae650dSJack F Vogel struct tx_ring *txr; 2945*61ae650dSJack F Vogel struct rx_ring *rxr; 2946*61ae650dSJack F Vogel 2947*61ae650dSJack F Vogel /* Driver statistics */ 2948*61ae650dSJack F Vogel SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events", 2949*61ae650dSJack F Vogel CTLFLAG_RD, &pf->watchdog_events, 2950*61ae650dSJack F Vogel "Watchdog timeouts"); 2951*61ae650dSJack F Vogel SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "admin_irq", 2952*61ae650dSJack F Vogel CTLFLAG_RD, &pf->admin_irq, 2953*61ae650dSJack F Vogel "Admin Queue IRQ Handled"); 2954*61ae650dSJack F Vogel 2955*61ae650dSJack F Vogel /* VSI statistics */ 2956*61ae650dSJack F Vogel #define QUEUE_NAME_LEN 32 2957*61ae650dSJack F Vogel char queue_namebuf[QUEUE_NAME_LEN]; 2958*61ae650dSJack F Vogel 2959*61ae650dSJack F Vogel // ERJ: Only one vsi now, re-do when >1 VSI enabled 2960*61ae650dSJack F Vogel // snprintf(vsi_namebuf, QUEUE_NAME_LEN, "vsi%d", vsi->info.stat_counter_idx); 2961*61ae650dSJack F Vogel vsi_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "vsi", 2962*61ae650dSJack F Vogel CTLFLAG_RD, NULL, "VSI-specific stats"); 2963*61ae650dSJack F Vogel vsi_list = SYSCTL_CHILDREN(vsi_node); 2964*61ae650dSJack F Vogel 2965*61ae650dSJack F Vogel ixl_add_sysctls_eth_stats(ctx, vsi_list, vsi_stats); 2966*61ae650dSJack F Vogel 2967*61ae650dSJack F Vogel /* Queue statistics */ 2968*61ae650dSJack F Vogel for (int q = 0; q < vsi->num_queues; q++) { 2969*61ae650dSJack F Vogel snprintf(queue_namebuf, QUEUE_NAME_LEN, "que%d", q); 2970*61ae650dSJack F Vogel queue_node = SYSCTL_ADD_NODE(ctx, vsi_list, OID_AUTO, queue_namebuf, 2971*61ae650dSJack F Vogel CTLFLAG_RD, NULL, "Queue #"); 2972*61ae650dSJack F Vogel queue_list = SYSCTL_CHILDREN(queue_node); 2973*61ae650dSJack F Vogel 2974*61ae650dSJack F Vogel txr = &(queues[q].txr); 2975*61ae650dSJack F Vogel rxr = &(queues[q].rxr); 2976*61ae650dSJack F Vogel 2977*61ae650dSJack F Vogel SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "mbuf_defrag_failed", 2978*61ae650dSJack F Vogel CTLFLAG_RD, &(queues[q].mbuf_defrag_failed), 2979*61ae650dSJack F Vogel "m_defrag() failed"); 2980*61ae650dSJack F Vogel SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "dropped", 2981*61ae650dSJack F Vogel CTLFLAG_RD, &(queues[q].dropped_pkts), 2982*61ae650dSJack F Vogel "Driver dropped packets"); 2983*61ae650dSJack F Vogel SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs", 2984*61ae650dSJack F Vogel CTLFLAG_RD, &(queues[q].irqs), 2985*61ae650dSJack F Vogel "irqs on this queue"); 2986*61ae650dSJack F Vogel SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx", 2987*61ae650dSJack F Vogel CTLFLAG_RD, &(queues[q].tso), 2988*61ae650dSJack F Vogel "TSO"); 2989*61ae650dSJack F Vogel SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_dma_setup", 2990*61ae650dSJack F Vogel CTLFLAG_RD, &(queues[q].tx_dma_setup), 2991*61ae650dSJack F Vogel "Driver tx dma failure in xmit"); 2992*61ae650dSJack F Vogel SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "no_desc_avail", 2993*61ae650dSJack F Vogel CTLFLAG_RD, &(txr->no_desc), 2994*61ae650dSJack F Vogel "Queue No Descriptor Available"); 2995*61ae650dSJack F Vogel SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets", 2996*61ae650dSJack F Vogel CTLFLAG_RD, &(txr->total_packets), 2997*61ae650dSJack F Vogel "Queue Packets Transmitted"); 2998*61ae650dSJack F Vogel SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_bytes", 2999*61ae650dSJack F Vogel CTLFLAG_RD, &(txr->tx_bytes), 3000*61ae650dSJack F Vogel "Queue Bytes Transmitted"); 3001*61ae650dSJack F Vogel SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets", 3002*61ae650dSJack F Vogel CTLFLAG_RD, &(rxr->rx_packets), 3003*61ae650dSJack F Vogel "Queue Packets Received"); 3004*61ae650dSJack F Vogel SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes", 3005*61ae650dSJack F Vogel CTLFLAG_RD, &(rxr->rx_bytes), 3006*61ae650dSJack F Vogel "Queue Bytes Received"); 3007*61ae650dSJack F Vogel } 3008*61ae650dSJack F Vogel 3009*61ae650dSJack F Vogel /* MAC stats */ 3010*61ae650dSJack F Vogel ixl_add_sysctls_mac_stats(ctx, child, pf_stats); 3011*61ae650dSJack F Vogel } 3012*61ae650dSJack F Vogel 3013*61ae650dSJack F Vogel static void 3014*61ae650dSJack F Vogel ixl_add_sysctls_eth_stats(struct sysctl_ctx_list *ctx, 3015*61ae650dSJack F Vogel struct sysctl_oid_list *child, 3016*61ae650dSJack F Vogel struct i40e_eth_stats *eth_stats) 3017*61ae650dSJack F Vogel { 3018*61ae650dSJack F Vogel struct ixl_sysctl_info ctls[] = 3019*61ae650dSJack F Vogel { 3020*61ae650dSJack F Vogel {ð_stats->rx_bytes, "good_octets_rcvd", "Good Octets Received"}, 3021*61ae650dSJack F Vogel {ð_stats->rx_unicast, "ucast_pkts_rcvd", 3022*61ae650dSJack F Vogel "Unicast Packets Received"}, 3023*61ae650dSJack F Vogel {ð_stats->rx_multicast, "mcast_pkts_rcvd", 3024*61ae650dSJack F Vogel "Multicast Packets Received"}, 3025*61ae650dSJack F Vogel {ð_stats->rx_broadcast, "bcast_pkts_rcvd", 3026*61ae650dSJack F Vogel "Broadcast Packets Received"}, 3027*61ae650dSJack F Vogel {ð_stats->rx_discards, "rx_discards", "Discarded RX packets"}, 3028*61ae650dSJack F Vogel {ð_stats->tx_bytes, "good_octets_txd", "Good Octets Transmitted"}, 3029*61ae650dSJack F Vogel {ð_stats->tx_unicast, "ucast_pkts_txd", "Unicast Packets Transmitted"}, 3030*61ae650dSJack F Vogel {ð_stats->tx_multicast, "mcast_pkts_txd", 3031*61ae650dSJack F Vogel "Multicast Packets Transmitted"}, 3032*61ae650dSJack F Vogel {ð_stats->tx_broadcast, "bcast_pkts_txd", 3033*61ae650dSJack F Vogel "Broadcast Packets Transmitted"}, 3034*61ae650dSJack F Vogel {ð_stats->tx_discards, "tx_discards", "Discarded TX packets"}, 3035*61ae650dSJack F Vogel // end 3036*61ae650dSJack F Vogel {0,0,0} 3037*61ae650dSJack F Vogel }; 3038*61ae650dSJack F Vogel 3039*61ae650dSJack F Vogel struct ixl_sysctl_info *entry = ctls; 3040*61ae650dSJack F Vogel while (entry->stat != 0) 3041*61ae650dSJack F Vogel { 3042*61ae650dSJack F Vogel SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, entry->name, 3043*61ae650dSJack F Vogel CTLFLAG_RD, entry->stat, 3044*61ae650dSJack F Vogel entry->description); 3045*61ae650dSJack F Vogel entry++; 3046*61ae650dSJack F Vogel } 3047*61ae650dSJack F Vogel } 3048*61ae650dSJack F Vogel 3049*61ae650dSJack F Vogel static void 3050*61ae650dSJack F Vogel ixl_add_sysctls_mac_stats(struct sysctl_ctx_list *ctx, 3051*61ae650dSJack F Vogel struct sysctl_oid_list *child, 3052*61ae650dSJack F Vogel struct i40e_hw_port_stats *stats) 3053*61ae650dSJack F Vogel { 3054*61ae650dSJack F Vogel struct sysctl_oid *stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac", 3055*61ae650dSJack F Vogel CTLFLAG_RD, NULL, "Mac Statistics"); 3056*61ae650dSJack F Vogel struct sysctl_oid_list *stat_list = SYSCTL_CHILDREN(stat_node); 3057*61ae650dSJack F Vogel 3058*61ae650dSJack F Vogel struct i40e_eth_stats *eth_stats = &stats->eth; 3059*61ae650dSJack F Vogel ixl_add_sysctls_eth_stats(ctx, stat_list, eth_stats); 3060*61ae650dSJack F Vogel 3061*61ae650dSJack F Vogel struct ixl_sysctl_info ctls[] = 3062*61ae650dSJack F Vogel { 3063*61ae650dSJack F Vogel {&stats->crc_errors, "crc_errors", "CRC Errors"}, 3064*61ae650dSJack F Vogel {&stats->illegal_bytes, "illegal_bytes", "Illegal Byte Errors"}, 3065*61ae650dSJack F Vogel {&stats->mac_local_faults, "local_faults", "MAC Local Faults"}, 3066*61ae650dSJack F Vogel {&stats->mac_remote_faults, "remote_faults", "MAC Remote Faults"}, 3067*61ae650dSJack F Vogel {&stats->rx_length_errors, "rx_length_errors", "Receive Length Errors"}, 3068*61ae650dSJack F Vogel /* Packet Reception Stats */ 3069*61ae650dSJack F Vogel {&stats->rx_size_64, "rx_frames_64", "64 byte frames received"}, 3070*61ae650dSJack F Vogel {&stats->rx_size_127, "rx_frames_65_127", "65-127 byte frames received"}, 3071*61ae650dSJack F Vogel {&stats->rx_size_255, "rx_frames_128_255", "128-255 byte frames received"}, 3072*61ae650dSJack F Vogel {&stats->rx_size_511, "rx_frames_256_511", "256-511 byte frames received"}, 3073*61ae650dSJack F Vogel {&stats->rx_size_1023, "rx_frames_512_1023", "512-1023 byte frames received"}, 3074*61ae650dSJack F Vogel {&stats->rx_size_1522, "rx_frames_1024_1522", "1024-1522 byte frames received"}, 3075*61ae650dSJack F Vogel {&stats->rx_size_big, "rx_frames_big", "1523-9522 byte frames received"}, 3076*61ae650dSJack F Vogel {&stats->rx_undersize, "rx_undersize", "Undersized packets received"}, 3077*61ae650dSJack F Vogel {&stats->rx_fragments, "rx_fragmented", "Fragmented packets received"}, 3078*61ae650dSJack F Vogel {&stats->rx_oversize, "rx_oversized", "Oversized packets received"}, 3079*61ae650dSJack F Vogel {&stats->rx_jabber, "rx_jabber", "Received Jabber"}, 3080*61ae650dSJack F Vogel {&stats->checksum_error, "checksum_errors", "Checksum Errors"}, 3081*61ae650dSJack F Vogel /* Packet Transmission Stats */ 3082*61ae650dSJack F Vogel {&stats->tx_size_64, "tx_frames_64", "64 byte frames transmitted"}, 3083*61ae650dSJack F Vogel {&stats->tx_size_127, "tx_frames_65_127", "65-127 byte frames transmitted"}, 3084*61ae650dSJack F Vogel {&stats->tx_size_255, "tx_frames_128_255", "128-255 byte frames transmitted"}, 3085*61ae650dSJack F Vogel {&stats->tx_size_511, "tx_frames_256_511", "256-511 byte frames transmitted"}, 3086*61ae650dSJack F Vogel {&stats->tx_size_1023, "tx_frames_512_1023", "512-1023 byte frames transmitted"}, 3087*61ae650dSJack F Vogel {&stats->tx_size_1522, "tx_frames_1024_1522", "1024-1522 byte frames transmitted"}, 3088*61ae650dSJack F Vogel {&stats->tx_size_big, "tx_frames_big", "1523-9522 byte frames transmitted"}, 3089*61ae650dSJack F Vogel /* Flow control */ 3090*61ae650dSJack F Vogel {&stats->link_xon_tx, "xon_txd", "Link XON transmitted"}, 3091*61ae650dSJack F Vogel {&stats->link_xon_rx, "xon_recvd", "Link XON received"}, 3092*61ae650dSJack F Vogel {&stats->link_xoff_tx, "xoff_txd", "Link XOFF transmitted"}, 3093*61ae650dSJack F Vogel {&stats->link_xoff_rx, "xoff_recvd", "Link XOFF received"}, 3094*61ae650dSJack F Vogel /* End */ 3095*61ae650dSJack F Vogel {0,0,0} 3096*61ae650dSJack F Vogel }; 3097*61ae650dSJack F Vogel 3098*61ae650dSJack F Vogel struct ixl_sysctl_info *entry = ctls; 3099*61ae650dSJack F Vogel while (entry->stat != 0) 3100*61ae650dSJack F Vogel { 3101*61ae650dSJack F Vogel SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, entry->name, 3102*61ae650dSJack F Vogel CTLFLAG_RD, entry->stat, 3103*61ae650dSJack F Vogel entry->description); 3104*61ae650dSJack F Vogel entry++; 3105*61ae650dSJack F Vogel } 3106*61ae650dSJack F Vogel } 3107*61ae650dSJack F Vogel 3108*61ae650dSJack F Vogel /* 3109*61ae650dSJack F Vogel ** ixl_config_rss - setup RSS 3110*61ae650dSJack F Vogel ** - note this is done for the single vsi 3111*61ae650dSJack F Vogel */ 3112*61ae650dSJack F Vogel static void ixl_config_rss(struct ixl_vsi *vsi) 3113*61ae650dSJack F Vogel { 3114*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)vsi->back; 3115*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 3116*61ae650dSJack F Vogel u32 lut = 0; 3117*61ae650dSJack F Vogel u64 set_hena, hena; 3118*61ae650dSJack F Vogel int i, j; 3119*61ae650dSJack F Vogel 3120*61ae650dSJack F Vogel static const u32 seed[I40E_PFQF_HKEY_MAX_INDEX + 1] = {0x41b01687, 3121*61ae650dSJack F Vogel 0x183cfd8c, 0xce880440, 0x580cbc3c, 0x35897377, 3122*61ae650dSJack F Vogel 0x328b25e1, 0x4fa98922, 0xb7d90c14, 0xd5bad70d, 3123*61ae650dSJack F Vogel 0xcd15a2c1, 0xe8580225, 0x4a1e9d11, 0xfe5731be}; 3124*61ae650dSJack F Vogel 3125*61ae650dSJack F Vogel /* Fill out hash function seed */ 3126*61ae650dSJack F Vogel for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++) 3127*61ae650dSJack F Vogel wr32(hw, I40E_PFQF_HKEY(i), seed[i]); 3128*61ae650dSJack F Vogel 3129*61ae650dSJack F Vogel /* Enable PCTYPES for RSS: */ 3130*61ae650dSJack F Vogel set_hena = 3131*61ae650dSJack F Vogel ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | 3132*61ae650dSJack F Vogel ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | 3133*61ae650dSJack F Vogel ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) | 3134*61ae650dSJack F Vogel ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | 3135*61ae650dSJack F Vogel ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) | 3136*61ae650dSJack F Vogel ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | 3137*61ae650dSJack F Vogel ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | 3138*61ae650dSJack F Vogel ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | 3139*61ae650dSJack F Vogel ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | 3140*61ae650dSJack F Vogel ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6) | 3141*61ae650dSJack F Vogel ((u64)1 << I40E_FILTER_PCTYPE_L2_PAYLOAD); 3142*61ae650dSJack F Vogel 3143*61ae650dSJack F Vogel hena = (u64)rd32(hw, I40E_PFQF_HENA(0)) | 3144*61ae650dSJack F Vogel ((u64)rd32(hw, I40E_PFQF_HENA(1)) << 32); 3145*61ae650dSJack F Vogel hena |= set_hena; 3146*61ae650dSJack F Vogel wr32(hw, I40E_PFQF_HENA(0), (u32)hena); 3147*61ae650dSJack F Vogel wr32(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32)); 3148*61ae650dSJack F Vogel 3149*61ae650dSJack F Vogel /* Populate the LUT with max no. of queues in round robin fashion */ 3150*61ae650dSJack F Vogel for (i = j = 0; i < pf->hw.func_caps.rss_table_size; i++, j++) { 3151*61ae650dSJack F Vogel if (j == vsi->num_queues) 3152*61ae650dSJack F Vogel j = 0; 3153*61ae650dSJack F Vogel /* lut = 4-byte sliding window of 4 lut entries */ 3154*61ae650dSJack F Vogel lut = (lut << 8) | (j & 3155*61ae650dSJack F Vogel ((0x1 << pf->hw.func_caps.rss_table_entry_width) - 1)); 3156*61ae650dSJack F Vogel /* On i = 3, we have 4 entries in lut; write to the register */ 3157*61ae650dSJack F Vogel if ((i & 3) == 3) 3158*61ae650dSJack F Vogel wr32(hw, I40E_PFQF_HLUT(i >> 2), lut); 3159*61ae650dSJack F Vogel } 3160*61ae650dSJack F Vogel ixl_flush(hw); 3161*61ae650dSJack F Vogel } 3162*61ae650dSJack F Vogel 3163*61ae650dSJack F Vogel 3164*61ae650dSJack F Vogel /* 3165*61ae650dSJack F Vogel ** This routine is run via an vlan config EVENT, 3166*61ae650dSJack F Vogel ** it enables us to use the HW Filter table since 3167*61ae650dSJack F Vogel ** we can get the vlan id. This just creates the 3168*61ae650dSJack F Vogel ** entry in the soft version of the VFTA, init will 3169*61ae650dSJack F Vogel ** repopulate the real table. 3170*61ae650dSJack F Vogel */ 3171*61ae650dSJack F Vogel static void 3172*61ae650dSJack F Vogel ixl_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) 3173*61ae650dSJack F Vogel { 3174*61ae650dSJack F Vogel struct ixl_vsi *vsi = ifp->if_softc; 3175*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 3176*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)vsi->back; 3177*61ae650dSJack F Vogel 3178*61ae650dSJack F Vogel if (ifp->if_softc != arg) /* Not our event */ 3179*61ae650dSJack F Vogel return; 3180*61ae650dSJack F Vogel 3181*61ae650dSJack F Vogel if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 3182*61ae650dSJack F Vogel return; 3183*61ae650dSJack F Vogel 3184*61ae650dSJack F Vogel IXL_PF_LOCK(pf); 3185*61ae650dSJack F Vogel ++vsi->num_vlans; 3186*61ae650dSJack F Vogel ixl_add_filter(vsi, hw->mac.addr, vtag); 3187*61ae650dSJack F Vogel IXL_PF_UNLOCK(pf); 3188*61ae650dSJack F Vogel } 3189*61ae650dSJack F Vogel 3190*61ae650dSJack F Vogel /* 3191*61ae650dSJack F Vogel ** This routine is run via an vlan 3192*61ae650dSJack F Vogel ** unconfig EVENT, remove our entry 3193*61ae650dSJack F Vogel ** in the soft vfta. 3194*61ae650dSJack F Vogel */ 3195*61ae650dSJack F Vogel static void 3196*61ae650dSJack F Vogel ixl_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) 3197*61ae650dSJack F Vogel { 3198*61ae650dSJack F Vogel struct ixl_vsi *vsi = ifp->if_softc; 3199*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 3200*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)vsi->back; 3201*61ae650dSJack F Vogel 3202*61ae650dSJack F Vogel if (ifp->if_softc != arg) 3203*61ae650dSJack F Vogel return; 3204*61ae650dSJack F Vogel 3205*61ae650dSJack F Vogel if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 3206*61ae650dSJack F Vogel return; 3207*61ae650dSJack F Vogel 3208*61ae650dSJack F Vogel IXL_PF_LOCK(pf); 3209*61ae650dSJack F Vogel --vsi->num_vlans; 3210*61ae650dSJack F Vogel ixl_del_filter(vsi, hw->mac.addr, vtag); 3211*61ae650dSJack F Vogel IXL_PF_UNLOCK(pf); 3212*61ae650dSJack F Vogel } 3213*61ae650dSJack F Vogel 3214*61ae650dSJack F Vogel /* 3215*61ae650dSJack F Vogel ** This routine updates vlan filters, called by init 3216*61ae650dSJack F Vogel ** it scans the filter table and then updates the hw 3217*61ae650dSJack F Vogel ** after a soft reset. 3218*61ae650dSJack F Vogel */ 3219*61ae650dSJack F Vogel static void 3220*61ae650dSJack F Vogel ixl_setup_vlan_filters(struct ixl_vsi *vsi) 3221*61ae650dSJack F Vogel { 3222*61ae650dSJack F Vogel struct ixl_mac_filter *f; 3223*61ae650dSJack F Vogel int cnt = 0, flags; 3224*61ae650dSJack F Vogel 3225*61ae650dSJack F Vogel if (vsi->num_vlans == 0) 3226*61ae650dSJack F Vogel return; 3227*61ae650dSJack F Vogel /* 3228*61ae650dSJack F Vogel ** Scan the filter list for vlan entries, 3229*61ae650dSJack F Vogel ** mark them for addition and then call 3230*61ae650dSJack F Vogel ** for the AQ update. 3231*61ae650dSJack F Vogel */ 3232*61ae650dSJack F Vogel SLIST_FOREACH(f, &vsi->ftl, next) { 3233*61ae650dSJack F Vogel if (f->flags & IXL_FILTER_VLAN) { 3234*61ae650dSJack F Vogel f->flags |= 3235*61ae650dSJack F Vogel (IXL_FILTER_ADD | 3236*61ae650dSJack F Vogel IXL_FILTER_USED); 3237*61ae650dSJack F Vogel cnt++; 3238*61ae650dSJack F Vogel } 3239*61ae650dSJack F Vogel } 3240*61ae650dSJack F Vogel if (cnt == 0) { 3241*61ae650dSJack F Vogel printf("setup vlan: no filters found!\n"); 3242*61ae650dSJack F Vogel return; 3243*61ae650dSJack F Vogel } 3244*61ae650dSJack F Vogel flags = IXL_FILTER_VLAN; 3245*61ae650dSJack F Vogel flags |= (IXL_FILTER_ADD | IXL_FILTER_USED); 3246*61ae650dSJack F Vogel ixl_add_hw_filters(vsi, flags, cnt); 3247*61ae650dSJack F Vogel return; 3248*61ae650dSJack F Vogel } 3249*61ae650dSJack F Vogel 3250*61ae650dSJack F Vogel /* 3251*61ae650dSJack F Vogel ** Initialize filter list and add filters that the hardware 3252*61ae650dSJack F Vogel ** needs to know about. 3253*61ae650dSJack F Vogel */ 3254*61ae650dSJack F Vogel static void 3255*61ae650dSJack F Vogel ixl_init_filters(struct ixl_vsi *vsi) 3256*61ae650dSJack F Vogel { 3257*61ae650dSJack F Vogel /* Add broadcast address */ 3258*61ae650dSJack F Vogel u8 bc[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 3259*61ae650dSJack F Vogel ixl_add_filter(vsi, bc, IXL_VLAN_ANY); 3260*61ae650dSJack F Vogel } 3261*61ae650dSJack F Vogel 3262*61ae650dSJack F Vogel /* 3263*61ae650dSJack F Vogel ** This routine adds mulicast filters 3264*61ae650dSJack F Vogel */ 3265*61ae650dSJack F Vogel static void 3266*61ae650dSJack F Vogel ixl_add_mc_filter(struct ixl_vsi *vsi, u8 *macaddr) 3267*61ae650dSJack F Vogel { 3268*61ae650dSJack F Vogel struct ixl_mac_filter *f; 3269*61ae650dSJack F Vogel 3270*61ae650dSJack F Vogel /* Does one already exist */ 3271*61ae650dSJack F Vogel f = ixl_find_filter(vsi, macaddr, IXL_VLAN_ANY); 3272*61ae650dSJack F Vogel if (f != NULL) 3273*61ae650dSJack F Vogel return; 3274*61ae650dSJack F Vogel 3275*61ae650dSJack F Vogel f = ixl_get_filter(vsi); 3276*61ae650dSJack F Vogel if (f == NULL) { 3277*61ae650dSJack F Vogel printf("WARNING: no filter available!!\n"); 3278*61ae650dSJack F Vogel return; 3279*61ae650dSJack F Vogel } 3280*61ae650dSJack F Vogel bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN); 3281*61ae650dSJack F Vogel f->vlan = IXL_VLAN_ANY; 3282*61ae650dSJack F Vogel f->flags |= (IXL_FILTER_ADD | IXL_FILTER_USED 3283*61ae650dSJack F Vogel | IXL_FILTER_MC); 3284*61ae650dSJack F Vogel 3285*61ae650dSJack F Vogel return; 3286*61ae650dSJack F Vogel } 3287*61ae650dSJack F Vogel 3288*61ae650dSJack F Vogel /* 3289*61ae650dSJack F Vogel ** This routine adds macvlan filters 3290*61ae650dSJack F Vogel */ 3291*61ae650dSJack F Vogel static void 3292*61ae650dSJack F Vogel ixl_add_filter(struct ixl_vsi *vsi, u8 *macaddr, s16 vlan) 3293*61ae650dSJack F Vogel { 3294*61ae650dSJack F Vogel struct ixl_mac_filter *f, *tmp; 3295*61ae650dSJack F Vogel device_t dev = vsi->dev; 3296*61ae650dSJack F Vogel 3297*61ae650dSJack F Vogel DEBUGOUT("ixl_add_filter: begin"); 3298*61ae650dSJack F Vogel 3299*61ae650dSJack F Vogel /* Does one already exist */ 3300*61ae650dSJack F Vogel f = ixl_find_filter(vsi, macaddr, vlan); 3301*61ae650dSJack F Vogel if (f != NULL) 3302*61ae650dSJack F Vogel return; 3303*61ae650dSJack F Vogel /* 3304*61ae650dSJack F Vogel ** Is this the first vlan being registered, if so we 3305*61ae650dSJack F Vogel ** need to remove the ANY filter that indicates we are 3306*61ae650dSJack F Vogel ** not in a vlan, and replace that with a 0 filter. 3307*61ae650dSJack F Vogel */ 3308*61ae650dSJack F Vogel if ((vlan != IXL_VLAN_ANY) && (vsi->num_vlans == 1)) { 3309*61ae650dSJack F Vogel tmp = ixl_find_filter(vsi, macaddr, IXL_VLAN_ANY); 3310*61ae650dSJack F Vogel if (tmp != NULL) { 3311*61ae650dSJack F Vogel ixl_del_filter(vsi, macaddr, IXL_VLAN_ANY); 3312*61ae650dSJack F Vogel ixl_add_filter(vsi, macaddr, 0); 3313*61ae650dSJack F Vogel } 3314*61ae650dSJack F Vogel } 3315*61ae650dSJack F Vogel 3316*61ae650dSJack F Vogel f = ixl_get_filter(vsi); 3317*61ae650dSJack F Vogel if (f == NULL) { 3318*61ae650dSJack F Vogel device_printf(dev, "WARNING: no filter available!!\n"); 3319*61ae650dSJack F Vogel return; 3320*61ae650dSJack F Vogel } 3321*61ae650dSJack F Vogel bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN); 3322*61ae650dSJack F Vogel f->vlan = vlan; 3323*61ae650dSJack F Vogel f->flags |= (IXL_FILTER_ADD | IXL_FILTER_USED); 3324*61ae650dSJack F Vogel if (f->vlan != IXL_VLAN_ANY) 3325*61ae650dSJack F Vogel f->flags |= IXL_FILTER_VLAN; 3326*61ae650dSJack F Vogel 3327*61ae650dSJack F Vogel ixl_add_hw_filters(vsi, f->flags, 1); 3328*61ae650dSJack F Vogel return; 3329*61ae650dSJack F Vogel } 3330*61ae650dSJack F Vogel 3331*61ae650dSJack F Vogel static void 3332*61ae650dSJack F Vogel ixl_del_filter(struct ixl_vsi *vsi, u8 *macaddr, s16 vlan) 3333*61ae650dSJack F Vogel { 3334*61ae650dSJack F Vogel struct ixl_mac_filter *f; 3335*61ae650dSJack F Vogel 3336*61ae650dSJack F Vogel f = ixl_find_filter(vsi, macaddr, vlan); 3337*61ae650dSJack F Vogel if (f == NULL) 3338*61ae650dSJack F Vogel return; 3339*61ae650dSJack F Vogel 3340*61ae650dSJack F Vogel f->flags |= IXL_FILTER_DEL; 3341*61ae650dSJack F Vogel ixl_del_hw_filters(vsi, 1); 3342*61ae650dSJack F Vogel 3343*61ae650dSJack F Vogel /* Check if this is the last vlan removal */ 3344*61ae650dSJack F Vogel if (vlan != IXL_VLAN_ANY && vsi->num_vlans == 0) { 3345*61ae650dSJack F Vogel /* Switch back to a non-vlan filter */ 3346*61ae650dSJack F Vogel ixl_del_filter(vsi, macaddr, 0); 3347*61ae650dSJack F Vogel ixl_add_filter(vsi, macaddr, IXL_VLAN_ANY); 3348*61ae650dSJack F Vogel } 3349*61ae650dSJack F Vogel return; 3350*61ae650dSJack F Vogel } 3351*61ae650dSJack F Vogel 3352*61ae650dSJack F Vogel /* 3353*61ae650dSJack F Vogel ** Find the filter with both matching mac addr and vlan id 3354*61ae650dSJack F Vogel */ 3355*61ae650dSJack F Vogel static struct ixl_mac_filter * 3356*61ae650dSJack F Vogel ixl_find_filter(struct ixl_vsi *vsi, u8 *macaddr, s16 vlan) 3357*61ae650dSJack F Vogel { 3358*61ae650dSJack F Vogel struct ixl_mac_filter *f; 3359*61ae650dSJack F Vogel bool match = FALSE; 3360*61ae650dSJack F Vogel 3361*61ae650dSJack F Vogel SLIST_FOREACH(f, &vsi->ftl, next) { 3362*61ae650dSJack F Vogel if (!cmp_etheraddr(f->macaddr, macaddr)) 3363*61ae650dSJack F Vogel continue; 3364*61ae650dSJack F Vogel if (f->vlan == vlan) { 3365*61ae650dSJack F Vogel match = TRUE; 3366*61ae650dSJack F Vogel break; 3367*61ae650dSJack F Vogel } 3368*61ae650dSJack F Vogel } 3369*61ae650dSJack F Vogel 3370*61ae650dSJack F Vogel if (!match) 3371*61ae650dSJack F Vogel f = NULL; 3372*61ae650dSJack F Vogel return (f); 3373*61ae650dSJack F Vogel } 3374*61ae650dSJack F Vogel 3375*61ae650dSJack F Vogel /* 3376*61ae650dSJack F Vogel ** This routine takes additions to the vsi filter 3377*61ae650dSJack F Vogel ** table and creates an Admin Queue call to create 3378*61ae650dSJack F Vogel ** the filters in the hardware. 3379*61ae650dSJack F Vogel */ 3380*61ae650dSJack F Vogel static void 3381*61ae650dSJack F Vogel ixl_add_hw_filters(struct ixl_vsi *vsi, int flags, int cnt) 3382*61ae650dSJack F Vogel { 3383*61ae650dSJack F Vogel struct i40e_aqc_add_macvlan_element_data *a, *b; 3384*61ae650dSJack F Vogel struct ixl_mac_filter *f; 3385*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 3386*61ae650dSJack F Vogel device_t dev = vsi->dev; 3387*61ae650dSJack F Vogel int err, j = 0; 3388*61ae650dSJack F Vogel 3389*61ae650dSJack F Vogel a = malloc(sizeof(struct i40e_aqc_add_macvlan_element_data) * cnt, 3390*61ae650dSJack F Vogel M_DEVBUF, M_NOWAIT | M_ZERO); 3391*61ae650dSJack F Vogel if (a == NULL) { 3392*61ae650dSJack F Vogel device_printf(dev, "add hw filter failed to get memory\n"); 3393*61ae650dSJack F Vogel return; 3394*61ae650dSJack F Vogel } 3395*61ae650dSJack F Vogel 3396*61ae650dSJack F Vogel /* 3397*61ae650dSJack F Vogel ** Scan the filter list, each time we find one 3398*61ae650dSJack F Vogel ** we add it to the admin queue array and turn off 3399*61ae650dSJack F Vogel ** the add bit. 3400*61ae650dSJack F Vogel */ 3401*61ae650dSJack F Vogel SLIST_FOREACH(f, &vsi->ftl, next) { 3402*61ae650dSJack F Vogel if (f->flags == flags) { 3403*61ae650dSJack F Vogel b = &a[j]; // a pox on fvl long names :) 3404*61ae650dSJack F Vogel bcopy(f->macaddr, b->mac_addr, ETHER_ADDR_LEN); 3405*61ae650dSJack F Vogel b->vlan_tag = 3406*61ae650dSJack F Vogel (f->vlan == IXL_VLAN_ANY ? 0 : f->vlan); 3407*61ae650dSJack F Vogel b->flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH; 3408*61ae650dSJack F Vogel f->flags &= ~IXL_FILTER_ADD; 3409*61ae650dSJack F Vogel j++; 3410*61ae650dSJack F Vogel } 3411*61ae650dSJack F Vogel if (j == cnt) 3412*61ae650dSJack F Vogel break; 3413*61ae650dSJack F Vogel } 3414*61ae650dSJack F Vogel if (j > 0) { 3415*61ae650dSJack F Vogel err = i40e_aq_add_macvlan(hw, vsi->seid, a, j, NULL); 3416*61ae650dSJack F Vogel if (err) 3417*61ae650dSJack F Vogel device_printf(dev, "aq_add_macvlan failure %d\n", 3418*61ae650dSJack F Vogel hw->aq.asq_last_status); 3419*61ae650dSJack F Vogel else 3420*61ae650dSJack F Vogel vsi->hw_filters_add += j; 3421*61ae650dSJack F Vogel } 3422*61ae650dSJack F Vogel free(a, M_DEVBUF); 3423*61ae650dSJack F Vogel return; 3424*61ae650dSJack F Vogel } 3425*61ae650dSJack F Vogel 3426*61ae650dSJack F Vogel /* 3427*61ae650dSJack F Vogel ** This routine takes removals in the vsi filter 3428*61ae650dSJack F Vogel ** table and creates an Admin Queue call to delete 3429*61ae650dSJack F Vogel ** the filters in the hardware. 3430*61ae650dSJack F Vogel */ 3431*61ae650dSJack F Vogel static void 3432*61ae650dSJack F Vogel ixl_del_hw_filters(struct ixl_vsi *vsi, int cnt) 3433*61ae650dSJack F Vogel { 3434*61ae650dSJack F Vogel struct i40e_aqc_remove_macvlan_element_data *d, *e; 3435*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 3436*61ae650dSJack F Vogel device_t dev = vsi->dev; 3437*61ae650dSJack F Vogel struct ixl_mac_filter *f, *f_temp; 3438*61ae650dSJack F Vogel int err, j = 0; 3439*61ae650dSJack F Vogel 3440*61ae650dSJack F Vogel DEBUGOUT("ixl_del_hw_filters: begin\n"); 3441*61ae650dSJack F Vogel 3442*61ae650dSJack F Vogel d = malloc(sizeof(struct i40e_aqc_remove_macvlan_element_data) * cnt, 3443*61ae650dSJack F Vogel M_DEVBUF, M_NOWAIT | M_ZERO); 3444*61ae650dSJack F Vogel if (d == NULL) { 3445*61ae650dSJack F Vogel printf("del hw filter failed to get memory\n"); 3446*61ae650dSJack F Vogel return; 3447*61ae650dSJack F Vogel } 3448*61ae650dSJack F Vogel 3449*61ae650dSJack F Vogel SLIST_FOREACH_SAFE(f, &vsi->ftl, next, f_temp) { 3450*61ae650dSJack F Vogel if (f->flags & IXL_FILTER_DEL) { 3451*61ae650dSJack F Vogel e = &d[j]; // a pox on fvl long names :) 3452*61ae650dSJack F Vogel bcopy(f->macaddr, e->mac_addr, ETHER_ADDR_LEN); 3453*61ae650dSJack F Vogel e->vlan_tag = (f->vlan == IXL_VLAN_ANY ? 0 : f->vlan); 3454*61ae650dSJack F Vogel e->flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH; 3455*61ae650dSJack F Vogel /* delete entry from vsi list */ 3456*61ae650dSJack F Vogel SLIST_REMOVE(&vsi->ftl, f, ixl_mac_filter, next); 3457*61ae650dSJack F Vogel free(f, M_DEVBUF); 3458*61ae650dSJack F Vogel j++; 3459*61ae650dSJack F Vogel } 3460*61ae650dSJack F Vogel if (j == cnt) 3461*61ae650dSJack F Vogel break; 3462*61ae650dSJack F Vogel } 3463*61ae650dSJack F Vogel if (j > 0) { 3464*61ae650dSJack F Vogel err = i40e_aq_remove_macvlan(hw, vsi->seid, d, j, NULL); 3465*61ae650dSJack F Vogel /* NOTE: returns ENOENT every time but seems to work fine, 3466*61ae650dSJack F Vogel so we'll ignore that specific error. */ 3467*61ae650dSJack F Vogel if (err && hw->aq.asq_last_status != I40E_AQ_RC_ENOENT) { 3468*61ae650dSJack F Vogel int sc = 0; 3469*61ae650dSJack F Vogel for (int i = 0; i < j; i++) 3470*61ae650dSJack F Vogel sc += (!d[i].error_code); 3471*61ae650dSJack F Vogel vsi->hw_filters_del += sc; 3472*61ae650dSJack F Vogel device_printf(dev, 3473*61ae650dSJack F Vogel "Failed to remove %d/%d filters, aq error %d\n", 3474*61ae650dSJack F Vogel j - sc, j, hw->aq.asq_last_status); 3475*61ae650dSJack F Vogel } else 3476*61ae650dSJack F Vogel vsi->hw_filters_del += j; 3477*61ae650dSJack F Vogel } 3478*61ae650dSJack F Vogel free(d, M_DEVBUF); 3479*61ae650dSJack F Vogel 3480*61ae650dSJack F Vogel DEBUGOUT("ixl_del_hw_filters: end\n"); 3481*61ae650dSJack F Vogel return; 3482*61ae650dSJack F Vogel } 3483*61ae650dSJack F Vogel 3484*61ae650dSJack F Vogel 3485*61ae650dSJack F Vogel static void 3486*61ae650dSJack F Vogel ixl_enable_rings(struct ixl_vsi *vsi) 3487*61ae650dSJack F Vogel { 3488*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 3489*61ae650dSJack F Vogel u32 reg; 3490*61ae650dSJack F Vogel 3491*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++) { 3492*61ae650dSJack F Vogel i40e_pre_tx_queue_cfg(hw, i, TRUE); 3493*61ae650dSJack F Vogel 3494*61ae650dSJack F Vogel reg = rd32(hw, I40E_QTX_ENA(i)); 3495*61ae650dSJack F Vogel reg |= I40E_QTX_ENA_QENA_REQ_MASK | 3496*61ae650dSJack F Vogel I40E_QTX_ENA_QENA_STAT_MASK; 3497*61ae650dSJack F Vogel wr32(hw, I40E_QTX_ENA(i), reg); 3498*61ae650dSJack F Vogel /* Verify the enable took */ 3499*61ae650dSJack F Vogel for (int j = 0; j < 10; j++) { 3500*61ae650dSJack F Vogel reg = rd32(hw, I40E_QTX_ENA(i)); 3501*61ae650dSJack F Vogel if (reg & I40E_QTX_ENA_QENA_STAT_MASK) 3502*61ae650dSJack F Vogel break; 3503*61ae650dSJack F Vogel i40e_msec_delay(10); 3504*61ae650dSJack F Vogel } 3505*61ae650dSJack F Vogel if ((reg & I40E_QTX_ENA_QENA_STAT_MASK) == 0) 3506*61ae650dSJack F Vogel printf("TX queue %d disabled!\n", i); 3507*61ae650dSJack F Vogel 3508*61ae650dSJack F Vogel reg = rd32(hw, I40E_QRX_ENA(i)); 3509*61ae650dSJack F Vogel reg |= I40E_QRX_ENA_QENA_REQ_MASK | 3510*61ae650dSJack F Vogel I40E_QRX_ENA_QENA_STAT_MASK; 3511*61ae650dSJack F Vogel wr32(hw, I40E_QRX_ENA(i), reg); 3512*61ae650dSJack F Vogel /* Verify the enable took */ 3513*61ae650dSJack F Vogel for (int j = 0; j < 10; j++) { 3514*61ae650dSJack F Vogel reg = rd32(hw, I40E_QRX_ENA(i)); 3515*61ae650dSJack F Vogel if (reg & I40E_QRX_ENA_QENA_STAT_MASK) 3516*61ae650dSJack F Vogel break; 3517*61ae650dSJack F Vogel i40e_msec_delay(10); 3518*61ae650dSJack F Vogel } 3519*61ae650dSJack F Vogel if ((reg & I40E_QRX_ENA_QENA_STAT_MASK) == 0) 3520*61ae650dSJack F Vogel printf("RX queue %d disabled!\n", i); 3521*61ae650dSJack F Vogel } 3522*61ae650dSJack F Vogel } 3523*61ae650dSJack F Vogel 3524*61ae650dSJack F Vogel static void 3525*61ae650dSJack F Vogel ixl_disable_rings(struct ixl_vsi *vsi) 3526*61ae650dSJack F Vogel { 3527*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 3528*61ae650dSJack F Vogel u32 reg; 3529*61ae650dSJack F Vogel 3530*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++) { 3531*61ae650dSJack F Vogel i40e_pre_tx_queue_cfg(hw, i, FALSE); 3532*61ae650dSJack F Vogel i40e_usec_delay(500); 3533*61ae650dSJack F Vogel 3534*61ae650dSJack F Vogel reg = rd32(hw, I40E_QTX_ENA(i)); 3535*61ae650dSJack F Vogel reg &= ~I40E_QTX_ENA_QENA_REQ_MASK; 3536*61ae650dSJack F Vogel wr32(hw, I40E_QTX_ENA(i), reg); 3537*61ae650dSJack F Vogel /* Verify the disable took */ 3538*61ae650dSJack F Vogel for (int j = 0; j < 10; j++) { 3539*61ae650dSJack F Vogel reg = rd32(hw, I40E_QTX_ENA(i)); 3540*61ae650dSJack F Vogel if (!(reg & I40E_QTX_ENA_QENA_STAT_MASK)) 3541*61ae650dSJack F Vogel break; 3542*61ae650dSJack F Vogel i40e_msec_delay(10); 3543*61ae650dSJack F Vogel } 3544*61ae650dSJack F Vogel if (reg & I40E_QTX_ENA_QENA_STAT_MASK) 3545*61ae650dSJack F Vogel printf("TX queue %d still enabled!\n", i); 3546*61ae650dSJack F Vogel 3547*61ae650dSJack F Vogel reg = rd32(hw, I40E_QRX_ENA(i)); 3548*61ae650dSJack F Vogel reg &= ~I40E_QRX_ENA_QENA_REQ_MASK; 3549*61ae650dSJack F Vogel wr32(hw, I40E_QRX_ENA(i), reg); 3550*61ae650dSJack F Vogel /* Verify the disable took */ 3551*61ae650dSJack F Vogel for (int j = 0; j < 10; j++) { 3552*61ae650dSJack F Vogel reg = rd32(hw, I40E_QRX_ENA(i)); 3553*61ae650dSJack F Vogel if (!(reg & I40E_QRX_ENA_QENA_STAT_MASK)) 3554*61ae650dSJack F Vogel break; 3555*61ae650dSJack F Vogel i40e_msec_delay(10); 3556*61ae650dSJack F Vogel } 3557*61ae650dSJack F Vogel if (reg & I40E_QRX_ENA_QENA_STAT_MASK) 3558*61ae650dSJack F Vogel printf("RX queue %d still enabled!\n", i); 3559*61ae650dSJack F Vogel } 3560*61ae650dSJack F Vogel } 3561*61ae650dSJack F Vogel 3562*61ae650dSJack F Vogel /** 3563*61ae650dSJack F Vogel * ixl_handle_mdd_event 3564*61ae650dSJack F Vogel * 3565*61ae650dSJack F Vogel * Called from interrupt handler to identify possibly malicious vfs 3566*61ae650dSJack F Vogel * (But also detects events from the PF, as well) 3567*61ae650dSJack F Vogel **/ 3568*61ae650dSJack F Vogel static void ixl_handle_mdd_event(struct ixl_pf *pf) 3569*61ae650dSJack F Vogel { 3570*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 3571*61ae650dSJack F Vogel device_t dev = pf->dev; 3572*61ae650dSJack F Vogel bool mdd_detected = false; 3573*61ae650dSJack F Vogel bool pf_mdd_detected = false; 3574*61ae650dSJack F Vogel u32 reg; 3575*61ae650dSJack F Vogel 3576*61ae650dSJack F Vogel /* find what triggered the MDD event */ 3577*61ae650dSJack F Vogel reg = rd32(hw, I40E_GL_MDET_TX); 3578*61ae650dSJack F Vogel if (reg & I40E_GL_MDET_TX_VALID_MASK) { 3579*61ae650dSJack F Vogel u8 pf_num = (reg & I40E_GL_MDET_TX_PF_NUM_MASK) >> 3580*61ae650dSJack F Vogel I40E_GL_MDET_TX_PF_NUM_SHIFT; 3581*61ae650dSJack F Vogel u8 event = (reg & I40E_GL_MDET_TX_EVENT_MASK) >> 3582*61ae650dSJack F Vogel I40E_GL_MDET_TX_EVENT_SHIFT; 3583*61ae650dSJack F Vogel u8 queue = (reg & I40E_GL_MDET_TX_QUEUE_MASK) >> 3584*61ae650dSJack F Vogel I40E_GL_MDET_TX_QUEUE_SHIFT; 3585*61ae650dSJack F Vogel device_printf(dev, 3586*61ae650dSJack F Vogel "Malicious Driver Detection event 0x%02x" 3587*61ae650dSJack F Vogel " on TX queue %d pf number 0x%02x\n", 3588*61ae650dSJack F Vogel event, queue, pf_num); 3589*61ae650dSJack F Vogel wr32(hw, I40E_GL_MDET_TX, 0xffffffff); 3590*61ae650dSJack F Vogel mdd_detected = true; 3591*61ae650dSJack F Vogel } 3592*61ae650dSJack F Vogel reg = rd32(hw, I40E_GL_MDET_RX); 3593*61ae650dSJack F Vogel if (reg & I40E_GL_MDET_RX_VALID_MASK) { 3594*61ae650dSJack F Vogel u8 func = (reg & I40E_GL_MDET_RX_FUNCTION_MASK) >> 3595*61ae650dSJack F Vogel I40E_GL_MDET_RX_FUNCTION_SHIFT; 3596*61ae650dSJack F Vogel u8 event = (reg & I40E_GL_MDET_RX_EVENT_MASK) >> 3597*61ae650dSJack F Vogel I40E_GL_MDET_RX_EVENT_SHIFT; 3598*61ae650dSJack F Vogel u8 queue = (reg & I40E_GL_MDET_RX_QUEUE_MASK) >> 3599*61ae650dSJack F Vogel I40E_GL_MDET_RX_QUEUE_SHIFT; 3600*61ae650dSJack F Vogel device_printf(dev, 3601*61ae650dSJack F Vogel "Malicious Driver Detection event 0x%02x" 3602*61ae650dSJack F Vogel " on RX queue %d of function 0x%02x\n", 3603*61ae650dSJack F Vogel event, queue, func); 3604*61ae650dSJack F Vogel wr32(hw, I40E_GL_MDET_RX, 0xffffffff); 3605*61ae650dSJack F Vogel mdd_detected = true; 3606*61ae650dSJack F Vogel } 3607*61ae650dSJack F Vogel 3608*61ae650dSJack F Vogel if (mdd_detected) { 3609*61ae650dSJack F Vogel reg = rd32(hw, I40E_PF_MDET_TX); 3610*61ae650dSJack F Vogel if (reg & I40E_PF_MDET_TX_VALID_MASK) { 3611*61ae650dSJack F Vogel wr32(hw, I40E_PF_MDET_TX, 0xFFFF); 3612*61ae650dSJack F Vogel device_printf(dev, 3613*61ae650dSJack F Vogel "MDD TX event is for this function 0x%08x", 3614*61ae650dSJack F Vogel reg); 3615*61ae650dSJack F Vogel pf_mdd_detected = true; 3616*61ae650dSJack F Vogel } 3617*61ae650dSJack F Vogel reg = rd32(hw, I40E_PF_MDET_RX); 3618*61ae650dSJack F Vogel if (reg & I40E_PF_MDET_RX_VALID_MASK) { 3619*61ae650dSJack F Vogel wr32(hw, I40E_PF_MDET_RX, 0xFFFF); 3620*61ae650dSJack F Vogel device_printf(dev, 3621*61ae650dSJack F Vogel "MDD RX event is for this function 0x%08x", 3622*61ae650dSJack F Vogel reg); 3623*61ae650dSJack F Vogel pf_mdd_detected = true; 3624*61ae650dSJack F Vogel } 3625*61ae650dSJack F Vogel } 3626*61ae650dSJack F Vogel 3627*61ae650dSJack F Vogel /* re-enable mdd interrupt cause */ 3628*61ae650dSJack F Vogel reg = rd32(hw, I40E_PFINT_ICR0_ENA); 3629*61ae650dSJack F Vogel reg |= I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK; 3630*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ICR0_ENA, reg); 3631*61ae650dSJack F Vogel ixl_flush(hw); 3632*61ae650dSJack F Vogel } 3633*61ae650dSJack F Vogel 3634*61ae650dSJack F Vogel static void 3635*61ae650dSJack F Vogel ixl_enable_intr(struct ixl_vsi *vsi) 3636*61ae650dSJack F Vogel { 3637*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 3638*61ae650dSJack F Vogel struct ixl_queue *que = vsi->queues; 3639*61ae650dSJack F Vogel 3640*61ae650dSJack F Vogel if (ixl_enable_msix) { 3641*61ae650dSJack F Vogel ixl_enable_adminq(hw); 3642*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++, que++) 3643*61ae650dSJack F Vogel ixl_enable_queue(hw, que->me); 3644*61ae650dSJack F Vogel } else 3645*61ae650dSJack F Vogel ixl_enable_legacy(hw); 3646*61ae650dSJack F Vogel } 3647*61ae650dSJack F Vogel 3648*61ae650dSJack F Vogel static void 3649*61ae650dSJack F Vogel ixl_disable_intr(struct ixl_vsi *vsi) 3650*61ae650dSJack F Vogel { 3651*61ae650dSJack F Vogel struct i40e_hw *hw = vsi->hw; 3652*61ae650dSJack F Vogel struct ixl_queue *que = vsi->queues; 3653*61ae650dSJack F Vogel 3654*61ae650dSJack F Vogel if (ixl_enable_msix) { 3655*61ae650dSJack F Vogel ixl_disable_adminq(hw); 3656*61ae650dSJack F Vogel for (int i = 0; i < vsi->num_queues; i++, que++) 3657*61ae650dSJack F Vogel ixl_disable_queue(hw, que->me); 3658*61ae650dSJack F Vogel } else 3659*61ae650dSJack F Vogel ixl_disable_legacy(hw); 3660*61ae650dSJack F Vogel } 3661*61ae650dSJack F Vogel 3662*61ae650dSJack F Vogel static void 3663*61ae650dSJack F Vogel ixl_enable_adminq(struct i40e_hw *hw) 3664*61ae650dSJack F Vogel { 3665*61ae650dSJack F Vogel u32 reg; 3666*61ae650dSJack F Vogel 3667*61ae650dSJack F Vogel reg = I40E_PFINT_DYN_CTL0_INTENA_MASK | 3668*61ae650dSJack F Vogel I40E_PFINT_DYN_CTL0_CLEARPBA_MASK | 3669*61ae650dSJack F Vogel (IXL_ITR_NONE << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT); 3670*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_DYN_CTL0, reg); 3671*61ae650dSJack F Vogel ixl_flush(hw); 3672*61ae650dSJack F Vogel return; 3673*61ae650dSJack F Vogel } 3674*61ae650dSJack F Vogel 3675*61ae650dSJack F Vogel static void 3676*61ae650dSJack F Vogel ixl_disable_adminq(struct i40e_hw *hw) 3677*61ae650dSJack F Vogel { 3678*61ae650dSJack F Vogel u32 reg; 3679*61ae650dSJack F Vogel 3680*61ae650dSJack F Vogel reg = IXL_ITR_NONE << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT; 3681*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_DYN_CTL0, reg); 3682*61ae650dSJack F Vogel 3683*61ae650dSJack F Vogel return; 3684*61ae650dSJack F Vogel } 3685*61ae650dSJack F Vogel 3686*61ae650dSJack F Vogel static void 3687*61ae650dSJack F Vogel ixl_enable_queue(struct i40e_hw *hw, int id) 3688*61ae650dSJack F Vogel { 3689*61ae650dSJack F Vogel u32 reg; 3690*61ae650dSJack F Vogel 3691*61ae650dSJack F Vogel reg = I40E_PFINT_DYN_CTLN_INTENA_MASK | 3692*61ae650dSJack F Vogel I40E_PFINT_DYN_CTLN_CLEARPBA_MASK | 3693*61ae650dSJack F Vogel (IXL_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT); 3694*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_DYN_CTLN(id), reg); 3695*61ae650dSJack F Vogel } 3696*61ae650dSJack F Vogel 3697*61ae650dSJack F Vogel static void 3698*61ae650dSJack F Vogel ixl_disable_queue(struct i40e_hw *hw, int id) 3699*61ae650dSJack F Vogel { 3700*61ae650dSJack F Vogel u32 reg; 3701*61ae650dSJack F Vogel 3702*61ae650dSJack F Vogel reg = IXL_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT; 3703*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_DYN_CTLN(id), reg); 3704*61ae650dSJack F Vogel 3705*61ae650dSJack F Vogel return; 3706*61ae650dSJack F Vogel } 3707*61ae650dSJack F Vogel 3708*61ae650dSJack F Vogel static void 3709*61ae650dSJack F Vogel ixl_enable_legacy(struct i40e_hw *hw) 3710*61ae650dSJack F Vogel { 3711*61ae650dSJack F Vogel u32 reg; 3712*61ae650dSJack F Vogel reg = I40E_PFINT_DYN_CTL0_INTENA_MASK | 3713*61ae650dSJack F Vogel I40E_PFINT_DYN_CTL0_CLEARPBA_MASK | 3714*61ae650dSJack F Vogel (IXL_ITR_NONE << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT); 3715*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_DYN_CTL0, reg); 3716*61ae650dSJack F Vogel } 3717*61ae650dSJack F Vogel 3718*61ae650dSJack F Vogel static void 3719*61ae650dSJack F Vogel ixl_disable_legacy(struct i40e_hw *hw) 3720*61ae650dSJack F Vogel { 3721*61ae650dSJack F Vogel u32 reg; 3722*61ae650dSJack F Vogel 3723*61ae650dSJack F Vogel reg = IXL_ITR_NONE << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT; 3724*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_DYN_CTL0, reg); 3725*61ae650dSJack F Vogel 3726*61ae650dSJack F Vogel return; 3727*61ae650dSJack F Vogel } 3728*61ae650dSJack F Vogel 3729*61ae650dSJack F Vogel static void 3730*61ae650dSJack F Vogel ixl_update_stats_counters(struct ixl_pf *pf) 3731*61ae650dSJack F Vogel { 3732*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 3733*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 3734*61ae650dSJack F Vogel struct ifnet *ifp = vsi->ifp; 3735*61ae650dSJack F Vogel 3736*61ae650dSJack F Vogel struct i40e_hw_port_stats *nsd = &pf->stats; 3737*61ae650dSJack F Vogel struct i40e_hw_port_stats *osd = &pf->stats_offsets; 3738*61ae650dSJack F Vogel 3739*61ae650dSJack F Vogel /* Update hw stats */ 3740*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_CRCERRS(hw->port), 3741*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3742*61ae650dSJack F Vogel &osd->crc_errors, &nsd->crc_errors); 3743*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_ILLERRC(hw->port), 3744*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3745*61ae650dSJack F Vogel &osd->illegal_bytes, &nsd->illegal_bytes); 3746*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_GORCH(hw->port), 3747*61ae650dSJack F Vogel I40E_GLPRT_GORCL(hw->port), 3748*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3749*61ae650dSJack F Vogel &osd->eth.rx_bytes, &nsd->eth.rx_bytes); 3750*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_GOTCH(hw->port), 3751*61ae650dSJack F Vogel I40E_GLPRT_GOTCL(hw->port), 3752*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3753*61ae650dSJack F Vogel &osd->eth.tx_bytes, &nsd->eth.tx_bytes); 3754*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_RDPC(hw->port), 3755*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3756*61ae650dSJack F Vogel &osd->eth.rx_discards, 3757*61ae650dSJack F Vogel &nsd->eth.rx_discards); 3758*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_TDPC(hw->port), 3759*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3760*61ae650dSJack F Vogel &osd->eth.tx_discards, 3761*61ae650dSJack F Vogel &nsd->eth.tx_discards); 3762*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_UPRCH(hw->port), 3763*61ae650dSJack F Vogel I40E_GLPRT_UPRCL(hw->port), 3764*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3765*61ae650dSJack F Vogel &osd->eth.rx_unicast, 3766*61ae650dSJack F Vogel &nsd->eth.rx_unicast); 3767*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_UPTCH(hw->port), 3768*61ae650dSJack F Vogel I40E_GLPRT_UPTCL(hw->port), 3769*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3770*61ae650dSJack F Vogel &osd->eth.tx_unicast, 3771*61ae650dSJack F Vogel &nsd->eth.tx_unicast); 3772*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_MPRCH(hw->port), 3773*61ae650dSJack F Vogel I40E_GLPRT_MPRCL(hw->port), 3774*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3775*61ae650dSJack F Vogel &osd->eth.rx_multicast, 3776*61ae650dSJack F Vogel &nsd->eth.rx_multicast); 3777*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_MPTCH(hw->port), 3778*61ae650dSJack F Vogel I40E_GLPRT_MPTCL(hw->port), 3779*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3780*61ae650dSJack F Vogel &osd->eth.tx_multicast, 3781*61ae650dSJack F Vogel &nsd->eth.tx_multicast); 3782*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_BPRCH(hw->port), 3783*61ae650dSJack F Vogel I40E_GLPRT_BPRCL(hw->port), 3784*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3785*61ae650dSJack F Vogel &osd->eth.rx_broadcast, 3786*61ae650dSJack F Vogel &nsd->eth.rx_broadcast); 3787*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_BPTCH(hw->port), 3788*61ae650dSJack F Vogel I40E_GLPRT_BPTCL(hw->port), 3789*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3790*61ae650dSJack F Vogel &osd->eth.tx_broadcast, 3791*61ae650dSJack F Vogel &nsd->eth.tx_broadcast); 3792*61ae650dSJack F Vogel 3793*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_TDOLD(hw->port), 3794*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3795*61ae650dSJack F Vogel &osd->tx_dropped_link_down, 3796*61ae650dSJack F Vogel &nsd->tx_dropped_link_down); 3797*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_MLFC(hw->port), 3798*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3799*61ae650dSJack F Vogel &osd->mac_local_faults, 3800*61ae650dSJack F Vogel &nsd->mac_local_faults); 3801*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_MRFC(hw->port), 3802*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3803*61ae650dSJack F Vogel &osd->mac_remote_faults, 3804*61ae650dSJack F Vogel &nsd->mac_remote_faults); 3805*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_RLEC(hw->port), 3806*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3807*61ae650dSJack F Vogel &osd->rx_length_errors, 3808*61ae650dSJack F Vogel &nsd->rx_length_errors); 3809*61ae650dSJack F Vogel 3810*61ae650dSJack F Vogel /* Flow control (LFC) stats */ 3811*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_LXONRXC(hw->port), 3812*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3813*61ae650dSJack F Vogel &osd->link_xon_rx, &nsd->link_xon_rx); 3814*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_LXONTXC(hw->port), 3815*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3816*61ae650dSJack F Vogel &osd->link_xon_tx, &nsd->link_xon_tx); 3817*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_LXOFFRXC(hw->port), 3818*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3819*61ae650dSJack F Vogel &osd->link_xoff_rx, &nsd->link_xoff_rx); 3820*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_LXOFFTXC(hw->port), 3821*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3822*61ae650dSJack F Vogel &osd->link_xoff_tx, &nsd->link_xoff_tx); 3823*61ae650dSJack F Vogel 3824*61ae650dSJack F Vogel /* Priority flow control stats */ 3825*61ae650dSJack F Vogel #if 0 3826*61ae650dSJack F Vogel for (int i = 0; i < 8; i++) { 3827*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_PXONRXC(hw->port, i), 3828*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3829*61ae650dSJack F Vogel &osd->priority_xon_rx[i], 3830*61ae650dSJack F Vogel &nsd->priority_xon_rx[i]); 3831*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_PXONTXC(hw->port, i), 3832*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3833*61ae650dSJack F Vogel &osd->priority_xon_tx[i], 3834*61ae650dSJack F Vogel &nsd->priority_xon_tx[i]); 3835*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_PXOFFTXC(hw->port, i), 3836*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3837*61ae650dSJack F Vogel &osd->priority_xoff_tx[i], 3838*61ae650dSJack F Vogel &nsd->priority_xoff_tx[i]); 3839*61ae650dSJack F Vogel ixl_stat_update32(hw, 3840*61ae650dSJack F Vogel I40E_GLPRT_RXON2OFFCNT(hw->port, i), 3841*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3842*61ae650dSJack F Vogel &osd->priority_xon_2_xoff[i], 3843*61ae650dSJack F Vogel &nsd->priority_xon_2_xoff[i]); 3844*61ae650dSJack F Vogel } 3845*61ae650dSJack F Vogel #endif 3846*61ae650dSJack F Vogel 3847*61ae650dSJack F Vogel /* Packet size stats rx */ 3848*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PRC64H(hw->port), 3849*61ae650dSJack F Vogel I40E_GLPRT_PRC64L(hw->port), 3850*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3851*61ae650dSJack F Vogel &osd->rx_size_64, &nsd->rx_size_64); 3852*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PRC127H(hw->port), 3853*61ae650dSJack F Vogel I40E_GLPRT_PRC127L(hw->port), 3854*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3855*61ae650dSJack F Vogel &osd->rx_size_127, &nsd->rx_size_127); 3856*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PRC255H(hw->port), 3857*61ae650dSJack F Vogel I40E_GLPRT_PRC255L(hw->port), 3858*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3859*61ae650dSJack F Vogel &osd->rx_size_255, &nsd->rx_size_255); 3860*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PRC511H(hw->port), 3861*61ae650dSJack F Vogel I40E_GLPRT_PRC511L(hw->port), 3862*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3863*61ae650dSJack F Vogel &osd->rx_size_511, &nsd->rx_size_511); 3864*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PRC1023H(hw->port), 3865*61ae650dSJack F Vogel I40E_GLPRT_PRC1023L(hw->port), 3866*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3867*61ae650dSJack F Vogel &osd->rx_size_1023, &nsd->rx_size_1023); 3868*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PRC1522H(hw->port), 3869*61ae650dSJack F Vogel I40E_GLPRT_PRC1522L(hw->port), 3870*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3871*61ae650dSJack F Vogel &osd->rx_size_1522, &nsd->rx_size_1522); 3872*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PRC9522H(hw->port), 3873*61ae650dSJack F Vogel I40E_GLPRT_PRC9522L(hw->port), 3874*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3875*61ae650dSJack F Vogel &osd->rx_size_big, &nsd->rx_size_big); 3876*61ae650dSJack F Vogel 3877*61ae650dSJack F Vogel /* Packet size stats tx */ 3878*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PTC64H(hw->port), 3879*61ae650dSJack F Vogel I40E_GLPRT_PTC64L(hw->port), 3880*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3881*61ae650dSJack F Vogel &osd->tx_size_64, &nsd->tx_size_64); 3882*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PTC127H(hw->port), 3883*61ae650dSJack F Vogel I40E_GLPRT_PTC127L(hw->port), 3884*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3885*61ae650dSJack F Vogel &osd->tx_size_127, &nsd->tx_size_127); 3886*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PTC255H(hw->port), 3887*61ae650dSJack F Vogel I40E_GLPRT_PTC255L(hw->port), 3888*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3889*61ae650dSJack F Vogel &osd->tx_size_255, &nsd->tx_size_255); 3890*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PTC511H(hw->port), 3891*61ae650dSJack F Vogel I40E_GLPRT_PTC511L(hw->port), 3892*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3893*61ae650dSJack F Vogel &osd->tx_size_511, &nsd->tx_size_511); 3894*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PTC1023H(hw->port), 3895*61ae650dSJack F Vogel I40E_GLPRT_PTC1023L(hw->port), 3896*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3897*61ae650dSJack F Vogel &osd->tx_size_1023, &nsd->tx_size_1023); 3898*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PTC1522H(hw->port), 3899*61ae650dSJack F Vogel I40E_GLPRT_PTC1522L(hw->port), 3900*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3901*61ae650dSJack F Vogel &osd->tx_size_1522, &nsd->tx_size_1522); 3902*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLPRT_PTC9522H(hw->port), 3903*61ae650dSJack F Vogel I40E_GLPRT_PTC9522L(hw->port), 3904*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3905*61ae650dSJack F Vogel &osd->tx_size_big, &nsd->tx_size_big); 3906*61ae650dSJack F Vogel 3907*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_RUC(hw->port), 3908*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3909*61ae650dSJack F Vogel &osd->rx_undersize, &nsd->rx_undersize); 3910*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_RFC(hw->port), 3911*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3912*61ae650dSJack F Vogel &osd->rx_fragments, &nsd->rx_fragments); 3913*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_ROC(hw->port), 3914*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3915*61ae650dSJack F Vogel &osd->rx_oversize, &nsd->rx_oversize); 3916*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLPRT_RJC(hw->port), 3917*61ae650dSJack F Vogel pf->stat_offsets_loaded, 3918*61ae650dSJack F Vogel &osd->rx_jabber, &nsd->rx_jabber); 3919*61ae650dSJack F Vogel pf->stat_offsets_loaded = true; 3920*61ae650dSJack F Vogel /* End hw stats */ 3921*61ae650dSJack F Vogel 3922*61ae650dSJack F Vogel /* Update vsi stats */ 3923*61ae650dSJack F Vogel ixl_update_eth_stats(vsi); 3924*61ae650dSJack F Vogel 3925*61ae650dSJack F Vogel /* OS statistics */ 3926*61ae650dSJack F Vogel // ERJ - these are per-port, update all vsis? 3927*61ae650dSJack F Vogel ifp->if_ierrors = nsd->crc_errors + nsd->illegal_bytes; 3928*61ae650dSJack F Vogel } 3929*61ae650dSJack F Vogel 3930*61ae650dSJack F Vogel /* 3931*61ae650dSJack F Vogel ** Tasklet handler for MSIX Adminq interrupts 3932*61ae650dSJack F Vogel ** - do outside interrupt since it might sleep 3933*61ae650dSJack F Vogel */ 3934*61ae650dSJack F Vogel static void 3935*61ae650dSJack F Vogel ixl_do_adminq(void *context, int pending) 3936*61ae650dSJack F Vogel { 3937*61ae650dSJack F Vogel struct ixl_pf *pf = context; 3938*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 3939*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 3940*61ae650dSJack F Vogel struct i40e_arq_event_info event; 3941*61ae650dSJack F Vogel i40e_status ret; 3942*61ae650dSJack F Vogel u32 reg, loop = 0; 3943*61ae650dSJack F Vogel u16 opcode, result; 3944*61ae650dSJack F Vogel 3945*61ae650dSJack F Vogel event.msg_len = IXL_AQ_BUF_SZ; 3946*61ae650dSJack F Vogel event.msg_buf = malloc(event.msg_len, 3947*61ae650dSJack F Vogel M_DEVBUF, M_NOWAIT | M_ZERO); 3948*61ae650dSJack F Vogel if (!event.msg_buf) { 3949*61ae650dSJack F Vogel printf("Unable to allocate adminq memory\n"); 3950*61ae650dSJack F Vogel return; 3951*61ae650dSJack F Vogel } 3952*61ae650dSJack F Vogel 3953*61ae650dSJack F Vogel /* clean and process any events */ 3954*61ae650dSJack F Vogel do { 3955*61ae650dSJack F Vogel ret = i40e_clean_arq_element(hw, &event, &result); 3956*61ae650dSJack F Vogel if (ret) 3957*61ae650dSJack F Vogel break; 3958*61ae650dSJack F Vogel opcode = LE16_TO_CPU(event.desc.opcode); 3959*61ae650dSJack F Vogel switch (opcode) { 3960*61ae650dSJack F Vogel case i40e_aqc_opc_get_link_status: 3961*61ae650dSJack F Vogel vsi->link_up = ixl_config_link(hw); 3962*61ae650dSJack F Vogel ixl_update_link_status(pf); 3963*61ae650dSJack F Vogel break; 3964*61ae650dSJack F Vogel case i40e_aqc_opc_send_msg_to_pf: 3965*61ae650dSJack F Vogel /* process pf/vf communication here */ 3966*61ae650dSJack F Vogel break; 3967*61ae650dSJack F Vogel case i40e_aqc_opc_event_lan_overflow: 3968*61ae650dSJack F Vogel break; 3969*61ae650dSJack F Vogel default: 3970*61ae650dSJack F Vogel #ifdef IXL_DEBUG 3971*61ae650dSJack F Vogel printf("AdminQ unknown event %x\n", opcode); 3972*61ae650dSJack F Vogel #endif 3973*61ae650dSJack F Vogel break; 3974*61ae650dSJack F Vogel } 3975*61ae650dSJack F Vogel 3976*61ae650dSJack F Vogel } while (result && (loop++ < IXL_ADM_LIMIT)); 3977*61ae650dSJack F Vogel 3978*61ae650dSJack F Vogel reg = rd32(hw, I40E_PFINT_ICR0_ENA); 3979*61ae650dSJack F Vogel reg |= I40E_PFINT_ICR0_ENA_ADMINQ_MASK; 3980*61ae650dSJack F Vogel wr32(hw, I40E_PFINT_ICR0_ENA, reg); 3981*61ae650dSJack F Vogel free(event.msg_buf, M_DEVBUF); 3982*61ae650dSJack F Vogel 3983*61ae650dSJack F Vogel if (pf->msix > 1) 3984*61ae650dSJack F Vogel ixl_enable_adminq(&pf->hw); 3985*61ae650dSJack F Vogel else 3986*61ae650dSJack F Vogel ixl_enable_intr(vsi); 3987*61ae650dSJack F Vogel } 3988*61ae650dSJack F Vogel 3989*61ae650dSJack F Vogel static int 3990*61ae650dSJack F Vogel ixl_debug_info(SYSCTL_HANDLER_ARGS) 3991*61ae650dSJack F Vogel { 3992*61ae650dSJack F Vogel struct ixl_pf *pf; 3993*61ae650dSJack F Vogel int error, input = 0; 3994*61ae650dSJack F Vogel 3995*61ae650dSJack F Vogel error = sysctl_handle_int(oidp, &input, 0, req); 3996*61ae650dSJack F Vogel 3997*61ae650dSJack F Vogel if (error || !req->newptr) 3998*61ae650dSJack F Vogel return (error); 3999*61ae650dSJack F Vogel 4000*61ae650dSJack F Vogel if (input == 1) { 4001*61ae650dSJack F Vogel pf = (struct ixl_pf *)arg1; 4002*61ae650dSJack F Vogel ixl_print_debug_info(pf); 4003*61ae650dSJack F Vogel } 4004*61ae650dSJack F Vogel 4005*61ae650dSJack F Vogel return (error); 4006*61ae650dSJack F Vogel } 4007*61ae650dSJack F Vogel 4008*61ae650dSJack F Vogel static void 4009*61ae650dSJack F Vogel ixl_print_debug_info(struct ixl_pf *pf) 4010*61ae650dSJack F Vogel { 4011*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 4012*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 4013*61ae650dSJack F Vogel struct ixl_queue *que = vsi->queues; 4014*61ae650dSJack F Vogel struct rx_ring *rxr = &que->rxr; 4015*61ae650dSJack F Vogel struct tx_ring *txr = &que->txr; 4016*61ae650dSJack F Vogel u32 reg; 4017*61ae650dSJack F Vogel 4018*61ae650dSJack F Vogel 4019*61ae650dSJack F Vogel printf("Queue irqs = %lx\n", que->irqs); 4020*61ae650dSJack F Vogel printf("AdminQ irqs = %lx\n", pf->admin_irq); 4021*61ae650dSJack F Vogel printf("RX next check = %x\n", rxr->next_check); 4022*61ae650dSJack F Vogel printf("RX not ready = %lx\n", rxr->not_done); 4023*61ae650dSJack F Vogel printf("RX packets = %lx\n", rxr->rx_packets); 4024*61ae650dSJack F Vogel printf("TX desc avail = %x\n", txr->avail); 4025*61ae650dSJack F Vogel 4026*61ae650dSJack F Vogel reg = rd32(hw, I40E_GLV_GORCL(0xc)); 4027*61ae650dSJack F Vogel printf("RX Bytes = %x\n", reg); 4028*61ae650dSJack F Vogel reg = rd32(hw, I40E_GLPRT_GORCL(hw->port)); 4029*61ae650dSJack F Vogel printf("Port RX Bytes = %x\n", reg); 4030*61ae650dSJack F Vogel reg = rd32(hw, I40E_GLV_RDPC(0xc)); 4031*61ae650dSJack F Vogel printf("RX discard = %x\n", reg); 4032*61ae650dSJack F Vogel reg = rd32(hw, I40E_GLPRT_RDPC(hw->port)); 4033*61ae650dSJack F Vogel printf("Port RX discard = %x\n", reg); 4034*61ae650dSJack F Vogel 4035*61ae650dSJack F Vogel reg = rd32(hw, I40E_GLV_TEPC(0xc)); 4036*61ae650dSJack F Vogel printf("TX errors = %x\n", reg); 4037*61ae650dSJack F Vogel reg = rd32(hw, I40E_GLV_GOTCL(0xc)); 4038*61ae650dSJack F Vogel printf("TX Bytes = %x\n", reg); 4039*61ae650dSJack F Vogel 4040*61ae650dSJack F Vogel reg = rd32(hw, I40E_GLPRT_RUC(hw->port)); 4041*61ae650dSJack F Vogel printf("RX undersize = %x\n", reg); 4042*61ae650dSJack F Vogel reg = rd32(hw, I40E_GLPRT_RFC(hw->port)); 4043*61ae650dSJack F Vogel printf("RX fragments = %x\n", reg); 4044*61ae650dSJack F Vogel reg = rd32(hw, I40E_GLPRT_ROC(hw->port)); 4045*61ae650dSJack F Vogel printf("RX oversize = %x\n", reg); 4046*61ae650dSJack F Vogel reg = rd32(hw, I40E_GLPRT_RLEC(hw->port)); 4047*61ae650dSJack F Vogel printf("RX length error = %x\n", reg); 4048*61ae650dSJack F Vogel reg = rd32(hw, I40E_GLPRT_MRFC(hw->port)); 4049*61ae650dSJack F Vogel printf("mac remote fault = %x\n", reg); 4050*61ae650dSJack F Vogel reg = rd32(hw, I40E_GLPRT_MLFC(hw->port)); 4051*61ae650dSJack F Vogel printf("mac local fault = %x\n", reg); 4052*61ae650dSJack F Vogel } 4053*61ae650dSJack F Vogel 4054*61ae650dSJack F Vogel /** 4055*61ae650dSJack F Vogel * Update VSI-specific ethernet statistics counters. 4056*61ae650dSJack F Vogel **/ 4057*61ae650dSJack F Vogel void ixl_update_eth_stats(struct ixl_vsi *vsi) 4058*61ae650dSJack F Vogel { 4059*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)vsi->back; 4060*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 4061*61ae650dSJack F Vogel struct ifnet *ifp = vsi->ifp; 4062*61ae650dSJack F Vogel struct i40e_eth_stats *es; 4063*61ae650dSJack F Vogel struct i40e_eth_stats *oes; 4064*61ae650dSJack F Vogel u16 stat_idx = vsi->info.stat_counter_idx; 4065*61ae650dSJack F Vogel 4066*61ae650dSJack F Vogel es = &vsi->eth_stats; 4067*61ae650dSJack F Vogel oes = &vsi->eth_stats_offsets; 4068*61ae650dSJack F Vogel 4069*61ae650dSJack F Vogel /* Gather up the stats that the hw collects */ 4070*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLV_TEPC(stat_idx), 4071*61ae650dSJack F Vogel vsi->stat_offsets_loaded, 4072*61ae650dSJack F Vogel &oes->tx_errors, &es->tx_errors); 4073*61ae650dSJack F Vogel ixl_stat_update32(hw, I40E_GLV_RDPC(stat_idx), 4074*61ae650dSJack F Vogel vsi->stat_offsets_loaded, 4075*61ae650dSJack F Vogel &oes->rx_discards, &es->rx_discards); 4076*61ae650dSJack F Vogel 4077*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLV_GORCH(stat_idx), 4078*61ae650dSJack F Vogel I40E_GLV_GORCL(stat_idx), 4079*61ae650dSJack F Vogel vsi->stat_offsets_loaded, 4080*61ae650dSJack F Vogel &oes->rx_bytes, &es->rx_bytes); 4081*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLV_UPRCH(stat_idx), 4082*61ae650dSJack F Vogel I40E_GLV_UPRCL(stat_idx), 4083*61ae650dSJack F Vogel vsi->stat_offsets_loaded, 4084*61ae650dSJack F Vogel &oes->rx_unicast, &es->rx_unicast); 4085*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLV_MPRCH(stat_idx), 4086*61ae650dSJack F Vogel I40E_GLV_MPRCL(stat_idx), 4087*61ae650dSJack F Vogel vsi->stat_offsets_loaded, 4088*61ae650dSJack F Vogel &oes->rx_multicast, &es->rx_multicast); 4089*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLV_BPRCH(stat_idx), 4090*61ae650dSJack F Vogel I40E_GLV_BPRCL(stat_idx), 4091*61ae650dSJack F Vogel vsi->stat_offsets_loaded, 4092*61ae650dSJack F Vogel &oes->rx_broadcast, &es->rx_broadcast); 4093*61ae650dSJack F Vogel 4094*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLV_GOTCH(stat_idx), 4095*61ae650dSJack F Vogel I40E_GLV_GOTCL(stat_idx), 4096*61ae650dSJack F Vogel vsi->stat_offsets_loaded, 4097*61ae650dSJack F Vogel &oes->tx_bytes, &es->tx_bytes); 4098*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLV_UPTCH(stat_idx), 4099*61ae650dSJack F Vogel I40E_GLV_UPTCL(stat_idx), 4100*61ae650dSJack F Vogel vsi->stat_offsets_loaded, 4101*61ae650dSJack F Vogel &oes->tx_unicast, &es->tx_unicast); 4102*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLV_MPTCH(stat_idx), 4103*61ae650dSJack F Vogel I40E_GLV_MPTCL(stat_idx), 4104*61ae650dSJack F Vogel vsi->stat_offsets_loaded, 4105*61ae650dSJack F Vogel &oes->tx_multicast, &es->tx_multicast); 4106*61ae650dSJack F Vogel ixl_stat_update48(hw, I40E_GLV_BPTCH(stat_idx), 4107*61ae650dSJack F Vogel I40E_GLV_BPTCL(stat_idx), 4108*61ae650dSJack F Vogel vsi->stat_offsets_loaded, 4109*61ae650dSJack F Vogel &oes->tx_broadcast, &es->tx_broadcast); 4110*61ae650dSJack F Vogel vsi->stat_offsets_loaded = true; 4111*61ae650dSJack F Vogel 4112*61ae650dSJack F Vogel /* Update ifnet stats */ 4113*61ae650dSJack F Vogel ifp->if_ipackets = es->rx_unicast + 4114*61ae650dSJack F Vogel es->rx_multicast + 4115*61ae650dSJack F Vogel es->rx_broadcast; 4116*61ae650dSJack F Vogel ifp->if_opackets = es->tx_unicast + 4117*61ae650dSJack F Vogel es->tx_multicast + 4118*61ae650dSJack F Vogel es->tx_broadcast; 4119*61ae650dSJack F Vogel ifp->if_ibytes = es->rx_bytes; 4120*61ae650dSJack F Vogel ifp->if_obytes = es->tx_bytes; 4121*61ae650dSJack F Vogel ifp->if_imcasts = es->rx_multicast; 4122*61ae650dSJack F Vogel ifp->if_omcasts = es->tx_multicast; 4123*61ae650dSJack F Vogel 4124*61ae650dSJack F Vogel ifp->if_oerrors = es->tx_errors; 4125*61ae650dSJack F Vogel ifp->if_iqdrops = es->rx_discards; 4126*61ae650dSJack F Vogel ifp->if_noproto = es->rx_unknown_protocol; 4127*61ae650dSJack F Vogel ifp->if_collisions = 0; 4128*61ae650dSJack F Vogel } 4129*61ae650dSJack F Vogel 4130*61ae650dSJack F Vogel /** 4131*61ae650dSJack F Vogel * Reset all of the stats for the given pf 4132*61ae650dSJack F Vogel **/ 4133*61ae650dSJack F Vogel void ixl_pf_reset_stats(struct ixl_pf *pf) 4134*61ae650dSJack F Vogel { 4135*61ae650dSJack F Vogel bzero(&pf->stats, sizeof(struct i40e_hw_port_stats)); 4136*61ae650dSJack F Vogel bzero(&pf->stats_offsets, sizeof(struct i40e_hw_port_stats)); 4137*61ae650dSJack F Vogel pf->stat_offsets_loaded = false; 4138*61ae650dSJack F Vogel } 4139*61ae650dSJack F Vogel 4140*61ae650dSJack F Vogel /** 4141*61ae650dSJack F Vogel * Resets all stats of the given vsi 4142*61ae650dSJack F Vogel **/ 4143*61ae650dSJack F Vogel void ixl_vsi_reset_stats(struct ixl_vsi *vsi) 4144*61ae650dSJack F Vogel { 4145*61ae650dSJack F Vogel bzero(&vsi->eth_stats, sizeof(struct i40e_eth_stats)); 4146*61ae650dSJack F Vogel bzero(&vsi->eth_stats_offsets, sizeof(struct i40e_eth_stats)); 4147*61ae650dSJack F Vogel vsi->stat_offsets_loaded = false; 4148*61ae650dSJack F Vogel } 4149*61ae650dSJack F Vogel 4150*61ae650dSJack F Vogel /** 4151*61ae650dSJack F Vogel * Read and update a 48 bit stat from the hw 4152*61ae650dSJack F Vogel * 4153*61ae650dSJack F Vogel * Since the device stats are not reset at PFReset, they likely will not 4154*61ae650dSJack F Vogel * be zeroed when the driver starts. We'll save the first values read 4155*61ae650dSJack F Vogel * and use them as offsets to be subtracted from the raw values in order 4156*61ae650dSJack F Vogel * to report stats that count from zero. 4157*61ae650dSJack F Vogel **/ 4158*61ae650dSJack F Vogel static void 4159*61ae650dSJack F Vogel ixl_stat_update48(struct i40e_hw *hw, u32 hireg, u32 loreg, 4160*61ae650dSJack F Vogel bool offset_loaded, u64 *offset, u64 *stat) 4161*61ae650dSJack F Vogel { 4162*61ae650dSJack F Vogel u64 new_data; 4163*61ae650dSJack F Vogel 4164*61ae650dSJack F Vogel #if __FreeBSD__ >= 10 && __amd64__ 4165*61ae650dSJack F Vogel new_data = rd64(hw, loreg); 4166*61ae650dSJack F Vogel #else 4167*61ae650dSJack F Vogel /* 4168*61ae650dSJack F Vogel * Use two rd32's instead of one rd64; FreeBSD versions before 4169*61ae650dSJack F Vogel * 10 don't support 8 byte bus reads/writes. 4170*61ae650dSJack F Vogel */ 4171*61ae650dSJack F Vogel new_data = rd32(hw, loreg); 4172*61ae650dSJack F Vogel new_data |= ((u64)(rd32(hw, hireg) & 0xFFFF)) << 32; 4173*61ae650dSJack F Vogel #endif 4174*61ae650dSJack F Vogel 4175*61ae650dSJack F Vogel if (!offset_loaded) 4176*61ae650dSJack F Vogel *offset = new_data; 4177*61ae650dSJack F Vogel if (new_data >= *offset) 4178*61ae650dSJack F Vogel *stat = new_data - *offset; 4179*61ae650dSJack F Vogel else 4180*61ae650dSJack F Vogel *stat = (new_data + ((u64)1 << 48)) - *offset; 4181*61ae650dSJack F Vogel *stat &= 0xFFFFFFFFFFFFULL; 4182*61ae650dSJack F Vogel } 4183*61ae650dSJack F Vogel 4184*61ae650dSJack F Vogel /** 4185*61ae650dSJack F Vogel * Read and update a 32 bit stat from the hw 4186*61ae650dSJack F Vogel **/ 4187*61ae650dSJack F Vogel static void 4188*61ae650dSJack F Vogel ixl_stat_update32(struct i40e_hw *hw, u32 reg, 4189*61ae650dSJack F Vogel bool offset_loaded, u64 *offset, u64 *stat) 4190*61ae650dSJack F Vogel { 4191*61ae650dSJack F Vogel u32 new_data; 4192*61ae650dSJack F Vogel 4193*61ae650dSJack F Vogel new_data = rd32(hw, reg); 4194*61ae650dSJack F Vogel if (!offset_loaded) 4195*61ae650dSJack F Vogel *offset = new_data; 4196*61ae650dSJack F Vogel if (new_data >= *offset) 4197*61ae650dSJack F Vogel *stat = (u32)(new_data - *offset); 4198*61ae650dSJack F Vogel else 4199*61ae650dSJack F Vogel *stat = (u32)((new_data + ((u64)1 << 32)) - *offset); 4200*61ae650dSJack F Vogel } 4201*61ae650dSJack F Vogel 4202*61ae650dSJack F Vogel /* 4203*61ae650dSJack F Vogel ** Set flow control using sysctl: 4204*61ae650dSJack F Vogel ** 0 - off 4205*61ae650dSJack F Vogel ** 1 - rx pause 4206*61ae650dSJack F Vogel ** 2 - tx pause 4207*61ae650dSJack F Vogel ** 3 - full 4208*61ae650dSJack F Vogel */ 4209*61ae650dSJack F Vogel static int 4210*61ae650dSJack F Vogel ixl_set_flowcntl(SYSCTL_HANDLER_ARGS) 4211*61ae650dSJack F Vogel { 4212*61ae650dSJack F Vogel /* 4213*61ae650dSJack F Vogel * TODO: ensure flow control is disabled if 4214*61ae650dSJack F Vogel * priority flow control is enabled 4215*61ae650dSJack F Vogel * 4216*61ae650dSJack F Vogel * TODO: ensure tx CRC by hardware should be enabled 4217*61ae650dSJack F Vogel * if tx flow control is enabled. 4218*61ae650dSJack F Vogel */ 4219*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)arg1; 4220*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 4221*61ae650dSJack F Vogel device_t dev = pf->dev; 4222*61ae650dSJack F Vogel int requested_fc = 0, error = 0; 4223*61ae650dSJack F Vogel enum i40e_status_code aq_error = 0; 4224*61ae650dSJack F Vogel u8 fc_aq_err = 0; 4225*61ae650dSJack F Vogel 4226*61ae650dSJack F Vogel aq_error = i40e_aq_get_link_info(hw, TRUE, NULL, NULL); 4227*61ae650dSJack F Vogel if (aq_error) { 4228*61ae650dSJack F Vogel device_printf(dev, 4229*61ae650dSJack F Vogel "%s: Error retrieving link info from aq, %d\n", 4230*61ae650dSJack F Vogel __func__, aq_error); 4231*61ae650dSJack F Vogel return (EAGAIN); 4232*61ae650dSJack F Vogel } 4233*61ae650dSJack F Vogel 4234*61ae650dSJack F Vogel /* Read in new mode */ 4235*61ae650dSJack F Vogel requested_fc = hw->fc.current_mode; 4236*61ae650dSJack F Vogel error = sysctl_handle_int(oidp, &requested_fc, 0, req); 4237*61ae650dSJack F Vogel if ((error) || (req->newptr == NULL)) 4238*61ae650dSJack F Vogel return (error); 4239*61ae650dSJack F Vogel if (requested_fc < 0 || requested_fc > 3) { 4240*61ae650dSJack F Vogel device_printf(dev, 4241*61ae650dSJack F Vogel "Invalid fc mode; valid modes are 0 through 3\n"); 4242*61ae650dSJack F Vogel return (EINVAL); 4243*61ae650dSJack F Vogel } 4244*61ae650dSJack F Vogel 4245*61ae650dSJack F Vogel /* 4246*61ae650dSJack F Vogel ** Changing flow control mode currently does not work on 4247*61ae650dSJack F Vogel ** 40GBASE-CR4 PHYs 4248*61ae650dSJack F Vogel */ 4249*61ae650dSJack F Vogel if (hw->phy.link_info.phy_type == I40E_PHY_TYPE_40GBASE_CR4 4250*61ae650dSJack F Vogel || hw->phy.link_info.phy_type == I40E_PHY_TYPE_40GBASE_CR4_CU) { 4251*61ae650dSJack F Vogel device_printf(dev, "Changing flow control mode unsupported" 4252*61ae650dSJack F Vogel " on 40GBase-CR4 media.\n"); 4253*61ae650dSJack F Vogel return (ENODEV); 4254*61ae650dSJack F Vogel } 4255*61ae650dSJack F Vogel 4256*61ae650dSJack F Vogel /* Set fc ability for port */ 4257*61ae650dSJack F Vogel hw->fc.requested_mode = requested_fc; 4258*61ae650dSJack F Vogel aq_error = i40e_set_fc(hw, &fc_aq_err, TRUE); 4259*61ae650dSJack F Vogel if (aq_error) { 4260*61ae650dSJack F Vogel device_printf(dev, 4261*61ae650dSJack F Vogel "%s: Error setting new fc mode %d; fc_err %#x\n", 4262*61ae650dSJack F Vogel __func__, aq_error, fc_aq_err); 4263*61ae650dSJack F Vogel return (EAGAIN); 4264*61ae650dSJack F Vogel } 4265*61ae650dSJack F Vogel 4266*61ae650dSJack F Vogel if (hw->fc.current_mode != hw->fc.requested_mode) { 4267*61ae650dSJack F Vogel device_printf(dev, "%s: FC set failure:\n", __func__); 4268*61ae650dSJack F Vogel device_printf(dev, "%s: Current: %s / Requested: %s\n", 4269*61ae650dSJack F Vogel __func__, 4270*61ae650dSJack F Vogel ixl_fc_string[hw->fc.current_mode], 4271*61ae650dSJack F Vogel ixl_fc_string[hw->fc.requested_mode]); 4272*61ae650dSJack F Vogel } 4273*61ae650dSJack F Vogel 4274*61ae650dSJack F Vogel return (0); 4275*61ae650dSJack F Vogel } 4276*61ae650dSJack F Vogel 4277*61ae650dSJack F Vogel static int 4278*61ae650dSJack F Vogel ixl_current_speed(SYSCTL_HANDLER_ARGS) 4279*61ae650dSJack F Vogel { 4280*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)arg1; 4281*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 4282*61ae650dSJack F Vogel int error = 0, index = 0; 4283*61ae650dSJack F Vogel 4284*61ae650dSJack F Vogel char *speeds[] = { 4285*61ae650dSJack F Vogel "Unknown", 4286*61ae650dSJack F Vogel "100M", 4287*61ae650dSJack F Vogel "1G", 4288*61ae650dSJack F Vogel "10G", 4289*61ae650dSJack F Vogel "40G", 4290*61ae650dSJack F Vogel "20G" 4291*61ae650dSJack F Vogel }; 4292*61ae650dSJack F Vogel 4293*61ae650dSJack F Vogel ixl_update_link_status(pf); 4294*61ae650dSJack F Vogel 4295*61ae650dSJack F Vogel switch (hw->phy.link_info.link_speed) { 4296*61ae650dSJack F Vogel case I40E_LINK_SPEED_100MB: 4297*61ae650dSJack F Vogel index = 1; 4298*61ae650dSJack F Vogel break; 4299*61ae650dSJack F Vogel case I40E_LINK_SPEED_1GB: 4300*61ae650dSJack F Vogel index = 2; 4301*61ae650dSJack F Vogel break; 4302*61ae650dSJack F Vogel case I40E_LINK_SPEED_10GB: 4303*61ae650dSJack F Vogel index = 3; 4304*61ae650dSJack F Vogel break; 4305*61ae650dSJack F Vogel case I40E_LINK_SPEED_40GB: 4306*61ae650dSJack F Vogel index = 4; 4307*61ae650dSJack F Vogel break; 4308*61ae650dSJack F Vogel case I40E_LINK_SPEED_20GB: 4309*61ae650dSJack F Vogel index = 5; 4310*61ae650dSJack F Vogel break; 4311*61ae650dSJack F Vogel case I40E_LINK_SPEED_UNKNOWN: 4312*61ae650dSJack F Vogel default: 4313*61ae650dSJack F Vogel index = 0; 4314*61ae650dSJack F Vogel break; 4315*61ae650dSJack F Vogel } 4316*61ae650dSJack F Vogel 4317*61ae650dSJack F Vogel error = sysctl_handle_string(oidp, speeds[index], 4318*61ae650dSJack F Vogel strlen(speeds[index]), req); 4319*61ae650dSJack F Vogel return (error); 4320*61ae650dSJack F Vogel } 4321*61ae650dSJack F Vogel 4322*61ae650dSJack F Vogel /* 4323*61ae650dSJack F Vogel ** Control link advertise speed: 4324*61ae650dSJack F Vogel ** Flags: 4325*61ae650dSJack F Vogel ** 0x1 - advertise 100 Mb 4326*61ae650dSJack F Vogel ** 0x2 - advertise 1G 4327*61ae650dSJack F Vogel ** 0x4 - advertise 10G 4328*61ae650dSJack F Vogel ** 4329*61ae650dSJack F Vogel ** Does not work on 40G devices. 4330*61ae650dSJack F Vogel */ 4331*61ae650dSJack F Vogel static int 4332*61ae650dSJack F Vogel ixl_set_advertise(SYSCTL_HANDLER_ARGS) 4333*61ae650dSJack F Vogel { 4334*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)arg1; 4335*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 4336*61ae650dSJack F Vogel device_t dev = pf->dev; 4337*61ae650dSJack F Vogel struct i40e_aq_get_phy_abilities_resp abilities; 4338*61ae650dSJack F Vogel struct i40e_aq_set_phy_config config; 4339*61ae650dSJack F Vogel int requested_ls = 0; 4340*61ae650dSJack F Vogel enum i40e_status_code aq_error = 0; 4341*61ae650dSJack F Vogel int error = 0; 4342*61ae650dSJack F Vogel 4343*61ae650dSJack F Vogel /* 4344*61ae650dSJack F Vogel ** FW doesn't support changing advertised speed 4345*61ae650dSJack F Vogel ** for 40G devices; speed is always 40G. 4346*61ae650dSJack F Vogel */ 4347*61ae650dSJack F Vogel if (i40e_is_40G_device(hw->device_id)) 4348*61ae650dSJack F Vogel return (ENODEV); 4349*61ae650dSJack F Vogel 4350*61ae650dSJack F Vogel /* Read in new mode */ 4351*61ae650dSJack F Vogel requested_ls = pf->advertised_speed; 4352*61ae650dSJack F Vogel error = sysctl_handle_int(oidp, &requested_ls, 0, req); 4353*61ae650dSJack F Vogel if ((error) || (req->newptr == NULL)) 4354*61ae650dSJack F Vogel return (error); 4355*61ae650dSJack F Vogel if (requested_ls < 1 || requested_ls > 7) { 4356*61ae650dSJack F Vogel device_printf(dev, 4357*61ae650dSJack F Vogel "Invalid advertised speed; valid modes are 0x1 through 0x7\n"); 4358*61ae650dSJack F Vogel return (EINVAL); 4359*61ae650dSJack F Vogel } 4360*61ae650dSJack F Vogel 4361*61ae650dSJack F Vogel /* Exit if no change */ 4362*61ae650dSJack F Vogel if (pf->advertised_speed == requested_ls) 4363*61ae650dSJack F Vogel return (0); 4364*61ae650dSJack F Vogel 4365*61ae650dSJack F Vogel /* Get current capability information */ 4366*61ae650dSJack F Vogel aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, FALSE, &abilities, NULL); 4367*61ae650dSJack F Vogel if (aq_error) { 4368*61ae650dSJack F Vogel device_printf(dev, "%s: Error getting phy capabilities %d," 4369*61ae650dSJack F Vogel " aq error: %d\n", __func__, aq_error, 4370*61ae650dSJack F Vogel hw->aq.asq_last_status); 4371*61ae650dSJack F Vogel return (EAGAIN); 4372*61ae650dSJack F Vogel } 4373*61ae650dSJack F Vogel 4374*61ae650dSJack F Vogel /* Prepare new config */ 4375*61ae650dSJack F Vogel bzero(&config, sizeof(config)); 4376*61ae650dSJack F Vogel config.phy_type = abilities.phy_type; 4377*61ae650dSJack F Vogel config.abilities = abilities.abilities 4378*61ae650dSJack F Vogel | I40E_AQ_PHY_ENABLE_ATOMIC_LINK; 4379*61ae650dSJack F Vogel config.eee_capability = abilities.eee_capability; 4380*61ae650dSJack F Vogel config.eeer = abilities.eeer_val; 4381*61ae650dSJack F Vogel config.low_power_ctrl = abilities.d3_lpan; 4382*61ae650dSJack F Vogel /* Translate into aq cmd link_speed */ 4383*61ae650dSJack F Vogel if (requested_ls & 0x4) 4384*61ae650dSJack F Vogel config.link_speed |= I40E_LINK_SPEED_10GB; 4385*61ae650dSJack F Vogel if (requested_ls & 0x2) 4386*61ae650dSJack F Vogel config.link_speed |= I40E_LINK_SPEED_1GB; 4387*61ae650dSJack F Vogel if (requested_ls & 0x1) 4388*61ae650dSJack F Vogel config.link_speed |= I40E_LINK_SPEED_100MB; 4389*61ae650dSJack F Vogel 4390*61ae650dSJack F Vogel /* Do aq command & restart link */ 4391*61ae650dSJack F Vogel aq_error = i40e_aq_set_phy_config(hw, &config, NULL); 4392*61ae650dSJack F Vogel if (aq_error) { 4393*61ae650dSJack F Vogel device_printf(dev, "%s: Error setting new phy config %d," 4394*61ae650dSJack F Vogel " aq error: %d\n", __func__, aq_error, 4395*61ae650dSJack F Vogel hw->aq.asq_last_status); 4396*61ae650dSJack F Vogel return (EAGAIN); 4397*61ae650dSJack F Vogel } 4398*61ae650dSJack F Vogel 4399*61ae650dSJack F Vogel pf->advertised_speed = requested_ls; 4400*61ae650dSJack F Vogel ixl_update_link_status(pf); 4401*61ae650dSJack F Vogel return (0); 4402*61ae650dSJack F Vogel } 4403*61ae650dSJack F Vogel 4404*61ae650dSJack F Vogel /* 4405*61ae650dSJack F Vogel ** Get the width and transaction speed of 4406*61ae650dSJack F Vogel ** the bus this adapter is plugged into. 4407*61ae650dSJack F Vogel */ 4408*61ae650dSJack F Vogel static u16 4409*61ae650dSJack F Vogel ixl_get_bus_info(struct i40e_hw *hw, device_t dev) 4410*61ae650dSJack F Vogel { 4411*61ae650dSJack F Vogel u16 link; 4412*61ae650dSJack F Vogel u32 offset; 4413*61ae650dSJack F Vogel 4414*61ae650dSJack F Vogel 4415*61ae650dSJack F Vogel /* Get the PCI Express Capabilities offset */ 4416*61ae650dSJack F Vogel pci_find_cap(dev, PCIY_EXPRESS, &offset); 4417*61ae650dSJack F Vogel 4418*61ae650dSJack F Vogel /* ...and read the Link Status Register */ 4419*61ae650dSJack F Vogel link = pci_read_config(dev, offset + PCIER_LINK_STA, 2); 4420*61ae650dSJack F Vogel 4421*61ae650dSJack F Vogel switch (link & I40E_PCI_LINK_WIDTH) { 4422*61ae650dSJack F Vogel case I40E_PCI_LINK_WIDTH_1: 4423*61ae650dSJack F Vogel hw->bus.width = i40e_bus_width_pcie_x1; 4424*61ae650dSJack F Vogel break; 4425*61ae650dSJack F Vogel case I40E_PCI_LINK_WIDTH_2: 4426*61ae650dSJack F Vogel hw->bus.width = i40e_bus_width_pcie_x2; 4427*61ae650dSJack F Vogel break; 4428*61ae650dSJack F Vogel case I40E_PCI_LINK_WIDTH_4: 4429*61ae650dSJack F Vogel hw->bus.width = i40e_bus_width_pcie_x4; 4430*61ae650dSJack F Vogel break; 4431*61ae650dSJack F Vogel case I40E_PCI_LINK_WIDTH_8: 4432*61ae650dSJack F Vogel hw->bus.width = i40e_bus_width_pcie_x8; 4433*61ae650dSJack F Vogel break; 4434*61ae650dSJack F Vogel default: 4435*61ae650dSJack F Vogel hw->bus.width = i40e_bus_width_unknown; 4436*61ae650dSJack F Vogel break; 4437*61ae650dSJack F Vogel } 4438*61ae650dSJack F Vogel 4439*61ae650dSJack F Vogel switch (link & I40E_PCI_LINK_SPEED) { 4440*61ae650dSJack F Vogel case I40E_PCI_LINK_SPEED_2500: 4441*61ae650dSJack F Vogel hw->bus.speed = i40e_bus_speed_2500; 4442*61ae650dSJack F Vogel break; 4443*61ae650dSJack F Vogel case I40E_PCI_LINK_SPEED_5000: 4444*61ae650dSJack F Vogel hw->bus.speed = i40e_bus_speed_5000; 4445*61ae650dSJack F Vogel break; 4446*61ae650dSJack F Vogel case I40E_PCI_LINK_SPEED_8000: 4447*61ae650dSJack F Vogel hw->bus.speed = i40e_bus_speed_8000; 4448*61ae650dSJack F Vogel break; 4449*61ae650dSJack F Vogel default: 4450*61ae650dSJack F Vogel hw->bus.speed = i40e_bus_speed_unknown; 4451*61ae650dSJack F Vogel break; 4452*61ae650dSJack F Vogel } 4453*61ae650dSJack F Vogel 4454*61ae650dSJack F Vogel 4455*61ae650dSJack F Vogel device_printf(dev,"PCI Express Bus: Speed %s %s\n", 4456*61ae650dSJack F Vogel ((hw->bus.speed == i40e_bus_speed_8000) ? "8.0GT/s": 4457*61ae650dSJack F Vogel (hw->bus.speed == i40e_bus_speed_5000) ? "5.0GT/s": 4458*61ae650dSJack F Vogel (hw->bus.speed == i40e_bus_speed_2500) ? "2.5GT/s":"Unknown"), 4459*61ae650dSJack F Vogel (hw->bus.width == i40e_bus_width_pcie_x8) ? "Width x8" : 4460*61ae650dSJack F Vogel (hw->bus.width == i40e_bus_width_pcie_x4) ? "Width x4" : 4461*61ae650dSJack F Vogel (hw->bus.width == i40e_bus_width_pcie_x1) ? "Width x1" : 4462*61ae650dSJack F Vogel ("Unknown")); 4463*61ae650dSJack F Vogel 4464*61ae650dSJack F Vogel if ((hw->bus.width <= i40e_bus_width_pcie_x8) && 4465*61ae650dSJack F Vogel (hw->bus.speed < i40e_bus_speed_8000)) { 4466*61ae650dSJack F Vogel device_printf(dev, "PCI-Express bandwidth available" 4467*61ae650dSJack F Vogel " for this device\n is not sufficient for" 4468*61ae650dSJack F Vogel " normal operation.\n"); 4469*61ae650dSJack F Vogel device_printf(dev, "For expected performance a x8 " 4470*61ae650dSJack F Vogel "PCIE Gen3 slot is required.\n"); 4471*61ae650dSJack F Vogel } 4472*61ae650dSJack F Vogel 4473*61ae650dSJack F Vogel return (link); 4474*61ae650dSJack F Vogel } 4475*61ae650dSJack F Vogel 4476*61ae650dSJack F Vogel #ifdef IXL_DEBUG 4477*61ae650dSJack F Vogel static int 4478*61ae650dSJack F Vogel ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS) 4479*61ae650dSJack F Vogel { 4480*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)arg1; 4481*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 4482*61ae650dSJack F Vogel struct i40e_link_status link_status; 4483*61ae650dSJack F Vogel char buf[512]; 4484*61ae650dSJack F Vogel 4485*61ae650dSJack F Vogel enum i40e_status_code aq_error = 0; 4486*61ae650dSJack F Vogel 4487*61ae650dSJack F Vogel aq_error = i40e_aq_get_link_info(hw, TRUE, &link_status, NULL); 4488*61ae650dSJack F Vogel if (aq_error) { 4489*61ae650dSJack F Vogel printf("i40e_aq_get_link_info() error %d\n", aq_error); 4490*61ae650dSJack F Vogel return (EPERM); 4491*61ae650dSJack F Vogel } 4492*61ae650dSJack F Vogel 4493*61ae650dSJack F Vogel sprintf(buf, "\n" 4494*61ae650dSJack F Vogel "PHY Type : %#04x\n" 4495*61ae650dSJack F Vogel "Speed : %#04x\n" 4496*61ae650dSJack F Vogel "Link info: %#04x\n" 4497*61ae650dSJack F Vogel "AN info : %#04x\n" 4498*61ae650dSJack F Vogel "Ext info : %#04x", 4499*61ae650dSJack F Vogel link_status.phy_type, link_status.link_speed, 4500*61ae650dSJack F Vogel link_status.link_info, link_status.an_info, 4501*61ae650dSJack F Vogel link_status.ext_info); 4502*61ae650dSJack F Vogel 4503*61ae650dSJack F Vogel return (sysctl_handle_string(oidp, buf, strlen(buf), req)); 4504*61ae650dSJack F Vogel } 4505*61ae650dSJack F Vogel 4506*61ae650dSJack F Vogel static int 4507*61ae650dSJack F Vogel ixl_sysctl_phy_abilities(SYSCTL_HANDLER_ARGS) 4508*61ae650dSJack F Vogel { 4509*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)arg1; 4510*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 4511*61ae650dSJack F Vogel struct i40e_aq_get_phy_abilities_resp abilities_resp; 4512*61ae650dSJack F Vogel char buf[512]; 4513*61ae650dSJack F Vogel 4514*61ae650dSJack F Vogel enum i40e_status_code aq_error = 0; 4515*61ae650dSJack F Vogel 4516*61ae650dSJack F Vogel // TODO: Print out list of qualified modules as well? 4517*61ae650dSJack F Vogel aq_error = i40e_aq_get_phy_capabilities(hw, TRUE, FALSE, &abilities_resp, NULL); 4518*61ae650dSJack F Vogel if (aq_error) { 4519*61ae650dSJack F Vogel printf("i40e_aq_get_phy_capabilities() error %d\n", aq_error); 4520*61ae650dSJack F Vogel return (EPERM); 4521*61ae650dSJack F Vogel } 4522*61ae650dSJack F Vogel 4523*61ae650dSJack F Vogel sprintf(buf, "\n" 4524*61ae650dSJack F Vogel "PHY Type : %#010x\n" 4525*61ae650dSJack F Vogel "Speed : %#04x\n" 4526*61ae650dSJack F Vogel "Abilities: %#04x\n" 4527*61ae650dSJack F Vogel "EEE cap : %#06x\n" 4528*61ae650dSJack F Vogel "EEER reg : %#010x\n" 4529*61ae650dSJack F Vogel "D3 Lpan : %#04x", 4530*61ae650dSJack F Vogel abilities_resp.phy_type, abilities_resp.link_speed, 4531*61ae650dSJack F Vogel abilities_resp.abilities, abilities_resp.eee_capability, 4532*61ae650dSJack F Vogel abilities_resp.eeer_val, abilities_resp.d3_lpan); 4533*61ae650dSJack F Vogel 4534*61ae650dSJack F Vogel return (sysctl_handle_string(oidp, buf, strlen(buf), req)); 4535*61ae650dSJack F Vogel } 4536*61ae650dSJack F Vogel 4537*61ae650dSJack F Vogel static int 4538*61ae650dSJack F Vogel ixl_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS) 4539*61ae650dSJack F Vogel { 4540*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)arg1; 4541*61ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 4542*61ae650dSJack F Vogel struct ixl_mac_filter *f; 4543*61ae650dSJack F Vogel char *buf, *buf_i; 4544*61ae650dSJack F Vogel 4545*61ae650dSJack F Vogel int error = 0; 4546*61ae650dSJack F Vogel int ftl_len = 0; 4547*61ae650dSJack F Vogel int ftl_counter = 0; 4548*61ae650dSJack F Vogel int buf_len = 0; 4549*61ae650dSJack F Vogel int entry_len = 42; 4550*61ae650dSJack F Vogel 4551*61ae650dSJack F Vogel SLIST_FOREACH(f, &vsi->ftl, next) { 4552*61ae650dSJack F Vogel ftl_len++; 4553*61ae650dSJack F Vogel } 4554*61ae650dSJack F Vogel 4555*61ae650dSJack F Vogel if (ftl_len < 1) { 4556*61ae650dSJack F Vogel sysctl_handle_string(oidp, "(none)", 6, req); 4557*61ae650dSJack F Vogel return (0); 4558*61ae650dSJack F Vogel } 4559*61ae650dSJack F Vogel 4560*61ae650dSJack F Vogel buf_len = sizeof(char) * (entry_len + 1) * ftl_len + 2; 4561*61ae650dSJack F Vogel buf = buf_i = malloc(buf_len, M_DEVBUF, M_NOWAIT); 4562*61ae650dSJack F Vogel 4563*61ae650dSJack F Vogel sprintf(buf_i++, "\n"); 4564*61ae650dSJack F Vogel SLIST_FOREACH(f, &vsi->ftl, next) { 4565*61ae650dSJack F Vogel sprintf(buf_i, 4566*61ae650dSJack F Vogel MAC_FORMAT ", vlan %4d, flags %#06x", 4567*61ae650dSJack F Vogel MAC_FORMAT_ARGS(f->macaddr), f->vlan, f->flags); 4568*61ae650dSJack F Vogel buf_i += entry_len; 4569*61ae650dSJack F Vogel /* don't print '\n' for last entry */ 4570*61ae650dSJack F Vogel if (++ftl_counter != ftl_len) { 4571*61ae650dSJack F Vogel sprintf(buf_i, "\n"); 4572*61ae650dSJack F Vogel buf_i++; 4573*61ae650dSJack F Vogel } 4574*61ae650dSJack F Vogel } 4575*61ae650dSJack F Vogel 4576*61ae650dSJack F Vogel error = sysctl_handle_string(oidp, buf, strlen(buf), req); 4577*61ae650dSJack F Vogel if (error) 4578*61ae650dSJack F Vogel printf("sysctl error: %d\n", error); 4579*61ae650dSJack F Vogel free(buf, M_DEVBUF); 4580*61ae650dSJack F Vogel return error; 4581*61ae650dSJack F Vogel } 4582*61ae650dSJack F Vogel 4583*61ae650dSJack F Vogel #define IXL_SW_RES_SIZE 0x14 4584*61ae650dSJack F Vogel static int 4585*61ae650dSJack F Vogel ixl_sysctl_hw_res_info(SYSCTL_HANDLER_ARGS) 4586*61ae650dSJack F Vogel { 4587*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)arg1; 4588*61ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 4589*61ae650dSJack F Vogel device_t dev = pf->dev; 4590*61ae650dSJack F Vogel struct sbuf *buf; 4591*61ae650dSJack F Vogel int error = 0; 4592*61ae650dSJack F Vogel 4593*61ae650dSJack F Vogel u8 num_entries; 4594*61ae650dSJack F Vogel struct i40e_aqc_switch_resource_alloc_element_resp resp[IXL_SW_RES_SIZE]; 4595*61ae650dSJack F Vogel 4596*61ae650dSJack F Vogel buf = sbuf_new_for_sysctl(NULL, NULL, 0, req); 4597*61ae650dSJack F Vogel if (!buf) { 4598*61ae650dSJack F Vogel device_printf(dev, "Could not allocate sbuf for output.\n"); 4599*61ae650dSJack F Vogel return (ENOMEM); 4600*61ae650dSJack F Vogel } 4601*61ae650dSJack F Vogel 4602*61ae650dSJack F Vogel error = i40e_aq_get_switch_resource_alloc(hw, &num_entries, 4603*61ae650dSJack F Vogel resp, 4604*61ae650dSJack F Vogel IXL_SW_RES_SIZE, 4605*61ae650dSJack F Vogel NULL); 4606*61ae650dSJack F Vogel if (error) { 4607*61ae650dSJack F Vogel device_printf(dev, "%s: get_switch_resource_alloc() error %d, aq error %d\n", 4608*61ae650dSJack F Vogel __func__, error, hw->aq.asq_last_status); 4609*61ae650dSJack F Vogel sbuf_delete(buf); 4610*61ae650dSJack F Vogel return error; 4611*61ae650dSJack F Vogel } 4612*61ae650dSJack F Vogel device_printf(dev, "Num_entries: %d\n", num_entries); 4613*61ae650dSJack F Vogel 4614*61ae650dSJack F Vogel sbuf_cat(buf, "\n"); 4615*61ae650dSJack F Vogel sbuf_printf(buf, 4616*61ae650dSJack F Vogel "Type | Guaranteed | Total | Used | Un-allocated\n" 4617*61ae650dSJack F Vogel " | (this) | (all) | (this) | (all) \n"); 4618*61ae650dSJack F Vogel for (int i = 0; i < num_entries; i++) { 4619*61ae650dSJack F Vogel sbuf_printf(buf, 4620*61ae650dSJack F Vogel "%#4x | %10d %5d %6d %12d", 4621*61ae650dSJack F Vogel resp[i].resource_type, 4622*61ae650dSJack F Vogel resp[i].guaranteed, 4623*61ae650dSJack F Vogel resp[i].total, 4624*61ae650dSJack F Vogel resp[i].used, 4625*61ae650dSJack F Vogel resp[i].total_unalloced); 4626*61ae650dSJack F Vogel if (i < num_entries - 1) 4627*61ae650dSJack F Vogel sbuf_cat(buf, "\n"); 4628*61ae650dSJack F Vogel } 4629*61ae650dSJack F Vogel 4630*61ae650dSJack F Vogel error = sbuf_finish(buf); 4631*61ae650dSJack F Vogel if (error) { 4632*61ae650dSJack F Vogel device_printf(dev, "Error finishing sbuf: %d\n", error); 4633*61ae650dSJack F Vogel sbuf_delete(buf); 4634*61ae650dSJack F Vogel return error; 4635*61ae650dSJack F Vogel } 4636*61ae650dSJack F Vogel 4637*61ae650dSJack F Vogel error = sysctl_handle_string(oidp, sbuf_data(buf), sbuf_len(buf), req); 4638*61ae650dSJack F Vogel if (error) 4639*61ae650dSJack F Vogel device_printf(dev, "sysctl error: %d\n", error); 4640*61ae650dSJack F Vogel sbuf_delete(buf); 4641*61ae650dSJack F Vogel return error; 4642*61ae650dSJack F Vogel 4643*61ae650dSJack F Vogel } 4644*61ae650dSJack F Vogel 4645*61ae650dSJack F Vogel /* 4646*61ae650dSJack F Vogel ** Dump TX desc given index. 4647*61ae650dSJack F Vogel ** Doesn't work; don't use. 4648*61ae650dSJack F Vogel ** TODO: Also needs a queue index input! 4649*61ae650dSJack F Vogel **/ 4650*61ae650dSJack F Vogel static int 4651*61ae650dSJack F Vogel ixl_sysctl_dump_txd(SYSCTL_HANDLER_ARGS) 4652*61ae650dSJack F Vogel { 4653*61ae650dSJack F Vogel struct ixl_pf *pf = (struct ixl_pf *)arg1; 4654*61ae650dSJack F Vogel device_t dev = pf->dev; 4655*61ae650dSJack F Vogel struct sbuf *buf; 4656*61ae650dSJack F Vogel int error = 0; 4657*61ae650dSJack F Vogel 4658*61ae650dSJack F Vogel u16 desc_idx = 0; 4659*61ae650dSJack F Vogel 4660*61ae650dSJack F Vogel buf = sbuf_new_for_sysctl(NULL, NULL, 0, req); 4661*61ae650dSJack F Vogel if (!buf) { 4662*61ae650dSJack F Vogel device_printf(dev, "Could not allocate sbuf for output.\n"); 4663*61ae650dSJack F Vogel return (ENOMEM); 4664*61ae650dSJack F Vogel } 4665*61ae650dSJack F Vogel 4666*61ae650dSJack F Vogel /* Read in index */ 4667*61ae650dSJack F Vogel error = sysctl_handle_int(oidp, &desc_idx, 0, req); 4668*61ae650dSJack F Vogel if (error) 4669*61ae650dSJack F Vogel return (error); 4670*61ae650dSJack F Vogel if (req->newptr == NULL) 4671*61ae650dSJack F Vogel return (EIO); // fix 4672*61ae650dSJack F Vogel if (desc_idx > 1024) { // fix 4673*61ae650dSJack F Vogel device_printf(dev, 4674*61ae650dSJack F Vogel "Invalid descriptor index, needs to be < 1024\n"); // fix 4675*61ae650dSJack F Vogel return (EINVAL); 4676*61ae650dSJack F Vogel } 4677*61ae650dSJack F Vogel 4678*61ae650dSJack F Vogel // Don't use this sysctl yet 4679*61ae650dSJack F Vogel if (TRUE) 4680*61ae650dSJack F Vogel return (ENODEV); 4681*61ae650dSJack F Vogel 4682*61ae650dSJack F Vogel sbuf_cat(buf, "\n"); 4683*61ae650dSJack F Vogel 4684*61ae650dSJack F Vogel // set to queue 1? 4685*61ae650dSJack F Vogel struct ixl_queue *que = pf->vsi.queues; 4686*61ae650dSJack F Vogel struct tx_ring *txr = &(que[1].txr); 4687*61ae650dSJack F Vogel struct i40e_tx_desc *txd = &txr->base[desc_idx]; 4688*61ae650dSJack F Vogel 4689*61ae650dSJack F Vogel sbuf_printf(buf, "Que: %d, Desc: %d\n", que->me, desc_idx); 4690*61ae650dSJack F Vogel sbuf_printf(buf, "Addr: %#18lx\n", txd->buffer_addr); 4691*61ae650dSJack F Vogel sbuf_printf(buf, "Opts: %#18lx\n", txd->cmd_type_offset_bsz); 4692*61ae650dSJack F Vogel 4693*61ae650dSJack F Vogel error = sbuf_finish(buf); 4694*61ae650dSJack F Vogel if (error) { 4695*61ae650dSJack F Vogel device_printf(dev, "Error finishing sbuf: %d\n", error); 4696*61ae650dSJack F Vogel sbuf_delete(buf); 4697*61ae650dSJack F Vogel return error; 4698*61ae650dSJack F Vogel } 4699*61ae650dSJack F Vogel 4700*61ae650dSJack F Vogel error = sysctl_handle_string(oidp, sbuf_data(buf), sbuf_len(buf), req); 4701*61ae650dSJack F Vogel if (error) 4702*61ae650dSJack F Vogel device_printf(dev, "sysctl error: %d\n", error); 4703*61ae650dSJack F Vogel sbuf_delete(buf); 4704*61ae650dSJack F Vogel return error; 4705*61ae650dSJack F Vogel } 4706*61ae650dSJack F Vogel #endif 4707*61ae650dSJack F Vogel 4708