ixl: Update to 1.4.20-k.

Changes by author:

Eric Joyner	ixl: Add more error messages/checks to ixl_vsi_assign_msix().
Eric Joyner	ixl/ixlv: Clarify a comment about descriptors.
Eric Joyner	ixl/ixlv: Improve i40e_debug() implementation.
Eric Joyner	ixl/ixlv: Remove unused ASSERT() macro; move struct around.
Eric Joyner	ixl: Set initial advertised speed value in init_locked().
Eric Joyner	ixl: Fix flow control sysctl value being stored when new value is invalid.
Eric Joyner	Edit comments and spacing.
Carolyn Wyborny	i40e-shared: Add functions to blink led on Coppervale PHY
Eric Joyner	ixl: Re-do interrupt setup.
Eric Joyner	ixl: Remove VFLR task setup from legacy flow.
Eric Joyner	ixl: Shutdown/setup HMC when handling an EMPR reset.

Differential Revision:  https://reviews.freebsd.org/D6211
Reviewed by:    sbruno, kmacy, jeffrey.e.pieper@intel.com
MFC after:      2 weeks
Sponsored by:   Intel Corporation
This commit is contained in:
Eric Joyner 2016-05-12 18:21:34 +00:00
parent 1d767a8eae
commit 6c42605965
7 changed files with 781 additions and 172 deletions

View File

@ -5600,6 +5600,335 @@ enum i40e_status_code i40e_aq_configure_partition_bw(struct i40e_hw *hw,
return status;
}
/**
* i40e_read_phy_register
* @hw: pointer to the HW structure
* @page: registers page number
* @reg: register address in the page
* @phy_adr: PHY address on MDIO interface
* @value: PHY register value
*
* Reads specified PHY register value
**/
enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr,
u16 *value)
{
enum i40e_status_code status = I40E_ERR_TIMEOUT;
u32 command = 0;
u16 retry = 1000;
u8 port_num = (u8)hw->func_caps.mdio_port_num;
command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
(page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_OPCODE_ADDRESS) |
(I40E_MDIO_STCODE) |
(I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
wr32(hw, I40E_GLGEN_MSCA(port_num), command);
do {
command = rd32(hw, I40E_GLGEN_MSCA(port_num));
if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
status = I40E_SUCCESS;
break;
}
i40e_usec_delay(10);
retry--;
} while (retry);
if (status) {
i40e_debug(hw, I40E_DEBUG_PHY,
"PHY: Can't write command to external PHY.\n");
goto phy_read_end;
}
command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_OPCODE_READ) |
(I40E_MDIO_STCODE) |
(I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
status = I40E_ERR_TIMEOUT;
retry = 1000;
wr32(hw, I40E_GLGEN_MSCA(port_num), command);
do {
command = rd32(hw, I40E_GLGEN_MSCA(port_num));
if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
status = I40E_SUCCESS;
break;
}
i40e_usec_delay(10);
retry--;
} while (retry);
if (!status) {
command = rd32(hw, I40E_GLGEN_MSRWD(port_num));
*value = (command & I40E_GLGEN_MSRWD_MDIRDDATA_MASK) >>
I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT;
} else {
i40e_debug(hw, I40E_DEBUG_PHY,
"PHY: Can't read register value from external PHY.\n");
}
phy_read_end:
return status;
}
/**
* i40e_write_phy_register
* @hw: pointer to the HW structure
* @page: registers page number
* @reg: register address in the page
* @phy_adr: PHY address on MDIO interface
* @value: PHY register value
*
* Writes value to specified PHY register
**/
enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr,
u16 value)
{
enum i40e_status_code status = I40E_ERR_TIMEOUT;
u32 command = 0;
u16 retry = 1000;
u8 port_num = (u8)hw->func_caps.mdio_port_num;
command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
(page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_OPCODE_ADDRESS) |
(I40E_MDIO_STCODE) |
(I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
wr32(hw, I40E_GLGEN_MSCA(port_num), command);
do {
command = rd32(hw, I40E_GLGEN_MSCA(port_num));
if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
status = I40E_SUCCESS;
break;
}
i40e_usec_delay(10);
retry--;
} while (retry);
if (status) {
i40e_debug(hw, I40E_DEBUG_PHY,
"PHY: Can't write command to external PHY.\n");
goto phy_write_end;
}
command = value << I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT;
wr32(hw, I40E_GLGEN_MSRWD(port_num), command);
command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_OPCODE_WRITE) |
(I40E_MDIO_STCODE) |
(I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
status = I40E_ERR_TIMEOUT;
retry = 1000;
wr32(hw, I40E_GLGEN_MSCA(port_num), command);
do {
command = rd32(hw, I40E_GLGEN_MSCA(port_num));
if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
status = I40E_SUCCESS;
break;
}
i40e_usec_delay(10);
retry--;
} while (retry);
phy_write_end:
return status;
}
/**
* i40e_get_phy_address
* @hw: pointer to the HW structure
* @dev_num: PHY port num that address we want
* @phy_addr: Returned PHY address
*
* Gets PHY address for current port
**/
u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num)
{
u8 port_num = (u8)hw->func_caps.mdio_port_num;
u32 reg_val = rd32(hw, I40E_GLGEN_MDIO_I2C_SEL(port_num));
return (u8)(reg_val >> ((dev_num + 1) * 5)) & 0x1f;
}
/**
* i40e_blink_phy_led
* @hw: pointer to the HW structure
* @time: time how long led will blinks in secs
* @interval: gap between LED on and off in msecs
*
* Blinks PHY link LED
**/
enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw,
u32 time, u32 interval)
{
enum i40e_status_code status = I40E_SUCCESS;
u32 i;
u16 led_ctl = 0;
u16 gpio_led_port;
u16 led_reg;
u16 led_addr = I40E_PHY_LED_PROV_REG_1;
u8 phy_addr = 0;
u8 port_num;
i = rd32(hw, I40E_PFGEN_PORTNUM);
port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
phy_addr = i40e_get_phy_address(hw, port_num);
for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
led_addr++) {
status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, &led_reg);
if (status)
goto phy_blinking_end;
led_ctl = led_reg;
if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
led_reg = 0;
status = i40e_write_phy_register(hw,
I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr,
led_reg);
if (status)
goto phy_blinking_end;
break;
}
}
if (time > 0 && interval > 0) {
for (i = 0; i < time * 1000; i += interval) {
status = i40e_read_phy_register(hw,
I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr,
&led_reg);
if (status)
goto restore_config;
if (led_reg & I40E_PHY_LED_MANUAL_ON)
led_reg = 0;
else
led_reg = I40E_PHY_LED_MANUAL_ON;
status = i40e_write_phy_register(hw,
I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr,
led_reg);
if (status)
goto restore_config;
i40e_msec_delay(interval);
}
}
restore_config:
status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
phy_addr, led_ctl);
phy_blinking_end:
return status;
}
/**
* i40e_led_get_phy - return current on/off mode
* @hw: pointer to the hw struct
* @led_addr: address of led register to use
* @val: original value of register to use
*
**/
enum i40e_status_code i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
u16 *val)
{
enum i40e_status_code status = I40E_SUCCESS;
u16 gpio_led_port;
u8 phy_addr = 0;
u16 reg_val;
u16 temp_addr;
u8 port_num;
u32 i;
temp_addr = I40E_PHY_LED_PROV_REG_1;
i = rd32(hw, I40E_PFGEN_PORTNUM);
port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
phy_addr = i40e_get_phy_address(hw, port_num);
for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
temp_addr++) {
status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
temp_addr, phy_addr, &reg_val);
if (status)
return status;
*val = reg_val;
if (reg_val & I40E_PHY_LED_LINK_MODE_MASK) {
*led_addr = temp_addr;
break;
}
}
return status;
}
/**
* i40e_led_set_phy
* @hw: pointer to the HW structure
* @on: TRUE or FALSE
* @mode: original val plus bit for set or ignore
* Set led's on or off when controlled by the PHY
*
**/
enum i40e_status_code i40e_led_set_phy(struct i40e_hw *hw, bool on,
u16 led_addr, u32 mode)
{
enum i40e_status_code status = I40E_SUCCESS;
u16 led_ctl = 0;
u16 led_reg = 0;
u8 phy_addr = 0;
u8 port_num;
u32 i;
i = rd32(hw, I40E_PFGEN_PORTNUM);
port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
phy_addr = i40e_get_phy_address(hw, port_num);
status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
phy_addr, &led_reg);
if (status)
return status;
led_ctl = led_reg;
if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
led_reg = 0;
status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_reg);
if (status)
return status;
}
status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, &led_reg);
if (status)
goto restore_config;
if (on)
led_reg = I40E_PHY_LED_MANUAL_ON;
else
led_reg = 0;
status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_reg);
if (status)
goto restore_config;
if (mode & I40E_PHY_LED_MODE_ORIG) {
led_ctl = (mode & I40E_PHY_LED_MODE_MASK);
status = i40e_write_phy_register(hw,
I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_ctl);
}
return status;
restore_config:
status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
phy_addr, led_ctl);
return status;
}
/**
* i40e_aq_send_msg_to_pf
* @hw: pointer to the hardware structure

View File

@ -159,22 +159,19 @@ i40e_destroy_spinlock(struct i40e_spinlock *lock)
}
/*
** i40e_debug_d - OS dependent version of shared code debug printing
*/
void i40e_debug_d(void *hw, u32 mask, char *fmt, ...)
* Helper function for debug statement printing
*/
void
i40e_debug_d(struct i40e_hw *hw, enum i40e_debug_mask mask, char *fmt, ...)
{
char buf[512];
va_list args;
va_list args;
if (!(mask & ((struct i40e_hw *)hw)->debug_mask))
return;
if (!(mask & ((struct i40e_hw *)hw)->debug_mask))
return;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
device_printf(((struct i40e_osdep *)hw->back)->dev, fmt, args);
va_end(args);
/* the debug string is already formatted with a newline */
printf("%s", buf);
}
u16

