DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 1/2] net/octeontx2: fix ptp performance issue
@ 2019-07-27 14:57 Harman Kalra
  2019-07-27 14:57 ` [dpdk-dev] [PATCH 2/2] net/octeontx2: support read clock API Harman Kalra
  0 siblings, 1 reply; 11+ messages in thread
From: Harman Kalra @ 2019-07-27 14:57 UTC (permalink / raw)
  To: Pavan Nikhilesh Bhagavatula, Jerin Jacob Kollanukkaran,
	Nithin Kumar Dabilpuram, Kiran Kumar Kokkilagadda
  Cc: dev, Harman Kalra

A huge drop in per core MPPS value was observed when PTP stack is
enabled. The reason behind the bottleneck is HW serialises the
transfer of all SQEs, which seeks timestamp capture, on the same
send DMA path. Hence only those packets which requires timestamp
capture should set SETTSTAMP in send mem alg.
With this patch timestamping would be done only for those packets
with PKT_TX_IEEE1588_TMST set.

Fixes: fb3ae0951abd ("net/octeontx2: support Tx")
Fixes: 8980a153006b ("event/octeontx2: support PTP for SSO")

Signed-off-by: Harman Kalra <hkalra@marvell.com>
---
 drivers/event/octeontx2/otx2_evdev.h       |  7 ++++++-
 drivers/event/octeontx2/otx2_worker.h      | 10 +++++++--
 drivers/event/octeontx2/otx2_worker_dual.h | 14 +++++++++++--
 drivers/net/octeontx2/otx2_ethdev.c        |  2 --
 drivers/net/octeontx2/otx2_rx.c            |  3 ++-
 drivers/net/octeontx2/otx2_rx.h            | 24 +++++++++++++---------
 drivers/net/octeontx2/otx2_tx.h            | 19 +++++++++++++----
 7 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/drivers/event/octeontx2/otx2_evdev.h b/drivers/event/octeontx2/otx2_evdev.h
index 9c9718f6f..5cd80e3b2 100644
--- a/drivers/event/octeontx2/otx2_evdev.h
+++ b/drivers/event/octeontx2/otx2_evdev.h
@@ -25,6 +25,7 @@
 #define OTX2_SSO_SQB_LIMIT                  (0x180)
 #define OTX2_SSO_XAQ_SLACK                  (8)
 #define OTX2_SSO_XAQ_CACHE_CNT              (0x7)
+#define OTX2_SSO_WQE_SG_PTR                 (9)
 
 /* SSO LF register offsets (BAR2) */
 #define SSO_LF_GGRP_OP_ADD_WORK0            (0x0ull)
@@ -222,10 +223,14 @@ otx2_wqe_to_mbuf(uint64_t get_work1, const uint64_t mbuf, uint8_t port_id,
 		 const void * const lookup_mem)
 {
 	struct nix_wqe_hdr_s *wqe = (struct nix_wqe_hdr_s *)get_work1;
+	uint64_t val = mbuf_init.value | (uint64_t)port_id << 48;
+
+	if (flags & NIX_RX_OFFLOAD_TSTAMP_F)
+		val |= NIX_TIMESYNC_RX_OFFSET;
 
 	otx2_nix_cqe_to_mbuf((struct nix_cqe_hdr_s *)wqe, tag,
 			     (struct rte_mbuf *)mbuf, lookup_mem,
-			     mbuf_init.value | (uint64_t)port_id << 48, flags);
+			      val, flags);
 
 }
 
diff --git a/drivers/event/octeontx2/otx2_worker.h b/drivers/event/octeontx2/otx2_worker.h
index 3c847d223..76f91bb59 100644
--- a/drivers/event/octeontx2/otx2_worker.h
+++ b/drivers/event/octeontx2/otx2_worker.h
@@ -18,6 +18,7 @@ otx2_ssogws_get_work(struct otx2_ssogws *ws, struct rte_event *ev,
 		     const uint32_t flags, const void * const lookup_mem)
 {
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -69,8 +70,10 @@ otx2_ssogws_get_work(struct otx2_ssogws *ws, struct rte_event *ev,
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, lookup_mem);
 		/* Extracting tstamp, if PTP enabled*/
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
 		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, ws->tstamp,
-					flags);
+					flags, (uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
@@ -86,6 +89,7 @@ otx2_ssogws_get_work_empty(struct otx2_ssogws *ws, struct rte_event *ev,
 			   const uint32_t flags)
 {
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -131,8 +135,10 @@ otx2_ssogws_get_work_empty(struct otx2_ssogws *ws, struct rte_event *ev,
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, NULL);
 		/* Extracting tstamp, if PTP enabled*/
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
 		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, ws->tstamp,
-					flags);
+					flags, (uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
diff --git a/drivers/event/octeontx2/otx2_worker_dual.h b/drivers/event/octeontx2/otx2_worker_dual.h
index 4a72f424d..5134e3d52 100644
--- a/drivers/event/octeontx2/otx2_worker_dual.h
+++ b/drivers/event/octeontx2/otx2_worker_dual.h
@@ -21,6 +21,7 @@ otx2_ssogws_dual_get_work(struct otx2_ssogws_state *ws,
 {
 	const uint64_t set_gw = BIT_ULL(16) | 1;
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -70,8 +71,17 @@ otx2_ssogws_dual_get_work(struct otx2_ssogws_state *ws,
 	    event.event_type == RTE_EVENT_TYPE_ETHDEV) {
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, lookup_mem);
-		/* Extracting tstamp, if PTP enabled*/
-		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, tstamp, flags);
+		/* Extracting tstamp, if PTP enabled. CGX will prepend the
+		 * timestamp at starting of packet data and it can be derieved
+		 * from WQE 9 dword which corresponds to SG iova.
+		 * rte_pktmbuf_mtod_offset can be used for this purpose but it
+		 * brings down the performance as it reads mbuf->buf_addr which
+		 * is not part of cache in general fast path.
+		 */
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
+		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, tstamp, flags,
+					(uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
diff --git a/drivers/net/octeontx2/otx2_ethdev.c b/drivers/net/octeontx2/otx2_ethdev.c
index b018b25b7..595c8003a 100644
--- a/drivers/net/octeontx2/otx2_ethdev.c
+++ b/drivers/net/octeontx2/otx2_ethdev.c
@@ -874,8 +874,6 @@ otx2_nix_form_default_desc(struct otx2_eth_txq *txq)
 			send_mem = (struct nix_send_mem_s *)(txq->cmd +
 						(send_hdr->w0.sizem1 << 1));
 			send_mem->subdc = NIX_SUBDC_MEM;
-			send_mem->dsz = 0x0;
-			send_mem->wmem = 0x1;
 			send_mem->alg = NIX_SENDMEMALG_SETTSTMP;
 			send_mem->addr = txq->dev->tstamp.tx_tstamp_iova;
 		}
diff --git a/drivers/net/octeontx2/otx2_rx.c b/drivers/net/octeontx2/otx2_rx.c
index deefe9588..701efc858 100644
--- a/drivers/net/octeontx2/otx2_rx.c
+++ b/drivers/net/octeontx2/otx2_rx.c
@@ -68,7 +68,8 @@ nix_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 
 		otx2_nix_cqe_to_mbuf(cq, cq->tag, mbuf, lookup_mem, mbuf_init,
 				     flags);
-		otx2_nix_mbuf_to_tstamp(mbuf, rxq->tstamp, flags);
+		otx2_nix_mbuf_to_tstamp(mbuf, rxq->tstamp, flags,
+				(uint64_t *)((uint8_t *)mbuf + data_off));
 		rx_pkts[packets++] = mbuf;
 		otx2_prefetch_store_keep(mbuf);
 		head++;
diff --git a/drivers/net/octeontx2/otx2_rx.h b/drivers/net/octeontx2/otx2_rx.h
index e150f38d7..d12e8b809 100644
--- a/drivers/net/octeontx2/otx2_rx.h
+++ b/drivers/net/octeontx2/otx2_rx.h
@@ -50,22 +50,26 @@ union mbuf_initializer {
 
 static __rte_always_inline void
 otx2_nix_mbuf_to_tstamp(struct rte_mbuf *mbuf,
-			struct otx2_timesync_info *tstamp, const uint16_t flag)
+			struct otx2_timesync_info *tstamp, const uint16_t flag,
+			uint64_t *tstamp_ptr)
 {
 	if ((flag & NIX_RX_OFFLOAD_TSTAMP_F) &&
-	    mbuf->packet_type == RTE_PTYPE_L2_ETHER_TIMESYNC &&
 	    (mbuf->data_off == RTE_PKTMBUF_HEADROOM +
 	     NIX_TIMESYNC_RX_OFFSET)) {
-		uint64_t *tstamp_ptr;
 
-		/* Deal with rx timestamp */
-		tstamp_ptr = rte_pktmbuf_mtod_offset(mbuf, uint64_t *,
-						     -NIX_TIMESYNC_RX_OFFSET);
+		/* Reading the rx timestamp inserted by CGX, viz at
+		 * starting of the packet data.
+		 */
 		mbuf->timestamp = rte_be_to_cpu_64(*tstamp_ptr);
-		tstamp->rx_tstamp = mbuf->timestamp;
-		tstamp->rx_ready = 1;
-		mbuf->ol_flags |= PKT_RX_IEEE1588_PTP | PKT_RX_IEEE1588_TMST
-			| PKT_RX_TIMESTAMP;
+		/* PKT_RX_IEEE1588_TMST flag needs to be set only in case
+		 * PTP packets are received.
+		 */
+		if (mbuf->packet_type == RTE_PTYPE_L2_ETHER_TIMESYNC) {
+			tstamp->rx_tstamp = mbuf->timestamp;
+			tstamp->rx_ready = 1;
+			mbuf->ol_flags |= PKT_RX_IEEE1588_PTP |
+				PKT_RX_IEEE1588_TMST | PKT_RX_TIMESTAMP;
+		}
 	}
 }
 
diff --git a/drivers/net/octeontx2/otx2_tx.h b/drivers/net/octeontx2/otx2_tx.h
index b75a220ea..494ba3884 100644
--- a/drivers/net/octeontx2/otx2_tx.h
+++ b/drivers/net/octeontx2/otx2_tx.h
@@ -43,18 +43,29 @@ otx2_nix_xmit_prepare_tstamp(uint64_t *cmd,  const uint64_t *send_mem_desc,
 	if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
 		struct nix_send_mem_s *send_mem;
 		uint16_t off = (no_segdw - 1) << 1;
+		const uint8_t is_ol_tstamp = !(ol_flags & PKT_TX_IEEE1588_TMST);
 
 		send_mem = (struct nix_send_mem_s *)(cmd + off);
-		if (flags & NIX_TX_MULTI_SEG_F)
+		if (flags & NIX_TX_MULTI_SEG_F) {
 			/* Retrieving the default desc values */
 			cmd[off] = send_mem_desc[6];
 
+			/* Using compiler barier to avoid voilation of C
+			 * aliasing rules.
+			 */
+			rte_compiler_barrier();
+		}
+
 		/* Packets for which PKT_TX_IEEE1588_TMST is not set, tx tstamp
-		 * should not be updated at tx tstamp registered address, rather
-		 * a dummy address which is eight bytes ahead would be updated
+		 * should not be recorded, hence changing the alg type to
+		 * NIX_SENDMEMALG_SET and also changing send mem addr field to
+		 * next 8 bytes as it corrpt the actual tx tstamp registered
+		 * address.
 		 */
+		send_mem->alg = NIX_SENDMEMALG_SETTSTMP - (is_ol_tstamp);
+
 		send_mem->addr = (rte_iova_t)((uint64_t *)send_mem_desc[7] +
-				!(ol_flags & PKT_TX_IEEE1588_TMST));
+					      (is_ol_tstamp));
 	}
 }
 
-- 
2.18.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [PATCH 2/2] net/octeontx2: support read clock API
  2019-07-27 14:57 [dpdk-dev] [PATCH 1/2] net/octeontx2: fix ptp performance issue Harman Kalra
@ 2019-07-27 14:57 ` Harman Kalra
  2019-07-27 15:48   ` Jerin Jacob Kollanukkaran
  0 siblings, 1 reply; 11+ messages in thread
From: Harman Kalra @ 2019-07-27 14:57 UTC (permalink / raw)
  To: Jerin Jacob Kollanukkaran, Nithin Kumar Dabilpuram,
	Vamsi Krishna Attunuru, Kiran Kumar Kokkilagadda
  Cc: dev, Harman Kalra

This patch implements read clock api whose purpose is to return
raw clock ticks. Using this API real time ticks spent in
processing a packet can be known:
    <read_clock val at any time> - mbuf->timestamp

Signed-off-by: Harman Kalra <hkalra@marvell.com>
---
 drivers/common/octeontx2/otx2_mbox.h |  2 +
 drivers/net/octeontx2/otx2_ethdev.c  | 86 ++++++++++++++++++++++++++++
 drivers/net/octeontx2/otx2_ethdev.h  |  4 ++
 drivers/net/octeontx2/otx2_ptp.c     | 30 ++++++++++
 4 files changed, 122 insertions(+)

diff --git a/drivers/common/octeontx2/otx2_mbox.h b/drivers/common/octeontx2/otx2_mbox.h
index c0bb676b2..b2c59c86e 100644
--- a/drivers/common/octeontx2/otx2_mbox.h
+++ b/drivers/common/octeontx2/otx2_mbox.h
@@ -1354,11 +1354,13 @@ struct ptp_req {
 	struct mbox_msghdr hdr;
 	uint8_t __otx2_io op;
 	int64_t __otx2_io scaled_ppm;
+	uint8_t __otx2_io is_pmu;
 };
 
 struct ptp_rsp {
 	struct mbox_msghdr hdr;
 	uint64_t __otx2_io clk;
+	uint64_t __otx2_io tsc;
 };
 
 struct get_hw_cap_rsp {
diff --git a/drivers/net/octeontx2/otx2_ethdev.c b/drivers/net/octeontx2/otx2_ethdev.c
index 595c8003a..799e67480 100644
--- a/drivers/net/octeontx2/otx2_ethdev.c
+++ b/drivers/net/octeontx2/otx2_ethdev.c
@@ -521,6 +521,17 @@ otx2_nix_rx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t rq,
 
 	eth_dev->data->rx_queues[rq] = rxq;
 	eth_dev->data->rx_queue_state[rq] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+	/* Calculating delta and freq mult between PTP HI clock and rdtsc.
+	 * These are needed for deriving PTP HI clock value from tsc counter.
+	 */
+	if ((dev->rx_offloads & DEV_RX_OFFLOAD_TIMESTAMP) ||
+	    otx2_ethdev_is_ptp_en(dev)) {
+		rc = otx2_nix_raw_clock_rdtsc_conv(dev);
+		if (rc)
+			otx2_err("Failed to calculate delta and freq mult");
+	}
+
 	return 0;
 
 free_rxq:
@@ -1186,6 +1197,79 @@ nix_set_nop_rxtx_function(struct rte_eth_dev *eth_dev)
 	rte_mb();
 }
 
+static int
+nix_read_raw_clock(struct otx2_eth_dev *dev, uint64_t *clock, uint64_t *tsc,
+		   uint8_t is_pmu)
+{
+	struct otx2_mbox *mbox = dev->mbox;
+	struct ptp_req *req;
+	struct ptp_rsp *rsp;
+	int rc = 0;
+
+	req = otx2_mbox_alloc_msg_ptp_op(mbox);
+	req->op = PTP_OP_GET_CLOCK;
+	req->is_pmu = is_pmu;
+	rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
+	if (rc)
+		goto done;
+
+	*clock = rsp->clk;
+	*tsc = rsp->tsc;
+
+done:
+	return rc;
+}
+
+/* This function calculates two parameters "clk_freq_mult" and
+ * "clk_delta" which is useful in deriving PTP HI clock from
+ * rdtsc value.
+ */
+int
+otx2_nix_raw_clock_rdtsc_conv(struct otx2_eth_dev *dev)
+{
+	uint64_t ticks_base = 0, ticks = 0, t_freq = 0, tsc = 0;
+	uint8_t retval = 0, val;
+
+	/* Calculating the frequency at which PTP HI clock is running */
+	retval = nix_read_raw_clock(dev, &ticks_base, &tsc, false);
+	if (retval != 0) {
+		otx2_err("Failed to read the raw clock value: %d", retval);
+		goto done;
+	}
+
+	rte_delay_ms(100);
+
+	retval = nix_read_raw_clock(dev, &ticks, &tsc, false);
+	if (retval != 0) {
+		otx2_err("Failed to read the raw clock value: %d", retval);
+		goto done;
+	}
+
+	t_freq = (ticks - ticks_base) * 10;
+
+	/* Calculating the freq multiplier viz the ratio between the
+	 * frequency at which PTP HI clock works and rdtsc clock runs
+	 */
+	dev->clk_freq_mult =
+		(double)pow(10, floor(log10(t_freq))) / rte_get_timer_hz();
+
+	val = false;
+#ifdef RTE_ARM_EAL_RDTSC_USE_PMU
+	val = true;
+#endif
+	retval = nix_read_raw_clock(dev, &ticks, &tsc, val);
+	if (retval != 0) {
+		otx2_err("Failed to read the raw clock value: %d", retval);
+		goto done;
+	}
+
+	/* Calculating delta between PTP HI clock and rdtsc */
+	dev->clk_delta = ((uint64_t)(ticks / dev->clk_freq_mult) - tsc);
+
+done:
+	return retval;
+}
+
 static int
 otx2_nix_configure(struct rte_eth_dev *eth_dev)
 {
@@ -1363,6 +1447,7 @@ otx2_nix_configure(struct rte_eth_dev *eth_dev)
 	dev->configured = 1;
 	dev->configured_nb_rx_qs = data->nb_rx_queues;
 	dev->configured_nb_tx_qs = data->nb_tx_queues;
+
 	return 0;
 
 cq_fini:
@@ -1649,6 +1734,7 @@ static const struct eth_dev_ops otx2_eth_dev_ops = {
 	.vlan_pvid_set		  = otx2_nix_vlan_pvid_set,
 	.rx_queue_intr_enable	  = otx2_nix_rx_queue_intr_enable,
 	.rx_queue_intr_disable	  = otx2_nix_rx_queue_intr_disable,
+	.read_clock		  = otx2_nix_read_clock,
 };
 
 static inline int
diff --git a/drivers/net/octeontx2/otx2_ethdev.h b/drivers/net/octeontx2/otx2_ethdev.h
index 863d4877f..a2bd0ffcf 100644
--- a/drivers/net/octeontx2/otx2_ethdev.h
+++ b/drivers/net/octeontx2/otx2_ethdev.h
@@ -300,6 +300,8 @@ struct otx2_eth_dev {
 	struct rte_timecounter  systime_tc;
 	struct rte_timecounter  rx_tstamp_tc;
 	struct rte_timecounter  tx_tstamp_tc;
+	double clk_freq_mult;
+	uint64_t clk_delta;
 } __rte_cache_aligned;
 
 struct otx2_eth_txq {
@@ -527,5 +529,7 @@ int otx2_nix_timesync_write_time(struct rte_eth_dev *eth_dev,
 int otx2_nix_timesync_read_time(struct rte_eth_dev *eth_dev,
 				struct timespec *ts);
 int otx2_eth_dev_ptp_info_update(struct otx2_dev *dev, bool ptp_en);
+int otx2_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *time);
+int otx2_nix_raw_clock_rdtsc_conv(struct otx2_eth_dev *dev);
 
 #endif /* __OTX2_ETHDEV_H__ */
diff --git a/drivers/net/octeontx2/otx2_ptp.c b/drivers/net/octeontx2/otx2_ptp.c
index 0186c629a..3f54cfeaf 100644
--- a/drivers/net/octeontx2/otx2_ptp.c
+++ b/drivers/net/octeontx2/otx2_ptp.c
@@ -224,6 +224,13 @@ otx2_nix_timesync_adjust_time(struct rte_eth_dev *eth_dev, int64_t delta)
 		rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
 		if (rc)
 			return rc;
+		/* Since the frequency of PTP comp register is tuned, delta and
+		 * freq mult calculation for deriving PTP_HI from rdtsc should
+		 * be done again.
+		 */
+		rc = otx2_nix_raw_clock_rdtsc_conv(dev);
+		if (rc)
+			otx2_err("Failed to calculate delta and freq mult");
 	}
 	dev->systime_tc.nsec += delta;
 	dev->rx_tstamp_tc.nsec += delta;
@@ -271,3 +278,26 @@ otx2_nix_timesync_read_time(struct rte_eth_dev *eth_dev, struct timespec *ts)
 
 	return 0;
 }
+
+
+int
+otx2_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *clock)
+{
+	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+
+	if (!otx2_ethdev_is_ptp_en(dev)) {
+		otx2_err("PTP should be enabled.");
+		return -EINVAL;
+	}
+
+	/* This API returns the raw PTP HI clock value. Since LFs doesn't
+	 * have direct access to PTP registers and it requires mbox msg
+	 * to AF for this value. In fastpath reading this value for every
+	 * packet (which involes mbox call) becomes very expensive, hence
+	 * we should be able to derive PTP HI clock value from rdtsc by
+	 * using freq_mult and clk_delta calculated during configure stage.
+	 */
+	*clock = (rte_rdtsc() + dev->clk_delta) * dev->clk_freq_mult;
+
+	return 0;
+}
-- 
2.18.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [dpdk-dev] [PATCH 2/2] net/octeontx2: support read clock API
  2019-07-27 14:57 ` [dpdk-dev] [PATCH 2/2] net/octeontx2: support read clock API Harman Kalra
