From d3b127b9ecd60a6bff64269708b9099fe902c198 Mon Sep 17 00:00:00 2001
From: Alessandro Rubini <rubini@gnudd.com>
Date: Sat, 18 Dec 2010 17:01:30 +0100
Subject: [PATCH] r8169: added timestamp ioctl

This is a tool to fake hw timestamping on the 8169 gigabit ethernet.
The patch makes no actual stamping, which is added later.

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

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index cdc6a5c..4b4cca0 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
+#include <linux/net_tstamp.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -511,6 +512,9 @@ struct rtl8169_private {
 	struct mii_if_info mii;
 	struct rtl8169_counters counters;
 	u32 saved_wolopts;
+	int hwtstamp; /* hack -- ARub */
+#define TSTAMP_TX 1
+#define TSTAMP_RX 2
 };
 
 MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -2880,11 +2884,54 @@ static int rtl_set_mac_address(struct net_device *dev, void *p)
 	return 0;
 }
 
+/* This copied from gianfar -- ARub */
+static int rtl8169_tstamp_ioctl(struct net_device *netdev,
+                        struct ifreq *ifr, int cmd)
+{
+	struct hwtstamp_config config;
+	struct rtl8169_private *priv = netdev_priv(netdev);
+
+	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	/* reserved for future extensions */
+	if (config.flags)
+		return -EINVAL;
+
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+		priv->hwtstamp &= ~TSTAMP_TX;
+		break;
+	case HWTSTAMP_TX_ON:
+		priv->hwtstamp |= TSTAMP_TX;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (config.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		priv->hwtstamp &= ~TSTAMP_RX;
+		break;
+	default:
+		priv->hwtstamp |= TSTAMP_RX;
+		break;
+	}
+	printk("%s: stamp is %i\n", __func__, priv->hwtstamp);
+
+	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+		-EFAULT : 0;
+}
+
 static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	struct mii_ioctl_data *data = if_mii(ifr);
 
+	if (cmd == SIOCSHWTSTAMP) {
+		return rtl8169_tstamp_ioctl(dev, ifr, cmd);
+	}
+
 	return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV;
 }
 
-- 
1.5.6.5

