Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 *  Copyright IBM Corp. 2008, 2009
  4 *
  5 *  Author: Jan Glauber (jang@linux.vnet.ibm.com)
  6 */
  7#include <linux/seq_file.h>
  8#include <linux/debugfs.h>
  9#include <linux/uaccess.h>
 10#include <linux/export.h>
 11#include <linux/slab.h>
 12#include <asm/debug.h>
 13#include "qdio_debug.h"
 14#include "qdio.h"
 15
 16debug_info_t *qdio_dbf_setup;
 17debug_info_t *qdio_dbf_error;
 18
 19static struct dentry *debugfs_root;
 20#define QDIO_DEBUGFS_NAME_LEN	10
 21#define QDIO_DBF_NAME_LEN	20
 22
 23struct qdio_dbf_entry {
 24	char dbf_name[QDIO_DBF_NAME_LEN];
 25	debug_info_t *dbf_info;
 26	struct list_head dbf_list;
 27};
 28
 29static LIST_HEAD(qdio_dbf_list);
 30static DEFINE_MUTEX(qdio_dbf_list_mutex);
 31
 32static debug_info_t *qdio_get_dbf_entry(char *name)
 33{
 34	struct qdio_dbf_entry *entry;
 35	debug_info_t *rc = NULL;
 36
 37	mutex_lock(&qdio_dbf_list_mutex);
 38	list_for_each_entry(entry, &qdio_dbf_list, dbf_list) {
 39		if (strcmp(entry->dbf_name, name) == 0) {
 40			rc = entry->dbf_info;
 41			break;
 42		}
 43	}
 44	mutex_unlock(&qdio_dbf_list_mutex);
 45	return rc;
 46}
 47
 48static void qdio_clear_dbf_list(void)
 49{
 50	struct qdio_dbf_entry *entry, *tmp;
 51
 52	mutex_lock(&qdio_dbf_list_mutex);
 53	list_for_each_entry_safe(entry, tmp, &qdio_dbf_list, dbf_list) {
 54		list_del(&entry->dbf_list);
 55		debug_unregister(entry->dbf_info);
 56		kfree(entry);
 57	}
 58	mutex_unlock(&qdio_dbf_list_mutex);
 59}
 60
 61int qdio_allocate_dbf(struct qdio_irq *irq_ptr)
 
 62{
 63	char text[QDIO_DBF_NAME_LEN];
 64	struct qdio_dbf_entry *new_entry;
 65
 
 
 
 
 
 
 
 
 
 
 
 
 
 66	DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
 67
 68	/* allocate trace view for the interface */
 69	snprintf(text, QDIO_DBF_NAME_LEN, "qdio_%s",
 70		 dev_name(&irq_ptr->cdev->dev));
 71	irq_ptr->debug_area = qdio_get_dbf_entry(text);
 72	if (irq_ptr->debug_area)
 73		DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf reused");
 74	else {
 75		irq_ptr->debug_area = debug_register(text, 2, 1, 16);
 76		if (!irq_ptr->debug_area)
 77			return -ENOMEM;
 78		if (debug_register_view(irq_ptr->debug_area,
 79						&debug_hex_ascii_view)) {
 80			debug_unregister(irq_ptr->debug_area);
 81			return -ENOMEM;
 82		}
 83		debug_set_level(irq_ptr->debug_area, DBF_WARN);
 84		DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created");
 85		new_entry = kzalloc(sizeof(struct qdio_dbf_entry), GFP_KERNEL);
 86		if (!new_entry) {
 87			debug_unregister(irq_ptr->debug_area);
 88			return -ENOMEM;
 89		}
 90		strlcpy(new_entry->dbf_name, text, QDIO_DBF_NAME_LEN);
 91		new_entry->dbf_info = irq_ptr->debug_area;
 92		mutex_lock(&qdio_dbf_list_mutex);
 93		list_add(&new_entry->dbf_list, &qdio_dbf_list);
 94		mutex_unlock(&qdio_dbf_list_mutex);
 95	}
 96	return 0;
 97}
 98
 99static int qstat_show(struct seq_file *m, void *v)
