18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2012 Cisco Systems, Inc.  All rights reserved.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * This program is free software; you may redistribute it and/or modify
58c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by
68c2ecf20Sopenharmony_ci * the Free Software Foundation; version 2 of the License.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
98c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
108c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
118c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
128c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
138c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
148c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
158c2ecf20Sopenharmony_ci * SOFTWARE.
168c2ecf20Sopenharmony_ci */
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <linux/module.h>
198c2ecf20Sopenharmony_ci#include <linux/errno.h>
208c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
218c2ecf20Sopenharmony_ci#include <linux/vmalloc.h>
228c2ecf20Sopenharmony_ci#include "fnic.h"
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistatic struct dentry *fnic_trace_debugfs_root;
258c2ecf20Sopenharmony_cistatic struct dentry *fnic_trace_debugfs_file;
268c2ecf20Sopenharmony_cistatic struct dentry *fnic_trace_enable;
278c2ecf20Sopenharmony_cistatic struct dentry *fnic_stats_debugfs_root;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic struct dentry *fnic_fc_trace_debugfs_file;
308c2ecf20Sopenharmony_cistatic struct dentry *fnic_fc_rdata_trace_debugfs_file;
318c2ecf20Sopenharmony_cistatic struct dentry *fnic_fc_trace_enable;
328c2ecf20Sopenharmony_cistatic struct dentry *fnic_fc_trace_clear;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistruct fc_trace_flag_type {
358c2ecf20Sopenharmony_ci	u8 fc_row_file;
368c2ecf20Sopenharmony_ci	u8 fc_normal_file;
378c2ecf20Sopenharmony_ci	u8 fnic_trace;
388c2ecf20Sopenharmony_ci	u8 fc_trace;
398c2ecf20Sopenharmony_ci	u8 fc_clear;
408c2ecf20Sopenharmony_ci};
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic struct fc_trace_flag_type *fc_trc_flag;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/*
458c2ecf20Sopenharmony_ci * fnic_debugfs_init - Initialize debugfs for fnic debug logging
468c2ecf20Sopenharmony_ci *
478c2ecf20Sopenharmony_ci * Description:
488c2ecf20Sopenharmony_ci * When Debugfs is configured this routine sets up the fnic debugfs
498c2ecf20Sopenharmony_ci * file system. If not already created, this routine will create the
508c2ecf20Sopenharmony_ci * fnic directory and statistics directory for trace buffer and
518c2ecf20Sopenharmony_ci * stats logging.
528c2ecf20Sopenharmony_ci */
538c2ecf20Sopenharmony_ciint fnic_debugfs_init(void)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	fnic_trace_debugfs_root = debugfs_create_dir("fnic", NULL);
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	fnic_stats_debugfs_root = debugfs_create_dir("statistics",
588c2ecf20Sopenharmony_ci						fnic_trace_debugfs_root);
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	/* Allocate memory to structure */
618c2ecf20Sopenharmony_ci	fc_trc_flag = (struct fc_trace_flag_type *)
628c2ecf20Sopenharmony_ci		vmalloc(sizeof(struct fc_trace_flag_type));
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	if (fc_trc_flag) {
658c2ecf20Sopenharmony_ci		fc_trc_flag->fc_row_file = 0;
668c2ecf20Sopenharmony_ci		fc_trc_flag->fc_normal_file = 1;
678c2ecf20Sopenharmony_ci		fc_trc_flag->fnic_trace = 2;
688c2ecf20Sopenharmony_ci		fc_trc_flag->fc_trace = 3;
698c2ecf20Sopenharmony_ci		fc_trc_flag->fc_clear = 4;
708c2ecf20Sopenharmony_ci		return 0;
718c2ecf20Sopenharmony_ci	}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	return -ENOMEM;
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci/*
778c2ecf20Sopenharmony_ci * fnic_debugfs_terminate - Tear down debugfs infrastructure
788c2ecf20Sopenharmony_ci *
798c2ecf20Sopenharmony_ci * Description:
808c2ecf20Sopenharmony_ci * When Debugfs is configured this routine removes debugfs file system
818c2ecf20Sopenharmony_ci * elements that are specific to fnic.
828c2ecf20Sopenharmony_ci */
838c2ecf20Sopenharmony_civoid fnic_debugfs_terminate(void)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	debugfs_remove(fnic_stats_debugfs_root);
868c2ecf20Sopenharmony_ci	fnic_stats_debugfs_root = NULL;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	debugfs_remove(fnic_trace_debugfs_root);
898c2ecf20Sopenharmony_ci	fnic_trace_debugfs_root = NULL;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	if (fc_trc_flag)
928c2ecf20Sopenharmony_ci		vfree(fc_trc_flag);
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci/*
968c2ecf20Sopenharmony_ci * fnic_trace_ctrl_read -
978c2ecf20Sopenharmony_ci *          Read  trace_enable ,fc_trace_enable
988c2ecf20Sopenharmony_ci *              or fc_trace_clear debugfs file
998c2ecf20Sopenharmony_ci * @filp: The file pointer to read from.
1008c2ecf20Sopenharmony_ci * @ubuf: The buffer to copy the data to.
1018c2ecf20Sopenharmony_ci * @cnt: The number of bytes to read.
1028c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from.
1038c2ecf20Sopenharmony_ci *
1048c2ecf20Sopenharmony_ci * Description:
1058c2ecf20Sopenharmony_ci * This routine reads value of variable fnic_tracing_enabled or
1068c2ecf20Sopenharmony_ci * fnic_fc_tracing_enabled or fnic_fc_trace_cleared
1078c2ecf20Sopenharmony_ci * and stores into local @buf.
1088c2ecf20Sopenharmony_ci * It will start reading file at @ppos and
1098c2ecf20Sopenharmony_ci * copy up to @cnt of data to @ubuf from @buf.
1108c2ecf20Sopenharmony_ci *
1118c2ecf20Sopenharmony_ci * Returns:
1128c2ecf20Sopenharmony_ci * This function returns the amount of data that was read.
1138c2ecf20Sopenharmony_ci */
1148c2ecf20Sopenharmony_cistatic ssize_t fnic_trace_ctrl_read(struct file *filp,
1158c2ecf20Sopenharmony_ci				  char __user *ubuf,
1168c2ecf20Sopenharmony_ci				  size_t cnt, loff_t *ppos)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	char buf[64];
1198c2ecf20Sopenharmony_ci	int len;
1208c2ecf20Sopenharmony_ci	u8 *trace_type;
1218c2ecf20Sopenharmony_ci	len = 0;
1228c2ecf20Sopenharmony_ci	trace_type = (u8 *)filp->private_data;
1238c2ecf20Sopenharmony_ci	if (*trace_type == fc_trc_flag->fnic_trace)
1248c2ecf20Sopenharmony_ci		len = sprintf(buf, "%d\n", fnic_tracing_enabled);
1258c2ecf20Sopenharmony_ci	else if (*trace_type == fc_trc_flag->fc_trace)
1268c2ecf20Sopenharmony_ci		len = sprintf(buf, "%d\n", fnic_fc_tracing_enabled);
1278c2ecf20Sopenharmony_ci	else if (*trace_type == fc_trc_flag->fc_clear)
1288c2ecf20Sopenharmony_ci		len = sprintf(buf, "%d\n", fnic_fc_trace_cleared);
1298c2ecf20Sopenharmony_ci	else
1308c2ecf20Sopenharmony_ci		pr_err("fnic: Cannot read to any debugfs file\n");
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
1338c2ecf20Sopenharmony_ci}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci/*
1368c2ecf20Sopenharmony_ci * fnic_trace_ctrl_write -
1378c2ecf20Sopenharmony_ci * Write to trace_enable, fc_trace_enable or
1388c2ecf20Sopenharmony_ci *         fc_trace_clear debugfs file
1398c2ecf20Sopenharmony_ci * @filp: The file pointer to write from.
1408c2ecf20Sopenharmony_ci * @ubuf: The buffer to copy the data from.
1418c2ecf20Sopenharmony_ci * @cnt: The number of bytes to write.
1428c2ecf20Sopenharmony_ci * @ppos: The position in the file to start writing to.
1438c2ecf20Sopenharmony_ci *
1448c2ecf20Sopenharmony_ci * Description:
1458c2ecf20Sopenharmony_ci * This routine writes data from user buffer @ubuf to buffer @buf and
1468c2ecf20Sopenharmony_ci * sets fc_trace_enable ,tracing_enable or fnic_fc_trace_cleared
1478c2ecf20Sopenharmony_ci * value as per user input.
1488c2ecf20Sopenharmony_ci *
1498c2ecf20Sopenharmony_ci * Returns:
1508c2ecf20Sopenharmony_ci * This function returns the amount of data that was written.
1518c2ecf20Sopenharmony_ci */
1528c2ecf20Sopenharmony_cistatic ssize_t fnic_trace_ctrl_write(struct file *filp,
1538c2ecf20Sopenharmony_ci				  const char __user *ubuf,
1548c2ecf20Sopenharmony_ci				  size_t cnt, loff_t *ppos)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	char buf[64];
1578c2ecf20Sopenharmony_ci	unsigned long val;
1588c2ecf20Sopenharmony_ci	int ret;
1598c2ecf20Sopenharmony_ci	u8 *trace_type;
1608c2ecf20Sopenharmony_ci	trace_type = (u8 *)filp->private_data;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	if (cnt >= sizeof(buf))
1638c2ecf20Sopenharmony_ci		return -EINVAL;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	if (copy_from_user(&buf, ubuf, cnt))
1668c2ecf20Sopenharmony_ci		return -EFAULT;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	buf[cnt] = 0;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	ret = kstrtoul(buf, 10, &val);
1718c2ecf20Sopenharmony_ci	if (ret < 0)
1728c2ecf20Sopenharmony_ci		return ret;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	if (*trace_type == fc_trc_flag->fnic_trace)
1758c2ecf20Sopenharmony_ci		fnic_tracing_enabled = val;
1768c2ecf20Sopenharmony_ci	else if (*trace_type == fc_trc_flag->fc_trace)
1778c2ecf20Sopenharmony_ci		fnic_fc_tracing_enabled = val;
1788c2ecf20Sopenharmony_ci	else if (*trace_type == fc_trc_flag->fc_clear)
1798c2ecf20Sopenharmony_ci		fnic_fc_trace_cleared = val;
1808c2ecf20Sopenharmony_ci	else
1818c2ecf20Sopenharmony_ci		pr_err("fnic: cannot write to any debugfs file\n");
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	(*ppos)++;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	return cnt;
1868c2ecf20Sopenharmony_ci}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_cistatic const struct file_operations fnic_trace_ctrl_fops = {
1898c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
1908c2ecf20Sopenharmony_ci	.open = simple_open,
1918c2ecf20Sopenharmony_ci	.read = fnic_trace_ctrl_read,
1928c2ecf20Sopenharmony_ci	.write = fnic_trace_ctrl_write,
1938c2ecf20Sopenharmony_ci};
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci/*
1968c2ecf20Sopenharmony_ci * fnic_trace_debugfs_open - Open the fnic trace log
1978c2ecf20Sopenharmony_ci * @inode: The inode pointer
1988c2ecf20Sopenharmony_ci * @file: The file pointer to attach the log output
1998c2ecf20Sopenharmony_ci *
2008c2ecf20Sopenharmony_ci * Description:
2018c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs open file operation.
2028c2ecf20Sopenharmony_ci * It allocates the necessary buffer for the log, fills the buffer from
2038c2ecf20Sopenharmony_ci * the in-memory log and then returns a pointer to that log in
2048c2ecf20Sopenharmony_ci * the private_data field in @file.
2058c2ecf20Sopenharmony_ci *
2068c2ecf20Sopenharmony_ci * Returns:
2078c2ecf20Sopenharmony_ci * This function returns zero if successful. On error it will return
2088c2ecf20Sopenharmony_ci * a negative error value.
2098c2ecf20Sopenharmony_ci */
2108c2ecf20Sopenharmony_cistatic int fnic_trace_debugfs_open(struct inode *inode,
2118c2ecf20Sopenharmony_ci				  struct file *file)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	fnic_dbgfs_t *fnic_dbg_prt;
2148c2ecf20Sopenharmony_ci	u8 *rdata_ptr;
2158c2ecf20Sopenharmony_ci	rdata_ptr = (u8 *)inode->i_private;
2168c2ecf20Sopenharmony_ci	fnic_dbg_prt = kzalloc(sizeof(fnic_dbgfs_t), GFP_KERNEL);
2178c2ecf20Sopenharmony_ci	if (!fnic_dbg_prt)
2188c2ecf20Sopenharmony_ci		return -ENOMEM;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	if (*rdata_ptr == fc_trc_flag->fnic_trace) {
2218c2ecf20Sopenharmony_ci		fnic_dbg_prt->buffer = vmalloc(array3_size(3, trace_max_pages,
2228c2ecf20Sopenharmony_ci							   PAGE_SIZE));
2238c2ecf20Sopenharmony_ci		if (!fnic_dbg_prt->buffer) {
2248c2ecf20Sopenharmony_ci			kfree(fnic_dbg_prt);
2258c2ecf20Sopenharmony_ci			return -ENOMEM;
2268c2ecf20Sopenharmony_ci		}
2278c2ecf20Sopenharmony_ci		memset((void *)fnic_dbg_prt->buffer, 0,
2288c2ecf20Sopenharmony_ci		3 * (trace_max_pages * PAGE_SIZE));
2298c2ecf20Sopenharmony_ci		fnic_dbg_prt->buffer_len = fnic_get_trace_data(fnic_dbg_prt);
2308c2ecf20Sopenharmony_ci	} else {
2318c2ecf20Sopenharmony_ci		fnic_dbg_prt->buffer =
2328c2ecf20Sopenharmony_ci			vmalloc(array3_size(3, fnic_fc_trace_max_pages,
2338c2ecf20Sopenharmony_ci					    PAGE_SIZE));
2348c2ecf20Sopenharmony_ci		if (!fnic_dbg_prt->buffer) {
2358c2ecf20Sopenharmony_ci			kfree(fnic_dbg_prt);
2368c2ecf20Sopenharmony_ci			return -ENOMEM;
2378c2ecf20Sopenharmony_ci		}
2388c2ecf20Sopenharmony_ci		memset((void *)fnic_dbg_prt->buffer, 0,
2398c2ecf20Sopenharmony_ci			3 * (fnic_fc_trace_max_pages * PAGE_SIZE));
2408c2ecf20Sopenharmony_ci		fnic_dbg_prt->buffer_len =
2418c2ecf20Sopenharmony_ci			fnic_fc_trace_get_data(fnic_dbg_prt, *rdata_ptr);
2428c2ecf20Sopenharmony_ci	}
2438c2ecf20Sopenharmony_ci	file->private_data = fnic_dbg_prt;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	return 0;
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci/*
2498c2ecf20Sopenharmony_ci * fnic_trace_debugfs_lseek - Seek through a debugfs file
2508c2ecf20Sopenharmony_ci * @file: The file pointer to seek through.
2518c2ecf20Sopenharmony_ci * @offset: The offset to seek to or the amount to seek by.
2528c2ecf20Sopenharmony_ci * @howto: Indicates how to seek.
2538c2ecf20Sopenharmony_ci *
2548c2ecf20Sopenharmony_ci * Description:
2558c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs lseek file operation.
2568c2ecf20Sopenharmony_ci * The @howto parameter indicates whether @offset is the offset to directly
2578c2ecf20Sopenharmony_ci * seek to, or if it is a value to seek forward or reverse by. This function
2588c2ecf20Sopenharmony_ci * figures out what the new offset of the debugfs file will be and assigns
2598c2ecf20Sopenharmony_ci * that value to the f_pos field of @file.
2608c2ecf20Sopenharmony_ci *
2618c2ecf20Sopenharmony_ci * Returns:
2628c2ecf20Sopenharmony_ci * This function returns the new offset if successful and returns a negative
2638c2ecf20Sopenharmony_ci * error if unable to process the seek.
2648c2ecf20Sopenharmony_ci */
2658c2ecf20Sopenharmony_cistatic loff_t fnic_trace_debugfs_lseek(struct file *file,
2668c2ecf20Sopenharmony_ci					loff_t offset,
2678c2ecf20Sopenharmony_ci					int howto)
2688c2ecf20Sopenharmony_ci{
2698c2ecf20Sopenharmony_ci	fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
2708c2ecf20Sopenharmony_ci	return fixed_size_llseek(file, offset, howto,
2718c2ecf20Sopenharmony_ci				fnic_dbg_prt->buffer_len);
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci/*
2758c2ecf20Sopenharmony_ci * fnic_trace_debugfs_read - Read a debugfs file
2768c2ecf20Sopenharmony_ci * @file: The file pointer to read from.
2778c2ecf20Sopenharmony_ci * @ubuf: The buffer to copy the data to.
2788c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to read.
2798c2ecf20Sopenharmony_ci * @pos: The position in the file to start reading from.
2808c2ecf20Sopenharmony_ci *
2818c2ecf20Sopenharmony_ci * Description:
2828c2ecf20Sopenharmony_ci * This routine reads data from the buffer indicated in the private_data
2838c2ecf20Sopenharmony_ci * field of @file. It will start reading at @pos and copy up to @nbytes of
2848c2ecf20Sopenharmony_ci * data to @ubuf.
2858c2ecf20Sopenharmony_ci *
2868c2ecf20Sopenharmony_ci * Returns:
2878c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be
2888c2ecf20Sopenharmony_ci * less than @nbytes if the end of the file was reached).
2898c2ecf20Sopenharmony_ci */
2908c2ecf20Sopenharmony_cistatic ssize_t fnic_trace_debugfs_read(struct file *file,
2918c2ecf20Sopenharmony_ci					char __user *ubuf,
2928c2ecf20Sopenharmony_ci					size_t nbytes,
2938c2ecf20Sopenharmony_ci					loff_t *pos)
2948c2ecf20Sopenharmony_ci{
2958c2ecf20Sopenharmony_ci	fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
2968c2ecf20Sopenharmony_ci	int rc = 0;
2978c2ecf20Sopenharmony_ci	rc = simple_read_from_buffer(ubuf, nbytes, pos,
2988c2ecf20Sopenharmony_ci				  fnic_dbg_prt->buffer,
2998c2ecf20Sopenharmony_ci				  fnic_dbg_prt->buffer_len);
3008c2ecf20Sopenharmony_ci	return rc;
3018c2ecf20Sopenharmony_ci}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci/*
3048c2ecf20Sopenharmony_ci * fnic_trace_debugfs_release - Release the buffer used to store
3058c2ecf20Sopenharmony_ci * debugfs file data
3068c2ecf20Sopenharmony_ci * @inode: The inode pointer
3078c2ecf20Sopenharmony_ci * @file: The file pointer that contains the buffer to release
3088c2ecf20Sopenharmony_ci *
3098c2ecf20Sopenharmony_ci * Description:
3108c2ecf20Sopenharmony_ci * This routine frees the buffer that was allocated when the debugfs
3118c2ecf20Sopenharmony_ci * file was opened.
3128c2ecf20Sopenharmony_ci *
3138c2ecf20Sopenharmony_ci * Returns:
3148c2ecf20Sopenharmony_ci * This function returns zero.
3158c2ecf20Sopenharmony_ci */
3168c2ecf20Sopenharmony_cistatic int fnic_trace_debugfs_release(struct inode *inode,
3178c2ecf20Sopenharmony_ci					  struct file *file)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	vfree(fnic_dbg_prt->buffer);
3228c2ecf20Sopenharmony_ci	kfree(fnic_dbg_prt);
3238c2ecf20Sopenharmony_ci	return 0;
3248c2ecf20Sopenharmony_ci}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_cistatic const struct file_operations fnic_trace_debugfs_fops = {
3278c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
3288c2ecf20Sopenharmony_ci	.open = fnic_trace_debugfs_open,
3298c2ecf20Sopenharmony_ci	.llseek = fnic_trace_debugfs_lseek,
3308c2ecf20Sopenharmony_ci	.read = fnic_trace_debugfs_read,
3318c2ecf20Sopenharmony_ci	.release = fnic_trace_debugfs_release,
3328c2ecf20Sopenharmony_ci};
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci/*
3358c2ecf20Sopenharmony_ci * fnic_trace_debugfs_init - Initialize debugfs for fnic trace logging
3368c2ecf20Sopenharmony_ci *
3378c2ecf20Sopenharmony_ci * Description:
3388c2ecf20Sopenharmony_ci * When Debugfs is configured this routine sets up the fnic debugfs
3398c2ecf20Sopenharmony_ci * file system. If not already created, this routine will create the
3408c2ecf20Sopenharmony_ci * create file trace to log fnic trace buffer output into debugfs and
3418c2ecf20Sopenharmony_ci * it will also create file trace_enable to control enable/disable of
3428c2ecf20Sopenharmony_ci * trace logging into trace buffer.
3438c2ecf20Sopenharmony_ci */
3448c2ecf20Sopenharmony_civoid fnic_trace_debugfs_init(void)
3458c2ecf20Sopenharmony_ci{
3468c2ecf20Sopenharmony_ci	fnic_trace_enable = debugfs_create_file("tracing_enable",
3478c2ecf20Sopenharmony_ci					S_IFREG|S_IRUGO|S_IWUSR,
3488c2ecf20Sopenharmony_ci					fnic_trace_debugfs_root,
3498c2ecf20Sopenharmony_ci					&(fc_trc_flag->fnic_trace),
3508c2ecf20Sopenharmony_ci					&fnic_trace_ctrl_fops);
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	fnic_trace_debugfs_file = debugfs_create_file("trace",
3538c2ecf20Sopenharmony_ci					S_IFREG|S_IRUGO|S_IWUSR,
3548c2ecf20Sopenharmony_ci					fnic_trace_debugfs_root,
3558c2ecf20Sopenharmony_ci					&(fc_trc_flag->fnic_trace),
3568c2ecf20Sopenharmony_ci					&fnic_trace_debugfs_fops);
3578c2ecf20Sopenharmony_ci}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci/*
3608c2ecf20Sopenharmony_ci * fnic_trace_debugfs_terminate - Tear down debugfs infrastructure
3618c2ecf20Sopenharmony_ci *
3628c2ecf20Sopenharmony_ci * Description:
3638c2ecf20Sopenharmony_ci * When Debugfs is configured this routine removes debugfs file system
3648c2ecf20Sopenharmony_ci * elements that are specific to fnic trace logging.
3658c2ecf20Sopenharmony_ci */
3668c2ecf20Sopenharmony_civoid fnic_trace_debugfs_terminate(void)
3678c2ecf20Sopenharmony_ci{
3688c2ecf20Sopenharmony_ci	debugfs_remove(fnic_trace_debugfs_file);
3698c2ecf20Sopenharmony_ci	fnic_trace_debugfs_file = NULL;
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	debugfs_remove(fnic_trace_enable);
3728c2ecf20Sopenharmony_ci	fnic_trace_enable = NULL;
3738c2ecf20Sopenharmony_ci}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci/*
3768c2ecf20Sopenharmony_ci * fnic_fc_trace_debugfs_init -
3778c2ecf20Sopenharmony_ci * Initialize debugfs for fnic control frame trace logging
3788c2ecf20Sopenharmony_ci *
3798c2ecf20Sopenharmony_ci * Description:
3808c2ecf20Sopenharmony_ci * When Debugfs is configured this routine sets up the fnic_fc debugfs
3818c2ecf20Sopenharmony_ci * file system. If not already created, this routine will create the
3828c2ecf20Sopenharmony_ci * create file trace to log fnic fc trace buffer output into debugfs and
3838c2ecf20Sopenharmony_ci * it will also create file fc_trace_enable to control enable/disable of
3848c2ecf20Sopenharmony_ci * trace logging into trace buffer.
3858c2ecf20Sopenharmony_ci */
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_civoid fnic_fc_trace_debugfs_init(void)
3888c2ecf20Sopenharmony_ci{
3898c2ecf20Sopenharmony_ci	fnic_fc_trace_enable = debugfs_create_file("fc_trace_enable",
3908c2ecf20Sopenharmony_ci					S_IFREG|S_IRUGO|S_IWUSR,
3918c2ecf20Sopenharmony_ci					fnic_trace_debugfs_root,
3928c2ecf20Sopenharmony_ci					&(fc_trc_flag->fc_trace),
3938c2ecf20Sopenharmony_ci					&fnic_trace_ctrl_fops);
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	fnic_fc_trace_clear = debugfs_create_file("fc_trace_clear",
3968c2ecf20Sopenharmony_ci					S_IFREG|S_IRUGO|S_IWUSR,
3978c2ecf20Sopenharmony_ci					fnic_trace_debugfs_root,
3988c2ecf20Sopenharmony_ci					&(fc_trc_flag->fc_clear),
3998c2ecf20Sopenharmony_ci					&fnic_trace_ctrl_fops);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	fnic_fc_rdata_trace_debugfs_file =
4028c2ecf20Sopenharmony_ci		debugfs_create_file("fc_trace_rdata",
4038c2ecf20Sopenharmony_ci				    S_IFREG|S_IRUGO|S_IWUSR,
4048c2ecf20Sopenharmony_ci				    fnic_trace_debugfs_root,
4058c2ecf20Sopenharmony_ci				    &(fc_trc_flag->fc_normal_file),
4068c2ecf20Sopenharmony_ci				    &fnic_trace_debugfs_fops);
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	fnic_fc_trace_debugfs_file =
4098c2ecf20Sopenharmony_ci		debugfs_create_file("fc_trace",
4108c2ecf20Sopenharmony_ci				    S_IFREG|S_IRUGO|S_IWUSR,
4118c2ecf20Sopenharmony_ci				    fnic_trace_debugfs_root,
4128c2ecf20Sopenharmony_ci				    &(fc_trc_flag->fc_row_file),
4138c2ecf20Sopenharmony_ci				    &fnic_trace_debugfs_fops);
4148c2ecf20Sopenharmony_ci}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci/*
4178c2ecf20Sopenharmony_ci * fnic_fc_trace_debugfs_terminate - Tear down debugfs infrastructure
4188c2ecf20Sopenharmony_ci *
4198c2ecf20Sopenharmony_ci * Description:
4208c2ecf20Sopenharmony_ci * When Debugfs is configured this routine removes debugfs file system
4218c2ecf20Sopenharmony_ci * elements that are specific to fnic_fc trace logging.
4228c2ecf20Sopenharmony_ci */
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_civoid fnic_fc_trace_debugfs_terminate(void)
4258c2ecf20Sopenharmony_ci{
4268c2ecf20Sopenharmony_ci	debugfs_remove(fnic_fc_trace_debugfs_file);
4278c2ecf20Sopenharmony_ci	fnic_fc_trace_debugfs_file = NULL;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	debugfs_remove(fnic_fc_rdata_trace_debugfs_file);
4308c2ecf20Sopenharmony_ci	fnic_fc_rdata_trace_debugfs_file = NULL;
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	debugfs_remove(fnic_fc_trace_enable);
4338c2ecf20Sopenharmony_ci	fnic_fc_trace_enable = NULL;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	debugfs_remove(fnic_fc_trace_clear);
4368c2ecf20Sopenharmony_ci	fnic_fc_trace_clear = NULL;
4378c2ecf20Sopenharmony_ci}
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci/*
4408c2ecf20Sopenharmony_ci * fnic_reset_stats_open - Open the reset_stats file
4418c2ecf20Sopenharmony_ci * @inode: The inode pointer.
4428c2ecf20Sopenharmony_ci * @file: The file pointer to attach the stats reset flag.
4438c2ecf20Sopenharmony_ci *
4448c2ecf20Sopenharmony_ci * Description:
4458c2ecf20Sopenharmony_ci * This routine opens a debugsfs file reset_stats and stores i_private data
4468c2ecf20Sopenharmony_ci * to debug structure to retrieve later for while performing other
4478c2ecf20Sopenharmony_ci * file oprations.
4488c2ecf20Sopenharmony_ci *
4498c2ecf20Sopenharmony_ci * Returns:
4508c2ecf20Sopenharmony_ci * This function returns zero if successful.
4518c2ecf20Sopenharmony_ci */
4528c2ecf20Sopenharmony_cistatic int fnic_reset_stats_open(struct inode *inode, struct file *file)
4538c2ecf20Sopenharmony_ci{
4548c2ecf20Sopenharmony_ci	struct stats_debug_info *debug;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	debug = kzalloc(sizeof(struct stats_debug_info), GFP_KERNEL);
4578c2ecf20Sopenharmony_ci	if (!debug)
4588c2ecf20Sopenharmony_ci		return -ENOMEM;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	debug->i_private = inode->i_private;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	file->private_data = debug;
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	return 0;
4658c2ecf20Sopenharmony_ci}
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci/*
4688c2ecf20Sopenharmony_ci * fnic_reset_stats_read - Read a reset_stats debugfs file
4698c2ecf20Sopenharmony_ci * @filp: The file pointer to read from.
4708c2ecf20Sopenharmony_ci * @ubuf: The buffer to copy the data to.
4718c2ecf20Sopenharmony_ci * @cnt: The number of bytes to read.
4728c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from.
4738c2ecf20Sopenharmony_ci *
4748c2ecf20Sopenharmony_ci * Description:
4758c2ecf20Sopenharmony_ci * This routine reads value of variable reset_stats
4768c2ecf20Sopenharmony_ci * and stores into local @buf. It will start reading file at @ppos and
4778c2ecf20Sopenharmony_ci * copy up to @cnt of data to @ubuf from @buf.
4788c2ecf20Sopenharmony_ci *
4798c2ecf20Sopenharmony_ci * Returns:
4808c2ecf20Sopenharmony_ci * This function returns the amount of data that was read.
4818c2ecf20Sopenharmony_ci */
4828c2ecf20Sopenharmony_cistatic ssize_t fnic_reset_stats_read(struct file *file,
4838c2ecf20Sopenharmony_ci					char __user *ubuf,
4848c2ecf20Sopenharmony_ci					size_t cnt, loff_t *ppos)
4858c2ecf20Sopenharmony_ci{
4868c2ecf20Sopenharmony_ci	struct stats_debug_info *debug = file->private_data;
4878c2ecf20Sopenharmony_ci	struct fnic *fnic = (struct fnic *)debug->i_private;
4888c2ecf20Sopenharmony_ci	char buf[64];
4898c2ecf20Sopenharmony_ci	int len;
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	len = sprintf(buf, "%u\n", fnic->reset_stats);
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci/*
4978c2ecf20Sopenharmony_ci * fnic_reset_stats_write - Write to reset_stats debugfs file
4988c2ecf20Sopenharmony_ci * @filp: The file pointer to write from.
4998c2ecf20Sopenharmony_ci * @ubuf: The buffer to copy the data from.
5008c2ecf20Sopenharmony_ci * @cnt: The number of bytes to write.
5018c2ecf20Sopenharmony_ci * @ppos: The position in the file to start writing to.
5028c2ecf20Sopenharmony_ci *
5038c2ecf20Sopenharmony_ci * Description:
5048c2ecf20Sopenharmony_ci * This routine writes data from user buffer @ubuf to buffer @buf and
5058c2ecf20Sopenharmony_ci * resets cumulative stats of fnic.
5068c2ecf20Sopenharmony_ci *
5078c2ecf20Sopenharmony_ci * Returns:
5088c2ecf20Sopenharmony_ci * This function returns the amount of data that was written.
5098c2ecf20Sopenharmony_ci */
5108c2ecf20Sopenharmony_cistatic ssize_t fnic_reset_stats_write(struct file *file,
5118c2ecf20Sopenharmony_ci					const char __user *ubuf,
5128c2ecf20Sopenharmony_ci					size_t cnt, loff_t *ppos)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	struct stats_debug_info *debug = file->private_data;
5158c2ecf20Sopenharmony_ci	struct fnic *fnic = (struct fnic *)debug->i_private;
5168c2ecf20Sopenharmony_ci	struct fnic_stats *stats = &fnic->fnic_stats;
5178c2ecf20Sopenharmony_ci	u64 *io_stats_p = (u64 *)&stats->io_stats;
5188c2ecf20Sopenharmony_ci	u64 *fw_stats_p = (u64 *)&stats->fw_stats;
5198c2ecf20Sopenharmony_ci	char buf[64];
5208c2ecf20Sopenharmony_ci	unsigned long val;
5218c2ecf20Sopenharmony_ci	int ret;
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	if (cnt >= sizeof(buf))
5248c2ecf20Sopenharmony_ci		return -EINVAL;
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	if (copy_from_user(&buf, ubuf, cnt))
5278c2ecf20Sopenharmony_ci		return -EFAULT;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	buf[cnt] = 0;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	ret = kstrtoul(buf, 10, &val);
5328c2ecf20Sopenharmony_ci	if (ret < 0)
5338c2ecf20Sopenharmony_ci		return ret;
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	fnic->reset_stats = val;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	if (fnic->reset_stats) {
5388c2ecf20Sopenharmony_ci		/* Skip variable is used to avoid descrepancies to Num IOs
5398c2ecf20Sopenharmony_ci		 * and IO Completions stats. Skip incrementing No IO Compls
5408c2ecf20Sopenharmony_ci		 * for pending active IOs after reset stats
5418c2ecf20Sopenharmony_ci		 */
5428c2ecf20Sopenharmony_ci		atomic64_set(&fnic->io_cmpl_skip,
5438c2ecf20Sopenharmony_ci			atomic64_read(&stats->io_stats.active_ios));
5448c2ecf20Sopenharmony_ci		memset(&stats->abts_stats, 0, sizeof(struct abort_stats));
5458c2ecf20Sopenharmony_ci		memset(&stats->term_stats, 0,
5468c2ecf20Sopenharmony_ci			sizeof(struct terminate_stats));
5478c2ecf20Sopenharmony_ci		memset(&stats->reset_stats, 0, sizeof(struct reset_stats));
5488c2ecf20Sopenharmony_ci		memset(&stats->misc_stats, 0, sizeof(struct misc_stats));
5498c2ecf20Sopenharmony_ci		memset(&stats->vlan_stats, 0, sizeof(struct vlan_stats));
5508c2ecf20Sopenharmony_ci		memset(io_stats_p+1, 0,
5518c2ecf20Sopenharmony_ci			sizeof(struct io_path_stats) - sizeof(u64));
5528c2ecf20Sopenharmony_ci		memset(fw_stats_p+1, 0,
5538c2ecf20Sopenharmony_ci			sizeof(struct fw_stats) - sizeof(u64));
5548c2ecf20Sopenharmony_ci		ktime_get_real_ts64(&stats->stats_timestamps.last_reset_time);
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	(*ppos)++;
5588c2ecf20Sopenharmony_ci	return cnt;
5598c2ecf20Sopenharmony_ci}
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci/*
5628c2ecf20Sopenharmony_ci * fnic_reset_stats_release - Release the buffer used to store
5638c2ecf20Sopenharmony_ci * debugfs file data
5648c2ecf20Sopenharmony_ci * @inode: The inode pointer
5658c2ecf20Sopenharmony_ci * @file: The file pointer that contains the buffer to release
5668c2ecf20Sopenharmony_ci *
5678c2ecf20Sopenharmony_ci * Description:
5688c2ecf20Sopenharmony_ci * This routine frees the buffer that was allocated when the debugfs
5698c2ecf20Sopenharmony_ci * file was opened.
5708c2ecf20Sopenharmony_ci *
5718c2ecf20Sopenharmony_ci * Returns:
5728c2ecf20Sopenharmony_ci * This function returns zero.
5738c2ecf20Sopenharmony_ci */
5748c2ecf20Sopenharmony_cistatic int fnic_reset_stats_release(struct inode *inode,
5758c2ecf20Sopenharmony_ci					struct file *file)
5768c2ecf20Sopenharmony_ci{
5778c2ecf20Sopenharmony_ci	struct stats_debug_info *debug = file->private_data;
5788c2ecf20Sopenharmony_ci	kfree(debug);
5798c2ecf20Sopenharmony_ci	return 0;
5808c2ecf20Sopenharmony_ci}
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci/*
5838c2ecf20Sopenharmony_ci * fnic_stats_debugfs_open - Open the stats file for specific host
5848c2ecf20Sopenharmony_ci * and get fnic stats.
5858c2ecf20Sopenharmony_ci * @inode: The inode pointer.
5868c2ecf20Sopenharmony_ci * @file: The file pointer to attach the specific host statistics.
5878c2ecf20Sopenharmony_ci *
5888c2ecf20Sopenharmony_ci * Description:
5898c2ecf20Sopenharmony_ci * This routine opens a debugsfs file stats of specific host and print
5908c2ecf20Sopenharmony_ci * fnic stats.
5918c2ecf20Sopenharmony_ci *
5928c2ecf20Sopenharmony_ci * Returns:
5938c2ecf20Sopenharmony_ci * This function returns zero if successful.
5948c2ecf20Sopenharmony_ci */
5958c2ecf20Sopenharmony_cistatic int fnic_stats_debugfs_open(struct inode *inode,
5968c2ecf20Sopenharmony_ci					struct file *file)
5978c2ecf20Sopenharmony_ci{
5988c2ecf20Sopenharmony_ci	struct fnic *fnic = inode->i_private;
5998c2ecf20Sopenharmony_ci	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
6008c2ecf20Sopenharmony_ci	struct stats_debug_info *debug;
6018c2ecf20Sopenharmony_ci	int buf_size = 2 * PAGE_SIZE;
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	debug = kzalloc(sizeof(struct stats_debug_info), GFP_KERNEL);
6048c2ecf20Sopenharmony_ci	if (!debug)
6058c2ecf20Sopenharmony_ci		return -ENOMEM;
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	debug->debug_buffer = vmalloc(buf_size);
6088c2ecf20Sopenharmony_ci	if (!debug->debug_buffer) {
6098c2ecf20Sopenharmony_ci		kfree(debug);
6108c2ecf20Sopenharmony_ci		return -ENOMEM;
6118c2ecf20Sopenharmony_ci	}
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	debug->buf_size = buf_size;
6148c2ecf20Sopenharmony_ci	memset((void *)debug->debug_buffer, 0, buf_size);
6158c2ecf20Sopenharmony_ci	debug->buffer_len = fnic_get_stats_data(debug, fnic_stats);
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	file->private_data = debug;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	return 0;
6208c2ecf20Sopenharmony_ci}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci/*
6238c2ecf20Sopenharmony_ci * fnic_stats_debugfs_read - Read a debugfs file
6248c2ecf20Sopenharmony_ci * @file: The file pointer to read from.
6258c2ecf20Sopenharmony_ci * @ubuf: The buffer to copy the data to.
6268c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to read.
6278c2ecf20Sopenharmony_ci * @pos: The position in the file to start reading from.
6288c2ecf20Sopenharmony_ci *
6298c2ecf20Sopenharmony_ci * Description:
6308c2ecf20Sopenharmony_ci * This routine reads data from the buffer indicated in the private_data
6318c2ecf20Sopenharmony_ci * field of @file. It will start reading at @pos and copy up to @nbytes of
6328c2ecf20Sopenharmony_ci * data to @ubuf.
6338c2ecf20Sopenharmony_ci *
6348c2ecf20Sopenharmony_ci * Returns:
6358c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be
6368c2ecf20Sopenharmony_ci * less than @nbytes if the end of the file was reached).
6378c2ecf20Sopenharmony_ci */
6388c2ecf20Sopenharmony_cistatic ssize_t fnic_stats_debugfs_read(struct file *file,
6398c2ecf20Sopenharmony_ci					char __user *ubuf,
6408c2ecf20Sopenharmony_ci					size_t nbytes,
6418c2ecf20Sopenharmony_ci					loff_t *pos)
6428c2ecf20Sopenharmony_ci{
6438c2ecf20Sopenharmony_ci	struct stats_debug_info *debug = file->private_data;
6448c2ecf20Sopenharmony_ci	int rc = 0;
6458c2ecf20Sopenharmony_ci	rc = simple_read_from_buffer(ubuf, nbytes, pos,
6468c2ecf20Sopenharmony_ci					debug->debug_buffer,
6478c2ecf20Sopenharmony_ci					debug->buffer_len);
6488c2ecf20Sopenharmony_ci	return rc;
6498c2ecf20Sopenharmony_ci}
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci/*
6528c2ecf20Sopenharmony_ci * fnic_stats_stats_release - Release the buffer used to store
6538c2ecf20Sopenharmony_ci * debugfs file data
6548c2ecf20Sopenharmony_ci * @inode: The inode pointer
6558c2ecf20Sopenharmony_ci * @file: The file pointer that contains the buffer to release
6568c2ecf20Sopenharmony_ci *
6578c2ecf20Sopenharmony_ci * Description:
6588c2ecf20Sopenharmony_ci * This routine frees the buffer that was allocated when the debugfs
6598c2ecf20Sopenharmony_ci * file was opened.
6608c2ecf20Sopenharmony_ci *
6618c2ecf20Sopenharmony_ci * Returns:
6628c2ecf20Sopenharmony_ci * This function returns zero.
6638c2ecf20Sopenharmony_ci */
6648c2ecf20Sopenharmony_cistatic int fnic_stats_debugfs_release(struct inode *inode,
6658c2ecf20Sopenharmony_ci					struct file *file)
6668c2ecf20Sopenharmony_ci{
6678c2ecf20Sopenharmony_ci	struct stats_debug_info *debug = file->private_data;
6688c2ecf20Sopenharmony_ci	vfree(debug->debug_buffer);
6698c2ecf20Sopenharmony_ci	kfree(debug);
6708c2ecf20Sopenharmony_ci	return 0;
6718c2ecf20Sopenharmony_ci}
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_cistatic const struct file_operations fnic_stats_debugfs_fops = {
6748c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
6758c2ecf20Sopenharmony_ci	.open = fnic_stats_debugfs_open,
6768c2ecf20Sopenharmony_ci	.read = fnic_stats_debugfs_read,
6778c2ecf20Sopenharmony_ci	.release = fnic_stats_debugfs_release,
6788c2ecf20Sopenharmony_ci};
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_cistatic const struct file_operations fnic_reset_debugfs_fops = {
6818c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
6828c2ecf20Sopenharmony_ci	.open = fnic_reset_stats_open,
6838c2ecf20Sopenharmony_ci	.read = fnic_reset_stats_read,
6848c2ecf20Sopenharmony_ci	.write = fnic_reset_stats_write,
6858c2ecf20Sopenharmony_ci	.release = fnic_reset_stats_release,
6868c2ecf20Sopenharmony_ci};
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci/*
6898c2ecf20Sopenharmony_ci * fnic_stats_init - Initialize stats struct and create stats file per fnic
6908c2ecf20Sopenharmony_ci *
6918c2ecf20Sopenharmony_ci * Description:
6928c2ecf20Sopenharmony_ci * When Debugfs is configured this routine sets up the stats file per fnic
6938c2ecf20Sopenharmony_ci * It will create file stats and reset_stats under statistics/host# directory
6948c2ecf20Sopenharmony_ci * to log per fnic stats.
6958c2ecf20Sopenharmony_ci */
6968c2ecf20Sopenharmony_civoid fnic_stats_debugfs_init(struct fnic *fnic)
6978c2ecf20Sopenharmony_ci{
6988c2ecf20Sopenharmony_ci	char name[16];
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	snprintf(name, sizeof(name), "host%d", fnic->lport->host->host_no);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	fnic->fnic_stats_debugfs_host = debugfs_create_dir(name,
7038c2ecf20Sopenharmony_ci						fnic_stats_debugfs_root);
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	fnic->fnic_stats_debugfs_file = debugfs_create_file("stats",
7068c2ecf20Sopenharmony_ci						S_IFREG|S_IRUGO|S_IWUSR,
7078c2ecf20Sopenharmony_ci						fnic->fnic_stats_debugfs_host,
7088c2ecf20Sopenharmony_ci						fnic,
7098c2ecf20Sopenharmony_ci						&fnic_stats_debugfs_fops);
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	fnic->fnic_reset_debugfs_file = debugfs_create_file("reset_stats",
7128c2ecf20Sopenharmony_ci						S_IFREG|S_IRUGO|S_IWUSR,
7138c2ecf20Sopenharmony_ci						fnic->fnic_stats_debugfs_host,
7148c2ecf20Sopenharmony_ci						fnic,
7158c2ecf20Sopenharmony_ci						&fnic_reset_debugfs_fops);
7168c2ecf20Sopenharmony_ci}
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci/*
7198c2ecf20Sopenharmony_ci * fnic_stats_debugfs_remove - Tear down debugfs infrastructure of stats
7208c2ecf20Sopenharmony_ci *
7218c2ecf20Sopenharmony_ci * Description:
7228c2ecf20Sopenharmony_ci * When Debugfs is configured this routine removes debugfs file system
7238c2ecf20Sopenharmony_ci * elements that are specific to fnic stats.
7248c2ecf20Sopenharmony_ci */
7258c2ecf20Sopenharmony_civoid fnic_stats_debugfs_remove(struct fnic *fnic)
7268c2ecf20Sopenharmony_ci{
7278c2ecf20Sopenharmony_ci	if (!fnic)
7288c2ecf20Sopenharmony_ci		return;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	debugfs_remove(fnic->fnic_stats_debugfs_file);
7318c2ecf20Sopenharmony_ci	fnic->fnic_stats_debugfs_file = NULL;
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	debugfs_remove(fnic->fnic_reset_debugfs_file);
7348c2ecf20Sopenharmony_ci	fnic->fnic_reset_debugfs_file = NULL;
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	debugfs_remove(fnic->fnic_stats_debugfs_host);
7378c2ecf20Sopenharmony_ci	fnic->fnic_stats_debugfs_host = NULL;
7388c2ecf20Sopenharmony_ci}
739