1 /* 2 * Copyright 2014 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 22 #include "snic.h" 23 24 /* 25 * snic_debugfs_init - Initialize debugfs for snic debug logging 26 * 27 * Description: 28 * When Debugfs is configured this routine sets up fnic debugfs 29 * filesystem. If not already created. this routine will crate the 30 * fnic directory and statistics directory for trace buffer and 31 * stats logging 32 */ 33 void snic_debugfs_init(void) 34 { 35 snic_glob->trc_root = debugfs_create_dir("snic", NULL); 36 37 snic_glob->stats_root = debugfs_create_dir("statistics", 38 snic_glob->trc_root); 39 } 40 41 /* 42 * snic_debugfs_term - Tear down debugfs intrastructure 43 * 44 * Description: 45 * When Debufs is configured this routine removes debugfs file system 46 * elements that are specific to snic 47 */ 48 void 49 snic_debugfs_term(void) 50 { 51 debugfs_remove(snic_glob->stats_root); 52 snic_glob->stats_root = NULL; 53 54 debugfs_remove(snic_glob->trc_root); 55 snic_glob->trc_root = NULL; 56 } 57 58 /* 59 * snic_reset_stats_open - Open the reset_stats file 60 */ 61 static int 62 snic_reset_stats_open(struct inode *inode, struct file *filp) 63 { 64 SNIC_BUG_ON(!inode->i_private); 65 filp->private_data = inode->i_private; 66 67 return 0; 68 } 69 70 /* 71 * snic_reset_stats_read - Read a reset_stats debugfs file 72 * @filp: The file pointer to read from. 73 * @ubuf: The buffer tocopy the data to. 74 * @cnt: The number of bytes to read. 75 * @ppos: The position in the file to start reading frm. 76 * 77 * Description: 78 * This routine reads value of variable reset_stats 79 * and stores into local @buf. It will start reading file @ppos and 80 * copy up to @cnt of data to @ubuf from @buf. 81 * 82 * Returns: 83 * This function returns the amount of data that was read. 84 */ 85 static ssize_t 86 snic_reset_stats_read(struct file *filp, 87 char __user *ubuf, 88 size_t cnt, 89 loff_t *ppos) 90 { 91 struct snic *snic = (struct snic *) filp->private_data; 92 char buf[64]; 93 int len; 94 95 len = sprintf(buf, "%u\n", snic->reset_stats); 96 97 return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); 98 } 99 100 /* 101 * snic_reset_stats_write - Write to reset_stats debugfs file 102 * @filp: The file pointer to write from 103 * @ubuf: The buffer to copy the data from. 104 * @cnt: The number of bytes to write. 105 * @ppos: The position in the file to start writing to. 106 * 107 * Description: 108 * This routine writes data from user buffer @ubuf to buffer @buf and 109 * resets cumulative stats of snic. 110 * 111 * Returns: 112 * This function returns the amount of data that was written. 113 */ 114 static ssize_t 115 snic_reset_stats_write(struct file *filp, 116 const char __user *ubuf, 117 size_t cnt, 118 loff_t *ppos) 119 { 120 struct snic *snic = (struct snic *) filp->private_data; 121 struct snic_stats *stats = &snic->s_stats; 122 u64 *io_stats_p = (u64 *) &stats->io; 123 u64 *fw_stats_p = (u64 *) &stats->fw; 124 char buf[64]; 125 unsigned long val; 126 int ret; 127 128 if (cnt >= sizeof(buf)) 129 return -EINVAL; 130 131 if (copy_from_user(&buf, ubuf, cnt)) 132 return -EFAULT; 133 134 buf[cnt] = '\0'; 135 136 ret = kstrtoul(buf, 10, &val); 137 if (ret < 0) 138 return ret; 139 140 snic->reset_stats = val; 141 142 if (snic->reset_stats) { 143 /* Skip variable is used to avoid descrepancies to Num IOs 144 * and IO Completions stats. Skip incrementing No IO Compls 145 * for pending active IOs after reset_stats 146 */ 147 atomic64_set(&snic->io_cmpl_skip, 148 atomic64_read(&stats->io.active)); 149 memset(&stats->abts, 0, sizeof(struct snic_abort_stats)); 150 memset(&stats->reset, 0, sizeof(struct snic_reset_stats)); 151 memset(&stats->misc, 0, sizeof(struct snic_misc_stats)); 152 memset(io_stats_p+1, 153 0, 154 sizeof(struct snic_io_stats) - sizeof(u64)); 155 memset(fw_stats_p+1, 156 0, 157 sizeof(struct snic_fw_stats) - sizeof(u64)); 158 } 159 160 (*ppos)++; 161 162 SNIC_HOST_INFO(snic->shost, "Reset Op: Driver statistics.\n"); 163 164 return cnt; 165 } 166 167 static int 168 snic_reset_stats_release(struct inode *inode, struct file *filp) 169 { 170 filp->private_data = NULL; 171 172 return 0; 173 } 174 175 /* 176 * snic_stats_show - Formats and prints per host specific driver stats. 177 */ 178 static int 179 snic_stats_show(struct seq_file *sfp, void *data) 180 { 181 struct snic *snic = (struct snic *) sfp->private; 182 struct snic_stats *stats = &snic->s_stats; 183 struct timespec64 last_isr_tms, last_ack_tms; 184 u64 maxio_tm; 185 int i; 186 187 /* Dump IO Stats */ 188 seq_printf(sfp, 189 "------------------------------------------\n" 190 "\t\t IO Statistics\n" 191 "------------------------------------------\n"); 192 193 maxio_tm = (u64) atomic64_read(&stats->io.max_time); 194 seq_printf(sfp, 195 "Active IOs : %lld\n" 196 "Max Active IOs : %lld\n" 197 "Total IOs : %lld\n" 198 "IOs Completed : %lld\n" 199 "IOs Failed : %lld\n" 200 "IOs Not Found : %lld\n" 201 "Memory Alloc Failures : %lld\n" 202 "REQs Null : %lld\n" 203 "SCSI Cmd Pointers Null : %lld\n" 204 "Max SGL for any IO : %lld\n" 205 "Max IO Size : %lld Sectors\n" 206 "Max Queuing Time : %lld\n" 207 "Max Completion Time : %lld\n" 208 "Max IO Process Time(FW) : %lld (%u msec)\n", 209 (u64) atomic64_read(&stats->io.active), 210 (u64) atomic64_read(&stats->io.max_active), 211 (u64) atomic64_read(&stats->io.num_ios), 212 (u64) atomic64_read(&stats->io.compl), 213 (u64) atomic64_read(&stats->io.fail), 214 (u64) atomic64_read(&stats->io.io_not_found), 215 (u64) atomic64_read(&stats->io.alloc_fail), 216 (u64) atomic64_read(&stats->io.req_null), 217 (u64) atomic64_read(&stats->io.sc_null), 218 (u64) atomic64_read(&stats->io.max_sgl), 219 (u64) atomic64_read(&stats->io.max_io_sz), 220 (u64) atomic64_read(&stats->io.max_qtime), 221 (u64) atomic64_read(&stats->io.max_cmpl_time), 222 maxio_tm, 223 jiffies_to_msecs(maxio_tm)); 224 225 seq_puts(sfp, "\nSGL Counters\n"); 226 227 for (i = 0; i < SNIC_MAX_SG_DESC_CNT; i++) { 228 seq_printf(sfp, 229 "%10lld ", 230 (u64) atomic64_read(&stats->io.sgl_cnt[i])); 231 232 if ((i + 1) % 8 == 0) 233 seq_puts(sfp, "\n"); 234 } 235 236 /* Dump Abort Stats */ 237 seq_printf(sfp, 238 "\n-------------------------------------------\n" 239 "\t\t Abort Statistics\n" 240 "---------------------------------------------\n"); 241 242 seq_printf(sfp, 243 "Aborts : %lld\n" 244 "Aborts Fail : %lld\n" 245 "Aborts Driver Timeout : %lld\n" 246 "Abort FW Timeout : %lld\n" 247 "Abort IO NOT Found : %lld\n" 248 "Abort Queuing Failed : %lld\n", 249 (u64) atomic64_read(&stats->abts.num), 250 (u64) atomic64_read(&stats->abts.fail), 251 (u64) atomic64_read(&stats->abts.drv_tmo), 252 (u64) atomic64_read(&stats->abts.fw_tmo), 253 (u64) atomic64_read(&stats->abts.io_not_found), 254 (u64) atomic64_read(&stats->abts.q_fail)); 255 256 /* Dump Reset Stats */ 257 seq_printf(sfp, 258 "\n-------------------------------------------\n" 259 "\t\t Reset Statistics\n" 260 "---------------------------------------------\n"); 261 262 seq_printf(sfp, 263 "HBA Resets : %lld\n" 264 "HBA Reset Cmpls : %lld\n" 265 "HBA Reset Fail : %lld\n", 266 (u64) atomic64_read(&stats->reset.hba_resets), 267 (u64) atomic64_read(&stats->reset.hba_reset_cmpl), 268 (u64) atomic64_read(&stats->reset.hba_reset_fail)); 269 270 /* Dump Firmware Stats */ 271 seq_printf(sfp, 272 "\n-------------------------------------------\n" 273 "\t\t Firmware Statistics\n" 274 "---------------------------------------------\n"); 275 276 seq_printf(sfp, 277 "Active FW Requests : %lld\n" 278 "Max FW Requests : %lld\n" 279 "FW Out Of Resource Errs : %lld\n" 280 "FW IO Errors : %lld\n" 281 "FW SCSI Errors : %lld\n", 282 (u64) atomic64_read(&stats->fw.actv_reqs), 283 (u64) atomic64_read(&stats->fw.max_actv_reqs), 284 (u64) atomic64_read(&stats->fw.out_of_res), 285 (u64) atomic64_read(&stats->fw.io_errs), 286 (u64) atomic64_read(&stats->fw.scsi_errs)); 287 288 289 /* Dump Miscellenous Stats */ 290 seq_printf(sfp, 291 "\n---------------------------------------------\n" 292 "\t\t Other Statistics\n" 293 "\n---------------------------------------------\n"); 294 295 jiffies_to_timespec64(stats->misc.last_isr_time, &last_isr_tms); 296 jiffies_to_timespec64(stats->misc.last_ack_time, &last_ack_tms); 297 298 seq_printf(sfp, 299 "Last ISR Time : %llu (%8llu.%09lu)\n" 300 "Last Ack Time : %llu (%8llu.%09lu)\n" 301 "Ack ISRs : %llu\n" 302 "IO Cmpl ISRs : %llu\n" 303 "Err Notify ISRs : %llu\n" 304 "Max CQ Entries : %lld\n" 305 "Data Count Mismatch : %lld\n" 306 "IOs w/ Timeout Status : %lld\n" 307 "IOs w/ Aborted Status : %lld\n" 308 "IOs w/ SGL Invalid Stat : %lld\n" 309 "WQ Desc Alloc Fail : %lld\n" 310 "Queue Full : %lld\n" 311 "Queue Ramp Up : %lld\n" 312 "Queue Ramp Down : %lld\n" 313 "Queue Last Queue Depth : %lld\n" 314 "Target Not Ready : %lld\n", 315 (u64) stats->misc.last_isr_time, 316 last_isr_tms.tv_sec, last_isr_tms.tv_nsec, 317 (u64)stats->misc.last_ack_time, 318 last_ack_tms.tv_sec, last_ack_tms.tv_nsec, 319 (u64) atomic64_read(&stats->misc.ack_isr_cnt), 320 (u64) atomic64_read(&stats->misc.cmpl_isr_cnt), 321 (u64) atomic64_read(&stats->misc.errnotify_isr_cnt), 322 (u64) atomic64_read(&stats->misc.max_cq_ents), 323 (u64) atomic64_read(&stats->misc.data_cnt_mismat), 324 (u64) atomic64_read(&stats->misc.io_tmo), 325 (u64) atomic64_read(&stats->misc.io_aborted), 326 (u64) atomic64_read(&stats->misc.sgl_inval), 327 (u64) atomic64_read(&stats->misc.wq_alloc_fail), 328 (u64) atomic64_read(&stats->misc.qfull), 329 (u64) atomic64_read(&stats->misc.qsz_rampup), 330 (u64) atomic64_read(&stats->misc.qsz_rampdown), 331 (u64) atomic64_read(&stats->misc.last_qsz), 332 (u64) atomic64_read(&stats->misc.tgt_not_rdy)); 333 334 return 0; 335 } 336 337 /* 338 * snic_stats_open - Open the stats file for specific host 339 * 340 * Description: 341 * This routine opens a debugfs file stats of specific host 342 */ 343 static int 344 snic_stats_open(struct inode *inode, struct file *filp) 345 { 346 return single_open(filp, snic_stats_show, inode->i_private); 347 } 348 349 static const struct file_operations snic_stats_fops = { 350 .owner = THIS_MODULE, 351 .open = snic_stats_open, 352 .read = seq_read, 353 .llseek = seq_lseek, 354 .release = single_release, 355 }; 356 357 static const struct file_operations snic_reset_stats_fops = { 358 .owner = THIS_MODULE, 359 .open = snic_reset_stats_open, 360 .read = snic_reset_stats_read, 361 .write = snic_reset_stats_write, 362 .release = snic_reset_stats_release, 363 }; 364 365 /* 366 * snic_stats_init - Initialize stats struct and create stats file 367 * per snic 368 * 369 * Description: 370 * When debugfs is cofigured this routine sets up the stats file per snic 371 * It will create file stats and reset_stats under statistics/host# directory 372 * to log per snic stats 373 */ 374 void snic_stats_debugfs_init(struct snic *snic) 375 { 376 char name[16]; 377 378 snprintf(name, sizeof(name), "host%d", snic->shost->host_no); 379 380 snic->stats_host = debugfs_create_dir(name, snic_glob->stats_root); 381 382 snic->stats_file = debugfs_create_file("stats", S_IFREG|S_IRUGO, 383 snic->stats_host, snic, 384 &snic_stats_fops); 385 386 snic->reset_stats_file = debugfs_create_file("reset_stats", 387 S_IFREG|S_IRUGO|S_IWUSR, 388 snic->stats_host, snic, 389 &snic_reset_stats_fops); 390 } 391 392 /* 393 * snic_stats_debugfs_remove - Tear down debugfs infrastructure of stats 394 * 395 * Description: 396 * When Debufs is configured this routine removes debugfs file system 397 * elements that are specific to to snic stats 398 */ 399 void 400 snic_stats_debugfs_remove(struct snic *snic) 401 { 402 debugfs_remove(snic->stats_file); 403 snic->stats_file = NULL; 404 405 debugfs_remove(snic->reset_stats_file); 406 snic->reset_stats_file = NULL; 407 408 debugfs_remove(snic->stats_host); 409 snic->stats_host = NULL; 410 } 411 412 /* Trace Facility related API */ 413 static void * 414 snic_trc_seq_start(struct seq_file *sfp, loff_t *pos) 415 { 416 return &snic_glob->trc; 417 } 418 419 static void * 420 snic_trc_seq_next(struct seq_file *sfp, void *data, loff_t *pos) 421 { 422 return NULL; 423 } 424 425 static void 426 snic_trc_seq_stop(struct seq_file *sfp, void *data) 427 { 428 } 429 430 #define SNIC_TRC_PBLEN 256 431 static int 432 snic_trc_seq_show(struct seq_file *sfp, void *data) 433 { 434 char buf[SNIC_TRC_PBLEN]; 435 436 if (snic_get_trc_data(buf, SNIC_TRC_PBLEN) > 0) 437 seq_printf(sfp, "%s\n", buf); 438 439 return 0; 440 } 441 442 static const struct seq_operations snic_trc_sops = { 443 .start = snic_trc_seq_start, 444 .next = snic_trc_seq_next, 445 .stop = snic_trc_seq_stop, 446 .show = snic_trc_seq_show, 447 }; 448 449 DEFINE_SEQ_ATTRIBUTE(snic_trc); 450 451 /* 452 * snic_trc_debugfs_init : creates trace/tracing_enable files for trace 453 * under debugfs 454 */ 455 void snic_trc_debugfs_init(void) 456 { 457 snic_glob->trc.trc_enable = debugfs_create_bool("tracing_enable", 458 S_IFREG | S_IRUGO | S_IWUSR, 459 snic_glob->trc_root, 460 &snic_glob->trc.enable); 461 462 snic_glob->trc.trc_file = debugfs_create_file("trace", 463 S_IFREG | S_IRUGO | S_IWUSR, 464 snic_glob->trc_root, NULL, 465 &snic_trc_fops); 466 } 467 468 /* 469 * snic_trc_debugfs_term : cleans up the files created for trace under debugfs 470 */ 471 void 472 snic_trc_debugfs_term(void) 473 { 474 debugfs_remove(snic_glob->trc.trc_file); 475 snic_glob->trc.trc_file = NULL; 476 477 debugfs_remove(snic_glob->trc.trc_enable); 478 snic_glob->trc.trc_enable = NULL; 479 } 480