[dpdk-dev,v2,5/5] i40evf: support of configurable crc stripping in VF

Message ID 1410706109-30448-6-git-send-email-helin.zhang@intel.com (mailing list archive)
State Superseded, archived
Headers

Commit Message

Zhang, Helin Sept. 14, 2014, 2:48 p.m. UTC
  Configurable crc stripping is supported in DPDK PF host,
while not in Linux PF host. Two functions have been
defined to talk with the those PF hosts respectively.

v2 changes:
* Put configuring crc stripping in VF into a single patch.

Signed-off-by: Helin Zhang <helin.zhang@intel.com>
Reviewed-by: Jingjing Wu <jingjing.wu@intel.com>
Reviewed-by: Jing Chen <jing.d.chen@intel.com>
---
 lib/librte_pmd_i40e/i40e_ethdev_vf.c | 133 +++++++++++++++++++++++++++--------
 1 file changed, 102 insertions(+), 31 deletions(-)
  

Patch

diff --git a/lib/librte_pmd_i40e/i40e_ethdev_vf.c b/lib/librte_pmd_i40e/i40e_ethdev_vf.c
index 113bff8..af5a0f3 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev_vf.c
+++ b/lib/librte_pmd_i40e/i40e_ethdev_vf.c
@@ -523,8 +523,9 @@  i40evf_config_vlan_pvid(struct rte_eth_dev *dev,
 	return err;
 }
 
+/* It configures VSI queues without extra configuration */
 static int
