net/nfp: add NFDk option and queue function
authorJin Liu <jin.liu@corigine.com>
Fri, 17 Jun 2022 09:34:40 +0000 (11:34 +0200)
committerFerruh Yigit <ferruh.yigit@xilinx.com>
Fri, 17 Jun 2022 13:32:41 +0000 (15:32 +0200)
Add ethdev option for firmware with NFDk, implement tx_queue setup
function for firmware with NFDk.

Signed-off-by: Jin Liu <jin.liu@corigine.com>
Signed-off-by: Diana Wang <na.wang@corigine.com>
Signed-off-by: Peng Zhang <peng.zhang@corigine.com>
Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Signed-off-by: Niklas Söderlund <niklas.soderlund@corigine.com>
drivers/net/nfp/nfp_ethdev.c
drivers/net/nfp/nfp_ethdev_vf.c
drivers/net/nfp/nfp_rxtx.c
drivers/net/nfp/nfp_rxtx.h

index 1bbba91..0d650ef 100644 (file)
@@ -358,11 +358,41 @@ static const struct eth_dev_ops nfp_net_nfd3_eth_dev_ops = {
        .rx_queue_intr_disable  = nfp_rx_queue_intr_disable,
 };
 
+static const struct eth_dev_ops nfp_net_nfdk_eth_dev_ops = {
+       .dev_configure          = nfp_net_configure,
+       .dev_start              = nfp_net_start,
+       .dev_stop               = nfp_net_stop,
+       .dev_set_link_up        = nfp_net_set_link_up,
+       .dev_set_link_down      = nfp_net_set_link_down,
+       .dev_close              = nfp_net_close,
+       .promiscuous_enable     = nfp_net_promisc_enable,
+       .promiscuous_disable    = nfp_net_promisc_disable,
+       .link_update            = nfp_net_link_update,
+       .stats_get              = nfp_net_stats_get,
+       .stats_reset            = nfp_net_stats_reset,
+       .dev_infos_get          = nfp_net_infos_get,
+       .dev_supported_ptypes_get = nfp_net_supported_ptypes_get,
+       .mtu_set                = nfp_net_dev_mtu_set,
+       .mac_addr_set           = nfp_net_set_mac_addr,
+       .vlan_offload_set       = nfp_net_vlan_offload_set,
+       .reta_update            = nfp_net_reta_update,
+       .reta_query             = nfp_net_reta_query,
+       .rss_hash_update        = nfp_net_rss_hash_update,
+       .rss_hash_conf_get      = nfp_net_rss_hash_conf_get,
+       .rx_queue_setup         = nfp_net_rx_queue_setup,
+       .rx_queue_release       = nfp_net_rx_queue_release,
+       .tx_queue_setup         = nfp_net_nfdk_tx_queue_setup,
+       .tx_queue_release       = nfp_net_tx_queue_release,
+       .rx_queue_intr_enable   = nfp_rx_queue_intr_enable,
+       .rx_queue_intr_disable  = nfp_rx_queue_intr_disable,
+};
+
 static inline int
 nfp_net_ethdev_ops_mount(struct nfp_net_hw *hw, struct rte_eth_dev *eth_dev)
 {
        switch (NFD_CFG_CLASS_VER_of(hw->ver)) {
        case NFP_NET_CFG_VERSION_DP_NFD3:
+               eth_dev->dev_ops = &nfp_net_nfd3_eth_dev_ops;
                break;
        case NFP_NET_CFG_VERSION_DP_NFDK:
                if (NFD_CFG_MAJOR_VERSION_of(hw->ver) < 5) {
@@ -370,13 +400,13 @@ nfp_net_ethdev_ops_mount(struct nfp_net_hw *hw, struct rte_eth_dev *eth_dev)
                                NFD_CFG_MAJOR_VERSION_of(hw->ver));
                        return -EINVAL;
                }
+               eth_dev->dev_ops = &nfp_net_nfdk_eth_dev_ops;
                break;
        default:
                PMD_DRV_LOG(ERR, "The version of firmware is not correct.");
                return -EINVAL;
        }
 
-       eth_dev->dev_ops = &nfp_net_nfd3_eth_dev_ops;
        eth_dev->rx_queue_count = nfp_net_rx_queue_count;
        eth_dev->rx_pkt_burst = &nfp_net_recv_pkts;
        eth_dev->tx_pkt_burst = &nfp_net_nfd3_xmit_pkts;
index 0b4660a..2342f44 100644 (file)
@@ -265,11 +265,41 @@ static const struct eth_dev_ops nfp_netvf_nfd3_eth_dev_ops = {
        .rx_queue_intr_disable  = nfp_rx_queue_intr_disable,
 };
 
