DPDK patches and discussions
 help / color / mirror / Atom feed
From: Simei Su <simei.su@intel.com>
To: qi.z.zhang@intel.com, junfeng.guo@intel.com
Cc: dev@dpdk.org, wenjun1.wu@intel.com, Simei Su <simei.su@intel.com>
Subject: [PATCH v3 2/2] net/igc: enable launch time offloading
Date: Thu,  2 Feb 2023 15:18:01 +0800	[thread overview]
Message-ID: <20230202071801.30576-3-simei.su@intel.com> (raw)
In-Reply-To: <20230202071801.30576-1-simei.su@intel.com>

The LaunchTime defines the scheduling time of the packet from
the packet buffer to the MAC. The launchtime of each packet is
specified as an offset applied to the BaseT registers while BaseT
is automatically incremented each cycle.

This patch supports Tx timestamp based packet pacing by leveraging
offload flag "RTE_ETH_TX_OFFLOAD_SEND_ON_TIMESTAMP". We should set
the expected launchtime to the advanced transmit descriptor.

Signed-off-by: Simei Su <simei.su@intel.com>
---
 doc/guides/rel_notes/release_23_03.rst |  2 +-
 drivers/net/igc/igc_ethdev.c           | 70 ++++++++++++++++++++++++++++++++++
 drivers/net/igc/igc_ethdev.h           |  6 ++-
 drivers/net/igc/igc_txrx.c             | 58 ++++++++++++++++++++++++----
 drivers/net/igc/igc_txrx.h             |  3 ++
 5 files changed, 129 insertions(+), 10 deletions(-)

diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst
index d175f8e..5bca6af 100644
--- a/doc/guides/rel_notes/release_23_03.rst
+++ b/doc/guides/rel_notes/release_23_03.rst
@@ -79,7 +79,7 @@ New Features
 * **Updated Intel igc driver.**
 
   * Added timesync API support.
-
+  * Added packet pacing(launch time offloading) support.
 
 Removed Items
 -------------
diff --git a/drivers/net/igc/igc_ethdev.c b/drivers/net/igc/igc_ethdev.c
index ef3346b..fab2ab6 100644
--- a/drivers/net/igc/igc_ethdev.c
+++ b/drivers/net/igc/igc_ethdev.c
@@ -88,6 +88,9 @@
 #define IGC_I225_RX_LATENCY_1000	300
 #define IGC_I225_RX_LATENCY_2500	1485
 
