Commit 613c4e04 authored by Stefan Raspl's avatar Stefan Raspl Committed by Martin Schwidefsky

qdio: Keep device-specific dbf entries

Keep the per-device dbf entries until module is removed, with
proper error checking for debug feature setup.
Signed-off-by: default avatarStefan Raspl <raspl@linux.vnet.ibm.com>
Reviewed-by: default avatarSteffen Maier <maier@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent b9c9a33b
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/slab.h>
#include <asm/debug.h> #include <asm/debug.h>
#include "qdio_debug.h" #include "qdio_debug.h"
#include "qdio.h" #include "qdio.h"
...@@ -16,11 +17,51 @@ debug_info_t *qdio_dbf_error; ...@@ -16,11 +17,51 @@ debug_info_t *qdio_dbf_error;
static struct dentry *debugfs_root; static struct dentry *debugfs_root;
#define QDIO_DEBUGFS_NAME_LEN 10 #define QDIO_DEBUGFS_NAME_LEN 10
#define QDIO_DBF_NAME_LEN 20
void qdio_allocate_dbf(struct qdio_initialize *init_data, 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;
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) 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_EVENT("qfmt:%1d", init_data->q_format);
DBF_HEX(init_data->adapter_name, 8); DBF_HEX(init_data->adapter_name, 8);
...@@ -38,11 +79,34 @@ void qdio_allocate_dbf(struct qdio_initialize *init_data, ...@@ -38,11 +79,34 @@ void qdio_allocate_dbf(struct qdio_initialize *init_data,
DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr); DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
/* allocate trace view for the interface */ /* allocate trace view for the interface */
snprintf(text, 20, "qdio_%s", dev_name(&init_data->cdev->dev)); 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); irq_ptr->debug_area = debug_register(text, 2, 1, 16);
debug_register_view(irq_ptr->debug_area, &debug_hex_ascii_view); 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); debug_set_level(irq_ptr->debug_area, DBF_WARN);
DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created"); 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) static int qstat_show(struct seq_file *m, void *v)
...@@ -300,6 +364,7 @@ int __init qdio_debug_init(void) ...@@ -300,6 +364,7 @@ int __init qdio_debug_init(void)
void qdio_debug_exit(void) void qdio_debug_exit(void)
{ {
qdio_clear_dbf_list();
debugfs_remove(debugfs_root); debugfs_remove(debugfs_root);
if (qdio_dbf_setup) if (qdio_dbf_setup)
debug_unregister(qdio_dbf_setup); debug_unregister(qdio_dbf_setup);
......
...@@ -75,7 +75,7 @@ static inline void DBF_DEV_HEX(struct qdio_irq *dev, void *addr, ...@@ -75,7 +75,7 @@ static inline void DBF_DEV_HEX(struct qdio_irq *dev, void *addr,
} }
} }
void qdio_allocate_dbf(struct qdio_initialize *init_data, int qdio_allocate_dbf(struct qdio_initialize *init_data,
struct qdio_irq *irq_ptr); struct qdio_irq *irq_ptr);
void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, void qdio_setup_debug_entries(struct qdio_irq *irq_ptr,
struct ccw_device *cdev); struct ccw_device *cdev);
......
...@@ -1233,12 +1233,10 @@ int qdio_free(struct ccw_device *cdev) ...@@ -1233,12 +1233,10 @@ int qdio_free(struct ccw_device *cdev)
return -ENODEV; return -ENODEV;
DBF_EVENT("qfree:%4x", cdev->private->schid.sch_no); DBF_EVENT("qfree:%4x", cdev->private->schid.sch_no);
DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf abandoned");
mutex_lock(&irq_ptr->setup_mutex); mutex_lock(&irq_ptr->setup_mutex);
if (irq_ptr->debug_area != NULL) {
debug_unregister(irq_ptr->debug_area);
irq_ptr->debug_area = NULL; irq_ptr->debug_area = NULL;
}
cdev->private->qdio_data = NULL; cdev->private->qdio_data = NULL;
mutex_unlock(&irq_ptr->setup_mutex); mutex_unlock(&irq_ptr->setup_mutex);
...@@ -1275,7 +1273,8 @@ int qdio_allocate(struct qdio_initialize *init_data) ...@@ -1275,7 +1273,8 @@ int qdio_allocate(struct qdio_initialize *init_data)
goto out_err; goto out_err;
mutex_init(&irq_ptr->setup_mutex); mutex_init(&irq_ptr->setup_mutex);
qdio_allocate_dbf(init_data, irq_ptr); if (qdio_allocate_dbf(init_data, irq_ptr))
goto out_rel;
/* /*
* Allocate a page for the chsc calls in qdio_establish. * Allocate a page for the chsc calls in qdio_establish.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment