1 /* 2 * Copyright (c) 2004 Topspin Communications. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 * 32 * $Id: ipoib_fs.c 1389 2004-12-27 22:56:47Z roland $ 33 */ 34 35 #include <linux/err.h> 36 #include <linux/seq_file.h> 37 38 struct file_operations; 39 40 #include <linux/debugfs.h> 41 42 #include "ipoib.h" 43 44 static struct dentry *ipoib_root; 45 46 static void *ipoib_mcg_seq_start(struct seq_file *file, loff_t *pos) 47 { 48 struct ipoib_mcast_iter *iter; 49 loff_t n = *pos; 50 51 iter = ipoib_mcast_iter_init(file->private); 52 if (!iter) 53 return NULL; 54 55 while (n--) { 56 if (ipoib_mcast_iter_next(iter)) { 57 ipoib_mcast_iter_free(iter); 58 return NULL; 59 } 60 } 61 62 return iter; 63 } 64 65 static void *ipoib_mcg_seq_next(struct seq_file *file, void *iter_ptr, 66 loff_t *pos) 67 { 68 struct ipoib_mcast_iter *iter = iter_ptr; 69 70 (*pos)++; 71 72 if (ipoib_mcast_iter_next(iter)) { 73 ipoib_mcast_iter_free(iter); 74 return NULL; 75 } 76 77 return iter; 78 } 79 80 static void ipoib_mcg_seq_stop(struct seq_file *file, void *iter_ptr) 81 { 82 /* nothing for now */ 83 } 84 85 static int ipoib_mcg_seq_show(struct seq_file *file, void *iter_ptr) 86 { 87 struct ipoib_mcast_iter *iter = iter_ptr; 88 char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; 89 union ib_gid mgid; 90 int i, n; 91 unsigned long created; 92 unsigned int queuelen, complete, send_only; 93 94 if (iter) { 95 ipoib_mcast_iter_read(iter, &mgid, &created, &queuelen, 96 &complete, &send_only); 97 98 for (n = 0, i = 0; i < sizeof mgid / 2; ++i) { 99 n += sprintf(gid_buf + n, "%x", 100 be16_to_cpu(((__be16 *) mgid.raw)[i])); 101 if (i < sizeof mgid / 2 - 1) 102 gid_buf[n++] = ':'; 103 } 104 } 105 106 seq_printf(file, "GID: %*s", -(1 + (int) sizeof gid_buf), gid_buf); 107 108 seq_printf(file, 109 " created: %10ld queuelen: %4d complete: %d send_only: %d\n", 110 created, queuelen, complete, send_only); 111 112 return 0; 113 } 114 115 static struct seq_operations ipoib_seq_ops = { 116 .start = ipoib_mcg_seq_start, 117 .next = ipoib_mcg_seq_next, 118 .stop = ipoib_mcg_seq_stop, 119 .show = ipoib_mcg_seq_show, 120 }; 121 122 static int ipoib_mcg_open(struct inode *inode, struct file *file) 123 { 124 struct seq_file *seq; 125 int ret; 126 127 ret = seq_open(file, &ipoib_seq_ops); 128 if (ret) 129 return ret; 130 131 seq = file->private_data; 132 seq->private = inode->u.generic_ip; 133 134 return 0; 135 } 136 137 static struct file_operations ipoib_fops = { 138 .owner = THIS_MODULE, 139 .open = ipoib_mcg_open, 140 .read = seq_read, 141 .llseek = seq_lseek, 142 .release = seq_release 143 }; 144 145 int ipoib_create_debug_file(struct net_device *dev) 146 { 147 struct ipoib_dev_priv *priv = netdev_priv(dev); 148 char name[IFNAMSIZ + sizeof "_mcg"]; 149 150 snprintf(name, sizeof name, "%s_mcg", dev->name); 151 152 priv->mcg_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO, 153 ipoib_root, dev, &ipoib_fops); 154 155 return priv->mcg_dentry ? 0 : -ENOMEM; 156 } 157 158 void ipoib_delete_debug_file(struct net_device *dev) 159 { 160 struct ipoib_dev_priv *priv = netdev_priv(dev); 161 162 if (priv->mcg_dentry) 163 debugfs_remove(priv->mcg_dentry); 164 } 165 166 int ipoib_register_debugfs(void) 167 { 168 ipoib_root = debugfs_create_dir("ipoib", NULL); 169 return ipoib_root ? 0 : -ENOMEM; 170 } 171 172 void ipoib_unregister_debugfs(void) 173 { 174 debugfs_remove(ipoib_root); 175 } 176