From f68d43fbd71a12a31da21fe825987f87179c125b Mon Sep 17 00:00:00 2001
From: Alessandro Rubini <rubini@gnudd.com>
Date: Sat, 18 Dec 2010 17:35:08 +0100
Subject: [PATCH] r8169: added tx timestamp (possibly too late)

This adds actual stamping in the tx-done interrupt, for the fake
hw-timestap in the RTL8169 device. The stamp is taken with
getnstimeofday, keeping only the last 4 digits and 2 digits of the
seconds field.

Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
---
 drivers/net/r8169.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 4b4cca0..2a85588 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -4447,6 +4447,25 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
 	rtl8169_schedule_work(dev, rtl8169_reinit_task);
 }
 
+static inline void __tstamp_tx(struct sk_buff *skb)
+{
+	union skb_shared_tx *shtx;
+	struct timespec ts;
+
+	getnstimeofday(&ts);
+	shtx = skb_tx(skb);
+	if (unlikely(shtx->hardware)) {
+		struct skb_shared_hwtstamps shhwtstamps;
+
+		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+		ts.tv_sec %=10000; /* sys tstamp different from sw one */
+		shhwtstamps.syststamp = timespec_to_ktime(ts);
+		ts.tv_sec %=100; /* and hw tstamp is still different */
+		shhwtstamps.hwtstamp = timespec_to_ktime(ts);
+		skb_tstamp_tx(skb, &shhwtstamps);
+	}
+}
+
 static void rtl8169_tx_interrupt(struct net_device *dev,
 				 struct rtl8169_private *tp,
 				 void __iomem *ioaddr)
@@ -4474,6 +4493,9 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
 		rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry);
 
 		if (status & LastFrag) {
+			/* We may need to tx-timestamp. FIXME: too late? */
+			if (unlikely(tp->hwtstamp & TSTAMP_TX))
+				__tstamp_tx(tx_skb->skb);
 			dev_kfree_skb(tx_skb->skb);
 			tx_skb->skb = NULL;
 		}
-- 
1.5.6.5

