1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright 2012 Cisco Systems, Inc. All rights reserved. 3 4 #include <linux/module.h> 5 #include <linux/mempool.h> 6 #include <linux/errno.h> 7 #include <linux/spinlock.h> 8 #include <linux/kallsyms.h> 9 #include <linux/time.h> 10 #include <linux/vmalloc.h> 11 #include "fnic_io.h" 12 #include "fnic.h" 13 14 unsigned int trace_max_pages; 15 static int fnic_max_trace_entries; 16 17 static unsigned long fnic_trace_buf_p; 18 static DEFINE_SPINLOCK(fnic_trace_lock); 19 20 static fnic_trace_dbg_t fnic_trace_entries; 21 int fnic_tracing_enabled = 1; 22 23 /* static char *fnic_fc_ctlr_trace_buf_p; */ 24 25 static int fc_trace_max_entries; 26 static unsigned long fnic_fc_ctlr_trace_buf_p; 27 static fnic_trace_dbg_t fc_trace_entries; 28 int fnic_fc_tracing_enabled = 1; 29 int fnic_fc_trace_cleared = 1; 30 static DEFINE_SPINLOCK(fnic_fc_trace_lock); 31 32 33 /* 34 * fnic_trace_get_buf - Give buffer pointer to user to fill up trace information 35 * 36 * Description: 37 * This routine gets next available trace buffer entry location @wr_idx 38 * from allocated trace buffer pages and give that memory location 39 * to user to store the trace information. 40 * 41 * Return Value: 42 * This routine returns pointer to next available trace entry 43 * @fnic_buf_head for user to fill trace information. 44 */ 45 fnic_trace_data_t *fnic_trace_get_buf(void) 46 { 47 unsigned long fnic_buf_head; 48 unsigned long flags; 49 50 spin_lock_irqsave(&fnic_trace_lock, flags); 51 52 /* 53 * Get next available memory location for writing trace information 54 * at @wr_idx and increment @wr_idx 55 */ 56 fnic_buf_head = 57 fnic_trace_entries.page_offset[fnic_trace_entries.wr_idx]; 58 fnic_trace_entries.wr_idx++; 59 60 /* 61 * Verify if trace buffer is full then change wd_idx to 62 * start from zero 63 */ 64 if (fnic_trace_entries.wr_idx >= fnic_max_trace_entries) 65 fnic_trace_entries.wr_idx = 0; 66 67 /* 68 * Verify if write index @wr_idx and read index @rd_idx are same then 69 * increment @rd_idx to move to next entry in trace buffer 70 */ 71 if (fnic_trace_entries.wr_idx == fnic_trace_entries.rd_idx) { 72 fnic_trace_entries.rd_idx++; 73 if (fnic_trace_entries.rd_idx >= fnic_max_trace_entries) 74 fnic_trace_entries.rd_idx = 0; 75 } 76 spin_unlock_irqrestore(&fnic_trace_lock, flags); 77 return (fnic_trace_data_t *)fnic_buf_head; 78 } 79 80 /* 81 * fnic_get_trace_data - Copy trace buffer to a memory file 82 * @fnic_dbgfs_t: pointer to debugfs trace buffer 83 * 84 * Description: 85 * This routine gathers the fnic trace debugfs data from the fnic_trace_data_t 86 * buffer and dumps it to fnic_dbgfs_t. It will start at the rd_idx entry in 87 * the log and process the log until the end of the buffer. Then it will gather 88 * from the beginning of the log and process until the current entry @wr_idx. 89 * 90 * Return Value: 91 * This routine returns the amount of bytes that were dumped into fnic_dbgfs_t 92 */ 93 int fnic_get_trace_data(fnic_dbgfs_t *fnic_dbgfs_prt) 94 { 95 int rd_idx; 96 int wr_idx; 97 int len = 0; 98 unsigned long flags; 99 char str[KSYM_SYMBOL_LEN]; 100 struct timespec64 val; 101 fnic_trace_data_t *tbp; 102 103 spin_lock_irqsave(&fnic_trace_lock, flags); 104 rd_idx = fnic_trace_entries.rd_idx; 105 wr_idx = fnic_trace_entries.wr_idx; 106 if (wr_idx < rd_idx) { 107 while (1) { 108 /* Start from read index @rd_idx */ 109 tbp = (fnic_trace_data_t *) 110 fnic_trace_entries.page_offset[rd_idx]; 111 if (!tbp) { 112 spin_unlock_irqrestore(&fnic_trace_lock, flags); 113 return 0; 114 } 115 /* Convert function pointer to function name */ 116 if (sizeof(unsigned long) < 8) { 117 sprint_symbol(str, tbp->fnaddr.low); 118 jiffies_to_timespec64(tbp->timestamp.low, &val); 119 } else { 120 sprint_symbol(str, tbp->fnaddr.val); 121 jiffies_to_timespec64(tbp->timestamp.val, &val); 122 } 123 /* 124 * Dump trace buffer entry to memory file 125 * and increment read index @rd_idx 126 */ 127 len += scnprintf(fnic_dbgfs_prt->buffer + len, 128 (trace_max_pages * PAGE_SIZE * 3) - len, 129 "%16llu.%09lu %-50s %8x %8x %16llx %16llx " 130 "%16llx %16llx %16llx\n", (u64)val.tv_sec, 131 val.tv_nsec, str, tbp->host_no, tbp->tag, 132 tbp->data[0], tbp->data[1], tbp->data[2], 133 tbp->data[3], tbp->data[4]); 134 rd_idx++; 135 /* 136 * If rd_idx is reached to maximum trace entries 137 * then move rd_idx to zero 138 */ 139 if (rd_idx > (fnic_max_trace_entries-1)) 140 rd_idx = 0; 141 /* 142 * Continue dumping trace buffer entries into 143 * memory file till rd_idx reaches write index 144 */ 145 if (rd_idx == wr_idx) 146 break; 147 } 148 } else if (wr_idx > rd_idx) { 149 while (1) { 150 /* Start from read index @rd_idx */ 151 tbp = (fnic_trace_data_t *) 152 fnic_trace_entries.page_offset[rd_idx]; 153 if (!tbp) { 154 spin_unlock_irqrestore(&fnic_trace_lock, flags); 155 return 0; 156 } 157 /* Convert function pointer to function name */ 158 if (sizeof(unsigned long) < 8) { 159 sprint_symbol(str, tbp->fnaddr.low); 160 jiffies_to_timespec64(tbp->timestamp.low, &val); 161 } else { 162 sprint_symbol(str, tbp->fnaddr.val); 163 jiffies_to_timespec64(tbp->timestamp.val, &val); 164 } 165 /* 166 * Dump trace buffer entry to memory file 167 * and increment read index @rd_idx 168 */ 169 len += scnprintf(fnic_dbgfs_prt->buffer + len, 170 (trace_max_pages * PAGE_SIZE * 3) - len, 171 "%16llu.%09lu %-50s %8x %8x %16llx %16llx " 172 "%16llx %16llx %16llx\n", (u64)val.tv_sec, 173 val.tv_nsec, str, tbp->host_no, tbp->tag, 174 tbp->data[0], tbp->data[1], tbp->data[2], 175 tbp->data[3], tbp->data[4]); 176 rd_idx++; 177 /* 178 * Continue dumping trace buffer entries into 179 * memory file till rd_idx reaches write index 180 */ 181 if (rd_idx == wr_idx) 182 break; 183 } 184 } 185 spin_unlock_irqrestore(&fnic_trace_lock, flags); 186 return len; 187 } 188 189 /* 190 * fnic_get_stats_data - Copy fnic stats buffer to a memory file 191 * @fnic_dbgfs_t: pointer to debugfs fnic stats buffer 192 * 193 * Description: 194 * This routine gathers the fnic stats debugfs data from the fnic_stats struct 195 * and dumps it to stats_debug_info. 196 * 197 * Return Value: 198 * This routine returns the amount of bytes that were dumped into 199 * stats_debug_info 200 */ 201 int fnic_get_stats_data(struct stats_debug_info *debug, 202 struct fnic_stats *stats) 203 { 204 int len = 0; 205 int buf_size = debug->buf_size; 206 struct timespec64 val1, val2; 207 int i = 0; 208 209 ktime_get_real_ts64(&val1); 210 len = scnprintf(debug->debug_buffer + len, buf_size - len, 211 "------------------------------------------\n" 212 "\t\tTime\n" 213 "------------------------------------------\n"); 214 215 len += scnprintf(debug->debug_buffer + len, buf_size - len, 216 "Current time : [%lld:%ld]\n" 217 "Last stats reset time: [%lld:%09ld]\n" 218 "Last stats read time: [%lld:%ld]\n" 219 "delta since last reset: [%lld:%ld]\n" 220 "delta since last read: [%lld:%ld]\n", 221 (s64)val1.tv_sec, val1.tv_nsec, 222 (s64)stats->stats_timestamps.last_reset_time.tv_sec, 223 stats->stats_timestamps.last_reset_time.tv_nsec, 224 (s64)stats->stats_timestamps.last_read_time.tv_sec, 225 stats->stats_timestamps.last_read_time.tv_nsec, 226 (s64)timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_sec, 227 timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_nsec, 228 (s64)timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_sec, 229 timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_nsec); 230 231 stats->stats_timestamps.last_read_time = val1; 232 233 len += scnprintf(debug->debug_buffer + len, buf_size - len, 234 "------------------------------------------\n" 235 "\t\tIO Statistics\n" 236 "------------------------------------------\n"); 237 len += scnprintf(debug->debug_buffer + len, buf_size - len, 238 "Number of Active IOs: %lld\nMaximum Active IOs: %lld\n" 239 "Number of IOs: %lld\nNumber of IO Completions: %lld\n" 240 "Number of IO Failures: %lld\nNumber of IO NOT Found: %lld\n" 241 "Number of Memory alloc Failures: %lld\n" 242 "Number of IOREQ Null: %lld\n" 243 "Number of SCSI cmd pointer Null: %lld\n" 244 245 "\nIO completion times: \n" 246 " < 10 ms : %lld\n" 247 " 10 ms - 100 ms : %lld\n" 248 " 100 ms - 500 ms : %lld\n" 249 " 500 ms - 5 sec: %lld\n" 250 " 5 sec - 10 sec: %lld\n" 251 " 10 sec - 30 sec: %lld\n" 252 " > 30 sec: %lld\n", 253 (u64)atomic64_read(&stats->io_stats.active_ios), 254 (u64)atomic64_read(&stats->io_stats.max_active_ios), 255 (u64)atomic64_read(&stats->io_stats.num_ios), 256 (u64)atomic64_read(&stats->io_stats.io_completions), 257 (u64)atomic64_read(&stats->io_stats.io_failures), 258 (u64)atomic64_read(&stats->io_stats.io_not_found), 259 (u64)atomic64_read(&stats->io_stats.alloc_failures), 260 (u64)atomic64_read(&stats->io_stats.ioreq_null), 261 (u64)atomic64_read(&stats->io_stats.sc_null), 262 (u64)atomic64_read(&stats->io_stats.io_btw_0_to_10_msec), 263 (u64)atomic64_read(&stats->io_stats.io_btw_10_to_100_msec), 264 (u64)atomic64_read(&stats->io_stats.io_btw_100_to_500_msec), 265 (u64)atomic64_read(&stats->io_stats.io_btw_500_to_5000_msec), 266 (u64)atomic64_read(&stats->io_stats.io_btw_5000_to_10000_msec), 267 (u64)atomic64_read(&stats->io_stats.io_btw_10000_to_30000_msec), 268 (u64)atomic64_read(&stats->io_stats.io_greater_than_30000_msec)); 269 270 len += scnprintf(debug->debug_buffer + len, buf_size - len, 271 "------------------------------------------\n" 272 "\t\tIO Queues and cumulative IOs\n" 273 "------------------------------------------\n"); 274 275 for (i = 0; i < FNIC_MQ_MAX_QUEUES; i++) { 276 len += scnprintf(debug->debug_buffer + len, buf_size - len, 277 "Q:%d -> %lld\n", i, (u64)atomic64_read(&stats->io_stats.ios[i])); 278 } 279 280 len += scnprintf(debug->debug_buffer + len, buf_size - len, 281 "\nCurrent Max IO time : %lld\n", 282 (u64)atomic64_read(&stats->io_stats.current_max_io_time)); 283 284 len += scnprintf(debug->debug_buffer + len, buf_size - len, 285 "\n------------------------------------------\n" 286 "\t\tAbort Statistics\n" 287 "------------------------------------------\n"); 288 289 len += scnprintf(debug->debug_buffer + len, buf_size - len, 290 "Number of Aborts: %lld\n" 291 "Number of Abort Failures: %lld\n" 292 "Number of Abort Driver Timeouts: %lld\n" 293 "Number of Abort FW Timeouts: %lld\n" 294 "Number of Abort IO NOT Found: %lld\n" 295 296 "Abort issued times: \n" 297 " < 6 sec : %lld\n" 298 " 6 sec - 20 sec : %lld\n" 299 " 20 sec - 30 sec : %lld\n" 300 " 30 sec - 40 sec : %lld\n" 301 " 40 sec - 50 sec : %lld\n" 302 " 50 sec - 60 sec : %lld\n" 303 " > 60 sec: %lld\n", 304 305 (u64)atomic64_read(&stats->abts_stats.aborts), 306 (u64)atomic64_read(&stats->abts_stats.abort_failures), 307 (u64)atomic64_read(&stats->abts_stats.abort_drv_timeouts), 308 (u64)atomic64_read(&stats->abts_stats.abort_fw_timeouts), 309 (u64)atomic64_read(&stats->abts_stats.abort_io_not_found), 310 (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_0_to_6_sec), 311 (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_6_to_20_sec), 312 (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_20_to_30_sec), 313 (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_30_to_40_sec), 314 (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_40_to_50_sec), 315 (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_50_to_60_sec), 316 (u64)atomic64_read(&stats->abts_stats.abort_issued_greater_than_60_sec)); 317 318 len += scnprintf(debug->debug_buffer + len, buf_size - len, 319 "\n------------------------------------------\n" 320 "\t\tTerminate Statistics\n" 321 "------------------------------------------\n"); 322 323 len += scnprintf(debug->debug_buffer + len, buf_size - len, 324 "Number of Terminates: %lld\n" 325 "Maximum Terminates: %lld\n" 326 "Number of Terminate Driver Timeouts: %lld\n" 327 "Number of Terminate FW Timeouts: %lld\n" 328 "Number of Terminate IO NOT Found: %lld\n" 329 "Number of Terminate Failures: %lld\n", 330 (u64)atomic64_read(&stats->term_stats.terminates), 331 (u64)atomic64_read(&stats->term_stats.max_terminates), 332 (u64)atomic64_read(&stats->term_stats.terminate_drv_timeouts), 333 (u64)atomic64_read(&stats->term_stats.terminate_fw_timeouts), 334 (u64)atomic64_read(&stats->term_stats.terminate_io_not_found), 335 (u64)atomic64_read(&stats->term_stats.terminate_failures)); 336 337 len += scnprintf(debug->debug_buffer + len, buf_size - len, 338 "\n------------------------------------------\n" 339 "\t\tReset Statistics\n" 340 "------------------------------------------\n"); 341 342 len += scnprintf(debug->debug_buffer + len, buf_size - len, 343 "Number of Device Resets: %lld\n" 344 "Number of Device Reset Failures: %lld\n" 345 "Number of Device Reset Aborts: %lld\n" 346 "Number of Device Reset Timeouts: %lld\n" 347 "Number of Device Reset Terminates: %lld\n" 348 "Number of FW Resets: %lld\n" 349 "Number of FW Reset Completions: %lld\n" 350 "Number of FW Reset Failures: %lld\n" 351 "Number of Fnic Reset: %lld\n" 352 "Number of Fnic Reset Completions: %lld\n" 353 "Number of Fnic Reset Failures: %lld\n", 354 (u64)atomic64_read(&stats->reset_stats.device_resets), 355 (u64)atomic64_read(&stats->reset_stats.device_reset_failures), 356 (u64)atomic64_read(&stats->reset_stats.device_reset_aborts), 357 (u64)atomic64_read(&stats->reset_stats.device_reset_timeouts), 358 (u64)atomic64_read( 359 &stats->reset_stats.device_reset_terminates), 360 (u64)atomic64_read(&stats->reset_stats.fw_resets), 361 (u64)atomic64_read(&stats->reset_stats.fw_reset_completions), 362 (u64)atomic64_read(&stats->reset_stats.fw_reset_failures), 363 (u64)atomic64_read(&stats->reset_stats.fnic_resets), 364 (u64)atomic64_read( 365 &stats->reset_stats.fnic_reset_completions), 366 (u64)atomic64_read(&stats->reset_stats.fnic_reset_failures)); 367 368 len += scnprintf(debug->debug_buffer + len, buf_size - len, 369 "\n------------------------------------------\n" 370 "\t\tFirmware Statistics\n" 371 "------------------------------------------\n"); 372 373 len += scnprintf(debug->debug_buffer + len, buf_size - len, 374 "Number of Active FW Requests %lld\n" 375 "Maximum FW Requests: %lld\n" 376 "Number of FW out of resources: %lld\n" 377 "Number of FW IO errors: %lld\n", 378 (u64)atomic64_read(&stats->fw_stats.active_fw_reqs), 379 (u64)atomic64_read(&stats->fw_stats.max_fw_reqs), 380 (u64)atomic64_read(&stats->fw_stats.fw_out_of_resources), 381 (u64)atomic64_read(&stats->fw_stats.io_fw_errs)); 382 383 len += scnprintf(debug->debug_buffer + len, buf_size - len, 384 "\n------------------------------------------\n" 385 "\t\tVlan Discovery Statistics\n" 386 "------------------------------------------\n"); 387 388 len += scnprintf(debug->debug_buffer + len, buf_size - len, 389 "Number of Vlan Discovery Requests Sent %lld\n" 390 "Vlan Response Received with no FCF VLAN ID: %lld\n" 391 "No solicitations recvd after vlan set, expiry count: %lld\n" 392 "Flogi rejects count: %lld\n", 393 (u64)atomic64_read(&stats->vlan_stats.vlan_disc_reqs), 394 (u64)atomic64_read(&stats->vlan_stats.resp_withno_vlanID), 395 (u64)atomic64_read(&stats->vlan_stats.sol_expiry_count), 396 (u64)atomic64_read(&stats->vlan_stats.flogi_rejects)); 397 398 len += scnprintf(debug->debug_buffer + len, buf_size - len, 399 "\n------------------------------------------\n" 400 "\t\tOther Important Statistics\n" 401 "------------------------------------------\n"); 402 403 jiffies_to_timespec64(stats->misc_stats.last_isr_time, &val1); 404 jiffies_to_timespec64(stats->misc_stats.last_ack_time, &val2); 405 406 len += scnprintf(debug->debug_buffer + len, buf_size - len, 407 "Last ISR time: %llu (%8llu.%09lu)\n" 408 "Last ACK time: %llu (%8llu.%09lu)\n" 409 "Max ISR jiffies: %llu\n" 410 "Max ISR time (ms) (0 denotes < 1 ms): %llu\n" 411 "Corr. work done: %llu\n" 412 "Number of ISRs: %lld\n" 413 "Maximum CQ Entries: %lld\n" 414 "Number of ACK index out of range: %lld\n" 415 "Number of data count mismatch: %lld\n" 416 "Number of FCPIO Timeouts: %lld\n" 417 "Number of FCPIO Aborted: %lld\n" 418 "Number of SGL Invalid: %lld\n" 419 "Number of Copy WQ Alloc Failures for ABTs: %lld\n" 420 "Number of Copy WQ Alloc Failures for Device Reset: %lld\n" 421 "Number of Copy WQ Alloc Failures for IOs: %lld\n" 422 "Number of no icmnd itmf Completions: %lld\n" 423 "Number of Check Conditions encountered: %lld\n" 424 "Number of QUEUE Fulls: %lld\n" 425 "Number of rport not ready: %lld\n" 426 "Number of receive frame errors: %lld\n", 427 (u64)stats->misc_stats.last_isr_time, 428 (s64)val1.tv_sec, val1.tv_nsec, 429 (u64)stats->misc_stats.last_ack_time, 430 (s64)val2.tv_sec, val2.tv_nsec, 431 (u64)atomic64_read(&stats->misc_stats.max_isr_jiffies), 432 (u64)atomic64_read(&stats->misc_stats.max_isr_time_ms), 433 (u64)atomic64_read(&stats->misc_stats.corr_work_done), 434 (u64)atomic64_read(&stats->misc_stats.isr_count), 435 (u64)atomic64_read(&stats->misc_stats.max_cq_entries), 436 (u64)atomic64_read(&stats->misc_stats.ack_index_out_of_range), 437 (u64)atomic64_read(&stats->misc_stats.data_count_mismatch), 438 (u64)atomic64_read(&stats->misc_stats.fcpio_timeout), 439 (u64)atomic64_read(&stats->misc_stats.fcpio_aborted), 440 (u64)atomic64_read(&stats->misc_stats.sgl_invalid), 441 (u64)atomic64_read( 442 &stats->misc_stats.abts_cpwq_alloc_failures), 443 (u64)atomic64_read( 444 &stats->misc_stats.devrst_cpwq_alloc_failures), 445 (u64)atomic64_read(&stats->misc_stats.io_cpwq_alloc_failures), 446 (u64)atomic64_read(&stats->misc_stats.no_icmnd_itmf_cmpls), 447 (u64)atomic64_read(&stats->misc_stats.check_condition), 448 (u64)atomic64_read(&stats->misc_stats.queue_fulls), 449 (u64)atomic64_read(&stats->misc_stats.rport_not_ready), 450 (u64)atomic64_read(&stats->misc_stats.frame_errors)); 451 452 len += scnprintf(debug->debug_buffer + len, buf_size - len, 453 "Firmware reported port speed: %llu\n", 454 (u64)atomic64_read( 455 &stats->misc_stats.current_port_speed)); 456 457 return len; 458 459 } 460 461 /* 462 * fnic_trace_buf_init - Initialize fnic trace buffer logging facility 463 * 464 * Description: 465 * Initialize trace buffer data structure by allocating required memory and 466 * setting page_offset information for every trace entry by adding trace entry 467 * length to previous page_offset value. 468 */ 469 int fnic_trace_buf_init(void) 470 { 471 unsigned long fnic_buf_head; 472 int i; 473 int err = 0; 474 475 trace_max_pages = fnic_trace_max_pages; 476 fnic_max_trace_entries = (trace_max_pages * PAGE_SIZE)/ 477 FNIC_ENTRY_SIZE_BYTES; 478 479 fnic_trace_buf_p = (unsigned long)vcalloc(trace_max_pages, PAGE_SIZE); 480 if (!fnic_trace_buf_p) { 481 printk(KERN_ERR PFX "Failed to allocate memory " 482 "for fnic_trace_buf_p\n"); 483 err = -ENOMEM; 484 goto err_fnic_trace_buf_init; 485 } 486 487 fnic_trace_entries.page_offset = 488 vmalloc(array_size(fnic_max_trace_entries, 489 sizeof(unsigned long))); 490 if (!fnic_trace_entries.page_offset) { 491 printk(KERN_ERR PFX "Failed to allocate memory for" 492 " page_offset\n"); 493 if (fnic_trace_buf_p) { 494 vfree((void *)fnic_trace_buf_p); 495 fnic_trace_buf_p = 0; 496 } 497 err = -ENOMEM; 498 goto err_fnic_trace_buf_init; 499 } 500 memset((void *)fnic_trace_entries.page_offset, 0, 501 (fnic_max_trace_entries * sizeof(unsigned long))); 502 fnic_trace_entries.wr_idx = fnic_trace_entries.rd_idx = 0; 503 fnic_buf_head = fnic_trace_buf_p; 504 505 /* 506 * Set page_offset field of fnic_trace_entries struct by 507 * calculating memory location for every trace entry using 508 * length of each trace entry 509 */ 510 for (i = 0; i < fnic_max_trace_entries; i++) { 511 fnic_trace_entries.page_offset[i] = fnic_buf_head; 512 fnic_buf_head += FNIC_ENTRY_SIZE_BYTES; 513 } 514 fnic_trace_debugfs_init(); 515 pr_info("fnic: Successfully Initialized Trace Buffer\n"); 516 return err; 517 518 err_fnic_trace_buf_init: 519 return err; 520 } 521 522 /* 523 * fnic_trace_free - Free memory of fnic trace data structures. 524 */ 525 void fnic_trace_free(void) 526 { 527 fnic_tracing_enabled = 0; 528 fnic_trace_debugfs_terminate(); 529 if (fnic_trace_entries.page_offset) { 530 vfree((void *)fnic_trace_entries.page_offset); 531 fnic_trace_entries.page_offset = NULL; 532 } 533 if (fnic_trace_buf_p) { 534 vfree((void *)fnic_trace_buf_p); 535 fnic_trace_buf_p = 0; 536 } 537 printk(KERN_INFO PFX "Successfully Freed Trace Buffer\n"); 538 } 539 540 /* 541 * fnic_fc_ctlr_trace_buf_init - 542 * Initialize trace buffer to log fnic control frames 543 * Description: 544 * Initialize trace buffer data structure by allocating 545 * required memory for trace data as well as for Indexes. 546 * Frame size is 256 bytes and 547 * memory is allocated for 1024 entries of 256 bytes. 548 * Page_offset(Index) is set to the address of trace entry 549 * and page_offset is initialized by adding frame size 550 * to the previous page_offset entry. 551 */ 552 553 int fnic_fc_trace_init(void) 554 { 555 unsigned long fc_trace_buf_head; 556 int err = 0; 557 int i; 558 559 fc_trace_max_entries = (fnic_fc_trace_max_pages * PAGE_SIZE)/ 560 FC_TRC_SIZE_BYTES; 561 fnic_fc_ctlr_trace_buf_p = 562 (unsigned long)vmalloc(array_size(PAGE_SIZE, 563 fnic_fc_trace_max_pages)); 564 if (!fnic_fc_ctlr_trace_buf_p) { 565 pr_err("fnic: Failed to allocate memory for " 566 "FC Control Trace Buf\n"); 567 err = -ENOMEM; 568 goto err_fnic_fc_ctlr_trace_buf_init; 569 } 570 571 memset((void *)fnic_fc_ctlr_trace_buf_p, 0, 572 fnic_fc_trace_max_pages * PAGE_SIZE); 573 574 /* Allocate memory for page offset */ 575 fc_trace_entries.page_offset = 576 vmalloc(array_size(fc_trace_max_entries, 577 sizeof(unsigned long))); 578 if (!fc_trace_entries.page_offset) { 579 pr_err("fnic:Failed to allocate memory for page_offset\n"); 580 if (fnic_fc_ctlr_trace_buf_p) { 581 pr_err("fnic: Freeing FC Control Trace Buf\n"); 582 vfree((void *)fnic_fc_ctlr_trace_buf_p); 583 fnic_fc_ctlr_trace_buf_p = 0; 584 } 585 err = -ENOMEM; 586 goto err_fnic_fc_ctlr_trace_buf_init; 587 } 588 memset((void *)fc_trace_entries.page_offset, 0, 589 (fc_trace_max_entries * sizeof(unsigned long))); 590 591 fc_trace_entries.rd_idx = fc_trace_entries.wr_idx = 0; 592 fc_trace_buf_head = fnic_fc_ctlr_trace_buf_p; 593 594 /* 595 * Set up fc_trace_entries.page_offset field with memory location 596 * for every trace entry 597 */ 598 for (i = 0; i < fc_trace_max_entries; i++) { 599 fc_trace_entries.page_offset[i] = fc_trace_buf_head; 600 fc_trace_buf_head += FC_TRC_SIZE_BYTES; 601 } 602 fnic_fc_trace_debugfs_init(); 603 pr_info("fnic: Successfully Initialized FC_CTLR Trace Buffer\n"); 604 return err; 605 606 err_fnic_fc_ctlr_trace_buf_init: 607 return err; 608 } 609 610 /* 611 * Fnic_fc_ctlr_trace_free - Free memory of fnic_fc_ctlr trace data structures. 612 */ 613 void fnic_fc_trace_free(void) 614 { 615 fnic_fc_tracing_enabled = 0; 616 fnic_fc_trace_debugfs_terminate(); 617 if (fc_trace_entries.page_offset) { 618 vfree((void *)fc_trace_entries.page_offset); 619 fc_trace_entries.page_offset = NULL; 620 } 621 if (fnic_fc_ctlr_trace_buf_p) { 622 vfree((void *)fnic_fc_ctlr_trace_buf_p); 623 fnic_fc_ctlr_trace_buf_p = 0; 624 } 625 pr_info("fnic:Successfully FC_CTLR Freed Trace Buffer\n"); 626 } 627 628 /* 629 * fnic_fc_ctlr_set_trace_data: 630 * Maintain rd & wr idx accordingly and set data 631 * Passed parameters: 632 * host_no: host number associated with fnic 633 * frame_type: send_frame, rece_frame or link event 634 * fc_frame: pointer to fc_frame 635 * frame_len: Length of the fc_frame 636 * Description: 637 * This routine will get next available wr_idx and 638 * copy all passed trace data to the buffer pointed by wr_idx 639 * and increment wr_idx. It will also make sure that we dont 640 * overwrite the entry which we are reading and also 641 * wrap around if we reach the maximum entries. 642 * Returned Value: 643 * It will return 0 for success or -1 for failure 644 */ 645 int fnic_fc_trace_set_data(u32 host_no, u8 frame_type, 646 char *frame, u32 fc_trc_frame_len) 647 { 648 unsigned long flags; 649 struct fc_trace_hdr *fc_buf; 650 unsigned long eth_fcoe_hdr_len; 651 char *fc_trace; 652 653 if (fnic_fc_tracing_enabled == 0) 654 return 0; 655 656 spin_lock_irqsave(&fnic_fc_trace_lock, flags); 657 658 if (fnic_fc_trace_cleared == 1) { 659 fc_trace_entries.rd_idx = fc_trace_entries.wr_idx = 0; 660 pr_info("fnic: Resetting the read idx\n"); 661 memset((void *)fnic_fc_ctlr_trace_buf_p, 0, 662 fnic_fc_trace_max_pages * PAGE_SIZE); 663 fnic_fc_trace_cleared = 0; 664 } 665 666 fc_buf = (struct fc_trace_hdr *) 667 fc_trace_entries.page_offset[fc_trace_entries.wr_idx]; 668 669 fc_trace_entries.wr_idx++; 670 671 if (fc_trace_entries.wr_idx >= fc_trace_max_entries) 672 fc_trace_entries.wr_idx = 0; 673 674 if (fc_trace_entries.wr_idx == fc_trace_entries.rd_idx) { 675 fc_trace_entries.rd_idx++; 676 if (fc_trace_entries.rd_idx >= fc_trace_max_entries) 677 fc_trace_entries.rd_idx = 0; 678 } 679 680 ktime_get_real_ts64(&fc_buf->time_stamp); 681 fc_buf->host_no = host_no; 682 fc_buf->frame_type = frame_type; 683 684 fc_trace = (char *)FC_TRACE_ADDRESS(fc_buf); 685 686 /* During the receive path, we do not have eth hdr as well as fcoe hdr 687 * at trace entry point so we will stuff 0xff just to make it generic. 688 */ 689 if (frame_type == FNIC_FC_RECV) { 690 eth_fcoe_hdr_len = sizeof(struct ethhdr) + 691 sizeof(struct fcoe_hdr); 692 memset((char *)fc_trace, 0xff, eth_fcoe_hdr_len); 693 /* Copy the rest of data frame */ 694 memcpy((char *)(fc_trace + eth_fcoe_hdr_len), (void *)frame, 695 min_t(u8, fc_trc_frame_len, 696 (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE 697 - eth_fcoe_hdr_len))); 698 } else { 699 memcpy((char *)fc_trace, (void *)frame, 700 min_t(u8, fc_trc_frame_len, 701 (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE))); 702 } 703 704 /* Store the actual received length */ 705 fc_buf->frame_len = fc_trc_frame_len; 706 707 spin_unlock_irqrestore(&fnic_fc_trace_lock, flags); 708 return 0; 709 } 710 711 /* 712 * fnic_fc_ctlr_get_trace_data: Copy trace buffer to a memory file 713 * Passed parameter: 714 * @fnic_dbgfs_t: pointer to debugfs trace buffer 715 * rdata_flag: 1 => Unformatted file 716 * 0 => formatted file 717 * Description: 718 * This routine will copy the trace data to memory file with 719 * proper formatting and also copy to another memory 720 * file without formatting for further processing. 721 * Return Value: 722 * Number of bytes that were dumped into fnic_dbgfs_t 723 */ 724 725 int fnic_fc_trace_get_data(fnic_dbgfs_t *fnic_dbgfs_prt, u8 rdata_flag) 726 { 727 int rd_idx, wr_idx; 728 unsigned long flags; 729 int len = 0, j; 730 struct fc_trace_hdr *tdata; 731 char *fc_trace; 732 733 spin_lock_irqsave(&fnic_fc_trace_lock, flags); 734 if (fc_trace_entries.wr_idx == fc_trace_entries.rd_idx) { 735 spin_unlock_irqrestore(&fnic_fc_trace_lock, flags); 736 pr_info("fnic: Buffer is empty\n"); 737 return 0; 738 } 739 rd_idx = fc_trace_entries.rd_idx; 740 wr_idx = fc_trace_entries.wr_idx; 741 if (rdata_flag == 0) { 742 len += scnprintf(fnic_dbgfs_prt->buffer + len, 743 (fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len, 744 "Time Stamp (UTC)\t\t" 745 "Host No: F Type: len: FCoE_FRAME:\n"); 746 } 747 748 while (rd_idx != wr_idx) { 749 tdata = (struct fc_trace_hdr *) 750 fc_trace_entries.page_offset[rd_idx]; 751 if (!tdata) { 752 pr_info("fnic: Rd data is NULL\n"); 753 spin_unlock_irqrestore(&fnic_fc_trace_lock, flags); 754 return 0; 755 } 756 if (rdata_flag == 0) { 757 copy_and_format_trace_data(tdata, 758 fnic_dbgfs_prt, &len, rdata_flag); 759 } else { 760 fc_trace = (char *)tdata; 761 for (j = 0; j < FC_TRC_SIZE_BYTES; j++) { 762 len += scnprintf(fnic_dbgfs_prt->buffer + len, 763 (fnic_fc_trace_max_pages * PAGE_SIZE * 3) 764 - len, "%02x", fc_trace[j] & 0xff); 765 } /* for loop */ 766 len += scnprintf(fnic_dbgfs_prt->buffer + len, 767 (fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len, 768 "\n"); 769 } 770 rd_idx++; 771 if (rd_idx > (fc_trace_max_entries - 1)) 772 rd_idx = 0; 773 } 774 775 spin_unlock_irqrestore(&fnic_fc_trace_lock, flags); 776 return len; 777 } 778 779 /* 780 * copy_and_format_trace_data: Copy formatted data to char * buffer 781 * Passed Parameter: 782 * @fc_trace_hdr_t: pointer to trace data 783 * @fnic_dbgfs_t: pointer to debugfs trace buffer 784 * @orig_len: pointer to len 785 * rdata_flag: 0 => Formatted file, 1 => Unformatted file 786 * Description: 787 * This routine will format and copy the passed trace data 788 * for formatted file or unformatted file accordingly. 789 */ 790 791 void copy_and_format_trace_data(struct fc_trace_hdr *tdata, 792 fnic_dbgfs_t *fnic_dbgfs_prt, int *orig_len, 793 u8 rdata_flag) 794 { 795 int j, i = 1, len; 796 int ethhdr_len = sizeof(struct ethhdr) - 1; 797 int fcoehdr_len = sizeof(struct fcoe_hdr); 798 int fchdr_len = sizeof(struct fc_frame_header); 799 int max_size = fnic_fc_trace_max_pages * PAGE_SIZE * 3; 800 char *fc_trace; 801 802 tdata->frame_type = tdata->frame_type & 0x7F; 803 804 len = *orig_len; 805 806 len += scnprintf(fnic_dbgfs_prt->buffer + len, max_size - len, 807 "%ptTs.%09lu ns%8x %c%8x\t", 808 &tdata->time_stamp.tv_sec, tdata->time_stamp.tv_nsec, 809 tdata->host_no, tdata->frame_type, tdata->frame_len); 810 811 fc_trace = (char *)FC_TRACE_ADDRESS(tdata); 812 813 for (j = 0; j < min_t(u8, tdata->frame_len, 814 (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE)); j++) { 815 if (tdata->frame_type == FNIC_FC_LE) { 816 len += scnprintf(fnic_dbgfs_prt->buffer + len, 817 max_size - len, "%c", fc_trace[j]); 818 } else { 819 len += scnprintf(fnic_dbgfs_prt->buffer + len, 820 max_size - len, "%02x", fc_trace[j] & 0xff); 821 len += scnprintf(fnic_dbgfs_prt->buffer + len, 822 max_size - len, " "); 823 if (j == ethhdr_len || 824 j == ethhdr_len + fcoehdr_len || 825 j == ethhdr_len + fcoehdr_len + fchdr_len || 826 (i > 3 && j%fchdr_len == 0)) { 827 len += scnprintf(fnic_dbgfs_prt->buffer 828 + len, max_size - len, 829 "\n\t\t\t\t\t\t\t\t"); 830 i++; 831 } 832 } /* end of else*/ 833 } /* End of for loop*/ 834 len += scnprintf(fnic_dbgfs_prt->buffer + len, 835 max_size - len, "\n"); 836 *orig_len = len; 837 } 838