diff options
author | Don Skidmore <donald.c.skidmore@intel.com> | 2014-02-27 20:32:41 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-02-28 12:40:56 -0500 |
commit | 429d6a3be9b656f9400356f026328f3a2e900887 (patch) | |
tree | 074535acb391a3918afa797528df1d725f4bd286 /drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c | |
parent | 1f86c983bebbb226b69f986bdc7b8b4299a2004c (diff) | |
download | blackbird-op-linux-429d6a3be9b656f9400356f026328f3a2e900887.tar.gz blackbird-op-linux-429d6a3be9b656f9400356f026328f3a2e900887.zip |
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>
Diffstat (limited to 'drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c')
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c | 171 |
1 files changed, 92 insertions, 79 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index edda6814108c..1c31d2d62f75 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -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 = { |