Commit fe301cf6 authored by Jan Sokolowski's avatar Jan Sokolowski Committed by Greg Kroah-Hartman

i40e: Check and correct speed values for link on open

[ Upstream commit e78d9a39 ]

If our card has been put in an unstable state due to
other drivers interacting with it, speed settings
might be incorrect. If incorrect, forcefully reset them
on open to known default values.
Signed-off-by: default avatarJan Sokolowski <jan.sokolowski@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 8d7e6ab3
...@@ -6587,6 +6587,24 @@ static i40e_status i40e_force_link_state(struct i40e_pf *pf, bool is_up) ...@@ -6587,6 +6587,24 @@ static i40e_status i40e_force_link_state(struct i40e_pf *pf, bool is_up)
struct i40e_hw *hw = &pf->hw; struct i40e_hw *hw = &pf->hw;
i40e_status err; i40e_status err;
u64 mask; u64 mask;
u8 speed;
/* Card might've been put in an unstable state by other drivers
* and applications, which causes incorrect speed values being
* set on startup. In order to clear speed registers, we call
* get_phy_capabilities twice, once to get initial state of
* available speeds, and once to get current PHY config.
*/
err = i40e_aq_get_phy_capabilities(hw, false, true, &abilities,
NULL);
if (err) {
dev_err(&pf->pdev->dev,
"failed to get phy cap., ret = %s last_status = %s\n",
i40e_stat_str(hw, err),
i40e_aq_str(hw, hw->aq.asq_last_status));
return err;
}
speed = abilities.link_speed;
/* Get the current phy config */ /* Get the current phy config */
err = i40e_aq_get_phy_capabilities(hw, false, false, &abilities, err = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
...@@ -6600,9 +6618,9 @@ static i40e_status i40e_force_link_state(struct i40e_pf *pf, bool is_up) ...@@ -6600,9 +6618,9 @@ static i40e_status i40e_force_link_state(struct i40e_pf *pf, bool is_up)
} }
/* If link needs to go up, but was not forced to go down, /* If link needs to go up, but was not forced to go down,
* no need for a flap * and its speed values are OK, no need for a flap
*/ */
if (is_up && abilities.phy_type != 0) if (is_up && abilities.phy_type != 0 && abilities.link_speed != 0)
return I40E_SUCCESS; return I40E_SUCCESS;
/* To force link we need to set bits for all supported PHY types, /* To force link we need to set bits for all supported PHY types,
...@@ -6614,7 +6632,10 @@ static i40e_status i40e_force_link_state(struct i40e_pf *pf, bool is_up) ...@@ -6614,7 +6632,10 @@ static i40e_status i40e_force_link_state(struct i40e_pf *pf, bool is_up)
config.phy_type_ext = is_up ? (u8)((mask >> 32) & 0xff) : 0; config.phy_type_ext = is_up ? (u8)((mask >> 32) & 0xff) : 0;
/* Copy the old settings, except of phy_type */ /* Copy the old settings, except of phy_type */
config.abilities = abilities.abilities; config.abilities = abilities.abilities;
config.link_speed = abilities.link_speed; if (abilities.link_speed != 0)
config.link_speed = abilities.link_speed;
else
config.link_speed = speed;
config.eee_capability = abilities.eee_capability; config.eee_capability = abilities.eee_capability;
config.eeer = abilities.eeer_val; config.eeer = abilities.eeer_val;
config.low_power_ctrl = abilities.d3_lpan; config.low_power_ctrl = abilities.d3_lpan;
......
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