-i40evf_configure_queues(struct rte_eth_dev *dev)
+i40evf_configure_vsi_queues(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 	struct i40e_rx_queue **rxq =
@@ -533,13 +534,13 @@  i40evf_configure_queues(struct rte_eth_dev *dev)
 		(struct i40e_tx_queue **)dev->data->tx_queues;
 	struct i40e_virtchnl_vsi_queue_config_info *vc_vqci;
 	struct i40e_virtchnl_queue_pair_info *vc_qpi;
-	int size, i, nb_qp, ret, num_rxq, num_txq;
 	struct vf_cmd_info args;
-	struct rte_pktmbuf_pool_private *mbp_priv;
+	int size, i, nb_qp, ret;
 
 	nb_qp = vf->num_queue_pairs;
-	size = sizeof(*vc_vqci) + sizeof(*vc_qpi) * nb_qp;
-	vc_vqci = rte_zmalloc("vc_vqci", size, 0);
+	size = sizeof(struct i40e_virtchnl_vsi_queue_config_info) +
+		sizeof(struct i40e_virtchnl_queue_pair_info) * nb_qp;
+	vc_vqci = rte_zmalloc("queue_info", size, 0);
 	if (!vc_vqci) {
 		PMD_DRV_LOG(ERR, "Failed to allocate memory for VF "
 					"configuring queues\n");
@@ -547,62 +548,132 @@  i40evf_configure_queues(struct rte_eth_dev *dev)
 	}
 	vc_vqci->vsi_id = vf->vsi_res->vsi_id;
 	vc_vqci->num_queue_pairs = nb_qp;
-	vc_qpi = vc_vqci->qpair;
 
-	num_rxq = dev->data->nb_rx_queues;
-	num_txq = dev->data->nb_tx_queues;
-	/*
-	 * PF host driver required to configure queues in pairs, which means
-	 * rxq_num should equals to txq_num. The actual usage won't always
-	 * work that way. The solution is fills 0 with HW ring option in case
-	 * they are not equal.
-	 */
-	for (i = 0; i < nb_qp; i++) {
-		/*Fill TX info */
+	for (i = 0, vc_qpi = vc_vqci->qpair; i < nb_qp; i++, vc_qpi++) {
 		vc_qpi->txq.vsi_id = vc_vqci->vsi_id;
 		vc_qpi->txq.queue_id = i;
-		if (i < num_txq) {
+		if (i < dev->data->nb_tx_queues) {
 			vc_qpi->txq.ring_len = txq[i]->nb_tx_desc;
 			vc_qpi->txq.dma_ring_addr = txq[i]->tx_ring_phys_addr;
-		} else {
-			vc_qpi->txq.ring_len = 0;
-			vc_qpi->txq.dma_ring_addr = 0;
 		}
 
-		/* Fill RX info */
 		vc_qpi->rxq.vsi_id = vc_vqci->vsi_id;
 		vc_qpi->rxq.queue_id = i;
 		vc_qpi->rxq.max_pkt_size = vf->max_pkt_len;
-		if (i < num_rxq) {
+		if (i < dev->data->nb_rx_queues) {
+			struct rte_pktmbuf_pool_private *mbp_priv;
+
+			vc_qpi->rxq.ring_len = rxq[i]->nb_rx_desc;
+			vc_qpi->rxq.dma_ring_addr = rxq[i]->rx_ring_phys_addr;
 			mbp_priv = rte_mempool_get_priv(rxq[i]->mp);
 			vc_qpi->rxq.databuffer_size =
 				mbp_priv->mbuf_data_room_size -
 					RTE_PKTMBUF_HEADROOM;
+		}
+	}
+	memset(&args, 0, sizeof(args));
+	args.ops = I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES;
+	args.in_args = (uint8_t *)vc_vqci;
+	args.in_args_size = size;
+	args.out_buffer = cmd_result_buffer;
+	args.out_size = I40E_AQ_BUF_SZ;
+	ret = i40evf_execute_vf_cmd(dev, &args);
+	if (ret)
+		PMD_DRV_LOG(ERR, "Failed to execute command of "
+			"I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES\n");
+	rte_free(vc_vqci);
+
+	return ret;
+}
+
+/* It configures VSI queues with extra configuration of crc stripping */
+static int
+i40evf_configure_vsi_queues_ex(struct rte_eth_dev *dev)
+{
+	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+	struct i40e_rx_queue **rxq =
+		(struct i40e_rx_queue **)dev->data->rx_queues;
+	struct i40e_tx_queue **txq =
+		(struct i40e_tx_queue **)dev->data->tx_queues;
+	struct i40e_virtchnl_vsi_queue_config_info *vc_vqci;
+	struct i40e_virtchnl_queue_pair_info *vc_qpi;
+	struct i40e_virtchnl_queue_pair_extra_info *vc_qpei;
+	struct vf_cmd_info args;
+	int size, i, nb_qp, ret;
+
+	nb_qp = vf->num_queue_pairs;
+	size = sizeof(struct i40e_virtchnl_vsi_queue_config_info) +
+		sizeof(struct i40e_virtchnl_queue_pair_info) * nb_qp +
+		sizeof(struct i40e_virtchnl_queue_pair_extra_info) * nb_qp;
+	vc_vqci = rte_zmalloc("queue_info", size, 0);
+	if (!vc_vqci) {
+		PMD_DRV_LOG(ERR, "Failed to allocate memory for VF "
+					"configuring queues\n");
+		return -ENOMEM;
+	}
+	vc_vqci->vsi_id = vf->vsi_res->vsi_id;
+	vc_vqci->num_queue_pairs = nb_qp;
+	vc_qpi = vc_vqci->qpair;
+	vc_qpei = (struct i40e_virtchnl_queue_pair_extra_info *)
+		(((uint8_t *)vc_vqci->qpair) +
+		sizeof(struct i40e_virtchnl_queue_pair_info) * nb_qp);
+
+	for (i = 0; i < nb_qp; i++, vc_qpi++, vc_qpei++) {
+		vc_qpi->txq.vsi_id = vc_vqci->vsi_id;
+		vc_qpi->txq.queue_id = i;
+		if (i < dev->data->nb_tx_queues) {
+			vc_qpi->txq.ring_len = txq[i]->nb_tx_desc;
+			vc_qpi->txq.dma_ring_addr = txq[i]->tx_ring_phys_addr;
+		}
+		vc_qpi->rxq.vsi_id = vc_vqci->vsi_id;
+		vc_qpi->rxq.queue_id = i;
+		vc_qpi->rxq.max_pkt_size = vf->max_pkt_len;
+		if (i < dev->data->nb_rx_queues) {
+			struct rte_pktmbuf_pool_private *mbp_priv;
+
 			vc_qpi->rxq.ring_len = rxq[i]->nb_rx_desc;
 			vc_qpi->rxq.dma_ring_addr = rxq[i]->rx_ring_phys_addr;
-		} else {
-			vc_qpi->rxq.ring_len = 0;
-			vc_qpi->rxq.dma_ring_addr = 0;
-			vc_qpi->rxq.databuffer_size = 0;
+			mbp_priv = rte_mempool_get_priv(rxq[i]->mp);
+			vc_qpi->rxq.databuffer_size =
+				mbp_priv->mbuf_data_room_size -
+					RTE_PKTMBUF_HEADROOM;
+			/*
+			 * It adds extra info for configuring VSI queues, which
+			 * is needed to enable the configurable crc stripping
+			 * in VF.
+			 */
+			vc_qpei->crcstrip =
+				dev->data->dev_conf.rxmode.hw_strip_crc;
 		}
-		vc_qpi++;
 	}
-
-	args.ops = I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES;
+	memset(&args, 0, sizeof(args));
+	args.ops =
+		(enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EX;
 	args.in_args = (uint8_t *)vc_vqci;
 	args.in_args_size = size;
 	args.out_buffer = cmd_result_buffer;
 	args.out_size = I40E_AQ_BUF_SZ;
 	ret = i40evf_execute_vf_cmd(dev, &args);
 	if (ret)
-		PMD_DRV_LOG(ERR, "fail to execute command "
-				"OP_CONFIG_VSI_QUEUES\n");
+		PMD_DRV_LOG(ERR, "Failed to execute command of "
+			"I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EX\n");
 	rte_free(vc_vqci);
 
 	return ret;
 }
 
 static int
+i40evf_configure_queues(struct rte_eth_dev *dev)
+{
+	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+
+	if (vf->host_is_dpdk) /* To support DPDK PF host */
+		return i40evf_configure_vsi_queues_ex(dev);
+	else /* To support Linux PF host */
+		return i40evf_configure_vsi_queues(dev);
+}
+
+static int
 i40evf_config_irq_map(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);