From: Helin Zhang Date: Thu, 6 Nov 2014 12:53:50 +0000 (+0800) Subject: i40evf: support configurable crc stripping X-Git-Tag: spdx-start~10177 X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=d6b19729093ec4fbe2395d85f4390b2115d0d638;p=dpdk.git i40evf: support configurable crc stripping Configurable CRC stripping needs to be supported in VF, and the configuration should be finally set in relevant RX queue context with PF host support. Signed-off-by: Helin Zhang Acked-by: Konstantin Ananyev --- diff --git a/lib/librte_pmd_i40e/i40e_ethdev_vf.c b/lib/librte_pmd_i40e/i40e_ethdev_vf.c index 9a8cdc84ca..554d9d73b7 100644 --- a/lib/librte_pmd_i40e/i40e_ethdev_vf.c +++ b/lib/librte_pmd_i40e/i40e_ethdev_vf.c @@ -533,8 +533,46 @@ i40evf_config_vlan_pvid(struct rte_eth_dev *dev, return err; } +static void +i40evf_fill_virtchnl_vsi_txq_info(struct i40e_virtchnl_txq_info *txq_info, + uint16_t vsi_id, + uint16_t queue_id, + uint16_t nb_txq, + struct i40e_tx_queue *txq) +{ + txq_info->vsi_id = vsi_id; + txq_info->queue_id = queue_id; + if (queue_id < nb_txq) { + txq_info->ring_len = txq->nb_tx_desc; + txq_info->dma_ring_addr = txq->tx_ring_phys_addr; + } +} + +static void +i40evf_fill_virtchnl_vsi_rxq_info(struct i40e_virtchnl_rxq_info *rxq_info, + uint16_t vsi_id, + uint16_t queue_id, + uint16_t nb_rxq, + uint32_t max_pkt_size, + struct i40e_rx_queue *rxq) +{ + rxq_info->vsi_id = vsi_id; + rxq_info->queue_id = queue_id; + rxq_info->max_pkt_size = max_pkt_size; + if (queue_id < nb_rxq) { + struct rte_pktmbuf_pool_private *mbp_priv; + + rxq_info->ring_len = rxq->nb_rx_desc; + rxq_info->dma_ring_addr = rxq->rx_ring_phys_addr; + mbp_priv = rte_mempool_get_priv(rxq->mp); + rxq_info->databuffer_size = + mbp_priv->mbuf_data_room_size - RTE_PKTMBUF_HEADROOM; + } +} + +/* It configures VSI queues to co-work with Linux PF host */ 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 = @@ -554,47 +592,14 @@ i40evf_configure_queues(struct rte_eth_dev *dev) vc_vqci = (struct i40e_virtchnl_vsi_queue_config_info *)buff; vc_vqci->vsi_id = vf->vsi_res->vsi_id; vc_vqci->num_queue_pairs = nb_qp; - vc_qpi = vc_vqci->qpair; - - /* - * 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 */ - 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; - } 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 < dev->data->nb_rx_queues) { - struct rte_pktmbuf_pool_private *mbp_priv = - rte_mempool_get_priv(rxq[i]->mp); - - vc_qpi->rxq.databuffer_size = - mbp_priv->mbuf_data_room_size - - RTE_PKTMBUF_HEADROOM; - 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; - } - vc_qpi++; + for (i = 0, vc_qpi = vc_vqci->qpair; i < nb_qp; i++, vc_qpi++) { + i40evf_fill_virtchnl_vsi_txq_info(&vc_qpi->txq, + vc_vqci->vsi_id, i, dev->data->nb_tx_queues, txq[i]); + i40evf_fill_virtchnl_vsi_rxq_info(&vc_qpi->rxq, + vc_vqci->vsi_id, i, dev->data->nb_rx_queues, + vf->max_pkt_len, rxq[i]); } - memset(&args, 0, sizeof(args)); args.ops = I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES; args.in_args = (uint8_t *)vc_vqci; @@ -603,12 +608,78 @@ i40evf_configure_queues(struct rte_eth_dev *dev) 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"); + PMD_DRV_LOG(ERR, "Failed to execute command of " + "I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES\n"); + + return ret; +} + +/* It configures VSI queues to co-work with DPDK PF host */ +static int +i40evf_configure_vsi_queues_ext(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_ext_info *vc_vqcei; + struct i40e_virtchnl_queue_pair_ext_info *vc_qpei; + struct vf_cmd_info args; + uint16_t i, nb_qp = vf->num_queue_pairs; + const uint32_t size = + I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqcei, nb_qp); + uint8_t buff[size]; + int ret; + + memset(buff, 0, sizeof(buff)); + vc_vqcei = (struct i40e_virtchnl_vsi_queue_config_ext_info *)buff; + vc_vqcei->vsi_id = vf->vsi_res->vsi_id; + vc_vqcei->num_queue_pairs = nb_qp; + vc_qpei = vc_vqcei->qpair; + for (i = 0; i < nb_qp; i++, vc_qpei++) { + i40evf_fill_virtchnl_vsi_txq_info(&vc_qpei->txq, + vc_vqcei->vsi_id, i, dev->data->nb_tx_queues, txq[i]); + i40evf_fill_virtchnl_vsi_rxq_info(&vc_qpei->rxq, + vc_vqcei->vsi_id, i, dev->data->nb_rx_queues, + vf->max_pkt_len, rxq[i]); + if (i < dev->data->nb_rx_queues) + /* + * It adds extra info for configuring VSI queues, which + * is needed to enable the configurable crc stripping + * in VF. + */ + vc_qpei->rxq_ext.crcstrip = + dev->data->dev_conf.rxmode.hw_strip_crc; + } + memset(&args, 0, sizeof(args)); + args.ops = + (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT; + args.in_args = (uint8_t *)vc_vqcei; + 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_EXT\n"); 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->version_major == I40E_DPDK_VERSION_MAJOR) + /* To support DPDK PF host */ + return i40evf_configure_vsi_queues_ext(dev); + else + /* To support Linux PF host */ + return i40evf_configure_vsi_queues(dev); +} + static int i40evf_config_irq_map(struct rte_eth_dev *dev) { diff --git a/lib/librte_pmd_i40e/i40e_pf.c b/lib/librte_pmd_i40e/i40e_pf.c index 7f98636e0e..cbb2dcc10f 100644 --- a/lib/librte_pmd_i40e/i40e_pf.c +++ b/lib/librte_pmd_i40e/i40e_pf.c @@ -421,9 +421,11 @@ i40e_pf_host_process_cmd_config_vsi_queues(struct i40e_pf_vf *vf, struct i40e_virtchnl_queue_pair_info *vc_qpi; int i, ret = I40E_SUCCESS; - if (msg == NULL || msglen <= sizeof(*vc_vqci) || - vc_vqci->num_queue_pairs > vsi->nb_qps) { - PMD_DRV_LOG(ERR, "vsi_queue_config_info argument wrong"); + 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; } @@ -436,7 +438,13 @@ i40e_pf_host_process_cmd_config_vsi_queues(struct i40e_pf_vf *vf, goto send_msg; } - /* Apply VF RX queue setting to HMC */ + /* + * 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"); @@ -445,8 +453,8 @@ i40e_pf_host_process_cmd_config_vsi_queues(struct i40e_pf_vf *vf, } /* Apply VF TX queue setting to HMC */ - if (i40e_pf_host_hmc_config_txq(hw, vf, &vc_qpi[i].txq) - != I40E_SUCCESS) { + 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; @@ -460,6 +468,64 @@ send_msg: return ret; } +static int +i40e_pf_host_process_cmd_config_vsi_queues_ext(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_ext_info *vc_vqcei = + (struct i40e_virtchnl_vsi_queue_config_ext_info *)msg; + struct i40e_virtchnl_queue_pair_ext_info *vc_qpei; + int i, ret = I40E_SUCCESS; + + if (!msg || vc_vqcei->num_queue_pairs > vsi->nb_qps || + vc_vqcei->num_queue_pairs > I40E_MAX_VSI_QP || + msglen < I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqcei, + vc_vqcei->num_queue_pairs)) { + PMD_DRV_LOG(ERR, "vsi_queue_config_ext_info argument wrong\n"); + ret = I40E_ERR_PARAM; + goto send_msg; + } + + vc_qpei = vc_vqcei->qpair; + for (i = 0; i < vc_vqcei->num_queue_pairs; i++) { + if (vc_qpei[i].rxq.queue_id > vsi->nb_qps - 1 || + vc_qpei[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_ext_info' is needed, + * otherwise set the last parameter to NULL. + */ + if (i40e_pf_host_hmc_config_rxq(hw, vf, &vc_qpei[i].rxq, + vc_qpei[i].rxq_ext.crcstrip) != 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_qpei[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_EXT, + ret, NULL, 0); + + return ret; +} + static int i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf, uint8_t *msg, uint16_t msglen) @@ -878,6 +944,11 @@ i40e_pf_host_handle_vf_msg(struct rte_eth_dev *dev, PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES received"); i40e_pf_host_process_cmd_config_vsi_queues(vf, msg, msglen); break; + case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT: + PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES_EXT received"); + i40e_pf_host_process_cmd_config_vsi_queues_ext(vf, msg, + msglen); + break; case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP: PMD_DRV_LOG(INFO, "OP_CONFIG_IRQ_MAP received"); i40e_pf_host_process_cmd_config_irq_map(vf, msg, msglen); diff --git a/lib/librte_pmd_i40e/i40e_pf.h b/lib/librte_pmd_i40e/i40e_pf.h index ce5a97844b..8bf83c21b4 100644 --- a/lib/librte_pmd_i40e/i40e_pf.h +++ b/lib/librte_pmd_i40e/i40e_pf.h @@ -63,6 +63,34 @@ enum i40e_virtchnl_ops_dpdk { I40E_DPDK_OFFSET, I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD, I40E_VIRTCHNL_OP_CFG_VLAN_PVID, + I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT, +}; + +/* A structure to support extended info of a receive queue. */ +struct i40e_virtchnl_rxq_ext_info { + uint8_t crcstrip; +}; + +/* + * A structure to support extended info of queue pairs, an additional field + * is added, comparing to original 'struct i40e_virtchnl_queue_pair_info'. + */ +struct i40e_virtchnl_queue_pair_ext_info { + /* vsi_id and queue_id should be identical for both rx and tx queues.*/ + struct i40e_virtchnl_txq_info txq; + struct i40e_virtchnl_rxq_info rxq; + struct i40e_virtchnl_rxq_ext_info rxq_ext; +}; + +/* + * A structure to support extended info of VSI queue pairs, + * 'struct i40e_virtchnl_queue_pair_ext_info' is used, see its original + * of 'struct i40e_virtchnl_queue_pair_info'. + */ +struct i40e_virtchnl_vsi_queue_config_ext_info { + uint16_t vsi_id; + uint16_t num_queue_pairs; + struct i40e_virtchnl_queue_pair_ext_info qpair[0]; }; struct i40e_virtchnl_vlan_offload_info {