@ 2019-07-27 15:48   ` Jerin Jacob Kollanukkaran
  2019-07-27 20:41     ` [dpdk-dev] [PATCH v2 1/2] net/octeontx2: fix ptp performance issue Harman Kalra
  0 siblings, 1 reply; 11+ messages in thread
From: Jerin Jacob Kollanukkaran @ 2019-07-27 15:48 UTC (permalink / raw)
  To: Harman Kalra, Nithin Kumar Dabilpuram, Vamsi Krishna Attunuru,
	Kiran Kumar Kokkilagadda
  Cc: dev

> -----Original Message-----
> From: Harman Kalra <hkalra@marvell.com>
> Sent: Saturday, July 27, 2019 8:27 PM
> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Nithin Kumar
> Dabilpuram <ndabilpuram@marvell.com>; Vamsi Krishna Attunuru
> <vattunuru@marvell.com>; Kiran Kumar Kokkilagadda
> <kirankumark@marvell.com>
> Cc: dev@dpdk.org; Harman Kalra <hkalra@marvell.com>
> Subject: [PATCH 2/2] net/octeontx2: support read clock API
> 
> This patch implements read clock api whose purpose is to return raw clock
> ticks. Using this API real time ticks spent in processing a packet can be known:
>     <read_clock val at any time> - mbuf->timestamp

Add more details.

