int
i40e_pf_host_uninit(struct rte_eth_dev *dev)
{
	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
	uint32_t val;

	PMD_INIT_FUNC_TRACE();

	/**
	 * return if SRIOV not enabled, VF number not configured or
	 * no queue assigned.
	 */
	if ((!hw->func_caps.sr_iov_1_1) ||
		(pf->vf_num == 0) ||
		(pf->vf_nb_qps == 0))
		return I40E_SUCCESS;

	/* free memory to store VF structure */
	rte_free(pf->vfs);
	pf->vfs = NULL;

	/* Disable irq0 for VFR event */
	i40e_pf_disable_irq0(hw);

	/* Disable VF link status interrupt */
	val = I40E_READ_REG(hw, I40E_PFGEN_PORTMDIO_NUM);
	val &= ~I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK;
	I40E_WRITE_REG(hw, I40E_PFGEN_PORTMDIO_NUM, val);
	I40E_WRITE_FLUSH(hw);

	return I40E_SUCCESS;
}
예제 #2
0
파일: i40e_pf.c 프로젝트: AMildner/MoonGen
static int
i40e_pf_host_process_cmd_config_promisc_mode(
					struct i40e_pf_vf *vf,
					uint8_t *msg,
					uint16_t msglen)
{
	int ret = I40E_SUCCESS;
	struct i40e_virtchnl_promisc_info *promisc =
				(struct i40e_virtchnl_promisc_info *)msg;
	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
	bool unicast = FALSE, multicast = FALSE;

	if (msg == NULL || msglen != sizeof(*promisc)) {
		ret = I40E_ERR_PARAM;
		goto send_msg;
	}

	if (promisc->flags & I40E_FLAG_VF_UNICAST_PROMISC)
		unicast = TRUE;
	ret = i40e_aq_set_vsi_unicast_promiscuous(hw,
			vf->vsi->seid, unicast, NULL);
	if (ret != I40E_SUCCESS)
		goto send_msg;

	if (promisc->flags & I40E_FLAG_VF_MULTICAST_PROMISC)
		multicast = TRUE;
	ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vf->vsi->seid,
						multicast, NULL);

send_msg:
	i40e_pf_host_send_msg_to_vf(vf,
		I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE, ret, NULL, 0);

	return ret;
}
static int
i40e_pf_host_process_cmd_config_vsi_queues(struct i40e_pf_vf *vf,
					   uint8_t *msg,
					   uint16_t msglen)
{
	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
	struct i40e_vsi *vsi = vf->vsi;
	struct i40e_virtchnl_vsi_queue_config_info *vc_vqci =
		(struct i40e_virtchnl_vsi_queue_config_info *)msg;
	struct i40e_virtchnl_queue_pair_info *vc_qpi;
	int i, ret = I40E_SUCCESS;

	if (!msg || vc_vqci->num_queue_pairs > vsi->nb_qps ||
		vc_vqci->num_queue_pairs > I40E_MAX_VSI_QP ||
		msglen < I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqci,
					vc_vqci->num_queue_pairs)) {
		PMD_DRV_LOG(ERR, "vsi_queue_config_info argument wrong\n");
		ret = I40E_ERR_PARAM;
		goto send_msg;
	}

	vc_qpi = vc_vqci->qpair;
	for (i = 0; i < vc_vqci->num_queue_pairs; i++) {
		if (vc_qpi[i].rxq.queue_id > vsi->nb_qps - 1 ||
			vc_qpi[i].txq.queue_id > vsi->nb_qps - 1) {
			ret = I40E_ERR_PARAM;
			goto send_msg;
		}

		/*
		 * Apply VF RX queue setting to HMC.
		 * If the opcode is I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT,
		 * then the extra information of
		 * 'struct i40e_virtchnl_queue_pair_extra_info' is needed,
		 * otherwise set the last parameter to NULL.
		 */
		if (i40e_pf_host_hmc_config_rxq(hw, vf, &vc_qpi[i].rxq,
			I40E_CFG_CRCSTRIP_DEFAULT) != I40E_SUCCESS) {
			PMD_DRV_LOG(ERR, "Configure RX queue HMC failed");
			ret = I40E_ERR_PARAM;
			goto send_msg;
		}

		/* Apply VF TX queue setting to HMC */
		if (i40e_pf_host_hmc_config_txq(hw, vf,
			&vc_qpi[i].txq) != I40E_SUCCESS) {
			PMD_DRV_LOG(ERR, "Configure TX queue HMC failed");
			ret = I40E_ERR_PARAM;
			goto send_msg;
		}
	}

