[PATCH 1/2] r8169: debugfs support.
From: Francois Romieu
Date: Fri May 25 2012 - 05:18:03 EST
Mostly copied from Stephen Hemminger's sky2.
Signed-off-by: Francois Romieu <romieu@xxxxxxxxxxxxx>
---
drivers/net/ethernet/realtek/Kconfig | 9 ++
drivers/net/ethernet/realtek/r8169.c | 186 ++++++++++++++++++++++++++++++++++
2 files changed, 195 insertions(+)
diff --git a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek/Kconfig
index 5821966..4f7930c 100644
--- a/drivers/net/ethernet/realtek/Kconfig
+++ b/drivers/net/ethernet/realtek/Kconfig
@@ -115,4 +115,13 @@ config R8169
To compile this driver as a module, choose M here: the module
will be called r8169. This is recommended.
+config R8169_DEBUGFS
+ bool "Realtek 8169 gigabit ethernet debugfs support"
+ depends on R8169 && DEBUG_FS
+ ---help---
+ This option adds the ability to dump driver state for debugging.
+ Debug data is available in the /sys/kernel/debug/r8169/ethX file.
+
+ If unsure, say N.
+
endif # NET_VENDOR_REALTEK
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 9757ce3..abb028a 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -28,6 +28,7 @@
#include <linux/firmware.h>
#include <linux/pci-aspm.h>
#include <linux/prefetch.h>
+#include <linux/debugfs.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -60,6 +61,10 @@
#define dprintk(fmt, args...) do {} while (0)
#endif /* RTL8169_DEBUG */
+#ifdef CONFIG_R8169_DEBUGFS
+static struct dentry *rtl_debug;
+#endif
+
#define R8169_MSG_DEFAULT \
(NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
@@ -774,6 +779,10 @@ struct rtl8169_private {
} phy_action;
} *rtl_fw;
#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN)
+
+#ifdef CONFIG_R8169_DEBUGFS
+ struct dentry *debugfs;
+#endif
};
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@xxxxxxxxxxxxxxx>");
@@ -6692,14 +6701,191 @@ static struct pci_driver rtl8169_pci_driver = {
.driver.pm = RTL8169_PM_OPS,
};
+#ifdef CONFIG_R8169_DEBUGFS
+
+static struct dentry *rtl_debug;
+
+struct Desc {
+ __le32 opts1;
+ __le32 opts2;
+ __le64 addr;
+};
+
+union rtl_ring {
+ struct RxDesc *rx;
+ struct TxDesc *tx;
+ struct Desc *anon;
+};
+
+static void rtl_debug_show_ring(struct seq_file *seq, union rtl_ring u, int n)
+{
+ struct Desc *desc = u.anon;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ seq_printf(seq, "[%03d] %08x %08x %0llx\n", i, desc->opts1,
+ desc->opts2, (u64)desc->addr);
+ desc++;
+ }
+}
+
+#define DECLARE_RTL_DEBUG_FOPS(name) \
+static const struct file_operations rtl_debug_fops_##name = { \
+ .owner = THIS_MODULE, \
+ .open = rtl_debug_open_##name, \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .release = single_release, \
+}
+
+static int rtl_debug_show_rx(struct seq_file *seq, void *v)
+{
+ struct rtl8169_private *tp = seq->private;
+ union rtl_ring u = { .rx = tp->RxDescArray };
+
+ seq_printf(seq, "Rx: dirty=%08x current=%08x\n", tp->dirty_rx,
+ tp->cur_rx);
+ rtl_debug_show_ring(seq, u, NUM_RX_DESC);
+
+ return 0;
+}
+
+static int rtl_debug_open_rx(struct inode *inode, struct file *file)
+{
+ return single_open(file, rtl_debug_show_rx, inode->i_private);
+}
+
+DECLARE_RTL_DEBUG_FOPS(rx);
+
+static int rtl_debug_show_tx(struct seq_file *seq, void *v)
+{
+ struct rtl8169_private *tp = seq->private;
+ union rtl_ring u = { .tx = tp->TxDescArray };
+
+ seq_printf(seq, "Tx: dirty=%08x current=%08x queue:%s\n", tp->dirty_tx,
+ tp->cur_tx, netif_queue_stopped(tp->dev) ? "off" : "on");
+ rtl_debug_show_ring(seq, u, NUM_TX_DESC);
+
+ return 0;
+}
+
+static int rtl_debug_open_tx(struct inode *inode, struct file *file)
+{
+ return single_open(file, rtl_debug_show_tx, inode->i_private);
+}
+
+DECLARE_RTL_DEBUG_FOPS(tx);
+
+static void rtl_debug_create_tree(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ struct dentry *parent;
+ static const struct rtl_debug_ent {
+ const struct file_operations *fops;
+ const char *name;
+ } ent[] = {
+ { &rtl_debug_fops_rx, "rx" },
+ { &rtl_debug_fops_tx, "tx" },
+ { NULL, }
+ };
+ int i;
+
+ parent = debugfs_create_dir(dev->name, rtl_debug);
+ if (IS_ERR(parent))
+ goto err;
+
+ for (i = 0; i < ARRAY_SIZE(ent) - 1; i++) {
+ const struct rtl_debug_ent *e = ent + i;
+ struct dentry *d;
+
+ d = debugfs_create_file(e->name, S_IRUGO, parent, tp, e->fops);
+ if (!d)
+ goto err_remove;
+ }
+
+ tp->debugfs = parent;
+ return;
+
+err_remove:
+ debugfs_remove_recursive(parent);
+err:
+ netif_err(tp, drv, dev, "failed to create debugfs tree.\n");
+ return;
+}
+
+
+static int rtl_device_event(struct notifier_block *unused, unsigned long event,
+ void *ptr)
+{
+ struct net_device *dev = ptr;
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ if (dev->netdev_ops->ndo_open != rtl_open || !rtl_debug)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_CHANGENAME:
+ if (tp->debugfs) {
+ tp->debugfs = debugfs_rename(rtl_debug, tp->debugfs,
+ rtl_debug, dev->name);
+ }
+ break;
+
+ case NETDEV_GOING_DOWN:
+ if (tp->debugfs) {
+ netdev_printk(KERN_DEBUG, dev, "remove debugfs\n");
+ debugfs_remove_recursive(tp->debugfs);
+ tp->debugfs = NULL;
+ }
+ break;
+
+ case NETDEV_UP:
+ rtl_debug_create_tree(dev);
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block rtl_debug_notifier = {
+ .notifier_call = rtl_device_event,
+};
+
+static __init void rtl_debug_init(void)
+{
+ struct dentry *ent;
+
+ ent = debugfs_create_dir(MODULENAME, NULL);
+ if (ent && !IS_ERR(ent)) {
+ rtl_debug = ent;
+ register_netdevice_notifier(&rtl_debug_notifier);
+ }
+}
+
+static __exit void rtl_debug_cleanup(void)
+{
+ if (rtl_debug) {
+ unregister_netdevice_notifier(&rtl_debug_notifier);
+ debugfs_remove(rtl_debug);
+ rtl_debug = NULL;
+ }
+}
+
+#else
+#define rtl_debug_init()
+#define rtl_debug_cleanup()
+#endif
+
static int __init rtl8169_init_module(void)
{
+ rtl_debug_init();
return pci_register_driver(&rtl8169_pci_driver);
}
static void __exit rtl8169_cleanup_module(void)
{
pci_unregister_driver(&rtl8169_pci_driver);
+ rtl_debug_cleanup();
}
module_init(rtl8169_init_module);
--
1.7.10.2
--x+6KMIRAuhnl3hBn
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="0002-r8169-irq-debug-stuff.patch"