blob: 4221b02085ad46dc13838461c901abd72c786fca [file] [log] [blame]
Jan Glauber779e6e12008-07-17 17:16:48 +02001/*
Heiko Carstensa53c8fa2012-07-20 11:15:04 +02002 * Copyright IBM Corp. 2008, 2009
Jan Glauber779e6e12008-07-17 17:16:48 +02003 *
4 * Author: Jan Glauber (jang@linux.vnet.ibm.com)
5 */
Jan Glauber779e6e12008-07-17 17:16:48 +02006#include <linux/seq_file.h>
7#include <linux/debugfs.h>
Heiko Carstens3a4c5d52011-07-30 09:25:15 +02008#include <linux/uaccess.h>
9#include <linux/export.h>
Jan Glauber779e6e12008-07-17 17:16:48 +020010#include <asm/debug.h>
11#include "qdio_debug.h"
12#include "qdio.h"
13
14debug_info_t *qdio_dbf_setup;
Jan Glauber22f99342008-12-25 13:38:46 +010015debug_info_t *qdio_dbf_error;
Jan Glauber779e6e12008-07-17 17:16:48 +020016
17static struct dentry *debugfs_root;
Jan Glauber3f09bb82009-09-11 10:28:22 +020018#define QDIO_DEBUGFS_NAME_LEN 10
Jan Glauber779e6e12008-07-17 17:16:48 +020019
Jan Glauber22f99342008-12-25 13:38:46 +010020void qdio_allocate_dbf(struct qdio_initialize *init_data,
21 struct qdio_irq *irq_ptr)
Jan Glauber779e6e12008-07-17 17:16:48 +020022{
Jan Glauber22f99342008-12-25 13:38:46 +010023 char text[20];
Jan Glauber779e6e12008-07-17 17:16:48 +020024
Jan Glauber22f99342008-12-25 13:38:46 +010025 DBF_EVENT("qfmt:%1d", init_data->q_format);
26 DBF_HEX(init_data->adapter_name, 8);
27 DBF_EVENT("qpff%4x", init_data->qib_param_field_format);
28 DBF_HEX(&init_data->qib_param_field, sizeof(void *));
29 DBF_HEX(&init_data->input_slib_elements, sizeof(void *));
30 DBF_HEX(&init_data->output_slib_elements, sizeof(void *));
31 DBF_EVENT("niq:%1d noq:%1d", init_data->no_input_qs,
32 init_data->no_output_qs);
33 DBF_HEX(&init_data->input_handler, sizeof(void *));
34 DBF_HEX(&init_data->output_handler, sizeof(void *));
35 DBF_HEX(&init_data->int_parm, sizeof(long));
Jan Glauber22f99342008-12-25 13:38:46 +010036 DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *));
37 DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *));
38 DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
Jan Glauber779e6e12008-07-17 17:16:48 +020039
Jan Glauber22f99342008-12-25 13:38:46 +010040 /* allocate trace view for the interface */
41 snprintf(text, 20, "qdio_%s", dev_name(&init_data->cdev->dev));
42 irq_ptr->debug_area = debug_register(text, 2, 1, 16);
43 debug_register_view(irq_ptr->debug_area, &debug_hex_ascii_view);
44 debug_set_level(irq_ptr->debug_area, DBF_WARN);
45 DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created");
Jan Glauber779e6e12008-07-17 17:16:48 +020046}
47
48static int qstat_show(struct seq_file *m, void *v)
49{
50 unsigned char state;
51 struct qdio_q *q = m->private;
52 int i;
53
54 if (!q)
55 return 0;
56
Jan Glaubera2b86012011-10-30 15:17:05 +010057 seq_printf(m, "Timestamp: %Lx Last AI: %Lx\n",
58 q->timestamp, last_ai_time);
59 seq_printf(m, "nr_used: %d ftc: %d last_move: %d\n",
60 atomic_read(&q->nr_buf_used),
Jan Glauberd36deae2010-09-07 21:14:39 +000061 q->first_to_check, q->last_move);
62 if (q->is_input_q) {
63 seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
64 q->u.in.polling, q->u.in.ack_start,
65 q->u.in.ack_count);
Jan Glaubera2b86012011-10-30 15:17:05 +010066 seq_printf(m, "DSCI: %d IRQs disabled: %u\n",
67 *(u32 *)q->irq_ptr->dsci,
Jan Glauberd36deae2010-09-07 21:14:39 +000068 test_bit(QDIO_QUEUE_IRQS_DISABLED,
69 &q->u.in.queue_irq_state));
70 }
Jan Glauberd3072972010-02-26 22:37:36 +010071 seq_printf(m, "SBAL states:\n");
Jan Glauber50f769d2008-12-25 13:38:47 +010072 seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
Jan Glauber779e6e12008-07-17 17:16:48 +020073
Jan Glauber779e6e12008-07-17 17:16:48 +020074 for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
Jan Glauber60b5df22009-06-22 12:08:10 +020075 debug_get_buf_state(q, i, &state);
Jan Glauber779e6e12008-07-17 17:16:48 +020076 switch (state) {
77 case SLSB_P_INPUT_NOT_INIT:
78 case SLSB_P_OUTPUT_NOT_INIT:
79 seq_printf(m, "N");
80 break;
frank.blaschka@de.ibm.com104ea552011-08-08 01:33:55 +000081 case SLSB_P_OUTPUT_PENDING:
82 seq_printf(m, "P");
83 break;
Jan Glauber779e6e12008-07-17 17:16:48 +020084 case SLSB_P_INPUT_PRIMED:
85 case SLSB_CU_OUTPUT_PRIMED:
86 seq_printf(m, "+");
87 break;
88 case SLSB_P_INPUT_ACK:
89 seq_printf(m, "A");
90 break;
91 case SLSB_P_INPUT_ERROR:
92 case SLSB_P_OUTPUT_ERROR:
93 seq_printf(m, "x");
94 break;
95 case SLSB_CU_INPUT_EMPTY:
96 case SLSB_P_OUTPUT_EMPTY:
97 seq_printf(m, "-");
98 break;
99 case SLSB_P_INPUT_HALTED:
100 case SLSB_P_OUTPUT_HALTED:
101 seq_printf(m, ".");
102 break;
103 default:
104 seq_printf(m, "?");
105 }
106 if (i == 63)
107 seq_printf(m, "\n");
108 }
109 seq_printf(m, "\n");
Jan Glauber50f769d2008-12-25 13:38:47 +0100110 seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\n");
Jan Glauberd3072972010-02-26 22:37:36 +0100111
112 seq_printf(m, "\nSBAL statistics:");
113 if (!q->irq_ptr->perf_stat_enabled) {
114 seq_printf(m, " disabled\n");
115 return 0;
116 }
117
118 seq_printf(m, "\n1 2.. 4.. 8.. "
119 "16.. 32.. 64.. 127\n");
120 for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++)
121 seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]);
122 seq_printf(m, "\nError NOP Total\n%-10u %-10u %-10u\n\n",
123 q->q_stats.nr_sbal_error, q->q_stats.nr_sbal_nop,
124 q->q_stats.nr_sbal_total);
Jan Glauber779e6e12008-07-17 17:16:48 +0200125 return 0;
126}
127
Jan Glauber779e6e12008-07-17 17:16:48 +0200128static int qstat_seq_open(struct inode *inode, struct file *filp)
129{
130 return single_open(filp, qstat_show,
Al Viro496ad9a2013-01-23 17:07:38 -0500131 file_inode(filp)->i_private);
Jan Glauber779e6e12008-07-17 17:16:48 +0200132}
133
Alexey Dobriyan828c0952009-10-01 15:43:56 -0700134static const struct file_operations debugfs_fops = {
Jan Glauber779e6e12008-07-17 17:16:48 +0200135 .owner = THIS_MODULE,
136 .open = qstat_seq_open,
137 .read = seq_read,
Jan Glauber779e6e12008-07-17 17:16:48 +0200138 .llseek = seq_lseek,
139 .release = single_release,
140};
141
Jan Glauber6486cda2010-01-04 09:05:42 +0100142static char *qperf_names[] = {
143 "Assumed adapter interrupts",
144 "QDIO interrupts",
145 "Requested PCIs",
146 "Inbound tasklet runs",
147 "Inbound tasklet resched",
148 "Inbound tasklet resched2",
149 "Outbound tasklet runs",
150 "SIGA read",
151 "SIGA write",
152 "SIGA sync",
153 "Inbound calls",
154 "Inbound handler",
155 "Inbound stop_polling",
156 "Inbound queue full",
157 "Outbound calls",
158 "Outbound handler",
Jan Glauber01958432011-01-05 12:47:51 +0100159 "Outbound queue full",
Jan Glauber6486cda2010-01-04 09:05:42 +0100160 "Outbound fast_requeue",
161 "Outbound target_full",
162 "QEBSM eqbs",
163 "QEBSM eqbs partial",
164 "QEBSM sqbs",
Jan Glauberd36deae2010-09-07 21:14:39 +0000165 "QEBSM sqbs partial",
166 "Discarded interrupts"
Jan Glauber6486cda2010-01-04 09:05:42 +0100167};
168
169static int qperf_show(struct seq_file *m, void *v)
170{
171 struct qdio_irq *irq_ptr = m->private;
172 unsigned int *stat;
173 int i;
174
175 if (!irq_ptr)
176 return 0;
177 if (!irq_ptr->perf_stat_enabled) {
178 seq_printf(m, "disabled\n");
179 return 0;
180 }
181 stat = (unsigned int *)&irq_ptr->perf_stat;
182
183 for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
184 seq_printf(m, "%26s:\t%u\n",
185 qperf_names[i], *(stat + i));
186 return 0;
187}
188
189static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
190 size_t count, loff_t *off)
191{
192 struct seq_file *seq = file->private_data;
193 struct qdio_irq *irq_ptr = seq->private;
Jan Glauberd3072972010-02-26 22:37:36 +0100194 struct qdio_q *q;
Jan Glauber6486cda2010-01-04 09:05:42 +0100195 unsigned long val;
Jan Glauberd3072972010-02-26 22:37:36 +0100196 int ret, i;
Jan Glauber6486cda2010-01-04 09:05:42 +0100197
198 if (!irq_ptr)
199 return 0;
Jan Glauber6486cda2010-01-04 09:05:42 +0100200
Peter Hueweaf6df872011-08-03 16:44:30 +0200201 ret = kstrtoul_from_user(ubuf, count, 10, &val);
202 if (ret)
Jan Glauber6486cda2010-01-04 09:05:42 +0100203 return ret;
204
205 switch (val) {
206 case 0:
207 irq_ptr->perf_stat_enabled = 0;
208 memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
Jan Glauberd3072972010-02-26 22:37:36 +0100209 for_each_input_queue(irq_ptr, q, i)
210 memset(&q->q_stats, 0, sizeof(q->q_stats));
211 for_each_output_queue(irq_ptr, q, i)
212 memset(&q->q_stats, 0, sizeof(q->q_stats));
Jan Glauber6486cda2010-01-04 09:05:42 +0100213 break;
214 case 1:
215 irq_ptr->perf_stat_enabled = 1;
216 break;
217 }
218 return count;
219}
220
221static int qperf_seq_open(struct inode *inode, struct file *filp)
222{
223 return single_open(filp, qperf_show,
Al Viro496ad9a2013-01-23 17:07:38 -0500224 file_inode(filp)->i_private);
Jan Glauber6486cda2010-01-04 09:05:42 +0100225}
226
Al Viro75ef9de2013-04-04 19:09:41 -0400227static const struct file_operations debugfs_perf_fops = {
Jan Glauber6486cda2010-01-04 09:05:42 +0100228 .owner = THIS_MODULE,
229 .open = qperf_seq_open,
230 .read = seq_read,
231 .write = qperf_seq_write,
232 .llseek = seq_lseek,
233 .release = single_release,
234};
Stefan Rasplaa2383f2013-02-26 13:08:34 +0100235
236static void setup_debugfs_entry(struct qdio_q *q)
Jan Glauber779e6e12008-07-17 17:16:48 +0200237{
Jan Glauber2c780912008-10-28 11:10:14 +0100238 char name[QDIO_DEBUGFS_NAME_LEN];
Jan Glauber779e6e12008-07-17 17:16:48 +0200239
Jan Glauber3f09bb82009-09-11 10:28:22 +0200240 snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
Jan Glauber2c780912008-10-28 11:10:14 +0100241 q->is_input_q ? "input" : "output",
242 q->nr);
Jan Glauber3f09bb82009-09-11 10:28:22 +0200243 q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
244 q->irq_ptr->debugfs_dev, q, &debugfs_fops);
245 if (IS_ERR(q->debugfs_q))
246 q->debugfs_q = NULL;
Jan Glauber779e6e12008-07-17 17:16:48 +0200247}
248
249void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
250{
251 struct qdio_q *q;
252 int i;
253
Jan Glauber3f09bb82009-09-11 10:28:22 +0200254 irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev),
255 debugfs_root);
256 if (IS_ERR(irq_ptr->debugfs_dev))
257 irq_ptr->debugfs_dev = NULL;
Jan Glauber6486cda2010-01-04 09:05:42 +0100258
259 irq_ptr->debugfs_perf = debugfs_create_file("statistics",
260 S_IFREG | S_IRUGO | S_IWUSR,
261 irq_ptr->debugfs_dev, irq_ptr,
262 &debugfs_perf_fops);
263 if (IS_ERR(irq_ptr->debugfs_perf))
264 irq_ptr->debugfs_perf = NULL;
265
Jan Glauber779e6e12008-07-17 17:16:48 +0200266 for_each_input_queue(irq_ptr, q, i)
Stefan Rasplaa2383f2013-02-26 13:08:34 +0100267 setup_debugfs_entry(q);
Jan Glauber779e6e12008-07-17 17:16:48 +0200268 for_each_output_queue(irq_ptr, q, i)
Stefan Rasplaa2383f2013-02-26 13:08:34 +0100269 setup_debugfs_entry(q);
Jan Glauber779e6e12008-07-17 17:16:48 +0200270}
271
Stefan Rasplaa2383f2013-02-26 13:08:34 +0100272void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr)
Jan Glauber779e6e12008-07-17 17:16:48 +0200273{
274 struct qdio_q *q;
275 int i;
276
Jan Glauber779e6e12008-07-17 17:16:48 +0200277 for_each_input_queue(irq_ptr, q, i)
Jan Glauber3f09bb82009-09-11 10:28:22 +0200278 debugfs_remove(q->debugfs_q);
Jan Glauber779e6e12008-07-17 17:16:48 +0200279 for_each_output_queue(irq_ptr, q, i)
Jan Glauber3f09bb82009-09-11 10:28:22 +0200280 debugfs_remove(q->debugfs_q);
Jan Glauber6486cda2010-01-04 09:05:42 +0100281 debugfs_remove(irq_ptr->debugfs_perf);
Jan Glauber3f09bb82009-09-11 10:28:22 +0200282 debugfs_remove(irq_ptr->debugfs_dev);
Jan Glauber779e6e12008-07-17 17:16:48 +0200283}
284
285int __init qdio_debug_init(void)
286{
Jan Glauber3f09bb82009-09-11 10:28:22 +0200287 debugfs_root = debugfs_create_dir("qdio", NULL);
Jan Glauber22f99342008-12-25 13:38:46 +0100288
289 qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
290 debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
291 debug_set_level(qdio_dbf_setup, DBF_INFO);
292 DBF_EVENT("dbf created\n");
293
294 qdio_dbf_error = debug_register("qdio_error", 4, 1, 16);
295 debug_register_view(qdio_dbf_error, &debug_hex_ascii_view);
296 debug_set_level(qdio_dbf_error, DBF_INFO);
297 DBF_ERROR("dbf created\n");
298 return 0;
Jan Glauber779e6e12008-07-17 17:16:48 +0200299}
300
301void qdio_debug_exit(void)
302{
303 debugfs_remove(debugfs_root);
Jan Glauber22f99342008-12-25 13:38:46 +0100304 if (qdio_dbf_setup)
305 debug_unregister(qdio_dbf_setup);
306 if (qdio_dbf_error)
307 debug_unregister(qdio_dbf_error);
Jan Glauber779e6e12008-07-17 17:16:48 +0200308}