161ae650dSJack F Vogel /****************************************************************************** 261ae650dSJack F Vogel 3*ceebc2f3SEric Joyner Copyright (c) 2013-2017, 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 38cb6b8299SEric Joyner #ifdef IXL_IW 39cb6b8299SEric Joyner #include "ixl_iw.h" 40cb6b8299SEric Joyner #include "ixl_iw_int.h" 41cb6b8299SEric Joyner #endif 42cb6b8299SEric Joyner 434294f337SSean Bruno #ifdef PCI_IOV 444294f337SSean Bruno #include "ixl_pf_iov.h" 45dcd7b3b2SJack F Vogel #endif 46dcd7b3b2SJack F Vogel 4761ae650dSJack F Vogel /********************************************************************* 4861ae650dSJack F Vogel * Driver version 4961ae650dSJack F Vogel *********************************************************************/ 50*ceebc2f3SEric Joyner #define IXL_DRIVER_VERSION_MAJOR 1 51*ceebc2f3SEric Joyner #define IXL_DRIVER_VERSION_MINOR 9 52*ceebc2f3SEric Joyner #define IXL_DRIVER_VERSION_BUILD 9 53*ceebc2f3SEric Joyner 54*ceebc2f3SEric Joyner char ixl_driver_version[] = __XSTRING(IXL_DRIVER_VERSION_MAJOR) "." 55*ceebc2f3SEric Joyner __XSTRING(IXL_DRIVER_VERSION_MINOR) "." 56*ceebc2f3SEric Joyner __XSTRING(IXL_DRIVER_VERSION_BUILD) "-k"; 5761ae650dSJack F Vogel 5861ae650dSJack F Vogel /********************************************************************* 5961ae650dSJack F Vogel * PCI Device ID Table 6061ae650dSJack F Vogel * 6161ae650dSJack F Vogel * Used by probe to select devices to load on 6261ae650dSJack F Vogel * Last field stores an index into ixl_strings 6361ae650dSJack F Vogel * Last entry must be all 0s 6461ae650dSJack F Vogel * 6561ae650dSJack F Vogel * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } 6661ae650dSJack F Vogel *********************************************************************/ 6761ae650dSJack F Vogel 6861ae650dSJack F Vogel static ixl_vendor_info_t ixl_vendor_info_array[] = 6961ae650dSJack F Vogel { 7061ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710, 0, 0, 0}, 7161ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B, 0, 0, 0}, 7261ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C, 0, 0, 0}, 7361ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A, 0, 0, 0}, 7461ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B, 0, 0, 0}, 7561ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_C, 0, 0, 0}, 7661ae650dSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T, 0, 0, 0}, 77be771cdaSJack F Vogel {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T4, 0, 0, 0}, 784294f337SSean Bruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_X722, 0, 0, 0}, 794294f337SSean Bruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_X722, 0, 0, 0}, 804294f337SSean Bruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_X722, 0, 0, 0}, 814294f337SSean Bruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_1G_BASE_T_X722, 0, 0, 0}, 824294f337SSean Bruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T_X722, 0, 0, 0}, 834294f337SSean Bruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_I_X722, 0, 0, 0}, 84cb6b8299SEric Joyner {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_B, 0, 0, 0}, 85cb6b8299SEric Joyner {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_SFP28, 0, 0, 0}, 8661ae650dSJack F Vogel /* required last entry */ 8761ae650dSJack F Vogel {0, 0, 0, 0, 0} 8861ae650dSJack F Vogel }; 8961ae650dSJack F Vogel 9061ae650dSJack F Vogel /********************************************************************* 9161ae650dSJack F Vogel * Table of branding strings 9261ae650dSJack F Vogel *********************************************************************/ 9361ae650dSJack F Vogel 9461ae650dSJack F Vogel static char *ixl_strings[] = { 95*ceebc2f3SEric Joyner "Intel(R) Ethernet Connection 700 Series PF Driver" 9661ae650dSJack F Vogel }; 9761ae650dSJack F Vogel 9861ae650dSJack F Vogel 9961ae650dSJack F Vogel /********************************************************************* 10061ae650dSJack F Vogel * Function prototypes 10161ae650dSJack F Vogel *********************************************************************/ 10261ae650dSJack F Vogel static int ixl_probe(device_t); 10361ae650dSJack F Vogel static int ixl_attach(device_t); 10461ae650dSJack F Vogel static int ixl_detach(device_t); 10561ae650dSJack F Vogel static int ixl_shutdown(device_t); 1066c426059SEric Joyner 1074294f337SSean Bruno static int ixl_save_pf_tunables(struct ixl_pf *); 10861ae650dSJack F Vogel 10961ae650dSJack F Vogel /********************************************************************* 11061ae650dSJack F Vogel * FreeBSD Device Interface Entry Points 11161ae650dSJack F Vogel *********************************************************************/ 11261ae650dSJack F Vogel 11361ae650dSJack F Vogel static device_method_t ixl_methods[] = { 11461ae650dSJack F Vogel /* Device interface */ 11561ae650dSJack F Vogel DEVMETHOD(device_probe, ixl_probe), 11661ae650dSJack F Vogel DEVMETHOD(device_attach, ixl_attach), 11761ae650dSJack F Vogel DEVMETHOD(device_detach, ixl_detach), 11861ae650dSJack F Vogel DEVMETHOD(device_shutdown, ixl_shutdown), 11956c2c47bSJack F Vogel #ifdef PCI_IOV 120a48d00d2SEric Joyner DEVMETHOD(pci_iov_init, ixl_iov_init), 121a48d00d2SEric Joyner DEVMETHOD(pci_iov_uninit, ixl_iov_uninit), 122a48d00d2SEric Joyner DEVMETHOD(pci_iov_add_vf, ixl_add_vf), 12356c2c47bSJack F Vogel #endif 12461ae650dSJack F Vogel {0, 0} 12561ae650dSJack F Vogel }; 12661ae650dSJack F Vogel 12761ae650dSJack F Vogel static driver_t ixl_driver = { 12861ae650dSJack F Vogel "ixl", ixl_methods, sizeof(struct ixl_pf), 12961ae650dSJack F Vogel }; 13061ae650dSJack F Vogel 13161ae650dSJack F Vogel devclass_t ixl_devclass; 13261ae650dSJack F Vogel DRIVER_MODULE(ixl, pci, ixl_driver, ixl_devclass, 0, 0); 13361ae650dSJack F Vogel 134cb6b8299SEric Joyner MODULE_VERSION(ixl, 1); 135cb6b8299SEric Joyner 13661ae650dSJack F Vogel MODULE_DEPEND(ixl, pci, 1, 1, 1); 13761ae650dSJack F Vogel MODULE_DEPEND(ixl, ether, 1, 1, 1); 138cb6b8299SEric Joyner #if defined(DEV_NETMAP) && __FreeBSD_version >= 1100000 13931830672SJack F Vogel MODULE_DEPEND(ixl, netmap, 1, 1, 1); 14031830672SJack F Vogel #endif /* DEV_NETMAP */ 14131830672SJack F Vogel 14261ae650dSJack F Vogel /* 14361ae650dSJack F Vogel ** TUNEABLE PARAMETERS: 14461ae650dSJack F Vogel */ 14561ae650dSJack F Vogel 14661ae650dSJack F Vogel static SYSCTL_NODE(_hw, OID_AUTO, ixl, CTLFLAG_RD, 0, 14761ae650dSJack F Vogel "IXL driver parameters"); 14861ae650dSJack F Vogel 14961ae650dSJack F Vogel /* 15061ae650dSJack F Vogel * MSIX should be the default for best performance, 15161ae650dSJack F Vogel * but this allows it to be forced off for testing. 15261ae650dSJack F Vogel */ 15361ae650dSJack F Vogel static int ixl_enable_msix = 1; 15461ae650dSJack F Vogel TUNABLE_INT("hw.ixl.enable_msix", &ixl_enable_msix); 15561ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixl_enable_msix, 0, 15661ae650dSJack F Vogel "Enable MSI-X interrupts"); 15761ae650dSJack F Vogel 15861ae650dSJack F Vogel /* 159*ceebc2f3SEric Joyner ** Number of descriptors per ring 160*ceebc2f3SEric Joyner ** - TX and RX sizes are independently configurable 16161ae650dSJack F Vogel */ 162*ceebc2f3SEric Joyner static int ixl_tx_ring_size = IXL_DEFAULT_RING; 163*ceebc2f3SEric Joyner TUNABLE_INT("hw.ixl.tx_ring_size", &ixl_tx_ring_size); 164*ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, tx_ring_size, CTLFLAG_RDTUN, 165*ceebc2f3SEric Joyner &ixl_tx_ring_size, 0, "TX Descriptor Ring Size"); 166*ceebc2f3SEric Joyner 167*ceebc2f3SEric Joyner static int ixl_rx_ring_size = IXL_DEFAULT_RING; 168*ceebc2f3SEric Joyner TUNABLE_INT("hw.ixl.rx_ring_size", &ixl_rx_ring_size); 169*ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, rx_ring_size, CTLFLAG_RDTUN, 170*ceebc2f3SEric Joyner &ixl_rx_ring_size, 0, "RX Descriptor Ring Size"); 17161ae650dSJack F Vogel 17261ae650dSJack F Vogel /* 17361ae650dSJack F Vogel ** This can be set manually, if left as 0 the 17461ae650dSJack F Vogel ** number of queues will be calculated based 17561ae650dSJack F Vogel ** on cpus and msix vectors available. 17661ae650dSJack F Vogel */ 1774294f337SSean Bruno static int ixl_max_queues = 0; 17861ae650dSJack F Vogel TUNABLE_INT("hw.ixl.max_queues", &ixl_max_queues); 17961ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, max_queues, CTLFLAG_RDTUN, 18061ae650dSJack F Vogel &ixl_max_queues, 0, "Number of Queues"); 18161ae650dSJack F Vogel 182*ceebc2f3SEric Joyner /* 183*ceebc2f3SEric Joyner * Leave this on unless you need to send flow control 184*ceebc2f3SEric Joyner * frames (or other control frames) from software 185*ceebc2f3SEric Joyner */ 1864294f337SSean Bruno static int ixl_enable_tx_fc_filter = 1; 1874294f337SSean Bruno TUNABLE_INT("hw.ixl.enable_tx_fc_filter", 1884294f337SSean Bruno &ixl_enable_tx_fc_filter); 1894294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, enable_tx_fc_filter, CTLFLAG_RDTUN, 1904294f337SSean Bruno &ixl_enable_tx_fc_filter, 0, 1914294f337SSean Bruno "Filter out packets with Ethertype 0x8808 from being sent out by non-HW sources"); 1924294f337SSean Bruno 193*ceebc2f3SEric Joyner /* 194*ceebc2f3SEric Joyner * Different method for processing TX descriptor 195*ceebc2f3SEric Joyner * completion. 196*ceebc2f3SEric Joyner */ 197*ceebc2f3SEric Joyner static int ixl_enable_head_writeback = 1; 198*ceebc2f3SEric Joyner TUNABLE_INT("hw.ixl.enable_head_writeback", 199*ceebc2f3SEric Joyner &ixl_enable_head_writeback); 200*ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, enable_head_writeback, CTLFLAG_RDTUN, 201*ceebc2f3SEric Joyner &ixl_enable_head_writeback, 0, 202*ceebc2f3SEric Joyner "For detecting last completed TX descriptor by hardware, use value written by HW instead of checking descriptors"); 203*ceebc2f3SEric Joyner 2044294f337SSean Bruno static int ixl_core_debug_mask = 0; 2054294f337SSean Bruno TUNABLE_INT("hw.ixl.core_debug_mask", 2064294f337SSean Bruno &ixl_core_debug_mask); 2074294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, core_debug_mask, CTLFLAG_RDTUN, 2084294f337SSean Bruno &ixl_core_debug_mask, 0, 2094294f337SSean Bruno "Display debug statements that are printed in non-shared code"); 2104294f337SSean Bruno 2114294f337SSean Bruno static int ixl_shared_debug_mask = 0; 2124294f337SSean Bruno TUNABLE_INT("hw.ixl.shared_debug_mask", 2134294f337SSean Bruno &ixl_shared_debug_mask); 2144294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, shared_debug_mask, CTLFLAG_RDTUN, 2154294f337SSean Bruno &ixl_shared_debug_mask, 0, 2164294f337SSean Bruno "Display debug statements that are printed in shared code"); 2174294f337SSean Bruno 21861ae650dSJack F Vogel /* 21961ae650dSJack F Vogel ** Controls for Interrupt Throttling 22061ae650dSJack F Vogel ** - true/false for dynamic adjustment 22161ae650dSJack F Vogel ** - default values for static ITR 22261ae650dSJack F Vogel */ 2234294f337SSean Bruno static int ixl_dynamic_rx_itr = 1; 22461ae650dSJack F Vogel TUNABLE_INT("hw.ixl.dynamic_rx_itr", &ixl_dynamic_rx_itr); 22561ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_rx_itr, CTLFLAG_RDTUN, 22661ae650dSJack F Vogel &ixl_dynamic_rx_itr, 0, "Dynamic RX Interrupt Rate"); 22761ae650dSJack F Vogel 2284294f337SSean Bruno static int ixl_dynamic_tx_itr = 1; 22961ae650dSJack F Vogel TUNABLE_INT("hw.ixl.dynamic_tx_itr", &ixl_dynamic_tx_itr); 23061ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_tx_itr, CTLFLAG_RDTUN, 23161ae650dSJack F Vogel &ixl_dynamic_tx_itr, 0, "Dynamic TX Interrupt Rate"); 23261ae650dSJack F Vogel 2334294f337SSean Bruno static int ixl_rx_itr = IXL_ITR_8K; 23461ae650dSJack F Vogel TUNABLE_INT("hw.ixl.rx_itr", &ixl_rx_itr); 23561ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, rx_itr, CTLFLAG_RDTUN, 23661ae650dSJack F Vogel &ixl_rx_itr, 0, "RX Interrupt Rate"); 23761ae650dSJack F Vogel 2384294f337SSean Bruno static int ixl_tx_itr = IXL_ITR_4K; 23961ae650dSJack F Vogel TUNABLE_INT("hw.ixl.tx_itr", &ixl_tx_itr); 24061ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, tx_itr, CTLFLAG_RDTUN, 24161ae650dSJack F Vogel &ixl_tx_itr, 0, "TX Interrupt Rate"); 24261ae650dSJack F Vogel 243cb6b8299SEric Joyner #ifdef IXL_IW 244cb6b8299SEric Joyner int ixl_enable_iwarp = 0; 245cb6b8299SEric Joyner TUNABLE_INT("hw.ixl.enable_iwarp", &ixl_enable_iwarp); 246*ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, enable_iwarp, CTLFLAG_RDTUN, 247*ceebc2f3SEric Joyner &ixl_enable_iwarp, 0, "iWARP enabled"); 248*ceebc2f3SEric Joyner 249*ceebc2f3SEric Joyner #if __FreeBSD_version < 1100000 250*ceebc2f3SEric Joyner int ixl_limit_iwarp_msix = 1; 251*ceebc2f3SEric Joyner #else 252*ceebc2f3SEric Joyner int ixl_limit_iwarp_msix = IXL_IW_MAX_MSIX; 253*ceebc2f3SEric Joyner #endif 254*ceebc2f3SEric Joyner TUNABLE_INT("hw.ixl.limit_iwarp_msix", &ixl_limit_iwarp_msix); 255*ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, limit_iwarp_msix, CTLFLAG_RDTUN, 256*ceebc2f3SEric Joyner &ixl_limit_iwarp_msix, 0, "Limit MSIX vectors assigned to iWARP"); 257cb6b8299SEric Joyner #endif 258cb6b8299SEric Joyner 25931830672SJack F Vogel #ifdef DEV_NETMAP 26031830672SJack F Vogel #define NETMAP_IXL_MAIN /* only bring in one part of the netmap code */ 26131830672SJack F Vogel #include <dev/netmap/if_ixl_netmap.h> 26231830672SJack F Vogel #endif /* DEV_NETMAP */ 263e5100ee2SJack F Vogel 26461ae650dSJack F Vogel /********************************************************************* 26561ae650dSJack F Vogel * Device identification routine 26661ae650dSJack F Vogel * 26761ae650dSJack F Vogel * ixl_probe determines if the driver should be loaded on 26861ae650dSJack F Vogel * the hardware based on PCI vendor/device id of the device. 26961ae650dSJack F Vogel * 27061ae650dSJack F Vogel * return BUS_PROBE_DEFAULT on success, positive on failure 27161ae650dSJack F Vogel *********************************************************************/ 27261ae650dSJack F Vogel 27361ae650dSJack F Vogel static int 27461ae650dSJack F Vogel ixl_probe(device_t dev) 27561ae650dSJack F Vogel { 27661ae650dSJack F Vogel ixl_vendor_info_t *ent; 27761ae650dSJack F Vogel 27861ae650dSJack F Vogel u16 pci_vendor_id, pci_device_id; 27961ae650dSJack F Vogel u16 pci_subvendor_id, pci_subdevice_id; 28061ae650dSJack F Vogel char device_name[256]; 28161ae650dSJack F Vogel 2821d767a8eSEric Joyner #if 0 28361ae650dSJack F Vogel INIT_DEBUGOUT("ixl_probe: begin"); 2841d767a8eSEric Joyner #endif 28561ae650dSJack F Vogel pci_vendor_id = pci_get_vendor(dev); 28661ae650dSJack F Vogel if (pci_vendor_id != I40E_INTEL_VENDOR_ID) 28761ae650dSJack F Vogel return (ENXIO); 28861ae650dSJack F Vogel 28961ae650dSJack F Vogel pci_device_id = pci_get_device(dev); 29061ae650dSJack F Vogel pci_subvendor_id = pci_get_subvendor(dev); 29161ae650dSJack F Vogel pci_subdevice_id = pci_get_subdevice(dev); 29261ae650dSJack F Vogel 29361ae650dSJack F Vogel ent = ixl_vendor_info_array; 29461ae650dSJack F Vogel while (ent->vendor_id != 0) { 29561ae650dSJack F Vogel if ((pci_vendor_id == ent->vendor_id) && 29661ae650dSJack F Vogel (pci_device_id == ent->device_id) && 29761ae650dSJack F Vogel 29861ae650dSJack F Vogel ((pci_subvendor_id == ent->subvendor_id) || 29961ae650dSJack F Vogel (ent->subvendor_id == 0)) && 30061ae650dSJack F Vogel 30161ae650dSJack F Vogel ((pci_subdevice_id == ent->subdevice_id) || 30261ae650dSJack F Vogel (ent->subdevice_id == 0))) { 30361ae650dSJack F Vogel sprintf(device_name, "%s, Version - %s", 30461ae650dSJack F Vogel ixl_strings[ent->index], 30561ae650dSJack F Vogel ixl_driver_version); 30661ae650dSJack F Vogel device_set_desc_copy(dev, device_name); 30761ae650dSJack F Vogel return (BUS_PROBE_DEFAULT); 30861ae650dSJack F Vogel } 30961ae650dSJack F Vogel ent++; 31061ae650dSJack F Vogel } 31161ae650dSJack F Vogel return (ENXIO); 31261ae650dSJack F Vogel } 31361ae650dSJack F Vogel 3144294f337SSean Bruno /* 3154294f337SSean Bruno * Sanity check and save off tunable values. 3164294f337SSean Bruno */ 3174294f337SSean Bruno static int 3184294f337SSean Bruno ixl_save_pf_tunables(struct ixl_pf *pf) 3194294f337SSean Bruno { 3204294f337SSean Bruno device_t dev = pf->dev; 3214294f337SSean Bruno 3224294f337SSean Bruno /* Save tunable information */ 3234294f337SSean Bruno pf->enable_msix = ixl_enable_msix; 3244294f337SSean Bruno pf->max_queues = ixl_max_queues; 3254294f337SSean Bruno pf->enable_tx_fc_filter = ixl_enable_tx_fc_filter; 3264294f337SSean Bruno pf->dynamic_rx_itr = ixl_dynamic_rx_itr; 3274294f337SSean Bruno pf->dynamic_tx_itr = ixl_dynamic_tx_itr; 3284294f337SSean Bruno pf->dbg_mask = ixl_core_debug_mask; 3294294f337SSean Bruno pf->hw.debug_mask = ixl_shared_debug_mask; 330*ceebc2f3SEric Joyner #ifdef DEV_NETMAP 331*ceebc2f3SEric Joyner if (ixl_enable_head_writeback == 0) 332*ceebc2f3SEric Joyner device_printf(dev, "Head writeback mode cannot be disabled " 333*ceebc2f3SEric Joyner "when netmap is enabled\n"); 334*ceebc2f3SEric Joyner pf->vsi.enable_head_writeback = 1; 335*ceebc2f3SEric Joyner #else 336*ceebc2f3SEric Joyner pf->vsi.enable_head_writeback = !!(ixl_enable_head_writeback); 337*ceebc2f3SEric Joyner #endif 3384294f337SSean Bruno 339*ceebc2f3SEric Joyner ixl_vsi_setup_rings_size(&pf->vsi, ixl_tx_ring_size, ixl_rx_ring_size); 340cb6b8299SEric Joyner 341cb6b8299SEric Joyner if (ixl_tx_itr < 0 || ixl_tx_itr > IXL_MAX_ITR) { 342cb6b8299SEric Joyner device_printf(dev, "Invalid tx_itr value of %d set!\n", 343cb6b8299SEric Joyner ixl_tx_itr); 344cb6b8299SEric Joyner device_printf(dev, "tx_itr must be between %d and %d, " 345cb6b8299SEric Joyner "inclusive\n", 346cb6b8299SEric Joyner 0, IXL_MAX_ITR); 347cb6b8299SEric Joyner device_printf(dev, "Using default value of %d instead\n", 348cb6b8299SEric Joyner IXL_ITR_4K); 349cb6b8299SEric Joyner pf->tx_itr = IXL_ITR_4K; 350cb6b8299SEric Joyner } else 351cb6b8299SEric Joyner pf->tx_itr = ixl_tx_itr; 352cb6b8299SEric Joyner 353cb6b8299SEric Joyner if (ixl_rx_itr < 0 || ixl_rx_itr > IXL_MAX_ITR) { 354cb6b8299SEric Joyner device_printf(dev, "Invalid rx_itr value of %d set!\n", 355cb6b8299SEric Joyner ixl_rx_itr); 356cb6b8299SEric Joyner device_printf(dev, "rx_itr must be between %d and %d, " 357cb6b8299SEric Joyner "inclusive\n", 358cb6b8299SEric Joyner 0, IXL_MAX_ITR); 359cb6b8299SEric Joyner device_printf(dev, "Using default value of %d instead\n", 360cb6b8299SEric Joyner IXL_ITR_8K); 361cb6b8299SEric Joyner pf->rx_itr = IXL_ITR_8K; 362cb6b8299SEric Joyner } else 363cb6b8299SEric Joyner pf->rx_itr = ixl_rx_itr; 3644294f337SSean Bruno 3654294f337SSean Bruno return (0); 3664294f337SSean Bruno } 3674294f337SSean Bruno 36861ae650dSJack F Vogel /********************************************************************* 36961ae650dSJack F Vogel * Device initialization routine 37061ae650dSJack F Vogel * 37161ae650dSJack F Vogel * The attach entry point is called when the driver is being loaded. 37261ae650dSJack F Vogel * This routine identifies the type of hardware, allocates all resources 37361ae650dSJack F Vogel * and initializes the hardware. 37461ae650dSJack F Vogel * 37561ae650dSJack F Vogel * return 0 on success, positive on failure 37661ae650dSJack F Vogel *********************************************************************/ 37761ae650dSJack F Vogel 37861ae650dSJack F Vogel static int 37961ae650dSJack F Vogel ixl_attach(device_t dev) 38061ae650dSJack F Vogel { 38161ae650dSJack F Vogel struct ixl_pf *pf; 38261ae650dSJack F Vogel struct i40e_hw *hw; 38361ae650dSJack F Vogel struct ixl_vsi *vsi; 3844294f337SSean Bruno enum i40e_status_code status; 38561ae650dSJack F Vogel int error = 0; 38661ae650dSJack F Vogel 38761ae650dSJack F Vogel INIT_DEBUGOUT("ixl_attach: begin"); 38861ae650dSJack F Vogel 38961ae650dSJack F Vogel /* Allocate, clear, and link in our primary soft structure */ 39061ae650dSJack F Vogel pf = device_get_softc(dev); 39161ae650dSJack F Vogel pf->dev = pf->osdep.dev = dev; 39261ae650dSJack F Vogel hw = &pf->hw; 39361ae650dSJack F Vogel 39461ae650dSJack F Vogel /* 39561ae650dSJack F Vogel ** Note this assumes we have a single embedded VSI, 39661ae650dSJack F Vogel ** this could be enhanced later to allocate multiple 39761ae650dSJack F Vogel */ 39861ae650dSJack F Vogel vsi = &pf->vsi; 39961ae650dSJack F Vogel vsi->dev = pf->dev; 400*ceebc2f3SEric Joyner vsi->back = pf; 40161ae650dSJack F Vogel 4024294f337SSean Bruno /* Save tunable values */ 4034294f337SSean Bruno error = ixl_save_pf_tunables(pf); 4044294f337SSean Bruno if (error) 4054294f337SSean Bruno return (error); 4064294f337SSean Bruno 40761ae650dSJack F Vogel /* Core Lock Init*/ 40861ae650dSJack F Vogel IXL_PF_LOCK_INIT(pf, device_get_nameunit(dev)); 40961ae650dSJack F Vogel 41061ae650dSJack F Vogel /* Set up the timer callout */ 41161ae650dSJack F Vogel callout_init_mtx(&pf->timer, &pf->pf_mtx, 0); 41261ae650dSJack F Vogel 41361ae650dSJack F Vogel /* Do PCI setup - map BAR0, etc */ 41461ae650dSJack F Vogel if (ixl_allocate_pci_resources(pf)) { 41561ae650dSJack F Vogel device_printf(dev, "Allocation of PCI resources failed\n"); 41661ae650dSJack F Vogel error = ENXIO; 41761ae650dSJack F Vogel goto err_out; 41861ae650dSJack F Vogel } 41961ae650dSJack F Vogel 42061ae650dSJack F Vogel /* Establish a clean starting point */ 42161ae650dSJack F Vogel i40e_clear_hw(hw); 4224294f337SSean Bruno status = i40e_pf_reset(hw); 4234294f337SSean Bruno if (status) { 4244294f337SSean Bruno device_printf(dev, "PF reset failure %s\n", 4254294f337SSean Bruno i40e_stat_str(hw, status)); 42661ae650dSJack F Vogel error = EIO; 42761ae650dSJack F Vogel goto err_out; 42861ae650dSJack F Vogel } 42961ae650dSJack F Vogel 43061ae650dSJack F Vogel /* Initialize the shared code */ 4314294f337SSean Bruno status = i40e_init_shared_code(hw); 4324294f337SSean Bruno if (status) { 4334294f337SSean Bruno device_printf(dev, "Unable to initialize shared code, error %s\n", 4344294f337SSean Bruno i40e_stat_str(hw, status)); 43561ae650dSJack F Vogel error = EIO; 43661ae650dSJack F Vogel goto err_out; 43761ae650dSJack F Vogel } 43861ae650dSJack F Vogel 43961ae650dSJack F Vogel /* Set up the admin queue */ 4404294f337SSean Bruno hw->aq.num_arq_entries = IXL_AQ_LEN; 4414294f337SSean Bruno hw->aq.num_asq_entries = IXL_AQ_LEN; 4424294f337SSean Bruno hw->aq.arq_buf_size = IXL_AQ_BUF_SZ; 4434294f337SSean Bruno hw->aq.asq_buf_size = IXL_AQ_BUF_SZ; 4444294f337SSean Bruno 4454294f337SSean Bruno status = i40e_init_adminq(hw); 4464294f337SSean Bruno if (status != 0 && status != I40E_ERR_FIRMWARE_API_VERSION) { 4474294f337SSean Bruno device_printf(dev, "Unable to initialize Admin Queue, error %s\n", 4484294f337SSean Bruno i40e_stat_str(hw, status)); 449fdb6f38aSEric Joyner error = EIO; 450fdb6f38aSEric Joyner goto err_out; 451fdb6f38aSEric Joyner } 4521d767a8eSEric Joyner ixl_print_nvm_version(pf); 4531d767a8eSEric Joyner 4544294f337SSean Bruno if (status == I40E_ERR_FIRMWARE_API_VERSION) { 45561ae650dSJack F Vogel device_printf(dev, "The driver for the device stopped " 456*ceebc2f3SEric Joyner "because the NVM image is newer than expected.\n"); 457*ceebc2f3SEric Joyner device_printf(dev, "You must install the most recent version of " 45861ae650dSJack F Vogel "the network driver.\n"); 459fdb6f38aSEric Joyner error = EIO; 46061ae650dSJack F Vogel goto err_out; 46161ae650dSJack F Vogel } 46261ae650dSJack F Vogel 46361ae650dSJack F Vogel if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR && 464*ceebc2f3SEric Joyner hw->aq.api_min_ver > I40E_FW_MINOR_VERSION(hw)) { 46561ae650dSJack F Vogel device_printf(dev, "The driver for the device detected " 466*ceebc2f3SEric Joyner "a newer version of the NVM image than expected.\n"); 467*ceebc2f3SEric Joyner device_printf(dev, "Please install the most recent version " 468*ceebc2f3SEric Joyner "of the network driver.\n"); 469*ceebc2f3SEric Joyner } else if (hw->aq.api_maj_ver == 1 && hw->aq.api_min_ver < 4) { 47061ae650dSJack F Vogel device_printf(dev, "The driver for the device detected " 471*ceebc2f3SEric Joyner "an older version of the NVM image than expected.\n"); 472*ceebc2f3SEric Joyner device_printf(dev, "Please update the NVM image.\n"); 473*ceebc2f3SEric Joyner } 47461ae650dSJack F Vogel 47561ae650dSJack F Vogel /* Clear PXE mode */ 47661ae650dSJack F Vogel i40e_clear_pxe_mode(hw); 47761ae650dSJack F Vogel 47861ae650dSJack F Vogel /* Get capabilities from the device */ 47961ae650dSJack F Vogel error = ixl_get_hw_capabilities(pf); 48061ae650dSJack F Vogel if (error) { 48161ae650dSJack F Vogel device_printf(dev, "HW capabilities failure!\n"); 48261ae650dSJack F Vogel goto err_get_cap; 48361ae650dSJack F Vogel } 48461ae650dSJack F Vogel 485*ceebc2f3SEric Joyner /* 486*ceebc2f3SEric Joyner * Allocate interrupts and figure out number of queues to use 487*ceebc2f3SEric Joyner * for PF interface 488*ceebc2f3SEric Joyner */ 489*ceebc2f3SEric Joyner pf->msix = ixl_init_msix(pf); 490*ceebc2f3SEric Joyner 49161ae650dSJack F Vogel /* Set up host memory cache */ 4924294f337SSean Bruno status = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp, 49356c2c47bSJack F Vogel hw->func_caps.num_rx_qp, 0, 0); 4944294f337SSean Bruno if (status) { 4954294f337SSean Bruno device_printf(dev, "init_lan_hmc failed: %s\n", 4964294f337SSean Bruno i40e_stat_str(hw, status)); 49761ae650dSJack F Vogel goto err_get_cap; 49861ae650dSJack F Vogel } 49961ae650dSJack F Vogel 5004294f337SSean Bruno status = i40e_configure_lan_hmc(hw, I40E_HMC_MODEL_DIRECT_ONLY); 5014294f337SSean Bruno if (status) { 5024294f337SSean Bruno device_printf(dev, "configure_lan_hmc failed: %s\n", 5034294f337SSean Bruno i40e_stat_str(hw, status)); 50461ae650dSJack F Vogel goto err_mac_hmc; 50561ae650dSJack F Vogel } 50661ae650dSJack F Vogel 5074294f337SSean Bruno /* Init queue allocation manager */ 5084294f337SSean Bruno error = ixl_pf_qmgr_init(&pf->qmgr, hw->func_caps.num_tx_qp); 5094294f337SSean Bruno if (error) { 5104294f337SSean Bruno device_printf(dev, "Failed to init queue manager for PF queues, error %d\n", 5114294f337SSean Bruno error); 5124294f337SSean Bruno goto err_mac_hmc; 5134294f337SSean Bruno } 5144294f337SSean Bruno /* reserve a contiguous allocation for the PF's VSI */ 5154294f337SSean Bruno error = ixl_pf_qmgr_alloc_contiguous(&pf->qmgr, vsi->num_queues, &pf->qtag); 5164294f337SSean Bruno if (error) { 5174294f337SSean Bruno device_printf(dev, "Failed to reserve queues for PF LAN VSI, error %d\n", 5184294f337SSean Bruno error); 5194294f337SSean Bruno goto err_mac_hmc; 5204294f337SSean Bruno } 5214294f337SSean Bruno device_printf(dev, "Allocating %d queues for PF LAN VSI; %d queues active\n", 5224294f337SSean Bruno pf->qtag.num_allocated, pf->qtag.num_active); 5234294f337SSean Bruno 524d4683565SEric Joyner /* Disable LLDP from the firmware for certain NVM versions */ 525d4683565SEric Joyner if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 3)) || 526*ceebc2f3SEric Joyner (pf->hw.aq.fw_maj_ver < 4)) { 52761ae650dSJack F Vogel i40e_aq_stop_lldp(hw, TRUE, NULL); 528*ceebc2f3SEric Joyner pf->state |= IXL_PF_STATE_FW_LLDP_DISABLED; 529*ceebc2f3SEric Joyner } 53061ae650dSJack F Vogel 5314294f337SSean Bruno /* Get MAC addresses from hardware */ 53261ae650dSJack F Vogel i40e_get_mac_addr(hw, hw->mac.addr); 53361ae650dSJack F Vogel error = i40e_validate_mac_addr(hw->mac.addr); 53461ae650dSJack F Vogel if (error) { 53561ae650dSJack F Vogel device_printf(dev, "validate_mac_addr failed: %d\n", error); 53661ae650dSJack F Vogel goto err_mac_hmc; 53761ae650dSJack F Vogel } 53861ae650dSJack F Vogel bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN); 53961ae650dSJack F Vogel i40e_get_port_mac_addr(hw, hw->mac.port_addr); 54061ae650dSJack F Vogel 541*ceebc2f3SEric Joyner /* Query device FW LLDP status */ 542*ceebc2f3SEric Joyner ixl_get_fw_lldp_status(pf); 543*ceebc2f3SEric Joyner /* Tell FW to apply DCB config on link up */ 544*ceebc2f3SEric Joyner if ((hw->mac.type != I40E_MAC_X722) 545*ceebc2f3SEric Joyner && ((pf->hw.aq.api_maj_ver > 1) 546*ceebc2f3SEric Joyner || (pf->hw.aq.api_maj_ver == 1 && pf->hw.aq.api_min_ver >= 7))) 547*ceebc2f3SEric Joyner i40e_aq_set_dcb_parameters(hw, true, NULL); 548*ceebc2f3SEric Joyner 5494294f337SSean Bruno /* Initialize mac filter list for VSI */ 5504294f337SSean Bruno SLIST_INIT(&vsi->ftl); 5514294f337SSean Bruno 5524294f337SSean Bruno /* Set up SW VSI and allocate queue memory and rings */ 5534294f337SSean Bruno if (ixl_setup_stations(pf)) { 55461ae650dSJack F Vogel device_printf(dev, "setup stations failed!\n"); 55561ae650dSJack F Vogel error = ENOMEM; 55661ae650dSJack F Vogel goto err_mac_hmc; 55761ae650dSJack F Vogel } 55861ae650dSJack F Vogel 5594294f337SSean Bruno /* Setup OS network interface / ifnet */ 5604294f337SSean Bruno if (ixl_setup_interface(dev, vsi)) { 5614294f337SSean Bruno device_printf(dev, "interface setup failed!\n"); 5624294f337SSean Bruno error = EIO; 563223d846dSEric Joyner goto err_late; 564223d846dSEric Joyner } 56561ae650dSJack F Vogel 56661ae650dSJack F Vogel /* Determine link state */ 5674294f337SSean Bruno if (ixl_attach_get_link_status(pf)) { 5684294f337SSean Bruno error = EINVAL; 56961ae650dSJack F Vogel goto err_late; 570e5100ee2SJack F Vogel } 57161ae650dSJack F Vogel 572b6c8f260SJack F Vogel error = ixl_switch_config(pf); 573b6c8f260SJack F Vogel if (error) { 5746c426059SEric Joyner device_printf(dev, "Initial ixl_switch_config() failed: %d\n", 5756c426059SEric Joyner error); 576a48d00d2SEric Joyner goto err_late; 577b6c8f260SJack F Vogel } 578b6c8f260SJack F Vogel 579223d846dSEric Joyner /* Limit PHY interrupts to link, autoneg, and modules failure */ 5804294f337SSean Bruno status = i40e_aq_set_phy_int_mask(hw, IXL_DEFAULT_PHY_INT_MASK, 581223d846dSEric Joyner NULL); 5824294f337SSean Bruno if (status) { 5834294f337SSean Bruno device_printf(dev, "i40e_aq_set_phy_mask() failed: err %s," 5844294f337SSean Bruno " aq_err %s\n", i40e_stat_str(hw, status), 5854294f337SSean Bruno i40e_aq_str(hw, hw->aq.asq_last_status)); 586223d846dSEric Joyner goto err_late; 587223d846dSEric Joyner } 588b6c8f260SJack F Vogel 5896c426059SEric Joyner /* Get the bus configuration and set the shared code's config */ 590cb6b8299SEric Joyner ixl_get_bus_info(pf); 59161ae650dSJack F Vogel 5926c426059SEric Joyner /* 5936c426059SEric Joyner * In MSI-X mode, initialize the Admin Queue interrupt, 5946c426059SEric Joyner * so userland tools can communicate with the adapter regardless of 5956c426059SEric Joyner * the ifnet interface's status. 5966c426059SEric Joyner */ 5976c426059SEric Joyner if (pf->msix > 1) { 5986c426059SEric Joyner error = ixl_setup_adminq_msix(pf); 5996c426059SEric Joyner if (error) { 600cb6b8299SEric Joyner device_printf(dev, "ixl_setup_adminq_msix() error: %d\n", 6016c426059SEric Joyner error); 6026c426059SEric Joyner goto err_late; 6036c426059SEric Joyner } 6046c426059SEric Joyner error = ixl_setup_adminq_tq(pf); 6056c426059SEric Joyner if (error) { 606cb6b8299SEric Joyner device_printf(dev, "ixl_setup_adminq_tq() error: %d\n", 6076c426059SEric Joyner error); 6086c426059SEric Joyner goto err_late; 6096c426059SEric Joyner } 6106c426059SEric Joyner ixl_configure_intr0_msix(pf); 611cb6b8299SEric Joyner ixl_enable_intr0(hw); 612cb6b8299SEric Joyner 613cb6b8299SEric Joyner error = ixl_setup_queue_msix(vsi); 614cb6b8299SEric Joyner if (error) 615cb6b8299SEric Joyner device_printf(dev, "ixl_setup_queue_msix() error: %d\n", 616cb6b8299SEric Joyner error); 617cb6b8299SEric Joyner error = ixl_setup_queue_tqs(vsi); 618cb6b8299SEric Joyner if (error) 619cb6b8299SEric Joyner device_printf(dev, "ixl_setup_queue_tqs() error: %d\n", 620cb6b8299SEric Joyner error); 621cb6b8299SEric Joyner } else { 622cb6b8299SEric Joyner error = ixl_setup_legacy(pf); 623cb6b8299SEric Joyner 624cb6b8299SEric Joyner error = ixl_setup_adminq_tq(pf); 625cb6b8299SEric Joyner if (error) { 626cb6b8299SEric Joyner device_printf(dev, "ixl_setup_adminq_tq() error: %d\n", 627cb6b8299SEric Joyner error); 628cb6b8299SEric Joyner goto err_late; 6296c426059SEric Joyner } 630a48d00d2SEric Joyner 631cb6b8299SEric Joyner error = ixl_setup_queue_tqs(vsi); 632cb6b8299SEric Joyner if (error) 633cb6b8299SEric Joyner device_printf(dev, "ixl_setup_queue_tqs() error: %d\n", 634cb6b8299SEric Joyner error); 635cb6b8299SEric Joyner } 636cb6b8299SEric Joyner 637cb6b8299SEric Joyner if (error) { 638cb6b8299SEric Joyner device_printf(dev, "interrupt setup error: %d\n", error); 639cb6b8299SEric Joyner } 640cb6b8299SEric Joyner 641cb6b8299SEric Joyner /* Set initial advertised speed sysctl value */ 642*ceebc2f3SEric Joyner ixl_set_initial_advertised_speeds(pf); 643cb6b8299SEric Joyner 644fdb6f38aSEric Joyner /* Initialize statistics & add sysctls */ 645fdb6f38aSEric Joyner ixl_add_device_sysctls(pf); 646fdb6f38aSEric Joyner 64761ae650dSJack F Vogel ixl_pf_reset_stats(pf); 64861ae650dSJack F Vogel ixl_update_stats_counters(pf); 64961ae650dSJack F Vogel ixl_add_hw_stats(pf); 65061ae650dSJack F Vogel 65161ae650dSJack F Vogel /* Register for VLAN events */ 65261ae650dSJack F Vogel vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, 65361ae650dSJack F Vogel ixl_register_vlan, vsi, EVENTHANDLER_PRI_FIRST); 65461ae650dSJack F Vogel vsi->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, 65561ae650dSJack F Vogel ixl_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST); 65661ae650dSJack F Vogel 65756c2c47bSJack F Vogel #ifdef PCI_IOV 6584294f337SSean Bruno ixl_initialize_sriov(pf); 65956c2c47bSJack F Vogel #endif 66056c2c47bSJack F Vogel 66131830672SJack F Vogel #ifdef DEV_NETMAP 662*ceebc2f3SEric Joyner if (vsi->num_rx_desc == vsi->num_tx_desc) { 663*ceebc2f3SEric Joyner vsi->queues[0].num_desc = vsi->num_rx_desc; 66431830672SJack F Vogel ixl_netmap_attach(vsi); 665*ceebc2f3SEric Joyner } else 666*ceebc2f3SEric Joyner device_printf(dev, 667*ceebc2f3SEric Joyner "Netmap is not supported when RX and TX descriptor ring sizes differ\n"); 668*ceebc2f3SEric Joyner 66931830672SJack F Vogel #endif /* DEV_NETMAP */ 670cb6b8299SEric Joyner 671cb6b8299SEric Joyner #ifdef IXL_IW 672cb6b8299SEric Joyner if (hw->func_caps.iwarp && ixl_enable_iwarp) { 673cb6b8299SEric Joyner pf->iw_enabled = (pf->iw_msix > 0) ? true : false; 674cb6b8299SEric Joyner if (pf->iw_enabled) { 675cb6b8299SEric Joyner error = ixl_iw_pf_attach(pf); 676cb6b8299SEric Joyner if (error) { 677cb6b8299SEric Joyner device_printf(dev, 678cb6b8299SEric Joyner "interfacing to iwarp driver failed: %d\n", 679cb6b8299SEric Joyner error); 680cb6b8299SEric Joyner goto err_late; 681*ceebc2f3SEric Joyner } else 682*ceebc2f3SEric Joyner device_printf(dev, "iWARP ready\n"); 683cb6b8299SEric Joyner } else 684cb6b8299SEric Joyner device_printf(dev, 685cb6b8299SEric Joyner "iwarp disabled on this device (no msix vectors)\n"); 686cb6b8299SEric Joyner } else { 687cb6b8299SEric Joyner pf->iw_enabled = false; 688cb6b8299SEric Joyner device_printf(dev, "The device is not iWARP enabled\n"); 689cb6b8299SEric Joyner } 690cb6b8299SEric Joyner #endif 691cb6b8299SEric Joyner 69261ae650dSJack F Vogel INIT_DEBUGOUT("ixl_attach: end"); 69361ae650dSJack F Vogel return (0); 69461ae650dSJack F Vogel 69561ae650dSJack F Vogel err_late: 6964294f337SSean Bruno if (vsi->ifp != NULL) { 6974294f337SSean Bruno ether_ifdetach(vsi->ifp); 698e5100ee2SJack F Vogel if_free(vsi->ifp); 6994294f337SSean Bruno } 70061ae650dSJack F Vogel err_mac_hmc: 70161ae650dSJack F Vogel i40e_shutdown_lan_hmc(hw); 70261ae650dSJack F Vogel err_get_cap: 70361ae650dSJack F Vogel i40e_shutdown_adminq(hw); 70461ae650dSJack F Vogel err_out: 70561ae650dSJack F Vogel ixl_free_pci_resources(pf); 706e5100ee2SJack F Vogel ixl_free_vsi(vsi); 70761ae650dSJack F Vogel IXL_PF_LOCK_DESTROY(pf); 70861ae650dSJack F Vogel return (error); 70961ae650dSJack F Vogel } 71061ae650dSJack F Vogel 71161ae650dSJack F Vogel /********************************************************************* 71261ae650dSJack F Vogel * Device removal routine 71361ae650dSJack F Vogel * 71461ae650dSJack F Vogel * The detach entry point is called when the driver is being removed. 71561ae650dSJack F Vogel * This routine stops the adapter and deallocates all the resources 71661ae650dSJack F Vogel * that were allocated for driver operation. 71761ae650dSJack F Vogel * 71861ae650dSJack F Vogel * return 0 on success, positive on failure 71961ae650dSJack F Vogel *********************************************************************/ 72061ae650dSJack F Vogel 72161ae650dSJack F Vogel static int 72261ae650dSJack F Vogel ixl_detach(device_t dev) 72361ae650dSJack F Vogel { 72461ae650dSJack F Vogel struct ixl_pf *pf = device_get_softc(dev); 72561ae650dSJack F Vogel struct i40e_hw *hw = &pf->hw; 72661ae650dSJack F Vogel struct ixl_vsi *vsi = &pf->vsi; 7276c426059SEric Joyner enum i40e_status_code status; 728cb6b8299SEric Joyner #if defined(PCI_IOV) || defined(IXL_IW) 72956c2c47bSJack F Vogel int error; 73056c2c47bSJack F Vogel #endif 73161ae650dSJack F Vogel 73261ae650dSJack F Vogel INIT_DEBUGOUT("ixl_detach: begin"); 73361ae650dSJack F Vogel 73461ae650dSJack F Vogel /* Make sure VLANS are not using driver */ 73561ae650dSJack F Vogel if (vsi->ifp->if_vlantrunk != NULL) { 73661ae650dSJack F Vogel device_printf(dev, "Vlan in use, detach first\n"); 73761ae650dSJack F Vogel return (EBUSY); 73861ae650dSJack F Vogel } 73961ae650dSJack F Vogel 74056c2c47bSJack F Vogel #ifdef PCI_IOV 74156c2c47bSJack F Vogel error = pci_iov_detach(dev); 74256c2c47bSJack F Vogel if (error != 0) { 74356c2c47bSJack F Vogel device_printf(dev, "SR-IOV in use; detach first.\n"); 74456c2c47bSJack F Vogel return (error); 74556c2c47bSJack F Vogel } 74656c2c47bSJack F Vogel #endif 74756c2c47bSJack F Vogel 748*ceebc2f3SEric Joyner /* Remove all previously allocated media types */ 749*ceebc2f3SEric Joyner ifmedia_removeall(&vsi->media); 750*ceebc2f3SEric Joyner 751b6c8f260SJack F Vogel ether_ifdetach(vsi->ifp); 752223d846dSEric Joyner if (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING) 75361ae650dSJack F Vogel ixl_stop(pf); 75461ae650dSJack F Vogel 75561ae650dSJack F Vogel /* Shutdown LAN HMC */ 75661ae650dSJack F Vogel status = i40e_shutdown_lan_hmc(hw); 75761ae650dSJack F Vogel if (status) 75861ae650dSJack F Vogel device_printf(dev, 75961ae650dSJack F Vogel "Shutdown LAN HMC failed with code %d\n", status); 76061ae650dSJack F Vogel 761cb6b8299SEric Joyner /* Teardown LAN queue resources */ 762cb6b8299SEric Joyner ixl_teardown_queue_msix(vsi); 763cb6b8299SEric Joyner ixl_free_queue_tqs(vsi); 76461ae650dSJack F Vogel /* Shutdown admin queue */ 765cb6b8299SEric Joyner ixl_disable_intr0(hw); 7666c426059SEric Joyner ixl_teardown_adminq_msix(pf); 767cb6b8299SEric Joyner ixl_free_adminq_tq(pf); 76861ae650dSJack F Vogel status = i40e_shutdown_adminq(hw); 76961ae650dSJack F Vogel if (status) 77061ae650dSJack F Vogel device_printf(dev, 77161ae650dSJack F Vogel "Shutdown Admin queue failed with code %d\n", status); 77261ae650dSJack F Vogel 77361ae650dSJack F Vogel /* Unregister VLAN events */ 77461ae650dSJack F Vogel if (vsi->vlan_attach != NULL) 77561ae650dSJack F Vogel EVENTHANDLER_DEREGISTER(vlan_config, vsi->vlan_attach); 77661ae650dSJack F Vogel if (vsi->vlan_detach != NULL) 77761ae650dSJack F Vogel EVENTHANDLER_DEREGISTER(vlan_unconfig, vsi->vlan_detach); 77861ae650dSJack F Vogel 77961ae650dSJack F Vogel callout_drain(&pf->timer); 780cb6b8299SEric Joyner 781cb6b8299SEric Joyner #ifdef IXL_IW 782cb6b8299SEric Joyner if (ixl_enable_iwarp && pf->iw_enabled) { 783cb6b8299SEric Joyner error = ixl_iw_pf_detach(pf); 784cb6b8299SEric Joyner if (error == EBUSY) { 785cb6b8299SEric Joyner device_printf(dev, "iwarp in use; stop it first.\n"); 786cb6b8299SEric Joyner return (error); 787cb6b8299SEric Joyner } 788cb6b8299SEric Joyner } 789cb6b8299SEric Joyner #endif 790cb6b8299SEric Joyner 79131830672SJack F Vogel #ifdef DEV_NETMAP 79231830672SJack F Vogel netmap_detach(vsi->ifp); 79331830672SJack F Vogel #endif /* DEV_NETMAP */ 7944294f337SSean Bruno ixl_pf_qmgr_destroy(&pf->qmgr); 79561ae650dSJack F Vogel ixl_free_pci_resources(pf); 79661ae650dSJack F Vogel bus_generic_detach(dev); 79761ae650dSJack F Vogel if_free(vsi->ifp); 79861ae650dSJack F Vogel ixl_free_vsi(vsi); 79961ae650dSJack F Vogel IXL_PF_LOCK_DESTROY(pf); 80061ae650dSJack F Vogel return (0); 80161ae650dSJack F Vogel } 80261ae650dSJack F Vogel 80361ae650dSJack F Vogel /********************************************************************* 80461ae650dSJack F Vogel * 80561ae650dSJack F Vogel * Shutdown entry point 80661ae650dSJack F Vogel * 80761ae650dSJack F Vogel **********************************************************************/ 80861ae650dSJack F Vogel 80961ae650dSJack F Vogel static int 81061ae650dSJack F Vogel ixl_shutdown(device_t dev) 81161ae650dSJack F Vogel { 81261ae650dSJack F Vogel struct ixl_pf *pf = device_get_softc(dev); 81361ae650dSJack F Vogel ixl_stop(pf); 81461ae650dSJack F Vogel return (0); 81561ae650dSJack F Vogel } 81661ae650dSJack F Vogel 817