aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/qdio_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/qdio_debug.c')
-rw-r--r--drivers/s390/cio/qdio_debug.c136
1 files changed, 126 insertions, 10 deletions
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index 76769978285f..6ce83f56d537 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -33,7 +33,6 @@ void qdio_allocate_dbf(struct qdio_initialize *init_data,
33 DBF_HEX(&init_data->input_handler, sizeof(void *)); 33 DBF_HEX(&init_data->input_handler, sizeof(void *));
34 DBF_HEX(&init_data->output_handler, sizeof(void *)); 34 DBF_HEX(&init_data->output_handler, sizeof(void *));
35 DBF_HEX(&init_data->int_parm, sizeof(long)); 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 *)); 36 DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *));
38 DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *)); 37 DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *));
39 DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr); 38 DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
@@ -55,14 +54,12 @@ static int qstat_show(struct seq_file *m, void *v)
55 if (!q) 54 if (!q)
56 return 0; 55 return 0;
57 56
58 seq_printf(m, "device state indicator: %d\n", *(u32 *)q->irq_ptr->dsci); 57 seq_printf(m, "DSCI: %d nr_used: %d\n",
59 seq_printf(m, "nr_used: %d\n", atomic_read(&q->nr_buf_used)); 58 *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used));
60 seq_printf(m, "ftc: %d\n", q->first_to_check); 59 seq_printf(m, "ftc: %d last_move: %d\n", q->first_to_check, q->last_move);
61 seq_printf(m, "last_move: %d\n", q->last_move); 60 seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
62 seq_printf(m, "polling: %d\n", q->u.in.polling); 61 q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count);
63 seq_printf(m, "ack start: %d\n", q->u.in.ack_start); 62 seq_printf(m, "SBAL states:\n");
64 seq_printf(m, "ack count: %d\n", q->u.in.ack_count);
65 seq_printf(m, "slsb buffer states:\n");
66 seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); 63 seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
67 64
68 for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) { 65 for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
@@ -99,6 +96,20 @@ static int qstat_show(struct seq_file *m, void *v)
99 } 96 }
100 seq_printf(m, "\n"); 97 seq_printf(m, "\n");
101 seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\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);
102 return 0; 113 return 0;
103} 114}
104 115
@@ -110,7 +121,6 @@ static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
110 121
111 if (!q) 122 if (!q)
112 return 0; 123 return 0;
113
114 if (q->is_input_q) 124 if (q->is_input_q)
115 xchg(q->irq_ptr->dsci, 1); 125 xchg(q->irq_ptr->dsci, 1);
116 local_bh_disable(); 126 local_bh_disable();
@@ -134,6 +144,103 @@ static const struct file_operations debugfs_fops = {
134 .release = single_release, 144 .release = single_release,
135}; 145};
136 146
147static 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
172static 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
192static 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
230static 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
236static 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};
137static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev) 244static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
138{ 245{
139 char name[QDIO_DEBUGFS_NAME_LEN]; 246 char name[QDIO_DEBUGFS_NAME_LEN];
@@ -156,6 +263,14 @@ void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
156 debugfs_root); 263 debugfs_root);
157 if (IS_ERR(irq_ptr->debugfs_dev)) 264 if (IS_ERR(irq_ptr->debugfs_dev))
158 irq_ptr->debugfs_dev = NULL; 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
159 for_each_input_queue(irq_ptr, q, i) 274 for_each_input_queue(irq_ptr, q, i)
160 setup_debugfs_entry(q, cdev); 275 setup_debugfs_entry(q, cdev);
161 for_each_output_queue(irq_ptr, q, i) 276 for_each_output_queue(irq_ptr, q, i)
@@ -171,6 +286,7 @@ void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cd
171 debugfs_remove(q->debugfs_q); 286 debugfs_remove(q->debugfs_q);
172 for_each_output_queue(irq_ptr, q, i) 287 for_each_output_queue(irq_ptr, q, i)
173 debugfs_remove(q->debugfs_q); 288 debugfs_remove(q->debugfs_q);
289 debugfs_remove(irq_ptr->debugfs_perf);
174 debugfs_remove(irq_ptr->debugfs_dev); 290 debugfs_remove(irq_ptr->debugfs_dev);
175} 291}
176 292