~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/s390/cio/qdio_debug.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <linux/uaccess.h>
 
11
#include <linux/export.h>
 
12
#include <asm/debug.h>
 
13
#include "qdio_debug.h"
 
14
#include "qdio.h"
 
15
 
 
16
debug_info_t *qdio_dbf_setup;
 
17
debug_info_t *qdio_dbf_error;
 
18
 
 
19
static struct dentry *debugfs_root;
 
20
#define QDIO_DEBUGFS_NAME_LEN   10
 
21
 
 
22
void qdio_allocate_dbf(struct qdio_initialize *init_data,
 
23
                       struct qdio_irq *irq_ptr)
 
24
{
 
25
        char text[20];
 
26
 
 
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);
 
41
 
 
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");
 
48
}
 
49
 
 
50
static int qstat_show(struct seq_file *m, void *v)
 
51
{
 
52
        unsigned char state;
 
53
        struct qdio_q *q = m->private;
 
54
        int i;
 
55
 
 
56
        if (!q)
 
57
                return 0;
 
58
 
 
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));
 
72
        }
 
73
        seq_printf(m, "SBAL states:\n");
 
74
        seq_printf(m, "|0      |8      |16     |24     |32     |40     |48     |56  63|\n");
 
75
 
 
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, "?");
 
107
                }
 
108
                if (i == 63)
 
109
                        seq_printf(m, "\n");
 
110
        }
 
111
        seq_printf(m, "\n");
 
112
        seq_printf(m, "|64     |72     |80     |88     |96     |104    |112    |   127|\n");
 
113
 
 
114
        seq_printf(m, "\nSBAL statistics:");
 
115
        if (!q->irq_ptr->perf_stat_enabled) {
 
116
                seq_printf(m, " disabled\n");
 
117
                return 0;
 
118
        }
 
119
 
 
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;
 
128
}
 
129
 
 
130
static int qstat_seq_open(struct inode *inode, struct file *filp)
 
131
{
 
132
        return single_open(filp, qstat_show,
 
133
                           filp->f_path.dentry->d_inode->i_private);
 
134
}
 
135
 
 
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,
 
142
};
 
143
 
 
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"
 
169
};
 
170
 
 
171
static int qperf_show(struct seq_file *m, void *v)
 
172
{
 
173
        struct qdio_irq *irq_ptr = m->private;
 
174
        unsigned int *stat;
 
175
        int i;
 
176
 
 
177
        if (!irq_ptr)
 
178
                return 0;
 
179
        if (!irq_ptr->perf_stat_enabled) {
 
180
                seq_printf(m, "disabled\n");
 
181
                return 0;
 
182
        }
 
183
        stat = (unsigned int *)&irq_ptr->perf_stat;
 
184
 
 
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;
 
189
}
 
190
 
 
191
static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
 
192
                               size_t count, loff_t *off)
 
193
{
 
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;
 
199
 
 
200
        if (!irq_ptr)
 
201
                return 0;
 
202
 
 
203
        ret = kstrtoul_from_user(ubuf, count, 10, &val);
 
204
        if (ret)
 
205
                return ret;
 
206
 
 
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;
 
219
        }
 
220
        return count;
 
221
}
 
222
 
 
223
static int qperf_seq_open(struct inode *inode, struct file *filp)
 
224
{
 
225
        return single_open(filp, qperf_show,
 
226
                           filp->f_path.dentry->d_inode->i_private);
 
227
}
 
228
 
 
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,
 
236
};
 
237
static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
 
238
{
 
239
        char name[QDIO_DEBUGFS_NAME_LEN];
 
240
 
 
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;
 
248
}
 
249
 
 
250
void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
 
251
{
 
252
        struct qdio_q *q;
 
253
        int i;
 
254
 
 
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;
 
259
 
 
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;
 
266
 
 
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);
 
271
}
 
272
 
 
273
void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
 
274
{
 
275
        struct qdio_q *q;
 
276
        int i;
 
277
 
 
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);
 
284
}
 
285
 
 
286
int __init qdio_debug_init(void)
 
287
{
 
288
        debugfs_root = debugfs_create_dir("qdio", NULL);
 
289
 
 
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");
 
294
 
 
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;
 
300
}
 
301
 
 
302
void qdio_debug_exit(void)
 
303
{
 
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);
 
309
}