send_msg:
	i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES,
							ret, NULL, 0);

	return ret;
}
int
i40e_pf_host_init(struct rte_eth_dev *dev)
{
	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
	int ret, i;
	uint32_t val;

	PMD_INIT_FUNC_TRACE();

	/**
	 * return if SRIOV not enabled, VF number not configured or
	 * no queue assigned.
	 */
	if(!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 || pf->vf_nb_qps == 0)
		return I40E_SUCCESS;

	/* Allocate memory to store VF structure */
	pf->vfs = rte_zmalloc("i40e_pf_vf",sizeof(*pf->vfs) * pf->vf_num, 0);
	if(pf->vfs == NULL)
		return -ENOMEM;

	/* Disable irq0 for VFR event */
	i40e_pf_disable_irq0(hw);

	/* Disable VF link status interrupt */
	val = I40E_READ_REG(hw, I40E_PFGEN_PORTMDIO_NUM);
	val &= ~I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK;
	I40E_WRITE_REG(hw, I40E_PFGEN_PORTMDIO_NUM, val);
	I40E_WRITE_FLUSH(hw);

	for (i = 0; i < pf->vf_num; i++) {
		pf->vfs[i].pf = pf;
		pf->vfs[i].state = I40E_VF_INACTIVE;
		pf->vfs[i].vf_idx = i;
		ret = i40e_pf_host_vf_reset(&pf->vfs[i], 0);
		if (ret != I40E_SUCCESS)
			goto fail;
		eth_random_addr(pf->vfs[i].mac_addr.addr_bytes);
	}

	/* restore irq0 */
	i40e_pf_enable_irq0(hw);

	return I40E_SUCCESS;

fail:
	rte_free(pf->vfs);
	i40e_pf_enable_irq0(hw);

	return ret;
}
예제 #5
0
파일: i40e_fdir.c 프로젝트: RIFTIO/dpdk
/*
 * i40e_set_flx_pld_cfg -configure the rule how bytes stream is extracted as flexible payload
 * @pf: board private structure
 * @cfg: the rule how bytes stream is extracted as flexible payload
 */