100{
101	unsigned char state;
102	struct qdio_q *q = m->private;
103	int i;
104
105	if (!q)
106		return 0;
107
108	seq_printf(m, "Timestamp: %Lx  Last AI: %Lx\n",
109		   q->timestamp, last_ai_time);
110	seq_printf(m, "nr_used: %d  ftc: %d\n",
111		   atomic_read(&q->nr_buf_used), q->first_to_check);
112	if (q->is_input_q) {
113		seq_printf(m, "batch start: %u  batch count: %u\n",
114			   q->u.in.batch_start, q->u.in.batch_count);
 
115		seq_printf(m, "DSCI: %x   IRQs disabled: %u\n",
116			   *(u8 *)q->irq_ptr->dsci,
117			   test_bit(QDIO_IRQ_DISABLED,
118				    &q->irq_ptr->poll_state));
119	}
120	seq_printf(m, "SBAL states:\n");
121	seq_printf(m, "|0      |8      |16     |24     |32     |40     |48     |56  63|\n");
122
123	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
124		debug_get_buf_state(q, i, &state);
125		switch (state) {
126		case SLSB_P_INPUT_NOT_INIT:
127		case SLSB_P_OUTPUT_NOT_INIT:
128			seq_printf(m, "N");
129			break;
130		case SLSB_P_OUTPUT_PENDING:
131			seq_printf(m, "P");
132			break;
133		case SLSB_P_INPUT_PRIMED:
134		case SLSB_CU_OUTPUT_PRIMED:
135			seq_printf(m, "+");
136			break;
137		case SLSB_P_INPUT_ACK:
138			seq_printf(m, "A");
139			break;
140		case SLSB_P_INPUT_ERROR:
141		case SLSB_P_OUTPUT_ERROR:
142			seq_printf(m, "x");
143			break;
144		case SLSB_CU_INPUT_EMPTY:
145		case SLSB_P_OUTPUT_EMPTY:
146			seq_printf(m, "-");
147			break;
148		case SLSB_P_INPUT_HALTED:
149		case SLSB_P_OUTPUT_HALTED:
150			seq_printf(m, ".");
151			break;
152		default:
153			seq_printf(m, "?");
154		}
155		if (i == 63)
156			seq_printf(m, "\n");
157	}
158	seq_printf(m, "\n");
159	seq_printf(m, "|64     |72     |80     |88     |96     |104    |112    |   127|\n");
160
161	seq_printf(m, "\nSBAL statistics:");
162	if (!q->irq_ptr->perf_stat_enabled) {
163		seq_printf(m, " disabled\n");
164		return 0;
165	}
166
167	seq_printf(m, "\n1          2..        4..        8..        "
168		   "16..       32..       64..       128\n");
169	for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++)
170		seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]);
171	seq_printf(m, "\nError      NOP        Total\n%-10u %-10u %-10u\n\n",
172		   q->q_stats.nr_sbal_error, q->q_stats.nr_sbal_nop,
173		   q->q_stats.nr_sbal_total);
174	return 0;
175}
176
177DEFINE_SHOW_ATTRIBUTE(qstat);
178
179static int ssqd_show(struct seq_file *m, void *v)
180{
181	struct ccw_device *cdev = m->private;
182	struct qdio_ssqd_desc ssqd;
183	int rc;
184
185	rc = qdio_get_ssqd_desc(cdev, &ssqd);
186	if (rc)
187		return rc;
188
189	seq_hex_dump(m, "", DUMP_PREFIX_NONE, 16, 4, &ssqd, sizeof(ssqd),
190		     false);
191	return 0;
192}
193
194DEFINE_SHOW_ATTRIBUTE(ssqd);
195
196static char *qperf_names[] = {
197	"Assumed adapter interrupts",
198	"QDIO interrupts",
199	"Requested PCIs",
200	"Inbound tasklet runs",
201	"Inbound tasklet resched",
202	"Inbound tasklet resched2",
203	"Outbound tasklet runs",
204	"SIGA read",
205	"SIGA write",
206	"SIGA sync",
207	"Inbound calls",
208	"Inbound handler",
209	"Inbound stop_polling",
210	"Inbound queue full",
211	"Outbound calls",
212	"Outbound handler",
213	"Outbound queue full",
214	"Outbound fast_requeue",
215	"Outbound target_full",
216	"QEBSM eqbs",
217	"QEBSM eqbs partial",
218	"QEBSM sqbs",
219	"QEBSM sqbs partial",
220	"Discarded interrupts"
221};
222
223static int qperf_show(struct seq_file *m, void *v)
224{
225	struct qdio_irq *irq_ptr = m->private;
226	unsigned int *stat;
227	int i;
228
229	if (!irq_ptr)
230		return 0;
231	if (!irq_ptr->perf_stat_enabled) {
232		seq_printf(m, "disabled\n");
233		return 0;
234	}
235	stat = (unsigned int *)&irq_ptr->perf_stat;
236
237	for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
238		seq_printf(m, "%26s:\t%u\n",
239			   qperf_names[i], *(stat + i));
240	return 0;
241}
242
243static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
244			       size_t count, loff_t *off)
245{
246	struct seq_file *seq = file->private_data;
247	struct qdio_irq *irq_ptr = seq->private;
248	struct qdio_q *q;
249	unsigned long val;
250	int ret, i;
251
252	if (!irq_ptr)
253		return 0;
254
255	ret = kstrtoul_from_user(ubuf, count, 10, &val);
256	if (ret)
257		return ret;
258
259	switch (val) {
260	case 0:
261		irq_ptr->perf_stat_enabled = 0;
262		memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
263		for_each_input_queue(irq_ptr, q, i)
264			memset(&q->q_stats, 0, sizeof(q->q_stats));
265		for_each_output_queue(irq_ptr, q, i)
266			memset(&q->q_stats, 0, sizeof(q->q_stats));
267		break;
268	case 1:
269		irq_ptr->perf_stat_enabled = 1;
270		break;
271	}
272	return count;
273}
274
275static int qperf_seq_open(struct inode *inode, struct file *filp)
276{
277	return single_open(filp, qperf_show,
278			   file_inode(filp)->i_private);
279}
280
281static const struct file_operations debugfs_perf_fops = {
282	.owner	 = THIS_MODULE,
283	.open	 = qperf_seq_open,
284	.read	 = seq_read,
285	.write	 = qperf_seq_write,
286	.llseek  = seq_lseek,
287	.release = single_release,
288};
289
290static void setup_debugfs_entry(struct dentry *parent, struct qdio_q *q)
291{
292	char name[QDIO_DEBUGFS_NAME_LEN];
293
294	snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
295		 q->is_input_q ? "input" : "output",
296		 q->nr);
297	debugfs_create_file(name, 0444, parent, q, &qstat_fops);
 
 
 
