|
@@ -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");
|