static void
i40e_set_flx_pld_cfg(struct i40e_pf *pf,
			 const struct rte_eth_flex_payload_cfg *cfg)
{
	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
	struct i40e_fdir_flex_pit flex_pit[I40E_MAX_FLXPLD_FIED];
	uint32_t flx_pit;
	uint16_t num, min_next_off;  /* in words */
	uint8_t field_idx = 0;
	uint8_t layer_idx = 0;
	uint16_t i;

	if (cfg->type == RTE_ETH_L2_PAYLOAD)
		layer_idx = I40E_FLXPLD_L2_IDX;
	else if (cfg->type == RTE_ETH_L3_PAYLOAD)
		layer_idx = I40E_FLXPLD_L3_IDX;
	else if (cfg->type == RTE_ETH_L4_PAYLOAD)
		layer_idx = I40E_FLXPLD_L4_IDX;

	memset(flex_pit, 0, sizeof(flex_pit));
	num = i40e_srcoff_to_flx_pit(cfg->src_offset, flex_pit);

	for (i = 0; i < RTE_MIN(num, RTE_DIM(flex_pit)); i++) {
		field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
		/* record the info in fdir structure */
		pf->fdir.flex_set[field_idx].src_offset =
			flex_pit[i].src_offset / sizeof(uint16_t);
		pf->fdir.flex_set[field_idx].size =
			flex_pit[i].size / sizeof(uint16_t);
		pf->fdir.flex_set[field_idx].dst_offset =
			flex_pit[i].dst_offset / sizeof(uint16_t);
		flx_pit = MK_FLX_PIT(pf->fdir.flex_set[field_idx].src_offset,
				pf->fdir.flex_set[field_idx].size,
				pf->fdir.flex_set[field_idx].dst_offset);

		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), flx_pit);
	}
	min_next_off = pf->fdir.flex_set[field_idx].src_offset +
				pf->fdir.flex_set[field_idx].size;

	for (; i < I40E_MAX_FLXPLD_FIED; i++) {
		/* set the non-used register obeying register's constrain */
		flx_pit = MK_FLX_PIT(min_next_off, NONUSE_FLX_PIT_FSIZE,
			   NONUSE_FLX_PIT_DEST_OFF);
		I40E_WRITE_REG(hw,
			I40E_PRTQF_FLX_PIT(layer_idx * I40E_MAX_FLXPLD_FIED + i),
			flx_pit);
		min_next_off++;
	}
}
예제 #6
0
파일: i40e_pf.c 프로젝트: AMildner/MoonGen
static int
i40e_pf_host_process_cmd_config_vsi_queues(struct i40e_pf_vf *vf,
					   uint8_t *msg,
					   uint16_t msglen)
{
	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
	struct i40e_vsi *vsi = vf->vsi;
	int ret = I40E_SUCCESS;
	struct i40e_virtchnl_vsi_queue_config_info *qconfig =
	    (struct i40e_virtchnl_vsi_queue_config_info *)msg;
	int i;
	struct i40e_virtchnl_queue_pair_info *qpair;

	if (msg == NULL || msglen <= sizeof(*qconfig) ||
		qconfig->num_queue_pairs > vsi->nb_qps) {
		PMD_DRV_LOG(ERR, "vsi_queue_config_info argument wrong\n");
		ret = I40E_ERR_PARAM;
		goto send_msg;
	}

	qpair = qconfig->qpair;
	for (i = 0; i < qconfig->num_queue_pairs; i++) {
		if (qpair[i].rxq.queue_id > vsi->nb_qps - 1 ||
			qpair[i].txq.queue_id > vsi->nb_qps - 1) {
			ret = I40E_ERR_PARAM;
			goto send_msg;
		}

		/* Apply VF RX queue setting to HMC */
		if (i40e_pf_host_hmc_config_rxq(hw, vf, &qpair[i].rxq)
			!= I40E_SUCCESS) {
			PMD_DRV_LOG(ERR, "Configure RX queue HMC failed");
			ret = I40E_ERR_PARAM;
			goto send_msg;
		}

		/* Apply VF TX queue setting to HMC */
		if (i40e_pf_host_hmc_config_txq(hw, vf, &qpair[i].txq)
			!= I40E_SUCCESS) {
			PMD_DRV_LOG(ERR, "Configure TX queue HMC failed");
			ret = I40E_ERR_PARAM;
			goto send_msg;
		}
	}

send_msg:
	i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES,
							ret, NULL, 0);
	return ret;
}
예제 #7
0
static int
i40e_pf_host_process_cmd_get_vf_resource(struct i40e_pf_vf *vf, bool b_op)
{
	struct virtchnl_vf_resource *vf_res = NULL;
	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
	uint32_t len = 0;
	int ret = I40E_SUCCESS;

	if (!b_op) {
		i40e_pf_host_send_msg_to_vf(vf,
					    VIRTCHNL_OP_GET_VF_RESOURCES,
					    I40E_NOT_SUPPORTED, NULL, 0);
		return ret;
	}

	/* only have 1 VSI by default */
	len =  sizeof(struct virtchnl_vf_resource) +
				I40E_DEFAULT_VF_VSI_NUM *
		sizeof(struct virtchnl_vsi_resource);

	vf_res = rte_zmalloc("i40e_vf_res", len, 0);
	if (vf_res == NULL) {
		PMD_DRV_LOG(ERR, "failed to allocate mem");
		ret = I40E_ERR_NO_MEMORY;
		vf_res = NULL;
		len = 0;
		goto send_msg;
	}

	vf_res->vf_offload_flags = VIRTCHNL_VF_OFFLOAD_L2 |
				VIRTCHNL_VF_OFFLOAD_VLAN;
	vf_res->max_vectors = hw->func_caps.num_msix_vectors_vf;
	vf_res->num_queue_pairs = vf->vsi->nb_qps;
	vf_res->num_vsis = I40E_DEFAULT_VF_VSI_NUM;

	/* Change below setting if PF host can support more VSIs for VF */
	vf_res->vsi_res[0].vsi_type = VIRTCHNL_VSI_SRIOV;
	vf_res->vsi_res[0].vsi_id = vf->vsi->vsi_id;
	vf_res->vsi_res[0].num_queue_pairs = vf->vsi->nb_qps;
	ether_addr_copy(&vf->mac_addr,
		(struct ether_addr *)vf_res->vsi_res[0].default_mac_addr);

send_msg:
	i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_GET_VF_RESOURCES,
					ret, (uint8_t *)vf_res, len);
	rte_free(vf_res);

	return ret;
}
예제 #8
0
파일: i40e_pf.c 프로젝트: AMildner/MoonGen
/**
 * Bind PF queues with VSI and VF.
 **/
