cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fnic_debugfs.c (20730B)


      1/*
      2 * Copyright 2012 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#include <linux/module.h>
     19#include <linux/errno.h>
     20#include <linux/debugfs.h>
     21#include <linux/vmalloc.h>
     22#include "fnic.h"
     23
     24static struct dentry *fnic_trace_debugfs_root;
     25static struct dentry *fnic_trace_debugfs_file;
     26static struct dentry *fnic_trace_enable;
     27static struct dentry *fnic_stats_debugfs_root;
     28
     29static struct dentry *fnic_fc_trace_debugfs_file;
     30static struct dentry *fnic_fc_rdata_trace_debugfs_file;
     31static struct dentry *fnic_fc_trace_enable;
     32static struct dentry *fnic_fc_trace_clear;
     33
     34struct fc_trace_flag_type {
     35	u8 fc_row_file;
     36	u8 fc_normal_file;
     37	u8 fnic_trace;
     38	u8 fc_trace;
     39	u8 fc_clear;
     40};
     41
     42static struct fc_trace_flag_type *fc_trc_flag;
     43
     44/*
     45 * fnic_debugfs_init - Initialize debugfs for fnic debug logging
     46 *
     47 * Description:
     48 * When Debugfs is configured this routine sets up the fnic debugfs
     49 * file system. If not already created, this routine will create the
     50 * fnic directory and statistics directory for trace buffer and
     51 * stats logging.
     52 */
     53int fnic_debugfs_init(void)
     54{
     55	fnic_trace_debugfs_root = debugfs_create_dir("fnic", NULL);
     56
     57	fnic_stats_debugfs_root = debugfs_create_dir("statistics",
     58						fnic_trace_debugfs_root);
     59
     60	/* Allocate memory to structure */
     61	fc_trc_flag = vmalloc(sizeof(struct fc_trace_flag_type));
     62
     63	if (fc_trc_flag) {
     64		fc_trc_flag->fc_row_file = 0;
     65		fc_trc_flag->fc_normal_file = 1;
     66		fc_trc_flag->fnic_trace = 2;
     67		fc_trc_flag->fc_trace = 3;
     68		fc_trc_flag->fc_clear = 4;
     69	}
     70
     71	return 0;
     72}
     73
     74/*
     75 * fnic_debugfs_terminate - Tear down debugfs infrastructure
     76 *
     77 * Description:
     78 * When Debugfs is configured this routine removes debugfs file system
     79 * elements that are specific to fnic.
     80 */
     81void fnic_debugfs_terminate(void)
     82{
     83	debugfs_remove(fnic_stats_debugfs_root);
     84	fnic_stats_debugfs_root = NULL;
     85
     86	debugfs_remove(fnic_trace_debugfs_root);
     87	fnic_trace_debugfs_root = NULL;
     88
     89	vfree(fc_trc_flag);
     90}
     91
     92/*
     93 * fnic_trace_ctrl_read -
     94 *          Read  trace_enable ,fc_trace_enable
     95 *              or fc_trace_clear debugfs file
     96 * @filp: The file pointer to read from.
     97 * @ubuf: The buffer to copy the data to.
     98 * @cnt: The number of bytes to read.
     99 * @ppos: The position in the file to start reading from.
    100 *
    101 * Description:
    102 * This routine reads value of variable fnic_tracing_enabled or
    103 * fnic_fc_tracing_enabled or fnic_fc_trace_cleared
    104 * and stores into local @buf.
    105 * It will start reading file at @ppos and
    106 * copy up to @cnt of data to @ubuf from @buf.
    107 *
    108 * Returns:
    109 * This function returns the amount of data that was read.
    110 */
    111static ssize_t fnic_trace_ctrl_read(struct file *filp,
    112				  char __user *ubuf,
    113				  size_t cnt, loff_t *ppos)
    114{
    115	char buf[64];
    116	int len;
    117	u8 *trace_type;
    118	len = 0;
    119	trace_type = (u8 *)filp->private_data;
    120	if (*trace_type == fc_trc_flag->fnic_trace)
    121		len = sprintf(buf, "%d\n", fnic_tracing_enabled);
    122	else if (*trace_type == fc_trc_flag->fc_trace)
    123		len = sprintf(buf, "%d\n", fnic_fc_tracing_enabled);
    124	else if (*trace_type == fc_trc_flag->fc_clear)
    125		len = sprintf(buf, "%d\n", fnic_fc_trace_cleared);
    126	else
    127		pr_err("fnic: Cannot read to any debugfs file\n");
    128
    129	return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
    130}
    131
    132/*
    133 * fnic_trace_ctrl_write -
    134 * Write to trace_enable, fc_trace_enable or
    135 *         fc_trace_clear debugfs file
    136 * @filp: The file pointer to write from.
    137 * @ubuf: The buffer to copy the data from.
    138 * @cnt: The number of bytes to write.
    139 * @ppos: The position in the file to start writing to.
    140 *
    141 * Description:
    142 * This routine writes data from user buffer @ubuf to buffer @buf and
    143 * sets fc_trace_enable ,tracing_enable or fnic_fc_trace_cleared
    144 * value as per user input.
    145 *
    146 * Returns:
    147 * This function returns the amount of data that was written.
    148 */
    149static ssize_t fnic_trace_ctrl_write(struct file *filp,
    150				  const char __user *ubuf,
    151				  size_t cnt, loff_t *ppos)
    152{
    153	char buf[64];
    154	unsigned long val;
    155	int ret;
    156	u8 *trace_type;
    157	trace_type = (u8 *)filp->private_data;
    158
    159	if (cnt >= sizeof(buf))
    160		return -EINVAL;
    161
    162	if (copy_from_user(&buf, ubuf, cnt))
    163		return -EFAULT;
    164
    165	buf[cnt] = 0;
    166
    167	ret = kstrtoul(buf, 10, &val);
    168	if (ret < 0)
    169		return ret;
    170
    171	if (*trace_type == fc_trc_flag->fnic_trace)
    172		fnic_tracing_enabled = val;
    173	else if (*trace_type == fc_trc_flag->fc_trace)
    174		fnic_fc_tracing_enabled = val;
    175	else if (*trace_type == fc_trc_flag->fc_clear)
    176		fnic_fc_trace_cleared = val;
    177	else
    178		pr_err("fnic: cannot write to any debugfs file\n");
    179
    180	(*ppos)++;
    181
    182	return cnt;
    183}
    184
    185static const struct file_operations fnic_trace_ctrl_fops = {
    186	.owner = THIS_MODULE,
    187	.open = simple_open,
    188	.read = fnic_trace_ctrl_read,
    189	.write = fnic_trace_ctrl_write,
    190};
    191
    192/*
    193 * fnic_trace_debugfs_open - Open the fnic trace log
    194 * @inode: The inode pointer
    195 * @file: The file pointer to attach the log output
    196 *
    197 * Description:
    198 * This routine is the entry point for the debugfs open file operation.
    199 * It allocates the necessary buffer for the log, fills the buffer from
    200 * the in-memory log and then returns a pointer to that log in
    201 * the private_data field in @file.
    202 *
    203 * Returns:
    204 * This function returns zero if successful. On error it will return
    205 * a negative error value.
    206 */
    207static int fnic_trace_debugfs_open(struct inode *inode,
    208				  struct file *file)
    209{
    210	fnic_dbgfs_t *fnic_dbg_prt;
    211	u8 *rdata_ptr;
    212	rdata_ptr = (u8 *)inode->i_private;
    213	fnic_dbg_prt = kzalloc(sizeof(fnic_dbgfs_t), GFP_KERNEL);
    214	if (!fnic_dbg_prt)
    215		return -ENOMEM;
    216
    217	if (*rdata_ptr == fc_trc_flag->fnic_trace) {
    218		fnic_dbg_prt->buffer = vmalloc(array3_size(3, trace_max_pages,
    219							   PAGE_SIZE));
    220		if (!fnic_dbg_prt->buffer) {
    221			kfree(fnic_dbg_prt);
    222			return -ENOMEM;
    223		}
    224		memset((void *)fnic_dbg_prt->buffer, 0,
    225		3 * (trace_max_pages * PAGE_SIZE));
    226		fnic_dbg_prt->buffer_len = fnic_get_trace_data(fnic_dbg_prt);
    227	} else {
    228		fnic_dbg_prt->buffer =
    229			vmalloc(array3_size(3, fnic_fc_trace_max_pages,
    230					    PAGE_SIZE));
    231		if (!fnic_dbg_prt->buffer) {
    232			kfree(fnic_dbg_prt);
    233			return -ENOMEM;
    234		}
    235		memset((void *)fnic_dbg_prt->buffer, 0,
    236			3 * (fnic_fc_trace_max_pages * PAGE_SIZE));
    237		fnic_dbg_prt->buffer_len =
    238			fnic_fc_trace_get_data(fnic_dbg_prt, *rdata_ptr);
    239	}
    240	file->private_data = fnic_dbg_prt;
    241
    242	return 0;
    243}
    244
    245/*
    246 * fnic_trace_debugfs_lseek - Seek through a debugfs file
    247 * @file: The file pointer to seek through.
    248 * @offset: The offset to seek to or the amount to seek by.
    249 * @howto: Indicates how to seek.
    250 *
    251 * Description:
    252 * This routine is the entry point for the debugfs lseek file operation.
    253 * The @howto parameter indicates whether @offset is the offset to directly
    254 * seek to, or if it is a value to seek forward or reverse by. This function
    255 * figures out what the new offset of the debugfs file will be and assigns
    256 * that value to the f_pos field of @file.
    257 *
    258 * Returns:
    259 * This function returns the new offset if successful and returns a negative
    260 * error if unable to process the seek.
    261 */
    262static loff_t fnic_trace_debugfs_lseek(struct file *file,
    263					loff_t offset,
    264					int howto)
    265{
    266	fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
    267	return fixed_size_llseek(file, offset, howto,
    268				fnic_dbg_prt->buffer_len);
    269}
    270
    271/*
    272 * fnic_trace_debugfs_read - Read a debugfs file
    273 * @file: The file pointer to read from.
    274 * @ubuf: The buffer to copy the data to.
    275 * @nbytes: The number of bytes to read.
    276 * @pos: The position in the file to start reading from.
    277 *
    278 * Description:
    279 * This routine reads data from the buffer indicated in the private_data
    280 * field of @file. It will start reading at @pos and copy up to @nbytes of
    281 * data to @ubuf.
    282 *
    283 * Returns:
    284 * This function returns the amount of data that was read (this could be
    285 * less than @nbytes if the end of the file was reached).
    286 */
    287static ssize_t fnic_trace_debugfs_read(struct file *file,
    288					char __user *ubuf,
    289					size_t nbytes,
    290					loff_t *pos)
    291{
    292	fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
    293	int rc = 0;
    294	rc = simple_read_from_buffer(ubuf, nbytes, pos,
    295				  fnic_dbg_prt->buffer,
    296				  fnic_dbg_prt->buffer_len);
    297	return rc;
    298}
    299
    300/*
    301 * fnic_trace_debugfs_release - Release the buffer used to store
    302 * debugfs file data
    303 * @inode: The inode pointer
    304 * @file: The file pointer that contains the buffer to release
    305 *
    306 * Description:
    307 * This routine frees the buffer that was allocated when the debugfs
    308 * file was opened.
    309 *
    310 * Returns:
    311 * This function returns zero.
    312 */
    313static int fnic_trace_debugfs_release(struct inode *inode,
    314					  struct file *file)
    315{
    316	fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
    317
    318	vfree(fnic_dbg_prt->buffer);
    319	kfree(fnic_dbg_prt);
    320	return 0;
    321}
    322
    323static const struct file_operations fnic_trace_debugfs_fops = {
    324	.owner = THIS_MODULE,
    325	.open = fnic_trace_debugfs_open,
    326	.llseek = fnic_trace_debugfs_lseek,
    327	.read = fnic_trace_debugfs_read,
    328	.release = fnic_trace_debugfs_release,
    329};
    330
    331/*
    332 * fnic_trace_debugfs_init - Initialize debugfs for fnic trace logging
    333 *
    334 * Description:
    335 * When Debugfs is configured this routine sets up the fnic debugfs
    336 * file system. If not already created, this routine will create the
    337 * create file trace to log fnic trace buffer output into debugfs and
    338 * it will also create file trace_enable to control enable/disable of
    339 * trace logging into trace buffer.
    340 */
    341void fnic_trace_debugfs_init(void)
    342{
    343	fnic_trace_enable = debugfs_create_file("tracing_enable",
    344					S_IFREG|S_IRUGO|S_IWUSR,
    345					fnic_trace_debugfs_root,
    346					&(fc_trc_flag->fnic_trace),
    347					&fnic_trace_ctrl_fops);
    348
    349	fnic_trace_debugfs_file = debugfs_create_file("trace",
    350					S_IFREG|S_IRUGO|S_IWUSR,
    351					fnic_trace_debugfs_root,
    352					&(fc_trc_flag->fnic_trace),
    353					&fnic_trace_debugfs_fops);
    354}
    355
    356/*
    357 * fnic_trace_debugfs_terminate - Tear down debugfs infrastructure
    358 *
    359 * Description:
    360 * When Debugfs is configured this routine removes debugfs file system
    361 * elements that are specific to fnic trace logging.
    362 */
    363void fnic_trace_debugfs_terminate(void)
    364{
    365	debugfs_remove(fnic_trace_debugfs_file);
    366	fnic_trace_debugfs_file = NULL;
    367
    368	debugfs_remove(fnic_trace_enable);
    369	fnic_trace_enable = NULL;
    370}
    371
    372/*
    373 * fnic_fc_trace_debugfs_init -
    374 * Initialize debugfs for fnic control frame trace logging
    375 *
    376 * Description:
    377 * When Debugfs is configured this routine sets up the fnic_fc debugfs
    378 * file system. If not already created, this routine will create the
    379 * create file trace to log fnic fc trace buffer output into debugfs and
    380 * it will also create file fc_trace_enable to control enable/disable of
    381 * trace logging into trace buffer.
    382 */
    383
    384void fnic_fc_trace_debugfs_init(void)
    385{
    386	fnic_fc_trace_enable = debugfs_create_file("fc_trace_enable",
    387					S_IFREG|S_IRUGO|S_IWUSR,
    388					fnic_trace_debugfs_root,
    389					&(fc_trc_flag->fc_trace),
    390					&fnic_trace_ctrl_fops);
    391
    392	fnic_fc_trace_clear = debugfs_create_file("fc_trace_clear",
    393					S_IFREG|S_IRUGO|S_IWUSR,
    394					fnic_trace_debugfs_root,
    395					&(fc_trc_flag->fc_clear),
    396					&fnic_trace_ctrl_fops);
    397
    398	fnic_fc_rdata_trace_debugfs_file =
    399		debugfs_create_file("fc_trace_rdata",
    400				    S_IFREG|S_IRUGO|S_IWUSR,
    401				    fnic_trace_debugfs_root,
    402				    &(fc_trc_flag->fc_normal_file),
    403				    &fnic_trace_debugfs_fops);
    404
    405	fnic_fc_trace_debugfs_file =
    406		debugfs_create_file("fc_trace",
    407				    S_IFREG|S_IRUGO|S_IWUSR,
    408				    fnic_trace_debugfs_root,
    409				    &(fc_trc_flag->fc_row_file),
    410				    &fnic_trace_debugfs_fops);
    411}
    412
    413/*
    414 * fnic_fc_trace_debugfs_terminate - Tear down debugfs infrastructure
    415 *
    416 * Description:
    417 * When Debugfs is configured this routine removes debugfs file system
    418 * elements that are specific to fnic_fc trace logging.
    419 */
    420
    421void fnic_fc_trace_debugfs_terminate(void)
    422{
    423	debugfs_remove(fnic_fc_trace_debugfs_file);
    424	fnic_fc_trace_debugfs_file = NULL;
    425
    426	debugfs_remove(fnic_fc_rdata_trace_debugfs_file);
    427	fnic_fc_rdata_trace_debugfs_file = NULL;
    428
    429	debugfs_remove(fnic_fc_trace_enable);
    430	fnic_fc_trace_enable = NULL;
    431
    432	debugfs_remove(fnic_fc_trace_clear);
    433	fnic_fc_trace_clear = NULL;
    434}
    435
    436/*
    437 * fnic_reset_stats_open - Open the reset_stats file
    438 * @inode: The inode pointer.
    439 * @file: The file pointer to attach the stats reset flag.
    440 *
    441 * Description:
    442 * This routine opens a debugsfs file reset_stats and stores i_private data
    443 * to debug structure to retrieve later for while performing other
    444 * file oprations.
    445 *
    446 * Returns:
    447 * This function returns zero if successful.
    448 */
    449static int fnic_reset_stats_open(struct inode *inode, struct file *file)
    450{
    451	struct stats_debug_info *debug;
    452
    453	debug = kzalloc(sizeof(struct stats_debug_info), GFP_KERNEL);
    454	if (!debug)
    455		return -ENOMEM;
    456
    457	debug->i_private = inode->i_private;
    458
    459	file->private_data = debug;
    460
    461	return 0;
    462}
    463
    464/*
    465 * fnic_reset_stats_read - Read a reset_stats debugfs file
    466 * @filp: The file pointer to read from.
    467 * @ubuf: The buffer to copy the data to.
    468 * @cnt: The number of bytes to read.
    469 * @ppos: The position in the file to start reading from.
    470 *
    471 * Description:
    472 * This routine reads value of variable reset_stats
    473 * and stores into local @buf. It will start reading file at @ppos and
    474 * copy up to @cnt of data to @ubuf from @buf.
    475 *
    476 * Returns:
    477 * This function returns the amount of data that was read.
    478 */
    479static ssize_t fnic_reset_stats_read(struct file *file,
    480					char __user *ubuf,
    481					size_t cnt, loff_t *ppos)
    482{
    483	struct stats_debug_info *debug = file->private_data;
    484	struct fnic *fnic = (struct fnic *)debug->i_private;
    485	char buf[64];
    486	int len;
    487
    488	len = sprintf(buf, "%u\n", fnic->reset_stats);
    489
    490	return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
    491}
    492
    493/*
    494 * fnic_reset_stats_write - Write to reset_stats debugfs file
    495 * @filp: The file pointer to write from.
    496 * @ubuf: The buffer to copy the data from.
    497 * @cnt: The number of bytes to write.
    498 * @ppos: The position in the file to start writing to.
    499 *
    500 * Description:
    501 * This routine writes data from user buffer @ubuf to buffer @buf and
    502 * resets cumulative stats of fnic.
    503 *
    504 * Returns:
    505 * This function returns the amount of data that was written.
    506 */
    507static ssize_t fnic_reset_stats_write(struct file *file,
    508					const char __user *ubuf,
    509					size_t cnt, loff_t *ppos)
    510{
    511	struct stats_debug_info *debug = file->private_data;
    512	struct fnic *fnic = (struct fnic *)debug->i_private;
    513	struct fnic_stats *stats = &fnic->fnic_stats;
    514	u64 *io_stats_p = (u64 *)&stats->io_stats;
    515	u64 *fw_stats_p = (u64 *)&stats->fw_stats;
    516	char buf[64];
    517	unsigned long val;
    518	int ret;
    519
    520	if (cnt >= sizeof(buf))
    521		return -EINVAL;
    522
    523	if (copy_from_user(&buf, ubuf, cnt))
    524		return -EFAULT;
    525
    526	buf[cnt] = 0;
    527
    528	ret = kstrtoul(buf, 10, &val);
    529	if (ret < 0)
    530		return ret;
    531
    532	fnic->reset_stats = val;
    533
    534	if (fnic->reset_stats) {
    535		/* Skip variable is used to avoid descrepancies to Num IOs
    536		 * and IO Completions stats. Skip incrementing No IO Compls
    537		 * for pending active IOs after reset stats
    538		 */
    539		atomic64_set(&fnic->io_cmpl_skip,
    540			atomic64_read(&stats->io_stats.active_ios));
    541		memset(&stats->abts_stats, 0, sizeof(struct abort_stats));
    542		memset(&stats->term_stats, 0,
    543			sizeof(struct terminate_stats));
    544		memset(&stats->reset_stats, 0, sizeof(struct reset_stats));
    545		memset(&stats->misc_stats, 0, sizeof(struct misc_stats));
    546		memset(&stats->vlan_stats, 0, sizeof(struct vlan_stats));
    547		memset(io_stats_p+1, 0,
    548			sizeof(struct io_path_stats) - sizeof(u64));
    549		memset(fw_stats_p+1, 0,
    550			sizeof(struct fw_stats) - sizeof(u64));
    551		ktime_get_real_ts64(&stats->stats_timestamps.last_reset_time);
    552	}
    553
    554	(*ppos)++;
    555	return cnt;
    556}
    557
    558/*
    559 * fnic_reset_stats_release - Release the buffer used to store
    560 * debugfs file data
    561 * @inode: The inode pointer
    562 * @file: The file pointer that contains the buffer to release
    563 *
    564 * Description:
    565 * This routine frees the buffer that was allocated when the debugfs
    566 * file was opened.
    567 *
    568 * Returns:
    569 * This function returns zero.
    570 */
    571static int fnic_reset_stats_release(struct inode *inode,
    572					struct file *file)
    573{
    574	struct stats_debug_info *debug = file->private_data;
    575	kfree(debug);
    576	return 0;
    577}
    578
    579/*
    580 * fnic_stats_debugfs_open - Open the stats file for specific host
    581 * and get fnic stats.
    582 * @inode: The inode pointer.
    583 * @file: The file pointer to attach the specific host statistics.
    584 *
    585 * Description:
    586 * This routine opens a debugsfs file stats of specific host and print
    587 * fnic stats.
    588 *
    589 * Returns:
    590 * This function returns zero if successful.
    591 */
    592static int fnic_stats_debugfs_open(struct inode *inode,
    593					struct file *file)
    594{
    595	struct fnic *fnic = inode->i_private;
    596	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
    597	struct stats_debug_info *debug;
    598	int buf_size = 2 * PAGE_SIZE;
    599
    600	debug = kzalloc(sizeof(struct stats_debug_info), GFP_KERNEL);
    601	if (!debug)
    602		return -ENOMEM;
    603
    604	debug->debug_buffer = vmalloc(buf_size);
    605	if (!debug->debug_buffer) {
    606		kfree(debug);
    607		return -ENOMEM;
    608	}
    609
    610	debug->buf_size = buf_size;
    611	memset((void *)debug->debug_buffer, 0, buf_size);
    612	debug->buffer_len = fnic_get_stats_data(debug, fnic_stats);
    613
    614	file->private_data = debug;
    615
    616	return 0;
    617}
    618
    619/*
    620 * fnic_stats_debugfs_read - Read a debugfs file
    621 * @file: The file pointer to read from.
    622 * @ubuf: The buffer to copy the data to.
    623 * @nbytes: The number of bytes to read.
    624 * @pos: The position in the file to start reading from.
    625 *
    626 * Description:
    627 * This routine reads data from the buffer indicated in the private_data
    628 * field of @file. It will start reading at @pos and copy up to @nbytes of
    629 * data to @ubuf.
    630 *
    631 * Returns:
    632 * This function returns the amount of data that was read (this could be
    633 * less than @nbytes if the end of the file was reached).
    634 */
    635static ssize_t fnic_stats_debugfs_read(struct file *file,
    636					char __user *ubuf,
    637					size_t nbytes,
    638					loff_t *pos)
    639{
    640	struct stats_debug_info *debug = file->private_data;
    641	int rc = 0;
    642	rc = simple_read_from_buffer(ubuf, nbytes, pos,
    643					debug->debug_buffer,
    644					debug->buffer_len);
    645	return rc;
    646}
    647
    648/*
    649 * fnic_stats_stats_release - Release the buffer used to store
    650 * debugfs file data
    651 * @inode: The inode pointer
    652 * @file: The file pointer that contains the buffer to release
    653 *
    654 * Description:
    655 * This routine frees the buffer that was allocated when the debugfs
    656 * file was opened.
    657 *
    658 * Returns:
    659 * This function returns zero.
    660 */
    661static int fnic_stats_debugfs_release(struct inode *inode,
    662					struct file *file)
    663{
    664	struct stats_debug_info *debug = file->private_data;
    665	vfree(debug->debug_buffer);
    666	kfree(debug);
    667	return 0;
    668}
    669
    670static const struct file_operations fnic_stats_debugfs_fops = {
    671	.owner = THIS_MODULE,
    672	.open = fnic_stats_debugfs_open,
    673	.read = fnic_stats_debugfs_read,
    674	.release = fnic_stats_debugfs_release,
    675};
    676
    677static const struct file_operations fnic_reset_debugfs_fops = {
    678	.owner = THIS_MODULE,
    679	.open = fnic_reset_stats_open,
    680	.read = fnic_reset_stats_read,
    681	.write = fnic_reset_stats_write,
    682	.release = fnic_reset_stats_release,
    683};
    684
    685/*
    686 * fnic_stats_init - Initialize stats struct and create stats file per fnic
    687 *
    688 * Description:
    689 * When Debugfs is configured this routine sets up the stats file per fnic
    690 * It will create file stats and reset_stats under statistics/host# directory
    691 * to log per fnic stats.
    692 */
    693void fnic_stats_debugfs_init(struct fnic *fnic)
    694{
    695	char name[16];
    696
    697	snprintf(name, sizeof(name), "host%d", fnic->lport->host->host_no);
    698
    699	fnic->fnic_stats_debugfs_host = debugfs_create_dir(name,
    700						fnic_stats_debugfs_root);
    701
    702	fnic->fnic_stats_debugfs_file = debugfs_create_file("stats",
    703						S_IFREG|S_IRUGO|S_IWUSR,
    704						fnic->fnic_stats_debugfs_host,
    705						fnic,
    706						&fnic_stats_debugfs_fops);
    707
    708	fnic->fnic_reset_debugfs_file = debugfs_create_file("reset_stats",
    709						S_IFREG|S_IRUGO|S_IWUSR,
    710						fnic->fnic_stats_debugfs_host,
    711						fnic,
    712						&fnic_reset_debugfs_fops);
    713}
    714
    715/*
    716 * fnic_stats_debugfs_remove - Tear down debugfs infrastructure of stats
    717 *
    718 * Description:
    719 * When Debugfs is configured this routine removes debugfs file system
    720 * elements that are specific to fnic stats.
    721 */
    722void fnic_stats_debugfs_remove(struct fnic *fnic)
    723{
    724	if (!fnic)
    725		return;
    726
    727	debugfs_remove(fnic->fnic_stats_debugfs_file);
    728	fnic->fnic_stats_debugfs_file = NULL;
    729
    730	debugfs_remove(fnic->fnic_reset_debugfs_file);
    731	fnic->fnic_reset_debugfs_file = NULL;
    732
    733	debugfs_remove(fnic->fnic_stats_debugfs_host);
    734	fnic->fnic_stats_debugfs_host = NULL;
    735}