xref: /openbmc/linux/drivers/scsi/qedi/qedi_debugfs.c (revision fa85b016)
13287e96aSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ace7f46bSManish Rangankar /*
3ace7f46bSManish Rangankar  * QLogic iSCSI Offload Driver
4ace7f46bSManish Rangankar  * Copyright (c) 2016 Cavium Inc.
5ace7f46bSManish Rangankar  */
6ace7f46bSManish Rangankar 
7ace7f46bSManish Rangankar #include "qedi.h"
8ace7f46bSManish Rangankar #include "qedi_dbg.h"
9ace7f46bSManish Rangankar 
10ace7f46bSManish Rangankar #include <linux/uaccess.h>
11ace7f46bSManish Rangankar #include <linux/debugfs.h>
12ace7f46bSManish Rangankar #include <linux/module.h>
13ace7f46bSManish Rangankar 
14bd571195SArnd Bergmann int qedi_do_not_recover;
15ace7f46bSManish Rangankar static struct dentry *qedi_dbg_root;
16ace7f46bSManish Rangankar 
17ace7f46bSManish Rangankar void
qedi_dbg_host_init(struct qedi_dbg_ctx * qedi,const struct qedi_debugfs_ops * dops,const struct file_operations * fops)18ace7f46bSManish Rangankar qedi_dbg_host_init(struct qedi_dbg_ctx *qedi,
19779936faSArnd Bergmann 		   const struct qedi_debugfs_ops *dops,
20ace7f46bSManish Rangankar 		   const struct file_operations *fops)
21ace7f46bSManish Rangankar {
22ace7f46bSManish Rangankar 	char host_dirname[32];
23ace7f46bSManish Rangankar 
24ace7f46bSManish Rangankar 	sprintf(host_dirname, "host%u", qedi->host_no);
25ace7f46bSManish Rangankar 	qedi->bdf_dentry = debugfs_create_dir(host_dirname, qedi_dbg_root);
26ace7f46bSManish Rangankar 
27ace7f46bSManish Rangankar 	while (dops) {
28ace7f46bSManish Rangankar 		if (!(dops->name))
29ace7f46bSManish Rangankar 			break;
30ace7f46bSManish Rangankar 
3126febfb3SGreg Kroah-Hartman 		debugfs_create_file(dops->name, 0600, qedi->bdf_dentry, qedi,
32ace7f46bSManish Rangankar 				    fops);
33ace7f46bSManish Rangankar 		dops++;
34ace7f46bSManish Rangankar 		fops++;
35ace7f46bSManish Rangankar 	}
36ace7f46bSManish Rangankar }
37ace7f46bSManish Rangankar 
38ace7f46bSManish Rangankar void
qedi_dbg_host_exit(struct qedi_dbg_ctx * qedi)39ace7f46bSManish Rangankar qedi_dbg_host_exit(struct qedi_dbg_ctx *qedi)
40ace7f46bSManish Rangankar {
41ace7f46bSManish Rangankar 	debugfs_remove_recursive(qedi->bdf_dentry);
42ace7f46bSManish Rangankar 	qedi->bdf_dentry = NULL;
43ace7f46bSManish Rangankar }
44ace7f46bSManish Rangankar 
45ace7f46bSManish Rangankar void
qedi_dbg_init(char * drv_name)46ace7f46bSManish Rangankar qedi_dbg_init(char *drv_name)
47ace7f46bSManish Rangankar {
48ace7f46bSManish Rangankar 	qedi_dbg_root = debugfs_create_dir(drv_name, NULL);
49ace7f46bSManish Rangankar }
50ace7f46bSManish Rangankar 
51ace7f46bSManish Rangankar void
qedi_dbg_exit(void)52ace7f46bSManish Rangankar qedi_dbg_exit(void)
53ace7f46bSManish Rangankar {
54ace7f46bSManish Rangankar 	debugfs_remove_recursive(qedi_dbg_root);
55ace7f46bSManish Rangankar 	qedi_dbg_root = NULL;
56ace7f46bSManish Rangankar }
57ace7f46bSManish Rangankar 
58ace7f46bSManish Rangankar static ssize_t
qedi_dbg_do_not_recover_enable(struct qedi_dbg_ctx * qedi_dbg)59ace7f46bSManish Rangankar qedi_dbg_do_not_recover_enable(struct qedi_dbg_ctx *qedi_dbg)
60ace7f46bSManish Rangankar {
61bd571195SArnd Bergmann 	if (!qedi_do_not_recover)
62bd571195SArnd Bergmann 		qedi_do_not_recover = 1;
63ace7f46bSManish Rangankar 
64ace7f46bSManish Rangankar 	QEDI_INFO(qedi_dbg, QEDI_LOG_DEBUGFS, "do_not_recover=%d\n",
65bd571195SArnd Bergmann 		  qedi_do_not_recover);
66ace7f46bSManish Rangankar 	return 0;
67ace7f46bSManish Rangankar }
68ace7f46bSManish Rangankar 
69ace7f46bSManish Rangankar static ssize_t
qedi_dbg_do_not_recover_disable(struct qedi_dbg_ctx * qedi_dbg)70ace7f46bSManish Rangankar qedi_dbg_do_not_recover_disable(struct qedi_dbg_ctx *qedi_dbg)
71ace7f46bSManish Rangankar {
72bd571195SArnd Bergmann 	if (qedi_do_not_recover)
73bd571195SArnd Bergmann 		qedi_do_not_recover = 0;
74ace7f46bSManish Rangankar 
75ace7f46bSManish Rangankar 	QEDI_INFO(qedi_dbg, QEDI_LOG_DEBUGFS, "do_not_recover=%d\n",
76bd571195SArnd Bergmann 		  qedi_do_not_recover);
77ace7f46bSManish Rangankar 	return 0;
78ace7f46bSManish Rangankar }
79ace7f46bSManish Rangankar 
80ace7f46bSManish Rangankar static struct qedi_list_of_funcs qedi_dbg_do_not_recover_ops[] = {
81ace7f46bSManish Rangankar 	{ "enable", qedi_dbg_do_not_recover_enable },
82ace7f46bSManish Rangankar 	{ "disable", qedi_dbg_do_not_recover_disable },
83ace7f46bSManish Rangankar 	{ NULL, NULL }
84ace7f46bSManish Rangankar };
85ace7f46bSManish Rangankar 
86779936faSArnd Bergmann const struct qedi_debugfs_ops qedi_debugfs_ops[] = {
87ace7f46bSManish Rangankar 	{ "gbl_ctx", NULL },
88ace7f46bSManish Rangankar 	{ "do_not_recover", qedi_dbg_do_not_recover_ops},
89ace7f46bSManish Rangankar 	{ "io_trace", NULL },
90ace7f46bSManish Rangankar 	{ NULL, NULL }
91ace7f46bSManish Rangankar };
92ace7f46bSManish Rangankar 
93ace7f46bSManish Rangankar static ssize_t
qedi_dbg_do_not_recover_cmd_write(struct file * filp,const char __user * buffer,size_t count,loff_t * ppos)94ace7f46bSManish Rangankar qedi_dbg_do_not_recover_cmd_write(struct file *filp, const char __user *buffer,
95ace7f46bSManish Rangankar 				  size_t count, loff_t *ppos)
96ace7f46bSManish Rangankar {
97ace7f46bSManish Rangankar 	size_t cnt = 0;
98ace7f46bSManish Rangankar 	struct qedi_dbg_ctx *qedi_dbg =
99ace7f46bSManish Rangankar 			(struct qedi_dbg_ctx *)filp->private_data;
100ace7f46bSManish Rangankar 	struct qedi_list_of_funcs *lof = qedi_dbg_do_not_recover_ops;
101ace7f46bSManish Rangankar 
102ace7f46bSManish Rangankar 	if (*ppos)
103ace7f46bSManish Rangankar 		return 0;
104ace7f46bSManish Rangankar 
105ace7f46bSManish Rangankar 	while (lof) {
106ace7f46bSManish Rangankar 		if (!(lof->oper_str))
107ace7f46bSManish Rangankar 			break;
108ace7f46bSManish Rangankar 
109ace7f46bSManish Rangankar 		if (!strncmp(lof->oper_str, buffer, strlen(lof->oper_str))) {
110ace7f46bSManish Rangankar 			cnt = lof->oper_func(qedi_dbg);
111ace7f46bSManish Rangankar 			break;
112ace7f46bSManish Rangankar 		}
113ace7f46bSManish Rangankar 
114ace7f46bSManish Rangankar 		lof++;
115ace7f46bSManish Rangankar 	}
116ace7f46bSManish Rangankar 	return (count - cnt);
117ace7f46bSManish Rangankar }
118ace7f46bSManish Rangankar 
119ace7f46bSManish Rangankar static ssize_t
qedi_dbg_do_not_recover_cmd_read(struct file * filp,char __user * buffer,size_t count,loff_t * ppos)120ace7f46bSManish Rangankar qedi_dbg_do_not_recover_cmd_read(struct file *filp, char __user *buffer,
121ace7f46bSManish Rangankar 				 size_t count, loff_t *ppos)
122ace7f46bSManish Rangankar {
123*fa85b016SManish Rangankar 	char buf[64];
124*fa85b016SManish Rangankar 	int len;
125ace7f46bSManish Rangankar 
126*fa85b016SManish Rangankar 	len = sprintf(buf, "do_not_recover=%d\n", qedi_do_not_recover);
127*fa85b016SManish Rangankar 	return simple_read_from_buffer(buffer, count, ppos, buf, len);
128ace7f46bSManish Rangankar }
129ace7f46bSManish Rangankar 
130ace7f46bSManish Rangankar static int
qedi_gbl_ctx_show(struct seq_file * s,void * unused)131ace7f46bSManish Rangankar qedi_gbl_ctx_show(struct seq_file *s, void *unused)
132ace7f46bSManish Rangankar {
133ace7f46bSManish Rangankar 	struct qedi_fastpath *fp = NULL;
134ace7f46bSManish Rangankar 	struct qed_sb_info *sb_info = NULL;
135fb09a1edSShai Malin 	struct status_block *sb = NULL;
136ace7f46bSManish Rangankar 	struct global_queue *que = NULL;
137ace7f46bSManish Rangankar 	int id;
138ace7f46bSManish Rangankar 	u16 prod_idx;
139ace7f46bSManish Rangankar 	struct qedi_ctx *qedi = s->private;
140ace7f46bSManish Rangankar 	unsigned long flags;
141ace7f46bSManish Rangankar 
142ace7f46bSManish Rangankar 	seq_puts(s, " DUMP CQ CONTEXT:\n");
143ace7f46bSManish Rangankar 
144ace7f46bSManish Rangankar 	for (id = 0; id < MIN_NUM_CPUS_MSIX(qedi); id++) {
145ace7f46bSManish Rangankar 		spin_lock_irqsave(&qedi->hba_lock, flags);
146ace7f46bSManish Rangankar 		seq_printf(s, "=========FAST CQ PATH [%d] ==========\n", id);
147ace7f46bSManish Rangankar 		fp = &qedi->fp_array[id];
148ace7f46bSManish Rangankar 		sb_info = fp->sb_info;
149ace7f46bSManish Rangankar 		sb = sb_info->sb_virt;
150ace7f46bSManish Rangankar 		prod_idx = (sb->pi_array[QEDI_PROTO_CQ_PROD_IDX] &
151fb09a1edSShai Malin 			    STATUS_BLOCK_PROD_INDEX_MASK);
152ace7f46bSManish Rangankar 		seq_printf(s, "SB PROD IDX: %d\n", prod_idx);
153ace7f46bSManish Rangankar 		que = qedi->global_queues[fp->sb_id];
154ace7f46bSManish Rangankar 		seq_printf(s, "DRV CONS IDX: %d\n", que->cq_cons_idx);
155ace7f46bSManish Rangankar 		seq_printf(s, "CQ complete host memory: %d\n", fp->sb_id);
156ace7f46bSManish Rangankar 		seq_puts(s, "=========== END ==================\n\n\n");
157ace7f46bSManish Rangankar 		spin_unlock_irqrestore(&qedi->hba_lock, flags);
158ace7f46bSManish Rangankar 	}
159ace7f46bSManish Rangankar 	return 0;
160ace7f46bSManish Rangankar }
161ace7f46bSManish Rangankar 
162ace7f46bSManish Rangankar static int
qedi_dbg_gbl_ctx_open(struct inode * inode,struct file * file)163ace7f46bSManish Rangankar qedi_dbg_gbl_ctx_open(struct inode *inode, struct file *file)
164ace7f46bSManish Rangankar {
165ace7f46bSManish Rangankar 	struct qedi_dbg_ctx *qedi_dbg = inode->i_private;
166ace7f46bSManish Rangankar 	struct qedi_ctx *qedi = container_of(qedi_dbg, struct qedi_ctx,
167ace7f46bSManish Rangankar 					     dbg_ctx);
168ace7f46bSManish Rangankar 
169ace7f46bSManish Rangankar 	return single_open(file, qedi_gbl_ctx_show, qedi);
170ace7f46bSManish Rangankar }
171ace7f46bSManish Rangankar 
172ace7f46bSManish Rangankar static int
qedi_io_trace_show(struct seq_file * s,void * unused)173ace7f46bSManish Rangankar qedi_io_trace_show(struct seq_file *s, void *unused)
174ace7f46bSManish Rangankar {
175ace7f46bSManish Rangankar 	int id, idx = 0;
176ace7f46bSManish Rangankar 	struct qedi_ctx *qedi = s->private;
177ace7f46bSManish Rangankar 	struct qedi_io_log *io_log;
178ace7f46bSManish Rangankar 	unsigned long flags;
179ace7f46bSManish Rangankar 
180ace7f46bSManish Rangankar 	seq_puts(s, " DUMP IO LOGS:\n");
181ace7f46bSManish Rangankar 	spin_lock_irqsave(&qedi->io_trace_lock, flags);
182ace7f46bSManish Rangankar 	idx = qedi->io_trace_idx;
183ace7f46bSManish Rangankar 	for (id = 0; id < QEDI_IO_TRACE_SIZE; id++) {
184ace7f46bSManish Rangankar 		io_log = &qedi->io_trace_buf[idx];
185ace7f46bSManish Rangankar 		seq_printf(s, "iodir-%d:", io_log->direction);
186ace7f46bSManish Rangankar 		seq_printf(s, "tid-0x%x:", io_log->task_id);
187ace7f46bSManish Rangankar 		seq_printf(s, "cid-0x%x:", io_log->cid);
188ace7f46bSManish Rangankar 		seq_printf(s, "lun-%d:", io_log->lun);
189ace7f46bSManish Rangankar 		seq_printf(s, "op-0x%02x:", io_log->op);
190ace7f46bSManish Rangankar 		seq_printf(s, "0x%02x%02x%02x%02x:", io_log->lba[0],
191ace7f46bSManish Rangankar 			   io_log->lba[1], io_log->lba[2], io_log->lba[3]);
192ace7f46bSManish Rangankar 		seq_printf(s, "buflen-%d:", io_log->bufflen);
193ace7f46bSManish Rangankar 		seq_printf(s, "sgcnt-%d:", io_log->sg_count);
194ace7f46bSManish Rangankar 		seq_printf(s, "res-0x%08x:", io_log->result);
195ace7f46bSManish Rangankar 		seq_printf(s, "jif-%lu:", io_log->jiffies);
196ace7f46bSManish Rangankar 		seq_printf(s, "blk_req_cpu-%d:", io_log->blk_req_cpu);
197ace7f46bSManish Rangankar 		seq_printf(s, "req_cpu-%d:", io_log->req_cpu);
198ace7f46bSManish Rangankar 		seq_printf(s, "intr_cpu-%d:", io_log->intr_cpu);
199ace7f46bSManish Rangankar 		seq_printf(s, "blk_rsp_cpu-%d\n", io_log->blk_rsp_cpu);
200ace7f46bSManish Rangankar 
201ace7f46bSManish Rangankar 		idx++;
202ace7f46bSManish Rangankar 		if (idx == QEDI_IO_TRACE_SIZE)
203ace7f46bSManish Rangankar 			idx = 0;
204ace7f46bSManish Rangankar 	}
205ace7f46bSManish Rangankar 	spin_unlock_irqrestore(&qedi->io_trace_lock, flags);
206ace7f46bSManish Rangankar 	return 0;
207ace7f46bSManish Rangankar }
208ace7f46bSManish Rangankar 
209ace7f46bSManish Rangankar static int
qedi_dbg_io_trace_open(struct inode * inode,struct file * file)210ace7f46bSManish Rangankar qedi_dbg_io_trace_open(struct inode *inode, struct file *file)
211ace7f46bSManish Rangankar {
212ace7f46bSManish Rangankar 	struct qedi_dbg_ctx *qedi_dbg = inode->i_private;
213ace7f46bSManish Rangankar 	struct qedi_ctx *qedi = container_of(qedi_dbg, struct qedi_ctx,
214ace7f46bSManish Rangankar 					     dbg_ctx);
215ace7f46bSManish Rangankar 
216ace7f46bSManish Rangankar 	return single_open(file, qedi_io_trace_show, qedi);
217ace7f46bSManish Rangankar }
218ace7f46bSManish Rangankar 
219ace7f46bSManish Rangankar const struct file_operations qedi_dbg_fops[] = {
220ace7f46bSManish Rangankar 	qedi_dbg_fileops_seq(qedi, gbl_ctx),
221ace7f46bSManish Rangankar 	qedi_dbg_fileops(qedi, do_not_recover),
222ace7f46bSManish Rangankar 	qedi_dbg_fileops_seq(qedi, io_trace),
223efacae6dSKees Cook 	{ },
224ace7f46bSManish Rangankar };
225