> 
> Signed-off-by: Harman Kalra <hkalra@marvell.com>
> ---
>  drivers/common/octeontx2/otx2_mbox.h |  2 +
> drivers/net/octeontx2/otx2_ethdev.c  | 86
> ++++++++++++++++++++++++++++  drivers/net/octeontx2/otx2_ethdev.h
> |  4 ++
>  drivers/net/octeontx2/otx2_ptp.c     | 30 ++++++++++
>  4 files changed, 122 insertions(+)
> 
> diff --git a/drivers/common/octeontx2/otx2_mbox.h
> b/drivers/common/octeontx2/otx2_mbox.h
> index c0bb676b2..b2c59c86e 100644
> --- a/drivers/common/octeontx2/otx2_mbox.h
> +++ b/drivers/common/octeontx2/otx2_mbox.h
> @@ -1354,11 +1354,13 @@ struct ptp_req {
>  	struct mbox_msghdr hdr;
>  	uint8_t __otx2_io op;
>  	int64_t __otx2_io scaled_ppm;
> +	uint8_t __otx2_io is_pmu;
>  };
> 
>  struct ptp_rsp {
>  	struct mbox_msghdr hdr;
>  	uint64_t __otx2_io clk;
> +	uint64_t __otx2_io tsc;
>  };
> 
>  struct get_hw_cap_rsp {
> diff --git a/drivers/net/octeontx2/otx2_ethdev.c
> b/drivers/net/octeontx2/otx2_ethdev.c
> index 595c8003a..799e67480 100644
> --- a/drivers/net/octeontx2/otx2_ethdev.c
> +++ b/drivers/net/octeontx2/otx2_ethdev.c
> @@ -521,6 +521,17 @@ otx2_nix_rx_queue_setup(struct rte_eth_dev
> *eth_dev, uint16_t rq,
> 
>  	eth_dev->data->rx_queues[rq] = rxq;
>  	eth_dev->data->rx_queue_state[rq] =
> RTE_ETH_QUEUE_STATE_STOPPED;
> +
> +	/* Calculating delta and freq mult between PTP HI clock and rdtsc.
> +	 * These are needed for deriving PTP HI clock value from tsc counter.
> +	 */
> +	if ((dev->rx_offloads & DEV_RX_OFFLOAD_TIMESTAMP) ||
> +	    otx2_ethdev_is_ptp_en(dev)) {
> +		rc = otx2_nix_raw_clock_rdtsc_conv(dev);

rdtsc is an x86 instruction. Change tmc wherever rdtsc used.

> +		if (rc)
> +			otx2_err("Failed to calculate delta and freq mult");
> +	}
> +
>  	return 0;

Make it as return rc to avoid return 0 incase above failure.



> 
>  free_rxq:
> @@ -1186,6 +1197,79 @@ nix_set_nop_rxtx_function(struct rte_eth_dev
> *eth_dev)
>  	rte_mb();
>  }
> 
> +static int
> +nix_read_raw_clock(struct otx2_eth_dev *dev, uint64_t *clock, uint64_t
> *tsc,
> +		   uint8_t is_pmu)
> +{
> +	struct otx2_mbox *mbox = dev->mbox;
> +	struct ptp_req *req;
> +	struct ptp_rsp *rsp;
> +	int rc = 0;

No need to init with 0

> +
> +	req = otx2_mbox_alloc_msg_ptp_op(mbox);
> +	req->op = PTP_OP_GET_CLOCK;
> +	req->is_pmu = is_pmu;
> +	rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
> +	if (rc)
> +		goto done;

s/done/error

> +
> +	*clock = rsp->clk;
If (clock)

> +	*tsc = rsp->tsc;

If (tsc)

> +
> +done:
> +	return rc;
> +}
> +
> +/* This function calculates two parameters "clk_freq_mult" and
> + * "clk_delta" which is useful in deriving PTP HI clock from
> + * rdtsc value.
s/rdstc/tmc

> + */
> +int
> +otx2_nix_raw_clock_rdtsc_conv(struct otx2_eth_dev *dev) {

s/rdstc/tmc

> +	uint64_t ticks_base = 0, ticks = 0, t_freq = 0, tsc = 0;


Init with 0 if it absolute necessary


> +	uint8_t retval = 0, val;

# It should be int
# Change retval to rc for consistency

> +
> +	/* Calculating the frequency at which PTP HI clock is running */
> +	retval = nix_read_raw_clock(dev, &ticks_base, &tsc, false);
> +	if (retval != 0) {

If (rc)

> +		otx2_err("Failed to read the raw clock value: %d", retval);
> +		goto done;
> +	}
> +
> +	rte_delay_ms(100);
> +
> +	retval = nix_read_raw_clock(dev, &ticks, &tsc, false);
> +	if (retval != 0) {

If (rc)

> +		otx2_err("Failed to read the raw clock value: %d", retval);
> +		goto done;
> +	}
> +
> +	t_freq = (ticks - ticks_base) * 10;
> +
> +	/* Calculating the freq multiplier viz the ratio between the
> +	 * frequency at which PTP HI clock works and rdtsc clock runs
> +	 */
> +	dev->clk_freq_mult =
> +		(double)pow(10, floor(log10(t_freq))) / rte_get_timer_hz();
> +
> +	val = false;
> +#ifdef RTE_ARM_EAL_RDTSC_USE_PMU
> +	val = true;
> +#endif
> +	retval = nix_read_raw_clock(dev, &ticks, &tsc, val);
> +	if (retval != 0) {


If (rc)

> +		otx2_err("Failed to read the raw clock value: %d", retval);
> +		goto done;
> +	}
> +
> +	/* Calculating delta between PTP HI clock and rdtsc */
> +	dev->clk_delta = ((uint64_t)(ticks / dev->clk_freq_mult) - tsc);
> +
> +done:
> +	return retval;
> +}
> +
>  static int
>  otx2_nix_configure(struct rte_eth_dev *eth_dev)  { @@ -1363,6 +1447,7
> @@ otx2_nix_configure(struct rte_eth_dev *eth_dev)
>  	dev->configured = 1;
>  	dev->configured_nb_rx_qs = data->nb_rx_queues;
>  	dev->configured_nb_tx_qs = data->nb_tx_queues;
> +

Unrelated change

>  	return 0;
> 
>  cq_fini:
> @@ -1649,6 +1734,7 @@ static const struct eth_dev_ops otx2_eth_dev_ops
> = {
>  	.vlan_pvid_set		  = otx2_nix_vlan_pvid_set,
>  	.rx_queue_intr_enable	  = otx2_nix_rx_queue_intr_enable,
>  	.rx_queue_intr_disable	  = otx2_nix_rx_queue_intr_disable,
> +	.read_clock		  = otx2_nix_read_clock,
>  };
> 
>  static inline int
> diff --git a/drivers/net/octeontx2/otx2_ethdev.h
> b/drivers/net/octeontx2/otx2_ethdev.h
> index 863d4877f..a2bd0ffcf 100644
> --- a/drivers/net/octeontx2/otx2_ethdev.h
> +++ b/drivers/net/octeontx2/otx2_ethdev.h
> @@ -300,6 +300,8 @@ struct otx2_eth_dev {
>  	struct rte_timecounter  systime_tc;
>  	struct rte_timecounter  rx_tstamp_tc;
>  	struct rte_timecounter  tx_tstamp_tc;
> +	double clk_freq_mult;
> +	uint64_t clk_delta;
>  } __rte_cache_aligned;
> 
>  struct otx2_eth_txq {
> @@ -527,5 +529,7 @@ int otx2_nix_timesync_write_time(struct
> rte_eth_dev *eth_dev,  int otx2_nix_timesync_read_time(struct
> rte_eth_dev *eth_dev,
>  				struct timespec *ts);
>  int otx2_eth_dev_ptp_info_update(struct otx2_dev *dev, bool ptp_en);
> +int otx2_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *time);
> +int otx2_nix_raw_clock_rdtsc_conv(struct otx2_eth_dev *dev);

s/rdtsc/tsc

> 
>  #endif /* __OTX2_ETHDEV_H__ */
> diff --git a/drivers/net/octeontx2/otx2_ptp.c
> b/drivers/net/octeontx2/otx2_ptp.c
> index 0186c629a..3f54cfeaf 100644
> --- a/drivers/net/octeontx2/otx2_ptp.c
> +++ b/drivers/net/octeontx2/otx2_ptp.c
> @@ -224,6 +224,13 @@ otx2_nix_timesync_adjust_time(struct rte_eth_dev
> *eth_dev, int64_t delta)
>  		rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
>  		if (rc)
>  			return rc;
> +		/* Since the frequency of PTP comp register is tuned, delta
> and
> +		 * freq mult calculation for deriving PTP_HI from rdtsc should
> +		 * be done again.
> +		 */
> +		rc = otx2_nix_raw_clock_rdtsc_conv(dev);
s/rdtsc/tsc
> +		if (rc)
> +			otx2_err("Failed to calculate delta and freq mult");
>  	}
>  	dev->systime_tc.nsec += delta;
>  	dev->rx_tstamp_tc.nsec += delta;
> @@ -271,3 +278,26 @@ otx2_nix_timesync_read_time(struct rte_eth_dev
> *eth_dev, struct timespec *ts)
> 
>  	return 0;
>  }
> +
> +
> +int
> +otx2_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *clock) {
> +	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
> +
> +	if (!otx2_ethdev_is_ptp_en(dev)) {
> +		otx2_err("PTP should be enabled.");
> +		return -EINVAL;
> +	}
> +
> +	/* This API returns the raw PTP HI clock value. Since LFs doesn't
> +	 * have direct access to PTP registers and it requires mbox msg
> +	 * to AF for this value. In fastpath reading this value for every
> +	 * packet (which involes mbox call) becomes very expensive, hence
> +	 * we should be able to derive PTP HI clock value from rdtsc by
> +	 * using freq_mult and clk_delta calculated during configure stage.
> +	 */
> +	*clock = (rte_rdtsc() + dev->clk_delta) * dev->clk_freq_mult;

s/rte_rdtsc /rte_get_tsc_cycles/g

> +
> +	return 0;
> +}
> --
> 2.18.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [PATCH v2 1/2] net/octeontx2: fix ptp performance issue
  2019-07-27 15:48   ` Jerin Jacob Kollanukkaran
@ 2019-07-27 20:41     ` Harman Kalra
  2019-07-27 20:41       ` [dpdk-dev] [PATCH v2 2/2] net/octeontx2: support read clock API Harman Kalra
  0 siblings, 1 reply; 11+ messages in thread
From: Harman Kalra @ 2019-07-27 20:41 UTC (permalink / raw)
  To: Pavan Nikhilesh Bhagavatula, Jerin Jacob Kollanukkaran,
	Nithin Kumar Dabilpuram, Kiran Kumar Kokkilagadda
  Cc: dev, Harman Kalra

A huge drop in per core MPPS value was observed when PTP stack is
enabled. The reason behind the bottleneck is HW serialises the
transfer of all SQEs, which seeks timestamp capture, on the same
send DMA path. Hence only those packets which requires timestamp
capture should set SETTSTAMP in send mem alg.
With this patch timestamping would be done only for those packets
with PKT_TX_IEEE1588_TMST set.

Fixes: fb3ae0951abd ("net/octeontx2: support Tx")
Fixes: 8980a153006b ("event/octeontx2: support PTP for SSO")

Signed-off-by: Harman Kalra <hkalra@marvell.com>
---
 drivers/event/octeontx2/otx2_evdev.h       |  7 ++++++-
 drivers/event/octeontx2/otx2_worker.h      | 10 +++++++--
 drivers/event/octeontx2/otx2_worker_dual.h | 14 +++++++++++--
 drivers/net/octeontx2/otx2_ethdev.c        |  2 --
 drivers/net/octeontx2/otx2_rx.c            |  3 ++-
 drivers/net/octeontx2/otx2_rx.h            | 24 +++++++++++++---------
 drivers/net/octeontx2/otx2_tx.h            | 19 +++++++++++++----
 7 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/drivers/event/octeontx2/otx2_evdev.h b/drivers/event/octeontx2/otx2_evdev.h
index 9c9718f6f..5cd80e3b2 100644
--- a/drivers/event/octeontx2/otx2_evdev.h
+++ b/drivers/event/octeontx2/otx2_evdev.h
@@ -25,6 +25,7 @@
 #define OTX2_SSO_SQB_LIMIT                  (0x180)
 #define OTX2_SSO_XAQ_SLACK                  (8)
 #define OTX2_SSO_XAQ_CACHE_CNT              (0x7)
+#define OTX2_SSO_WQE_SG_PTR                 (9)
 
 /* SSO LF register offsets (BAR2) */
 #define SSO_LF_GGRP_OP_ADD_WORK0            (0x0ull)
@@ -222,10 +223,14 @@ otx2_wqe_to_mbuf(uint64_t get_work1, const uint64_t mbuf, uint8_t port_id,
 		 const void * const lookup_mem)
 {
 	struct nix_wqe_hdr_s *wqe = (struct nix_wqe_hdr_s *)get_work1;
+	uint64_t val = mbuf_init.value | (uint64_t)port_id << 48;
+
+	if (flags & NIX_RX_OFFLOAD_TSTAMP_F)
+		val |= NIX_TIMESYNC_RX_OFFSET;
 
 	otx2_nix_cqe_to_mbuf((struct nix_cqe_hdr_s *)wqe, tag,
 			     (struct rte_mbuf *)mbuf, lookup_mem,
-			     mbuf_init.value | (uint64_t)port_id << 48, flags);
+			      val, flags);
 
 }
 
diff --git a/drivers/event/octeontx2/otx2_worker.h b/drivers/event/octeontx2/otx2_worker.h
index 3c847d223..76f91bb59 100644
--- a/drivers/event/octeontx2/otx2_worker.h
+++ b/drivers/event/octeontx2/otx2_worker.h
@@ -18,6 +18,7 @@ otx2_ssogws_get_work(struct otx2_ssogws *ws, struct rte_event *ev,
 		     const uint32_t flags, const void * const lookup_mem)
 {
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -69,8 +70,10 @@ otx2_ssogws_get_work(struct otx2_ssogws *ws, struct rte_event *ev,
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, lookup_mem);
 		/* Extracting tstamp, if PTP enabled*/
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
 		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, ws->tstamp,
-					flags);
+					flags, (uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
@@ -86,6 +89,7 @@ otx2_ssogws_get_work_empty(struct otx2_ssogws *ws, struct rte_event *ev,
 			   const uint32_t flags)
 {
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -131,8 +135,10 @@ otx2_ssogws_get_work_empty(struct otx2_ssogws *ws, struct rte_event *ev,
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, NULL);
 		/* Extracting tstamp, if PTP enabled*/
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
 		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, ws->tstamp,
-					flags);
+					flags, (uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
diff --git a/drivers/event/octeontx2/otx2_worker_dual.h b/drivers/event/octeontx2/otx2_worker_dual.h
index 4a72f424d..5134e3d52 100644
--- a/drivers/event/octeontx2/otx2_worker_dual.h
+++ b/drivers/event/octeontx2/otx2_worker_dual.h
@@ -21,6 +21,7 @@ otx2_ssogws_dual_get_work(struct otx2_ssogws_state *ws,
 {
 	const uint64_t set_gw = BIT_ULL(16) | 1;
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -70,8 +71,17 @@ otx2_ssogws_dual_get_work(struct otx2_ssogws_state *ws,
 	    event.event_type == RTE_EVENT_TYPE_ETHDEV) {
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, lookup_mem);
-		/* Extracting tstamp, if PTP enabled*/
-		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, tstamp, flags);
+		/* Extracting tstamp, if PTP enabled. CGX will prepend the
+		 * timestamp at starting of packet data and it can be derieved
+		 * from WQE 9 dword which corresponds to SG iova.
+		 * rte_pktmbuf_mtod_offset can be used for this purpose but it
+		 * brings down the performance as it reads mbuf->buf_addr which
+		 * is not part of cache in general fast path.
+		 */
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
+		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, tstamp, flags,
+					(uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
diff --git a/drivers/net/octeontx2/otx2_ethdev.c b/drivers/net/octeontx2/otx2_ethdev.c
index b018b25b7..595c8003a 100644
--- a/drivers/net/octeontx2/otx2_ethdev.c
+++ b/drivers/net/octeontx2/otx2_ethdev.c
@@ -874,8 +874,6 @@ otx2_nix_form_default_desc(struct otx2_eth_txq *txq)
 			send_mem = (struct nix_send_mem_s *)(txq->cmd +
 						(send_hdr->w0.sizem1 << 1));
 			send_mem->subdc = NIX_SUBDC_MEM;
-			send_mem->dsz = 0x0;
-			send_mem->wmem = 0x1;
 			send_mem->alg = NIX_SENDMEMALG_SETTSTMP;
 			send_mem->addr = txq->dev->tstamp.tx_tstamp_iova;
 		}
diff --git a/drivers/net/octeontx2/otx2_rx.c b/drivers/net/octeontx2/otx2_rx.c
index deefe9588..701efc858 100644
--- a/drivers/net/octeontx2/otx2_rx.c
+++ b/drivers/net/octeontx2/otx2_rx.c
@@ -68,7 +68,8 @@ nix_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 
 		otx2_nix_cqe_to_mbuf(cq, cq->tag, mbuf, lookup_mem, mbuf_init,
 				     flags);
-		otx2_nix_mbuf_to_tstamp(mbuf, rxq->tstamp, flags);
+		otx2_nix_mbuf_to_tstamp(mbuf, rxq->tstamp, flags,
+				(uint64_t *)((uint8_t *)mbuf + data_off));
 		rx_pkts[packets++] = mbuf;
 		otx2_prefetch_store_keep(mbuf);
 		head++;
diff --git a/drivers/net/octeontx2/otx2_rx.h b/drivers/net/octeontx2/otx2_rx.h
index e150f38d7..d12e8b809 100644
--- a/drivers/net/octeontx2/otx2_rx.h
+++ b/drivers/net/octeontx2/otx2_rx.h
@@ -50,22 +50,26 @@ union mbuf_initializer {
 
 static __rte_always_inline void
 otx2_nix_mbuf_to_tstamp(struct rte_mbuf *mbuf,
-			struct otx2_timesync_info *tstamp, const uint16_t flag)
+			struct otx2_timesync_info *tstamp, const uint16_t flag,
+			uint64_t *tstamp_ptr)
 {
 	if ((flag & NIX_RX_OFFLOAD_TSTAMP_F) &&
-	    mbuf->packet_type == RTE_PTYPE_L2_ETHER_TIMESYNC &&
 	    (mbuf->data_off == RTE_PKTMBUF_HEADROOM +
 	     NIX_TIMESYNC_RX_OFFSET)) {
-		uint64_t *tstamp_ptr;
 
-		/* Deal with rx timestamp */
-		tstamp_ptr = rte_pktmbuf_mtod_offset(mbuf, uint64_t *,
-						     -NIX_TIMESYNC_RX_OFFSET);
+		/* Reading the rx timestamp inserted by CGX, viz at
+		 * starting of the packet data.
+		 */
 		mbuf->timestamp = rte_be_to_cpu_64(*tstamp_ptr);
-		tstamp->rx_tstamp = mbuf->timestamp;
-		tstamp->rx_ready = 1;
-		mbuf->ol_flags |= PKT_RX_IEEE1588_PTP | PKT_RX_IEEE1588_TMST
-			| PKT_RX_TIMESTAMP;
+		/* PKT_RX_IEEE1588_TMST flag needs to be set only in case
+		 * PTP packets are received.
+		 */
+		if (mbuf->packet_type == RTE_PTYPE_L2_ETHER_TIMESYNC) {
+			tstamp->rx_tstamp = mbuf->timestamp;
+			tstamp->rx_ready = 1;
+			mbuf->ol_flags |= PKT_RX_IEEE1588_PTP |
+				PKT_RX_IEEE1588_TMST | PKT_RX_TIMESTAMP;
+		}
 	}
 }
 
diff --git a/drivers/net/octeontx2/otx2_tx.h b/drivers/net/octeontx2/otx2_tx.h
index b75a220ea..494ba3884 100644
--- a/drivers/net/octeontx2/otx2_tx.h
+++ b/drivers/net/octeontx2/otx2_tx.h
@@ -43,18 +43,29 @@ otx2_nix_xmit_prepare_tstamp(uint64_t *cmd,  const uint64_t *send_mem_desc,
 	if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
 		struct nix_send_mem_s *send_mem;
 		uint16_t off = (no_segdw - 1) << 1;
+		const uint8_t is_ol_tstamp = !(ol_flags & PKT_TX_IEEE1588_TMST);
 
 		send_mem = (struct nix_send_mem_s *)(cmd + off);
-		if (flags & NIX_TX_MULTI_SEG_F)
+		if (flags & NIX_TX_MULTI_SEG_F) {
 			/* Retrieving the default desc values */
 			cmd[off] = send_mem_desc[6];
 
+			/* Using compiler barier to avoid voilation of C
+			 * aliasing rules.
+			 */
+			rte_compiler_barrier();
+		}
+
 		/* Packets for which PKT_TX_IEEE1588_TMST is not set, tx tstamp
-		 * should not be updated at tx tstamp registered address, rather
-		 * a dummy address which is eight bytes ahead would be updated
+		 * should not be recorded, hence changing the alg type to
+		 * NIX_SENDMEMALG_SET and also changing send mem addr field to
+		 * next 8 bytes as it corrpt the actual tx tstamp registered
+		 * address.
 		 */
+		send_mem->alg = NIX_SENDMEMALG_SETTSTMP - (is_ol_tstamp);
+
 		send_mem->addr = (rte_iova_t)((uint64_t *)send_mem_desc[7] +
-				!(ol_flags & PKT_TX_IEEE1588_TMST));
+					      (is_ol_tstamp));
 	}
 }
 
-- 
2.18.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [PATCH v2 2/2] net/octeontx2: support read clock API
  2019-07-27 20:41     ` [dpdk-dev] [PATCH v2 1/2] net/octeontx2: fix ptp performance issue Harman Kalra