View File

@ -54,8 +54,6 @@
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#define ASSERT(x) if(!(x)) panic("IXL: x")
#define i40e_usec_delay(x) DELAY(x)
#define i40e_msec_delay(x) DELAY(1000*(x))
@ -169,21 +167,26 @@ struct i40e_dma_mem {
int flags;
};
struct i40e_hw; /* forward decl */
u16 i40e_read_pci_cfg(struct i40e_hw *, u32);
void i40e_write_pci_cfg(struct i40e_hw *, u32, u16);
#define i40e_debug(h, m, s, ...) i40e_debug_d(h, m, s, ##__VA_ARGS__)
extern void i40e_debug_d(void *hw, u32 mask, char *fmt_str, ...);
struct i40e_virt_mem {
void *va;
u32 size;
};
struct i40e_hw; /* forward decl */
u16 i40e_read_pci_cfg(struct i40e_hw *, u32);
void i40e_write_pci_cfg(struct i40e_hw *, u32, u16);
/*
** This hardware supports either 16 or 32 byte rx descriptors
** we default here to the larger size.
** i40e_debug - OS dependent version of shared code debug printing
*/
enum i40e_debug_mask;
#define i40e_debug(h, m, s, ...) i40e_debug_d(h, m, s, ##__VA_ARGS__)
extern void i40e_debug_d(struct i40e_hw *hw, enum i40e_debug_mask mask,
char *fmt_str, ...);
/*
** This hardware supports either 16 or 32 byte rx descriptors;
** the driver only uses the 32 byte kind.
*/
#define i40e_rx_desc i40e_32byte_rx_desc

View File

