Merge branch 'modsplit-Oct31_2011' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / s390 / cio / qdio_debug.c
blob29021f4e96b6409bc5dffc12b9717871a652bb49
1 /*
2 * drivers/s390/cio/qdio_debug.c
4 * Copyright IBM Corp. 2008,2009
6 * Author: Jan Glauber (jang@linux.vnet.ibm.com)
7 */
8 #include <linux/seq_file.h>
9 #include <linux/debugfs.h>
10 #include <linux/uaccess.h>
11 #include <linux/export.h>
12 #include <asm/debug.h>
13 #include "qdio_debug.h"
14 #include "qdio.h"
16 debug_info_t *qdio_dbf_setup;
17 debug_info_t *qdio_dbf_error;
19 static struct dentry *debugfs_root;
20 #define QDIO_DEBUGFS_NAME_LEN 10
22 void qdio_allocate_dbf(struct qdio_initialize *init_data,
23 struct qdio_irq *irq_ptr)
25 char text[20];
27 DBF_EVENT("qfmt:%1d", init_data->q_format);
28 DBF_HEX(init_data->adapter_name, 8);
29 DBF_EVENT("qpff%4x", init_data->qib_param_field_format);
30 DBF_HEX(&init_data->qib_param_field, sizeof(void *));
31 DBF_HEX(&init_data->input_slib_elements, sizeof(void *));
32 DBF_HEX(&init_data->output_slib_elements, sizeof(void *));
33 DBF_EVENT("niq:%1d noq:%1d", init_data->no_input_qs,
34 init_data->no_output_qs);
35 DBF_HEX(&init_data->input_handler, sizeof(void *));
36 DBF_HEX(&init_data->output_handler, sizeof(void *));
37 DBF_HEX(&init_data->int_parm, sizeof(long));
38 DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *));
39 DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *));
40 DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
42 /* allocate trace view for the interface */
43 snprintf(text, 20, "qdio_%s", dev_name(&init_data->cdev->dev));
44 irq_ptr->debug_area = debug_register(text, 2, 1, 16);
45 debug_register_view(irq_ptr->debug_area, &debug_hex_ascii_view);
46 debug_set_level(irq_ptr->debug_area, DBF_WARN);
47 DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created");
50 static int qstat_show(struct seq_file *m, void *v)
52 unsigned char state;
53 struct qdio_q *q = m->private;
54 int i;
56 if (!q)
57 return 0;
59 seq_printf(m, "Timestamp: %Lx Last AI: %Lx\n",
60 q->timestamp, last_ai_time);
61 seq_printf(m, "nr_used: %d ftc: %d last_move: %d\n",
62 atomic_read(&q->nr_buf_used),
63 q->first_to_check, q->last_move);
64 if (q->is_input_q) {
65 seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
66 q->u.in.polling, q->u.in.ack_start,
67 q->u.in.ack_count);
68 seq_printf(m, "DSCI: %d IRQs disabled: %u\n",
69 *(u32 *)q->irq_ptr->dsci,
70 test_bit(QDIO_QUEUE_IRQS_DISABLED,
71 &q->u.in.queue_irq_state));
73 seq_printf(m, "SBAL states:\n");
74 seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
76 for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
77 debug_get_buf_state(q, i, &state);
78 switch (state) {
79 case SLSB_P_INPUT_NOT_INIT:
80 case SLSB_P_OUTPUT_NOT_INIT:
81 seq_printf(m, "N");
82 break;
83 case SLSB_P_OUTPUT_PENDING:
84 seq_printf(m, "P");
85 break;
86 case SLSB_P_INPUT_PRIMED:
87 case SLSB_CU_OUTPUT_PRIMED:
88 seq_printf(m, "+");
89 break;
90 case SLSB_P_INPUT_ACK:
91 seq_printf(m, "A");
92 break;
93 case SLSB_P_INPUT_ERROR:
94 case SLSB_P_OUTPUT_ERROR:
95 seq_printf(m, "x");
96 break;
97 case SLSB_CU_INPUT_EMPTY:
98 case SLSB_P_OUTPUT_EMPTY:
99 seq_printf(m, "-");
100 break;
101 case SLSB_P_INPUT_HALTED:
102 case SLSB_P_OUTPUT_HALTED:
103 seq_printf(m, ".");
104 break;
105 default:
106 seq_printf(m, "?");
108 if (i == 63)
109 seq_printf(m, "\n");
111 seq_printf(m, "\n");
112 seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\n");
114 seq_printf(m, "\nSBAL statistics:");
115 if (!q->irq_ptr->perf_stat_enabled) {
116 seq_printf(m, " disabled\n");
117 return 0;
120 seq_printf(m, "\n1 2.. 4.. 8.. "
121 "16.. 32.. 64.. 127\n");
122 for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++)
123 seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]);
124 seq_printf(m, "\nError NOP Total\n%-10u %-10u %-10u\n\n",
125 q->q_stats.nr_sbal_error, q->q_stats.nr_sbal_nop,
126 q->q_stats.nr_sbal_total);
127 return 0;
130 static int qstat_seq_open(struct inode *inode, struct file *filp)
132 return single_open(filp, qstat_show,
133 filp->f_path.dentry->d_inode->i_private);
136 static const struct file_operations debugfs_fops = {
137 .owner = THIS_MODULE,
138 .open = qstat_seq_open,
139 .read = seq_read,
140 .llseek = seq_lseek,
141 .release = single_release,
144 static char *qperf_names[] = {
145 "Assumed adapter interrupts",
146 "QDIO interrupts",
147 "Requested PCIs",
148 "Inbound tasklet runs",
149 "Inbound tasklet resched",
150 "Inbound tasklet resched2",
151 "Outbound tasklet runs",
152 "SIGA read",
153 "SIGA write",
154 "SIGA sync",
155 "Inbound calls",
156 "Inbound handler",
157 "Inbound stop_polling",
158 "Inbound queue full",
159 "Outbound calls",
160 "Outbound handler",
161 "Outbound queue full",
162 "Outbound fast_requeue",
163 "Outbound target_full",
164 "QEBSM eqbs",
165 "QEBSM eqbs partial",
166 "QEBSM sqbs",
167 "QEBSM sqbs partial",
168 "Discarded interrupts"
171 static int qperf_show(struct seq_file *m, void *v)
173 struct qdio_irq *irq_ptr = m->private;
174 unsigned int *stat;
175 int i;
177 if (!irq_ptr)
178 return 0;
179 if (!irq_ptr->perf_stat_enabled) {
180 seq_printf(m, "disabled\n");
181 return 0;
183 stat = (unsigned int *)&irq_ptr->perf_stat;
185 for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
186 seq_printf(m, "%26s:\t%u\n",
187 qperf_names[i], *(stat + i));
188 return 0;
191 static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
192 size_t count, loff_t *off)
194 struct seq_file *seq = file->private_data;
195 struct qdio_irq *irq_ptr = seq->private;
196 struct qdio_q *q;
197 unsigned long val;
198 int ret, i;
200 if (!irq_ptr)
201 return 0;
203 ret = kstrtoul_from_user(ubuf, count, 10, &val);
204 if (ret)
205 return ret;
207 switch (val) {
208 case 0:
209 irq_ptr->perf_stat_enabled = 0;
210 memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
211 for_each_input_queue(irq_ptr, q, i)
212 memset(&q->q_stats, 0, sizeof(q->q_stats));
213 for_each_output_queue(irq_ptr, q, i)
214 memset(&q->q_stats, 0, sizeof(q->q_stats));
215 break;
216 case 1:
217 irq_ptr->perf_stat_enabled = 1;
218 break;
220 return count;
223 static int qperf_seq_open(struct inode *inode, struct file *filp)
225 return single_open(filp, qperf_show,
226 filp->f_path.dentry->d_inode->i_private);
229 static struct file_operations debugfs_perf_fops = {
230 .owner = THIS_MODULE,
231 .open = qperf_seq_open,
232 .read = seq_read,
233 .write = qperf_seq_write,
234 .llseek = seq_lseek,
235 .release = single_release,
237 static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
239 char name[QDIO_DEBUGFS_NAME_LEN];
241 snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
242 q->is_input_q ? "input" : "output",
243 q->nr);
244 q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
245 q->irq_ptr->debugfs_dev, q, &debugfs_fops);
246 if (IS_ERR(q->debugfs_q))
247 q->debugfs_q = NULL;
250 void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
252 struct qdio_q *q;
253 int i;
255 irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev),
256 debugfs_root);
257 if (IS_ERR(irq_ptr->debugfs_dev))
258 irq_ptr->debugfs_dev = NULL;
260 irq_ptr->debugfs_perf = debugfs_create_file("statistics",
261 S_IFREG | S_IRUGO | S_IWUSR,
262 irq_ptr->debugfs_dev, irq_ptr,
263 &debugfs_perf_fops);
264 if (IS_ERR(irq_ptr->debugfs_perf))
265 irq_ptr->debugfs_perf = NULL;
267 for_each_input_queue(irq_ptr, q, i)
268 setup_debugfs_entry(q, cdev);
269 for_each_output_queue(irq_ptr, q, i)
270 setup_debugfs_entry(q, cdev);
273 void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
275 struct qdio_q *q;
276 int i;
278 for_each_input_queue(irq_ptr, q, i)
279 debugfs_remove(q->debugfs_q);
280 for_each_output_queue(irq_ptr, q, i)
281 debugfs_remove(q->debugfs_q);
282 debugfs_remove(irq_ptr->debugfs_perf);
283 debugfs_remove(irq_ptr->debugfs_dev);
286 int __init qdio_debug_init(void)
288 debugfs_root = debugfs_create_dir("qdio", NULL);
290 qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
291 debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
292 debug_set_level(qdio_dbf_setup, DBF_INFO);
293 DBF_EVENT("dbf created\n");
295 qdio_dbf_error = debug_register("qdio_error", 4, 1, 16);
296 debug_register_view(qdio_dbf_error, &debug_hex_ascii_view);
297 debug_set_level(qdio_dbf_error, DBF_INFO);
298 DBF_ERROR("dbf created\n");
299 return 0;
302 void qdio_debug_exit(void)
304 debugfs_remove(debugfs_root);
305 if (qdio_dbf_setup)
306 debug_unregister(qdio_dbf_setup);
307 if (qdio_dbf_error)
308 debug_unregister(qdio_dbf_error);