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