diff mbox series

[net-next,v3,7/7] net: mvpp2: ptp: add support for transmit timestamping

Message ID E1kFlfN-0006di-Pu@rmk-PC.armlinux.org.uk
State Changes Requested
Delegated to: David Miller
Headers show
Series Marvell PP2.2 PTP support | expand

Commit Message

Russell King (Oracle) Sept. 8, 2020, 10 p.m. UTC
Add support for timestamping transmit packets.  We allocate SYNC
messages to queue 1, every other message to queue 0.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/ethernet/marvell/mvpp2/mvpp2.h    |  48 +++++-
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   | 156 ++++++++++++++++--
 2 files changed, 193 insertions(+), 11 deletions(-)

Comments

Richard Cochran Sept. 8, 2020, 11:40 p.m. UTC | #1
On Tue, Sep 08, 2020 at 11:00:41PM +0100, Russell King wrote:

> @@ -2984,13 +2985,19 @@ static irqreturn_t mvpp2_isr(int irq, void *dev_id)
>  
>  static void mvpp2_isr_handle_ptp_queue(struct mvpp2_port *port, int nq)
>  {
> +	struct skb_shared_hwtstamps shhwtstamps;
> +	struct mvpp2_hwtstamp_queue *queue;
> +	struct sk_buff *skb;
>  	void __iomem *ptp_q;
> +	unsigned int id;
>  	u32 r0, r1, r2;
>  
>  	ptp_q = port->priv->iface_base + MVPP22_PTP_BASE(port->gop_id);
>  	if (nq)
>  		ptp_q += MVPP22_PTP_TX_Q1_R0 - MVPP22_PTP_TX_Q0_R0;
>  
> +	queue = &port->tx_hwtstamp_queue[nq];
> +
>  	while (1) {
>  		r0 = readl_relaxed(ptp_q + MVPP22_PTP_TX_Q0_R0) & 0xffff;
>  		if (!r0)
> @@ -2998,6 +3005,19 @@ static void mvpp2_isr_handle_ptp_queue(struct mvpp2_port *port, int nq)
>  
>  		r1 = readl_relaxed(ptp_q + MVPP22_PTP_TX_Q0_R1) & 0xffff;
>  		r2 = readl_relaxed(ptp_q + MVPP22_PTP_TX_Q0_R2) & 0xffff;
> +
> +		id = (r0 >> 1) & 31;
> +
> +		skb = queue->skb[id];
> +		queue->skb[id] = NULL;
> +		if (skb) {
> +			u32 ts = r2 << 19 | r1 << 3 | r0 >> 13;
> +
> +			netdev_info(port->dev, "tx stamp 0x%08x\n", ts);

This probably should be _debug instead.

> +			mvpp22_tai_tstamp(port->priv->tai, ts, &shhwtstamps);
> +			skb_tstamp_tx(skb, &shhwtstamps);
> +			dev_kfree_skb_any(skb);
> +		}
>  	}
>  }

