Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/ixgbe/ixgbe_common.c
/****************************************************************************** | /****************************************************************************** | ||||
Copyright (c) 2001-2013, Intel Corporation | Copyright (c) 2001-2014, 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 | ||||
Context not available. | |||||
DEBUGFUNC("ixgbe_init_ops_generic"); | DEBUGFUNC("ixgbe_init_ops_generic"); | ||||
/* EEPROM */ | /* EEPROM */ | ||||
eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic; | eeprom->ops.init_params = ixgbe_init_eeprom_params_generic; | ||||
/* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ | /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ | ||||
if (eec & IXGBE_EEC_PRES) { | if (eec & IXGBE_EEC_PRES) { | ||||
eeprom->ops.read = &ixgbe_read_eerd_generic; | eeprom->ops.read = ixgbe_read_eerd_generic; | ||||
eeprom->ops.read_buffer = &ixgbe_read_eerd_buffer_generic; | eeprom->ops.read_buffer = ixgbe_read_eerd_buffer_generic; | ||||
} else { | } else { | ||||
eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic; | eeprom->ops.read = ixgbe_read_eeprom_bit_bang_generic; | ||||
eeprom->ops.read_buffer = | eeprom->ops.read_buffer = | ||||
&ixgbe_read_eeprom_buffer_bit_bang_generic; | ixgbe_read_eeprom_buffer_bit_bang_generic; | ||||
} | } | ||||
eeprom->ops.write = &ixgbe_write_eeprom_generic; | eeprom->ops.write = ixgbe_write_eeprom_generic; | ||||
eeprom->ops.write_buffer = &ixgbe_write_eeprom_buffer_bit_bang_generic; | eeprom->ops.write_buffer = ixgbe_write_eeprom_buffer_bit_bang_generic; | ||||
eeprom->ops.validate_checksum = | eeprom->ops.validate_checksum = | ||||
&ixgbe_validate_eeprom_checksum_generic; | ixgbe_validate_eeprom_checksum_generic; | ||||
eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_generic; | eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_generic; | ||||
eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_generic; | eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_generic; | ||||
/* MAC */ | /* MAC */ | ||||
mac->ops.init_hw = &ixgbe_init_hw_generic; | mac->ops.init_hw = ixgbe_init_hw_generic; | ||||
mac->ops.reset_hw = NULL; | mac->ops.reset_hw = NULL; | ||||
mac->ops.start_hw = &ixgbe_start_hw_generic; | mac->ops.start_hw = ixgbe_start_hw_generic; | ||||
mac->ops.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic; | mac->ops.clear_hw_cntrs = ixgbe_clear_hw_cntrs_generic; | ||||
mac->ops.get_media_type = NULL; | mac->ops.get_media_type = NULL; | ||||
mac->ops.get_supported_physical_layer = NULL; | mac->ops.get_supported_physical_layer = NULL; | ||||
mac->ops.enable_rx_dma = &ixgbe_enable_rx_dma_generic; | mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_generic; | ||||
mac->ops.get_mac_addr = &ixgbe_get_mac_addr_generic; | mac->ops.get_mac_addr = ixgbe_get_mac_addr_generic; | ||||
mac->ops.stop_adapter = &ixgbe_stop_adapter_generic; | mac->ops.stop_adapter = ixgbe_stop_adapter_generic; | ||||
mac->ops.get_bus_info = &ixgbe_get_bus_info_generic; | mac->ops.get_bus_info = ixgbe_get_bus_info_generic; | ||||
mac->ops.set_lan_id = &ixgbe_set_lan_id_multi_port_pcie; | mac->ops.set_lan_id = ixgbe_set_lan_id_multi_port_pcie; | ||||
mac->ops.acquire_swfw_sync = &ixgbe_acquire_swfw_sync; | mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync; | ||||
mac->ops.release_swfw_sync = &ixgbe_release_swfw_sync; | mac->ops.release_swfw_sync = ixgbe_release_swfw_sync; | ||||
mac->ops.prot_autoc_read = prot_autoc_read_generic; | |||||
mac->ops.prot_autoc_write = prot_autoc_write_generic; | |||||
/* LEDs */ | /* LEDs */ | ||||
mac->ops.led_on = &ixgbe_led_on_generic; | mac->ops.led_on = ixgbe_led_on_generic; | ||||
mac->ops.led_off = &ixgbe_led_off_generic; | mac->ops.led_off = ixgbe_led_off_generic; | ||||
mac->ops.blink_led_start = &ixgbe_blink_led_start_generic; | mac->ops.blink_led_start = ixgbe_blink_led_start_generic; | ||||
mac->ops.blink_led_stop = &ixgbe_blink_led_stop_generic; | mac->ops.blink_led_stop = ixgbe_blink_led_stop_generic; | ||||
/* RAR, Multicast, VLAN */ | /* RAR, Multicast, VLAN */ | ||||
mac->ops.set_rar = &ixgbe_set_rar_generic; | mac->ops.set_rar = ixgbe_set_rar_generic; | ||||
mac->ops.clear_rar = &ixgbe_clear_rar_generic; | mac->ops.clear_rar = ixgbe_clear_rar_generic; | ||||
mac->ops.insert_mac_addr = NULL; | mac->ops.insert_mac_addr = NULL; | ||||
mac->ops.set_vmdq = NULL; | mac->ops.set_vmdq = NULL; | ||||
mac->ops.clear_vmdq = NULL; | mac->ops.clear_vmdq = NULL; | ||||
mac->ops.init_rx_addrs = &ixgbe_init_rx_addrs_generic; | mac->ops.init_rx_addrs = ixgbe_init_rx_addrs_generic; | ||||
mac->ops.update_uc_addr_list = &ixgbe_update_uc_addr_list_generic; | mac->ops.update_uc_addr_list = ixgbe_update_uc_addr_list_generic; | ||||
mac->ops.update_mc_addr_list = &ixgbe_update_mc_addr_list_generic; | mac->ops.update_mc_addr_list = ixgbe_update_mc_addr_list_generic; | ||||
mac->ops.enable_mc = &ixgbe_enable_mc_generic; | mac->ops.enable_mc = ixgbe_enable_mc_generic; | ||||
mac->ops.disable_mc = &ixgbe_disable_mc_generic; | mac->ops.disable_mc = ixgbe_disable_mc_generic; | ||||
mac->ops.clear_vfta = NULL; | mac->ops.clear_vfta = NULL; | ||||
mac->ops.set_vfta = NULL; | mac->ops.set_vfta = NULL; | ||||
mac->ops.set_vlvf = NULL; | mac->ops.set_vlvf = NULL; | ||||
mac->ops.init_uta_tables = NULL; | mac->ops.init_uta_tables = NULL; | ||||
mac->ops.enable_rx = ixgbe_enable_rx_generic; | |||||
mac->ops.disable_rx = ixgbe_disable_rx_generic; | |||||
/* Flow Control */ | /* Flow Control */ | ||||
mac->ops.fc_enable = &ixgbe_fc_enable_generic; | mac->ops.fc_enable = ixgbe_fc_enable_generic; | ||||
mac->ops.setup_fc = ixgbe_setup_fc_generic; | |||||
/* Link */ | /* Link */ | ||||
mac->ops.get_link_capabilities = NULL; | mac->ops.get_link_capabilities = NULL; | ||||
Context not available. | |||||
switch (hw->phy.media_type) { | switch (hw->phy.media_type) { | ||||
case ixgbe_media_type_fiber_fixed: | case ixgbe_media_type_fiber_fixed: | ||||
case ixgbe_media_type_fiber_qsfp: | |||||
case ixgbe_media_type_fiber: | case ixgbe_media_type_fiber: | ||||
hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); | hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); | ||||
/* if link is down, assume supported */ | /* if link is down, assume supported */ | ||||
Context not available. | |||||
switch (hw->device_id) { | switch (hw->device_id) { | ||||
case IXGBE_DEV_ID_82599_T3_LOM: | case IXGBE_DEV_ID_82599_T3_LOM: | ||||
case IXGBE_DEV_ID_X540T: | case IXGBE_DEV_ID_X540T: | ||||
case IXGBE_DEV_ID_X540T1: | |||||
case IXGBE_DEV_ID_X540_BYPASS: | case IXGBE_DEV_ID_X540_BYPASS: | ||||
case IXGBE_DEV_ID_X550T: | |||||
supported = TRUE; | supported = TRUE; | ||||
break; | break; | ||||
default: | default: | ||||
Context not available. | |||||
} | } | ||||
/** | /** | ||||
* ixgbe_setup_fc - Set up flow control | * ixgbe_setup_fc_generic - Set up flow control | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* | * | ||||
* Called at init time to set up flow control. | * Called at init time to set up flow control. | ||||
**/ | **/ | ||||
static s32 ixgbe_setup_fc(struct ixgbe_hw *hw) | s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw) | ||||
{ | { | ||||
s32 ret_val = IXGBE_SUCCESS; | s32 ret_val = IXGBE_SUCCESS; | ||||
u32 reg = 0, reg_bp = 0; | u32 reg = 0, reg_bp = 0; | ||||
u16 reg_cu = 0; | u16 reg_cu = 0; | ||||
bool got_lock = FALSE; | bool locked = FALSE; | ||||
DEBUGFUNC("ixgbe_setup_fc"); | DEBUGFUNC("ixgbe_setup_fc_generic"); | ||||
/* | /* Validate the requested mode */ | ||||
* Validate the requested mode. Strict IEEE mode does not allow | |||||
* ixgbe_fc_rx_pause because it will cause us to fail at UNH. | |||||
*/ | |||||
if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { | if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { | ||||
ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, | ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, | ||||
"ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); | "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); | ||||
Context not available. | |||||
* we link at 10G, the 1G advertisement is harmless and vice versa. | * we link at 10G, the 1G advertisement is harmless and vice versa. | ||||
*/ | */ | ||||
switch (hw->phy.media_type) { | switch (hw->phy.media_type) { | ||||
case ixgbe_media_type_backplane: | |||||
/* some MAC's need RMW protection on AUTOC */ | |||||
ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, ®_bp); | |||||
if (ret_val != IXGBE_SUCCESS) | |||||
goto out; | |||||
/* only backplane uses autoc so fall though */ | |||||
case ixgbe_media_type_fiber_fixed: | case ixgbe_media_type_fiber_fixed: | ||||
case ixgbe_media_type_fiber_qsfp: | |||||
case ixgbe_media_type_fiber: | case ixgbe_media_type_fiber: | ||||
case ixgbe_media_type_backplane: | |||||
reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); | reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); | ||||
reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC); | |||||
break; | break; | ||||
case ixgbe_media_type_copper: | case ixgbe_media_type_copper: | ||||
hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, | hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, | ||||
Context not available. | |||||
break; | break; | ||||
} | } | ||||
if (hw->mac.type != ixgbe_mac_X540) { | if (hw->mac.type < ixgbe_mac_X540) { | ||||
/* | /* | ||||
* Enable auto-negotiation between the MAC & PHY; | * Enable auto-negotiation between the MAC & PHY; | ||||
* the MAC will advertise clause 37 flow control. | * the MAC will advertise clause 37 flow control. | ||||
Context not available. | |||||
*/ | */ | ||||
if (hw->phy.media_type == ixgbe_media_type_backplane) { | if (hw->phy.media_type == ixgbe_media_type_backplane) { | ||||
reg_bp |= IXGBE_AUTOC_AN_RESTART; | reg_bp |= IXGBE_AUTOC_AN_RESTART; | ||||
/* Need the SW/FW semaphore around AUTOC writes if 82599 and | ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked); | ||||
* LESM is on, likewise reset_pipeline requries the lock as | if (ret_val) | ||||
* it also writes AUTOC. | goto out; | ||||
*/ | |||||
if ((hw->mac.type == ixgbe_mac_82599EB) && | |||||
ixgbe_verify_lesm_fw_enabled_82599(hw)) { | |||||
ret_val = hw->mac.ops.acquire_swfw_sync(hw, | |||||
IXGBE_GSSR_MAC_CSR_SM); | |||||
if (ret_val != IXGBE_SUCCESS) { | |||||
ret_val = IXGBE_ERR_SWFW_SYNC; | |||||
goto out; | |||||
} | |||||
got_lock = TRUE; | |||||
} | |||||
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp); | |||||
if (hw->mac.type == ixgbe_mac_82599EB) | |||||
ixgbe_reset_pipeline_82599(hw); | |||||
if (got_lock) | |||||
hw->mac.ops.release_swfw_sync(hw, | |||||
IXGBE_GSSR_MAC_CSR_SM); | |||||
} else if ((hw->phy.media_type == ixgbe_media_type_copper) && | } else if ((hw->phy.media_type == ixgbe_media_type_copper) && | ||||
(ixgbe_device_supports_autoneg_fc(hw))) { | (ixgbe_device_supports_autoneg_fc(hw))) { | ||||
hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, | hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, | ||||
Context not available. | |||||
IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu); | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu); | ||||
} | } | ||||
DEBUGOUT1("Set up FC; IXGBE_AUTOC = 0x%08X\n", reg); | DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); | ||||
out: | out: | ||||
return ret_val; | return ret_val; | ||||
} | } | ||||
Context not available. | |||||
} | } | ||||
} | } | ||||
if (hw->mac.type == ixgbe_mac_X540) { | if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) { | ||||
if (hw->phy.id == 0) | if (hw->phy.id == 0) | ||||
ixgbe_identify_phy(hw); | ixgbe_identify_phy(hw); | ||||
hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, | hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, | ||||
Context not available. | |||||
return ret_val; | return ret_val; | ||||
} else { | } else { | ||||
if (eeprom_buf_size > (u32)(pba->word[1] + | if (eeprom_buf_size > (u32)(pba->word[1] + | ||||
pba->pba_block[0])) { | pba_block_size)) { | ||||
memcpy(pba->pba_block, | memcpy(pba->pba_block, | ||||
&eeprom_buf[pba->word[1]], | &eeprom_buf[pba->word[1]], | ||||
pba_block_size * sizeof(u16)); | pba_block_size * sizeof(u16)); | ||||
Context not available. | |||||
{ | { | ||||
struct ixgbe_mac_info *mac = &hw->mac; | struct ixgbe_mac_info *mac = &hw->mac; | ||||
hw->bus.type = ixgbe_bus_type_pci_express; | if (hw->bus.type == ixgbe_bus_type_unknown) | ||||
hw->bus.type = ixgbe_bus_type_pci_express; | |||||
switch (link_status & IXGBE_PCI_LINK_WIDTH) { | switch (link_status & IXGBE_PCI_LINK_WIDTH) { | ||||
case IXGBE_PCI_LINK_WIDTH_1: | case IXGBE_PCI_LINK_WIDTH_1: | ||||
Context not available. | |||||
hw->adapter_stopped = TRUE; | hw->adapter_stopped = TRUE; | ||||
/* Disable the receive unit */ | /* Disable the receive unit */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, 0); | ixgbe_disable_rx(hw); | ||||
/* Clear interrupt mask to stop interrupts from being generated */ | /* Clear interrupt mask to stop interrupts from being generated */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); | IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); | ||||
Context not available. | |||||
/** | /** | ||||
* ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum | * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* | |||||
* Returns a negative error code on error, or the 16-bit checksum | |||||
**/ | **/ | ||||
u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) | s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) | ||||
{ | { | ||||
u16 i; | u16 i; | ||||
u16 j; | u16 j; | ||||
Context not available. | |||||
/* Include 0x0-0x3F in the checksum */ | /* Include 0x0-0x3F in the checksum */ | ||||
for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { | for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { | ||||
if (hw->eeprom.ops.read(hw, i, &word) != IXGBE_SUCCESS) { | if (hw->eeprom.ops.read(hw, i, &word)) { | ||||
DEBUGOUT("EEPROM read failed\n"); | DEBUGOUT("EEPROM read failed\n"); | ||||
break; | return IXGBE_ERR_EEPROM; | ||||
} | } | ||||
checksum += word; | checksum += word; | ||||
} | } | ||||
Context not available. | |||||
/* Include all data from pointers except for the fw pointer */ | /* Include all data from pointers except for the fw pointer */ | ||||
for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { | for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { | ||||
hw->eeprom.ops.read(hw, i, &pointer); | if (hw->eeprom.ops.read(hw, i, &pointer)) { | ||||
DEBUGOUT("EEPROM read failed\n"); | |||||
return IXGBE_ERR_EEPROM; | |||||
} | |||||
/* Make sure the pointer seems valid */ | /* If the pointer seems invalid */ | ||||
if (pointer != 0xFFFF && pointer != 0) { | if (pointer == 0xFFFF || pointer == 0) | ||||
hw->eeprom.ops.read(hw, pointer, &length); | continue; | ||||
if (length != 0xFFFF && length != 0) { | if (hw->eeprom.ops.read(hw, pointer, &length)) { | ||||
for (j = pointer+1; j <= pointer+length; j++) { | DEBUGOUT("EEPROM read failed\n"); | ||||
hw->eeprom.ops.read(hw, j, &word); | return IXGBE_ERR_EEPROM; | ||||
checksum += word; | } | ||||
} | |||||
if (length == 0xFFFF || length == 0) | |||||
continue; | |||||
for (j = pointer + 1; j <= pointer + length; j++) { | |||||
if (hw->eeprom.ops.read(hw, j, &word)) { | |||||
DEBUGOUT("EEPROM read failed\n"); | |||||
return IXGBE_ERR_EEPROM; | |||||
} | } | ||||
checksum += word; | |||||
} | } | ||||
} | } | ||||
checksum = (u16)IXGBE_EEPROM_SUM - checksum; | checksum = (u16)IXGBE_EEPROM_SUM - checksum; | ||||
return checksum; | return (s32)checksum; | ||||
} | } | ||||
/** | /** | ||||
Context not available. | |||||
DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic"); | DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic"); | ||||
/* | /* Read the first word from the EEPROM. If this times out or fails, do | ||||
* Read the first word from the EEPROM. If this times out or fails, do | |||||
* not continue or we could be in for a very long wait while every | * not continue or we could be in for a very long wait while every | ||||
* EEPROM read fails | * EEPROM read fails | ||||
*/ | */ | ||||
status = hw->eeprom.ops.read(hw, 0, &checksum); | status = hw->eeprom.ops.read(hw, 0, &checksum); | ||||
if (status) { | |||||
DEBUGOUT("EEPROM read failed\n"); | |||||
return status; | |||||
} | |||||
if (status == IXGBE_SUCCESS) { | status = hw->eeprom.ops.calc_checksum(hw); | ||||
checksum = hw->eeprom.ops.calc_checksum(hw); | if (status < 0) | ||||
return status; | |||||
hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); | checksum = (u16)(status & 0xffff); | ||||
/* | status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); | ||||
* Verify read checksum from EEPROM is the same as | if (status) { | ||||
* calculated checksum | |||||
*/ | |||||
if (read_checksum != checksum) | |||||
status = IXGBE_ERR_EEPROM_CHECKSUM; | |||||
/* If the user cares, return the calculated checksum */ | |||||
if (checksum_val) | |||||
*checksum_val = checksum; | |||||
} else { | |||||
DEBUGOUT("EEPROM read failed\n"); | DEBUGOUT("EEPROM read failed\n"); | ||||
return status; | |||||
} | } | ||||
/* Verify read checksum from EEPROM is the same as | |||||
* calculated checksum | |||||
*/ | |||||
if (read_checksum != checksum) | |||||
status = IXGBE_ERR_EEPROM_CHECKSUM; | |||||
/* If the user cares, return the calculated checksum */ | |||||
if (checksum_val) | |||||
*checksum_val = checksum; | |||||
return status; | return status; | ||||
} | } | ||||
Context not available. | |||||
DEBUGFUNC("ixgbe_update_eeprom_checksum_generic"); | DEBUGFUNC("ixgbe_update_eeprom_checksum_generic"); | ||||
/* | /* Read the first word from the EEPROM. If this times out or fails, do | ||||
* Read the first word from the EEPROM. If this times out or fails, do | |||||
* not continue or we could be in for a very long wait while every | * not continue or we could be in for a very long wait while every | ||||
* EEPROM read fails | * EEPROM read fails | ||||
*/ | */ | ||||
status = hw->eeprom.ops.read(hw, 0, &checksum); | status = hw->eeprom.ops.read(hw, 0, &checksum); | ||||
if (status) { | |||||
if (status == IXGBE_SUCCESS) { | |||||
checksum = hw->eeprom.ops.calc_checksum(hw); | |||||
status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, | |||||
checksum); | |||||
} else { | |||||
DEBUGOUT("EEPROM read failed\n"); | DEBUGOUT("EEPROM read failed\n"); | ||||
return status; | |||||
} | } | ||||
status = hw->eeprom.ops.calc_checksum(hw); | |||||
if (status < 0) | |||||
return status; | |||||
checksum = (u16)(status & 0xffff); | |||||
status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum); | |||||
return status; | return status; | ||||
} | } | ||||
Context not available. | |||||
/* | /* | ||||
* In order to prevent Tx hangs when the internal Tx | * In order to prevent Tx hangs when the internal Tx | ||||
* switch is enabled we must set the high water mark | * switch is enabled we must set the high water mark | ||||
* to the maximum FCRTH value. This allows the Tx | * to the Rx packet buffer size - 24KB. This allows | ||||
* switch to function even under heavy Rx workloads. | * the Tx switch to function even under heavy Rx | ||||
* workloads. | |||||
*/ | */ | ||||
fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32; | fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576; | ||||
} | } | ||||
IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth); | IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth); | ||||
Context not available. | |||||
linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); | linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); | ||||
if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || | if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || | ||||
(!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { | (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { | ||||
ERROR_REPORT1(IXGBE_ERROR_POLLING, | DEBUGOUT("Auto-Negotiation did not complete or timed out\n"); | ||||
"Auto-Negotiation did not complete or timed out"); | |||||
goto out; | goto out; | ||||
} | } | ||||
Context not available. | |||||
*/ | */ | ||||
links = IXGBE_READ_REG(hw, IXGBE_LINKS); | links = IXGBE_READ_REG(hw, IXGBE_LINKS); | ||||
if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) { | if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) { | ||||
ERROR_REPORT1(IXGBE_ERROR_POLLING, | DEBUGOUT("Auto-Negotiation did not complete\n"); | ||||
"Auto-Negotiation did not complete"); | |||||
goto out; | goto out; | ||||
} | } | ||||
Context not available. | |||||
if (hw->mac.type == ixgbe_mac_82599EB) { | if (hw->mac.type == ixgbe_mac_82599EB) { | ||||
links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2); | links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2); | ||||
if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) { | if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) { | ||||
ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, | DEBUGOUT("Link partner is not AN enabled\n"); | ||||
"Link partner is not AN enabled"); | |||||
goto out; | goto out; | ||||
} | } | ||||
} | } | ||||
Context not available. | |||||
switch (hw->phy.media_type) { | switch (hw->phy.media_type) { | ||||
/* Autoneg flow control on fiber adapters */ | /* Autoneg flow control on fiber adapters */ | ||||
case ixgbe_media_type_fiber_fixed: | case ixgbe_media_type_fiber_fixed: | ||||
case ixgbe_media_type_fiber_qsfp: | |||||
case ixgbe_media_type_fiber: | case ixgbe_media_type_fiber: | ||||
if (speed == IXGBE_LINK_SPEED_1GB_FULL) | if (speed == IXGBE_LINK_SPEED_1GB_FULL) | ||||
ret_val = ixgbe_fc_autoneg_fiber(hw); | ret_val = ixgbe_fc_autoneg_fiber(hw); | ||||
Context not available. | |||||
{ | { | ||||
s32 status = IXGBE_SUCCESS; | s32 status = IXGBE_SUCCESS; | ||||
u32 i, poll; | u32 i, poll; | ||||
u16 value; | |||||
DEBUGFUNC("ixgbe_disable_pcie_master"); | DEBUGFUNC("ixgbe_disable_pcie_master"); | ||||
Context not available. | |||||
IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS); | IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS); | ||||
/* Exit if master requests are blocked */ | /* Exit if master requests are blocked */ | ||||
if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) | if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) || | ||||
IXGBE_REMOVED(hw->hw_addr)) | |||||
goto out; | goto out; | ||||
/* Poll for master request bit to clear */ | /* Poll for master request bit to clear */ | ||||
Context not available. | |||||
poll = ixgbe_pcie_timeout_poll(hw); | poll = ixgbe_pcie_timeout_poll(hw); | ||||
for (i = 0; i < poll; i++) { | for (i = 0; i < poll; i++) { | ||||
usec_delay(100); | usec_delay(100); | ||||
if (!(IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS) & | value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); | ||||
IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) | if (IXGBE_REMOVED(hw->hw_addr)) | ||||
goto out; | goto out; | ||||
if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) | |||||
goto out; | |||||
} | } | ||||
ERROR_REPORT1(IXGBE_ERROR_POLLING, | ERROR_REPORT1(IXGBE_ERROR_POLLING, | ||||
Context not available. | |||||
* Acquires the SWFW semaphore through the GSSR register for the specified | * Acquires the SWFW semaphore through the GSSR register for the specified | ||||
* function (CSR, PHY0, PHY1, EEPROM, Flash) | * function (CSR, PHY0, PHY1, EEPROM, Flash) | ||||
**/ | **/ | ||||
s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) | s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask) | ||||
{ | { | ||||
u32 gssr = 0; | u32 gssr = 0; | ||||
u32 swmask = mask; | u32 swmask = mask; | ||||
Context not available. | |||||
* Releases the SWFW semaphore through the GSSR register for the specified | * Releases the SWFW semaphore through the GSSR register for the specified | ||||
* function (CSR, PHY0, PHY1, EEPROM, Flash) | * function (CSR, PHY0, PHY1, EEPROM, Flash) | ||||
**/ | **/ | ||||
void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask) | void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask) | ||||
{ | { | ||||
u32 gssr; | u32 gssr; | ||||
u32 swmask = mask; | u32 swmask = mask; | ||||
Context not available. | |||||
} | } | ||||
/** | /** | ||||
* prot_autoc_read_generic - Hides MAC differences needed for AUTOC read | |||||
* @hw: pointer to hardware structure | |||||
* @reg_val: Value we read from AUTOC | |||||
* | |||||
* The default case requires no protection so just to the register read. | |||||
*/ | |||||
s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val) | |||||
{ | |||||
*locked = FALSE; | |||||
*reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC); | |||||
return IXGBE_SUCCESS; | |||||
} | |||||
/** | |||||
* prot_autoc_write_generic - Hides MAC differences needed for AUTOC write | |||||
* @hw: pointer to hardware structure | |||||
* @reg_val: value to write to AUTOC | |||||
* @locked: bool to indicate whether the SW/FW lock was already taken by | |||||
* previous read. | |||||
* | |||||
* The default case requires no protection so just to the register write. | |||||
*/ | |||||
s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked) | |||||
{ | |||||
UNREFERENCED_1PARAMETER(locked); | |||||
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val); | |||||
return IXGBE_SUCCESS; | |||||
} | |||||
/** | |||||
* ixgbe_enable_sec_rx_path_generic - Enables the receive data path | * ixgbe_enable_sec_rx_path_generic - Enables the receive data path | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* | * | ||||
Context not available. | |||||
{ | { | ||||
DEBUGFUNC("ixgbe_enable_rx_dma_generic"); | DEBUGFUNC("ixgbe_enable_rx_dma_generic"); | ||||
IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval); | if (regval & IXGBE_RXCTRL_RXEN) | ||||
ixgbe_enable_rx(hw); | |||||
else | |||||
ixgbe_disable_rx(hw); | |||||
return IXGBE_SUCCESS; | return IXGBE_SUCCESS; | ||||
} | } | ||||
Context not available. | |||||
{ | { | ||||
ixgbe_link_speed speed = 0; | ixgbe_link_speed speed = 0; | ||||
bool link_up = 0; | bool link_up = 0; | ||||
u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); | u32 autoc_reg = 0; | ||||
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); | u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); | ||||
s32 ret_val = IXGBE_SUCCESS; | s32 ret_val = IXGBE_SUCCESS; | ||||
bool locked = FALSE; | |||||
DEBUGFUNC("ixgbe_blink_led_start_generic"); | DEBUGFUNC("ixgbe_blink_led_start_generic"); | ||||
Context not available. | |||||
hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); | hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); | ||||
if (!link_up) { | if (!link_up) { | ||||
/* Need the SW/FW semaphore around AUTOC writes if 82599 and | ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); | ||||
* LESM is on. | if (ret_val != IXGBE_SUCCESS) | ||||
*/ | goto out; | ||||
bool got_lock = FALSE; | |||||
if ((hw->mac.type == ixgbe_mac_82599EB) && | |||||
ixgbe_verify_lesm_fw_enabled_82599(hw)) { | |||||
ret_val = hw->mac.ops.acquire_swfw_sync(hw, | |||||
IXGBE_GSSR_MAC_CSR_SM); | |||||
if (ret_val != IXGBE_SUCCESS) { | |||||
ret_val = IXGBE_ERR_SWFW_SYNC; | |||||
goto out; | |||||
} | |||||
got_lock = TRUE; | |||||
} | |||||
autoc_reg |= IXGBE_AUTOC_AN_RESTART; | autoc_reg |= IXGBE_AUTOC_AN_RESTART; | ||||
autoc_reg |= IXGBE_AUTOC_FLU; | autoc_reg |= IXGBE_AUTOC_FLU; | ||||
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); | |||||
ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); | |||||
if (ret_val != IXGBE_SUCCESS) | |||||
goto out; | |||||
IXGBE_WRITE_FLUSH(hw); | IXGBE_WRITE_FLUSH(hw); | ||||
if (got_lock) | |||||
hw->mac.ops.release_swfw_sync(hw, | |||||
IXGBE_GSSR_MAC_CSR_SM); | |||||
msec_delay(10); | msec_delay(10); | ||||
} | } | ||||
Context not available. | |||||
**/ | **/ | ||||
s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) | s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) | ||||
{ | { | ||||
u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); | u32 autoc_reg = 0; | ||||
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); | u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); | ||||
s32 ret_val = IXGBE_SUCCESS; | s32 ret_val = IXGBE_SUCCESS; | ||||
bool got_lock = FALSE; | bool locked = FALSE; | ||||
DEBUGFUNC("ixgbe_blink_led_stop_generic"); | DEBUGFUNC("ixgbe_blink_led_stop_generic"); | ||||
/* Need the SW/FW semaphore around AUTOC writes if 82599 and | |||||
* LESM is on. | |||||
*/ | |||||
if ((hw->mac.type == ixgbe_mac_82599EB) && | |||||
ixgbe_verify_lesm_fw_enabled_82599(hw)) { | |||||
ret_val = hw->mac.ops.acquire_swfw_sync(hw, | |||||
IXGBE_GSSR_MAC_CSR_SM); | |||||
if (ret_val != IXGBE_SUCCESS) { | |||||
ret_val = IXGBE_ERR_SWFW_SYNC; | |||||
goto out; | |||||
} | |||||
got_lock = TRUE; | |||||
} | |||||
ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); | |||||
if (ret_val != IXGBE_SUCCESS) | |||||
goto out; | |||||
autoc_reg &= ~IXGBE_AUTOC_FLU; | autoc_reg &= ~IXGBE_AUTOC_FLU; | ||||
autoc_reg |= IXGBE_AUTOC_AN_RESTART; | autoc_reg |= IXGBE_AUTOC_AN_RESTART; | ||||
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); | |||||
if (hw->mac.type == ixgbe_mac_82599EB) | ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); | ||||
ixgbe_reset_pipeline_82599(hw); | if (ret_val != IXGBE_SUCCESS) | ||||
goto out; | |||||
if (got_lock) | |||||
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); | |||||
led_reg &= ~IXGBE_LED_MODE_MASK(index); | led_reg &= ~IXGBE_LED_MODE_MASK(index); | ||||
led_reg &= ~IXGBE_LED_BLINK(index); | led_reg &= ~IXGBE_LED_BLINK(index); | ||||
led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); | led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); | ||||
Context not available. | |||||
break; | break; | ||||
case ixgbe_mac_82599EB: | case ixgbe_mac_82599EB: | ||||
case ixgbe_mac_X540: | case ixgbe_mac_X540: | ||||
case ixgbe_mac_X550: | |||||
case ixgbe_mac_X550EM_x: | |||||
case ixgbe_mac_X550EM_a: | |||||
pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; | pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; | ||||
max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; | max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; | ||||
break; | break; | ||||
Context not available. | |||||
DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); | DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); | ||||
msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset); | msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset); | ||||
if (IXGBE_REMOVED(hw->hw_addr)) | |||||
msix_count = 0; | |||||
msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; | msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; | ||||
/* MSI-X count is zero-based in HW */ | /* MSI-X count is zero-based in HW */ | ||||
Context not available. | |||||
mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); | mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); | ||||
mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); | mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); | ||||
if (IXGBE_REMOVED(hw->hw_addr)) | |||||
goto done; | |||||
if (!mpsar_lo && !mpsar_hi) | if (!mpsar_lo && !mpsar_hi) | ||||
goto done; | goto done; | ||||
Context not available. | |||||
*link_up = FALSE; | *link_up = FALSE; | ||||
} | } | ||||
if ((links_reg & IXGBE_LINKS_SPEED_82599) == | switch (links_reg & IXGBE_LINKS_SPEED_82599) { | ||||
IXGBE_LINKS_SPEED_10G_82599) | case IXGBE_LINKS_SPEED_10G_82599: | ||||
*speed = IXGBE_LINK_SPEED_10GB_FULL; | *speed = IXGBE_LINK_SPEED_10GB_FULL; | ||||
else if ((links_reg & IXGBE_LINKS_SPEED_82599) == | if (hw->mac.type >= ixgbe_mac_X550) { | ||||
IXGBE_LINKS_SPEED_1G_82599) | if (links_reg & IXGBE_LINKS_SPEED_NON_STD) | ||||
*speed = IXGBE_LINK_SPEED_2_5GB_FULL; | |||||
} | |||||
break; | |||||
case IXGBE_LINKS_SPEED_1G_82599: | |||||
*speed = IXGBE_LINK_SPEED_1GB_FULL; | *speed = IXGBE_LINK_SPEED_1GB_FULL; | ||||
else if ((links_reg & IXGBE_LINKS_SPEED_82599) == | break; | ||||
IXGBE_LINKS_SPEED_100_82599) | case IXGBE_LINKS_SPEED_100_82599: | ||||
*speed = IXGBE_LINK_SPEED_100_FULL; | *speed = IXGBE_LINK_SPEED_100_FULL; | ||||
else | if (hw->mac.type >= ixgbe_mac_X550) { | ||||
if (links_reg & IXGBE_LINKS_SPEED_NON_STD) | |||||
*speed = IXGBE_LINK_SPEED_5GB_FULL; | |||||
} | |||||
break; | |||||
default: | |||||
*speed = IXGBE_LINK_SPEED_UNKNOWN; | *speed = IXGBE_LINK_SPEED_UNKNOWN; | ||||
} | |||||
return IXGBE_SUCCESS; | return IXGBE_SUCCESS; | ||||
} | } | ||||
Context not available. | |||||
* ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing | * ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* @enable: enable or disable switch for VLAN anti-spoofing | * @enable: enable or disable switch for VLAN anti-spoofing | ||||
* @pf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing | * @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing | ||||
* | * | ||||
**/ | **/ | ||||
void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) | void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) | ||||
Context not available. | |||||
* @buffer: contains the command to write and where the return status will | * @buffer: contains the command to write and where the return status will | ||||
* be placed | * be placed | ||||
* @length: length of buffer, must be multiple of 4 bytes | * @length: length of buffer, must be multiple of 4 bytes | ||||
* @timeout: time in ms to wait for command completion | |||||
* @return_data: read and return data from the buffer (TRUE) or not (FALSE) | |||||
* Needed because FW structures are big endian and decoding of | |||||
* these fields can be 8 bit or 16 bit based on command. Decoding | |||||
* is not easily understood without making a table of commands. | |||||
* So we will leave this up to the caller to read back the data | |||||
* in these cases. | |||||
* | * | ||||
* Communicates with the manageability block. On success return IXGBE_SUCCESS | * Communicates with the manageability block. On success return IXGBE_SUCCESS | ||||
* else return IXGBE_ERR_HOST_INTERFACE_COMMAND. | * else return IXGBE_ERR_HOST_INTERFACE_COMMAND. | ||||
**/ | **/ | ||||
s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, | s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, | ||||
u32 length) | u32 length, u32 timeout, bool return_data) | ||||
{ | { | ||||
u32 hicr, i, bi; | u32 hicr, i, bi, fwsts; | ||||
u32 hdr_size = sizeof(struct ixgbe_hic_hdr); | u32 hdr_size = sizeof(struct ixgbe_hic_hdr); | ||||
u8 buf_len, dword_len; | u16 buf_len; | ||||
u16 dword_len; | |||||
s32 ret_val = IXGBE_SUCCESS; | |||||
DEBUGFUNC("ixgbe_host_interface_command"); | DEBUGFUNC("ixgbe_host_interface_command"); | ||||
if (length == 0 || length & 0x3 || | if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { | ||||
length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { | DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); | ||||
DEBUGOUT("Buffer length failure.\n"); | return IXGBE_ERR_HOST_INTERFACE_COMMAND; | ||||
ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; | |||||
goto out; | |||||
} | } | ||||
/* Set bit 9 of FWSTS clearing FW reset indication */ | |||||
fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS); | |||||
IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI); | |||||
/* Check that the host interface is enabled. */ | /* Check that the host interface is enabled. */ | ||||
hicr = IXGBE_READ_REG(hw, IXGBE_HICR); | hicr = IXGBE_READ_REG(hw, IXGBE_HICR); | ||||
if ((hicr & IXGBE_HICR_EN) == 0) { | if ((hicr & IXGBE_HICR_EN) == 0) { | ||||
DEBUGOUT("IXGBE_HOST_EN bit disabled.\n"); | DEBUGOUT("IXGBE_HOST_EN bit disabled.\n"); | ||||
ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; | return IXGBE_ERR_HOST_INTERFACE_COMMAND; | ||||
goto out; | |||||
} | } | ||||
/* Calculate length in DWORDs */ | /* Calculate length in DWORDs. We must be DWORD aligned */ | ||||
if ((length % (sizeof(u32))) != 0) { | |||||
DEBUGOUT("Buffer length failure, not aligned to dword"); | |||||
return IXGBE_ERR_INVALID_ARGUMENT; | |||||
} | |||||
dword_len = length >> 2; | dword_len = length >> 2; | ||||
/* | /* The device driver writes the relevant command block | ||||
* The device driver writes the relevant command block | |||||
* into the ram area. | * into the ram area. | ||||
*/ | */ | ||||
for (i = 0; i < dword_len; i++) | for (i = 0; i < dword_len; i++) | ||||
Context not available. | |||||
/* Setting this bit tells the ARC that a new command is pending. */ | /* Setting this bit tells the ARC that a new command is pending. */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); | IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); | ||||
for (i = 0; i < IXGBE_HI_COMMAND_TIMEOUT; i++) { | for (i = 0; i < timeout; i++) { | ||||
hicr = IXGBE_READ_REG(hw, IXGBE_HICR); | hicr = IXGBE_READ_REG(hw, IXGBE_HICR); | ||||
if (!(hicr & IXGBE_HICR_C)) | if (!(hicr & IXGBE_HICR_C)) | ||||
break; | break; | ||||
Context not available. | |||||
msec_delay(1); | msec_delay(1); | ||||
} | } | ||||
/* Check command successful completion. */ | /* Check command completion */ | ||||
if (i == IXGBE_HI_COMMAND_TIMEOUT || | if ((timeout != 0 && i == timeout) || | ||||
(!(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV))) { | !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) { | ||||
DEBUGOUT("Command has failed with no status valid.\n"); | ERROR_REPORT1(IXGBE_ERROR_CAUTION, | ||||
ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; | "Command has failed with no status valid.\n"); | ||||
goto out; | return IXGBE_ERR_HOST_INTERFACE_COMMAND; | ||||
} | } | ||||
if (!return_data) | |||||
return 0; | |||||
/* Calculate length in DWORDs */ | /* Calculate length in DWORDs */ | ||||
dword_len = hdr_size >> 2; | dword_len = hdr_size >> 2; | ||||
Context not available. | |||||
/* If there is any thing in data position pull it in */ | /* If there is any thing in data position pull it in */ | ||||
buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len; | buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len; | ||||
if (buf_len == 0) | if (buf_len == 0) | ||||
goto out; | return 0; | ||||
if (length < (buf_len + hdr_size)) { | if (length < buf_len + hdr_size) { | ||||
DEBUGOUT("Buffer not large enough for reply message.\n"); | DEBUGOUT("Buffer not large enough for reply message.\n"); | ||||
ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; | return IXGBE_ERR_HOST_INTERFACE_COMMAND; | ||||
goto out; | |||||
} | } | ||||
/* Calculate length in DWORDs, add 3 for odd lengths */ | /* Calculate length in DWORDs, add 3 for odd lengths */ | ||||
dword_len = (buf_len + 3) >> 2; | dword_len = (buf_len + 3) >> 2; | ||||
/* Pull in the rest of the buffer (bi is where we left off)*/ | /* Pull in the rest of the buffer (bi is where we left off) */ | ||||
for (; bi <= dword_len; bi++) { | for (; bi <= dword_len; bi++) { | ||||
buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); | buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); | ||||
IXGBE_LE32_TO_CPUS(&buffer[bi]); | IXGBE_LE32_TO_CPUS(&buffer[bi]); | ||||
} | } | ||||
out: | return 0; | ||||
return ret_val; | |||||
} | } | ||||
/** | /** | ||||
Context not available. | |||||
for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { | for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { | ||||
ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, | ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, | ||||
sizeof(fw_cmd)); | sizeof(fw_cmd), | ||||
IXGBE_HI_COMMAND_TIMEOUT, | |||||
TRUE); | |||||
if (ret_val != IXGBE_SUCCESS) | if (ret_val != IXGBE_SUCCESS) | ||||
continue; | continue; | ||||
Context not available. | |||||
**/ | **/ | ||||
void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) | void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) | ||||
{ | { | ||||
u32 gcr_ext, hlreg0; | u32 gcr_ext, hlreg0, i, poll; | ||||
u16 value; | |||||
/* | /* | ||||
* If double reset is not requested then all transactions should | * If double reset is not requested then all transactions should | ||||
Context not available. | |||||
hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); | hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); | ||||
IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK); | IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK); | ||||
/* Wait for a last completion before clearing buffers */ | |||||
IXGBE_WRITE_FLUSH(hw); | |||||
msec_delay(3); | |||||
/* | |||||
* Before proceeding, make sure that the PCIe block does not have | |||||
* transactions pending. | |||||
*/ | |||||
poll = ixgbe_pcie_timeout_poll(hw); | |||||
for (i = 0; i < poll; i++) { | |||||
usec_delay(100); | |||||
value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); | |||||
if (IXGBE_REMOVED(hw->hw_addr)) | |||||
goto out; | |||||
if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) | |||||
goto out; | |||||
} | |||||
out: | |||||
/* initiate cleaning flow for buffers in the PCIe transaction layer */ | /* initiate cleaning flow for buffers in the PCIe transaction layer */ | ||||
gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); | gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); | ||||
IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, | IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, | ||||
Context not available. | |||||
(reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT)); | (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT)); | ||||
return; | return; | ||||
} | } | ||||
void ixgbe_disable_rx_generic(struct ixgbe_hw *hw) | |||||
{ | |||||
u32 pfdtxgswc; | |||||
u32 rxctrl; | |||||
rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); | |||||
if (rxctrl & IXGBE_RXCTRL_RXEN) { | |||||
if (hw->mac.type != ixgbe_mac_82598EB) { | |||||
pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); | |||||
if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { | |||||
pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; | |||||
IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); | |||||
hw->mac.set_lben = TRUE; | |||||
} else { | |||||
hw->mac.set_lben = FALSE; | |||||
} | |||||
} | |||||
rxctrl &= ~IXGBE_RXCTRL_RXEN; | |||||
IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); | |||||
} | |||||
} | |||||
void ixgbe_enable_rx_generic(struct ixgbe_hw *hw) | |||||
{ | |||||
u32 pfdtxgswc; | |||||
u32 rxctrl; | |||||
rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); | |||||
IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, (rxctrl | IXGBE_RXCTRL_RXEN)); | |||||
if (hw->mac.type != ixgbe_mac_82598EB) { | |||||
if (hw->mac.set_lben) { | |||||
pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); | |||||
pfdtxgswc |= IXGBE_PFDTXGSWC_VT_LBEN; | |||||
IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); | |||||
hw->mac.set_lben = FALSE; | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* ixgbe_mng_present - returns TRUE when management capability is present | |||||
* @hw: pointer to hardware structure | |||||
*/ | |||||
bool ixgbe_mng_present(struct ixgbe_hw *hw) | |||||
{ | |||||
u32 fwsm; | |||||
if (hw->mac.type < ixgbe_mac_82599EB) | |||||
return FALSE; | |||||
fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); | |||||
fwsm &= IXGBE_FWSM_MODE_MASK; | |||||
return fwsm == IXGBE_FWSM_FW_MODE_PT; | |||||
} | |||||
/** | |||||
* ixgbe_mng_enabled - Is the manageability engine enabled? | |||||
* @hw: pointer to hardware structure | |||||
* | |||||
* Returns TRUE if the manageability engine is enabled. | |||||
**/ | |||||
bool ixgbe_mng_enabled(struct ixgbe_hw *hw) | |||||
{ | |||||
u32 fwsm, manc, factps; | |||||
fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); | |||||
if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) | |||||
return FALSE; | |||||
manc = IXGBE_READ_REG(hw, IXGBE_MANC); | |||||
if (!(manc & IXGBE_MANC_RCV_TCO_EN)) | |||||
return FALSE; | |||||
if (hw->mac.type <= ixgbe_mac_X540) { | |||||
factps = IXGBE_READ_REG(hw, IXGBE_FACTPS); | |||||
if (factps & IXGBE_FACTPS_MNGCG) | |||||
return FALSE; | |||||
} | |||||
return TRUE; | |||||
} | |||||
/** | |||||
* ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed | |||||
* @hw: pointer to hardware structure | |||||
* @speed: new link speed | |||||
* @autoneg_wait_to_complete: TRUE when waiting for completion is needed | |||||
* | |||||
* Set the link speed in the MAC and/or PHY register and restarts link. | |||||
**/ | |||||
s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, | |||||
ixgbe_link_speed speed, | |||||
bool autoneg_wait_to_complete) | |||||
{ | |||||
ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; | |||||
ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; | |||||
s32 status = IXGBE_SUCCESS; | |||||
u32 speedcnt = 0; | |||||
u32 i = 0; | |||||
bool autoneg, link_up = FALSE; | |||||
DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); | |||||
/* Mask off requested but non-supported speeds */ | |||||
status = ixgbe_get_link_capabilities(hw, &link_speed, &autoneg); | |||||
if (status != IXGBE_SUCCESS) | |||||
return status; | |||||
speed &= link_speed; | |||||
/* Try each speed one by one, highest priority first. We do this in | |||||
* software because 10Gb fiber doesn't support speed autonegotiation. | |||||
*/ | |||||
if (speed & IXGBE_LINK_SPEED_10GB_FULL) { | |||||
speedcnt++; | |||||
highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; | |||||
/* If we already have link at this speed, just jump out */ | |||||
status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); | |||||
if (status != IXGBE_SUCCESS) | |||||
return status; | |||||
if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up) | |||||
goto out; | |||||
/* Set the module link speed */ | |||||
switch (hw->phy.media_type) { | |||||
case ixgbe_media_type_fiber_fixed: | |||||
case ixgbe_media_type_fiber: | |||||
ixgbe_set_rate_select_speed(hw, | |||||
IXGBE_LINK_SPEED_10GB_FULL); | |||||
break; | |||||
case ixgbe_media_type_fiber_qsfp: | |||||
/* QSFP module automatically detects MAC link speed */ | |||||
break; | |||||
default: | |||||
DEBUGOUT("Unexpected media type.\n"); | |||||
break; | |||||
} | |||||
/* Allow module to change analog characteristics (1G->10G) */ | |||||
msec_delay(40); | |||||
status = ixgbe_setup_mac_link(hw, | |||||
IXGBE_LINK_SPEED_10GB_FULL, | |||||
autoneg_wait_to_complete); | |||||
if (status != IXGBE_SUCCESS) | |||||
return status; | |||||
/* Flap the Tx laser if it has not already been done */ | |||||
ixgbe_flap_tx_laser(hw); | |||||
/* Wait for the controller to acquire link. Per IEEE 802.3ap, | |||||
* Section 73.10.2, we may have to wait up to 500ms if KR is | |||||
* attempted. 82599 uses the same timing for 10g SFI. | |||||
*/ | |||||
for (i = 0; i < 5; i++) { | |||||
/* Wait for the link partner to also set speed */ | |||||
msec_delay(100); | |||||
/* If we have link, just jump out */ | |||||
status = ixgbe_check_link(hw, &link_speed, | |||||
&link_up, FALSE); | |||||
if (status != IXGBE_SUCCESS) | |||||
return status; | |||||
if (link_up) | |||||
goto out; | |||||
} | |||||
} | |||||
if (speed & IXGBE_LINK_SPEED_1GB_FULL) { | |||||
speedcnt++; | |||||
if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) | |||||
highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; | |||||
/* If we already have link at this speed, just jump out */ | |||||
status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); | |||||
if (status != IXGBE_SUCCESS) | |||||
return status; | |||||
if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up) | |||||
goto out; | |||||
/* Set the module link speed */ | |||||
switch (hw->phy.media_type) { | |||||
case ixgbe_media_type_fiber_fixed: | |||||
case ixgbe_media_type_fiber: | |||||
ixgbe_set_rate_select_speed(hw, | |||||
IXGBE_LINK_SPEED_1GB_FULL); | |||||
break; | |||||
case ixgbe_media_type_fiber_qsfp: | |||||
/* QSFP module automatically detects link speed */ | |||||
break; | |||||
default: | |||||
DEBUGOUT("Unexpected media type.\n"); | |||||
break; | |||||
} | |||||
/* Allow module to change analog characteristics (10G->1G) */ | |||||
msec_delay(40); | |||||
status = ixgbe_setup_mac_link(hw, | |||||
IXGBE_LINK_SPEED_1GB_FULL, | |||||
autoneg_wait_to_complete); | |||||
if (status != IXGBE_SUCCESS) | |||||
return status; | |||||
/* Flap the Tx laser if it has not already been done */ | |||||
ixgbe_flap_tx_laser(hw); | |||||
/* Wait for the link partner to also set speed */ | |||||
msec_delay(100); | |||||
/* If we have link, just jump out */ | |||||
status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); | |||||
if (status != IXGBE_SUCCESS) | |||||
return status; | |||||
if (link_up) | |||||
goto out; | |||||
} | |||||
/* We didn't get link. Configure back to the highest speed we tried, | |||||
* (if there was more than one). We call ourselves back with just the | |||||
* single highest speed that the user requested. | |||||
*/ | |||||
if (speedcnt > 1) | |||||
status = ixgbe_setup_mac_link_multispeed_fiber(hw, | |||||
highest_link_speed, | |||||
autoneg_wait_to_complete); | |||||
out: | |||||
/* Set autoneg_advertised value based on input link speed */ | |||||
hw->phy.autoneg_advertised = 0; | |||||
if (speed & IXGBE_LINK_SPEED_10GB_FULL) | |||||
hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; | |||||
if (speed & IXGBE_LINK_SPEED_1GB_FULL) | |||||
hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; | |||||
return status; | |||||
} | |||||
/** | |||||
* ixgbe_set_soft_rate_select_speed - Set module link speed | |||||
* @hw: pointer to hardware structure | |||||
* @speed: link speed to set | |||||
* | |||||
* Set module link speed via the soft rate select. | |||||
*/ | |||||
void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, | |||||
ixgbe_link_speed speed) | |||||
{ | |||||
s32 status; | |||||
u8 rs, eeprom_data; | |||||
switch (speed) { | |||||
case IXGBE_LINK_SPEED_10GB_FULL: | |||||
/* one bit mask same as setting on */ | |||||
rs = IXGBE_SFF_SOFT_RS_SELECT_10G; | |||||
break; | |||||
case IXGBE_LINK_SPEED_1GB_FULL: | |||||
rs = IXGBE_SFF_SOFT_RS_SELECT_1G; | |||||
break; | |||||
default: | |||||
DEBUGOUT("Invalid fixed module speed\n"); | |||||
return; | |||||
} | |||||
/* Set RS0 */ | |||||
status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, | |||||
IXGBE_I2C_EEPROM_DEV_ADDR2, | |||||
&eeprom_data); | |||||
if (status) { | |||||
DEBUGOUT("Failed to read Rx Rate Select RS0\n"); | |||||
goto out; | |||||
} | |||||
eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; | |||||
status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, | |||||
IXGBE_I2C_EEPROM_DEV_ADDR2, | |||||
eeprom_data); | |||||
if (status) { | |||||
DEBUGOUT("Failed to write Rx Rate Select RS0\n"); | |||||
goto out; | |||||
} | |||||
/* Set RS1 */ | |||||
status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, | |||||
IXGBE_I2C_EEPROM_DEV_ADDR2, | |||||
&eeprom_data); | |||||
if (status) { | |||||
DEBUGOUT("Failed to read Rx Rate Select RS1\n"); | |||||
goto out; | |||||
} | |||||
eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; | |||||
status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, | |||||
IXGBE_I2C_EEPROM_DEV_ADDR2, | |||||
eeprom_data); | |||||
if (status) { | |||||
DEBUGOUT("Failed to write Rx Rate Select RS1\n"); | |||||
goto out; | |||||
} | |||||
out: | |||||
return; | |||||
} | |||||
Context not available. |