Create a virtual file under debugfs for each cma device and use it to print
information about each rdma_id that is attached to this device.

Here is an example of 'cat /sys/kernel/debug/rdma_cm/mthca0_rdma_id'. This
example is for a host that runs a rping server (when a remote client is
connected to it)  and a rping client to a remote server.

TP DEV     PO NDEV SRC                                                 DST      
                                           PS   ST QPN
0  mthca0  0       0.0.0.0:7174                                                 
                                           262  8  0
1  mthca0  1  ib0  192.30.3.249:50113                                  
192.30.3.248:7174                                   262  5  66566
1  mthca0  1  ib0  192.30.3.249:7174                                   
192.30.3.248:42560                                  262  5  66567

Signed-off-by: Moni Shoua <mo...@voltaire.com>
-- 

 drivers/infiniband/core/cma.c |  161 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 161 insertions(+)

diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 2a2e508..ea16d44 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -51,6 +51,9 @@
 #include <rdma/ib_sa.h>
 #include <rdma/iw_cm.h>
 
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+
 MODULE_AUTHOR("Sean Hefty");
 MODULE_DESCRIPTION("Generic RDMA CM Agent");
 MODULE_LICENSE("Dual BSD/GPL");
@@ -59,6 +62,8 @@ MODULE_LICENSE("Dual BSD/GPL");
 #define CMA_MAX_CM_RETRIES 15
 #define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24)
 
+static struct dentry *cma_root_dentry;
+
 static void cma_add_one(struct ib_device *device);
 static void cma_remove_one(struct ib_device *device);
 