Thanks,
Richard
Russell King (Oracle) Sept. 8, 2020, 11:50 p.m. UTC | #2
On Tue, Sep 08, 2020 at 04:40:52PM -0700, Richard Cochran wrote:
> On Tue, Sep 08, 2020 at 11:00:41PM +0100, Russell King wrote:
> 
> > @@ -2984,13 +2985,19 @@ static irqreturn_t mvpp2_isr(int irq, void *dev_id)
> >  
> >  static void mvpp2_isr_handle_ptp_queue(struct mvpp2_port *port, int nq)
> >  {
> > +	struct skb_shared_hwtstamps shhwtstamps;
> > +	struct mvpp2_hwtstamp_queue *queue;
> > +	struct sk_buff *skb;
> >  	void __iomem *ptp_q;
> > +	unsigned int id;
> >  	u32 r0, r1, r2;
> >  
> >  	ptp_q = port->priv->iface_base + MVPP22_PTP_BASE(port->gop_id);
> >  	if (nq)
> >  		ptp_q += MVPP22_PTP_TX_Q1_R0 - MVPP22_PTP_TX_Q0_R0;
> >  
> > +	queue = &port->tx_hwtstamp_queue[nq];
> > +
> >  	while (1) {
> >  		r0 = readl_relaxed(ptp_q + MVPP22_PTP_TX_Q0_R0) & 0xffff;
> >  		if (!r0)
> > @@ -2998,6 +3005,19 @@ static void mvpp2_isr_handle_ptp_queue(struct mvpp2_port *port, int nq)
> >  
> >  		r1 = readl_relaxed(ptp_q + MVPP22_PTP_TX_Q0_R1) & 0xffff;
> >  		r2 = readl_relaxed(ptp_q + MVPP22_PTP_TX_Q0_R2) & 0xffff;
> > +
> > +		id = (r0 >> 1) & 31;
> > +
> > +		skb = queue->skb[id];
> > +		queue->skb[id] = NULL;
> > +		if (skb) {
> > +			u32 ts = r2 << 19 | r1 << 3 | r0 >> 13;
> > +
> > +			netdev_info(port->dev, "tx stamp 0x%08x\n", ts);
> 
> This probably should be _debug instead.

It shouldn't be there; one of the problems of juggling patches between
trees is that things sometimes get fixed in one tree but not in the
"main" tree... will fix.  This also should've been combined with patch
6.

Anything else on any of the patches, so we don't have to continue doing
this one comment at a time?
Richard Cochran Sept. 9, 2020, 6 p.m. UTC | #3
On Tue, Sep 08, 2020 at 11:00:41PM +0100, Russell King wrote:

> +static bool mvpp2_tx_hw_tstamp(struct mvpp2_port *port,
> +			       struct mvpp2_tx_desc *tx_desc,
> +			       struct sk_buff *skb)
> +{
> +	unsigned int mtype, type, i, offset;
> +	struct mvpp2_hwtstamp_queue *queue;
> +	struct ptp_header *hdr;
> +	u64 ptpdesc;
> +
> +	if (port->priv->hw_version == MVPP21 ||
> +	    port->tx_hwtstamp_type == HWTSTAMP_TX_OFF)
> +		return false;
> +
> +	type = ptp_classify_raw(skb);
> +	if (!type)
> +		return false;
> +
> +	hdr = ptp_parse_header(skb, type);
> +	if (!hdr)
> +		return false;

At this point, the skb will be queued up to receive a transmit time
stamp, and so it should be marked with:

	skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;


The rest of the patch looks reasonable.

Acked-by: Richard Cochran <richardcochran@gmail.com>
Richard Cochran Sept. 11, 2020, 4:08 p.m. UTC | #4
On Wed, Sep 09, 2020 at 11:00:47AM -0700, Richard Cochran wrote:
> On Tue, Sep 08, 2020 at 11:00:41PM +0100, Russell King wrote:
> 
> > +static bool mvpp2_tx_hw_tstamp(struct mvpp2_port *port,
> > +			       struct mvpp2_tx_desc *tx_desc,
> > +			       struct sk_buff *skb)
> > +{
> > +	unsigned int mtype, type, i, offset;
> > +	struct mvpp2_hwtstamp_queue *queue;
> > +	struct ptp_header *hdr;
> > +	u64 ptpdesc;
> > +
> > +	if (port->priv->hw_version == MVPP21 ||
> > +	    port->tx_hwtstamp_type == HWTSTAMP_TX_OFF)
> > +		return false;
> > +
> > +	type = ptp_classify_raw(skb);
> > +	if (!type)
> > +		return false;
> > +
> > +	hdr = ptp_parse_header(skb, type);
> > +	if (!hdr)
> > +		return false;
> 
> At this point, the skb will be queued up to receive a transmit time
> stamp, and so it should be marked with:
> 
> 	skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;

Russell, since this series went in already, can you follow up with
a patch for this please?

Thanks,
Richard
diff mbox series

Patch

diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
index e0341a85f7f1..4f21f0620e2a 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
@@ -12,6 +12,7 @@ 
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <linux/phylink.h>
 #include <net/flow_offload.h>
@@ -804,6 +805,43 @@  enum mvpp2_prs_l3_cast {
 	MVPP2_PRS_L3_BROAD_CAST
 };
 
+/* PTP descriptor constants. The low bits of the descriptor are stored
+ * separately from the high bits.
+ */
+#define MVPP22_PTP_DESC_MASK_LOW	0xfff
+
+/* PTPAction */
+enum mvpp22_ptp_action {
+	MVPP22_PTP_ACTION_NONE = 0,
+	MVPP22_PTP_ACTION_FORWARD = 1,
+	MVPP22_PTP_ACTION_CAPTURE = 3,
+	/* The following have not been verified */
+	MVPP22_PTP_ACTION_ADDTIME = 4,
+	MVPP22_PTP_ACTION_ADDCORRECTEDTIME = 5,
+	MVPP22_PTP_ACTION_CAPTUREADDTIME = 6,
+	MVPP22_PTP_ACTION_CAPTUREADDCORRECTEDTIME = 7,
+	MVPP22_PTP_ACTION_ADDINGRESSTIME = 8,
+	MVPP22_PTP_ACTION_CAPTUREADDINGRESSTIME = 9,
+	MVPP22_PTP_ACTION_CAPTUREINGRESSTIME = 10,
+};
+
+/* PTPPacketFormat */
+enum mvpp22_ptp_packet_format {
+	MVPP22_PTP_PKT_FMT_PTPV2 = 0,
+	MVPP22_PTP_PKT_FMT_PTPV1 = 1,
+	MVPP22_PTP_PKT_FMT_Y1731 = 2,
+	MVPP22_PTP_PKT_FMT_NTPTS = 3,
+	MVPP22_PTP_PKT_FMT_NTPRX = 4,
+	MVPP22_PTP_PKT_FMT_NTPTX = 5,
+	MVPP22_PTP_PKT_FMT_TWAMP = 6,
+};
+
+#define MVPP22_PTP_ACTION(x)		(((x) & 15) << 0)
+#define MVPP22_PTP_PACKETFORMAT(x)	(((x) & 7) << 4)
+#define MVPP22_PTP_MACTIMESTAMPINGEN	BIT(11)
+#define MVPP22_PTP_TIMESTAMPENTRYID(x)	(((x) & 31) << 12)
+#define MVPP22_PTP_TIMESTAMPQUEUESELECT	BIT(18)
+
 /* BM constants */
 #define MVPP2_BM_JUMBO_BUF_NUM		512
 #define MVPP2_BM_LONG_BUF_NUM		1024
@@ -1022,6 +1060,11 @@  struct mvpp2_ethtool_fs {
 	struct ethtool_rxnfc rxnfc;
 };
 
+struct mvpp2_hwtstamp_queue {
+	struct sk_buff *skb[32];
+	u8 next;
+};
+
 struct mvpp2_port {
 	u8 id;
 
@@ -1108,6 +1151,8 @@  struct mvpp2_port {
 
 	bool hwtstamp;
 	bool rx_hwtstamp;
+	enum hwtstamp_tx_types tx_hwtstamp_type;
+	struct mvpp2_hwtstamp_queue tx_hwtstamp_queue[2];
 };
 
 /* The mvpp2_tx_desc and mvpp2_rx_desc structures describe the
@@ -1176,7 +1221,8 @@  struct mvpp22_tx_desc {
 	u8  packet_offset;
 	u8  phys_txq;
 	__le16 data_size;
-	__le64 reserved1;
+	__le32 ptp_descriptor;
+	__le32 reserved2;
 	__le64 buf_dma_addr_ptp;
 	__le64 buf_cookie_misc;
 };
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 07751e543842..b5db9254a4f9 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -28,6 +28,7 @@ 
 #include <linux/phy.h>
 #include <linux/phylink.h>
 #include <linux/phy/phy.h>
+#include <linux/ptp_classify.h>
 #include <linux/clk.h>
 #include <linux/hrtimer.h>
 #include <linux/ktime.h>
@@ -2984,13 +2985,19 @@  static irqreturn_t mvpp2_isr(int irq, void *dev_id)
 
 static void mvpp2_isr_handle_ptp_queue(struct mvpp2_port *port, int nq)
 {
+	struct skb_shared_hwtstamps shhwtstamps;
+	struct mvpp2_hwtstamp_queue *queue;
+	struct sk_buff *skb;
 	void __iomem *ptp_q;
+	unsigned int id;
 	u32 r0, r1, r2;
 
 	ptp_q = port->priv->iface_base + MVPP22_PTP_BASE(port->gop_id);
 	if (nq)
 		ptp_q += MVPP22_PTP_TX_Q1_R0 - MVPP22_PTP_TX_Q0_R0;
 
+	queue = &port->tx_hwtstamp_queue[nq];
+
 	while (1) {
 		r0 = readl_relaxed(ptp_q + MVPP22_PTP_TX_Q0_R0) & 0xffff;
 		if (!r0)
@@ -2998,6 +3005,19 @@  static void mvpp2_isr_handle_ptp_queue(struct mvpp2_port *port, int nq)
 
 		r1 = readl_relaxed(ptp_q + MVPP22_PTP_TX_Q0_R1) & 0xffff;
 		r2 = readl_relaxed(ptp_q + MVPP22_PTP_TX_Q0_R2) & 0xffff;
+
+		id = (r0 >> 1) & 31;
+
+		skb = queue->skb[id];
+		queue->skb[id] = NULL;
+		if (skb) {
+			u32 ts = r2 << 19 | r1 << 3 | r0 >> 13;
+
+			netdev_info(port->dev, "tx stamp 0x%08x\n", ts);
+			mvpp22_tai_tstamp(port->priv->tai, ts, &shhwtstamps);
+			skb_tstamp_tx(skb, &shhwtstamps);
+			dev_kfree_skb_any(skb);
+		}
 	}
 }
 
@@ -3654,6 +3674,92 @@  tx_desc_unmap_put(struct mvpp2_port *port, struct mvpp2_tx_queue *txq,
 	mvpp2_txq_desc_put(txq);
 }
 
+static void mvpp2_txdesc_clear_ptp(struct mvpp2_port *port,
+				   struct mvpp2_tx_desc *desc)
+{
+	/* We only need to clear the low bits */
+	if (port->priv->hw_version != MVPP21)
+		desc->pp22.ptp_descriptor &=
+			cpu_to_le32(~MVPP22_PTP_DESC_MASK_LOW);
+}
+
+static bool mvpp2_tx_hw_tstamp(struct mvpp2_port *port,
+			       struct mvpp2_tx_desc *tx_desc,
+			       struct sk_buff *skb)
+{
+	unsigned int mtype, type, i, offset;
+	struct mvpp2_hwtstamp_queue *queue;
+	struct ptp_header *hdr;
+	u64 ptpdesc;
+
+	if (port->priv->hw_version == MVPP21 ||
+	    port->tx_hwtstamp_type == HWTSTAMP_TX_OFF)
+		return false;
+
+	type = ptp_classify_raw(skb);
+	if (!type)
+		return false;
+
+	hdr = ptp_parse_header(skb, type);
+	if (!hdr)
+		return false;
+
+	ptpdesc = MVPP22_PTP_MACTIMESTAMPINGEN |
+		  MVPP22_PTP_ACTION_CAPTURE;
+	queue = &port->tx_hwtstamp_queue[0];
+
+	switch (type & PTP_CLASS_VMASK) {
+	case PTP_CLASS_V1:
+		ptpdesc |= MVPP22_PTP_PACKETFORMAT(MVPP22_PTP_PKT_FMT_PTPV1);
+		break;
+
+	case PTP_CLASS_V2:
+		ptpdesc |= MVPP22_PTP_PACKETFORMAT(MVPP22_PTP_PKT_FMT_PTPV2);
+		mtype = hdr->tsmt & 15;
+		/* Direct PTP Sync messages to queue 1 */
+		if (mtype == 0) {
+			ptpdesc |= MVPP22_PTP_TIMESTAMPQUEUESELECT;
+			queue = &port->tx_hwtstamp_queue[1];
+		}
+		break;
+	}
+
+	/* Take a reference on the skb and insert into our queue */
+	i = queue->next;
+	queue->next = (i + 1) & 31;
+	if (queue->skb[i])
+		dev_kfree_skb_any(queue->skb[i]);
+	queue->skb[i] = skb_get(skb);
+
+	ptpdesc |= MVPP22_PTP_TIMESTAMPENTRYID(i);
+
+	/*
+	 * 3:0		- PTPAction
+	 * 6:4		- PTPPacketFormat
+	 * 7		- PTP_CF_WraparoundCheckEn
+	 * 9:8		- IngressTimestampSeconds[1:0]
+	 * 10		- Reserved
+	 * 11		- MACTimestampingEn
+	 * 17:12	- PTP_TimestampQueueEntryID[5:0]
+	 * 18		- PTPTimestampQueueSelect
+	 * 19		- UDPChecksumUpdateEn
+	 * 27:20	- TimestampOffset
+	 *			PTP, NTPTransmit, OWAMP/TWAMP - L3 to PTP header
+	 *			NTPTs, Y.1731 - L3 to timestamp entry
+	 * 35:28	- UDP Checksum Offset
+	 *
+	 * stored in tx descriptor bits 75:64 (11:0) and 191:168 (35:12)
+	 */
+	tx_desc->pp22.ptp_descriptor &=
+		cpu_to_le32(~MVPP22_PTP_DESC_MASK_LOW);
+	tx_desc->pp22.ptp_descriptor |=
+		cpu_to_le32(ptpdesc & MVPP22_PTP_DESC_MASK_LOW);
+	tx_desc->pp22.buf_dma_addr_ptp &= cpu_to_le64(~0xffffff0000000000ULL);
+	tx_desc->pp22.buf_dma_addr_ptp |= cpu_to_le64((ptpdesc >> 12) << 40);
+
+	return true;
+}
+
 /* Handle tx fragmentation processing */
 static int mvpp2_tx_frag_process(struct mvpp2_port *port, struct sk_buff *skb,
 				 struct mvpp2_tx_queue *aggr_txq,
@@ -3670,6 +3776,7 @@  static int mvpp2_tx_frag_process(struct mvpp2_port *port, struct sk_buff *skb,
 		void *addr = skb_frag_address(frag);
 
 		tx_desc = mvpp2_txq_next_desc_get(aggr_txq);
+		mvpp2_txdesc_clear_ptp(port, tx_desc);
 		mvpp2_txdesc_txq_set(port, tx_desc, txq->id);
 		mvpp2_txdesc_size_set(port, tx_desc, skb_frag_size(frag));
 
@@ -3719,6 +3826,7 @@  static inline void mvpp2_tso_put_hdr(struct sk_buff *skb,
 	struct mvpp2_tx_desc *tx_desc = mvpp2_txq_next_desc_get(aggr_txq);
 	dma_addr_t addr;
 
+	mvpp2_txdesc_clear_ptp(port, tx_desc);
 	mvpp2_txdesc_txq_set(port, tx_desc, txq->id);
 	mvpp2_txdesc_size_set(port, tx_desc, hdr_sz);
 
@@ -3743,6 +3851,7 @@  static inline int mvpp2_tso_put_data(struct sk_buff *skb,
 	struct mvpp2_tx_desc *tx_desc = mvpp2_txq_next_desc_get(aggr_txq);
 	dma_addr_t buf_dma_addr;
 
+	mvpp2_txdesc_clear_ptp(port, tx_desc);
 	mvpp2_txdesc_txq_set(port, tx_desc, txq->id);
 	mvpp2_txdesc_size_set(port, tx_desc, sz);
 
@@ -3859,6 +3968,9 @@  static netdev_tx_t mvpp2_tx(struct sk_buff *skb, struct net_device *dev)
 
 	/* Get a descriptor for the first part of the packet */
 	tx_desc = mvpp2_txq_next_desc_get(aggr_txq);
+	if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) ||
+	    !mvpp2_tx_hw_tstamp(port, tx_desc, skb))
+		mvpp2_txdesc_clear_ptp(port, tx_desc);
 	mvpp2_txdesc_txq_set(port, tx_desc, txq->id);
 	mvpp2_txdesc_size_set(port, tx_desc, skb_headlen(skb));
 
@@ -4618,6 +4730,7 @@  static int mvpp2_set_ts_config(struct mvpp2_port *port, struct ifreq *ifr)
 {
 	struct hwtstamp_config config;
 	void __iomem *ptp;
+	u32 gcr, int_mask;
 
 	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
 		return -EFAULT;
@@ -4625,30 +4738,51 @@  static int mvpp2_set_ts_config(struct mvpp2_port *port, struct ifreq *ifr)
 	if (config.flags)
 		return -EINVAL;
 
-	if (config.tx_type != HWTSTAMP_TX_OFF)
+	if (config.tx_type != HWTSTAMP_TX_OFF &&
+	    config.tx_type != HWTSTAMP_TX_ON)
 		return -ERANGE;
 
 	ptp = port->priv->iface_base + MVPP22_PTP_BASE(port->gop_id);
+
+	int_mask = gcr = 0;
+	if (config.tx_type != HWTSTAMP_TX_OFF) {
+		gcr |= MVPP22_PTP_GCR_TSU_ENABLE | MVPP22_PTP_GCR_TX_RESET;
+		int_mask |= MVPP22_PTP_INT_MASK_QUEUE1 |
+			    MVPP22_PTP_INT_MASK_QUEUE0;
+	}
+
+	/* It seems we must also release the TX reset when enabling the TSU */
+	if (config.rx_filter != HWTSTAMP_FILTER_NONE)
+		gcr |= MVPP22_PTP_GCR_TSU_ENABLE | MVPP22_PTP_GCR_RX_RESET |
+		       MVPP22_PTP_GCR_TX_RESET;
+
+	if (gcr & MVPP22_PTP_GCR_TSU_ENABLE)
+		mvpp22_tai_start(port->priv->tai);
+
 	if (config.rx_filter != HWTSTAMP_FILTER_NONE) {
 		config.rx_filter = HWTSTAMP_FILTER_ALL;
-		mvpp22_tai_start(port->priv->tai);
 		mvpp2_modify(ptp + MVPP22_PTP_GCR,
 			     MVPP22_PTP_GCR_RX_RESET |
 			     MVPP22_PTP_GCR_TX_RESET |
-			     MVPP22_PTP_GCR_TSU_ENABLE,
-			     MVPP22_PTP_GCR_RX_RESET |
-			     MVPP22_PTP_GCR_TX_RESET |
-			     MVPP22_PTP_GCR_TSU_ENABLE);
+			     MVPP22_PTP_GCR_TSU_ENABLE, gcr);
 		port->rx_hwtstamp = true;
 	} else {
 		port->rx_hwtstamp = false;
 		mvpp2_modify(ptp + MVPP22_PTP_GCR,
 			     MVPP22_PTP_GCR_RX_RESET |
 			     MVPP22_PTP_GCR_TX_RESET |
-			     MVPP22_PTP_GCR_TSU_ENABLE, 0);
-		mvpp22_tai_stop(port->priv->tai);
+			     MVPP22_PTP_GCR_TSU_ENABLE, gcr);
 	}
 
+	mvpp2_modify(ptp + MVPP22_PTP_INT_MASK,
+		     MVPP22_PTP_INT_MASK_QUEUE1 |
+		     MVPP22_PTP_INT_MASK_QUEUE0, int_mask);
+
+	if (!(gcr & MVPP22_PTP_GCR_TSU_ENABLE))
+		mvpp22_tai_stop(port->priv->tai);
+
+	port->tx_hwtstamp_type = config.tx_type;
+
 	if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
 		return -EFAULT;
 
@@ -4661,7 +4795,7 @@  static int mvpp2_get_ts_config(struct mvpp2_port *port, struct ifreq *ifr)
 
 	memset(&config, 0, sizeof(config));
 
-	config.tx_type = HWTSTAMP_TX_OFF;
+	config.tx_type = port->tx_hwtstamp_type;
 	config.rx_filter = port->rx_hwtstamp ?
 		HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE;
 
@@ -4683,9 +4817,11 @@  static int mvpp2_ethtool_get_ts_info(struct net_device *dev,
 	info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
 				SOF_TIMESTAMPING_RX_SOFTWARE |
 				SOF_TIMESTAMPING_SOFTWARE |
+				SOF_TIMESTAMPING_TX_HARDWARE |
 				SOF_TIMESTAMPING_RX_HARDWARE |
 				SOF_TIMESTAMPING_RAW_HARDWARE;
-	info->tx_types = BIT(HWTSTAMP_TX_OFF);
+	info->tx_types = BIT(HWTSTAMP_TX_OFF) |
+			 BIT(HWTSTAMP_TX_ON);
 	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
 			   BIT(HWTSTAMP_FILTER_ALL);