]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/s390/cio/qdio_debug.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[net-next-2.6.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));
22f99347
JG
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");
779e6e1c
JG
46}
47
48static 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
6486cda6
JG
57 seq_printf(m, "DSCI: %d nr_used: %d\n",
58 *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used));
d36deae7
JG
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 }
d307297f 69 seq_printf(m, "SBAL states:\n");
50f769df 70 seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
779e6e1c 71
779e6e1c 72 for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
60b5df2f 73 debug_get_buf_state(q, i, &state);
779e6e1c
JG
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");
50f769df 105 seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\n");
d307297f
JG
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);
779e6e1c
JG
120 return 0;
121}
122
779e6e1c
JG
123static 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
828c0950 129static const struct file_operations debugfs_fops = {
779e6e1c
JG
130 .owner = THIS_MODULE,
131 .open = qstat_seq_open,
132 .read = seq_read,
779e6e1c
JG
133 .llseek = seq_lseek,
134 .release = single_release,
135};
136
6486cda6
JG
137static 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",
d36deae7
JG
159 "QEBSM sqbs partial",
160 "Discarded interrupts"
6486cda6
JG
161};
162
163static 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
183static 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;
d307297f 188 struct qdio_q *q;
6486cda6
JG
189 unsigned long val;
190 char buf[8];
d307297f 191 int ret, i;
6486cda6
JG
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));
d307297f
JG
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));
6486cda6
JG
213 break;
214 case 1:
215 irq_ptr->perf_stat_enabled = 1;
216 break;
217 }
218 return count;
219}
220
221static 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
227static 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};
779e6e1c
JG
235static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
236{
2c780914 237 char name[QDIO_DEBUGFS_NAME_LEN];
779e6e1c 238
3f09bb89 239 snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
2c780914
JG
240 q->is_input_q ? "input" : "output",
241 q->nr);
3f09bb89
JG
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;
779e6e1c
JG
246}
247
248void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
249{
250 struct qdio_q *q;
251 int i;
252
3f09bb89
JG
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;
6486cda6
JG
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
779e6e1c
JG
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);
779e6e1c
JG
269}
270
271void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
272{
273 struct qdio_q *q;
274 int i;
275
779e6e1c 276 for_each_input_queue(irq_ptr, q, i)
3f09bb89 277 debugfs_remove(q->debugfs_q);
779e6e1c 278 for_each_output_queue(irq_ptr, q, i)
3f09bb89 279 debugfs_remove(q->debugfs_q);
6486cda6 280 debugfs_remove(irq_ptr->debugfs_perf);
3f09bb89 281 debugfs_remove(irq_ptr->debugfs_dev);
779e6e1c
JG
282}
283
284int __init qdio_debug_init(void)
285{
3f09bb89 286 debugfs_root = debugfs_create_dir("qdio", NULL);
22f99347
JG
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;
779e6e1c
JG
298}
299
300void qdio_debug_exit(void)
301{
302 debugfs_remove(debugfs_root);
22f99347
JG
303 if (qdio_dbf_setup)
304 debug_unregister(qdio_dbf_setup);
305 if (qdio_dbf_error)
306 debug_unregister(qdio_dbf_error);
779e6e1c 307}