Skip to content

Commit

Permalink
ixgbe: Additional adapter removal checks
Browse files Browse the repository at this point in the history
Additional checks are needed for a detected removal not to cause
problems. Some involve simply avoiding a lot of stuff that can't
do anything good, and also cases where the phony return value can
cause problems. In addition, down the adapter when the removal is
sensed.

Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Mark Rustad authored and David S. Miller committed Jan 15, 2014
1 parent b12babd commit b0483c8
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
22 changes: 22 additions & 0 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,10 @@ static bool reg_pattern_test(struct ixgbe_adapter *adapter, u64 *data, int reg,
static const u32 test_pattern[] = {
0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};

if (ixgbe_removed(adapter->hw.hw_addr)) {
*data = 1;
return 1;
}
for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
before = ixgbe_read_reg(&adapter->hw, reg);
ixgbe_write_reg(&adapter->hw, reg, test_pattern[pat] & write);
Expand All @@ -1364,6 +1368,10 @@ static bool reg_set_and_check(struct ixgbe_adapter *adapter, u64 *data, int reg,
{
u32 val, before;

if (ixgbe_removed(adapter->hw.hw_addr)) {
*data = 1;
return 1;
}
before = ixgbe_read_reg(&adapter->hw, reg);
ixgbe_write_reg(&adapter->hw, reg, write & mask);
val = ixgbe_read_reg(&adapter->hw, reg);
Expand All @@ -1384,6 +1392,11 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
u32 value, before, after;
u32 i, toggle;

if (ixgbe_removed(adapter->hw.hw_addr)) {
e_err(drv, "Adapter removed - register test blocked\n");
*data = 1;
return 1;
}
switch (adapter->hw.mac.type) {
case ixgbe_mac_82598EB:
toggle = 0x7FFFF3FF;
Expand Down Expand Up @@ -1950,6 +1963,15 @@ static void ixgbe_diag_test(struct net_device *netdev,
struct ixgbe_adapter *adapter = netdev_priv(netdev);
bool if_running = netif_running(netdev);

if (ixgbe_removed(adapter->hw.hw_addr)) {
e_err(hw, "Adapter removed - test blocked\n");
data[0] = 1;
data[1] = 1;
data[2] = 1;
data[3] = 1;
eth_test->flags |= ETH_TEST_FL_FAILED;
return;
}
set_bit(__IXGBE_TESTING, &adapter->state);
if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
struct ixgbe_hw *hw = &adapter->hw;
Expand Down
16 changes: 16 additions & 0 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ static void ixgbe_remove_adapter(struct ixgbe_hw *hw)
return;
hw->hw_addr = NULL;
e_dev_err("Adapter removed\n");
ixgbe_service_event_schedule(adapter);
}

void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
Expand Down Expand Up @@ -3338,6 +3339,8 @@ static void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter,
u32 rxdctl;
u8 reg_idx = ring->reg_idx;

if (ixgbe_removed(hw->hw_addr))
return;
/* RXDCTL.EN will return 0 on 82598 if link is down, so skip it */
if (hw->mac.type == ixgbe_mac_82598EB &&
!(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
Expand All @@ -3362,6 +3365,8 @@ void ixgbe_disable_rx_queue(struct ixgbe_adapter *adapter,
u32 rxdctl;
u8 reg_idx = ring->reg_idx;

if (ixgbe_removed(hw->hw_addr))
return;
rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
rxdctl &= ~IXGBE_RXDCTL_ENABLE;

Expand Down Expand Up @@ -4687,6 +4692,8 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
int err;

if (ixgbe_removed(hw->hw_addr))
return;
/* lock SFP init bit to prevent race conditions with the watchdog */
while (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
usleep_range(1000, 2000);
Expand Down Expand Up @@ -6397,6 +6404,15 @@ static void ixgbe_service_task(struct work_struct *work)
struct ixgbe_adapter *adapter = container_of(work,
struct ixgbe_adapter,
service_task);
if (ixgbe_removed(adapter->hw.hw_addr)) {
if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
rtnl_lock();
ixgbe_down(adapter);
rtnl_unlock();
}
ixgbe_service_event_complete(adapter);
return;
}
ixgbe_reset_subtask(adapter);
ixgbe_sfp_detection_subtask(adapter);
ixgbe_sfp_link_config_subtask(adapter);
Expand Down

0 comments on commit b0483c8

Please sign in to comment.