1 /* 2 * drivers/s390/cio/qdio_debug.c 3 * 4 * Copyright IBM Corp. 2008,2009 5 * 6 * Author: Jan Glauber (jang@linux.vnet.ibm.com) 7 */ 8 #include <linux/seq_file.h> 9 #include <linux/debugfs.h> 10 #include <asm/debug.h> 11 #include "qdio_debug.h" 12 #include "qdio.h" 13 14 debug_info_t *qdio_dbf_setup; 15 debug_info_t *qdio_dbf_error; 16 17 static struct dentry *debugfs_root; 18 #define QDIO_DEBUGFS_NAME_LEN 10 19 20 void qdio_allocate_dbf(struct qdio_initialize *init_data, 21 struct qdio_irq *irq_ptr) 22 { 23 char text[20]; 24 25 DBF_EVENT("qfmt:%1d", init_data->q_format); 26 DBF_HEX(init_data->adapter_name, 8); 27 DBF_EVENT("qpff%4x", init_data->qib_param_field_format); 28 DBF_HEX(&init_data->qib_param_field, sizeof(void *)); 29 DBF_HEX(&init_data->input_slib_elements, sizeof(void *)); 30 DBF_HEX(&init_data->output_slib_elements, sizeof(void *)); 31 DBF_EVENT("niq:%1d noq:%1d", init_data->no_input_qs, 32 init_data->no_output_qs); 33 DBF_HEX(&init_data->input_handler, sizeof(void *)); 34 DBF_HEX(&init_data->output_handler, sizeof(void *)); 35 DBF_HEX(&init_data->int_parm, sizeof(long)); 36 DBF_HEX(&init_data->flags, sizeof(long)); 37 DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *)); 38 DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *)); 39 DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr); 40 41 /* allocate trace view for the interface */ 42 snprintf(text, 20, "qdio_%s", dev_name(&init_data->cdev->dev)); 43 irq_ptr->debug_area = debug_register(text, 2, 1, 16); 44 debug_register_view(irq_ptr->debug_area, &debug_hex_ascii_view); 45 debug_set_level(irq_ptr->debug_area, DBF_WARN); 46 DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created"); 47 } 48 49 static int qstat_show(struct seq_file *m, void *v) 50 { 51 unsigned char state; 52 struct qdio_q *q = m->private; 53 int i; 54 55 if (!q) 56 return 0; 57 58 seq_printf(m, "DSCI: %d nr_used: %d\n", 59 *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used)); 60 seq_printf(m, "ftc: %d last_move: %d\n", q->first_to_check, q->last_move); 61 seq_printf(m, "polling: %d ack start: %d ack count: %d\n", 62 q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count); 63 seq_printf(m, "slsb buffer states:\n"); 64 seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); 65 66 for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) { 67 debug_get_buf_state(q, i, &state); 68 switch (state) { 69 case SLSB_P_INPUT_NOT_INIT: 70 case SLSB_P_OUTPUT_NOT_INIT: 71 seq_printf(m, "N"); 72 break; 73 case SLSB_P_INPUT_PRIMED: 74 case SLSB_CU_OUTPUT_PRIMED: 75 seq_printf(m, "+"); 76 break; 77 case SLSB_P_INPUT_ACK: 78 seq_printf(m, "A"); 79 break; 80 case SLSB_P_INPUT_ERROR: 81 case SLSB_P_OUTPUT_ERROR: 82 seq_printf(m, "x"); 83 break; 84 case SLSB_CU_INPUT_EMPTY: 85 case SLSB_P_OUTPUT_EMPTY: 86 seq_printf(m, "-"); 87 break; 88 case SLSB_P_INPUT_HALTED: 89 case SLSB_P_OUTPUT_HALTED: 90 seq_printf(m, "."); 91 break; 92 default: 93 seq_printf(m, "?"); 94 } 95 if (i == 63) 96 seq_printf(m, "\n"); 97 } 98 seq_printf(m, "\n"); 99 seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\n"); 100 return 0; 101 } 102 103 static ssize_t qstat_seq_write(struct file *file, const char __user *buf, 104 size_t count, loff_t *off) 105 { 106 struct seq_file *seq = file->private_data; 107 struct qdio_q *q = seq->private; 108 109 if (!q) 110 return 0; 111 if (q->is_input_q) 112 xchg(q->irq_ptr->dsci, 1); 113 local_bh_disable(); 114 tasklet_schedule(&q->tasklet); 115 local_bh_enable(); 116 return count; 117 } 118 119 static int qstat_seq_open(struct inode *inode, struct file *filp) 120 { 121 return single_open(filp, qstat_show, 122 filp->f_path.dentry->d_inode->i_private); 123 } 124 125 static const struct file_operations debugfs_fops = { 126 .owner = THIS_MODULE, 127 .open = qstat_seq_open, 128 .read = seq_read, 129 .write = qstat_seq_write, 130 .llseek = seq_lseek, 131 .release = single_release, 132 }; 133 134 static char *qperf_names[] = { 135 "Assumed adapter interrupts", 136 "QDIO interrupts", 137 "Requested PCIs", 138 "Inbound tasklet runs", 139 "Inbound tasklet resched", 140 "Inbound tasklet resched2", 141 "Outbound tasklet runs", 142 "SIGA read", 143 "SIGA write", 144 "SIGA sync", 145 "Inbound calls", 146 "Inbound handler", 147 "Inbound stop_polling", 148 "Inbound queue full", 149 "Outbound calls", 150 "Outbound handler", 151 "Outbound fast_requeue", 152 "Outbound target_full", 153 "QEBSM eqbs", 154 "QEBSM eqbs partial", 155 "QEBSM sqbs", 156 "QEBSM sqbs partial" 157 }; 158 159 static int qperf_show(struct seq_file *m, void *v) 160 { 161 struct qdio_irq *irq_ptr = m->private; 162 unsigned int *stat; 163 int i; 164 165 if (!irq_ptr) 166 return 0; 167 if (!irq_ptr->perf_stat_enabled) { 168 seq_printf(m, "disabled\n"); 169 return 0; 170 } 171 stat = (unsigned int *)&irq_ptr->perf_stat; 172 173 for (i = 0; i < ARRAY_SIZE(qperf_names); i++) 174 seq_printf(m, "%26s:\t%u\n", 175 qperf_names[i], *(stat + i)); 176 return 0; 177 } 178 179 static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf, 180 size_t count, loff_t *off) 181 { 182 struct seq_file *seq = file->private_data; 183 struct qdio_irq *irq_ptr = seq->private; 184 unsigned long val; 185 char buf[8]; 186 int ret; 187 188 if (!irq_ptr) 189 return 0; 190 if (count >= sizeof(buf)) 191 return -EINVAL; 192 if (copy_from_user(&buf, ubuf, count)) 193 return -EFAULT; 194 buf[count] = 0; 195 196 ret = strict_strtoul(buf, 10, &val); 197 if (ret < 0) 198 return ret; 199 200 switch (val) { 201 case 0: 202 irq_ptr->perf_stat_enabled = 0; 203 memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat)); 204 break; 205 case 1: 206 irq_ptr->perf_stat_enabled = 1; 207 break; 208 } 209 return count; 210 } 211 212 static int qperf_seq_open(struct inode *inode, struct file *filp) 213 { 214 return single_open(filp, qperf_show, 215 filp->f_path.dentry->d_inode->i_private); 216 } 217 218 static struct file_operations debugfs_perf_fops = { 219 .owner = THIS_MODULE, 220 .open = qperf_seq_open, 221 .read = seq_read, 222 .write = qperf_seq_write, 223 .llseek = seq_lseek, 224 .release = single_release, 225 }; 226 static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev) 227 { 228 char name[QDIO_DEBUGFS_NAME_LEN]; 229 230 snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d", 231 q->is_input_q ? "input" : "output", 232 q->nr); 233 q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR, 234 q->irq_ptr->debugfs_dev, q, &debugfs_fops); 235 if (IS_ERR(q->debugfs_q)) 236 q->debugfs_q = NULL; 237 } 238 239 void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev) 240 { 241 struct qdio_q *q; 242 int i; 243 244 irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev), 245 debugfs_root); 246 if (IS_ERR(irq_ptr->debugfs_dev)) 247 irq_ptr->debugfs_dev = NULL; 248 249 irq_ptr->debugfs_perf = debugfs_create_file("statistics", 250 S_IFREG | S_IRUGO | S_IWUSR, 251 irq_ptr->debugfs_dev, irq_ptr, 252 &debugfs_perf_fops); 253 if (IS_ERR(irq_ptr->debugfs_perf)) 254 irq_ptr->debugfs_perf = NULL; 255 256 for_each_input_queue(irq_ptr, q, i) 257 setup_debugfs_entry(q, cdev); 258 for_each_output_queue(irq_ptr, q, i) 259 setup_debugfs_entry(q, cdev); 260 } 261 262 void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev) 263 { 264 struct qdio_q *q; 265 int i; 266 267 for_each_input_queue(irq_ptr, q, i) 268 debugfs_remove(q->debugfs_q); 269 for_each_output_queue(irq_ptr, q, i) 270 debugfs_remove(q->debugfs_q); 271 debugfs_remove(irq_ptr->debugfs_perf); 272 debugfs_remove(irq_ptr->debugfs_dev); 273 } 274 275 int __init qdio_debug_init(void) 276 { 277 debugfs_root = debugfs_create_dir("qdio", NULL); 278 279 qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16); 280 debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view); 281 debug_set_level(qdio_dbf_setup, DBF_INFO); 282 DBF_EVENT("dbf created\n"); 283 284 qdio_dbf_error = debug_register("qdio_error", 4, 1, 16); 285 debug_register_view(qdio_dbf_error, &debug_hex_ascii_view); 286 debug_set_level(qdio_dbf_error, DBF_INFO); 287 DBF_ERROR("dbf created\n"); 288 return 0; 289 } 290 291 void qdio_debug_exit(void) 292 { 293 debugfs_remove(debugfs_root); 294 if (qdio_dbf_setup) 295 debug_unregister(qdio_dbf_setup); 296 if (qdio_dbf_error) 297 debug_unregister(qdio_dbf_error); 298 } 299