Skip to content

Commit

Permalink
ixgbe: collect all 82599 AUTOC code in one function
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Don Skidmore authored and David S. Miller committed Feb 28, 2014
1 parent 1f86c98 commit 429d6a3
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 141 deletions.
1 change: 0 additions & 1 deletion drivers/net/ethernet/intel/ixgbe/ixgbe.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
171 changes: 92 additions & 79 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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");
Expand All @@ -207,6 +188,74 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
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;
Expand Down Expand Up @@ -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. */
Expand All @@ -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;

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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:
/*
Expand Down Expand Up @@ -1205,7 +1232,7 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
* 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 */
Expand All @@ -1216,7 +1243,7 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
}

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 {
Expand All @@ -1233,28 +1260,12 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
(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) !=
Expand Down Expand Up @@ -2260,7 +2271,7 @@ static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
* 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;
Expand Down Expand Up @@ -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;
Expand All @@ -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 */
Expand Down Expand Up @@ -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 = {
Expand Down
Loading

0 comments on commit 429d6a3

Please sign in to comment.