Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixgbe/ixgbe_common.c
/****************************************************************************** | /****************************************************************************** | ||||
Copyright (c) 2001-2015, Intel Corporation | Copyright (c) 2001-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. | ||||
2. Redistributions in binary form must reproduce the above copyright | 2. Redistributions in binary form must reproduce the above copyright | ||||
notice, this list of conditions and the following disclaimer in the | notice, this list of conditions and the following disclaimer in the | ||||
documentation and/or other materials provided with the distribution. | documentation and/or other materials provided with the distribution. | ||||
3. Neither the name of the Intel Corporation nor the names of its | 3. Neither the name of the Intel Corporation nor the names of its | ||||
contributors may be used to endorse or promote products derived from | contributors may be used to endorse or promote products derived from | ||||
this software without specific prior written permission. | this software without specific prior written permission. | ||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||
POSSIBILITY OF SUCH DAMAGE. | POSSIBILITY OF SUCH DAMAGE. | ||||
******************************************************************************/ | ******************************************************************************/ | ||||
/*$FreeBSD$*/ | /*$FreeBSD$*/ | ||||
#include "ixgbe_common.h" | #include "ixgbe_common.h" | ||||
#include "ixgbe_phy.h" | #include "ixgbe_phy.h" | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw) | ||||
mac->ops.prot_autoc_read = prot_autoc_read_generic; | mac->ops.prot_autoc_read = prot_autoc_read_generic; | ||||
mac->ops.prot_autoc_write = prot_autoc_write_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; | ||||
mac->ops.init_led_link_act = ixgbe_init_led_link_act_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.enable_rx = ixgbe_enable_rx_generic; | ||||
mac->ops.disable_rx = ixgbe_disable_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; | mac->ops.setup_fc = ixgbe_setup_fc_generic; | ||||
mac->ops.fc_autoneg = ixgbe_fc_autoneg; | |||||
/* Link */ | /* Link */ | ||||
mac->ops.get_link_capabilities = NULL; | mac->ops.get_link_capabilities = NULL; | ||||
mac->ops.setup_link = NULL; | mac->ops.setup_link = NULL; | ||||
mac->ops.check_link = NULL; | mac->ops.check_link = NULL; | ||||
mac->ops.dmac_config = NULL; | mac->ops.dmac_config = NULL; | ||||
mac->ops.dmac_update_tcs = NULL; | mac->ops.dmac_update_tcs = NULL; | ||||
mac->ops.dmac_config_tcs = NULL; | mac->ops.dmac_config_tcs = NULL; | ||||
Show All 17 Lines | bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) | ||||
bool link_up; | bool link_up; | ||||
DEBUGFUNC("ixgbe_device_supports_autoneg_fc"); | DEBUGFUNC("ixgbe_device_supports_autoneg_fc"); | ||||
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_qsfp: | ||||
case ixgbe_media_type_fiber: | case ixgbe_media_type_fiber: | ||||
/* flow control autoneg black list */ | |||||
switch (hw->device_id) { | |||||
case IXGBE_DEV_ID_X550EM_A_SFP: | |||||
case IXGBE_DEV_ID_X550EM_A_SFP_N: | |||||
case IXGBE_DEV_ID_X550EM_A_QSFP: | |||||
case IXGBE_DEV_ID_X550EM_A_QSFP_N: | |||||
supported = FALSE; | |||||
break; | |||||
default: | |||||
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 */ | ||||
if (link_up) | if (link_up) | ||||
supported = speed == IXGBE_LINK_SPEED_1GB_FULL ? | supported = speed == IXGBE_LINK_SPEED_1GB_FULL ? | ||||
TRUE : FALSE; | TRUE : FALSE; | ||||
else | else | ||||
supported = TRUE; | supported = TRUE; | ||||
} | |||||
break; | break; | ||||
case ixgbe_media_type_backplane: | case ixgbe_media_type_backplane: | ||||
if (hw->device_id == IXGBE_DEV_ID_X550EM_X_XFI) | |||||
supported = FALSE; | |||||
else | |||||
supported = TRUE; | supported = TRUE; | ||||
break; | break; | ||||
case ixgbe_media_type_copper: | case ixgbe_media_type_copper: | ||||
/* only some copper devices support flow control autoneg */ | /* only some copper devices support flow control autoneg */ | ||||
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_X540T1: | ||||
case IXGBE_DEV_ID_X540_BYPASS: | case IXGBE_DEV_ID_X540_BYPASS: | ||||
case IXGBE_DEV_ID_X550T: | case IXGBE_DEV_ID_X550T: | ||||
case IXGBE_DEV_ID_X550T1: | case IXGBE_DEV_ID_X550T1: | ||||
case IXGBE_DEV_ID_X550EM_X_10G_T: | case IXGBE_DEV_ID_X550EM_X_10G_T: | ||||
case IXGBE_DEV_ID_X550EM_A_10G_T: | |||||
case IXGBE_DEV_ID_X550EM_A_1G_T: | |||||
case IXGBE_DEV_ID_X550EM_A_1G_T_L: | |||||
supported = TRUE; | supported = TRUE; | ||||
break; | break; | ||||
default: | default: | ||||
supported = FALSE; | supported = FALSE; | ||||
} | } | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 171 Lines • ▼ Show 20 Lines | |||||
* all on chip counters, initializes receive address registers, multicast | * all on chip counters, initializes receive address registers, multicast | ||||
* table, VLAN filter table, calls routine to set up link and flow control | * table, VLAN filter table, calls routine to set up link and flow control | ||||
* settings, and leaves transmit and receive units disabled and uninitialized | * settings, and leaves transmit and receive units disabled and uninitialized | ||||
**/ | **/ | ||||
s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) | s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) | ||||
{ | { | ||||
s32 ret_val; | s32 ret_val; | ||||
u32 ctrl_ext; | u32 ctrl_ext; | ||||
u16 device_caps; | |||||
DEBUGFUNC("ixgbe_start_hw_generic"); | DEBUGFUNC("ixgbe_start_hw_generic"); | ||||
/* Set the media type */ | /* Set the media type */ | ||||
hw->phy.media_type = hw->mac.ops.get_media_type(hw); | hw->phy.media_type = hw->mac.ops.get_media_type(hw); | ||||
/* PHY ops initialization must be done in reset_hw() */ | /* PHY ops initialization must be done in reset_hw() */ | ||||
/* Clear the VLAN filter table */ | /* Clear the VLAN filter table */ | ||||
hw->mac.ops.clear_vfta(hw); | hw->mac.ops.clear_vfta(hw); | ||||
/* Clear statistics registers */ | /* Clear statistics registers */ | ||||
hw->mac.ops.clear_hw_cntrs(hw); | hw->mac.ops.clear_hw_cntrs(hw); | ||||
/* Set No Snoop Disable */ | /* Set No Snoop Disable */ | ||||
ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); | ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); | ||||
ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; | ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; | ||||
IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); | IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); | ||||
IXGBE_WRITE_FLUSH(hw); | IXGBE_WRITE_FLUSH(hw); | ||||
/* Setup flow control */ | /* Setup flow control */ | ||||
ret_val = ixgbe_setup_fc(hw); | ret_val = ixgbe_setup_fc(hw); | ||||
if (ret_val != IXGBE_SUCCESS) | if (ret_val != IXGBE_SUCCESS && ret_val != IXGBE_NOT_IMPLEMENTED) { | ||||
goto out; | DEBUGOUT1("Flow control setup failed, returning %d\n", ret_val); | ||||
return ret_val; | |||||
smh: bracing | |||||
} | |||||
/* Cache bit indicating need for crosstalk fix */ | |||||
switch (hw->mac.type) { | |||||
case ixgbe_mac_82599EB: | |||||
case ixgbe_mac_X550EM_x: | |||||
case ixgbe_mac_X550EM_a: | |||||
hw->mac.ops.get_device_caps(hw, &device_caps); | |||||
if (device_caps & IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR) | |||||
smhUnsubmitted Not Done Inline Actions!= 0 smh: != 0 | |||||
hw->need_crosstalk_fix = FALSE; | |||||
else | |||||
hw->need_crosstalk_fix = TRUE; | |||||
break; | |||||
default: | |||||
hw->need_crosstalk_fix = FALSE; | |||||
break; | |||||
} | |||||
/* Clear adapter stopped flag */ | /* Clear adapter stopped flag */ | ||||
hw->adapter_stopped = FALSE; | hw->adapter_stopped = FALSE; | ||||
out: | return IXGBE_SUCCESS; | ||||
smhUnsubmitted Not Done Inline Actionsbracing smh: bracing | |||||
return ret_val; | |||||
} | } | ||||
/** | /** | ||||
* ixgbe_start_hw_gen2 - Init sequence for common device family | * ixgbe_start_hw_gen2 - Init sequence for common device family | ||||
* @hw: pointer to hw structure | * @hw: pointer to hw structure | ||||
* | * | ||||
* Performs the init sequence common to the second generation | * Performs the init sequence common to the second generation | ||||
* of 10 GbE devices. | * of 10 GbE devices. | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
s32 status; | s32 status; | ||||
DEBUGFUNC("ixgbe_init_hw_generic"); | DEBUGFUNC("ixgbe_init_hw_generic"); | ||||
/* Reset the hardware */ | /* Reset the hardware */ | ||||
status = hw->mac.ops.reset_hw(hw); | status = hw->mac.ops.reset_hw(hw); | ||||
if (status == IXGBE_SUCCESS) { | if (status == IXGBE_SUCCESS || status == IXGBE_ERR_SFP_NOT_PRESENT) { | ||||
/* Start the HW */ | /* Start the HW */ | ||||
status = hw->mac.ops.start_hw(hw); | status = hw->mac.ops.start_hw(hw); | ||||
} | } | ||||
/* Initialize the LED link active for LED blink support */ | |||||
hw->mac.ops.init_led_link_act(hw); | |||||
if (status != IXGBE_SUCCESS) | |||||
DEBUGOUT1("Failed to initialize HW, STATUS = %d\n", status); | |||||
return status; | return status; | ||||
} | } | ||||
/** | /** | ||||
* ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters | * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* | * | ||||
* Clears all hardware statistics counters by reading them from the hardware | * Clears all hardware statistics counters by reading them from the hardware | ||||
▲ Show 20 Lines • Show All 539 Lines • ▼ Show 20 Lines | s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) | ||||
return IXGBE_SUCCESS; | return IXGBE_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices | * ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices | ||||
* @hw: pointer to the HW structure | * @hw: pointer to the HW structure | ||||
* | * | ||||
* Determines the LAN function id by reading memory-mapped registers | * Determines the LAN function id by reading memory-mapped registers and swaps | ||||
* and swaps the port value if requested. | * the port value if requested, and set MAC instance for devices that share | ||||
* CS4227. | |||||
**/ | **/ | ||||
void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) | void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) | ||||
{ | { | ||||
struct ixgbe_bus_info *bus = &hw->bus; | struct ixgbe_bus_info *bus = &hw->bus; | ||||
u32 reg; | u32 reg; | ||||
u16 ee_ctrl_4; | |||||
DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie"); | DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie"); | ||||
reg = IXGBE_READ_REG(hw, IXGBE_STATUS); | reg = IXGBE_READ_REG(hw, IXGBE_STATUS); | ||||
bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; | bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; | ||||
bus->lan_id = bus->func; | bus->lan_id = (u8)bus->func; | ||||
/* check for a port swap */ | /* check for a port swap */ | ||||
reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); | reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); | ||||
if (reg & IXGBE_FACTPS_LFS) | if (reg & IXGBE_FACTPS_LFS) | ||||
bus->func ^= 0x1; | bus->func ^= 0x1; | ||||
/* Get MAC instance from EEPROM for configuring CS4227 */ | |||||
if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) { | |||||
hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4); | |||||
bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >> | |||||
IXGBE_EE_CTRL_4_INST_ID_SHIFT; | |||||
} | } | ||||
} | |||||
/** | /** | ||||
* ixgbe_stop_adapter_generic - Generic stop Tx/Rx units | * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* | * | ||||
* Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, | * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, | ||||
* disables transmit and receive units. The adapter_stopped flag is used by | * disables transmit and receive units. The adapter_stopped flag is used by | ||||
* the shared code and drivers to determine if the adapter is in a stopped | * the shared code and drivers to determine if the adapter is in a stopped | ||||
Show All 40 Lines | s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) | ||||
/* | /* | ||||
* Prevent the PCI-E bus from hanging by disabling PCI-E master | * Prevent the PCI-E bus from hanging by disabling PCI-E master | ||||
* access and verify no pending requests | * access and verify no pending requests | ||||
*/ | */ | ||||
return ixgbe_disable_pcie_master(hw); | return ixgbe_disable_pcie_master(hw); | ||||
} | } | ||||
/** | /** | ||||
* ixgbe_init_led_link_act_generic - Store the LED index link/activity. | |||||
* @hw: pointer to hardware structure | |||||
* | |||||
* Store the index for the link active LED. This will be used to support | |||||
* blinking the LED. | |||||
**/ | |||||
s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw) | |||||
{ | |||||
struct ixgbe_mac_info *mac = &hw->mac; | |||||
u32 led_reg, led_mode; | |||||
u8 i; | |||||
led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); | |||||
/* Get LED link active from the LEDCTL register */ | |||||
for (i = 0; i < 4; i++) { | |||||
led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i); | |||||
if ((led_mode & IXGBE_LED_MODE_MASK_BASE) == | |||||
IXGBE_LED_LINK_ACTIVE) { | |||||
mac->led_link_act = i; | |||||
return IXGBE_SUCCESS; | |||||
} | |||||
} | |||||
/* | |||||
* If LEDCTL register does not have the LED link active set, then use | |||||
* known MAC defaults. | |||||
*/ | |||||
switch (hw->mac.type) { | |||||
case ixgbe_mac_X550EM_a: | |||||
case ixgbe_mac_X550EM_x: | |||||
mac->led_link_act = 1; | |||||
break; | |||||
default: | |||||
mac->led_link_act = 2; | |||||
} | |||||
return IXGBE_SUCCESS; | |||||
smhUnsubmitted Not Done Inline Actionsbracing more below. smh: bracing more below. | |||||
} | |||||
/** | |||||
* ixgbe_led_on_generic - Turns on the software controllable LEDs. | * ixgbe_led_on_generic - Turns on the software controllable LEDs. | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* @index: led number to turn on | * @index: led number to turn on | ||||
**/ | **/ | ||||
s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) | s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) | ||||
{ | { | ||||
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); | u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); | ||||
DEBUGFUNC("ixgbe_led_on_generic"); | DEBUGFUNC("ixgbe_led_on_generic"); | ||||
if (index > 3) | |||||
return IXGBE_ERR_PARAM; | |||||
/* To turn on the LED, set mode to ON. */ | /* To turn on the LED, set mode to ON. */ | ||||
led_reg &= ~IXGBE_LED_MODE_MASK(index); | led_reg &= ~IXGBE_LED_MODE_MASK(index); | ||||
led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); | led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); | ||||
IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); | IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); | ||||
IXGBE_WRITE_FLUSH(hw); | IXGBE_WRITE_FLUSH(hw); | ||||
return IXGBE_SUCCESS; | return IXGBE_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* ixgbe_led_off_generic - Turns off the software controllable LEDs. | * ixgbe_led_off_generic - Turns off the software controllable LEDs. | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* @index: led number to turn off | * @index: led number to turn off | ||||
**/ | **/ | ||||
s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) | s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) | ||||
{ | { | ||||
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); | u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); | ||||
DEBUGFUNC("ixgbe_led_off_generic"); | DEBUGFUNC("ixgbe_led_off_generic"); | ||||
if (index > 3) | |||||
return IXGBE_ERR_PARAM; | |||||
/* To turn off the LED, set mode to OFF. */ | /* To turn off the LED, set mode to OFF. */ | ||||
led_reg &= ~IXGBE_LED_MODE_MASK(index); | led_reg &= ~IXGBE_LED_MODE_MASK(index); | ||||
led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); | led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); | ||||
IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); | IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); | ||||
IXGBE_WRITE_FLUSH(hw); | IXGBE_WRITE_FLUSH(hw); | ||||
return IXGBE_SUCCESS; | return IXGBE_SUCCESS; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,259 Lines • ▼ Show 20 Lines | if (ixgbe_validate_mac_addr(hw->mac.addr) == | ||||
DEBUGOUT("Overriding MAC Address in RAR[0]\n"); | DEBUGOUT("Overriding MAC Address in RAR[0]\n"); | ||||
DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ", | DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ", | ||||
hw->mac.addr[0], hw->mac.addr[1], | hw->mac.addr[0], hw->mac.addr[1], | ||||
hw->mac.addr[2]); | hw->mac.addr[2]); | ||||
DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], | DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], | ||||
hw->mac.addr[4], hw->mac.addr[5]); | hw->mac.addr[4], hw->mac.addr[5]); | ||||
hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); | hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); | ||||
} | |||||
/* clear VMDq pool/queue selection for RAR 0 */ | /* clear VMDq pool/queue selection for RAR 0 */ | ||||
hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL); | hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL); | ||||
} | |||||
hw->addr_ctrl.overflow_promisc = 0; | hw->addr_ctrl.overflow_promisc = 0; | ||||
hw->addr_ctrl.rar_used_count = 1; | hw->addr_ctrl.rar_used_count = 1; | ||||
/* Zero out the other receive addresses. */ | /* Zero out the other receive addresses. */ | ||||
DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1); | DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1); | ||||
for (i = 1; i < rar_entries; i++) { | for (i = 1; i < rar_entries; i++) { | ||||
IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); | IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); | ||||
▲ Show 20 Lines • Show All 312 Lines • ▼ Show 20 Lines | if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && | ||||
DEBUGOUT("Invalid water mark configuration\n"); | DEBUGOUT("Invalid water mark configuration\n"); | ||||
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; | ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; | ||||
goto out; | goto out; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/* Negotiate the fc mode to use */ | /* Negotiate the fc mode to use */ | ||||
ixgbe_fc_autoneg(hw); | hw->mac.ops.fc_autoneg(hw); | ||||
/* Disable any previous flow control settings */ | /* Disable any previous flow control settings */ | ||||
mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); | mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); | ||||
mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE); | mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE); | ||||
fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); | fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); | ||||
fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY); | fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY); | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | |||||
* @adv_sym: symmetric pause bit in advertisement | * @adv_sym: symmetric pause bit in advertisement | ||||
* @adv_asm: asymmetric pause bit in advertisement | * @adv_asm: asymmetric pause bit in advertisement | ||||
* @lp_sym: symmetric pause bit in link partner advertisement | * @lp_sym: symmetric pause bit in link partner advertisement | ||||
* @lp_asm: asymmetric pause bit in link partner advertisement | * @lp_asm: asymmetric pause bit in link partner advertisement | ||||
* | * | ||||
* Find the intersection between advertised settings and link partner's | * Find the intersection between advertised settings and link partner's | ||||
* advertised settings | * advertised settings | ||||
**/ | **/ | ||||
static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, | s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, | ||||
u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm) | u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm) | ||||
{ | { | ||||
if ((!(adv_reg)) || (!(lp_reg))) { | if ((!(adv_reg)) || (!(lp_reg))) { | ||||
ERROR_REPORT3(IXGBE_ERROR_UNSUPPORTED, | ERROR_REPORT3(IXGBE_ERROR_UNSUPPORTED, | ||||
"Local or link partner's advertised flow control " | "Local or link partner's advertised flow control " | ||||
"settings are NULL. Local: %x, link partner: %x\n", | "settings are NULL. Local: %x, link partner: %x\n", | ||||
adv_reg, lp_reg); | adv_reg, lp_reg); | ||||
return IXGBE_ERR_FC_NOT_NEGOTIATED; | return IXGBE_ERR_FC_NOT_NEGOTIATED; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 456 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* 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 | ||||
* | * | ||||
* Enables the receive data path. | * Enables the receive data path. | ||||
**/ | **/ | ||||
s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw) | s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw) | ||||
{ | { | ||||
int secrxreg; | u32 secrxreg; | ||||
DEBUGFUNC("ixgbe_enable_sec_rx_path_generic"); | DEBUGFUNC("ixgbe_enable_sec_rx_path_generic"); | ||||
secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); | secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); | ||||
secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS; | secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS; | ||||
IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); | IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); | ||||
IXGBE_WRITE_FLUSH(hw); | IXGBE_WRITE_FLUSH(hw); | ||||
Show All 30 Lines | s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) | ||||
bool link_up = 0; | bool link_up = 0; | ||||
u32 autoc_reg = 0; | 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; | bool locked = FALSE; | ||||
DEBUGFUNC("ixgbe_blink_led_start_generic"); | DEBUGFUNC("ixgbe_blink_led_start_generic"); | ||||
if (index > 3) | |||||
return IXGBE_ERR_PARAM; | |||||
/* | /* | ||||
* Link must be up to auto-blink the LEDs; | * Link must be up to auto-blink the LEDs; | ||||
* Force it if link is down. | * Force it if link is down. | ||||
*/ | */ | ||||
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) { | ||||
ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); | ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); | ||||
Show All 29 Lines | |||||
{ | { | ||||
u32 autoc_reg = 0; | 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; | bool locked = FALSE; | ||||
DEBUGFUNC("ixgbe_blink_led_stop_generic"); | DEBUGFUNC("ixgbe_blink_led_stop_generic"); | ||||
if (index > 3) | |||||
return IXGBE_ERR_PARAM; | |||||
ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); | ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); | ||||
if (ret_val != IXGBE_SUCCESS) | if (ret_val != IXGBE_SUCCESS) | ||||
goto out; | goto out; | ||||
autoc_reg &= ~IXGBE_AUTOC_FLU; | autoc_reg &= ~IXGBE_AUTOC_FLU; | ||||
autoc_reg |= IXGBE_AUTOC_AN_RESTART; | autoc_reg |= IXGBE_AUTOC_AN_RESTART; | ||||
ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); | ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) | ||||
case ixgbe_mac_82598EB: | case ixgbe_mac_82598EB: | ||||
pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS; | pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS; | ||||
max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598; | max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598; | ||||
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_X550: | ||||
case ixgbe_mac_X550EM_x: | 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; | ||||
default: | default: | ||||
return msix_count; | return msix_count; | ||||
} | } | ||||
DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); | DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); | ||||
▲ Show 20 Lines • Show All 122 Lines • ▼ Show 20 Lines | if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { | ||||
mpsar_lo &= ~(1 << vmdq); | mpsar_lo &= ~(1 << vmdq); | ||||
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); | IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); | ||||
} else { | } else { | ||||
mpsar_hi &= ~(1 << (vmdq - 32)); | mpsar_hi &= ~(1 << (vmdq - 32)); | ||||
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); | IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); | ||||
} | } | ||||
/* was that the last pool using this rar? */ | /* was that the last pool using this rar? */ | ||||
if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0) | if (mpsar_lo == 0 && mpsar_hi == 0 && | ||||
rar != 0 && rar != hw->mac.san_mac_rar_index) | |||||
hw->mac.ops.clear_rar(hw, rar); | hw->mac.ops.clear_rar(hw, rar); | ||||
done: | done: | ||||
return IXGBE_SUCCESS; | return IXGBE_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address | * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address | ||||
* @hw: pointer to hardware struct | * @hw: pointer to hardware struct | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* ixgbe_find_vlvf_slot - find the vlanid or the first empty slot | * ixgbe_find_vlvf_slot - find the vlanid or the first empty slot | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* @vlan: VLAN id to write to VLAN filter | * @vlan: VLAN id to write to VLAN filter | ||||
* | * | ||||
* return the VLVF index where this VLAN id should be placed | * return the VLVF index where this VLAN id should be placed | ||||
* | * | ||||
**/ | **/ | ||||
s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan) | s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass) | ||||
{ | { | ||||
u32 bits = 0; | s32 regindex, first_empty_slot; | ||||
u32 first_empty_slot = 0; | u32 bits; | ||||
s32 regindex; | |||||
/* short cut the special case */ | /* short cut the special case */ | ||||
if (vlan == 0) | if (vlan == 0) | ||||
return 0; | return 0; | ||||
/* | /* if vlvf_bypass is set we don't want to use an empty slot, we | ||||
* Search for the vlan id in the VLVF entries. Save off the first empty | * will simply bypass the VLVF if there are no entries present in the | ||||
* slot found along the way | * VLVF that contain our VLAN | ||||
*/ | */ | ||||
for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) { | first_empty_slot = vlvf_bypass ? IXGBE_ERR_NO_SPACE : 0; | ||||
/* add VLAN enable bit for comparison */ | |||||
vlan |= IXGBE_VLVF_VIEN; | |||||
/* Search for the vlan id in the VLVF entries. Save off the first empty | |||||
* slot found along the way. | |||||
* | |||||
* pre-decrement loop covering (IXGBE_VLVF_ENTRIES - 1) .. 1 | |||||
*/ | |||||
for (regindex = IXGBE_VLVF_ENTRIES; --regindex;) { | |||||
bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); | bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); | ||||
if (!bits && !(first_empty_slot)) | if (bits == vlan) | ||||
return regindex; | |||||
if (!first_empty_slot && !bits) | |||||
first_empty_slot = regindex; | first_empty_slot = regindex; | ||||
else if ((bits & 0x0FFF) == vlan) | |||||
break; | |||||
} | } | ||||
/* | /* If we are here then we didn't find the VLAN. Return first empty | ||||
* If regindex is less than IXGBE_VLVF_ENTRIES, then we found the vlan | * slot we found during our search, else error. | ||||
* in the VLVF. Else use the first empty VLVF register for this | |||||
* vlan id. | |||||
*/ | */ | ||||
if (regindex >= IXGBE_VLVF_ENTRIES) { | if (!first_empty_slot) | ||||
if (first_empty_slot) | ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "No space in VLVF.\n"); | ||||
regindex = first_empty_slot; | |||||
else { | |||||
ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, | |||||
"No space in VLVF.\n"); | |||||
regindex = IXGBE_ERR_NO_SPACE; | |||||
} | |||||
} | |||||
return regindex; | return first_empty_slot ? first_empty_slot : IXGBE_ERR_NO_SPACE; | ||||
} | } | ||||
/** | /** | ||||
* ixgbe_set_vfta_generic - Set VLAN filter table | * ixgbe_set_vfta_generic - Set VLAN filter table | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* @vlan: VLAN id to write to VLAN filter | * @vlan: VLAN id to write to VLAN filter | ||||
* @vind: VMDq output index that maps queue to VLAN id in VFVFB | * @vind: VMDq output index that maps queue to VLAN id in VLVFB | ||||
* @vlan_on: boolean flag to turn on/off VLAN in VFVF | * @vlan_on: boolean flag to turn on/off VLAN | ||||
* @vlvf_bypass: boolean flag indicating updating default pool is okay | |||||
* | * | ||||
* Turn on/off specified VLAN in the VLAN filter table. | * Turn on/off specified VLAN in the VLAN filter table. | ||||
**/ | **/ | ||||
s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, | s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, | ||||
bool vlan_on) | bool vlan_on, bool vlvf_bypass) | ||||
{ | { | ||||
s32 regindex; | u32 regidx, vfta_delta, vfta; | ||||
u32 bitindex; | s32 ret_val; | ||||
u32 vfta; | |||||
u32 targetbit; | |||||
s32 ret_val = IXGBE_SUCCESS; | |||||
bool vfta_changed = FALSE; | |||||
DEBUGFUNC("ixgbe_set_vfta_generic"); | DEBUGFUNC("ixgbe_set_vfta_generic"); | ||||
if (vlan > 4095) | if (vlan > 4095 || vind > 63) | ||||
return IXGBE_ERR_PARAM; | return IXGBE_ERR_PARAM; | ||||
/* | /* | ||||
* this is a 2 part operation - first the VFTA, then the | * this is a 2 part operation - first the VFTA, then the | ||||
* VLVF and VLVFB if VT Mode is set | * VLVF and VLVFB if VT Mode is set | ||||
* We don't write the VFTA until we know the VLVF part succeeded. | * We don't write the VFTA until we know the VLVF part succeeded. | ||||
*/ | */ | ||||
/* Part 1 | /* Part 1 | ||||
* The VFTA is a bitstring made up of 128 32-bit registers | * The VFTA is a bitstring made up of 128 32-bit registers | ||||
* that enable the particular VLAN id, much like the MTA: | * that enable the particular VLAN id, much like the MTA: | ||||
* bits[11-5]: which register | * bits[11-5]: which register | ||||
* bits[4-0]: which bit in the register | * bits[4-0]: which bit in the register | ||||
*/ | */ | ||||
regindex = (vlan >> 5) & 0x7F; | regidx = vlan / 32; | ||||
bitindex = vlan & 0x1F; | vfta_delta = 1 << (vlan % 32); | ||||
targetbit = (1 << bitindex); | vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regidx)); | ||||
vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); | |||||
if (vlan_on) { | /* | ||||
if (!(vfta & targetbit)) { | * vfta_delta represents the difference between the current value | ||||
vfta |= targetbit; | * of vfta and the value we want in the register. Since the diff | ||||
vfta_changed = TRUE; | * is an XOR mask we can just update the vfta using an XOR | ||||
} | */ | ||||
} else { | vfta_delta &= vlan_on ? ~vfta : vfta; | ||||
if ((vfta & targetbit)) { | vfta ^= vfta_delta; | ||||
vfta &= ~targetbit; | |||||
vfta_changed = TRUE; | |||||
} | |||||
} | |||||
/* Part 2 | /* Part 2 | ||||
* Call ixgbe_set_vlvf_generic to set VLVFB and VLVF | * Call ixgbe_set_vlvf_generic to set VLVFB and VLVF | ||||
*/ | */ | ||||
ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, | ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, &vfta_delta, | ||||
&vfta_changed); | vfta, vlvf_bypass); | ||||
if (ret_val != IXGBE_SUCCESS) | if (ret_val != IXGBE_SUCCESS) { | ||||
if (vlvf_bypass) | |||||
goto vfta_update; | |||||
return ret_val; | return ret_val; | ||||
} | |||||
if (vfta_changed) | vfta_update: | ||||
IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta); | /* Update VFTA now that we are ready for traffic */ | ||||
if (vfta_delta) | |||||
IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta); | |||||
return IXGBE_SUCCESS; | return IXGBE_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* ixgbe_set_vlvf_generic - Set VLAN Pool Filter | * ixgbe_set_vlvf_generic - Set VLAN Pool Filter | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* @vlan: VLAN id to write to VLAN filter | * @vlan: VLAN id to write to VLAN filter | ||||
* @vind: VMDq output index that maps queue to VLAN id in VFVFB | * @vind: VMDq output index that maps queue to VLAN id in VLVFB | ||||
* @vlan_on: boolean flag to turn on/off VLAN in VFVF | * @vlan_on: boolean flag to turn on/off VLAN in VLVF | ||||
* @vfta_changed: pointer to boolean flag which indicates whether VFTA | * @vfta_delta: pointer to the difference between the current value of VFTA | ||||
* should be changed | * and the desired value | ||||
* @vfta: the desired value of the VFTA | |||||
* @vlvf_bypass: boolean flag indicating updating default pool is okay | |||||
* | * | ||||
* Turn on/off specified bit in VLVF table. | * Turn on/off specified bit in VLVF table. | ||||
**/ | **/ | ||||
s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, | s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, | ||||
bool vlan_on, bool *vfta_changed) | bool vlan_on, u32 *vfta_delta, u32 vfta, | ||||
bool vlvf_bypass) | |||||
{ | { | ||||
u32 vt; | u32 bits; | ||||
s32 vlvf_index; | |||||
DEBUGFUNC("ixgbe_set_vlvf_generic"); | DEBUGFUNC("ixgbe_set_vlvf_generic"); | ||||
if (vlan > 4095) | if (vlan > 4095 || vind > 63) | ||||
return IXGBE_ERR_PARAM; | return IXGBE_ERR_PARAM; | ||||
/* If VT Mode is set | /* If VT Mode is set | ||||
* Either vlan_on | * Either vlan_on | ||||
* make sure the vlan is in VLVF | * make sure the vlan is in VLVF | ||||
* set the vind bit in the matching VLVFB | * set the vind bit in the matching VLVFB | ||||
* Or !vlan_on | * Or !vlan_on | ||||
* clear the pool bit and possibly the vind | * clear the pool bit and possibly the vind | ||||
*/ | */ | ||||
vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL); | if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE)) | ||||
if (vt & IXGBE_VT_CTL_VT_ENABLE) { | return IXGBE_SUCCESS; | ||||
s32 vlvf_index; | |||||
u32 bits; | |||||
vlvf_index = ixgbe_find_vlvf_slot(hw, vlan); | vlvf_index = ixgbe_find_vlvf_slot(hw, vlan, vlvf_bypass); | ||||
if (vlvf_index < 0) | if (vlvf_index < 0) | ||||
return vlvf_index; | return vlvf_index; | ||||
if (vlan_on) { | bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32)); | ||||
/* set the pool bit */ | /* set the pool bit */ | ||||
if (vind < 32) { | bits |= 1 << (vind % 32); | ||||
bits = IXGBE_READ_REG(hw, | if (vlan_on) | ||||
IXGBE_VLVFB(vlvf_index * 2)); | goto vlvf_update; | ||||
bits |= (1 << vind); | |||||
IXGBE_WRITE_REG(hw, | |||||
IXGBE_VLVFB(vlvf_index * 2), | |||||
bits); | |||||
} else { | |||||
bits = IXGBE_READ_REG(hw, | |||||
IXGBE_VLVFB((vlvf_index * 2) + 1)); | |||||
bits |= (1 << (vind - 32)); | |||||
IXGBE_WRITE_REG(hw, | |||||
IXGBE_VLVFB((vlvf_index * 2) + 1), | |||||
bits); | |||||
} | |||||
} else { | |||||
/* clear the pool bit */ | /* clear the pool bit */ | ||||
if (vind < 32) { | bits ^= 1 << (vind % 32); | ||||
bits = IXGBE_READ_REG(hw, | |||||
IXGBE_VLVFB(vlvf_index * 2)); | if (!bits && | ||||
bits &= ~(1 << vind); | !IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + 1 - vind / 32))) { | ||||
IXGBE_WRITE_REG(hw, | /* Clear VFTA first, then disable VLVF. Otherwise | ||||
IXGBE_VLVFB(vlvf_index * 2), | * we run the risk of stray packets leaking into | ||||
bits); | * the PF via the default pool | ||||
bits |= IXGBE_READ_REG(hw, | */ | ||||
IXGBE_VLVFB((vlvf_index * 2) + 1)); | if (*vfta_delta) | ||||
} else { | IXGBE_WRITE_REG(hw, IXGBE_VFTA(vlan / 32), vfta); | ||||
bits = IXGBE_READ_REG(hw, | |||||
IXGBE_VLVFB((vlvf_index * 2) + 1)); | /* disable VLVF and clear remaining bit from pool */ | ||||
bits &= ~(1 << (vind - 32)); | IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0); | ||||
IXGBE_WRITE_REG(hw, | IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), 0); | ||||
IXGBE_VLVFB((vlvf_index * 2) + 1), | |||||
bits); | return IXGBE_SUCCESS; | ||||
bits |= IXGBE_READ_REG(hw, | |||||
IXGBE_VLVFB(vlvf_index * 2)); | |||||
} | } | ||||
} | |||||
/* | /* If there are still bits set in the VLVFB registers | ||||
* If there are still bits set in the VLVFB registers | |||||
* for the VLAN ID indicated we need to see if the | * for the VLAN ID indicated we need to see if the | ||||
* caller is requesting that we clear the VFTA entry bit. | * caller is requesting that we clear the VFTA entry bit. | ||||
* If the caller has requested that we clear the VFTA | * If the caller has requested that we clear the VFTA | ||||
* entry bit but there are still pools/VFs using this VLAN | * entry bit but there are still pools/VFs using this VLAN | ||||
* ID entry then ignore the request. We're not worried | * ID entry then ignore the request. We're not worried | ||||
* about the case where we're turning the VFTA VLAN ID | * about the case where we're turning the VFTA VLAN ID | ||||
* entry bit on, only when requested to turn it off as | * entry bit on, only when requested to turn it off as | ||||
* there may be multiple pools and/or VFs using the | * there may be multiple pools and/or VFs using the | ||||
* VLAN ID entry. In that case we cannot clear the | * VLAN ID entry. In that case we cannot clear the | ||||
* VFTA bit until all pools/VFs using that VLAN ID have also | * VFTA bit until all pools/VFs using that VLAN ID have also | ||||
* been cleared. This will be indicated by "bits" being | * been cleared. This will be indicated by "bits" being | ||||
* zero. | * zero. | ||||
*/ | */ | ||||
if (bits) { | *vfta_delta = 0; | ||||
IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), | |||||
(IXGBE_VLVF_VIEN | vlan)); | |||||
if ((!vlan_on) && (vfta_changed != NULL)) { | |||||
/* someone wants to clear the vfta entry | |||||
* but some pools/VFs are still using it. | |||||
* Ignore it. */ | |||||
*vfta_changed = FALSE; | |||||
} | |||||
} else | |||||
IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0); | |||||
} | |||||
vlvf_update: | |||||
/* record pool change and enable VLAN ID if not already enabled */ | |||||
IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), bits); | |||||
IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), IXGBE_VLVF_VIEN | vlan); | |||||
return IXGBE_SUCCESS; | return IXGBE_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* ixgbe_clear_vfta_generic - Clear VLAN filter table | * ixgbe_clear_vfta_generic - Clear VLAN filter table | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* | * | ||||
* Clears the VLAN filer table, and the VMDq index associated with the filter | * Clears the VLAN filer table, and the VMDq index associated with the filter | ||||
Show All 12 Lines | for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { | ||||
IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0); | IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0); | ||||
IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset * 2) + 1), 0); | IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset * 2) + 1), 0); | ||||
} | } | ||||
return IXGBE_SUCCESS; | return IXGBE_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* ixgbe_need_crosstalk_fix - Determine if we need to do cross talk fix | |||||
* @hw: pointer to hardware structure | |||||
* | |||||
* Contains the logic to identify if we need to verify link for the | |||||
* crosstalk fix | |||||
**/ | |||||
static bool ixgbe_need_crosstalk_fix(struct ixgbe_hw *hw) | |||||
{ | |||||
/* Does FW say we need the fix */ | |||||
if (!hw->need_crosstalk_fix) | |||||
return FALSE; | |||||
/* Only consider SFP+ PHYs i.e. media type fiber */ | |||||
switch (hw->mac.ops.get_media_type(hw)) { | |||||
case ixgbe_media_type_fiber: | |||||
case ixgbe_media_type_fiber_qsfp: | |||||
break; | |||||
default: | |||||
return FALSE; | |||||
} | |||||
return TRUE; | |||||
} | |||||
/** | |||||
* ixgbe_check_mac_link_generic - Determine link and speed status | * ixgbe_check_mac_link_generic - Determine link and speed status | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* @speed: pointer to link speed | * @speed: pointer to link speed | ||||
* @link_up: TRUE when link is up | * @link_up: TRUE when link is up | ||||
* @link_up_wait_to_complete: bool used to wait for link up or not | * @link_up_wait_to_complete: bool used to wait for link up or not | ||||
* | * | ||||
* Reads the links register to determine if link is up and the current speed | * Reads the links register to determine if link is up and the current speed | ||||
**/ | **/ | ||||
s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, | s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, | ||||
bool *link_up, bool link_up_wait_to_complete) | bool *link_up, bool link_up_wait_to_complete) | ||||
{ | { | ||||
u32 links_reg, links_orig; | u32 links_reg, links_orig; | ||||
u32 i; | u32 i; | ||||
DEBUGFUNC("ixgbe_check_mac_link_generic"); | DEBUGFUNC("ixgbe_check_mac_link_generic"); | ||||
/* If Crosstalk fix enabled do the sanity check of making sure | |||||
* the SFP+ cage is full. | |||||
*/ | |||||
if (ixgbe_need_crosstalk_fix(hw)) { | |||||
u32 sfp_cage_full; | |||||
switch (hw->mac.type) { | |||||
case ixgbe_mac_82599EB: | |||||
sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & | |||||
IXGBE_ESDP_SDP2; | |||||
break; | |||||
case ixgbe_mac_X550EM_x: | |||||
case ixgbe_mac_X550EM_a: | |||||
sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & | |||||
IXGBE_ESDP_SDP0; | |||||
break; | |||||
default: | |||||
/* sanity check - No SFP+ devices here */ | |||||
sfp_cage_full = FALSE; | |||||
break; | |||||
} | |||||
if (!sfp_cage_full) { | |||||
*link_up = FALSE; | |||||
*speed = IXGBE_LINK_SPEED_UNKNOWN; | |||||
return IXGBE_SUCCESS; | |||||
} | |||||
} | |||||
/* clear the old state */ | /* clear the old state */ | ||||
links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS); | links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS); | ||||
links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); | links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); | ||||
if (links_orig != links_reg) { | if (links_orig != links_reg) { | ||||
DEBUGOUT2("LINKS changed from %08X to %08X\n", | DEBUGOUT2("LINKS changed from %08X to %08X\n", | ||||
links_orig, links_reg); | links_orig, links_reg); | ||||
Show All 25 Lines | if (hw->mac.type >= ixgbe_mac_X550) { | ||||
*speed = IXGBE_LINK_SPEED_2_5GB_FULL; | *speed = IXGBE_LINK_SPEED_2_5GB_FULL; | ||||
} | } | ||||
break; | break; | ||||
case IXGBE_LINKS_SPEED_1G_82599: | case IXGBE_LINKS_SPEED_1G_82599: | ||||
*speed = IXGBE_LINK_SPEED_1GB_FULL; | *speed = IXGBE_LINK_SPEED_1GB_FULL; | ||||
break; | break; | ||||
case IXGBE_LINKS_SPEED_100_82599: | case IXGBE_LINKS_SPEED_100_82599: | ||||
*speed = IXGBE_LINK_SPEED_100_FULL; | *speed = IXGBE_LINK_SPEED_100_FULL; | ||||
if (hw->mac.type >= ixgbe_mac_X550) { | if (hw->mac.type == ixgbe_mac_X550) { | ||||
if (links_reg & IXGBE_LINKS_SPEED_NON_STD) | if (links_reg & IXGBE_LINKS_SPEED_NON_STD) | ||||
*speed = IXGBE_LINK_SPEED_5GB_FULL; | *speed = IXGBE_LINK_SPEED_5GB_FULL; | ||||
} | } | ||||
break; | break; | ||||
case IXGBE_LINKS_SPEED_10_X550EM_A: | |||||
*speed = IXGBE_LINK_SPEED_UNKNOWN; | |||||
if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T || | |||||
hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) { | |||||
*speed = IXGBE_LINK_SPEED_10_FULL; | |||||
} | |||||
break; | |||||
default: | default: | ||||
*speed = IXGBE_LINK_SPEED_UNKNOWN; | *speed = IXGBE_LINK_SPEED_UNKNOWN; | ||||
} | } | ||||
return IXGBE_SUCCESS; | return IXGBE_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | |||||
out: | out: | ||||
return status; | return status; | ||||
} | } | ||||
/** | /** | ||||
* ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing | * ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* @enable: enable or disable switch for anti-spoofing | * @enable: enable or disable switch for MAC anti-spoofing | ||||
* @pf: Physical Function pool - do not enable anti-spoofing for the PF | * @vf: Virtual Function pool - VF Pool to set for MAC anti-spoofing | ||||
* | * | ||||
**/ | **/ | ||||
void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf) | void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) | ||||
{ | { | ||||
int j; | int vf_target_reg = vf >> 3; | ||||
int pf_target_reg = pf >> 3; | int vf_target_shift = vf % 8; | ||||
int pf_target_shift = pf % 8; | u32 pfvfspoof; | ||||
u32 pfvfspoof = 0; | |||||
if (hw->mac.type == ixgbe_mac_82598EB) | if (hw->mac.type == ixgbe_mac_82598EB) | ||||
return; | return; | ||||
pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); | |||||
if (enable) | if (enable) | ||||
pfvfspoof = IXGBE_SPOOF_MACAS_MASK; | pfvfspoof |= (1 << vf_target_shift); | ||||
else | |||||
/* | pfvfspoof &= ~(1 << vf_target_shift); | ||||
* PFVFSPOOF register array is size 8 with 8 bits assigned to | IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); | ||||
* MAC anti-spoof enables in each register array element. | |||||
*/ | |||||
for (j = 0; j < pf_target_reg; j++) | |||||
IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof); | |||||
/* | |||||
* The PF should be allowed to spoof so that it can support | |||||
* emulation mode NICs. Do not set the bits assigned to the PF | |||||
*/ | |||||
pfvfspoof &= (1 << pf_target_shift) - 1; | |||||
IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof); | |||||
/* | |||||
* Remaining pools belong to the PF so they do not need to have | |||||
* anti-spoofing enabled. | |||||
*/ | |||||
for (j++; j < IXGBE_PFVFSPOOF_REG_COUNT; j++) | |||||
IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), 0); | |||||
} | } | ||||
/** | /** | ||||
* 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 | ||||
* @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing | * @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing | ||||
* | * | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | u8 ixgbe_calculate_checksum(u8 *buffer, u32 length) | ||||
for (i = 0; i < length; i++) | for (i = 0; i < length; i++) | ||||
sum += buffer[i]; | sum += buffer[i]; | ||||
return (u8) (0 - sum); | return (u8) (0 - sum); | ||||
} | } | ||||
/** | /** | ||||
* ixgbe_host_interface_command - Issue command to manageability block | * ixgbe_hic_unlocked - Issue command to manageability block unlocked | ||||
* @hw: pointer to the HW structure | * @hw: pointer to the HW structure | ||||
* @buffer: contains the command to write and where the return status will | * @buffer: 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 | * @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 returns semaphore error when encountering an error acquiring | ||||
* semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. | |||||
* | |||||
* This function assumes that the IXGBE_GSSR_SW_MNG_SM semaphore is held | |||||
* by the caller. | |||||
**/ | **/ | ||||
s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, | s32 ixgbe_hic_unlocked(struct ixgbe_hw *hw, u32 *buffer, u32 length, | ||||
u32 length, u32 timeout, bool return_data) | u32 timeout) | ||||
{ | { | ||||
u32 hicr, i, bi, fwsts; | u32 hicr, i, fwsts; | ||||
u32 hdr_size = sizeof(struct ixgbe_hic_hdr); | |||||
u16 buf_len; | |||||
u16 dword_len; | u16 dword_len; | ||||
DEBUGFUNC("ixgbe_host_interface_command"); | DEBUGFUNC("ixgbe_hic_unlocked"); | ||||
if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { | if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { | ||||
DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); | DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); | ||||
return IXGBE_ERR_HOST_INTERFACE_COMMAND; | return IXGBE_ERR_HOST_INTERFACE_COMMAND; | ||||
} | } | ||||
/* Set bit 9 of FWSTS clearing FW reset indication */ | /* Set bit 9 of FWSTS clearing FW reset indication */ | ||||
fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS); | fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS); | ||||
IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI); | 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)) { | ||||
DEBUGOUT("IXGBE_HOST_EN bit disabled.\n"); | DEBUGOUT("IXGBE_HOST_EN bit disabled.\n"); | ||||
return IXGBE_ERR_HOST_INTERFACE_COMMAND; | return IXGBE_ERR_HOST_INTERFACE_COMMAND; | ||||
} | } | ||||
/* Calculate length in DWORDs. We must be DWORD aligned */ | /* Calculate length in DWORDs. We must be DWORD aligned */ | ||||
if ((length % (sizeof(u32))) != 0) { | if (length % sizeof(u32)) { | ||||
DEBUGOUT("Buffer length failure, not aligned to dword"); | DEBUGOUT("Buffer length failure, not aligned to dword"); | ||||
return IXGBE_ERR_INVALID_ARGUMENT; | 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++) | ||||
IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, | IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, | ||||
i, IXGBE_CPU_TO_LE32(buffer[i])); | i, IXGBE_CPU_TO_LE32(buffer[i])); | ||||
/* 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 < 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; | ||||
msec_delay(1); | msec_delay(1); | ||||
} | } | ||||
/* Check command completion */ | /* Check command completion */ | ||||
if ((timeout != 0 && i == timeout) || | if ((timeout && i == timeout) || | ||||
!(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) { | !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) { | ||||
ERROR_REPORT1(IXGBE_ERROR_CAUTION, | ERROR_REPORT1(IXGBE_ERROR_CAUTION, | ||||
"Command has failed with no status valid.\n"); | "Command has failed with no status valid.\n"); | ||||
return IXGBE_ERR_HOST_INTERFACE_COMMAND; | return IXGBE_ERR_HOST_INTERFACE_COMMAND; | ||||
} | } | ||||
return IXGBE_SUCCESS; | |||||
} | |||||
/** | |||||
* ixgbe_host_interface_command - Issue command to manageability block | |||||
* @hw: pointer to the HW structure | |||||
* @buffer: contains the command to write and where the return status will | |||||
* be placed | |||||
* @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 | |||||
* else returns semaphore error when encountering an error acquiring | |||||
* semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. | |||||
**/ | |||||
s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, | |||||
u32 length, u32 timeout, bool return_data) | |||||
{ | |||||
u32 hdr_size = sizeof(struct ixgbe_hic_hdr); | |||||
u16 dword_len; | |||||
u16 buf_len; | |||||
s32 status; | |||||
u32 bi; | |||||
DEBUGFUNC("ixgbe_host_interface_command"); | |||||
if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { | |||||
DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); | |||||
return IXGBE_ERR_HOST_INTERFACE_COMMAND; | |||||
} | |||||
/* Take management host interface semaphore */ | |||||
status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); | |||||
if (status) | |||||
return status; | |||||
status = ixgbe_hic_unlocked(hw, buffer, length, timeout); | |||||
if (status) | |||||
goto rel_out; | |||||
if (!return_data) | if (!return_data) | ||||
return 0; | goto rel_out; | ||||
/* Calculate length in DWORDs */ | /* Calculate length in DWORDs */ | ||||
dword_len = hdr_size >> 2; | dword_len = hdr_size >> 2; | ||||
/* first pull in the header so we know the buffer length */ | /* first pull in the header so we know the buffer length */ | ||||
for (bi = 0; bi < dword_len; bi++) { | for (bi = 0; 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]); | ||||
} | } | ||||
/* 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) | ||||
return 0; | goto rel_out; | ||||
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"); | ||||
return IXGBE_ERR_HOST_INTERFACE_COMMAND; | status = IXGBE_ERR_HOST_INTERFACE_COMMAND; | ||||
goto rel_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]); | ||||
} | } | ||||
return 0; | rel_out: | ||||
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); | |||||
return status; | |||||
} | } | ||||
/** | /** | ||||
* ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware | * ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware | ||||
* @hw: pointer to the HW structure | * @hw: pointer to the HW structure | ||||
* @maj: driver version major number | * @maj: driver version major number | ||||
* @min: driver version minor number | * @min: driver version minor number | ||||
* @build: driver version build number | * @build: driver version build number | ||||
* @sub: driver version sub build number | * @sub: driver version sub build number | ||||
* | * | ||||
* Sends driver version number to firmware through the manageability | * Sends driver version number to firmware through the manageability | ||||
* block. On success return IXGBE_SUCCESS | * block. On success return IXGBE_SUCCESS | ||||
* else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring | * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring | ||||
* semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. | * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. | ||||
**/ | **/ | ||||
s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, | s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, | ||||
u8 build, u8 sub) | u8 build, u8 sub, u16 len, | ||||
const char *driver_ver) | |||||
{ | { | ||||
struct ixgbe_hic_drv_info fw_cmd; | struct ixgbe_hic_drv_info fw_cmd; | ||||
int i; | int i; | ||||
s32 ret_val = IXGBE_SUCCESS; | s32 ret_val = IXGBE_SUCCESS; | ||||
DEBUGFUNC("ixgbe_set_fw_drv_ver_generic"); | DEBUGFUNC("ixgbe_set_fw_drv_ver_generic"); | ||||
UNREFERENCED_2PARAMETER(len, driver_ver); | |||||
if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM) | |||||
!= IXGBE_SUCCESS) { | |||||
ret_val = IXGBE_ERR_SWFW_SYNC; | |||||
goto out; | |||||
} | |||||
fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; | fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; | ||||
fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; | fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; | ||||
fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; | fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; | ||||
fw_cmd.port_num = (u8)hw->bus.func; | fw_cmd.port_num = (u8)hw->bus.func; | ||||
fw_cmd.ver_maj = maj; | fw_cmd.ver_maj = maj; | ||||
fw_cmd.ver_min = min; | fw_cmd.ver_min = min; | ||||
fw_cmd.ver_build = build; | fw_cmd.ver_build = build; | ||||
fw_cmd.ver_sub = sub; | fw_cmd.ver_sub = sub; | ||||
Show All 15 Lines | if (fw_cmd.hdr.cmd_or_resp.ret_status == | ||||
FW_CEM_RESP_STATUS_SUCCESS) | FW_CEM_RESP_STATUS_SUCCESS) | ||||
ret_val = IXGBE_SUCCESS; | ret_val = IXGBE_SUCCESS; | ||||
else | else | ||||
ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; | ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; | ||||
break; | break; | ||||
} | } | ||||
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); | |||||
out: | |||||
return ret_val; | return ret_val; | ||||
} | } | ||||
/** | /** | ||||
* ixgbe_set_rxpba_generic - Initialize Rx packet buffer | * ixgbe_set_rxpba_generic - Initialize Rx packet buffer | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* @num_pb: number of packet buffers to allocate | * @num_pb: number of packet buffers to allocate | ||||
* @headroom: reserve n KB of headroom | * @headroom: reserve n KB of headroom | ||||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | out: | ||||
IXGBE_WRITE_FLUSH(hw); | IXGBE_WRITE_FLUSH(hw); | ||||
usec_delay(20); | usec_delay(20); | ||||
/* restore previous register values */ | /* restore previous register values */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); | IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); | ||||
IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); | IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); | ||||
} | } | ||||
/** | |||||
* ixgbe_bypass_rw_generic - Bit bang data into by_pass FW | |||||
* | |||||
* @hw: pointer to hardware structure | |||||
* @cmd: Command we send to the FW | |||||
* @status: The reply from the FW | |||||
* | |||||
* Bit-bangs the cmd to the by_pass FW status points to what is returned. | |||||
**/ | |||||
#define IXGBE_BYPASS_BB_WAIT 1 | |||||
s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status) | |||||
{ | |||||
int i; | |||||
u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo; | |||||
u32 esdp; | |||||
if (!status) | |||||
return IXGBE_ERR_PARAM; | |||||
*status = 0; | |||||
/* SDP vary by MAC type */ | |||||
switch (hw->mac.type) { | |||||
case ixgbe_mac_82599EB: | |||||
sck = IXGBE_ESDP_SDP7; | |||||
sdi = IXGBE_ESDP_SDP0; | |||||
sdo = IXGBE_ESDP_SDP6; | |||||
dir_sck = IXGBE_ESDP_SDP7_DIR; | |||||
dir_sdi = IXGBE_ESDP_SDP0_DIR; | |||||
dir_sdo = IXGBE_ESDP_SDP6_DIR; | |||||
break; | |||||
case ixgbe_mac_X540: | |||||
sck = IXGBE_ESDP_SDP2; | |||||
sdi = IXGBE_ESDP_SDP0; | |||||
sdo = IXGBE_ESDP_SDP1; | |||||
dir_sck = IXGBE_ESDP_SDP2_DIR; | |||||
dir_sdi = IXGBE_ESDP_SDP0_DIR; | |||||
dir_sdo = IXGBE_ESDP_SDP1_DIR; | |||||
break; | |||||
default: | |||||
return IXGBE_ERR_DEVICE_NOT_SUPPORTED; | |||||
} | |||||
/* Set SDP pins direction */ | |||||
esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); | |||||
esdp |= dir_sck; /* SCK as output */ | |||||
esdp |= dir_sdi; /* SDI as output */ | |||||
esdp &= ~dir_sdo; /* SDO as input */ | |||||
esdp |= sck; | |||||
esdp |= sdi; | |||||
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); | |||||
IXGBE_WRITE_FLUSH(hw); | |||||
msec_delay(IXGBE_BYPASS_BB_WAIT); | |||||
/* Generate start condition */ | |||||
esdp &= ~sdi; | |||||
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); | |||||
IXGBE_WRITE_FLUSH(hw); | |||||
msec_delay(IXGBE_BYPASS_BB_WAIT); | |||||
esdp &= ~sck; | |||||
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); | |||||
IXGBE_WRITE_FLUSH(hw); | |||||
msec_delay(IXGBE_BYPASS_BB_WAIT); | |||||
/* Clock out the new control word and clock in the status */ | |||||
for (i = 0; i < 32; i++) { | |||||
if ((cmd >> (31 - i)) & 0x01) { | |||||
esdp |= sdi; | |||||
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); | |||||
} else { | |||||
esdp &= ~sdi; | |||||
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); | |||||
} | |||||
IXGBE_WRITE_FLUSH(hw); | |||||
msec_delay(IXGBE_BYPASS_BB_WAIT); | |||||
esdp |= sck; | |||||
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); | |||||
IXGBE_WRITE_FLUSH(hw); | |||||
msec_delay(IXGBE_BYPASS_BB_WAIT); | |||||
esdp &= ~sck; | |||||
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); | |||||
IXGBE_WRITE_FLUSH(hw); | |||||
msec_delay(IXGBE_BYPASS_BB_WAIT); | |||||
esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); | |||||
if (esdp & sdo) | |||||
*status = (*status << 1) | 0x01; | |||||
else | |||||
*status = (*status << 1) | 0x00; | |||||
msec_delay(IXGBE_BYPASS_BB_WAIT); | |||||
} | |||||
/* stop condition */ | |||||
esdp |= sck; | |||||
esdp &= ~sdi; | |||||
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); | |||||
IXGBE_WRITE_FLUSH(hw); | |||||
msec_delay(IXGBE_BYPASS_BB_WAIT); | |||||
esdp |= sdi; | |||||
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); | |||||
IXGBE_WRITE_FLUSH(hw); | |||||
/* set the page bits to match the cmd that the status it belongs to */ | |||||
*status = (*status & 0x3fffffff) | (cmd & 0xc0000000); | |||||
return IXGBE_SUCCESS; | |||||
} | |||||
/** | /** | ||||
* ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang. | |||||
* | |||||
* If we send a write we can't be sure it took until we can read back | |||||
* that same register. It can be a problem as some of the feilds may | |||||
* for valid reasons change inbetween the time wrote the register and | |||||
* we read it again to verify. So this function check everything we | |||||
* can check and then assumes it worked. | |||||
* | |||||
* @u32 in_reg - The register cmd for the bit-bang read. | |||||
* @u32 out_reg - The register returned from a bit-bang read. | |||||
**/ | |||||
bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg) | |||||
{ | |||||
u32 mask; | |||||
/* Page must match for all control pages */ | |||||
if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M)) | |||||
return FALSE; | |||||
switch (in_reg & BYPASS_PAGE_M) { | |||||
case BYPASS_PAGE_CTL0: | |||||
/* All the following can't change since the last write | |||||
* - All the event actions | |||||
* - The timeout value | |||||
*/ | |||||
mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M | | |||||
BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M | | |||||
BYPASS_WDTIMEOUT_M | | |||||
BYPASS_WDT_VALUE_M; | |||||
if ((out_reg & mask) != (in_reg & mask)) | |||||
return FALSE; | |||||
/* 0x0 is never a valid value for bypass status */ | |||||
if (!(out_reg & BYPASS_STATUS_OFF_M)) | |||||
return FALSE; | |||||
break; | |||||
case BYPASS_PAGE_CTL1: | |||||
/* All the following can't change since the last write | |||||
* - time valid bit | |||||
* - time we last sent | |||||
*/ | |||||
mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M; | |||||
if ((out_reg & mask) != (in_reg & mask)) | |||||
return FALSE; | |||||
break; | |||||
case BYPASS_PAGE_CTL2: | |||||
/* All we can check in this page is control number | |||||
* which is already done above. | |||||
*/ | |||||
break; | |||||
} | |||||
/* We are as sure as we can be return TRUE */ | |||||
return TRUE; | |||||
} | |||||
/** | |||||
* ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter. | |||||
* | |||||
* @hw: pointer to hardware structure | |||||
* @cmd: The control word we are setting. | |||||
* @event: The event we are setting in the FW. This also happens to | |||||
* be the mask for the event we are setting (handy) | |||||
* @action: The action we set the event to in the FW. This is in a | |||||
* bit field that happens to be what we want to put in | |||||
* the event spot (also handy) | |||||
**/ | |||||
s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event, | |||||
u32 action) | |||||
{ | |||||
u32 by_ctl = 0; | |||||
u32 cmd, verify; | |||||
u32 count = 0; | |||||
/* Get current values */ | |||||
cmd = ctrl; /* just reading only need control number */ | |||||
if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) | |||||
return IXGBE_ERR_INVALID_ARGUMENT; | |||||
/* Set to new action */ | |||||
cmd = (by_ctl & ~event) | BYPASS_WE | action; | |||||
if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) | |||||
return IXGBE_ERR_INVALID_ARGUMENT; | |||||
/* Page 0 force a FW eeprom write which is slow so verify */ | |||||
if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) { | |||||
verify = BYPASS_PAGE_CTL0; | |||||
do { | |||||
if (count++ > 5) | |||||
return IXGBE_BYPASS_FW_WRITE_FAILURE; | |||||
if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl)) | |||||
return IXGBE_ERR_INVALID_ARGUMENT; | |||||
} while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl)); | |||||
} else { | |||||
/* We have give the FW time for the write to stick */ | |||||
msec_delay(100); | |||||
} | |||||
return IXGBE_SUCCESS; | |||||
} | |||||
/** | |||||
* ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom addres. | |||||
* | |||||
* @hw: pointer to hardware structure | |||||
* @addr: The bypass eeprom address to read. | |||||
* @value: The 8b of data at the address above. | |||||
**/ | |||||
s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value) | |||||
{ | |||||
u32 cmd; | |||||
u32 status; | |||||
/* send the request */ | |||||
cmd = BYPASS_PAGE_CTL2 | BYPASS_WE; | |||||
cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M; | |||||
if (ixgbe_bypass_rw_generic(hw, cmd, &status)) | |||||
return IXGBE_ERR_INVALID_ARGUMENT; | |||||
/* We have give the FW time for the write to stick */ | |||||
msec_delay(100); | |||||
/* now read the results */ | |||||
cmd &= ~BYPASS_WE; | |||||
if (ixgbe_bypass_rw_generic(hw, cmd, &status)) | |||||
return IXGBE_ERR_INVALID_ARGUMENT; | |||||
*value = status & BYPASS_CTL2_DATA_M; | |||||
return IXGBE_SUCCESS; | |||||
} | |||||
/** | |||||
* ixgbe_dcb_get_rtrup2tc_generic - read rtrup2tc reg | * ixgbe_dcb_get_rtrup2tc_generic - read rtrup2tc reg | ||||
* @hw: pointer to hardware structure | * @hw: pointer to hardware structure | ||||
* @map: pointer to u8 arr for returning map | * @map: pointer to u8 arr for returning map | ||||
* | * | ||||
* Read the rtrup2tc HW register and resolve its content into map | * Read the rtrup2tc HW register and resolve its content into map | ||||
**/ | **/ | ||||
void ixgbe_dcb_get_rtrup2tc_generic(struct ixgbe_hw *hw, u8 *map) | void ixgbe_dcb_get_rtrup2tc_generic(struct ixgbe_hw *hw, u8 *map) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Lines | s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, | ||||
/* Try each speed one by one, highest priority first. We do this in | /* Try each speed one by one, highest priority first. We do this in | ||||
* software because 10Gb fiber doesn't support speed autonegotiation. | * software because 10Gb fiber doesn't support speed autonegotiation. | ||||
*/ | */ | ||||
if (speed & IXGBE_LINK_SPEED_10GB_FULL) { | if (speed & IXGBE_LINK_SPEED_10GB_FULL) { | ||||
speedcnt++; | speedcnt++; | ||||
highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; | 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 */ | /* Set the module link speed */ | ||||
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: | case ixgbe_media_type_fiber: | ||||
ixgbe_set_rate_select_speed(hw, | ixgbe_set_rate_select_speed(hw, | ||||
IXGBE_LINK_SPEED_10GB_FULL); | IXGBE_LINK_SPEED_10GB_FULL); | ||||
break; | break; | ||||
case ixgbe_media_type_fiber_qsfp: | case ixgbe_media_type_fiber_qsfp: | ||||
Show All 34 Lines | for (i = 0; i < 5; i++) { | ||||
goto out; | goto out; | ||||
} | } | ||||
} | } | ||||
if (speed & IXGBE_LINK_SPEED_1GB_FULL) { | if (speed & IXGBE_LINK_SPEED_1GB_FULL) { | ||||
speedcnt++; | speedcnt++; | ||||
if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) | if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) | ||||
highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; | 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 */ | /* Set the module link speed */ | ||||
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: | case ixgbe_media_type_fiber: | ||||
ixgbe_set_rate_select_speed(hw, | ixgbe_set_rate_select_speed(hw, | ||||
IXGBE_LINK_SPEED_1GB_FULL); | IXGBE_LINK_SPEED_1GB_FULL); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 120 Lines • Show Last 20 Lines |
bracing