qdio: support asynchronous delivery of storage blocks
[pandora-kernel.git] / drivers / s390 / cio / qdio_debug.c
1 /*
2  *  drivers/s390/cio/qdio_debug.c
3  *
4  *  Copyright IBM Corp. 2008,2009
5  *
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"
13
14 debug_info_t *qdio_dbf_setup;
15 debug_info_t *qdio_dbf_error;
16
17 static struct dentry *debugfs_root;
18 #define QDIO_DEBUGFS_NAME_LEN   10
19
20 void qdio_allocate_dbf(struct qdio_initialize *init_data,
21                        struct qdio_irq *irq_ptr)
22 {
23         char text[20];
24
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);
39
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");
46 }
47
48 static 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
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",
60                    q->first_to_check, q->last_move);
61         if (q->is_input_q) {
62                 seq_printf(m, "polling: %d  ack start: %d  ack count: %d\n",
63                            q->u.in.polling, q->u.in.ack_start,
64                            q->u.in.ack_count);
65                 seq_printf(m, "IRQs disabled: %u\n",
66                            test_bit(QDIO_QUEUE_IRQS_DISABLED,
67                            &q->u.in.queue_irq_state));
68         }
69         seq_printf(m, "SBAL states:\n");
70         seq_printf(m, "|0      |8      |16     |24     |32     |40     |48     |56  63|\n");
71
72         for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
73                 debug_get_buf_state(q, i, &state);
74                 switch (state) {
75                 case SLSB_P_INPUT_NOT_INIT:
76                 case SLSB_P_OUTPUT_NOT_INIT:
77                         seq_printf(m, "N");
78                         break;
79                 case SLSB_P_OUTPUT_PENDING:
80                         seq_printf(m, "P");
81                         break;
82                 case SLSB_P_INPUT_PRIMED:
83                 case SLSB_CU_OUTPUT_PRIMED:
84                         seq_printf(m, "+");
85                         break;
86                 case SLSB_P_INPUT_ACK:
87                         seq_printf(m, "A");
88                         break;
89                 case SLSB_P_INPUT_ERROR:
90                 case SLSB_P_OUTPUT_ERROR:
91                         seq_printf(m, "x");
92                         break;
93                 case SLSB_CU_INPUT_EMPTY:
94                 case SLSB_P_OUTPUT_EMPTY:
95                         seq_printf(m, "-");
96                         break;
97                 case SLSB_P_INPUT_HALTED:
98                 case SLSB_P_OUTPUT_HALTED:
99                         seq_printf(m, ".");
100                         break;
101                 default:
102                         seq_printf(m, "?");
103                 }
104                 if (i == 63)
105                         seq_printf(m, "\n");
106         }
107         seq_printf(m, "\n");
108         seq_printf(m, "|64     |72     |80     |88     |96     |104    |112    |   127|\n");
109
110         seq_printf(m, "\nSBAL statistics:");
111         if (!q->irq_ptr->perf_stat_enabled) {
112                 seq_printf(m, " disabled\n");
113                 return 0;
114         }
115
116         seq_printf(m, "\n1          2..        4..        8..        "
117                    "16..       32..       64..       127\n");
118         for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++)
119                 seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]);
120         seq_printf(m, "\nError      NOP        Total\n%-10u %-10u %-10u\n\n",
121                    q->q_stats.nr_sbal_error, q->q_stats.nr_sbal_nop,
122                    q->q_stats.nr_sbal_total);
123         return 0;
124 }
125
126 static int qstat_seq_open(struct inode *inode, struct file *filp)
127 {
128         return single_open(filp, qstat_show,
129                            filp->f_path.dentry->d_inode->i_private);
130 }
131
132 static const struct file_operations debugfs_fops = {
133         .owner   = THIS_MODULE,
134         .open    = qstat_seq_open,
135         .read    = seq_read,
136         .llseek  = seq_lseek,
137         .release = single_release,
138 };
139
140 static char *qperf_names[] = {
141         "Assumed adapter interrupts",
142         "QDIO interrupts",
143         "Requested PCIs",
144         "Inbound tasklet runs",
145         "Inbound tasklet resched",
146         "Inbound tasklet resched2",
147         "Outbound tasklet runs",
148         "SIGA read",
149         "SIGA write",
150         "SIGA sync",
151         "Inbound calls",
152         "Inbound handler",
153         "Inbound stop_polling",
154         "Inbound queue full",
155         "Outbound calls",
156         "Outbound handler",
157         "Outbound queue full",
158         "Outbound fast_requeue",
159         "Outbound target_full",
160         "QEBSM eqbs",
161         "QEBSM eqbs partial",
162         "QEBSM sqbs",
163         "QEBSM sqbs partial",
164         "Discarded interrupts"
165 };
166
167 static int qperf_show(struct seq_file *m, void *v)
168 {
169         struct qdio_irq *irq_ptr = m->private;
170         unsigned int *stat;
171         int i;
172
173         if (!irq_ptr)
174                 return 0;
175         if (!irq_ptr->perf_stat_enabled) {
176                 seq_printf(m, "disabled\n");
177                 return 0;
178         }
179         stat = (unsigned int *)&irq_ptr->perf_stat;
180
181         for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
182                 seq_printf(m, "%26s:\t%u\n",
183                            qperf_names[i], *(stat + i));
184         return 0;
185 }
186
187 static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
188                                size_t count, loff_t *off)
189 {
190         struct seq_file *seq = file->private_data;
191         struct qdio_irq *irq_ptr = seq->private;
192         struct qdio_q *q;
193         unsigned long val;
194         int ret, i;
195
196         if (!irq_ptr)
197                 return 0;
198
199         ret = kstrtoul_from_user(ubuf, count, 10, &val);
200         if (ret)
201                 return ret;
202
203         switch (val) {
204         case 0:
205                 irq_ptr->perf_stat_enabled = 0;
206                 memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
207                 for_each_input_queue(irq_ptr, q, i)
208                         memset(&q->q_stats, 0, sizeof(q->q_stats));
209                 for_each_output_queue(irq_ptr, q, i)
210                         memset(&q->q_stats, 0, sizeof(q->q_stats));
211                 break;
212         case 1:
213                 irq_ptr->perf_stat_enabled = 1;
214                 break;
215         }
216         return count;
217 }
218
219 static int qperf_seq_open(struct inode *inode, struct file *filp)
220 {
221         return single_open(filp, qperf_show,
222                            filp->f_path.dentry->d_inode->i_private);
223 }
224
225 static struct file_operations debugfs_perf_fops = {
226         .owner   = THIS_MODULE,
227         .open    = qperf_seq_open,
228         .read    = seq_read,
229         .write   = qperf_seq_write,
230         .llseek  = seq_lseek,
231         .release = single_release,
232 };
233 static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
234 {
235         char name[QDIO_DEBUGFS_NAME_LEN];
236
237         snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
238                  q->is_input_q ? "input" : "output",
239                  q->nr);
240         q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
241                                 q->irq_ptr->debugfs_dev, q, &debugfs_fops);
242         if (IS_ERR(q->debugfs_q))
243                 q->debugfs_q = NULL;
244 }
245
246 void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
247 {
248         struct qdio_q *q;
249         int i;
250
251         irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev),
252                                                   debugfs_root);
253         if (IS_ERR(irq_ptr->debugfs_dev))
254                 irq_ptr->debugfs_dev = NULL;
255
256         irq_ptr->debugfs_perf = debugfs_create_file("statistics",
257                                 S_IFREG | S_IRUGO | S_IWUSR,
258                                 irq_ptr->debugfs_dev, irq_ptr,
259                                 &debugfs_perf_fops);
260         if (IS_ERR(irq_ptr->debugfs_perf))
261                 irq_ptr->debugfs_perf = NULL;
262
263         for_each_input_queue(irq_ptr, q, i)
264                 setup_debugfs_entry(q, cdev);
265         for_each_output_queue(irq_ptr, q, i)
266                 setup_debugfs_entry(q, cdev);
267 }
268
269 void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
270 {
271         struct qdio_q *q;
272         int i;
273
274         for_each_input_queue(irq_ptr, q, i)
275                 debugfs_remove(q->debugfs_q);
276         for_each_output_queue(irq_ptr, q, i)
277                 debugfs_remove(q->debugfs_q);
278         debugfs_remove(irq_ptr->debugfs_perf);
279         debugfs_remove(irq_ptr->debugfs_dev);
280 }
281
282 int __init qdio_debug_init(void)
283 {
284         debugfs_root = debugfs_create_dir("qdio", NULL);
285
286         qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
287         debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
288         debug_set_level(qdio_dbf_setup, DBF_INFO);
289         DBF_EVENT("dbf created\n");
290
291         qdio_dbf_error = debug_register("qdio_error", 4, 1, 16);
292         debug_register_view(qdio_dbf_error, &debug_hex_ascii_view);
293         debug_set_level(qdio_dbf_error, DBF_INFO);
294         DBF_ERROR("dbf created\n");
295         return 0;
296 }
297
298 void qdio_debug_exit(void)
299 {
300         debugfs_remove(debugfs_root);
301         if (qdio_dbf_setup)
302                 debug_unregister(qdio_dbf_setup);
303         if (qdio_dbf_error)
304                 debug_unregister(qdio_dbf_error);
305 }