+uint64_t igc_tx_timestamp_dynflag;
+int igc_tx_timestamp_dynfield_offset = -1;
+
 static const struct rte_eth_desc_lim rx_desc_lim = {
 	.nb_max = IGC_MAX_RXD,
 	.nb_min = IGC_MIN_RXD,
@@ -267,6 +270,7 @@ static int eth_igc_timesync_read_time(struct rte_eth_dev *dev,
 				  struct timespec *timestamp);
 static int eth_igc_timesync_write_time(struct rte_eth_dev *dev,
 				   const struct timespec *timestamp);
+static int eth_igc_read_clock(struct rte_eth_dev *dev, uint64_t *clock);
 
 static const struct eth_dev_ops eth_igc_ops = {
 	.dev_configure		= eth_igc_configure,
@@ -327,6 +331,7 @@ static const struct eth_dev_ops eth_igc_ops = {
 	.timesync_adjust_time	= eth_igc_timesync_adjust_time,
 	.timesync_read_time	= eth_igc_timesync_read_time,
 	.timesync_write_time	= eth_igc_timesync_write_time,
+	.read_clock             = eth_igc_read_clock,
 };
 
 /*
@@ -949,7 +954,12 @@ eth_igc_start(struct rte_eth_dev *dev)
 	struct igc_adapter *adapter = IGC_DEV_PRIVATE(dev);
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
+	uint32_t nsec, sec, baset_l, baset_h, tqavctrl;
+	struct timespec system_time;
+	int64_t n, systime;
+	uint32_t txqctl = 0;
 	uint32_t *speeds;
+	uint16_t i;
 	int ret;
 
 	PMD_INIT_FUNC_TRACE();
@@ -1009,6 +1019,55 @@ eth_igc_start(struct rte_eth_dev *dev)
 		return ret;
 	}
 
+	if (igc_tx_timestamp_dynflag > 0) {
+		adapter->base_time = 0;
+		adapter->cycle_time = NSEC_PER_SEC;
+
+		IGC_WRITE_REG(hw, IGC_TSSDP, 0);
+		IGC_WRITE_REG(hw, IGC_TSIM, TSINTR_TXTS);
+		IGC_WRITE_REG(hw, IGC_IMS, IGC_ICR_TS);
+
+		IGC_WRITE_REG(hw, IGC_TSAUXC, 0);
+		IGC_WRITE_REG(hw, IGC_I350_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
+		IGC_WRITE_REG(hw, IGC_TXPBS, IGC_TXPBSIZE_TSN);
+
+		tqavctrl = IGC_READ_REG(hw, IGC_I210_TQAVCTRL);
+		tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
+			    IGC_TQAVCTRL_ENHANCED_QAV;
+		IGC_WRITE_REG(hw, IGC_I210_TQAVCTRL, tqavctrl);
+
+		IGC_WRITE_REG(hw, IGC_QBVCYCLET_S, adapter->cycle_time);
+		IGC_WRITE_REG(hw, IGC_QBVCYCLET, adapter->cycle_time);
+
+		for (i = 0; i < dev->data->nb_tx_queues; i++) {
+			IGC_WRITE_REG(hw, IGC_STQT(i), 0);
+			IGC_WRITE_REG(hw, IGC_ENDQT(i), NSEC_PER_SEC);
+
+			txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
+			IGC_WRITE_REG(hw, IGC_TXQCTL(i), txqctl);
+		}
+
+		clock_gettime(CLOCK_REALTIME, &system_time);
+		IGC_WRITE_REG(hw, IGC_SYSTIML, system_time.tv_nsec);
+		IGC_WRITE_REG(hw, IGC_SYSTIMH, system_time.tv_sec);
+
+		nsec = IGC_READ_REG(hw, IGC_SYSTIML);
+		sec = IGC_READ_REG(hw, IGC_SYSTIMH);
+		systime = (int64_t)sec * NSEC_PER_SEC + (int64_t)nsec;
+
+		if (systime > adapter->base_time) {
+			n = (systime - adapter->base_time) /
+			     adapter->cycle_time;
+			adapter->base_time = adapter->base_time +
+				(n + 1) * adapter->cycle_time;
+		}
+
+		baset_h = adapter->base_time / NSEC_PER_SEC;
+		baset_l = adapter->base_time % NSEC_PER_SEC;
+		IGC_WRITE_REG(hw, IGC_BASET_H, baset_h);
+		IGC_WRITE_REG(hw, IGC_BASET_L, baset_l);
+	}
+
 	igc_clear_hw_cntrs_base_generic(hw);
 
 	/* VLAN Offload Settings */
@@ -2804,6 +2863,17 @@ eth_igc_timesync_disable(struct rte_eth_dev *dev)
 }
 
 static int
+eth_igc_read_clock(__rte_unused struct rte_eth_dev *dev, uint64_t *clock)
+{
+	struct timespec system_time;
+
+	clock_gettime(CLOCK_REALTIME, &system_time);
+	*clock = system_time.tv_sec * NSEC_PER_SEC + system_time.tv_nsec;
+
+	return 0;
+}
+
+static int
 eth_igc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	struct rte_pci_device *pci_dev)
 {
diff --git a/drivers/net/igc/igc_ethdev.h b/drivers/net/igc/igc_ethdev.h
index 237d3c1..8d7eb54 100644
--- a/drivers/net/igc/igc_ethdev.h
+++ b/drivers/net/igc/igc_ethdev.h
@@ -87,7 +87,8 @@ extern "C" {
 	RTE_ETH_TX_OFFLOAD_SCTP_CKSUM  | \
 	RTE_ETH_TX_OFFLOAD_TCP_TSO     | \
 	RTE_ETH_TX_OFFLOAD_UDP_TSO	   | \
-	RTE_ETH_TX_OFFLOAD_MULTI_SEGS)
+	RTE_ETH_TX_OFFLOAD_MULTI_SEGS  | \
+	RTE_ETH_TX_OFFLOAD_SEND_ON_TIMESTAMP)
 
 #define IGC_RSS_OFFLOAD_ALL	(    \
 	RTE_ETH_RSS_IPV4               | \
