Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / s390 / cio / qdio_debug.c
1 /*
2  *  Copyright IBM Corp. 2008, 2009
3  *
4  *  Author: Jan Glauber (jang@linux.vnet.ibm.com)
5  */
6 #include <linux/seq_file.h>
7 #include <linux/debugfs.h>
8 #include <linux/uaccess.h>
9 #include <linux/export.h>
10 #include <linux/slab.h>
11 #include <asm/debug.h>
12 #include "qdio_debug.h"
13 #include "qdio.h"
14
15 debug_info_t *qdio_dbf_setup;
16 debug_info_t *qdio_dbf_error;
17
18 static struct dentry *debugfs_root;
19 #define QDIO_DEBUGFS_NAME_LEN   10
20 #define QDIO_DBF_NAME_LEN       20
21
22 struct qdio_dbf_entry {
23         char dbf_name[QDIO_DBF_NAME_LEN];
24         debug_info_t *dbf_info;
25         struct list_head dbf_list;
26 };
27
28 static LIST_HEAD(qdio_dbf_list);
29 static DEFINE_MUTEX(qdio_dbf_list_mutex);
30
31 static debug_info_t *qdio_get_dbf_entry(char *name)
32 {
33         struct qdio_dbf_entry *entry;
34         debug_info_t *rc = NULL;
35
36         mutex_lock(&qdio_dbf_list_mutex);
37         list_for_each_entry(entry, &qdio_dbf_list, dbf_list) {
38                 if (strcmp(entry->dbf_name, name) == 0) {
39                         rc = entry->dbf_info;
40                         break;
41                 }
42         }
43         mutex_unlock(&qdio_dbf_list_mutex);
44         return rc;
45 }
46
47 static void qdio_clear_dbf_list(void)
48 {
49         struct qdio_dbf_entry *entry, *tmp;
50
51         mutex_lock(&qdio_dbf_list_mutex);
52         list_for_each_entry_safe(entry, tmp, &qdio_dbf_list, dbf_list) {
53                 list_del(&entry->dbf_list);
54                 debug_unregister(entry->dbf_info);
55                 kfree(entry);
56         }
57         mutex_unlock(&qdio_dbf_list_mutex);
58 }
59
60 int qdio_allocate_dbf(struct qdio_initialize *init_data,
61                        struct qdio_irq *irq_ptr)
62 {
63         char text[QDIO_DBF_NAME_LEN];
64         struct qdio_dbf_entry *new_entry;
65
66         DBF_EVENT("qfmt:%1d", init_data->q_format);
67         DBF_HEX(init_data->adapter_name, 8);
68         DBF_EVENT("qpff%4x", init_data->qib_param_field_format);
69         DBF_HEX(&init_data->qib_param_field, sizeof(void *));
70         DBF_HEX(&init_data->input_slib_elements, sizeof(void *));
71         DBF_HEX(&init_data->output_slib_elements, sizeof(void *));
72         DBF_EVENT("niq:%1d noq:%1d", init_data->no_input_qs,
73                   init_data->no_output_qs);
74         DBF_HEX(&init_data->input_handler, sizeof(void *));
75         DBF_HEX(&init_data->output_handler, sizeof(void *));
76         DBF_HEX(&init_data->int_parm, sizeof(long));
77         DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *));
78         DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *));
79         DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
80
81         /* allocate trace view for the interface */
82         snprintf(text, QDIO_DBF_NAME_LEN, "qdio_%s",
83                                         dev_name(&init_data->cdev->dev));
84         irq_ptr->debug_area = qdio_get_dbf_entry(text);
85         if (irq_ptr->debug_area)
86                 DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf reused");
87         else {
88                 irq_ptr->debug_area = debug_register(text, 2, 1, 16);
89                 if (!irq_ptr->debug_area)
90                         return -ENOMEM;
91                 if (debug_register_view(irq_ptr->debug_area,
92                                                 &debug_hex_ascii_view)) {
93                         debug_unregister(irq_ptr->debug_area);
94                         return -ENOMEM;
95                 }
96                 debug_set_level(irq_ptr->debug_area, DBF_WARN);
97                 DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created");
98                 new_entry = kzalloc(sizeof(struct qdio_dbf_entry), GFP_KERNEL);
99                 if (!new_entry) {
100                         debug_unregister(irq_ptr->debug_area);
101                         return -ENOMEM;
102                 }
103                 strlcpy(new_entry->dbf_name, text, QDIO_DBF_NAME_LEN);
104                 new_entry->dbf_info = irq_ptr->debug_area;
105                 mutex_lock(&qdio_dbf_list_mutex);
106                 list_add(&new_entry->dbf_list, &qdio_dbf_list);
107                 mutex_unlock(&qdio_dbf_list_mutex);
108         }
109         return 0;
110 }
111
112 static int qstat_show(struct seq_file *m, void *v)
113 {
114         unsigned char state;
115         struct qdio_q *q = m->private;
116         int i;
117
118         if (!q)
119                 return 0;
120
121         seq_printf(m, "Timestamp: %Lx  Last AI: %Lx\n",
122                    q->timestamp, last_ai_time);
123         seq_printf(m, "nr_used: %d  ftc: %d  last_move: %d\n",
124                    atomic_read(&q->nr_buf_used),
125                    q->first_to_check, q->last_move);
126         if (q->is_input_q) {
127                 seq_printf(m, "polling: %d  ack start: %d  ack count: %d\n",
128                            q->u.in.polling, q->u.in.ack_start,
129                            q->u.in.ack_count);
130                 seq_printf(m, "DSCI: %d   IRQs disabled: %u\n",
131                            *(u32 *)q->irq_ptr->dsci,
132                            test_bit(QDIO_QUEUE_IRQS_DISABLED,
133                            &q->u.in.queue_irq_state));
134         }
135         seq_printf(m, "SBAL states:\n");
136         seq_printf(m, "|0      |8      |16     |24     |32     |40     |48     |56  63|\n");
137
138         for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
139                 debug_get_buf_state(q, i, &state);
140                 switch (state) {
141                 case SLSB_P_INPUT_NOT_INIT:
142                 case SLSB_P_OUTPUT_NOT_INIT:
143                         seq_printf(m, "N");
144                         break;
145                 case SLSB_P_OUTPUT_PENDING:
146                         seq_printf(m, "P");
147                         break;
148                 case SLSB_P_INPUT_PRIMED:
149                 case SLSB_CU_OUTPUT_PRIMED:
150                         seq_printf(m, "+");
151                         break;
152                 case SLSB_P_INPUT_ACK:
153                         seq_printf(m, "A");
154                         break;
155                 case SLSB_P_INPUT_ERROR:
156                 case SLSB_P_OUTPUT_ERROR:
157                         seq_printf(m, "x");
158                         break;
159                 case SLSB_CU_INPUT_EMPTY:
160                 case SLSB_P_OUTPUT_EMPTY:
161                         seq_printf(m, "-");
162                         break;
163                 case SLSB_P_INPUT_HALTED:
164                 case SLSB_P_OUTPUT_HALTED:
165                         seq_printf(m, ".");
166                         break;
167                 default:
168                         seq_printf(m, "?");
169                 }
170                 if (i == 63)
171                         seq_printf(m, "\n");
172         }
173         seq_printf(m, "\n");
174         seq_printf(m, "|64     |72     |80     |88     |96     |104    |112    |   127|\n");
175
176         seq_printf(m, "\nSBAL statistics:");
177         if (!q->irq_ptr->perf_stat_enabled) {
178                 seq_printf(m, " disabled\n");
179                 return 0;
180         }
181
182         seq_printf(m, "\n1          2..        4..        8..        "
183                    "16..       32..       64..       127\n");
184         for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++)
185                 seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]);
186         seq_printf(m, "\nError      NOP        Total\n%-10u %-10u %-10u\n\n",
187                    q->q_stats.nr_sbal_error, q->q_stats.nr_sbal_nop,
188                    q->q_stats.nr_sbal_total);
189         return 0;
190 }
191
192 static int qstat_seq_open(struct inode *inode, struct file *filp)
193 {
194         return single_open(filp, qstat_show,
195                            file_inode(filp)->i_private);
196 }
197
198 static const struct file_operations debugfs_fops = {
199         .owner   = THIS_MODULE,
200         .open    = qstat_seq_open,
201         .read    = seq_read,
202         .llseek  = seq_lseek,
203         .release = single_release,
204 };
205
206 static char *qperf_names[] = {
207         "Assumed adapter interrupts",
208         "QDIO interrupts",
209         "Requested PCIs",
210         "Inbound tasklet runs",
211         "Inbound tasklet resched",
212         "Inbound tasklet resched2",
213         "Outbound tasklet runs",
214         "SIGA read",
215         "SIGA write",
216         "SIGA sync",
217         "Inbound calls",
218         "Inbound handler",
219         "Inbound stop_polling",
220         "Inbound queue full",
221         "Outbound calls",
222         "Outbound handler",
223         "Outbound queue full",
224         "Outbound fast_requeue",
225         "Outbound target_full",
226         "QEBSM eqbs",
227         "QEBSM eqbs partial",
228         "QEBSM sqbs",
229         "QEBSM sqbs partial",
230         "Discarded interrupts"
231 };
232
233 static int qperf_show(struct seq_file *m, void *v)
234 {
235         struct qdio_irq *irq_ptr = m->private;
236         unsigned int *stat;
237         int i;
238
239         if (!irq_ptr)
240                 return 0;
241         if (!irq_ptr->perf_stat_enabled) {
242                 seq_printf(m, "disabled\n");
243                 return 0;
244         }
245         stat = (unsigned int *)&irq_ptr->perf_stat;
246
247         for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
248                 seq_printf(m, "%26s:\t%u\n",
249                            qperf_names[i], *(stat + i));
250         return 0;
251 }
252
253 static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
254                                size_t count, loff_t *off)
255 {
256         struct seq_file *seq = file->private_data;
257         struct qdio_irq *irq_ptr = seq->private;
258         struct qdio_q *q;
259         unsigned long val;
260         int ret, i;
261
262         if (!irq_ptr)
263                 return 0;
264
265         ret = kstrtoul_from_user(ubuf, count, 10, &val);
266         if (ret)
267                 return ret;
268
269         switch (val) {
270         case 0:
271                 irq_ptr->perf_stat_enabled = 0;
272                 memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
273                 for_each_input_queue(irq_ptr, q, i)
274                         memset(&q->q_stats, 0, sizeof(q->q_stats));
275                 for_each_output_queue(irq_ptr, q, i)
276                         memset(&q->q_stats, 0, sizeof(q->q_stats));
277                 break;
278         case 1:
279                 irq_ptr->perf_stat_enabled = 1;
280                 break;
281         }
282         return count;
283 }
284
285 static int qperf_seq_open(struct inode *inode, struct file *filp)
286 {
287         return single_open(filp, qperf_show,
288                            file_inode(filp)->i_private);
289 }
290
291 static const struct file_operations debugfs_perf_fops = {
292         .owner   = THIS_MODULE,
293         .open    = qperf_seq_open,
294         .read    = seq_read,
295         .write   = qperf_seq_write,
296         .llseek  = seq_lseek,
297         .release = single_release,
298 };
299
300 static void setup_debugfs_entry(struct qdio_q *q)
301 {
302         char name[QDIO_DEBUGFS_NAME_LEN];
303
304         snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
305                  q->is_input_q ? "input" : "output",
306                  q->nr);
307         q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
308                                 q->irq_ptr->debugfs_dev, q, &debugfs_fops);
309         if (IS_ERR(q->debugfs_q))
310                 q->debugfs_q = NULL;
311 }
312
313 void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
314 {
315         struct qdio_q *q;
316         int i;
317
318         irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev),
319                                                   debugfs_root);
320         if (IS_ERR(irq_ptr->debugfs_dev))
321                 irq_ptr->debugfs_dev = NULL;
322
323         irq_ptr->debugfs_perf = debugfs_create_file("statistics",
324                                 S_IFREG | S_IRUGO | S_IWUSR,
325                                 irq_ptr->debugfs_dev, irq_ptr,
326                                 &debugfs_perf_fops);
327         if (IS_ERR(irq_ptr->debugfs_perf))
328                 irq_ptr->debugfs_perf = NULL;
329
330         for_each_input_queue(irq_ptr, q, i)
331                 setup_debugfs_entry(q);
332         for_each_output_queue(irq_ptr, q, i)
333                 setup_debugfs_entry(q);
334 }
335
336 void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr)
337 {
338         struct qdio_q *q;
339         int i;
340
341         for_each_input_queue(irq_ptr, q, i)
342                 debugfs_remove(q->debugfs_q);
343         for_each_output_queue(irq_ptr, q, i)
344                 debugfs_remove(q->debugfs_q);
345         debugfs_remove(irq_ptr->debugfs_perf);
346         debugfs_remove(irq_ptr->debugfs_dev);
347 }
348
349 int __init qdio_debug_init(void)
350 {
351         debugfs_root = debugfs_create_dir("qdio", NULL);
352
353         qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
354         debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
355         debug_set_level(qdio_dbf_setup, DBF_INFO);
356         DBF_EVENT("dbf created\n");
357
358         qdio_dbf_error = debug_register("qdio_error", 4, 1, 16);
359         debug_register_view(qdio_dbf_error, &debug_hex_ascii_view);
360         debug_set_level(qdio_dbf_error, DBF_INFO);
361         DBF_ERROR("dbf created\n");
362         return 0;
363 }
364
365 void qdio_debug_exit(void)
366 {
367         qdio_clear_dbf_list();
368         debugfs_remove(debugfs_root);
369         if (qdio_dbf_setup)
370                 debug_unregister(qdio_dbf_setup);
371         if (qdio_dbf_error)
372                 debug_unregister(qdio_dbf_error);
373 }