static int
i40e_pf_vf_queues_mapping(struct i40e_pf_vf *vf)
{
	int i;
	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
	uint16_t vsi_id = vf->vsi->vsi_id;
	uint16_t vf_id  = vf->vf_idx;
	uint16_t nb_qps = vf->vsi->nb_qps;
	uint16_t qbase  = vf->vsi->base_queue;
	uint16_t q1, q2;
	uint32_t val;

	/*
	 * VF should use scatter range queues. So, it needn't
	 * to set QBASE in this register.
	 */
	I40E_WRITE_REG(hw, I40E_VSILAN_QBASE(vsi_id),
	     I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK);

	/* Set to enable VFLAN_QTABLE[] registers valid */
	I40E_WRITE_REG(hw, I40E_VPLAN_MAPENA(vf_id),
		I40E_VPLAN_MAPENA_TXRX_ENA_MASK);

	/* map PF queues to VF */
	for (i = 0; i < nb_qps; i++) {
		val = ((qbase + i) & I40E_VPLAN_QTABLE_QINDEX_MASK);
		I40E_WRITE_REG(hw, I40E_VPLAN_QTABLE(i, vf_id), val);
	}

	/* map PF queues to VSI */
	for (i = 0; i < I40E_MAX_QP_NUM_PER_VF / 2; i++) {
		if (2 * i > nb_qps - 1)
			q1 = I40E_VSILAN_QTABLE_QINDEX_0_MASK;
		else
			q1 = qbase + 2 * i;

		if (2 * i + 1 > nb_qps - 1)
			q2 = I40E_VSILAN_QTABLE_QINDEX_0_MASK;
		else
			q2 = qbase + 2 * i + 1;

		val = (q2 << I40E_VSILAN_QTABLE_QINDEX_1_SHIFT) + q1;
		I40E_WRITE_REG(hw, I40E_VSILAN_QTABLE(i, vsi_id), val);
	}
	I40E_WRITE_FLUSH(hw);

	return I40E_SUCCESS;
}
예제 #9
0
파일: i40e_pf.c 프로젝트: AMildner/MoonGen
static int
i40e_pf_host_switch_queues(struct i40e_pf_vf *vf,
			   struct i40e_virtchnl_queue_select *qsel,
			   bool on)
{
	int ret = I40E_SUCCESS;
	int i;
	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
	uint16_t baseq = vf->vsi->base_queue;

	if (qsel->rx_queues + qsel->tx_queues == 0)
		return I40E_ERR_PARAM;

	/* always enable RX first and disable last */
	/* Enable RX if it's enable */
	if (on) {
		for (i = 0; i < I40E_MAX_QP_NUM_PER_VF; i++)
			if (qsel->rx_queues & (1 << i)) {
				ret = i40e_switch_rx_queue(hw, baseq + i, on);
				if (ret != I40E_SUCCESS)
					return ret;
			}
	}

	/* Enable/Disable TX */
	for (i = 0; i < I40E_MAX_QP_NUM_PER_VF; i++)
		if (qsel->tx_queues & (1 << i)) {
			ret = i40e_switch_tx_queue(hw, baseq + i, on);
			if (ret != I40E_SUCCESS)
				return ret;
		}

	/* disable RX last if it's disable */
	if (!on) {
		/* disable RX */
		for (i = 0; i < I40E_MAX_QP_NUM_PER_VF; i++)
			if (qsel->rx_queues & (1 << i)) {
				ret = i40e_switch_rx_queue(hw, baseq + i, on);
				if (ret != I40E_SUCCESS)
					return ret;
			}
	}

	return ret;
}
예제 #10
0
파일: i40e_fdir.c 프로젝트: RIFTIO/dpdk
/*
 * i40e_fdir_teardown - release the Flow Director resources
 * @pf: board private structure
 */
