ethdev: add return value to stats get dev op
[dpdk.git] / drivers / net / octeontx / octeontx_ethdev.c
index 498ea2a..82e38c2 100644 (file)
@@ -47,6 +47,7 @@
 #include <rte_vdev.h>
 
 #include "octeontx_ethdev.h"
+#include "octeontx_rxtx.h"
 #include "octeontx_logs.h"
 
 struct octeontx_vdev_init_params {
@@ -160,6 +161,22 @@ octeontx_port_close(struct octeontx_nic *nic)
        octeontx_log_dbg("port closed %d", nic->port_id);
 }
 
+static int
+octeontx_port_start(struct octeontx_nic *nic)
+{
+       PMD_INIT_FUNC_TRACE();
+
+       return octeontx_bgx_port_start(nic->port_id);
+}
+
+static int
+octeontx_port_stop(struct octeontx_nic *nic)
+{
+       PMD_INIT_FUNC_TRACE();
+
+       return octeontx_bgx_port_stop(nic->port_id);
+}
+
 static void
 octeontx_port_promisc_set(struct octeontx_nic *nic, int en)
 {
@@ -182,7 +199,7 @@ octeontx_port_promisc_set(struct octeontx_nic *nic, int en)
                        nic->port_id, en ? "set" : "unset");
 }
 
-static void
+static int
 octeontx_port_stats(struct octeontx_nic *nic, struct rte_eth_stats *stats)
 {
        octeontx_mbox_bgx_port_stats_t bgx_stats;
@@ -191,8 +208,10 @@ octeontx_port_stats(struct octeontx_nic *nic, struct rte_eth_stats *stats)
        PMD_INIT_FUNC_TRACE();
 
        res = octeontx_bgx_port_stats(nic->port_id, &bgx_stats);
-       if (res < 0)
+       if (res < 0) {
                octeontx_log_err("failed to get port stats %d", nic->port_id);
+               return res;
+       }
 
        stats->ipackets = bgx_stats.rx_packets;
        stats->ibytes = bgx_stats.rx_bytes;
@@ -204,6 +223,8 @@ octeontx_port_stats(struct octeontx_nic *nic, struct rte_eth_stats *stats)
 
        octeontx_log_dbg("port%d stats inpkts=%" PRIx64 " outpkts=%" PRIx64 "",
                        nic->port_id, stats->ipackets, stats->opackets);
+
+       return 0;
 }
 
 static void
@@ -327,6 +348,130 @@ octeontx_dev_configure(struct rte_eth_dev *dev)
        return 0;
 }
 
