Commit 59dd45d5 authored by Sebastian Basierski's avatar Sebastian Basierski Committed by Jeff Kirsher
Browse files

ixgbe: firmware recovery mode



Add check for FW NVM recovery mode during driver initialization and
service task. If in recovery mode, log message and unregister device

Signed-off-by: default avatarSebastian Basierski <sebastianx.basierski@intel.com>
Tested-by: default avatarDon Buchholz <donald.buchholz@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 050cdc6c
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -3484,6 +3484,17 @@ void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf)
	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
}

/**
 * ixgbe_fw_recovery_mode - Check if in FW NVM recovery mode
 * @hw: pointer to hardware structure
 */
bool ixgbe_fw_recovery_mode(struct ixgbe_hw *hw)
{
	if (hw->mac.ops.fw_recovery_mode)
		return hw->mac.ops.fw_recovery_mode(hw);
	return false;
}

/**
 *  ixgbe_get_device_caps_generic - Get additional device capabilities
 *  @hw: pointer to hardware structure
+41 −0
Original line number Diff line number Diff line
@@ -7774,6 +7774,33 @@ static void ixgbe_reset_subtask(struct ixgbe_adapter *adapter)
	rtnl_unlock();
}

/**
 * ixgbe_check_fw_error - Check firmware for errors
 * @adapter: the adapter private structure
 *
 * Check firmware errors in register FWSM
 */
static bool ixgbe_check_fw_error(struct ixgbe_adapter *adapter)
{
	struct ixgbe_hw *hw = &adapter->hw;
	u32 fwsm;

	/* read fwsm.ext_err_ind register and log errors */
	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));

	if (fwsm & IXGBE_FWSM_EXT_ERR_IND_MASK ||
	    !(fwsm & IXGBE_FWSM_FW_VAL_BIT))
		e_dev_warn("Warning firmware error detected FWSM: 0x%08X\n",
			   fwsm);

	if (hw->mac.ops.fw_recovery_mode && hw->mac.ops.fw_recovery_mode(hw)) {
		e_dev_err("Firmware recovery mode detected. Limiting functionality. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode.\n");
		return true;
	}

	return false;
}

/**
 * ixgbe_service_task - manages and runs subtasks
 * @work: pointer to work_struct containing our data
@@ -7792,6 +7819,15 @@ static void ixgbe_service_task(struct work_struct *work)
		ixgbe_service_event_complete(adapter);
		return;
	}
	if (ixgbe_check_fw_error(adapter)) {
		if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
			rtnl_lock();
			unregister_netdev(adapter->netdev);
			rtnl_unlock();
		}
		ixgbe_service_event_complete(adapter);
		return;
	}
	if (adapter->flags2 & IXGBE_FLAG2_UDP_TUN_REREG_NEEDED) {
		rtnl_lock();
		adapter->flags2 &= ~IXGBE_FLAG2_UDP_TUN_REREG_NEEDED;
@@ -10716,6 +10752,11 @@ skip_sriov:
	if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
		netdev->features |= NETIF_F_LRO;

	if (ixgbe_check_fw_error(adapter)) {
		err = -EIO;
		goto err_sw_init;
	}

	/* make sure the EEPROM is good */
	if (hw->eeprom.ops.validate_checksum(hw, NULL) < 0) {
		e_dev_err("The EEPROM Checksum Is Not Valid\n");
+4 −0
Original line number Diff line number Diff line
@@ -924,6 +924,9 @@ struct ixgbe_nvm_version {
/* Firmware Semaphore Register */
#define IXGBE_FWSM_MODE_MASK	0xE
#define IXGBE_FWSM_FW_MODE_PT	0x4
#define IXGBE_FWSM_FW_NVM_RECOVERY_MODE	BIT(5)
#define IXGBE_FWSM_EXT_ERR_IND_MASK	0x01F80000
#define IXGBE_FWSM_FW_VAL_BIT	BIT(15)

/* ARC Subsystem registers */
#define IXGBE_HICR      0x15F00
@@ -3461,6 +3464,7 @@ struct ixgbe_mac_operations {
			      const char *);
	s32 (*get_thermal_sensor_data)(struct ixgbe_hw *);
	s32 (*init_thermal_sensor_thresh)(struct ixgbe_hw *hw);
	bool (*fw_recovery_mode)(struct ixgbe_hw *hw);
	void (*disable_rx)(struct ixgbe_hw *hw);
	void (*enable_rx)(struct ixgbe_hw *hw);
	void (*set_source_address_pruning)(struct ixgbe_hw *, bool,
+15 −0
Original line number Diff line number Diff line
@@ -1247,6 +1247,20 @@ static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw)
	return 0;
}

/**
 * ixgbe_fw_recovery_mode - Check FW NVM recovery mode
 * @hw: pointer t hardware structure
 *
 * Returns true if in FW NVM recovery mode.
 */
static bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw)
{
	u32 fwsm;

	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
	return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE);
}

/** ixgbe_disable_rx_x550 - Disable RX unit
 *
 *  Enables the Rx DMA unit for x550
@@ -3816,6 +3830,7 @@ static s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
	.enable_rx_buff			= &ixgbe_enable_rx_buff_generic, \
	.get_thermal_sensor_data	= NULL, \
	.init_thermal_sensor_thresh	= NULL, \
	.fw_recovery_mode		= &ixgbe_fw_recovery_mode_X550, \
	.enable_rx			= &ixgbe_enable_rx_generic, \
	.disable_rx			= &ixgbe_disable_rx_x550, \