|
@@ -353,23 +353,32 @@ static void ixgbe_remove_adapter(struct ixgbe_hw *hw)
|
|
ixgbe_service_event_schedule(adapter);
|
|
ixgbe_service_event_schedule(adapter);
|
|
}
|
|
}
|
|
|
|
|
|
-static void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
|
|
|
|
|
|
+static u32 ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
|
|
{
|
|
{
|
|
|
|
+ u8 __iomem *reg_addr;
|
|
u32 value;
|
|
u32 value;
|
|
|
|
+ int i;
|
|
|
|
|
|
- /* The following check not only optimizes a bit by not
|
|
|
|
- * performing a read on the status register when the
|
|
|
|
- * register just read was a status register read that
|
|
|
|
- * returned IXGBE_FAILED_READ_REG. It also blocks any
|
|
|
|
- * potential recursion.
|
|
|
|
|
|
+ reg_addr = READ_ONCE(hw->hw_addr);
|
|
|
|
+ if (ixgbe_removed(reg_addr))
|
|
|
|
+ return IXGBE_FAILED_READ_REG;
|
|
|
|
+
|
|
|
|
+ /* Register read of 0xFFFFFFF can indicate the adapter has been removed,
|
|
|
|
+ * so perform several status register reads to determine if the adapter
|
|
|
|
+ * has been removed.
|
|
*/
|
|
*/
|
|
- if (reg == IXGBE_STATUS) {
|
|
|
|
- ixgbe_remove_adapter(hw);
|
|
|
|
- return;
|
|
|
|
|
|
+ for (i = 0; i < IXGBE_FAILED_READ_RETRIES; i++) {
|
|
|
|
+ value = readl(reg_addr + IXGBE_STATUS);
|
|
|
|
+ if (value != IXGBE_FAILED_READ_REG)
|
|
|
|
+ break;
|
|
|
|
+ mdelay(3);
|
|
}
|
|
}
|
|
- value = ixgbe_read_reg(hw, IXGBE_STATUS);
|
|
|
|
|
|
+
|
|
if (value == IXGBE_FAILED_READ_REG)
|
|
if (value == IXGBE_FAILED_READ_REG)
|
|
ixgbe_remove_adapter(hw);
|
|
ixgbe_remove_adapter(hw);
|
|
|
|
+ else
|
|
|
|
+ value = readl(reg_addr + reg);
|
|
|
|
+ return value;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -415,7 +424,7 @@ u32 ixgbe_read_reg(struct ixgbe_hw *hw, u32 reg)
|
|
writes_completed:
|
|
writes_completed:
|
|
value = readl(reg_addr + reg);
|
|
value = readl(reg_addr + reg);
|
|
if (unlikely(value == IXGBE_FAILED_READ_REG))
|
|
if (unlikely(value == IXGBE_FAILED_READ_REG))
|
|
- ixgbe_check_remove(hw, reg);
|
|
|
|
|
|
+ value = ixgbe_check_remove(hw, reg);
|
|
return value;
|
|
return value;
|
|
}
|
|
}
|
|
|
|
|