diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_common.c')
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_common.c | 283 | 
1 files changed, 183 insertions, 100 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index e16d4c83ed5f..80deca45ab59 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -5,6 +5,7 @@  #include "ice_sched.h"  #include "ice_adminq_cmd.h"  #include "ice_flow.h" +#include "ice_ptp_hw.h"  #define ICE_PF_RESET_WAIT_COUNT	300 @@ -1999,37 +2000,31 @@ void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)  /**   * ice_aq_alloc_free_res - command to allocate/free resources   * @hw: pointer to the HW struct - * @num_entries: number of resource entries in buffer   * @buf: Indirect buffer to hold data parameters and response   * @buf_size: size of buffer for indirect commands   * @opc: pass in the command opcode - * @cd: pointer to command details structure or NULL   *   * Helper function to allocate/free resources using the admin queue commands   */ -int -ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries, -		      struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, -		      enum ice_adminq_opc opc, struct ice_sq_cd *cd) +int ice_aq_alloc_free_res(struct ice_hw *hw, +			  struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, +			  enum ice_adminq_opc opc)  {  	struct ice_aqc_alloc_free_res_cmd *cmd;  	struct ice_aq_desc desc;  	cmd = &desc.params.sw_res_ctrl; -	if (!buf) -		return -EINVAL; - -	if (buf_size < flex_array_size(buf, elem, num_entries)) +	if (!buf || buf_size < flex_array_size(buf, elem, 1))  		return -EINVAL;  	ice_fill_dflt_direct_cmd_desc(&desc, opc);  	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); -	cmd->num_entries = cpu_to_le16(num_entries); +	cmd->num_entries = cpu_to_le16(1); -	return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); +	return ice_aq_send_cmd(hw, &desc, buf, buf_size, NULL);  }  /** @@ -2059,8 +2054,7 @@ ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res)  	if (btm)  		buf->res_type |= cpu_to_le16(ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM); -	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, -				       ice_aqc_opc_alloc_res, NULL); +	status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_alloc_res);  	if (status)  		goto ice_alloc_res_exit; @@ -2094,8 +2088,7 @@ int ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res)  	buf->res_type = cpu_to_le16(type);  	memcpy(buf->elem, res, sizeof(*buf->elem) * num); -	status = ice_aq_alloc_free_res(hw, num, buf, buf_len, -				       ice_aqc_opc_free_res, NULL); +	status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_free_res);  	if (status)  		ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n"); @@ -2241,6 +2234,14 @@ ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,  			  "%s: reset_restrict_support = %d\n", prefix,  			  caps->reset_restrict_support);  		break; +	case ICE_AQC_CAPS_FW_LAG_SUPPORT: +		caps->roce_lag = !!(number & ICE_AQC_BIT_ROCEV2_LAG); +		ice_debug(hw, ICE_DBG_INIT, "%s: roce_lag = %u\n", +			  prefix, caps->roce_lag); +		caps->sriov_lag = !!(number & ICE_AQC_BIT_SRIOV_LAG); +		ice_debug(hw, ICE_DBG_INIT, "%s: sriov_lag = %u\n", +			  prefix, caps->sriov_lag); +		break;  	default:  		/* Not one of the recognized common capabilities */  		found = false; @@ -2654,6 +2655,67 @@ ice_parse_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,  }  /** + * ice_aq_get_netlist_node + * @hw: pointer to the hw struct + * @cmd: get_link_topo AQ structure + * @node_part_number: output node part number if node found + * @node_handle: output node handle parameter if node found + */ +static int +ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd, +			u8 *node_part_number, u16 *node_handle) +{ +	struct ice_aq_desc desc; + +	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo); +	desc.params.get_link_topo = *cmd; + +	if (ice_aq_send_cmd(hw, &desc, NULL, 0, NULL)) +		return -EIO; + +	if (node_handle) +		*node_handle = le16_to_cpu(desc.params.get_link_topo.addr.handle); +	if (node_part_number) +		*node_part_number = desc.params.get_link_topo.node_part_num; + +	return 0; +} + +/** + * ice_is_pf_c827 - check if pf contains c827 phy + * @hw: pointer to the hw struct + */ +bool ice_is_pf_c827(struct ice_hw *hw) +{ +	struct ice_aqc_get_link_topo cmd = {}; +	u8 node_part_number; +	u16 node_handle; +	int status; + +	if (hw->mac_type != ICE_MAC_E810) +		return false; + +	if (hw->device_id != ICE_DEV_ID_E810C_QSFP) +		return true; + +	cmd.addr.topo_params.node_type_ctx = +		FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_TYPE_M, ICE_AQC_LINK_TOPO_NODE_TYPE_PHY) | +		FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M, ICE_AQC_LINK_TOPO_NODE_CTX_PORT); +	cmd.addr.topo_params.index = 0; + +	status = ice_aq_get_netlist_node(hw, &cmd, &node_part_number, +					 &node_handle); + +	if (status || node_part_number != ICE_AQC_GET_LINK_TOPO_NODE_NR_C827) +		return false; + +	if (node_handle == E810C_QSFP_C827_0_HANDLE || node_handle == E810C_QSFP_C827_1_HANDLE) +		return true; + +	return false; +} + +/**   * ice_aq_list_caps - query function/device capabilities   * @hw: pointer to the HW struct   * @buf: a buffer to hold the capabilities @@ -3869,6 +3931,34 @@ ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,  	return status;  } +static enum ice_lut_size ice_lut_type_to_size(enum ice_lut_type type) +{ +	switch (type) { +	case ICE_LUT_VSI: +		return ICE_LUT_VSI_SIZE; +	case ICE_LUT_GLOBAL: +		return ICE_LUT_GLOBAL_SIZE; +	case ICE_LUT_PF: +		return ICE_LUT_PF_SIZE; +	} +	WARN_ONCE(1, "incorrect type passed"); +	return ICE_LUT_VSI_SIZE; +} + +static enum ice_aqc_lut_flags ice_lut_size_to_flag(enum ice_lut_size size) +{ +	switch (size) { +	case ICE_LUT_VSI_SIZE: +		return ICE_AQC_LUT_SIZE_SMALL; +	case ICE_LUT_GLOBAL_SIZE: +		return ICE_AQC_LUT_SIZE_512; +	case ICE_LUT_PF_SIZE: +		return ICE_AQC_LUT_SIZE_2K; +	} +	WARN_ONCE(1, "incorrect size passed"); +	return 0; +} +  /**   * __ice_aq_get_set_rss_lut   * @hw: pointer to the hardware structure @@ -3878,95 +3968,44 @@ ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,   * Internal function to get (0x0B05) or set (0x0B03) RSS look up table   */  static int -__ice_aq_get_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *params, 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; +	u16 opcode, vsi_id, vsi_handle = params->vsi_handle, glob_lut_idx = 0; +	enum ice_lut_type lut_type = params->lut_type; +	struct ice_aqc_get_set_rss_lut *desc_params; +	enum ice_aqc_lut_flags flags; +	enum ice_lut_size lut_size;  	struct ice_aq_desc desc; -	int status; -	u8 *lut; +	u8 *lut = params->lut; -	if (!params) -		return -EINVAL; -	vsi_handle = params->vsi_handle; -	lut = params->lut; - -	if (!ice_is_vsi_valid(hw, vsi_handle) || !lut) +	if (!lut || !ice_is_vsi_valid(hw, vsi_handle))  		return -EINVAL; -	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; +	lut_size = ice_lut_type_to_size(lut_type); +	if (lut_size > params->lut_size) +		return -EINVAL; +	else if (set && lut_size != params->lut_size) +		return -EINVAL; -	if (set) { -		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_lut); +	opcode = set ? ice_aqc_opc_set_rss_lut : ice_aqc_opc_get_rss_lut; +	ice_fill_dflt_direct_cmd_desc(&desc, opcode); +	if (set)  		desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); -	} else { -		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_lut); -	} - -	cmd_resp->vsi_id = cpu_to_le16(((vsi_id << -					 ICE_AQC_GSET_RSS_LUT_VSI_ID_S) & -					ICE_AQC_GSET_RSS_LUT_VSI_ID_M) | -				       ICE_AQC_GSET_RSS_LUT_VSI_VALID); - -	switch (lut_type) { -	case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI: -	case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF: -	case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL: -		flags |= ((lut_type << ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S) & -			  ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_M); -		break; -	default: -		status = -EINVAL; -		goto ice_aq_get_set_rss_lut_exit; -	} - -	if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL) { -		flags |= ((glob_lut_idx << ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_S) & -			  ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_M); -		if (!set) -			goto ice_aq_get_set_rss_lut_send; -	} else if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) { -		if (!set) -			goto ice_aq_get_set_rss_lut_send; -	} else { -		goto ice_aq_get_set_rss_lut_send; -	} +	desc_params = &desc.params.get_set_rss_lut; +	vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); +	desc_params->vsi_id = cpu_to_le16(vsi_id | ICE_AQC_RSS_VSI_VALID); -	/* LUT size is only valid for Global and PF table types */ -	switch (lut_size) { -	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128: -		break; -	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512: -		flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512_FLAG << -			  ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) & -			 ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M; -		break; -	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K: -		if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) { -			flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG << -				  ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) & -				 ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M; -			break; -		} -		fallthrough; -	default: -		status = -EINVAL; -		goto ice_aq_get_set_rss_lut_exit; -	} +	if (lut_type == ICE_LUT_GLOBAL) +		glob_lut_idx = FIELD_PREP(ICE_AQC_LUT_GLOBAL_IDX, +					  params->global_lut_id); -ice_aq_get_set_rss_lut_send: -	cmd_resp->flags = cpu_to_le16(flags); -	status = ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL); +	flags = lut_type | glob_lut_idx | ice_lut_size_to_flag(lut_size); +	desc_params->flags = cpu_to_le16(flags); -ice_aq_get_set_rss_lut_exit: -	return status; +	return ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL);  }  /** @@ -4008,12 +4047,10 @@ static int  __ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id,  			 struct ice_aqc_get_set_rss_keys *key, bool set)  { -	struct ice_aqc_get_set_rss_key *cmd_resp; +	struct ice_aqc_get_set_rss_key *desc_params;  	u16 key_size = sizeof(*key);  	struct ice_aq_desc desc; -	cmd_resp = &desc.params.get_set_rss_key; -  	if (set) {  		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_key);  		desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); @@ -4021,10 +4058,8 @@ __ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id,  		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_key);  	} -	cmd_resp->vsi_id = cpu_to_le16(((vsi_id << -					 ICE_AQC_GSET_RSS_KEY_VSI_ID_S) & -					ICE_AQC_GSET_RSS_KEY_VSI_ID_M) | -				       ICE_AQC_GSET_RSS_KEY_VSI_VALID); +	desc_params = &desc.params.get_set_rss_key; +	desc_params->vsi_id = cpu_to_le16(vsi_id | ICE_AQC_RSS_VSI_VALID);  	return ice_aq_send_cmd(hw, &desc, key, key_size, NULL);  } @@ -4222,6 +4257,53 @@ do_aq:  }  /** + * ice_aq_cfg_lan_txq + * @hw: pointer to the hardware structure + * @buf: buffer for command + * @buf_size: size of buffer in bytes + * @num_qs: number of queues being configured + * @oldport: origination lport + * @newport: destination lport + * @cd: pointer to command details structure or NULL + * + * Move/Configure LAN Tx queue (0x0C32) + * + * There is a better AQ command to use for moving nodes, so only coding + * this one for configuring the node. + */ +int +ice_aq_cfg_lan_txq(struct ice_hw *hw, struct ice_aqc_cfg_txqs_buf *buf, +		   u16 buf_size, u16 num_qs, u8 oldport, u8 newport, +		   struct ice_sq_cd *cd) +{ +	struct ice_aqc_cfg_txqs *cmd; +	struct ice_aq_desc desc; +	int status; + +	cmd = &desc.params.cfg_txqs; +	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_cfg_txqs); +	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); + +	if (!buf) +		return -EINVAL; + +	cmd->cmd_type = ICE_AQC_Q_CFG_TC_CHNG; +	cmd->num_qs = num_qs; +	cmd->port_num_chng = (oldport & ICE_AQC_Q_CFG_SRC_PRT_M); +	cmd->port_num_chng |= (newport << ICE_AQC_Q_CFG_DST_PRT_S) & +			      ICE_AQC_Q_CFG_DST_PRT_M; +	cmd->time_out = (5 << ICE_AQC_Q_CFG_TIMEOUT_S) & +			ICE_AQC_Q_CFG_TIMEOUT_M; +	cmd->blocked_cgds = 0; + +	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); +	if (status) +		ice_debug(hw, ICE_DBG_SCHED, "Failed to reconfigure nodes %d\n", +			  hw->adminq.sq_last_status); +	return status; +} + +/**   * ice_aq_add_rdma_qsets   * @hw: pointer to the hardware structure   * @num_qset_grps: Number of RDMA Qset groups @@ -4700,6 +4782,7 @@ ice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues,  			break;  		ice_free_sched_node(pi, node);  		q_ctx->q_handle = ICE_INVAL_Q_HANDLE; +		q_ctx->q_teid = ICE_INVAL_TEID;  	}  	mutex_unlock(&pi->sched_lock);  	kfree(qg_list);  | 
