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