diff options
-rw-r--r-- | drivers/net/Kconfig | 10 | ||||
-rw-r--r-- | drivers/net/skge.c | 143 | ||||
-rw-r--r-- | drivers/net/skge.h | 3 |
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 | ||
2176 | config 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 | |||
2176 | config SKY2 | 2186 | config 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 | |||
3684 | static struct dentry *skge_debug; | ||
3685 | |||
3686 | static 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 | |||
3722 | static int skge_debug_open(struct inode *inode, struct file *file) | ||
3723 | { | ||
3724 | return single_open(file, skge_debug_show, inode->i_private); | ||
3725 | } | ||
3726 | |||
3727 | static 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 | */ | ||
3739 | static 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 | |||
3783 | done: | ||
3784 | return NOTIFY_DONE; | ||
3785 | } | ||
3786 | |||
3787 | static struct notifier_block skge_notifier = { | ||
3788 | .notifier_call = skge_device_event, | ||
3789 | }; | ||
3790 | |||
3791 | |||
3792 | static __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 | |||
3806 | static __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 */ |
3680 | static struct net_device *skge_devinit(struct skge_hw *hw, int port, | 3821 | static 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 | ||
4041 | static int __init skge_init_module(void) | 4182 | static 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 | ||
4046 | static void __exit skge_cleanup_module(void) | 4188 | static 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 | ||
4051 | module_init(skge_init_module); | 4194 | module_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 | ||