@@ -240,6 +241,9 @@ struct igc_adapter {
 	struct igc_syn_filter syn_filter;
 	struct igc_rss_filter rss_filter;
 	struct igc_flow_list flow_list;
+
+	int64_t base_time;
+	uint32_t cycle_time;
 };
 
 #define IGC_DEV_PRIVATE(_dev)	((_dev)->data->dev_private)
diff --git a/drivers/net/igc/igc_txrx.c b/drivers/net/igc/igc_txrx.c
index 0236c7f..c11b6f7 100644
--- a/drivers/net/igc/igc_txrx.c
+++ b/drivers/net/igc/igc_txrx.c
@@ -1411,6 +1411,19 @@ what_advctx_update(struct igc_tx_queue *txq, uint64_t flags,
 	return IGC_CTX_NUM;
 }
 
+static uint32_t igc_tx_launchtime(uint64_t txtime, uint16_t port_id)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	struct igc_adapter *adapter = IGC_DEV_PRIVATE(dev);
+	uint64_t base_time = adapter->base_time;
+	uint64_t cycle_time = adapter->cycle_time;
+	uint32_t launchtime;
+
+	launchtime = (txtime - base_time) % cycle_time;
+
+	return rte_cpu_to_le_32(launchtime);
+}
+
 /*
  * This is a separate function, looking for optimization opportunity here
  * Rework required to go with the pre-defined values.
@@ -1418,7 +1431,8 @@ what_advctx_update(struct igc_tx_queue *txq, uint64_t flags,
 static inline void
 igc_set_xmit_ctx(struct igc_tx_queue *txq,
 		volatile struct igc_adv_tx_context_desc *ctx_txd,
-		uint64_t ol_flags, union igc_tx_offload tx_offload)
+		uint64_t ol_flags, union igc_tx_offload tx_offload,
+		uint64_t txtime)
 {
 	uint32_t type_tucmd_mlhl;
 	uint32_t mss_l4len_idx;
@@ -1492,16 +1506,23 @@ igc_set_xmit_ctx(struct igc_tx_queue *txq,
 		}
 	}
 
-	txq->ctx_cache[ctx_curr].flags = ol_flags;
-	txq->ctx_cache[ctx_curr].tx_offload.data =
-		tx_offload_mask.data & tx_offload.data;
-	txq->ctx_cache[ctx_curr].tx_offload_mask = tx_offload_mask;
+	if (!txtime) {
+		txq->ctx_cache[ctx_curr].flags = ol_flags;
+		txq->ctx_cache[ctx_curr].tx_offload.data =
+			tx_offload_mask.data & tx_offload.data;
+		txq->ctx_cache[ctx_curr].tx_offload_mask = tx_offload_mask;
+	}
 
 	ctx_txd->type_tucmd_mlhl = rte_cpu_to_le_32(type_tucmd_mlhl);
 	vlan_macip_lens = (uint32_t)tx_offload.data;
 	ctx_txd->vlan_macip_lens = rte_cpu_to_le_32(vlan_macip_lens);
 	ctx_txd->mss_l4len_idx = rte_cpu_to_le_32(mss_l4len_idx);
-	ctx_txd->u.launch_time = 0;
+
+	if (txtime)
+		ctx_txd->u.launch_time = igc_tx_launchtime(txtime,
+							   txq->port_id);
+	else
+		ctx_txd->u.launch_time = 0;
 }
 
 static inline uint32_t
@@ -1551,6 +1572,7 @@ igc_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 	uint64_t tx_ol_req;
 	uint32_t new_ctx = 0;
 	union igc_tx_offload tx_offload = {0};
+	uint64_t ts;
 
 	tx_id = txq->tx_tail;
 	txe = &sw_ring[tx_id];
@@ -1698,8 +1720,16 @@ igc_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 					txe->mbuf = NULL;
 				}
 
-				igc_set_xmit_ctx(txq, ctx_txd, tx_ol_req,
-						tx_offload);
+				if (igc_tx_timestamp_dynflag > 0) {
+					ts = *RTE_MBUF_DYNFIELD(tx_pkt,
+						igc_tx_timestamp_dynfield_offset,
+						uint64_t *);
+					igc_set_xmit_ctx(txq, ctx_txd,
+						tx_ol_req, tx_offload, ts);
+				} else {
+					igc_set_xmit_ctx(txq, ctx_txd,
+						tx_ol_req, tx_offload, 0);
+				}
 
 				txe->last_id = tx_last;
 				tx_id = txe->next_id;
@@ -2081,9 +2111,11 @@ void
 igc_tx_init(struct rte_eth_dev *dev)
 {
 	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+	uint64_t offloads = dev->data->dev_conf.txmode.offloads;
 	uint32_t tctl;
 	uint32_t txdctl;
 	uint16_t i;
+	int err;
 
 	/* Setup the Base and Length of the Tx Descriptor Rings. */
 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
