net/octeontx2: support base PTP
authorHarman Kalra <hkalra@marvell.com>
Fri, 31 May 2019 08:24:42 +0000 (13:54 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Thu, 4 Jul 2019 23:52:01 +0000 (01:52 +0200)
Add PTP enable and disable operations.

Signed-off-by: Harman Kalra <hkalra@marvell.com>
Signed-off-by: Zyta Szpak <zyta@marvell.com>
Acked-by: Jerin Jacob <jerinj@marvell.com>
doc/guides/nics/octeontx2.rst
drivers/net/octeontx2/Makefile
drivers/net/octeontx2/meson.build
drivers/net/octeontx2/otx2_ethdev.c
drivers/net/octeontx2/otx2_ethdev.h
drivers/net/octeontx2/otx2_ptp.c [new file with mode: 0644]
drivers/net/octeontx2/otx2_rx.h

index 20281b0..41eb3c7 100644 (file)
@@ -27,6 +27,7 @@ Features of the OCTEON TX2 Ethdev PMD are:
 - Link state information
 - Link flow control
 - Debug utilities - Context dump and error interrupt support
+- IEEE1588 timestamping
 
 Prerequisites
 -------------
index e9bfeec..da0b4e0 100644 (file)
@@ -34,6 +34,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX2_PMD) += \
        otx2_tm.c       \
        otx2_rss.c      \
        otx2_mac.c      \
+       otx2_ptp.c      \
        otx2_link.c     \
        otx2_stats.c    \
        otx2_lookup.c   \
index 4b56f44..2cac57d 100644 (file)
@@ -6,6 +6,7 @@ sources = files(
                'otx2_tm.c',
                'otx2_rss.c',
                'otx2_mac.c',
+               'otx2_ptp.c',
                'otx2_link.c',
                'otx2_stats.c',
                'otx2_lookup.c',
index 25469c5..6ab8ed7 100644 (file)
@@ -336,9 +336,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
@@ -450,6 +448,7 @@ otx2_nix_rx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t rq,
        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);
