ixgbe: collect all 82599 AUTOC code in one function

When reading or writing to the AUTOC register on 82599 devices we need to
preform various operations that aren't needed for other MAC types.  This
patch will collect all of that code into one place to minimize MAC checks
in common code paths.

While doing this I also clean up some cases where we weren't holding the
SW/FW semaphore during a read/modify/write of AUTOC.

Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Don Skidmore 2014-02-27 20:32:41 -08:00 committed by David S. Miller
parent 1f86c983be
commit 429d6a3be9
7 changed files with 161 additions and 141 deletions

View File

@ -884,7 +884,6 @@ s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
u16 soft_id);
void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
union ixgbe_atr_input *mask);
bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
void ixgbe_set_rx_mode(struct net_device *netdev);
#ifdef CONFIG_IXGBE_DCB
void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter);

View File

@ -1316,6 +1316,8 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
.get_thermal_sensor_data = NULL,
.init_thermal_sensor_thresh = NULL,
.mng_fw_enabled = NULL,
.prot_autoc_read = &prot_autoc_read_generic,
.prot_autoc_write = &prot_autoc_write_generic,
};
static struct ixgbe_eeprom_operations eeprom_ops_82598 = {

View File

@ -63,6 +63,8 @@ static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 *data);
static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 data);
static s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
static bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
{
@ -122,7 +124,6 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
{
s32 ret_val = 0;
u16 list_offset, data_offset, data_value;
bool got_lock = false;
if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
ixgbe_init_mac_link_ops_82599(hw);
@ -160,30 +161,10 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
usleep_range(hw->eeprom.semaphore_delay * 1000,
hw->eeprom.semaphore_delay * 2000);
/* Need SW/FW semaphore around AUTOC writes if LESM on,
* likewise reset_pipeline requires lock as it also writes
* AUTOC.
*/
if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
ret_val = hw->mac.ops.acquire_swfw_sync(hw,
IXGBE_GSSR_MAC_CSR_SM);
if (ret_val)
goto setup_sfp_out;
got_lock = true;
}
/* Restart DSP and set SFI mode */
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, ((hw->mac.orig_autoc) |
IXGBE_AUTOC_LMS_10G_SERIAL));
hw->mac.cached_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
ret_val = ixgbe_reset_pipeline_82599(hw);
if (got_lock) {
hw->mac.ops.release_swfw_sync(hw,
IXGBE_GSSR_MAC_CSR_SM);
got_lock = false;
}
ret_val = hw->mac.ops.prot_autoc_write(hw,
hw->mac.orig_autoc | IXGBE_AUTOC_LMS_10G_SERIAL,
false);
if (ret_val) {
hw_dbg(hw, " sfp module setup not complete\n");
@ -207,6 +188,74 @@ setup_sfp_err:
return IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
}
/**
* prot_autoc_read_82599 - Hides MAC differences needed for AUTOC read
* @hw: pointer to hardware structure
* @locked: Return the if we locked for this read.
* @reg_val: Value we read from AUTOC
*
* For this part (82599) we need to wrap read-modify-writes with a possible
* FW/SW lock. It is assumed this lock will be freed with the next
* prot_autoc_write_82599(). Note, that locked can only be true in cases
* where this function doesn't return an error.
**/
static s32 prot_autoc_read_82599(struct ixgbe_hw *hw, bool *locked,
u32 *reg_val)
{
s32 ret_val;
*locked = false;
/* If LESM is on then we need to hold the SW/FW semaphore. */
if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
ret_val = hw->mac.ops.acquire_swfw_sync(hw,
IXGBE_GSSR_MAC_CSR_SM);
if (!ret_val)
return IXGBE_ERR_SWFW_SYNC;
*locked = true;
}
*reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC);
return 0;
}
/**
* prot_autoc_write_82599 - 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 proc_autoc_read_82599.
*
* This part (82599) may need to hold a the SW/FW lock around all writes to
* AUTOC. Likewise after a write we need to do a pipeline reset.
**/
static s32 prot_autoc_write_82599(struct ixgbe_hw *hw, u32 autoc, bool locked)
{
s32 ret_val = 0;
/* We only need to get the lock if:
* - We didn't do it already (in the read part of a read-modify-write)
* - LESM is enabled.
*/
if (!locked && ixgbe_verify_lesm_fw_enabled_82599(hw)) {
ret_val = hw->mac.ops.acquire_swfw_sync(hw,
IXGBE_GSSR_MAC_CSR_SM);
if (!ret_val)
return IXGBE_ERR_SWFW_SYNC;
}
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
ret_val = ixgbe_reset_pipeline_82599(hw);
/* Free the SW/FW semaphore as we either grabbed it here or
* already had it when this function was called.
*/
if (locked)
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
return ret_val;
}
static s32 ixgbe_get_invariants_82599(struct ixgbe_hw *hw)
{
struct ixgbe_mac_info *mac = &hw->mac;
@ -966,7 +1015,6 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
u32 links_reg;
u32 i;
ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
bool got_lock = false;
bool autoneg = false;
/* Check to see if speed passed in is supported. */
@ -989,7 +1037,7 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
orig_autoc = autoc;
start_autoc = hw->mac.cached_autoc;
start_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
link_mode = autoc & IXGBE_AUTOC_LMS_MASK;
pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
@ -1030,27 +1078,10 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
}
if (autoc != start_autoc) {
/* Need SW/FW semaphore around AUTOC writes if LESM is on,
* likewise reset_pipeline requires us to hold this lock as
* it also writes to AUTOC.
*/
if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
status = hw->mac.ops.acquire_swfw_sync(hw,
IXGBE_GSSR_MAC_CSR_SM);
if (status != 0)
goto out;
got_lock = true;
}
/* Restart link */
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
hw->mac.cached_autoc = autoc;
ixgbe_reset_pipeline_82599(hw);
if (got_lock)
hw->mac.ops.release_swfw_sync(hw,
IXGBE_GSSR_MAC_CSR_SM);
status = hw->mac.ops.prot_autoc_write(hw, autoc, false);
if (!status)
goto out;
/* Only poll for autoneg to complete if specified to do so */
if (autoneg_wait_to_complete) {
@ -1117,7 +1148,7 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
{
ixgbe_link_speed link_speed;
s32 status;
u32 ctrl, i, autoc2;
u32 ctrl, i, autoc, autoc2;
u32 curr_lms;
bool link_up = false;
@ -1151,11 +1182,7 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
hw->phy.ops.reset(hw);
/* remember AUTOC from before we reset */
if (hw->mac.cached_autoc)
curr_lms = hw->mac.cached_autoc & IXGBE_AUTOC_LMS_MASK;
else
curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) &
IXGBE_AUTOC_LMS_MASK;
curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) & IXGBE_AUTOC_LMS_MASK;
mac_reset_top:
/*
@ -1205,7 +1232,7 @@ mac_reset_top:
* stored off yet. Otherwise restore the stored original
* values since the reset operation sets back to defaults.
*/
hw->mac.cached_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
/* Enable link if disabled in NVM */
@ -1216,7 +1243,7 @@ mac_reset_top:
}
if (hw->mac.orig_link_settings_stored == false) {
hw->mac.orig_autoc = hw->mac.cached_autoc;
hw->mac.orig_autoc = autoc;
hw->mac.orig_autoc2 = autoc2;
hw->mac.orig_link_settings_stored = true;
} else {
@ -1233,28 +1260,12 @@ mac_reset_top:
(hw->mac.orig_autoc & ~IXGBE_AUTOC_LMS_MASK) |
curr_lms;
if (hw->mac.cached_autoc != hw->mac.orig_autoc) {
/* Need SW/FW semaphore around AUTOC writes if LESM is
* on, likewise reset_pipeline requires us to hold
* this lock as it also writes to AUTOC.
*/
bool got_lock = false;
if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
status = hw->mac.ops.acquire_swfw_sync(hw,
IXGBE_GSSR_MAC_CSR_SM);
if (status)
goto reset_hw_out;
got_lock = true;
}
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
hw->mac.cached_autoc = hw->mac.orig_autoc;
ixgbe_reset_pipeline_82599(hw);
if (got_lock)
hw->mac.ops.release_swfw_sync(hw,
IXGBE_GSSR_MAC_CSR_SM);
if (autoc != hw->mac.orig_autoc) {
status = hw->mac.ops.prot_autoc_write(hw,
hw->mac.orig_autoc,
false);
if (!status)
goto reset_hw_out;
}
if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
@ -2260,7 +2271,7 @@ fw_version_err:
* Returns true if the LESM FW module is present and enabled. Otherwise
* returns false. Smart Speed must be disabled if LESM FW module is enabled.
**/
bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
{
bool lesm_enabled = false;
u16 fw_offset, fw_lesm_param_offset, fw_lesm_state;
@ -2366,7 +2377,7 @@ static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
* full pipeline reset. Note - We must hold the SW/FW semaphore before writing
* to AUTOC, so this function assumes the semaphore is held.
**/
s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
static s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
{
s32 ret_val;
u32 anlp1_reg = 0;
@ -2380,7 +2391,7 @@ s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
IXGBE_WRITE_FLUSH(hw);
}
autoc_reg = hw->mac.cached_autoc;
autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
autoc_reg |= IXGBE_AUTOC_AN_RESTART;
/* Write AUTOC register with toggled LMS[2] bit and Restart_AN */
@ -2566,6 +2577,8 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
.get_thermal_sensor_data = &ixgbe_get_thermal_sensor_data_generic,
.init_thermal_sensor_thresh = &ixgbe_init_thermal_sensor_thresh_generic,
.mng_fw_enabled = &ixgbe_mng_enabled,
.prot_autoc_read = &prot_autoc_read_82599,
.prot_autoc_write = &prot_autoc_write_82599,
};
static struct ixgbe_eeprom_operations eeprom_ops_82599 = {

View File

@ -114,7 +114,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
s32 ret_val = 0;
u32 reg = 0, reg_bp = 0;
u16 reg_cu = 0;
bool got_lock = false;
bool locked = false;
/*
* Validate the requested mode. Strict IEEE mode does not allow
@ -139,11 +139,17 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
* we link at 10G, the 1G advertisement is harmless and vice versa.
*/
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, &reg_bp);
if (!ret_val)
goto out;
/* only backplane uses autoc so fall though */
case ixgbe_media_type_fiber_fixed:
case ixgbe_media_type_fiber:
case ixgbe_media_type_backplane:
reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
break;
case ixgbe_media_type_copper:
hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
@ -240,27 +246,12 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
* LESM is on, likewise reset_pipeline requries the lock as
* it also writes AUTOC.
*/
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)
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);
ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked);
if (ret_val)
goto out;
} 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, MDIO_AN_ADVERTISE,
MDIO_MMD_AN, reg_cu);
}
@ -2613,6 +2604,35 @@ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
ixgbe_release_eeprom_semaphore(hw);
}
/**
* prot_autoc_read_generic - Hides MAC differences needed for AUTOC read
* @hw: pointer to hardware structure
* @reg_val: Value we read from AUTOC
* @locked: bool to indicate whether the SW/FW lock should be taken. Never
* true in this the generic case.
*
* 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 0;
}
/**
* 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.
**/
s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked)
{
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val);
return 0;
}
/**
* ixgbe_disable_rx_buff_generic - Stops the receive data path
* @hw: pointer to hardware structure
@ -2691,6 +2711,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
s32 ret_val = 0;
bool locked = false;
/*
* Link must be up to auto-blink the LEDs;
@ -2699,28 +2720,19 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
hw->mac.ops.check_link(hw, &speed, &link_up, false);
if (!link_up) {
/* Need the SW/FW semaphore around AUTOC writes if 82599 and
* LESM is on.
*/
bool got_lock = false;
ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
if (!ret_val)
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)
goto out;
got_lock = true;
}
autoc_reg |= IXGBE_AUTOC_AN_RESTART;
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)
goto out;
IXGBE_WRITE_FLUSH(hw);
if (got_lock)
hw->mac.ops.release_swfw_sync(hw,
IXGBE_GSSR_MAC_CSR_SM);
usleep_range(10000, 20000);
}
@ -2740,33 +2752,21 @@ out:
**/
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);
s32 ret_val = 0;
bool got_lock = false;
bool locked = false;
/* 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)
goto out;
got_lock = true;
}
ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
if (!ret_val)
goto out;
autoc_reg &= ~IXGBE_AUTOC_FLU;
autoc_reg |= IXGBE_AUTOC_AN_RESTART;
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
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);
ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
if (!ret_val)
goto out;
led_reg &= ~IXGBE_LED_MODE_MASK(index);
led_reg &= ~IXGBE_LED_BLINK(index);

View File

@ -98,6 +98,10 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw,
bool *link_up, bool link_up_wait_to_complete);
s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
u16 *wwpn_prefix);
s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *, u32 *reg_val);
s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked);
s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index);
void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf);
@ -109,7 +113,6 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw);
void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
u32 headroom, int strategy);
s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
#define IXGBE_I2C_THERMAL_SENSOR_ADDR 0xF8
#define IXGBE_EMC_INTERNAL_DATA 0x00

View File

@ -2870,6 +2870,8 @@ struct ixgbe_mac_operations {
s32 (*enable_rx_dma)(struct ixgbe_hw *, u32);
s32 (*acquire_swfw_sync)(struct ixgbe_hw *, u16);
void (*release_swfw_sync)(struct ixgbe_hw *, u16);
s32 (*prot_autoc_read)(struct ixgbe_hw *, bool *, u32 *);
s32 (*prot_autoc_write)(struct ixgbe_hw *, u32, bool);
/* Link */
void (*disable_tx_laser)(struct ixgbe_hw *);
@ -2969,7 +2971,6 @@ struct ixgbe_mac_info {
u32 max_tx_queues;
u32 max_rx_queues;
u32 orig_autoc;
u32 cached_autoc;
u32 orig_autoc2;
bool orig_link_settings_stored;
bool autotry_restart;

View File

@ -855,6 +855,8 @@ static struct ixgbe_mac_operations mac_ops_X540 = {
.get_thermal_sensor_data = NULL,
.init_thermal_sensor_thresh = NULL,
.mng_fw_enabled = NULL,
.prot_autoc_read = &prot_autoc_read_generic,
.prot_autoc_write = &prot_autoc_write_generic,
};
static struct ixgbe_eeprom_operations eeprom_ops_X540 = {