1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2004 Topspin Communications. All rights reserved.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * This software is available to you under a choice of one of two
5*4882a593Smuzhiyun * licenses. You may choose to be licensed under the terms of the GNU
6*4882a593Smuzhiyun * General Public License (GPL) Version 2, available from the file
7*4882a593Smuzhiyun * COPYING in the main directory of this source tree, or the
8*4882a593Smuzhiyun * OpenIB.org BSD license below:
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Redistribution and use in source and binary forms, with or
11*4882a593Smuzhiyun * without modification, are permitted provided that the following
12*4882a593Smuzhiyun * conditions are met:
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * - Redistributions of source code must retain the above
15*4882a593Smuzhiyun * copyright notice, this list of conditions and the following
16*4882a593Smuzhiyun * disclaimer.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * - Redistributions in binary form must reproduce the above
19*4882a593Smuzhiyun * copyright notice, this list of conditions and the following
20*4882a593Smuzhiyun * disclaimer in the documentation and/or other materials
21*4882a593Smuzhiyun * provided with the distribution.
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24*4882a593Smuzhiyun * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25*4882a593Smuzhiyun * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26*4882a593Smuzhiyun * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27*4882a593Smuzhiyun * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28*4882a593Smuzhiyun * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29*4882a593Smuzhiyun * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30*4882a593Smuzhiyun * SOFTWARE.
31*4882a593Smuzhiyun */
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #include <linux/err.h>
34*4882a593Smuzhiyun #include <linux/seq_file.h>
35*4882a593Smuzhiyun #include <linux/slab.h>
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun struct file_operations;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #include <linux/debugfs.h>
40*4882a593Smuzhiyun #include <linux/export.h>
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #include "ipoib.h"
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun static struct dentry *ipoib_root;
45*4882a593Smuzhiyun
format_gid(union ib_gid * gid,char * buf)46*4882a593Smuzhiyun static void format_gid(union ib_gid *gid, char *buf)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun int i, n;
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun for (n = 0, i = 0; i < 8; ++i) {
51*4882a593Smuzhiyun n += sprintf(buf + n, "%x",
52*4882a593Smuzhiyun be16_to_cpu(((__be16 *) gid->raw)[i]));
53*4882a593Smuzhiyun if (i < 7)
54*4882a593Smuzhiyun buf[n++] = ':';
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
ipoib_mcg_seq_start(struct seq_file * file,loff_t * pos)58*4882a593Smuzhiyun static void *ipoib_mcg_seq_start(struct seq_file *file, loff_t *pos)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun struct ipoib_mcast_iter *iter;
61*4882a593Smuzhiyun loff_t n = *pos;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun iter = ipoib_mcast_iter_init(file->private);
64*4882a593Smuzhiyun if (!iter)
65*4882a593Smuzhiyun return NULL;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun while (n--) {
68*4882a593Smuzhiyun if (ipoib_mcast_iter_next(iter)) {
69*4882a593Smuzhiyun kfree(iter);
70*4882a593Smuzhiyun return NULL;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun return iter;
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
ipoib_mcg_seq_next(struct seq_file * file,void * iter_ptr,loff_t * pos)77*4882a593Smuzhiyun static void *ipoib_mcg_seq_next(struct seq_file *file, void *iter_ptr,
78*4882a593Smuzhiyun loff_t *pos)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun struct ipoib_mcast_iter *iter = iter_ptr;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun (*pos)++;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun if (ipoib_mcast_iter_next(iter)) {
85*4882a593Smuzhiyun kfree(iter);
86*4882a593Smuzhiyun return NULL;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun return iter;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
ipoib_mcg_seq_stop(struct seq_file * file,void * iter_ptr)92*4882a593Smuzhiyun static void ipoib_mcg_seq_stop(struct seq_file *file, void *iter_ptr)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun /* nothing for now */
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
ipoib_mcg_seq_show(struct seq_file * file,void * iter_ptr)97*4882a593Smuzhiyun static int ipoib_mcg_seq_show(struct seq_file *file, void *iter_ptr)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun struct ipoib_mcast_iter *iter = iter_ptr;
100*4882a593Smuzhiyun char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
101*4882a593Smuzhiyun union ib_gid mgid;
102*4882a593Smuzhiyun unsigned long created;
103*4882a593Smuzhiyun unsigned int queuelen, complete, send_only;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun if (!iter)
106*4882a593Smuzhiyun return 0;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun ipoib_mcast_iter_read(iter, &mgid, &created, &queuelen,
109*4882a593Smuzhiyun &complete, &send_only);
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun format_gid(&mgid, gid_buf);
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun seq_printf(file,
114*4882a593Smuzhiyun "GID: %s\n"
115*4882a593Smuzhiyun " created: %10ld\n"
116*4882a593Smuzhiyun " queuelen: %9d\n"
117*4882a593Smuzhiyun " complete: %9s\n"
118*4882a593Smuzhiyun " send_only: %8s\n"
119*4882a593Smuzhiyun "\n",
120*4882a593Smuzhiyun gid_buf, created, queuelen,
121*4882a593Smuzhiyun complete ? "yes" : "no",
122*4882a593Smuzhiyun send_only ? "yes" : "no");
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun return 0;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun static const struct seq_operations ipoib_mcg_sops = {
128*4882a593Smuzhiyun .start = ipoib_mcg_seq_start,
129*4882a593Smuzhiyun .next = ipoib_mcg_seq_next,
130*4882a593Smuzhiyun .stop = ipoib_mcg_seq_stop,
131*4882a593Smuzhiyun .show = ipoib_mcg_seq_show,
132*4882a593Smuzhiyun };
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun DEFINE_SEQ_ATTRIBUTE(ipoib_mcg);
135*4882a593Smuzhiyun
ipoib_path_seq_start(struct seq_file * file,loff_t * pos)136*4882a593Smuzhiyun static void *ipoib_path_seq_start(struct seq_file *file, loff_t *pos)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun struct ipoib_path_iter *iter;
139*4882a593Smuzhiyun loff_t n = *pos;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun iter = ipoib_path_iter_init(file->private);
142*4882a593Smuzhiyun if (!iter)
143*4882a593Smuzhiyun return NULL;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun while (n--) {
146*4882a593Smuzhiyun if (ipoib_path_iter_next(iter)) {
147*4882a593Smuzhiyun kfree(iter);
148*4882a593Smuzhiyun return NULL;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun return iter;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
ipoib_path_seq_next(struct seq_file * file,void * iter_ptr,loff_t * pos)155*4882a593Smuzhiyun static void *ipoib_path_seq_next(struct seq_file *file, void *iter_ptr,
156*4882a593Smuzhiyun loff_t *pos)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun struct ipoib_path_iter *iter = iter_ptr;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun (*pos)++;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun if (ipoib_path_iter_next(iter)) {
163*4882a593Smuzhiyun kfree(iter);
164*4882a593Smuzhiyun return NULL;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun return iter;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
ipoib_path_seq_stop(struct seq_file * file,void * iter_ptr)170*4882a593Smuzhiyun static void ipoib_path_seq_stop(struct seq_file *file, void *iter_ptr)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun /* nothing for now */
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
ipoib_path_seq_show(struct seq_file * file,void * iter_ptr)175*4882a593Smuzhiyun static int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun struct ipoib_path_iter *iter = iter_ptr;
178*4882a593Smuzhiyun char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
179*4882a593Smuzhiyun struct ipoib_path path;
180*4882a593Smuzhiyun int rate;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun if (!iter)
183*4882a593Smuzhiyun return 0;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun ipoib_path_iter_read(iter, &path);
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun format_gid(&path.pathrec.dgid, gid_buf);
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun seq_printf(file,
190*4882a593Smuzhiyun "GID: %s\n"
191*4882a593Smuzhiyun " complete: %6s\n",
192*4882a593Smuzhiyun gid_buf, sa_path_get_dlid(&path.pathrec) ? "yes" : "no");
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun if (sa_path_get_dlid(&path.pathrec)) {
195*4882a593Smuzhiyun rate = ib_rate_to_mbps(path.pathrec.rate);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun seq_printf(file,
198*4882a593Smuzhiyun " DLID: 0x%04x\n"
199*4882a593Smuzhiyun " SL: %12d\n"
200*4882a593Smuzhiyun " rate: %8d.%d Gb/sec\n",
201*4882a593Smuzhiyun be32_to_cpu(sa_path_get_dlid(&path.pathrec)),
202*4882a593Smuzhiyun path.pathrec.sl,
203*4882a593Smuzhiyun rate / 1000, rate % 1000);
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun seq_putc(file, '\n');
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun return 0;
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun static const struct seq_operations ipoib_path_sops = {
212*4882a593Smuzhiyun .start = ipoib_path_seq_start,
213*4882a593Smuzhiyun .next = ipoib_path_seq_next,
214*4882a593Smuzhiyun .stop = ipoib_path_seq_stop,
215*4882a593Smuzhiyun .show = ipoib_path_seq_show,
216*4882a593Smuzhiyun };
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun DEFINE_SEQ_ATTRIBUTE(ipoib_path);
219*4882a593Smuzhiyun
ipoib_create_debug_files(struct net_device * dev)220*4882a593Smuzhiyun void ipoib_create_debug_files(struct net_device *dev)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun struct ipoib_dev_priv *priv = ipoib_priv(dev);
223*4882a593Smuzhiyun char name[IFNAMSIZ + sizeof("_path")];
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun snprintf(name, sizeof(name), "%s_mcg", dev->name);
226*4882a593Smuzhiyun priv->mcg_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
227*4882a593Smuzhiyun ipoib_root, dev, &ipoib_mcg_fops);
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun snprintf(name, sizeof(name), "%s_path", dev->name);
230*4882a593Smuzhiyun priv->path_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
231*4882a593Smuzhiyun ipoib_root, dev, &ipoib_path_fops);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
ipoib_delete_debug_files(struct net_device * dev)234*4882a593Smuzhiyun void ipoib_delete_debug_files(struct net_device *dev)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun struct ipoib_dev_priv *priv = ipoib_priv(dev);
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun debugfs_remove(priv->mcg_dentry);
239*4882a593Smuzhiyun debugfs_remove(priv->path_dentry);
240*4882a593Smuzhiyun priv->mcg_dentry = priv->path_dentry = NULL;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
ipoib_register_debugfs(void)243*4882a593Smuzhiyun void ipoib_register_debugfs(void)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun ipoib_root = debugfs_create_dir("ipoib", NULL);
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun
ipoib_unregister_debugfs(void)248*4882a593Smuzhiyun void ipoib_unregister_debugfs(void)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun debugfs_remove(ipoib_root);
251*4882a593Smuzhiyun }
252