[PATCH net-next] r8169: Add some tracepoints for watching rx/tx events

From: David Howells
Date: Thu Oct 04 2018 - 04:31:13 EST


Add some tracepoints into the Realtek r8169 driver to watch events involved
in the reception and transmission of packets, including:

(1) Interrupts occurring. The device status is logged.

(2) NAPI polling. The device status is logged.

(3) Packet received and about to be handed off. The sk_buff address is
logged.

(4) Packet queued for transmission and device poked. The sk_buff address
is logged along with the revised Tx ring indices.

(5) Packet removed from Tx ring after transmission. The sk_buff address
is logged along with the Tx ring slot number.

Signed-off-by: David Howells <dhowells@xxxxxxxxxx>
---

drivers/net/ethernet/realtek/r8169.c | 9 ++
include/trace/events/net_rtl8169.h | 125 ++++++++++++++++++++++++++++++++++
2 files changed, 134 insertions(+)
create mode 100644 include/trace/events/net_rtl8169.h

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 9a5e2969df61..1d4d3d953628 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -31,6 +31,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"
@@ -6192,6 +6195,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
RTL_W8(tp, TxPoll, NPQ);

mmiowb();
+ trace_net_rtl8169_tx(tp->dev, tp->dirty_tx, tp->cur_tx, skb);

if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
/* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
@@ -6297,6 +6301,7 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
rtl8169_unmap_tx_skb(tp_to_dev(tp), tx_skb,
tp->TxDescArray + entry);
if (status & LastFrag) {
+ trace_net_rtl8169_tx_done(dev, dirty_tx, tx_skb->skb);
u64_stats_update_begin(&tp->tx_stats.syncp);
tp->tx_stats.packets++;
tp->tx_stats.bytes += tx_skb->skb->len;
@@ -6447,6 +6452,7 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget
if (skb->pkt_type == PACKET_MULTICAST)
dev->stats.multicast++;

+ trace_net_rtl8169_rx(dev, skb);
napi_gro_receive(&tp->napi, skb);

u64_stats_update_begin(&tp->rx_stats.syncp);
@@ -6473,6 +6479,8 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
if (status == 0xffff || !(status & (RTL_EVENT_NAPI | tp->event_slow)))
return IRQ_NONE;

+ trace_net_rtl8169_interrupt(tp->napi.dev, status);
+
rtl_irq_disable(tp);
napi_schedule_irqoff(&tp->napi);

@@ -6554,6 +6562,7 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)

status = rtl_get_events(tp);
rtl_ack_events(tp, status & ~tp->event_slow);
+ trace_net_rtl8169_poll(dev, status);

if (status & RTL_EVENT_NAPI_RX)
work_done = rtl_rx(dev, tp, (u32) budget);
diff --git a/include/trace/events/net_rtl8169.h b/include/trace/events/net_rtl8169.h
new file mode 100644
index 000000000000..15b3984c3939
--- /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@xxxxxxxxxx)
+ *
+ * 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, 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_rx,
+ TP_PROTO(struct net_device *netdev, struct sk_buff *skb),
+
+ TP_ARGS(netdev, skb),
+
+ TP_STRUCT__entry(
+ __field(struct sk_buff *, skb )
+ __array(char, name, IFNAMSIZ )
+ ),
+
+ TP_fast_assign(
+ __entry->skb = skb;
+ memcpy(__entry->name, netdev->name, IFNAMSIZ);
+ ),
+
+ TP_printk("%s skb=%p", __entry->name, __entry->skb)
+ );
+
+TRACE_EVENT(net_rtl8169_tx_done,
+ TP_PROTO(struct net_device *netdev, unsigned int dirty_tx,
+ struct sk_buff *skb),
+
+ TP_ARGS(netdev, dirty_tx, skb),
+
+ TP_STRUCT__entry(
+ __field(struct sk_buff *, skb)
+ __field(unsigned int, dirty_tx)
+ __array(char, name, IFNAMSIZ )
+ ),
+
+ TP_fast_assign(
+ __entry->skb = skb;
+ __entry->dirty_tx = dirty_tx;
+ memcpy(__entry->name, netdev->name, IFNAMSIZ);
+ ),
+
+ TP_printk("%s p=%u skb=%p",
+ __entry->name, __entry->dirty_tx, __entry->skb)
+ );
+
+TRACE_EVENT(net_rtl8169_tx,
+ TP_PROTO(struct net_device *netdev, unsigned int dirty_tx,
+ unsigned int cur_tx, struct sk_buff *skb),
+
+ TP_ARGS(netdev, dirty_tx, cur_tx, skb),
+
+ TP_STRUCT__entry(
+ __field(struct sk_buff *, skb )
+ __field(unsigned int, dirty_tx )
+ __field(unsigned int, cur_tx )
+ __array(char, name, IFNAMSIZ )
+ ),
+
+ TP_fast_assign(
+ __entry->skb = skb;
+ __entry->dirty_tx = dirty_tx;
+ __entry->cur_tx = cur_tx;
+ memcpy(__entry->name, netdev->name, IFNAMSIZ);
+ ),
+
+ TP_printk("%s p=%u-%u skb=%p",
+ __entry->name, __entry->dirty_tx, __entry->cur_tx,
+ __entry->skb)
+ );
+
+#endif /* _TRACE_NET_RTL8169_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>