Commit ae14a1d8 authored by Mark Rustad's avatar Mark Rustad Committed by Jeff Kirsher

ixgbe: Fix IOSF SB access issues

IOSF is the Intel On-chip System Fabric used in SOCs. IOSF SB is
the IOSF SideBand message interface. This patch serializes IOSF SB
access using both phy bits in the SWFW_SEMAPHORE register. It also
adds a helper function to wait for IOSF SB accesses to complete.
Use the new function to perform this wait before each access, as
specified in the datasheet, in addition to using it to wait for
IOSF SB read/write completion.
Signed-off-by: default avatarMark Rustad <mark.d.rustad@intel.com>
Tested-by: default avatarPhil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 30544af5
...@@ -103,6 +103,39 @@ static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) ...@@ -103,6 +103,39 @@ static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw)
return 0; return 0;
} }
/**
* ixgbe_iosf_wait - Wait for IOSF command completion
* @hw: pointer to hardware structure
* @ctrl: pointer to location to receive final IOSF control value
*
* Return: failing status on timeout
*
* Note: ctrl can be NULL if the IOSF control register value is not needed
*/
static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl)
{
u32 i, command;
/* Check every 10 usec to see if the address cycle completed.
* The SB IOSF BUSY bit will clear when the operation is
* complete.
*/
for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
if (!(command & IXGBE_SB_IOSF_CTRL_BUSY))
break;
usleep_range(10, 20);
}
if (ctrl)
*ctrl = command;
if (i == IXGBE_MDIO_COMMAND_TIMEOUT) {
hw_dbg(hw, "IOSF wait timed out\n");
return IXGBE_ERR_PHY;
}
return 0;
}
/** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the
* IOSF device * IOSF device
* @hw: pointer to hardware structure * @hw: pointer to hardware structure
...@@ -113,7 +146,17 @@ static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) ...@@ -113,7 +146,17 @@ static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw)
static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u32 *data) u32 device_type, u32 *data)
{ {
u32 i, command, error; u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
u32 command, error;
s32 ret;
ret = hw->mac.ops.acquire_swfw_sync(hw, gssr);
if (ret)
return ret;
ret = ixgbe_iosf_wait(hw, NULL);
if (ret)
goto out;
command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
(device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
...@@ -121,17 +164,7 @@ static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, ...@@ -121,17 +164,7 @@ static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
/* Write IOSF control register */ /* Write IOSF control register */
IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
/* Check every 10 usec to see if the address cycle completed. ret = ixgbe_iosf_wait(hw, &command);
* The SB IOSF BUSY bit will clear when the operation is
* complete
*/
for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
usleep_range(10, 20);
command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0)
break;
}
if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
...@@ -140,14 +173,12 @@ static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, ...@@ -140,14 +173,12 @@ static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
return IXGBE_ERR_PHY; return IXGBE_ERR_PHY;
} }
if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { if (!ret)
hw_dbg(hw, "Read timed out\n");
return IXGBE_ERR_PHY;
}
*data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA);
return 0; out:
hw->mac.ops.release_swfw_sync(hw, gssr);
return ret;
} }
/** ixgbe_read_ee_hostif_data_X550 - Read EEPROM word using a host interface /** ixgbe_read_ee_hostif_data_X550 - Read EEPROM word using a host interface
...@@ -789,7 +820,17 @@ static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, ...@@ -789,7 +820,17 @@ static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u32 data) u32 device_type, u32 data)
{ {
u32 i, command, error; u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
u32 command, error;
s32 ret;
ret = hw->mac.ops.acquire_swfw_sync(hw, gssr);
if (ret)
return ret;
ret = ixgbe_iosf_wait(hw, NULL);
if (ret)
goto out;
command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
(device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
...@@ -800,17 +841,7 @@ static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, ...@@ -800,17 +841,7 @@ static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
/* Write IOSF data register */ /* Write IOSF data register */
IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data);
/* Check every 10 usec to see if the address cycle completed. ret = ixgbe_iosf_wait(hw, &command);
* The SB IOSF BUSY bit will clear when the operation is
* complete
*/
for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
usleep_range(10, 20);
command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0)
break;
}
if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
...@@ -819,12 +850,9 @@ static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, ...@@ -819,12 +850,9 @@ static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
return IXGBE_ERR_PHY; return IXGBE_ERR_PHY;
} }
if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { out:
hw_dbg(hw, "Write timed out\n"); hw->mac.ops.release_swfw_sync(hw, gssr);
return IXGBE_ERR_PHY; return ret;
}
return 0;
} }
/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment