mm: fix page table unmap for stack guard page properly
[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", 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");
64
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, "?");
93                 }
94                 if (i == 63)
95                         seq_printf(m, "\n");
96         }
97         seq_printf(m, "\n");
98         seq_printf(m, "|64     |72     |80     |88     |96     |104    |112    |   127|\n");
99
100         seq_printf(m, "\nSBAL statistics:");
101         if (!q->irq_ptr->perf_stat_enabled) {
102                 seq_printf(m, " disabled\n");
103                 return 0;
104         }
105
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;
114 }
115
116 static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
117                                size_t count, loff_t *off)
118 {
119         struct seq_file *seq = file->private_data;
120         struct qdio_q *q = seq->private;
121
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;
130 }
131
132 static int qstat_seq_open(struct inode *inode, struct file *filp)
133 {
134         return single_open(filp, qstat_show,
135                            filp->f_path.dentry->d_inode->i_private);
136 }
137
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,
145 };
146
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"
170 };
171
172 static int qperf_show(struct seq_file *m, void *v)
173 {
174         struct qdio_irq *irq_ptr = m->private;
175         unsigned int *stat;
176         int i;
177
178         if (!irq_ptr)
179                 return 0;
180         if (!irq_ptr->perf_stat_enabled) {
181                 seq_printf(m, "disabled\n");
182                 return 0;
183         }
184         stat = (unsigned int *)&irq_ptr->perf_stat;
185
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;
190 }
191
192 static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
193                                size_t count, loff_t *off)
194 {
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;
201
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;
209
210         ret = strict_strtoul(buf, 10, &val);
211         if (ret < 0)
212                 return ret;
213
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;
226         }
227         return count;
228 }
229
230 static int qperf_seq_open(struct inode *inode, struct file *filp)
231 {
232         return single_open(filp, qperf_show,
233                            filp->f_path.dentry->d_inode->i_private);
234 }
235
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,
243 };
244 static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
245 {
246         char name[QDIO_DEBUGFS_NAME_LEN];
247
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;
255 }
256
257 void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
258 {
259         struct qdio_q *q;
260         int i;
261
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;
266
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;
273
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);
278 }
279
280 void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
281 {
282         struct qdio_q *q;
283         int i;
284
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);
291 }
292
293 int __init qdio_debug_init(void)
294 {
295         debugfs_root = debugfs_create_dir("qdio", NULL);
296
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");
301
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;
307 }
308
309 void qdio_debug_exit(void)
310 {
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);
316 }