diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_virtchnl.c')
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_virtchnl.c | 219 | 
1 files changed, 207 insertions, 12 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c index 2b4c791b6cba..e24e3f5017ca 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c @@ -462,6 +462,9 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg)  			vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RSS_REG;  	} +	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC) +		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC; +  	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_FDIR_PF)  		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_FDIR_PF; @@ -504,7 +507,7 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg)  	vfres->vsi_res[0].vsi_type = VIRTCHNL_VSI_SRIOV;  	vfres->vsi_res[0].num_queue_pairs = vsi->num_txq;  	ether_addr_copy(vfres->vsi_res[0].default_mac_addr, -			vf->hw_lan_addr.addr); +			vf->hw_lan_addr);  	/* match guest capabilities */  	vf->driver_caps = vfres->vf_cap_flags; @@ -1658,6 +1661,7 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)  		/* copy Rx queue info from VF into VSI */  		if (qpi->rxq.ring_len > 0) {  			u16 max_frame_size = ice_vc_get_max_frame_size(vf); +			u32 rxdid;  			vsi->rx_rings[i]->dma = qpi->rxq.dma_ring_addr;  			vsi->rx_rings[i]->count = qpi->rxq.ring_len; @@ -1685,6 +1689,24 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)  					 vf->vf_id, i);  				goto error_param;  			} + +			/* If Rx flex desc is supported, select RXDID for Rx +			 * queues. Otherwise, use legacy 32byte descriptor +			 * format. Legacy 16byte descriptor is not supported. +			 * If this RXDID is selected, return error. +			 */ +			if (vf->driver_caps & +			    VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC) { +				rxdid = qpi->rxq.rxdid; +				if (!(BIT(rxdid) & pf->supported_rxdids)) +					goto error_param; +			} else { +				rxdid = ICE_RXDID_LEGACY_1; +			} + +			ice_write_qrxflxp_cntxt(&vsi->back->hw, +						vsi->rxq_map[q_idx], +						rxdid, 0x03, false);  		}  	} @@ -1780,10 +1802,10 @@ ice_vfhw_mac_add(struct ice_vf *vf, struct virtchnl_ether_addr *vc_ether_addr)  	 * was correctly specified over VIRTCHNL  	 */  	if ((ice_is_vc_addr_legacy(vc_ether_addr) && -	     is_zero_ether_addr(vf->hw_lan_addr.addr)) || +	     is_zero_ether_addr(vf->hw_lan_addr)) ||  	    ice_is_vc_addr_primary(vc_ether_addr)) { -		ether_addr_copy(vf->dev_lan_addr.addr, mac_addr); -		ether_addr_copy(vf->hw_lan_addr.addr, mac_addr); +		ether_addr_copy(vf->dev_lan_addr, mac_addr); +		ether_addr_copy(vf->hw_lan_addr, mac_addr);  	}  	/* hardware and device MACs are already set, but its possible that the @@ -1814,7 +1836,7 @@ ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi,  	int ret;  	/* device MAC already added */ -	if (ether_addr_equal(mac_addr, vf->dev_lan_addr.addr)) +	if (ether_addr_equal(mac_addr, vf->dev_lan_addr))  		return 0;  	if (is_unicast_ether_addr(mac_addr) && !ice_can_vf_change_mac(vf)) { @@ -1869,8 +1891,8 @@ ice_update_legacy_cached_mac(struct ice_vf *vf,  	    ice_is_legacy_umac_expired(&vf->legacy_last_added_umac))  		return; -	ether_addr_copy(vf->dev_lan_addr.addr, vf->legacy_last_added_umac.addr); -	ether_addr_copy(vf->hw_lan_addr.addr, vf->legacy_last_added_umac.addr); +	ether_addr_copy(vf->dev_lan_addr, vf->legacy_last_added_umac.addr); +	ether_addr_copy(vf->hw_lan_addr, vf->legacy_last_added_umac.addr);  }  /** @@ -1884,15 +1906,15 @@ ice_vfhw_mac_del(struct ice_vf *vf, struct virtchnl_ether_addr *vc_ether_addr)  	u8 *mac_addr = vc_ether_addr->addr;  	if (!is_valid_ether_addr(mac_addr) || -	    !ether_addr_equal(vf->dev_lan_addr.addr, mac_addr)) +	    !ether_addr_equal(vf->dev_lan_addr, mac_addr))  		return;  	/* allow the device MAC to be repopulated in the add flow and don't -	 * clear the hardware MAC (i.e. hw_lan_addr.addr) here as that is meant +	 * clear the hardware MAC (i.e. hw_lan_addr) here as that is meant  	 * to be persistent on VM reboot and across driver unload/load, which  	 * won't work if we clear the hardware MAC here  	 */ -	eth_zero_addr(vf->dev_lan_addr.addr); +	eth_zero_addr(vf->dev_lan_addr);  	ice_update_legacy_cached_mac(vf, vc_ether_addr);  } @@ -1912,7 +1934,7 @@ ice_vc_del_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi,  	int status;  	if (!ice_can_vf_change_mac(vf) && -	    ether_addr_equal(vf->dev_lan_addr.addr, mac_addr)) +	    ether_addr_equal(vf->dev_lan_addr, mac_addr))  		return 0;  	status = ice_fltr_remove_mac(vsi, mac_addr, ICE_FWD_TO_VSI); @@ -2457,6 +2479,164 @@ error_param:  }  /** + * ice_vc_get_rss_hena - return the RSS HENA bits allowed by the hardware + * @vf: pointer to the VF info + */ +static int ice_vc_get_rss_hena(struct ice_vf *vf) +{ +	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; +	struct virtchnl_rss_hena *vrh = NULL; +	int len = 0, ret; + +	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { +		v_ret = VIRTCHNL_STATUS_ERR_PARAM; +		goto err; +	} + +	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) { +		dev_err(ice_pf_to_dev(vf->pf), "RSS not supported by PF\n"); +		v_ret = VIRTCHNL_STATUS_ERR_PARAM; +		goto err; +	} + +	len = sizeof(struct virtchnl_rss_hena); +	vrh = kzalloc(len, GFP_KERNEL); +	if (!vrh) { +		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; +		len = 0; +		goto err; +	} + +	vrh->hena = ICE_DEFAULT_RSS_HENA; +err: +	/* send the response back to the VF */ +	ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_RSS_HENA_CAPS, v_ret, +				    (u8 *)vrh, len); +	kfree(vrh); +	return ret; +} + +/** + * ice_vc_set_rss_hena - set RSS HENA bits for the VF + * @vf: pointer to the VF info + * @msg: pointer to the msg buffer + */ +static int ice_vc_set_rss_hena(struct ice_vf *vf, u8 *msg) +{ +	struct virtchnl_rss_hena *vrh = (struct virtchnl_rss_hena *)msg; +	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; +	struct ice_pf *pf = vf->pf; +	struct ice_vsi *vsi; +	struct device *dev; +	int status; + +	dev = ice_pf_to_dev(pf); + +	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { +		v_ret = VIRTCHNL_STATUS_ERR_PARAM; +		goto err; +	} + +	if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { +		dev_err(dev, "RSS not supported by PF\n"); +		v_ret = VIRTCHNL_STATUS_ERR_PARAM; +		goto err; +	} + +	vsi = ice_get_vf_vsi(vf); +	if (!vsi) { +		v_ret = VIRTCHNL_STATUS_ERR_PARAM; +		goto err; +	} + +	/* clear all previously programmed RSS configuration to allow VF drivers +	 * the ability to customize the RSS configuration and/or completely +	 * disable RSS +	 */ +	status = ice_rem_vsi_rss_cfg(&pf->hw, vsi->idx); +	if (status && !vrh->hena) { +		/* only report failure to clear the current RSS configuration if +		 * that was clearly the VF's intention (i.e. vrh->hena = 0) +		 */ +		v_ret = ice_err_to_virt_err(status); +		goto err; +	} else if (status) { +		/* allow the VF to update the RSS configuration even on failure +		 * to clear the current RSS confguration in an attempt to keep +		 * RSS in a working state +		 */ +		dev_warn(dev, "Failed to clear the RSS configuration for VF %u\n", +			 vf->vf_id); +	} + +	if (vrh->hena) { +		status = ice_add_avf_rss_cfg(&pf->hw, vsi->idx, vrh->hena); +		v_ret = ice_err_to_virt_err(status); +	} + +	/* send the response to the VF */ +err: +	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_SET_RSS_HENA, v_ret, +				     NULL, 0); +} + +/** + * ice_vc_query_rxdid - query RXDID supported by DDP package + * @vf: pointer to VF info + * + * Called from VF to query a bitmap of supported flexible + * descriptor RXDIDs of a DDP package. + */ +static int ice_vc_query_rxdid(struct ice_vf *vf) +{ +	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; +	struct virtchnl_supported_rxdids *rxdid = NULL; +	struct ice_hw *hw = &vf->pf->hw; +	struct ice_pf *pf = vf->pf; +	int len = 0; +	int ret, i; +	u32 regval; + +	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { +		v_ret = VIRTCHNL_STATUS_ERR_PARAM; +		goto err; +	} + +	if (!(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC)) { +		v_ret = VIRTCHNL_STATUS_ERR_PARAM; +		goto err; +	} + +	len = sizeof(struct virtchnl_supported_rxdids); +	rxdid = kzalloc(len, GFP_KERNEL); +	if (!rxdid) { +		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; +		len = 0; +		goto err; +	} + +	/* Read flexiflag registers to determine whether the +	 * corresponding RXDID is configured and supported or not. +	 * Since Legacy 16byte descriptor format is not supported, +	 * start from Legacy 32byte descriptor. +	 */ +	for (i = ICE_RXDID_LEGACY_1; i < ICE_FLEX_DESC_RXDID_MAX_NUM; i++) { +		regval = rd32(hw, GLFLXP_RXDID_FLAGS(i, 0)); +		if ((regval >> GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S) +			& GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M) +			rxdid->supported_rxdids |= BIT(i); +	} + +	pf->supported_rxdids = rxdid->supported_rxdids; + +err: +	ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_SUPPORTED_RXDIDS, +				    v_ret, (u8 *)rxdid, len); +	kfree(rxdid); +	return ret; +} + +/**   * ice_vf_init_vlan_stripping - enable/disable VLAN stripping on initialization   * @vf: VF to enable/disable VLAN stripping for on initialization   * @@ -3490,6 +3670,9 @@ static const struct ice_virtchnl_ops ice_virtchnl_dflt_ops = {  	.cfg_promiscuous_mode_msg = ice_vc_cfg_promiscuous_mode_msg,  	.add_vlan_msg = ice_vc_add_vlan_msg,  	.remove_vlan_msg = ice_vc_remove_vlan_msg, +	.query_rxdid = ice_vc_query_rxdid, +	.get_rss_hena = ice_vc_get_rss_hena, +	.set_rss_hena_msg = ice_vc_set_rss_hena,  	.ena_vlan_stripping = ice_vc_ena_vlan_stripping,  	.dis_vlan_stripping = ice_vc_dis_vlan_stripping,  	.handle_rss_cfg_msg = ice_vc_handle_rss_cfg, @@ -3550,7 +3733,7 @@ static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg)  		int result;  		if (!is_unicast_ether_addr(mac_addr) || -		    ether_addr_equal(mac_addr, vf->hw_lan_addr.addr)) +		    ether_addr_equal(mac_addr, vf->hw_lan_addr))  			continue;  		if (vf->pf_set_mac) { @@ -3624,6 +3807,9 @@ static const struct ice_virtchnl_ops ice_virtchnl_repr_ops = {  	.cfg_promiscuous_mode_msg = ice_vc_repr_cfg_promiscuous_mode,  	.add_vlan_msg = ice_vc_add_vlan_msg,  	.remove_vlan_msg = ice_vc_remove_vlan_msg, +	.query_rxdid = ice_vc_query_rxdid, +	.get_rss_hena = ice_vc_get_rss_hena, +	.set_rss_hena_msg = ice_vc_set_rss_hena,  	.ena_vlan_stripping = ice_vc_ena_vlan_stripping,  	.dis_vlan_stripping = ice_vc_dis_vlan_stripping,  	.handle_rss_cfg_msg = ice_vc_handle_rss_cfg, @@ -3764,6 +3950,15 @@ error_handler:  	case VIRTCHNL_OP_DEL_VLAN:  		err = ops->remove_vlan_msg(vf, msg);  		break; +	case VIRTCHNL_OP_GET_SUPPORTED_RXDIDS: +		err = ops->query_rxdid(vf); +		break; +	case VIRTCHNL_OP_GET_RSS_HENA_CAPS: +		err = ops->get_rss_hena(vf); +		break; +	case VIRTCHNL_OP_SET_RSS_HENA: +		err = ops->set_rss_hena_msg(vf, msg); +		break;  	case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:  		err = ops->ena_vlan_stripping(vf);  		break;  |