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