161ae650dSJack F Vogel /****************************************************************************** 261ae650dSJack F Vogel 3b6c8f260SJack F Vogel Copyright (c) 2013-2015, Intel Corporation 461ae650dSJack F Vogel All rights reserved. 561ae650dSJack F Vogel 661ae650dSJack F Vogel Redistribution and use in source and binary forms, with or without 761ae650dSJack F Vogel modification, are permitted provided that the following conditions are met: 861ae650dSJack F Vogel 961ae650dSJack F Vogel 1. Redistributions of source code must retain the above copyright notice, 1061ae650dSJack F Vogel this list of conditions and the following disclaimer. 1161ae650dSJack F Vogel 1261ae650dSJack F Vogel 2. Redistributions in binary form must reproduce the above copyright 1361ae650dSJack F Vogel notice, this list of conditions and the following disclaimer in the 1461ae650dSJack F Vogel documentation and/or other materials provided with the distribution. 1561ae650dSJack F Vogel 1661ae650dSJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its 1761ae650dSJack F Vogel contributors may be used to endorse or promote products derived from 1861ae650dSJack F Vogel this software without specific prior written permission. 1961ae650dSJack F Vogel 2061ae650dSJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2161ae650dSJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2261ae650dSJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2361ae650dSJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2461ae650dSJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2561ae650dSJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2661ae650dSJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2761ae650dSJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2861ae650dSJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2961ae650dSJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3061ae650dSJack F Vogel POSSIBILITY OF SUCH DAMAGE. 3161ae650dSJack F Vogel 3261ae650dSJack F Vogel ******************************************************************************/ 3361ae650dSJack F Vogel /*$FreeBSD$*/ 3461ae650dSJack F Vogel 3561ae650dSJack F Vogel #include "ixl.h" 3661ae650dSJack F Vogel #include "ixl_pf.h" 3761ae650dSJack F Vogel 38*4294f337SSean Bruno #ifdef PCI_IOV 39*4294f337SSean Bruno #include "ixl_pf_iov.h" 40dcd7b3b2SJack F Vogel #endif 41dcd7b3b2SJack F Vogel 4261ae650dSJack F Vogel /********************************************************************* 4361ae650dSJack F Vogel * Driver version 4461ae650dSJack F Vogel *********************************************************************/ 45*4294f337SSean Bruno char ixl_driver_version[] = "1.6.6-k"; 4661ae650dSJack F Vogel 4761ae650dSJack F Vogel /********************************************************************* 4861ae650dSJack F Vogel * PCI Device ID Table 4961ae650dSJack F Vogel * 5061ae650dSJack F Vogel * Used by probe to select devices to load on 5161ae650dSJack F Vogel * Last field stores an index into ixl_strings 5261ae650dSJack F Vogel * Last entry must be all 0s 5361ae650dSJack F Vogel * 5461ae650dSJack F Vogel * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } 5561ae650dSJack F Vogel *********************************************************************/ 5661ae650dSJack F Vogel 5761ae650dSJack F Vogel static ixl_vendor_info_t ixl_vendor_info_array[] = 5861ae650dSJack F Vogel { 5961ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710, 0, 0, 0}, 6061ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B, 0, 0, 0}, 6161ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C, 0, 0, 0}, 6261ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A, 0, 0, 0}, 6361ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B, 0, 0, 0}, 6461ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_C, 0, 0, 0}, 6561ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T, 0, 0, 0}, 66be771cdaSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T4, 0, 0, 0}, 67*4294f337SSean Bruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_X722, 0, 0, 0}, 68*4294f337SSean Bruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_X722, 0, 0, 0}, 69*4294f337SSean Bruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_X722, 0, 0, 0}, 70*4294f337SSean Bruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_1G_BASE_T_X722, 0, 0, 0}, 71*4294f337SSean Bruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T_X722, 0, 0, 0}, 72*4294f337SSean Bruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_I_X722, 0, 0, 0}, 7361ae650dSJack F Vogel /* required last entry */ 7461ae650dSJack F Vogel {0, 0, 0, 0, 0} 7561ae650dSJack F Vogel }; 7661ae650dSJack F Vogel 7761ae650dSJack F Vogel /********************************************************************* 7861ae650dSJack F Vogel * Table of branding strings 7961ae650dSJack F Vogel *********************************************************************/ 8061ae650dSJack F Vogel 8161ae650dSJack F Vogel static char *ixl_strings[] = { 82*4294f337SSean Bruno "Intel(R) Ethernet Connection XL710/X722 Driver" 8361ae650dSJack F Vogel }; 8461ae650dSJack F Vogel 8561ae650dSJack F Vogel 8661ae650dSJack F Vogel /********************************************************************* 8761ae650dSJack F Vogel * Function prototypes 8861ae650dSJack F Vogel *********************************************************************/ 8961ae650dSJack F Vogel static int ixl_probe(device_t); 9061ae650dSJack F Vogel static int ixl_attach(device_t); 9161ae650dSJack F Vogel static int ixl_detach(device_t); 9261ae650dSJack F Vogel static int ixl_shutdown(device_t); 936c426059SEric Joyner 94*4294f337SSean Bruno static int ixl_save_pf_tunables(struct ixl_pf *); 95*4294f337SSean Bruno static int ixl_attach_get_link_status(struct ixl_pf *); 9661ae650dSJack F Vogel 9761ae650dSJack F Vogel /********************************************************************* 9861ae650dSJack F Vogel * FreeBSD Device Interface Entry Points 9961ae650dSJack F Vogel *********************************************************************/ 10061ae650dSJack F Vogel 10161ae650dSJack F Vogel static device_method_t ixl_methods[] = { 10261ae650dSJack F Vogel /* Device interface */ 10361ae650dSJack F Vogel DEVMETHOD(device_probe, ixl_probe), 10461ae650dSJack F Vogel DEVMETHOD(device_attach, ixl_attach), 10561ae650dSJack F Vogel DEVMETHOD(device_detach, ixl_detach), 10661ae650dSJack F Vogel DEVMETHOD(device_shutdown, ixl_shutdown), 10756c2c47bSJack F Vogel #ifdef PCI_IOV 108a48d00d2SEric Joyner DEVMETHOD(pci_iov_init, ixl_iov_init), 109a48d00d2SEric Joyner DEVMETHOD(pci_iov_uninit, ixl_iov_uninit), 110a48d00d2SEric Joyner DEVMETHOD(pci_iov_add_vf, ixl_add_vf), 11156c2c47bSJack F Vogel #endif 11261ae650dSJack F Vogel {0, 0} 11361ae650dSJack F Vogel }; 11461ae650dSJack F Vogel 11561ae650dSJack F Vogel static driver_t ixl_driver = { 11661ae650dSJack F Vogel "ixl", ixl_methods, sizeof(struct ixl_pf), 11761ae650dSJack F Vogel }; 11861ae650dSJack F Vogel 11961ae650dSJack F Vogel devclass_t ixl_devclass; 12061ae650dSJack F Vogel DRIVER_MODULE(ixl, pci, ixl_driver, ixl_devclass, 0, 0); 12161ae650dSJack F Vogel 12261ae650dSJack F Vogel MODULE_DEPEND(ixl, pci, 1, 1, 1); 12361ae650dSJack F Vogel MODULE_DEPEND(ixl, ether, 1, 1, 1); 12431830672SJack F Vogel #ifdef DEV_NETMAP 12531830672SJack F Vogel MODULE_DEPEND(ixl, netmap, 1, 1, 1); 12631830672SJack F Vogel #endif /* DEV_NETMAP */ 12731830672SJack F Vogel 12861ae650dSJack F Vogel /* 12961ae650dSJack F Vogel ** TUNEABLE PARAMETERS: 13061ae650dSJack F Vogel */ 13161ae650dSJack F Vogel 13261ae650dSJack F Vogel static SYSCTL_NODE(_hw, OID_AUTO, ixl, CTLFLAG_RD, 0, 13361ae650dSJack F Vogel "IXL driver parameters"); 13461ae650dSJack F Vogel 13561ae650dSJack F Vogel /* 13661ae650dSJack F Vogel * MSIX should be the default for best performance, 13761ae650dSJack F Vogel * but this allows it to be forced off for testing. 13861ae650dSJack F Vogel */ 13961ae650dSJack F Vogel static int ixl_enable_msix = 1; 14061ae650dSJack F Vogel TUNABLE_INT("hw.ixl.enable_msix", &ixl_enable_msix); 14161ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixl_enable_msix, 0, 14261ae650dSJack F Vogel "Enable MSI-X interrupts"); 14361ae650dSJack F Vogel 14461ae650dSJack F Vogel /* 14561ae650dSJack F Vogel ** Number of descriptors per ring: 14661ae650dSJack F Vogel ** - TX and RX are the same size 14761ae650dSJack F Vogel */ 148*4294f337SSean Bruno static int ixl_ring_size = DEFAULT_RING; 149*4294f337SSean Bruno TUNABLE_INT("hw.ixl.ring_size", &ixl_ring_size); 15061ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, ring_size, CTLFLAG_RDTUN, 151*4294f337SSean Bruno &ixl_ring_size, 0, "Descriptor Ring Size"); 15261ae650dSJack F Vogel 15361ae650dSJack F Vogel /* 15461ae650dSJack F Vogel ** This can be set manually, if left as 0 the 15561ae650dSJack F Vogel ** number of queues will be calculated based 15661ae650dSJack F Vogel ** on cpus and msix vectors available. 15761ae650dSJack F Vogel */ 158*4294f337SSean Bruno static int ixl_max_queues = 0; 15961ae650dSJack F Vogel TUNABLE_INT("hw.ixl.max_queues", &ixl_max_queues); 16061ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, max_queues, CTLFLAG_RDTUN, 16161ae650dSJack F Vogel &ixl_max_queues, 0, "Number of Queues"); 16261ae650dSJack F Vogel 163*4294f337SSean Bruno static int ixl_enable_tx_fc_filter = 1; 164*4294f337SSean Bruno TUNABLE_INT("hw.ixl.enable_tx_fc_filter", 165*4294f337SSean Bruno &ixl_enable_tx_fc_filter); 166*4294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, enable_tx_fc_filter, CTLFLAG_RDTUN, 167*4294f337SSean Bruno &ixl_enable_tx_fc_filter, 0, 168*4294f337SSean Bruno "Filter out packets with Ethertype 0x8808 from being sent out by non-HW sources"); 169*4294f337SSean Bruno 170*4294f337SSean Bruno static int ixl_core_debug_mask = 0; 171*4294f337SSean Bruno TUNABLE_INT("hw.ixl.core_debug_mask", 172*4294f337SSean Bruno &ixl_core_debug_mask); 173*4294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, core_debug_mask, CTLFLAG_RDTUN, 174*4294f337SSean Bruno &ixl_core_debug_mask, 0, 175*4294f337SSean Bruno "Display debug statements that are printed in non-shared code"); 176*4294f337SSean Bruno 177*4294f337SSean Bruno static int ixl_shared_debug_mask = 0; 178*4294f337SSean Bruno TUNABLE_INT("hw.ixl.shared_debug_mask", 179*4294f337SSean Bruno &ixl_shared_debug_mask); 180*4294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, shared_debug_mask, CTLFLAG_RDTUN, 181*4294f337SSean Bruno &ixl_shared_debug_mask, 0, 182*4294f337SSean Bruno "Display debug statements that are printed in shared code"); 183*4294f337SSean Bruno 18461ae650dSJack F Vogel /* 18561ae650dSJack F Vogel ** Controls for Interrupt Throttling 18661ae650dSJack F Vogel ** - true/false for dynamic adjustment 18761ae650dSJack F Vogel ** - default values for static ITR 18861ae650dSJack F Vogel */ 189*4294f337SSean Bruno static int ixl_dynamic_rx_itr = 1; 19061ae650dSJack F Vogel TUNABLE_INT("hw.ixl.dynamic_rx_itr", &ixl_dynamic_rx_itr); 19161ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_rx_itr, CTLFLAG_RDTUN, 19261ae650dSJack F Vogel &ixl_dynamic_rx_itr, 0, "Dynamic RX Interrupt Rate"); 19361ae650dSJack F Vogel 194*4294f337SSean Bruno static int ixl_dynamic_tx_itr = 1; 19561ae650dSJack F Vogel TUNABLE_INT("hw.ixl.dynamic_tx_itr", &ixl_dynamic_tx_itr); 19661ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_tx_itr, CTLFLAG_RDTUN, 19761ae650dSJack F Vogel &ixl_dynamic_tx_itr, 0, "Dynamic TX Interrupt Rate"); 19861ae650dSJack F Vogel 199*4294f337SSean Bruno static int ixl_rx_itr = IXL_ITR_8K; 20061ae650dSJack F Vogel TUNABLE_INT("hw.ixl.rx_itr", &ixl_rx_itr); 20161ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, rx_itr, CTLFLAG_RDTUN, 20261ae650dSJack F Vogel &ixl_rx_itr, 0, "RX Interrupt Rate"); 20361ae650dSJack F Vogel 204*4294f337SSean Bruno static int ixl_tx_itr = IXL_ITR_4K; 20561ae650dSJack F Vogel TUNABLE_INT("hw.ixl.tx_itr", &ixl_tx_itr); 20661ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, tx_itr, CTLFLAG_RDTUN, 20761ae650dSJack F Vogel &ixl_tx_itr, 0, "TX Interrupt Rate"); 20861ae650dSJack F Vogel 20931830672SJack F Vogel #ifdef DEV_NETMAP 21031830672SJack F Vogel #define NETMAP_IXL_MAIN /* only bring in one part of the netmap code */ 21131830672SJack F Vogel #include <dev/netmap/if_ixl_netmap.h> 21231830672SJack F Vogel #endif /* DEV_NETMAP */ 213e5100ee2SJack F Vogel 21461ae650dSJack F Vogel /********************************************************************* 21561ae650dSJack F Vogel * Device identification routine 21661ae650dSJack F Vogel * 21761ae650dSJack F Vogel * ixl_probe determines if the driver should be loaded on 21861ae650dSJack F Vogel * the hardware based on PCI vendor/device id of the device. 21961ae650dSJack F Vogel * 22061ae650dSJack F Vogel * return BUS_PROBE_DEFAULT on success, positive on failure 22161ae650dSJack F Vogel *********************************************************************/ 22261ae650dSJack F Vogel 22361ae650dSJack F Vogel static int 22461ae650dSJack F Vogel ixl_probe(device_t dev) 22561ae650dSJack F Vogel { 22661ae650dSJack F Vogel ixl_vendor_info_t *ent; 22761ae650dSJack F Vogel 22861ae650dSJack F Vogel u16 pci_vendor_id, pci_device_id; 22961ae650dSJack F Vogel u16 pci_subvendor_id, pci_subdevice_id; 23061ae650dSJack F Vogel char device_name[256]; 23161ae650dSJack F Vogel 2321d767a8eSEric Joyner #if 0 23361ae650dSJack F Vogel INIT_DEBUGOUT("ixl_probe: begin"); 2341d767a8eSEric Joyner #endif 23561ae650dSJack F Vogel pci_vendor_id = pci_get_vendor(dev); 23661ae650dSJack F Vogel if (pci_vendor_id != I40E_INTEL_VENDOR_ID) 23761ae650dSJack F Vogel return (ENXIO); 23861ae650dSJack F Vogel 23961ae650dSJack F Vogel pci_device_id = pci_get_device(dev); 24061ae650dSJack F Vogel pci_subvendor_id = pci_get_subvendor(dev); 24161ae650dSJack F Vogel pci_subdevice_id = pci_get_subdevice(dev); 24261ae650dSJack F Vogel 24361ae650dSJack F Vogel ent = ixl_vendor_info_array; 24461ae650dSJack F Vogel while (ent->vendor_id != 0) { 24561ae650dSJack F Vogel if ((pci_vendor_id == ent->vendor_id) && 24661ae650dSJack F Vogel (pci_device_id == ent->device_id) && 24761ae650dSJack F Vogel 24861ae650dSJack F Vogel ((pci_subvendor_id == ent->subvendor_id) || 24961ae650dSJack F Vogel (ent->subvendor_id == 0)) && 25061ae650dSJack F Vogel 25161ae650dSJack F Vogel ((pci_subdevice_id == ent->subdevice_id) || 25261ae650dSJack F Vogel (ent->subdevice_id == 0))) { 25361ae650dSJack F Vogel sprintf(device_name, "%s, Version - %s", 25461ae650dSJack F Vogel ixl_strings[ent->index], 25561ae650dSJack F Vogel ixl_driver_version); 25661ae650dSJack F Vogel device_set_desc_copy(dev, device_name); 25761ae650dSJack F Vogel return (BUS_PROBE_DEFAULT); 25861ae650dSJack F Vogel } 25961ae650dSJack F Vogel ent++; 26061ae650dSJack F Vogel } 26161ae650dSJack F Vogel return (ENXIO); 26261ae650dSJack F Vogel } 26361ae650dSJack F Vogel 264*4294f337SSean Bruno static int 265*4294f337SSean Bruno ixl_attach_get_link_status(struct ixl_pf *pf) 266*4294f337SSean Bruno { 267*4294f337SSean Bruno struct i40e_hw *hw = &pf->hw; 268*4294f337SSean Bruno device_t dev = pf->dev; 269*4294f337SSean Bruno int error = 0; 270*4294f337SSean Bruno 271*4294f337SSean Bruno if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || 272*4294f337SSean Bruno (hw->aq.fw_maj_ver < 4)) { 273*4294f337SSean Bruno i40e_msec_delay(75); 274*4294f337SSean Bruno error = i40e_aq_set_link_restart_an(hw, TRUE, NULL); 275*4294f337SSean Bruno if (error) { 276*4294f337SSean Bruno device_printf(dev, "link restart failed, aq_err=%d\n", 277*4294f337SSean Bruno pf->hw.aq.asq_last_status); 278*4294f337SSean Bruno return error; 279*4294f337SSean Bruno } 280*4294f337SSean Bruno } 281*4294f337SSean Bruno 282*4294f337SSean Bruno /* Determine link state */ 283*4294f337SSean Bruno hw->phy.get_link_info = TRUE; 284*4294f337SSean Bruno i40e_get_link_status(hw, &pf->link_up); 285*4294f337SSean Bruno return (0); 286*4294f337SSean Bruno } 287*4294f337SSean Bruno 288*4294f337SSean Bruno /* 289*4294f337SSean Bruno * Sanity check and save off tunable values. 290*4294f337SSean Bruno */ 291*4294f337SSean Bruno static int 292*4294f337SSean Bruno ixl_save_pf_tunables(struct ixl_pf *pf) 293*4294f337SSean Bruno { 294*4294f337SSean Bruno device_t dev = pf->dev; 295*4294f337SSean Bruno 296*4294f337SSean Bruno /* Save tunable information */ 297*4294f337SSean Bruno pf->enable_msix = ixl_enable_msix; 298*4294f337SSean Bruno pf->max_queues = ixl_max_queues; 299*4294f337SSean Bruno pf->ringsz = ixl_ring_size; 300*4294f337SSean Bruno pf->enable_tx_fc_filter = ixl_enable_tx_fc_filter; 301*4294f337SSean Bruno pf->dynamic_rx_itr = ixl_dynamic_rx_itr; 302*4294f337SSean Bruno pf->dynamic_tx_itr = ixl_dynamic_tx_itr; 303*4294f337SSean Bruno pf->tx_itr = ixl_tx_itr; 304*4294f337SSean Bruno pf->rx_itr = ixl_rx_itr; 305*4294f337SSean Bruno pf->dbg_mask = ixl_core_debug_mask; 306*4294f337SSean Bruno pf->hw.debug_mask = ixl_shared_debug_mask; 307*4294f337SSean Bruno 308*4294f337SSean Bruno if (ixl_ring_size < IXL_MIN_RING 309*4294f337SSean Bruno || ixl_ring_size > IXL_MAX_RING 310*4294f337SSean Bruno || ixl_ring_size % IXL_RING_INCREMENT != 0) { 311*4294f337SSean Bruno device_printf(dev, "Invalid ring_size value of %d set!\n", 312*4294f337SSean Bruno ixl_ring_size); 313*4294f337SSean Bruno device_printf(dev, "ring_size must be between %d and %d, " 314*4294f337SSean Bruno "inclusive, and must be a multiple of %d\n", 315*4294f337SSean Bruno IXL_MIN_RING, IXL_MAX_RING, IXL_RING_INCREMENT); 316*4294f337SSean Bruno return (EINVAL); 317*4294f337SSean Bruno } 318*4294f337SSean Bruno 319*4294f337SSean Bruno return (0); 320*4294f337SSean Bruno } 321*4294f337SSean Bruno 32261ae650dSJack F Vogel /********************************************************************* 32361ae650dSJack F Vogel * Device initialization routine 32461ae650dSJack F Vogel * 32561ae650dSJack F Vogel * The attach entry point is called when the driver is being loaded. 32661ae650dSJack F Vogel * This routine identifies the type of hardware, allocates all resources 32761ae650dSJack F Vogel * and initializes the hardware. 32861ae650dSJack F Vogel * 32961ae650dSJack F Vogel * return 0 on success, positive on failure 33061ae650dSJack F Vogel *********************************************************************/ 33161ae650dSJack F Vogel 33261ae650dSJack F Vogel static int 33361ae650dSJack F Vogel ixl_attach(device_t dev) 33461ae650dSJack F Vogel { 33561ae650dSJack F Vogel struct ixl_pf *pf; 33661ae650dSJack F Vogel struct i40e_hw *hw; 33761ae650dSJack F Vogel struct ixl_vsi *vsi; 338*4294f337SSean Bruno enum i40e_status_code status; 33961ae650dSJack F Vogel int error = 0; 34061ae650dSJack F Vogel 34161ae650dSJack F Vogel INIT_DEBUGOUT("ixl_attach: begin"); 34261ae650dSJack F Vogel 34361ae650dSJack F Vogel /* Allocate, clear, and link in our primary soft structure */ 34461ae650dSJack F Vogel pf = device_get_softc(dev); 34561ae650dSJack F Vogel pf->dev = pf->osdep.dev = dev; 34661ae650dSJack F Vogel hw = &pf->hw; 34761ae650dSJack F Vogel 34861ae650dSJack F Vogel /* 34961ae650dSJack F Vogel ** Note this assumes we have a single embedded VSI, 35061ae650dSJack F Vogel ** this could be enhanced later to allocate multiple 35161ae650dSJack F Vogel */ 35261ae650dSJack F Vogel vsi = &pf->vsi; 35361ae650dSJack F Vogel vsi->dev = pf->dev; 35461ae650dSJack F Vogel 355*4294f337SSean Bruno /* Save tunable values */ 356*4294f337SSean Bruno error = ixl_save_pf_tunables(pf); 357*4294f337SSean Bruno if (error) 358*4294f337SSean Bruno return (error); 359*4294f337SSean Bruno 36061ae650dSJack F Vogel /* Core Lock Init*/ 36161ae650dSJack F Vogel IXL_PF_LOCK_INIT(pf, device_get_nameunit(dev)); 36261ae650dSJack F Vogel 36361ae650dSJack F Vogel /* Set up the timer callout */ 36461ae650dSJack F Vogel callout_init_mtx(&pf->timer, &pf->pf_mtx, 0); 36561ae650dSJack F Vogel 36661ae650dSJack F Vogel /* Do PCI setup - map BAR0, etc */ 36761ae650dSJack F Vogel if (ixl_allocate_pci_resources(pf)) { 36861ae650dSJack F Vogel device_printf(dev, "Allocation of PCI resources failed\n"); 36961ae650dSJack F Vogel error = ENXIO; 37061ae650dSJack F Vogel goto err_out; 37161ae650dSJack F Vogel } 37261ae650dSJack F Vogel 37361ae650dSJack F Vogel /* Establish a clean starting point */ 37461ae650dSJack F Vogel i40e_clear_hw(hw); 375*4294f337SSean Bruno status = i40e_pf_reset(hw); 376*4294f337SSean Bruno if (status) { 377*4294f337SSean Bruno device_printf(dev, "PF reset failure %s\n", 378*4294f337SSean Bruno i40e_stat_str(hw, status)); 37961ae650dSJack F Vogel error = EIO; 38061ae650dSJack F Vogel goto err_out; 38161ae650dSJack F Vogel } 38261ae650dSJack F Vogel 38361ae650dSJack F Vogel /* Initialize the shared code */ 384*4294f337SSean Bruno status = i40e_init_shared_code(hw); 385*4294f337SSean Bruno if (status) { 386*4294f337SSean Bruno device_printf(dev, "Unable to initialize shared code, error %s\n", 387*4294f337SSean Bruno i40e_stat_str(hw, status)); 38861ae650dSJack F Vogel error = EIO; 38961ae650dSJack F Vogel goto err_out; 39061ae650dSJack F Vogel } 39161ae650dSJack F Vogel 392*4294f337SSean Bruno /* 393*4294f337SSean Bruno * Allocate interrupts and figure out number of queues to use 394*4294f337SSean Bruno * for PF interface 395*4294f337SSean Bruno */ 396*4294f337SSean Bruno pf->msix = ixl_init_msix(pf); 397*4294f337SSean Bruno 39861ae650dSJack F Vogel /* Set up the admin queue */ 399*4294f337SSean Bruno hw->aq.num_arq_entries = IXL_AQ_LEN; 400*4294f337SSean Bruno hw->aq.num_asq_entries = IXL_AQ_LEN; 401*4294f337SSean Bruno hw->aq.arq_buf_size = IXL_AQ_BUF_SZ; 402*4294f337SSean Bruno hw->aq.asq_buf_size = IXL_AQ_BUF_SZ; 403*4294f337SSean Bruno 404*4294f337SSean Bruno status = i40e_init_adminq(hw); 405*4294f337SSean Bruno if (status != 0 && status != I40E_ERR_FIRMWARE_API_VERSION) { 406*4294f337SSean Bruno device_printf(dev, "Unable to initialize Admin Queue, error %s\n", 407*4294f337SSean Bruno i40e_stat_str(hw, status)); 408fdb6f38aSEric Joyner error = EIO; 409fdb6f38aSEric Joyner goto err_out; 410fdb6f38aSEric Joyner } 4111d767a8eSEric Joyner ixl_print_nvm_version(pf); 4121d767a8eSEric Joyner 413*4294f337SSean Bruno if (status == I40E_ERR_FIRMWARE_API_VERSION) { 41461ae650dSJack F Vogel device_printf(dev, "The driver for the device stopped " 41561ae650dSJack F Vogel "because the NVM image is newer than expected.\n" 41661ae650dSJack F Vogel "You must install the most recent version of " 41761ae650dSJack F Vogel "the network driver.\n"); 418fdb6f38aSEric Joyner error = EIO; 41961ae650dSJack F Vogel goto err_out; 42061ae650dSJack F Vogel } 42161ae650dSJack F Vogel 42261ae650dSJack F Vogel if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR && 42361ae650dSJack F Vogel hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR) 42461ae650dSJack F Vogel device_printf(dev, "The driver for the device detected " 42561ae650dSJack F Vogel "a newer version of the NVM image than expected.\n" 42661ae650dSJack F Vogel "Please install the most recent version of the network driver.\n"); 42761ae650dSJack F Vogel else if (hw->aq.api_maj_ver < I40E_FW_API_VERSION_MAJOR || 42861ae650dSJack F Vogel hw->aq.api_min_ver < (I40E_FW_API_VERSION_MINOR - 1)) 42961ae650dSJack F Vogel device_printf(dev, "The driver for the device detected " 43061ae650dSJack F Vogel "an older version of the NVM image than expected.\n" 43161ae650dSJack F Vogel "Please update the NVM image.\n"); 43261ae650dSJack F Vogel 43361ae650dSJack F Vogel /* Clear PXE mode */ 43461ae650dSJack F Vogel i40e_clear_pxe_mode(hw); 43561ae650dSJack F Vogel 43661ae650dSJack F Vogel /* Get capabilities from the device */ 43761ae650dSJack F Vogel error = ixl_get_hw_capabilities(pf); 43861ae650dSJack F Vogel if (error) { 43961ae650dSJack F Vogel device_printf(dev, "HW capabilities failure!\n"); 44061ae650dSJack F Vogel goto err_get_cap; 44161ae650dSJack F Vogel } 44261ae650dSJack F Vogel 44361ae650dSJack F Vogel /* Set up host memory cache */ 444*4294f337SSean Bruno status = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp, 44556c2c47bSJack F Vogel hw->func_caps.num_rx_qp, 0, 0); 446*4294f337SSean Bruno if (status) { 447*4294f337SSean Bruno device_printf(dev, "init_lan_hmc failed: %s\n", 448*4294f337SSean Bruno i40e_stat_str(hw, status)); 44961ae650dSJack F Vogel goto err_get_cap; 45061ae650dSJack F Vogel } 45161ae650dSJack F Vogel 452*4294f337SSean Bruno status = i40e_configure_lan_hmc(hw, I40E_HMC_MODEL_DIRECT_ONLY); 453*4294f337SSean Bruno if (status) { 454*4294f337SSean Bruno device_printf(dev, "configure_lan_hmc failed: %s\n", 455*4294f337SSean Bruno i40e_stat_str(hw, status)); 45661ae650dSJack F Vogel goto err_mac_hmc; 45761ae650dSJack F Vogel } 45861ae650dSJack F Vogel 459*4294f337SSean Bruno /* Init queue allocation manager */ 460*4294f337SSean Bruno error = ixl_pf_qmgr_init(&pf->qmgr, hw->func_caps.num_tx_qp); 461*4294f337SSean Bruno if (error) { 462*4294f337SSean Bruno device_printf(dev, "Failed to init queue manager for PF queues, error %d\n", 463*4294f337SSean Bruno error); 464*4294f337SSean Bruno goto err_mac_hmc; 465*4294f337SSean Bruno } 466*4294f337SSean Bruno /* reserve a contiguous allocation for the PF's VSI */ 467*4294f337SSean Bruno error = ixl_pf_qmgr_alloc_contiguous(&pf->qmgr, vsi->num_queues, &pf->qtag); 468*4294f337SSean Bruno if (error) { 469*4294f337SSean Bruno device_printf(dev, "Failed to reserve queues for PF LAN VSI, error %d\n", 470*4294f337SSean Bruno error); 471*4294f337SSean Bruno goto err_mac_hmc; 472*4294f337SSean Bruno } 473*4294f337SSean Bruno device_printf(dev, "Allocating %d queues for PF LAN VSI; %d queues active\n", 474*4294f337SSean Bruno pf->qtag.num_allocated, pf->qtag.num_active); 475*4294f337SSean Bruno 476d4683565SEric Joyner /* Disable LLDP from the firmware for certain NVM versions */ 477d4683565SEric Joyner if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 3)) || 478d4683565SEric Joyner (pf->hw.aq.fw_maj_ver < 4)) 47961ae650dSJack F Vogel i40e_aq_stop_lldp(hw, TRUE, NULL); 48061ae650dSJack F Vogel 481*4294f337SSean Bruno /* Get MAC addresses from hardware */ 48261ae650dSJack F Vogel i40e_get_mac_addr(hw, hw->mac.addr); 48361ae650dSJack F Vogel error = i40e_validate_mac_addr(hw->mac.addr); 48461ae650dSJack F Vogel if (error) { 48561ae650dSJack F Vogel device_printf(dev, "validate_mac_addr failed: %d\n", error); 48661ae650dSJack F Vogel goto err_mac_hmc; 48761ae650dSJack F Vogel } 48861ae650dSJack F Vogel bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN); 48961ae650dSJack F Vogel i40e_get_port_mac_addr(hw, hw->mac.port_addr); 49061ae650dSJack F Vogel 491*4294f337SSean Bruno /* Initialize mac filter list for VSI */ 492*4294f337SSean Bruno SLIST_INIT(&vsi->ftl); 493*4294f337SSean Bruno 494*4294f337SSean Bruno /* Set up SW VSI and allocate queue memory and rings */ 495*4294f337SSean Bruno if (ixl_setup_stations(pf)) { 49661ae650dSJack F Vogel device_printf(dev, "setup stations failed!\n"); 49761ae650dSJack F Vogel error = ENOMEM; 49861ae650dSJack F Vogel goto err_mac_hmc; 49961ae650dSJack F Vogel } 50061ae650dSJack F Vogel 501*4294f337SSean Bruno /* Setup OS network interface / ifnet */ 502*4294f337SSean Bruno if (ixl_setup_interface(dev, vsi)) { 503*4294f337SSean Bruno device_printf(dev, "interface setup failed!\n"); 504*4294f337SSean Bruno error = EIO; 505223d846dSEric Joyner goto err_late; 506223d846dSEric Joyner } 50761ae650dSJack F Vogel 50861ae650dSJack F Vogel /* Determine link state */ 509*4294f337SSean Bruno if (ixl_attach_get_link_status(pf)) { 510*4294f337SSean Bruno error = EINVAL; 51161ae650dSJack F Vogel goto err_late; 512e5100ee2SJack F Vogel } 51361ae650dSJack F Vogel 514b6c8f260SJack F Vogel error = ixl_switch_config(pf); 515b6c8f260SJack F Vogel if (error) { 5166c426059SEric Joyner device_printf(dev, "Initial ixl_switch_config() failed: %d\n", 5176c426059SEric Joyner error); 518a48d00d2SEric Joyner goto err_late; 519b6c8f260SJack F Vogel } 520b6c8f260SJack F Vogel 521223d846dSEric Joyner /* Limit PHY interrupts to link, autoneg, and modules failure */ 522*4294f337SSean Bruno status = i40e_aq_set_phy_int_mask(hw, IXL_DEFAULT_PHY_INT_MASK, 523223d846dSEric Joyner NULL); 524*4294f337SSean Bruno if (status) { 525*4294f337SSean Bruno device_printf(dev, "i40e_aq_set_phy_mask() failed: err %s," 526*4294f337SSean Bruno " aq_err %s\n", i40e_stat_str(hw, status), 527*4294f337SSean Bruno i40e_aq_str(hw, hw->aq.asq_last_status)); 528223d846dSEric Joyner goto err_late; 529223d846dSEric Joyner } 530b6c8f260SJack F Vogel 5316c426059SEric Joyner /* Get the bus configuration and set the shared code's config */ 532*4294f337SSean Bruno ixl_get_bus_info(hw, dev); 53361ae650dSJack F Vogel 5346c426059SEric Joyner /* 5356c426059SEric Joyner * In MSI-X mode, initialize the Admin Queue interrupt, 5366c426059SEric Joyner * so userland tools can communicate with the adapter regardless of 5376c426059SEric Joyner * the ifnet interface's status. 5386c426059SEric Joyner */ 5396c426059SEric Joyner if (pf->msix > 1) { 5406c426059SEric Joyner error = ixl_setup_adminq_msix(pf); 5416c426059SEric Joyner if (error) { 5426c426059SEric Joyner device_printf(dev, "ixl_setup_adminq_msix error: %d\n", 5436c426059SEric Joyner error); 5446c426059SEric Joyner goto err_late; 5456c426059SEric Joyner } 5466c426059SEric Joyner error = ixl_setup_adminq_tq(pf); 5476c426059SEric Joyner if (error) { 5486c426059SEric Joyner device_printf(dev, "ixl_setup_adminq_tq error: %d\n", 5496c426059SEric Joyner error); 5506c426059SEric Joyner goto err_late; 5516c426059SEric Joyner } 5526c426059SEric Joyner ixl_configure_intr0_msix(pf); 5536c426059SEric Joyner ixl_enable_adminq(hw); 5546c426059SEric Joyner } 555a48d00d2SEric Joyner 556fdb6f38aSEric Joyner /* Initialize statistics & add sysctls */ 557fdb6f38aSEric Joyner ixl_add_device_sysctls(pf); 558fdb6f38aSEric Joyner 55961ae650dSJack F Vogel ixl_pf_reset_stats(pf); 56061ae650dSJack F Vogel ixl_update_stats_counters(pf); 56161ae650dSJack F Vogel ixl_add_hw_stats(pf); 56261ae650dSJack F Vogel 56361ae650dSJack F Vogel /* Register for VLAN events */ 56461ae650dSJack F Vogel vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, 56561ae650dSJack F Vogel ixl_register_vlan, vsi, EVENTHANDLER_PRI_FIRST); 56661ae650dSJack F Vogel vsi->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, 56761ae650dSJack F Vogel ixl_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST); 56861ae650dSJack F Vogel 56956c2c47bSJack F Vogel #ifdef PCI_IOV 570*4294f337SSean Bruno ixl_initialize_sriov(pf); 57156c2c47bSJack F Vogel #endif 57256c2c47bSJack F Vogel 57331830672SJack F Vogel #ifdef DEV_NETMAP 57431830672SJack F Vogel ixl_netmap_attach(vsi); 57531830672SJack F Vogel #endif /* DEV_NETMAP */ 57661ae650dSJack F Vogel INIT_DEBUGOUT("ixl_attach: end"); 57761ae650dSJack F Vogel return (0); 57861ae650dSJack F Vogel 57961ae650dSJack F Vogel err_late: 580*4294f337SSean Bruno if (vsi->ifp != NULL) { 581*4294f337SSean Bruno ether_ifdetach(vsi->ifp); 582e5100ee2SJack F Vogel if_free(vsi->ifp); 583*4294f337SSean Bruno } 58461ae650dSJack F Vogel err_mac_hmc: 58561ae650dSJack F Vogel i40e_shutdown_lan_hmc(hw); 58661ae650dSJack F Vogel err_get_cap: 58761ae650dSJack F Vogel i40e_shutdown_adminq(hw); 58861ae650dSJack F Vogel err_out: 58961ae650dSJack F Vogel ixl_free_pci_resources(pf); 590e5100ee2SJack F Vogel ixl_free_vsi(vsi); 59161ae650dSJack F Vogel IXL_PF_LOCK_DESTROY(pf); 59261ae650dSJack F Vogel return (error); 59361ae650dSJack F Vogel } 59461ae650dSJack F Vogel 59561ae650dSJack F Vogel /********************************************************************* 59661ae650dSJack F Vogel * Device removal routine 59761ae650dSJack F Vogel * 59861ae650dSJack F Vogel * The detach entry point is called when the driver is being removed. 59961ae650dSJack F Vogel * This routine stops the adapter and deallocates all the resources 60061ae650dSJack F Vogel * that were allocated for driver operation. 60161ae650dSJack F Vogel * 60261ae650dSJack F Vogel * return 0 on success, positive on failure 60361ae650dSJack F Vogel *********************************************************************/ 60461ae650dSJack F Vogel 60561ae650dSJack F Vogel static int 60661ae650dSJack F Vogel ixl_detach(device_t dev) 60761ae650dSJack F Vogel { 60861ae650dSJack F Vogel struct ixl_pf *pf = device_get_softc(dev); 60961ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 61061ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 6116c426059SEric Joyner enum i40e_status_code status; 61256c2c47bSJack F Vogel #ifdef PCI_IOV 61356c2c47bSJack F Vogel int error; 61456c2c47bSJack F Vogel #endif 61561ae650dSJack F Vogel 61661ae650dSJack F Vogel INIT_DEBUGOUT("ixl_detach: begin"); 61761ae650dSJack F Vogel 61861ae650dSJack F Vogel /* Make sure VLANS are not using driver */ 61961ae650dSJack F Vogel if (vsi->ifp->if_vlantrunk != NULL) { 62061ae650dSJack F Vogel device_printf(dev, "Vlan in use, detach first\n"); 62161ae650dSJack F Vogel return (EBUSY); 62261ae650dSJack F Vogel } 62361ae650dSJack F Vogel 62456c2c47bSJack F Vogel #ifdef PCI_IOV 62556c2c47bSJack F Vogel error = pci_iov_detach(dev); 62656c2c47bSJack F Vogel if (error != 0) { 62756c2c47bSJack F Vogel device_printf(dev, "SR-IOV in use; detach first.\n"); 62856c2c47bSJack F Vogel return (error); 62956c2c47bSJack F Vogel } 63056c2c47bSJack F Vogel #endif 63156c2c47bSJack F Vogel 632b6c8f260SJack F Vogel ether_ifdetach(vsi->ifp); 633223d846dSEric Joyner if (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING) 63461ae650dSJack F Vogel ixl_stop(pf); 63561ae650dSJack F Vogel 6366c426059SEric Joyner ixl_free_queue_tqs(vsi); 63761ae650dSJack F Vogel 63861ae650dSJack F Vogel /* Shutdown LAN HMC */ 63961ae650dSJack F Vogel status = i40e_shutdown_lan_hmc(hw); 64061ae650dSJack F Vogel if (status) 64161ae650dSJack F Vogel device_printf(dev, 64261ae650dSJack F Vogel "Shutdown LAN HMC failed with code %d\n", status); 64361ae650dSJack F Vogel 64461ae650dSJack F Vogel /* Shutdown admin queue */ 6456c426059SEric Joyner ixl_disable_adminq(hw); 6466c426059SEric Joyner ixl_free_adminq_tq(pf); 6476c426059SEric Joyner ixl_teardown_adminq_msix(pf); 64861ae650dSJack F Vogel status = i40e_shutdown_adminq(hw); 64961ae650dSJack F Vogel if (status) 65061ae650dSJack F Vogel device_printf(dev, 65161ae650dSJack F Vogel "Shutdown Admin queue failed with code %d\n", status); 65261ae650dSJack F Vogel 65361ae650dSJack F Vogel /* Unregister VLAN events */ 65461ae650dSJack F Vogel if (vsi->vlan_attach != NULL) 65561ae650dSJack F Vogel EVENTHANDLER_DEREGISTER(vlan_config, vsi->vlan_attach); 65661ae650dSJack F Vogel if (vsi->vlan_detach != NULL) 65761ae650dSJack F Vogel EVENTHANDLER_DEREGISTER(vlan_unconfig, vsi->vlan_detach); 65861ae650dSJack F Vogel 65961ae650dSJack F Vogel callout_drain(&pf->timer); 66031830672SJack F Vogel #ifdef DEV_NETMAP 66131830672SJack F Vogel netmap_detach(vsi->ifp); 66231830672SJack F Vogel #endif /* DEV_NETMAP */ 663*4294f337SSean Bruno ixl_pf_qmgr_destroy(&pf->qmgr); 66461ae650dSJack F Vogel ixl_free_pci_resources(pf); 66561ae650dSJack F Vogel bus_generic_detach(dev); 66661ae650dSJack F Vogel if_free(vsi->ifp); 66761ae650dSJack F Vogel ixl_free_vsi(vsi); 66861ae650dSJack F Vogel IXL_PF_LOCK_DESTROY(pf); 66961ae650dSJack F Vogel return (0); 67061ae650dSJack F Vogel } 67161ae650dSJack F Vogel 67261ae650dSJack F Vogel /********************************************************************* 67361ae650dSJack F Vogel * 67461ae650dSJack F Vogel * Shutdown entry point 67561ae650dSJack F Vogel * 67661ae650dSJack F Vogel **********************************************************************/ 67761ae650dSJack F Vogel 67861ae650dSJack F Vogel static int 67961ae650dSJack F Vogel ixl_shutdown(device_t dev) 68061ae650dSJack F Vogel { 68161ae650dSJack F Vogel struct ixl_pf *pf = device_get_softc(dev); 68261ae650dSJack F Vogel ixl_stop(pf); 68361ae650dSJack F Vogel return (0); 68461ae650dSJack F Vogel } 68561ae650dSJack F Vogel 686