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 */
fnic_debugfs_init(void)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 */
fnic_debugfs_terminate(void)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 */
fnic_trace_ctrl_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)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 */
fnic_trace_ctrl_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)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 */
fnic_trace_debugfs_open(struct inode * inode,struct file * file)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 */
fnic_trace_debugfs_lseek(struct file * file,loff_t offset,int howto)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 */
fnic_trace_debugfs_read(struct file * file,char __user * ubuf,size_t nbytes,loff_t * pos)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 */
fnic_trace_debugfs_release(struct inode * inode,struct file * file)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 */
fnic_trace_debugfs_init(void)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 */
fnic_trace_debugfs_terminate(void)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
fnic_fc_trace_debugfs_init(void)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
fnic_fc_trace_debugfs_terminate(void)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 */
fnic_reset_stats_open(struct inode * inode,struct file * file)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 */
fnic_reset_stats_read(struct file * file,char __user * ubuf,size_t cnt,loff_t * ppos)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 */
fnic_reset_stats_write(struct file * file,const char __user * ubuf,size_t cnt,loff_t * ppos)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 */
fnic_reset_stats_release(struct inode * inode,struct file * file)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 */
fnic_stats_debugfs_open(struct inode * inode,struct file * file)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 */
fnic_stats_debugfs_read(struct file * file,char __user * ubuf,size_t nbytes,loff_t * pos)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 */
fnic_stats_debugfs_release(struct inode * inode,struct file * file)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 */
fnic_stats_debugfs_init(struct fnic * fnic)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 */
fnic_stats_debugfs_remove(struct fnic * fnic)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