brintos

brintos / linux-shallow public Read only

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