if_ixl.c revision 318357
1266423Sjfv/****************************************************************************** 2266423Sjfv 3279033Sjfv Copyright (c) 2013-2015, Intel Corporation 4266423Sjfv All rights reserved. 5266423Sjfv 6266423Sjfv Redistribution and use in source and binary forms, with or without 7266423Sjfv modification, are permitted provided that the following conditions are met: 8266423Sjfv 9266423Sjfv 1. Redistributions of source code must retain the above copyright notice, 10266423Sjfv this list of conditions and the following disclaimer. 11266423Sjfv 12266423Sjfv 2. Redistributions in binary form must reproduce the above copyright 13266423Sjfv notice, this list of conditions and the following disclaimer in the 14266423Sjfv documentation and/or other materials provided with the distribution. 15266423Sjfv 16266423Sjfv 3. Neither the name of the Intel Corporation nor the names of its 17266423Sjfv contributors may be used to endorse or promote products derived from 18266423Sjfv this software without specific prior written permission. 19266423Sjfv 20266423Sjfv THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21266423Sjfv AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22266423Sjfv IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23266423Sjfv ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24266423Sjfv LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25266423Sjfv CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26266423Sjfv SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27266423Sjfv INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28266423Sjfv CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29266423Sjfv ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30266423Sjfv POSSIBILITY OF SUCH DAMAGE. 31266423Sjfv 32266423Sjfv******************************************************************************/ 33266423Sjfv/*$FreeBSD: stable/11/sys/dev/ixl/if_ixl.c 318357 2017-05-16 17:49:15Z erj $*/ 34266423Sjfv 35270346Sjfv#include "ixl.h" 36270346Sjfv#include "ixl_pf.h" 37269198Sjfv 38318357Serj#ifdef IXL_IW 39318357Serj#include "ixl_iw.h" 40318357Serj#include "ixl_iw_int.h" 41318357Serj#endif 42318357Serj 43303967Ssbruno#ifdef PCI_IOV 44303967Ssbruno#include "ixl_pf_iov.h" 45277262Sjfv#endif 46277262Sjfv 47266423Sjfv/********************************************************************* 48266423Sjfv * Driver version 49266423Sjfv *********************************************************************/ 50318357Serjchar ixl_driver_version[] = "1.7.12-k"; 51266423Sjfv 52266423Sjfv/********************************************************************* 53266423Sjfv * PCI Device ID Table 54266423Sjfv * 55266423Sjfv * Used by probe to select devices to load on 56270346Sjfv * Last field stores an index into ixl_strings 57266423Sjfv * Last entry must be all 0s 58266423Sjfv * 59266423Sjfv * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } 60266423Sjfv *********************************************************************/ 61266423Sjfv 62270346Sjfvstatic ixl_vendor_info_t ixl_vendor_info_array[] = 63266423Sjfv{ 64266423Sjfv {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710, 0, 0, 0}, 65266423Sjfv {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B, 0, 0, 0}, 66266423Sjfv {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C, 0, 0, 0}, 67266423Sjfv {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A, 0, 0, 0}, 68266423Sjfv {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B, 0, 0, 0}, 69266423Sjfv {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_C, 0, 0, 0}, 70270346Sjfv {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T, 0, 0, 0}, 71284049Sjfv {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T4, 0, 0, 0}, 72303967Ssbruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_X722, 0, 0, 0}, 73303967Ssbruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_X722, 0, 0, 0}, 74303967Ssbruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_X722, 0, 0, 0}, 75303967Ssbruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_1G_BASE_T_X722, 0, 0, 0}, 76303967Ssbruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T_X722, 0, 0, 0}, 77303967Ssbruno {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_I_X722, 0, 0, 0}, 78318357Serj {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_B, 0, 0, 0}, 79318357Serj {I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_SFP28, 0, 0, 0}, 80266423Sjfv /* required last entry */ 81266423Sjfv {0, 0, 0, 0, 0} 82266423Sjfv}; 83266423Sjfv 84266423Sjfv/********************************************************************* 85266423Sjfv * Table of branding strings 86266423Sjfv *********************************************************************/ 87266423Sjfv 88270346Sjfvstatic char *ixl_strings[] = { 89303967Ssbruno "Intel(R) Ethernet Connection XL710/X722 Driver" 90266423Sjfv}; 91266423Sjfv 92266423Sjfv 93266423Sjfv/********************************************************************* 94266423Sjfv * Function prototypes 95266423Sjfv *********************************************************************/ 96270346Sjfvstatic int ixl_probe(device_t); 97270346Sjfvstatic int ixl_attach(device_t); 98270346Sjfvstatic int ixl_detach(device_t); 99270346Sjfvstatic int ixl_shutdown(device_t); 100299553Serj 101303967Ssbrunostatic int ixl_save_pf_tunables(struct ixl_pf *); 102303967Ssbrunostatic int ixl_attach_get_link_status(struct ixl_pf *); 103299553Serj 104266423Sjfv/********************************************************************* 105266423Sjfv * FreeBSD Device Interface Entry Points 106266423Sjfv *********************************************************************/ 107266423Sjfv 108270346Sjfvstatic device_method_t ixl_methods[] = { 109266423Sjfv /* Device interface */ 110270346Sjfv DEVMETHOD(device_probe, ixl_probe), 111270346Sjfv DEVMETHOD(device_attach, ixl_attach), 112270346Sjfv DEVMETHOD(device_detach, ixl_detach), 113270346Sjfv DEVMETHOD(device_shutdown, ixl_shutdown), 114279858Sjfv#ifdef PCI_IOV 115299546Serj DEVMETHOD(pci_iov_init, ixl_iov_init), 116299546Serj DEVMETHOD(pci_iov_uninit, ixl_iov_uninit), 117299546Serj DEVMETHOD(pci_iov_add_vf, ixl_add_vf), 118279858Sjfv#endif 119266423Sjfv {0, 0} 120266423Sjfv}; 121266423Sjfv 122270346Sjfvstatic driver_t ixl_driver = { 123270346Sjfv "ixl", ixl_methods, sizeof(struct ixl_pf), 124266423Sjfv}; 125266423Sjfv 126270346Sjfvdevclass_t ixl_devclass; 127270346SjfvDRIVER_MODULE(ixl, pci, ixl_driver, ixl_devclass, 0, 0); 128266423Sjfv 129318357SerjMODULE_VERSION(ixl, 1); 130318357Serj 131270346SjfvMODULE_DEPEND(ixl, pci, 1, 1, 1); 132270346SjfvMODULE_DEPEND(ixl, ether, 1, 1, 1); 133318357Serj#if defined(DEV_NETMAP) && __FreeBSD_version >= 1100000 134279860SjfvMODULE_DEPEND(ixl, netmap, 1, 1, 1); 135279860Sjfv#endif /* DEV_NETMAP */ 136279860Sjfv 137266423Sjfv/* 138270346Sjfv** TUNEABLE PARAMETERS: 139270346Sjfv*/ 140270346Sjfv 141270346Sjfvstatic SYSCTL_NODE(_hw, OID_AUTO, ixl, CTLFLAG_RD, 0, 142270346Sjfv "IXL driver parameters"); 143270346Sjfv 144270346Sjfv/* 145266423Sjfv * MSIX should be the default for best performance, 146266423Sjfv * but this allows it to be forced off for testing. 147266423Sjfv */ 148270346Sjfvstatic int ixl_enable_msix = 1; 149270346SjfvTUNABLE_INT("hw.ixl.enable_msix", &ixl_enable_msix); 150270346SjfvSYSCTL_INT(_hw_ixl, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixl_enable_msix, 0, 151270346Sjfv "Enable MSI-X interrupts"); 152266423Sjfv 153266423Sjfv/* 154266423Sjfv** Number of descriptors per ring: 155266423Sjfv** - TX and RX are the same size 156266423Sjfv*/ 157318357Serjstatic int ixl_ring_size = IXL_DEFAULT_RING; 158303967SsbrunoTUNABLE_INT("hw.ixl.ring_size", &ixl_ring_size); 159270346SjfvSYSCTL_INT(_hw_ixl, OID_AUTO, ring_size, CTLFLAG_RDTUN, 160303967Ssbruno &ixl_ring_size, 0, "Descriptor Ring Size"); 161266423Sjfv 162266423Sjfv/* 163266423Sjfv** This can be set manually, if left as 0 the 164266423Sjfv** number of queues will be calculated based 165266423Sjfv** on cpus and msix vectors available. 166266423Sjfv*/ 167303967Ssbrunostatic int ixl_max_queues = 0; 168270346SjfvTUNABLE_INT("hw.ixl.max_queues", &ixl_max_queues); 169270346SjfvSYSCTL_INT(_hw_ixl, OID_AUTO, max_queues, CTLFLAG_RDTUN, 170270346Sjfv &ixl_max_queues, 0, "Number of Queues"); 171266423Sjfv 172303967Ssbrunostatic int ixl_enable_tx_fc_filter = 1; 173303967SsbrunoTUNABLE_INT("hw.ixl.enable_tx_fc_filter", 174303967Ssbruno &ixl_enable_tx_fc_filter); 175303967SsbrunoSYSCTL_INT(_hw_ixl, OID_AUTO, enable_tx_fc_filter, CTLFLAG_RDTUN, 176303967Ssbruno &ixl_enable_tx_fc_filter, 0, 177303967Ssbruno "Filter out packets with Ethertype 0x8808 from being sent out by non-HW sources"); 178303967Ssbruno 179303967Ssbrunostatic int ixl_core_debug_mask = 0; 180303967SsbrunoTUNABLE_INT("hw.ixl.core_debug_mask", 181303967Ssbruno &ixl_core_debug_mask); 182303967SsbrunoSYSCTL_INT(_hw_ixl, OID_AUTO, core_debug_mask, CTLFLAG_RDTUN, 183303967Ssbruno &ixl_core_debug_mask, 0, 184303967Ssbruno "Display debug statements that are printed in non-shared code"); 185303967Ssbruno 186303967Ssbrunostatic int ixl_shared_debug_mask = 0; 187303967SsbrunoTUNABLE_INT("hw.ixl.shared_debug_mask", 188303967Ssbruno &ixl_shared_debug_mask); 189303967SsbrunoSYSCTL_INT(_hw_ixl, OID_AUTO, shared_debug_mask, CTLFLAG_RDTUN, 190303967Ssbruno &ixl_shared_debug_mask, 0, 191303967Ssbruno "Display debug statements that are printed in shared code"); 192303967Ssbruno 193266423Sjfv/* 194266423Sjfv** Controls for Interrupt Throttling 195266423Sjfv** - true/false for dynamic adjustment 196266423Sjfv** - default values for static ITR 197266423Sjfv*/ 198303967Ssbrunostatic int ixl_dynamic_rx_itr = 1; 199270346SjfvTUNABLE_INT("hw.ixl.dynamic_rx_itr", &ixl_dynamic_rx_itr); 200270346SjfvSYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_rx_itr, CTLFLAG_RDTUN, 201270346Sjfv &ixl_dynamic_rx_itr, 0, "Dynamic RX Interrupt Rate"); 202266423Sjfv 203303967Ssbrunostatic int ixl_dynamic_tx_itr = 1; 204270346SjfvTUNABLE_INT("hw.ixl.dynamic_tx_itr", &ixl_dynamic_tx_itr); 205270346SjfvSYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_tx_itr, CTLFLAG_RDTUN, 206270346Sjfv &ixl_dynamic_tx_itr, 0, "Dynamic TX Interrupt Rate"); 207266423Sjfv 208303967Ssbrunostatic int ixl_rx_itr = IXL_ITR_8K; 209270346SjfvTUNABLE_INT("hw.ixl.rx_itr", &ixl_rx_itr); 210270346SjfvSYSCTL_INT(_hw_ixl, OID_AUTO, rx_itr, CTLFLAG_RDTUN, 211270346Sjfv &ixl_rx_itr, 0, "RX Interrupt Rate"); 212270346Sjfv 213303967Ssbrunostatic int ixl_tx_itr = IXL_ITR_4K; 214270346SjfvTUNABLE_INT("hw.ixl.tx_itr", &ixl_tx_itr); 215270346SjfvSYSCTL_INT(_hw_ixl, OID_AUTO, tx_itr, CTLFLAG_RDTUN, 216270346Sjfv &ixl_tx_itr, 0, "TX Interrupt Rate"); 217270346Sjfv 218318357Serj#ifdef IXL_IW 219318357Serjint ixl_enable_iwarp = 0; 220318357SerjTUNABLE_INT("hw.ixl.enable_iwarp", &ixl_enable_iwarp); 221318357Serj#endif 222318357Serj 223279860Sjfv#ifdef DEV_NETMAP 224279860Sjfv#define NETMAP_IXL_MAIN /* only bring in one part of the netmap code */ 225279860Sjfv#include <dev/netmap/if_ixl_netmap.h> 226279860Sjfv#endif /* DEV_NETMAP */ 227274205Sjfv 228266423Sjfv/********************************************************************* 229266423Sjfv * Device identification routine 230266423Sjfv * 231270346Sjfv * ixl_probe determines if the driver should be loaded on 232266423Sjfv * the hardware based on PCI vendor/device id of the device. 233266423Sjfv * 234266423Sjfv * return BUS_PROBE_DEFAULT on success, positive on failure 235266423Sjfv *********************************************************************/ 236266423Sjfv 237266423Sjfvstatic int 238270346Sjfvixl_probe(device_t dev) 239266423Sjfv{ 240270346Sjfv ixl_vendor_info_t *ent; 241266423Sjfv 242266423Sjfv u16 pci_vendor_id, pci_device_id; 243266423Sjfv u16 pci_subvendor_id, pci_subdevice_id; 244266423Sjfv char device_name[256]; 245266423Sjfv 246299552Serj#if 0 247270346Sjfv INIT_DEBUGOUT("ixl_probe: begin"); 248299552Serj#endif 249266423Sjfv pci_vendor_id = pci_get_vendor(dev); 250266423Sjfv if (pci_vendor_id != I40E_INTEL_VENDOR_ID) 251266423Sjfv return (ENXIO); 252266423Sjfv 253266423Sjfv pci_device_id = pci_get_device(dev); 254266423Sjfv pci_subvendor_id = pci_get_subvendor(dev); 255266423Sjfv pci_subdevice_id = pci_get_subdevice(dev); 256266423Sjfv 257270346Sjfv ent = ixl_vendor_info_array; 258266423Sjfv while (ent->vendor_id != 0) { 259266423Sjfv if ((pci_vendor_id == ent->vendor_id) && 260266423Sjfv (pci_device_id == ent->device_id) && 261266423Sjfv 262266423Sjfv ((pci_subvendor_id == ent->subvendor_id) || 263266423Sjfv (ent->subvendor_id == 0)) && 264266423Sjfv 265266423Sjfv ((pci_subdevice_id == ent->subdevice_id) || 266266423Sjfv (ent->subdevice_id == 0))) { 267266423Sjfv sprintf(device_name, "%s, Version - %s", 268270346Sjfv ixl_strings[ent->index], 269270346Sjfv ixl_driver_version); 270266423Sjfv device_set_desc_copy(dev, device_name); 271266423Sjfv return (BUS_PROBE_DEFAULT); 272266423Sjfv } 273266423Sjfv ent++; 274266423Sjfv } 275266423Sjfv return (ENXIO); 276266423Sjfv} 277266423Sjfv 278303967Ssbrunostatic int 279303967Ssbrunoixl_attach_get_link_status(struct ixl_pf *pf) 280303967Ssbruno{ 281303967Ssbruno struct i40e_hw *hw = &pf->hw; 282303967Ssbruno device_t dev = pf->dev; 283303967Ssbruno int error = 0; 284303967Ssbruno 285303967Ssbruno if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || 286303967Ssbruno (hw->aq.fw_maj_ver < 4)) { 287303967Ssbruno i40e_msec_delay(75); 288303967Ssbruno error = i40e_aq_set_link_restart_an(hw, TRUE, NULL); 289303967Ssbruno if (error) { 290303967Ssbruno device_printf(dev, "link restart failed, aq_err=%d\n", 291303967Ssbruno pf->hw.aq.asq_last_status); 292303967Ssbruno return error; 293303967Ssbruno } 294303967Ssbruno } 295303967Ssbruno 296303967Ssbruno /* Determine link state */ 297303967Ssbruno hw->phy.get_link_info = TRUE; 298303967Ssbruno i40e_get_link_status(hw, &pf->link_up); 299303967Ssbruno return (0); 300303967Ssbruno} 301303967Ssbruno 302303967Ssbruno/* 303303967Ssbruno * Sanity check and save off tunable values. 304303967Ssbruno */ 305303967Ssbrunostatic int 306303967Ssbrunoixl_save_pf_tunables(struct ixl_pf *pf) 307303967Ssbruno{ 308303967Ssbruno device_t dev = pf->dev; 309303967Ssbruno 310303967Ssbruno /* Save tunable information */ 311303967Ssbruno pf->enable_msix = ixl_enable_msix; 312303967Ssbruno pf->max_queues = ixl_max_queues; 313303967Ssbruno pf->enable_tx_fc_filter = ixl_enable_tx_fc_filter; 314303967Ssbruno pf->dynamic_rx_itr = ixl_dynamic_rx_itr; 315303967Ssbruno pf->dynamic_tx_itr = ixl_dynamic_tx_itr; 316303967Ssbruno pf->dbg_mask = ixl_core_debug_mask; 317303967Ssbruno pf->hw.debug_mask = ixl_shared_debug_mask; 318303967Ssbruno 319303967Ssbruno if (ixl_ring_size < IXL_MIN_RING 320303967Ssbruno || ixl_ring_size > IXL_MAX_RING 321303967Ssbruno || ixl_ring_size % IXL_RING_INCREMENT != 0) { 322303967Ssbruno device_printf(dev, "Invalid ring_size value of %d set!\n", 323303967Ssbruno ixl_ring_size); 324303967Ssbruno device_printf(dev, "ring_size must be between %d and %d, " 325303967Ssbruno "inclusive, and must be a multiple of %d\n", 326303967Ssbruno IXL_MIN_RING, IXL_MAX_RING, IXL_RING_INCREMENT); 327318357Serj device_printf(dev, "Using default value of %d instead\n", 328318357Serj IXL_DEFAULT_RING); 329318357Serj pf->ringsz = IXL_DEFAULT_RING; 330318357Serj } else 331318357Serj pf->ringsz = ixl_ring_size; 332303967Ssbruno 333318357Serj if (ixl_tx_itr < 0 || ixl_tx_itr > IXL_MAX_ITR) { 334318357Serj device_printf(dev, "Invalid tx_itr value of %d set!\n", 335318357Serj ixl_tx_itr); 336318357Serj device_printf(dev, "tx_itr must be between %d and %d, " 337318357Serj "inclusive\n", 338318357Serj 0, IXL_MAX_ITR); 339318357Serj device_printf(dev, "Using default value of %d instead\n", 340318357Serj IXL_ITR_4K); 341318357Serj pf->tx_itr = IXL_ITR_4K; 342318357Serj } else 343318357Serj pf->tx_itr = ixl_tx_itr; 344318357Serj 345318357Serj if (ixl_rx_itr < 0 || ixl_rx_itr > IXL_MAX_ITR) { 346318357Serj device_printf(dev, "Invalid rx_itr value of %d set!\n", 347318357Serj ixl_rx_itr); 348318357Serj device_printf(dev, "rx_itr must be between %d and %d, " 349318357Serj "inclusive\n", 350318357Serj 0, IXL_MAX_ITR); 351318357Serj device_printf(dev, "Using default value of %d instead\n", 352318357Serj IXL_ITR_8K); 353318357Serj pf->rx_itr = IXL_ITR_8K; 354318357Serj } else 355318357Serj pf->rx_itr = ixl_rx_itr; 356318357Serj 357303967Ssbruno return (0); 358303967Ssbruno} 359303967Ssbruno 360266423Sjfv/********************************************************************* 361266423Sjfv * Device initialization routine 362266423Sjfv * 363266423Sjfv * The attach entry point is called when the driver is being loaded. 364266423Sjfv * This routine identifies the type of hardware, allocates all resources 365266423Sjfv * and initializes the hardware. 366266423Sjfv * 367266423Sjfv * return 0 on success, positive on failure 368266423Sjfv *********************************************************************/ 369266423Sjfv 370266423Sjfvstatic int 371270346Sjfvixl_attach(device_t dev) 372266423Sjfv{ 373270346Sjfv struct ixl_pf *pf; 374266423Sjfv struct i40e_hw *hw; 375299552Serj struct ixl_vsi *vsi; 376303967Ssbruno enum i40e_status_code status; 377266423Sjfv int error = 0; 378266423Sjfv 379270346Sjfv INIT_DEBUGOUT("ixl_attach: begin"); 380266423Sjfv 381266423Sjfv /* Allocate, clear, and link in our primary soft structure */ 382266423Sjfv pf = device_get_softc(dev); 383266423Sjfv pf->dev = pf->osdep.dev = dev; 384266423Sjfv hw = &pf->hw; 385266423Sjfv 386266423Sjfv /* 387266423Sjfv ** Note this assumes we have a single embedded VSI, 388266423Sjfv ** this could be enhanced later to allocate multiple 389266423Sjfv */ 390266423Sjfv vsi = &pf->vsi; 391266423Sjfv vsi->dev = pf->dev; 392266423Sjfv 393303967Ssbruno /* Save tunable values */ 394303967Ssbruno error = ixl_save_pf_tunables(pf); 395303967Ssbruno if (error) 396303967Ssbruno return (error); 397303967Ssbruno 398266423Sjfv /* Core Lock Init*/ 399270346Sjfv IXL_PF_LOCK_INIT(pf, device_get_nameunit(dev)); 400266423Sjfv 401266423Sjfv /* Set up the timer callout */ 402266423Sjfv callout_init_mtx(&pf->timer, &pf->pf_mtx, 0); 403266423Sjfv 404266423Sjfv /* Do PCI setup - map BAR0, etc */ 405270346Sjfv if (ixl_allocate_pci_resources(pf)) { 406266423Sjfv device_printf(dev, "Allocation of PCI resources failed\n"); 407266423Sjfv error = ENXIO; 408266423Sjfv goto err_out; 409266423Sjfv } 410266423Sjfv 411266423Sjfv /* Establish a clean starting point */ 412269198Sjfv i40e_clear_hw(hw); 413303967Ssbruno status = i40e_pf_reset(hw); 414303967Ssbruno if (status) { 415303967Ssbruno device_printf(dev, "PF reset failure %s\n", 416303967Ssbruno i40e_stat_str(hw, status)); 417269198Sjfv error = EIO; 418269198Sjfv goto err_out; 419269198Sjfv } 420266423Sjfv 421266423Sjfv /* Initialize the shared code */ 422303967Ssbruno status = i40e_init_shared_code(hw); 423303967Ssbruno if (status) { 424303967Ssbruno device_printf(dev, "Unable to initialize shared code, error %s\n", 425303967Ssbruno i40e_stat_str(hw, status)); 426266423Sjfv error = EIO; 427266423Sjfv goto err_out; 428266423Sjfv } 429266423Sjfv 430303967Ssbruno /* 431303967Ssbruno * Allocate interrupts and figure out number of queues to use 432303967Ssbruno * for PF interface 433303967Ssbruno */ 434303967Ssbruno pf->msix = ixl_init_msix(pf); 435303967Ssbruno 436266423Sjfv /* Set up the admin queue */ 437303967Ssbruno hw->aq.num_arq_entries = IXL_AQ_LEN; 438303967Ssbruno hw->aq.num_asq_entries = IXL_AQ_LEN; 439303967Ssbruno hw->aq.arq_buf_size = IXL_AQ_BUF_SZ; 440303967Ssbruno hw->aq.asq_buf_size = IXL_AQ_BUF_SZ; 441303967Ssbruno 442303967Ssbruno status = i40e_init_adminq(hw); 443303967Ssbruno if (status != 0 && status != I40E_ERR_FIRMWARE_API_VERSION) { 444303967Ssbruno device_printf(dev, "Unable to initialize Admin Queue, error %s\n", 445303967Ssbruno i40e_stat_str(hw, status)); 446299549Serj error = EIO; 447299549Serj goto err_out; 448299549Serj } 449299552Serj ixl_print_nvm_version(pf); 450299552Serj 451303967Ssbruno if (status == I40E_ERR_FIRMWARE_API_VERSION) { 452269198Sjfv device_printf(dev, "The driver for the device stopped " 453269198Sjfv "because the NVM image is newer than expected.\n" 454269198Sjfv "You must install the most recent version of " 455299549Serj "the network driver.\n"); 456299549Serj error = EIO; 457266423Sjfv goto err_out; 458266423Sjfv } 459266423Sjfv 460269198Sjfv if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR && 461269198Sjfv hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR) 462269198Sjfv device_printf(dev, "The driver for the device detected " 463269198Sjfv "a newer version of the NVM image than expected.\n" 464269198Sjfv "Please install the most recent version of the network driver.\n"); 465269198Sjfv else if (hw->aq.api_maj_ver < I40E_FW_API_VERSION_MAJOR || 466269198Sjfv hw->aq.api_min_ver < (I40E_FW_API_VERSION_MINOR - 1)) 467269198Sjfv device_printf(dev, "The driver for the device detected " 468269198Sjfv "an older version of the NVM image than expected.\n" 469269198Sjfv "Please update the NVM image.\n"); 470266423Sjfv 471266423Sjfv /* Clear PXE mode */ 472266423Sjfv i40e_clear_pxe_mode(hw); 473266423Sjfv 474266423Sjfv /* Get capabilities from the device */ 475270346Sjfv error = ixl_get_hw_capabilities(pf); 476266423Sjfv if (error) { 477266423Sjfv device_printf(dev, "HW capabilities failure!\n"); 478266423Sjfv goto err_get_cap; 479266423Sjfv } 480266423Sjfv 481266423Sjfv /* Set up host memory cache */ 482303967Ssbruno status = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp, 483279858Sjfv hw->func_caps.num_rx_qp, 0, 0); 484303967Ssbruno if (status) { 485303967Ssbruno device_printf(dev, "init_lan_hmc failed: %s\n", 486303967Ssbruno i40e_stat_str(hw, status)); 487266423Sjfv goto err_get_cap; 488266423Sjfv } 489266423Sjfv 490303967Ssbruno status = i40e_configure_lan_hmc(hw, I40E_HMC_MODEL_DIRECT_ONLY); 491303967Ssbruno if (status) { 492303967Ssbruno device_printf(dev, "configure_lan_hmc failed: %s\n", 493303967Ssbruno i40e_stat_str(hw, status)); 494303967Ssbruno goto err_mac_hmc; 495303967Ssbruno } 496303967Ssbruno 497303967Ssbruno /* Init queue allocation manager */ 498303967Ssbruno error = ixl_pf_qmgr_init(&pf->qmgr, hw->func_caps.num_tx_qp); 499266423Sjfv if (error) { 500303967Ssbruno device_printf(dev, "Failed to init queue manager for PF queues, error %d\n", 501303967Ssbruno error); 502266423Sjfv goto err_mac_hmc; 503266423Sjfv } 504303967Ssbruno /* reserve a contiguous allocation for the PF's VSI */ 505303967Ssbruno error = ixl_pf_qmgr_alloc_contiguous(&pf->qmgr, vsi->num_queues, &pf->qtag); 506303967Ssbruno if (error) { 507303967Ssbruno device_printf(dev, "Failed to reserve queues for PF LAN VSI, error %d\n", 508303967Ssbruno error); 509303967Ssbruno goto err_mac_hmc; 510303967Ssbruno } 511303967Ssbruno device_printf(dev, "Allocating %d queues for PF LAN VSI; %d queues active\n", 512303967Ssbruno pf->qtag.num_allocated, pf->qtag.num_active); 513266423Sjfv 514299555Serj /* Disable LLDP from the firmware for certain NVM versions */ 515299555Serj if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 3)) || 516299555Serj (pf->hw.aq.fw_maj_ver < 4)) 517299555Serj i40e_aq_stop_lldp(hw, TRUE, NULL); 518269198Sjfv 519303967Ssbruno /* Get MAC addresses from hardware */ 520266423Sjfv i40e_get_mac_addr(hw, hw->mac.addr); 521266423Sjfv error = i40e_validate_mac_addr(hw->mac.addr); 522266423Sjfv if (error) { 523266423Sjfv device_printf(dev, "validate_mac_addr failed: %d\n", error); 524266423Sjfv goto err_mac_hmc; 525266423Sjfv } 526266423Sjfv bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN); 527266423Sjfv i40e_get_port_mac_addr(hw, hw->mac.port_addr); 528266423Sjfv 529303967Ssbruno /* Initialize mac filter list for VSI */ 530303967Ssbruno SLIST_INIT(&vsi->ftl); 531303967Ssbruno 532303967Ssbruno /* Set up SW VSI and allocate queue memory and rings */ 533303967Ssbruno if (ixl_setup_stations(pf)) { 534266423Sjfv device_printf(dev, "setup stations failed!\n"); 535266423Sjfv error = ENOMEM; 536266423Sjfv goto err_mac_hmc; 537266423Sjfv } 538266423Sjfv 539299547Serj /* Setup OS network interface / ifnet */ 540303967Ssbruno if (ixl_setup_interface(dev, vsi)) { 541274205Sjfv device_printf(dev, "interface setup failed!\n"); 542274205Sjfv error = EIO; 543266423Sjfv goto err_late; 544274205Sjfv } 545266423Sjfv 546303967Ssbruno /* Determine link state */ 547303967Ssbruno if (ixl_attach_get_link_status(pf)) { 548303967Ssbruno error = EINVAL; 549303967Ssbruno goto err_late; 550303967Ssbruno } 551303967Ssbruno 552279033Sjfv error = ixl_switch_config(pf); 553279033Sjfv if (error) { 554299553Serj device_printf(dev, "Initial ixl_switch_config() failed: %d\n", 555299553Serj error); 556299546Serj goto err_late; 557279033Sjfv } 558279033Sjfv 559299547Serj /* Limit PHY interrupts to link, autoneg, and modules failure */ 560303967Ssbruno status = i40e_aq_set_phy_int_mask(hw, IXL_DEFAULT_PHY_INT_MASK, 561299547Serj NULL); 562303967Ssbruno if (status) { 563303967Ssbruno device_printf(dev, "i40e_aq_set_phy_mask() failed: err %s," 564303967Ssbruno " aq_err %s\n", i40e_stat_str(hw, status), 565303967Ssbruno i40e_aq_str(hw, hw->aq.asq_last_status)); 566299547Serj goto err_late; 567299547Serj } 568279033Sjfv 569299553Serj /* Get the bus configuration and set the shared code's config */ 570318357Serj ixl_get_bus_info(pf); 571266423Sjfv 572299553Serj /* 573299553Serj * In MSI-X mode, initialize the Admin Queue interrupt, 574299553Serj * so userland tools can communicate with the adapter regardless of 575299553Serj * the ifnet interface's status. 576299553Serj */ 577299553Serj if (pf->msix > 1) { 578299553Serj error = ixl_setup_adminq_msix(pf); 579299553Serj if (error) { 580318357Serj device_printf(dev, "ixl_setup_adminq_msix() error: %d\n", 581299553Serj error); 582299553Serj goto err_late; 583299553Serj } 584299553Serj error = ixl_setup_adminq_tq(pf); 585299553Serj if (error) { 586318357Serj device_printf(dev, "ixl_setup_adminq_tq() error: %d\n", 587299553Serj error); 588299553Serj goto err_late; 589299553Serj } 590299553Serj ixl_configure_intr0_msix(pf); 591318357Serj ixl_enable_intr0(hw); 592318357Serj 593318357Serj error = ixl_setup_queue_msix(vsi); 594318357Serj if (error) 595318357Serj device_printf(dev, "ixl_setup_queue_msix() error: %d\n", 596318357Serj error); 597318357Serj error = ixl_setup_queue_tqs(vsi); 598318357Serj if (error) 599318357Serj device_printf(dev, "ixl_setup_queue_tqs() error: %d\n", 600318357Serj error); 601318357Serj } else { 602318357Serj error = ixl_setup_legacy(pf); 603318357Serj 604318357Serj error = ixl_setup_adminq_tq(pf); 605318357Serj if (error) { 606318357Serj device_printf(dev, "ixl_setup_adminq_tq() error: %d\n", 607318357Serj error); 608318357Serj goto err_late; 609318357Serj } 610318357Serj 611318357Serj error = ixl_setup_queue_tqs(vsi); 612318357Serj if (error) 613318357Serj device_printf(dev, "ixl_setup_queue_tqs() error: %d\n", 614318357Serj error); 615299553Serj } 616299546Serj 617318357Serj if (error) { 618318357Serj device_printf(dev, "interrupt setup error: %d\n", error); 619318357Serj } 620318357Serj 621318357Serj /* Set initial advertised speed sysctl value */ 622318357Serj ixl_get_initial_advertised_speeds(pf); 623318357Serj 624299549Serj /* Initialize statistics & add sysctls */ 625299549Serj ixl_add_device_sysctls(pf); 626299549Serj 627270346Sjfv ixl_pf_reset_stats(pf); 628270346Sjfv ixl_update_stats_counters(pf); 629270346Sjfv ixl_add_hw_stats(pf); 630266423Sjfv 631266423Sjfv /* Register for VLAN events */ 632266423Sjfv vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, 633270346Sjfv ixl_register_vlan, vsi, EVENTHANDLER_PRI_FIRST); 634266423Sjfv vsi->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, 635270346Sjfv ixl_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST); 636266423Sjfv 637279858Sjfv#ifdef PCI_IOV 638303967Ssbruno ixl_initialize_sriov(pf); 639279858Sjfv#endif 640279858Sjfv 641279860Sjfv#ifdef DEV_NETMAP 642279860Sjfv ixl_netmap_attach(vsi); 643279860Sjfv#endif /* DEV_NETMAP */ 644318357Serj 645318357Serj#ifdef IXL_IW 646318357Serj if (hw->func_caps.iwarp && ixl_enable_iwarp) { 647318357Serj pf->iw_enabled = (pf->iw_msix > 0) ? true : false; 648318357Serj if (pf->iw_enabled) { 649318357Serj error = ixl_iw_pf_attach(pf); 650318357Serj if (error) { 651318357Serj device_printf(dev, 652318357Serj "interfacing to iwarp driver failed: %d\n", 653318357Serj error); 654318357Serj goto err_late; 655318357Serj } 656318357Serj } else 657318357Serj device_printf(dev, 658318357Serj "iwarp disabled on this device (no msix vectors)\n"); 659318357Serj } else { 660318357Serj pf->iw_enabled = false; 661318357Serj device_printf(dev, "The device is not iWARP enabled\n"); 662318357Serj } 663318357Serj#endif 664318357Serj 665270346Sjfv INIT_DEBUGOUT("ixl_attach: end"); 666266423Sjfv return (0); 667266423Sjfv 668266423Sjfverr_late: 669303967Ssbruno if (vsi->ifp != NULL) { 670303967Ssbruno ether_ifdetach(vsi->ifp); 671274205Sjfv if_free(vsi->ifp); 672303967Ssbruno } 673266423Sjfverr_mac_hmc: 674266423Sjfv i40e_shutdown_lan_hmc(hw); 675266423Sjfverr_get_cap: 676266423Sjfv i40e_shutdown_adminq(hw); 677266423Sjfverr_out: 678270346Sjfv ixl_free_pci_resources(pf); 679274205Sjfv ixl_free_vsi(vsi); 680270346Sjfv IXL_PF_LOCK_DESTROY(pf); 681266423Sjfv return (error); 682266423Sjfv} 683266423Sjfv 684266423Sjfv/********************************************************************* 685266423Sjfv * Device removal routine 686266423Sjfv * 687266423Sjfv * The detach entry point is called when the driver is being removed. 688266423Sjfv * This routine stops the adapter and deallocates all the resources 689266423Sjfv * that were allocated for driver operation. 690266423Sjfv * 691266423Sjfv * return 0 on success, positive on failure 692266423Sjfv *********************************************************************/ 693266423Sjfv 694266423Sjfvstatic int 695270346Sjfvixl_detach(device_t dev) 696266423Sjfv{ 697270346Sjfv struct ixl_pf *pf = device_get_softc(dev); 698266423Sjfv struct i40e_hw *hw = &pf->hw; 699270346Sjfv struct ixl_vsi *vsi = &pf->vsi; 700299553Serj enum i40e_status_code status; 701318357Serj#if defined(PCI_IOV) || defined(IXL_IW) 702279858Sjfv int error; 703279858Sjfv#endif 704266423Sjfv 705270346Sjfv INIT_DEBUGOUT("ixl_detach: begin"); 706266423Sjfv 707266423Sjfv /* Make sure VLANS are not using driver */ 708266423Sjfv if (vsi->ifp->if_vlantrunk != NULL) { 709299553Serj device_printf(dev, "Vlan in use, detach first\n"); 710266423Sjfv return (EBUSY); 711266423Sjfv } 712266423Sjfv 713279858Sjfv#ifdef PCI_IOV 714279858Sjfv error = pci_iov_detach(dev); 715279858Sjfv if (error != 0) { 716279858Sjfv device_printf(dev, "SR-IOV in use; detach first.\n"); 717279858Sjfv return (error); 718279858Sjfv } 719279858Sjfv#endif 720279858Sjfv 721279033Sjfv ether_ifdetach(vsi->ifp); 722299547Serj if (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING) 723279033Sjfv ixl_stop(pf); 724266423Sjfv 725266423Sjfv /* Shutdown LAN HMC */ 726266423Sjfv status = i40e_shutdown_lan_hmc(hw); 727266423Sjfv if (status) 728266423Sjfv device_printf(dev, 729266423Sjfv "Shutdown LAN HMC failed with code %d\n", status); 730266423Sjfv 731318357Serj /* Teardown LAN queue resources */ 732318357Serj ixl_teardown_queue_msix(vsi); 733318357Serj ixl_free_queue_tqs(vsi); 734266423Sjfv /* Shutdown admin queue */ 735318357Serj ixl_disable_intr0(hw); 736318357Serj ixl_teardown_adminq_msix(pf); 737299553Serj ixl_free_adminq_tq(pf); 738266423Sjfv status = i40e_shutdown_adminq(hw); 739266423Sjfv if (status) 740266423Sjfv device_printf(dev, 741266423Sjfv "Shutdown Admin queue failed with code %d\n", status); 742266423Sjfv 743266423Sjfv /* Unregister VLAN events */ 744266423Sjfv if (vsi->vlan_attach != NULL) 745266423Sjfv EVENTHANDLER_DEREGISTER(vlan_config, vsi->vlan_attach); 746266423Sjfv if (vsi->vlan_detach != NULL) 747266423Sjfv EVENTHANDLER_DEREGISTER(vlan_unconfig, vsi->vlan_detach); 748266423Sjfv 749266423Sjfv callout_drain(&pf->timer); 750318357Serj 751318357Serj#ifdef IXL_IW 752318357Serj if (ixl_enable_iwarp && pf->iw_enabled) { 753318357Serj error = ixl_iw_pf_detach(pf); 754318357Serj if (error == EBUSY) { 755318357Serj device_printf(dev, "iwarp in use; stop it first.\n"); 756318357Serj return (error); 757318357Serj } 758318357Serj } 759318357Serj#endif 760318357Serj 761279860Sjfv#ifdef DEV_NETMAP 762279860Sjfv netmap_detach(vsi->ifp); 763279860Sjfv#endif /* DEV_NETMAP */ 764303967Ssbruno ixl_pf_qmgr_destroy(&pf->qmgr); 765270346Sjfv ixl_free_pci_resources(pf); 766266423Sjfv bus_generic_detach(dev); 767266423Sjfv if_free(vsi->ifp); 768270346Sjfv ixl_free_vsi(vsi); 769270346Sjfv IXL_PF_LOCK_DESTROY(pf); 770266423Sjfv return (0); 771266423Sjfv} 772266423Sjfv 773266423Sjfv/********************************************************************* 774266423Sjfv * 775266423Sjfv * Shutdown entry point 776266423Sjfv * 777266423Sjfv **********************************************************************/ 778266423Sjfv 779266423Sjfvstatic int 780270346Sjfvixl_shutdown(device_t dev) 781266423Sjfv{ 782270346Sjfv struct ixl_pf *pf = device_get_softc(dev); 783270346Sjfv ixl_stop(pf); 784266423Sjfv return (0); 785266423Sjfv} 786266423Sjfv 787