@ 2019-07-27 20:41       ` Harman Kalra
  2019-07-28  7:43         ` Jerin Jacob Kollanukkaran
  0 siblings, 1 reply; 11+ messages in thread
From: Harman Kalra @ 2019-07-27 20:41 UTC (permalink / raw)
  To: Jerin Jacob Kollanukkaran, Nithin Kumar Dabilpuram,
	Vamsi Krishna Attunuru, Kiran Kumar Kokkilagadda
  Cc: dev, Harman Kalra

This patch implements read clock api whose purpose is to return
raw clock ticks. Using this API real time ticks spent in
processing a packet can be known:
    <read_clock val at any time> - mbuf->timestamp

Calling mbox for reading raw clock ticks in fastpath is very
expensive so its value is derived from time stamp counter(tsc)
using freq multipler (ratio of raw clock ticks and tsc) and clock
delta (by how much tsc is lagging from raw clock value).

Signed-off-by: Harman Kalra <hkalra@marvell.com>
---
V2:
* More detailed commit message
* changed rdtsc to tsc (timestamp counter)
* Initialized a variable to zero only when needed
* changed done label to fail

 drivers/common/octeontx2/otx2_mbox.h |  2 +
 drivers/net/octeontx2/otx2_ethdev.c  | 89 ++++++++++++++++++++++++++++
 drivers/net/octeontx2/otx2_ethdev.h  |  4 ++
 drivers/net/octeontx2/otx2_ptp.c     | 30 ++++++++++
 4 files changed, 125 insertions(+)

diff --git a/drivers/common/octeontx2/otx2_mbox.h b/drivers/common/octeontx2/otx2_mbox.h
index c0bb676b2..b2c59c86e 100644
--- a/drivers/common/octeontx2/otx2_mbox.h
+++ b/drivers/common/octeontx2/otx2_mbox.h
@@ -1354,11 +1354,13 @@ struct ptp_req {
 	struct mbox_msghdr hdr;
 	uint8_t __otx2_io op;
 	int64_t __otx2_io scaled_ppm;
+	uint8_t __otx2_io is_pmu;
 };
 
 struct ptp_rsp {
 	struct mbox_msghdr hdr;
 	uint64_t __otx2_io clk;
+	uint64_t __otx2_io tsc;
 };
 
 struct get_hw_cap_rsp {
diff --git a/drivers/net/octeontx2/otx2_ethdev.c b/drivers/net/octeontx2/otx2_ethdev.c
index 595c8003a..ddbce945d 100644
--- a/drivers/net/octeontx2/otx2_ethdev.c
+++ b/drivers/net/octeontx2/otx2_ethdev.c
@@ -521,6 +521,19 @@ otx2_nix_rx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t rq,
 
 	eth_dev->data->rx_queues[rq] = rxq;
 	eth_dev->data->rx_queue_state[rq] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+	/* Calculating delta and freq mult between PTP HI clock and tsc.
+	 * These are needed for deriving PTP HI clock value from tsc counter.
+	 */
+	if ((dev->rx_offloads & DEV_RX_OFFLOAD_TIMESTAMP) ||
+	    otx2_ethdev_is_ptp_en(dev)) {
+		rc = otx2_nix_raw_clock_tsc_conv(dev);
+		if (rc) {
+			otx2_err("Failed to calculate delta and freq mult");
+			goto fail;
+		}
+	}
+
 	return 0;
 
 free_rxq:
@@ -1186,6 +1199,81 @@ nix_set_nop_rxtx_function(struct rte_eth_dev *eth_dev)
 	rte_mb();
 }
 
+static int
+nix_read_raw_clock(struct otx2_eth_dev *dev, uint64_t *clock, uint64_t *tsc,
+		   uint8_t is_pmu)
+{
+	struct otx2_mbox *mbox = dev->mbox;
+	struct ptp_req *req;
+	struct ptp_rsp *rsp;
+	int rc;
+
+	req = otx2_mbox_alloc_msg_ptp_op(mbox);
+	req->op = PTP_OP_GET_CLOCK;
+	req->is_pmu = is_pmu;
+	rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
+	if (rc)
+		goto fail;
+
+	if (clock)
+		*clock = rsp->clk;
+	if (tsc)
+		*tsc = rsp->tsc;
+
+fail:
+	return rc;
+}
+
+/* This function calculates two parameters "clk_freq_mult" and
+ * "clk_delta" which is useful in deriving PTP HI clock from
+ * timestamp counter (tsc) value.
+ */
+int
+otx2_nix_raw_clock_tsc_conv(struct otx2_eth_dev *dev)
+{
+	uint64_t ticks_base = 0, ticks = 0, tsc = 0, t_freq;
+	int rc, val;
+
+	/* Calculating the frequency at which PTP HI clock is running */
+	rc = nix_read_raw_clock(dev, &ticks_base, &tsc, false);
+	if (rc) {
+		otx2_err("Failed to read the raw clock value: %d", rc);
+		goto fail;
+	}
+
+	rte_delay_ms(100);
+
+	rc = nix_read_raw_clock(dev, &ticks, &tsc, false);
+	if (rc) {
+		otx2_err("Failed to read the raw clock value: %d", rc);
+		goto fail;
+	}
+
+	t_freq = (ticks - ticks_base) * 10;
+
+	/* Calculating the freq multiplier viz the ratio between the
+	 * frequency at which PTP HI clock works and tsc clock runs
+	 */
+	dev->clk_freq_mult =
+		(double)pow(10, floor(log10(t_freq))) / rte_get_timer_hz();
+
+	val = false;
+#ifdef RTE_ARM_EAL_RDTSC_USE_PMU
+	val = true;
+#endif
+	rc = nix_read_raw_clock(dev, &ticks, &tsc, val);
+	if (rc) {
+		otx2_err("Failed to read the raw clock value: %d", rc);
+		goto fail;
+	}
+
+	/* Calculating delta between PTP HI clock and tsc */
+	dev->clk_delta = ((uint64_t)(ticks / dev->clk_freq_mult) - tsc);
+
+fail:
+	return rc;
+}
+
 static int
 otx2_nix_configure(struct rte_eth_dev *eth_dev)
 {
@@ -1649,6 +1737,7 @@ static const struct eth_dev_ops otx2_eth_dev_ops = {
 	.vlan_pvid_set		  = otx2_nix_vlan_pvid_set,
 	.rx_queue_intr_enable	  = otx2_nix_rx_queue_intr_enable,
 	.rx_queue_intr_disable	  = otx2_nix_rx_queue_intr_disable,
+	.read_clock		  = otx2_nix_read_clock,
 };
 
 static inline int
diff --git a/drivers/net/octeontx2/otx2_ethdev.h b/drivers/net/octeontx2/otx2_ethdev.h
index 863d4877f..ef2ff762d 100644
--- a/drivers/net/octeontx2/otx2_ethdev.h
+++ b/drivers/net/octeontx2/otx2_ethdev.h
@@ -300,6 +300,8 @@ struct otx2_eth_dev {
 	struct rte_timecounter  systime_tc;
 	struct rte_timecounter  rx_tstamp_tc;
 	struct rte_timecounter  tx_tstamp_tc;
+	double clk_freq_mult;
+	uint64_t clk_delta;
 } __rte_cache_aligned;
 
 struct otx2_eth_txq {
@@ -527,5 +529,7 @@ int otx2_nix_timesync_write_time(struct rte_eth_dev *eth_dev,
 int otx2_nix_timesync_read_time(struct rte_eth_dev *eth_dev,
 				struct timespec *ts);
 int otx2_eth_dev_ptp_info_update(struct otx2_dev *dev, bool ptp_en);
+int otx2_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *time);
+int otx2_nix_raw_clock_tsc_conv(struct otx2_eth_dev *dev);
 
 #endif /* __OTX2_ETHDEV_H__ */
diff --git a/drivers/net/octeontx2/otx2_ptp.c b/drivers/net/octeontx2/otx2_ptp.c
index 0186c629a..7b24c6644 100644
--- a/drivers/net/octeontx2/otx2_ptp.c
+++ b/drivers/net/octeontx2/otx2_ptp.c
@@ -224,6 +224,13 @@ otx2_nix_timesync_adjust_time(struct rte_eth_dev *eth_dev, int64_t delta)
 		rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
 		if (rc)
 			return rc;
+		/* Since the frequency of PTP comp register is tuned, delta and
+		 * freq mult calculation for deriving PTP_HI from timestamp
+		 * counter should be done again.
+		 */
+		rc = otx2_nix_raw_clock_tsc_conv(dev);
+		if (rc)
+			otx2_err("Failed to calculate delta and freq mult");
 	}
 	dev->systime_tc.nsec += delta;
 	dev->rx_tstamp_tc.nsec += delta;
@@ -271,3 +278,26 @@ otx2_nix_timesync_read_time(struct rte_eth_dev *eth_dev, struct timespec *ts)
 
 	return 0;
 }
