net/mrvl: support packet type parsing
[dpdk.git] / drivers / net / octeontx / octeontx_ethdev.c
index 7575078..94af880 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,14 @@ 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)
 {
@@ -335,6 +344,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)
 {
@@ -588,6 +721,92 @@ octeontx_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx)
        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,
@@ -754,10 +973,33 @@ 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,
@@ -766,8 +1008,11 @@ static const struct eth_dev_ops octeontx_dev_ops = {
        .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 */
@@ -790,6 +1035,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;
        }