void
i40e_fdir_teardown(struct i40e_pf *pf)
{
	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
	struct i40e_vsi *vsi;

	vsi = pf->fdir.fdir_vsi;
	if (!vsi)
		return;
	i40e_switch_tx_queue(hw, vsi->base_queue, FALSE);
	i40e_switch_rx_queue(hw, vsi->base_queue, FALSE);
	i40e_dev_rx_queue_release(pf->fdir.rxq);
	pf->fdir.rxq = NULL;
	i40e_dev_tx_queue_release(pf->fdir.txq);
	pf->fdir.txq = NULL;
	i40e_vsi_release(vsi);
	pf->fdir.fdir_vsi = NULL;
}
예제 #11
0
파일: i40e_fdir.c 프로젝트: RIFTIO/dpdk
/*
 * i40e_set_flex_mask_on_pctype - configure the mask on flexible payload
 * @pf: board private structure
 * @pctype: packet classify type
 * @flex_masks: mask for flexible payload
 */
static void
i40e_set_flex_mask_on_pctype(struct i40e_pf *pf,
		enum i40e_filter_pctype pctype,
		const struct rte_eth_fdir_flex_mask *mask_cfg)
{
	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
	struct i40e_fdir_flex_mask *flex_mask;
	uint32_t flxinset, fd_mask;
	uint16_t mask_tmp;
	uint8_t i, nb_bitmask = 0;

	flex_mask = &pf->fdir.flex_mask[pctype];
	memset(flex_mask, 0, sizeof(struct i40e_fdir_flex_mask));
	for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i += sizeof(uint16_t)) {
		mask_tmp = I40E_WORD(mask_cfg->mask[i], mask_cfg->mask[i + 1]);
		if (mask_tmp != 0x0) {
			flex_mask->word_mask |=
				I40E_FLEX_WORD_MASK(i / sizeof(uint16_t));
			if (mask_tmp != UINT16_MAX) {
				/* set bit mask */
				flex_mask->bitmask[nb_bitmask].mask = ~mask_tmp;
				flex_mask->bitmask[nb_bitmask].offset =
					i / sizeof(uint16_t);
				nb_bitmask++;
			}
		}
	}
	/* write mask to hw */
	flxinset = (flex_mask->word_mask <<
		I40E_PRTQF_FD_FLXINSET_INSET_SHIFT) &
		I40E_PRTQF_FD_FLXINSET_INSET_MASK;
	i40e_write_rx_ctl(hw, I40E_PRTQF_FD_FLXINSET(pctype), flxinset);

	for (i = 0; i < nb_bitmask; i++) {
		fd_mask = (flex_mask->bitmask[i].mask <<
			I40E_PRTQF_FD_MSK_MASK_SHIFT) &
			I40E_PRTQF_FD_MSK_MASK_MASK;
		fd_mask |= ((flex_mask->bitmask[i].offset +
			I40E_FLX_OFFSET_IN_FIELD_VECTOR) <<
			I40E_PRTQF_FD_MSK_OFFSET_SHIFT) &
			I40E_PRTQF_FD_MSK_OFFSET_MASK;
		i40e_write_rx_ctl(hw, I40E_PRTQF_FD_MSK(pctype, i), fd_mask);
	}
}
static int
i40e_pf_host_send_msg_to_vf(struct i40e_pf_vf *vf,
			    uint32_t opcode,
			    uint32_t retval,
			    uint8_t *msg,
			    uint16_t msglen)
{
	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
	uint16_t abs_vf_id = hw->func_caps.vf_base_id + vf->vf_idx;
	int ret;

	ret = i40e_aq_send_msg_to_vf(hw, abs_vf_id, opcode, retval,
						msg, msglen, NULL);
	if (ret) {
		PMD_INIT_LOG(ERR, "Fail to send message to VF, err %u",
			     hw->aq.asq_last_status);
	}

	return ret;
}
예제 #13
0
파일: i40e_pf.c 프로젝트: AMildner/MoonGen
static int
i40e_pf_host_process_cmd_get_vf_resource(struct i40e_pf_vf *vf)
{
	struct i40e_virtchnl_vf_resource *vf_res = NULL;
	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
	uint32_t len = 0;
	int ret = I40E_SUCCESS;

	/* only have 1 VSI by default */
	len =  sizeof(struct i40e_virtchnl_vf_resource) +
				I40E_DEFAULT_VF_VSI_NUM *
		sizeof(struct i40e_virtchnl_vsi_resource);

	vf_res = rte_zmalloc("i40e_vf_res", len, 0);
	if (vf_res == NULL) {
		PMD_DRV_LOG(ERR, "failed to allocate mem\n");
		ret = I40E_ERR_NO_MEMORY;
		vf_res = NULL;
		len = 0;
		goto send_msg;
	}

	vf_res->vf_offload_flags = I40E_VIRTCHNL_VF_OFFLOAD_L2 |
				I40E_VIRTCHNL_VF_OFFLOAD_VLAN;
	vf_res->max_vectors = hw->func_caps.num_msix_vectors_vf;
	vf_res->num_queue_pairs = vf->vsi->nb_qps;
	vf_res->num_vsis = I40E_DEFAULT_VF_VSI_NUM;

	/* Change below setting if PF host can support more VSIs for VF */
	vf_res->vsi_res[0].vsi_type = I40E_VSI_SRIOV;
	/* As assume Vf only has single VSI now, always return 0 */
	vf_res->vsi_res[0].vsi_id = 0;
	vf_res->vsi_res[0].num_queue_pairs = vf->vsi->nb_qps;

send_msg:
	i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_VF_RESOURCES,
					ret, (uint8_t *)vf_res, len);
	rte_free(vf_res);

	return ret;
}
예제 #14
0
파일: i40e_fdir.c 프로젝트: RIFTIO/dpdk
/*
 * Initialize the configuration about bytes stream extracted as flexible payload
 * and mask setting
 */