+
+
+int
+otx2_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *clock)
+{
+	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+
+	if (!otx2_ethdev_is_ptp_en(dev)) {
+		otx2_err("PTP should be enabled.");
+		return -EINVAL;
+	}
+
+	/* This API returns the raw PTP HI clock value. Since LFs doesn't
+	 * have direct access to PTP registers and it requires mbox msg
+	 * to AF for this value. In fastpath reading this value for every
+	 * packet (which involes mbox call) becomes very expensive, hence
+	 * we should be able to derive PTP HI clock value from tsc by
+	 * using freq_mult and clk_delta calculated during configure stage.
+	 */
+	*clock = (rte_get_tsc_cycles() + dev->clk_delta) * dev->clk_freq_mult;
+
+	return 0;
+}
-- 
2.18.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [dpdk-dev] [PATCH v2 2/2] net/octeontx2: support read clock API
  2019-07-27 20:41       ` [dpdk-dev] [PATCH v2 2/2] net/octeontx2: support read clock API Harman Kalra
@ 2019-07-28  7:43         ` Jerin Jacob Kollanukkaran
  2019-07-28  9:09           ` [dpdk-dev] [PATCH v3 1/2] net/octeontx2: fix ptp performance issue Harman Kalra
  0 siblings, 1 reply; 11+ messages in thread
From: Jerin Jacob Kollanukkaran @ 2019-07-28  7:43 UTC (permalink / raw)
  To: Harman Kalra, Nithin Kumar Dabilpuram, Vamsi Krishna Attunuru,
	Kiran Kumar Kokkilagadda
  Cc: dev

> -----Original Message-----
> From: Harman Kalra <hkalra@marvell.com>
> Sent: Sunday, July 28, 2019 2:11 AM
> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Nithin Kumar Dabilpuram
> <ndabilpuram@marvell.com>; Vamsi Krishna Attunuru
> <vattunuru@marvell.com>; Kiran Kumar Kokkilagadda
> <kirankumark@marvell.com>
> Cc: dev@dpdk.org; Harman Kalra <hkalra@marvell.com>
> Subject: [PATCH v2 2/2] net/octeontx2: support read clock API
> 
> This patch implements read clock api whose purpose is to return raw clock ticks.
> Using this API real time ticks spent in processing a packet can be known:
>     <read_clock val at any time> - mbuf->timestamp
> 
> Calling mbox for reading raw clock ticks in fastpath is very expensive so its value
> is derived from time stamp counter(tsc) using freq multipler (ratio of raw clock
> ticks and tsc) and clock delta (by how much tsc is lagging from raw clock value).
> 
> Signed-off-by: Harman Kalra <hkalra@marvell.com>
> ---
> V2:
> * More detailed commit message
> * changed rdtsc to tsc (timestamp counter)
> * Initialized a variable to zero only when needed
> * changed done label to fail
> 
>  drivers/common/octeontx2/otx2_mbox.h |  2 +
> drivers/net/octeontx2/otx2_ethdev.c  | 89 ++++++++++++++++++++++++++++

Move as much changes to otx2_ptp.c, rest it looks good to me.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [PATCH v3 1/2] net/octeontx2: fix ptp performance issue
  2019-07-28  7:43         ` Jerin Jacob Kollanukkaran
@ 2019-07-28  9:09           ` Harman Kalra
  2019-07-28  9:09             ` [dpdk-dev] [PATCH v3 2/2] net/octeontx2: support read clock API Harman Kalra
  2019-07-28 16:52             ` [dpdk-dev] [PATCH v3 1/2] net/octeontx2: fix ptp performance issue Jerin Jacob Kollanukkaran
  0 siblings, 2 replies; 11+ messages in thread
From: Harman Kalra @ 2019-07-28  9:09 UTC (permalink / raw)
  To: Pavan Nikhilesh Bhagavatula, Jerin Jacob Kollanukkaran,
	Nithin Kumar Dabilpuram, Kiran Kumar Kokkilagadda
  Cc: dev, Harman Kalra

A huge drop in per core MPPS value was observed when PTP stack is
enabled. The reason behind the bottleneck is HW serialises the
transfer of all SQEs, which seeks timestamp capture, on the same
send DMA path. Hence only those packets which requires timestamp
capture should set SETTSTAMP in send mem alg.
With this patch timestamping would be done only for those packets
with PKT_TX_IEEE1588_TMST set.

Fixes: fb3ae0951abd ("net/octeontx2: support Tx")
Fixes: 8980a153006b ("event/octeontx2: support PTP for SSO")

Signed-off-by: Harman Kalra <hkalra@marvell.com>
---
 drivers/event/octeontx2/otx2_evdev.h       |  7 ++++++-
 drivers/event/octeontx2/otx2_worker.h      | 10 +++++++--
 drivers/event/octeontx2/otx2_worker_dual.h | 14 +++++++++++--
 drivers/net/octeontx2/otx2_ethdev.c        |  2 --
 drivers/net/octeontx2/otx2_rx.c            |  3 ++-
 drivers/net/octeontx2/otx2_rx.h            | 24 +++++++++++++---------
 drivers/net/octeontx2/otx2_tx.h            | 19 +++++++++++++----
 7 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/drivers/event/octeontx2/otx2_evdev.h b/drivers/event/octeontx2/otx2_evdev.h
index 9c9718f6f..5cd80e3b2 100644
--- a/drivers/event/octeontx2/otx2_evdev.h
+++ b/drivers/event/octeontx2/otx2_evdev.h
@@ -25,6 +25,7 @@
 #define OTX2_SSO_SQB_LIMIT                  (0x180)
 #define OTX2_SSO_XAQ_SLACK                  (8)
 #define OTX2_SSO_XAQ_CACHE_CNT              (0x7)
+#define OTX2_SSO_WQE_SG_PTR                 (9)
 
 /* SSO LF register offsets (BAR2) */
 #define SSO_LF_GGRP_OP_ADD_WORK0            (0x0ull)
@@ -222,10 +223,14 @@ otx2_wqe_to_mbuf(uint64_t get_work1, const uint64_t mbuf, uint8_t port_id,
 		 const void * const lookup_mem)
 {
 	struct nix_wqe_hdr_s *wqe = (struct nix_wqe_hdr_s *)get_work1;
+	uint64_t val = mbuf_init.value | (uint64_t)port_id << 48;
+
+	if (flags & NIX_RX_OFFLOAD_TSTAMP_F)
+		val |= NIX_TIMESYNC_RX_OFFSET;
 
 	otx2_nix_cqe_to_mbuf((struct nix_cqe_hdr_s *)wqe, tag,
 			     (struct rte_mbuf *)mbuf, lookup_mem,
-			     mbuf_init.value | (uint64_t)port_id << 48, flags);
+			      val, flags);
 
 }
 
diff --git a/drivers/event/octeontx2/otx2_worker.h b/drivers/event/octeontx2/otx2_worker.h
index 3c847d223..76f91bb59 100644
--- a/drivers/event/octeontx2/otx2_worker.h
+++ b/drivers/event/octeontx2/otx2_worker.h
@@ -18,6 +18,7 @@ otx2_ssogws_get_work(struct otx2_ssogws *ws, struct rte_event *ev,
 		     const uint32_t flags, const void * const lookup_mem)
 {
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -69,8 +70,10 @@ otx2_ssogws_get_work(struct otx2_ssogws *ws, struct rte_event *ev,
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, lookup_mem);
 		/* Extracting tstamp, if PTP enabled*/
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
 		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, ws->tstamp,
-					flags);
+					flags, (uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
@@ -86,6 +89,7 @@ otx2_ssogws_get_work_empty(struct otx2_ssogws *ws, struct rte_event *ev,
 			   const uint32_t flags)
 {
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -131,8 +135,10 @@ otx2_ssogws_get_work_empty(struct otx2_ssogws *ws, struct rte_event *ev,
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, NULL);
 		/* Extracting tstamp, if PTP enabled*/
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
 		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, ws->tstamp,
-					flags);
+					flags, (uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
diff --git a/drivers/event/octeontx2/otx2_worker_dual.h b/drivers/event/octeontx2/otx2_worker_dual.h
index 4a72f424d..5134e3d52 100644
--- a/drivers/event/octeontx2/otx2_worker_dual.h
+++ b/drivers/event/octeontx2/otx2_worker_dual.h
@@ -21,6 +21,7 @@ otx2_ssogws_dual_get_work(struct otx2_ssogws_state *ws,
 {
 	const uint64_t set_gw = BIT_ULL(16) | 1;
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -70,8 +71,17 @@ otx2_ssogws_dual_get_work(struct otx2_ssogws_state *ws,
 	    event.event_type == RTE_EVENT_TYPE_ETHDEV) {
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, lookup_mem);
-		/* Extracting tstamp, if PTP enabled*/
-		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, tstamp, flags);
+		/* Extracting tstamp, if PTP enabled. CGX will prepend the
+		 * timestamp at starting of packet data and it can be derieved
+		 * from WQE 9 dword which corresponds to SG iova.
+		 * rte_pktmbuf_mtod_offset can be used for this purpose but it
+		 * brings down the performance as it reads mbuf->buf_addr which
+		 * is not part of cache in general fast path.
+		 */
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
+		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, tstamp, flags,
+					(uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
diff --git a/drivers/net/octeontx2/otx2_ethdev.c b/drivers/net/octeontx2/otx2_ethdev.c
index b018b25b7..595c8003a 100644
--- a/drivers/net/octeontx2/otx2_ethdev.c
+++ b/drivers/net/octeontx2/otx2_ethdev.c
@@ -874,8 +874,6 @@ otx2_nix_form_default_desc(struct otx2_eth_txq *txq)
 			send_mem = (struct nix_send_mem_s *)(txq->cmd +
 						(send_hdr->w0.sizem1 << 1));
 			send_mem->subdc = NIX_SUBDC_MEM;
-			send_mem->dsz = 0x0;
-			send_mem->wmem = 0x1;
 			send_mem->alg = NIX_SENDMEMALG_SETTSTMP;
 			send_mem->addr = txq->dev->tstamp.tx_tstamp_iova;
 		}
diff --git a/drivers/net/octeontx2/otx2_rx.c b/drivers/net/octeontx2/otx2_rx.c
index deefe9588..701efc858 100644
--- a/drivers/net/octeontx2/otx2_rx.c
+++ b/drivers/net/octeontx2/otx2_rx.c
@@ -68,7 +68,8 @@ nix_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 
 		otx2_nix_cqe_to_mbuf(cq, cq->tag, mbuf, lookup_mem, mbuf_init,
 				     flags);
-		otx2_nix_mbuf_to_tstamp(mbuf, rxq->tstamp, flags);
+		otx2_nix_mbuf_to_tstamp(mbuf, rxq->tstamp, flags,
+				(uint64_t *)((uint8_t *)mbuf + data_off));
 		rx_pkts[packets++] = mbuf;
 		otx2_prefetch_store_keep(mbuf);
 		head++;
diff --git a/drivers/net/octeontx2/otx2_rx.h b/drivers/net/octeontx2/otx2_rx.h
index e150f38d7..d12e8b809 100644
--- a/drivers/net/octeontx2/otx2_rx.h
+++ b/drivers/net/octeontx2/otx2_rx.h
@@ -50,22 +50,26 @@ union mbuf_initializer {
 
 static __rte_always_inline void
 otx2_nix_mbuf_to_tstamp(struct rte_mbuf *mbuf,
-			struct otx2_timesync_info *tstamp, const uint16_t flag)
+			struct otx2_timesync_info *tstamp, const uint16_t flag,
+			uint64_t *tstamp_ptr)
 {
 	if ((flag & NIX_RX_OFFLOAD_TSTAMP_F) &&
-	    mbuf->packet_type == RTE_PTYPE_L2_ETHER_TIMESYNC &&
 	    (mbuf->data_off == RTE_PKTMBUF_HEADROOM +
 	     NIX_TIMESYNC_RX_OFFSET)) {
-		uint64_t *tstamp_ptr;
 
-		/* Deal with rx timestamp */
-		tstamp_ptr = rte_pktmbuf_mtod_offset(mbuf, uint64_t *,
-						     -NIX_TIMESYNC_RX_OFFSET);
+		/* Reading the rx timestamp inserted by CGX, viz at
+		 * starting of the packet data.
+		 */
 		mbuf->timestamp = rte_be_to_cpu_64(*tstamp_ptr);
-		tstamp->rx_tstamp = mbuf->timestamp;
-		tstamp->rx_ready = 1;
-		mbuf->ol_flags |= PKT_RX_IEEE1588_PTP | PKT_RX_IEEE1588_TMST
-			| PKT_RX_TIMESTAMP;
+		/* PKT_RX_IEEE1588_TMST flag needs to be set only in case
+		 * PTP packets are received.
+		 */
+		if (mbuf->packet_type == RTE_PTYPE_L2_ETHER_TIMESYNC) {
+			tstamp->rx_tstamp = mbuf->timestamp;
+			tstamp->rx_ready = 1;
+			mbuf->ol_flags |= PKT_RX_IEEE1588_PTP |
+				PKT_RX_IEEE1588_TMST | PKT_RX_TIMESTAMP;
+		}
 	}
 }
 
diff --git a/drivers/net/octeontx2/otx2_tx.h b/drivers/net/octeontx2/otx2_tx.h
index b75a220ea..494ba3884 100644
--- a/drivers/net/octeontx2/otx2_tx.h
+++ b/drivers/net/octeontx2/otx2_tx.h
@@ -43,18 +43,29 @@ otx2_nix_xmit_prepare_tstamp(uint64_t *cmd,  const uint64_t *send_mem_desc,
 	if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
 		struct nix_send_mem_s *send_mem;
 		uint16_t off = (no_segdw - 1) << 1;
+		const uint8_t is_ol_tstamp = !(ol_flags & PKT_TX_IEEE1588_TMST);
 
 		send_mem = (struct nix_send_mem_s *)(cmd + off);
-		if (flags & NIX_TX_MULTI_SEG_F)
+		if (flags & NIX_TX_MULTI_SEG_F) {
 			/* Retrieving the default desc values */
 			cmd[off] = send_mem_desc[6];
 
+			/* Using compiler barier to avoid voilation of C
+			 * aliasing rules.
+			 */
+			rte_compiler_barrier();
+		}
+
 		/* Packets for which PKT_TX_IEEE1588_TMST is not set, tx tstamp
-		 * should not be updated at tx tstamp registered address, rather
-		 * a dummy address which is eight bytes ahead would be updated
+		 * should not be recorded, hence changing the alg type to
+		 * NIX_SENDMEMALG_SET and also changing send mem addr field to
+		 * next 8 bytes as it corrpt the actual tx tstamp registered
+		 * address.
 		 */
+		send_mem->alg = NIX_SENDMEMALG_SETTSTMP - (is_ol_tstamp);
+
 		send_mem->addr = (rte_iova_t)((uint64_t *)send_mem_desc[7] +
-				!(ol_flags & PKT_TX_IEEE1588_TMST));
+					      (is_ol_tstamp));
 	}
 }
 
-- 
2.18.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [PATCH v3 2/2] net/octeontx2: support read clock API
  2019-07-28  9:09           ` [dpdk-dev] [PATCH v3 1/2] net/octeontx2: fix ptp performance issue Harman Kalra
