From 2a28af021703f8323cadfdab19e9545308bcdcb4 Mon Sep 17 00:00:00 2001 From: Qi Zhang Date: Mon, 23 Mar 2020 15:17:46 +0800 Subject: [PATCH] net/ice/base: support PHY persistent feature In this patch, we will modify the ice_copy_phy_caps_to_cfg(...) function to conditionally fill up the ice_aqc_set_phy_cfg_data.module_compliance_enforcement with correct value, based on the PHY persistent feature. Apply the ice_copy_phy_caps_to_cfg() function inside ice_set_fc() Signed-off-by: Chinh T Cao Signed-off-by: Paul M Stillwell Jr Signed-off-by: Qi Zhang Acked-by: Qiming Yang --- drivers/net/ice/base/ice_common.c | 124 +++++++++++++++++++++--------- drivers/net/ice/base/ice_common.h | 8 +- 2 files changed, 93 insertions(+), 39 deletions(-) diff --git a/drivers/net/ice/base/ice_common.c b/drivers/net/ice/base/ice_common.c index 25e2059444..756868a5a4 100644 --- a/drivers/net/ice/base/ice_common.c +++ b/drivers/net/ice/base/ice_common.c @@ -2540,14 +2540,14 @@ 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_phy_cache_mode_data cache_data; - struct ice_link_default_override_tlv tlv; struct ice_aqc_get_phy_caps_data *pcaps; enum ice_status status; u8 pause_mask = 0x0; struct ice_hw *hw; - if (!pi) + if (!pi || !aq_failures) return ICE_ERR_PARAM; + hw = pi->hw; *aq_failures = ICE_SET_FC_AQ_FAIL_NONE; @@ -2555,7 +2555,26 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update) cache_data.data.curr_user_fc_req = pi->fc.req_mode; ice_cache_phy_user_req(pi, cache_data, ICE_FC_MODE); + pcaps = (struct ice_aqc_get_phy_caps_data *) + ice_malloc(hw, sizeof(*pcaps)); + if (!pcaps) + return ICE_ERR_NO_MEMORY; + switch (pi->fc.req_mode) { + case ICE_FC_AUTO: + /* Query the value of FC that both the NIC and attached media + * can do. + */ + status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, + pcaps, NULL); + if (status) { + *aq_failures = ICE_SET_FC_AQ_FAIL_GET; + goto out; + } + + pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE; + pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE; + break; case ICE_FC_FULL: pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE; pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE; @@ -2570,12 +2589,8 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update) break; } - pcaps = (struct ice_aqc_get_phy_caps_data *) - ice_malloc(hw, sizeof(*pcaps)); - if (!pcaps) - return ICE_ERR_NO_MEMORY; - /* Get the current PHY config */ + ice_memset(pcaps, 0, sizeof(*pcaps), ICE_NONDMA_MEM); status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps, NULL); if (status) { @@ -2583,23 +2598,14 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update) goto out; } + ice_copy_phy_caps_to_cfg(pi, pcaps, &cfg); + /* clear the old pause settings */ - cfg.caps = pcaps->caps & ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE | - ICE_AQC_PHY_EN_RX_LINK_PAUSE); + cfg.caps &= ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE | + ICE_AQC_PHY_EN_RX_LINK_PAUSE); /* set the new capabilities */ - if (pi->fc.req_mode == ICE_FC_AUTO && - ice_fw_supports_link_override(hw)) { - status = ice_get_link_default_override(&tlv, pi); - if (status) - return status; - - if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) && - (tlv.options & ICE_LINK_OVERRIDE_EN)) - cfg.caps |= tlv.phy_config & ICE_LINK_OVERRIDE_PAUSE_M; - } else { - cfg.caps |= pause_mask; - } + cfg.caps |= pause_mask; /* If the capabilities have changed, then set the new config */ if (cfg.caps != pcaps->caps) { @@ -2608,13 +2614,6 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update) /* Auto restart link so settings take effect */ if (ena_auto_link_update) cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; - /* Copy over all the old settings */ - cfg.phy_type_high = pcaps->phy_type_high; - cfg.phy_type_low = pcaps->phy_type_low; - cfg.low_power_ctrl_an = pcaps->low_power_ctrl_an; - cfg.eee_cap = pcaps->eee_cap; - cfg.eeer_value = pcaps->eeer_value; - cfg.link_fec_opt = pcaps->link_fec_options; status = ice_aq_set_phy_cfg(hw, pi, &cfg, NULL); if (status) { @@ -2683,6 +2682,7 @@ ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps, /** * ice_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data + * @pi: port information structure * @caps: PHY ability structure to copy date from * @cfg: PHY configuration structure to copy data to * @@ -2690,12 +2690,14 @@ ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps, * data structure */ void -ice_copy_phy_caps_to_cfg(struct ice_aqc_get_phy_caps_data *caps, +ice_copy_phy_caps_to_cfg(struct ice_port_info *pi, + struct ice_aqc_get_phy_caps_data *caps, struct ice_aqc_set_phy_cfg_data *cfg) { - if (!caps || !cfg) + if (!pi || !caps || !cfg) return; + ice_memset(cfg, 0, sizeof(*cfg), ICE_NONDMA_MEM); cfg->phy_type_low = caps->phy_type_low; cfg->phy_type_high = caps->phy_type_high; cfg->caps = caps->caps; @@ -2703,20 +2705,50 @@ ice_copy_phy_caps_to_cfg(struct ice_aqc_get_phy_caps_data *caps, cfg->eee_cap = caps->eee_cap; cfg->eeer_value = caps->eeer_value; cfg->link_fec_opt = caps->link_fec_options; + cfg->module_compliance_enforcement = + caps->module_compliance_enforcement; + + if (ice_fw_supports_link_override(pi->hw)) { + struct ice_link_default_override_tlv tlv; + + if (ice_get_link_default_override(&tlv, pi)) + return; + + if (tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) + cfg->module_compliance_enforcement |= + ICE_LINK_OVERRIDE_STRICT_MODE; + } } /** * ice_cfg_phy_fec - Configure PHY FEC data based on FEC mode + * @pi: port information structure * @cfg: PHY configuration data to set FEC mode * @fec: FEC mode to configure - * - * Caller should copy ice_aqc_get_phy_caps_data.caps ICE_AQC_PHY_EN_AUTO_FEC - * (bit 7) and ice_aqc_get_phy_caps_data.link_fec_options to cfg.caps - * ICE_AQ_PHY_ENA_AUTO_FEC (bit 7) and cfg.link_fec_options before calling. */ -void -ice_cfg_phy_fec(struct ice_aqc_set_phy_cfg_data *cfg, enum ice_fec_mode fec) +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) { + struct ice_aqc_get_phy_caps_data *pcaps; + enum ice_status status = ICE_SUCCESS; + struct ice_hw *hw; + + if (!pi || !cfg) + return ICE_ERR_BAD_PTR; + + hw = pi->hw; + + pcaps = (struct ice_aqc_get_phy_caps_data *) + ice_malloc(hw, sizeof(*pcaps)); + if (!pcaps) + return ICE_ERR_NO_MEMORY; + + status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, pcaps, + NULL); + if (status) + goto out; + switch (fec) { case ICE_FEC_BASER: /* Clear RS bits, and AND BASE-R ability @@ -2742,8 +2774,28 @@ ice_cfg_phy_fec(struct ice_aqc_set_phy_cfg_data *cfg, enum ice_fec_mode fec) case ICE_FEC_AUTO: /* AND auto FEC bit, and all caps bits. */ cfg->caps &= ICE_AQC_PHY_CAPS_MASK; + cfg->link_fec_opt |= pcaps->link_fec_options; + break; + default: + status = ICE_ERR_PARAM; break; } + + if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(pi->hw)) { + struct ice_link_default_override_tlv tlv; + + if (ice_get_link_default_override(&tlv, pi)) + goto out; + + if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) && + (tlv.options & ICE_LINK_OVERRIDE_EN)) + cfg->link_fec_opt = tlv.fec_options; + } + +out: + ice_free(hw, pcaps); + + return status; } /** diff --git a/drivers/net/ice/base/ice_common.h b/drivers/net/ice/base/ice_common.h index 4e2e257442..ffe4e9f773 100644 --- a/drivers/net/ice/base/ice_common.h +++ b/drivers/net/ice/base/ice_common.h @@ -154,10 +154,12 @@ 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, +ice_copy_phy_caps_to_cfg(struct ice_port_info *pi, + struct ice_aqc_get_phy_caps_data *caps, struct ice_aqc_set_phy_cfg_data *cfg); -void -ice_cfg_phy_fec(struct ice_aqc_set_phy_cfg_data *cfg, enum ice_fec_mode fec); +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); -- 2.20.1