static inline void
i40e_init_flx_pld(struct i40e_pf *pf)
{
	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
	uint8_t pctype;
	int i, index;

	/*
	 * Define the bytes stream extracted as flexible payload in
	 * field vector. By default, select 8 words from the beginning
	 * of payload as flexible payload.
	 */
	for (i = I40E_FLXPLD_L2_IDX; i < I40E_MAX_FLXPLD_LAYER; i++) {
		index = i * I40E_MAX_FLXPLD_FIED;
		pf->fdir.flex_set[index].src_offset = 0;
		pf->fdir.flex_set[index].size = I40E_FDIR_MAX_FLEXWORD_NUM;
		pf->fdir.flex_set[index].dst_offset = 0;
		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(index), 0x0000C900);
		I40E_WRITE_REG(hw,
			I40E_PRTQF_FLX_PIT(index + 1), 0x0000FC29);/*non-used*/
		I40E_WRITE_REG(hw,
			I40E_PRTQF_FLX_PIT(index + 2), 0x0000FC2A);/*non-used*/
	}

	/* initialize the masks */
	for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
	     pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++) {
		if (!I40E_VALID_PCTYPE((enum i40e_filter_pctype)pctype))
			continue;
		pf->fdir.flex_mask[pctype].word_mask = 0;
		i40e_write_rx_ctl(hw, I40E_PRTQF_FD_FLXINSET(pctype), 0);
		for (i = 0; i < I40E_FDIR_BITMASK_NUM_WORD; i++) {
			pf->fdir.flex_mask[pctype].bitmask[i].offset = 0;
			pf->fdir.flex_mask[pctype].bitmask[i].mask = 0;
			i40e_write_rx_ctl(hw, I40E_PRTQF_FD_MSK(pctype, i), 0);
		}
	}
}
예제 #15
0
파일: i40e_fdir.c 프로젝트: RIFTIO/dpdk
/*
 * i40e_fdir_setup - reserve and initialize the Flow Director resources
 * @pf: board private structure
 */
