net/octeontx2: add remaining PTP operations
[dpdk.git] / drivers / net / octeontx2 / otx2_ethdev.c
index 9a011de..834b052 100644 (file)
@@ -47,6 +47,7 @@ nix_get_tx_offload_capa(struct otx2_eth_dev *dev)
 
 static const struct otx2_dev_ops otx2_dev_ops = {
        .link_status_update = otx2_eth_dev_link_status_update,
+       .ptp_info_update = otx2_eth_dev_ptp_info_update
 };
 
 static int
@@ -120,6 +121,32 @@ nix_lf_free(struct otx2_eth_dev *dev)
        return otx2_mbox_process(mbox);
 }
 
+int
+otx2_cgx_rxtx_start(struct otx2_eth_dev *dev)
+{
+       struct otx2_mbox *mbox = dev->mbox;
+
+       if (otx2_dev_is_vf(dev))
+               return 0;
+
+       otx2_mbox_alloc_msg_cgx_start_rxtx(mbox);
+
+       return otx2_mbox_process(mbox);
+}
+
+int
+otx2_cgx_rxtx_stop(struct otx2_eth_dev *dev)
+{
+       struct otx2_mbox *mbox = dev->mbox;
+
+       if (otx2_dev_is_vf(dev))
+               return 0;
+
+       otx2_mbox_alloc_msg_cgx_stop_rxtx(mbox);
+
+       return otx2_mbox_process(mbox);
+}
+
 static inline void
 nix_rx_queue_reset(struct otx2_eth_rxq *rxq)
 {
@@ -190,6 +217,14 @@ nix_cq_rq_init(struct rte_eth_dev *eth_dev, struct otx2_eth_dev *dev,
        aq->cq.cq_err_int_ena = BIT(NIX_CQERRINT_CQE_FAULT);
        aq->cq.cq_err_int_ena |= BIT(NIX_CQERRINT_DOOR_ERR);
 
+       /* TX pause frames enable flowctrl on RX side */
+       if (dev->fc_info.tx_pause) {
+               /* Single bpid is allocated for all rx channels for now */
+               aq->cq.bpid = dev->fc_info.bpid[0];
+               aq->cq.bp = NIX_CQ_BP_LEVEL;
+               aq->cq.bp_ena = 1;
+       }
+
        /* Many to one reduction */
        aq->cq.qint_idx = qid % dev->qints;
 
@@ -302,9 +337,7 @@ nix_cq_rq_uninit(struct rte_eth_dev *eth_dev, struct otx2_eth_rxq *rxq)
 static inline int
 nix_get_data_off(struct otx2_eth_dev *dev)
 {
-       RTE_SET_USED(dev);
-
-       return 0;
+       return otx2_ethdev_is_ptp_en(dev) ? NIX_TIMESYNC_RX_OFFSET : 0;
 }
 
 uint64_t
@@ -415,6 +448,8 @@ otx2_nix_rx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t rq,
        rxq->pool = mp;
        rxq->qlen = nix_qsize_to_val(qsize);
        rxq->qsize = qsize;
+       rxq->lookup_mem = otx2_nix_fastpath_lookup_mem_get();
+       rxq->tstamp = &dev->tstamp;
 
        /* Alloc completion queue */
        rc = nix_cq_rq_init(eth_dev, dev, rq, rxq, mp);
@@ -461,16 +496,27 @@ nix_sq_init(struct otx2_eth_txq *txq)
        struct otx2_eth_dev *dev = txq->dev;
        struct otx2_mbox *mbox = dev->mbox;
        struct nix_aq_enq_req *sq;
+       uint32_t rr_quantum;
+       uint16_t smq;
+       int rc;
 
        if (txq->sqb_pool->pool_id == 0)
                return -EINVAL;
 
+       rc = otx2_nix_tm_get_leaf_data(dev, txq->sq, &rr_quantum, &smq);
+       if (rc) {
+               otx2_err("Failed to get sq->smq(leaf node), rc=%d", rc);
+               return rc;
+       }
+
        sq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
        sq->qidx = txq->sq;
        sq->ctype = NIX_AQ_CTYPE_SQ;
        sq->op = NIX_AQ_INSTOP_INIT;
        sq->sq.max_sqe_size = nix_sq_max_sqe_sz(txq);
 
+       sq->sq.smq = smq;
+       sq->sq.smq_rr_quantum = rr_quantum;
        sq->sq.default_chan = dev->tx_chan_base;
        sq->sq.sqe_stype = NIX_STYPE_STF;
        sq->sq.ena = 1;
@@ -690,6 +736,7 @@ otx2_nix_form_default_desc(struct otx2_eth_txq *txq)
                        send_mem->dsz = 0x0;
                        send_mem->wmem = 0x1;
                        send_mem->alg = NIX_SENDMEMALG_SETTSTMP;
+                       send_mem->addr = txq->dev->tstamp.tx_tstamp_iova;
                }
                sg = (union nix_send_sg_s *)&txq->cmd[4];
        } else {
@@ -711,12 +758,18 @@ static void
 otx2_nix_tx_queue_release(void *_txq)
 {
        struct otx2_eth_txq *txq = _txq;
+       struct rte_eth_dev *eth_dev;
 
        if (!txq)
                return;
 
+       eth_dev = txq->dev->eth_dev;
+
        otx2_nix_dbg("Releasing txq %u", txq->sq);
 
+       /* Flush and disable tm */
+       otx2_nix_tm_sw_xoff(txq, eth_dev->data->dev_started);
+
        /* Free sqb's and disable sq */
        nix_sq_uninit(txq);
 
@@ -1048,11 +1101,13 @@ otx2_nix_configure(struct rte_eth_dev *eth_dev)
 
        /* Free the resources allocated from the previous configure */
        if (dev->configured == 1) {
+               otx2_nix_rxchan_bpid_cfg(eth_dev, false);
                oxt2_nix_unregister_queue_irqs(eth_dev);
                nix_set_nop_rxtx_function(eth_dev);
                rc = nix_store_queue_cfg_and_then_release(eth_dev);
                if (rc)
                        goto fail;
+               otx2_nix_tm_fini(eth_dev);
                nix_lf_free(dev);
        }
 
@@ -1086,6 +1141,13 @@ otx2_nix_configure(struct rte_eth_dev *eth_dev)
                goto free_nix_lf;
        }
 
+       /* Init the default TM scheduler hierarchy */
+       rc = otx2_nix_tm_init_default(eth_dev);
+       if (rc) {
+               otx2_err("Failed to init traffic manager rc=%d", rc);
+               goto free_nix_lf;
+       }
+
        /* Register queue IRQs */
        rc = oxt2_nix_register_queue_irqs(eth_dev);
        if (rc) {
@@ -1093,6 +1155,22 @@ otx2_nix_configure(struct rte_eth_dev *eth_dev)
                goto free_nix_lf;
        }
 
+       rc = otx2_nix_rxchan_bpid_cfg(eth_dev, true);
+       if (rc) {
+               otx2_err("Failed to configure nix rx chan bpid cfg rc=%d", rc);
+               goto free_nix_lf;
+       }
+
+       /* Enable PTP if it was requested by the app or if it is already
+        * enabled in PF owning this VF
+        */
+       memset(&dev->tstamp, 0, sizeof(struct otx2_timesync_info));
+       if ((dev->rx_offloads & DEV_RX_OFFLOAD_TIMESTAMP) ||
+           otx2_ethdev_is_ptp_en(dev))
+               otx2_nix_timesync_enable(eth_dev);
+       else
+               otx2_nix_timesync_disable(eth_dev);
+
        /*
         * Restore queue config when reconfigure followed by
         * reconfigure and no queue configure invoked from application case.
@@ -1134,24 +1212,52 @@ int
 otx2_nix_tx_queue_start(struct rte_eth_dev *eth_dev, uint16_t qidx)
 {
        struct rte_eth_dev_data *data = eth_dev->data;
+       struct otx2_eth_txq *txq;
+       int rc = -EINVAL;
+
+       txq = eth_dev->data->tx_queues[qidx];
 
        if (data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED)
                return 0;
 
+       rc = otx2_nix_sq_sqb_aura_fc(txq, true);
+       if (rc) {
+               otx2_err("Failed to enable sqb aura fc, txq=%u, rc=%d",
+                        qidx, rc);
+               goto done;
+       }
+
        data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED;
-       return 0;
+
+done:
+       return rc;
 }
 
 int
 otx2_nix_tx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t qidx)
 {
        struct rte_eth_dev_data *data = eth_dev->data;
+       struct otx2_eth_txq *txq;
+       int rc;
+
+       txq = eth_dev->data->tx_queues[qidx];
 
        if (data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED)
                return 0;
 
+       txq->fc_cache_pkts = 0;
+
+       rc = otx2_nix_sq_sqb_aura_fc(txq, false);
+       if (rc) {
+               otx2_err("Failed to disable sqb aura fc, txq=%u, rc=%d",
+                        qidx, rc);
+               goto done;
+       }
+
        data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
-       return 0;
+
+done:
+       return rc;
 }
 
 static int
@@ -1211,6 +1317,7 @@ static const struct eth_dev_ops otx2_eth_dev_ops = {
        .tx_queue_stop            = otx2_nix_tx_queue_stop,
        .rx_queue_start           = otx2_nix_rx_queue_start,
        .rx_queue_stop            = otx2_nix_rx_queue_stop,
+       .dev_supported_ptypes_get = otx2_nix_supported_ptypes_get,
        .stats_get                = otx2_nix_dev_stats_get,
        .stats_reset              = otx2_nix_dev_stats_reset,
        .get_reg                  = otx2_nix_dev_get_reg,
@@ -1231,6 +1338,24 @@ static const struct eth_dev_ops otx2_eth_dev_ops = {
        .xstats_reset             = otx2_nix_xstats_reset,
        .xstats_get_by_id         = otx2_nix_xstats_get_by_id,
        .xstats_get_names_by_id   = otx2_nix_xstats_get_names_by_id,
+       .rxq_info_get             = otx2_nix_rxq_info_get,
+       .txq_info_get             = otx2_nix_txq_info_get,
+       .rx_queue_count           = otx2_nix_rx_queue_count,
+       .rx_descriptor_done       = otx2_nix_rx_descriptor_done,
+       .rx_descriptor_status     = otx2_nix_rx_descriptor_status,
+       .tx_done_cleanup          = otx2_nix_tx_done_cleanup,
+       .pool_ops_supported       = otx2_nix_pool_ops_supported,
+       .get_module_info          = otx2_nix_get_module_info,
+       .get_module_eeprom        = otx2_nix_get_module_eeprom,
+       .flow_ctrl_get            = otx2_nix_flow_ctrl_get,
+       .flow_ctrl_set            = otx2_nix_flow_ctrl_set,
+       .timesync_enable          = otx2_nix_timesync_enable,
+       .timesync_disable         = otx2_nix_timesync_disable,
+       .timesync_read_rx_timestamp = otx2_nix_timesync_read_rx_timestamp,
+       .timesync_read_tx_timestamp = otx2_nix_timesync_read_tx_timestamp,
+       .timesync_adjust_time     = otx2_nix_timesync_adjust_time,
+       .timesync_read_time       = otx2_nix_timesync_read_time,
+       .timesync_write_time      = otx2_nix_timesync_write_time,
 };
 
 static inline int
@@ -1388,6 +1513,9 @@ otx2_eth_dev_init(struct rte_eth_dev *eth_dev)
        /* Also sync same MAC address to CGX table */
        otx2_cgx_mac_addr_set(eth_dev, &eth_dev->data->mac_addrs[0]);
 
+       /* Initialize the tm data structures */
+       otx2_nix_tm_conf_init(eth_dev);
+
        dev->tx_offload_capa = nix_get_tx_offload_capa(dev);
        dev->rx_offload_capa = nix_get_rx_offload_capa(dev);
 
@@ -1429,6 +1557,13 @@ otx2_eth_dev_uninit(struct rte_eth_dev *eth_dev, bool mbox_close)
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return 0;
 
+       /* Disable nix bpid config */
+       otx2_nix_rxchan_bpid_cfg(eth_dev, false);
+
+       /* Disable PTP if already enabled */
+       if (otx2_ethdev_is_ptp_en(dev))
+               otx2_nix_timesync_disable(eth_dev);
+
        /* Free up SQs */
        for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
                otx2_nix_tx_queue_release(eth_dev->data->tx_queues[i]);
@@ -1443,6 +1578,11 @@ otx2_eth_dev_uninit(struct rte_eth_dev *eth_dev, bool mbox_close)
        }
        eth_dev->data->nb_rx_queues = 0;
 
+       /* Free tm resources */
+       rc = otx2_nix_tm_fini(eth_dev);
+       if (rc)
+               otx2_err("Failed to cleanup tm, rc=%d", rc);
+
        /* Unregister queue irqs */
        oxt2_nix_unregister_queue_irqs(eth_dev);