Commit 59bb8835 authored by David S. Miller's avatar David S. Miller

Merge branch '1GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-queue

Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2018-03-12

This series contains fixes to e1000e only.

Benjamin Poirier provides two fixes, first reverts commits that changed
what happens to the link status when there is an error.  These commits
were to resolve a race condition, but in the process of fixing the race
condition, they changed the behavior when an error occurred.  Second fix
resolves a race condition by not setting "get_link_status" to false
after checking the link.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 38fbbc9c e2710dbf
...@@ -1367,9 +1367,6 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) ...@@ -1367,9 +1367,6 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force)
* Checks to see of the link status of the hardware has changed. If a * Checks to see of the link status of the hardware has changed. If a
* change in link status has been detected, then we read the PHY registers * change in link status has been detected, then we read the PHY registers
* to get the current speed/duplex if link exists. * to get the current speed/duplex if link exists.
*
* Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link
* up).
**/ **/
static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
{ {
...@@ -1385,7 +1382,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ...@@ -1385,7 +1382,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
* Change or Rx Sequence Error interrupt. * Change or Rx Sequence Error interrupt.
*/ */
if (!mac->get_link_status) if (!mac->get_link_status)
return 1; return 0;
mac->get_link_status = false;
/* First we want to see if the MII Status Register reports /* First we want to see if the MII Status Register reports
* link. If so, then we want to get the current speed/duplex * link. If so, then we want to get the current speed/duplex
...@@ -1393,12 +1391,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ...@@ -1393,12 +1391,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
*/ */
ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val) if (ret_val)
return ret_val; goto out;
if (hw->mac.type == e1000_pchlan) { if (hw->mac.type == e1000_pchlan) {
ret_val = e1000_k1_gig_workaround_hv(hw, link); ret_val = e1000_k1_gig_workaround_hv(hw, link);
if (ret_val) if (ret_val)
return ret_val; goto out;
} }
/* When connected at 10Mbps half-duplex, some parts are excessively /* When connected at 10Mbps half-duplex, some parts are excessively
...@@ -1431,7 +1429,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ...@@ -1431,7 +1429,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
ret_val = hw->phy.ops.acquire(hw); ret_val = hw->phy.ops.acquire(hw);
if (ret_val) if (ret_val)
return ret_val; goto out;
if (hw->mac.type == e1000_pch2lan) if (hw->mac.type == e1000_pch2lan)
emi_addr = I82579_RX_CONFIG; emi_addr = I82579_RX_CONFIG;
...@@ -1453,7 +1451,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ...@@ -1453,7 +1451,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
hw->phy.ops.release(hw); hw->phy.ops.release(hw);
if (ret_val) if (ret_val)
return ret_val; goto out;
if (hw->mac.type >= e1000_pch_spt) { if (hw->mac.type >= e1000_pch_spt) {
u16 data; u16 data;
...@@ -1462,14 +1460,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ...@@ -1462,14 +1460,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
if (speed == SPEED_1000) { if (speed == SPEED_1000) {
ret_val = hw->phy.ops.acquire(hw); ret_val = hw->phy.ops.acquire(hw);
if (ret_val) if (ret_val)
return ret_val; goto out;
ret_val = e1e_rphy_locked(hw, ret_val = e1e_rphy_locked(hw,
PHY_REG(776, 20), PHY_REG(776, 20),
&data); &data);
if (ret_val) { if (ret_val) {
hw->phy.ops.release(hw); hw->phy.ops.release(hw);
return ret_val; goto out;
} }
ptr_gap = (data & (0x3FF << 2)) >> 2; ptr_gap = (data & (0x3FF << 2)) >> 2;
...@@ -1483,18 +1481,18 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ...@@ -1483,18 +1481,18 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
} }
hw->phy.ops.release(hw); hw->phy.ops.release(hw);
if (ret_val) if (ret_val)
return ret_val; goto out;
} else { } else {
ret_val = hw->phy.ops.acquire(hw); ret_val = hw->phy.ops.acquire(hw);
if (ret_val) if (ret_val)
return ret_val; goto out;
ret_val = e1e_wphy_locked(hw, ret_val = e1e_wphy_locked(hw,
PHY_REG(776, 20), PHY_REG(776, 20),
0xC023); 0xC023);
hw->phy.ops.release(hw); hw->phy.ops.release(hw);
if (ret_val) if (ret_val)
return ret_val; goto out;
} }
} }
...@@ -1521,7 +1519,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ...@@ -1521,7 +1519,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
(hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V3)) { (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V3)) {
ret_val = e1000_k1_workaround_lpt_lp(hw, link); ret_val = e1000_k1_workaround_lpt_lp(hw, link);
if (ret_val) if (ret_val)
return ret_val; goto out;
} }
if (hw->mac.type >= e1000_pch_lpt) { if (hw->mac.type >= e1000_pch_lpt) {
/* Set platform power management values for /* Set platform power management values for
...@@ -1529,7 +1527,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ...@@ -1529,7 +1527,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
*/ */
ret_val = e1000_platform_pm_pch_lpt(hw, link); ret_val = e1000_platform_pm_pch_lpt(hw, link);
if (ret_val) if (ret_val)
return ret_val; goto out;
} }
/* Clear link partner's EEE ability */ /* Clear link partner's EEE ability */
...@@ -1552,9 +1550,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ...@@ -1552,9 +1550,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
} }
if (!link) if (!link)
return 0; /* No link detected */ goto out;
mac->get_link_status = false;
switch (hw->mac.type) { switch (hw->mac.type) {
case e1000_pch2lan: case e1000_pch2lan:
...@@ -1602,7 +1598,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ...@@ -1602,7 +1598,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
* we have already determined whether we have link or not. * we have already determined whether we have link or not.
*/ */
if (!mac->autoneg) if (!mac->autoneg)
return 1; return -E1000_ERR_CONFIG;
/* Auto-Neg is enabled. Auto Speed Detection takes care /* Auto-Neg is enabled. Auto Speed Detection takes care
* of MAC speed/duplex configuration. So we only need to * of MAC speed/duplex configuration. So we only need to
...@@ -1616,12 +1612,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ...@@ -1616,12 +1612,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
* different link partner. * different link partner.
*/ */
ret_val = e1000e_config_fc_after_link_up(hw); ret_val = e1000e_config_fc_after_link_up(hw);
if (ret_val) { if (ret_val)
e_dbg("Error configuring flow control\n"); e_dbg("Error configuring flow control\n");
return ret_val;
}
return 1; return ret_val;
out:
mac->get_link_status = true;
return ret_val;
} }
static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
......
...@@ -410,9 +410,6 @@ void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw) ...@@ -410,9 +410,6 @@ void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw)
* Checks to see of the link status of the hardware has changed. If a * Checks to see of the link status of the hardware has changed. If a
* change in link status has been detected, then we read the PHY registers * change in link status has been detected, then we read the PHY registers
* to get the current speed/duplex if link exists. * to get the current speed/duplex if link exists.
*
* Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link
* up).
**/ **/
s32 e1000e_check_for_copper_link(struct e1000_hw *hw) s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
{ {
...@@ -426,20 +423,16 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) ...@@ -426,20 +423,16 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
* Change or Rx Sequence Error interrupt. * Change or Rx Sequence Error interrupt.
*/ */
if (!mac->get_link_status) if (!mac->get_link_status)
return 1; return 0;
mac->get_link_status = false;
/* First we want to see if the MII Status Register reports /* First we want to see if the MII Status Register reports
* link. If so, then we want to get the current speed/duplex * link. If so, then we want to get the current speed/duplex
* of the PHY. * of the PHY.
*/ */
ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val) if (ret_val || !link)
return ret_val; goto out;
if (!link)
return 0; /* No link detected */
mac->get_link_status = false;
/* Check if there was DownShift, must be checked /* Check if there was DownShift, must be checked
* immediately after link-up * immediately after link-up
...@@ -450,7 +443,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) ...@@ -450,7 +443,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
* we have already determined whether we have link or not. * we have already determined whether we have link or not.
*/ */
if (!mac->autoneg) if (!mac->autoneg)
return 1; return -E1000_ERR_CONFIG;
/* Auto-Neg is enabled. Auto Speed Detection takes care /* Auto-Neg is enabled. Auto Speed Detection takes care
* of MAC speed/duplex configuration. So we only need to * of MAC speed/duplex configuration. So we only need to
...@@ -464,12 +457,14 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) ...@@ -464,12 +457,14 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
* different link partner. * different link partner.
*/ */
ret_val = e1000e_config_fc_after_link_up(hw); ret_val = e1000e_config_fc_after_link_up(hw);
if (ret_val) { if (ret_val)
e_dbg("Error configuring flow control\n"); e_dbg("Error configuring flow control\n");
return ret_val;
}
return 1; return ret_val;
out:
mac->get_link_status = true;
return ret_val;
} }
/** /**
......
...@@ -5090,7 +5090,7 @@ static bool e1000e_has_link(struct e1000_adapter *adapter) ...@@ -5090,7 +5090,7 @@ static bool e1000e_has_link(struct e1000_adapter *adapter)
case e1000_media_type_copper: case e1000_media_type_copper:
if (hw->mac.get_link_status) { if (hw->mac.get_link_status) {
ret_val = hw->mac.ops.check_for_link(hw); ret_val = hw->mac.ops.check_for_link(hw);
link_active = ret_val > 0; link_active = !hw->mac.get_link_status;
} else { } else {
link_active = true; link_active = true;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment