Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixl/if_ixl.c
/****************************************************************************** | /****************************************************************************** | ||||
Copyright (c) 2013-2015, Intel Corporation | Copyright (c) 2013-2017, Intel Corporation | ||||
All rights reserved. | All rights reserved. | ||||
Redistribution and use in source and binary forms, with or without | Redistribution and use in source and binary forms, with or without | ||||
modification, are permitted provided that the following conditions are met: | modification, are permitted provided that the following conditions are met: | ||||
1. Redistributions of source code must retain the above copyright notice, | 1. Redistributions of source code must retain the above copyright notice, | ||||
this list of conditions and the following disclaimer. | this list of conditions and the following disclaimer. | ||||
Show All 30 Lines | |||||
#ifdef PCI_IOV | #ifdef PCI_IOV | ||||
#include "ixl_pf_iov.h" | #include "ixl_pf_iov.h" | ||||
#endif | #endif | ||||
/********************************************************************* | /********************************************************************* | ||||
* Driver version | * Driver version | ||||
*********************************************************************/ | *********************************************************************/ | ||||
char ixl_driver_version[] = "1.7.12-k"; | #define IXL_DRIVER_VERSION_MAJOR 1 | ||||
#define IXL_DRIVER_VERSION_MINOR 9 | |||||
#define IXL_DRIVER_VERSION_BUILD 9 | |||||
char ixl_driver_version[] = __XSTRING(IXL_DRIVER_VERSION_MAJOR) "." | |||||
__XSTRING(IXL_DRIVER_VERSION_MINOR) "." | |||||
__XSTRING(IXL_DRIVER_VERSION_BUILD) "-k"; | |||||
/********************************************************************* | /********************************************************************* | ||||
* PCI Device ID Table | * PCI Device ID Table | ||||
* | * | ||||
* Used by probe to select devices to load on | * Used by probe to select devices to load on | ||||
* Last field stores an index into ixl_strings | * Last field stores an index into ixl_strings | ||||
* Last entry must be all 0s | * Last entry must be all 0s | ||||
* | * | ||||
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } | * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } | ||||
Show All 21 Lines | static ixl_vendor_info_t ixl_vendor_info_array[] = | ||||
{0, 0, 0, 0, 0} | {0, 0, 0, 0, 0} | ||||
}; | }; | ||||
/********************************************************************* | /********************************************************************* | ||||
* Table of branding strings | * Table of branding strings | ||||
*********************************************************************/ | *********************************************************************/ | ||||
static char *ixl_strings[] = { | static char *ixl_strings[] = { | ||||
"Intel(R) Ethernet Connection XL710/X722 Driver" | "Intel(R) Ethernet Connection 700 Series PF Driver" | ||||
}; | }; | ||||
/********************************************************************* | /********************************************************************* | ||||
* Function prototypes | * Function prototypes | ||||
*********************************************************************/ | *********************************************************************/ | ||||
static int ixl_probe(device_t); | static int ixl_probe(device_t); | ||||
static int ixl_attach(device_t); | static int ixl_attach(device_t); | ||||
static int ixl_detach(device_t); | static int ixl_detach(device_t); | ||||
static int ixl_shutdown(device_t); | static int ixl_shutdown(device_t); | ||||
static int ixl_save_pf_tunables(struct ixl_pf *); | static int ixl_save_pf_tunables(struct ixl_pf *); | ||||
static int ixl_attach_get_link_status(struct ixl_pf *); | |||||
/********************************************************************* | /********************************************************************* | ||||
* FreeBSD Device Interface Entry Points | * FreeBSD Device Interface Entry Points | ||||
*********************************************************************/ | *********************************************************************/ | ||||
static device_method_t ixl_methods[] = { | static device_method_t ixl_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_probe, ixl_probe), | DEVMETHOD(device_probe, ixl_probe), | ||||
Show All 35 Lines | |||||
* but this allows it to be forced off for testing. | * but this allows it to be forced off for testing. | ||||
*/ | */ | ||||
static int ixl_enable_msix = 1; | static int ixl_enable_msix = 1; | ||||
TUNABLE_INT("hw.ixl.enable_msix", &ixl_enable_msix); | TUNABLE_INT("hw.ixl.enable_msix", &ixl_enable_msix); | ||||
SYSCTL_INT(_hw_ixl, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixl_enable_msix, 0, | SYSCTL_INT(_hw_ixl, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixl_enable_msix, 0, | ||||
"Enable MSI-X interrupts"); | "Enable MSI-X interrupts"); | ||||
/* | /* | ||||
** Number of descriptors per ring: | ** Number of descriptors per ring | ||||
** - TX and RX are the same size | ** - TX and RX sizes are independently configurable | ||||
*/ | */ | ||||
static int ixl_ring_size = IXL_DEFAULT_RING; | static int ixl_tx_ring_size = IXL_DEFAULT_RING; | ||||
TUNABLE_INT("hw.ixl.ring_size", &ixl_ring_size); | TUNABLE_INT("hw.ixl.tx_ring_size", &ixl_tx_ring_size); | ||||
SYSCTL_INT(_hw_ixl, OID_AUTO, ring_size, CTLFLAG_RDTUN, | SYSCTL_INT(_hw_ixl, OID_AUTO, tx_ring_size, CTLFLAG_RDTUN, | ||||
&ixl_ring_size, 0, "Descriptor Ring Size"); | &ixl_tx_ring_size, 0, "TX Descriptor Ring Size"); | ||||
static int ixl_rx_ring_size = IXL_DEFAULT_RING; | |||||
TUNABLE_INT("hw.ixl.rx_ring_size", &ixl_rx_ring_size); | |||||
SYSCTL_INT(_hw_ixl, OID_AUTO, rx_ring_size, CTLFLAG_RDTUN, | |||||
&ixl_rx_ring_size, 0, "RX Descriptor Ring Size"); | |||||
/* | /* | ||||
** This can be set manually, if left as 0 the | ** This can be set manually, if left as 0 the | ||||
** number of queues will be calculated based | ** number of queues will be calculated based | ||||
** on cpus and msix vectors available. | ** on cpus and msix vectors available. | ||||
*/ | */ | ||||
static int ixl_max_queues = 0; | static int ixl_max_queues = 0; | ||||
TUNABLE_INT("hw.ixl.max_queues", &ixl_max_queues); | TUNABLE_INT("hw.ixl.max_queues", &ixl_max_queues); | ||||
SYSCTL_INT(_hw_ixl, OID_AUTO, max_queues, CTLFLAG_RDTUN, | SYSCTL_INT(_hw_ixl, OID_AUTO, max_queues, CTLFLAG_RDTUN, | ||||
&ixl_max_queues, 0, "Number of Queues"); | &ixl_max_queues, 0, "Number of Queues"); | ||||
/* | |||||
* Leave this on unless you need to send flow control | |||||
* frames (or other control frames) from software | |||||
*/ | |||||
static int ixl_enable_tx_fc_filter = 1; | static int ixl_enable_tx_fc_filter = 1; | ||||
TUNABLE_INT("hw.ixl.enable_tx_fc_filter", | TUNABLE_INT("hw.ixl.enable_tx_fc_filter", | ||||
&ixl_enable_tx_fc_filter); | &ixl_enable_tx_fc_filter); | ||||
SYSCTL_INT(_hw_ixl, OID_AUTO, enable_tx_fc_filter, CTLFLAG_RDTUN, | SYSCTL_INT(_hw_ixl, OID_AUTO, enable_tx_fc_filter, CTLFLAG_RDTUN, | ||||
&ixl_enable_tx_fc_filter, 0, | &ixl_enable_tx_fc_filter, 0, | ||||
"Filter out packets with Ethertype 0x8808 from being sent out by non-HW sources"); | "Filter out packets with Ethertype 0x8808 from being sent out by non-HW sources"); | ||||
/* | |||||
* Different method for processing TX descriptor | |||||
* completion. | |||||
*/ | |||||
static int ixl_enable_head_writeback = 1; | |||||
TUNABLE_INT("hw.ixl.enable_head_writeback", | |||||
&ixl_enable_head_writeback); | |||||
SYSCTL_INT(_hw_ixl, OID_AUTO, enable_head_writeback, CTLFLAG_RDTUN, | |||||
&ixl_enable_head_writeback, 0, | |||||
"For detecting last completed TX descriptor by hardware, use value written by HW instead of checking descriptors"); | |||||
static int ixl_core_debug_mask = 0; | static int ixl_core_debug_mask = 0; | ||||
TUNABLE_INT("hw.ixl.core_debug_mask", | TUNABLE_INT("hw.ixl.core_debug_mask", | ||||
&ixl_core_debug_mask); | &ixl_core_debug_mask); | ||||
SYSCTL_INT(_hw_ixl, OID_AUTO, core_debug_mask, CTLFLAG_RDTUN, | SYSCTL_INT(_hw_ixl, OID_AUTO, core_debug_mask, CTLFLAG_RDTUN, | ||||
&ixl_core_debug_mask, 0, | &ixl_core_debug_mask, 0, | ||||
"Display debug statements that are printed in non-shared code"); | "Display debug statements that are printed in non-shared code"); | ||||
static int ixl_shared_debug_mask = 0; | static int ixl_shared_debug_mask = 0; | ||||
Show All 26 Lines | |||||
static int ixl_tx_itr = IXL_ITR_4K; | static int ixl_tx_itr = IXL_ITR_4K; | ||||
TUNABLE_INT("hw.ixl.tx_itr", &ixl_tx_itr); | TUNABLE_INT("hw.ixl.tx_itr", &ixl_tx_itr); | ||||
SYSCTL_INT(_hw_ixl, OID_AUTO, tx_itr, CTLFLAG_RDTUN, | SYSCTL_INT(_hw_ixl, OID_AUTO, tx_itr, CTLFLAG_RDTUN, | ||||
&ixl_tx_itr, 0, "TX Interrupt Rate"); | &ixl_tx_itr, 0, "TX Interrupt Rate"); | ||||
#ifdef IXL_IW | #ifdef IXL_IW | ||||
int ixl_enable_iwarp = 0; | int ixl_enable_iwarp = 0; | ||||
TUNABLE_INT("hw.ixl.enable_iwarp", &ixl_enable_iwarp); | TUNABLE_INT("hw.ixl.enable_iwarp", &ixl_enable_iwarp); | ||||
SYSCTL_INT(_hw_ixl, OID_AUTO, enable_iwarp, CTLFLAG_RDTUN, | |||||
&ixl_enable_iwarp, 0, "iWARP enabled"); | |||||
#if __FreeBSD_version < 1100000 | |||||
int ixl_limit_iwarp_msix = 1; | |||||
#else | |||||
int ixl_limit_iwarp_msix = IXL_IW_MAX_MSIX; | |||||
#endif | #endif | ||||
TUNABLE_INT("hw.ixl.limit_iwarp_msix", &ixl_limit_iwarp_msix); | |||||
SYSCTL_INT(_hw_ixl, OID_AUTO, limit_iwarp_msix, CTLFLAG_RDTUN, | |||||
&ixl_limit_iwarp_msix, 0, "Limit MSIX vectors assigned to iWARP"); | |||||
#endif | |||||
#ifdef DEV_NETMAP | #ifdef DEV_NETMAP | ||||
#define NETMAP_IXL_MAIN /* only bring in one part of the netmap code */ | #define NETMAP_IXL_MAIN /* only bring in one part of the netmap code */ | ||||
#include <dev/netmap/if_ixl_netmap.h> | #include <dev/netmap/if_ixl_netmap.h> | ||||
#endif /* DEV_NETMAP */ | #endif /* DEV_NETMAP */ | ||||
/********************************************************************* | /********************************************************************* | ||||
* Device identification routine | * Device identification routine | ||||
Show All 40 Lines | if ((pci_vendor_id == ent->vendor_id) && | ||||
device_set_desc_copy(dev, device_name); | device_set_desc_copy(dev, device_name); | ||||
return (BUS_PROBE_DEFAULT); | return (BUS_PROBE_DEFAULT); | ||||
} | } | ||||
ent++; | ent++; | ||||
} | } | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
static int | |||||
ixl_attach_get_link_status(struct ixl_pf *pf) | |||||
{ | |||||
struct i40e_hw *hw = &pf->hw; | |||||
device_t dev = pf->dev; | |||||
int error = 0; | |||||
if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || | |||||
(hw->aq.fw_maj_ver < 4)) { | |||||
i40e_msec_delay(75); | |||||
error = i40e_aq_set_link_restart_an(hw, TRUE, NULL); | |||||
if (error) { | |||||
device_printf(dev, "link restart failed, aq_err=%d\n", | |||||
pf->hw.aq.asq_last_status); | |||||
return error; | |||||
} | |||||
} | |||||
/* Determine link state */ | |||||
hw->phy.get_link_info = TRUE; | |||||
i40e_get_link_status(hw, &pf->link_up); | |||||
return (0); | |||||
} | |||||
/* | /* | ||||
* Sanity check and save off tunable values. | * Sanity check and save off tunable values. | ||||
*/ | */ | ||||
static int | static int | ||||
ixl_save_pf_tunables(struct ixl_pf *pf) | ixl_save_pf_tunables(struct ixl_pf *pf) | ||||
{ | { | ||||
device_t dev = pf->dev; | device_t dev = pf->dev; | ||||
/* Save tunable information */ | /* Save tunable information */ | ||||
pf->enable_msix = ixl_enable_msix; | pf->enable_msix = ixl_enable_msix; | ||||
pf->max_queues = ixl_max_queues; | pf->max_queues = ixl_max_queues; | ||||
pf->enable_tx_fc_filter = ixl_enable_tx_fc_filter; | pf->enable_tx_fc_filter = ixl_enable_tx_fc_filter; | ||||
pf->dynamic_rx_itr = ixl_dynamic_rx_itr; | pf->dynamic_rx_itr = ixl_dynamic_rx_itr; | ||||
pf->dynamic_tx_itr = ixl_dynamic_tx_itr; | pf->dynamic_tx_itr = ixl_dynamic_tx_itr; | ||||
pf->dbg_mask = ixl_core_debug_mask; | pf->dbg_mask = ixl_core_debug_mask; | ||||
pf->hw.debug_mask = ixl_shared_debug_mask; | pf->hw.debug_mask = ixl_shared_debug_mask; | ||||
#ifdef DEV_NETMAP | |||||
if (ixl_enable_head_writeback == 0) | |||||
device_printf(dev, "Head writeback mode cannot be disabled " | |||||
"when netmap is enabled\n"); | |||||
pf->vsi.enable_head_writeback = 1; | |||||
#else | |||||
pf->vsi.enable_head_writeback = !!(ixl_enable_head_writeback); | |||||
#endif | |||||
if (ixl_ring_size < IXL_MIN_RING | ixl_vsi_setup_rings_size(&pf->vsi, ixl_tx_ring_size, ixl_rx_ring_size); | ||||
|| ixl_ring_size > IXL_MAX_RING | |||||
|| ixl_ring_size % IXL_RING_INCREMENT != 0) { | |||||
device_printf(dev, "Invalid ring_size value of %d set!\n", | |||||
ixl_ring_size); | |||||
device_printf(dev, "ring_size must be between %d and %d, " | |||||
"inclusive, and must be a multiple of %d\n", | |||||
IXL_MIN_RING, IXL_MAX_RING, IXL_RING_INCREMENT); | |||||
device_printf(dev, "Using default value of %d instead\n", | |||||
IXL_DEFAULT_RING); | |||||
pf->ringsz = IXL_DEFAULT_RING; | |||||
} else | |||||
pf->ringsz = ixl_ring_size; | |||||
if (ixl_tx_itr < 0 || ixl_tx_itr > IXL_MAX_ITR) { | if (ixl_tx_itr < 0 || ixl_tx_itr > IXL_MAX_ITR) { | ||||
device_printf(dev, "Invalid tx_itr value of %d set!\n", | device_printf(dev, "Invalid tx_itr value of %d set!\n", | ||||
ixl_tx_itr); | ixl_tx_itr); | ||||
device_printf(dev, "tx_itr must be between %d and %d, " | device_printf(dev, "tx_itr must be between %d and %d, " | ||||
"inclusive\n", | "inclusive\n", | ||||
0, IXL_MAX_ITR); | 0, IXL_MAX_ITR); | ||||
device_printf(dev, "Using default value of %d instead\n", | device_printf(dev, "Using default value of %d instead\n", | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | ixl_attach(device_t dev) | ||||
hw = &pf->hw; | hw = &pf->hw; | ||||
/* | /* | ||||
** Note this assumes we have a single embedded VSI, | ** Note this assumes we have a single embedded VSI, | ||||
** this could be enhanced later to allocate multiple | ** this could be enhanced later to allocate multiple | ||||
*/ | */ | ||||
vsi = &pf->vsi; | vsi = &pf->vsi; | ||||
vsi->dev = pf->dev; | vsi->dev = pf->dev; | ||||
vsi->back = pf; | |||||
/* Save tunable values */ | /* Save tunable values */ | ||||
error = ixl_save_pf_tunables(pf); | error = ixl_save_pf_tunables(pf); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
/* Core Lock Init*/ | /* Core Lock Init*/ | ||||
IXL_PF_LOCK_INIT(pf, device_get_nameunit(dev)); | IXL_PF_LOCK_INIT(pf, device_get_nameunit(dev)); | ||||
Show All 22 Lines | ixl_attach(device_t dev) | ||||
status = i40e_init_shared_code(hw); | status = i40e_init_shared_code(hw); | ||||
if (status) { | if (status) { | ||||
device_printf(dev, "Unable to initialize shared code, error %s\n", | device_printf(dev, "Unable to initialize shared code, error %s\n", | ||||
i40e_stat_str(hw, status)); | i40e_stat_str(hw, status)); | ||||
error = EIO; | error = EIO; | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
/* | |||||
* Allocate interrupts and figure out number of queues to use | |||||
* for PF interface | |||||
*/ | |||||
pf->msix = ixl_init_msix(pf); | |||||
/* Set up the admin queue */ | /* Set up the admin queue */ | ||||
hw->aq.num_arq_entries = IXL_AQ_LEN; | hw->aq.num_arq_entries = IXL_AQ_LEN; | ||||
hw->aq.num_asq_entries = IXL_AQ_LEN; | hw->aq.num_asq_entries = IXL_AQ_LEN; | ||||
hw->aq.arq_buf_size = IXL_AQ_BUF_SZ; | hw->aq.arq_buf_size = IXL_AQ_BUF_SZ; | ||||
hw->aq.asq_buf_size = IXL_AQ_BUF_SZ; | hw->aq.asq_buf_size = IXL_AQ_BUF_SZ; | ||||
status = i40e_init_adminq(hw); | status = i40e_init_adminq(hw); | ||||
if (status != 0 && status != I40E_ERR_FIRMWARE_API_VERSION) { | if (status != 0 && status != I40E_ERR_FIRMWARE_API_VERSION) { | ||||
device_printf(dev, "Unable to initialize Admin Queue, error %s\n", | device_printf(dev, "Unable to initialize Admin Queue, error %s\n", | ||||
i40e_stat_str(hw, status)); | i40e_stat_str(hw, status)); | ||||
error = EIO; | error = EIO; | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
ixl_print_nvm_version(pf); | ixl_print_nvm_version(pf); | ||||
if (status == I40E_ERR_FIRMWARE_API_VERSION) { | if (status == I40E_ERR_FIRMWARE_API_VERSION) { | ||||
device_printf(dev, "The driver for the device stopped " | device_printf(dev, "The driver for the device stopped " | ||||
"because the NVM image is newer than expected.\n" | "because the NVM image is newer than expected.\n"); | ||||
"You must install the most recent version of " | device_printf(dev, "You must install the most recent version of " | ||||
"the network driver.\n"); | "the network driver.\n"); | ||||
error = EIO; | error = EIO; | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR && | if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR && | ||||
hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR) | hw->aq.api_min_ver > I40E_FW_MINOR_VERSION(hw)) { | ||||
device_printf(dev, "The driver for the device detected " | device_printf(dev, "The driver for the device detected " | ||||
"a newer version of the NVM image than expected.\n" | "a newer version of the NVM image than expected.\n"); | ||||
"Please install the most recent version of the network driver.\n"); | device_printf(dev, "Please install the most recent version " | ||||
else if (hw->aq.api_maj_ver < I40E_FW_API_VERSION_MAJOR || | "of the network driver.\n"); | ||||
hw->aq.api_min_ver < (I40E_FW_API_VERSION_MINOR - 1)) | } else if (hw->aq.api_maj_ver == 1 && hw->aq.api_min_ver < 4) { | ||||
device_printf(dev, "The driver for the device detected " | device_printf(dev, "The driver for the device detected " | ||||
"an older version of the NVM image than expected.\n" | "an older version of the NVM image than expected.\n"); | ||||
"Please update the NVM image.\n"); | device_printf(dev, "Please update the NVM image.\n"); | ||||
} | |||||
/* Clear PXE mode */ | /* Clear PXE mode */ | ||||
i40e_clear_pxe_mode(hw); | i40e_clear_pxe_mode(hw); | ||||
/* Get capabilities from the device */ | /* Get capabilities from the device */ | ||||
error = ixl_get_hw_capabilities(pf); | error = ixl_get_hw_capabilities(pf); | ||||
if (error) { | if (error) { | ||||
device_printf(dev, "HW capabilities failure!\n"); | device_printf(dev, "HW capabilities failure!\n"); | ||||
goto err_get_cap; | goto err_get_cap; | ||||
} | } | ||||
/* | |||||
* Allocate interrupts and figure out number of queues to use | |||||
* for PF interface | |||||
*/ | |||||
pf->msix = ixl_init_msix(pf); | |||||
/* Set up host memory cache */ | /* Set up host memory cache */ | ||||
status = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp, | status = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp, | ||||
hw->func_caps.num_rx_qp, 0, 0); | hw->func_caps.num_rx_qp, 0, 0); | ||||
if (status) { | if (status) { | ||||
device_printf(dev, "init_lan_hmc failed: %s\n", | device_printf(dev, "init_lan_hmc failed: %s\n", | ||||
i40e_stat_str(hw, status)); | i40e_stat_str(hw, status)); | ||||
goto err_get_cap; | goto err_get_cap; | ||||
} | } | ||||
Show All 19 Lines | device_printf(dev, "Failed to reserve queues for PF LAN VSI, error %d\n", | ||||
error); | error); | ||||
goto err_mac_hmc; | goto err_mac_hmc; | ||||
} | } | ||||
device_printf(dev, "Allocating %d queues for PF LAN VSI; %d queues active\n", | device_printf(dev, "Allocating %d queues for PF LAN VSI; %d queues active\n", | ||||
pf->qtag.num_allocated, pf->qtag.num_active); | pf->qtag.num_allocated, pf->qtag.num_active); | ||||
/* Disable LLDP from the firmware for certain NVM versions */ | /* Disable LLDP from the firmware for certain NVM versions */ | ||||
if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 3)) || | if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 3)) || | ||||
(pf->hw.aq.fw_maj_ver < 4)) | (pf->hw.aq.fw_maj_ver < 4)) { | ||||
i40e_aq_stop_lldp(hw, TRUE, NULL); | i40e_aq_stop_lldp(hw, TRUE, NULL); | ||||
pf->state |= IXL_PF_STATE_FW_LLDP_DISABLED; | |||||
} | |||||
/* Get MAC addresses from hardware */ | /* Get MAC addresses from hardware */ | ||||
i40e_get_mac_addr(hw, hw->mac.addr); | i40e_get_mac_addr(hw, hw->mac.addr); | ||||
error = i40e_validate_mac_addr(hw->mac.addr); | error = i40e_validate_mac_addr(hw->mac.addr); | ||||
if (error) { | if (error) { | ||||
device_printf(dev, "validate_mac_addr failed: %d\n", error); | device_printf(dev, "validate_mac_addr failed: %d\n", error); | ||||
goto err_mac_hmc; | goto err_mac_hmc; | ||||
} | } | ||||
bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN); | bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN); | ||||
i40e_get_port_mac_addr(hw, hw->mac.port_addr); | i40e_get_port_mac_addr(hw, hw->mac.port_addr); | ||||
/* Query device FW LLDP status */ | |||||
ixl_get_fw_lldp_status(pf); | |||||
/* Tell FW to apply DCB config on link up */ | |||||
if ((hw->mac.type != I40E_MAC_X722) | |||||
&& ((pf->hw.aq.api_maj_ver > 1) | |||||
|| (pf->hw.aq.api_maj_ver == 1 && pf->hw.aq.api_min_ver >= 7))) | |||||
i40e_aq_set_dcb_parameters(hw, true, NULL); | |||||
/* Initialize mac filter list for VSI */ | /* Initialize mac filter list for VSI */ | ||||
SLIST_INIT(&vsi->ftl); | SLIST_INIT(&vsi->ftl); | ||||
/* Set up SW VSI and allocate queue memory and rings */ | /* Set up SW VSI and allocate queue memory and rings */ | ||||
if (ixl_setup_stations(pf)) { | if (ixl_setup_stations(pf)) { | ||||
device_printf(dev, "setup stations failed!\n"); | device_printf(dev, "setup stations failed!\n"); | ||||
error = ENOMEM; | error = ENOMEM; | ||||
goto err_mac_hmc; | goto err_mac_hmc; | ||||
▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | if (error) | ||||
error); | error); | ||||
} | } | ||||
if (error) { | if (error) { | ||||
device_printf(dev, "interrupt setup error: %d\n", error); | device_printf(dev, "interrupt setup error: %d\n", error); | ||||
} | } | ||||
/* Set initial advertised speed sysctl value */ | /* Set initial advertised speed sysctl value */ | ||||
ixl_get_initial_advertised_speeds(pf); | ixl_set_initial_advertised_speeds(pf); | ||||
/* Initialize statistics & add sysctls */ | /* Initialize statistics & add sysctls */ | ||||
ixl_add_device_sysctls(pf); | ixl_add_device_sysctls(pf); | ||||
ixl_pf_reset_stats(pf); | ixl_pf_reset_stats(pf); | ||||
ixl_update_stats_counters(pf); | ixl_update_stats_counters(pf); | ||||
ixl_add_hw_stats(pf); | ixl_add_hw_stats(pf); | ||||
/* Register for VLAN events */ | /* Register for VLAN events */ | ||||
vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, | vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, | ||||
ixl_register_vlan, vsi, EVENTHANDLER_PRI_FIRST); | ixl_register_vlan, vsi, EVENTHANDLER_PRI_FIRST); | ||||
vsi->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, | vsi->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, | ||||
ixl_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST); | ixl_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST); | ||||
#ifdef PCI_IOV | #ifdef PCI_IOV | ||||
ixl_initialize_sriov(pf); | ixl_initialize_sriov(pf); | ||||
#endif | #endif | ||||
#ifdef DEV_NETMAP | #ifdef DEV_NETMAP | ||||
if (vsi->num_rx_desc == vsi->num_tx_desc) { | |||||
vsi->queues[0].num_desc = vsi->num_rx_desc; | |||||
ixl_netmap_attach(vsi); | ixl_netmap_attach(vsi); | ||||
} else | |||||
device_printf(dev, | |||||
"Netmap is not supported when RX and TX descriptor ring sizes differ\n"); | |||||
#endif /* DEV_NETMAP */ | #endif /* DEV_NETMAP */ | ||||
#ifdef IXL_IW | #ifdef IXL_IW | ||||
if (hw->func_caps.iwarp && ixl_enable_iwarp) { | if (hw->func_caps.iwarp && ixl_enable_iwarp) { | ||||
pf->iw_enabled = (pf->iw_msix > 0) ? true : false; | pf->iw_enabled = (pf->iw_msix > 0) ? true : false; | ||||
if (pf->iw_enabled) { | if (pf->iw_enabled) { | ||||
error = ixl_iw_pf_attach(pf); | error = ixl_iw_pf_attach(pf); | ||||
if (error) { | if (error) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"interfacing to iwarp driver failed: %d\n", | "interfacing to iwarp driver failed: %d\n", | ||||
error); | error); | ||||
goto err_late; | goto err_late; | ||||
} | |||||
} else | } else | ||||
device_printf(dev, "iWARP ready\n"); | |||||
} else | |||||
device_printf(dev, | device_printf(dev, | ||||
"iwarp disabled on this device (no msix vectors)\n"); | "iwarp disabled on this device (no msix vectors)\n"); | ||||
} else { | } else { | ||||
pf->iw_enabled = false; | pf->iw_enabled = false; | ||||
device_printf(dev, "The device is not iWARP enabled\n"); | device_printf(dev, "The device is not iWARP enabled\n"); | ||||
} | } | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | |||||
#ifdef PCI_IOV | #ifdef PCI_IOV | ||||
error = pci_iov_detach(dev); | error = pci_iov_detach(dev); | ||||
if (error != 0) { | if (error != 0) { | ||||
device_printf(dev, "SR-IOV in use; detach first.\n"); | device_printf(dev, "SR-IOV in use; detach first.\n"); | ||||
return (error); | return (error); | ||||
} | } | ||||
#endif | #endif | ||||
/* Remove all previously allocated media types */ | |||||
ifmedia_removeall(&vsi->media); | |||||
ether_ifdetach(vsi->ifp); | ether_ifdetach(vsi->ifp); | ||||
if (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING) | if (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING) | ||||
ixl_stop(pf); | ixl_stop(pf); | ||||
/* Shutdown LAN HMC */ | /* Shutdown LAN HMC */ | ||||
status = i40e_shutdown_lan_hmc(hw); | status = i40e_shutdown_lan_hmc(hw); | ||||
if (status) | if (status) | ||||
▲ Show 20 Lines • Show All 59 Lines • Show Last 20 Lines |