ipoib_fs.c revision 219820
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
33#include <linux/err.h>
34#include <linux/seq_file.h>
35
36struct file_operations;
37
38#include <linux/debugfs.h>
39
40#include "ipoib.h"
41
42static struct dentry *ipoib_root;
43
44static void format_gid(union ib_gid *gid, char *buf)
45{
46	int i, n;
47
48	for (n = 0, i = 0; i < 8; ++i) {
49		n += sprintf(buf + n, "%x",
50			     be16_to_cpu(((__be16 *) gid->raw)[i]));
51		if (i < 7)
52			buf[n++] = ':';
53	}
54}
55
56static void *ipoib_mcg_seq_start(struct seq_file *file, loff_t *pos)
57{
58	struct ipoib_mcast_iter *iter;
59	loff_t n = *pos;
60
61	iter = ipoib_mcast_iter_init(file->private);
62	if (!iter)
63		return NULL;
64
65	while (n--) {
66		if (ipoib_mcast_iter_next(iter)) {
67			kfree(iter);
68			return NULL;
69		}
70	}
71
72	return iter;
73}
74
75static void *ipoib_mcg_seq_next(struct seq_file *file, void *iter_ptr,
76				   loff_t *pos)
77{
78	struct ipoib_mcast_iter *iter = iter_ptr;
79
80	(*pos)++;
81
82	if (ipoib_mcast_iter_next(iter)) {
83		kfree(iter);
84		return NULL;
85	}
86
87	return iter;
88}
89
90static void ipoib_mcg_seq_stop(struct seq_file *file, void *iter_ptr)
91{
92	/* nothing for now */
93}
94
95static int ipoib_mcg_seq_show(struct seq_file *file, void *iter_ptr)
96{
97	struct ipoib_mcast_iter *iter = iter_ptr;
98	char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
99	union ib_gid mgid;
100	unsigned long created;
101	unsigned int queuelen, complete, send_only;
102
103	if (!iter)
104		return 0;
105
106	ipoib_mcast_iter_read(iter, &mgid, &created, &queuelen,
107			      &complete, &send_only);
108
109	format_gid(&mgid, gid_buf);
110
111	seq_printf(file,
112		   "GID: %s\n"
113		   "  created: %10ld\n"
114		   "  queuelen: %9d\n"
115		   "  complete: %9s\n"
116		   "  send_only: %8s\n"
117		   "\n",
118		   gid_buf, created, queuelen,
119		   complete ? "yes" : "no",
120		   send_only ? "yes" : "no");
121
122	return 0;
123}
124
125static const struct seq_operations ipoib_mcg_seq_ops = {
126	.start = ipoib_mcg_seq_start,
127	.next  = ipoib_mcg_seq_next,
128	.stop  = ipoib_mcg_seq_stop,
129	.show  = ipoib_mcg_seq_show,
130};
131
132static int ipoib_mcg_open(struct inode *inode, struct file *file)
133{
134	struct seq_file *seq;
135	int ret;
136
137	ret = seq_open(file, &ipoib_mcg_seq_ops);
138	if (ret)
139		return ret;
140
141	seq = file->private_data;
142	seq->private = inode->i_private;
143
144	return 0;
145}
146
147static const struct file_operations ipoib_mcg_fops = {
148	.owner   = THIS_MODULE,
149	.open    = ipoib_mcg_open,
150	.read    = seq_read,
151	.llseek  = seq_lseek,
152	.release = seq_release
153};
154
155static void *ipoib_path_seq_start(struct seq_file *file, loff_t *pos)
156{
157	struct ipoib_path_iter *iter;
158	loff_t n = *pos;
159
160	iter = ipoib_path_iter_init(file->private);
161	if (!iter)
162		return NULL;
163
164	while (n--) {
165		if (ipoib_path_iter_next(iter)) {
166			kfree(iter);
167			return NULL;
168		}
169	}
170
171	return iter;
172}
173
174static void *ipoib_path_seq_next(struct seq_file *file, void *iter_ptr,
175				   loff_t *pos)
176{
177	struct ipoib_path_iter *iter = iter_ptr;
178
179	(*pos)++;
180
181	if (ipoib_path_iter_next(iter)) {
182		kfree(iter);
183		return NULL;
184	}
185
186	return iter;
187}
188
189static void ipoib_path_seq_stop(struct seq_file *file, void *iter_ptr)
190{
191	/* nothing for now */
192}
193
194static int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr)
195{
196	struct ipoib_path_iter *iter = iter_ptr;
197	char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
198	struct ipoib_path path;
199	int rate;
200
201	if (!iter)
202		return 0;
203
204	ipoib_path_iter_read(iter, &path);
205
206	format_gid(&path.pathrec.dgid, gid_buf);
207
208	seq_printf(file,
209		   "GID: %s\n"
210		   "  complete: %6s\n",
211		   gid_buf, path.pathrec.dlid ? "yes" : "no");
212
213	if (path.pathrec.dlid) {
214		rate = ib_rate_to_mult(path.pathrec.rate) * 25;
215
216		seq_printf(file,
217			   "  DLID:     0x%04x\n"
218			   "  SL: %12d\n"
219			   "  rate: %*d%s Gb/sec\n",
220			   be16_to_cpu(path.pathrec.dlid),
221			   path.pathrec.sl,
222			   10 - ((rate % 10) ? 2 : 0),
223			   rate / 10, rate % 10 ? ".5" : "");
224	}
225
226	seq_putc(file, '\n');
227
228	return 0;
229}
230
231static const struct seq_operations ipoib_path_seq_ops = {
232	.start = ipoib_path_seq_start,
233	.next  = ipoib_path_seq_next,
234	.stop  = ipoib_path_seq_stop,
235	.show  = ipoib_path_seq_show,
236};
237
238static int ipoib_path_open(struct inode *inode, struct file *file)
239{
240	struct seq_file *seq;
241	int ret;
242
243	ret = seq_open(file, &ipoib_path_seq_ops);
244	if (ret)
245		return ret;
246
247	seq = file->private_data;
248	seq->private = inode->i_private;
249
250	return 0;
251}
252
253static const struct file_operations ipoib_path_fops = {
254	.owner   = THIS_MODULE,
255	.open    = ipoib_path_open,
256	.read    = seq_read,
257	.llseek  = seq_lseek,
258	.release = seq_release
259};
260
261void ipoib_create_debug_files(struct ifnet *dev)
262{
263	struct ipoib_dev_priv *priv = dev->if_softc;
264	char name[IFNAMSIZ + sizeof "_path"];
265
266	snprintf(name, sizeof name, "%s_mcg", if_name(dev));
267	priv->mcg_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
268					       ipoib_root, dev, &ipoib_mcg_fops);
269	if (!priv->mcg_dentry)
270		ipoib_warn(priv, "failed to create mcg debug file\n");
271
272	snprintf(name, sizeof name, "%s_path", if_name(dev));
273	priv->path_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
274						ipoib_root, dev, &ipoib_path_fops);
275	if (!priv->path_dentry)
276		ipoib_warn(priv, "failed to create path debug file\n");
277}
278
279void ipoib_delete_debug_files(struct ifnet *dev)
280{
281	struct ipoib_dev_priv *priv = dev->if_softc;
282
283	if (priv->mcg_dentry)
284		debugfs_remove(priv->mcg_dentry);
285	if (priv->path_dentry)
286		debugfs_remove(priv->path_dentry);
287}
288
289int ipoib_register_debugfs(void)
290{
291	ipoib_root = debugfs_create_dir("ipoib", NULL);
292	return ipoib_root ? 0 : -ENOMEM;
293}
294
295void ipoib_unregister_debugfs(void)
296{
297	debugfs_remove(ipoib_root);
298}
299