1 /* 2 * Copyright IBM Corp. 2008, 2009 3 * 4 * Author: Jan Glauber (jang@linux.vnet.ibm.com) 5 */ 6 #include <linux/seq_file.h> 7 #include <linux/debugfs.h> 8 #include <linux/uaccess.h> 9 #include <linux/export.h> 10 #include <linux/slab.h> 11 #include <asm/debug.h> 12 #include "qdio_debug.h" 13 #include "qdio.h" 14 15 debug_info_t *qdio_dbf_setup; 16 debug_info_t *qdio_dbf_error; 17 18 static struct dentry *debugfs_root; 19 #define QDIO_DEBUGFS_NAME_LEN 10 20 #define QDIO_DBF_NAME_LEN 20 21 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, 61 struct qdio_irq *irq_ptr) 62 { 63 char text[QDIO_DBF_NAME_LEN]; 64 struct qdio_dbf_entry *new_entry; 65 66 DBF_EVENT("qfmt:%1d", init_data->q_format); 67 DBF_HEX(init_data->adapter_name, 8); 68 DBF_EVENT("qpff%4x", init_data->qib_param_field_format); 69 DBF_HEX(&init_data->qib_param_field, sizeof(void *)); 70 DBF_HEX(&init_data->input_slib_elements, sizeof(void *)); 71 DBF_HEX(&init_data->output_slib_elements, sizeof(void *)); 72 DBF_EVENT("niq:%1d noq:%1d", init_data->no_input_qs, 73 init_data->no_output_qs); 74 DBF_HEX(&init_data->input_handler, sizeof(void *)); 75 DBF_HEX(&init_data->output_handler, sizeof(void *)); 76 DBF_HEX(&init_data->int_parm, sizeof(long)); 77 DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *)); 78 DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *)); 79 DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr); 80 81 /* allocate trace view for the interface */ 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; 110 } 111 112 static int qstat_show(struct seq_file *m, void *v) 113 { 114 unsigned char state; 115 struct qdio_q *q = m->private; 116 int i; 117 118 if (!q) 119 return 0; 120 121 seq_printf(m, "Timestamp: %Lx Last AI: %Lx\n", 122 q->timestamp, last_ai_time); 123 seq_printf(m, "nr_used: %d ftc: %d last_move: %d\n", 124 atomic_read(&q->nr_buf_used), 125 q->first_to_check, q->last_move); 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: %d IRQs disabled: %u\n", 131 *(u32 *)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 192 static int qstat_seq_open(struct inode *inode, struct file *filp) 193 { 194 return single_open(filp, qstat_show, 195 file_inode(filp)->i_private); 196 } 197 198 static const struct file_operations debugfs_fops = { 199 .owner = THIS_MODULE, 200 .open = qstat_seq_open, 201 .read = seq_read, 202 .llseek = seq_lseek, 203 .release = single_release, 204 }; 205 206 static char *qperf_names[] = { 207 "Assumed adapter interrupts", 208 "QDIO interrupts", 209 "Requested PCIs", 210 "Inbound tasklet runs", 211 "Inbound tasklet resched", 212 "Inbound tasklet resched2", 213 "Outbound tasklet runs", 214 "SIGA read", 215 "SIGA write", 216 "SIGA sync", 217 "Inbound calls", 218 "Inbound handler", 219 "Inbound stop_polling", 220 "Inbound queue full", 221 "Outbound calls", 222 "Outbound handler", 223 "Outbound queue full", 224 "Outbound fast_requeue", 225 "Outbound target_full", 226 "QEBSM eqbs", 227 "QEBSM eqbs partial", 228 "QEBSM sqbs", 229 "QEBSM sqbs partial", 230 "Discarded interrupts" 231 }; 232 233 static int qperf_show(struct seq_file *m, void *v) 234 { 235 struct qdio_irq *irq_ptr = m->private; 236 unsigned int *stat; 237 int i; 238 239 if (!irq_ptr) 240 return 0; 241 if (!irq_ptr->perf_stat_enabled) { 242 seq_printf(m, "disabled\n"); 243 return 0; 244 } 245 stat = (unsigned int *)&irq_ptr->perf_stat; 246 247 for (i = 0; i < ARRAY_SIZE(qperf_names); i++) 248 seq_printf(m, "%26s:\t%u\n", 249 qperf_names[i], *(stat + i)); 250 return 0; 251 } 252 253 static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf, 254 size_t count, loff_t *off) 255 { 256 struct seq_file *seq = file->private_data; 257 struct qdio_irq *irq_ptr = seq->private; 258 struct qdio_q *q; 259 unsigned long val; 260 int ret, i; 261 262 if (!irq_ptr) 263 return 0; 264 265 ret = kstrtoul_from_user(ubuf, count, 10, &val); 266 if (ret) 267 return ret; 268 269 switch (val) { 270 case 0: 271 irq_ptr->perf_stat_enabled = 0; 272 memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat)); 273 for_each_input_queue(irq_ptr, q, i) 274 memset(&q->q_stats, 0, sizeof(q->q_stats)); 275 for_each_output_queue(irq_ptr, q, i) 276 memset(&q->q_stats, 0, sizeof(q->q_stats)); 277 break; 278 case 1: 279 irq_ptr->perf_stat_enabled = 1; 280 break; 281 } 282 return count; 283 } 284 285 static int qperf_seq_open(struct inode *inode, struct file *filp) 286 { 287 return single_open(filp, qperf_show, 288 file_inode(filp)->i_private); 289 } 290 291 static const struct file_operations debugfs_perf_fops = { 292 .owner = THIS_MODULE, 293 .open = qperf_seq_open, 294 .read = seq_read, 295 .write = qperf_seq_write, 296 .llseek = seq_lseek, 297 .release = single_release, 298 }; 299 300 static void setup_debugfs_entry(struct qdio_q *q) 301 { 302 char name[QDIO_DEBUGFS_NAME_LEN]; 303 304 snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d", 305 q->is_input_q ? "input" : "output", 306 q->nr); 307 q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR, 308 q->irq_ptr->debugfs_dev, q, &debugfs_fops); 309 if (IS_ERR(q->debugfs_q)) 310 q->debugfs_q = NULL; 311 } 312 313 void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev) 314 { 315 struct qdio_q *q; 316 int i; 317 318 irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev), 319 debugfs_root); 320 if (IS_ERR(irq_ptr->debugfs_dev)) 321 irq_ptr->debugfs_dev = NULL; 322 323 irq_ptr->debugfs_perf = debugfs_create_file("statistics", 324 S_IFREG | S_IRUGO | S_IWUSR, 325 irq_ptr->debugfs_dev, irq_ptr, 326 &debugfs_perf_fops); 327 if (IS_ERR(irq_ptr->debugfs_perf)) 328 irq_ptr->debugfs_perf = NULL; 329 330 for_each_input_queue(irq_ptr, q, i) 331 setup_debugfs_entry(q); 332 for_each_output_queue(irq_ptr, q, i) 333 setup_debugfs_entry(q); 334 } 335 336 void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr) 337 { 338 struct qdio_q *q; 339 int i; 340 341 for_each_input_queue(irq_ptr, q, i) 342 debugfs_remove(q->debugfs_q); 343 for_each_output_queue(irq_ptr, q, i) 344 debugfs_remove(q->debugfs_q); 345 debugfs_remove(irq_ptr->debugfs_perf); 346 debugfs_remove(irq_ptr->debugfs_dev); 347 } 348 349 int __init qdio_debug_init(void) 350 { 351 debugfs_root = debugfs_create_dir("qdio", NULL); 352 353 qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16); 354 debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view); 355 debug_set_level(qdio_dbf_setup, DBF_INFO); 356 DBF_EVENT("dbf created\n"); 357 358 qdio_dbf_error = debug_register("qdio_error", 4, 1, 16); 359 debug_register_view(qdio_dbf_error, &debug_hex_ascii_view); 360 debug_set_level(qdio_dbf_error, DBF_INFO); 361 DBF_ERROR("dbf created\n"); 362 return 0; 363 } 364 365 void qdio_debug_exit(void) 366 { 367 qdio_clear_dbf_list(); 368 debugfs_remove(debugfs_root); 369 if (qdio_dbf_setup) 370 debug_unregister(qdio_dbf_setup); 371 if (qdio_dbf_error) 372 debug_unregister(qdio_dbf_error); 373 } 374