Merge branches 'amd-iommu/fixes' and 'dma-debug/fixes' into iommu/fixes
[linux-2.6-block.git] / drivers / s390 / cio / qdio_debug.c
CommitLineData
779e6e1c
JG
1/*
2 * drivers/s390/cio/qdio_debug.c
3 *
3f09bb89 4 * Copyright IBM Corp. 2008,2009
779e6e1c
JG
5 *
6 * Author: Jan Glauber (jang@linux.vnet.ibm.com)
7 */
779e6e1c
JG
8#include <linux/seq_file.h>
9#include <linux/debugfs.h>
779e6e1c
JG
10#include <asm/debug.h>
11#include "qdio_debug.h"
12#include "qdio.h"
13
14debug_info_t *qdio_dbf_setup;
22f99347 15debug_info_t *qdio_dbf_error;
779e6e1c
JG
16
17static struct dentry *debugfs_root;
3f09bb89 18#define QDIO_DEBUGFS_NAME_LEN 10
779e6e1c 19
22f99347
JG
20void qdio_allocate_dbf(struct qdio_initialize *init_data,
21 struct qdio_irq *irq_ptr)
779e6e1c 22{
22f99347
JG
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->flags, sizeof(long));
37 DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *));
38 DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *));
39 DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
40
41 /* allocate trace view for the interface */
42 snprintf(text, 20, "qdio_%s", dev_name(&init_data->cdev->dev));
43 irq_ptr->debug_area = debug_register(text, 2, 1, 16);
44 debug_register_view(irq_ptr->debug_area, &debug_hex_ascii_view);
45 debug_set_level(irq_ptr->debug_area, DBF_WARN);
46 DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created");
779e6e1c
JG
47}
48
49static int qstat_show(struct seq_file *m, void *v)
50{
51 unsigned char state;
52 struct qdio_q *q = m->private;
53 int i;
54
55 if (!q)
56 return 0;
57
6486cda6
JG
58 seq_printf(m, "DSCI: %d nr_used: %d\n",
59 *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used));
60 seq_printf(m, "ftc: %d last_move: %d\n", q->first_to_check, q->last_move);
61 seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
62 q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count);
779e6e1c 63 seq_printf(m, "slsb buffer states:\n");
50f769df 64 seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
779e6e1c 65
779e6e1c 66 for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
60b5df2f 67 debug_get_buf_state(q, i, &state);
779e6e1c
JG
68 switch (state) {
69 case SLSB_P_INPUT_NOT_INIT:
70 case SLSB_P_OUTPUT_NOT_INIT:
71 seq_printf(m, "N");
72 break;
73 case SLSB_P_INPUT_PRIMED:
74 case SLSB_CU_OUTPUT_PRIMED:
75 seq_printf(m, "+");
76 break;
77 case SLSB_P_INPUT_ACK:
78 seq_printf(m, "A");
79 break;
80 case SLSB_P_INPUT_ERROR:
81 case SLSB_P_OUTPUT_ERROR:
82 seq_printf(m, "x");
83 break;
84 case SLSB_CU_INPUT_EMPTY:
85 case SLSB_P_OUTPUT_EMPTY:
86 seq_printf(m, "-");
87 break;
88 case SLSB_P_INPUT_HALTED:
89 case SLSB_P_OUTPUT_HALTED:
90 seq_printf(m, ".");
91 break;
92 default:
93 seq_printf(m, "?");
94 }
95 if (i == 63)
96 seq_printf(m, "\n");
97 }
98 seq_printf(m, "\n");
50f769df 99 seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\n");
779e6e1c
JG
100 return 0;
101}
102
103static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
104 size_t count, loff_t *off)
105{
106 struct seq_file *seq = file->private_data;
107 struct qdio_q *q = seq->private;
108
109 if (!q)
110 return 0;
779e6e1c
JG
111 if (q->is_input_q)
112 xchg(q->irq_ptr->dsci, 1);
113 local_bh_disable();
114 tasklet_schedule(&q->tasklet);
115 local_bh_enable();
116 return count;
117}
118
119static int qstat_seq_open(struct inode *inode, struct file *filp)
120{
121 return single_open(filp, qstat_show,
122 filp->f_path.dentry->d_inode->i_private);
123}
124
828c0950 125static const struct file_operations debugfs_fops = {
779e6e1c
JG
126 .owner = THIS_MODULE,
127 .open = qstat_seq_open,
128 .read = seq_read,
129 .write = qstat_seq_write,
130 .llseek = seq_lseek,
131 .release = single_release,
132};
133
6486cda6
JG
134static char *qperf_names[] = {
135 "Assumed adapter interrupts",
136 "QDIO interrupts",
137 "Requested PCIs",
138 "Inbound tasklet runs",
139 "Inbound tasklet resched",
140 "Inbound tasklet resched2",
141 "Outbound tasklet runs",
142 "SIGA read",
143 "SIGA write",
144 "SIGA sync",
145 "Inbound calls",
146 "Inbound handler",
147 "Inbound stop_polling",
148 "Inbound queue full",
149 "Outbound calls",
150 "Outbound handler",
151 "Outbound fast_requeue",
152 "Outbound target_full",
153 "QEBSM eqbs",
154 "QEBSM eqbs partial",
155 "QEBSM sqbs",
156 "QEBSM sqbs partial"
157};
158
159static int qperf_show(struct seq_file *m, void *v)
160{
161 struct qdio_irq *irq_ptr = m->private;
162 unsigned int *stat;
163 int i;
164
165 if (!irq_ptr)
166 return 0;
167 if (!irq_ptr->perf_stat_enabled) {
168 seq_printf(m, "disabled\n");
169 return 0;
170 }
171 stat = (unsigned int *)&irq_ptr->perf_stat;
172
173 for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
174 seq_printf(m, "%26s:\t%u\n",
175 qperf_names[i], *(stat + i));
176 return 0;
177}
178
179static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
180 size_t count, loff_t *off)
181{
182 struct seq_file *seq = file->private_data;
183 struct qdio_irq *irq_ptr = seq->private;
184 unsigned long val;
185 char buf[8];
186 int ret;
187
188 if (!irq_ptr)
189 return 0;
190 if (count >= sizeof(buf))
191 return -EINVAL;
192 if (copy_from_user(&buf, ubuf, count))
193 return -EFAULT;
194 buf[count] = 0;
195
196 ret = strict_strtoul(buf, 10, &val);
197 if (ret < 0)
198 return ret;
199
200 switch (val) {
201 case 0:
202 irq_ptr->perf_stat_enabled = 0;
203 memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
204 break;
205 case 1:
206 irq_ptr->perf_stat_enabled = 1;
207 break;
208 }
209 return count;
210}
211
212static int qperf_seq_open(struct inode *inode, struct file *filp)
213{
214 return single_open(filp, qperf_show,
215 filp->f_path.dentry->d_inode->i_private);
216}
217
218static struct file_operations debugfs_perf_fops = {
219 .owner = THIS_MODULE,
220 .open = qperf_seq_open,
221 .read = seq_read,
222 .write = qperf_seq_write,
223 .llseek = seq_lseek,
224 .release = single_release,
225};
779e6e1c
JG
226static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
227{
2c780914 228 char name[QDIO_DEBUGFS_NAME_LEN];
779e6e1c 229
3f09bb89 230 snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
2c780914
JG
231 q->is_input_q ? "input" : "output",
232 q->nr);
3f09bb89
JG
233 q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
234 q->irq_ptr->debugfs_dev, q, &debugfs_fops);
235 if (IS_ERR(q->debugfs_q))
236 q->debugfs_q = NULL;
779e6e1c
JG
237}
238
239void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
240{
241 struct qdio_q *q;
242 int i;
243
3f09bb89
JG
244 irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev),
245 debugfs_root);
246 if (IS_ERR(irq_ptr->debugfs_dev))
247 irq_ptr->debugfs_dev = NULL;
6486cda6
JG
248
249 irq_ptr->debugfs_perf = debugfs_create_file("statistics",
250 S_IFREG | S_IRUGO | S_IWUSR,
251 irq_ptr->debugfs_dev, irq_ptr,
252 &debugfs_perf_fops);
253 if (IS_ERR(irq_ptr->debugfs_perf))
254 irq_ptr->debugfs_perf = NULL;
255
779e6e1c
JG
256 for_each_input_queue(irq_ptr, q, i)
257 setup_debugfs_entry(q, cdev);
258 for_each_output_queue(irq_ptr, q, i)
259 setup_debugfs_entry(q, cdev);
779e6e1c
JG
260}
261
262void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
263{
264 struct qdio_q *q;
265 int i;
266
779e6e1c 267 for_each_input_queue(irq_ptr, q, i)
3f09bb89 268 debugfs_remove(q->debugfs_q);
779e6e1c 269 for_each_output_queue(irq_ptr, q, i)
3f09bb89 270 debugfs_remove(q->debugfs_q);
6486cda6 271 debugfs_remove(irq_ptr->debugfs_perf);
3f09bb89 272 debugfs_remove(irq_ptr->debugfs_dev);
779e6e1c
JG
273}
274
275int __init qdio_debug_init(void)
276{
3f09bb89 277 debugfs_root = debugfs_create_dir("qdio", NULL);
22f99347
JG
278
279 qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
280 debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
281 debug_set_level(qdio_dbf_setup, DBF_INFO);
282 DBF_EVENT("dbf created\n");
283
284 qdio_dbf_error = debug_register("qdio_error", 4, 1, 16);
285 debug_register_view(qdio_dbf_error, &debug_hex_ascii_view);
286 debug_set_level(qdio_dbf_error, DBF_INFO);
287 DBF_ERROR("dbf created\n");
288 return 0;
779e6e1c
JG
289}
290
291void qdio_debug_exit(void)
292{
293 debugfs_remove(debugfs_root);
22f99347
JG
294 if (qdio_dbf_setup)
295 debug_unregister(qdio_dbf_setup);
296 if (qdio_dbf_error)
297 debug_unregister(qdio_dbf_error);
779e6e1c 298}