Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Stefan Raspl and committed by
Martin Schwidefsky
613c4e04 b9c9a33b

+77 -13
+72 -7
drivers/s390/cio/qdio_debug.c
··· 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" ··· 17 16 18 17 static struct dentry *debugfs_root; 19 18 #define QDIO_DEBUGFS_NAME_LEN 10 19 + #define QDIO_DBF_NAME_LEN 20 20 20 21 - void qdio_allocate_dbf(struct qdio_initialize *init_data, 21 + struct qdio_dbf_entry { 22 + char dbf_name[QDIO_DBF_NAME_LEN]; 23 + debug_info_t *dbf_info; 24 + struct list_head dbf_list; 25 + }; 26 + 27 + static LIST_HEAD(qdio_dbf_list); 28 + static DEFINE_MUTEX(qdio_dbf_list_mutex); 29 + 30 + static debug_info_t *qdio_get_dbf_entry(char *name) 31 + { 32 + struct qdio_dbf_entry *entry; 33 + debug_info_t *rc = NULL; 34 + 35 + mutex_lock(&qdio_dbf_list_mutex); 36 + list_for_each_entry(entry, &qdio_dbf_list, dbf_list) { 37 + if (strcmp(entry->dbf_name, name) == 0) { 38 + rc = entry->dbf_info; 39 + break; 40 + } 41 + } 42 + mutex_unlock(&qdio_dbf_list_mutex); 43 + return rc; 44 + } 45 + 46 + static void qdio_clear_dbf_list(void) 47 + { 48 + struct qdio_dbf_entry *entry, *tmp; 49 + 50 + mutex_lock(&qdio_dbf_list_mutex); 51 + list_for_each_entry_safe(entry, tmp, &qdio_dbf_list, dbf_list) { 52 + list_del(&entry->dbf_list); 53 + debug_unregister(entry->dbf_info); 54 + kfree(entry); 55 + } 56 + mutex_unlock(&qdio_dbf_list_mutex); 57 + } 58 + 59 + int qdio_allocate_dbf(struct qdio_initialize *init_data, 22 60 struct qdio_irq *irq_ptr) 23 61 { 24 - char text[20]; 62 + char text[QDIO_DBF_NAME_LEN]; 63 + struct qdio_dbf_entry *new_entry; 25 64 26 65 DBF_EVENT("qfmt:%1d", init_data->q_format); 27 66 DBF_HEX(init_data->adapter_name, 8); ··· 79 38 DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr); 80 39 81 40 /* allocate trace view for the interface */ 82 - snprintf(text, 20, "qdio_%s", dev_name(&init_data->cdev->dev)); 83 - irq_ptr->debug_area = debug_register(text, 2, 1, 16); 84 - debug_register_view(irq_ptr->debug_area, &debug_hex_ascii_view); 85 - debug_set_level(irq_ptr->debug_area, DBF_WARN); 86 - DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created"); 41 + snprintf(text, QDIO_DBF_NAME_LEN, "qdio_%s", 42 + dev_name(&init_data->cdev->dev)); 43 + irq_ptr->debug_area = qdio_get_dbf_entry(text); 44 + if (irq_ptr->debug_area) 45 + DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf reused"); 46 + else { 47 + irq_ptr->debug_area = debug_register(text, 2, 1, 16); 48 + if (!irq_ptr->debug_area) 49 + return -ENOMEM; 50 + if (debug_register_view(irq_ptr->debug_area, 51 + &debug_hex_ascii_view)) { 52 + debug_unregister(irq_ptr->debug_area); 53 + return -ENOMEM; 54 + } 55 + debug_set_level(irq_ptr->debug_area, DBF_WARN); 56 + DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created"); 57 + new_entry = kzalloc(sizeof(struct qdio_dbf_entry), GFP_KERNEL); 58 + if (!new_entry) { 59 + debug_unregister(irq_ptr->debug_area); 60 + return -ENOMEM; 61 + } 62 + strlcpy(new_entry->dbf_name, text, QDIO_DBF_NAME_LEN); 63 + new_entry->dbf_info = irq_ptr->debug_area; 64 + mutex_lock(&qdio_dbf_list_mutex); 65 + list_add(&new_entry->dbf_list, &qdio_dbf_list); 66 + mutex_unlock(&qdio_dbf_list_mutex); 67 + } 68 + return 0; 87 69 } 88 70 89 71 static int qstat_show(struct seq_file *m, void *v) ··· 364 300 365 301 void qdio_debug_exit(void) 366 302 { 303 + qdio_clear_dbf_list(); 367 304 debugfs_remove(debugfs_root); 368 305 if (qdio_dbf_setup) 369 306 debug_unregister(qdio_dbf_setup);
+1 -1
drivers/s390/cio/qdio_debug.h
··· 75 75 } 76 76 } 77 77 78 - void qdio_allocate_dbf(struct qdio_initialize *init_data, 78 + int qdio_allocate_dbf(struct qdio_initialize *init_data, 79 79 struct qdio_irq *irq_ptr); 80 80 void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, 81 81 struct ccw_device *cdev);
+4 -5
drivers/s390/cio/qdio_main.c
··· 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 ··· 1273 1275 goto out_err; 1274 1276 1275 1277 mutex_init(&irq_ptr->setup_mutex); 1276 - qdio_allocate_dbf(init_data, irq_ptr); 1278 + if (qdio_allocate_dbf(init_data, irq_ptr)) 1279 + goto out_rel; 1277 1280 1278 1281 /* 1279 1282 * Allocate a page for the chsc calls in qdio_establish.