Skip to content

Commit

Permalink
ice: restore PHY settings on media insertion
Browse files Browse the repository at this point in the history
After the transition from no media to media FW will clear the
set-phy-cfg data set by the user. Save initial PHY settings and any
settings later requested by the user and use that data to restore PHY
settings on media insertion. Since PHY configuration is now being stored,
replace calls that were calling FW to get the configuration with the saved
copy.

Signed-off-by: Paul Greenwalt <[email protected]>
Signed-off-by: Chinh T Cao <[email protected]>
Signed-off-by: Paul M Stillwell Jr <[email protected]>
Tested-by: Andrew Bowers <[email protected]>
Signed-off-by: Tony Nguyen <[email protected]>
  • Loading branch information
pgreenwa authored and anguy11 committed Jul 23, 2020
1 parent 61cf42e commit 1a3571b
Show file tree
Hide file tree
Showing 7 changed files with 518 additions and 95 deletions.
4 changes: 4 additions & 0 deletions drivers/net/ethernet/intel/ice/ice.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ enum ice_state {
__ICE_OICR_INTR_DIS, /* Global OICR interrupt disabled */
__ICE_MDD_VF_PRINT_PENDING, /* set when MDD event handle */
__ICE_VF_RESETS_DISABLED, /* disable resets during ice_remove */
__ICE_PHY_INIT_COMPLETE,
__ICE_STATE_NBITS /* must be last */
};

Expand Down Expand Up @@ -437,6 +438,9 @@ struct ice_pf {
u32 tx_timeout_recovery_level;
char int_name[ICE_INT_NAME_STR_LEN];
u32 sw_int_count;

__le64 nvm_phy_type_lo; /* NVM PHY type low */
__le64 nvm_phy_type_hi; /* NVM PHY type high */
};

struct ice_netdev_priv {
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -1147,6 +1147,7 @@ struct ice_aqc_get_link_status_data {
#define ICE_AQ_LINK_PWR_QSFP_CLASS_3 2
#define ICE_AQ_LINK_PWR_QSFP_CLASS_4 3
__le16 link_speed;
#define ICE_AQ_LINK_SPEED_M 0x7FF
#define ICE_AQ_LINK_SPEED_10MB BIT(0)
#define ICE_AQ_LINK_SPEED_100MB BIT(1)
#define ICE_AQ_LINK_SPEED_1000MB BIT(2)
Expand Down
145 changes: 135 additions & 10 deletions drivers/net/ethernet/intel/ice/ice_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -2424,7 +2424,7 @@ ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
/**
* ice_aq_set_phy_cfg
* @hw: pointer to the HW struct
* @lport: logical port number
* @pi: port info structure of the interested logical port
* @cfg: structure with PHY configuration data to be set
* @cd: pointer to command details structure or NULL
*
Expand All @@ -2434,7 +2434,7 @@ ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
* parameters. This status will be indicated by the command response (0x0601).
*/
enum ice_status
ice_aq_set_phy_cfg(struct ice_hw *hw, u8 lport,
ice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi,
struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd)
{
struct ice_aq_desc desc;
Expand All @@ -2453,7 +2453,7 @@ ice_aq_set_phy_cfg(struct ice_hw *hw, u8 lport,
}

ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_phy_cfg);
desc.params.set_phy.lport_num = lport;
desc.params.set_phy.lport_num = pi->lport;
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);

ice_debug(hw, ICE_DBG_LINK, "phy_type_low = 0x%llx\n",
Expand All @@ -2471,6 +2471,9 @@ ice_aq_set_phy_cfg(struct ice_hw *hw, u8 lport,
if (hw->adminq.sq_last_status == ICE_AQ_RC_EMODE)
status = 0;

if (!status)
pi->phy.curr_user_phy_cfg = *cfg;

return status;
}

Expand Down Expand Up @@ -2514,17 +2517,99 @@ enum ice_status ice_update_link_info(struct ice_port_info *pi)
return status;
}

/**
* ice_cache_phy_user_req
* @pi: port information structure
* @cache_data: PHY logging data
* @cache_mode: PHY logging mode
*
* Log the user request on (FC, FEC, SPEED) for later use.
*/
static void
ice_cache_phy_user_req(struct ice_port_info *pi,
struct ice_phy_cache_mode_data cache_data,
enum ice_phy_cache_mode cache_mode)
{
if (!pi)
return;

switch (cache_mode) {
case ICE_FC_MODE:
pi->phy.curr_user_fc_req = cache_data.data.curr_user_fc_req;
break;
case ICE_SPEED_MODE:
pi->phy.curr_user_speed_req =
cache_data.data.curr_user_speed_req;
break;
case ICE_FEC_MODE:
pi->phy.curr_user_fec_req = cache_data.data.curr_user_fec_req;
break;
default:
break;
}
}

/**
* ice_caps_to_fc_mode
* @caps: PHY capabilities
*
* Convert PHY FC capabilities to ice FC mode
*/
enum ice_fc_mode ice_caps_to_fc_mode(u8 caps)
{
if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE &&
caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
return ICE_FC_FULL;

if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE)
return ICE_FC_TX_PAUSE;

if (caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
return ICE_FC_RX_PAUSE;

return ICE_FC_NONE;
}

/**
* ice_caps_to_fec_mode
* @caps: PHY capabilities
* @fec_options: Link FEC options
*
* Convert PHY FEC capabilities to ice FEC mode
*/
enum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options)
{
if (caps & ICE_AQC_PHY_EN_AUTO_FEC)
return ICE_FEC_AUTO;

if (fec_options & (ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN |
ICE_AQC_PHY_FEC_25G_KR_REQ))
return ICE_FEC_BASER;

if (fec_options & (ICE_AQC_PHY_FEC_25G_RS_528_REQ |
ICE_AQC_PHY_FEC_25G_RS_544_REQ |
ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN))
return ICE_FEC_RS;

return ICE_FEC_NONE;
}