@ 2019-07-28  9:09             ` Harman Kalra
  2019-07-28 16:52             ` [dpdk-dev] [PATCH v3 1/2] net/octeontx2: fix ptp performance issue Jerin Jacob Kollanukkaran
  1 sibling, 0 replies; 11+ messages in thread
From: Harman Kalra @ 2019-07-28  9:09 UTC (permalink / raw)
  To: Jerin Jacob Kollanukkaran, Nithin Kumar Dabilpuram,
	Vamsi Krishna Attunuru, Kiran Kumar Kokkilagadda
  Cc: dev, Harman Kalra

This patch implements read clock api whose purpose is to return
raw clock ticks. Using this API real time ticks spent in
processing a packet can be known:
    <read_clock val at any time> - mbuf->timestamp

Calling mbox for reading raw clock ticks in fastpath is very
expensive so its value is derived from time stamp counter(tsc)
using freq multipler (ratio of raw clock ticks and tsc) and clock
delta (by how much tsc is lagging from raw clock value).

Signed-off-by: Harman Kalra <hkalra@marvell.com>
---
V3:
* Moved most implementation in otx2_ptp.c keeping
otx2_ethdev.c cleaner.
* Removed ptp enable check in read_clock op fastpath.

V2:
* More detailed commit message
* changed rdtsc to tsc (timestamp counter)
* Initialized a variable to zero only when needed
* changed done label to fail

 drivers/common/octeontx2/otx2_mbox.h |   2 +
 drivers/net/octeontx2/otx2_ethdev.c  |  16 ++++-
 drivers/net/octeontx2/otx2_ethdev.h  |   5 ++
 drivers/net/octeontx2/otx2_ptp.c     | 100 +++++++++++++++++++++++++++
 4 files changed, 122 insertions(+), 1 deletion(-)

diff --git a/drivers/common/octeontx2/otx2_mbox.h b/drivers/common/octeontx2/otx2_mbox.h
index c0bb676b2..b2c59c86e 100644
--- a/drivers/common/octeontx2/otx2_mbox.h
+++ b/drivers/common/octeontx2/otx2_mbox.h
@@ -1354,11 +1354,13 @@ struct ptp_req {
 	struct mbox_msghdr hdr;
 	uint8_t __otx2_io op;
 	int64_t __otx2_io scaled_ppm;
+	uint8_t __otx2_io is_pmu;
 };
 
 struct ptp_rsp {
 	struct mbox_msghdr hdr;
 	uint64_t __otx2_io clk;
+	uint64_t __otx2_io tsc;
 };
 
 struct get_hw_cap_rsp {
diff --git a/drivers/net/octeontx2/otx2_ethdev.c b/drivers/net/octeontx2/otx2_ethdev.c
index 595c8003a..3fb7bd93f 100644
--- a/drivers/net/octeontx2/otx2_ethdev.c
+++ b/drivers/net/octeontx2/otx2_ethdev.c
@@ -3,7 +3,6 @@
  */
 
 #include <inttypes.h>
-#include <math.h>
 
 #include <rte_ethdev_pci.h>
 #include <rte_io.h>
@@ -521,6 +520,20 @@ otx2_nix_rx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t rq,
 
 	eth_dev->data->rx_queues[rq] = rxq;
 	eth_dev->data->rx_queue_state[rq] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+	/* Calculating delta and freq mult between PTP HI clock and tsc.
+	 * These are needed in deriving raw clock value from tsc counter.
+	 * read_clock eth op returns raw clock value.
+	 */
+	if ((dev->rx_offloads & DEV_RX_OFFLOAD_TIMESTAMP) ||
+	    otx2_ethdev_is_ptp_en(dev)) {
+		rc = otx2_nix_raw_clock_tsc_conv(dev);
+		if (rc) {
+			otx2_err("Failed to calculate delta and freq mult");
+			goto fail;
+		}
+	}
+
 	return 0;
 
 free_rxq:
@@ -1649,6 +1662,7 @@ static const struct eth_dev_ops otx2_eth_dev_ops = {
 	.vlan_pvid_set		  = otx2_nix_vlan_pvid_set,
 	.rx_queue_intr_enable	  = otx2_nix_rx_queue_intr_enable,
 	.rx_queue_intr_disable	  = otx2_nix_rx_queue_intr_disable,
+	.read_clock		  = otx2_nix_read_clock,
 };
 
 static inline int
diff --git a/drivers/net/octeontx2/otx2_ethdev.h b/drivers/net/octeontx2/otx2_ethdev.h
index 863d4877f..720386fd1 100644
--- a/drivers/net/octeontx2/otx2_ethdev.h
+++ b/drivers/net/octeontx2/otx2_ethdev.h
@@ -5,6 +5,7 @@
 #ifndef __OTX2_ETHDEV_H__
 #define __OTX2_ETHDEV_H__
 
+#include <math.h>
 #include <stdint.h>
 
 #include <rte_common.h>
@@ -300,6 +301,8 @@ struct otx2_eth_dev {
 	struct rte_timecounter  systime_tc;
 	struct rte_timecounter  rx_tstamp_tc;
 	struct rte_timecounter  tx_tstamp_tc;
+	double clk_freq_mult;
+	uint64_t clk_delta;
 } __rte_cache_aligned;
 
 struct otx2_eth_txq {
@@ -527,5 +530,7 @@ int otx2_nix_timesync_write_time(struct rte_eth_dev *eth_dev,
 int otx2_nix_timesync_read_time(struct rte_eth_dev *eth_dev,
 				struct timespec *ts);
 int otx2_eth_dev_ptp_info_update(struct otx2_dev *dev, bool ptp_en);
+int otx2_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *time);
+int otx2_nix_raw_clock_tsc_conv(struct otx2_eth_dev *dev);
 
 #endif /* __OTX2_ETHDEV_H__ */
diff --git a/drivers/net/octeontx2/otx2_ptp.c b/drivers/net/octeontx2/otx2_ptp.c
index 0186c629a..52e5456b5 100644
--- a/drivers/net/octeontx2/otx2_ptp.c
+++ b/drivers/net/octeontx2/otx2_ptp.c
@@ -8,6 +8,81 @@
 
 #define PTP_FREQ_ADJUST (1 << 9)
 
+static int
+nix_read_raw_clock(struct otx2_eth_dev *dev, uint64_t *clock, uint64_t *tsc,
+		   uint8_t is_pmu)
+{
+	struct otx2_mbox *mbox = dev->mbox;
+	struct ptp_req *req;
+	struct ptp_rsp *rsp;
+	int rc;
+
+	req = otx2_mbox_alloc_msg_ptp_op(mbox);
+	req->op = PTP_OP_GET_CLOCK;
+	req->is_pmu = is_pmu;
+	rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
+	if (rc)
+		goto fail;
+
+	if (clock)
+		*clock = rsp->clk;
+	if (tsc)
+		*tsc = rsp->tsc;
+
+fail:
+	return rc;
+}
+
+/* This function calculates two parameters "clk_freq_mult" and
+ * "clk_delta" which is useful in deriving PTP HI clock from
+ * timestamp counter (tsc) value.
+ */
+int
+otx2_nix_raw_clock_tsc_conv(struct otx2_eth_dev *dev)
+{
+	uint64_t ticks_base = 0, ticks = 0, tsc = 0, t_freq;
+	int rc, val;
+
+	/* Calculating the frequency at which PTP HI clock is running */
+	rc = nix_read_raw_clock(dev, &ticks_base, &tsc, false);
+	if (rc) {
+		otx2_err("Failed to read the raw clock value: %d", rc);
+		goto fail;
+	}
+
+	rte_delay_ms(100);
+
+	rc = nix_read_raw_clock(dev, &ticks, &tsc, false);
+	if (rc) {
+		otx2_err("Failed to read the raw clock value: %d", rc);
+		goto fail;
+	}
+
+	t_freq = (ticks - ticks_base) * 10;
+
+	/* Calculating the freq multiplier viz the ratio between the
+	 * frequency at which PTP HI clock works and tsc clock runs
+	 */
+	dev->clk_freq_mult =
+		(double)pow(10, floor(log10(t_freq))) / rte_get_timer_hz();
+
+	val = false;
+#ifdef RTE_ARM_EAL_RDTSC_USE_PMU
+	val = true;
+#endif
+	rc = nix_read_raw_clock(dev, &ticks, &tsc, val);
+	if (rc) {
+		otx2_err("Failed to read the raw clock value: %d", rc);
+		goto fail;
+	}
+
+	/* Calculating delta between PTP HI clock and tsc */
+	dev->clk_delta = ((uint64_t)(ticks / dev->clk_freq_mult) - tsc);
+
+fail:
+	return rc;
+}
+
 static void
 nix_start_timecounters(struct rte_eth_dev *eth_dev)
 {
@@ -224,6 +299,13 @@ otx2_nix_timesync_adjust_time(struct rte_eth_dev *eth_dev, int64_t delta)
 		rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
 		if (rc)
 			return rc;
+		/* Since the frequency of PTP comp register is tuned, delta and
+		 * freq mult calculation for deriving PTP_HI from timestamp
+		 * counter should be done again.
+		 */
+		rc = otx2_nix_raw_clock_tsc_conv(dev);
+		if (rc)
+			otx2_err("Failed to calculate delta and freq mult");
 	}
 	dev->systime_tc.nsec += delta;
 	dev->rx_tstamp_tc.nsec += delta;
@@ -271,3 +353,21 @@ otx2_nix_timesync_read_time(struct rte_eth_dev *eth_dev, struct timespec *ts)
 
 	return 0;
 }
+
+
+int
+otx2_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *clock)
+{
+	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+
+	/* This API returns the raw PTP HI clock value. Since LFs doesn't
+	 * have direct access to PTP registers and it requires mbox msg
+	 * to AF for this value. In fastpath reading this value for every
+	 * packet (which involes mbox call) becomes very expensive, hence
+	 * we should be able to derive PTP HI clock value from tsc by
+	 * using freq_mult and clk_delta calculated during configure stage.
+	 */
+	*clock = (rte_get_tsc_cycles() + dev->clk_delta) * dev->clk_freq_mult;
+
+	return 0;
+}
-- 
2.18.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/2] net/octeontx2: fix ptp performance issue
  2019-07-28  9:09           ` [dpdk-dev] [PATCH v3 1/2] net/octeontx2: fix ptp performance issue Harman Kalra
  2019-07-28  9:09             ` [dpdk-dev] [PATCH v3 2/2] net/octeontx2: support read clock API Harman Kalra
