xref: /linux/drivers/scsi/fnic/fnic_debugfs.c (revision 24bce201d79807b668bf9d9e0aca801c5c0d5f78)
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 
24 static struct dentry *fnic_trace_debugfs_root;
25 static struct dentry *fnic_trace_debugfs_file;
26 static struct dentry *fnic_trace_enable;
27 static struct dentry *fnic_stats_debugfs_root;
28 
29 static struct dentry *fnic_fc_trace_debugfs_file;
30 static struct dentry *fnic_fc_rdata_trace_debugfs_file;
31 static struct dentry *fnic_fc_trace_enable;
32 static struct dentry *fnic_fc_trace_clear;
33 
34 struct 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 
42 static 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  */
53 int 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  */
81 void 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  */
111 static 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  */
149 static 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 
185 static 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  */
207 static 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  */
262 static 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  */
287 static 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  */
313 static 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 
323 static 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  */
341 void 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  */
363 void 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 
384 void 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 
421 void 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  */
449 static 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  */
479 static 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  */
507 static 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  */
571 static 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  */
592 static 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  */
635 static 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  */
661 static 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 
670 static 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 
677 static 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  */
693 void 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  */
722 void 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 }
736