diff options
Diffstat (limited to 'drivers/s390/cio/qdio_debug.c')
| -rw-r--r-- | drivers/s390/cio/qdio_debug.c | 126 | 
1 files changed, 96 insertions, 30 deletions
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index 28868e7471a..f1f3baa8e6e 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c @@ -1,12 +1,13 @@  /* - *  drivers/s390/cio/qdio_debug.c - * - *  Copyright IBM Corp. 2008,2009 + *  Copyright IBM Corp. 2008, 2009   *   *  Author: Jan Glauber (jang@linux.vnet.ibm.com)   */  #include <linux/seq_file.h>  #include <linux/debugfs.h> +#include <linux/uaccess.h> +#include <linux/export.h> +#include <linux/slab.h>  #include <asm/debug.h>  #include "qdio_debug.h"  #include "qdio.h" @@ -16,11 +17,51 @@ debug_info_t *qdio_dbf_error;  static struct dentry *debugfs_root;  #define QDIO_DEBUGFS_NAME_LEN	10 +#define QDIO_DBF_NAME_LEN	20 + +struct qdio_dbf_entry { +	char dbf_name[QDIO_DBF_NAME_LEN]; +	debug_info_t *dbf_info; +	struct list_head dbf_list; +}; + +static LIST_HEAD(qdio_dbf_list); +static DEFINE_MUTEX(qdio_dbf_list_mutex); + +static debug_info_t *qdio_get_dbf_entry(char *name) +{ +	struct qdio_dbf_entry *entry; +	debug_info_t *rc = NULL; -void qdio_allocate_dbf(struct qdio_initialize *init_data, +	mutex_lock(&qdio_dbf_list_mutex); +	list_for_each_entry(entry, &qdio_dbf_list, dbf_list) { +		if (strcmp(entry->dbf_name, name) == 0) { +			rc = entry->dbf_info; +			break; +		} +	} +	mutex_unlock(&qdio_dbf_list_mutex); +	return rc; +} + +static void qdio_clear_dbf_list(void) +{ +	struct qdio_dbf_entry *entry, *tmp; + +	mutex_lock(&qdio_dbf_list_mutex); +	list_for_each_entry_safe(entry, tmp, &qdio_dbf_list, dbf_list) { +		list_del(&entry->dbf_list); +		debug_unregister(entry->dbf_info); +		kfree(entry); +	} +	mutex_unlock(&qdio_dbf_list_mutex); +} + +int qdio_allocate_dbf(struct qdio_initialize *init_data,  		       struct qdio_irq *irq_ptr)  { -	char text[20]; +	char text[QDIO_DBF_NAME_LEN]; +	struct qdio_dbf_entry *new_entry;  	DBF_EVENT("qfmt:%1d", init_data->q_format);  	DBF_HEX(init_data->adapter_name, 8); @@ -38,11 +79,34 @@ void qdio_allocate_dbf(struct qdio_initialize *init_data,  	DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);  	/* allocate trace view for the interface */ -	snprintf(text, 20, "qdio_%s", dev_name(&init_data->cdev->dev)); -	irq_ptr->debug_area = debug_register(text, 2, 1, 16); -	debug_register_view(irq_ptr->debug_area, &debug_hex_ascii_view); -	debug_set_level(irq_ptr->debug_area, DBF_WARN); -	DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created"); +	snprintf(text, QDIO_DBF_NAME_LEN, "qdio_%s", +					dev_name(&init_data->cdev->dev)); +	irq_ptr->debug_area = qdio_get_dbf_entry(text); +	if (irq_ptr->debug_area) +		DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf reused"); +	else { +		irq_ptr->debug_area = debug_register(text, 2, 1, 16); +		if (!irq_ptr->debug_area) +			return -ENOMEM; +		if (debug_register_view(irq_ptr->debug_area, +						&debug_hex_ascii_view)) { +			debug_unregister(irq_ptr->debug_area); +			return -ENOMEM; +		} +		debug_set_level(irq_ptr->debug_area, DBF_WARN); +		DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created"); +		new_entry = kzalloc(sizeof(struct qdio_dbf_entry), GFP_KERNEL); +		if (!new_entry) { +			debug_unregister(irq_ptr->debug_area); +			return -ENOMEM; +		} +		strlcpy(new_entry->dbf_name, text, QDIO_DBF_NAME_LEN); +		new_entry->dbf_info = irq_ptr->debug_area; +		mutex_lock(&qdio_dbf_list_mutex); +		list_add(&new_entry->dbf_list, &qdio_dbf_list); +		mutex_unlock(&qdio_dbf_list_mutex); +	} +	return 0;  }  static int qstat_show(struct seq_file *m, void *v) @@ -54,15 +118,17 @@ static int qstat_show(struct seq_file *m, void *v)  	if (!q)  		return 0; -	seq_printf(m, "DSCI: %d   nr_used: %d\n", -		   *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used)); -	seq_printf(m, "ftc: %d  last_move: %d\n", +	seq_printf(m, "Timestamp: %Lx  Last AI: %Lx\n", +		   q->timestamp, last_ai_time); +	seq_printf(m, "nr_used: %d  ftc: %d  last_move: %d\n", +		   atomic_read(&q->nr_buf_used),  		   q->first_to_check, q->last_move);  	if (q->is_input_q) {  		seq_printf(m, "polling: %d  ack start: %d  ack count: %d\n",  			   q->u.in.polling, q->u.in.ack_start,  			   q->u.in.ack_count); -		seq_printf(m, "IRQs disabled: %u\n", +		seq_printf(m, "DSCI: %d   IRQs disabled: %u\n", +			   *(u32 *)q->irq_ptr->dsci,  			   test_bit(QDIO_QUEUE_IRQS_DISABLED,  			   &q->u.in.queue_irq_state));  	} @@ -76,6 +142,9 @@ static int qstat_show(struct seq_file *m, void *v)  		case SLSB_P_OUTPUT_NOT_INIT:  			seq_printf(m, "N");  			break; +		case SLSB_P_OUTPUT_PENDING: +			seq_printf(m, "P"); +			break;  		case SLSB_P_INPUT_PRIMED:  		case SLSB_CU_OUTPUT_PRIMED:  			seq_printf(m, "+"); @@ -123,7 +192,7 @@ static int qstat_show(struct seq_file *m, void *v)  static int qstat_seq_open(struct inode *inode, struct file *filp)  {  	return single_open(filp, qstat_show, -			   filp->f_path.dentry->d_inode->i_private); +			   file_inode(filp)->i_private);  }  static const struct file_operations debugfs_fops = { @@ -151,6 +220,7 @@ static char *qperf_names[] = {  	"Inbound queue full",  	"Outbound calls",  	"Outbound handler", +	"Outbound queue full",  	"Outbound fast_requeue",  	"Outbound target_full",  	"QEBSM eqbs", @@ -187,19 +257,13 @@ static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,  	struct qdio_irq *irq_ptr = seq->private;  	struct qdio_q *q;  	unsigned long val; -	char buf[8];  	int ret, i;  	if (!irq_ptr)  		return 0; -	if (count >= sizeof(buf)) -		return -EINVAL; -	if (copy_from_user(&buf, ubuf, count)) -		return -EFAULT; -	buf[count] = 0; - -	ret = strict_strtoul(buf, 10, &val); -	if (ret < 0) + +	ret = kstrtoul_from_user(ubuf, count, 10, &val); +	if (ret)  		return ret;  	switch (val) { @@ -221,10 +285,10 @@ static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,  static int qperf_seq_open(struct inode *inode, struct file *filp)  {  	return single_open(filp, qperf_show, -			   filp->f_path.dentry->d_inode->i_private); +			   file_inode(filp)->i_private);  } -static struct file_operations debugfs_perf_fops = { +static const struct file_operations debugfs_perf_fops = {  	.owner	 = THIS_MODULE,  	.open	 = qperf_seq_open,  	.read	 = seq_read, @@ -232,7 +296,8 @@ static struct file_operations debugfs_perf_fops = {  	.llseek  = seq_lseek,  	.release = single_release,  }; -static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev) + +static void setup_debugfs_entry(struct qdio_q *q)  {  	char name[QDIO_DEBUGFS_NAME_LEN]; @@ -263,12 +328,12 @@ void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)  		irq_ptr->debugfs_perf = NULL;  	for_each_input_queue(irq_ptr, q, i) -		setup_debugfs_entry(q, cdev); +		setup_debugfs_entry(q);  	for_each_output_queue(irq_ptr, q, i) -		setup_debugfs_entry(q, cdev); +		setup_debugfs_entry(q);  } -void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev) +void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr)  {  	struct qdio_q *q;  	int i; @@ -299,6 +364,7 @@ int __init qdio_debug_init(void)  void qdio_debug_exit(void)  { +	qdio_clear_dbf_list();  	debugfs_remove(debugfs_root);  	if (qdio_dbf_setup)  		debug_unregister(qdio_dbf_setup);  | 
