Add tracepoints for Realtek r8169
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 549be1c..a448482 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -32,6 +32,9 @@
 #include <linux/ipv6.h>
 #include <net/ip6_checksum.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/net_rtl8169.h>
+
 #define MODULENAME "r8169"
 
 #define FIRMWARE_8168D_1	"rtl_nic/rtl8168d-1.fw"
@@ -5997,6 +6000,28 @@
 	return slots_avail > nr_frags;
 }
 
+static void dhowells_trace_xmit(struct rtl8169_private *tp)
+{
+	unsigned int dirty_tx, cursor, n = 0;
+
+	dirty_tx = tp->dirty_tx;
+	smp_rmb();
+
+	for (cursor = dirty_tx; cursor != tp->cur_tx; cursor++) {
+		unsigned int entry = cursor % NUM_TX_DESC;
+		u32 status;
+
+		status = le32_to_cpu(tp->TxDescArray[entry].opts1);
+		if (status & DescOwn)
+			break;
+		n++;
+		if (n >= 32)
+			break;
+	}
+
+	trace_net_rtl8169_tx(tp->dev, dirty_tx, tp->cur_tx, n);
+}
+
 static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
 				      struct net_device *dev)
 {
@@ -6058,6 +6083,7 @@
 
 	/* Force all memory writes to complete before notifying device */
 	wmb();
+	dhowells_trace_xmit(tp);
 
 	tp->cur_tx += frags + 1;
 
@@ -6197,6 +6223,8 @@
 		if (tp->cur_tx != dirty_tx)
 			RTL_W8(tp, TxPoll, NPQ);
 	}
+
+	trace_net_rtl8169_napi_tx(dev, tx_left);
 }
 
 static inline int rtl8169_fragmented_frame(u32 status)
@@ -6327,6 +6355,7 @@
 	count = cur_rx - tp->cur_rx;
 	tp->cur_rx = cur_rx;
 
+	trace_net_rtl8169_napi_rx(dev, count, budget);
 	return count;
 }
 
@@ -6338,6 +6367,9 @@
 	if (!tp->irq_enabled || status == 0xffff || !(status & tp->irq_mask))
 		return IRQ_NONE;
 
+	if (status && status != 0xffff)
+		trace_net_rtl8169_interrupt(tp->napi.dev, status);
+
 	if (unlikely(status & SYSErr)) {
 		rtl8169_pcierr_interrupt(tp->dev);
 		goto out;
@@ -6399,6 +6431,7 @@
 	int work_done;
 
 	work_done = rtl_rx(dev, tp, (u32) budget);
+	trace_net_rtl8169_poll(dev, work_done);
 
 	rtl_tx(dev, tp, budget);
 
diff --git a/include/trace/events/net_rtl8169.h b/include/trace/events/net_rtl8169.h
new file mode 100644
index 0000000..8cc911b
--- /dev/null
+++ b/include/trace/events/net_rtl8169.h
@@ -0,0 +1,125 @@
+/* Realtek RTL8169 tracepoints
+ *
+ * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM net_rtl8169
+
+#if !defined(_TRACE_NET_RTL8169_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_NET_RTL8169_H
+
+#include <linux/tracepoint.h>
+#include <linux/errqueue.h>
+
+
+TRACE_EVENT(net_rtl8169_interrupt,
+	    TP_PROTO(struct net_device *netdev, u16 status),
+
+	    TP_ARGS(netdev, status),
+
+	    TP_STRUCT__entry(
+		    __field(u16,			status		)
+		    __array(char,			name, IFNAMSIZ	)
+			     ),
+
+	    TP_fast_assign(
+		    __entry->status = status;
+		    memcpy(__entry->name, netdev->name, IFNAMSIZ);
+			   ),
+
+	    TP_printk("%s st=%x", __entry->name, __entry->status)
+	    );
+
+TRACE_EVENT(net_rtl8169_poll,
+	    TP_PROTO(struct net_device *netdev, int work_done),
+
+	    TP_ARGS(netdev, work_done),
+
+	    TP_STRUCT__entry(
+		    __field(int,			work_done	)
+		    __array(char,			name, IFNAMSIZ	)
+			     ),
+
+	    TP_fast_assign(
+		    __entry->work_done = work_done;
+		    memcpy(__entry->name, netdev->name, IFNAMSIZ);
+			   ),
+
+	    TP_printk("%s wd=%d", __entry->name, __entry->work_done)
+	    );
+
+TRACE_EVENT(net_rtl8169_napi_rx,
+	    TP_PROTO(struct net_device *netdev, unsigned int count, u32 budget),
+
+	    TP_ARGS(netdev, count, budget),
+
+	    TP_STRUCT__entry(
+		    __field(unsigned int,		count		)
+		    __field(u32,			budget		)
+		    __array(char,			name, IFNAMSIZ	)
+			     ),
+
+	    TP_fast_assign(
+		    __entry->count = count;
+		    __entry->budget = budget;
+		    memcpy(__entry->name, netdev->name, IFNAMSIZ);
+			   ),
+
+	    TP_printk("%s count=%d/%d",
+		      __entry->name, __entry->count, __entry->budget)
+	    );
+
+TRACE_EVENT(net_rtl8169_napi_tx,
+	    TP_PROTO(struct net_device *netdev, unsigned int tx_left),
+
+	    TP_ARGS(netdev, tx_left),
+
+	    TP_STRUCT__entry(
+		    __field(unsigned int,		tx_left		)
+		    __array(char,			name, IFNAMSIZ	)
+			     ),
+
+	    TP_fast_assign(
+		    __entry->tx_left = tx_left;
+		    memcpy(__entry->name, netdev->name, IFNAMSIZ);
+			   ),
+
+	    TP_printk("%s l=%u",
+		      __entry->name, __entry->tx_left)
+	    );
+
+TRACE_EVENT(net_rtl8169_tx,
+	    TP_PROTO(struct net_device *netdev, unsigned int dirty_tx,
+		     unsigned int cur_tx, unsigned int n),
+
+	    TP_ARGS(netdev, dirty_tx, cur_tx, n),
+
+	    TP_STRUCT__entry(
+		    __field(unsigned int,		dirty_tx	)
+		    __field(unsigned int,		cur_tx		)
+		    __field(unsigned int,		n		)
+		    __array(char,			name, IFNAMSIZ	)
+			     ),
+
+	    TP_fast_assign(
+		    __entry->dirty_tx = dirty_tx;
+		    __entry->cur_tx = cur_tx;
+		    __entry->n = n;
+		    memcpy(__entry->name, netdev->name, IFNAMSIZ);
+			   ),
+
+	    TP_printk("%s p=%u/%u n=%u",
+		      __entry->name, __entry->dirty_tx, __entry->cur_tx,
+		      __entry->n)
+	    );
+
+#endif /* _TRACE_NET_RTL8169_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>