int
i40e_fdir_setup(struct i40e_pf *pf)
{
	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
	struct i40e_vsi *vsi;
	int err = I40E_SUCCESS;
	char z_name[RTE_MEMZONE_NAMESIZE];
	const struct rte_memzone *mz = NULL;
	struct rte_eth_dev *eth_dev = pf->adapter->eth_dev;

	if ((pf->flags & I40E_FLAG_FDIR) == 0) {
		PMD_INIT_LOG(ERR, "HW doesn't support FDIR");
		return I40E_NOT_SUPPORTED;
	}

	PMD_DRV_LOG(INFO, "FDIR HW Capabilities: num_filters_guaranteed = %u,"
			" num_filters_best_effort = %u.",
			hw->func_caps.fd_filters_guaranteed,
			hw->func_caps.fd_filters_best_effort);

	vsi = pf->fdir.fdir_vsi;
	if (vsi) {
		PMD_DRV_LOG(INFO, "FDIR initialization has been done.");
		return I40E_SUCCESS;
	}
	/* make new FDIR VSI */
	vsi = i40e_vsi_setup(pf, I40E_VSI_FDIR, pf->main_vsi, 0);
	if (!vsi) {
		PMD_DRV_LOG(ERR, "Couldn't create FDIR VSI.");
		return I40E_ERR_NO_AVAILABLE_VSI;
	}
	pf->fdir.fdir_vsi = vsi;

	/*Fdir tx queue setup*/
	err = i40e_fdir_setup_tx_resources(pf);
	if (err) {
		PMD_DRV_LOG(ERR, "Failed to setup FDIR TX resources.");
		goto fail_setup_tx;
	}

	/*Fdir rx queue setup*/
	err = i40e_fdir_setup_rx_resources(pf);
	if (err) {
		PMD_DRV_LOG(ERR, "Failed to setup FDIR RX resources.");
		goto fail_setup_rx;
	}

	err = i40e_tx_queue_init(pf->fdir.txq);
	if (err) {
		PMD_DRV_LOG(ERR, "Failed to do FDIR TX initialization.");
		goto fail_mem;
	}

	/* need switch on before dev start*/
	err = i40e_switch_tx_queue(hw, vsi->base_queue, TRUE);
	if (err) {
		PMD_DRV_LOG(ERR, "Failed to do fdir TX switch on.");
		goto fail_mem;
	}

	/* Init the rx queue in hardware */
	err = i40e_fdir_rx_queue_init(pf->fdir.rxq);
	if (err) {
		PMD_DRV_LOG(ERR, "Failed to do FDIR RX initialization.");
		goto fail_mem;
	}

	/* switch on rx queue */
	err = i40e_switch_rx_queue(hw, vsi->base_queue, TRUE);
	if (err) {
		PMD_DRV_LOG(ERR, "Failed to do FDIR RX switch on.");
		goto fail_mem;
	}

	/* reserve memory for the fdir programming packet */
	snprintf(z_name, sizeof(z_name), "%s_%s_%d",
			eth_dev->driver->pci_drv.name,
			I40E_FDIR_MZ_NAME,
			eth_dev->data->port_id);
	mz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN, SOCKET_ID_ANY);
	if (!mz) {
		PMD_DRV_LOG(ERR, "Cannot init memzone for "
				 "flow director program packet.");
		err = I40E_ERR_NO_MEMORY;
		goto fail_mem;
	}
	pf->fdir.prg_pkt = mz->addr;
	pf->fdir.dma_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);

	pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id);
	PMD_DRV_LOG(INFO, "FDIR setup successfully, with programming queue %u.",
		    vsi->base_queue);
	return I40E_SUCCESS;

fail_mem:
	i40e_dev_rx_queue_release(pf->fdir.rxq);
	pf->fdir.rxq = NULL;
fail_setup_rx:
	i40e_dev_tx_queue_release(pf->fdir.txq);
	pf->fdir.txq = NULL;
fail_setup_tx:
	i40e_vsi_release(vsi);
	pf->fdir.fdir_vsi = NULL;
	return err;
}
예제 #16
0
파일: i40e_pf.c 프로젝트: AMildner/MoonGen
/**
 * Proceed VF reset operation.
 */
int
i40e_pf_host_vf_reset(struct i40e_pf_vf *vf, bool do_hw_reset)
{
	uint32_t val, i;
	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
	uint16_t vf_id, abs_vf_id, vf_msix_num;
	int ret;
	struct i40e_virtchnl_queue_select qsel;

	if (vf == NULL)
		return -EINVAL;

	vf_id = vf->vf_idx;
	abs_vf_id = vf_id + hw->func_caps.vf_base_id;

	/* Notify VF that we are in VFR progress */
	I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_PF_VFR_INPROGRESS);

	/*
	 * If require a SW VF reset, a VFLR interrupt will be generated,
	 * this function will be called again. To avoid it,
	 * disable interrupt first.
	 */
	if (do_hw_reset) {
		vf->state = I40E_VF_INRESET;
		val = I40E_READ_REG(hw, I40E_VPGEN_VFRTRIG(vf_id));
		val |= I40E_VPGEN_VFRTRIG_VFSWR_MASK;
		I40E_WRITE_REG(hw, I40E_VPGEN_VFRTRIG(vf_id), val);
		I40E_WRITE_FLUSH(hw);
	}

