staging/fwserial: Factor unstable stats/debug/status info to debugfs
authorPeter Hurley <peter@hurleysoftware.com>
Tue, 29 Jan 2013 03:34:40 +0000 (22:34 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 30 Jan 2013 04:28:45 +0000 (23:28 -0500)
Add the following file hierarchy to debugfs:

  <debugfs>-+
            +- firewire_serial -+- <unit> -+- peers
                                |          +- stats
                                |
                                +- <unit> -+- peers
                                           +- stats

The 'peers' file (read-only) contains status and configuration
info for attached peers for the given fwserial unit.

The 'stats' file (read-only) contains statistics and data profiling
information for each tty port for the given fwserial unit.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/fwserial/fwserial.c
drivers/staging/fwserial/fwserial.h

index fb00a8a7bb8c6af7694348424adbf6e5ff488359..37b082be9d24c5c8109cfc1e4fc8450b7a023028 100644 (file)
@@ -84,6 +84,8 @@ static struct kmem_cache *fwtty_txn_cache;
 struct tty_driver *fwtty_driver;
 static struct tty_driver *fwloop_driver;
 
+static struct dentry *fwserial_debugfs;
+
 struct fwtty_transaction;
 typedef void (*fwtty_transaction_cb)(struct fw_card *card, int rcode,
                                     void *data, size_t length,
@@ -1568,11 +1570,71 @@ static int fwtty_proc_show(struct seq_file *m, void *v)
        return 0;
 }
 
+static int fwtty_debugfs_stats_show(struct seq_file *m, void *v)
+{
+       struct fw_serial *serial = m->private;
+       struct fwtty_port *port;
+       int i;
+
+       for (i = 0; i < num_ports; ++i) {
+               port = fwtty_port_get(serial->ports[i]->index);
+               if (port) {
+                       seq_printf(m, "%2d:", port->index);
+                       fwtty_proc_show_port(m, port);
+                       fwtty_debugfs_show_port(m, port);
+                       fwtty_port_put(port);
+                       seq_printf(m, "\n");
+               }
+       }
+       return 0;
+}
+
+static int fwtty_debugfs_peers_show(struct seq_file *m, void *v)
+{
+       struct fw_serial *serial = m->private;
+       struct fwtty_peer *peer;
+
+       rcu_read_lock();
+       seq_printf(m, "card: %s  guid: %016llx\n",
+                  dev_name(serial->card->device),
+                  (unsigned long long) serial->card->guid);
+       list_for_each_entry_rcu(peer, &serial->peer_list, list)
+               fwtty_debugfs_show_peer(m, peer);
+       rcu_read_unlock();
+       return 0;
+}
+
 static int fwtty_proc_open(struct inode *inode, struct file *fp)
 {
        return single_open(fp, fwtty_proc_show, NULL);
 }
 
+static int fwtty_stats_open(struct inode *inode, struct file *fp)
+{
+       return single_open(fp, fwtty_debugfs_stats_show, inode->i_private);
+}
+
+static int fwtty_peers_open(struct inode *inode, struct file *fp)
+{
+       return single_open(fp, fwtty_debugfs_peers_show, inode->i_private);
+}
+
+static const struct file_operations fwtty_stats_fops = {
+       .owner =        THIS_MODULE,
+       .open =         fwtty_stats_open,
+       .read =         seq_read,
+       .llseek =       seq_lseek,
+       .release =      single_release,
+};
+
+static const struct file_operations fwtty_peers_fops = {
+       .owner =        THIS_MODULE,
+       .open =         fwtty_peers_open,
+       .read =         seq_read,
+       .llseek =       seq_lseek,
+       .release =      single_release,
+};
+
 static const struct file_operations fwtty_proc_fops = {
        .owner =        THIS_MODULE,
        .open =         fwtty_proc_open,
@@ -2309,6 +2371,17 @@ static int fwserial_create(struct fw_unit *unit)
                serial->ports[j]->loopback = true;
        }
 
+       if (!IS_ERR_OR_NULL(fwserial_debugfs)) {
+               serial->debugfs = debugfs_create_dir(dev_name(&unit->device),
+                                                    fwserial_debugfs);
+               if (!IS_ERR_OR_NULL(serial->debugfs)) {
+                       debugfs_create_file("peers", 0444, serial->debugfs,
+                                           serial, &fwtty_peers_fops);
+                       debugfs_create_file("stats", 0444, serial->debugfs,
+                                           serial, &fwtty_stats_fops);
+               }
+       }
+
        list_add_rcu(&serial->list, &fwserial_list);
 
        fwtty_notice(&unit, "TTY over FireWire on device %s (guid %016llx)",
@@ -2321,6 +2394,8 @@ static int fwserial_create(struct fw_unit *unit)
        fwtty_err(&unit, "unable to add peer unit device (%d)", err);
 
        /* fall-through to error processing */
+       debugfs_remove_recursive(serial->debugfs);
+
        list_del_rcu(&serial->list);
        if (create_loop_dev)
                tty_unregister_device(fwloop_driver, loop_idx(serial->ports[j]));
@@ -2412,6 +2487,8 @@ static int fwserial_remove(struct device *dev)
                /* unlink from the fwserial_list here */
                list_del_rcu(&serial->list);
 
+               debugfs_remove_recursive(serial->debugfs);
+
                for (i = 0; i < num_ttys; ++i)
                        fwserial_close_port(fwtty_driver, serial->ports[i]);
                if (create_loop_dev)
@@ -2806,6 +2883,9 @@ static int __init fwserial_init(void)
 {
        int err, num_loops = !!(create_loop_dev);
 
+       /* XXX: placeholder for a "firewire" debugfs node */
+       fwserial_debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
+
        /* num_ttys/num_ports must not be set above the static alloc avail */
        if (num_ttys + num_loops > MAX_CARD_PORTS)
                num_ttys = MAX_CARD_PORTS - num_loops;
@@ -2920,6 +3000,7 @@ unregister_driver:
        tty_unregister_driver(fwtty_driver);
 put_tty:
        put_tty_driver(fwtty_driver);
+       debugfs_remove_recursive(fwserial_debugfs);
        return err;
 }
 
@@ -2935,6 +3016,7 @@ static void __exit fwserial_exit(void)
        }
        tty_unregister_driver(fwtty_driver);
        put_tty_driver(fwtty_driver);
+       debugfs_remove_recursive(fwserial_debugfs);
 }
 
 module_init(fwserial_init);
index 360280946ce408f7a76415fbd1b2bad1891c8267..c768aad146e63426f0ac89db540c4ec6f6b5b422 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/serial_reg.h>
 #include <linux/module.h>
 #include <linux/seq_file.h>
+#include <linux/debugfs.h>
 
 #include "dma_fifo.h"
 
@@ -338,6 +339,7 @@ struct fw_serial {
        struct fw_card    *card;
        struct kref       kref;
 
+       struct dentry     *debugfs;
        struct fwtty_peer *self;
 
        struct list_head  list;