+static void
+octeontx_dev_close(struct rte_eth_dev *dev)
+{
+       struct octeontx_txq *txq = NULL;
+       struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+       unsigned int i;
+       int ret;
+
+       PMD_INIT_FUNC_TRACE();
+
+       rte_event_dev_close(nic->evdev);
+
+       ret = octeontx_pko_channel_close(nic->base_ochan);
+       if (ret < 0) {
+               octeontx_log_err("failed to close channel %d VF%d %d %d",
+                            nic->base_ochan, nic->port_id, nic->num_tx_queues,
+                            ret);
+       }
+       /* Free txq resources for this port */
+       for (i = 0; i < nic->num_tx_queues; i++) {
+               txq = dev->data->tx_queues[i];
+               if (!txq)
+                       continue;
+
+               rte_free(txq);
+       }
+}
+
+static int
+octeontx_dev_start(struct rte_eth_dev *dev)
+{
+       struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+       int ret;
+
+       ret = 0;
+
+       PMD_INIT_FUNC_TRACE();
+       /*
+        * Tx start
+        */
+       dev->tx_pkt_burst = octeontx_xmit_pkts;
+       ret = octeontx_pko_channel_start(nic->base_ochan);
+       if (ret < 0) {
+               octeontx_log_err("fail to conf VF%d no. txq %d chan %d ret %d",
+                          nic->port_id, nic->num_tx_queues, nic->base_ochan,
+                          ret);
+               goto error;
+       }
+
+       /*
+        * Rx start
+        */
+       dev->rx_pkt_burst = octeontx_recv_pkts;
+       ret = octeontx_pki_port_start(nic->port_id);
+       if (ret < 0) {
+               octeontx_log_err("fail to start Rx on port %d", nic->port_id);
+               goto channel_stop_error;
+       }
+
+       /*
+        * Start port
+        */
+       ret = octeontx_port_start(nic);
+       if (ret < 0) {
+               octeontx_log_err("failed start port %d", ret);
+               goto pki_port_stop_error;
+       }
+
+       PMD_TX_LOG(DEBUG, "pko: start channel %d no.of txq %d port %d",
+                       nic->base_ochan, nic->num_tx_queues, nic->port_id);
+
+       ret = rte_event_dev_start(nic->evdev);
+       if (ret < 0) {
+               octeontx_log_err("failed to start evdev: ret (%d)", ret);
+               goto pki_port_stop_error;
+       }
+
+       /* Success */
+       return ret;
+
+pki_port_stop_error:
+       octeontx_pki_port_stop(nic->port_id);
+channel_stop_error:
+       octeontx_pko_channel_stop(nic->base_ochan);
+error:
+       return ret;
+}
+
+static void
+octeontx_dev_stop(struct rte_eth_dev *dev)
+{
+       struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+       int ret;
+
+       PMD_INIT_FUNC_TRACE();
+
+       rte_event_dev_stop(nic->evdev);
+
+       ret = octeontx_port_stop(nic);
+       if (ret < 0) {
+               octeontx_log_err("failed to req stop port %d res=%d",
+                                       nic->port_id, ret);
+               return;
+       }
+
+       ret = octeontx_pki_port_stop(nic->port_id);
+       if (ret < 0) {
+               octeontx_log_err("failed to stop pki port %d res=%d",
+                                       nic->port_id, ret);
+               return;
+       }
+
+       ret = octeontx_pko_channel_stop(nic->base_ochan);
+       if (ret < 0) {
+               octeontx_log_err("failed to stop channel %d VF%d %d %d",
+                            nic->base_ochan, nic->port_id, nic->num_tx_queues,
+                            ret);
+               return;
+       }
+
+       dev->tx_pkt_burst = NULL;
+       dev->rx_pkt_burst = NULL;
+}
+
 static void
 octeontx_dev_promisc_enable(struct rte_eth_dev *dev)
 {
@@ -433,13 +578,13 @@ octeontx_dev_link_update(struct rte_eth_dev *dev,
        return octeontx_atomic_write_link_status(dev, &link);
 }
 
-static void
+static int
 octeontx_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 {
        struct octeontx_nic *nic = octeontx_pmd_priv(dev);
 
        PMD_INIT_FUNC_TRACE();
-       octeontx_port_stats(nic, stats);
+       return octeontx_port_stats(nic, stats);
 }
 
 static void
@@ -500,6 +645,172 @@ octeontx_dev_info(struct rte_eth_dev *dev,
        dev_info->tx_offload_capa = DEV_TX_OFFLOAD_MT_LOCKFREE;
 }
 
+static void
+octeontx_dq_info_getter(octeontx_dq_t *dq, void *out)
+{
+       ((octeontx_dq_t *)out)->lmtline_va = dq->lmtline_va;
+       ((octeontx_dq_t *)out)->ioreg_va = dq->ioreg_va;
+       ((octeontx_dq_t *)out)->fc_status_va = dq->fc_status_va;
+}
+
+static int
+octeontx_vf_start_tx_queue(struct rte_eth_dev *dev, struct octeontx_nic *nic,
+                               uint16_t qidx)
+{
+       struct octeontx_txq *txq;
+       int res;
+
+       PMD_INIT_FUNC_TRACE();
+
+       if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED)
+               return 0;
+
+       txq = dev->data->tx_queues[qidx];
+
+       res = octeontx_pko_channel_query_dqs(nic->base_ochan,
+                                               &txq->dq,
+                                               sizeof(octeontx_dq_t),
+                                               txq->queue_id,
+                                               octeontx_dq_info_getter);
+       if (res < 0) {
+               res = -EFAULT;
+               goto close_port;
+       }
+
+       dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED;
+       return res;
+
+close_port:
+       (void)octeontx_port_stop(nic);
+       octeontx_pko_channel_stop(nic->base_ochan);
+       octeontx_pko_channel_close(nic->base_ochan);
+       dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
+       return res;
+}
+
+static int
+octeontx_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t qidx)
+{
+       struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+
+       PMD_INIT_FUNC_TRACE();
+       qidx = qidx % PKO_VF_NUM_DQ;
+       return octeontx_vf_start_tx_queue(dev, nic, qidx);
+}
+
+static inline int
+octeontx_vf_stop_tx_queue(struct rte_eth_dev *dev, struct octeontx_nic *nic,
+                         uint16_t qidx)
+{
+       int ret = 0;
+
+       RTE_SET_USED(nic);
+       PMD_INIT_FUNC_TRACE();
+
+       if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED)
+               return 0;
+
+       dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
+       return ret;
+}
+
+static int
+octeontx_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx)
+{
+       struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+
+       PMD_INIT_FUNC_TRACE();
+       qidx = qidx % PKO_VF_NUM_DQ;
+
+       return octeontx_vf_stop_tx_queue(dev, nic, qidx);
+}
+
+static void
+octeontx_dev_tx_queue_release(void *tx_queue)
+{
+       struct octeontx_txq *txq = tx_queue;
+       int res;
+
+       PMD_INIT_FUNC_TRACE();
+
+       if (txq) {
+               res = octeontx_dev_tx_queue_stop(txq->eth_dev, txq->queue_id);
+               if (res < 0)
+                       octeontx_log_err("failed stop tx_queue(%d)\n",
+                                  txq->queue_id);
+
+               rte_free(txq);
+       }
+}
+
+static int
+octeontx_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t qidx,
+                           uint16_t nb_desc, unsigned int socket_id,
+                           const struct rte_eth_txconf *tx_conf)
+{
+       struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+       struct octeontx_txq *txq = NULL;
+       uint16_t dq_num;
+       int res = 0;
+
+       RTE_SET_USED(nb_desc);
+       RTE_SET_USED(socket_id);
+       RTE_SET_USED(tx_conf);
+
+       dq_num = (nic->port_id * PKO_VF_NUM_DQ) + qidx;
+
+       /* Socket id check */
+       if (socket_id != (unsigned int)SOCKET_ID_ANY &&
+                       socket_id != (unsigned int)nic->node)
+               PMD_TX_LOG(INFO, "socket_id expected %d, configured %d",
+                                               socket_id, nic->node);
+
+       /* Free memory prior to re-allocation if needed. */
+       if (dev->data->tx_queues[qidx] != NULL) {
+               PMD_TX_LOG(DEBUG, "freeing memory prior to re-allocation %d",
+                               qidx);
+               octeontx_dev_tx_queue_release(dev->data->tx_queues[qidx]);
+               dev->data->tx_queues[qidx] = NULL;
+       }
+
+       /* Allocating tx queue data structure */
+       txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct octeontx_txq),
+                                RTE_CACHE_LINE_SIZE, nic->node);
+       if (txq == NULL) {
+               octeontx_log_err("failed to allocate txq=%d", qidx);
+               res = -ENOMEM;
+               goto err;
+       }
+
+       txq->eth_dev = dev;
+       txq->queue_id = dq_num;
+       dev->data->tx_queues[qidx] = txq;
+       dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+       res = octeontx_pko_channel_query_dqs(nic->base_ochan,
+                                               &txq->dq,
+                                               sizeof(octeontx_dq_t),
+                                               txq->queue_id,
+                                               octeontx_dq_info_getter);
+       if (res < 0) {
+               res = -EFAULT;
+               goto err;
+       }
+
+       PMD_TX_LOG(DEBUG, "[%d]:[%d] txq=%p nb_desc=%d lmtline=%p ioreg_va=%p fc_status_va=%p",
+                       qidx, txq->queue_id, txq, nb_desc, txq->dq.lmtline_va,
+                       txq->dq.ioreg_va,
+                       txq->dq.fc_status_va);
+
+       return res;
+
+err:
+       if (txq)
+               rte_free(txq);
+
+       return res;
+}
+
 static int
 octeontx_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t qidx,
                                uint16_t nb_desc, unsigned int socket_id,