#define VFRESET_MAX_WAIT_CNT 100
	/* Wait until VF reset is done */
	for (i = 0; i < VFRESET_MAX_WAIT_CNT; i++) {
		rte_delay_us(10);
		val = I40E_READ_REG(hw, I40E_VPGEN_VFRSTAT(vf_id));
		if (val & I40E_VPGEN_VFRSTAT_VFRD_MASK)
			break;
	}

	if (i >= VFRESET_MAX_WAIT_CNT) {
		PMD_DRV_LOG(ERR, "VF reset timeout\n");
		return -ETIMEDOUT;
	}

	/* This is not first time to do reset, do cleanup job first */
	if (vf->vsi) {
		/* Disable queues */
		memset(&qsel, 0, sizeof(qsel));
		for (i = 0; i < vf->vsi->nb_qps; i++)
			qsel.rx_queues |= 1 << i;
		qsel.tx_queues = qsel.rx_queues;
		ret = i40e_pf_host_switch_queues(vf, &qsel, false);
		if (ret != I40E_SUCCESS) {
			PMD_DRV_LOG(ERR, "Disable VF queues failed\n");
			return -EFAULT;
		}

		/* Disable VF interrupt setting */
		vf_msix_num = hw->func_caps.num_msix_vectors_vf;
		for (i = 0; i < vf_msix_num; i++) {
			if (!i)
				val = I40E_VFINT_DYN_CTL0(vf_id);
			else
				val = I40E_VFINT_DYN_CTLN(((vf_msix_num - 1) *
							(vf_id)) + (i - 1));
			I40E_WRITE_REG(hw, val, I40E_VFINT_DYN_CTLN_CLEARPBA_MASK);
		}
		I40E_WRITE_FLUSH(hw);

		/* remove VSI */
		ret = i40e_vsi_release(vf->vsi);
		if (ret != I40E_SUCCESS) {
			PMD_DRV_LOG(ERR, "Release VSI failed\n");
			return -EFAULT;
		}
	}

#define I40E_VF_PCI_ADDR  0xAA
#define I40E_VF_PEND_MASK 0x20
	/* Check the pending transactions of this VF */
	/* Use absolute VF id, refer to datasheet for details */
	I40E_WRITE_REG(hw, I40E_PF_PCI_CIAA, I40E_VF_PCI_ADDR |
		(abs_vf_id << I40E_PF_PCI_CIAA_VF_NUM_SHIFT));
	for (i = 0; i < VFRESET_MAX_WAIT_CNT; i++) {
		rte_delay_us(1);
		val = I40E_READ_REG(hw, I40E_PF_PCI_CIAD);
		if ((val & I40E_VF_PEND_MASK) == 0)
			break;
	}

	if (i >= VFRESET_MAX_WAIT_CNT) {
		PMD_DRV_LOG(ERR, "Wait VF PCI transaction end timeout\n");
		return -ETIMEDOUT;
	}

	/* Reset done, Set COMPLETE flag and clear reset bit */
	I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_PF_VFR_COMPLETED);
	val = I40E_READ_REG(hw, I40E_VPGEN_VFRTRIG(vf_id));
	val &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK;
	I40E_WRITE_REG(hw, I40E_VPGEN_VFRTRIG(vf_id), val);
	vf->reset_cnt++;
	I40E_WRITE_FLUSH(hw);

	/* Allocate resource again */
	vf->vsi = i40e_vsi_setup(vf->pf, I40E_VSI_SRIOV,
			vf->pf->main_vsi, vf->vf_idx);
	if (vf->vsi == NULL) {
		PMD_DRV_LOG(ERR, "Add vsi failed\n");
		return -EFAULT;
	}

	ret = i40e_pf_vf_queues_mapping(vf);
	if (ret != I40E_SUCCESS) {
		PMD_DRV_LOG(ERR, "queue mapping error\n");
		i40e_vsi_release(vf->vsi);
		return -EFAULT;
	}

	return ret;
}