Commit 613c4e0459603cc04384723b08fd62103b5eaaaf
Committed by
Martin Schwidefsky
1 parent
b9c9a33b76
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
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: Stefan Raspl <raspl@linux.vnet.ibm.com> Reviewed-by: Steffen Maier <maier@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Showing 3 changed files with 77 additions and 13 deletions Side-by-side Diff
drivers/s390/cio/qdio_debug.c
... | ... | @@ -7,6 +7,7 @@ |
7 | 7 | #include <linux/debugfs.h> |
8 | 8 | #include <linux/uaccess.h> |
9 | 9 | #include <linux/export.h> |
10 | +#include <linux/slab.h> | |
10 | 11 | #include <asm/debug.h> |
11 | 12 | #include "qdio_debug.h" |
12 | 13 | #include "qdio.h" |
13 | 14 | |
14 | 15 | |
... | ... | @@ -16,11 +17,51 @@ |
16 | 17 | |
17 | 18 | static struct dentry *debugfs_root; |
18 | 19 | #define QDIO_DEBUGFS_NAME_LEN 10 |
20 | +#define QDIO_DBF_NAME_LEN 20 | |
19 | 21 | |
20 | -void qdio_allocate_dbf(struct qdio_initialize *init_data, | |
22 | +struct qdio_dbf_entry { | |
23 | + char dbf_name[QDIO_DBF_NAME_LEN]; | |
24 | + debug_info_t *dbf_info; | |
25 | + struct list_head dbf_list; | |
26 | +}; | |
27 | + | |
28 | +static LIST_HEAD(qdio_dbf_list); | |
29 | +static DEFINE_MUTEX(qdio_dbf_list_mutex); | |
30 | + | |
31 | +static debug_info_t *qdio_get_dbf_entry(char *name) | |
32 | +{ | |
33 | + struct qdio_dbf_entry *entry; | |
34 | + debug_info_t *rc = NULL; | |
35 | + | |
36 | + mutex_lock(&qdio_dbf_list_mutex); | |
37 | + list_for_each_entry(entry, &qdio_dbf_list, dbf_list) { | |
38 | + if (strcmp(entry->dbf_name, name) == 0) { | |
39 | + rc = entry->dbf_info; | |
40 | + break; | |
41 | + } | |
42 | + } | |
43 | + mutex_unlock(&qdio_dbf_list_mutex); | |
44 | + return rc; | |
45 | +} | |
46 | + | |
47 | +static void qdio_clear_dbf_list(void) | |
48 | +{ | |
49 | + struct qdio_dbf_entry *entry, *tmp; | |
50 | + | |
51 | + mutex_lock(&qdio_dbf_list_mutex); | |
52 | + list_for_each_entry_safe(entry, tmp, &qdio_dbf_list, dbf_list) { | |
53 | + list_del(&entry->dbf_list); | |
54 | + debug_unregister(entry->dbf_info); | |
55 | + kfree(entry); | |
56 | + } | |
57 | + mutex_unlock(&qdio_dbf_list_mutex); | |
58 | +} | |
59 | + | |
60 | +int qdio_allocate_dbf(struct qdio_initialize *init_data, | |
21 | 61 | struct qdio_irq *irq_ptr) |
22 | 62 | { |
23 | - char text[20]; | |
63 | + char text[QDIO_DBF_NAME_LEN]; | |
64 | + struct qdio_dbf_entry *new_entry; | |
24 | 65 | |
25 | 66 | DBF_EVENT("qfmt:%1d", init_data->q_format); |
26 | 67 | DBF_HEX(init_data->adapter_name, 8); |
... | ... | @@ -38,11 +79,34 @@ |
38 | 79 | DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr); |
39 | 80 | |
40 | 81 | /* 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"); | |
82 | + snprintf(text, QDIO_DBF_NAME_LEN, "qdio_%s", | |
83 | + dev_name(&init_data->cdev->dev)); | |
84 | + irq_ptr->debug_area = qdio_get_dbf_entry(text); | |
85 | + if (irq_ptr->debug_area) | |
86 | + DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf reused"); | |
87 | + else { | |
88 | + irq_ptr->debug_area = debug_register(text, 2, 1, 16); | |
89 | + if (!irq_ptr->debug_area) | |
90 | + return -ENOMEM; | |
91 | + if (debug_register_view(irq_ptr->debug_area, | |
92 | + &debug_hex_ascii_view)) { | |
93 | + debug_unregister(irq_ptr->debug_area); | |
94 | + return -ENOMEM; | |
95 | + } | |
96 | + debug_set_level(irq_ptr->debug_area, DBF_WARN); | |
97 | + DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created"); | |
98 | + new_entry = kzalloc(sizeof(struct qdio_dbf_entry), GFP_KERNEL); | |
99 | + if (!new_entry) { | |
100 | + debug_unregister(irq_ptr->debug_area); | |
101 | + return -ENOMEM; | |
102 | + } | |
103 | + strlcpy(new_entry->dbf_name, text, QDIO_DBF_NAME_LEN); | |
104 | + new_entry->dbf_info = irq_ptr->debug_area; | |
105 | + mutex_lock(&qdio_dbf_list_mutex); | |
106 | + list_add(&new_entry->dbf_list, &qdio_dbf_list); | |
107 | + mutex_unlock(&qdio_dbf_list_mutex); | |
108 | + } | |
109 | + return 0; | |
46 | 110 | } |
47 | 111 | |
48 | 112 | static int qstat_show(struct seq_file *m, void *v) |
... | ... | @@ -300,6 +364,7 @@ |
300 | 364 | |
301 | 365 | void qdio_debug_exit(void) |
302 | 366 | { |
367 | + qdio_clear_dbf_list(); | |
303 | 368 | debugfs_remove(debugfs_root); |
304 | 369 | if (qdio_dbf_setup) |
305 | 370 | debug_unregister(qdio_dbf_setup); |
drivers/s390/cio/qdio_debug.h
drivers/s390/cio/qdio_main.c
... | ... | @@ -1233,12 +1233,10 @@ |
1233 | 1233 | return -ENODEV; |
1234 | 1234 | |
1235 | 1235 | DBF_EVENT("qfree:%4x", cdev->private->schid.sch_no); |
1236 | + DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf abandoned"); | |
1236 | 1237 | mutex_lock(&irq_ptr->setup_mutex); |
1237 | 1238 | |
1238 | - if (irq_ptr->debug_area != NULL) { | |
1239 | - debug_unregister(irq_ptr->debug_area); | |
1240 | - irq_ptr->debug_area = NULL; | |
1241 | - } | |
1239 | + irq_ptr->debug_area = NULL; | |
1242 | 1240 | cdev->private->qdio_data = NULL; |
1243 | 1241 | mutex_unlock(&irq_ptr->setup_mutex); |
1244 | 1242 | |
... | ... | @@ -1275,7 +1273,8 @@ |
1275 | 1273 | goto out_err; |
1276 | 1274 | |
1277 | 1275 | mutex_init(&irq_ptr->setup_mutex); |
1278 | - qdio_allocate_dbf(init_data, irq_ptr); | |
1276 | + if (qdio_allocate_dbf(init_data, irq_ptr)) | |
1277 | + goto out_rel; | |
1279 | 1278 | |
1280 | 1279 | /* |
1281 | 1280 | * Allocate a page for the chsc calls in qdio_establish. |