Linux 2.6.34-rc3
[pohmelfs.git] / drivers / s390 / cio / qdio_debug.c
blob6ce83f56d5371c5acdd0a216b9992019188a6e69
1 /*
2 * drivers/s390/cio/qdio_debug.c
4 * Copyright IBM Corp. 2008,2009
6 * Author: Jan Glauber (jang@linux.vnet.ibm.com)
7 */
8 #include <linux/seq_file.h>
9 #include <linux/debugfs.h>
10 #include <asm/debug.h>
11 #include "qdio_debug.h"
12 #include "qdio.h"
14 debug_info_t *qdio_dbf_setup;
15 debug_info_t *qdio_dbf_error;
17 static struct dentry *debugfs_root;
18 #define QDIO_DEBUGFS_NAME_LEN 10
20 void qdio_allocate_dbf(struct qdio_initialize *init_data,
21 struct qdio_irq *irq_ptr)
23 char text[20];
25 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->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);
40 /* 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");
48 static int qstat_show(struct seq_file *m, void *v)
50 unsigned char state;
51 struct qdio_q *q = m->private;
52 int i;
54 if (!q)
55 return 0;
57 seq_printf(m, "DSCI: %d nr_used: %d\n",
58 *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used));
59 seq_printf(m, "ftc: %d last_move: %d\n", q->first_to_check, q->last_move);
60 seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
61 q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count);
62 seq_printf(m, "SBAL states:\n");
63 seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
65 for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
66 debug_get_buf_state(q, i, &state);
67 switch (state) {
68 case SLSB_P_INPUT_NOT_INIT:
69 case SLSB_P_OUTPUT_NOT_INIT:
70 seq_printf(m, "N");
71 break;
72 case SLSB_P_INPUT_PRIMED:
73 case SLSB_CU_OUTPUT_PRIMED:
74 seq_printf(m, "+");
75 break;
76 case SLSB_P_INPUT_ACK:
77 seq_printf(m, "A");
78 break;
79 case SLSB_P_INPUT_ERROR:
80 case SLSB_P_OUTPUT_ERROR:
81 seq_printf(m, "x");
82 break;
83 case SLSB_CU_INPUT_EMPTY:
84 case SLSB_P_OUTPUT_EMPTY:
85 seq_printf(m, "-");
86 break;
87 case SLSB_P_INPUT_HALTED:
88 case SLSB_P_OUTPUT_HALTED:
89 seq_printf(m, ".");
90 break;
91 default:
92 seq_printf(m, "?");
94 if (i == 63)
95 seq_printf(m, "\n");
97 seq_printf(m, "\n");
98 seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\n");
100 seq_printf(m, "\nSBAL statistics:");
101 if (!q->irq_ptr->perf_stat_enabled) {
102 seq_printf(m, " disabled\n");
103 return 0;
106 seq_printf(m, "\n1 2.. 4.. 8.. "
107 "16.. 32.. 64.. 127\n");
108 for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++)
109 seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]);
110 seq_printf(m, "\nError NOP Total\n%-10u %-10u %-10u\n\n",
111 q->q_stats.nr_sbal_error, q->q_stats.nr_sbal_nop,
112 q->q_stats.nr_sbal_total);
113 return 0;
116 static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
117 size_t count, loff_t *off)
119 struct seq_file *seq = file->private_data;
120 struct qdio_q *q = seq->private;
122 if (!q)
123 return 0;
124 if (q->is_input_q)
125 xchg(q->irq_ptr->dsci, 1);
126 local_bh_disable();
127 tasklet_schedule(&q->tasklet);
128 local_bh_enable();
129 return count;
132 static int qstat_seq_open(struct inode *inode, struct file *filp)
134 return single_open(filp, qstat_show,
135 filp->f_path.dentry->d_inode->i_private);
138 static const struct file_operations debugfs_fops = {
139 .owner = THIS_MODULE,
140 .open = qstat_seq_open,
141 .read = seq_read,
142 .write = qstat_seq_write,
143 .llseek = seq_lseek,
144 .release = single_release,
147 static char *qperf_names[] = {
148 "Assumed adapter interrupts",
149 "QDIO interrupts",
150 "Requested PCIs",
151 "Inbound tasklet runs",
152 "Inbound tasklet resched",
153 "Inbound tasklet resched2",
154 "Outbound tasklet runs",
155 "SIGA read",
156 "SIGA write",
157 "SIGA sync",
158 "Inbound calls",
159 "Inbound handler",
160 "Inbound stop_polling",
161 "Inbound queue full",
162 "Outbound calls",
163 "Outbound handler",
164 "Outbound fast_requeue",
165 "Outbound target_full",
166 "QEBSM eqbs",
167 "QEBSM eqbs partial",
168 "QEBSM sqbs",
169 "QEBSM sqbs partial"
172 static int qperf_show(struct seq_file *m, void *v)
174 struct qdio_irq *irq_ptr = m->private;
175 unsigned int *stat;
176 int i;
178 if (!irq_ptr)
179 return 0;
180 if (!irq_ptr->perf_stat_enabled) {
181 seq_printf(m, "disabled\n");
182 return 0;
184 stat = (unsigned int *)&irq_ptr->perf_stat;
186 for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
187 seq_printf(m, "%26s:\t%u\n",
188 qperf_names[i], *(stat + i));
189 return 0;
192 static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
193 size_t count, loff_t *off)
195 struct seq_file *seq = file->private_data;
196 struct qdio_irq *irq_ptr = seq->private;
197 struct qdio_q *q;
198 unsigned long val;
199 char buf[8];
200 int ret, i;
202 if (!irq_ptr)
203 return 0;
204 if (count >= sizeof(buf))
205 return -EINVAL;
206 if (copy_from_user(&buf, ubuf, count))
207 return -EFAULT;
208 buf[count] = 0;
210 ret = strict_strtoul(buf, 10, &val);
211 if (ret < 0)
212 return ret;
214 switch (val) {
215 case 0:
216 irq_ptr->perf_stat_enabled = 0;
217 memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
218 for_each_input_queue(irq_ptr, q, i)
219 memset(&q->q_stats, 0, sizeof(q->q_stats));
220 for_each_output_queue(irq_ptr, q, i)
221 memset(&q->q_stats, 0, sizeof(q->q_stats));
222 break;
223 case 1:
224 irq_ptr->perf_stat_enabled = 1;
225 break;
227 return count;
230 static int qperf_seq_open(struct inode *inode, struct file *filp)
232 return single_open(filp, qperf_show,
233 filp->f_path.dentry->d_inode->i_private);
236 static struct file_operations debugfs_perf_fops = {
237 .owner = THIS_MODULE,
238 .open = qperf_seq_open,
239 .read = seq_read,
240 .write = qperf_seq_write,
241 .llseek = seq_lseek,
242 .release = single_release,
244 static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
246 char name[QDIO_DEBUGFS_NAME_LEN];
248 snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
249 q->is_input_q ? "input" : "output",
250 q->nr);
251 q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
252 q->irq_ptr->debugfs_dev, q, &debugfs_fops);
253 if (IS_ERR(q->debugfs_q))
254 q->debugfs_q = NULL;
257 void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
259 struct qdio_q *q;
260 int i;
262 irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev),
263 debugfs_root);
264 if (IS_ERR(irq_ptr->debugfs_dev))
265 irq_ptr->debugfs_dev = NULL;
267 irq_ptr->debugfs_perf = debugfs_create_file("statistics",
268 S_IFREG | S_IRUGO | S_IWUSR,
269 irq_ptr->debugfs_dev, irq_ptr,
270 &debugfs_perf_fops);
271 if (IS_ERR(irq_ptr->debugfs_perf))
272 irq_ptr->debugfs_perf = NULL;
274 for_each_input_queue(irq_ptr, q, i)
275 setup_debugfs_entry(q, cdev);
276 for_each_output_queue(irq_ptr, q, i)
277 setup_debugfs_entry(q, cdev);
280 void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
282 struct qdio_q *q;
283 int i;
285 for_each_input_queue(irq_ptr, q, i)
286 debugfs_remove(q->debugfs_q);
287 for_each_output_queue(irq_ptr, q, i)
288 debugfs_remove(q->debugfs_q);
289 debugfs_remove(irq_ptr->debugfs_perf);
290 debugfs_remove(irq_ptr->debugfs_dev);
293 int __init qdio_debug_init(void)
295 debugfs_root = debugfs_create_dir("qdio", NULL);
297 qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
298 debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
299 debug_set_level(qdio_dbf_setup, DBF_INFO);
300 DBF_EVENT("dbf created\n");
302 qdio_dbf_error = debug_register("qdio_error", 4, 1, 16);
303 debug_register_view(qdio_dbf_error, &debug_hex_ascii_view);
304 debug_set_level(qdio_dbf_error, DBF_INFO);
305 DBF_ERROR("dbf created\n");
306 return 0;
309 void qdio_debug_exit(void)
311 debugfs_remove(debugfs_root);
312 if (qdio_dbf_setup)
313 debug_unregister(qdio_dbf_setup);
314 if (qdio_dbf_error)
315 debug_unregister(qdio_dbf_error);