aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-10-16 15:15:54 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-16 21:10:29 -0400
commit678aa1f6ac8699ad69b347a22d9580425a587c14 (patch)
tree822791eef92fa6bbecefbf156eab2df2f23f7a7a
parentafa151b9b13e1c3ee0ee6f5a3323e7bf0e2df436 (diff)
skge: add a debug interface
Add a debugfs interface to look at internal ring state. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/net/Kconfig10
-rw-r--r--drivers/net/skge.c143
-rw-r--r--drivers/net/skge.h3
3 files changed, 156 insertions, 0 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 8f99a0626616..83d52c8acab0 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2173,6 +2173,16 @@ config SKGE
2173 To compile this driver as a module, choose M here: the module 2173 To compile this driver as a module, choose M here: the module
2174 will be called skge. This is recommended. 2174 will be called skge. This is recommended.
2175 2175
2176config SKGE_DEBUG
2177 bool "Debugging interface"
2178 depends on SKGE && DEBUG_FS
2179 help
2180 This option adds the ability to dump driver state for debugging.
2181 The file debugfs/skge/ethX displays the state of the internal
2182 transmit and receive rings.
2183
2184 If unsure, say N.
2185
2176config SKY2 2186config SKY2
2177 tristate "SysKonnect Yukon2 support" 2187 tristate "SysKonnect Yukon2 support"
2178 depends on PCI 2188 depends on PCI
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 953f8023f24c..cf7d79bc5e74 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -36,6 +36,8 @@
36#include <linux/delay.h> 36#include <linux/delay.h>
37#include <linux/crc32.h> 37#include <linux/crc32.h>
38#include <linux/dma-mapping.h> 38#include <linux/dma-mapping.h>
39#include <linux/debugfs.h>
40#include <linux/seq_file.h>
39#include <linux/mii.h> 41#include <linux/mii.h>
40#include <asm/irq.h> 42#include <asm/irq.h>
41 43
@@ -3676,6 +3678,145 @@ static int skge_reset(struct skge_hw *hw)
3676 return 0; 3678 return 0;
3677} 3679}
3678 3680
3681
3682#ifdef CONFIG_SKGE_DEBUG
3683
3684static struct dentry *skge_debug;
3685
3686static int skge_debug_show(struct seq_file *seq, void *v)
3687{
3688 struct net_device *dev = seq->private;
3689 const struct skge_port *skge = netdev_priv(dev);
3690 const struct skge_hw *hw = skge->hw;
3691 const struct skge_element *e;
3692
3693 if (!netif_running(dev))
3694 return -ENETDOWN;
3695
3696 seq_printf(seq, "IRQ src=%x mask=%x\n", skge_read32(hw, B0_ISRC),
3697 skge_read32(hw, B0_IMSK));
3698
3699 seq_printf(seq, "Tx Ring: (%d)\n", skge_avail(&skge->tx_ring));
3700 for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
3701 const struct skge_tx_desc *t = e->desc;
3702 seq_printf(seq, "%#x dma=%#x%08x %#x csum=%#x/%x/%x\n",
3703 t->control, t->dma_hi, t->dma_lo, t->status,
3704 t->csum_offs, t->csum_write, t->csum_start);
3705 }
3706
3707 seq_printf(seq, "\nRx Ring: \n");
3708 for (e = skge->rx_ring.to_clean; ; e = e->next) {
3709 const struct skge_rx_desc *r = e->desc;
3710
3711 if (r->control & BMU_OWN)
3712 break;
3713
3714 seq_printf(seq, "%#x dma=%#x%08x %#x %#x csum=%#x/%x\n",
3715 r->control, r->dma_hi, r->dma_lo, r->status,
3716 r->timestamp, r->csum1, r->csum1_start);
3717 }
3718
3719 return 0;
3720}
3721
3722static int skge_debug_open(struct inode *inode, struct file *file)
3723{
3724 return single_open(file, skge_debug_show, inode->i_private);
3725}
3726
3727static const struct file_operations skge_debug_fops = {
3728 .owner = THIS_MODULE,
3729 .open = skge_debug_open,
3730 .read = seq_read,
3731 .llseek = seq_lseek,
3732 .release = single_release,
3733};
3734
3735/*
3736 * Use network device events to create/remove/rename
3737 * debugfs file entries
3738 */
3739static int skge_device_event(struct notifier_block *unused,
3740 unsigned long event, void *ptr)
3741{
3742 struct net_device *dev = ptr;
3743 struct skge_port *skge;
3744 struct dentry *d;
3745
3746 if (dev->open != &skge_up || !skge_debug)
3747 goto done;
3748
3749 skge = netdev_priv(dev);
3750 switch(event) {
3751 case NETDEV_CHANGENAME:
3752 if (skge->debugfs) {
3753 d = debugfs_rename(skge_debug, skge->debugfs,
3754 skge_debug, dev->name);
3755 if (d)
3756 skge->debugfs = d;
3757 else {
3758 pr_info(PFX "%s: rename failed\n", dev->name);
3759 debugfs_remove(skge->debugfs);
3760 }
3761 }
3762 break;
3763
3764 case NETDEV_GOING_DOWN:
3765 if (skge->debugfs) {
3766 debugfs_remove(skge->debugfs);
3767 skge->debugfs = NULL;
3768 }
3769 break;
3770
3771 case NETDEV_UP:
3772 d = debugfs_create_file(dev->name, S_IRUGO,
3773 skge_debug, dev,
3774 &skge_debug_fops);
3775 if (!d || IS_ERR(d))
3776 pr_info(PFX "%s: debugfs create failed\n",
3777 dev->name);
3778 else
3779 skge->debugfs = d;
3780 break;
3781 }
3782
3783done:
3784 return NOTIFY_DONE;
3785}
3786
3787static struct notifier_block skge_notifier = {
3788 .notifier_call = skge_device_event,
3789};
3790
3791
3792static __init void skge_debug_init(void)
3793{
3794 struct dentry *ent;
3795
3796 ent = debugfs_create_dir("skge", NULL);
3797 if (!ent || IS_ERR(ent)) {
3798 pr_info(PFX "debugfs create directory failed\n");
3799 return;
3800 }
3801
3802 skge_debug = ent;
3803 register_netdevice_notifier(&skge_notifier);
3804}
3805
3806static __exit void skge_debug_cleanup(void)
3807{
3808 if (skge_debug) {
3809 unregister_netdevice_notifier(&skge_notifier);
3810 debugfs_remove(skge_debug);
3811 skge_debug = NULL;
3812 }
3813}
3814
3815#else
3816#define skge_debug_init()
3817#define skge_debug_cleanup()
3818#endif
3819
3679/* Initialize network device */ 3820/* Initialize network device */
3680static struct net_device *skge_devinit(struct skge_hw *hw, int port, 3821static struct net_device *skge_devinit(struct skge_hw *hw, int port,
3681 int highmem) 3822 int highmem)
@@ -4040,12 +4181,14 @@ static struct pci_driver skge_driver = {
4040 4181
4041static int __init skge_init_module(void) 4182static int __init skge_init_module(void)
4042{ 4183{
4184 skge_debug_init();
4043 return pci_register_driver(&skge_driver); 4185 return pci_register_driver(&skge_driver);
4044} 4186}
4045 4187
4046static void __exit skge_cleanup_module(void) 4188static void __exit skge_cleanup_module(void)
4047{ 4189{
4048 pci_unregister_driver(&skge_driver); 4190 pci_unregister_driver(&skge_driver);
4191 skge_debug_cleanup();
4049} 4192}
4050 4193
4051module_init(skge_init_module); 4194module_init(skge_init_module);
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 51754246d59d..17caccbb7685 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2469,6 +2469,9 @@ struct skge_port {
2469 void *mem; /* PCI memory for rings */ 2469 void *mem; /* PCI memory for rings */
2470 dma_addr_t dma; 2470 dma_addr_t dma;
2471 unsigned long mem_size; 2471 unsigned long mem_size;
2472#ifdef CONFIG_SKGE_DEBUG
2473 struct dentry *debugfs;
2474#endif
2472}; 2475};
2473 2476
2474 2477