+static const struct eth_dev_ops nfp_netvf_nfdk_eth_dev_ops = {
+       .dev_configure          = nfp_net_configure,
+       .dev_start              = nfp_netvf_start,
+       .dev_stop               = nfp_netvf_stop,
+       .dev_set_link_up        = nfp_netvf_set_link_up,
+       .dev_set_link_down      = nfp_netvf_set_link_down,
+       .dev_close              = nfp_netvf_close,
+       .promiscuous_enable     = nfp_net_promisc_enable,
+       .promiscuous_disable    = nfp_net_promisc_disable,
+       .link_update            = nfp_net_link_update,
+       .stats_get              = nfp_net_stats_get,
+       .stats_reset            = nfp_net_stats_reset,
+       .dev_infos_get          = nfp_net_infos_get,
+       .dev_supported_ptypes_get = nfp_net_supported_ptypes_get,
+       .mtu_set                = nfp_net_dev_mtu_set,
+       .mac_addr_set           = nfp_net_set_mac_addr,
+       .vlan_offload_set       = nfp_net_vlan_offload_set,
+       .reta_update            = nfp_net_reta_update,
+       .reta_query             = nfp_net_reta_query,
+       .rss_hash_update        = nfp_net_rss_hash_update,
+       .rss_hash_conf_get      = nfp_net_rss_hash_conf_get,
+       .rx_queue_setup         = nfp_net_rx_queue_setup,
+       .rx_queue_release       = nfp_net_rx_queue_release,
+       .tx_queue_setup         = nfp_net_nfdk_tx_queue_setup,
+       .tx_queue_release       = nfp_net_tx_queue_release,
+       .rx_queue_intr_enable   = nfp_rx_queue_intr_enable,
+       .rx_queue_intr_disable  = nfp_rx_queue_intr_disable,
+};
+
 static inline int
 nfp_netvf_ethdev_ops_mount(struct nfp_net_hw *hw, struct rte_eth_dev *eth_dev)
 {
        switch (NFD_CFG_CLASS_VER_of(hw->ver)) {
        case NFP_NET_CFG_VERSION_DP_NFD3:
+               eth_dev->dev_ops = &nfp_netvf_nfd3_eth_dev_ops;
                break;
        case NFP_NET_CFG_VERSION_DP_NFDK:
                if (NFD_CFG_MAJOR_VERSION_of(hw->ver) < 5) {
@@ -277,13 +307,13 @@ nfp_netvf_ethdev_ops_mount(struct nfp_net_hw *hw, struct rte_eth_dev *eth_dev)
                                NFD_CFG_MAJOR_VERSION_of(hw->ver));
                        return -EINVAL;
                }
+               eth_dev->dev_ops = &nfp_netvf_nfdk_eth_dev_ops;
                break;
        default:
                PMD_DRV_LOG(ERR, "The version of firmware is not correct.");
                return -EINVAL;
        }
 
-       eth_dev->dev_ops = &nfp_netvf_nfd3_eth_dev_ops;
        eth_dev->rx_queue_count = nfp_net_rx_queue_count;
        eth_dev->rx_pkt_burst = &nfp_net_recv_pkts;
        eth_dev->tx_pkt_burst = &nfp_net_nfd3_xmit_pkts;
index 9b769c9..4f422c5 100644 (file)
@@ -987,3 +987,120 @@ xmit_end:
 
        return i;
 }
