Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0483c8f authored by Mark Rustad's avatar Mark Rustad Committed by David S. Miller
Browse files

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: default avatarMark Rustad <mark.d.rustad@intel.com>
Tested-by: default avatarPhil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b12babd4
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -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);
@@ -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);
@@ -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;
@@ -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;
+16 −0
Original line number Diff line number Diff line
@@ -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)
@@ -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))
@@ -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;

@@ -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);
@@ -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);