298}
299
300void qdio_setup_debug_entries(struct qdio_irq *irq_ptr)
301{
302	struct qdio_q *q;
303	int i;
304
305	irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&irq_ptr->cdev->dev),
306						  debugfs_root);
307	debugfs_create_file("statistics", S_IFREG | S_IRUGO | S_IWUSR,
308			    irq_ptr->debugfs_dev, irq_ptr, &debugfs_perf_fops);
309	debugfs_create_file("ssqd", 0444, irq_ptr->debugfs_dev, irq_ptr->cdev,
310			    &ssqd_fops);
 
 
 
 
 
311
312	for_each_input_queue(irq_ptr, q, i)
313		setup_debugfs_entry(irq_ptr->debugfs_dev, q);
314	for_each_output_queue(irq_ptr, q, i)
315		setup_debugfs_entry(irq_ptr->debugfs_dev, q);
316}
317
318void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr)
319{
320	debugfs_remove_recursive(irq_ptr->debugfs_dev);
 
 
 
 
 
 
 
 
321}
322
323int __init qdio_debug_init(void)
324{
325	debugfs_root = debugfs_create_dir("qdio", NULL);
326
327	qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
328	debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
329	debug_set_level(qdio_dbf_setup, DBF_INFO);
330	DBF_EVENT("dbf created\n");
331
332	qdio_dbf_error = debug_register("qdio_error", 4, 1, 16);
333	debug_register_view(qdio_dbf_error, &debug_hex_ascii_view);
334	debug_set_level(qdio_dbf_error, DBF_INFO);
335	DBF_ERROR("dbf created\n");
336	return 0;
337}
338
339void qdio_debug_exit(void)
340{
341	qdio_clear_dbf_list();
342	debugfs_remove_recursive(debugfs_root);
343	debug_unregister(qdio_dbf_setup);
344	debug_unregister(qdio_dbf_error);
345}
v5.4
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 *  Copyright IBM Corp. 2008, 2009
  4 *
  5 *  Author: Jan Glauber (jang@linux.vnet.ibm.com)
  6 */
  7#include <linux/seq_file.h>
  8#include <linux/debugfs.h>
  9#include <linux/uaccess.h>
 10#include <linux/export.h>
 11#include <linux/slab.h>
 12#include <asm/debug.h>
 13#include "qdio_debug.h"
 14#include "qdio.h"
 15
 16debug_info_t *qdio_dbf_setup;
 17debug_info_t *qdio_dbf_error;
 18
 19static struct dentry *debugfs_root;
 20#define QDIO_DEBUGFS_NAME_LEN	10
 21#define QDIO_DBF_NAME_LEN	20
 22
 23struct qdio_dbf_entry {
 24	char dbf_name[QDIO_DBF_NAME_LEN];
 25	debug_info_t *dbf_info;
 26	struct list_head dbf_list;
 27};
 28
 29static LIST_HEAD(qdio_dbf_list);
 30static DEFINE_MUTEX(qdio_dbf_list_mutex);
 31
 32static debug_info_t *qdio_get_dbf_entry(char *name)
 33{
 34	struct qdio_dbf_entry *entry;
 35	debug_info_t *rc = NULL;
 36
 37	mutex_lock(&qdio_dbf_list_mutex);
 38	list_for_each_entry(entry, &qdio_dbf_list, dbf_list) {
 39		if (strcmp(entry->dbf_name, name) == 0) {
 40			rc = entry->dbf_info;
 41			break;
 42		}
 43	}
 44	mutex_unlock(&qdio_dbf_list_mutex);
 45	return rc;
 46}
 47
 48static void qdio_clear_dbf_list(void)
 49{
 50	struct qdio_dbf_entry *entry, *tmp;
 51
 52	mutex_lock(&qdio_dbf_list_mutex);
 53	list_for_each_entry_safe(entry, tmp, &qdio_dbf_list, dbf_list) {
 54		list_del(&entry->dbf_list);
 55		debug_unregister(entry->dbf_info);
 56		kfree(entry);
 57	}
 58	mutex_unlock(&qdio_dbf_list_mutex);
 59}
 60
 61int qdio_allocate_dbf(struct qdio_initialize *init_data,
 62		       struct qdio_irq *irq_ptr)
 63{
 64	char text[QDIO_DBF_NAME_LEN];
 65	struct qdio_dbf_entry *new_entry;
 66
 67	DBF_EVENT("qfmt:%1d", init_data->q_format);
 68	DBF_HEX(init_data->adapter_name, 8);
 69	DBF_EVENT("qpff%4x", init_data->qib_param_field_format);
 70	DBF_HEX(&init_data->qib_param_field, sizeof(void *));
 71	DBF_HEX(&init_data->input_slib_elements, sizeof(void *));
 72	DBF_HEX(&init_data->output_slib_elements, sizeof(void *));
 73	DBF_EVENT("niq:%1d noq:%1d", init_data->no_input_qs,
 74		  init_data->no_output_qs);
 75	DBF_HEX(&init_data->input_handler, sizeof(void *));
 76	DBF_HEX(&init_data->output_handler, sizeof(void *));
 77	DBF_HEX(&init_data->int_parm, sizeof(long));
 78	DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *));
 79	DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *));
 80	DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
 81
 82	/* allocate trace view for the interface */
 83	snprintf(text, QDIO_DBF_NAME_LEN, "qdio_%s",
 84					dev_name(&init_data->cdev->dev));
 85	irq_ptr->debug_area = qdio_get_dbf_entry(text);
 86	if (irq_ptr->debug_area)
 87		DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf reused");
 88	else {
 89		irq_ptr->debug_area = debug_register(text, 2, 1, 16);
 90		if (!irq_ptr->debug_area)
 91			return -ENOMEM;
 92		if (debug_register_view(irq_ptr->debug_area,
 93						&debug_hex_ascii_view)) {
 94			debug_unregister(irq_ptr->debug_area);
 95			return -ENOMEM;
 96		}
 97		debug_set_level(irq_ptr->debug_area, DBF_WARN);
 98		DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created");
 99		new_entry = kzalloc(sizeof(struct qdio_dbf_entry), GFP_KERNEL);
100		if (!new_entry) {
101			debug_unregister(irq_ptr->debug_area);
102			return -ENOMEM;
103		}
104		strlcpy(new_entry->dbf_name, text, QDIO_DBF_NAME_LEN);
105		new_entry->dbf_info = irq_ptr->debug_area;
106		mutex_lock(&qdio_dbf_list_mutex);
107		list_add(&new_entry->dbf_list, &qdio_dbf_list);
108		mutex_unlock(&qdio_dbf_list_mutex);
109	}
110	return 0;
111}
112
113static int qstat_show(struct seq_file *m, void *v)
114{
115	unsigned char state;
116	struct qdio_q *q = m->private;
117	int i;
118
119	if (!q)
120		return 0;
121
122	seq_printf(m, "Timestamp: %Lx  Last AI: %Lx\n",
123		   q->timestamp, last_ai_time);
124	seq_printf(m, "nr_used: %d  ftc: %d\n",
125		   atomic_read(&q->nr_buf_used), q->first_to_check);
126	if (q->is_input_q) {
127		seq_printf(m, "polling: %d  ack start: %d  ack count: %d\n",
128			   q->u.in.polling, q->u.in.ack_start,
129			   q->u.in.ack_count);
130		seq_printf(m, "DSCI: %x   IRQs disabled: %u\n",
131			   *(u8 *)q->irq_ptr->dsci,
132			   test_bit(QDIO_QUEUE_IRQS_DISABLED,
133			   &q->u.in.queue_irq_state));
134	}
135	seq_printf(m, "SBAL states:\n");
136	seq_printf(m, "|0      |8      |16     |24     |32     |40     |48     |56  63|\n");
137
138	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
139		debug_get_buf_state(q, i, &state);
140		switch (state) {
141		case SLSB_P_INPUT_NOT_INIT:
142		case SLSB_P_OUTPUT_NOT_INIT:
143			seq_printf(m, "N");
144			break;
145		case SLSB_P_OUTPUT_PENDING:
146			seq_printf(m, "P");
147			break;
148		case SLSB_P_INPUT_PRIMED:
149		case SLSB_CU_OUTPUT_PRIMED:
150			seq_printf(m, "+");
151			break;
152		case SLSB_P_INPUT_ACK:
153			seq_printf(m, "A");
154			break;
155		case SLSB_P_INPUT_ERROR:
156		case SLSB_P_OUTPUT_ERROR:
157			seq_printf(m, "x");
158			break;
159		case SLSB_CU_INPUT_EMPTY:
160		case SLSB_P_OUTPUT_EMPTY:
161			seq_printf(m, "-");
162			break;
163		case SLSB_P_INPUT_HALTED:
164		case SLSB_P_OUTPUT_HALTED:
165			seq_printf(m, ".");
166			break;
167		default:
168			seq_printf(m, "?");
169		}
170		if (i == 63)
171			seq_printf(m, "\n");
172	}
173	seq_printf(m, "\n");
174	seq_printf(m, "|64     |72     |80     |88     |96     |104    |112    |   127|\n");
175
176	seq_printf(m, "\nSBAL statistics:");
177	if (!q->irq_ptr->perf_stat_enabled) {
178		seq_printf(m, " disabled\n");
179		return 0;
180	}
181
182	seq_printf(m, "\n1          2..        4..        8..        "
183		   "16..       32..       64..       127\n");
184	for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++)
185		seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]);
186	seq_printf(m, "\nError      NOP        Total\n%-10u %-10u %-10u\n\n",
187		   q->q_stats.nr_sbal_error, q->q_stats.nr_sbal_nop,
188		   q->q_stats.nr_sbal_total);
189	return 0;
190}
191
192DEFINE_SHOW_ATTRIBUTE(qstat);
193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194static char *qperf_names[] = {
195	"Assumed adapter interrupts",
196	"QDIO interrupts",
197	"Requested PCIs",
198	"Inbound tasklet runs",
199	"Inbound tasklet resched",
200	"Inbound tasklet resched2",
201	"Outbound tasklet runs",
202	"SIGA read",
203	"SIGA write",
204	"SIGA sync",
205	"Inbound calls",
206	"Inbound handler",
207	"Inbound stop_polling",
208	"Inbound queue full",
209	"Outbound calls",
210	"Outbound handler",
211	"Outbound queue full",
212	"Outbound fast_requeue",
213	"Outbound target_full",
214	"QEBSM eqbs",
215	"QEBSM eqbs partial",
216	"QEBSM sqbs",
217	"QEBSM sqbs partial",
218	"Discarded interrupts"
219};
220
221static int qperf_show(struct seq_file *m, void *v)
222{
223	struct qdio_irq *irq_ptr = m->private;
224	unsigned int *stat;
225	int i;
226
227	if (!irq_ptr)
228		return 0;
229	if (!irq_ptr->perf_stat_enabled) {
230		seq_printf(m, "disabled\n");
231		return 0;
232	}
233	stat = (unsigned int *)&irq_ptr->perf_stat;
234
235	for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
236		seq_printf(m, "%26s:\t%u\n",
237			   qperf_names[i], *(stat + i));
238	return 0;
239}
240
241static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
242			       size_t count, loff_t *off)
243{
244	struct seq_file *seq = file->private_data;
245	struct qdio_irq *irq_ptr = seq->private;
246	struct qdio_q *q;
247	unsigned long val;
248	int ret, i;
249
250	if (!irq_ptr)
251		return 0;
252
253	ret = kstrtoul_from_user(ubuf, count, 10, &val);
254	if (ret)
255		return ret;
256
257	switch (val) {
258	case 0:
259		irq_ptr->perf_stat_enabled = 0;
260		memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
261		for_each_input_queue(irq_ptr, q, i)
262			memset(&q->q_stats, 0, sizeof(q->q_stats));
263		for_each_output_queue(irq_ptr, q, i)
264			memset(&q->q_stats, 0, sizeof(q->q_stats));
265		break;
266	case 1:
267		irq_ptr->perf_stat_enabled = 1;
268		break;
269	}
270	return count;
271}
272
273static int qperf_seq_open(struct inode *inode, struct file *filp)
274{
275	return single_open(filp, qperf_show,
276			   file_inode(filp)->i_private);
277}
278
279static const struct file_operations debugfs_perf_fops = {
280	.owner	 = THIS_MODULE,
281	.open	 = qperf_seq_open,
282	.read	 = seq_read,
283	.write	 = qperf_seq_write,
284	.llseek  = seq_lseek,
285	.release = single_release,
286};
287
288static void setup_debugfs_entry(struct qdio_q *q)
289{
290	char name[QDIO_DEBUGFS_NAME_LEN];
291
292	snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
293		 q->is_input_q ? "input" : "output",
294		 q->nr);
295	q->debugfs_q = debugfs_create_file(name, 0444,
296				q->irq_ptr->debugfs_dev, q, &qstat_fops);
297	if (IS_ERR(q->debugfs_q))
298		q->debugfs_q = NULL;
299}
300
301void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
302{
303	struct qdio_q *q;
304	int i;
305
306	irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev),
307						  debugfs_root);
308	if (IS_ERR(irq_ptr->debugfs_dev))
309		irq_ptr->debugfs_dev = NULL;
310
311	irq_ptr->debugfs_perf = debugfs_create_file("statistics",
312				S_IFREG | S_IRUGO | S_IWUSR,
313				irq_ptr->debugfs_dev, irq_ptr,
314				&debugfs_perf_fops);
315	if (IS_ERR(irq_ptr->debugfs_perf))
316		irq_ptr->debugfs_perf = NULL;
317
318	for_each_input_queue(irq_ptr, q, i)
319		setup_debugfs_entry(q);
320	for_each_output_queue(irq_ptr, q, i)
321		setup_debugfs_entry(q);
322}
323
324void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr)
325{
326	struct qdio_q *q;
327	int i;
328
329	for_each_input_queue(irq_ptr, q, i)
330		debugfs_remove(q->debugfs_q);
331	for_each_output_queue(irq_ptr, q, i)
332		debugfs_remove(q->debugfs_q);
333	debugfs_remove(irq_ptr->debugfs_perf);
334	debugfs_remove(irq_ptr->debugfs_dev);
335}
336
337int __init qdio_debug_init(void)
338{
339	debugfs_root = debugfs_create_dir("qdio", NULL);
340
341	qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
342	debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
343	debug_set_level(qdio_dbf_setup, DBF_INFO);
344	DBF_EVENT("dbf created\n");
345
346	qdio_dbf_error = debug_register("qdio_error", 4, 1, 16);
347	debug_register_view(qdio_dbf_error, &debug_hex_ascii_view);
348	debug_set_level(qdio_dbf_error, DBF_INFO);
349	DBF_ERROR("dbf created\n");
350	return 0;
351}
352
353void qdio_debug_exit(void)
354{
355	qdio_clear_dbf_list();
356	debugfs_remove(debugfs_root);
357	debug_unregister(qdio_dbf_setup);
358	debug_unregister(qdio_dbf_error);
359}