@@ -2113,6 +2145,16 @@ igc_tx_init(struct rte_eth_dev *dev)
 		IGC_WRITE_REG(hw, IGC_TXDCTL(txq->reg_idx), txdctl);
 	}
 
+	if (offloads & RTE_ETH_TX_OFFLOAD_SEND_ON_TIMESTAMP) {
+		err = rte_mbuf_dyn_tx_timestamp_register
+			(&igc_tx_timestamp_dynfield_offset,
+			 &igc_tx_timestamp_dynflag);
+		if (err) {
+			PMD_DRV_LOG(ERR,
+				"Cannot register mbuf field/flag for timestamp");
+		}
+	}
+
 	igc_config_collision_dist(hw);
 
 	/* Program the Transmit Control Register. */
diff --git a/drivers/net/igc/igc_txrx.h b/drivers/net/igc/igc_txrx.h
index e7272f8..ad7d3b4 100644
--- a/drivers/net/igc/igc_txrx.h
+++ b/drivers/net/igc/igc_txrx.h
@@ -11,6 +11,9 @@
 extern "C" {
 #endif
 
+extern uint64_t igc_tx_timestamp_dynflag;
+extern int igc_tx_timestamp_dynfield_offset;
+
 struct igc_rx_entry {
 	struct rte_mbuf *mbuf; /**< mbuf associated with RX descriptor. */
 };
-- 
2.9.5


  parent reply	other threads:[~2023-02-02  7:19 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-20  3:47 [PATCH 0/2] net/igc: support Tx timestamp offload Simei Su
2022-12-20  3:47 ` [PATCH 1/2] net/igc/base: " Simei Su
2022-12-20  3:47 ` [PATCH 2/2] net/igc: enable " Simei Su
2023-02-01  7:30 ` [PATCH v2 0/2] net/igc: support launch time offloading Simei Su
2023-02-01  7:30   ` [PATCH v2 1/2] net/igc/base: expose packet pacing registers Simei Su
2023-02-01  7:30   ` [PATCH v2 2/2] net/igc: enable launch time offloading Simei Su
2023-02-01  8:34     ` Zhang, Qi Z
2023-02-01  8:46   ` [PATCH v2 0/2] net/igc: support " Morten Brørup
2023-02-02  7:17   ` [PATCH v3 " Simei Su
2023-02-02  7:18     ` [PATCH v3 1/2] net/igc/base: expose packet pacing registers Simei Su
2023-02-02  7:18     ` Simei Su [this message]
2023-02-03  0:30       ` [PATCH v3 2/2] net/igc: enable launch time offloading Stephen Hemminger
2023-02-03  3:22         ` Su, Simei
2023-02-02  8:46     ` [PATCH v3 0/2] net/igc: support " Zhang, Qi Z

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230202071801.30576-3-simei.su@intel.com \
    --to=simei.su@intel.com \
    --cc=dev@dpdk.org \
    --cc=junfeng.guo@intel.com \
    --cc=qi.z.zhang@intel.com \
    --cc=wenjun1.wu@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).