Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
qdio_debug.c
Go to the documentation of this file.
1 /*
2  * Copyright IBM Corp. 2008, 2009
3  *
4  * Author: Jan Glauber ([email protected])
5  */
6 #include <linux/seq_file.h>
7 #include <linux/debugfs.h>
8 #include <linux/uaccess.h>
9 #include <linux/export.h>
10 #include <asm/debug.h>
11 #include "qdio_debug.h"
12 #include "qdio.h"
13 
16 
17 static struct dentry *debugfs_root;
18 #define QDIO_DEBUGFS_NAME_LEN 10
19 
20 void qdio_allocate_dbf(struct qdio_initialize *init_data,
21  struct qdio_irq *irq_ptr)
22 {
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->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");
46 }
47 
48 static 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 
57  seq_printf(m, "Timestamp: %Lx Last AI: %Lx\n",
59  seq_printf(m, "nr_used: %d ftc: %d last_move: %d\n",
61  q->first_to_check, q->last_move);
62  if (q->is_input_q) {
63  seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
64  q->u.in.polling, q->u.in.ack_start,
65  q->u.in.ack_count);
66  seq_printf(m, "DSCI: %d IRQs disabled: %u\n",
67  *(u32 *)q->irq_ptr->dsci,
69  &q->u.in.queue_irq_state));
70  }
71  seq_printf(m, "SBAL states:\n");
72  seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
73 
74  for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
75  debug_get_buf_state(q, i, &state);
76  switch (state) {
79  seq_printf(m, "N");
80  break;
82  seq_printf(m, "P");
83  break;
86  seq_printf(m, "+");
87  break;
88  case SLSB_P_INPUT_ACK:
89  seq_printf(m, "A");
90  break;
91  case SLSB_P_INPUT_ERROR:
93  seq_printf(m, "x");
94  break;
97  seq_printf(m, "-");
98  break;
101  seq_printf(m, ".");
102  break;
103  default:
104  seq_printf(m, "?");
105  }
106  if (i == 63)
107  seq_printf(m, "\n");
108  }
109  seq_printf(m, "\n");
110  seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\n");
111 
112  seq_printf(m, "\nSBAL statistics:");
113  if (!q->irq_ptr->perf_stat_enabled) {
114  seq_printf(m, " disabled\n");
115  return 0;
116  }
117 
118  seq_printf(m, "\n1 2.. 4.. 8.. "
119  "16.. 32.. 64.. 127\n");
120  for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++)
121  seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]);
122  seq_printf(m, "\nError NOP Total\n%-10u %-10u %-10u\n\n",
123  q->q_stats.nr_sbal_error, q->q_stats.nr_sbal_nop,
124  q->q_stats.nr_sbal_total);
125  return 0;
126 }
127 
128 static int qstat_seq_open(struct inode *inode, struct file *filp)
129 {
130  return single_open(filp, qstat_show,
131  filp->f_path.dentry->d_inode->i_private);
132 }
133 
134 static const struct file_operations debugfs_fops = {
135  .owner = THIS_MODULE,
136  .open = qstat_seq_open,
137  .read = seq_read,
138  .llseek = seq_lseek,
139  .release = single_release,
140 };
141 
142 static char *qperf_names[] = {
143  "Assumed adapter interrupts",
144  "QDIO interrupts",
145  "Requested PCIs",
146  "Inbound tasklet runs",
147  "Inbound tasklet resched",
148  "Inbound tasklet resched2",
149  "Outbound tasklet runs",
150  "SIGA read",
151  "SIGA write",
152  "SIGA sync",
153  "Inbound calls",
154  "Inbound handler",
155  "Inbound stop_polling",
156  "Inbound queue full",
157  "Outbound calls",
158  "Outbound handler",
159  "Outbound queue full",
160  "Outbound fast_requeue",
161  "Outbound target_full",
162  "QEBSM eqbs",
163  "QEBSM eqbs partial",
164  "QEBSM sqbs",
165  "QEBSM sqbs partial",
166  "Discarded interrupts"
167 };
168 
169 static int qperf_show(struct seq_file *m, void *v)
170 {
171  struct qdio_irq *irq_ptr = m->private;
172  unsigned int *stat;
173  int i;
174 
175  if (!irq_ptr)
176  return 0;
177  if (!irq_ptr->perf_stat_enabled) {
178  seq_printf(m, "disabled\n");
179  return 0;
180  }
181  stat = (unsigned int *)&irq_ptr->perf_stat;
182 
183  for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
184  seq_printf(m, "%26s:\t%u\n",
185  qperf_names[i], *(stat + i));
186  return 0;
187 }
188 
189 static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
190  size_t count, loff_t *off)
191 {
192  struct seq_file *seq = file->private_data;
193  struct qdio_irq *irq_ptr = seq->private;
194  struct qdio_q *q;
195  unsigned long val;
196  int ret, i;
197 
198  if (!irq_ptr)
199  return 0;
200 
201  ret = kstrtoul_from_user(ubuf, count, 10, &val);
202  if (ret)
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));
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));
213  break;
214  case 1:
215  irq_ptr->perf_stat_enabled = 1;
216  break;
217  }
218  return count;
219 }
220 
221 static 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 
227 static 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 };
235 static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
236 {
238 
239  snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
240  q->is_input_q ? "input" : "output",
241  q->nr);
243  q->irq_ptr->debugfs_dev, q, &debugfs_fops);
244  if (IS_ERR(q->debugfs_q))
245  q->debugfs_q = NULL;
246 }
247 
248 void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
249 {
250  struct qdio_q *q;
251  int i;
252 
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;
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 
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);
269 }
270 
271 void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
272 {
273  struct qdio_q *q;
274  int i;
275 
276  for_each_input_queue(irq_ptr, q, i)
278  for_each_output_queue(irq_ptr, q, i)
280  debugfs_remove(irq_ptr->debugfs_perf);
281  debugfs_remove(irq_ptr->debugfs_dev);
282 }
283 
285 {
286  debugfs_root = debugfs_create_dir("qdio", NULL);
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;
298 }
299 
300 void qdio_debug_exit(void)
301 {
302  debugfs_remove(debugfs_root);
303  if (qdio_dbf_setup)
304  debug_unregister(qdio_dbf_setup);
305  if (qdio_dbf_error)
306  debug_unregister(qdio_dbf_error);
307 }