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