+
+int
+nfp_net_nfdk_tx_queue_setup(struct rte_eth_dev *dev,
+               uint16_t queue_idx,
+               uint16_t nb_desc,
+               unsigned int socket_id,
+               const struct rte_eth_txconf *tx_conf)
+{
+       const struct rte_memzone *tz;
+       struct nfp_net_txq *txq;
+       uint16_t tx_free_thresh;
+       struct nfp_net_hw *hw;
+       uint32_t tx_desc_sz;
+
+       hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       PMD_INIT_FUNC_TRACE();
+
+       /* Validating number of descriptors */
+       tx_desc_sz = nb_desc * sizeof(struct nfp_net_nfdk_tx_desc);
+       if (((NFDK_TX_DESC_PER_SIMPLE_PKT * tx_desc_sz) % NFP_ALIGN_RING_DESC) != 0 ||
+           ((NFDK_TX_DESC_PER_SIMPLE_PKT * nb_desc) % NFDK_TX_DESC_BLOCK_CNT) != 0 ||
+             nb_desc > NFP_NET_MAX_TX_DESC || nb_desc < NFP_NET_MIN_TX_DESC) {
+               PMD_DRV_LOG(ERR, "Wrong nb_desc value");
+               return -EINVAL;
+       }
+
+       tx_free_thresh = (uint16_t)((tx_conf->tx_free_thresh) ?
+                               tx_conf->tx_free_thresh :
+                               DEFAULT_TX_FREE_THRESH);
+
+       if (tx_free_thresh > (nb_desc)) {
+               PMD_DRV_LOG(ERR,
+                       "tx_free_thresh must be less than the number of TX "
+                       "descriptors. (tx_free_thresh=%u port=%d "
+                       "queue=%d)", (unsigned int)tx_free_thresh,
+                       dev->data->port_id, (int)queue_idx);
+               return -(EINVAL);
+       }
+
+       /*
+        * Free memory prior to re-allocation if needed. This is the case after
+        * calling nfp_net_stop
+        */
+       if (dev->data->tx_queues[queue_idx]) {
+               PMD_TX_LOG(DEBUG, "Freeing memory prior to re-allocation %d",
+                               queue_idx);
+               nfp_net_tx_queue_release(dev, queue_idx);
+               dev->data->tx_queues[queue_idx] = NULL;
+       }
+
+       /* Allocating tx queue data structure */
+       txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct nfp_net_txq),
+                       RTE_CACHE_LINE_SIZE, socket_id);
+       if (txq == NULL) {
+               PMD_DRV_LOG(ERR, "Error allocating tx dma");
+               return -ENOMEM;
+       }
+
+       /*
+        * Allocate TX ring hardware descriptors. A memzone large enough to
+        * handle the maximum ring size is allocated in order to allow for
+        * resizing in later calls to the queue setup function.
+        */
+       tz = rte_eth_dma_zone_reserve(dev, "tx_ring", queue_idx,
+                               sizeof(struct nfp_net_nfdk_tx_desc) *
+                               NFDK_TX_DESC_PER_SIMPLE_PKT *
+                               NFP_NET_MAX_TX_DESC, NFP_MEMZONE_ALIGN,
+                               socket_id);
+       if (tz == NULL) {
+               PMD_DRV_LOG(ERR, "Error allocating tx dma");
+               nfp_net_tx_queue_release(dev, queue_idx);
+               return -ENOMEM;
+       }
+
+       txq->tx_count = nb_desc * NFDK_TX_DESC_PER_SIMPLE_PKT;
+       txq->tx_free_thresh = tx_free_thresh;
+       txq->tx_pthresh = tx_conf->tx_thresh.pthresh;
+       txq->tx_hthresh = tx_conf->tx_thresh.hthresh;
+       txq->tx_wthresh = tx_conf->tx_thresh.wthresh;
+
+       /* queue mapping based on firmware configuration */
+       txq->qidx = queue_idx;
+       txq->tx_qcidx = queue_idx * hw->stride_tx;
+       txq->qcp_q = hw->tx_bar + NFP_QCP_QUEUE_OFF(txq->tx_qcidx);
+
+       txq->port_id = dev->data->port_id;
+
+       /* Saving physical and virtual addresses for the TX ring */
+       txq->dma = (uint64_t)tz->iova;
+       txq->ktxds = (struct nfp_net_nfdk_tx_desc *)tz->addr;
+
+       /* mbuf pointers array for referencing mbufs linked to TX descriptors */
+       txq->txbufs = rte_zmalloc_socket("txq->txbufs",
+                               sizeof(*txq->txbufs) * txq->tx_count,
+                               RTE_CACHE_LINE_SIZE, socket_id);
+
+       if (txq->txbufs == NULL) {
+               nfp_net_tx_queue_release(dev, queue_idx);
+               return -ENOMEM;
+       }
+       PMD_TX_LOG(DEBUG, "txbufs=%p hw_ring=%p dma_addr=0x%" PRIx64,
+               txq->txbufs, txq->ktxds, (unsigned long)txq->dma);
+
+       nfp_net_reset_tx_queue(txq);
+
+       dev->data->tx_queues[queue_idx] = txq;
+       txq->hw = hw;
+       /*
+        * Telling the HW about the physical address of the TX ring and number
+        * of descriptors in log2 format
+        */
+       nn_cfg_writeq(hw, NFP_NET_CFG_TXR_ADDR(queue_idx), txq->dma);
+       nn_cfg_writeb(hw, NFP_NET_CFG_TXR_SZ(queue_idx), rte_log2_u32(txq->tx_count));
+
+       return 0;
+}
index 106980b..ba8ffbd 100644 (file)
@@ -347,6 +347,11 @@ int nfp_net_nfd3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
                                  const struct rte_eth_txconf *tx_conf);
 uint16_t nfp_net_nfd3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
                                  uint16_t nb_pkts);
+int nfp_net_nfdk_tx_queue_setup(struct rte_eth_dev *dev,
+               uint16_t queue_idx,
+               uint16_t nb_desc,
+               unsigned int socket_id,
+               const struct rte_eth_txconf *tx_conf);
 
 #endif /* _NFP_RXTX_H_ */
 /*