Commit 6c1b4af8 authored by Jedrzej Jagielski's avatar Jedrzej Jagielski Committed by Tony Nguyen
Browse files

ixgbe: Refactor overtemp event handling



Currently ixgbe driver is notified of overheating events
via internal IXGBE_ERR_OVERTEMP error code.

Change the approach for handle_lasi() to use freshly introduced
is_overtemp function parameter which set when such event occurs.
Change check_overtemp() to bool and return true if overtemp
event occurs.

Reviewed-by: default avatarPrzemek Kitszel <przemyslaw.kitszel@intel.com>
Signed-off-by: default avatarJedrzej Jagielski <jedrzej.jagielski@intel.com>
Reviewed-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Tested-by: Sunitha Mekala <sunithax.d.mekala@intel.com> (A Contingent worker at Intel)
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 738808ae
Loading
Loading
Loading
Loading
+6 −10
Original line number Diff line number Diff line
@@ -2756,7 +2756,6 @@ static void ixgbe_check_overtemp_subtask(struct ixgbe_adapter *adapter)
{
	struct ixgbe_hw *hw = &adapter->hw;
	u32 eicr = adapter->interrupt_event;
	s32 rc;

	if (test_bit(__IXGBE_DOWN, &adapter->state))
		return;
@@ -2790,14 +2789,13 @@ static void ixgbe_check_overtemp_subtask(struct ixgbe_adapter *adapter)
		}

		/* Check if this is not due to overtemp */
		if (hw->phy.ops.check_overtemp(hw) != IXGBE_ERR_OVERTEMP)
		if (!hw->phy.ops.check_overtemp(hw))
			return;

		break;
	case IXGBE_DEV_ID_X550EM_A_1G_T:
	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
		rc = hw->phy.ops.check_overtemp(hw);
		if (rc != IXGBE_ERR_OVERTEMP)
		if (!hw->phy.ops.check_overtemp(hw))
			return;
		break;
	default:
@@ -7938,7 +7936,7 @@ static void ixgbe_service_timer(struct timer_list *t)
static void ixgbe_phy_interrupt_subtask(struct ixgbe_adapter *adapter)
{
	struct ixgbe_hw *hw = &adapter->hw;
	u32 status;
	bool overtemp;

	if (!(adapter->flags2 & IXGBE_FLAG2_PHY_INTERRUPT))
		return;
@@ -7948,10 +7946,8 @@ static void ixgbe_phy_interrupt_subtask(struct ixgbe_adapter *adapter)
	if (!hw->phy.ops.handle_lasi)
		return;

	status = hw->phy.ops.handle_lasi(&adapter->hw);
	if (status != IXGBE_ERR_OVERTEMP)
		return;

	hw->phy.ops.handle_lasi(&adapter->hw, &overtemp);
	if (overtemp)
		e_crit(drv, "%s\n", ixgbe_overheat_msg);
}

+11 −10
Original line number Diff line number Diff line
@@ -407,8 +407,7 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
		return status;

	/* Don't reset PHY if it's shut down due to overtemp. */
	if (!hw->phy.reset_if_overtemp &&
	    (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw)))
	if (!hw->phy.reset_if_overtemp && hw->phy.ops.check_overtemp(hw))
		return 0;

	/* Blocked by MNG FW so bail */
@@ -2746,22 +2745,24 @@ static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw)
 *  @hw: pointer to hardware structure
 *
 *  Checks if the LASI temp alarm status was triggered due to overtemp
 *
 *  Return true when an overtemp event detected, otherwise false.
 **/
s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw)
bool ixgbe_tn_check_overtemp(struct ixgbe_hw *hw)
{
	u16 phy_data = 0;
	u32 status;

	if (hw->device_id != IXGBE_DEV_ID_82599_T3_LOM)
		return 0;
		return false;

	/* Check that the LASI temp alarm status was triggered */
	hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG,
	status = hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG,
				      MDIO_MMD_PMAPMD, &phy_data);
	if (status)
		return false;

	if (!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM))
		return 0;

	return IXGBE_ERR_OVERTEMP;
	return !!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM);
}

