void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw,
                                      ixgbe_link_speed speed);
 
+#define IXGBE_FAILED_READ_RETRIES 5
 #define IXGBE_FAILED_READ_REG 0xffffffffU
 #define IXGBE_FAILED_READ_CFG_DWORD 0xffffffffU
 #define IXGBE_FAILED_READ_CFG_WORD 0xffffU
 
                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;
+       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)
                ixgbe_remove_adapter(hw);
+       else
+               value = readl(reg_addr + reg);
+       return value;
 }
 
 /**
 writes_completed:
        value = readl(reg_addr + reg);
        if (unlikely(value == IXGBE_FAILED_READ_REG))
-               ixgbe_check_remove(hw, reg);
+               value = ixgbe_check_remove(hw, reg);
        return value;
 }