@@ -736,6 +735,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 {
@@ -1160,6 +1160,16 @@ otx2_nix_configure(struct rte_eth_dev *eth_dev)
                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.
@@ -1338,6 +1348,8 @@ static const struct eth_dev_ops otx2_eth_dev_ops = {
        .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,
 };
 
 static inline int
@@ -1542,6 +1554,10 @@ otx2_eth_dev_uninit(struct rte_eth_dev *eth_dev, bool mbox_close)
        /* 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]);
index 03ecd32..1ca28ad 100644 (file)
@@ -13,6 +13,7 @@
 #include <rte_mbuf.h>
 #include <rte_mempool.h>
 #include <rte_string_fns.h>
+#include <rte_time.h>
 
 #include "otx2_common.h"
 #include "otx2_dev.h"
 #define NIX_DEFAULT_RSS_CTX_GROUP  0
 #define NIX_DEFAULT_RSS_MCAM_IDX  -1
 
+#define otx2_ethdev_is_ptp_en(dev)     ((dev)->ptp_en)
+
+#define NIX_TIMESYNC_TX_CMD_LEN                8
+/* Additional timesync values. */
+#define OTX2_CYCLECOUNTER_MASK   0xffffffffffffffffULL
+
 enum nix_q_size_e {
        nix_q_size_16,  /* 16 entries */
        nix_q_size_64,  /* 64 entries */
@@ -234,6 +241,12 @@ struct otx2_eth_dev {
        struct otx2_eth_qconf *tx_qconf;
        struct otx2_eth_qconf *rx_qconf;
        struct rte_eth_dev *eth_dev;
+       /* PTP counters */
+       bool ptp_en;
+       struct otx2_timesync_info tstamp;
+       struct rte_timecounter  systime_tc;
+       struct rte_timecounter  rx_tstamp_tc;
+       struct rte_timecounter  tx_tstamp_tc;
 } __rte_cache_aligned;
 
 struct otx2_eth_txq {
@@ -414,4 +427,8 @@ int otx2_ethdev_parse_devargs(struct rte_devargs *devargs,
 /* Rx and Tx routines */
 void otx2_nix_form_default_desc(struct otx2_eth_txq *txq);
 
+/* Timesync - PTP routines */
+int otx2_nix_timesync_enable(struct rte_eth_dev *eth_dev);
+int otx2_nix_timesync_disable(struct rte_eth_dev *eth_dev);
+
 #endif /* __OTX2_ETHDEV_H__ */
diff --git a/drivers/net/octeontx2/otx2_ptp.c b/drivers/net/octeontx2/otx2_ptp.c
new file mode 100644 (file)
index 0000000..1050679
--- /dev/null
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2019 Marvell International Ltd.
+ */
+
+#include <rte_ethdev_driver.h>
+
+#include "otx2_ethdev.h"
+
+#define PTP_FREQ_ADJUST (1 << 9)
+
+static void
+nix_start_timecounters(struct rte_eth_dev *eth_dev)
+{
+       struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+
+       memset(&dev->systime_tc, 0, sizeof(struct rte_timecounter));
+       memset(&dev->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
+       memset(&dev->tx_tstamp_tc, 0, sizeof(struct rte_timecounter));
+
+       dev->systime_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
+       dev->rx_tstamp_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
+       dev->tx_tstamp_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
+}
+
+static int
+nix_ptp_config(struct rte_eth_dev *eth_dev, int en)
+{
+       struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+       struct otx2_mbox *mbox = dev->mbox;
+       uint8_t rc = 0;
+
+       if (otx2_dev_is_vf(dev))
+               return rc;
+
+       if (en) {
+               /* Enable time stamping of sent PTP packets. */
+               otx2_mbox_alloc_msg_nix_lf_ptp_tx_enable(mbox);
+               rc = otx2_mbox_process(mbox);
+               if (rc) {
+                       otx2_err("MBOX ptp tx conf enable failed: err %d", rc);
+                       return rc;
+               }
+               /* Enable time stamping of received PTP packets. */
+               otx2_mbox_alloc_msg_cgx_ptp_rx_enable(mbox);
+       } else {
+               /* Disable time stamping of sent PTP packets. */
+               otx2_mbox_alloc_msg_nix_lf_ptp_tx_disable(mbox);
+               rc = otx2_mbox_process(mbox);
+               if (rc) {
+                       otx2_err("MBOX ptp tx conf disable failed: err %d", rc);
+                       return rc;
+               }
+               /* Disable time stamping of received PTP packets. */
+               otx2_mbox_alloc_msg_cgx_ptp_rx_disable(mbox);
+       }
+
+       return otx2_mbox_process(mbox);
+}
+
+int
+otx2_nix_timesync_enable(struct rte_eth_dev *eth_dev)
+{
+       struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+       int i, rc = 0;
+
+       if (otx2_ethdev_is_ptp_en(dev)) {
+               otx2_info("PTP mode is already enabled ");
+               return -EINVAL;
+       }
+
+       /* If we are VF, no further action can be taken */
+       if (otx2_dev_is_vf(dev))
+               return -EINVAL;
+
+       if (!(dev->rx_offload_flags & NIX_RX_OFFLOAD_PTYPE_F)) {
+               otx2_err("Ptype offload is disabled, it should be enabled");
+               return -EINVAL;
+       }
+
+       /* Allocating a iova address for tx tstamp */
+       const struct rte_memzone *ts;
+       ts = rte_eth_dma_zone_reserve(eth_dev, "otx2_ts",
+                                     0, OTX2_ALIGN, OTX2_ALIGN,
+                                     dev->node);
+       if (ts == NULL)
+               otx2_err("Failed to allocate mem for tx tstamp addr");
+
+       dev->tstamp.tx_tstamp_iova = ts->iova;
+       dev->tstamp.tx_tstamp = ts->addr;
+
+       /* System time should be already on by default */
+       nix_start_timecounters(eth_dev);
+
+       dev->rx_offloads |= DEV_RX_OFFLOAD_TIMESTAMP;
+       dev->rx_offload_flags |= NIX_RX_OFFLOAD_TSTAMP_F;
+       dev->tx_offload_flags |= NIX_TX_OFFLOAD_TSTAMP_F;
+
+       rc = nix_ptp_config(eth_dev, 1);
+       if (!rc) {
+               for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
+                       struct otx2_eth_txq *txq = eth_dev->data->tx_queues[i];
+                       otx2_nix_form_default_desc(txq);
+               }
+       }
+       return rc;
+}
+
+int
+otx2_nix_timesync_disable(struct rte_eth_dev *eth_dev)
+{
+       struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+       int i, rc = 0;
+
+       if (!otx2_ethdev_is_ptp_en(dev)) {
+               otx2_nix_dbg("PTP mode is disabled");
+               return -EINVAL;
+       }
+
+       /* If we are VF, nothing else can be done */
+       if (otx2_dev_is_vf(dev))
+               return -EINVAL;
+
+       dev->rx_offloads &= ~DEV_RX_OFFLOAD_TIMESTAMP;
+       dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_TSTAMP_F;
+       dev->tx_offload_flags &= ~NIX_TX_OFFLOAD_TSTAMP_F;
+
+       rc = nix_ptp_config(eth_dev, 0);
+       if (!rc) {
+               for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
+                       struct otx2_eth_txq *txq = eth_dev->data->tx_queues[i];
+                       otx2_nix_form_default_desc(txq);
+               }
+       }
+       return rc;
+}
index 1283fdf..0c3627c 100644 (file)
                                         sizeof(uint16_t))
 
 #define NIX_RX_OFFLOAD_PTYPE_F         BIT(1)
+#define NIX_RX_OFFLOAD_TSTAMP_F        BIT(5)
+
+#define NIX_TIMESYNC_RX_OFFSET         8
+
+struct otx2_timesync_info {
+       uint64_t        rx_tstamp;
+       rte_iova_t      tx_tstamp_iova;
+       uint64_t        *tx_tstamp;
+       uint8_t         tx_ready;
+       uint8_t         rx_ready;
+} __rte_cache_aligned;
 
 #endif /* __OTX2_RX_H__ */