/** ixgbe_set_copper_phy_power - Control power for copper phy
+1 −1
Original line number Diff line number Diff line
@@ -155,7 +155,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
					u16 *list_offset,
					u16 *data_offset);
s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw);
bool ixgbe_tn_check_overtemp(struct ixgbe_hw *hw);
s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
				u8 dev_addr, u8 *data);
s32 ixgbe_read_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
+2 −2
Original line number Diff line number Diff line
@@ -3509,10 +3509,10 @@ struct ixgbe_phy_operations {
	s32 (*read_i2c_sff8472)(struct ixgbe_hw *, u8 , u8 *);
	s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *);
	s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8);
	s32 (*check_overtemp)(struct ixgbe_hw *);
	bool (*check_overtemp)(struct ixgbe_hw *);
	s32 (*set_phy_power)(struct ixgbe_hw *, bool on);
	s32 (*enter_lplu)(struct ixgbe_hw *);
	s32 (*handle_lasi)(struct ixgbe_hw *hw);
	s32 (*handle_lasi)(struct ixgbe_hw *hw, bool *);
	s32 (*read_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr,
				      u8 *value);
	s32 (*write_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr,
+23 −18
Original line number Diff line number Diff line
@@ -600,8 +600,10 @@ static s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw)
	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup);
	if (rc)
		return rc;

	if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN)
		return IXGBE_ERR_OVERTEMP;
		return -EIO;

	return 0;
}

@@ -2367,18 +2369,18 @@ static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
 * @hw: pointer to hardware structure
 * @lsc: pointer to boolean flag which indicates whether external Base T
 *	 PHY interrupt is lsc
 * @is_overtemp: indicate whether an overtemp event encountered
 *
 * Determime if external Base T PHY interrupt cause is high temperature
 * failure alarm or link status change.
 *
 * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
 * failure alarm, else return PHY access status.
 **/
static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc,
				       bool *is_overtemp)
{
	u32 status;
	u16 reg;

	*is_overtemp = false;
	*lsc = false;

	/* Vendor alarm triggered */
@@ -2410,7 +2412,8 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) {
		/* power down the PHY in case the PHY FW didn't already */
		ixgbe_set_copper_phy_power(hw, false);
		return IXGBE_ERR_OVERTEMP;
		*is_overtemp = true;
		return -EIO;
	}
	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
		/*  device fault alarm triggered */
@@ -2424,7 +2427,8 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
		if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) {
			/* power down the PHY in case the PHY FW didn't */
			ixgbe_set_copper_phy_power(hw, false);
			return IXGBE_ERR_OVERTEMP;
			*is_overtemp = true;
			return -EIO;
		}
	}

@@ -2460,12 +2464,12 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
 **/
static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
{
	bool lsc, overtemp;
	u32 status;
	u16 reg;
	bool lsc;

	/* Clear interrupt flags */
	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, &overtemp);

	/* Enable link status change alarm */

@@ -2544,21 +2548,20 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
/**
 * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt
 * @hw: pointer to hardware structure
 * @is_overtemp: indicate whether an overtemp event encountered
 *
 * Handle external Base T PHY interrupt. If high temperature
 * failure alarm then return error, else if link status change
 * then setup internal/external PHY link
 *
 * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
 * failure alarm, else return PHY access status.
 **/
static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw)
static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw,
					  bool *is_overtemp)
{
	struct ixgbe_phy_info *phy = &hw->phy;
	bool lsc;
	u32 status;

	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, is_overtemp);
	if (status)
		return status;

@@ -3185,21 +3188,23 @@ static s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw)
/**
 * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp
 * @hw: pointer to hardware structure
 *
 * Return true when an overtemp event detected, otherwise false.
 */
static s32 ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)
static bool ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)
{
	u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
	s32 rc;

	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store);
	if (rc)
		return rc;
		return false;

	if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) {
		ixgbe_shutdown_fw_phy(hw);
		return IXGBE_ERR_OVERTEMP;
		return true;
	}
	return 0;
	return false;
}

/**