1/*
2 * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
3 *
4 * This program is free software; you may redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
9 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
10 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
11 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
12 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
13 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
15 * SOFTWARE.
16 *
17 */
18
19#include <linux/debugfs.h>
20#include <linux/module.h>
21
22#include "usnic.h"
23#include "usnic_log.h"
24#include "usnic_debugfs.h"
25#include "usnic_ib_qp_grp.h"
26#include "usnic_transport.h"
27
28static struct dentry *debugfs_root;
29static struct dentry *flows_dentry;
30
31static ssize_t usnic_debugfs_buildinfo_read(struct file *f, char __user *data,
32						size_t count, loff_t *ppos)
33{
34	char buf[500];
35	int res;
36
37	if (*ppos > 0)
38		return 0;
39
40	res = scnprintf(buf, sizeof(buf),
41			"version:       %s\n"
42			"build date:    %s\n",
43			DRV_VERSION, DRV_RELDATE);
44
45	return simple_read_from_buffer(data, count, ppos, buf, res);
46}
47
48static const struct file_operations usnic_debugfs_buildinfo_ops = {
49	.owner = THIS_MODULE,
50	.open = simple_open,
51	.read = usnic_debugfs_buildinfo_read
52};
53
54static ssize_t flowinfo_read(struct file *f, char __user *data,
55				size_t count, loff_t *ppos)
56{
57	struct usnic_ib_qp_grp_flow *qp_flow;
58	int n;
59	int left;
60	char *ptr;
61	char buf[512];
62
63	qp_flow = f->private_data;
64	ptr = buf;
65	left = count;
66
67	if (*ppos > 0)
68		return 0;
69
70	spin_lock(&qp_flow->qp_grp->lock);
71	n = scnprintf(ptr, left,
72			"QP Grp ID: %d Transport: %s ",
73			qp_flow->qp_grp->grp_id,
74			usnic_transport_to_str(qp_flow->trans_type));
75	UPDATE_PTR_LEFT(n, ptr, left);
76	if (qp_flow->trans_type == USNIC_TRANSPORT_ROCE_CUSTOM) {
77		n = scnprintf(ptr, left, "Port_Num:%hu\n",
78					qp_flow->usnic_roce.port_num);
79		UPDATE_PTR_LEFT(n, ptr, left);
80	} else if (qp_flow->trans_type == USNIC_TRANSPORT_IPV4_UDP) {
81		n = usnic_transport_sock_to_str(ptr, left,
82				qp_flow->udp.sock);
83		UPDATE_PTR_LEFT(n, ptr, left);
84		n = scnprintf(ptr, left, "\n");
85		UPDATE_PTR_LEFT(n, ptr, left);
86	}
87	spin_unlock(&qp_flow->qp_grp->lock);
88
89	return simple_read_from_buffer(data, count, ppos, buf, ptr - buf);
90}
91
92static const struct file_operations flowinfo_ops = {
93	.owner = THIS_MODULE,
94	.open = simple_open,
95	.read = flowinfo_read,
96};
97
98void usnic_debugfs_init(void)
99{
100	debugfs_root = debugfs_create_dir(DRV_NAME, NULL);
101	if (IS_ERR(debugfs_root)) {
102		usnic_err("Failed to create debugfs root dir, check if debugfs is enabled in kernel configuration\n");
103		goto out_clear_root;
104	}
105
106	flows_dentry = debugfs_create_dir("flows", debugfs_root);
107	if (IS_ERR_OR_NULL(flows_dentry)) {
108		usnic_err("Failed to create debugfs flow dir with err %ld\n",
109				PTR_ERR(flows_dentry));
110		goto out_free_root;
111	}
112
113	debugfs_create_file("build-info", S_IRUGO, debugfs_root,
114				NULL, &usnic_debugfs_buildinfo_ops);
115	return;
116
117out_free_root:
118	debugfs_remove_recursive(debugfs_root);
119out_clear_root:
120	debugfs_root = NULL;
121}
122
123void usnic_debugfs_exit(void)
124{
125	if (!debugfs_root)
126		return;
127
128	debugfs_remove_recursive(debugfs_root);
129	debugfs_root = NULL;
130}
131
132void usnic_debugfs_flow_add(struct usnic_ib_qp_grp_flow *qp_flow)
133{
134	if (IS_ERR_OR_NULL(flows_dentry))
135		return;
136
137	scnprintf(qp_flow->dentry_name, sizeof(qp_flow->dentry_name),
138			"%u", qp_flow->flow->flow_id);
139	qp_flow->dbgfs_dentry = debugfs_create_file(qp_flow->dentry_name,
140							S_IRUGO,
141							flows_dentry,
142							qp_flow,
143							&flowinfo_ops);
144	if (IS_ERR_OR_NULL(qp_flow->dbgfs_dentry)) {
145		usnic_err("Failed to create dbg fs entry for flow %u\n",
146				qp_flow->flow->flow_id);
147	}
148}
149
150void usnic_debugfs_flow_remove(struct usnic_ib_qp_grp_flow *qp_flow)
151{
152	if (!IS_ERR_OR_NULL(qp_flow->dbgfs_dentry))
153		debugfs_remove(qp_flow->dbgfs_dentry);
154}
155