/*
 * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include <linux/debugfs.h>

#include "usnic.h"
#include "usnic_log.h"
#include "usnic_debugfs.h"
#include "usnic_ib_qp_grp.h"
#include "usnic_transport.h"

static struct dentry *debugfs_root;
static struct dentry *flows_dentry;

static ssize_t usnic_debugfs_buildinfo_read(struct file *f, char __user *data,
						size_t count, loff_t *ppos)
{
	char buf[500];
	int res;

	if (*ppos > 0)
		return 0;

	res = scnprintf(buf, sizeof(buf),
			"version:       %s\n"
			"build date:    %s\n",
			DRV_VERSION, DRV_RELDATE);

	return simple_read_from_buffer(data, count, ppos, buf, res);
}

static const struct file_operations usnic_debugfs_buildinfo_ops = {
	.owner = THIS_MODULE,
	.open = simple_open,
	.read = usnic_debugfs_buildinfo_read
};

static ssize_t flowinfo_read(struct file *f, char __user *data,
				size_t count, loff_t *ppos)
{
	struct usnic_ib_qp_grp_flow *qp_flow;
	int n;
	int left;
	char *ptr;
	char buf[512];

	qp_flow = f->private_data;
	ptr = buf;
	left = count;

	if (*ppos > 0)
		return 0;

	spin_lock(&qp_flow->qp_grp->lock);
	n = scnprintf(ptr, left,
			"QP Grp ID: %d Transport: %s ",
			qp_flow->qp_grp->grp_id,
			usnic_transport_to_str(qp_flow->trans_type));
	UPDATE_PTR_LEFT(n, ptr, left);
	if (qp_flow->trans_type == USNIC_TRANSPORT_ROCE_CUSTOM) {
		n = scnprintf(ptr, left, "Port_Num:%hu\n",
					qp_flow->usnic_roce.port_num);
		UPDATE_PTR_LEFT(n, ptr, left);
	} else if (qp_flow->trans_type == USNIC_TRANSPORT_IPV4_UDP) {
		n = usnic_transport_sock_to_str(ptr, left,
				qp_flow->udp.sock);
		UPDATE_PTR_LEFT(n, ptr, left);
		n = scnprintf(ptr, left, "\n");
		UPDATE_PTR_LEFT(n, ptr, left);
	}
	spin_unlock(&qp_flow->qp_grp->lock);

	return simple_read_from_buffer(data, count, ppos, buf, ptr - buf);
}

static const struct file_operations flowinfo_ops = {
	.owner = THIS_MODULE,
	.open = simple_open,
	.read = flowinfo_read,
};

void usnic_debugfs_init(void)
{
	debugfs_root = debugfs_create_dir(DRV_NAME, NULL);

	flows_dentry = debugfs_create_dir("flows", debugfs_root);

	debugfs_create_file("build-info", S_IRUGO, debugfs_root,
				NULL, &usnic_debugfs_buildinfo_ops);
}

void usnic_debugfs_exit(void)
{
	debugfs_remove_recursive(debugfs_root);
	debugfs_root = NULL;
}

void usnic_debugfs_flow_add(struct usnic_ib_qp_grp_flow *qp_flow)
{
	scnprintf(qp_flow->dentry_name, sizeof(qp_flow->dentry_name),
			"%u", qp_flow->flow->flow_id);
	qp_flow->dbgfs_dentry = debugfs_create_file(qp_flow->dentry_name,
							S_IRUGO,
							flows_dentry,
							qp_flow,
							&flowinfo_ops);
}

void usnic_debugfs_flow_remove(struct usnic_ib_qp_grp_flow *qp_flow)
{
	debugfs_remove(qp_flow->dbgfs_dentry);
}
