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