@ -84,6 +84,12 @@ const char *i40e_stat_str(struct i40e_hw *hw, enum i40e_status_code stat_err);
u32 i40e_led_get(struct i40e_hw *hw);
void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink);
enum i40e_status_code i40e_led_set_phy(struct i40e_hw *hw, bool on,
u16 led_addr, u32 mode);
enum i40e_status_code i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
u16 *val);
enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw,
u32 time, u32 interval);
/* admin send queue commands */
@ -483,4 +489,11 @@ enum i40e_status_code i40e_aq_debug_dump(struct i40e_hw *hw, u8 cluster_id,
struct i40e_asq_cmd_details *cmd_details);
void i40e_add_filter_to_drop_tx_flow_control_frames(struct i40e_hw *hw,
u16 vsi_seid);
enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw, u8 page,
u16 reg, u8 phy_addr, u16 *value);
enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw, u8 page,
u16 reg, u8 phy_addr, u16 value);
u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw,
u32 time, u32 interval);
#endif /* _I40E_PROTOTYPE_H_ */

View File

@ -147,6 +147,22 @@ enum i40e_debug_mask {
#define I40E_PCI_LINK_SPEED_5000 0x2
#define I40E_PCI_LINK_SPEED_8000 0x3
#define I40E_MDIO_STCODE 0
#define I40E_MDIO_OPCODE_ADDRESS 0
#define I40E_MDIO_OPCODE_WRITE I40E_MASK(1, \
I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_MDIO_OPCODE_READ_INC_ADDR I40E_MASK(2, \
I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_MDIO_OPCODE_READ I40E_MASK(3, \
I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_PHY_COM_REG_PAGE 0x1E
#define I40E_PHY_LED_LINK_MODE_MASK 0xF0
#define I40E_PHY_LED_MANUAL_ON 0x100
#define I40E_PHY_LED_PROV_REG_1 0xC430
#define I40E_PHY_LED_MODE_MASK 0xFFFF
#define I40E_PHY_LED_MODE_ORIG 0x80000000
/* Memory types */
enum i40e_memset_type {
I40E_NONDMA_MEM = 0,

View File

@ -48,7 +48,7 @@
/*********************************************************************
* Driver version
*********************************************************************/
char ixl_driver_version[] = "1.4.17-k";
char ixl_driver_version[] = "1.4.20-k";
/*********************************************************************
* PCI Device ID Table
@ -105,15 +105,22 @@ static u16 ixl_get_bus_info(struct i40e_hw *, device_t);
static int ixl_setup_stations(struct ixl_pf *);
static int ixl_switch_config(struct ixl_pf *);
static int ixl_initialize_vsi(struct ixl_vsi *);
static int ixl_assign_vsi_msix(struct ixl_pf *);
static int ixl_setup_adminq_msix(struct ixl_pf *);
static int ixl_setup_adminq_tq(struct ixl_pf *);
static int ixl_setup_queue_msix(struct ixl_vsi *);
static int ixl_setup_queue_tqs(struct ixl_vsi *);
static int ixl_teardown_adminq_msix(struct ixl_pf *);
static int ixl_teardown_queue_msix(struct ixl_vsi *);
static void ixl_configure_intr0_msix(struct ixl_pf *);
static void ixl_configure_queue_intr_msix(struct ixl_pf *);
static void ixl_free_queue_tqs(struct ixl_vsi *);
static void ixl_free_adminq_tq(struct ixl_pf *);
static int ixl_assign_vsi_legacy(struct ixl_pf *);
static int ixl_init_msix(struct ixl_pf *);
static void ixl_configure_msix(struct ixl_pf *);
static void ixl_configure_itr(struct ixl_pf *);
static void ixl_configure_legacy(struct ixl_pf *);
static void ixl_init_taskqueues(struct ixl_pf *);
static void ixl_free_taskqueues(struct ixl_pf *);
static void ixl_free_interrupt_resources(struct ixl_pf *);
static void ixl_free_pci_resources(struct ixl_pf *);
static void ixl_local_timer(void *);
static int ixl_setup_interface(device_t, struct ixl_vsi *);
@ -122,6 +129,7 @@ static void ixl_config_rss(struct ixl_vsi *);
static void ixl_set_queue_rx_itr(struct ixl_queue *);
static void ixl_set_queue_tx_itr(struct ixl_queue *);
static int ixl_set_advertised_speeds(struct ixl_pf *, int);
static void ixl_get_initial_advertised_speeds(struct ixl_pf *);
static int ixl_enable_rings(struct ixl_vsi *);
static int ixl_disable_rings(struct ixl_vsi *);
@ -200,6 +208,8 @@ static void ixl_stat_update32(struct i40e_hw *, u32, bool,
u64 *, u64 *);
/* NVM update */
static int ixl_handle_nvmupd_cmd(struct ixl_pf *, struct ifdrv *);
static void ixl_handle_empr_reset(struct ixl_pf *);
static int ixl_rebuild_hw_structs_after_reset(struct ixl_pf *);
#ifdef PCI_IOV
@ -586,7 +596,8 @@ ixl_attach(device_t dev)
error = ixl_switch_config(pf);
if (error) {
device_printf(dev, "Initial ixl_switch_config() failed: %d\n", error);
device_printf(dev, "Initial ixl_switch_config() failed: %d\n",
error);
goto err_late;
}
@ -599,12 +610,31 @@ ixl_attach(device_t dev)
goto err_late;
}
/* Get the bus configuration and set the shared code */
/* Get the bus configuration and set the shared code's config */
bus = ixl_get_bus_info(hw, dev);
i40e_set_pci_config_data(hw, bus);
/* Initialize taskqueues */
ixl_init_taskqueues(pf);
/*
* In MSI-X mode, initialize the Admin Queue interrupt,
* so userland tools can communicate with the adapter regardless of
* the ifnet interface's status.
*/
if (pf->msix > 1) {
error = ixl_setup_adminq_msix(pf);
if (error) {
device_printf(dev, "ixl_setup_adminq_msix error: %d\n",
error);
goto err_late;
}
error = ixl_setup_adminq_tq(pf);
if (error) {
device_printf(dev, "ixl_setup_adminq_tq error: %d\n",
error);
goto err_late;
}
ixl_configure_intr0_msix(pf);
ixl_enable_adminq(hw);
}
/* Initialize statistics & add sysctls */
ixl_add_device_sysctls(pf);
@ -678,7 +708,7 @@ ixl_detach(device_t dev)
struct ixl_pf *pf = device_get_softc(dev);
struct i40e_hw *hw = &pf->hw;
struct ixl_vsi *vsi = &pf->vsi;
i40e_status status;
enum i40e_status_code status;
#ifdef PCI_IOV
int error;
#endif
@ -687,7 +717,7 @@ ixl_detach(device_t dev)
/* Make sure VLANS are not using driver */
if (vsi->ifp->if_vlantrunk != NULL) {
device_printf(dev,"Vlan in use, detach first\n");
device_printf(dev, "Vlan in use, detach first\n");
return (EBUSY);
}
@ -703,7 +733,7 @@ ixl_detach(device_t dev)
if (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING)
ixl_stop(pf);
ixl_free_taskqueues(pf);
ixl_free_queue_tqs(vsi);
/* Shutdown LAN HMC */
status = i40e_shutdown_lan_hmc(hw);
@ -712,6 +742,9 @@ ixl_detach(device_t dev)
"Shutdown LAN HMC failed with code %d\n", status);
/* Shutdown admin queue */
ixl_disable_adminq(hw);
ixl_free_adminq_tq(pf);
ixl_teardown_adminq_msix(pf);
status = i40e_shutdown_adminq(hw);
if (status)
device_printf(dev,
@ -794,7 +827,7 @@ ixl_get_hw_capabilities(struct ixl_pf *pf)
pf->qbase = hw->func_caps.base_queue;
#ifdef IXL_DEBUG
device_printf(dev,"pf_id=%d, num_vfs=%d, msix_pf=%d, "
device_printf(dev, "pf_id=%d, num_vfs=%d, msix_pf=%d, "
"msix_vf=%d, fd_g=%d, fd_b=%d, tx_qp=%d rx_qp=%d qbase=%d\n",
hw->pf_id, hw->func_caps.num_vfs,
hw->func_caps.num_msix_vectors,
@ -1131,7 +1164,7 @@ ixl_init_locked(struct ixl_pf *pf)
/* Set up MSI/X routing and the ITR settings */
if (ixl_enable_msix) {
ixl_configure_msix(pf);
ixl_configure_queue_intr_msix(pf);
ixl_configure_itr(pf);
} else
ixl_configure_legacy(pf);
@ -1150,6 +1183,9 @@ ixl_init_locked(struct ixl_pf *pf)
i40e_get_link_status(hw, &pf->link_up);
ixl_update_link_status(pf);
/* Set initial advertised speed sysctl value */
ixl_get_initial_advertised_speeds(pf);
/* Start the local timer */
callout_reset(&pf->timer, hz, ixl_local_timer, pf);
@ -1159,6 +1195,37 @@ ixl_init_locked(struct ixl_pf *pf)
return;
}
/* For the set_advertise sysctl */
static void
ixl_get_initial_advertised_speeds(struct ixl_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
device_t dev = pf->dev;
enum i40e_status_code status;
struct i40e_aq_get_phy_abilities_resp abilities;
/* Set initial sysctl values */
status = i40e_aq_get_phy_capabilities(hw, FALSE, false, &abilities,
NULL);
if (status) {
/* Non-fatal error */
device_printf(dev, "%s: i40e_aq_get_phy_capabilities() error %d\n",
__func__, status);
return;
}
if (abilities.link_speed & I40E_LINK_SPEED_40GB)
pf->advertised_speed |= 0x10;
if (abilities.link_speed & I40E_LINK_SPEED_20GB)
pf->advertised_speed |= 0x8;
if (abilities.link_speed & I40E_LINK_SPEED_10GB)
pf->advertised_speed |= 0x4;
if (abilities.link_speed & I40E_LINK_SPEED_1GB)
pf->advertised_speed |= 0x2;
if (abilities.link_speed & I40E_LINK_SPEED_100MB)
pf->advertised_speed |= 0x1;
}
static int
ixl_teardown_hw_structs(struct ixl_pf *pf)
{
@ -1277,7 +1344,8 @@ static void
ixl_init(void *arg)
{
struct ixl_pf *pf = arg;
int ret = 0;
device_t dev = pf->dev;
int error = 0;
/*
* If the aq is dead here, it probably means something outside of the driver
@ -1285,20 +1353,32 @@ ixl_init(void *arg)
* So rebuild the driver's state here if that occurs.
*/
if (!i40e_check_asq_alive(&pf->hw)) {
device_printf(pf->dev, "asq is not alive; rebuilding...\n");
device_printf(dev, "Admin Queue is down; resetting...\n");
IXL_PF_LOCK(pf);
ixl_teardown_hw_structs(pf);
ixl_reset(pf);
IXL_PF_UNLOCK(pf);
}
/* Set up interrupt routing here */
if (pf->msix > 1)
ret = ixl_assign_vsi_msix(pf);
else
ret = ixl_assign_vsi_legacy(pf);
if (ret) {
device_printf(pf->dev, "assign_vsi_msix/legacy error: %d\n", ret);
/*
* Set up LAN queue interrupts here.
* Kernel interrupt setup functions cannot be called while holding a lock,
* so this is done outside of init_locked().
*/
if (pf->msix > 1) {
error = ixl_setup_queue_msix(&pf->vsi);
if (error)
device_printf(dev, "ixl_setup_queue_msix() error: %d\n",
error);
error = ixl_setup_queue_tqs(&pf->vsi);
if (error)
device_printf(dev, "ixl_setup_queue_tqs() error: %d\n",
error);
} else
// possibly broken
error = ixl_assign_vsi_legacy(pf);
if (error) {
device_printf(pf->dev, "assign_vsi_msix/legacy error: %d\n", error);
return;
}
@ -1309,9 +1389,7 @@ ixl_init(void *arg)
}
/*
**
** MSIX Interrupt Handlers and Tasklets
**
*/
static void
ixl_handle_que(void *context, int pending)
@ -2050,7 +2128,7 @@ ixl_stop(struct ixl_pf *pf)
ixl_stop_locked(pf);
IXL_PF_UNLOCK(pf);
ixl_free_interrupt_resources(pf);
ixl_teardown_queue_msix(&pf->vsi);
}
/*********************************************************************
@ -2073,14 +2151,11 @@ ixl_stop_locked(struct ixl_pf *pf)
/* Stop the local timer */
callout_stop(&pf->timer);
if (pf->num_vfs == 0)
ixl_disable_intr(vsi);
else
ixl_disable_rings_intr(vsi);
ixl_disable_rings_intr(vsi);
ixl_disable_rings(vsi);
/* Tell the stack that the interface is no longer active */
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING);
}
@ -2125,10 +2200,6 @@ ixl_assign_vsi_legacy(struct ixl_pf *pf)
device_get_nameunit(dev));
TASK_INIT(&pf->adminq, 0, ixl_do_adminq, pf);
#ifdef PCI_IOV
TASK_INIT(&pf->vflr_task, 0, ixl_handle_vflr, pf);
#endif
pf->tq = taskqueue_create_fast("ixl_adm", M_NOWAIT,
taskqueue_thread_enqueue, &pf->tq);
taskqueue_start_threads(&pf->tq, 1, PI_NET, "%s adminq",
@ -2137,25 +2208,41 @@ ixl_assign_vsi_legacy(struct ixl_pf *pf)
return (0);
}
static void
ixl_init_taskqueues(struct ixl_pf *pf)
static int
ixl_setup_adminq_tq(struct ixl_pf *pf)
{
struct ixl_vsi *vsi = &pf->vsi;
struct ixl_queue *que = vsi->queues;
device_t dev = pf->dev;
int error = 0;
/* Tasklet for Admin Queue */
/* Tasklet for Admin Queue interrupts */
TASK_INIT(&pf->adminq, 0, ixl_do_adminq, pf);
#ifdef PCI_IOV
/* VFLR Tasklet */
TASK_INIT(&pf->vflr_task, 0, ixl_handle_vflr, pf);
#endif
/* Create and start PF taskqueue */
pf->tq = taskqueue_create_fast("ixl_adm", M_NOWAIT,
/* Create and start Admin Queue taskqueue */
pf->tq = taskqueue_create_fast("ixl_aq", M_NOWAIT,
taskqueue_thread_enqueue, &pf->tq);
taskqueue_start_threads(&pf->tq, 1, PI_NET, "%s adminq",
if (!pf->tq) {
device_printf(dev, "taskqueue_create_fast (for AQ) returned NULL!\n");
return (ENOMEM);
}
error = taskqueue_start_threads(&pf->tq, 1, PI_NET, "%s aq",
device_get_nameunit(dev));
if (error) {
device_printf(dev, "taskqueue_start_threads (for AQ) error: %d\n",
error);
taskqueue_free(pf->tq);
return (error);
}
return (0);
}
static int
ixl_setup_queue_tqs(struct ixl_vsi *vsi)
{
struct ixl_queue *que = vsi->queues;
device_t dev = vsi->dev;
/* Create queue tasks and start queue taskqueues */
for (int i = 0; i < vsi->num_queues; i++, que++) {
@ -2174,71 +2261,90 @@ ixl_init_taskqueues(struct ixl_pf *pf)
#endif
}
return (0);
}
static void
ixl_free_taskqueues(struct ixl_pf *pf)
ixl_free_adminq_tq(struct ixl_pf *pf)
{
struct ixl_vsi *vsi = &pf->vsi;
struct ixl_queue *que = vsi->queues;
if (pf->tq)
taskqueue_free(pf->tq);
}
static void
ixl_free_queue_tqs(struct ixl_vsi *vsi)
{
struct ixl_queue *que = vsi->queues;
for (int i = 0; i < vsi->num_queues; i++, que++) {
if (que->tq)
taskqueue_free(que->tq);
}
}
/*********************************************************************
*
* Setup MSIX Interrupt resources and handlers for the VSI
*
**********************************************************************/
static int
ixl_assign_vsi_msix(struct ixl_pf *pf)
ixl_setup_adminq_msix(struct ixl_pf *pf)
{
device_t dev = pf->dev;
struct ixl_vsi *vsi = &pf->vsi;
struct ixl_queue *que = vsi->queues;
struct tx_ring *txr;
int error, rid, vector = 0;
#ifdef RSS
cpuset_t cpu_mask;
#endif
device_t dev = pf->dev;
int rid, error = 0;
/* Admin Queue interrupt vector is 0 */
rid = vector + 1;
/* Admin IRQ rid is 1, vector is 0 */
rid = 1;
/* Get interrupt resource from bus */
pf->res = bus_alloc_resource_any(dev,
SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
if (!pf->res) {
device_printf(dev, "Unable to allocate"
" bus resource: Adminq interrupt [rid=%d]\n", rid);
device_printf(dev, "bus_alloc_resource_any() for Admin Queue"
" interrupt failed [rid=%d]\n", rid);
return (ENXIO);
}
/* Set the adminq vector and handler */
/* Then associate interrupt with handler */
error = bus_setup_intr(dev, pf->res,
INTR_TYPE_NET | INTR_MPSAFE, NULL,
ixl_msix_adminq, pf, &pf->tag);
if (error) {
pf->res = NULL;
device_printf(dev, "Failed to register Admin que handler");
return (error);
device_printf(dev, "bus_setup_intr() for Admin Queue"
" interrupt handler failed, error %d\n", error);
return (ENXIO);
}
bus_describe_intr(dev, pf->res, pf->tag, "aq");
pf->admvec = vector;
++vector;
error = bus_describe_intr(dev, pf->res, pf->tag, "aq");
if (error) {
/* Probably non-fatal? */
device_printf(dev, "bus_describe_intr() for Admin Queue"
" interrupt name failed, error %d\n", error);
}
pf->admvec = 0;
/* Now set up the stations */
return (0);
}
/*
* Allocate interrupt resources from bus and associate an interrupt handler
* to those for the VSI's queues.
*/
static int
ixl_setup_queue_msix(struct ixl_vsi *vsi)
{
device_t dev = vsi->dev;
struct ixl_queue *que = vsi->queues;
struct tx_ring *txr;
int error, rid, vector = 1;
#ifdef RSS
cpuset_t cpu_mask;
#endif
/* Queue interrupt vector numbers start at 1 (adminq intr is 0) */
for (int i = 0; i < vsi->num_queues; i++, vector++, que++) {
int cpu_id = i;
rid = vector + 1;
txr = &que->txr;
que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE);
if (que->res == NULL) {
device_printf(dev, "Unable to allocate"
" bus resource: que interrupt [rid=%d]\n", rid);
if (!que->res) {
device_printf(dev, "bus_alloc_resource_any() for"
" Queue %d interrupt failed [rid=%d]\n",
que->me, rid);
return (ENXIO);
}
/* Set the handler function */
@ -2246,16 +2352,29 @@ ixl_assign_vsi_msix(struct ixl_pf *pf)
INTR_TYPE_NET | INTR_MPSAFE, NULL,
ixl_msix_que, que, &que->tag);
if (error) {
que->res = NULL;
device_printf(dev, "Failed to register que handler");
device_printf(dev, "bus_setup_intr() for Queue %d"
" interrupt handler failed, error %d\n",
que->me, error);
// TODO: Check for error from this?
bus_release_resource(dev, SYS_RES_IRQ, rid, que->res);
return (error);
}
bus_describe_intr(dev, que->res, que->tag, "que%d", i);
error = bus_describe_intr(dev, que->res, que->tag, "que%d", i);
if (error) {
device_printf(dev, "bus_describe_intr() for Queue %d"
" interrupt name failed, error %d\n",
que->me, error);
}
/* Bind the vector to a CPU */
#ifdef RSS
cpu_id = rss_getcpu(i % rss_getnumbuckets());
#endif
bus_bind_intr(dev, que->res, cpu_id);
error = bus_bind_intr(dev, que->res, cpu_id);
if (error) {
device_printf(dev, "bus_bind_intr() for Queue %d"
" to CPU %d failed, error %d\n",
que->me, cpu_id, error);
}
que->msix = vector;
}
@ -2391,15 +2510,13 @@ ixl_init_msix(struct ixl_pf *pf)
}
/*
* Plumb MSIX vectors
* Configure admin queue/misc interrupt cause registers in hardware.
*/
static void
ixl_configure_msix(struct ixl_pf *pf)
ixl_configure_intr0_msix(struct ixl_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
struct ixl_vsi *vsi = &pf->vsi;
u32 reg;
u16 vector = 1;
struct i40e_hw *hw = &pf->hw;
u32 reg;
/* First set up the adminq - vector 0 */
wr32(hw, I40E_PFINT_ICR0_ENA, 0); /* disable all */
@ -2428,8 +2545,19 @@ ixl_configure_msix(struct ixl_pf *pf)
I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK);
wr32(hw, I40E_PFINT_STAT_CTL0, 0);
}
/*
* Configure queue interrupt cause registers in hardware.
*/
static void
ixl_configure_queue_intr_msix(struct ixl_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
struct ixl_vsi *vsi = &pf->vsi;
u32 reg;
u16 vector = 1;
/* Next configure the queues */
for (int i = 0; i < vsi->num_queues; i++, vector++) {
wr32(hw, I40E_PFINT_DYN_CTLN(i), i);
wr32(hw, I40E_PFINT_LNKLSTN(i), i);
@ -2570,21 +2698,49 @@ ixl_allocate_pci_resources(struct ixl_pf *pf)
return (0);
}
static void
ixl_free_interrupt_resources(struct ixl_pf *pf)
/*
* Teardown and release the admin queue/misc vector
* interrupt.
*/
static int
ixl_teardown_adminq_msix(struct ixl_pf *pf)
{
struct ixl_vsi *vsi = &pf->vsi;
struct ixl_queue *que = vsi->queues;
device_t dev = pf->dev;
int rid;
int rid;
if (pf->admvec) /* we are doing MSIX */
rid = pf->admvec + 1;
else
(pf->msix != 0) ? (rid = 1):(rid = 0);
// TODO: Check for errors from bus_teardown_intr
// TODO: Check for errors from bus_release_resource
if (pf->tag != NULL) {
bus_teardown_intr(dev, pf->res, pf->tag);
pf->tag = NULL;
}
if (pf->res != NULL) {
bus_release_resource(dev, SYS_RES_IRQ, rid, pf->res);
pf->res = NULL;
}
return (0);
}
static int
ixl_teardown_queue_msix(struct ixl_vsi *vsi)
{
struct ixl_queue *que = vsi->queues;
device_t dev = vsi->dev;
int rid;
/* We may get here before stations are setup */
if ((!ixl_enable_msix) || (que == NULL))
goto early;
return (0);
/*
** Release all msix VSI resources:
*/
/* Release all MSIX queue resources */
// TODO: Check for errors from bus_teardown_intr
// TODO: Check for errors from bus_release_resource
for (int i = 0; i < vsi->num_queues; i++, que++) {
rid = que->msix + 1;
if (que->tag != NULL) {
@ -2597,21 +2753,7 @@ ixl_free_interrupt_resources(struct ixl_pf *pf)
}
}
early:
/* Clean the AdminQ interrupt last */
if (pf->admvec) /* we are doing MSIX */
rid = pf->admvec + 1;
else
(pf->msix != 0) ? (rid = 1):(rid = 0);
if (pf->tag != NULL) {
bus_teardown_intr(dev, pf->res, pf->tag);
pf->tag = NULL;
}
if (pf->res != NULL) {
bus_release_resource(dev, SYS_RES_IRQ, rid, pf->res);
pf->res = NULL;
}
return (0);
}
static void
@ -2620,7 +2762,8 @@ ixl_free_pci_resources(struct ixl_pf *pf)
device_t dev = pf->dev;
int memrid;
ixl_free_interrupt_resources(pf);
ixl_teardown_queue_msix(&pf->vsi);
ixl_teardown_adminq_msix(pf);
if (pf->msix)
pci_release_msi(dev);
@ -2837,7 +2980,6 @@ ixl_link_event(struct ixl_pf *pf, struct i40e_arq_event_info *e)
struct i40e_aqc_get_link_status *status =
(struct i40e_aqc_get_link_status *)&e->desc.params.raw;
/* Request link status from adapter */
hw->phy.get_link_info = TRUE;
i40e_get_link_status(hw, &pf->link_up);
@ -4498,6 +4640,89 @@ ixl_update_stats_counters(struct ixl_pf *pf)
}
}
static int
ixl_rebuild_hw_structs_after_reset(struct ixl_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
struct ixl_vsi *vsi = &pf->vsi;
device_t dev = pf->dev;
bool is_up = false;
int error = 0;
is_up = !!(vsi->ifp->if_drv_flags & IFF_DRV_RUNNING);
/* Teardown */
if (is_up)
ixl_stop(pf);
error = i40e_shutdown_lan_hmc(hw);
if (error)
device_printf(dev,
"Shutdown LAN HMC failed with code %d\n", error);
ixl_disable_adminq(hw);
ixl_teardown_adminq_msix(pf);
error = i40e_shutdown_adminq(hw);
if (error)
device_printf(dev,
"Shutdown Admin queue failed with code %d\n", error);
/* Setup */
error = i40e_init_adminq(hw);
if (error != 0 && error != I40E_ERR_FIRMWARE_API_VERSION) {
device_printf(dev, "Unable to initialize Admin Queue, error %d\n",
error);
}
error = ixl_setup_adminq_msix(pf);
if (error) {
device_printf(dev, "ixl_setup_adminq_msix error: %d\n",
error);
}
ixl_configure_intr0_msix(pf);
ixl_enable_adminq(hw);
/* setup hmc */
error = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp,
hw->func_caps.num_rx_qp, 0, 0);
if (error) {
device_printf(dev, "init_lan_hmc failed: %d\n", error);
}
error = i40e_configure_lan_hmc(hw, I40E_HMC_MODEL_DIRECT_ONLY);
if (error) {
device_printf(dev, "configure_lan_hmc failed: %d\n", error);
}
if (is_up)
ixl_init(pf);
return (0);
}
static void
ixl_handle_empr_reset(struct ixl_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
device_t dev = pf->dev;
int count = 0;
u32 reg;
/* Typically finishes within 3-4 seconds */
while (count++ < 100) {
reg = rd32(hw, I40E_GLGEN_RSTAT)
& I40E_GLGEN_RSTAT_DEVSTATE_MASK;
if (reg)
i40e_msec_delay(100);
else
break;
}
#ifdef IXL_DEBUG
// Reset-related
device_printf(dev, "EMPR reset wait count: %d\n", count);
#endif
device_printf(dev, "Rebuilding driver state...\n");
ixl_rebuild_hw_structs_after_reset(pf);
device_printf(dev, "Rebuilding driver state done.\n");
atomic_clear_int(&pf->state, IXL_PF_STATE_EMPR_RESETTING);
}
/*
** Tasklet handler for MSIX Adminq interrupts
** - do outside interrupt since it might sleep
@ -4510,34 +4735,16 @@ ixl_do_adminq(void *context, int pending)
struct i40e_arq_event_info event;
i40e_status ret;
device_t dev = pf->dev;
u32 reg, loop = 0;
u32 loop = 0;
u16 opcode, result;
// XXX: Possibly inappropriate overload
if (pf->state & IXL_PF_STATE_EMPR_RESETTING) {
int count = 0;
// ERJ: Typically finishes within 3-4 seconds
while (count++ < 100) {
reg = rd32(hw, I40E_GLGEN_RSTAT);
reg = reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK;
if (reg) {
i40e_msec_delay(100);
} else {
break;
}
}
device_printf(dev, "EMPR reset wait count: %d\n", count);
device_printf(dev, "Rebuilding HW structs...\n");
// XXX: I feel like this could cause a kernel panic some time in the future
ixl_stop(pf);
ixl_init(pf);
atomic_clear_int(&pf->state, IXL_PF_STATE_EMPR_RESETTING);
/* Flag cleared at end of this function */
ixl_handle_empr_reset(pf);
return;
}
// Actually do Admin Queue handling
/* Admin Queue handling */
event.buf_len = IXL_AQ_BUF_SZ;
event.msg_buf = malloc(event.buf_len,
M_DEVBUF, M_NOWAIT | M_ZERO);
@ -4555,7 +4762,8 @@ ixl_do_adminq(void *context, int pending)
break;
opcode = LE16_TO_CPU(event.desc.opcode);
#ifdef IXL_DEBUG
device_printf(dev, "%s: Admin Queue event: %#06x\n", __func__, opcode);
device_printf(dev, "%s: Admin Queue event: %#06x\n", __func__,
opcode);
#endif
switch (opcode) {
case i40e_aqc_opc_get_link_status:
@ -4872,15 +5080,16 @@ ixl_set_flowcntl(SYSCTL_HANDLER_ARGS)
struct ixl_pf *pf = (struct ixl_pf *)arg1;
struct i40e_hw *hw = &pf->hw;
device_t dev = pf->dev;
int error = 0;
int requested_fc, error = 0;
enum i40e_status_code aq_error = 0;
u8 fc_aq_err = 0;
/* Get request */
error = sysctl_handle_int(oidp, &pf->fc, 0, req);
requested_fc = pf->fc;
error = sysctl_handle_int(oidp, &requested_fc, 0, req);
if ((error) || (req->newptr == NULL))
return (error);
if (pf->fc < 0 || pf->fc > 3) {
if (requested_fc < 0 || requested_fc > 3) {
device_printf(dev,
"Invalid fc mode; valid modes are 0 through 3\n");
return (EINVAL);
@ -4898,7 +5107,7 @@ ixl_set_flowcntl(SYSCTL_HANDLER_ARGS)
}
/* Set fc ability for port */
hw->fc.requested_mode = pf->fc;
hw->fc.requested_mode = requested_fc;
aq_error = i40e_set_fc(hw, &fc_aq_err, TRUE);
if (aq_error) {
device_printf(dev,
@ -4906,6 +5115,7 @@ ixl_set_flowcntl(SYSCTL_HANDLER_ARGS)
__func__, aq_error, fc_aq_err);
return (EIO);
}
pf->fc = requested_fc;
/* Get new link state */
i40e_msec_delay(250);
@ -5192,6 +5402,39 @@ ixl_sysctl_show_fw(SYSCTL_HANDLER_ARGS)
return 0;
}
inline void
ixl_print_nvm_cmd(device_t dev, struct i40e_nvm_access *nvma)
{
if ((nvma->command == I40E_NVM_READ) &&
((nvma->config & 0xFF) == 0xF) &&
(((nvma->config & 0xF00) >> 8) == 0xF) &&
(nvma->offset == 0) &&
(nvma->data_size == 1)) {
// device_printf(dev, "- Get Driver Status Command\n");
}
else if (nvma->command == I40E_NVM_READ) {
}
else {
switch (nvma->command) {
case 0xB:
device_printf(dev, "- command: I40E_NVM_READ\n");
break;
case 0xC:
device_printf(dev, "- command: I40E_NVM_WRITE\n");
break;
default:
device_printf(dev, "- command: unknown 0x%08x\n", nvma->command);
break;
}
device_printf(dev, "- config (ptr) : 0x%02x\n", nvma->config & 0xFF);
device_printf(dev, "- config (flags): 0x%01x\n", (nvma->config & 0xF00) >> 8);
device_printf(dev, "- offset : 0x%08x\n", nvma->offset);
device_printf(dev, "- data_s : 0x%08x\n", nvma->data_size);
}
}
static int
ixl_handle_nvmupd_cmd(struct ixl_pf *pf, struct ifdrv *ifd)
{
@ -5203,17 +5446,24 @@ ixl_handle_nvmupd_cmd(struct ixl_pf *pf, struct ifdrv *ifd)
DEBUGFUNC("ixl_handle_nvmupd_cmd");
/* Sanity checks */
if (ifd->ifd_len < sizeof(struct i40e_nvm_access) ||
ifd->ifd_data == NULL) {
device_printf(dev, "%s: incorrect ifdrv length or data pointer\n", __func__);
device_printf(dev, "%s: ifdrv length: %lu, sizeof(struct i40e_nvm_access): %lu\n", __func__,
ifd->ifd_len, sizeof(struct i40e_nvm_access));
device_printf(dev, "%s: data pointer: %p\n", __func__, ifd->ifd_data);
device_printf(dev, "%s: incorrect ifdrv length or data pointer\n",
__func__);
device_printf(dev, "%s: ifdrv length: %lu, sizeof(struct i40e_nvm_access): %lu\n",
__func__, ifd->ifd_len, sizeof(struct i40e_nvm_access));
device_printf(dev, "%s: data pointer: %p\n", __func__,
ifd->ifd_data);
return (EINVAL);
}
nvma = (struct i40e_nvm_access *)ifd->ifd_data;
#ifdef IXL_DEBUG
ixl_print_nvm_cmd(dev, nvma);
#endif
if (pf->state & IXL_PF_STATE_EMPR_RESETTING) {
int count = 0;
while (count++ < 100) {
@ -5221,7 +5471,6 @@ ixl_handle_nvmupd_cmd(struct ixl_pf *pf, struct ifdrv *ifd)
if (!(pf->state & IXL_PF_STATE_EMPR_RESETTING))
break;
}
// device_printf(dev, "ioctl EMPR reset wait count %d\n", count);
}
if (!(pf->state & IXL_PF_STATE_EMPR_RESETTING)) {
@ -7008,7 +7257,7 @@ ixl_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *params)
goto fail;
}
ixl_configure_msix(pf);
// TODO: [Configure MSI-X here]
ixl_enable_adminq(hw);
pf->num_vfs = num_vfs;

View File

@ -162,8 +162,10 @@
/*
* Ring Descriptors Valid Range: 32-4096 Default Value: 1024 This value is the
* number of tx/rx descriptors allocated by the driver. Increasing this
* value allows the driver to queue more operations. Each descriptor is 16
* or 32 bytes (configurable in FVL)
* value allows the driver to queue more operations.
*
* Tx descriptors are always 16 bytes, but Rx descriptors can be 32 bytes.
* The driver currently always uses 32 byte Rx descriptors.
*/
#define DEFAULT_RING 1024
#define PERFORM_RING 2048
@ -215,7 +217,7 @@
#define IXL_TX_ITR 1
#define IXL_ITR_NONE 3
#define IXL_QUEUE_EOL 0x7FF
#define IXL_MAX_FRAME 0x2600
#define IXL_MAX_FRAME 9728
#define IXL_MAX_TX_SEGS 8
#define IXL_MAX_TSO_SEGS 66
#define IXL_SPARSE_CHAIN 6