@@ -666,18 +977,46 @@ octeontx_dev_rx_queue_release(void *rxq)
        rte_free(rxq);
 }
 
+static const uint32_t *
+octeontx_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+{
+       static const uint32_t ptypes[] = {
+               RTE_PTYPE_L3_IPV4,
+               RTE_PTYPE_L3_IPV4_EXT,
+               RTE_PTYPE_L3_IPV6,
+               RTE_PTYPE_L3_IPV6_EXT,
+               RTE_PTYPE_L4_TCP,
+               RTE_PTYPE_L4_UDP,
+               RTE_PTYPE_L4_FRAG,
+               RTE_PTYPE_UNKNOWN
+       };
+
+       if (dev->rx_pkt_burst == octeontx_recv_pkts)
+               return ptypes;
+
+       return NULL;
+}
+
 /* Initialize and register driver with DPDK Application */
 static const struct eth_dev_ops octeontx_dev_ops = {
        .dev_configure           = octeontx_dev_configure,
        .dev_infos_get           = octeontx_dev_info,
+       .dev_close               = octeontx_dev_close,
+       .dev_start               = octeontx_dev_start,
+       .dev_stop                = octeontx_dev_stop,
        .promiscuous_enable      = octeontx_dev_promisc_enable,
        .promiscuous_disable     = octeontx_dev_promisc_disable,
        .link_update             = octeontx_dev_link_update,
        .stats_get               = octeontx_dev_stats_get,
        .stats_reset             = octeontx_dev_stats_reset,
        .mac_addr_set            = octeontx_dev_default_mac_addr_set,
+       .tx_queue_start          = octeontx_dev_tx_queue_start,
+       .tx_queue_stop           = octeontx_dev_tx_queue_stop,
+       .tx_queue_setup          = octeontx_dev_tx_queue_setup,
+       .tx_queue_release        = octeontx_dev_tx_queue_release,
        .rx_queue_setup          = octeontx_dev_rx_queue_setup,
        .rx_queue_release        = octeontx_dev_rx_queue_release,
+       .dev_supported_ptypes_get = octeontx_dev_supported_ptypes_get,
 };
 
 /* Create Ethdev interface per BGX LMAC ports */
@@ -700,6 +1039,8 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
                if (eth_dev == NULL)
                        return -ENODEV;
 
+               eth_dev->tx_pkt_burst = octeontx_xmit_pkts;
+               eth_dev->rx_pkt_burst = octeontx_recv_pkts;
                return 0;
        }