|
@@ -43,6 +43,18 @@ struct file_operations;
|
|
|
|
|
|
static struct dentry *ipoib_root;
|
|
|
|
|
|
+static void format_gid(union ib_gid *gid, char *buf)
|
|
|
+{
|
|
|
+ int i, n;
|
|
|
+
|
|
|
+ for (n = 0, i = 0; i < 8; ++i) {
|
|
|
+ n += sprintf(buf + n, "%x",
|
|
|
+ be16_to_cpu(((__be16 *) gid->raw)[i]));
|
|
|
+ if (i < 7)
|
|
|
+ buf[n++] = ':';
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static void *ipoib_mcg_seq_start(struct seq_file *file, loff_t *pos)
|
|
|
{
|
|
|
struct ipoib_mcast_iter *iter;
|
|
@@ -54,7 +66,7 @@ static void *ipoib_mcg_seq_start(struct seq_file *file, loff_t *pos)
|
|
|
|
|
|
while (n--) {
|
|
|
if (ipoib_mcast_iter_next(iter)) {
|
|
|
- ipoib_mcast_iter_free(iter);
|
|
|
+ kfree(iter);
|
|
|
return NULL;
|
|
|
}
|
|
|
}
|
|
@@ -70,7 +82,7 @@ static void *ipoib_mcg_seq_next(struct seq_file *file, void *iter_ptr,
|
|
|
(*pos)++;
|
|
|
|
|
|
if (ipoib_mcast_iter_next(iter)) {
|
|
|
- ipoib_mcast_iter_free(iter);
|
|
|
+ kfree(iter);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
@@ -87,32 +99,32 @@ static int ipoib_mcg_seq_show(struct seq_file *file, void *iter_ptr)
|
|
|
struct ipoib_mcast_iter *iter = iter_ptr;
|
|
|
char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
|
|
|
union ib_gid mgid;
|
|
|
- int i, n;
|
|
|
unsigned long created;
|
|
|
unsigned int queuelen, complete, send_only;
|
|
|
|
|
|
- if (iter) {
|
|
|
- ipoib_mcast_iter_read(iter, &mgid, &created, &queuelen,
|
|
|
- &complete, &send_only);
|
|
|
+ if (!iter)
|
|
|
+ return 0;
|
|
|
|
|
|
- for (n = 0, i = 0; i < sizeof mgid / 2; ++i) {
|
|
|
- n += sprintf(gid_buf + n, "%x",
|
|
|
- be16_to_cpu(((__be16 *) mgid.raw)[i]));
|
|
|
- if (i < sizeof mgid / 2 - 1)
|
|
|
- gid_buf[n++] = ':';
|
|
|
- }
|
|
|
- }
|
|
|
+ ipoib_mcast_iter_read(iter, &mgid, &created, &queuelen,
|
|
|
+ &complete, &send_only);
|
|
|
|
|
|
- seq_printf(file, "GID: %*s", -(1 + (int) sizeof gid_buf), gid_buf);
|
|
|
+ format_gid(&mgid, gid_buf);
|
|
|
|
|
|
seq_printf(file,
|
|
|
- " created: %10ld queuelen: %4d complete: %d send_only: %d\n",
|
|
|
- created, queuelen, complete, send_only);
|
|
|
+ "GID: %s\n"
|
|
|
+ " created: %10ld\n"
|
|
|
+ " queuelen: %9d\n"
|
|
|
+ " complete: %9s\n"
|
|
|
+ " send_only: %8s\n"
|
|
|
+ "\n",
|
|
|
+ gid_buf, created, queuelen,
|
|
|
+ complete ? "yes" : "no",
|
|
|
+ send_only ? "yes" : "no");
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static struct seq_operations ipoib_seq_ops = {
|
|
|
+static struct seq_operations ipoib_mcg_seq_ops = {
|
|
|
.start = ipoib_mcg_seq_start,
|
|
|
.next = ipoib_mcg_seq_next,
|
|
|
.stop = ipoib_mcg_seq_stop,
|
|
@@ -124,7 +136,7 @@ static int ipoib_mcg_open(struct inode *inode, struct file *file)
|
|
|
struct seq_file *seq;
|
|
|
int ret;
|
|
|
|
|
|
- ret = seq_open(file, &ipoib_seq_ops);
|
|
|
+ ret = seq_open(file, &ipoib_mcg_seq_ops);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -134,7 +146,7 @@ static int ipoib_mcg_open(struct inode *inode, struct file *file)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static struct file_operations ipoib_fops = {
|
|
|
+static struct file_operations ipoib_mcg_fops = {
|
|
|
.owner = THIS_MODULE,
|
|
|
.open = ipoib_mcg_open,
|
|
|
.read = seq_read,
|
|
@@ -142,25 +154,138 @@ static struct file_operations ipoib_fops = {
|
|
|
.release = seq_release
|
|
|
};
|
|
|
|
|
|
-int ipoib_create_debug_file(struct net_device *dev)
|
|
|
+static void *ipoib_path_seq_start(struct seq_file *file, loff_t *pos)
|
|
|
+{
|
|
|
+ struct ipoib_path_iter *iter;
|
|
|
+ loff_t n = *pos;
|
|
|
+
|
|
|
+ iter = ipoib_path_iter_init(file->private);
|
|
|
+ if (!iter)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ while (n--) {
|
|
|
+ if (ipoib_path_iter_next(iter)) {
|
|
|
+ kfree(iter);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return iter;
|
|
|
+}
|
|
|
+
|
|
|
+static void *ipoib_path_seq_next(struct seq_file *file, void *iter_ptr,
|
|
|
+ loff_t *pos)
|
|
|
+{
|
|
|
+ struct ipoib_path_iter *iter = iter_ptr;
|
|
|
+
|
|
|
+ (*pos)++;
|
|
|
+
|
|
|
+ if (ipoib_path_iter_next(iter)) {
|
|
|
+ kfree(iter);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return iter;
|
|
|
+}
|
|
|
+
|
|
|
+static void ipoib_path_seq_stop(struct seq_file *file, void *iter_ptr)
|
|
|
+{
|
|
|
+ /* nothing for now */
|
|
|
+}
|
|
|
+
|
|
|
+static int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr)
|
|
|
+{
|
|
|
+ struct ipoib_path_iter *iter = iter_ptr;
|
|
|
+ char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
|
|
|
+ struct ipoib_path path;
|
|
|
+ int rate;
|
|
|
+
|
|
|
+ if (!iter)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ ipoib_path_iter_read(iter, &path);
|
|
|
+
|
|
|
+ format_gid(&path.pathrec.dgid, gid_buf);
|
|
|
+
|
|
|
+ seq_printf(file,
|
|
|
+ "GID: %s\n"
|
|
|
+ " complete: %6s\n",
|
|
|
+ gid_buf, path.pathrec.dlid ? "yes" : "no");
|
|
|
+
|
|
|
+ if (path.pathrec.dlid) {
|
|
|
+ rate = ib_sa_rate_enum_to_int(path.pathrec.rate) * 25;
|
|
|
+
|
|
|
+ seq_printf(file,
|
|
|
+ " DLID: 0x%04x\n"
|
|
|
+ " SL: %12d\n"
|
|
|
+ " rate: %*d%s Gb/sec\n",
|
|
|
+ be16_to_cpu(path.pathrec.dlid),
|
|
|
+ path.pathrec.sl,
|
|
|
+ 10 - ((rate % 10) ? 2 : 0),
|
|
|
+ rate / 10, rate % 10 ? ".5" : "");
|
|
|
+ }
|
|
|
+
|
|
|
+ seq_putc(file, '\n');
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct seq_operations ipoib_path_seq_ops = {
|
|
|
+ .start = ipoib_path_seq_start,
|
|
|
+ .next = ipoib_path_seq_next,
|
|
|
+ .stop = ipoib_path_seq_stop,
|
|
|
+ .show = ipoib_path_seq_show,
|
|
|
+};
|
|
|
+
|
|
|
+static int ipoib_path_open(struct inode *inode, struct file *file)
|
|
|
+{
|
|
|
+ struct seq_file *seq;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = seq_open(file, &ipoib_path_seq_ops);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ seq = file->private_data;
|
|
|
+ seq->private = inode->u.generic_ip;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct file_operations ipoib_path_fops = {
|
|
|
+ .owner = THIS_MODULE,
|
|
|
+ .open = ipoib_path_open,
|
|
|
+ .read = seq_read,
|
|
|
+ .llseek = seq_lseek,
|
|
|
+ .release = seq_release
|
|
|
+};
|
|
|
+
|
|
|
+void ipoib_create_debug_files(struct net_device *dev)
|
|
|
{
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
|
|
- char name[IFNAMSIZ + sizeof "_mcg"];
|
|
|
+ char name[IFNAMSIZ + sizeof "_path"];
|
|
|
|
|
|
snprintf(name, sizeof name, "%s_mcg", dev->name);
|
|
|
-
|
|
|
priv->mcg_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
|
|
|
- ipoib_root, dev, &ipoib_fops);
|
|
|
-
|
|
|
- return priv->mcg_dentry ? 0 : -ENOMEM;
|
|
|
+ ipoib_root, dev, &ipoib_mcg_fops);
|
|
|
+ if (!priv->mcg_dentry)
|
|
|
+ ipoib_warn(priv, "failed to create mcg debug file\n");
|
|
|
+
|
|
|
+ snprintf(name, sizeof name, "%s_path", dev->name);
|
|
|
+ priv->path_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
|
|
|
+ ipoib_root, dev, &ipoib_path_fops);
|
|
|
+ if (!priv->path_dentry)
|
|
|
+ ipoib_warn(priv, "failed to create path debug file\n");
|
|
|
}
|
|
|
|
|
|
-void ipoib_delete_debug_file(struct net_device *dev)
|
|
|
+void ipoib_delete_debug_files(struct net_device *dev)
|
|
|
{
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
|
|
|
|
|
if (priv->mcg_dentry)
|
|
|
debugfs_remove(priv->mcg_dentry);
|
|
|
+ if (priv->path_dentry)
|
|
|
+ debugfs_remove(priv->path_dentry);
|
|
|
}
|
|
|
|
|
|
int ipoib_register_debugfs(void)
|