@ 2019-07-28 16:52             ` Jerin Jacob Kollanukkaran
  1 sibling, 0 replies; 11+ messages in thread
From: Jerin Jacob Kollanukkaran @ 2019-07-28 16:52 UTC (permalink / raw)
  To: Harman Kalra, Pavan Nikhilesh Bhagavatula,
	Nithin Kumar Dabilpuram, Kiran Kumar Kokkilagadda
  Cc: dev, Ferruh Yigit

> -----Original Message-----
> From: Harman Kalra <hkalra@marvell.com>
> Sent: Sunday, July 28, 2019 2:40 PM
> To: Pavan Nikhilesh Bhagavatula <pbhagavatula@marvell.com>; Jerin Jacob
> Kollanukkaran <jerinj@marvell.com>; Nithin Kumar Dabilpuram
> <ndabilpuram@marvell.com>; Kiran Kumar Kokkilagadda
> <kirankumark@marvell.com>
> Cc: dev@dpdk.org; Harman Kalra <hkalra@marvell.com>
> Subject: [PATCH v3 1/2] net/octeontx2: fix ptp performance issue
> 
> A huge drop in per core MPPS value was observed when PTP stack is
> enabled. The reason behind the bottleneck is HW serialises the transfer of all
> SQEs, which seeks timestamp capture, on the same send DMA path. Hence
> only those packets which requires timestamp capture should set SETTSTAMP
> in send mem alg.
> With this patch timestamping would be done only for those packets with
> PKT_TX_IEEE1588_TMST set.
> 
> Fixes: fb3ae0951abd ("net/octeontx2: support Tx")
> Fixes: 8980a153006b ("event/octeontx2: support PTP for SSO")
> 
> Signed-off-by: Harman Kalra <hkalra@marvell.com>

Acked-by: Jerin Jacob <jerinj@marvell.com>
Series applied to dpdk-next-net-mrvl/master. Thanks.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [PATCH v2 1/2] net/octeontx2: fix ptp performance issue
  2019-07-27 17:14 [dpdk-dev] [PATCH] examples/rxtx_callbacks: fix HW timestamp enable Jerin Jacob Kollanukkaran
@ 2019-07-27 20:34 ` Harman Kalra
  0 siblings, 0 replies; 11+ messages in thread
From: Harman Kalra @ 2019-07-27 20:34 UTC (permalink / raw)
  To: Pavan Nikhilesh Bhagavatula, Jerin Jacob Kollanukkaran,
	Nithin Kumar Dabilpuram, Kiran Kumar Kokkilagadda
  Cc: dev, Harman Kalra

A huge drop in per core MPPS value was observed when PTP stack is
enabled. The reason behind the bottleneck is HW serialises the
transfer of all SQEs, which seeks timestamp capture, on the same
send DMA path. Hence only those packets which requires timestamp
capture should set SETTSTAMP in send mem alg.
With this patch timestamping would be done only for those packets
with PKT_TX_IEEE1588_TMST set.

Fixes: fb3ae0951abd ("net/octeontx2: support Tx")
Fixes: 8980a153006b ("event/octeontx2: support PTP for SSO")

Signed-off-by: Harman Kalra <hkalra@marvell.com>
---
 drivers/event/octeontx2/otx2_evdev.h       |  7 ++++++-
 drivers/event/octeontx2/otx2_worker.h      | 10 +++++++--
 drivers/event/octeontx2/otx2_worker_dual.h | 14 +++++++++++--
 drivers/net/octeontx2/otx2_ethdev.c        |  2 --
 drivers/net/octeontx2/otx2_rx.c            |  3 ++-
 drivers/net/octeontx2/otx2_rx.h            | 24 +++++++++++++---------
 drivers/net/octeontx2/otx2_tx.h            | 19 +++++++++++++----
 7 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/drivers/event/octeontx2/otx2_evdev.h b/drivers/event/octeontx2/otx2_evdev.h
index 9c9718f6f..5cd80e3b2 100644
--- a/drivers/event/octeontx2/otx2_evdev.h
+++ b/drivers/event/octeontx2/otx2_evdev.h
@@ -25,6 +25,7 @@
 #define OTX2_SSO_SQB_LIMIT                  (0x180)
 #define OTX2_SSO_XAQ_SLACK                  (8)
 #define OTX2_SSO_XAQ_CACHE_CNT              (0x7)
+#define OTX2_SSO_WQE_SG_PTR                 (9)
 
 /* SSO LF register offsets (BAR2) */
 #define SSO_LF_GGRP_OP_ADD_WORK0            (0x0ull)
@@ -222,10 +223,14 @@ otx2_wqe_to_mbuf(uint64_t get_work1, const uint64_t mbuf, uint8_t port_id,
 		 const void * const lookup_mem)
 {
 	struct nix_wqe_hdr_s *wqe = (struct nix_wqe_hdr_s *)get_work1;
+	uint64_t val = mbuf_init.value | (uint64_t)port_id << 48;
+
+	if (flags & NIX_RX_OFFLOAD_TSTAMP_F)
+		val |= NIX_TIMESYNC_RX_OFFSET;
 
 	otx2_nix_cqe_to_mbuf((struct nix_cqe_hdr_s *)wqe, tag,
 			     (struct rte_mbuf *)mbuf, lookup_mem,
-			     mbuf_init.value | (uint64_t)port_id << 48, flags);
+			      val, flags);
 
 }
 
diff --git a/drivers/event/octeontx2/otx2_worker.h b/drivers/event/octeontx2/otx2_worker.h
index 3c847d223..76f91bb59 100644
--- a/drivers/event/octeontx2/otx2_worker.h
+++ b/drivers/event/octeontx2/otx2_worker.h
@@ -18,6 +18,7 @@ otx2_ssogws_get_work(struct otx2_ssogws *ws, struct rte_event *ev,
 		     const uint32_t flags, const void * const lookup_mem)
 {
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -69,8 +70,10 @@ otx2_ssogws_get_work(struct otx2_ssogws *ws, struct rte_event *ev,
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, lookup_mem);
 		/* Extracting tstamp, if PTP enabled*/
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
 		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, ws->tstamp,
-					flags);
+					flags, (uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
@@ -86,6 +89,7 @@ otx2_ssogws_get_work_empty(struct otx2_ssogws *ws, struct rte_event *ev,
 			   const uint32_t flags)
 {
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -131,8 +135,10 @@ otx2_ssogws_get_work_empty(struct otx2_ssogws *ws, struct rte_event *ev,
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, NULL);
 		/* Extracting tstamp, if PTP enabled*/
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
 		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, ws->tstamp,
-					flags);
+					flags, (uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
diff --git a/drivers/event/octeontx2/otx2_worker_dual.h b/drivers/event/octeontx2/otx2_worker_dual.h
index 4a72f424d..5134e3d52 100644
--- a/drivers/event/octeontx2/otx2_worker_dual.h
+++ b/drivers/event/octeontx2/otx2_worker_dual.h
@@ -21,6 +21,7 @@ otx2_ssogws_dual_get_work(struct otx2_ssogws_state *ws,
 {
 	const uint64_t set_gw = BIT_ULL(16) | 1;
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -70,8 +71,17 @@ otx2_ssogws_dual_get_work(struct otx2_ssogws_state *ws,
 	    event.event_type == RTE_EVENT_TYPE_ETHDEV) {
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, lookup_mem);
-		/* Extracting tstamp, if PTP enabled*/
-		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, tstamp, flags);
+		/* Extracting tstamp, if PTP enabled. CGX will prepend the
+		 * timestamp at starting of packet data and it can be derieved
+		 * from WQE 9 dword which corresponds to SG iova.
+		 * rte_pktmbuf_mtod_offset can be used for this purpose but it
+		 * brings down the performance as it reads mbuf->buf_addr which
+		 * is not part of cache in general fast path.
+		 */
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
+		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, tstamp, flags,
+					(uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
diff --git a/drivers/net/octeontx2/otx2_ethdev.c b/drivers/net/octeontx2/otx2_ethdev.c
index b018b25b7..595c8003a 100644
--- a/drivers/net/octeontx2/otx2_ethdev.c
+++ b/drivers/net/octeontx2/otx2_ethdev.c
@@ -874,8 +874,6 @@ otx2_nix_form_default_desc(struct otx2_eth_txq *txq)
 			send_mem = (struct nix_send_mem_s *)(txq->cmd +
 						(send_hdr->w0.sizem1 << 1));
 			send_mem->subdc = NIX_SUBDC_MEM;
-			send_mem->dsz = 0x0;
-			send_mem->wmem = 0x1;
 			send_mem->alg = NIX_SENDMEMALG_SETTSTMP;
 			send_mem->addr = txq->dev->tstamp.tx_tstamp_iova;
 		}
diff --git a/drivers/net/octeontx2/otx2_rx.c b/drivers/net/octeontx2/otx2_rx.c
index deefe9588..701efc858 100644
--- a/drivers/net/octeontx2/otx2_rx.c
+++ b/drivers/net/octeontx2/otx2_rx.c
@@ -68,7 +68,8 @@ nix_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 
 		otx2_nix_cqe_to_mbuf(cq, cq->tag, mbuf, lookup_mem, mbuf_init,
 				     flags);
-		otx2_nix_mbuf_to_tstamp(mbuf, rxq->tstamp, flags);
+		otx2_nix_mbuf_to_tstamp(mbuf, rxq->tstamp, flags,
+				(uint64_t *)((uint8_t *)mbuf + data_off));
 		rx_pkts[packets++] = mbuf;
 		otx2_prefetch_store_keep(mbuf);
 		head++;
diff --git a/drivers/net/octeontx2/otx2_rx.h b/drivers/net/octeontx2/otx2_rx.h
index e150f38d7..d12e8b809 100644
--- a/drivers/net/octeontx2/otx2_rx.h
+++ b/drivers/net/octeontx2/otx2_rx.h
@@ -50,22 +50,26 @@ union mbuf_initializer {
 
 static __rte_always_inline void
 otx2_nix_mbuf_to_tstamp(struct rte_mbuf *mbuf,
-			struct otx2_timesync_info *tstamp, const uint16_t flag)
+			struct otx2_timesync_info *tstamp, const uint16_t flag,
+			uint64_t *tstamp_ptr)
 {
 	if ((flag & NIX_RX_OFFLOAD_TSTAMP_F) &&
-	    mbuf->packet_type == RTE_PTYPE_L2_ETHER_TIMESYNC &&
 	    (mbuf->data_off == RTE_PKTMBUF_HEADROOM +
 	     NIX_TIMESYNC_RX_OFFSET)) {
-		uint64_t *tstamp_ptr;
 
-		/* Deal with rx timestamp */
-		tstamp_ptr = rte_pktmbuf_mtod_offset(mbuf, uint64_t *,
-						     -NIX_TIMESYNC_RX_OFFSET);
+		/* Reading the rx timestamp inserted by CGX, viz at
+		 * starting of the packet data.
+		 */
 		mbuf->timestamp = rte_be_to_cpu_64(*tstamp_ptr);
-		tstamp->rx_tstamp = mbuf->timestamp;
-		tstamp->rx_ready = 1;
-		mbuf->ol_flags |= PKT_RX_IEEE1588_PTP | PKT_RX_IEEE1588_TMST
-			| PKT_RX_TIMESTAMP;
+		/* PKT_RX_IEEE1588_TMST flag needs to be set only in case
+		 * PTP packets are received.
+		 */
+		if (mbuf->packet_type == RTE_PTYPE_L2_ETHER_TIMESYNC) {
+			tstamp->rx_tstamp = mbuf->timestamp;
+			tstamp->rx_ready = 1;
+			mbuf->ol_flags |= PKT_RX_IEEE1588_PTP |
+				PKT_RX_IEEE1588_TMST | PKT_RX_TIMESTAMP;
+		}
 	}
 }
 
diff --git a/drivers/net/octeontx2/otx2_tx.h b/drivers/net/octeontx2/otx2_tx.h
index b75a220ea..494ba3884 100644
--- a/drivers/net/octeontx2/otx2_tx.h
+++ b/drivers/net/octeontx2/otx2_tx.h
@@ -43,18 +43,29 @@ otx2_nix_xmit_prepare_tstamp(uint64_t *cmd,  const uint64_t *send_mem_desc,
 	if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
 		struct nix_send_mem_s *send_mem;
 		uint16_t off = (no_segdw - 1) << 1;
+		const uint8_t is_ol_tstamp = !(ol_flags & PKT_TX_IEEE1588_TMST);
 
 		send_mem = (struct nix_send_mem_s *)(cmd + off);
-		if (flags & NIX_TX_MULTI_SEG_F)
+		if (flags & NIX_TX_MULTI_SEG_F) {
 			/* Retrieving the default desc values */
 			cmd[off] = send_mem_desc[6];
 
+			/* Using compiler barier to avoid voilation of C
+			 * aliasing rules.
+			 */
+			rte_compiler_barrier();
+		}
+
 		/* Packets for which PKT_TX_IEEE1588_TMST is not set, tx tstamp
-		 * should not be updated at tx tstamp registered address, rather
-		 * a dummy address which is eight bytes ahead would be updated
+		 * should not be recorded, hence changing the alg type to
+		 * NIX_SENDMEMALG_SET and also changing send mem addr field to
+		 * next 8 bytes as it corrpt the actual tx tstamp registered
+		 * address.
 		 */
+		send_mem->alg = NIX_SENDMEMALG_SETTSTMP - (is_ol_tstamp);
+
 		send_mem->addr = (rte_iova_t)((uint64_t *)send_mem_desc[7] +
-				!(ol_flags & PKT_TX_IEEE1588_TMST));
+					      (is_ol_tstamp));
 	}
 }
 
-- 
2.18.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [PATCH v2 1/2] net/octeontx2: fix ptp performance issue
@ 2019-07-27 20:27 Harman Kalra
  0 siblings, 0 replies; 11+ messages in thread
From: Harman Kalra @ 2019-07-27 20:27 UTC (permalink / raw)
  To: Pavan Nikhilesh Bhagavatula, Jerin Jacob Kollanukkaran,
	Nithin Kumar Dabilpuram, Kiran Kumar Kokkilagadda
  Cc: dev, Harman Kalra

A huge drop in per core MPPS value was observed when PTP stack is
enabled. The reason behind the bottleneck is HW serialises the
transfer of all SQEs, which seeks timestamp capture, on the same
send DMA path. Hence only those packets which requires timestamp
capture should set SETTSTAMP in send mem alg.
With this patch timestamping would be done only for those packets
with PKT_TX_IEEE1588_TMST set.

Fixes: fb3ae0951abd ("net/octeontx2: support Tx")
Fixes: 8980a153006b ("event/octeontx2: support PTP for SSO")

Signed-off-by: Harman Kalra <hkalra@marvell.com>
---
 drivers/event/octeontx2/otx2_evdev.h       |  7 ++++++-
 drivers/event/octeontx2/otx2_worker.h      | 10 +++++++--
 drivers/event/octeontx2/otx2_worker_dual.h | 14 +++++++++++--
 drivers/net/octeontx2/otx2_ethdev.c        |  2 --
 drivers/net/octeontx2/otx2_rx.c            |  3 ++-
 drivers/net/octeontx2/otx2_rx.h            | 24 +++++++++++++---------
 drivers/net/octeontx2/otx2_tx.h            | 19 +++++++++++++----
 7 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/drivers/event/octeontx2/otx2_evdev.h b/drivers/event/octeontx2/otx2_evdev.h
index 9c9718f6f..5cd80e3b2 100644
--- a/drivers/event/octeontx2/otx2_evdev.h
+++ b/drivers/event/octeontx2/otx2_evdev.h
@@ -25,6 +25,7 @@
 #define OTX2_SSO_SQB_LIMIT                  (0x180)
 #define OTX2_SSO_XAQ_SLACK                  (8)
 #define OTX2_SSO_XAQ_CACHE_CNT              (0x7)
+#define OTX2_SSO_WQE_SG_PTR                 (9)
 
 /* SSO LF register offsets (BAR2) */
 #define SSO_LF_GGRP_OP_ADD_WORK0            (0x0ull)
@@ -222,10 +223,14 @@ otx2_wqe_to_mbuf(uint64_t get_work1, const uint64_t mbuf, uint8_t port_id,
 		 const void * const lookup_mem)
 {
 	struct nix_wqe_hdr_s *wqe = (struct nix_wqe_hdr_s *)get_work1;
+	uint64_t val = mbuf_init.value | (uint64_t)port_id << 48;
+
+	if (flags & NIX_RX_OFFLOAD_TSTAMP_F)
+		val |= NIX_TIMESYNC_RX_OFFSET;
 
 	otx2_nix_cqe_to_mbuf((struct nix_cqe_hdr_s *)wqe, tag,
 			     (struct rte_mbuf *)mbuf, lookup_mem,
-			     mbuf_init.value | (uint64_t)port_id << 48, flags);
+			      val, flags);
 
 }
 
