net/ice/base: support PHY persistent feature
authorQi Zhang <qi.z.zhang@intel.com>
Mon, 23 Mar 2020 07:17:46 +0000 (15:17 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 21 Apr 2020 11:57:05 +0000 (13:57 +0200)
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 <chinh.t.cao@intel.com>
Signed-off-by: Paul M Stillwell Jr <paul.m.stillwell.jr@intel.com>
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Acked-by: Qiming Yang <qiming.yang@intel.com>
drivers/net/ice/base/ice_common.c
drivers/net/ice/base/ice_common.h

index 25e2059..756868a 100644 (file)
@@ -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;
 }
 
 /**
index 4e2e257..ffe4e9f 100644 (file)
@@ -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);