mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-13 09:20:17 +00:00
ixgbe: Additional adapter removal checks
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>
This commit is contained in:
parent
b12babd4d0
commit
b0483c8f36
@ -1342,6 +1342,10 @@ static bool reg_pattern_test(struct ixgbe_adapter *adapter, u64 *data, int reg,
|
|||||||
static const u32 test_pattern[] = {
|
static const u32 test_pattern[] = {
|
||||||
0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
|
0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
|
||||||
|
|
||||||
|
if (ixgbe_removed(adapter->hw.hw_addr)) {
|
||||||
|
*data = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
|
for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
|
||||||
before = ixgbe_read_reg(&adapter->hw, reg);
|
before = ixgbe_read_reg(&adapter->hw, reg);
|
||||||
ixgbe_write_reg(&adapter->hw, reg, test_pattern[pat] & write);
|
ixgbe_write_reg(&adapter->hw, reg, test_pattern[pat] & write);
|
||||||
@ -1364,6 +1368,10 @@ static bool reg_set_and_check(struct ixgbe_adapter *adapter, u64 *data, int reg,
|
|||||||
{
|
{
|
||||||
u32 val, before;
|
u32 val, before;
|
||||||
|
|
||||||
|
if (ixgbe_removed(adapter->hw.hw_addr)) {
|
||||||
|
*data = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
before = ixgbe_read_reg(&adapter->hw, reg);
|
before = ixgbe_read_reg(&adapter->hw, reg);
|
||||||
ixgbe_write_reg(&adapter->hw, reg, write & mask);
|
ixgbe_write_reg(&adapter->hw, reg, write & mask);
|
||||||
val = ixgbe_read_reg(&adapter->hw, reg);
|
val = ixgbe_read_reg(&adapter->hw, reg);
|
||||||
@ -1384,6 +1392,11 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
|
|||||||
u32 value, before, after;
|
u32 value, before, after;
|
||||||
u32 i, toggle;
|
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) {
|
switch (adapter->hw.mac.type) {
|
||||||
case ixgbe_mac_82598EB:
|
case ixgbe_mac_82598EB:
|
||||||
toggle = 0x7FFFF3FF;
|
toggle = 0x7FFFF3FF;
|
||||||
@ -1950,6 +1963,15 @@ static void ixgbe_diag_test(struct net_device *netdev,
|
|||||||
struct ixgbe_adapter *adapter = netdev_priv(netdev);
|
struct ixgbe_adapter *adapter = netdev_priv(netdev);
|
||||||
bool if_running = netif_running(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);
|
set_bit(__IXGBE_TESTING, &adapter->state);
|
||||||
if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
|
if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
|
||||||
struct ixgbe_hw *hw = &adapter->hw;
|
struct ixgbe_hw *hw = &adapter->hw;
|
||||||
|
@ -291,6 +291,7 @@ static void ixgbe_remove_adapter(struct ixgbe_hw *hw)
|
|||||||
return;
|
return;
|
||||||
hw->hw_addr = NULL;
|
hw->hw_addr = NULL;
|
||||||
e_dev_err("Adapter removed\n");
|
e_dev_err("Adapter removed\n");
|
||||||
|
ixgbe_service_event_schedule(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
|
void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
|
||||||
@ -3338,6 +3339,8 @@ static void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter,
|
|||||||
u32 rxdctl;
|
u32 rxdctl;
|
||||||
u8 reg_idx = ring->reg_idx;
|
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 */
|
/* RXDCTL.EN will return 0 on 82598 if link is down, so skip it */
|
||||||
if (hw->mac.type == ixgbe_mac_82598EB &&
|
if (hw->mac.type == ixgbe_mac_82598EB &&
|
||||||
!(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
|
!(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
|
||||||
@ -3362,6 +3365,8 @@ void ixgbe_disable_rx_queue(struct ixgbe_adapter *adapter,
|
|||||||
u32 rxdctl;
|
u32 rxdctl;
|
||||||
u8 reg_idx = ring->reg_idx;
|
u8 reg_idx = ring->reg_idx;
|
||||||
|
|
||||||
|
if (ixgbe_removed(hw->hw_addr))
|
||||||
|
return;
|
||||||
rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
|
rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
|
||||||
rxdctl &= ~IXGBE_RXDCTL_ENABLE;
|
rxdctl &= ~IXGBE_RXDCTL_ENABLE;
|
||||||
|
|
||||||
@ -4687,6 +4692,8 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
|
|||||||
struct ixgbe_hw *hw = &adapter->hw;
|
struct ixgbe_hw *hw = &adapter->hw;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (ixgbe_removed(hw->hw_addr))
|
||||||
|
return;
|
||||||
/* lock SFP init bit to prevent race conditions with the watchdog */
|
/* lock SFP init bit to prevent race conditions with the watchdog */
|
||||||
while (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
|
while (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
|
||||||
usleep_range(1000, 2000);
|
usleep_range(1000, 2000);
|
||||||
@ -6397,6 +6404,15 @@ static void ixgbe_service_task(struct work_struct *work)
|
|||||||
struct ixgbe_adapter *adapter = container_of(work,
|
struct ixgbe_adapter *adapter = container_of(work,
|
||||||
struct ixgbe_adapter,
|
struct ixgbe_adapter,
|
||||||
service_task);
|
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_reset_subtask(adapter);
|
||||||
ixgbe_sfp_detection_subtask(adapter);
|
ixgbe_sfp_detection_subtask(adapter);
|
||||||
ixgbe_sfp_link_config_subtask(adapter);
|
ixgbe_sfp_link_config_subtask(adapter);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user