diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_common.c')
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_common.c | 199 | 
1 files changed, 146 insertions, 53 deletions
| diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 3d9475e222cd..e93b1e40f627 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -158,6 +158,10 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,  		return ICE_ERR_PARAM;  	hw = pi->hw; +	if (report_mode == ICE_AQC_REPORT_DFLT_CFG && +	    !ice_fw_supports_report_dflt_cfg(hw)) +		return ICE_ERR_PARAM; +  	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps);  	if (qual_mods) @@ -191,7 +195,7 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,  	ice_debug(hw, ICE_DBG_LINK, "   module_type[2] = 0x%x\n",  		  pcaps->module_type[2]); -	if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP) { +	if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP_MEDIA) {  		pi->phy.phy_type_low = le64_to_cpu(pcaps->phy_type_low);  		pi->phy.phy_type_high = le64_to_cpu(pcaps->phy_type_high);  		memcpy(pi->phy.link_info.module_type, &pcaps->module_type, @@ -717,8 +721,8 @@ static enum ice_status ice_cfg_fw_log(struct ice_hw *hw, bool enable)  			if (!data) {  				data = devm_kcalloc(ice_hw_to_dev(hw), -						    sizeof(*data),  						    ICE_AQC_FW_LOG_ID_MAX, +						    sizeof(*data),  						    GFP_KERNEL);  				if (!data)  					return ICE_ERR_NO_MEMORY; @@ -922,7 +926,8 @@ enum ice_status ice_init_hw(struct ice_hw *hw)  	/* Initialize port_info struct with PHY capabilities */  	status = ice_aq_get_phy_caps(hw->port_info, false, -				     ICE_AQC_REPORT_TOPO_CAP, pcaps, NULL); +				     ICE_AQC_REPORT_TOPO_CAP_MEDIA, pcaps, +				     NULL);  	devm_kfree(ice_hw_to_dev(hw), pcaps);  	if (status)  		dev_warn(ice_hw_to_dev(hw), "Get PHY capabilities failed status = %d, continuing anyway\n", @@ -1293,6 +1298,85 @@ const struct ice_ctx_ele ice_tlan_ctx_info[] = {  DEFINE_MUTEX(ice_global_cfg_lock_sw);  /** + * ice_should_retry_sq_send_cmd + * @opcode: AQ opcode + * + * Decide if we should retry the send command routine for the ATQ, depending + * on the opcode. + */ +static bool ice_should_retry_sq_send_cmd(u16 opcode) +{ +	switch (opcode) { +	case ice_aqc_opc_get_link_topo: +	case ice_aqc_opc_lldp_stop: +	case ice_aqc_opc_lldp_start: +	case ice_aqc_opc_lldp_filter_ctrl: +		return true; +	} + +	return false; +} + +/** + * ice_sq_send_cmd_retry - send command to Control Queue (ATQ) + * @hw: pointer to the HW struct + * @cq: pointer to the specific Control queue + * @desc: prefilled descriptor describing the command + * @buf: buffer to use for indirect commands (or NULL for direct commands) + * @buf_size: size of buffer for indirect commands (or 0 for direct commands) + * @cd: pointer to command details structure + * + * Retry sending the FW Admin Queue command, multiple times, to the FW Admin + * Queue if the EBUSY AQ error is returned. + */ +static enum ice_status +ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq, +		      struct ice_aq_desc *desc, void *buf, u16 buf_size, +		      struct ice_sq_cd *cd) +{ +	struct ice_aq_desc desc_cpy; +	enum ice_status status; +	bool is_cmd_for_retry; +	u8 *buf_cpy = NULL; +	u8 idx = 0; +	u16 opcode; + +	opcode = le16_to_cpu(desc->opcode); +	is_cmd_for_retry = ice_should_retry_sq_send_cmd(opcode); +	memset(&desc_cpy, 0, sizeof(desc_cpy)); + +	if (is_cmd_for_retry) { +		if (buf) { +			buf_cpy = kzalloc(buf_size, GFP_KERNEL); +			if (!buf_cpy) +				return ICE_ERR_NO_MEMORY; +		} + +		memcpy(&desc_cpy, desc, sizeof(desc_cpy)); +	} + +	do { +		status = ice_sq_send_cmd(hw, cq, desc, buf, buf_size, cd); + +		if (!is_cmd_for_retry || !status || +		    hw->adminq.sq_last_status != ICE_AQ_RC_EBUSY) +			break; + +		if (buf_cpy) +			memcpy(buf, buf_cpy, buf_size); + +		memcpy(desc, &desc_cpy, sizeof(desc_cpy)); + +		mdelay(ICE_SQ_SEND_DELAY_TIME_MS); + +	} while (++idx < ICE_SQ_SEND_MAX_EXECUTE); + +	kfree(buf_cpy); + +	return status; +} + +/**   * ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue   * @hw: pointer to the HW struct   * @desc: descriptor describing the command @@ -1333,7 +1417,7 @@ ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf,  		break;  	} -	status = ice_sq_send_cmd(hw, &hw->adminq, desc, buf, buf_size, cd); +	status = ice_sq_send_cmd_retry(hw, &hw->adminq, desc, buf, buf_size, cd);  	if (lock_acquired)  		mutex_unlock(&ice_global_cfg_lock_sw); @@ -2655,7 +2739,7 @@ enum ice_status ice_update_link_info(struct ice_port_info *pi)  		if (!pcaps)  			return ICE_ERR_NO_MEMORY; -		status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, +		status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA,  					     pcaps, NULL);  		devm_kfree(ice_hw_to_dev(hw), pcaps); @@ -2815,8 +2899,8 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)  		return ICE_ERR_NO_MEMORY;  	/* Get the current PHY config */ -	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps, -				     NULL); +	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_ACTIVE_CFG, +				     pcaps, NULL);  	if (status) {  		*aq_failures = ICE_SET_FC_AQ_FAIL_GET;  		goto out; @@ -2929,17 +3013,6 @@ ice_copy_phy_caps_to_cfg(struct ice_port_info *pi,  	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; -	}  }  /** @@ -2954,16 +3027,21 @@ ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,  {  	struct ice_aqc_get_phy_caps_data *pcaps;  	enum ice_status status; +	struct ice_hw *hw;  	if (!pi || !cfg)  		return ICE_ERR_BAD_PTR; +	hw = pi->hw; +  	pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL);  	if (!pcaps)  		return ICE_ERR_NO_MEMORY; -	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, pcaps, -				     NULL); +	status = ice_aq_get_phy_caps(pi, false, +				     (ice_fw_supports_report_dflt_cfg(hw) ? +				      ICE_AQC_REPORT_DFLT_CFG : +				      ICE_AQC_REPORT_TOPO_CAP_MEDIA), pcaps, NULL);  	if (status)  		goto out; @@ -3002,7 +3080,8 @@ ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,  		break;  	} -	if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(pi->hw)) { +	if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(hw) && +	    !ice_fw_supports_report_dflt_cfg(hw)) {  		struct ice_link_default_override_tlv tlv;  		if (ice_get_link_default_override(&tlv, pi)) @@ -3186,7 +3265,7 @@ ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,  	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_sff_eeprom);  	cmd = &desc.params.read_write_sff_param; -	desc.flags = cpu_to_le16(ICE_AQ_FLAG_RD | ICE_AQ_FLAG_BUF); +	desc.flags = cpu_to_le16(ICE_AQ_FLAG_RD);  	cmd->lport_num = (u8)(lport & 0xff);  	cmd->lport_num_valid = (u8)((lport >> 8) & 0x01);  	cmd->i2c_bus_addr = cpu_to_le16(((bus_addr >> 1) & @@ -3206,23 +3285,33 @@ ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,  /**   * __ice_aq_get_set_rss_lut   * @hw: pointer to the hardware structure - * @vsi_id: VSI FW index - * @lut_type: LUT table type - * @lut: pointer to the LUT buffer provided by the caller - * @lut_size: size of the LUT buffer - * @glob_lut_idx: global LUT index + * @params: RSS LUT parameters   * @set: set true to set the table, false to get the table   *   * Internal function to get (0x0B05) or set (0x0B03) RSS look up table   */  static enum ice_status -__ice_aq_get_set_rss_lut(struct ice_hw *hw, u16 vsi_id, u8 lut_type, u8 *lut, -			 u16 lut_size, u8 glob_lut_idx, bool set) +__ice_aq_get_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *params, bool set)  { +	u16 flags = 0, vsi_id, lut_type, lut_size, glob_lut_idx, vsi_handle;  	struct ice_aqc_get_set_rss_lut *cmd_resp;  	struct ice_aq_desc desc;  	enum ice_status status; -	u16 flags = 0; +	u8 *lut; + +	if (!params) +		return ICE_ERR_PARAM; + +	vsi_handle = params->vsi_handle; +	lut = params->lut; + +	if (!ice_is_vsi_valid(hw, vsi_handle) || !lut) +		return ICE_ERR_PARAM; + +	lut_size = params->lut_size; +	lut_type = params->lut_type; +	glob_lut_idx = params->global_lut_id; +	vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);  	cmd_resp = &desc.params.get_set_rss_lut; @@ -3296,43 +3385,27 @@ ice_aq_get_set_rss_lut_exit:  /**   * ice_aq_get_rss_lut   * @hw: pointer to the hardware structure - * @vsi_handle: software VSI handle - * @lut_type: LUT table type - * @lut: pointer to the LUT buffer provided by the caller - * @lut_size: size of the LUT buffer + * @get_params: RSS LUT parameters used to specify which RSS LUT to get   *   * get the RSS lookup table, PF or VSI type   */  enum ice_status -ice_aq_get_rss_lut(struct ice_hw *hw, u16 vsi_handle, u8 lut_type, -		   u8 *lut, u16 lut_size) +ice_aq_get_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *get_params)  { -	if (!ice_is_vsi_valid(hw, vsi_handle) || !lut) -		return ICE_ERR_PARAM; - -	return __ice_aq_get_set_rss_lut(hw, ice_get_hw_vsi_num(hw, vsi_handle), -					lut_type, lut, lut_size, 0, false); +	return __ice_aq_get_set_rss_lut(hw, get_params, false);  }  /**   * ice_aq_set_rss_lut   * @hw: pointer to the hardware structure - * @vsi_handle: software VSI handle - * @lut_type: LUT table type - * @lut: pointer to the LUT buffer provided by the caller - * @lut_size: size of the LUT buffer + * @set_params: RSS LUT parameters used to specify how to set the RSS LUT   *   * set the RSS lookup table, PF or VSI type   */  enum ice_status -ice_aq_set_rss_lut(struct ice_hw *hw, u16 vsi_handle, u8 lut_type, -		   u8 *lut, u16 lut_size) +ice_aq_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *set_params)  { -	if (!ice_is_vsi_valid(hw, vsi_handle) || !lut) -		return ICE_ERR_PARAM; - -	return __ice_aq_get_set_rss_lut(hw, ice_get_hw_vsi_num(hw, vsi_handle), -					lut_type, lut, lut_size, 0, true); +	return __ice_aq_get_set_rss_lut(hw, set_params, true);  }  /** @@ -4373,7 +4446,7 @@ ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,  }  /** - * ice_fw_supports_lldp_fltr - check NVM version supports lldp_fltr_ctrl + * ice_fw_supports_lldp_fltr_ctrl - check NVM version supports lldp_fltr_ctrl   * @hw: pointer to HW struct   */  bool ice_fw_supports_lldp_fltr_ctrl(struct ice_hw *hw) @@ -4418,3 +4491,23 @@ ice_lldp_fltr_add_remove(struct ice_hw *hw, u16 vsi_num, bool add)  	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);  } + +/** + * ice_fw_supports_report_dflt_cfg + * @hw: pointer to the hardware structure + * + * Checks if the firmware supports report default configuration + */ +bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw) +{ +	if (hw->api_maj_ver == ICE_FW_API_REPORT_DFLT_CFG_MAJ) { +		if (hw->api_min_ver > ICE_FW_API_REPORT_DFLT_CFG_MIN) +			return true; +		if (hw->api_min_ver == ICE_FW_API_REPORT_DFLT_CFG_MIN && +		    hw->api_patch >= ICE_FW_API_REPORT_DFLT_CFG_PATCH) +			return true; +	} else if (hw->api_maj_ver > ICE_FW_API_REPORT_DFLT_CFG_MAJ) { +		return true; +	} +	return false; +} | 
