aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/skge.c
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 /drivers/net/skge.c
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>
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r--drivers/net/skge.c143
1 files changed, 143 insertions, 0 deletions
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);