/**
* ice_cfg_phy_fc - Configure PHY FC data based on FC mode
* @pi: port information structure
* @cfg: PHY configuration data to set FC mode
* @req_mode: FC mode to configure
*/
static enum ice_status
ice_cfg_phy_fc(struct ice_aqc_set_phy_cfg_data *cfg, enum ice_fc_mode req_mode)
enum ice_status
ice_cfg_phy_fc(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
enum ice_fc_mode req_mode)
{
struct ice_phy_cache_mode_data cache_data;
u8 pause_mask = 0x0;

if (!cfg)
if (!pi || !cfg)
return ICE_ERR_BAD_PTR;

switch (req_mode) {
Expand All @@ -2549,6 +2634,10 @@ ice_cfg_phy_fc(struct ice_aqc_set_phy_cfg_data *cfg, enum ice_fc_mode req_mode)
/* set the new capabilities */
cfg->caps |= pause_mask;

/* Cache user FC request */
cache_data.data.curr_user_fc_req = req_mode;
ice_cache_phy_user_req(pi, cache_data, ICE_FC_MODE);

return 0;
}

Expand All @@ -2563,12 +2652,12 @@ ice_cfg_phy_fc(struct ice_aqc_set_phy_cfg_data *cfg, enum ice_fc_mode req_mode)
enum ice_status
ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
{
struct ice_aqc_set_phy_cfg_data cfg = { 0 };
struct ice_aqc_set_phy_cfg_data cfg = { 0 };
struct ice_aqc_get_phy_caps_data *pcaps;
enum ice_status status;
struct ice_hw *hw;

if (!pi)
if (!pi || !aq_failures)
return ICE_ERR_BAD_PTR;

*aq_failures = 0;
Expand All @@ -2589,7 +2678,7 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
ice_copy_phy_caps_to_cfg(pcaps, &cfg);

/* Configure the set PHY data */
status = ice_cfg_phy_fc(&cfg, pi->fc.req_mode);
status = ice_cfg_phy_fc(pi, &cfg, pi->fc.req_mode);
if (status)
goto out;

Expand All @@ -2601,7 +2690,7 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
if (ena_auto_link_update)
cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;

status = ice_aq_set_phy_cfg(hw, pi->lport, &cfg, NULL);
status = ice_aq_set_phy_cfg(hw, pi, &cfg, NULL);
if (status) {
*aq_failures = ICE_SET_FC_AQ_FAIL_SET;
goto out;
Expand Down Expand Up @@ -2630,6 +2719,42 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
return status;
}

/**
* ice_phy_caps_equals_cfg
* @phy_caps: PHY capabilities
* @phy_cfg: PHY configuration
*
* Helper function to determine if PHY capabilities matches PHY
* configuration
*/
bool
ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps,
struct ice_aqc_set_phy_cfg_data *phy_cfg)
{
u8 caps_mask, cfg_mask;

if (!phy_caps || !phy_cfg)
return false;

/* These bits are not common between capabilities and configuration.
* Do not use them to determine equality.
*/
caps_mask = ICE_AQC_PHY_CAPS_MASK & ~(ICE_AQC_PHY_AN_MODE |
ICE_AQC_GET_PHY_EN_MOD_QUAL);
cfg_mask = ICE_AQ_PHY_ENA_VALID_MASK & ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;

if (phy_caps->phy_type_low != phy_cfg->phy_type_low ||
phy_caps->phy_type_high != phy_cfg->phy_type_high ||
((phy_caps->caps & caps_mask) != (phy_cfg->caps & cfg_mask)) ||
phy_caps->low_power_ctrl != phy_cfg->low_power_ctrl ||
phy_caps->eee_cap != phy_cfg->eee_cap ||
phy_caps->eeer_value != phy_cfg->eeer_value ||
phy_caps->link_fec_options != phy_cfg->link_fec_opt)
return false;

return true;
}

/**
* ice_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data
* @caps: PHY ability structure to copy date from
Expand Down
14 changes: 11 additions & 3 deletions drivers/net/ethernet/intel/ice/ice_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,26 @@ ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags,
struct ice_sq_cd *cd);
enum ice_status ice_clear_pf_cfg(struct ice_hw *hw);
enum ice_status
ice_aq_set_phy_cfg(struct ice_hw *hw, u8 lport,
ice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi,
struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd);
enum ice_fc_mode ice_caps_to_fc_mode(u8 caps);
enum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options);
enum ice_status
ice_set_fc(struct ice_port_info *pi, u8 *aq_failures,
bool ena_auto_link_update);
enum ice_status
ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
enum ice_fec_mode fec);
ice_cfg_phy_fc(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
enum ice_fc_mode fc);
bool
ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *caps,
struct ice_aqc_set_phy_cfg_data *cfg);
void
ice_copy_phy_caps_to_cfg(struct ice_aqc_get_phy_caps_data *caps,
struct ice_aqc_set_phy_cfg_data *cfg);
enum ice_status
ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
enum ice_fec_mode fec);
enum ice_status
ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
struct ice_sq_cd *cd);
enum ice_status
Expand Down
Loading

0 comments on commit 1a3571b

Please sign in to comment.