]> rtime.felk.cvut.cz Git - mcf548x/linux.git/blob - drivers/s390/cio/qdio_debug.c
Initial 2.6.37
[mcf548x/linux.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_INPUT_PRIMED:
80                 case SLSB_CU_OUTPUT_PRIMED:
81                         seq_printf(m, "+");
82                         break;
83                 case SLSB_P_INPUT_ACK:
84                         seq_printf(m, "A");
85                         break;
86                 case SLSB_P_INPUT_ERROR:
87                 case SLSB_P_OUTPUT_ERROR:
88                         seq_printf(m, "x");
89                         break;
90                 case SLSB_CU_INPUT_EMPTY:
91                 case SLSB_P_OUTPUT_EMPTY:
92                         seq_printf(m, "-");
93                         break;
94                 case SLSB_P_INPUT_HALTED:
95                 case SLSB_P_OUTPUT_HALTED:
96                         seq_printf(m, ".");
97                         break;
98                 default:
99                         seq_printf(m, "?");
100                 }
101                 if (i == 63)
102                         seq_printf(m, "\n");
103         }
104         seq_printf(m, "\n");
105         seq_printf(m, "|64     |72     |80     |88     |96     |104    |112    |   127|\n");
106
107         seq_printf(m, "\nSBAL statistics:");
108         if (!q->irq_ptr->perf_stat_enabled) {
109                 seq_printf(m, " disabled\n");
110                 return 0;
111         }
112
113         seq_printf(m, "\n1          2..        4..        8..        "
114                    "16..       32..       64..       127\n");
115         for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++)
116                 seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]);
117         seq_printf(m, "\nError      NOP        Total\n%-10u %-10u %-10u\n\n",
118                    q->q_stats.nr_sbal_error, q->q_stats.nr_sbal_nop,
119                    q->q_stats.nr_sbal_total);
120         return 0;
121 }
122
123 static int qstat_seq_open(struct inode *inode, struct file *filp)
124 {
125         return single_open(filp, qstat_show,
126                            filp->f_path.dentry->d_inode->i_private);
127 }
128
129 static const struct file_operations debugfs_fops = {
130         .owner   = THIS_MODULE,
131         .open    = qstat_seq_open,
132         .read    = seq_read,
133         .llseek  = seq_lseek,
134         .release = single_release,
135 };
136
137 static char *qperf_names[] = {
138         "Assumed adapter interrupts",
139         "QDIO interrupts",
140         "Requested PCIs",
141         "Inbound tasklet runs",
142         "Inbound tasklet resched",
143         "Inbound tasklet resched2",
144         "Outbound tasklet runs",
145         "SIGA read",
146         "SIGA write",
147         "SIGA sync",
148         "Inbound calls",
149         "Inbound handler",
150         "Inbound stop_polling",
151         "Inbound queue full",
152         "Outbound calls",
153         "Outbound handler",
154         "Outbound fast_requeue",
155         "Outbound target_full",
156         "QEBSM eqbs",
157         "QEBSM eqbs partial",
158         "QEBSM sqbs",
159         "QEBSM sqbs partial",
160         "Discarded interrupts"
161 };
162
163 static int qperf_show(struct seq_file *m, void *v)
164 {
165         struct qdio_irq *irq_ptr = m->private;
166         unsigned int *stat;
167         int i;
168
169         if (!irq_ptr)
170                 return 0;
171         if (!irq_ptr->perf_stat_enabled) {
172                 seq_printf(m, "disabled\n");
173                 return 0;
174         }
175         stat = (unsigned int *)&irq_ptr->perf_stat;
176
177         for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
178                 seq_printf(m, "%26s:\t%u\n",
179                            qperf_names[i], *(stat + i));
180         return 0;
181 }
182
183 static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
184                                size_t count, loff_t *off)
185 {
186         struct seq_file *seq = file->private_data;
187         struct qdio_irq *irq_ptr = seq->private;
188         struct qdio_q *q;
189         unsigned long val;
190         char buf[8];
191         int ret, i;
192
193         if (!irq_ptr)
194                 return 0;
195         if (count >= sizeof(buf))
196                 return -EINVAL;
197         if (copy_from_user(&buf, ubuf, count))
198                 return -EFAULT;
199         buf[count] = 0;
200
201         ret = strict_strtoul(buf, 10, &val);
202         if (ret < 0)
203                 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));
209                 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));
213                 break;
214         case 1:
215                 irq_ptr->perf_stat_enabled = 1;
216                 break;
217         }
218         return count;
219 }
220
221 static int qperf_seq_open(struct inode *inode, struct file *filp)
222 {
223         return single_open(filp, qperf_show,
224                            filp->f_path.dentry->d_inode->i_private);
225 }
226
227 static struct file_operations debugfs_perf_fops = {
228         .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 };
235 static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
236 {
237         char name[QDIO_DEBUGFS_NAME_LEN];
238
239         snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
240                  q->is_input_q ? "input" : "output",
241                  q->nr);
242         q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
243                                 q->irq_ptr->debugfs_dev, q, &debugfs_fops);
244         if (IS_ERR(q->debugfs_q))
245                 q->debugfs_q = NULL;
246 }
247
248 void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
249 {
250         struct qdio_q *q;
251         int i;
252
253         irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev),
254                                                   debugfs_root);
255         if (IS_ERR(irq_ptr->debugfs_dev))
256                 irq_ptr->debugfs_dev = NULL;
257
258         irq_ptr->debugfs_perf = debugfs_create_file("statistics",
259                                 S_IFREG | S_IRUGO | S_IWUSR,
260                                 irq_ptr->debugfs_dev, irq_ptr,
261                                 &debugfs_perf_fops);
262         if (IS_ERR(irq_ptr->debugfs_perf))
263                 irq_ptr->debugfs_perf = NULL;
264
265         for_each_input_queue(irq_ptr, q, i)
266                 setup_debugfs_entry(q, cdev);
267         for_each_output_queue(irq_ptr, q, i)
268                 setup_debugfs_entry(q, cdev);
269 }
270
271 void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
272 {
273         struct qdio_q *q;
274         int i;
275
276         for_each_input_queue(irq_ptr, q, i)
277                 debugfs_remove(q->debugfs_q);
278         for_each_output_queue(irq_ptr, q, i)
279                 debugfs_remove(q->debugfs_q);
280         debugfs_remove(irq_ptr->debugfs_perf);
281         debugfs_remove(irq_ptr->debugfs_dev);
282 }
283
284 int __init qdio_debug_init(void)
285 {
286         debugfs_root = debugfs_create_dir("qdio", NULL);
287
288         qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
289         debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
290         debug_set_level(qdio_dbf_setup, DBF_INFO);
291         DBF_EVENT("dbf created\n");
292
293         qdio_dbf_error = debug_register("qdio_error", 4, 1, 16);
294         debug_register_view(qdio_dbf_error, &debug_hex_ascii_view);
295         debug_set_level(qdio_dbf_error, DBF_INFO);
296         DBF_ERROR("dbf created\n");
297         return 0;
298 }
299
300 void qdio_debug_exit(void)
301 {
302         debugfs_remove(debugfs_root);
303         if (qdio_dbf_setup)
304                 debug_unregister(qdio_dbf_setup);
305         if (qdio_dbf_error)
306                 debug_unregister(qdio_dbf_error);
307 }