|
@@ -6570,6 +6570,24 @@ static i40e_status i40e_force_link_state(struct i40e_pf *pf, bool is_up)
|
|
|
struct i40e_hw *hw = &pf->hw;
|
|
|
i40e_status err;
|
|
|
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 */
|
|
|
err = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
|
|
@@ -6583,9 +6601,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,
|
|
|
- * 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;
|
|
|
|
|
|
/* To force link we need to set bits for all supported PHY types,
|
|
@@ -6597,7 +6615,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;
|
|
|
/* Copy the old settings, except of phy_type */
|
|
|
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.eeer = abilities.eeer_val;
|
|
|
config.low_power_ctrl = abilities.d3_lpan;
|