diff --git a/drivers/event/octeontx2/otx2_worker.h b/drivers/event/octeontx2/otx2_worker.h
index 3c847d223..76f91bb59 100644
--- a/drivers/event/octeontx2/otx2_worker.h
+++ b/drivers/event/octeontx2/otx2_worker.h
@@ -18,6 +18,7 @@ otx2_ssogws_get_work(struct otx2_ssogws *ws, struct rte_event *ev,
 		     const uint32_t flags, const void * const lookup_mem)
 {
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -69,8 +70,10 @@ otx2_ssogws_get_work(struct otx2_ssogws *ws, struct rte_event *ev,
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, lookup_mem);
 		/* Extracting tstamp, if PTP enabled*/
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
 		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, ws->tstamp,
-					flags);
+					flags, (uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
@@ -86,6 +89,7 @@ otx2_ssogws_get_work_empty(struct otx2_ssogws *ws, struct rte_event *ev,
 			   const uint32_t flags)
 {
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -131,8 +135,10 @@ otx2_ssogws_get_work_empty(struct otx2_ssogws *ws, struct rte_event *ev,
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, NULL);
 		/* Extracting tstamp, if PTP enabled*/
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
 		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, ws->tstamp,
-					flags);
+					flags, (uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
diff --git a/drivers/event/octeontx2/otx2_worker_dual.h b/drivers/event/octeontx2/otx2_worker_dual.h
index 4a72f424d..5134e3d52 100644
--- a/drivers/event/octeontx2/otx2_worker_dual.h
+++ b/drivers/event/octeontx2/otx2_worker_dual.h
@@ -21,6 +21,7 @@ otx2_ssogws_dual_get_work(struct otx2_ssogws_state *ws,
 {
 	const uint64_t set_gw = BIT_ULL(16) | 1;
 	union otx2_sso_event event;
+	uint64_t tstamp_ptr;
 	uint64_t get_work1;
 	uint64_t mbuf;
 
@@ -70,8 +71,17 @@ otx2_ssogws_dual_get_work(struct otx2_ssogws_state *ws,
 	    event.event_type == RTE_EVENT_TYPE_ETHDEV) {
 		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
 				 (uint32_t) event.get_work0, flags, lookup_mem);
-		/* Extracting tstamp, if PTP enabled*/
-		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, tstamp, flags);
+		/* Extracting tstamp, if PTP enabled. CGX will prepend the
+		 * timestamp at starting of packet data and it can be derieved
+		 * from WQE 9 dword which corresponds to SG iova.
+		 * rte_pktmbuf_mtod_offset can be used for this purpose but it
+		 * brings down the performance as it reads mbuf->buf_addr which
+		 * is not part of cache in general fast path.
+		 */
+		tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)get_work1)
+					     + OTX2_SSO_WQE_SG_PTR);
+		otx2_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, tstamp, flags,
+					(uint64_t *)tstamp_ptr);
 		get_work1 = mbuf;
 	}
 
diff --git a/drivers/net/octeontx2/otx2_ethdev.c b/drivers/net/octeontx2/otx2_ethdev.c
index b018b25b7..595c8003a 100644
--- a/drivers/net/octeontx2/otx2_ethdev.c
+++ b/drivers/net/octeontx2/otx2_ethdev.c
@@ -874,8 +874,6 @@ otx2_nix_form_default_desc(struct otx2_eth_txq *txq)
 			send_mem = (struct nix_send_mem_s *)(txq->cmd +
 						(send_hdr->w0.sizem1 << 1));
 			send_mem->subdc = NIX_SUBDC_MEM;
-			send_mem->dsz = 0x0;
-			send_mem->wmem = 0x1;
 			send_mem->alg = NIX_SENDMEMALG_SETTSTMP;
 			send_mem->addr = txq->dev->tstamp.tx_tstamp_iova;
 		}
diff --git a/drivers/net/octeontx2/otx2_rx.c b/drivers/net/octeontx2/otx2_rx.c
index deefe9588..701efc858 100644
--- a/drivers/net/octeontx2/otx2_rx.c
+++ b/drivers/net/octeontx2/otx2_rx.c
@@ -68,7 +68,8 @@ nix_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 
 		otx2_nix_cqe_to_mbuf(cq, cq->tag, mbuf, lookup_mem, mbuf_init,
 				     flags);
-		otx2_nix_mbuf_to_tstamp(mbuf, rxq->tstamp, flags);
+		otx2_nix_mbuf_to_tstamp(mbuf, rxq->tstamp, flags,
+				(uint64_t *)((uint8_t *)mbuf + data_off));
 		rx_pkts[packets++] = mbuf;
 		otx2_prefetch_store_keep(mbuf);
 		head++;
diff --git a/drivers/net/octeontx2/otx2_rx.h b/drivers/net/octeontx2/otx2_rx.h
index e150f38d7..d12e8b809 100644
--- a/drivers/net/octeontx2/otx2_rx.h
+++ b/drivers/net/octeontx2/otx2_rx.h
@@ -50,22 +50,26 @@ union mbuf_initializer {
 
 static __rte_always_inline void
 otx2_nix_mbuf_to_tstamp(struct rte_mbuf *mbuf,
-			struct otx2_timesync_info *tstamp, const uint16_t flag)
+			struct otx2_timesync_info *tstamp, const uint16_t flag,
+			uint64_t *tstamp_ptr)
 {
 	if ((flag & NIX_RX_OFFLOAD_TSTAMP_F) &&
-	    mbuf->packet_type == RTE_PTYPE_L2_ETHER_TIMESYNC &&
 	    (mbuf->data_off == RTE_PKTMBUF_HEADROOM +
 	     NIX_TIMESYNC_RX_OFFSET)) {
-		uint64_t *tstamp_ptr;
 
-		/* Deal with rx timestamp */
-		tstamp_ptr = rte_pktmbuf_mtod_offset(mbuf, uint64_t *,
-						     -NIX_TIMESYNC_RX_OFFSET);
+		/* Reading the rx timestamp inserted by CGX, viz at
+		 * starting of the packet data.
+		 */
 		mbuf->timestamp = rte_be_to_cpu_64(*tstamp_ptr);
-		tstamp->rx_tstamp = mbuf->timestamp;
-		tstamp->rx_ready = 1;
-		mbuf->ol_flags |= PKT_RX_IEEE1588_PTP | PKT_RX_IEEE1588_TMST
-			| PKT_RX_TIMESTAMP;
+		/* PKT_RX_IEEE1588_TMST flag needs to be set only in case
+		 * PTP packets are received.
+		 */
+		if (mbuf->packet_type == RTE_PTYPE_L2_ETHER_TIMESYNC) {
+			tstamp->rx_tstamp = mbuf->timestamp;
+			tstamp->rx_ready = 1;
+			mbuf->ol_flags |= PKT_RX_IEEE1588_PTP |
+				PKT_RX_IEEE1588_TMST | PKT_RX_TIMESTAMP;
+		}
 	}
 }
 
diff --git a/drivers/net/octeontx2/otx2_tx.h b/drivers/net/octeontx2/otx2_tx.h
index b75a220ea..494ba3884 100644
--- a/drivers/net/octeontx2/otx2_tx.h
+++ b/drivers/net/octeontx2/otx2_tx.h
@@ -43,18 +43,29 @@ otx2_nix_xmit_prepare_tstamp(uint64_t *cmd,  const uint64_t *send_mem_desc,
 	if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
 		struct nix_send_mem_s *send_mem;
 		uint16_t off = (no_segdw - 1) << 1;
+		const uint8_t is_ol_tstamp = !(ol_flags & PKT_TX_IEEE1588_TMST);
 
 		send_mem = (struct nix_send_mem_s *)(cmd + off);
-		if (flags & NIX_TX_MULTI_SEG_F)
+		if (flags & NIX_TX_MULTI_SEG_F) {
 			/* Retrieving the default desc values */
 			cmd[off] = send_mem_desc[6];
 
+			/* Using compiler barier to avoid voilation of C
+			 * aliasing rules.
+			 */
+			rte_compiler_barrier();
+		}
+
 		/* Packets for which PKT_TX_IEEE1588_TMST is not set, tx tstamp
-		 * should not be updated at tx tstamp registered address, rather
-		 * a dummy address which is eight bytes ahead would be updated
+		 * should not be recorded, hence changing the alg type to
+		 * NIX_SENDMEMALG_SET and also changing send mem addr field to
+		 * next 8 bytes as it corrpt the actual tx tstamp registered
+		 * address.
 		 */
+		send_mem->alg = NIX_SENDMEMALG_SETTSTMP - (is_ol_tstamp);
+
 		send_mem->addr = (rte_iova_t)((uint64_t *)send_mem_desc[7] +
-				!(ol_flags & PKT_TX_IEEE1588_TMST));
+					      (is_ol_tstamp));
 	}
 }
 
-- 
2.18.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2019-07-28 16:52 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-27 14:57 [dpdk-dev] [PATCH 1/2] net/octeontx2: fix ptp performance issue Harman Kalra
2019-07-27 14:57 ` [dpdk-dev] [PATCH 2/2] net/octeontx2: support read clock API Harman Kalra
2019-07-27 15:48   ` Jerin Jacob Kollanukkaran
2019-07-27 20:41     ` [dpdk-dev] [PATCH v2 1/2] net/octeontx2: fix ptp performance issue Harman Kalra
2019-07-27 20:41       ` [dpdk-dev] [PATCH v2 2/2] net/octeontx2: support read clock API Harman Kalra
2019-07-28  7:43         ` Jerin Jacob Kollanukkaran
2019-07-28  9:09           ` [dpdk-dev] [PATCH v3 1/2] net/octeontx2: fix ptp performance issue Harman Kalra
2019-07-28  9:09             ` [dpdk-dev] [PATCH v3 2/2] net/octeontx2: support read clock API Harman Kalra
2019-07-28 16:52             ` [dpdk-dev] [PATCH v3 1/2] net/octeontx2: fix ptp performance issue Jerin Jacob Kollanukkaran
2019-07-27 17:14 [dpdk-dev] [PATCH] examples/rxtx_callbacks: fix HW timestamp enable Jerin Jacob Kollanukkaran
2019-07-27 20:34 ` [dpdk-dev] [PATCH v2 1/2] net/octeontx2: fix ptp performance issue Harman Kalra
2019-07-27 20:27 Harman Kalra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).