Skip to content

Commit

Permalink
skge: add a debug interface
Browse files Browse the repository at this point in the history
Add a debugfs interface to look at internal ring state.

Signed-off-by: Stephen Hemminger <[email protected]>
Signed-off-by: Jeff Garzik <[email protected]>
  • Loading branch information
Stephen Hemminger authored and Jeff Garzik committed Oct 17, 2007
1 parent afa151b commit 678aa1f
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 0 deletions.
10 changes: 10 additions & 0 deletions drivers/net/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2173,6 +2173,16 @@ config SKGE
To compile this driver as a module, choose M here: the module
will be called skge. This is recommended.

config SKGE_DEBUG
bool "Debugging interface"
depends on SKGE && DEBUG_FS
help
This option adds the ability to dump driver state for debugging.
The file debugfs/skge/ethX displays the state of the internal
transmit and receive rings.

If unsure, say N.

config SKY2
tristate "SysKonnect Yukon2 support"
depends on PCI
Expand Down
143 changes: 143 additions & 0 deletions drivers/net/skge.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
#include <linux/delay.h>
#include <linux/crc32.h>
#include <linux/dma-mapping.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/mii.h>
#include <asm/irq.h>

Expand Down Expand Up @@ -3676,6 +3678,145 @@ static int skge_reset(struct skge_hw *hw)
return 0;
}


#ifdef CONFIG_SKGE_DEBUG

static struct dentry *skge_debug;

static int skge_debug_show(struct seq_file *seq, void *v)
{
struct net_device *dev = seq->private;
const struct skge_port *skge = netdev_priv(dev);
const struct skge_hw *hw = skge->hw;
const struct skge_element *e;

if (!netif_running(dev))
return -ENETDOWN;

seq_printf(seq, "IRQ src=%x mask=%x\n", skge_read32(hw, B0_ISRC),
skge_read32(hw, B0_IMSK));

seq_printf(seq, "Tx Ring: (%d)\n", skge_avail(&skge->tx_ring));
for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
const struct skge_tx_desc *t = e->desc;
seq_printf(seq, "%#x dma=%#x%08x %#x csum=%#x/%x/%x\n",
t->control, t->dma_hi, t->dma_lo, t->status,
t->csum_offs, t->csum_write, t->csum_start);
}

seq_printf(seq, "\nRx Ring: \n");
for (e = skge->rx_ring.to_clean; ; e = e->next) {
const struct skge_rx_desc *r = e->desc;

if (r->control & BMU_OWN)
break;

seq_printf(seq, "%#x dma=%#x%08x %#x %#x csum=%#x/%x\n",
r->control, r->dma_hi, r->dma_lo, r->status,
r->timestamp, r->csum1, r->csum1_start);
}

return 0;
}

static int skge_debug_open(struct inode *inode, struct file *file)
{
return single_open(file, skge_debug_show, inode->i_private);
}

static const struct file_operations skge_debug_fops = {
.owner = THIS_MODULE,
.open = skge_debug_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};

/*
* Use network device events to create/remove/rename
* debugfs file entries
*/
static int skge_device_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
struct net_device *dev = ptr;
struct skge_port *skge;
struct dentry *d;

if (dev->open != &skge_up || !skge_debug)
goto done;

skge = netdev_priv(dev);
switch(event) {
case NETDEV_CHANGENAME:
if (skge->debugfs) {
d = debugfs_rename(skge_debug, skge->debugfs,
skge_debug, dev->name);
if (d)
skge->debugfs = d;
else {
pr_info(PFX "%s: rename failed\n", dev->name);
debugfs_remove(skge->debugfs);
}
}
break;

case NETDEV_GOING_DOWN:
if (skge->debugfs) {
debugfs_remove(skge->debugfs);
skge->debugfs = NULL;
}
break;

case NETDEV_UP:
d = debugfs_create_file(dev->name, S_IRUGO,
skge_debug, dev,
&skge_debug_fops);
if (!d || IS_ERR(d))
pr_info(PFX "%s: debugfs create failed\n",
dev->name);
else
skge->debugfs = d;
break;
}

done:
return NOTIFY_DONE;
}

static struct notifier_block skge_notifier = {
.notifier_call = skge_device_event,
};


static __init void skge_debug_init(void)
{
struct dentry *ent;

ent = debugfs_create_dir("skge", NULL);
if (!ent || IS_ERR(ent)) {
pr_info(PFX "debugfs create directory failed\n");
return;
}

skge_debug = ent;
register_netdevice_notifier(&skge_notifier);
}

static __exit void skge_debug_cleanup(void)
{
if (skge_debug) {
unregister_netdevice_notifier(&skge_notifier);
debugfs_remove(skge_debug);
skge_debug = NULL;
}
}

#else
#define skge_debug_init()
#define skge_debug_cleanup()
#endif

/* Initialize network device */
static struct net_device *skge_devinit(struct skge_hw *hw, int port,
int highmem)
Expand Down Expand Up @@ -4040,12 +4181,14 @@ static struct pci_driver skge_driver = {

static int __init skge_init_module(void)
{
skge_debug_init();
return pci_register_driver(&skge_driver);
}

static void __exit skge_cleanup_module(void)
{
pci_unregister_driver(&skge_driver);
skge_debug_cleanup();
}

module_init(skge_init_module);
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/skge.h
Original file line number Diff line number Diff line change
Expand Up @@ -2469,6 +2469,9 @@ struct skge_port {
void *mem; /* PCI memory for rings */
dma_addr_t dma;
unsigned long mem_size;
#ifdef CONFIG_SKGE_DEBUG
struct dentry *debugfs;
#endif
};


Expand Down

0 comments on commit 678aa1f

Please sign in to comment.