@@ -86,6 +91,7 @@ struct cma_device {
        struct completion       comp;
        atomic_t                refcount;
        struct list_head        id_list;
+       struct dentry           *rdma_id_dentry;
 };
 
 enum cma_state {
@@ -2850,6 +2856,150 @@ static struct notifier_block cma_nb = {
        .notifier_call = cma_netdev_callback
 };
 
+static void *cma_rdma_id_seq_start(struct seq_file *file, loff_t *pos)
+{
+       struct cma_device *cma_dev = file->private;
+       void *ret;
+
+       mutex_lock(&lock);
+       if (*pos == 0)
+               return SEQ_START_TOKEN;
+       ret = seq_list_start_head(&cma_dev->id_list, *pos);
+       return ret;
+}
+
+static void *cma_rdma_id_seq_next(struct seq_file *file, void *v, loff_t *pos)
+{
+       void *ret;
+       struct cma_device *cma_dev = file->private;
+       if (v == SEQ_START_TOKEN) {
+               ++*pos;
+               if (!list_empty(&cma_dev->id_list))
+                       ret = cma_dev->id_list.next;
+               else
+                       ret = NULL;
+       } else {
+               ret = seq_list_next(v, &cma_dev->id_list, pos);
+       }
+       return ret;
+}
+
+static void cma_rdma_id_seq_stop(struct seq_file *file, void *iter_ptr)
+{
+       mutex_unlock(&lock);
+}
+
+static void format_addr(struct sockaddr *sa, char* buf)
+{
+       switch (sa->sa_family) {
+       case AF_INET: {
+               struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+               sprintf(buf, "%pI4:%u", &sin->sin_addr.s_addr,
+                               be16_to_cpu(cma_port(sa)));
+               break;
+       }
+       case AF_INET6: {
+               struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+               sprintf(buf, "%pI6:%u", &sin6->sin6_addr,
+                               be16_to_cpu(cma_port(sa)));
+               break;
+       }
+       default:
+               buf[0] = 0;
+       }
+}
+
+static int cma_rdma_id_seq_show(struct seq_file *file, void *v)
+{
+       struct rdma_id_private *id_priv;
+       char local_addr[64], remote_addr[64];
+
+       if (!v)
+               return 0;
+       if (v == SEQ_START_TOKEN) {
+               seq_printf(file,
+                      "%-3s"
+                      "%-8s"
+                      "%-3s"
+                      "%-5s"
+                      "%-52s"
+                      "%-52s"
+                      "%-5s"
+                      "%-3s"
+                      "%-8s"
+                      "\n",
+                      "TP", "DEV", "PO", "NDEV", "SRC", "DST", "PS", "ST", 
"QPN");
+       } else {
+               id_priv = list_entry(v, struct rdma_id_private, list);
+              format_addr((struct sockaddr *)&id_priv->id.route.addr.src_addr,
+                                      local_addr);
+              format_addr((struct sockaddr *)&id_priv->id.route.addr.dst_addr,
+                                      remote_addr);
+
+                      seq_printf(file,
+                              "%-3d"
+                              "%-8s"
+                              "%-3d"
+                              "%-5s"
+                              "%-52s"
+                              "%-52s"
+                              "%-5d"
+                              "%-3d"
+                              "%-8d"
+                              "\n",
+                              id_priv->id.route.addr.dev_addr.dev_type,
+                              (id_priv->id.device) ? id_priv->id.device->name 
: "",
+                              id_priv->id.port_num,
+                              (id_priv->id.route.addr.dev_addr.src_dev) ? 
id_priv->id.route.addr.dev_addr.src_dev->name : "",
+                              local_addr,
+                              remote_addr,
+                              id_priv->id.ps,
+                              id_priv->state,
+                              id_priv->qp_num);
+       }
+       return 0;
+}
+
+static const struct seq_operations cma_rdma_id_seq_ops = {
+       .start = cma_rdma_id_seq_start,
+       .next  = cma_rdma_id_seq_next,
+       .stop  = cma_rdma_id_seq_stop,
+       .show  = cma_rdma_id_seq_show,
+};
+
+static int cma_rdma_id_open(struct inode *inode, struct file *file)
+{
+       struct seq_file *seq;
+       int ret;
+
+       ret = seq_open(file, &cma_rdma_id_seq_ops);
+       if (ret)
+               return ret;
+
+       seq = file->private_data;
+       seq->private = inode->i_private;
+
+       return 0;
+}
+
+static const struct file_operations cma_rdma_id_fops = {
+       .owner   = THIS_MODULE,
+       .open    = cma_rdma_id_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = seq_release
+};
+
+void cma_create_debug_files(struct cma_device *cma_dev)
+{
+       char name[IB_DEVICE_NAME_MAX + sizeof "_rdma_id"];
+       snprintf(name, sizeof name, "%s_rdma_id", cma_dev->device->name);
+       cma_dev->rdma_id_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
+                                       cma_root_dentry, cma_dev, 
&cma_rdma_id_fops);
+       if (!cma_dev->rdma_id_dentry)
+               printk(KERN_WARNING "RDMA CMA: failed to create debugfs file 
%s\n",  name);
+}
+
 static void cma_add_one(struct ib_device *device)
 {
        struct cma_device *cma_dev;
@@ -2871,6 +3021,7 @@ static void cma_add_one(struct ib_device *device)
        list_for_each_entry(id_priv, &listen_any_list, list)
                cma_listen_on_dev(id_priv, cma_dev);
        mutex_unlock(&lock);
+       cma_create_debug_files(cma_dev);
 }
 
 static int cma_remove_id_dev(struct rdma_id_private *id_priv)
@@ -2905,6 +3056,8 @@ static void cma_process_remove(struct cma_device *cma_dev)
        int ret;
 
        mutex_lock(&lock);
+       if (cma_dev->rdma_id_dentry)
+               debugfs_remove(cma_dev->rdma_id_dentry);
        while (!list_empty(&cma_dev->id_list)) {
                id_priv = list_entry(cma_dev->id_list.next,
                                     struct rdma_id_private, list);
@@ -2940,6 +3093,7 @@ static void cma_remove_one(struct ib_device *device)
        mutex_unlock(&lock);
 
        cma_process_remove(cma_dev);
+
        kfree(cma_dev);
 }
 
@@ -2947,6 +3101,12 @@ static int cma_init(void)
 {
        int ret, low, high, remaining;
 
+       cma_root_dentry = debugfs_create_dir("rdma_cm", NULL);
+       if (!cma_root_dentry) {
+               printk(KERN_ERR "RDMA CMA: failed to create debugfs dir\n");
+               return  -ENOMEM;
+       }
+
        get_random_bytes(&next_port, sizeof next_port);
        inet_get_local_port_range(&low, &high);
        remaining = (high - low) + 1;
@@ -2984,6 +3144,7 @@ static void cma_cleanup(void)
        idr_destroy(&tcp_ps);
        idr_destroy(&udp_ps);
        idr_destroy(&ipoib_ps);
+       debugfs_remove(cma_root_dentry);
 }
 
 module_init(cma_init);
_______________________________________________
general mailing list
general@lists.openfabrics.org
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to