blob: f49761ff9a00a648b5f70e5500c7efb70cac6277 [file] [log] [blame]
Jan Glauber779e6e12008-07-17 17:16:48 +02001/*
2 * drivers/s390/cio/qdio_debug.c
3 *
Jan Glauber3f09bb82009-09-11 10:28:22 +02004 * Copyright IBM Corp. 2008,2009
Jan Glauber779e6e12008-07-17 17:16:48 +02005 *
6 * Author: Jan Glauber (jang@linux.vnet.ibm.com)
7 */
Jan Glauber779e6e12008-07-17 17:16:48 +02008#include <linux/seq_file.h>
9#include <linux/debugfs.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));
36 DBF_HEX(&init_data->flags, sizeof(long));
37 DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *));
38 DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *));
39 DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
Jan Glauber779e6e12008-07-17 17:16:48 +020040
Jan Glauber22f99342008-12-25 13:38:46 +010041 /* allocate trace view for the interface */
42 snprintf(text, 20, "qdio_%s", dev_name(&init_data->cdev->dev));
43 irq_ptr->debug_area = debug_register(text, 2, 1, 16);
44 debug_register_view(irq_ptr->debug_area, &debug_hex_ascii_view);
45 debug_set_level(irq_ptr->debug_area, DBF_WARN);
46 DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created");
Jan Glauber779e6e12008-07-17 17:16:48 +020047}
48
49static int qstat_show(struct seq_file *m, void *v)
50{
51 unsigned char state;
52 struct qdio_q *q = m->private;
53 int i;
54
55 if (!q)
56 return 0;
57
Jan Glauber6486cda2010-01-04 09:05:42 +010058 seq_printf(m, "DSCI: %d nr_used: %d\n",
59 *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used));
60 seq_printf(m, "ftc: %d last_move: %d\n", q->first_to_check, q->last_move);
61 seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
62 q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count);
Jan Glauber779e6e12008-07-17 17:16:48 +020063 seq_printf(m, "slsb buffer states:\n");
Jan Glauber50f769d2008-12-25 13:38:47 +010064 seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
Jan Glauber779e6e12008-07-17 17:16:48 +020065
Jan Glauber779e6e12008-07-17 17:16:48 +020066 for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
Jan Glauber60b5df22009-06-22 12:08:10 +020067 debug_get_buf_state(q, i, &state);
Jan Glauber779e6e12008-07-17 17:16:48 +020068 switch (state) {
69 case SLSB_P_INPUT_NOT_INIT:
70 case SLSB_P_OUTPUT_NOT_INIT:
71 seq_printf(m, "N");
72 break;
73 case SLSB_P_INPUT_PRIMED:
74 case SLSB_CU_OUTPUT_PRIMED:
75 seq_printf(m, "+");
76 break;
77 case SLSB_P_INPUT_ACK:
78 seq_printf(m, "A");
79 break;
80 case SLSB_P_INPUT_ERROR:
81 case SLSB_P_OUTPUT_ERROR:
82 seq_printf(m, "x");
83 break;
84 case SLSB_CU_INPUT_EMPTY:
85 case SLSB_P_OUTPUT_EMPTY:
86 seq_printf(m, "-");
87 break;
88 case SLSB_P_INPUT_HALTED:
89 case SLSB_P_OUTPUT_HALTED:
90 seq_printf(m, ".");
91 break;
92 default:
93 seq_printf(m, "?");
94 }
95 if (i == 63)
96 seq_printf(m, "\n");
97 }
98 seq_printf(m, "\n");
Jan Glauber50f769d2008-12-25 13:38:47 +010099 seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\n");
Jan Glauber779e6e12008-07-17 17:16:48 +0200100 return 0;
101}
102
103static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
104 size_t count, loff_t *off)
105{
106 struct seq_file *seq = file->private_data;
107 struct qdio_q *q = seq->private;
108
109 if (!q)
110 return 0;
Jan Glauber779e6e12008-07-17 17:16:48 +0200111 if (q->is_input_q)
112 xchg(q->irq_ptr->dsci, 1);
113 local_bh_disable();
114 tasklet_schedule(&q->tasklet);
115 local_bh_enable();
116 return count;
117}
118
119static int qstat_seq_open(struct inode *inode, struct file *filp)
120{
121 return single_open(filp, qstat_show,
122 filp->f_path.dentry->d_inode->i_private);
123}
124
Alexey Dobriyan828c0952009-10-01 15:43:56 -0700125static const struct file_operations debugfs_fops = {
Jan Glauber779e6e12008-07-17 17:16:48 +0200126 .owner = THIS_MODULE,
127 .open = qstat_seq_open,
128 .read = seq_read,
129 .write = qstat_seq_write,
130 .llseek = seq_lseek,
131 .release = single_release,
132};
133
Jan Glauber6486cda2010-01-04 09:05:42 +0100134static char *qperf_names[] = {
135 "Assumed adapter interrupts",
136 "QDIO interrupts",
137 "Requested PCIs",
138 "Inbound tasklet runs",
139 "Inbound tasklet resched",
140 "Inbound tasklet resched2",
141 "Outbound tasklet runs",
142 "SIGA read",
143 "SIGA write",
144 "SIGA sync",
145 "Inbound calls",
146 "Inbound handler",
147 "Inbound stop_polling",
148 "Inbound queue full",
149 "Outbound calls",
150 "Outbound handler",
151 "Outbound fast_requeue",
152 "Outbound target_full",
153 "QEBSM eqbs",
154 "QEBSM eqbs partial",
155 "QEBSM sqbs",
156 "QEBSM sqbs partial"
157};
158
159static int qperf_show(struct seq_file *m, void *v)
160{
161 struct qdio_irq *irq_ptr = m->private;
162 unsigned int *stat;
163 int i;
164
165 if (!irq_ptr)
166 return 0;
167 if (!irq_ptr->perf_stat_enabled) {
168 seq_printf(m, "disabled\n");
169 return 0;
170 }
171 stat = (unsigned int *)&irq_ptr->perf_stat;
172
173 for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
174 seq_printf(m, "%26s:\t%u\n",
175 qperf_names[i], *(stat + i));
176 return 0;
177}
178
179static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
180 size_t count, loff_t *off)
181{
182 struct seq_file *seq = file->private_data;
183 struct qdio_irq *irq_ptr = seq->private;
184 unsigned long val;
185 char buf[8];
186 int ret;
187
188 if (!irq_ptr)
189 return 0;
190 if (count >= sizeof(buf))
191 return -EINVAL;
192 if (copy_from_user(&buf, ubuf, count))
193 return -EFAULT;
194 buf[count] = 0;
195
196 ret = strict_strtoul(buf, 10, &val);
197 if (ret < 0)
198 return ret;
199
200 switch (val) {
201 case 0:
202 irq_ptr->perf_stat_enabled = 0;
203 memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
204 break;
205 case 1:
206 irq_ptr->perf_stat_enabled = 1;
207 break;
208 }
209 return count;
210}
211
212static int qperf_seq_open(struct inode *inode, struct file *filp)
213{
214 return single_open(filp, qperf_show,
215 filp->f_path.dentry->d_inode->i_private);
216}
217
218static struct file_operations debugfs_perf_fops = {
219 .owner = THIS_MODULE,
220 .open = qperf_seq_open,
221 .read = seq_read,
222 .write = qperf_seq_write,
223 .llseek = seq_lseek,
224 .release = single_release,
225};
Jan Glauber779e6e12008-07-17 17:16:48 +0200226static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
227{
Jan Glauber2c780912008-10-28 11:10:14 +0100228 char name[QDIO_DEBUGFS_NAME_LEN];
Jan Glauber779e6e12008-07-17 17:16:48 +0200229
Jan Glauber3f09bb82009-09-11 10:28:22 +0200230 snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
Jan Glauber2c780912008-10-28 11:10:14 +0100231 q->is_input_q ? "input" : "output",
232 q->nr);
Jan Glauber3f09bb82009-09-11 10:28:22 +0200233 q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
234 q->irq_ptr->debugfs_dev, q, &debugfs_fops);
235 if (IS_ERR(q->debugfs_q))
236 q->debugfs_q = NULL;
Jan Glauber779e6e12008-07-17 17:16:48 +0200237}
238
239void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
240{
241 struct qdio_q *q;
242 int i;
243
Jan Glauber3f09bb82009-09-11 10:28:22 +0200244 irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev),
245 debugfs_root);
246 if (IS_ERR(irq_ptr->debugfs_dev))
247 irq_ptr->debugfs_dev = NULL;
Jan Glauber6486cda2010-01-04 09:05:42 +0100248
249 irq_ptr->debugfs_perf = debugfs_create_file("statistics",
250 S_IFREG | S_IRUGO | S_IWUSR,
251 irq_ptr->debugfs_dev, irq_ptr,
252 &debugfs_perf_fops);
253 if (IS_ERR(irq_ptr->debugfs_perf))
254 irq_ptr->debugfs_perf = NULL;
255
Jan Glauber779e6e12008-07-17 17:16:48 +0200256 for_each_input_queue(irq_ptr, q, i)
257 setup_debugfs_entry(q, cdev);
258 for_each_output_queue(irq_ptr, q, i)
259 setup_debugfs_entry(q, cdev);
Jan Glauber779e6e12008-07-17 17:16:48 +0200260}
261
262void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
263{
264 struct qdio_q *q;
265 int i;
266
Jan Glauber779e6e12008-07-17 17:16:48 +0200267 for_each_input_queue(irq_ptr, q, i)
Jan Glauber3f09bb82009-09-11 10:28:22 +0200268 debugfs_remove(q->debugfs_q);
Jan Glauber779e6e12008-07-17 17:16:48 +0200269 for_each_output_queue(irq_ptr, q, i)
Jan Glauber3f09bb82009-09-11 10:28:22 +0200270 debugfs_remove(q->debugfs_q);
Jan Glauber6486cda2010-01-04 09:05:42 +0100271 debugfs_remove(irq_ptr->debugfs_perf);
Jan Glauber3f09bb82009-09-11 10:28:22 +0200272 debugfs_remove(irq_ptr->debugfs_dev);
Jan Glauber779e6e12008-07-17 17:16:48 +0200273}
274
275int __init qdio_debug_init(void)
276{
Jan Glauber3f09bb82009-09-11 10:28:22 +0200277 debugfs_root = debugfs_create_dir("qdio", NULL);
Jan Glauber22f99342008-12-25 13:38:46 +0100278
279 qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
280 debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
281 debug_set_level(qdio_dbf_setup, DBF_INFO);
282 DBF_EVENT("dbf created\n");
283
284 qdio_dbf_error = debug_register("qdio_error", 4, 1, 16);
285 debug_register_view(qdio_dbf_error, &debug_hex_ascii_view);
286 debug_set_level(qdio_dbf_error, DBF_INFO);
287 DBF_ERROR("dbf created\n");
288 return 0;
Jan Glauber779e6e12008-07-17 17:16:48 +0200289}
290
291void qdio_debug_exit(void)
292{
293 debugfs_remove(debugfs_root);
Jan Glauber22f99342008-12-25 13:38:46 +0100294 if (qdio_dbf_setup)
295 debug_unregister(qdio_dbf_setup);
296 if (qdio_dbf_error)
297 debug_unregister(qdio_dbf_error);
Jan Glauber779e6e12008-07-17 17:16:48 +0200298}