162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci// Copyright 2012 Cisco Systems, Inc. All rights reserved. 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/module.h> 562306a36Sopenharmony_ci#include <linux/mempool.h> 662306a36Sopenharmony_ci#include <linux/errno.h> 762306a36Sopenharmony_ci#include <linux/spinlock.h> 862306a36Sopenharmony_ci#include <linux/kallsyms.h> 962306a36Sopenharmony_ci#include <linux/time.h> 1062306a36Sopenharmony_ci#include <linux/vmalloc.h> 1162306a36Sopenharmony_ci#include "fnic_io.h" 1262306a36Sopenharmony_ci#include "fnic.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ciunsigned int trace_max_pages; 1562306a36Sopenharmony_cistatic int fnic_max_trace_entries; 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic unsigned long fnic_trace_buf_p; 1862306a36Sopenharmony_cistatic DEFINE_SPINLOCK(fnic_trace_lock); 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic fnic_trace_dbg_t fnic_trace_entries; 2162306a36Sopenharmony_ciint fnic_tracing_enabled = 1; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* static char *fnic_fc_ctlr_trace_buf_p; */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic int fc_trace_max_entries; 2662306a36Sopenharmony_cistatic unsigned long fnic_fc_ctlr_trace_buf_p; 2762306a36Sopenharmony_cistatic fnic_trace_dbg_t fc_trace_entries; 2862306a36Sopenharmony_ciint fnic_fc_tracing_enabled = 1; 2962306a36Sopenharmony_ciint fnic_fc_trace_cleared = 1; 3062306a36Sopenharmony_cistatic DEFINE_SPINLOCK(fnic_fc_trace_lock); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* 3462306a36Sopenharmony_ci * fnic_trace_get_buf - Give buffer pointer to user to fill up trace information 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * Description: 3762306a36Sopenharmony_ci * This routine gets next available trace buffer entry location @wr_idx 3862306a36Sopenharmony_ci * from allocated trace buffer pages and give that memory location 3962306a36Sopenharmony_ci * to user to store the trace information. 4062306a36Sopenharmony_ci * 4162306a36Sopenharmony_ci * Return Value: 4262306a36Sopenharmony_ci * This routine returns pointer to next available trace entry 4362306a36Sopenharmony_ci * @fnic_buf_head for user to fill trace information. 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_cifnic_trace_data_t *fnic_trace_get_buf(void) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci unsigned long fnic_buf_head; 4862306a36Sopenharmony_ci unsigned long flags; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci spin_lock_irqsave(&fnic_trace_lock, flags); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci /* 5362306a36Sopenharmony_ci * Get next available memory location for writing trace information 5462306a36Sopenharmony_ci * at @wr_idx and increment @wr_idx 5562306a36Sopenharmony_ci */ 5662306a36Sopenharmony_ci fnic_buf_head = 5762306a36Sopenharmony_ci fnic_trace_entries.page_offset[fnic_trace_entries.wr_idx]; 5862306a36Sopenharmony_ci fnic_trace_entries.wr_idx++; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci /* 6162306a36Sopenharmony_ci * Verify if trace buffer is full then change wd_idx to 6262306a36Sopenharmony_ci * start from zero 6362306a36Sopenharmony_ci */ 6462306a36Sopenharmony_ci if (fnic_trace_entries.wr_idx >= fnic_max_trace_entries) 6562306a36Sopenharmony_ci fnic_trace_entries.wr_idx = 0; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* 6862306a36Sopenharmony_ci * Verify if write index @wr_idx and read index @rd_idx are same then 6962306a36Sopenharmony_ci * increment @rd_idx to move to next entry in trace buffer 7062306a36Sopenharmony_ci */ 7162306a36Sopenharmony_ci if (fnic_trace_entries.wr_idx == fnic_trace_entries.rd_idx) { 7262306a36Sopenharmony_ci fnic_trace_entries.rd_idx++; 7362306a36Sopenharmony_ci if (fnic_trace_entries.rd_idx >= fnic_max_trace_entries) 7462306a36Sopenharmony_ci fnic_trace_entries.rd_idx = 0; 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci spin_unlock_irqrestore(&fnic_trace_lock, flags); 7762306a36Sopenharmony_ci return (fnic_trace_data_t *)fnic_buf_head; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci/* 8162306a36Sopenharmony_ci * fnic_get_trace_data - Copy trace buffer to a memory file 8262306a36Sopenharmony_ci * @fnic_dbgfs_t: pointer to debugfs trace buffer 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * Description: 8562306a36Sopenharmony_ci * This routine gathers the fnic trace debugfs data from the fnic_trace_data_t 8662306a36Sopenharmony_ci * buffer and dumps it to fnic_dbgfs_t. It will start at the rd_idx entry in 8762306a36Sopenharmony_ci * the log and process the log until the end of the buffer. Then it will gather 8862306a36Sopenharmony_ci * from the beginning of the log and process until the current entry @wr_idx. 8962306a36Sopenharmony_ci * 9062306a36Sopenharmony_ci * Return Value: 9162306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into fnic_dbgfs_t 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ciint fnic_get_trace_data(fnic_dbgfs_t *fnic_dbgfs_prt) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci int rd_idx; 9662306a36Sopenharmony_ci int wr_idx; 9762306a36Sopenharmony_ci int len = 0; 9862306a36Sopenharmony_ci unsigned long flags; 9962306a36Sopenharmony_ci char str[KSYM_SYMBOL_LEN]; 10062306a36Sopenharmony_ci struct timespec64 val; 10162306a36Sopenharmony_ci fnic_trace_data_t *tbp; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci spin_lock_irqsave(&fnic_trace_lock, flags); 10462306a36Sopenharmony_ci rd_idx = fnic_trace_entries.rd_idx; 10562306a36Sopenharmony_ci wr_idx = fnic_trace_entries.wr_idx; 10662306a36Sopenharmony_ci if (wr_idx < rd_idx) { 10762306a36Sopenharmony_ci while (1) { 10862306a36Sopenharmony_ci /* Start from read index @rd_idx */ 10962306a36Sopenharmony_ci tbp = (fnic_trace_data_t *) 11062306a36Sopenharmony_ci fnic_trace_entries.page_offset[rd_idx]; 11162306a36Sopenharmony_ci if (!tbp) { 11262306a36Sopenharmony_ci spin_unlock_irqrestore(&fnic_trace_lock, flags); 11362306a36Sopenharmony_ci return 0; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci /* Convert function pointer to function name */ 11662306a36Sopenharmony_ci if (sizeof(unsigned long) < 8) { 11762306a36Sopenharmony_ci sprint_symbol(str, tbp->fnaddr.low); 11862306a36Sopenharmony_ci jiffies_to_timespec64(tbp->timestamp.low, &val); 11962306a36Sopenharmony_ci } else { 12062306a36Sopenharmony_ci sprint_symbol(str, tbp->fnaddr.val); 12162306a36Sopenharmony_ci jiffies_to_timespec64(tbp->timestamp.val, &val); 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci /* 12462306a36Sopenharmony_ci * Dump trace buffer entry to memory file 12562306a36Sopenharmony_ci * and increment read index @rd_idx 12662306a36Sopenharmony_ci */ 12762306a36Sopenharmony_ci len += scnprintf(fnic_dbgfs_prt->buffer + len, 12862306a36Sopenharmony_ci (trace_max_pages * PAGE_SIZE * 3) - len, 12962306a36Sopenharmony_ci "%16llu.%09lu %-50s %8x %8x %16llx %16llx " 13062306a36Sopenharmony_ci "%16llx %16llx %16llx\n", (u64)val.tv_sec, 13162306a36Sopenharmony_ci val.tv_nsec, str, tbp->host_no, tbp->tag, 13262306a36Sopenharmony_ci tbp->data[0], tbp->data[1], tbp->data[2], 13362306a36Sopenharmony_ci tbp->data[3], tbp->data[4]); 13462306a36Sopenharmony_ci rd_idx++; 13562306a36Sopenharmony_ci /* 13662306a36Sopenharmony_ci * If rd_idx is reached to maximum trace entries 13762306a36Sopenharmony_ci * then move rd_idx to zero 13862306a36Sopenharmony_ci */ 13962306a36Sopenharmony_ci if (rd_idx > (fnic_max_trace_entries-1)) 14062306a36Sopenharmony_ci rd_idx = 0; 14162306a36Sopenharmony_ci /* 14262306a36Sopenharmony_ci * Continue dumping trace buffer entries into 14362306a36Sopenharmony_ci * memory file till rd_idx reaches write index 14462306a36Sopenharmony_ci */ 14562306a36Sopenharmony_ci if (rd_idx == wr_idx) 14662306a36Sopenharmony_ci break; 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci } else if (wr_idx > rd_idx) { 14962306a36Sopenharmony_ci while (1) { 15062306a36Sopenharmony_ci /* Start from read index @rd_idx */ 15162306a36Sopenharmony_ci tbp = (fnic_trace_data_t *) 15262306a36Sopenharmony_ci fnic_trace_entries.page_offset[rd_idx]; 15362306a36Sopenharmony_ci if (!tbp) { 15462306a36Sopenharmony_ci spin_unlock_irqrestore(&fnic_trace_lock, flags); 15562306a36Sopenharmony_ci return 0; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci /* Convert function pointer to function name */ 15862306a36Sopenharmony_ci if (sizeof(unsigned long) < 8) { 15962306a36Sopenharmony_ci sprint_symbol(str, tbp->fnaddr.low); 16062306a36Sopenharmony_ci jiffies_to_timespec64(tbp->timestamp.low, &val); 16162306a36Sopenharmony_ci } else { 16262306a36Sopenharmony_ci sprint_symbol(str, tbp->fnaddr.val); 16362306a36Sopenharmony_ci jiffies_to_timespec64(tbp->timestamp.val, &val); 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci /* 16662306a36Sopenharmony_ci * Dump trace buffer entry to memory file 16762306a36Sopenharmony_ci * and increment read index @rd_idx 16862306a36Sopenharmony_ci */ 16962306a36Sopenharmony_ci len += scnprintf(fnic_dbgfs_prt->buffer + len, 17062306a36Sopenharmony_ci (trace_max_pages * PAGE_SIZE * 3) - len, 17162306a36Sopenharmony_ci "%16llu.%09lu %-50s %8x %8x %16llx %16llx " 17262306a36Sopenharmony_ci "%16llx %16llx %16llx\n", (u64)val.tv_sec, 17362306a36Sopenharmony_ci val.tv_nsec, str, tbp->host_no, tbp->tag, 17462306a36Sopenharmony_ci tbp->data[0], tbp->data[1], tbp->data[2], 17562306a36Sopenharmony_ci tbp->data[3], tbp->data[4]); 17662306a36Sopenharmony_ci rd_idx++; 17762306a36Sopenharmony_ci /* 17862306a36Sopenharmony_ci * Continue dumping trace buffer entries into 17962306a36Sopenharmony_ci * memory file till rd_idx reaches write index 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_ci if (rd_idx == wr_idx) 18262306a36Sopenharmony_ci break; 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci spin_unlock_irqrestore(&fnic_trace_lock, flags); 18662306a36Sopenharmony_ci return len; 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci/* 19062306a36Sopenharmony_ci * fnic_get_stats_data - Copy fnic stats buffer to a memory file 19162306a36Sopenharmony_ci * @fnic_dbgfs_t: pointer to debugfs fnic stats buffer 19262306a36Sopenharmony_ci * 19362306a36Sopenharmony_ci * Description: 19462306a36Sopenharmony_ci * This routine gathers the fnic stats debugfs data from the fnic_stats struct 19562306a36Sopenharmony_ci * and dumps it to stats_debug_info. 19662306a36Sopenharmony_ci * 19762306a36Sopenharmony_ci * Return Value: 19862306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into 19962306a36Sopenharmony_ci * stats_debug_info 20062306a36Sopenharmony_ci */ 20162306a36Sopenharmony_ciint fnic_get_stats_data(struct stats_debug_info *debug, 20262306a36Sopenharmony_ci struct fnic_stats *stats) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci int len = 0; 20562306a36Sopenharmony_ci int buf_size = debug->buf_size; 20662306a36Sopenharmony_ci struct timespec64 val1, val2; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci ktime_get_real_ts64(&val1); 20962306a36Sopenharmony_ci len = scnprintf(debug->debug_buffer + len, buf_size - len, 21062306a36Sopenharmony_ci "------------------------------------------\n" 21162306a36Sopenharmony_ci "\t\tTime\n" 21262306a36Sopenharmony_ci "------------------------------------------\n"); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 21562306a36Sopenharmony_ci "Current time : [%lld:%ld]\n" 21662306a36Sopenharmony_ci "Last stats reset time: [%lld:%09ld]\n" 21762306a36Sopenharmony_ci "Last stats read time: [%lld:%ld]\n" 21862306a36Sopenharmony_ci "delta since last reset: [%lld:%ld]\n" 21962306a36Sopenharmony_ci "delta since last read: [%lld:%ld]\n", 22062306a36Sopenharmony_ci (s64)val1.tv_sec, val1.tv_nsec, 22162306a36Sopenharmony_ci (s64)stats->stats_timestamps.last_reset_time.tv_sec, 22262306a36Sopenharmony_ci stats->stats_timestamps.last_reset_time.tv_nsec, 22362306a36Sopenharmony_ci (s64)stats->stats_timestamps.last_read_time.tv_sec, 22462306a36Sopenharmony_ci stats->stats_timestamps.last_read_time.tv_nsec, 22562306a36Sopenharmony_ci (s64)timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_sec, 22662306a36Sopenharmony_ci timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_nsec, 22762306a36Sopenharmony_ci (s64)timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_sec, 22862306a36Sopenharmony_ci timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_nsec); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci stats->stats_timestamps.last_read_time = val1; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 23362306a36Sopenharmony_ci "------------------------------------------\n" 23462306a36Sopenharmony_ci "\t\tIO Statistics\n" 23562306a36Sopenharmony_ci "------------------------------------------\n"); 23662306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 23762306a36Sopenharmony_ci "Number of Active IOs: %lld\nMaximum Active IOs: %lld\n" 23862306a36Sopenharmony_ci "Number of IOs: %lld\nNumber of IO Completions: %lld\n" 23962306a36Sopenharmony_ci "Number of IO Failures: %lld\nNumber of IO NOT Found: %lld\n" 24062306a36Sopenharmony_ci "Number of Memory alloc Failures: %lld\n" 24162306a36Sopenharmony_ci "Number of IOREQ Null: %lld\n" 24262306a36Sopenharmony_ci "Number of SCSI cmd pointer Null: %lld\n" 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci "\nIO completion times: \n" 24562306a36Sopenharmony_ci " < 10 ms : %lld\n" 24662306a36Sopenharmony_ci " 10 ms - 100 ms : %lld\n" 24762306a36Sopenharmony_ci " 100 ms - 500 ms : %lld\n" 24862306a36Sopenharmony_ci " 500 ms - 5 sec: %lld\n" 24962306a36Sopenharmony_ci " 5 sec - 10 sec: %lld\n" 25062306a36Sopenharmony_ci " 10 sec - 30 sec: %lld\n" 25162306a36Sopenharmony_ci " > 30 sec: %lld\n", 25262306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.active_ios), 25362306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.max_active_ios), 25462306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.num_ios), 25562306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.io_completions), 25662306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.io_failures), 25762306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.io_not_found), 25862306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.alloc_failures), 25962306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.ioreq_null), 26062306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.sc_null), 26162306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.io_btw_0_to_10_msec), 26262306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.io_btw_10_to_100_msec), 26362306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.io_btw_100_to_500_msec), 26462306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.io_btw_500_to_5000_msec), 26562306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.io_btw_5000_to_10000_msec), 26662306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.io_btw_10000_to_30000_msec), 26762306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.io_greater_than_30000_msec)); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 27062306a36Sopenharmony_ci "\nCurrent Max IO time : %lld\n", 27162306a36Sopenharmony_ci (u64)atomic64_read(&stats->io_stats.current_max_io_time)); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 27462306a36Sopenharmony_ci "\n------------------------------------------\n" 27562306a36Sopenharmony_ci "\t\tAbort Statistics\n" 27662306a36Sopenharmony_ci "------------------------------------------\n"); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 27962306a36Sopenharmony_ci "Number of Aborts: %lld\n" 28062306a36Sopenharmony_ci "Number of Abort Failures: %lld\n" 28162306a36Sopenharmony_ci "Number of Abort Driver Timeouts: %lld\n" 28262306a36Sopenharmony_ci "Number of Abort FW Timeouts: %lld\n" 28362306a36Sopenharmony_ci "Number of Abort IO NOT Found: %lld\n" 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci "Abort issued times: \n" 28662306a36Sopenharmony_ci " < 6 sec : %lld\n" 28762306a36Sopenharmony_ci " 6 sec - 20 sec : %lld\n" 28862306a36Sopenharmony_ci " 20 sec - 30 sec : %lld\n" 28962306a36Sopenharmony_ci " 30 sec - 40 sec : %lld\n" 29062306a36Sopenharmony_ci " 40 sec - 50 sec : %lld\n" 29162306a36Sopenharmony_ci " 50 sec - 60 sec : %lld\n" 29262306a36Sopenharmony_ci " > 60 sec: %lld\n", 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci (u64)atomic64_read(&stats->abts_stats.aborts), 29562306a36Sopenharmony_ci (u64)atomic64_read(&stats->abts_stats.abort_failures), 29662306a36Sopenharmony_ci (u64)atomic64_read(&stats->abts_stats.abort_drv_timeouts), 29762306a36Sopenharmony_ci (u64)atomic64_read(&stats->abts_stats.abort_fw_timeouts), 29862306a36Sopenharmony_ci (u64)atomic64_read(&stats->abts_stats.abort_io_not_found), 29962306a36Sopenharmony_ci (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_0_to_6_sec), 30062306a36Sopenharmony_ci (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_6_to_20_sec), 30162306a36Sopenharmony_ci (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_20_to_30_sec), 30262306a36Sopenharmony_ci (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_30_to_40_sec), 30362306a36Sopenharmony_ci (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_40_to_50_sec), 30462306a36Sopenharmony_ci (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_50_to_60_sec), 30562306a36Sopenharmony_ci (u64)atomic64_read(&stats->abts_stats.abort_issued_greater_than_60_sec)); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 30862306a36Sopenharmony_ci "\n------------------------------------------\n" 30962306a36Sopenharmony_ci "\t\tTerminate Statistics\n" 31062306a36Sopenharmony_ci "------------------------------------------\n"); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 31362306a36Sopenharmony_ci "Number of Terminates: %lld\n" 31462306a36Sopenharmony_ci "Maximum Terminates: %lld\n" 31562306a36Sopenharmony_ci "Number of Terminate Driver Timeouts: %lld\n" 31662306a36Sopenharmony_ci "Number of Terminate FW Timeouts: %lld\n" 31762306a36Sopenharmony_ci "Number of Terminate IO NOT Found: %lld\n" 31862306a36Sopenharmony_ci "Number of Terminate Failures: %lld\n", 31962306a36Sopenharmony_ci (u64)atomic64_read(&stats->term_stats.terminates), 32062306a36Sopenharmony_ci (u64)atomic64_read(&stats->term_stats.max_terminates), 32162306a36Sopenharmony_ci (u64)atomic64_read(&stats->term_stats.terminate_drv_timeouts), 32262306a36Sopenharmony_ci (u64)atomic64_read(&stats->term_stats.terminate_fw_timeouts), 32362306a36Sopenharmony_ci (u64)atomic64_read(&stats->term_stats.terminate_io_not_found), 32462306a36Sopenharmony_ci (u64)atomic64_read(&stats->term_stats.terminate_failures)); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 32762306a36Sopenharmony_ci "\n------------------------------------------\n" 32862306a36Sopenharmony_ci "\t\tReset Statistics\n" 32962306a36Sopenharmony_ci "------------------------------------------\n"); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 33262306a36Sopenharmony_ci "Number of Device Resets: %lld\n" 33362306a36Sopenharmony_ci "Number of Device Reset Failures: %lld\n" 33462306a36Sopenharmony_ci "Number of Device Reset Aborts: %lld\n" 33562306a36Sopenharmony_ci "Number of Device Reset Timeouts: %lld\n" 33662306a36Sopenharmony_ci "Number of Device Reset Terminates: %lld\n" 33762306a36Sopenharmony_ci "Number of FW Resets: %lld\n" 33862306a36Sopenharmony_ci "Number of FW Reset Completions: %lld\n" 33962306a36Sopenharmony_ci "Number of FW Reset Failures: %lld\n" 34062306a36Sopenharmony_ci "Number of Fnic Reset: %lld\n" 34162306a36Sopenharmony_ci "Number of Fnic Reset Completions: %lld\n" 34262306a36Sopenharmony_ci "Number of Fnic Reset Failures: %lld\n", 34362306a36Sopenharmony_ci (u64)atomic64_read(&stats->reset_stats.device_resets), 34462306a36Sopenharmony_ci (u64)atomic64_read(&stats->reset_stats.device_reset_failures), 34562306a36Sopenharmony_ci (u64)atomic64_read(&stats->reset_stats.device_reset_aborts), 34662306a36Sopenharmony_ci (u64)atomic64_read(&stats->reset_stats.device_reset_timeouts), 34762306a36Sopenharmony_ci (u64)atomic64_read( 34862306a36Sopenharmony_ci &stats->reset_stats.device_reset_terminates), 34962306a36Sopenharmony_ci (u64)atomic64_read(&stats->reset_stats.fw_resets), 35062306a36Sopenharmony_ci (u64)atomic64_read(&stats->reset_stats.fw_reset_completions), 35162306a36Sopenharmony_ci (u64)atomic64_read(&stats->reset_stats.fw_reset_failures), 35262306a36Sopenharmony_ci (u64)atomic64_read(&stats->reset_stats.fnic_resets), 35362306a36Sopenharmony_ci (u64)atomic64_read( 35462306a36Sopenharmony_ci &stats->reset_stats.fnic_reset_completions), 35562306a36Sopenharmony_ci (u64)atomic64_read(&stats->reset_stats.fnic_reset_failures)); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 35862306a36Sopenharmony_ci "\n------------------------------------------\n" 35962306a36Sopenharmony_ci "\t\tFirmware Statistics\n" 36062306a36Sopenharmony_ci "------------------------------------------\n"); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 36362306a36Sopenharmony_ci "Number of Active FW Requests %lld\n" 36462306a36Sopenharmony_ci "Maximum FW Requests: %lld\n" 36562306a36Sopenharmony_ci "Number of FW out of resources: %lld\n" 36662306a36Sopenharmony_ci "Number of FW IO errors: %lld\n", 36762306a36Sopenharmony_ci (u64)atomic64_read(&stats->fw_stats.active_fw_reqs), 36862306a36Sopenharmony_ci (u64)atomic64_read(&stats->fw_stats.max_fw_reqs), 36962306a36Sopenharmony_ci (u64)atomic64_read(&stats->fw_stats.fw_out_of_resources), 37062306a36Sopenharmony_ci (u64)atomic64_read(&stats->fw_stats.io_fw_errs)); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 37362306a36Sopenharmony_ci "\n------------------------------------------\n" 37462306a36Sopenharmony_ci "\t\tVlan Discovery Statistics\n" 37562306a36Sopenharmony_ci "------------------------------------------\n"); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 37862306a36Sopenharmony_ci "Number of Vlan Discovery Requests Sent %lld\n" 37962306a36Sopenharmony_ci "Vlan Response Received with no FCF VLAN ID: %lld\n" 38062306a36Sopenharmony_ci "No solicitations recvd after vlan set, expiry count: %lld\n" 38162306a36Sopenharmony_ci "Flogi rejects count: %lld\n", 38262306a36Sopenharmony_ci (u64)atomic64_read(&stats->vlan_stats.vlan_disc_reqs), 38362306a36Sopenharmony_ci (u64)atomic64_read(&stats->vlan_stats.resp_withno_vlanID), 38462306a36Sopenharmony_ci (u64)atomic64_read(&stats->vlan_stats.sol_expiry_count), 38562306a36Sopenharmony_ci (u64)atomic64_read(&stats->vlan_stats.flogi_rejects)); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 38862306a36Sopenharmony_ci "\n------------------------------------------\n" 38962306a36Sopenharmony_ci "\t\tOther Important Statistics\n" 39062306a36Sopenharmony_ci "------------------------------------------\n"); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci jiffies_to_timespec64(stats->misc_stats.last_isr_time, &val1); 39362306a36Sopenharmony_ci jiffies_to_timespec64(stats->misc_stats.last_ack_time, &val2); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 39662306a36Sopenharmony_ci "Last ISR time: %llu (%8llu.%09lu)\n" 39762306a36Sopenharmony_ci "Last ACK time: %llu (%8llu.%09lu)\n" 39862306a36Sopenharmony_ci "Max ISR jiffies: %llu\n" 39962306a36Sopenharmony_ci "Max ISR time (ms) (0 denotes < 1 ms): %llu\n" 40062306a36Sopenharmony_ci "Corr. work done: %llu\n" 40162306a36Sopenharmony_ci "Number of ISRs: %lld\n" 40262306a36Sopenharmony_ci "Maximum CQ Entries: %lld\n" 40362306a36Sopenharmony_ci "Number of ACK index out of range: %lld\n" 40462306a36Sopenharmony_ci "Number of data count mismatch: %lld\n" 40562306a36Sopenharmony_ci "Number of FCPIO Timeouts: %lld\n" 40662306a36Sopenharmony_ci "Number of FCPIO Aborted: %lld\n" 40762306a36Sopenharmony_ci "Number of SGL Invalid: %lld\n" 40862306a36Sopenharmony_ci "Number of Copy WQ Alloc Failures for ABTs: %lld\n" 40962306a36Sopenharmony_ci "Number of Copy WQ Alloc Failures for Device Reset: %lld\n" 41062306a36Sopenharmony_ci "Number of Copy WQ Alloc Failures for IOs: %lld\n" 41162306a36Sopenharmony_ci "Number of no icmnd itmf Completions: %lld\n" 41262306a36Sopenharmony_ci "Number of Check Conditions encountered: %lld\n" 41362306a36Sopenharmony_ci "Number of QUEUE Fulls: %lld\n" 41462306a36Sopenharmony_ci "Number of rport not ready: %lld\n" 41562306a36Sopenharmony_ci "Number of receive frame errors: %lld\n", 41662306a36Sopenharmony_ci (u64)stats->misc_stats.last_isr_time, 41762306a36Sopenharmony_ci (s64)val1.tv_sec, val1.tv_nsec, 41862306a36Sopenharmony_ci (u64)stats->misc_stats.last_ack_time, 41962306a36Sopenharmony_ci (s64)val2.tv_sec, val2.tv_nsec, 42062306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.max_isr_jiffies), 42162306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.max_isr_time_ms), 42262306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.corr_work_done), 42362306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.isr_count), 42462306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.max_cq_entries), 42562306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.ack_index_out_of_range), 42662306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.data_count_mismatch), 42762306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.fcpio_timeout), 42862306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.fcpio_aborted), 42962306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.sgl_invalid), 43062306a36Sopenharmony_ci (u64)atomic64_read( 43162306a36Sopenharmony_ci &stats->misc_stats.abts_cpwq_alloc_failures), 43262306a36Sopenharmony_ci (u64)atomic64_read( 43362306a36Sopenharmony_ci &stats->misc_stats.devrst_cpwq_alloc_failures), 43462306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.io_cpwq_alloc_failures), 43562306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.no_icmnd_itmf_cmpls), 43662306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.check_condition), 43762306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.queue_fulls), 43862306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.rport_not_ready), 43962306a36Sopenharmony_ci (u64)atomic64_read(&stats->misc_stats.frame_errors)); 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci len += scnprintf(debug->debug_buffer + len, buf_size - len, 44262306a36Sopenharmony_ci "Firmware reported port speed: %llu\n", 44362306a36Sopenharmony_ci (u64)atomic64_read( 44462306a36Sopenharmony_ci &stats->misc_stats.current_port_speed)); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci return len; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci} 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci/* 45162306a36Sopenharmony_ci * fnic_trace_buf_init - Initialize fnic trace buffer logging facility 45262306a36Sopenharmony_ci * 45362306a36Sopenharmony_ci * Description: 45462306a36Sopenharmony_ci * Initialize trace buffer data structure by allocating required memory and 45562306a36Sopenharmony_ci * setting page_offset information for every trace entry by adding trace entry 45662306a36Sopenharmony_ci * length to previous page_offset value. 45762306a36Sopenharmony_ci */ 45862306a36Sopenharmony_ciint fnic_trace_buf_init(void) 45962306a36Sopenharmony_ci{ 46062306a36Sopenharmony_ci unsigned long fnic_buf_head; 46162306a36Sopenharmony_ci int i; 46262306a36Sopenharmony_ci int err = 0; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci trace_max_pages = fnic_trace_max_pages; 46562306a36Sopenharmony_ci fnic_max_trace_entries = (trace_max_pages * PAGE_SIZE)/ 46662306a36Sopenharmony_ci FNIC_ENTRY_SIZE_BYTES; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci fnic_trace_buf_p = (unsigned long)vcalloc(trace_max_pages, PAGE_SIZE); 46962306a36Sopenharmony_ci if (!fnic_trace_buf_p) { 47062306a36Sopenharmony_ci printk(KERN_ERR PFX "Failed to allocate memory " 47162306a36Sopenharmony_ci "for fnic_trace_buf_p\n"); 47262306a36Sopenharmony_ci err = -ENOMEM; 47362306a36Sopenharmony_ci goto err_fnic_trace_buf_init; 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci fnic_trace_entries.page_offset = 47762306a36Sopenharmony_ci vmalloc(array_size(fnic_max_trace_entries, 47862306a36Sopenharmony_ci sizeof(unsigned long))); 47962306a36Sopenharmony_ci if (!fnic_trace_entries.page_offset) { 48062306a36Sopenharmony_ci printk(KERN_ERR PFX "Failed to allocate memory for" 48162306a36Sopenharmony_ci " page_offset\n"); 48262306a36Sopenharmony_ci if (fnic_trace_buf_p) { 48362306a36Sopenharmony_ci vfree((void *)fnic_trace_buf_p); 48462306a36Sopenharmony_ci fnic_trace_buf_p = 0; 48562306a36Sopenharmony_ci } 48662306a36Sopenharmony_ci err = -ENOMEM; 48762306a36Sopenharmony_ci goto err_fnic_trace_buf_init; 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci memset((void *)fnic_trace_entries.page_offset, 0, 49062306a36Sopenharmony_ci (fnic_max_trace_entries * sizeof(unsigned long))); 49162306a36Sopenharmony_ci fnic_trace_entries.wr_idx = fnic_trace_entries.rd_idx = 0; 49262306a36Sopenharmony_ci fnic_buf_head = fnic_trace_buf_p; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci /* 49562306a36Sopenharmony_ci * Set page_offset field of fnic_trace_entries struct by 49662306a36Sopenharmony_ci * calculating memory location for every trace entry using 49762306a36Sopenharmony_ci * length of each trace entry 49862306a36Sopenharmony_ci */ 49962306a36Sopenharmony_ci for (i = 0; i < fnic_max_trace_entries; i++) { 50062306a36Sopenharmony_ci fnic_trace_entries.page_offset[i] = fnic_buf_head; 50162306a36Sopenharmony_ci fnic_buf_head += FNIC_ENTRY_SIZE_BYTES; 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci fnic_trace_debugfs_init(); 50462306a36Sopenharmony_ci pr_info("fnic: Successfully Initialized Trace Buffer\n"); 50562306a36Sopenharmony_ci return err; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_cierr_fnic_trace_buf_init: 50862306a36Sopenharmony_ci return err; 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci/* 51262306a36Sopenharmony_ci * fnic_trace_free - Free memory of fnic trace data structures. 51362306a36Sopenharmony_ci */ 51462306a36Sopenharmony_civoid fnic_trace_free(void) 51562306a36Sopenharmony_ci{ 51662306a36Sopenharmony_ci fnic_tracing_enabled = 0; 51762306a36Sopenharmony_ci fnic_trace_debugfs_terminate(); 51862306a36Sopenharmony_ci if (fnic_trace_entries.page_offset) { 51962306a36Sopenharmony_ci vfree((void *)fnic_trace_entries.page_offset); 52062306a36Sopenharmony_ci fnic_trace_entries.page_offset = NULL; 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci if (fnic_trace_buf_p) { 52362306a36Sopenharmony_ci vfree((void *)fnic_trace_buf_p); 52462306a36Sopenharmony_ci fnic_trace_buf_p = 0; 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci printk(KERN_INFO PFX "Successfully Freed Trace Buffer\n"); 52762306a36Sopenharmony_ci} 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci/* 53062306a36Sopenharmony_ci * fnic_fc_ctlr_trace_buf_init - 53162306a36Sopenharmony_ci * Initialize trace buffer to log fnic control frames 53262306a36Sopenharmony_ci * Description: 53362306a36Sopenharmony_ci * Initialize trace buffer data structure by allocating 53462306a36Sopenharmony_ci * required memory for trace data as well as for Indexes. 53562306a36Sopenharmony_ci * Frame size is 256 bytes and 53662306a36Sopenharmony_ci * memory is allocated for 1024 entries of 256 bytes. 53762306a36Sopenharmony_ci * Page_offset(Index) is set to the address of trace entry 53862306a36Sopenharmony_ci * and page_offset is initialized by adding frame size 53962306a36Sopenharmony_ci * to the previous page_offset entry. 54062306a36Sopenharmony_ci */ 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ciint fnic_fc_trace_init(void) 54362306a36Sopenharmony_ci{ 54462306a36Sopenharmony_ci unsigned long fc_trace_buf_head; 54562306a36Sopenharmony_ci int err = 0; 54662306a36Sopenharmony_ci int i; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci fc_trace_max_entries = (fnic_fc_trace_max_pages * PAGE_SIZE)/ 54962306a36Sopenharmony_ci FC_TRC_SIZE_BYTES; 55062306a36Sopenharmony_ci fnic_fc_ctlr_trace_buf_p = 55162306a36Sopenharmony_ci (unsigned long)vmalloc(array_size(PAGE_SIZE, 55262306a36Sopenharmony_ci fnic_fc_trace_max_pages)); 55362306a36Sopenharmony_ci if (!fnic_fc_ctlr_trace_buf_p) { 55462306a36Sopenharmony_ci pr_err("fnic: Failed to allocate memory for " 55562306a36Sopenharmony_ci "FC Control Trace Buf\n"); 55662306a36Sopenharmony_ci err = -ENOMEM; 55762306a36Sopenharmony_ci goto err_fnic_fc_ctlr_trace_buf_init; 55862306a36Sopenharmony_ci } 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci memset((void *)fnic_fc_ctlr_trace_buf_p, 0, 56162306a36Sopenharmony_ci fnic_fc_trace_max_pages * PAGE_SIZE); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci /* Allocate memory for page offset */ 56462306a36Sopenharmony_ci fc_trace_entries.page_offset = 56562306a36Sopenharmony_ci vmalloc(array_size(fc_trace_max_entries, 56662306a36Sopenharmony_ci sizeof(unsigned long))); 56762306a36Sopenharmony_ci if (!fc_trace_entries.page_offset) { 56862306a36Sopenharmony_ci pr_err("fnic:Failed to allocate memory for page_offset\n"); 56962306a36Sopenharmony_ci if (fnic_fc_ctlr_trace_buf_p) { 57062306a36Sopenharmony_ci pr_err("fnic: Freeing FC Control Trace Buf\n"); 57162306a36Sopenharmony_ci vfree((void *)fnic_fc_ctlr_trace_buf_p); 57262306a36Sopenharmony_ci fnic_fc_ctlr_trace_buf_p = 0; 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci err = -ENOMEM; 57562306a36Sopenharmony_ci goto err_fnic_fc_ctlr_trace_buf_init; 57662306a36Sopenharmony_ci } 57762306a36Sopenharmony_ci memset((void *)fc_trace_entries.page_offset, 0, 57862306a36Sopenharmony_ci (fc_trace_max_entries * sizeof(unsigned long))); 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci fc_trace_entries.rd_idx = fc_trace_entries.wr_idx = 0; 58162306a36Sopenharmony_ci fc_trace_buf_head = fnic_fc_ctlr_trace_buf_p; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci /* 58462306a36Sopenharmony_ci * Set up fc_trace_entries.page_offset field with memory location 58562306a36Sopenharmony_ci * for every trace entry 58662306a36Sopenharmony_ci */ 58762306a36Sopenharmony_ci for (i = 0; i < fc_trace_max_entries; i++) { 58862306a36Sopenharmony_ci fc_trace_entries.page_offset[i] = fc_trace_buf_head; 58962306a36Sopenharmony_ci fc_trace_buf_head += FC_TRC_SIZE_BYTES; 59062306a36Sopenharmony_ci } 59162306a36Sopenharmony_ci fnic_fc_trace_debugfs_init(); 59262306a36Sopenharmony_ci pr_info("fnic: Successfully Initialized FC_CTLR Trace Buffer\n"); 59362306a36Sopenharmony_ci return err; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_cierr_fnic_fc_ctlr_trace_buf_init: 59662306a36Sopenharmony_ci return err; 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci/* 60062306a36Sopenharmony_ci * Fnic_fc_ctlr_trace_free - Free memory of fnic_fc_ctlr trace data structures. 60162306a36Sopenharmony_ci */ 60262306a36Sopenharmony_civoid fnic_fc_trace_free(void) 60362306a36Sopenharmony_ci{ 60462306a36Sopenharmony_ci fnic_fc_tracing_enabled = 0; 60562306a36Sopenharmony_ci fnic_fc_trace_debugfs_terminate(); 60662306a36Sopenharmony_ci if (fc_trace_entries.page_offset) { 60762306a36Sopenharmony_ci vfree((void *)fc_trace_entries.page_offset); 60862306a36Sopenharmony_ci fc_trace_entries.page_offset = NULL; 60962306a36Sopenharmony_ci } 61062306a36Sopenharmony_ci if (fnic_fc_ctlr_trace_buf_p) { 61162306a36Sopenharmony_ci vfree((void *)fnic_fc_ctlr_trace_buf_p); 61262306a36Sopenharmony_ci fnic_fc_ctlr_trace_buf_p = 0; 61362306a36Sopenharmony_ci } 61462306a36Sopenharmony_ci pr_info("fnic:Successfully FC_CTLR Freed Trace Buffer\n"); 61562306a36Sopenharmony_ci} 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci/* 61862306a36Sopenharmony_ci * fnic_fc_ctlr_set_trace_data: 61962306a36Sopenharmony_ci * Maintain rd & wr idx accordingly and set data 62062306a36Sopenharmony_ci * Passed parameters: 62162306a36Sopenharmony_ci * host_no: host number associated with fnic 62262306a36Sopenharmony_ci * frame_type: send_frame, rece_frame or link event 62362306a36Sopenharmony_ci * fc_frame: pointer to fc_frame 62462306a36Sopenharmony_ci * frame_len: Length of the fc_frame 62562306a36Sopenharmony_ci * Description: 62662306a36Sopenharmony_ci * This routine will get next available wr_idx and 62762306a36Sopenharmony_ci * copy all passed trace data to the buffer pointed by wr_idx 62862306a36Sopenharmony_ci * and increment wr_idx. It will also make sure that we dont 62962306a36Sopenharmony_ci * overwrite the entry which we are reading and also 63062306a36Sopenharmony_ci * wrap around if we reach the maximum entries. 63162306a36Sopenharmony_ci * Returned Value: 63262306a36Sopenharmony_ci * It will return 0 for success or -1 for failure 63362306a36Sopenharmony_ci */ 63462306a36Sopenharmony_ciint fnic_fc_trace_set_data(u32 host_no, u8 frame_type, 63562306a36Sopenharmony_ci char *frame, u32 fc_trc_frame_len) 63662306a36Sopenharmony_ci{ 63762306a36Sopenharmony_ci unsigned long flags; 63862306a36Sopenharmony_ci struct fc_trace_hdr *fc_buf; 63962306a36Sopenharmony_ci unsigned long eth_fcoe_hdr_len; 64062306a36Sopenharmony_ci char *fc_trace; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci if (fnic_fc_tracing_enabled == 0) 64362306a36Sopenharmony_ci return 0; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci spin_lock_irqsave(&fnic_fc_trace_lock, flags); 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci if (fnic_fc_trace_cleared == 1) { 64862306a36Sopenharmony_ci fc_trace_entries.rd_idx = fc_trace_entries.wr_idx = 0; 64962306a36Sopenharmony_ci pr_info("fnic: Resetting the read idx\n"); 65062306a36Sopenharmony_ci memset((void *)fnic_fc_ctlr_trace_buf_p, 0, 65162306a36Sopenharmony_ci fnic_fc_trace_max_pages * PAGE_SIZE); 65262306a36Sopenharmony_ci fnic_fc_trace_cleared = 0; 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci fc_buf = (struct fc_trace_hdr *) 65662306a36Sopenharmony_ci fc_trace_entries.page_offset[fc_trace_entries.wr_idx]; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci fc_trace_entries.wr_idx++; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci if (fc_trace_entries.wr_idx >= fc_trace_max_entries) 66162306a36Sopenharmony_ci fc_trace_entries.wr_idx = 0; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci if (fc_trace_entries.wr_idx == fc_trace_entries.rd_idx) { 66462306a36Sopenharmony_ci fc_trace_entries.rd_idx++; 66562306a36Sopenharmony_ci if (fc_trace_entries.rd_idx >= fc_trace_max_entries) 66662306a36Sopenharmony_ci fc_trace_entries.rd_idx = 0; 66762306a36Sopenharmony_ci } 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci ktime_get_real_ts64(&fc_buf->time_stamp); 67062306a36Sopenharmony_ci fc_buf->host_no = host_no; 67162306a36Sopenharmony_ci fc_buf->frame_type = frame_type; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci fc_trace = (char *)FC_TRACE_ADDRESS(fc_buf); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci /* During the receive path, we do not have eth hdr as well as fcoe hdr 67662306a36Sopenharmony_ci * at trace entry point so we will stuff 0xff just to make it generic. 67762306a36Sopenharmony_ci */ 67862306a36Sopenharmony_ci if (frame_type == FNIC_FC_RECV) { 67962306a36Sopenharmony_ci eth_fcoe_hdr_len = sizeof(struct ethhdr) + 68062306a36Sopenharmony_ci sizeof(struct fcoe_hdr); 68162306a36Sopenharmony_ci memset((char *)fc_trace, 0xff, eth_fcoe_hdr_len); 68262306a36Sopenharmony_ci /* Copy the rest of data frame */ 68362306a36Sopenharmony_ci memcpy((char *)(fc_trace + eth_fcoe_hdr_len), (void *)frame, 68462306a36Sopenharmony_ci min_t(u8, fc_trc_frame_len, 68562306a36Sopenharmony_ci (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE 68662306a36Sopenharmony_ci - eth_fcoe_hdr_len))); 68762306a36Sopenharmony_ci } else { 68862306a36Sopenharmony_ci memcpy((char *)fc_trace, (void *)frame, 68962306a36Sopenharmony_ci min_t(u8, fc_trc_frame_len, 69062306a36Sopenharmony_ci (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE))); 69162306a36Sopenharmony_ci } 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci /* Store the actual received length */ 69462306a36Sopenharmony_ci fc_buf->frame_len = fc_trc_frame_len; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci spin_unlock_irqrestore(&fnic_fc_trace_lock, flags); 69762306a36Sopenharmony_ci return 0; 69862306a36Sopenharmony_ci} 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci/* 70162306a36Sopenharmony_ci * fnic_fc_ctlr_get_trace_data: Copy trace buffer to a memory file 70262306a36Sopenharmony_ci * Passed parameter: 70362306a36Sopenharmony_ci * @fnic_dbgfs_t: pointer to debugfs trace buffer 70462306a36Sopenharmony_ci * rdata_flag: 1 => Unformatted file 70562306a36Sopenharmony_ci * 0 => formatted file 70662306a36Sopenharmony_ci * Description: 70762306a36Sopenharmony_ci * This routine will copy the trace data to memory file with 70862306a36Sopenharmony_ci * proper formatting and also copy to another memory 70962306a36Sopenharmony_ci * file without formatting for further processing. 71062306a36Sopenharmony_ci * Return Value: 71162306a36Sopenharmony_ci * Number of bytes that were dumped into fnic_dbgfs_t 71262306a36Sopenharmony_ci */ 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ciint fnic_fc_trace_get_data(fnic_dbgfs_t *fnic_dbgfs_prt, u8 rdata_flag) 71562306a36Sopenharmony_ci{ 71662306a36Sopenharmony_ci int rd_idx, wr_idx; 71762306a36Sopenharmony_ci unsigned long flags; 71862306a36Sopenharmony_ci int len = 0, j; 71962306a36Sopenharmony_ci struct fc_trace_hdr *tdata; 72062306a36Sopenharmony_ci char *fc_trace; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci spin_lock_irqsave(&fnic_fc_trace_lock, flags); 72362306a36Sopenharmony_ci if (fc_trace_entries.wr_idx == fc_trace_entries.rd_idx) { 72462306a36Sopenharmony_ci spin_unlock_irqrestore(&fnic_fc_trace_lock, flags); 72562306a36Sopenharmony_ci pr_info("fnic: Buffer is empty\n"); 72662306a36Sopenharmony_ci return 0; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci rd_idx = fc_trace_entries.rd_idx; 72962306a36Sopenharmony_ci wr_idx = fc_trace_entries.wr_idx; 73062306a36Sopenharmony_ci if (rdata_flag == 0) { 73162306a36Sopenharmony_ci len += scnprintf(fnic_dbgfs_prt->buffer + len, 73262306a36Sopenharmony_ci (fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len, 73362306a36Sopenharmony_ci "Time Stamp (UTC)\t\t" 73462306a36Sopenharmony_ci "Host No: F Type: len: FCoE_FRAME:\n"); 73562306a36Sopenharmony_ci } 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci while (rd_idx != wr_idx) { 73862306a36Sopenharmony_ci tdata = (struct fc_trace_hdr *) 73962306a36Sopenharmony_ci fc_trace_entries.page_offset[rd_idx]; 74062306a36Sopenharmony_ci if (!tdata) { 74162306a36Sopenharmony_ci pr_info("fnic: Rd data is NULL\n"); 74262306a36Sopenharmony_ci spin_unlock_irqrestore(&fnic_fc_trace_lock, flags); 74362306a36Sopenharmony_ci return 0; 74462306a36Sopenharmony_ci } 74562306a36Sopenharmony_ci if (rdata_flag == 0) { 74662306a36Sopenharmony_ci copy_and_format_trace_data(tdata, 74762306a36Sopenharmony_ci fnic_dbgfs_prt, &len, rdata_flag); 74862306a36Sopenharmony_ci } else { 74962306a36Sopenharmony_ci fc_trace = (char *)tdata; 75062306a36Sopenharmony_ci for (j = 0; j < FC_TRC_SIZE_BYTES; j++) { 75162306a36Sopenharmony_ci len += scnprintf(fnic_dbgfs_prt->buffer + len, 75262306a36Sopenharmony_ci (fnic_fc_trace_max_pages * PAGE_SIZE * 3) 75362306a36Sopenharmony_ci - len, "%02x", fc_trace[j] & 0xff); 75462306a36Sopenharmony_ci } /* for loop */ 75562306a36Sopenharmony_ci len += scnprintf(fnic_dbgfs_prt->buffer + len, 75662306a36Sopenharmony_ci (fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len, 75762306a36Sopenharmony_ci "\n"); 75862306a36Sopenharmony_ci } 75962306a36Sopenharmony_ci rd_idx++; 76062306a36Sopenharmony_ci if (rd_idx > (fc_trace_max_entries - 1)) 76162306a36Sopenharmony_ci rd_idx = 0; 76262306a36Sopenharmony_ci } 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci spin_unlock_irqrestore(&fnic_fc_trace_lock, flags); 76562306a36Sopenharmony_ci return len; 76662306a36Sopenharmony_ci} 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci/* 76962306a36Sopenharmony_ci * copy_and_format_trace_data: Copy formatted data to char * buffer 77062306a36Sopenharmony_ci * Passed Parameter: 77162306a36Sopenharmony_ci * @fc_trace_hdr_t: pointer to trace data 77262306a36Sopenharmony_ci * @fnic_dbgfs_t: pointer to debugfs trace buffer 77362306a36Sopenharmony_ci * @orig_len: pointer to len 77462306a36Sopenharmony_ci * rdata_flag: 0 => Formatted file, 1 => Unformatted file 77562306a36Sopenharmony_ci * Description: 77662306a36Sopenharmony_ci * This routine will format and copy the passed trace data 77762306a36Sopenharmony_ci * for formatted file or unformatted file accordingly. 77862306a36Sopenharmony_ci */ 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_civoid copy_and_format_trace_data(struct fc_trace_hdr *tdata, 78162306a36Sopenharmony_ci fnic_dbgfs_t *fnic_dbgfs_prt, int *orig_len, 78262306a36Sopenharmony_ci u8 rdata_flag) 78362306a36Sopenharmony_ci{ 78462306a36Sopenharmony_ci int j, i = 1, len; 78562306a36Sopenharmony_ci int ethhdr_len = sizeof(struct ethhdr) - 1; 78662306a36Sopenharmony_ci int fcoehdr_len = sizeof(struct fcoe_hdr); 78762306a36Sopenharmony_ci int fchdr_len = sizeof(struct fc_frame_header); 78862306a36Sopenharmony_ci int max_size = fnic_fc_trace_max_pages * PAGE_SIZE * 3; 78962306a36Sopenharmony_ci char *fc_trace; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci tdata->frame_type = tdata->frame_type & 0x7F; 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci len = *orig_len; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci len += scnprintf(fnic_dbgfs_prt->buffer + len, max_size - len, 79662306a36Sopenharmony_ci "%ptTs.%09lu ns%8x %c%8x\t", 79762306a36Sopenharmony_ci &tdata->time_stamp.tv_sec, tdata->time_stamp.tv_nsec, 79862306a36Sopenharmony_ci tdata->host_no, tdata->frame_type, tdata->frame_len); 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci fc_trace = (char *)FC_TRACE_ADDRESS(tdata); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci for (j = 0; j < min_t(u8, tdata->frame_len, 80362306a36Sopenharmony_ci (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE)); j++) { 80462306a36Sopenharmony_ci if (tdata->frame_type == FNIC_FC_LE) { 80562306a36Sopenharmony_ci len += scnprintf(fnic_dbgfs_prt->buffer + len, 80662306a36Sopenharmony_ci max_size - len, "%c", fc_trace[j]); 80762306a36Sopenharmony_ci } else { 80862306a36Sopenharmony_ci len += scnprintf(fnic_dbgfs_prt->buffer + len, 80962306a36Sopenharmony_ci max_size - len, "%02x", fc_trace[j] & 0xff); 81062306a36Sopenharmony_ci len += scnprintf(fnic_dbgfs_prt->buffer + len, 81162306a36Sopenharmony_ci max_size - len, " "); 81262306a36Sopenharmony_ci if (j == ethhdr_len || 81362306a36Sopenharmony_ci j == ethhdr_len + fcoehdr_len || 81462306a36Sopenharmony_ci j == ethhdr_len + fcoehdr_len + fchdr_len || 81562306a36Sopenharmony_ci (i > 3 && j%fchdr_len == 0)) { 81662306a36Sopenharmony_ci len += scnprintf(fnic_dbgfs_prt->buffer 81762306a36Sopenharmony_ci + len, max_size - len, 81862306a36Sopenharmony_ci "\n\t\t\t\t\t\t\t\t"); 81962306a36Sopenharmony_ci i++; 82062306a36Sopenharmony_ci } 82162306a36Sopenharmony_ci } /* end of else*/ 82262306a36Sopenharmony_ci } /* End of for loop*/ 82362306a36Sopenharmony_ci len += scnprintf(fnic_dbgfs_prt->buffer + len, 82462306a36Sopenharmony_ci max_size - len, "\n"); 82562306a36Sopenharmony_ci *orig_len = len; 82662306a36Sopenharmony_ci} 827