Skip to content

Commit 1aa3784

Browse files
pgreenwaJeff Kirsher
authored andcommitted
ixgbe: add status reg reads to ixgbe_check_remove
Add status register reads and delay between reads to ixgbe_check_remove. Registers can read 0xFFFFFFFF during PCI reset, which causes the driver to remove the adapter. The additional status register reads can reduce the chance of this race condition. If the status register is not 0xFFFFFFFF, then ixgbe_check_remove returns the value of the register being read. Signed-off-by: Paul Greenwalt <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent f452518 commit 1aa3784

File tree

2 files changed

+21
-11
lines changed

2 files changed

+21
-11
lines changed

drivers/net/ethernet/intel/ixgbe/ixgbe_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
154154
void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw,
155155
ixgbe_link_speed speed);
156156

157+
#define IXGBE_FAILED_READ_RETRIES 5
157158
#define IXGBE_FAILED_READ_REG 0xffffffffU
158159
#define IXGBE_FAILED_READ_CFG_DWORD 0xffffffffU
159160
#define IXGBE_FAILED_READ_CFG_WORD 0xffffU

drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -353,23 +353,32 @@ static void ixgbe_remove_adapter(struct ixgbe_hw *hw)
353353
ixgbe_service_event_schedule(adapter);
354354
}
355355

356-
static void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
356+
static u32 ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
357357
{
358+
u8 __iomem *reg_addr;
358359
u32 value;
360+
int i;
359361

360-
/* The following check not only optimizes a bit by not
361-
* performing a read on the status register when the
362-
* register just read was a status register read that
363-
* returned IXGBE_FAILED_READ_REG. It also blocks any
364-
* potential recursion.
362+
reg_addr = READ_ONCE(hw->hw_addr);
363+
if (ixgbe_removed(reg_addr))
364+
return IXGBE_FAILED_READ_REG;
365+
366+
/* Register read of 0xFFFFFFF can indicate the adapter has been removed,
367+
* so perform several status register reads to determine if the adapter
368+
* has been removed.
365369
*/
366-
if (reg == IXGBE_STATUS) {
367-
ixgbe_remove_adapter(hw);
368-
return;
370+
for (i = 0; i < IXGBE_FAILED_READ_RETRIES; i++) {
371+
value = readl(reg_addr + IXGBE_STATUS);
372+
if (value != IXGBE_FAILED_READ_REG)
373+
break;
374+
mdelay(3);
369375
}
370-
value = ixgbe_read_reg(hw, IXGBE_STATUS);
376+
371377
if (value == IXGBE_FAILED_READ_REG)
372378
ixgbe_remove_adapter(hw);
379+
else
380+
value = readl(reg_addr + reg);
381+
return value;
373382
}
374383

375384
/**
@@ -415,7 +424,7 @@ u32 ixgbe_read_reg(struct ixgbe_hw *hw, u32 reg)
415424
writes_completed:
416425
value = readl(reg_addr + reg);
417426
if (unlikely(value == IXGBE_FAILED_READ_REG))
418-
ixgbe_check_remove(hw, reg);
427+
value = ixgbe_check_remove(hw, reg);
419428
return value;
420429
}
421430

0 commit comments

Comments
 (0)